PageSourceSearch

https://railsblocks.com/assets/lexxy_extensions-3a4f8ce2ad2947c7dd…2a3ff05fe20dbb90efe89e487ab212345ca90f20.js

js railsblocks.com collected 2026-09-25 20:22:28 UTC 2,849,733 bytes, 58,174 lines download raw bytes

1(() => {
2  var __create = Object.create;
3  var __defProp = Object.defineProperty;
4  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5  var __getOwnPropNames = Object.getOwnPropertyNames;
6  var __getProtoOf = Object.getPrototypeOf;
7  var __hasOwnProp = Object.prototype.hasOwnProperty;
8  var __esm = (fn, res) => function __init() {
9    return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
10  };
11  var __commonJS = (cb, mod18) => function __require() {
12    return mod18 || (0, cb[__getOwnPropNames(cb)[0]])((mod18 = { exports: {} }).exports, mod18), mod18.exports;
13  };
14  var __export = (target, all) => {
15    for (var name in all)
16      __defProp(target, name, { get: all[name], enumerable: true });
17  };
18  var __copyProps = (to, from, except, desc) => {
19    if (from && typeof from === "object" || typeof from === "function") {
20      for (let key of __getOwnPropNames(from))
21        if (!__hasOwnProp.call(to, key) && key !== except)
22          __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
23    }
24    return to;
25  };
26  var __toESM = (mod18, isNodeMode, target) => (target = mod18 != null ? __create(__getProtoOf(mod18)) : {}, __copyProps(
27    // If the importer is in node compatibility mode or this is not an ESM
28    // file that has been converted to a CommonJS file using a Babel-
29    // compatible transform (i.e. "__esModule" has not been set), then set
30    // "default" to the CommonJS "module.exports" for node compatibility.
31    isNodeMode || !mod18 || !mod18.__esModule ? __defProp(target, "default", { value: mod18, enumerable: true }) : target,
32    mod18
33  ));
34
35  
vendor: 61,303 bytes, lines 35-1484
35// node_modules/prismjs/prism.js
36  var require_prism = __commonJS({
37    "node_modules/prismjs/prism.js"(exports, module) {
38      var _self = typeof window !== "undefined" ? window : typeof WorkerGlobalScope !== "undefined" && self instanceof WorkerGlobalScope ? self : {};
39      var Prism3 = function(_self2) {
40        var lang = /(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i;
41        var uniqueId = 0;
42        var plainTextGrammar = {};
43        var _3 = {
44          /**
45           * By default, Prism will attempt to highlight all code elements (by calling {@link Prism.highlightAll}) on the
46           * current page after the page finished loading. This might be a problem if e.g. you wanted to asynchronously load
47           * additional languages or plugins yourself.
48           *
49           * By setting this value to `true`, Prism will not automatically highlight all code elements on the page.
50           *
51           * You obviously have to change this value before the automatic highlighting started. To do this, you can add an
52           * empty Prism object into the global scope before loading the Prism script like this:
53           *
54           * ```js
55           * window.Prism = window.Prism || {};
56           * Prism.manual = true;
57           * // add a new <script> to load Prism's script
58           * ```
59           *
60           * @default false
61           * @type {boolean}
62           * @memberof Prism
63           * @public
64           */
65          manual: _self2.Prism && _self2.Prism.manual,
66          /**
67           * By default, if Prism is in a web worker, it assumes that it is in a worker it created itself, so it uses
68           * `addEventListener` to communicate with its parent instance. However, if you're using Prism manually in your
69           * own worker, you don't want it to do this.
70           *
71           * By setting this value to `true`, Prism will not add its own listeners to the worker.
72           *
73           * You obviously have to change this value before Prism executes. To do this, you can add an
74           * empty Prism object into the global scope before loading the Prism script like this:
75           *
76           * ```js
77           * window.Prism = window.Prism || {};
78           * Prism.disableWorkerMessageHandler = true;
79           * // Load Prism's script
80           * ```
81           *
82           * @default false
83           * @type {boolean}
84           * @memberof Prism
85           * @public
86           */
87          disableWorkerMessageHandler: _self2.Prism && _self2.Prism.disableWorkerMessageHandler,
88          /**
89           * A namespace for utility methods.
90           *
91           * All function in this namespace that are not explicitly marked as _public_ are for __internal use only__ and may
92           * change or disappear at any time.
93           *
94           * @namespace
95           * @memberof Prism
96           */
97          util: {
98            encode: function encode(tokens) {
99              if (tokens instanceof Token) {
100                return new Token(tokens.type, encode(tokens.content), tokens.alias);
101              } else if (Array.isArray(tokens)) {
102                return tokens.map(encode);
103              } else {
104                return tokens.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/\u00a0/g, " ");
105              }
106            },
107            /**
108             * Returns the name of the type of the given value.
109             *
110             * @param {any} o
111             * @returns {string}
112             * @example
113             * type(null)      === 'Null'
114             * type(undefined) === 'Undefined'
115             * type(123)       === 'Number'
116             * type('foo')     === 'String'
117             * type(true)      === 'Boolean'
118             * type([1, 2])    === 'Array'
119             * type({})        === 'Object'
120             * type(String)    === 'Function'
121             * type(/abc+/)    === 'RegExp'
122             */
123            type: function(o2) {
124              return Object.prototype.toString.call(o2).slice(8, -1);
125            },
126            /**
127             * Returns a unique number for the given object. Later calls will still return the same number.
128             *
129             * @param {Object} obj
130             * @returns {number}
131             */
132            objId: function(obj) {
133              if (!obj["__id"]) {
134                Object.defineProperty(obj, "__id", { value: ++uniqueId });
135              }
136              return obj["__id"];
137            },
138            /**
139             * Creates a deep clone of the given object.
140             *
141             * The main intended use of this function is to clone language definitions.
142             *
143             * @param {T} o
144             * @param {Record<number, any>} [visited]
145             * @returns {T}
146             * @template T
147             */
148            clone: function deepClone(o2, visited) {
149              visited = visited || {};
150              var clone2;
151              var id3;
152              switch (_3.util.type(o2)) {
153                case "Object":
154                  id3 = _3.util.objId(o2);
155                  if (visited[id3]) {
156                    return visited[id3];
157                  }
158                  clone2 = /** @type {Record<string, any>} */
159                  {};
160                  visited[id3] = clone2;
161                  for (var key in o2) {
162                    if (o2.hasOwnProperty(key)) {
163                      clone2[key] = deepClone(o2[key], visited);
164                    }
165                  }
166                  return (
167                    /** @type {any} */
168                    clone2
169                  );
170                case "Array":
171                  id3 = _3.util.objId(o2);
172                  if (visited[id3]) {
173                    return visited[id3];
174                  }
175                  clone2 = [];
176                  visited[id3] = clone2;
177                  /** @type {Array} */
178                  /** @type {any} */
179                  o2.forEach(function(v3, i2) {
180                    clone2[i2] = deepClone(v3, visited);
181                  });
182                  return (
183                    /** @type {any} */
184                    clone2
185                  );
186                default:
187                  return o2;
188              }
189            },
190            /**
191             * Returns the Prism language of the given element set by a `language-xxxx` or `lang-xxxx` class.
192             *
193             * If no language is set for the element or the element is `null` or `undefined`, `none` will be returned.
194             *
195             * @param {Element} element
196             * @returns {string}
197             */
198            getLanguage: function(element) {
199              while (element) {
200                var m3 = lang.exec(element.className);
201                if (m3) {
202                  return m3[1].toLowerCase();
203                }
204                element = element.parentElement;
205              }
206              return "none";
207            },
208            /**
209             * Sets the Prism `language-xxxx` class of the given element.
210             *
211             * @param {Element} element
212             * @param {string} language
213             * @returns {void}
214             */
215            setLanguage: function(element, language) {
216              element.className = element.className.replace(RegExp(lang, "gi"), "");
217              element.classList.add("language-" + language);
218            },
219            /**
220             * Returns the script element that is currently executing.
221             *
222             * This does __not__ work for line script element.
223             *
224             * @returns {HTMLScriptElement | null}
225             */
226            currentScript: function() {
227              if (typeof document === "undefined") {
228                return null;
229              }
230              if (document.currentScript && document.currentScript.tagName === "SCRIPT" && 1 < 2) {
231                return (
232                  /** @type {any} */
233                  document.currentScript
234                );
235              }
236              try {
237                throw new Error();
238              } catch (err) {
239                var src = (/at [^(\r\n]*\((.*):[^:]+:[^:]+\)$/i.exec(err.stack) || [])[1];
240                if (src) {
241                  var scripts = document.getElementsByTagName("script");
242                  for (var i2 in scripts) {
243                    if (scripts[i2].src == src) {
244                      return scripts[i2];
245                    }
246                  }
247                }
248                return null;
249              }
250            },
251            /**
252             * Returns whether a given class is active for `element`.
253             *
254             * The class can be activated if `element` or one of its ancestors has the given class and it can be deactivated
255             * if `element` or one of its ancestors has the negated version of the given class. The _negated version_ of the
256             * given class is just the given class with a `no-` prefix.
257             *
258             * Whether the class is active is determined by the closest ancestor of `element` (where `element` itself is
259             * closest ancestor) that has the given class or the negated version of it. If neither `element` nor any of its
260             * ancestors have the given class or the negated version of it, then the default activation will be returned.
261             *
262             * In the paradoxical situation where the closest ancestor contains __both__ the given class and the negated
263             * version of it, the class is considered active.
264             *
265             * @param {Element} element
266             * @param {string} className
267             * @param {boolean} [defaultActivation=false]
268             * @returns {boolean}
269             */
270            isActive: function(element, className, defaultActivation) {
271              var no = "no-" + className;
272              while (element) {
273                var classList = element.classList;
274                if (classList.contains(className)) {
275                  return true;
276                }
277                if (classList.contains(no)) {
278                  return false;
279                }
280                element = element.parentElement;
281              }
282              return !!defaultActivation;
283            }
284          },
285          /**
286           * This namespace contains all currently loaded languages and the some helper functions to create and modify languages.
287           *
288           * @namespace
289           * @memberof Prism
290           * @public
291           */
292          languages: {
293            /**
294             * The grammar for plain, unformatted text.
295             */
296            plain: plainTextGrammar,
297            plaintext: plainTextGrammar,
298            text: plainTextGrammar,
299            txt: plainTextGrammar,
300            /**
301             * Creates a deep copy of the language with the given id and appends the given tokens.
302             *
303             * If a token in `redef` also appears in the copied language, then the existing token in the copied language
304             * will be overwritten at its original position.
305             *
306             * ## Best practices
307             *
308             * Since the position of overwriting tokens (token in `redef` that overwrite tokens in the copied language)
309             * doesn't matter, they can technically be in any order. However, this can be confusing to others that trying to
310             * understand the language definition because, normally, the order of tokens matters in Prism grammars.
311             *
312             * Therefore, it is encouraged to order overwriting tokens according to the positions of the overwritten tokens.
313             * Furthermore, all non-overwriting tokens should be placed after the overwriting ones.
314             *
315             * @param {string} id The id of the language to extend. This has to be a key in `Prism.languages`.
316             * @param {Grammar} redef The new tokens to append.
317             * @returns {Grammar} The new language created.
318             * @public
319             * @example
320             * Prism.languages['css-with-colors'] = Prism.languages.extend('css', {
321             *     // Prism.languages.css already has a 'comment' token, so this token will overwrite CSS' 'comment' token
322             *     // at its original position
323             *     'comment': { ... },
324             *     // CSS doesn't have a 'color' token, so this token will be appended
325             *     'color': /\b(?:red|green|blue)\b/
326             * });
327             */
328            extend: function(id3, redef) {
329              var lang2 = _3.util.clone(_3.languages[id3]);
330              for (var key in redef) {
331                lang2[key] = redef[key];
332              }
333              return lang2;
334            },
335            /**
336             * Inserts tokens _before_ another token in a language definition or any other grammar.
337             *
338             * ## Usage
339             *
340             * This helper method makes it easy to modify existing languages. For example, the CSS language definition
341             * not only defines CSS highlighting for CSS documents, but also needs to define highlighting for CSS embedded
342             * in HTML through `<style>` elements. To do this, it needs to modify `Prism.languages.markup` and add the
343             * appropriate tokens. However, `Prism.languages.markup` is a regular JavaScript object literal, so if you do
344             * this:
345             *
346             * ```js
347             * Prism.languages.markup.style = {
348             *     // token
349             * };
350             * ```
351             *
352             * then the `style` token will be added (and processed) at the end. `insertBefore` allows you to insert tokens
353             * before existing tokens. For the CSS example above, you would use it like this:
354             *
355             * ```js
356             * Prism.languages.insertBefore('markup', 'cdata', {
357             *     'style': {
358             *         // token
359             *     }
360             * });
361             * ```
362             *
363             * ## Special cases
364             *
365             * If the grammars of `inside` and `insert` have tokens with the same name, the tokens in `inside`'s grammar
366             * will be ignored.
367             *
368             * This behavior can be used to insert tokens after `before`:
369             *
370             * ```js
371             * Prism.languages.insertBefore('markup', 'comment', {
372             *     'comment': Prism.languages.markup.comment,
373             *     // tokens after 'comment'
374             * });
375             * ```
376             *
377             * ## Limitations
378             *
379             * The main problem `insertBefore` has to solve is iteration order. Since ES2015, the iteration order for object
380             * properties is guaranteed to be the insertion order (except for integer keys) but some browsers behave
381             * differently when keys are deleted and re-inserted. So `insertBefore` can't be implemented by temporarily
382             * deleting properties which is necessary to insert at arbitrary positions.
383             *
384             * To solve this problem, `insertBefore` doesn't actually insert the given tokens into the target object.
385             * Instead, it will create a new object and replace all references to the target object with the new one. This
386             * can be done without temporarily deleting properties, so the iteration order is well-defined.
387             *
388             * However, only references that can be reached from `Prism.languages` or `insert` will be replaced. I.e. if
389             * you hold the target object in a variable, then the value of the variable will not change.
390             *
391             * ```js
392             * var oldMarkup = Prism.languages.markup;
393             * var newMarkup = Prism.languages.insertBefore('markup', 'comment', { ... });
394             *
395             * assert(oldMarkup !== Prism.languages.markup);
396             * assert(newMarkup === Prism.languages.markup);
397             * ```
398             *
399             * @param {string} inside The property of `root` (e.g. a language id in `Prism.languages`) that contains the
400             * object to be modified.
401             * @param {string} before The key to insert before.
402             * @param {Grammar} insert An object containing the key-value pairs to be inserted.
403             * @param {Object<string, any>} [root] The object containing `inside`, i.e. the object that contains the
404             * object to be modified.
405             *
406             * Defaults to `Prism.languages`.
407             * @returns {Grammar} The new grammar object.
408             * @public
409             */
410            insertBefore: function(inside, before, insert, root) {
411              root = root || /** @type {any} */
412              _3.languages;
413              var grammar = root[inside];
414              var ret = {};
415              for (var token in grammar) {
416                if (grammar.hasOwnProperty(token)) {
417                  if (token == before) {
418                    for (var newToken in insert) {
419                      if (insert.hasOwnProperty(newToken)) {
420                        ret[newToken] = insert[newToken];
421                      }
422                    }
423                  }
424                  if (!insert.hasOwnProperty(token)) {
425                    ret[token] = grammar[token];
426                  }
427                }
428              }
429              var old = root[inside];
430              root[inside] = ret;
431              _3.languages.DFS(_3.languages, function(key, value) {
432                if (value === old && key != inside) {
433                  this[key] = ret;
434                }
435              });
436              return ret;
437            },
438            // Traverse a language definition with Depth First Search
439            DFS: function DFS(o2, callback, type, visited) {
440              visited = visited || {};
441              var objId = _3.util.objId;
442              for (var i2 in o2) {
443                if (o2.hasOwnProperty(i2)) {
444                  callback.call(o2, i2, o2[i2], type || i2);
445                  var property = o2[i2];
446                  var propertyType = _3.util.type(property);
447                  if (propertyType === "Object" && !visited[objId(property)]) {
448                    visited[objId(property)] = true;
449                    DFS(property, callback, null, visited);
450                  } else if (propertyType === "Array" && !visited[objId(property)]) {
451                    visited[objId(property)] = true;
452                    DFS(property, callback, i2, visited);
453                  }
454                }
455              }
456            }
457          },
458          plugins: {},
459          /**
460           * This is the most high-level function in Prism’s API.
461           * It fetches all the elements that have a `.language-xxxx` class and then calls {@link Prism.highlightElement} on
462           * each one of them.
463           *
464           * This is equivalent to `Prism.highlightAllUnder(document, async, callback)`.
465           *
466           * @param {boolean} [async=false] Same as in {@link Prism.highlightAllUnder}.
467           * @param {HighlightCallback} [callback] Same as in {@link Prism.highlightAllUnder}.
468           * @memberof Prism
469           * @public
470           */
471          highlightAll: function(async, callback) {
472            _3.highlightAllUnder(document, async, callback);
473          },
474          /**
475           * Fetches all the descendants of `container` that have a `.language-xxxx` class and then calls
476           * {@link Prism.highlightElement} on each one of them.
477           *
478           * The following hooks will be run:
479           * 1. `before-highlightall`
480           * 2. `before-all-elements-highlight`
481           * 3. All hooks of {@link Prism.highlightElement} for each element.
482           *
483           * @param {ParentNode} container The root element, whose descendants that have a `.language-xxxx` class will be highlighted.
484           * @param {boolean} [async=false] Whether each element is to be highlighted asynchronously using Web Workers.
485           * @param {HighlightCallback} [callback] An optional callback to be invoked on each element after its highlighting is done.
486           * @memberof Prism
487           * @public
488           */
489          highlightAllUnder: function(container, async, callback) {
490            var env = {
491              callback,
492              container,
493              selector: 'code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code'
494            };
495            _3.hooks.run("before-highlightall", env);
496            env.elements = Array.prototype.slice.apply(env.container.querySelectorAll(env.selector));
497            _3.hooks.run("before-all-elements-highlight", env);
498            for (var i2 = 0, element; element = env.elements[i2++]; ) {
499              _3.highlightElement(element, async === true, env.callback);
500            }
501          },
502          /**
503           * Highlights the code inside a single element.
504           *
505           * The following hooks will be run:
506           * 1. `before-sanity-check`
507           * 2. `before-highlight`
508           * 3. All hooks of {@link Prism.highlight}. These hooks will be run by an asynchronous worker if `async` is `true`.
509           * 4. `before-insert`
510           * 5. `after-highlight`
511           * 6. `complete`
512           *
513           * Some the above hooks will be skipped if the element doesn't contain any text or there is no grammar loaded for
514           * the element's language.
515           *
516           * @param {Element} element The element containing the code.
517           * It must have a class of `language-xxxx` to be processed, where `xxxx` is a valid language identifier.
518           * @param {boolean} [async=false] Whether the element is to be highlighted asynchronously using Web Workers
519           * to improve performance and avoid blocking the UI when highlighting very large chunks of code. This option is
520           * [disabled by default](https://prismjs.com/faq.html#why-is-asynchronous-highlighting-disabled-by-default).
521           *
522           * Note: All language definitions required to highlight the code must be included in the main `prism.js` file for
523           * asynchronous highlighting to work. You can build your own bundle on the
524           * [Download page](https://prismjs.com/download.html).
525           * @param {HighlightCallback} [callback] An optional callback to be invoked after the highlighting is done.
526           * Mostly useful when `async` is `true`, since in that case, the highlighting is done asynchronously.
527           * @memberof Prism
528           * @public
529           */
530          highlightElement: function(element, async, callback) {
531            var language = _3.util.getLanguage(element);
532            var grammar = _3.languages[language];
533            _3.util.setLanguage(element, language);
534            var parent = element.parentElement;
535            if (parent && parent.nodeName.toLowerCase() === "pre") {
536              _3.util.setLanguage(parent, language);
537            }
538            var code = element.textContent;
539            var env = {
540              element,
541              language,
542              grammar,
543              code
544            };
545            function insertHighlightedCode(highlightedCode) {
546              env.highlightedCode = highlightedCode;
547              _3.hooks.run("before-insert", env);
548              env.element.innerHTML = env.highlightedCode;
549              _3.hooks.run("after-highlight", env);
550              _3.hooks.run("complete", env);
551              callback && callback.call(env.element);
552            }
553            _3.hooks.run("before-sanity-check", env);
554            parent = env.element.parentElement;
555            if (parent && parent.nodeName.toLowerCase() === "pre" && !parent.hasAttribute("tabindex")) {
556              parent.setAttribute("tabindex", "0");
557            }
558            if (!env.code) {
559              _3.hooks.run("complete", env);
560              callback && callback.call(env.element);
561              return;
562            }
563            _3.hooks.run("before-highlight", env);
564            if (!env.grammar) {
565              insertHighlightedCode(_3.util.encode(env.code));
566              return;
567            }
568            if (async && _self2.Worker) {
569              var worker = new Worker(_3.filename);
570              worker.onmessage = function(evt) {
571                insertHighlightedCode(evt.data);
572              };
573              worker.postMessage(JSON.stringify({
574                language: env.language,
575                code: env.code,
576                immediateClose: true
577              }));
578            } else {
579              insertHighlightedCode(_3.highlight(env.code, env.grammar, env.language));
580            }
581          },
582          /**
583           * Low-level function, only use if you know what you’re doing. It accepts a string of text as input
584           * and the language definitions to use, and returns a string with the HTML produced.
585           *
586           * The following hooks will be run:
587           * 1. `before-tokenize`
588           * 2. `after-tokenize`
589           * 3. `wrap`: On each {@link Token}.
590           *
591           * @param {string} text A string with the code to be highlighted.
592           * @param {Grammar} grammar An object containing the tokens to use.
593           *
594           * Usually a language definition like `Prism.languages.markup`.
595           * @param {string} language The name of the language definition passed to `grammar`.
596           * @returns {string} The highlighted HTML.
597           * @memberof Prism
598           * @public
599           * @example
600           * Prism.highlight('var foo = true;', Prism.languages.javascript, 'javascript');
601           */
602          highlight: function(text2, grammar, language) {
603            var env = {
604              code: text2,
605              grammar,
606              language
607            };
608            _3.hooks.run("before-tokenize", env);
609            if (!env.grammar) {
610              throw new Error('The language "' + env.language + '" has no grammar.');
611            }
612            env.tokens = _3.tokenize(env.code, env.grammar);
613            _3.hooks.run("after-tokenize", env);
614            return Token.stringify(_3.util.encode(env.tokens), env.language);
615          },
616          /**
617           * This is the heart of Prism, and the most low-level function you can use. It accepts a string of text as input
618           * and the language definitions to use, and returns an array with the tokenized code.
619           *
620           * When the language definition includes nested tokens, the function is called recursively on each of these tokens.
621           *
622           * This method could be useful in other contexts as well, as a very crude parser.
623           *
624           * @param {string} text A string with the code to be highlighted.
625           * @param {Grammar} grammar An object containing the tokens to use.
626           *
627           * Usually a language definition like `Prism.languages.markup`.
628           * @returns {TokenStream} An array of strings and tokens, a token stream.
629           * @memberof Prism
630           * @public
631           * @example
632           * let code = `var foo = 0;`;
633           * let tokens = Prism.tokenize(code, Prism.languages.javascript);
634           * tokens.forEach(token => {
635           *     if (token instanceof Prism.Token && token.type === 'number') {
636           *         console.log(`Found numeric literal: ${token.content}`);
637           *     }
638           * });
639           */
640          tokenize: function(text2, grammar) {
641            var rest = grammar.rest;
642            if (rest) {
643              for (var token in rest) {
644                grammar[token] = rest[token];
645              }
646              delete grammar.rest;
647            }
648            var tokenList = new LinkedList();
649            addAfter(tokenList, tokenList.head, text2);
650            matchGrammar(text2, tokenList, grammar, tokenList.head, 0);
651            return toArray3(tokenList);
652          },
653          /**
654           * @namespace
655           * @memberof Prism
656           * @public
657           */
658          hooks: {
659            all: {},
660            /**
661             * Adds the given callback to the list of callbacks for the given hook.
662             *
663             * The callback will be invoked when the hook it is registered for is run.
664             * Hooks are usually directly run by a highlight function but you can also run hooks yourself.
665             *
666             * One callback function can be registered to multiple hooks and the same hook multiple times.
667             *
668             * @param {string} name The name of the hook.
669             * @param {HookCallback} callback The callback function which is given environment variables.
670             * @public
671             */
672            add: function(name, callback) {
673              var hooks = _3.hooks.all;
674              hooks[name] = hooks[name] || [];
675              hooks[name].push(callback);
676            },
677            /**
678             * Runs a hook invoking all registered callbacks with the given environment variables.
679             *
680             * Callbacks will be invoked synchronously and in the order in which they were registered.
681             *
682             * @param {string} name The name of the hook.
683             * @param {Object<string, any>} env The environment variables of the hook passed to all callbacks registered.
684             * @public
685             */
686            run: function(name, env) {
687              var callbacks = _3.hooks.all[name];
688              if (!callbacks || !callbacks.length) {
689                return;
690              }
691              for (var i2 = 0, callback; callback = callbacks[i2++]; ) {
692                callback(env);
693              }
694            }
695          },
696          Token
697        };
698        _self2.Prism = _3;
699        function Token(type, content, alias, matchedStr) {
700          this.type = type;
701          this.content = content;
702          this.alias = alias;
703          this.length = (matchedStr || "").length | 0;
704        }
705        Token.stringify = function stringify(o2, language) {
706          if (typeof o2 == "string") {
707            return o2;
708          }
709          if (Array.isArray(o2)) {
710            var s2 = "";
711            o2.forEach(function(e2) {
712              s2 += stringify(e2, language);
713            });
714            return s2;
715          }
716          var env = {
717            type: o2.type,
718            content: stringify(o2.content, language),
719            tag: "span",
720            classes: ["token", o2.type],
721            attributes: {},
722            language
723          };
724          var aliases = o2.alias;
725          if (aliases) {
726            if (Array.isArray(aliases)) {
727              Array.prototype.push.apply(env.classes, aliases);
728            } else {
729              env.classes.push(aliases);
730            }
731          }
732          _3.hooks.run("wrap", env);
733          var attributes = "";
734          for (var name in env.attributes) {
735            attributes += " " + name + '="' + (env.attributes[name] || "").replace(/"/g, "&quot;") + '"';
736          }
737          return "<" + env.tag + ' class="' + env.classes.join(" ") + '"' + attributes + ">" + env.content + "</" + env.tag + ">";
738        };
739        function matchPattern(pattern, pos, text2, lookbehind) {
740          pattern.lastIndex = pos;
741          var match = pattern.exec(text2);
742          if (match && lookbehind && match[1]) {
743            var lookbehindLength = match[1].length;
744            match.index += lookbehindLength;
745            match[0] = match[0].slice(lookbehindLength);
746          }
747          return match;
748        }
749        function matchGrammar(text2, tokenList, grammar, startNode, startPos, rematch) {
750          for (var token in grammar) {
751            if (!grammar.hasOwnProperty(token) || !grammar[token]) {
752              continue;
753            }
754            var patterns = grammar[token];
755            patterns = Array.isArray(patterns) ? patterns : [patterns];
756            for (var j3 = 0; j3 < patterns.length; ++j3) {
757              if (rematch && rematch.cause == token + "," + j3) {
758                return;
759              }
760              var patternObj = patterns[j3];
761              var inside = patternObj.inside;
762              var lookbehind = !!patternObj.lookbehind;
763              var greedy = !!patternObj.greedy;
764              var alias = patternObj.alias;
765              if (greedy && !patternObj.pattern.global) {
766                var flags = patternObj.pattern.toString().match(/[imsuy]*$/)[0];
767                patternObj.pattern = RegExp(patternObj.pattern.source, flags + "g");
768              }
769              var pattern = patternObj.pattern || patternObj;
770              for (var currentNode = startNode.next, pos = startPos; currentNode !== tokenList.tail; pos += currentNode.value.length, currentNode = currentNode.next) {
771                if (rematch && pos >= rematch.reach) {
772                  break;
773                }
774                var str = currentNode.value;
775                if (tokenList.length > text2.length) {
776                  return;
777                }
778                if (str instanceof Token) {
779                  continue;
780                }
781                var removeCount = 1;
782                var match;
783                if (greedy) {
784                  match = matchPattern(pattern, pos, text2, lookbehind);
785                  if (!match || match.index >= text2.length) {
786                    break;
787                  }
788                  var from = match.index;
789                  var to = match.index + match[0].length;
790                  var p2 = pos;
791                  p2 += currentNode.value.length;
792                  while (from >= p2) {
793                    currentNode = currentNode.next;
794                    p2 += currentNode.value.length;
795                  }
796                  p2 -= currentNode.value.length;
797                  pos = p2;
798                  if (currentNode.value instanceof Token) {
799                    continue;
800                  }
801                  for (var k2 = currentNode; k2 !== tokenList.tail && (p2 < to || typeof k2.value === "string"); k2 = k2.next) {
802                    removeCount++;
803                    p2 += k2.value.length;
804                  }
805                  removeCount--;
806                  str = text2.slice(pos, p2);
807                  match.index -= pos;
808                } else {
809                  match = matchPattern(pattern, 0, str, lookbehind);
810                  if (!match) {
811                    continue;
812                  }
813                }
814                var from = match.index;
815                var matchStr = match[0];
816                var before = str.slice(0, from);
817                var after = str.slice(from + matchStr.length);
818                var reach = pos + str.length;
819                if (rematch && reach > rematch.reach) {
820                  rematch.reach = reach;
821                }
822                var removeFrom = currentNode.prev;
823                if (before) {
824                  removeFrom = addAfter(tokenList, removeFrom, before);
825                  pos += before.length;
826                }
827                removeRange(tokenList, removeFrom, removeCount);
828                var wrapped = new Token(token, inside ? _3.tokenize(matchStr, inside) : matchStr, alias, matchStr);
829                currentNode = addAfter(tokenList, removeFrom, wrapped);
830                if (after) {
831                  addAfter(tokenList, currentNode, after);
832                }
833                if (removeCount > 1) {
834                  var nestedRematch = {
835                    cause: token + "," + j3,
836                    reach
837                  };
838                  matchGrammar(text2, tokenList, grammar, currentNode.prev, pos, nestedRematch);
839                  if (rematch && nestedRematch.reach > rematch.reach) {
840                    rematch.reach = nestedRematch.reach;
841                  }
842                }
843              }
844            }
845          }
846        }
847        function LinkedList() {
848          var head = { value: null, prev: null, next: null };
849          var tail = { value: null, prev: head, next: null };
850          head.next = tail;
851          this.head = head;
852          this.tail = tail;
853          this.length = 0;
854        }
855        function addAfter(list, node, value) {
856          var next = node.next;
857          var newNode = { value, prev: node, next };
858          node.next = newNode;
859          next.prev = newNode;
860          list.length++;
861          return newNode;
862        }
863        function removeRange(list, node, count) {
864          var next = node.next;
865          for (var i2 = 0; i2 < count && next !== list.tail; i2++) {
866            next = next.next;
867          }
868          node.next = next;
869          next.prev = node;
870          list.length -= i2;
871        }
872        function toArray3(list) {
873          var array = [];
874          var node = list.head.next;
875          while (node !== list.tail) {
876            array.push(node.value);
877            node = node.next;
878          }
879          return array;
880        }
881        if (!_self2.document) {
882          if (!_self2.addEventListener) {
883            return _3;
884          }
885          if (!_3.disableWorkerMessageHandler) {
886            _self2.addEventListener("message", function(evt) {
887              var message = JSON.parse(evt.data);
888              var lang2 = message.language;
889              var code = message.code;
890              var immediateClose = message.immediateClose;
891              _self2.postMessage(_3.highlight(code, _3.languages[lang2], lang2));
892              if (immediateClose) {
893                _self2.close();
894              }
895            }, false);
896          }
897          return _3;
898        }
899        var script = _3.util.currentScript();
900        if (script) {
901          _3.filename = script.src;
902          if (script.hasAttribute("data-manual")) {
903            _3.manual = true;
904          }
905        }
906        function highlightAutomaticallyCallback() {
907          if (!_3.manual) {
908            _3.highlightAll();
909          }
910        }
911        if (!_3.manual) {
912          var readyState = document.readyState;
913          if (readyState === "loading" || readyState === "interactive" && script && script.defer) {
914            document.addEventListener("DOMContentLoaded", highlightAutomaticallyCallback);
915          } else {
916            if (window.requestAnimationFrame) {
917              window.requestAnimationFrame(highlightAutomaticallyCallback);
918            } else {
919              window.setTimeout(highlightAutomaticallyCallback, 16);
920            }
921          }
922        }
923        return _3;
924      }(_self);
925      if (typeof module !== "undefined" && module.exports) {
926        module.exports = Prism3;
927      }
928      if (typeof global !== "undefined") {
929        global.Prism = Prism3;
930      }
931      Prism3.languages.markup = {
932        "comment": {
933          pattern: /<!--(?:(?!<!--)[\s\S])*?-->/,
934          greedy: true
935        },
936        "prolog": {
937          pattern: /<\?[\s\S]+?\?>/,
938          greedy: true
939        },
940        "doctype": {
941          // https://www.w3.org/TR/xml/#NT-doctypedecl
942          pattern: /<!DOCTYPE(?:[^>"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|<!--(?:[^-]|-(?!->))*-->)*\]\s*)?>/i,
943          greedy: true,
944          inside: {
945            "internal-subset": {
946              pattern: /(^[^\[]*\[)[\s\S]+(?=\]>$)/,
947              lookbehind: true,
948              greedy: true,
949              inside: null
950              // see below
951            },
952            "string": {
953              pattern: /"[^"]*"|'[^']*'/,
954              greedy: true
955            },
956            "punctuation": /^<!|>$|[[\]]/,
957            "doctype-tag": /^DOCTYPE/i,
958            "name": /[^\s<>'"]+/
959          }
960        },
961        "cdata": {
962          pattern: /<!\[CDATA\[[\s\S]*?\]\]>/i,
963          greedy: true
964        },
965        "tag": {
966          pattern: /<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,
967          greedy: true,
968          inside: {
969            "tag": {
970              pattern: /^<\/?[^\s>\/]+/,
971              inside: {
972                "punctuation": /^<\/?/,
973                "namespace": /^[^\s>\/:]+:/
974              }
975            },
976            "special-attr": [],
977            "attr-value": {
978              pattern: /=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,
979              inside: {
980                "punctuation": [
981                  {
982                    pattern: /^=/,
983                    alias: "attr-equals"
984                  },
985                  {
986                    pattern: /^(\s*)["']|["']$/,
987                    lookbehind: true
988                  }
989                ]
990              }
991            },
992            "punctuation": /\/?>/,
993            "attr-name": {
994              pattern: /[^\s>\/]+/,
995              inside: {
996                "namespace": /^[^\s>\/:]+:/
997              }
998            }
999          }
1000        },
1001        "entity": [
1002          {
1003            pattern: /&[\da-z]{1,8};/i,
1004            alias: "named-entity"
1005          },
1006          /&#x?[\da-f]{1,8};/i
1007        ]
1008      };
1009      Prism3.languages.markup["tag"].inside["attr-value"].inside["entity"] = Prism3.languages.markup["entity"];
1010      Prism3.languages.markup["doctype"].inside["internal-subset"].inside = Prism3.languages.markup;
1011      Prism3.hooks.add("wrap", function(env) {
1012        if (env.type === "entity") {
1013          env.attributes["title"] = env.content.replace(/&amp;/, "&");
1014        }
1015      });
1016      Object.defineProperty(Prism3.languages.markup.tag, "addInlined", {
1017        /**
1018         * Adds an inlined language to markup.
1019         *
1020         * An example of an inlined language is CSS with `<style>` tags.
1021         *
1022         * @param {string} tagName The name of the tag that contains the inlined language. This name will be treated as
1023         * case insensitive.
1024         * @param {string} lang The language key.
1025         * @example
1026         * addInlined('style', 'css');
1027         */
1028        value: function addInlined2(tagName, lang) {
1029          var includedCdataInside = {};
1030          includedCdataInside["language-" + lang] = {
1031            pattern: /(^<!\[CDATA\[)[\s\S]+?(?=\]\]>$)/i,
1032            lookbehind: true,
1033            inside: Prism3.languages[lang]
1034          };
1035          includedCdataInside["cdata"] = /^<!\[CDATA\[|\]\]>$/i;
1036          var inside = {
1037            "included-cdata": {
1038              pattern: /<!\[CDATA\[[\s\S]*?\]\]>/i,
1039              inside: includedCdataInside
1040            }
1041          };
1042          inside["language-" + lang] = {
1043            pattern: /[\s\S]+/,
1044            inside: Prism3.languages[lang]
1045          };
1046          var def = {};
1047          def[tagName] = {
1048            pattern: RegExp(/(<__[^>]*>)(?:<!\[CDATA\[(?:[^\]]|\](?!\]>))*\]\]>|(?!<!\[CDATA\[)[\s\S])*?(?=<\/__>)/.source.replace(/__/g, function() {
1049              return tagName;
1050            }), "i"),
1051            lookbehind: true,
1052            greedy: true,
1053            inside
1054          };
1055          Prism3.languages.insertBefore("markup", "cdata", def);
1056        }
1057      });
1058      Object.defineProperty(Prism3.languages.markup.tag, "addAttribute", {
1059        /**
1060         * Adds an pattern to highlight languages embedded in HTML attributes.
1061         *
1062         * An example of an inlined language is CSS with `style` attributes.
1063         *
1064         * @param {string} attrName The name of the tag that contains the inlined language. This name will be treated as
1065         * case insensitive.
1066         * @param {string} lang The language key.
1067         * @example
1068         * addAttribute('style', 'css');
1069         */
1070        value: function(attrName, lang) {
1071          Prism3.languages.markup.tag.inside["special-attr"].push({
1072            pattern: RegExp(
1073              /(^|["'\s])/.source + "(?:" + attrName + ")" + /\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))/.source,
1074              "i"
1075            ),
1076            lookbehind: true,
1077            inside: {
1078              "attr-name": /^[^\s=]+/,
1079              "attr-value": {
1080                pattern: /=[\s\S]+/,
1081                inside: {
1082                  "value": {
1083                    pattern: /(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,
1084                    lookbehind: true,
1085                    alias: [lang, "language-" + lang],
1086                    inside: Prism3.languages[lang]
1087                  },
1088                  "punctuation": [
1089                    {
1090                      pattern: /^=/,
1091                      alias: "attr-equals"
1092                    },
1093                    /"|'/
1094                  ]
1095                }
1096              }
1097            }
1098          });
1099        }
1100      });
1101      Prism3.languages.html = Prism3.languages.markup;
1102      Prism3.languages.mathml = Prism3.languages.markup;
1103      Prism3.languages.svg = Prism3.languages.markup;
1104      Prism3.languages.xml = Prism3.languages.extend("markup", {});
1105      Prism3.languages.ssml = Prism3.languages.xml;
1106      Prism3.languages.atom = Prism3.languages.xml;
1107      Prism3.languages.rss = Prism3.languages.xml;
1108      (function(Prism4) {
1109        var string = /(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/;
1110        Prism4.languages.css = {
1111          "comment": /\/\*[\s\S]*?\*\//,
1112          "atrule": {
1113            pattern: RegExp("@[\\w-](?:" + /[^;{\s"']|\s+(?!\s)/.source + "|" + string.source + ")*?" + /(?:;|(?=\s*\{))/.source),
1114            inside: {
1115              "rule": /^@[\w-]+/,
1116              "selector-function-argument": {
1117                pattern: /(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,
1118                lookbehind: true,
1119                alias: "selector"
1120              },
1121              "keyword": {
1122                pattern: /(^|[^\w-])(?:and|not|only|or)(?![\w-])/,
1123                lookbehind: true
1124              }
1125              // See rest below
1126            }
1127          },
1128          "url": {
1129            // https://drafts.csswg.org/css-values-3/#urls
1130            pattern: RegExp("\\burl\\((?:" + string.source + "|" + /(?:[^\\\r\n()"']|\\[\s\S])*/.source + ")\\)", "i"),
1131            greedy: true,
1132            inside: {
1133              "function": /^url/i,
1134              "punctuation": /^\(|\)$/,
1135              "string": {
1136                pattern: RegExp("^" + string.source + "$"),
1137                alias: "url"
1138              }
1139            }
1140          },
1141          "selector": {
1142            pattern: RegExp(`(^|[{}\\s])[^{}\\s](?:[^{};"'\\s]|\\s+(?![\\s{])|` + string.source + ")*(?=\\s*\\{)"),
1143            lookbehind: true
1144          },
1145          "string": {
1146            pattern: string,
1147            greedy: true
1148          },
1149          "property": {
1150            pattern: /(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,
1151            lookbehind: true
1152          },
1153          "important": /!important\b/i,
1154          "function": {
1155            pattern: /(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,
1156            lookbehind: true
1157          },
1158          "punctuation": /[(){};:,]/
1159        };
1160        Prism4.languages.css["atrule"].inside.rest = Prism4.languages.css;
1161        var markup = Prism4.languages.markup;
1162        if (markup) {
1163          markup.tag.addInlined("style", "css");
1164          markup.tag.addAttribute("style", "css");
1165        }
1166      })(Prism3);
1167      Prism3.languages.clike = {
1168        "comment": [
1169          {
1170            pattern: /(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,
1171            lookbehind: true,
1172            greedy: true
1173          },
1174          {
1175            pattern: /(^|[^\\:])\/\/.*/,
1176            lookbehind: true,
1177            greedy: true
1178          }
1179        ],
1180        "string": {
1181          pattern: /(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,
1182          greedy: true
1183        },
1184        "class-name": {
1185          pattern: /(\b(?:class|extends|implements|instanceof|interface|new|trait)\s+|\bcatch\s+\()[\w.\\]+/i,
1186          lookbehind: true,
1187          inside: {
1188            "punctuation": /[.\\]/
1189          }
1190        },
1191        "keyword": /\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\b/,
1192        "boolean": /\b(?:false|true)\b/,
1193        "function": /\b\w+(?=\()/,
1194        "number": /\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,
1195        "operator": /[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,
1196        "punctuation": /[{}[\];(),.:]/
1197      };
1198      Prism3.languages.javascript = Prism3.languages.extend("clike", {
1199        "class-name": [
1200          Prism3.languages.clike["class-name"],
1201          {
1202            pattern: /(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,
1203            lookbehind: true
1204          }
1205        ],
1206        "keyword": [
1207          {
1208            pattern: /((?:^|\})\s*)catch\b/,
1209            lookbehind: true
1210          },
1211          {
1212            pattern: /(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,
1213            lookbehind: true
1214          }
1215        ],
1216        // Allow for all non-ASCII characters (See http://stackoverflow.com/a/2008444)
1217        "function": /#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,
1218        "number": {
1219          pattern: RegExp(
1220            /(^|[^\w$])/.source + "(?:" + // constant
1221            (/NaN|Infinity/.source + "|" + // binary integer
1222            /0[bB][01]+(?:_[01]+)*n?/.source + "|" + // octal integer
1223            /0[oO][0-7]+(?:_[0-7]+)*n?/.source + "|" + // hexadecimal integer
1224            /0[xX][\dA-Fa-f]+(?:_[\dA-Fa-f]+)*n?/.source + "|" + // decimal bigint
1225            /\d+(?:_\d+)*n/.source + "|" + // decimal number (integer or float) but no bigint
1226            /(?:\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\.\d+(?:_\d+)*)(?:[Ee][+-]?\d+(?:_\d+)*)?/.source) + ")" + /(?![\w$])/.source
1227          ),
1228          lookbehind: true
1229        },
1230        "operator": /--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/
1231      });
1232      Prism3.languages.javascript["class-name"][0].pattern = /(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/;
1233      Prism3.languages.insertBefore("javascript", "keyword", {
1234        "regex": {
1235          pattern: RegExp(
1236            // lookbehind
1237            // eslint-disable-next-line regexp/no-dupe-characters-character-class
1238            /((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)/.source + // Regex pattern:
1239            // There are 2 regex patterns here. The RegExp set notation proposal added support for nested character
1240            // classes if the `v` flag is present. Unfortunately, nested CCs are both context-free and incompatible
1241            // with the only syntax, so we have to define 2 different regex patterns.
1242            /\//.source + "(?:" + /(?:\[(?:[^\]\\\r\n]|\\.)*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}/.source + "|" + // `v` flag syntax. This supports 3 levels of nested character classes.
1243            /(?:\[(?:[^[\]\\\r\n]|\\.|\[(?:[^[\]\\\r\n]|\\.|\[(?:[^[\]\\\r\n]|\\.)*\])*\])*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}v[dgimyus]{0,7}/.source + ")" + // lookahead
1244            /(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/.source
1245          ),
1246          lookbehind: true,
1247          greedy: true,
1248          inside: {
1249            "regex-source": {
1250              pattern: /^(\/)[\s\S]+(?=\/[a-z]*$)/,
1251              lookbehind: true,
1252              alias: "language-regex",
1253              inside: Prism3.languages.regex
1254            },
1255            "regex-delimiter": /^\/|\/$/,
1256            "regex-flags": /^[a-z]+$/
1257          }
1258        },
1259        // This must be declared before keyword because we use "function" inside the look-forward
1260        "function-variable": {
1261          pattern: /#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,
1262          alias: "function"
1263        },
1264        "parameter": [
1265          {
1266            pattern: /(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,
1267            lookbehind: true,
1268            inside: Prism3.languages.javascript
1269          },
1270          {
1271            pattern: /(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,
1272            lookbehind: true,
1273            inside: Prism3.languages.javascript
1274          },
1275          {
1276            pattern: /(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,
1277            lookbehind: true,
1278            inside: Prism3.languages.javascript
1279          },
1280          {
1281            pattern: /((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,
1282            lookbehind: true,
1283            inside: Prism3.languages.javascript
1284          }
1285        ],
1286        "constant": /\b[A-Z](?:[A-Z_]|\dx?)*\b/
1287      });
1288      Prism3.languages.insertBefore("javascript", "string", {
1289        "hashbang": {
1290          pattern: /^#!.*/,
1291          greedy: true,
1292          alias: "comment"
1293        },
1294        "template-string": {
1295          pattern: /`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,
1296          greedy: true,
1297          inside: {
1298            "template-punctuation": {
1299              pattern: /^`|`$/,
1300              alias: "string"
1301            },
1302            "interpolation": {
1303              pattern: /((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,
1304              lookbehind: true,
1305              inside: {
1306                "interpolation-punctuation": {
1307                  pattern: /^\$\{|\}$/,
1308                  alias: "punctuation"
1309                },
1310                rest: Prism3.languages.javascript
1311              }
1312            },
1313            "string": /[\s\S]+/
1314          }
1315        },
1316        "string-property": {
1317          pattern: /((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,
1318          lookbehind: true,
1319          greedy: true,
1320          alias: "property"
1321        }
1322      });
1323      Prism3.languages.insertBefore("javascript", "operator", {
1324        "literal-property": {
1325          pattern: /((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,
1326          lookbehind: true,
1327          alias: "property"
1328        }
1329      });
1330      if (Prism3.languages.markup) {
1331        Prism3.languages.markup.tag.addInlined("script", "javascript");
1332        Prism3.languages.markup.tag.addAttribute(
1333          /on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)/.source,
1334          "javascript"
1335        );
1336      }
1337      Prism3.languages.js = Prism3.languages.javascript;
1338      (function() {
1339        if (typeof Prism3 === "undefined" || typeof document === "undefined") {
1340          return;
1341        }
1342        if (!Element.prototype.matches) {
1343          Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector;
1344        }
1345        var LOADING_MESSAGE = "Loading\u2026";
1346        var FAILURE_MESSAGE = function(status, message) {
1347          return "\u2716 Error " + status + " while fetching file: " + message;
1348        };
1349        var FAILURE_EMPTY_MESSAGE = "\u2716 Error: File does not exist or is empty";
1350        var EXTENSIONS = {
1351          "js": "javascript",
1352          "py": "python",
1353          "rb": "ruby",
1354          "ps1": "powershell",
1355          "psm1": "powershell",
1356          "sh": "bash",
1357          "bat": "batch",
1358          "h": "c",
1359          "tex": "latex"
1360        };
1361        var STATUS_ATTR = "data-src-status";
1362        var STATUS_LOADING = "loading";
1363        var STATUS_LOADED = "loaded";
1364        var STATUS_FAILED = "failed";
1365        var SELECTOR = "pre[data-src]:not([" + STATUS_ATTR + '="' + STATUS_LOADED + '"]):not([' + STATUS_ATTR + '="' + STATUS_LOADING + '"])';
1366        function loadFile(src, success, error) {
1367          var xhr = new XMLHttpRequest();
1368          xhr.open("GET", src, true);
1369          xhr.onreadystatechange = function() {
1370            if (xhr.readyState == 4) {
1371              if (xhr.status < 400 && xhr.responseText) {
1372                success(xhr.responseText);
1373              } else {
1374                if (xhr.status >= 400) {
1375                  error(FAILURE_MESSAGE(xhr.status, xhr.statusText));
1376                } else {
1377                  error(FAILURE_EMPTY_MESSAGE);
1378                }
1379              }
1380            }
1381          };
1382          xhr.send(null);
1383        }
1384        function parseRange(range2) {
1385          var m3 = /^\s*(\d+)\s*(?:(,)\s*(?:(\d+)\s*)?)?$/.exec(range2 || "");
1386          if (m3) {
1387            var start3 = Number(m3[1]);
1388            var comma = m3[2];
1389            var end = m3[3];
1390            if (!comma) {
1391              return [start3, start3];
1392            }
1393            if (!end) {
1394              return [start3, void 0];
1395            }
1396            return [start3, Number(end)];
1397          }
1398          return void 0;
1399        }
1400        Prism3.hooks.add("before-highlightall", function(env) {
1401          env.selector += ", " + SELECTOR;
1402        });
1403        Prism3.hooks.add("before-sanity-check", function(env) {
1404          var pre = (
1405            /** @type {HTMLPreElement} */
1406            env.element
1407          );
1408          if (pre.matches(SELECTOR)) {
1409            env.code = "";
1410            pre.setAttribute(STATUS_ATTR, STATUS_LOADING);
1411            var code = pre.appendChild(document.createElement("CODE"));
1412            code.textContent = LOADING_MESSAGE;
1413            var src = pre.getAttribute("data-src");
1414            var language = env.language;
1415            if (language === "none") {
1416              var extension = (/\.(\w+)$/.exec(src) || [, "none"])[1];
1417              language = EXTENSIONS[extension] || extension;
1418            }
1419            Prism3.util.setLanguage(code, language);
1420            Prism3.util.setLanguage(pre, language);
1421            var autoloader = Prism3.plugins.autoloader;
1422            if (autoloader) {
1423              autoloader.loadLanguages(language);
1424            }
1425            loadFile(
1426              src,
1427              function(text2) {
1428                pre.setAttribute(STATUS_ATTR, STATUS_LOADED);
1429                var range2 = parseRange(pre.getAttribute("data-range"));
1430                if (range2) {
1431                  var lines = text2.split(/\r\n?|\n/g);
1432                  var start3 = range2[0];
1433                  var end = range2[1] == null ? lines.length : range2[1];
1434                  if (start3 < 0) {
1435                    start3 += lines.length;
1436                  }
1437                  start3 = Math.max(0, Math.min(start3 - 1, lines.length));
1438                  if (end < 0) {
1439                    end += lines.length;
1440                  }
1441                  end = Math.max(0, Math.min(end, lines.length));
1442                  text2 = lines.slice(start3, end).join("\n");
1443                  if (!pre.hasAttribute("data-start")) {
1444                    pre.setAttribute("data-start", String(start3 + 1));
1445                  }
1446                }
1447                code.textContent = text2;
1448                Prism3.highlightElement(code);
1449              },
1450              function(error) {
1451                pre.setAttribute(STATUS_ATTR, STATUS_FAILED);
1452                code.textContent = error;
1453              }
1454            );
1455          }
1456        });
1457        Prism3.plugins.fileHighlight = {
1458          /**
1459           * Executes the File Highlight plugin for all matching `pre` elements under the given container.
1460           *
1461           * Note: Elements which are already loaded or currently loading will not be touched by this method.
1462           *
1463           * @param {ParentNode} [container=document]
1464           */
1465          highlight: function highlight(container) {
1466            var elements = (container || document).querySelectorAll(SELECTOR);
1467            for (var i2 = 0, element; element = elements[i2++]; ) {
1468              Prism3.highlightElement(element);
1469            }
1470          }
1471        };
1472        var logged = false;
1473        Prism3.fileHighlight = function() {
1474          if (!logged) {
1475            console.warn("Prism.fileHighlight is deprecated. Use `Prism.plugins.fileHighlight.highlight` instead.");
1476            logged = true;
1477          }
1478          Prism3.plugins.fileHighlight.highlight.apply(this, arguments);
1479        };
1480      })();
1481    }
1482  });
1483
1484  
vendor: 34,211 bytes, lines 1484-2351
1484// node_modules/@rails/activestorage/app/assets/javascripts/activestorage.esm.js
1485  var activestorage_esm_exports = {};
1486  __export(activestorage_esm_exports, {
1487    DirectUpload: () => DirectUpload,
1488    DirectUploadController: () => DirectUploadController,
1489    DirectUploadsController: () => DirectUploadsController,
1490    dispatchEvent: () => dispatchEvent,
1491    start: () => start
1492  });
1493  function getMetaValue(name) {
1494    const element = findElement(document.head, `meta[name="${name}"]`);
1495    if (element) {
1496      return element.getAttribute("content");
1497    }
1498  }
1499  function findElements(root, selector) {
1500    if (typeof root == "string") {
1501      selector = root;
1502      root = document;
1503    }
1504    const elements = root.querySelectorAll(selector);
1505    return toArray(elements);
1506  }
1507  function findElement(root, selector) {
1508    if (typeof root == "string") {
1509      selector = root;
1510      root = document;
1511    }
1512    return root.querySelector(selector);
1513  }
1514  function dispatchEvent(element, type, eventInit = {}) {
1515    const { disabled } = element;
1516    const { bubbles, cancelable, detail } = eventInit;
1517    const event = document.createEvent("Event");
1518    event.initEvent(type, bubbles || true, cancelable || true);
1519    event.detail = detail || {};
1520    try {
1521      element.disabled = false;
1522      element.dispatchEvent(event);
1523    } finally {
1524      element.disabled = disabled;
1525    }
1526    return event;
1527  }
1528  function toArray(value) {
1529    if (Array.isArray(value)) {
1530      return value;
1531    } else if (Array.from) {
1532      return Array.from(value);
1533    } else {
1534      return [].slice.call(value);
1535    }
1536  }
1537  function notify(object, methodName, ...messages) {
1538    if (object && typeof object[methodName] == "function") {
1539      return object[methodName](...messages);
1540    }
1541  }
1542  function start() {
1543    if (!started) {
1544      started = true;
1545      document.addEventListener("click", didClick, true);
1546      document.addEventListener("submit", didSubmitForm, true);
1547      document.addEventListener("ajax:before", didSubmitRemoteElement);
1548    }
1549  }
1550  function didClick(event) {
1551    const button = event.target.closest("button, input");
1552    if (button && button.type === "submit" && button.form) {
1553      submitButtonsByForm.set(button.form, button);
1554    }
1555  }
1556  function didSubmitForm(event) {
1557    handleFormSubmissionEvent(event);
1558  }
1559  function didSubmitRemoteElement(event) {
1560    if (event.target.tagName == "FORM") {
1561      handleFormSubmissionEvent(event);
1562    }
1563  }
1564  function handleFormSubmissionEvent(event) {
1565    const form = event.target;
1566    if (form.hasAttribute(processingAttribute)) {
1567      event.preventDefault();
1568      return;
1569    }
1570    const controller = new DirectUploadsController(form);
1571    const { inputs } = controller;
1572    if (inputs.length) {
1573      event.preventDefault();
1574      form.setAttribute(processingAttribute, "");
1575      inputs.forEach(disable);
1576      controller.start((error) => {
1577        form.removeAttribute(processingAttribute);
1578        if (error) {
1579          inputs.forEach(enable);
1580        } else {
1581          submitForm(form);
1582        }
1583      });
1584    }
1585  }
1586  function submitForm(form) {
1587    let button = submitButtonsByForm.get(form) || findElement(form, "input[type=submit], button[type=submit]");
1588    if (button) {
1589      const { disabled } = button;
1590      button.disabled = false;
1591      button.focus();
1592      button.click();
1593      button.disabled = disabled;
1594    } else {
1595      button = document.createElement("input");
1596      button.type = "submit";
1597      button.style.display = "none";
1598      form.appendChild(button);
1599      button.click();
1600      form.removeChild(button);
1601    }
1602    submitButtonsByForm.delete(form);
1603  }
1604  function disable(input) {
1605    input.disabled = true;
1606  }
1607  function enable(input) {
1608    input.disabled = false;
1609  }
1610  function autostart() {
1611    if (window.ActiveStorage) {
1612      start();
1613    }
1614  }
1615  var sparkMd5, SparkMD5, fileSlice, FileChecksum, BlobRecord, BlobUpload, id, DirectUpload, DirectUploadController, inputSelector, DirectUploadsController, processingAttribute, submitButtonsByForm, started;
1616  var init_activestorage_esm = __esm({
1617    "node_modules/@rails/activestorage/app/assets/javascripts/activestorage.esm.js"() {
1618      sparkMd5 = {
1619        exports: {}
1620      };
1621      (function(module, exports) {
1622        (function(factory) {
1623          {
1624            module.exports = factory();
1625          }
1626        })(function(undefined$1) {
1627          var hex_chr = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"];
1628          function md5cycle(x3, k2) {
1629            var a2 = x3[0], b3 = x3[1], c2 = x3[2], d3 = x3[3];
1630            a2 += (b3 & c2 | ~b3 & d3) + k2[0] - 680876936 | 0;
1631            a2 = (a2 << 7 | a2 >>> 25) + b3 | 0;
1632            d3 += (a2 & b3 | ~a2 & c2) + k2[1] - 389564586 | 0;
1633            d3 = (d3 << 12 | d3 >>> 20) + a2 | 0;
1634            c2 += (d3 & a2 | ~d3 & b3) + k2[2] + 606105819 | 0;
1635            c2 = (c2 << 17 | c2 >>> 15) + d3 | 0;
1636            b3 += (c2 & d3 | ~c2 & a2) + k2[3] - 1044525330 | 0;
1637            b3 = (b3 << 22 | b3 >>> 10) + c2 | 0;
1638            a2 += (b3 & c2 | ~b3 & d3) + k2[4] - 176418897 | 0;
1639            a2 = (a2 << 7 | a2 >>> 25) + b3 | 0;
1640            d3 += (a2 & b3 | ~a2 & c2) + k2[5] + 1200080426 | 0;
1641            d3 = (d3 << 12 | d3 >>> 20) + a2 | 0;
1642            c2 += (d3 & a2 | ~d3 & b3) + k2[6] - 1473231341 | 0;
1643            c2 = (c2 << 17 | c2 >>> 15) + d3 | 0;
1644            b3 += (c2 & d3 | ~c2 & a2) + k2[7] - 45705983 | 0;
1645            b3 = (b3 << 22 | b3 >>> 10) + c2 | 0;
1646            a2 += (b3 & c2 | ~b3 & d3) + k2[8] + 1770035416 | 0;
1647            a2 = (a2 << 7 | a2 >>> 25) + b3 | 0;
1648            d3 += (a2 & b3 | ~a2 & c2) + k2[9] - 1958414417 | 0;
1649            d3 = (d3 << 12 | d3 >>> 20) + a2 | 0;
1650            c2 += (d3 & a2 | ~d3 & b3) + k2[10] - 42063 | 0;
1651            c2 = (c2 << 17 | c2 >>> 15) + d3 | 0;
1652            b3 += (c2 & d3 | ~c2 & a2) + k2[11] - 1990404162 | 0;
1653            b3 = (b3 << 22 | b3 >>> 10) + c2 | 0;
1654            a2 += (b3 & c2 | ~b3 & d3) + k2[12] + 1804603682 | 0;
1655            a2 = (a2 << 7 | a2 >>> 25) + b3 | 0;
1656            d3 += (a2 & b3 | ~a2 & c2) + k2[13] - 40341101 | 0;
1657            d3 = (d3 << 12 | d3 >>> 20) + a2 | 0;
1658            c2 += (d3 & a2 | ~d3 & b3) + k2[14] - 1502002290 | 0;
1659            c2 = (c2 << 17 | c2 >>> 15) + d3 | 0;
1660            b3 += (c2 & d3 | ~c2 & a2) + k2[15] + 1236535329 | 0;
1661            b3 = (b3 << 22 | b3 >>> 10) + c2 | 0;
1662            a2 += (b3 & d3 | c2 & ~d3) + k2[1] - 165796510 | 0;
1663            a2 = (a2 << 5 | a2 >>> 27) + b3 | 0;
1664            d3 += (a2 & c2 | b3 & ~c2) + k2[6] - 1069501632 | 0;
1665            d3 = (d3 << 9 | d3 >>> 23) + a2 | 0;
1666            c2 += (d3 & b3 | a2 & ~b3) + k2[11] + 643717713 | 0;
1667            c2 = (c2 << 14 | c2 >>> 18) + d3 | 0;
1668            b3 += (c2 & a2 | d3 & ~a2) + k2[0] - 373897302 | 0;
1669            b3 = (b3 << 20 | b3 >>> 12) + c2 | 0;
1670            a2 += (b3 & d3 | c2 & ~d3) + k2[5] - 701558691 | 0;
1671            a2 = (a2 << 5 | a2 >>> 27) + b3 | 0;
1672            d3 += (a2 & c2 | b3 & ~c2) + k2[10] + 38016083 | 0;
1673            d3 = (d3 << 9 | d3 >>> 23) + a2 | 0;
1674            c2 += (d3 & b3 | a2 & ~b3) + k2[15] - 660478335 | 0;
1675            c2 = (c2 << 14 | c2 >>> 18) + d3 | 0;
1676            b3 += (c2 & a2 | d3 & ~a2) + k2[4] - 405537848 | 0;
1677            b3 = (b3 << 20 | b3 >>> 12) + c2 | 0;
1678            a2 += (b3 & d3 | c2 & ~d3) + k2[9] + 568446438 | 0;
1679            a2 = (a2 << 5 | a2 >>> 27) + b3 | 0;
1680            d3 += (a2 & c2 | b3 & ~c2) + k2[14] - 1019803690 | 0;
1681            d3 = (d3 << 9 | d3 >>> 23) + a2 | 0;
1682            c2 += (d3 & b3 | a2 & ~b3) + k2[3] - 187363961 | 0;
1683            c2 = (c2 << 14 | c2 >>> 18) + d3 | 0;
1684            b3 += (c2 & a2 | d3 & ~a2) + k2[8] + 1163531501 | 0;
1685            b3 = (b3 << 20 | b3 >>> 12) + c2 | 0;
1686            a2 += (b3 & d3 | c2 & ~d3) + k2[13] - 1444681467 | 0;
1687            a2 = (a2 << 5 | a2 >>> 27) + b3 | 0;
1688            d3 += (a2 & c2 | b3 & ~c2) + k2[2] - 51403784 | 0;
1689            d3 = (d3 << 9 | d3 >>> 23) + a2 | 0;
1690            c2 += (d3 & b3 | a2 & ~b3) + k2[7] + 1735328473 | 0;
1691            c2 = (c2 << 14 | c2 >>> 18) + d3 | 0;
1692            b3 += (c2 & a2 | d3 & ~a2) + k2[12] - 1926607734 | 0;
1693            b3 = (b3 << 20 | b3 >>> 12) + c2 | 0;
1694            a2 += (b3 ^ c2 ^ d3) + k2[5] - 378558 | 0;
1695            a2 = (a2 << 4 | a2 >>> 28) + b3 | 0;
1696            d3 += (a2 ^ b3 ^ c2) + k2[8] - 2022574463 | 0;
1697            d3 = (d3 << 11 | d3 >>> 21) + a2 | 0;
1698            c2 += (d3 ^ a2 ^ b3) + k2[11] + 1839030562 | 0;
1699            c2 = (c2 << 16 | c2 >>> 16) + d3 | 0;
1700            b3 += (c2 ^ d3 ^ a2) + k2[14] - 35309556 | 0;
1701            b3 = (b3 << 23 | b3 >>> 9) + c2 | 0;
1702            a2 += (b3 ^ c2 ^ d3) + k2[1] - 1530992060 | 0;
1703            a2 = (a2 << 4 | a2 >>> 28) + b3 | 0;
1704            d3 += (a2 ^ b3 ^ c2) + k2[4] + 1272893353 | 0;
1705            d3 = (d3 << 11 | d3 >>> 21) + a2 | 0;
1706            c2 += (d3 ^ a2 ^ b3) + k2[7] - 155497632 | 0;
1707            c2 = (c2 << 16 | c2 >>> 16) + d3 | 0;
1708            b3 += (c2 ^ d3 ^ a2) + k2[10] - 1094730640 | 0;
1709            b3 = (b3 << 23 | b3 >>> 9) + c2 | 0;
1710            a2 += (b3 ^ c2 ^ d3) + k2[13] + 681279174 | 0;
1711            a2 = (a2 << 4 | a2 >>> 28) + b3 | 0;
1712            d3 += (a2 ^ b3 ^ c2) + k2[0] - 358537222 | 0;
1713            d3 = (d3 << 11 | d3 >>> 21) + a2 | 0;
1714            c2 += (d3 ^ a2 ^ b3) + k2[3] - 722521979 | 0;
1715            c2 = (c2 << 16 | c2 >>> 16) + d3 | 0;
1716            b3 += (c2 ^ d3 ^ a2) + k2[6] + 76029189 | 0;
1717            b3 = (b3 << 23 | b3 >>> 9) + c2 | 0;
1718            a2 += (b3 ^ c2 ^ d3) + k2[9] - 640364487 | 0;
1719            a2 = (a2 << 4 | a2 >>> 28) + b3 | 0;
1720            d3 += (a2 ^ b3 ^ c2) + k2[12] - 421815835 | 0;
1721            d3 = (d3 << 11 | d3 >>> 21) + a2 | 0;
1722            c2 += (d3 ^ a2 ^ b3) + k2[15] + 530742520 | 0;
1723            c2 = (c2 << 16 | c2 >>> 16) + d3 | 0;
1724            b3 += (c2 ^ d3 ^ a2) + k2[2] - 995338651 | 0;
1725            b3 = (b3 << 23 | b3 >>> 9) + c2 | 0;
1726            a2 += (c2 ^ (b3 | ~d3)) + k2[0] - 198630844 | 0;
1727            a2 = (a2 << 6 | a2 >>> 26) + b3 | 0;
1728            d3 += (b3 ^ (a2 | ~c2)) + k2[7] + 1126891415 | 0;
1729            d3 = (d3 << 10 | d3 >>> 22) + a2 | 0;
1730            c2 += (a2 ^ (d3 | ~b3)) + k2[14] - 1416354905 | 0;
1731            c2 = (c2 << 15 | c2 >>> 17) + d3 | 0;
1732            b3 += (d3 ^ (c2 | ~a2)) + k2[5] - 57434055 | 0;
1733            b3 = (b3 << 21 | b3 >>> 11) + c2 | 0;
1734            a2 += (c2 ^ (b3 | ~d3)) + k2[12] + 1700485571 | 0;
1735            a2 = (a2 << 6 | a2 >>> 26) + b3 | 0;
1736            d3 += (b3 ^ (a2 | ~c2)) + k2[3] - 1894986606 | 0;
1737            d3 = (d3 << 10 | d3 >>> 22) + a2 | 0;
1738            c2 += (a2 ^ (d3 | ~b3)) + k2[10] - 1051523 | 0;
1739            c2 = (c2 << 15 | c2 >>> 17) + d3 | 0;
1740            b3 += (d3 ^ (c2 | ~a2)) + k2[1] - 2054922799 | 0;
1741            b3 = (b3 << 21 | b3 >>> 11) + c2 | 0;
1742            a2 += (c2 ^ (b3 | ~d3)) + k2[8] + 1873313359 | 0;
1743            a2 = (a2 << 6 | a2 >>> 26) + b3 | 0;
1744            d3 += (b3 ^ (a2 | ~c2)) + k2[15] - 30611744 | 0;
1745            d3 = (d3 << 10 | d3 >>> 22) + a2 | 0;
1746            c2 += (a2 ^ (d3 | ~b3)) + k2[6] - 1560198380 | 0;
1747            c2 = (c2 << 15 | c2 >>> 17) + d3 | 0;
1748            b3 += (d3 ^ (c2 | ~a2)) + k2[13] + 1309151649 | 0;
1749            b3 = (b3 << 21 | b3 >>> 11) + c2 | 0;
1750            a2 += (c2 ^ (b3 | ~d3)) + k2[4] - 145523070 | 0;
1751            a2 = (a2 << 6 | a2 >>> 26) + b3 | 0;
1752            d3 += (b3 ^ (a2 | ~c2)) + k2[11] - 1120210379 | 0;
1753            d3 = (d3 << 10 | d3 >>> 22) + a2 | 0;
1754            c2 += (a2 ^ (d3 | ~b3)) + k2[2] + 718787259 | 0;
1755            c2 = (c2 << 15 | c2 >>> 17) + d3 | 0;
1756            b3 += (d3 ^ (c2 | ~a2)) + k2[9] - 343485551 | 0;
1757            b3 = (b3 << 21 | b3 >>> 11) + c2 | 0;
1758            x3[0] = a2 + x3[0] | 0;
1759            x3[1] = b3 + x3[1] | 0;
1760            x3[2] = c2 + x3[2] | 0;
1761            x3[3] = d3 + x3[3] | 0;
1762          }
1763          function md5blk(s2) {
1764            var md5blks = [], i2;
1765            for (i2 = 0; i2 < 64; i2 += 4) {
1766              md5blks[i2 >> 2] = s2.charCodeAt(i2) + (s2.charCodeAt(i2 + 1) << 8) + (s2.charCodeAt(i2 + 2) << 16) + (s2.charCodeAt(i2 + 3) << 24);
1767            }
1768            return md5blks;
1769          }
1770          function md5blk_array(a2) {
1771            var md5blks = [], i2;
1772            for (i2 = 0; i2 < 64; i2 += 4) {
1773              md5blks[i2 >> 2] = a2[i2] + (a2[i2 + 1] << 8) + (a2[i2 + 2] << 16) + (a2[i2 + 3] << 24);
1774            }
1775            return md5blks;
1776          }
1777          function md51(s2) {
1778            var n2 = s2.length, state = [1732584193, -271733879, -1732584194, 271733878], i2, length, tail, tmp, lo, hi;
1779            for (i2 = 64; i2 <= n2; i2 += 64) {
1780              md5cycle(state, md5blk(s2.substring(i2 - 64, i2)));
1781            }
1782            s2 = s2.substring(i2 - 64);
1783            length = s2.length;
1784            tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
1785            for (i2 = 0; i2 < length; i2 += 1) {
1786              tail[i2 >> 2] |= s2.charCodeAt(i2) << (i2 % 4 << 3);
1787            }
1788            tail[i2 >> 2] |= 128 << (i2 % 4 << 3);
1789            if (i2 > 55) {
1790              md5cycle(state, tail);
1791              for (i2 = 0; i2 < 16; i2 += 1) {
1792                tail[i2] = 0;
1793              }
1794            }
1795            tmp = n2 * 8;
1796            tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
1797            lo = parseInt(tmp[2], 16);
1798            hi = parseInt(tmp[1], 16) || 0;
1799            tail[14] = lo;
1800            tail[15] = hi;
1801            md5cycle(state, tail);
1802            return state;
1803          }
1804          function md51_array(a2) {
1805            var n2 = a2.length, state = [1732584193, -271733879, -1732584194, 271733878], i2, length, tail, tmp, lo, hi;
1806            for (i2 = 64; i2 <= n2; i2 += 64) {
1807              md5cycle(state, md5blk_array(a2.subarray(i2 - 64, i2)));
1808            }
1809            a2 = i2 - 64 < n2 ? a2.subarray(i2 - 64) : new Uint8Array(0);
1810            length = a2.length;
1811            tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
1812            for (i2 = 0; i2 < length; i2 += 1) {
1813              tail[i2 >> 2] |= a2[i2] << (i2 % 4 << 3);
1814            }
1815            tail[i2 >> 2] |= 128 << (i2 % 4 << 3);
1816            if (i2 > 55) {
1817              md5cycle(state, tail);
1818              for (i2 = 0; i2 < 16; i2 += 1) {
1819                tail[i2] = 0;
1820              }
1821            }
1822            tmp = n2 * 8;
1823            tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
1824            lo = parseInt(tmp[2], 16);
1825            hi = parseInt(tmp[1], 16) || 0;
1826            tail[14] = lo;
1827            tail[15] = hi;
1828            md5cycle(state, tail);
1829            return state;
1830          }
1831          function rhex(n2) {
1832            var s2 = "", j3;
1833            for (j3 = 0; j3 < 4; j3 += 1) {
1834              s2 += hex_chr[n2 >> j3 * 8 + 4 & 15] + hex_chr[n2 >> j3 * 8 & 15];
1835            }
1836            return s2;
1837          }
1838          function hex(x3) {
1839            var i2;
1840            for (i2 = 0; i2 < x3.length; i2 += 1) {
1841              x3[i2] = rhex(x3[i2]);
1842            }
1843            return x3.join("");
1844          }
1845          if (hex(md51("hello")) !== "5d41402abc4b2a76b9719d911017c592") ;
1846          if (typeof ArrayBuffer !== "undefined" && !ArrayBuffer.prototype.slice) {
1847            (function() {
1848              function clamp2(val, length) {
1849                val = val | 0 || 0;
1850                if (val < 0) {
1851                  return Math.max(val + length, 0);
1852                }
1853                return Math.min(val, length);
1854              }
1855              ArrayBuffer.prototype.slice = function(from, to) {
1856                var length = this.byteLength, begin = clamp2(from, length), end = length, num, target, targetArray, sourceArray;
1857                if (to !== undefined$1) {
1858                  end = clamp2(to, length);
1859                }
1860                if (begin > end) {
1861                  return new ArrayBuffer(0);
1862                }
1863                num = end - begin;
1864                target = new ArrayBuffer(num);
1865                targetArray = new Uint8Array(target);
1866                sourceArray = new Uint8Array(this, begin, num);
1867                targetArray.set(sourceArray);
1868                return target;
1869              };
1870            })();
1871          }
1872          function toUtf8(str) {
1873            if (/[\u0080-\uFFFF]/.test(str)) {
1874              str = unescape(encodeURIComponent(str));
1875            }
1876            return str;
1877          }
1878          function utf8Str2ArrayBuffer(str, returnUInt8Array) {
1879            var length = str.length, buff = new ArrayBuffer(length), arr = new Uint8Array(buff), i2;
1880            for (i2 = 0; i2 < length; i2 += 1) {
1881              arr[i2] = str.charCodeAt(i2);
1882            }
1883            return returnUInt8Array ? arr : buff;
1884          }
1885          function arrayBuffer2Utf8Str(buff) {
1886            return String.fromCharCode.apply(null, new Uint8Array(buff));
1887          }
1888          function concatenateArrayBuffers(first, second, returnUInt8Array) {
1889            var result = new Uint8Array(first.byteLength + second.byteLength);
1890            result.set(new Uint8Array(first));
1891            result.set(new Uint8Array(second), first.byteLength);
1892            return returnUInt8Array ? result : result.buffer;
1893          }
1894          function hexToBinaryString(hex2) {
1895            var bytes = [], length = hex2.length, x3;
1896            for (x3 = 0; x3 < length - 1; x3 += 2) {
1897              bytes.push(parseInt(hex2.substr(x3, 2), 16));
1898            }
1899            return String.fromCharCode.apply(String, bytes);
1900          }
1901          function SparkMD53() {
1902            this.reset();
1903          }
1904          SparkMD53.prototype.append = function(str) {
1905            this.appendBinary(toUtf8(str));
1906            return this;
1907          };
1908          SparkMD53.prototype.appendBinary = function(contents) {
1909            this._buff += contents;
1910            this._length += contents.length;
1911            var length = this._buff.length, i2;
1912            for (i2 = 64; i2 <= length; i2 += 64) {
1913              md5cycle(this._hash, md5blk(this._buff.substring(i2 - 64, i2)));
1914            }
1915            this._buff = this._buff.substring(i2 - 64);
1916            return this;
1917          };
1918          SparkMD53.prototype.end = function(raw) {
1919            var buff = this._buff, length = buff.length, i2, tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], ret;
1920            for (i2 = 0; i2 < length; i2 += 1) {
1921              tail[i2 >> 2] |= buff.charCodeAt(i2) << (i2 % 4 << 3);
1922            }
1923            this._finish(tail, length);
1924            ret = hex(this._hash);
1925            if (raw) {
1926              ret = hexToBinaryString(ret);
1927            }
1928            this.reset();
1929            return ret;
1930          };
1931          SparkMD53.prototype.reset = function() {
1932            this._buff = "";
1933            this._length = 0;
1934            this._hash = [1732584193, -271733879, -1732584194, 271733878];
1935            return this;
1936          };
1937          SparkMD53.prototype.getState = function() {
1938            return {
1939              buff: this._buff,
1940              length: this._length,
1941              hash: this._hash.slice()
1942            };
1943          };
1944          SparkMD53.prototype.setState = function(state) {
1945            this._buff = state.buff;
1946            this._length = state.length;
1947            this._hash = state.hash;
1948            return this;
1949          };
1950          SparkMD53.prototype.destroy = function() {
1951            delete this._hash;
1952            delete this._buff;
1953            delete this._length;
1954          };
1955          SparkMD53.prototype._finish = function(tail, length) {
1956            var i2 = length, tmp, lo, hi;
1957            tail[i2 >> 2] |= 128 << (i2 % 4 << 3);
1958            if (i2 > 55) {
1959              md5cycle(this._hash, tail);
1960              for (i2 = 0; i2 < 16; i2 += 1) {
1961                tail[i2] = 0;
1962              }
1963            }
1964            tmp = this._length * 8;
1965            tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
1966            lo = parseInt(tmp[2], 16);
1967            hi = parseInt(tmp[1], 16) || 0;
1968            tail[14] = lo;
1969            tail[15] = hi;
1970            md5cycle(this._hash, tail);
1971          };
1972          SparkMD53.hash = function(str, raw) {
1973            return SparkMD53.hashBinary(toUtf8(str), raw);
1974          };
1975          SparkMD53.hashBinary = function(content, raw) {
1976            var hash = md51(content), ret = hex(hash);
1977            return raw ? hexToBinaryString(ret) : ret;
1978          };
1979          SparkMD53.ArrayBuffer = function() {
1980            this.reset();
1981          };
1982          SparkMD53.ArrayBuffer.prototype.append = function(arr) {
1983            var buff = concatenateArrayBuffers(this._buff.buffer, arr, true), length = buff.length, i2;
1984            this._length += arr.byteLength;
1985            for (i2 = 64; i2 <= length; i2 += 64) {
1986              md5cycle(this._hash, md5blk_array(buff.subarray(i2 - 64, i2)));
1987            }
1988            this._buff = i2 - 64 < length ? new Uint8Array(buff.buffer.slice(i2 - 64)) : new Uint8Array(0);
1989            return this;
1990          };
1991          SparkMD53.ArrayBuffer.prototype.end = function(raw) {
1992            var buff = this._buff, length = buff.length, tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], i2, ret;
1993            for (i2 = 0; i2 < length; i2 += 1) {
1994              tail[i2 >> 2] |= buff[i2] << (i2 % 4 << 3);
1995            }
1996            this._finish(tail, length);
1997            ret = hex(this._hash);
1998            if (raw) {
1999              ret = hexToBinaryString(ret);
2000            }
2001            this.reset();
2002            return ret;
2003          };
2004          SparkMD53.ArrayBuffer.prototype.reset = function() {
2005            this._buff = new Uint8Array(0);
2006            this._length = 0;
2007            this._hash = [1732584193, -271733879, -1732584194, 271733878];
2008            return this;
2009          };
2010          SparkMD53.ArrayBuffer.prototype.getState = function() {
2011            var state = SparkMD53.prototype.getState.call(this);
2012            state.buff = arrayBuffer2Utf8Str(state.buff);
2013            return state;
2014          };
2015          SparkMD53.ArrayBuffer.prototype.setState = function(state) {
2016            state.buff = utf8Str2ArrayBuffer(state.buff, true);
2017            return SparkMD53.prototype.setState.call(this, state);
2018          };
2019          SparkMD53.ArrayBuffer.prototype.destroy = SparkMD53.prototype.destroy;
2020          SparkMD53.ArrayBuffer.prototype._finish = SparkMD53.prototype._finish;
2021          SparkMD53.ArrayBuffer.hash = function(arr, raw) {
2022            var hash = md51_array(new Uint8Array(arr)), ret = hex(hash);
2023            return raw ? hexToBinaryString(ret) : ret;
2024          };
2025          return SparkMD53;
2026        });
2027      })(sparkMd5);
2028      SparkMD5 = sparkMd5.exports;
2029      fileSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice;
2030      FileChecksum = class _FileChecksum {
2031        static create(file, callback) {
2032          const instance = new _FileChecksum(file);
2033          instance.create(callback);
2034        }
2035        constructor(file) {
2036          this.file = file;
2037          this.chunkSize = 2097152;
2038          this.chunkCount = Math.ceil(this.file.size / this.chunkSize);
2039          this.chunkIndex = 0;
2040        }
2041        create(callback) {
2042          this.callback = callback;
2043          this.md5Buffer = new SparkMD5.ArrayBuffer();
2044          this.fileReader = new FileReader();
2045          this.fileReader.addEventListener("load", (event) => this.fileReaderDidLoad(event));
2046          this.fileReader.addEventListener("error", (event) => this.fileReaderDidError(event));
2047          this.readNextChunk();
2048        }
2049        fileReaderDidLoad(event) {
2050          this.md5Buffer.append(event.target.result);
2051          if (!this.readNextChunk()) {
2052            const binaryDigest = this.md5Buffer.end(true);
2053            const base64digest = btoa(binaryDigest);
2054            this.callback(null, base64digest);
2055          }
2056        }
2057        fileReaderDidError(event) {
2058          this.callback(`Error reading ${this.file.name}`);
2059        }
2060        readNextChunk() {
2061          if (this.chunkIndex < this.chunkCount || this.chunkIndex == 0 && this.chunkCount == 0) {
2062            const start3 = this.chunkIndex * this.chunkSize;
2063            const end = Math.min(start3 + this.chunkSize, this.file.size);
2064            const bytes = fileSlice.call(this.file, start3, end);
2065            this.fileReader.readAsArrayBuffer(bytes);
2066            this.chunkIndex++;
2067            return true;
2068          } else {
2069            return false;
2070          }
2071        }
2072      };
2073      BlobRecord = class {
2074        constructor(file, checksum, url, customHeaders = {}) {
2075          this.file = file;
2076          this.attributes = {
2077            filename: file.name,
2078            content_type: file.type || "application/octet-stream",
2079            byte_size: file.size,
2080            checksum
2081          };
2082          this.xhr = new XMLHttpRequest();
2083          this.xhr.open("POST", url, true);
2084          this.xhr.responseType = "json";
2085          this.xhr.setRequestHeader("Content-Type", "application/json");
2086          this.xhr.setRequestHeader("Accept", "application/json");
2087          this.xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
2088          Object.keys(customHeaders).forEach((headerKey) => {
2089            this.xhr.setRequestHeader(headerKey, customHeaders[headerKey]);
2090          });
2091          const csrfToken = getMetaValue("csrf-token");
2092          if (csrfToken != void 0) {
2093            this.xhr.setRequestHeader("X-CSRF-Token", csrfToken);
2094          }
2095          this.xhr.addEventListener("load", (event) => this.requestDidLoad(event));
2096          this.xhr.addEventListener("error", (event) => this.requestDidError(event));
2097        }
2098        get status() {
2099          return this.xhr.status;
2100        }
2101        get response() {
2102          const { responseType, response } = this.xhr;
2103          if (responseType == "json") {
2104            return response;
2105          } else {
2106            return JSON.parse(response);
2107          }
2108        }
2109        create(callback) {
2110          this.callback = callback;
2111          this.xhr.send(JSON.stringify({
2112            blob: this.attributes
2113          }));
2114        }
2115        requestDidLoad(event) {
2116          if (this.status >= 200 && this.status < 300) {
2117            const { response } = this;
2118            const { direct_upload } = response;
2119            delete response.direct_upload;
2120            this.attributes = response;
2121            this.directUploadData = direct_upload;
2122            this.callback(null, this.toJSON());
2123          } else {
2124            this.requestDidError(event);
2125          }
2126        }
2127        requestDidError(event) {
2128          this.callback(`Error creating Blob for "${this.file.name}". Status: ${this.status}`);
2129        }
2130        toJSON() {
2131          const result = {};
2132          for (const key in this.attributes) {
2133            result[key] = this.attributes[key];
2134          }
2135          return result;
2136        }
2137      };
2138      BlobUpload = class {
2139        constructor(blob) {
2140          this.blob = blob;
2141          this.file = blob.file;
2142          const { url, headers } = blob.directUploadData;
2143          this.xhr = new XMLHttpRequest();
2144          this.xhr.open("PUT", url, true);
2145          this.xhr.responseType = "text";
2146          for (const key in headers) {
2147            this.xhr.setRequestHeader(key, headers[key]);
2148          }
2149          this.xhr.addEventListener("load", (event) => this.requestDidLoad(event));
2150          this.xhr.addEventListener("error", (event) => this.requestDidError(event));
2151        }
2152        create(callback) {
2153          this.callback = callback;
2154          this.xhr.send(this.file.slice());
2155        }
2156        requestDidLoad(event) {
2157          const { status, response } = this.xhr;
2158          if (status >= 200 && status < 300) {
2159            this.callback(null, response);
2160          } else {
2161            this.requestDidError(event);
2162          }
2163        }
2164        requestDidError(event) {
2165          this.callback(`Error storing "${this.file.name}". Status: ${this.xhr.status}`);
2166        }
2167      };
2168      id = 0;
2169      DirectUpload = class {
2170        constructor(file, url, delegate, customHeaders = {}) {
2171          this.id = ++id;
2172          this.file = file;
2173          this.url = url;
2174          this.delegate = delegate;
2175          this.customHeaders = customHeaders;
2176        }
2177        create(callback) {
2178          FileChecksum.create(this.file, (error, checksum) => {
2179            if (error) {
2180              callback(error);
2181              return;
2182            }
2183            const blob = new BlobRecord(this.file, checksum, this.url, this.customHeaders);
2184            notify(this.delegate, "directUploadWillCreateBlobWithXHR", blob.xhr);
2185            blob.create((error2) => {
2186              if (error2) {
2187                callback(error2);
2188              } else {
2189                const upload = new BlobUpload(blob);
2190                notify(this.delegate, "directUploadWillStoreFileWithXHR", upload.xhr);
2191                upload.create((error3) => {
2192                  if (error3) {
2193                    callback(error3);
2194                  } else {
2195                    callback(null, blob.toJSON());
2196                  }
2197                });
2198              }
2199            });
2200          });
2201        }
2202      };
2203      DirectUploadController = class {
2204        constructor(input, file) {
2205          this.input = input;
2206          this.file = file;
2207          this.directUpload = new DirectUpload(this.file, this.url, this);
2208          this.dispatch("initialize");
2209        }
2210        start(callback) {
2211          const hiddenInput = document.createElement("input");
2212          hiddenInput.type = "hidden";
2213          hiddenInput.name = this.input.name;
2214          this.input.insertAdjacentElement("beforebegin", hiddenInput);
2215          this.dispatch("start");
2216          this.directUpload.create((error, attributes) => {
2217            if (error) {
2218              hiddenInput.parentNode.removeChild(hiddenInput);
2219              this.dispatchError(error);
2220            } else {
2221              hiddenInput.value = attributes.signed_id;
2222            }
2223            this.dispatch("end");
2224            callback(error);
2225          });
2226        }
2227        uploadRequestDidProgress(event) {
2228          const progress = event.loaded / event.total * 90;
2229          if (progress) {
2230            this.dispatch("progress", {
2231              progress
2232            });
2233          }
2234        }
2235        get url() {
2236          return this.input.getAttribute("data-direct-upload-url");
2237        }
2238        dispatch(name, detail = {}) {
2239          detail.file = this.file;
2240          detail.id = this.directUpload.id;
2241          return dispatchEvent(this.input, `direct-upload:${name}`, {
2242            detail
2243          });
2244        }
2245        dispatchError(error) {
2246          const event = this.dispatch("error", {
2247            error
2248          });
2249          if (!event.defaultPrevented) {
2250            alert(error);
2251          }
2252        }
2253        directUploadWillCreateBlobWithXHR(xhr) {
2254          this.dispatch("before-blob-request", {
2255            xhr
2256          });
2257        }
2258        directUploadWillStoreFileWithXHR(xhr) {
2259          this.dispatch("before-storage-request", {
2260            xhr
2261          });
2262          xhr.upload.addEventListener("progress", (event) => this.uploadRequestDidProgress(event));
2263          xhr.upload.addEventListener("loadend", () => {
2264            this.simulateResponseProgress(xhr);
2265          });
2266        }
2267        simulateResponseProgress(xhr) {
2268          let progress = 90;
2269          const startTime = Date.now();
2270          const updateProgress = () => {
2271            const elapsed = Date.now() - startTime;
2272            const estimatedResponseTime = this.estimateResponseTime();
2273            const responseProgress = Math.min(elapsed / estimatedResponseTime, 1);
2274            progress = 90 + responseProgress * 9;
2275            this.dispatch("progress", {
2276              progress
2277            });
2278            if (xhr.readyState !== XMLHttpRequest.DONE && progress < 99) {
2279              requestAnimationFrame(updateProgress);
2280            }
2281          };
2282          xhr.addEventListener("loadend", () => {
2283            this.dispatch("progress", {
2284              progress: 100
2285            });
2286          });
2287          requestAnimationFrame(updateProgress);
2288        }
2289        estimateResponseTime() {
2290          const fileSize = this.file.size;
2291          const MB = 1024 * 1024;
2292          if (fileSize < MB) {
2293            return 1e3;
2294          } else if (fileSize < 10 * MB) {
2295            return 2e3;
2296          } else {
2297            return 3e3 + fileSize / MB * 50;
2298          }
2299        }
2300      };
2301      inputSelector = "input[type=file][data-direct-upload-url]:not([disabled])";
2302      DirectUploadsController = class {
2303        constructor(form) {
2304          this.form = form;
2305          this.inputs = findElements(form, inputSelector).filter((input) => input.files.length);
2306        }
2307        start(callback) {
2308          const controllers = this.createDirectUploadControllers();
2309          const startNextController = () => {
2310            const controller = controllers.shift();
2311            if (controller) {
2312              controller.start((error) => {
2313                if (error) {
2314                  callback(error);
2315                  this.dispatch("end");
2316                } else {
2317                  startNextController();
2318                }
2319              });
2320            } else {
2321              callback();
2322              this.dispatch("end");
2323            }
2324          };
2325          this.dispatch("start");
2326          startNextController();
2327        }
2328        createDirectUploadControllers() {
2329          const controllers = [];
2330          this.inputs.forEach((input) => {
2331            toArray(input.files).forEach((file) => {
2332              const controller = new DirectUploadController(input, file);
2333              controllers.push(controller);
2334            });
2335          });
2336          return controllers;
2337        }
2338        dispatch(name, detail = {}) {
2339          return dispatchEvent(this.form, `direct-uploads:${name}`, {
2340            detail
2341          });
2342        }
2343      };
2344      processingAttribute = "data-direct-uploads-processing";
2345      submitButtonsByForm = /* @__PURE__ */ new WeakMap();
2346      started = false;
2347      setTimeout(autostart, 1);
2348    }
2349  });
2350
2351  
vendor: 38,053 bytes, lines 2351-3317
2351// node_modules/@rails/actiontext/app/assets/javascripts/actiontext.esm.js
2352  var actiontext_esm_exports = {};
2353  __export(actiontext_esm_exports, {
2354    AttachmentUpload: () => AttachmentUpload
2355  });
2356  function getMetaValue2(name) {
2357    const element = findElement2(document.head, `meta[name="${name}"]`);
2358    if (element) {
2359      return element.getAttribute("content");
2360    }
2361  }
2362  function findElements2(root, selector) {
2363    if (typeof root == "string") {
2364      selector = root;
2365      root = document;
2366    }
2367    const elements = root.querySelectorAll(selector);
2368    return toArray2(elements);
2369  }
2370  function findElement2(root, selector) {
2371    if (typeof root == "string") {
2372      selector = root;
2373      root = document;
2374    }
2375    return root.querySelector(selector);
2376  }
2377  function dispatchEvent2(element, type, eventInit = {}) {
2378    const { disabled } = element;
2379    const { bubbles, cancelable, detail } = eventInit;
2380    const event = document.createEvent("Event");
2381    event.initEvent(type, bubbles || true, cancelable || true);
2382    event.detail = detail || {};
2383    try {
2384      element.disabled = false;
2385      element.dispatchEvent(event);
2386    } finally {
2387      element.disabled = disabled;
2388    }
2389    return event;
2390  }
2391  function toArray2(value) {
2392    if (Array.isArray(value)) {
2393      return value;
2394    } else if (Array.from) {
2395      return Array.from(value);
2396    } else {
2397      return [].slice.call(value);
2398    }
2399  }
2400  function notify2(object, methodName, ...messages) {
2401    if (object && typeof object[methodName] == "function") {
2402      return object[methodName](...messages);
2403    }
2404  }
2405  function start2() {
2406    if (!started2) {
2407      started2 = true;
2408      document.addEventListener("click", didClick2, true);
2409      document.addEventListener("submit", didSubmitForm2, true);
2410      document.addEventListener("ajax:before", didSubmitRemoteElement2);
2411    }
2412  }
2413  function didClick2(event) {
2414    const button = event.target.closest("button, input");
2415    if (button && button.type === "submit" && button.form) {
2416      submitButtonsByForm2.set(button.form, button);
2417    }
2418  }
2419  function didSubmitForm2(event) {
2420    handleFormSubmissionEvent2(event);
2421  }
2422  function didSubmitRemoteElement2(event) {
2423    if (event.target.tagName == "FORM") {
2424      handleFormSubmissionEvent2(event);
2425    }
2426  }
2427  function handleFormSubmissionEvent2(event) {
2428    const form = event.target;
2429    if (form.hasAttribute(processingAttribute2)) {
2430      event.preventDefault();
2431      return;
2432    }
2433    const controller = new DirectUploadsController2(form);
2434    const { inputs } = controller;
2435    if (inputs.length) {
2436      event.preventDefault();
2437      form.setAttribute(processingAttribute2, "");
2438      inputs.forEach(disable2);
2439      controller.start((error) => {
2440        form.removeAttribute(processingAttribute2);
2441        if (error) {
2442          inputs.forEach(enable2);
2443        } else {
2444          submitForm2(form);
2445        }
2446      });
2447    }
2448  }
2449  function submitForm2(form) {
2450    let button = submitButtonsByForm2.get(form) || findElement2(form, "input[type=submit], button[type=submit]");
2451    if (button) {
2452      const { disabled } = button;
2453      button.disabled = false;
2454      button.focus();
2455      button.click();
2456      button.disabled = disabled;
2457    } else {
2458      button = document.createElement("input");
2459      button.type = "submit";
2460      button.style.display = "none";
2461      form.appendChild(button);
2462      button.click();
2463      form.removeChild(button);
2464    }
2465    submitButtonsByForm2.delete(form);
2466  }
2467  function disable2(input) {
2468    input.disabled = true;
2469  }
2470  function enable2(input) {
2471    input.disabled = false;
2472  }
2473  function autostart2() {
2474    if (window.ActiveStorage) {
2475      start2();
2476    }
2477  }
2478  var sparkMd52, SparkMD52, fileSlice2, FileChecksum2, BlobRecord2, BlobUpload2, id2, DirectUpload2, DirectUploadController2, inputSelector2, DirectUploadsController2, processingAttribute2, submitButtonsByForm2, started2, AttachmentUpload;
2479  var init_actiontext_esm = __esm({
2480    "node_modules/@rails/actiontext/app/assets/javascripts/actiontext.esm.js"() {
2481      sparkMd52 = {
2482        exports: {}
2483      };
2484      (function(module, exports) {
2485        (function(factory) {
2486          {
2487            module.exports = factory();
2488          }
2489        })(function(undefined$1) {
2490          var hex_chr = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"];
2491          function md5cycle(x3, k2) {
2492            var a2 = x3[0], b3 = x3[1], c2 = x3[2], d3 = x3[3];
2493            a2 += (b3 & c2 | ~b3 & d3) + k2[0] - 680876936 | 0;
2494            a2 = (a2 << 7 | a2 >>> 25) + b3 | 0;
2495            d3 += (a2 & b3 | ~a2 & c2) + k2[1] - 389564586 | 0;
2496            d3 = (d3 << 12 | d3 >>> 20) + a2 | 0;
2497            c2 += (d3 & a2 | ~d3 & b3) + k2[2] + 606105819 | 0;
2498            c2 = (c2 << 17 | c2 >>> 15) + d3 | 0;
2499            b3 += (c2 & d3 | ~c2 & a2) + k2[3] - 1044525330 | 0;
2500            b3 = (b3 << 22 | b3 >>> 10) + c2 | 0;
2501            a2 += (b3 & c2 | ~b3 & d3) + k2[4] - 176418897 | 0;
2502            a2 = (a2 << 7 | a2 >>> 25) + b3 | 0;
2503            d3 += (a2 & b3 | ~a2 & c2) + k2[5] + 1200080426 | 0;
2504            d3 = (d3 << 12 | d3 >>> 20) + a2 | 0;
2505            c2 += (d3 & a2 | ~d3 & b3) + k2[6] - 1473231341 | 0;
2506            c2 = (c2 << 17 | c2 >>> 15) + d3 | 0;
2507            b3 += (c2 & d3 | ~c2 & a2) + k2[7] - 45705983 | 0;
2508            b3 = (b3 << 22 | b3 >>> 10) + c2 | 0;
2509            a2 += (b3 & c2 | ~b3 & d3) + k2[8] + 1770035416 | 0;
2510            a2 = (a2 << 7 | a2 >>> 25) + b3 | 0;
2511            d3 += (a2 & b3 | ~a2 & c2) + k2[9] - 1958414417 | 0;
2512            d3 = (d3 << 12 | d3 >>> 20) + a2 | 0;
2513            c2 += (d3 & a2 | ~d3 & b3) + k2[10] - 42063 | 0;
2514            c2 = (c2 << 17 | c2 >>> 15) + d3 | 0;
2515            b3 += (c2 & d3 | ~c2 & a2) + k2[11] - 1990404162 | 0;
2516            b3 = (b3 << 22 | b3 >>> 10) + c2 | 0;
2517            a2 += (b3 & c2 | ~b3 & d3) + k2[12] + 1804603682 | 0;
2518            a2 = (a2 << 7 | a2 >>> 25) + b3 | 0;
2519            d3 += (a2 & b3 | ~a2 & c2) + k2[13] - 40341101 | 0;
2520            d3 = (d3 << 12 | d3 >>> 20) + a2 | 0;
2521            c2 += (d3 & a2 | ~d3 & b3) + k2[14] - 1502002290 | 0;
2522            c2 = (c2 << 17 | c2 >>> 15) + d3 | 0;
2523            b3 += (c2 & d3 | ~c2 & a2) + k2[15] + 1236535329 | 0;
2524            b3 = (b3 << 22 | b3 >>> 10) + c2 | 0;
2525            a2 += (b3 & d3 | c2 & ~d3) + k2[1] - 165796510 | 0;
2526            a2 = (a2 << 5 | a2 >>> 27) + b3 | 0;
2527            d3 += (a2 & c2 | b3 & ~c2) + k2[6] - 1069501632 | 0;
2528            d3 = (d3 << 9 | d3 >>> 23) + a2 | 0;
2529            c2 += (d3 & b3 | a2 & ~b3) + k2[11] + 643717713 | 0;
2530            c2 = (c2 << 14 | c2 >>> 18) + d3 | 0;
2531            b3 += (c2 & a2 | d3 & ~a2) + k2[0] - 373897302 | 0;
2532            b3 = (b3 << 20 | b3 >>> 12) + c2 | 0;
2533            a2 += (b3 & d3 | c2 & ~d3) + k2[5] - 701558691 | 0;
2534            a2 = (a2 << 5 | a2 >>> 27) + b3 | 0;
2535            d3 += (a2 & c2 | b3 & ~c2) + k2[10] + 38016083 | 0;
2536            d3 = (d3 << 9 | d3 >>> 23) + a2 | 0;
2537            c2 += (d3 & b3 | a2 & ~b3) + k2[15] - 660478335 | 0;
2538            c2 = (c2 << 14 | c2 >>> 18) + d3 | 0;
2539            b3 += (c2 & a2 | d3 & ~a2) + k2[4] - 405537848 | 0;
2540            b3 = (b3 << 20 | b3 >>> 12) + c2 | 0;
2541            a2 += (b3 & d3 | c2 & ~d3) + k2[9] + 568446438 | 0;
2542            a2 = (a2 << 5 | a2 >>> 27) + b3 | 0;
2543            d3 += (a2 & c2 | b3 & ~c2) + k2[14] - 1019803690 | 0;
2544            d3 = (d3 << 9 | d3 >>> 23) + a2 | 0;
2545            c2 += (d3 & b3 | a2 & ~b3) + k2[3] - 187363961 | 0;
2546            c2 = (c2 << 14 | c2 >>> 18) + d3 | 0;
2547            b3 += (c2 & a2 | d3 & ~a2) + k2[8] + 1163531501 | 0;
2548            b3 = (b3 << 20 | b3 >>> 12) + c2 | 0;
2549            a2 += (b3 & d3 | c2 & ~d3) + k2[13] - 1444681467 | 0;
2550            a2 = (a2 << 5 | a2 >>> 27) + b3 | 0;
2551            d3 += (a2 & c2 | b3 & ~c2) + k2[2] - 51403784 | 0;
2552            d3 = (d3 << 9 | d3 >>> 23) + a2 | 0;
2553            c2 += (d3 & b3 | a2 & ~b3) + k2[7] + 1735328473 | 0;
2554            c2 = (c2 << 14 | c2 >>> 18) + d3 | 0;
2555            b3 += (c2 & a2 | d3 & ~a2) + k2[12] - 1926607734 | 0;
2556            b3 = (b3 << 20 | b3 >>> 12) + c2 | 0;
2557            a2 += (b3 ^ c2 ^ d3) + k2[5] - 378558 | 0;
2558            a2 = (a2 << 4 | a2 >>> 28) + b3 | 0;
2559            d3 += (a2 ^ b3 ^ c2) + k2[8] - 2022574463 | 0;
2560            d3 = (d3 << 11 | d3 >>> 21) + a2 | 0;
2561            c2 += (d3 ^ a2 ^ b3) + k2[11] + 1839030562 | 0;
2562            c2 = (c2 << 16 | c2 >>> 16) + d3 | 0;
2563            b3 += (c2 ^ d3 ^ a2) + k2[14] - 35309556 | 0;
2564            b3 = (b3 << 23 | b3 >>> 9) + c2 | 0;
2565            a2 += (b3 ^ c2 ^ d3) + k2[1] - 1530992060 | 0;
2566            a2 = (a2 << 4 | a2 >>> 28) + b3 | 0;
2567            d3 += (a2 ^ b3 ^ c2) + k2[4] + 1272893353 | 0;
2568            d3 = (d3 << 11 | d3 >>> 21) + a2 | 0;
2569            c2 += (d3 ^ a2 ^ b3) + k2[7] - 155497632 | 0;
2570            c2 = (c2 << 16 | c2 >>> 16) + d3 | 0;
2571            b3 += (c2 ^ d3 ^ a2) + k2[10] - 1094730640 | 0;
2572            b3 = (b3 << 23 | b3 >>> 9) + c2 | 0;
2573            a2 += (b3 ^ c2 ^ d3) + k2[13] + 681279174 | 0;
2574            a2 = (a2 << 4 | a2 >>> 28) + b3 | 0;
2575            d3 += (a2 ^ b3 ^ c2) + k2[0] - 358537222 | 0;
2576            d3 = (d3 << 11 | d3 >>> 21) + a2 | 0;
2577            c2 += (d3 ^ a2 ^ b3) + k2[3] - 722521979 | 0;
2578            c2 = (c2 << 16 | c2 >>> 16) + d3 | 0;
2579            b3 += (c2 ^ d3 ^ a2) + k2[6] + 76029189 | 0;
2580            b3 = (b3 << 23 | b3 >>> 9) + c2 | 0;
2581            a2 += (b3 ^ c2 ^ d3) + k2[9] - 640364487 | 0;
2582            a2 = (a2 << 4 | a2 >>> 28) + b3 | 0;
2583            d3 += (a2 ^ b3 ^ c2) + k2[12] - 421815835 | 0;
2584            d3 = (d3 << 11 | d3 >>> 21) + a2 | 0;
2585            c2 += (d3 ^ a2 ^ b3) + k2[15] + 530742520 | 0;
2586            c2 = (c2 << 16 | c2 >>> 16) + d3 | 0;
2587            b3 += (c2 ^ d3 ^ a2) + k2[2] - 995338651 | 0;
2588            b3 = (b3 << 23 | b3 >>> 9) + c2 | 0;
2589            a2 += (c2 ^ (b3 | ~d3)) + k2[0] - 198630844 | 0;
2590            a2 = (a2 << 6 | a2 >>> 26) + b3 | 0;
2591            d3 += (b3 ^ (a2 | ~c2)) + k2[7] + 1126891415 | 0;
2592            d3 = (d3 << 10 | d3 >>> 22) + a2 | 0;
2593            c2 += (a2 ^ (d3 | ~b3)) + k2[14] - 1416354905 | 0;
2594            c2 = (c2 << 15 | c2 >>> 17) + d3 | 0;
2595            b3 += (d3 ^ (c2 | ~a2)) + k2[5] - 57434055 | 0;
2596            b3 = (b3 << 21 | b3 >>> 11) + c2 | 0;
2597            a2 += (c2 ^ (b3 | ~d3)) + k2[12] + 1700485571 | 0;
2598            a2 = (a2 << 6 | a2 >>> 26) + b3 | 0;
2599            d3 += (b3 ^ (a2 | ~c2)) + k2[3] - 1894986606 | 0;
2600            d3 = (d3 << 10 | d3 >>> 22) + a2 | 0;
2601            c2 += (a2 ^ (d3 | ~b3)) + k2[10] - 1051523 | 0;
2602            c2 = (c2 << 15 | c2 >>> 17) + d3 | 0;
2603            b3 += (d3 ^ (c2 | ~a2)) + k2[1] - 2054922799 | 0;
2604            b3 = (b3 << 21 | b3 >>> 11) + c2 | 0;
2605            a2 += (c2 ^ (b3 | ~d3)) + k2[8] + 1873313359 | 0;
2606            a2 = (a2 << 6 | a2 >>> 26) + b3 | 0;
2607            d3 += (b3 ^ (a2 | ~c2)) + k2[15] - 30611744 | 0;
2608            d3 = (d3 << 10 | d3 >>> 22) + a2 | 0;
2609            c2 += (a2 ^ (d3 | ~b3)) + k2[6] - 1560198380 | 0;
2610            c2 = (c2 << 15 | c2 >>> 17) + d3 | 0;
2611            b3 += (d3 ^ (c2 | ~a2)) + k2[13] + 1309151649 | 0;
2612            b3 = (b3 << 21 | b3 >>> 11) + c2 | 0;
2613            a2 += (c2 ^ (b3 | ~d3)) + k2[4] - 145523070 | 0;
2614            a2 = (a2 << 6 | a2 >>> 26) + b3 | 0;
2615            d3 += (b3 ^ (a2 | ~c2)) + k2[11] - 1120210379 | 0;
2616            d3 = (d3 << 10 | d3 >>> 22) + a2 | 0;
2617            c2 += (a2 ^ (d3 | ~b3)) + k2[2] + 718787259 | 0;
2618            c2 = (c2 << 15 | c2 >>> 17) + d3 | 0;
2619            b3 += (d3 ^ (c2 | ~a2)) + k2[9] - 343485551 | 0;
2620            b3 = (b3 << 21 | b3 >>> 11) + c2 | 0;
2621            x3[0] = a2 + x3[0] | 0;
2622            x3[1] = b3 + x3[1] | 0;
2623            x3[2] = c2 + x3[2] | 0;
2624            x3[3] = d3 + x3[3] | 0;
2625          }
2626          function md5blk(s2) {
2627            var md5blks = [], i2;
2628            for (i2 = 0; i2 < 64; i2 += 4) {
2629              md5blks[i2 >> 2] = s2.charCodeAt(i2) + (s2.charCodeAt(i2 + 1) << 8) + (s2.charCodeAt(i2 + 2) << 16) + (s2.charCodeAt(i2 + 3) << 24);
2630            }
2631            return md5blks;
2632          }
2633          function md5blk_array(a2) {
2634            var md5blks = [], i2;
2635            for (i2 = 0; i2 < 64; i2 += 4) {
2636              md5blks[i2 >> 2] = a2[i2] + (a2[i2 + 1] << 8) + (a2[i2 + 2] << 16) + (a2[i2 + 3] << 24);
2637            }
2638            return md5blks;
2639          }
2640          function md51(s2) {
2641            var n2 = s2.length, state = [1732584193, -271733879, -1732584194, 271733878], i2, length, tail, tmp, lo, hi;
2642            for (i2 = 64; i2 <= n2; i2 += 64) {
2643              md5cycle(state, md5blk(s2.substring(i2 - 64, i2)));
2644            }
2645            s2 = s2.substring(i2 - 64);
2646            length = s2.length;
2647            tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
2648            for (i2 = 0; i2 < length; i2 += 1) {
2649              tail[i2 >> 2] |= s2.charCodeAt(i2) << (i2 % 4 << 3);
2650            }
2651            tail[i2 >> 2] |= 128 << (i2 % 4 << 3);
2652            if (i2 > 55) {
2653              md5cycle(state, tail);
2654              for (i2 = 0; i2 < 16; i2 += 1) {
2655                tail[i2] = 0;
2656              }
2657            }
2658            tmp = n2 * 8;
2659            tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
2660            lo = parseInt(tmp[2], 16);
2661            hi = parseInt(tmp[1], 16) || 0;
2662            tail[14] = lo;
2663            tail[15] = hi;
2664            md5cycle(state, tail);
2665            return state;
2666          }
2667          function md51_array(a2) {
2668            var n2 = a2.length, state = [1732584193, -271733879, -1732584194, 271733878], i2, length, tail, tmp, lo, hi;
2669            for (i2 = 64; i2 <= n2; i2 += 64) {
2670              md5cycle(state, md5blk_array(a2.subarray(i2 - 64, i2)));
2671            }
2672            a2 = i2 - 64 < n2 ? a2.subarray(i2 - 64) : new Uint8Array(0);
2673            length = a2.length;
2674            tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
2675            for (i2 = 0; i2 < length; i2 += 1) {
2676              tail[i2 >> 2] |= a2[i2] << (i2 % 4 << 3);
2677            }
2678            tail[i2 >> 2] |= 128 << (i2 % 4 << 3);
2679            if (i2 > 55) {
2680              md5cycle(state, tail);
2681              for (i2 = 0; i2 < 16; i2 += 1) {
2682                tail[i2] = 0;
2683              }
2684            }
2685            tmp = n2 * 8;
2686            tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
2687            lo = parseInt(tmp[2], 16);
2688            hi = parseInt(tmp[1], 16) || 0;
2689            tail[14] = lo;
2690            tail[15] = hi;
2691            md5cycle(state, tail);
2692            return state;
2693          }
2694          function rhex(n2) {
2695            var s2 = "", j3;
2696            for (j3 = 0; j3 < 4; j3 += 1) {
2697              s2 += hex_chr[n2 >> j3 * 8 + 4 & 15] + hex_chr[n2 >> j3 * 8 & 15];
2698            }
2699            return s2;
2700          }
2701          function hex(x3) {
2702            var i2;
2703            for (i2 = 0; i2 < x3.length; i2 += 1) {
2704              x3[i2] = rhex(x3[i2]);
2705            }
2706            return x3.join("");
2707          }
2708          if (hex(md51("hello")) !== "5d41402abc4b2a76b9719d911017c592") ;
2709          if (typeof ArrayBuffer !== "undefined" && !ArrayBuffer.prototype.slice) {
2710            (function() {
2711              function clamp2(val, length) {
2712                val = val | 0 || 0;
2713                if (val < 0) {
2714                  return Math.max(val + length, 0);
2715                }
2716                return Math.min(val, length);
2717              }
2718              ArrayBuffer.prototype.slice = function(from, to) {
2719                var length = this.byteLength, begin = clamp2(from, length), end = length, num, target, targetArray, sourceArray;
2720                if (to !== undefined$1) {
2721                  end = clamp2(to, length);
2722                }
2723                if (begin > end) {
2724                  return new ArrayBuffer(0);
2725                }
2726                num = end - begin;
2727                target = new ArrayBuffer(num);
2728                targetArray = new Uint8Array(target);
2729                sourceArray = new Uint8Array(this, begin, num);
2730                targetArray.set(sourceArray);
2731                return target;
2732              };
2733            })();
2734          }
2735          function toUtf8(str) {
2736            if (/[\u0080-\uFFFF]/.test(str)) {
2737              str = unescape(encodeURIComponent(str));
2738            }
2739            return str;
2740          }
2741          function utf8Str2ArrayBuffer(str, returnUInt8Array) {
2742            var length = str.length, buff = new ArrayBuffer(length), arr = new Uint8Array(buff), i2;
2743            for (i2 = 0; i2 < length; i2 += 1) {
2744              arr[i2] = str.charCodeAt(i2);
2745            }
2746            return returnUInt8Array ? arr : buff;
2747          }
2748          function arrayBuffer2Utf8Str(buff) {
2749            return String.fromCharCode.apply(null, new Uint8Array(buff));
2750          }
2751          function concatenateArrayBuffers(first, second, returnUInt8Array) {
2752            var result = new Uint8Array(first.byteLength + second.byteLength);
2753            result.set(new Uint8Array(first));
2754            result.set(new Uint8Array(second), first.byteLength);
2755            return returnUInt8Array ? result : result.buffer;
2756          }
2757          function hexToBinaryString(hex2) {
2758            var bytes = [], length = hex2.length, x3;
2759            for (x3 = 0; x3 < length - 1; x3 += 2) {
2760              bytes.push(parseInt(hex2.substr(x3, 2), 16));
2761            }
2762            return String.fromCharCode.apply(String, bytes);
2763          }
2764          function SparkMD53() {
2765            this.reset();
2766          }
2767          SparkMD53.prototype.append = function(str) {
2768            this.appendBinary(toUtf8(str));
2769            return this;
2770          };
2771          SparkMD53.prototype.appendBinary = function(contents) {
2772            this._buff += contents;
2773            this._length += contents.length;
2774            var length = this._buff.length, i2;
2775            for (i2 = 64; i2 <= length; i2 += 64) {
2776              md5cycle(this._hash, md5blk(this._buff.substring(i2 - 64, i2)));
2777            }
2778            this._buff = this._buff.substring(i2 - 64);
2779            return this;
2780          };
2781          SparkMD53.prototype.end = function(raw) {
2782            var buff = this._buff, length = buff.length, i2, tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], ret;
2783            for (i2 = 0; i2 < length; i2 += 1) {
2784              tail[i2 >> 2] |= buff.charCodeAt(i2) << (i2 % 4 << 3);
2785            }
2786            this._finish(tail, length);
2787            ret = hex(this._hash);
2788            if (raw) {
2789              ret = hexToBinaryString(ret);
2790            }
2791            this.reset();
2792            return ret;
2793          };
2794          SparkMD53.prototype.reset = function() {
2795            this._buff = "";
2796            this._length = 0;
2797            this._hash = [1732584193, -271733879, -1732584194, 271733878];
2798            return this;
2799          };
2800          SparkMD53.prototype.getState = function() {
2801            return {
2802              buff: this._buff,
2803              length: this._length,
2804              hash: this._hash.slice()
2805            };
2806          };
2807          SparkMD53.prototype.setState = function(state) {
2808            this._buff = state.buff;
2809            this._length = state.length;
2810            this._hash = state.hash;
2811            return this;
2812          };
2813          SparkMD53.prototype.destroy = function() {
2814            delete this._hash;
2815            delete this._buff;
2816            delete this._length;
2817          };
2818          SparkMD53.prototype._finish = function(tail, length) {
2819            var i2 = length, tmp, lo, hi;
2820            tail[i2 >> 2] |= 128 << (i2 % 4 << 3);
2821            if (i2 > 55) {
2822              md5cycle(this._hash, tail);
2823              for (i2 = 0; i2 < 16; i2 += 1) {
2824                tail[i2] = 0;
2825              }
2826            }
2827            tmp = this._length * 8;
2828            tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
2829            lo = parseInt(tmp[2], 16);
2830            hi = parseInt(tmp[1], 16) || 0;
2831            tail[14] = lo;
2832            tail[15] = hi;
2833            md5cycle(this._hash, tail);
2834          };
2835          SparkMD53.hash = function(str, raw) {
2836            return SparkMD53.hashBinary(toUtf8(str), raw);
2837          };
2838          SparkMD53.hashBinary = function(content, raw) {
2839            var hash = md51(content), ret = hex(hash);
2840            return raw ? hexToBinaryString(ret) : ret;
2841          };
2842          SparkMD53.ArrayBuffer = function() {
2843            this.reset();
2844          };
2845          SparkMD53.ArrayBuffer.prototype.append = function(arr) {
2846            var buff = concatenateArrayBuffers(this._buff.buffer, arr, true), length = buff.length, i2;
2847            this._length += arr.byteLength;
2848            for (i2 = 64; i2 <= length; i2 += 64) {
2849              md5cycle(this._hash, md5blk_array(buff.subarray(i2 - 64, i2)));
2850            }
2851            this._buff = i2 - 64 < length ? new Uint8Array(buff.buffer.slice(i2 - 64)) : new Uint8Array(0);
2852            return this;
2853          };
2854          SparkMD53.ArrayBuffer.prototype.end = function(raw) {
2855            var buff = this._buff, length = buff.length, tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], i2, ret;
2856            for (i2 = 0; i2 < length; i2 += 1) {
2857              tail[i2 >> 2] |= buff[i2] << (i2 % 4 << 3);
2858            }
2859            this._finish(tail, length);
2860            ret = hex(this._hash);
2861            if (raw) {
2862              ret = hexToBinaryString(ret);
2863            }
2864            this.reset();
2865            return ret;
2866          };
2867          SparkMD53.ArrayBuffer.prototype.reset = function() {
2868            this._buff = new Uint8Array(0);
2869            this._length = 0;
2870            this._hash = [1732584193, -271733879, -1732584194, 271733878];
2871            return this;
2872          };
2873          SparkMD53.ArrayBuffer.prototype.getState = function() {
2874            var state = SparkMD53.prototype.getState.call(this);
2875            state.buff = arrayBuffer2Utf8Str(state.buff);
2876            return state;
2877          };
2878          SparkMD53.ArrayBuffer.prototype.setState = function(state) {
2879            state.buff = utf8Str2ArrayBuffer(state.buff, true);
2880            return SparkMD53.prototype.setState.call(this, state);
2881          };
2882          SparkMD53.ArrayBuffer.prototype.destroy = SparkMD53.prototype.destroy;
2883          SparkMD53.ArrayBuffer.prototype._finish = SparkMD53.prototype._finish;
2884          SparkMD53.ArrayBuffer.hash = function(arr, raw) {
2885            var hash = md51_array(new Uint8Array(arr)), ret = hex(hash);
2886            return raw ? hexToBinaryString(ret) : ret;
2887          };
2888          return SparkMD53;
2889        });
2890      })(sparkMd52);
2891      SparkMD52 = sparkMd52.exports;
2892      fileSlice2 = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice;
2893      FileChecksum2 = class _FileChecksum {
2894        static create(file, callback) {
2895          const instance = new _FileChecksum(file);
2896          instance.create(callback);
2897        }
2898        constructor(file) {
2899          this.file = file;
2900          this.chunkSize = 2097152;
2901          this.chunkCount = Math.ceil(this.file.size / this.chunkSize);
2902          this.chunkIndex = 0;
2903        }
2904        create(callback) {
2905          this.callback = callback;
2906          this.md5Buffer = new SparkMD52.ArrayBuffer();
2907          this.fileReader = new FileReader();
2908          this.fileReader.addEventListener("load", (event) => this.fileReaderDidLoad(event));
2909          this.fileReader.addEventListener("error", (event) => this.fileReaderDidError(event));
2910          this.readNextChunk();
2911        }
2912        fileReaderDidLoad(event) {
2913          this.md5Buffer.append(event.target.result);
2914          if (!this.readNextChunk()) {
2915            const binaryDigest = this.md5Buffer.end(true);
2916            const base64digest = btoa(binaryDigest);
2917            this.callback(null, base64digest);
2918          }
2919        }
2920        fileReaderDidError(event) {
2921          this.callback(`Error reading ${this.file.name}`);
2922        }
2923        readNextChunk() {
2924          if (this.chunkIndex < this.chunkCount || this.chunkIndex == 0 && this.chunkCount == 0) {
2925            const start3 = this.chunkIndex * this.chunkSize;
2926            const end = Math.min(start3 + this.chunkSize, this.file.size);
2927            const bytes = fileSlice2.call(this.file, start3, end);
2928            this.fileReader.readAsArrayBuffer(bytes);
2929            this.chunkIndex++;
2930            return true;
2931          } else {
2932            return false;
2933          }
2934        }
2935      };
2936      BlobRecord2 = class {
2937        constructor(file, checksum, url, customHeaders = {}) {
2938          this.file = file;
2939          this.attributes = {
2940            filename: file.name,
2941            content_type: file.type || "application/octet-stream",
2942            byte_size: file.size,
2943            checksum
2944          };
2945          this.xhr = new XMLHttpRequest();
2946          this.xhr.open("POST", url, true);
2947          this.xhr.responseType = "json";
2948          this.xhr.setRequestHeader("Content-Type", "application/json");
2949          this.xhr.setRequestHeader("Accept", "application/json");
2950          this.xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
2951          Object.keys(customHeaders).forEach((headerKey) => {
2952            this.xhr.setRequestHeader(headerKey, customHeaders[headerKey]);
2953          });
2954          const csrfToken = getMetaValue2("csrf-token");
2955          if (csrfToken != void 0) {
2956            this.xhr.setRequestHeader("X-CSRF-Token", csrfToken);
2957          }
2958          this.xhr.addEventListener("load", (event) => this.requestDidLoad(event));
2959          this.xhr.addEventListener("error", (event) => this.requestDidError(event));
2960        }
2961        get status() {
2962          return this.xhr.status;
2963        }
2964        get response() {
2965          const { responseType, response } = this.xhr;
2966          if (responseType == "json") {
2967            return response;
2968          } else {
2969            return JSON.parse(response);
2970          }
2971        }
2972        create(callback) {
2973          this.callback = callback;
2974          this.xhr.send(JSON.stringify({
2975            blob: this.attributes
2976          }));
2977        }
2978        requestDidLoad(event) {
2979          if (this.status >= 200 && this.status < 300) {
2980            const { response } = this;
2981            const { direct_upload } = response;
2982            delete response.direct_upload;
2983            this.attributes = response;
2984            this.directUploadData = direct_upload;
2985            this.callback(null, this.toJSON());
2986          } else {
2987            this.requestDidError(event);
2988          }
2989        }
2990        requestDidError(event) {
2991          this.callback(`Error creating Blob for "${this.file.name}". Status: ${this.status}`);
2992        }
2993        toJSON() {
2994          const result = {};
2995          for (const key in this.attributes) {
2996            result[key] = this.attributes[key];
2997          }
2998          return result;
2999        }
3000      };
3001      BlobUpload2 = class {
3002        constructor(blob) {
3003          this.blob = blob;
3004          this.file = blob.file;
3005          const { url, headers } = blob.directUploadData;
3006          this.xhr = new XMLHttpRequest();
3007          this.xhr.open("PUT", url, true);
3008          this.xhr.responseType = "text";
3009          for (const key in headers) {
3010            this.xhr.setRequestHeader(key, headers[key]);
3011          }
3012          this.xhr.addEventListener("load", (event) => this.requestDidLoad(event));
3013          this.xhr.addEventListener("error", (event) => this.requestDidError(event));
3014        }
3015        create(callback) {
3016          this.callback = callback;
3017          this.xhr.send(this.file.slice());
3018        }
3019        requestDidLoad(event) {
3020          const { status, response } = this.xhr;
3021          if (status >= 200 && status < 300) {
3022            this.callback(null, response);
3023          } else {
3024            this.requestDidError(event);
3025          }
3026        }
3027        requestDidError(event) {
3028          this.callback(`Error storing "${this.file.name}". Status: ${this.xhr.status}`);
3029        }
3030      };
3031      id2 = 0;
3032      DirectUpload2 = class {
3033        constructor(file, url, delegate, customHeaders = {}) {
3034          this.id = ++id2;
3035          this.file = file;
3036          this.url = url;
3037          this.delegate = delegate;
3038          this.customHeaders = customHeaders;
3039        }
3040        create(callback) {
3041          FileChecksum2.create(this.file, (error, checksum) => {
3042            if (error) {
3043              callback(error);
3044              return;
3045            }
3046            const blob = new BlobRecord2(this.file, checksum, this.url, this.customHeaders);
3047            notify2(this.delegate, "directUploadWillCreateBlobWithXHR", blob.xhr);
3048            blob.create((error2) => {
3049              if (error2) {
3050                callback(error2);
3051              } else {
3052                const upload = new BlobUpload2(blob);
3053                notify2(this.delegate, "directUploadWillStoreFileWithXHR", upload.xhr);
3054                upload.create((error3) => {
3055                  if (error3) {
3056                    callback(error3);
3057                  } else {
3058                    callback(null, blob.toJSON());
3059                  }
3060                });
3061              }
3062            });
3063          });
3064        }
3065      };
3066      DirectUploadController2 = class {
3067        constructor(input, file) {
3068          this.input = input;
3069          this.file = file;
3070          this.directUpload = new DirectUpload2(this.file, this.url, this);
3071          this.dispatch("initialize");
3072        }
3073        start(callback) {
3074          const hiddenInput = document.createElement("input");
3075          hiddenInput.type = "hidden";
3076          hiddenInput.name = this.input.name;
3077          this.input.insertAdjacentElement("beforebegin", hiddenInput);
3078          this.dispatch("start");
3079          this.directUpload.create((error, attributes) => {
3080            if (error) {
3081              hiddenInput.parentNode.removeChild(hiddenInput);
3082              this.dispatchError(error);
3083            } else {
3084              hiddenInput.value = attributes.signed_id;
3085            }
3086            this.dispatch("end");
3087            callback(error);
3088          });
3089        }
3090        uploadRequestDidProgress(event) {
3091          const progress = event.loaded / event.total * 90;
3092          if (progress) {
3093            this.dispatch("progress", {
3094              progress
3095            });
3096          }
3097        }
3098        get url() {
3099          return this.input.getAttribute("data-direct-upload-url");
3100        }
3101        dispatch(name, detail = {}) {
3102          detail.file = this.file;
3103          detail.id = this.directUpload.id;
3104          return dispatchEvent2(this.input, `direct-upload:${name}`, {
3105            detail
3106          });
3107        }
3108        dispatchError(error) {
3109          const event = this.dispatch("error", {
3110            error
3111          });
3112          if (!event.defaultPrevented) {
3113            alert(error);
3114          }
3115        }
3116        directUploadWillCreateBlobWithXHR(xhr) {
3117          this.dispatch("before-blob-request", {
3118            xhr
3119          });
3120        }
3121        directUploadWillStoreFileWithXHR(xhr) {
3122          this.dispatch("before-storage-request", {
3123            xhr
3124          });
3125          xhr.upload.addEventListener("progress", (event) => this.uploadRequestDidProgress(event));
3126          xhr.upload.addEventListener("loadend", () => {
3127            this.simulateResponseProgress(xhr);
3128          });
3129        }
3130        simulateResponseProgress(xhr) {
3131          let progress = 90;
3132          const startTime = Date.now();
3133          const updateProgress = () => {
3134            const elapsed = Date.now() - startTime;
3135            const estimatedResponseTime = this.estimateResponseTime();
3136            const responseProgress = Math.min(elapsed / estimatedResponseTime, 1);
3137            progress = 90 + responseProgress * 9;
3138            this.dispatch("progress", {
3139              progress
3140            });
3141            if (xhr.readyState !== XMLHttpRequest.DONE && progress < 99) {
3142              requestAnimationFrame(updateProgress);
3143            }
3144          };
3145          xhr.addEventListener("loadend", () => {
3146            this.dispatch("progress", {
3147              progress: 100
3148            });
3149          });
3150          requestAnimationFrame(updateProgress);
3151        }
3152        estimateResponseTime() {
3153          const fileSize = this.file.size;
3154          const MB = 1024 * 1024;
3155          if (fileSize < MB) {
3156            return 1e3;
3157          } else if (fileSize < 10 * MB) {
3158            return 2e3;
3159          } else {
3160            return 3e3 + fileSize / MB * 50;
3161          }
3162        }
3163      };
3164      inputSelector2 = "input[type=file][data-direct-upload-url]:not([disabled])";
3165      DirectUploadsController2 = class {
3166        constructor(form) {
3167          this.form = form;
3168          this.inputs = findElements2(form, inputSelector2).filter((input) => input.files.length);
3169        }
3170        start(callback) {
3171          const controllers = this.createDirectUploadControllers();
3172          const startNextController = () => {
3173            const controller = controllers.shift();
3174            if (controller) {
3175              controller.start((error) => {
3176                if (error) {
3177                  callback(error);
3178                  this.dispatch("end");
3179                } else {
3180                  startNextController();
3181                }
3182              });
3183            } else {
3184              callback();
3185              this.dispatch("end");
3186            }
3187          };
3188          this.dispatch("start");
3189          startNextController();
3190        }
3191        createDirectUploadControllers() {
3192          const controllers = [];
3193          this.inputs.forEach((input) => {
3194            toArray2(input.files).forEach((file) => {
3195              const controller = new DirectUploadController2(input, file);
3196              controllers.push(controller);
3197            });
3198          });
3199          return controllers;
3200        }
3201        dispatch(name, detail = {}) {
3202          return dispatchEvent2(this.form, `direct-uploads:${name}`, {
3203            detail
3204          });
3205        }
3206      };
3207      processingAttribute2 = "data-direct-uploads-processing";
3208      submitButtonsByForm2 = /* @__PURE__ */ new WeakMap();
3209      started2 = false;
3210      setTimeout(autostart2, 1);
3211      AttachmentUpload = class {
3212        constructor(attachment, element, file = attachment.file) {
3213          this.attachment = attachment;
3214          this.element = element;
3215          this.directUpload = new DirectUpload2(file, this.directUploadUrl, this);
3216          this.file = file;
3217        }
3218        start() {
3219          return new Promise((resolve, reject) => {
3220            this.directUpload.create((error, attributes) => this.directUploadDidComplete(error, attributes, resolve, reject));
3221            this.dispatch("start");
3222          });
3223        }
3224        directUploadWillStoreFileWithXHR(xhr) {
3225          xhr.upload.addEventListener("progress", (event) => {
3226            const progress = event.loaded / event.total * 90;
3227            if (progress) {
3228              this.dispatch("progress", {
3229                progress
3230              });
3231            }
3232          });
3233          xhr.upload.addEventListener("loadend", () => {
3234            this.simulateResponseProgress(xhr);
3235          });
3236        }
3237        simulateResponseProgress(xhr) {
3238          let progress = 90;
3239          const startTime = Date.now();
3240          const updateProgress = () => {
3241            const elapsed = Date.now() - startTime;
3242            const estimatedResponseTime = this.estimateResponseTime();
3243            const responseProgress = Math.min(elapsed / estimatedResponseTime, 1);
3244            progress = 90 + responseProgress * 9;
3245            this.dispatch("progress", {
3246              progress
3247            });
3248            if (xhr.readyState !== XMLHttpRequest.DONE && progress < 99) {
3249              requestAnimationFrame(updateProgress);
3250            }
3251          };
3252          xhr.addEventListener("loadend", () => {
3253            this.dispatch("progress", {
3254              progress: 100
3255            });
3256          });
3257          requestAnimationFrame(updateProgress);
3258        }
3259        estimateResponseTime() {
3260          const fileSize = this.file.size;
3261          const MB = 1024 * 1024;
3262          if (fileSize < MB) {
3263            return 1e3;
3264          } else if (fileSize < 10 * MB) {
3265            return 2e3;
3266          } else {
3267            return 3e3 + fileSize / MB * 50;
3268          }
3269        }
3270        directUploadDidComplete(error, attributes, resolve, reject) {
3271          if (error) {
3272            this.dispatchError(error, reject);
3273          } else {
3274            resolve({
3275              sgid: attributes.attachable_sgid,
3276              url: this.createBlobUrl(attributes.signed_id, attributes.filename)
3277            });
3278            this.dispatch("end");
3279          }
3280        }
3281        createBlobUrl(signedId, filename) {
3282          return this.blobUrlTemplate.replace(":signed_id", signedId).replace(":filename", encodeURIComponent(filename));
3283        }
3284        dispatch(name, detail = {}) {
3285          detail.attachment = this.attachment;
3286          return dispatchEvent2(this.element, `direct-upload:${name}`, {
3287            detail
3288          });
3289        }
3290        dispatchError(error, reject) {
3291          const event = this.dispatch("error", {
3292            error
3293          });
3294          if (!event.defaultPrevented) {
3295            reject(error);
3296          }
3297        }
3298        get directUploadUrl() {
3299          return this.element.dataset.directUploadUrl;
3300        }
3301        get blobUrlTemplate() {
3302          return this.element.dataset.blobUrlTemplate;
3303        }
3304      };
3305      addEventListener("trix-attachment-add", (event) => {
3306        const { attachment, target } = event;
3307        if (attachment.file) {
3308          const upload = new AttachmentUpload(attachment, target, attachment.file);
3309          const onProgress = (event2) => attachment.setUploadProgress(event2.detail.progress);
3310          target.addEventListener("direct-upload:progress", onProgress);
3311          upload.start().then((attributes) => attachment.setAttributes(attributes)).catch((error) => alert(error)).finally(() => target.removeEventListener("direct-upload:progress", onProgress));
3312        }
3313      });
3314    }
3315  });
3316
3317  
vendor: 114 bytes, lines 3317-3320
3317// node_modules/@37signals/lexxy/dist/lexxy_helpers.esm.js
3318  var import_prismjs = __toESM(require_prism(), 1);
3319
3320  
vendor: 1,013 bytes, lines 3320-3353
3320// node_modules/prismjs/components/prism-clike.js
3321  Prism.languages.clike = {
3322    "comment": [
3323      {
3324        pattern: /(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,
3325        lookbehind: true,
3326        greedy: true
3327      },
3328      {
3329        pattern: /(^|[^\\:])\/\/.*/,
3330        lookbehind: true,
3331        greedy: true
3332      }
3333    ],
3334    "string": {
3335      pattern: /(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,
3336      greedy: true
3337    },
3338    "class-name": {
3339      pattern: /(\b(?:class|extends|implements|instanceof|interface|new|trait)\s+|\bcatch\s+\()[\w.\\]+/i,
3340      lookbehind: true,
3341      inside: {
3342        "punctuation": /[.\\]/
3343      }
3344    },
3345    "keyword": /\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\b/,
3346    "boolean": /\b(?:false|true)\b/,
3347    "function": /\b\w+(?=\()/,
3348    "number": /\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,
3349    "operator": /[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,
3350    "punctuation": /[{}[\];(),.:]/
3351  };
3352
3353  
vendor: 1,404 bytes, lines 3353-3403
3353// node_modules/prismjs/components/prism-diff.js
3354  (function(Prism3) {
3355    Prism3.languages.diff = {
3356      "coord": [
3357        // Match all kinds of coord lines (prefixed by "+++", "---" or "***").
3358        /^(?:\*{3}|-{3}|\+{3}).*$/m,
3359        // Match "@@ ... @@" coord lines in unified diff.
3360        /^@@.*@@$/m,
3361        // Match coord lines in normal diff (starts with a number).
3362        /^\d.*$/m
3363      ]
3364      // deleted, inserted, unchanged, diff
3365    };
3366    var PREFIXES = {
3367      "deleted-sign": "-",
3368      "deleted-arrow": "<",
3369      "inserted-sign": "+",
3370      "inserted-arrow": ">",
3371      "unchanged": " ",
3372      "diff": "!"
3373    };
3374    Object.keys(PREFIXES).forEach(function(name) {
3375      var prefix = PREFIXES[name];
3376      var alias = [];
3377      if (!/^\w+$/.test(name)) {
3378        alias.push(/\w+/.exec(name)[0]);
3379      }
3380      if (name === "diff") {
3381        alias.push("bold");
3382      }
3383      Prism3.languages.diff[name] = {
3384        pattern: RegExp("^(?:[" + prefix + "].*(?:\r\n?|\n|(?![\\s\\S])))+", "m"),
3385        alias,
3386        inside: {
3387          "line": {
3388            pattern: /(.)(?=[\s\S]).*(?:\r\n?|\n)?/,
3389            lookbehind: true
3390          },
3391          "prefix": {
3392            pattern: /[\s\S]/,
3393            alias: /\w+/.exec(name)[0]
3394          }
3395        }
3396      };
3397    });
3398    Object.defineProperty(Prism3.languages.diff, "PREFIXES", {
3399      value: PREFIXES
3400    });
3401  })(Prism);
3402
3403  
vendor: 6,755 bytes, lines 3403-3545
3403// node_modules/prismjs/components/prism-javascript.js
3404  Prism.languages.javascript = Prism.languages.extend("clike", {
3405    "class-name": [
3406      Prism.languages.clike["class-name"],
3407      {
3408        pattern: /(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,
3409        lookbehind: true
3410      }
3411    ],
3412    "keyword": [
3413      {
3414        pattern: /((?:^|\})\s*)catch\b/,
3415        lookbehind: true
3416      },
3417      {
3418        pattern: /(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,
3419        lookbehind: true
3420      }
3421    ],
3422    // Allow for all non-ASCII characters (See http://stackoverflow.com/a/2008444)
3423    "function": /#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,
3424    "number": {
3425      pattern: RegExp(
3426        /(^|[^\w$])/.source + "(?:" + // constant
3427        (/NaN|Infinity/.source + "|" + // binary integer
3428        /0[bB][01]+(?:_[01]+)*n?/.source + "|" + // octal integer
3429        /0[oO][0-7]+(?:_[0-7]+)*n?/.source + "|" + // hexadecimal integer
3430        /0[xX][\dA-Fa-f]+(?:_[\dA-Fa-f]+)*n?/.source + "|" + // decimal bigint
3431        /\d+(?:_\d+)*n/.source + "|" + // decimal number (integer or float) but no bigint
3432        /(?:\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\.\d+(?:_\d+)*)(?:[Ee][+-]?\d+(?:_\d+)*)?/.source) + ")" + /(?![\w$])/.source
3433      ),
3434      lookbehind: true
3435    },
3436    "operator": /--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/
3437  });
3438  Prism.languages.javascript["class-name"][0].pattern = /(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/;
3439  Prism.languages.insertBefore("javascript", "keyword", {
3440    "regex": {
3441      pattern: RegExp(
3442        // lookbehind
3443        // eslint-disable-next-line regexp/no-dupe-characters-character-class
3444        /((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)/.source + // Regex pattern:
3445        // There are 2 regex patterns here. The RegExp set notation proposal added support for nested character
3446        // classes if the `v` flag is present. Unfortunately, nested CCs are both context-free and incompatible
3447        // with the only syntax, so we have to define 2 different regex patterns.
3448        /\//.source + "(?:" + /(?:\[(?:[^\]\\\r\n]|\\.)*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}/.source + "|" + // `v` flag syntax. This supports 3 levels of nested character classes.
3449        /(?:\[(?:[^[\]\\\r\n]|\\.|\[(?:[^[\]\\\r\n]|\\.|\[(?:[^[\]\\\r\n]|\\.)*\])*\])*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}v[dgimyus]{0,7}/.source + ")" + // lookahead
3450        /(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/.source
3451      ),
3452      lookbehind: true,
3453      greedy: true,
3454      inside: {
3455        "regex-source": {
3456          pattern: /^(\/)[\s\S]+(?=\/[a-z]*$)/,
3457          lookbehind: true,
3458          alias: "language-regex",
3459          inside: Prism.languages.regex
3460        },
3461        "regex-delimiter": /^\/|\/$/,
3462        "regex-flags": /^[a-z]+$/
3463      }
3464    },
3465    // This must be declared before keyword because we use "function" inside the look-forward
3466    "function-variable": {
3467      pattern: /#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,
3468      alias: "function"
3469    },
3470    "parameter": [
3471      {
3472        pattern: /(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,
3473        lookbehind: true,
3474        inside: Prism.languages.javascript
3475      },
3476      {
3477        pattern: /(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,
3478        lookbehind: true,
3479        inside: Prism.languages.javascript
3480      },
3481      {
3482        pattern: /(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,
3483        lookbehind: true,
3484        inside: Prism.languages.javascript
3485      },
3486      {
3487        pattern: /((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,
3488        lookbehind: true,
3489        inside: Prism.languages.javascript
3490      }
3491    ],
3492    "constant": /\b[A-Z](?:[A-Z_]|\dx?)*\b/
3493  });
3494  Prism.languages.insertBefore("javascript", "string", {
3495    "hashbang": {
3496      pattern: /^#!.*/,
3497      greedy: true,
3498      alias: "comment"
3499    },
3500    "template-string": {
3501      pattern: /`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,
3502      greedy: true,
3503      inside: {
3504        "template-punctuation": {
3505          pattern: /^`|`$/,
3506          alias: "string"
3507        },
3508        "interpolation": {
3509          pattern: /((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,
3510          lookbehind: true,
3511          inside: {
3512            "interpolation-punctuation": {
3513              pattern: /^\$\{|\}$/,
3514              alias: "punctuation"
3515            },
3516            rest: Prism.languages.javascript
3517          }
3518        },
3519        "string": /[\s\S]+/
3520      }
3521    },
3522    "string-property": {
3523      pattern: /((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,
3524      lookbehind: true,
3525      greedy: true,
3526      alias: "property"
3527    }
3528  });
3529  Prism.languages.insertBefore("javascript", "operator", {
3530    "literal-property": {
3531      pattern: /((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,
3532      lookbehind: true,
3533      alias: "property"
3534    }
3535  });
3536  if (Prism.languages.markup) {
3537    Prism.languages.markup.tag.addInlined("script", "javascript");
3538    Prism.languages.markup.tag.addAttribute(
3539      /on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)/.source,
3540      "javascript"
3541    );
3542  }
3543  Prism.languages.js = Prism.languages.javascript;
3544
3545  
vendor: 5,558 bytes, lines 3545-3724
3545// node_modules/prismjs/components/prism-markup.js
3546  Prism.languages.markup = {
3547    "comment": {
3548      pattern: /<!--(?:(?!<!--)[\s\S])*?-->/,
3549      greedy: true
3550    },
3551    "prolog": {
3552      pattern: /<\?[\s\S]+?\?>/,
3553      greedy: true
3554    },
3555    "doctype": {
3556      // https://www.w3.org/TR/xml/#NT-doctypedecl
3557      pattern: /<!DOCTYPE(?:[^>"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|<!--(?:[^-]|-(?!->))*-->)*\]\s*)?>/i,
3558      greedy: true,
3559      inside: {
3560        "internal-subset": {
3561          pattern: /(^[^\[]*\[)[\s\S]+(?=\]>$)/,
3562          lookbehind: true,
3563          greedy: true,
3564          inside: null
3565          // see below
3566        },
3567        "string": {
3568          pattern: /"[^"]*"|'[^']*'/,
3569          greedy: true
3570        },
3571        "punctuation": /^<!|>$|[[\]]/,
3572        "doctype-tag": /^DOCTYPE/i,
3573        "name": /[^\s<>'"]+/
3574      }
3575    },
3576    "cdata": {
3577      pattern: /<!\[CDATA\[[\s\S]*?\]\]>/i,
3578      greedy: true
3579    },
3580    "tag": {
3581      pattern: /<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,
3582      greedy: true,
3583      inside: {
3584        "tag": {
3585          pattern: /^<\/?[^\s>\/]+/,
3586          inside: {
3587            "punctuation": /^<\/?/,
3588            "namespace": /^[^\s>\/:]+:/
3589          }
3590        },
3591        "special-attr": [],
3592        "attr-value": {
3593          pattern: /=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,
3594          inside: {
3595            "punctuation": [
3596              {
3597                pattern: /^=/,
3598                alias: "attr-equals"
3599              },
3600              {
3601                pattern: /^(\s*)["']|["']$/,
3602                lookbehind: true
3603              }
3604            ]
3605          }
3606        },
3607        "punctuation": /\/?>/,
3608        "attr-name": {
3609          pattern: /[^\s>\/]+/,
3610          inside: {
3611            "namespace": /^[^\s>\/:]+:/
3612          }
3613        }
3614      }
3615    },
3616    "entity": [
3617      {
3618        pattern: /&[\da-z]{1,8};/i,
3619        alias: "named-entity"
3620      },
3621      /&#x?[\da-f]{1,8};/i
3622    ]
3623  };
3624  Prism.languages.markup["tag"].inside["attr-value"].inside["entity"] = Prism.languages.markup["entity"];
3625  Prism.languages.markup["doctype"].inside["internal-subset"].inside = Prism.languages.markup;
3626  Prism.hooks.add("wrap", function(env) {
3627    if (env.type === "entity") {
3628      env.attributes["title"] = env.content.replace(/&amp;/, "&");
3629    }
3630  });
3631  Object.defineProperty(Prism.languages.markup.tag, "addInlined", {
3632    /**
3633     * Adds an inlined language to markup.
3634     *
3635     * An example of an inlined language is CSS with `<style>` tags.
3636     *
3637     * @param {string} tagName The name of the tag that contains the inlined language. This name will be treated as
3638     * case insensitive.
3639     * @param {string} lang The language key.
3640     * @example
3641     * addInlined('style', 'css');
3642     */
3643    value: function addInlined(tagName, lang) {
3644      var includedCdataInside = {};
3645      includedCdataInside["language-" + lang] = {
3646        pattern: /(^<!\[CDATA\[)[\s\S]+?(?=\]\]>$)/i,
3647        lookbehind: true,
3648        inside: Prism.languages[lang]
3649      };
3650      includedCdataInside["cdata"] = /^<!\[CDATA\[|\]\]>$/i;
3651      var inside = {
3652        "included-cdata": {
3653          pattern: /<!\[CDATA\[[\s\S]*?\]\]>/i,
3654          inside: includedCdataInside
3655        }
3656      };
3657      inside["language-" + lang] = {
3658        pattern: /[\s\S]+/,
3659        inside: Prism.languages[lang]
3660      };
3661      var def = {};
3662      def[tagName] = {
3663        pattern: RegExp(/(<__[^>]*>)(?:<!\[CDATA\[(?:[^\]]|\](?!\]>))*\]\]>|(?!<!\[CDATA\[)[\s\S])*?(?=<\/__>)/.source.replace(/__/g, function() {
3664          return tagName;
3665        }), "i"),
3666        lookbehind: true,
3667        greedy: true,
3668        inside
3669      };
3670      Prism.languages.insertBefore("markup", "cdata", def);
3671    }
3672  });
3673  Object.defineProperty(Prism.languages.markup.tag, "addAttribute", {
3674    /**
3675     * Adds an pattern to highlight languages embedded in HTML attributes.
3676     *
3677     * An example of an inlined language is CSS with `style` attributes.
3678     *
3679     * @param {string} attrName The name of the tag that contains the inlined language. This name will be treated as
3680     * case insensitive.
3681     * @param {string} lang The language key.
3682     * @example
3683     * addAttribute('style', 'css');
3684     */
3685    value: function(attrName, lang) {
3686      Prism.languages.markup.tag.inside["special-attr"].push({
3687        pattern: RegExp(
3688          /(^|["'\s])/.source + "(?:" + attrName + ")" + /\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))/.source,
3689          "i"
3690        ),
3691        lookbehind: true,
3692        inside: {
3693          "attr-name": /^[^\s=]+/,
3694          "attr-value": {
3695            pattern: /=[\s\S]+/,
3696            inside: {
3697              "value": {
3698                pattern: /(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,
3699                lookbehind: true,
3700                alias: [lang, "language-" + lang],
3701                inside: Prism.languages[lang]
3702              },
3703              "punctuation": [
3704                {
3705                  pattern: /^=/,
3706                  alias: "attr-equals"
3707                },
3708                /"|'/
3709              ]
3710            }
3711          }
3712        }
3713      });
3714    }
3715  });
3716  Prism.languages.html = Prism.languages.markup;
3717  Prism.languages.mathml = Prism.languages.markup;
3718  Prism.languages.svg = Prism.languages.markup;
3719  Prism.languages.xml = Prism.languages.extend("markup", {});
3720  Prism.languages.ssml = Prism.languages.xml;
3721  Prism.languages.atom = Prism.languages.xml;
3722  Prism.languages.rss = Prism.languages.xml;
3723
3724  
vendor: 11,010 bytes, lines 3724-4065
3724// node_modules/prismjs/components/prism-markdown.js
3725  (function(Prism3) {
3726    var inner = /(?:\\.|[^\\\n\r]|(?:\n|\r\n?)(?![\r\n]))/.source;
3727    function createInline(pattern) {
3728      pattern = pattern.replace(/<inner>/g, function() {
3729        return inner;
3730      });
3731      return RegExp(/((?:^|[^\\])(?:\\{2})*)/.source + "(?:" + pattern + ")");
3732    }
3733    var tableCell = /(?:\\.|``(?:[^`\r\n]|`(?!`))+``|`[^`\r\n]+`|[^\\|\r\n`])+/.source;
3734    var tableRow = /\|?__(?:\|__)+\|?(?:(?:\n|\r\n?)|(?![\s\S]))/.source.replace(/__/g, function() {
3735      return tableCell;
3736    });
3737    var tableLine = /\|?[ \t]*:?-{3,}:?[ \t]*(?:\|[ \t]*:?-{3,}:?[ \t]*)+\|?(?:\n|\r\n?)/.source;
3738    Prism3.languages.markdown = Prism3.languages.extend("markup", {});
3739    Prism3.languages.insertBefore("markdown", "prolog", {
3740      "front-matter-block": {
3741        pattern: /(^(?:\s*[\r\n])?)---(?!.)[\s\S]*?[\r\n]---(?!.)/,
3742        lookbehind: true,
3743        greedy: true,
3744        inside: {
3745          "punctuation": /^---|---$/,
3746          "front-matter": {
3747            pattern: /\S+(?:\s+\S+)*/,
3748            alias: ["yaml", "language-yaml"],
3749            inside: Prism3.languages.yaml
3750          }
3751        }
3752      },
3753      "blockquote": {
3754        // > ...
3755        pattern: /^>(?:[\t ]*>)*/m,
3756        alias: "punctuation"
3757      },
3758      "table": {
3759        pattern: RegExp("^" + tableRow + tableLine + "(?:" + tableRow + ")*", "m"),
3760        inside: {
3761          "table-data-rows": {
3762            pattern: RegExp("^(" + tableRow + tableLine + ")(?:" + tableRow + ")*$"),
3763            lookbehind: true,
3764            inside: {
3765              "table-data": {
3766                pattern: RegExp(tableCell),
3767                inside: Prism3.languages.markdown
3768              },
3769              "punctuation": /\|/
3770            }
3771          },
3772          "table-line": {
3773            pattern: RegExp("^(" + tableRow + ")" + tableLine + "$"),
3774            lookbehind: true,
3775            inside: {
3776              "punctuation": /\||:?-{3,}:?/
3777            }
3778          },
3779          "table-header-row": {
3780            pattern: RegExp("^" + tableRow + "$"),
3781            inside: {
3782              "table-header": {
3783                pattern: RegExp(tableCell),
3784                alias: "important",
3785                inside: Prism3.languages.markdown
3786              },
3787              "punctuation": /\|/
3788            }
3789          }
3790        }
3791      },
3792      "code": [
3793        {
3794          // Prefixed by 4 spaces or 1 tab and preceded by an empty line
3795          pattern: /((?:^|\n)[ \t]*\n|(?:^|\r\n?)[ \t]*\r\n?)(?: {4}|\t).+(?:(?:\n|\r\n?)(?: {4}|\t).+)*/,
3796          lookbehind: true,
3797          alias: "keyword"
3798        },
3799        {
3800          // ```optional language
3801          // code block
3802          // ```
3803          pattern: /^```[\s\S]*?^```$/m,
3804          greedy: true,
3805          inside: {
3806            "code-block": {
3807              pattern: /^(```.*(?:\n|\r\n?))[\s\S]+?(?=(?:\n|\r\n?)^```$)/m,
3808              lookbehind: true
3809            },
3810            "code-language": {
3811              pattern: /^(```).+/,
3812              lookbehind: true
3813            },
3814            "punctuation": /```/
3815          }
3816        }
3817      ],
3818      "title": [
3819        {
3820          // title 1
3821          // =======
3822          // title 2
3823          // -------
3824          pattern: /\S.*(?:\n|\r\n?)(?:==+|--+)(?=[ \t]*$)/m,
3825          alias: "important",
3826          inside: {
3827            punctuation: /==+$|--+$/
3828          }
3829        },
3830        {
3831          // # title 1
3832          // ###### title 6
3833          pattern: /(^\s*)#.+/m,
3834          lookbehind: true,
3835          alias: "important",
3836          inside: {
3837            punctuation: /^#+|#+$/
3838          }
3839        }
3840      ],
3841      "hr": {
3842        // ***
3843        // ---
3844        // * * *
3845        // -----------
3846        pattern: /(^\s*)([*-])(?:[\t ]*\2){2,}(?=\s*$)/m,
3847        lookbehind: true,
3848        alias: "punctuation"
3849      },
3850      "list": {
3851        // * item
3852        // + item
3853        // - item
3854        // 1. item
3855        pattern: /(^\s*)(?:[*+-]|\d+\.)(?=[\t ].)/m,
3856        lookbehind: true,
3857        alias: "punctuation"
3858      },
3859      "url-reference": {
3860        // [id]: http://example.com "Optional title"
3861        // [id]: http://example.com 'Optional title'
3862        // [id]: http://example.com (Optional title)
3863        // [id]: <http://example.com> "Optional title"
3864        pattern: /!?\[[^\]]+\]:[\t ]+(?:\S+|<(?:\\.|[^>\\])+>)(?:[\t ]+(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\)))?/,
3865        inside: {
3866          "variable": {
3867            pattern: /^(!?\[)[^\]]+/,
3868            lookbehind: true
3869          },
3870          "string": /(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\))$/,
3871          "punctuation": /^[\[\]!:]|[<>]/
3872        },
3873        alias: "url"
3874      },
3875      "bold": {
3876        // **strong**
3877        // __strong__
3878        // allow one nested instance of italic text using the same delimiter
3879        pattern: createInline(/\b__(?:(?!_)<inner>|_(?:(?!_)<inner>)+_)+__\b|\*\*(?:(?!\*)<inner>|\*(?:(?!\*)<inner>)+\*)+\*\*/.source),
3880        lookbehind: true,
3881        greedy: true,
3882        inside: {
3883          "content": {
3884            pattern: /(^..)[\s\S]+(?=..$)/,
3885            lookbehind: true,
3886            inside: {}
3887            // see below
3888          },
3889          "punctuation": /\*\*|__/
3890        }
3891      },
3892      "italic": {
3893        // *em*
3894        // _em_
3895        // allow one nested instance of bold text using the same delimiter
3896        pattern: createInline(/\b_(?:(?!_)<inner>|__(?:(?!_)<inner>)+__)+_\b|\*(?:(?!\*)<inner>|\*\*(?:(?!\*)<inner>)+\*\*)+\*/.source),
3897        lookbehind: true,
3898        greedy: true,
3899        inside: {
3900          "content": {
3901            pattern: /(^.)[\s\S]+(?=.$)/,
3902            lookbehind: true,
3903            inside: {}
3904            // see below
3905          },
3906          "punctuation": /[*_]/
3907        }
3908      },
3909      "strike": {
3910        // ~~strike through~~
3911        // ~strike~
3912        // eslint-disable-next-line regexp/strict
3913        pattern: createInline(/(~~?)(?:(?!~)<inner>)+\2/.source),
3914        lookbehind: true,
3915        greedy: true,
3916        inside: {
3917          "content": {
3918            pattern: /(^~~?)[\s\S]+(?=\1$)/,
3919            lookbehind: true,
3920            inside: {}
3921            // see below
3922          },
3923          "punctuation": /~~?/
3924        }
3925      },
3926      "code-snippet": {
3927        // `code`
3928        // ``code``
3929        pattern: /(^|[^\\`])(?:``[^`\r\n]+(?:`[^`\r\n]+)*``(?!`)|`[^`\r\n]+`(?!`))/,
3930        lookbehind: true,
3931        greedy: true,
3932        alias: ["code", "keyword"]
3933      },
3934      "url": {
3935        // [example](http://example.com "Optional title")
3936        // [example][id]
3937        // [example] [id]
3938        pattern: createInline(/!?\[(?:(?!\])<inner>)+\](?:\([^\s)]+(?:[\t ]+"(?:\\.|[^"\\])*")?\)|[ \t]?\[(?:(?!\])<inner>)+\])/.source),
3939        lookbehind: true,
3940        greedy: true,
3941        inside: {
3942          "operator": /^!/,
3943          "content": {
3944            pattern: /(^\[)[^\]]+(?=\])/,
3945            lookbehind: true,
3946            inside: {}
3947            // see below
3948          },
3949          "variable": {
3950            pattern: /(^\][ \t]?\[)[^\]]+(?=\]$)/,
3951            lookbehind: true
3952          },
3953          "url": {
3954            pattern: /(^\]\()[^\s)]+/,
3955            lookbehind: true
3956          },
3957          "string": {
3958            pattern: /(^[ \t]+)"(?:\\.|[^"\\])*"(?=\)$)/,
3959            lookbehind: true
3960          }
3961        }
3962      }
3963    });
3964    ["url", "bold", "italic", "strike"].forEach(function(token) {
3965      ["url", "bold", "italic", "strike", "code-snippet"].forEach(function(inside) {
3966        if (token !== inside) {
3967          Prism3.languages.markdown[token].inside.content.inside[inside] = Prism3.languages.markdown[inside];
3968        }
3969      });
3970    });
3971    Prism3.hooks.add("after-tokenize", function(env) {
3972      if (env.language !== "markdown" && env.language !== "md") {
3973        return;
3974      }
3975      function walkTokens(tokens) {
3976        if (!tokens || typeof tokens === "string") {
3977          return;
3978        }
3979        for (var i2 = 0, l4 = tokens.length; i2 < l4; i2++) {
3980          var token = tokens[i2];
3981          if (token.type !== "code") {
3982            walkTokens(token.content);
3983            continue;
3984          }
3985          var codeLang = token.content[1];
3986          var codeBlock = token.content[3];
3987          if (codeLang && codeBlock && codeLang.type === "code-language" && codeBlock.type === "code-block" && typeof codeLang.content === "string") {
3988            var lang = codeLang.content.replace(/\b#/g, "sharp").replace(/\b\+\+/g, "pp");
3989            lang = (/[a-z][\w-]*/i.exec(lang) || [""])[0].toLowerCase();
3990            var alias = "language-" + lang;
3991            if (!codeBlock.alias) {
3992              codeBlock.alias = [alias];
3993            } else if (typeof codeBlock.alias === "string") {
3994              codeBlock.alias = [codeBlock.alias, alias];
3995            } else {
3996              codeBlock.alias.push(alias);
3997            }
3998          }
3999        }
4000      }
4001      walkTokens(env.tokens);
4002    });
4003    Prism3.hooks.add("wrap", function(env) {
4004      if (env.type !== "code-block") {
4005        return;
4006      }
4007      var codeLang = "";
4008      for (var i2 = 0, l4 = env.classes.length; i2 < l4; i2++) {
4009        var cls = env.classes[i2];
4010        var match = /language-(.+)/.exec(cls);
4011        if (match) {
4012          codeLang = match[1];
4013          break;
4014        }
4015      }
4016      var grammar = Prism3.languages[codeLang];
4017      if (!grammar) {
4018        if (codeLang && codeLang !== "none" && Prism3.plugins.autoloader) {
4019          var id3 = "md-" + (/* @__PURE__ */ new Date()).valueOf() + "-" + Math.floor(Math.random() * 1e16);
4020          env.attributes["id"] = id3;
4021          Prism3.plugins.autoloader.loadLanguages(codeLang, function() {
4022            var ele = document.getElementById(id3);
4023            if (ele) {
4024              ele.innerHTML = Prism3.highlight(ele.textContent, Prism3.languages[codeLang], codeLang);
4025            }
4026          });
4027        }
4028      } else {
4029        env.content = Prism3.highlight(textContent(env.content), grammar, codeLang);
4030      }
4031    });
4032    var tagPattern = RegExp(Prism3.languages.markup.tag.pattern.source, "gi");
4033    var KNOWN_ENTITY_NAMES = {
4034      "amp": "&",
4035      "lt": "<",
4036      "gt": ">",
4037      "quot": '"'
4038    };
4039    var fromCodePoint = String.fromCodePoint || String.fromCharCode;
4040    function textContent(html2) {
4041      var text2 = html2.replace(tagPattern, "");
4042      text2 = text2.replace(/&(\w{1,8}|#x?[\da-f]{1,8});/gi, function(m3, code) {
4043        code = code.toLowerCase();
4044        if (code[0] === "#") {
4045          var value;
4046          if (code[1] === "x") {
4047            value = parseInt(code.slice(2), 16);
4048          } else {
4049            value = Number(code.slice(1));
4050          }
4051          return fromCodePoint(value);
4052        } else {
4053          var known = KNOWN_ENTITY_NAMES[code];
4054          if (known) {
4055            return known;
4056          }
4057          return m3;
4058        }
4059      });
4060      return text2;
4061    }
4062    Prism3.languages.md = Prism3.languages.markdown;
4063  })(Prism);
4064
4065  
vendor: 2,997 bytes, lines 4065-4143
4065// node_modules/prismjs/components/prism-c.js
4066  Prism.languages.c = Prism.languages.extend("clike", {
4067    "comment": {
4068      pattern: /\/\/(?:[^\r\n\\]|\\(?:\r\n?|\n|(?![\r\n])))*|\/\*[\s\S]*?(?:\*\/|$)/,
4069      greedy: true
4070    },
4071    "string": {
4072      // https://en.cppreference.com/w/c/language/string_literal
4073      pattern: /"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"/,
4074      greedy: true
4075    },
4076    "class-name": {
4077      pattern: /(\b(?:enum|struct)\s+(?:__attribute__\s*\(\([\s\S]*?\)\)\s*)?)\w+|\b[a-z]\w*_t\b/,
4078      lookbehind: true
4079    },
4080    "keyword": /\b(?:_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|__attribute__|asm|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|inline|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|typeof|union|unsigned|void|volatile|while)\b/,
4081    "function": /\b[a-z_]\w*(?=\s*\()/i,
4082    "number": /(?:\b0x(?:[\da-f]+(?:\.[\da-f]*)?|\.[\da-f]+)(?:p[+-]?\d+)?|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?)[ful]{0,4}/i,
4083    "operator": />>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*/%&|^!=<>]=?/
4084  });
4085  Prism.languages.insertBefore("c", "string", {
4086    "char": {
4087      // https://en.cppreference.com/w/c/language/character_constant
4088      pattern: /'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n]){0,32}'/,
4089      greedy: true
4090    }
4091  });
4092  Prism.languages.insertBefore("c", "string", {
4093    "macro": {
4094      // allow for multiline macro definitions
4095      // spaces after the # character compile fine with gcc
4096      pattern: /(^[\t ]*)#\s*[a-z](?:[^\r\n\\/]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/|\\(?:\r\n|[\s\S]))*/im,
4097      lookbehind: true,
4098      greedy: true,
4099      alias: "property",
4100      inside: {
4101        "string": [
4102          {
4103            // highlight the path of the include statement as a string
4104            pattern: /^(#\s*include\s*)<[^>]+>/,
4105            lookbehind: true
4106          },
4107          Prism.languages.c["string"]
4108        ],
4109        "char": Prism.languages.c["char"],
4110        "comment": Prism.languages.c["comment"],
4111        "macro-name": [
4112          {
4113            pattern: /(^#\s*define\s+)\w+\b(?!\()/i,
4114            lookbehind: true
4115          },
4116          {
4117            pattern: /(^#\s*define\s+)\w+\b(?=\()/i,
4118            lookbehind: true,
4119            alias: "function"
4120          }
4121        ],
4122        // highlight macro directives as keywords
4123        "directive": {
4124          pattern: /^(#\s*)[a-z]+/,
4125          lookbehind: true,
4126          alias: "keyword"
4127        },
4128        "directive-hash": /^#/,
4129        "punctuation": /##|\\(?=[\r\n])/,
4130        "expression": {
4131          pattern: /\S[\s\S]*/,
4132          inside: Prism.languages.c
4133        }
4134      }
4135    }
4136  });
4137  Prism.languages.insertBefore("c", "function", {
4138    // highlight predefined macros as constants
4139    "constant": /\b(?:EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|__DATE__|__FILE__|__LINE__|__TIMESTAMP__|__TIME__|__func__|stderr|stdin|stdout)\b/
4140  });
4141  delete Prism.languages.c["boolean"];
4142
4143  
vendor: 2,077 bytes, lines 4143-4204
4143// node_modules/prismjs/components/prism-css.js
4144  (function(Prism3) {
4145    var string = /(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/;
4146    Prism3.languages.css = {
4147      "comment": /\/\*[\s\S]*?\*\//,
4148      "atrule": {
4149        pattern: RegExp("@[\\w-](?:" + /[^;{\s"']|\s+(?!\s)/.source + "|" + string.source + ")*?" + /(?:;|(?=\s*\{))/.source),
4150        inside: {
4151          "rule": /^@[\w-]+/,
4152          "selector-function-argument": {
4153            pattern: /(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,
4154            lookbehind: true,
4155            alias: "selector"
4156          },
4157          "keyword": {
4158            pattern: /(^|[^\w-])(?:and|not|only|or)(?![\w-])/,
4159            lookbehind: true
4160          }
4161          // See rest below
4162        }
4163      },
4164      "url": {
4165        // https://drafts.csswg.org/css-values-3/#urls
4166        pattern: RegExp("\\burl\\((?:" + string.source + "|" + /(?:[^\\\r\n()"']|\\[\s\S])*/.source + ")\\)", "i"),
4167        greedy: true,
4168        inside: {
4169          "function": /^url/i,
4170          "punctuation": /^\(|\)$/,
4171          "string": {
4172            pattern: RegExp("^" + string.source + "$"),
4173            alias: "url"
4174          }
4175        }
4176      },
4177      "selector": {
4178        pattern: RegExp(`(^|[{}\\s])[^{}\\s](?:[^{};"'\\s]|\\s+(?![\\s{])|` + string.source + ")*(?=\\s*\\{)"),
4179        lookbehind: true
4180      },
4181      "string": {
4182        pattern: string,
4183        greedy: true
4184      },
4185      "property": {
4186        pattern: /(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,
4187        lookbehind: true
4188      },
4189      "important": /!important\b/i,
4190      "function": {
4191        pattern: /(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,
4192        lookbehind: true
4193      },
4194      "punctuation": /[(){};:,]/
4195    };
4196    Prism3.languages.css["atrule"].inside.rest = Prism3.languages.css;
4197    var markup = Prism3.languages.markup;
4198    if (markup) {
4199      markup.tag.addInlined("style", "css");
4200      markup.tag.addAttribute("style", "css");
4201    }
4202  })(Prism);
4203
4204  
vendor: 807 bytes, lines 4204-4216
4204// node_modules/prismjs/components/prism-objectivec.js
4205  Prism.languages.objectivec = Prism.languages.extend("c", {
4206    "string": {
4207      pattern: /@?"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"/,
4208      greedy: true
4209    },
4210    "keyword": /\b(?:asm|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|in|inline|int|long|register|return|self|short|signed|sizeof|static|struct|super|switch|typedef|typeof|union|unsigned|void|volatile|while)\b|(?:@interface|@end|@implementation|@protocol|@class|@public|@protected|@private|@property|@try|@catch|@finally|@throw|@synthesize|@dynamic|@selector)\b/,
4211    "operator": /-[->]?|\+\+?|!=?|<<?=?|>>?=?|==?|&&?|\|\|?|[~^%?*\/@]/
4212  });
4213  delete Prism.languages.objectivec["class-name"];
4214  Prism.languages.objc = Prism.languages.objectivec;
4215
4216  
vendor: 3,619 bytes, lines 4216-4251
4216// node_modules/prismjs/components/prism-sql.js
4217  Prism.languages.sql = {
4218    "comment": {
4219      pattern: /(^|[^\\])(?:\/\*[\s\S]*?\*\/|(?:--|\/\/|#).*)/,
4220      lookbehind: true
4221    },
4222    "variable": [
4223      {
4224        pattern: /@(["'`])(?:\\[\s\S]|(?!\1)[^\\])+\1/,
4225        greedy: true
4226      },
4227      /@[\w.$]+/
4228    ],
4229    "string": {
4230      pattern: /(^|[^@\\])("|')(?:\\[\s\S]|(?!\2)[^\\]|\2\2)*\2/,
4231      greedy: true,
4232      lookbehind: true
4233    },
4234    "identifier": {
4235      pattern: /(^|[^@\\])`(?:\\[\s\S]|[^`\\]|``)*`/,
4236      greedy: true,
4237      lookbehind: true,
4238      inside: {
4239        "punctuation": /^`|`$/
4240      }
4241    },
4242    "function": /\b(?:AVG|COUNT|FIRST|FORMAT|LAST|LCASE|LEN|MAX|MID|MIN|MOD|NOW|ROUND|SUM|UCASE)(?=\s*\()/i,
4243    // Should we highlight user defined functions too?
4244    "keyword": /\b(?:ACTION|ADD|AFTER|ALGORITHM|ALL|ALTER|ANALYZE|ANY|APPLY|AS|ASC|AUTHORIZATION|AUTO_INCREMENT|BACKUP|BDB|BEGIN|BERKELEYDB|BIGINT|BINARY|BIT|BLOB|BOOL|BOOLEAN|BREAK|BROWSE|BTREE|BULK|BY|CALL|CASCADED?|CASE|CHAIN|CHAR(?:ACTER|SET)?|CHECK(?:POINT)?|CLOSE|CLUSTERED|COALESCE|COLLATE|COLUMNS?|COMMENT|COMMIT(?:TED)?|COMPUTE|CONNECT|CONSISTENT|CONSTRAINT|CONTAINS(?:TABLE)?|CONTINUE|CONVERT|CREATE|CROSS|CURRENT(?:_DATE|_TIME|_TIMESTAMP|_USER)?|CURSOR|CYCLE|DATA(?:BASES?)?|DATE(?:TIME)?|DAY|DBCC|DEALLOCATE|DEC|DECIMAL|DECLARE|DEFAULT|DEFINER|DELAYED|DELETE|DELIMITERS?|DENY|DESC|DESCRIBE|DETERMINISTIC|DISABLE|DISCARD|DISK|DISTINCT|DISTINCTROW|DISTRIBUTED|DO|DOUBLE|DROP|DUMMY|DUMP(?:FILE)?|DUPLICATE|ELSE(?:IF)?|ENABLE|ENCLOSED|END|ENGINE|ENUM|ERRLVL|ERRORS|ESCAPED?|EXCEPT|EXEC(?:UTE)?|EXISTS|EXIT|EXPLAIN|EXTENDED|FETCH|FIELDS|FILE|FILLFACTOR|FIRST|FIXED|FLOAT|FOLLOWING|FOR(?: EACH ROW)?|FORCE|FOREIGN|FREETEXT(?:TABLE)?|FROM|FULL|FUNCTION|GEOMETRY(?:COLLECTION)?|GLOBAL|GOTO|GRANT|GROUP|HANDLER|HASH|HAVING|HOLDLOCK|HOUR|IDENTITY(?:COL|_INSERT)?|IF|IGNORE|IMPORT|INDEX|INFILE|INNER|INNODB|INOUT|INSERT|INT|INTEGER|INTERSECT|INTERVAL|INTO|INVOKER|ISOLATION|ITERATE|JOIN|KEYS?|KILL|LANGUAGE|LAST|LEAVE|LEFT|LEVEL|LIMIT|LINENO|LINES|LINESTRING|LOAD|LOCAL|LOCK|LONG(?:BLOB|TEXT)|LOOP|MATCH(?:ED)?|MEDIUM(?:BLOB|INT|TEXT)|MERGE|MIDDLEINT|MINUTE|MODE|MODIFIES|MODIFY|MONTH|MULTI(?:LINESTRING|POINT|POLYGON)|NATIONAL|NATURAL|NCHAR|NEXT|NO|NONCLUSTERED|NULLIF|NUMERIC|OFF?|OFFSETS?|ON|OPEN(?:DATASOURCE|QUERY|ROWSET)?|OPTIMIZE|OPTION(?:ALLY)?|ORDER|OUT(?:ER|FILE)?|OVER|PARTIAL|PARTITION|PERCENT|PIVOT|PLAN|POINT|POLYGON|PRECEDING|PRECISION|PREPARE|PREV|PRIMARY|PRINT|PRIVILEGES|PROC(?:EDURE)?|PUBLIC|PURGE|QUICK|RAISERROR|READS?|REAL|RECONFIGURE|REFERENCES|RELEASE|RENAME|REPEAT(?:ABLE)?|REPLACE|REPLICATION|REQUIRE|RESIGNAL|RESTORE|RESTRICT|RETURN(?:ING|S)?|REVOKE|RIGHT|ROLLBACK|ROUTINE|ROW(?:COUNT|GUIDCOL|S)?|RTREE|RULE|SAVE(?:POINT)?|SCHEMA|SECOND|SELECT|SERIAL(?:IZABLE)?|SESSION(?:_USER)?|SET(?:USER)?|SHARE|SHOW|SHUTDOWN|SIMPLE|SMALLINT|SNAPSHOT|SOME|SONAME|SQL|START(?:ING)?|STATISTICS|STATUS|STRIPED|SYSTEM_USER|TABLES?|TABLESPACE|TEMP(?:ORARY|TABLE)?|TERMINATED|TEXT(?:SIZE)?|THEN|TIME(?:STAMP)?|TINY(?:BLOB|INT|TEXT)|TOP?|TRAN(?:SACTIONS?)?|TRIGGER|TRUNCATE|TSEQUAL|TYPES?|UNBOUNDED|UNCOMMITTED|UNDEFINED|UNION|UNIQUE|UNLOCK|UNPIVOT|UNSIGNED|UPDATE(?:TEXT)?|USAGE|USE|USER|USING|VALUES?|VAR(?:BINARY|CHAR|CHARACTER|YING)|VIEW|WAITFOR|WARNINGS|WHEN|WHERE|WHILE|WITH(?: ROLLUP|IN)?|WORK|WRITE(?:TEXT)?|YEAR)\b/i,
4245    "boolean": /\b(?:FALSE|NULL|TRUE)\b/i,
4246    "number": /\b0x[\da-f]+\b|\b\d+(?:\.\d*)?|\B\.\d+\b/i,
4247    "operator": /[-+*\/=%^~]|&&?|\|\|?|!=?|<(?:=>?|<|>)?|>[>=]?|\b(?:AND|BETWEEN|DIV|ILIKE|IN|IS|LIKE|NOT|OR|REGEXP|RLIKE|SOUNDS LIKE|XOR)\b/i,
4248    "punctuation": /[;[\]()`,.]/
4249  };
4250
4251  
vendor: 3,404 bytes, lines 4251-4308
4251// node_modules/prismjs/components/prism-powershell.js
4252  (function(Prism3) {
4253    var powershell = Prism3.languages.powershell = {
4254      "comment": [
4255        {
4256          pattern: /(^|[^`])<#[\s\S]*?#>/,
4257          lookbehind: true
4258        },
4259        {
4260          pattern: /(^|[^`])#.*/,
4261          lookbehind: true
4262        }
4263      ],
4264      "string": [
4265        {
4266          pattern: /"(?:`[\s\S]|[^`"])*"/,
4267          greedy: true,
4268          inside: null
4269          // see below
4270        },
4271        {
4272          pattern: /'(?:[^']|'')*'/,
4273          greedy: true
4274        }
4275      ],
4276      // Matches name spaces as well as casts, attribute decorators. Force starting with letter to avoid matching array indices
4277      // Supports two levels of nested brackets (e.g. `[OutputType([System.Collections.Generic.List[int]])]`)
4278      "namespace": /\[[a-z](?:\[(?:\[[^\]]*\]|[^\[\]])*\]|[^\[\]])*\]/i,
4279      "boolean": /\$(?:false|true)\b/i,
4280      "variable": /\$\w+\b/,
4281      // Cmdlets and aliases. Aliases should come last, otherwise "write" gets preferred over "write-host" for example
4282      // Get-Command | ?{ $_.ModuleName -match "Microsoft.PowerShell.(Util|Core|Management)" }
4283      // Get-Alias | ?{ $_.ReferencedCommand.Module.Name -match "Microsoft.PowerShell.(Util|Core|Management)" }
4284      "function": [
4285        /\b(?:Add|Approve|Assert|Backup|Block|Checkpoint|Clear|Close|Compare|Complete|Compress|Confirm|Connect|Convert|ConvertFrom|ConvertTo|Copy|Debug|Deny|Disable|Disconnect|Dismount|Edit|Enable|Enter|Exit|Expand|Export|Find|ForEach|Format|Get|Grant|Group|Hide|Import|Initialize|Install|Invoke|Join|Limit|Lock|Measure|Merge|Move|New|Open|Optimize|Out|Ping|Pop|Protect|Publish|Push|Read|Receive|Redo|Register|Remove|Rename|Repair|Request|Reset|Resize|Resolve|Restart|Restore|Resume|Revoke|Save|Search|Select|Send|Set|Show|Skip|Sort|Split|Start|Step|Stop|Submit|Suspend|Switch|Sync|Tee|Test|Trace|Unblock|Undo|Uninstall|Unlock|Unprotect|Unpublish|Unregister|Update|Use|Wait|Watch|Where|Write)-[a-z]+\b/i,
4286        /\b(?:ac|cat|chdir|clc|cli|clp|clv|compare|copy|cp|cpi|cpp|cvpa|dbp|del|diff|dir|ebp|echo|epal|epcsv|epsn|erase|fc|fl|ft|fw|gal|gbp|gc|gci|gcs|gdr|gi|gl|gm|gp|gps|group|gsv|gu|gv|gwmi|iex|ii|ipal|ipcsv|ipsn|irm|iwmi|iwr|kill|lp|ls|measure|mi|mount|move|mp|mv|nal|ndr|ni|nv|ogv|popd|ps|pushd|pwd|rbp|rd|rdr|ren|ri|rm|rmdir|rni|rnp|rp|rv|rvpa|rwmi|sal|saps|sasv|sbp|sc|select|set|shcm|si|sl|sleep|sls|sort|sp|spps|spsv|start|sv|swmi|tee|trcm|type|write)\b/i
4287      ],
4288      // per http://technet.microsoft.com/en-us/library/hh847744.aspx
4289      "keyword": /\b(?:Begin|Break|Catch|Class|Continue|Data|Define|Do|DynamicParam|Else|ElseIf|End|Exit|Filter|Finally|For|ForEach|From|Function|If|InlineScript|Parallel|Param|Process|Return|Sequence|Switch|Throw|Trap|Try|Until|Using|Var|While|Workflow)\b/i,
4290      "operator": {
4291        pattern: /(^|\W)(?:!|-(?:b?(?:and|x?or)|as|(?:Not)?(?:Contains|In|Like|Match)|eq|ge|gt|is(?:Not)?|Join|le|lt|ne|not|Replace|sh[lr])\b|-[-=]?|\+[+=]?|[*\/%]=?)/i,
4292        lookbehind: true
4293      },
4294      "punctuation": /[|{}[\];(),.]/
4295    };
4296    powershell.string[0].inside = {
4297      "function": {
4298        // Allow for one level of nesting
4299        pattern: /(^|[^`])\$\((?:\$\([^\r\n()]*\)|(?!\$\()[^\r\n)])*\)/,
4300        lookbehind: true,
4301        inside: powershell
4302      },
4303      "boolean": powershell.boolean,
4304      "variable": powershell.variable
4305    };
4306  })(Prism);
4307
4308  
vendor: 2,829 bytes, lines 4308-4373
4308// node_modules/prismjs/components/prism-python.js
4309  Prism.languages.python = {
4310    "comment": {
4311      pattern: /(^|[^\\])#.*/,
4312      lookbehind: true,
4313      greedy: true
4314    },
4315    "string-interpolation": {
4316      pattern: /(?:f|fr|rf)(?:("""|''')[\s\S]*?\1|("|')(?:\\.|(?!\2)[^\\\r\n])*\2)/i,
4317      greedy: true,
4318      inside: {
4319        "interpolation": {
4320          // "{" <expression> <optional "!s", "!r", or "!a"> <optional ":" format specifier> "}"
4321          pattern: /((?:^|[^{])(?:\{\{)*)\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}])+\})+\})+\}/,
4322          lookbehind: true,
4323          inside: {
4324            "format-spec": {
4325              pattern: /(:)[^:(){}]+(?=\}$)/,
4326              lookbehind: true
4327            },
4328            "conversion-option": {
4329              pattern: /![sra](?=[:}]$)/,
4330              alias: "punctuation"
4331            },
4332            rest: null
4333          }
4334        },
4335        "string": /[\s\S]+/
4336      }
4337    },
4338    "triple-quoted-string": {
4339      pattern: /(?:[rub]|br|rb)?("""|''')[\s\S]*?\1/i,
4340      greedy: true,
4341      alias: "string"
4342    },
4343    "string": {
4344      pattern: /(?:[rub]|br|rb)?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/i,
4345      greedy: true
4346    },
4347    "function": {
4348      pattern: /((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g,
4349      lookbehind: true
4350    },
4351    "class-name": {
4352      pattern: /(\bclass\s+)\w+/i,
4353      lookbehind: true
4354    },
4355    "decorator": {
4356      pattern: /(^[\t ]*)@\w+(?:\.\w+)*/m,
4357      lookbehind: true,
4358      alias: ["annotation", "punctuation"],
4359      inside: {
4360        "punctuation": /\./
4361      }
4362    },
4363    "keyword": /\b(?:_(?=\s*:)|and|as|assert|async|await|break|case|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|match|nonlocal|not|or|pass|print|raise|return|try|while|with|yield)\b/,
4364    "builtin": /\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/,
4365    "boolean": /\b(?:False|None|True)\b/,
4366    "number": /\b0(?:b(?:_?[01])+|o(?:_?[0-7])+|x(?:_?[a-f0-9])+)\b|(?:\b\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\B\.\d+(?:_\d+)*)(?:e[+-]?\d+(?:_\d+)*)?j?(?!\w)/i,
4367    "operator": /[-+%=]=?|!=|:=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,
4368    "punctuation": /[{}[\];(),.:]/
4369  };
4370  Prism.languages.python["string-interpolation"].inside["interpolation"].inside.rest = Prism.languages.python;
4371  Prism.languages.py = Prism.languages.python;
4372
4373  
vendor: 4,406 bytes, lines 4373-4496
4373// node_modules/prismjs/components/prism-rust.js
4374  (function(Prism3) {
4375    var multilineComment = /\/\*(?:[^*/]|\*(?!\/)|\/(?!\*)|<self>)*\*\//.source;
4376    for (var i2 = 0; i2 < 2; i2++) {
4377      multilineComment = multilineComment.replace(/<self>/g, function() {
4378        return multilineComment;
4379      });
4380    }
4381    multilineComment = multilineComment.replace(/<self>/g, function() {
4382      return /[^\s\S]/.source;
4383    });
4384    Prism3.languages.rust = {
4385      "comment": [
4386        {
4387          pattern: RegExp(/(^|[^\\])/.source + multilineComment),
4388          lookbehind: true,
4389          greedy: true
4390        },
4391        {
4392          pattern: /(^|[^\\:])\/\/.*/,
4393          lookbehind: true,
4394          greedy: true
4395        }
4396      ],
4397      "string": {
4398        pattern: /b?"(?:\\[\s\S]|[^\\"])*"|b?r(#*)"(?:[^"]|"(?!\1))*"\1/,
4399        greedy: true
4400      },
4401      "char": {
4402        pattern: /b?'(?:\\(?:x[0-7][\da-fA-F]|u\{(?:[\da-fA-F]_*){1,6}\}|.)|[^\\\r\n\t'])'/,
4403        greedy: true
4404      },
4405      "attribute": {
4406        pattern: /#!?\[(?:[^\[\]"]|"(?:\\[\s\S]|[^\\"])*")*\]/,
4407        greedy: true,
4408        alias: "attr-name",
4409        inside: {
4410          "string": null
4411          // see below
4412        }
4413      },
4414      // Closure params should not be confused with bitwise OR |
4415      "closure-params": {
4416        pattern: /([=(,:]\s*|\bmove\s*)\|[^|]*\||\|[^|]*\|(?=\s*(?:\{|->))/,
4417        lookbehind: true,
4418        greedy: true,
4419        inside: {
4420          "closure-punctuation": {
4421            pattern: /^\||\|$/,
4422            alias: "punctuation"
4423          },
4424          rest: null
4425          // see below
4426        }
4427      },
4428      "lifetime-annotation": {
4429        pattern: /'\w+/,
4430        alias: "symbol"
4431      },
4432      "fragment-specifier": {
4433        pattern: /(\$\w+:)[a-z]+/,
4434        lookbehind: true,
4435        alias: "punctuation"
4436      },
4437      "variable": /\$\w+/,
4438      "function-definition": {
4439        pattern: /(\bfn\s+)\w+/,
4440        lookbehind: true,
4441        alias: "function"
4442      },
4443      "type-definition": {
4444        pattern: /(\b(?:enum|struct|trait|type|union)\s+)\w+/,
4445        lookbehind: true,
4446        alias: "class-name"
4447      },
4448      "module-declaration": [
4449        {
4450          pattern: /(\b(?:crate|mod)\s+)[a-z][a-z_\d]*/,
4451          lookbehind: true,
4452          alias: "namespace"
4453        },
4454        {
4455          pattern: /(\b(?:crate|self|super)\s*)::\s*[a-z][a-z_\d]*\b(?:\s*::(?:\s*[a-z][a-z_\d]*\s*::)*)?/,
4456          lookbehind: true,
4457          alias: "namespace",
4458          inside: {
4459            "punctuation": /::/
4460          }
4461        }
4462      ],
4463      "keyword": [
4464        // https://github.com/rust-lang/reference/blob/master/src/keywords.md
4465        /\b(?:Self|abstract|as|async|await|become|box|break|const|continue|crate|do|dyn|else|enum|extern|final|fn|for|if|impl|in|let|loop|macro|match|mod|move|mut|override|priv|pub|ref|return|self|static|struct|super|trait|try|type|typeof|union|unsafe|unsized|use|virtual|where|while|yield)\b/,
4466        // primitives and str
4467        // https://doc.rust-lang.org/stable/rust-by-example/primitives.html
4468        /\b(?:bool|char|f(?:32|64)|[ui](?:8|16|32|64|128|size)|str)\b/
4469      ],
4470      // functions can technically start with an upper-case letter, but this will introduce a lot of false positives
4471      // and Rust's naming conventions recommend snake_case anyway.
4472      // https://doc.rust-lang.org/1.0.0/style/style/naming/README.html
4473      "function": /\b[a-z_]\w*(?=\s*(?:::\s*<|\())/,
4474      "macro": {
4475        pattern: /\b\w+!/,
4476        alias: "property"
4477      },
4478      "constant": /\b[A-Z_][A-Z_\d]+\b/,
4479      "class-name": /\b[A-Z]\w*\b/,
4480      "namespace": {
4481        pattern: /(?:\b[a-z][a-z_\d]*\s*::\s*)*\b[a-z][a-z_\d]*\s*::(?!\s*<)/,
4482        inside: {
4483          "punctuation": /::/
4484        }
4485      },
4486      // Hex, oct, bin, dec numbers with visual separators and type suffix
4487      "number": /\b(?:0x[\dA-Fa-f](?:_?[\dA-Fa-f])*|0o[0-7](?:_?[0-7])*|0b[01](?:_?[01])*|(?:(?:\d(?:_?\d)*)?\.)?\d(?:_?\d)*(?:[Ee][+-]?\d+)?)(?:_?(?:f32|f64|[iu](?:8|16|32|64|size)?))?\b/,
4488      "boolean": /\b(?:false|true)\b/,
4489      "punctuation": /->|\.\.=|\.{1,3}|::|[{}[\];(),:]/,
4490      "operator": /[-+*\/%!^]=?|=[=>]?|&[&=]?|\|[|=]?|<<?=?|>>?=?|[@?]/
4491    };
4492    Prism3.languages.rust["closure-params"].inside.rest = Prism3.languages.rust;
4493    Prism3.languages.rust["attribute"].inside["string"] = Prism3.languages.rust["string"];
4494  })(Prism);
4495
4496  
vendor: 4,712 bytes, lines 4496-4611
4496// node_modules/prismjs/components/prism-swift.js
4497  Prism.languages.swift = {
4498    "comment": {
4499      // Nested comments are supported up to 2 levels
4500      pattern: /(^|[^\\:])(?:\/\/.*|\/\*(?:[^/*]|\/(?!\*)|\*(?!\/)|\/\*(?:[^*]|\*(?!\/))*\*\/)*\*\/)/,
4501      lookbehind: true,
4502      greedy: true
4503    },
4504    "string-literal": [
4505      // https://docs.swift.org/swift-book/LanguageGuide/StringsAndCharacters.html
4506      {
4507        pattern: RegExp(
4508          /(^|[^"#])/.source + "(?:" + /"(?:\\(?:\((?:[^()]|\([^()]*\))*\)|\r\n|[^(])|[^\\\r\n"])*"/.source + "|" + /"""(?:\\(?:\((?:[^()]|\([^()]*\))*\)|[^(])|[^\\"]|"(?!""))*"""/.source + ")" + /(?!["#])/.source
4509        ),
4510        lookbehind: true,
4511        greedy: true,
4512        inside: {
4513          "interpolation": {
4514            pattern: /(\\\()(?:[^()]|\([^()]*\))*(?=\))/,
4515            lookbehind: true,
4516            inside: null
4517            // see below
4518          },
4519          "interpolation-punctuation": {
4520            pattern: /^\)|\\\($/,
4521            alias: "punctuation"
4522          },
4523          "punctuation": /\\(?=[\r\n])/,
4524          "string": /[\s\S]+/
4525        }
4526      },
4527      {
4528        pattern: RegExp(
4529          /(^|[^"#])(#+)/.source + "(?:" + /"(?:\\(?:#+\((?:[^()]|\([^()]*\))*\)|\r\n|[^#])|[^\\\r\n])*?"/.source + "|" + /"""(?:\\(?:#+\((?:[^()]|\([^()]*\))*\)|[^#])|[^\\])*?"""/.source + ")\\2"
4530        ),
4531        lookbehind: true,
4532        greedy: true,
4533        inside: {
4534          "interpolation": {
4535            pattern: /(\\#+\()(?:[^()]|\([^()]*\))*(?=\))/,
4536            lookbehind: true,
4537            inside: null
4538            // see below
4539          },
4540          "interpolation-punctuation": {
4541            pattern: /^\)|\\#+\($/,
4542            alias: "punctuation"
4543          },
4544          "string": /[\s\S]+/
4545        }
4546      }
4547    ],
4548    "directive": {
4549      // directives with conditions
4550      pattern: RegExp(
4551        /#/.source + "(?:" + (/(?:elseif|if)\b/.source + "(?:[ 	]*" + /(?:![ \t]*)?(?:\b\w+\b(?:[ \t]*\((?:[^()]|\([^()]*\))*\))?|\((?:[^()]|\([^()]*\))*\))(?:[ \t]*(?:&&|\|\|))?/.source + ")+") + "|" + /(?:else|endif)\b/.source + ")"
4552      ),
4553      alias: "property",
4554      inside: {
4555        "directive-name": /^#\w+/,
4556        "boolean": /\b(?:false|true)\b/,
4557        "number": /\b\d+(?:\.\d+)*\b/,
4558        "operator": /!|&&|\|\||[<>]=?/,
4559        "punctuation": /[(),]/
4560      }
4561    },
4562    "literal": {
4563      pattern: /#(?:colorLiteral|column|dsohandle|file(?:ID|Literal|Path)?|function|imageLiteral|line)\b/,
4564      alias: "constant"
4565    },
4566    "other-directive": {
4567      pattern: /#\w+\b/,
4568      alias: "property"
4569    },
4570    "attribute": {
4571      pattern: /@\w+/,
4572      alias: "atrule"
4573    },
4574    "function-definition": {
4575      pattern: /(\bfunc\s+)\w+/,
4576      lookbehind: true,
4577      alias: "function"
4578    },
4579    "label": {
4580      // https://docs.swift.org/swift-book/LanguageGuide/ControlFlow.html#ID141
4581      pattern: /\b(break|continue)\s+\w+|\b[a-zA-Z_]\w*(?=\s*:\s*(?:for|repeat|while)\b)/,
4582      lookbehind: true,
4583      alias: "important"
4584    },
4585    "keyword": /\b(?:Any|Protocol|Self|Type|actor|as|assignment|associatedtype|associativity|async|await|break|case|catch|class|continue|convenience|default|defer|deinit|didSet|do|dynamic|else|enum|extension|fallthrough|fileprivate|final|for|func|get|guard|higherThan|if|import|in|indirect|infix|init|inout|internal|is|isolated|lazy|left|let|lowerThan|mutating|none|nonisolated|nonmutating|open|operator|optional|override|postfix|precedencegroup|prefix|private|protocol|public|repeat|required|rethrows|return|right|safe|self|set|some|static|struct|subscript|super|switch|throw|throws|try|typealias|unowned|unsafe|var|weak|where|while|willSet)\b/,
4586    "boolean": /\b(?:false|true)\b/,
4587    "nil": {
4588      pattern: /\bnil\b/,
4589      alias: "constant"
4590    },
4591    "short-argument": /\$\d+\b/,
4592    "omit": {
4593      pattern: /\b_\b/,
4594      alias: "keyword"
4595    },
4596    "number": /\b(?:[\d_]+(?:\.[\de_]+)?|0x[a-f0-9_]+(?:\.[a-f0-9p_]+)?|0b[01_]+|0o[0-7_]+)\b/i,
4597    // A class name must start with an upper-case letter and be either 1 letter long or contain a lower-case letter.
4598    "class-name": /\b[A-Z](?:[A-Z_\d]*[a-z]\w*)?\b/,
4599    "function": /\b[a-z_]\w*(?=\s*\()/i,
4600    "constant": /\b(?:[A-Z_]{2,}|k[A-Z][A-Za-z_]+)\b/,
4601    // Operators are generic in Swift. Developers can even create new operators (e.g. +++).
4602    // https://docs.swift.org/swift-book/ReferenceManual/zzSummaryOfTheGrammar.html#ID481
4603    // This regex only supports ASCII operators.
4604    "operator": /[-+*/%=!<>&|^~?]+|\.[.\-+*/%=!<>&|^~?]+/,
4605    "punctuation": /[{}[\]();,.:\\]/
4606  };
4607  Prism.languages.swift["string-literal"].forEach(function(rule) {
4608    rule.inside["interpolation"].inside = Prism.languages.swift;
4609  });
4610
4611  
vendor: 2,083 bytes, lines 4611-4664
4611// node_modules/prismjs/components/prism-typescript.js
4612  (function(Prism3) {
4613    Prism3.languages.typescript = Prism3.languages.extend("javascript", {
4614      "class-name": {
4615        pattern: /(\b(?:class|extends|implements|instanceof|interface|new|type)\s+)(?!keyof\b)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?:\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>)?/,
4616        lookbehind: true,
4617        greedy: true,
4618        inside: null
4619        // see below
4620      },
4621      "builtin": /\b(?:Array|Function|Promise|any|boolean|console|never|number|string|symbol|unknown)\b/
4622    });
4623    Prism3.languages.typescript.keyword.push(
4624      /\b(?:abstract|declare|is|keyof|readonly|require)\b/,
4625      // keywords that have to be followed by an identifier
4626      /\b(?:asserts|infer|interface|module|namespace|type)\b(?=\s*(?:[{_$a-zA-Z\xA0-\uFFFF]|$))/,
4627      // This is for `import type *, {}`
4628      /\btype\b(?=\s*(?:[\{*]|$))/
4629    );
4630    delete Prism3.languages.typescript["parameter"];
4631    delete Prism3.languages.typescript["literal-property"];
4632    var typeInside = Prism3.languages.extend("typescript", {});
4633    delete typeInside["class-name"];
4634    Prism3.languages.typescript["class-name"].inside = typeInside;
4635    Prism3.languages.insertBefore("typescript", "function", {
4636      "decorator": {
4637        pattern: /@[$\w\xA0-\uFFFF]+/,
4638        inside: {
4639          "at": {
4640            pattern: /^@/,
4641            alias: "operator"
4642          },
4643          "function": /^[\s\S]+/
4644        }
4645      },
4646      "generic-function": {
4647        // e.g. foo<T extends "bar" | "baz">( ...
4648        pattern: /#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>(?=\s*\()/,
4649        greedy: true,
4650        inside: {
4651          "function": /^#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*/,
4652          "generic": {
4653            pattern: /<[\s\S]+/,
4654            // everything after the first <
4655            alias: "class-name",
4656            inside: typeInside
4657          }
4658        }
4659      }
4660    });
4661    Prism3.languages.ts = Prism3.languages.typescript;
4662  })(Prism);
4663
4664  
vendor: 4,679 bytes, lines 4664-4784
4664// node_modules/prismjs/components/prism-java.js
4665  (function(Prism3) {
4666    var keywords = /\b(?:abstract|assert|boolean|break|byte|case|catch|char|class|const|continue|default|do|double|else|enum|exports|extends|final|finally|float|for|goto|if|implements|import|instanceof|int|interface|long|module|native|new|non-sealed|null|open|opens|package|permits|private|protected|provides|public|record(?!\s*[(){}[\]<>=%~.:,;?+\-*/&|^])|requires|return|sealed|short|static|strictfp|super|switch|synchronized|this|throw|throws|to|transient|transitive|try|uses|var|void|volatile|while|with|yield)\b/;
4667    var classNamePrefix = /(?:[a-z]\w*\s*\.\s*)*(?:[A-Z]\w*\s*\.\s*)*/.source;
4668    var className = {
4669      pattern: RegExp(/(^|[^\w.])/.source + classNamePrefix + /[A-Z](?:[\d_A-Z]*[a-z]\w*)?\b/.source),
4670      lookbehind: true,
4671      inside: {
4672        "namespace": {
4673          pattern: /^[a-z]\w*(?:\s*\.\s*[a-z]\w*)*(?:\s*\.)?/,
4674          inside: {
4675            "punctuation": /\./
4676          }
4677        },
4678        "punctuation": /\./
4679      }
4680    };
4681    Prism3.languages.java = Prism3.languages.extend("clike", {
4682      "string": {
4683        pattern: /(^|[^\\])"(?:\\.|[^"\\\r\n])*"/,
4684        lookbehind: true,
4685        greedy: true
4686      },
4687      "class-name": [
4688        className,
4689        {
4690          // variables, parameters, and constructor references
4691          // this to support class names (or generic parameters) which do not contain a lower case letter (also works for methods)
4692          pattern: RegExp(/(^|[^\w.])/.source + classNamePrefix + /[A-Z]\w*(?=\s+\w+\s*[;,=()]|\s*(?:\[[\s,]*\]\s*)?::\s*new\b)/.source),
4693          lookbehind: true,
4694          inside: className.inside
4695        },
4696        {
4697          // class names based on keyword
4698          // this to support class names (or generic parameters) which do not contain a lower case letter (also works for methods)
4699          pattern: RegExp(/(\b(?:class|enum|extends|implements|instanceof|interface|new|record|throws)\s+)/.source + classNamePrefix + /[A-Z]\w*\b/.source),
4700          lookbehind: true,
4701          inside: className.inside
4702        }
4703      ],
4704      "keyword": keywords,
4705      "function": [
4706        Prism3.languages.clike.function,
4707        {
4708          pattern: /(::\s*)[a-z_]\w*/,
4709          lookbehind: true
4710        }
4711      ],
4712      "number": /\b0b[01][01_]*L?\b|\b0x(?:\.[\da-f_p+-]+|[\da-f_]+(?:\.[\da-f_p+-]+)?)\b|(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?\d[\d_]*)?[dfl]?/i,
4713      "operator": {
4714        pattern: /(^|[^.])(?:<<=?|>>>?=?|->|--|\+\+|&&|\|\||::|[?:~]|[-+*/%&|^!=<>]=?)/m,
4715        lookbehind: true
4716      },
4717      "constant": /\b[A-Z][A-Z_\d]+\b/
4718    });
4719    Prism3.languages.insertBefore("java", "string", {
4720      "triple-quoted-string": {
4721        // http://openjdk.java.net/jeps/355#Description
4722        pattern: /"""[ \t]*[\r\n](?:(?:"|"")?(?:\\.|[^"\\]))*"""/,
4723        greedy: true,
4724        alias: "string"
4725      },
4726      "char": {
4727        pattern: /'(?:\\.|[^'\\\r\n]){1,6}'/,
4728        greedy: true
4729      }
4730    });
4731    Prism3.languages.insertBefore("java", "class-name", {
4732      "annotation": {
4733        pattern: /(^|[^.])@\w+(?:\s*\.\s*\w+)*/,
4734        lookbehind: true,
4735        alias: "punctuation"
4736      },
4737      "generics": {
4738        pattern: /<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&))*>)*>)*>)*>/,
4739        inside: {
4740          "class-name": className,
4741          "keyword": keywords,
4742          "punctuation": /[<>(),.:]/,
4743          "operator": /[?&|]/
4744        }
4745      },
4746      "import": [
4747        {
4748          pattern: RegExp(/(\bimport\s+)/.source + classNamePrefix + /(?:[A-Z]\w*|\*)(?=\s*;)/.source),
4749          lookbehind: true,
4750          inside: {
4751            "namespace": className.inside.namespace,
4752            "punctuation": /\./,
4753            "operator": /\*/,
4754            "class-name": /\w+/
4755          }
4756        },
4757        {
4758          pattern: RegExp(/(\bimport\s+static\s+)/.source + classNamePrefix + /(?:\w+|\*)(?=\s*;)/.source),
4759          lookbehind: true,
4760          alias: "static",
4761          inside: {
4762            "namespace": className.inside.namespace,
4763            "static": /\b\w+$/,
4764            "punctuation": /\./,
4765            "operator": /\*/,
4766            "class-name": /\w+/
4767          }
4768        }
4769      ],
4770      "namespace": {
4771        pattern: RegExp(
4772          /(\b(?:exports|import(?:\s+static)?|module|open|opens|package|provides|requires|to|transitive|uses|with)\s+)(?!<keyword>)[a-z]\w*(?:\.[a-z]\w*)*\.?/.source.replace(/<keyword>/g, function() {
4773            return keywords.source;
4774          })
4775        ),
4776        lookbehind: true,
4777        inside: {
4778          "punctuation": /\./
4779        }
4780      }
4781    });
4782  })(Prism);
4783
4784  
vendor: 4,463 bytes, lines 4784-4877
4784// node_modules/prismjs/components/prism-cpp.js
4785  (function(Prism3) {
4786    var keyword = /\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char16_t|char32_t|char8_t|class|co_await|co_return|co_yield|compl|concept|const|const_cast|consteval|constexpr|constinit|continue|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|final|float|for|friend|goto|if|import|inline|int|int16_t|int32_t|int64_t|int8_t|long|module|mutable|namespace|new|noexcept|nullptr|operator|override|private|protected|public|register|reinterpret_cast|requires|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|uint16_t|uint32_t|uint64_t|uint8_t|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/;
4787    var modName = /\b(?!<keyword>)\w+(?:\s*\.\s*\w+)*\b/.source.replace(/<keyword>/g, function() {
4788      return keyword.source;
4789    });
4790    Prism3.languages.cpp = Prism3.languages.extend("c", {
4791      "class-name": [
4792        {
4793          pattern: RegExp(/(\b(?:class|concept|enum|struct|typename)\s+)(?!<keyword>)\w+/.source.replace(/<keyword>/g, function() {
4794            return keyword.source;
4795          })),
4796          lookbehind: true
4797        },
4798        // This is intended to capture the class name of method implementations like:
4799        //   void foo::bar() const {}
4800        // However! The `foo` in the above example could also be a namespace, so we only capture the class name if
4801        // it starts with an uppercase letter. This approximation should give decent results.
4802        /\b[A-Z]\w*(?=\s*::\s*\w+\s*\()/,
4803        // This will capture the class name before destructors like:
4804        //   Foo::~Foo() {}
4805        /\b[A-Z_]\w*(?=\s*::\s*~\w+\s*\()/i,
4806        // This also intends to capture the class name of method implementations but here the class has template
4807        // parameters, so it can't be a namespace (until C++ adds generic namespaces).
4808        /\b\w+(?=\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>\s*::\s*\w+\s*\()/
4809      ],
4810      "keyword": keyword,
4811      "number": {
4812        pattern: /(?:\b0b[01']+|\b0x(?:[\da-f']+(?:\.[\da-f']*)?|\.[\da-f']+)(?:p[+-]?[\d']+)?|(?:\b[\d']+(?:\.[\d']*)?|\B\.[\d']+)(?:e[+-]?[\d']+)?)[ful]{0,4}/i,
4813        greedy: true
4814      },
4815      "operator": />>=?|<<=?|->|--|\+\+|&&|\|\||[?:~]|<=>|[-+*/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/,
4816      "boolean": /\b(?:false|true)\b/
4817    });
4818    Prism3.languages.insertBefore("cpp", "string", {
4819      "module": {
4820        // https://en.cppreference.com/w/cpp/language/modules
4821        pattern: RegExp(
4822          /(\b(?:import|module)\s+)/.source + "(?:" + // header-name
4823          /"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|<[^<>\r\n]*>/.source + "|" + // module name or partition or both
4824          /<mod-name>(?:\s*:\s*<mod-name>)?|:\s*<mod-name>/.source.replace(/<mod-name>/g, function() {
4825            return modName;
4826          }) + ")"
4827        ),
4828        lookbehind: true,
4829        greedy: true,
4830        inside: {
4831          "string": /^[<"][\s\S]+/,
4832          "operator": /:/,
4833          "punctuation": /\./
4834        }
4835      },
4836      "raw-string": {
4837        pattern: /R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/,
4838        alias: "string",
4839        greedy: true
4840      }
4841    });
4842    Prism3.languages.insertBefore("cpp", "keyword", {
4843      "generic-function": {
4844        pattern: /\b(?!operator\b)[a-z_]\w*\s*<(?:[^<>]|<[^<>]*>)*>(?=\s*\()/i,
4845        inside: {
4846          "function": /^\w+/,
4847          "generic": {
4848            pattern: /<[\s\S]+/,
4849            alias: "class-name",
4850            inside: Prism3.languages.cpp
4851          }
4852        }
4853      }
4854    });
4855    Prism3.languages.insertBefore("cpp", "operator", {
4856      "double-colon": {
4857        pattern: /::/,
4858        alias: "punctuation"
4859      }
4860    });
4861    Prism3.languages.insertBefore("cpp", "class-name", {
4862      // the base clause is an optional list of parent classes
4863      // https://en.cppreference.com/w/cpp/language/class
4864      "base-clause": {
4865        pattern: /(\b(?:class|struct)\s+\w+\s*:\s*)[^;{}"'\s]+(?:\s+[^;{}"'\s]+)*(?=\s*[;{])/,
4866        lookbehind: true,
4867        greedy: true,
4868        inside: Prism3.languages.extend("cpp", {})
4869      }
4870    });
4871    Prism3.languages.insertBefore("inside", "double-colon", {
4872      // All untokenized words that are not namespaces should be class names
4873      "class-name": /\b[a-z_]\w*\b(?!\s*::)/i
4874    }, Prism3.languages.cpp["base-clause"]);
4875  })(Prism);
4876
4877  
vendor: 3,855 bytes, lines 4877-4972
4877// node_modules/prismjs/components/prism-markup-templating.js
4878  (function(Prism3) {
4879    function getPlaceholder(language, index) {
4880      return "___" + language.toUpperCase() + index + "___";
4881    }
4882    Object.defineProperties(Prism3.languages["markup-templating"] = {}, {
4883      buildPlaceholders: {
4884        /**
4885         * Tokenize all inline templating expressions matching `placeholderPattern`.
4886         *
4887         * If `replaceFilter` is provided, only matches of `placeholderPattern` for which `replaceFilter` returns
4888         * `true` will be replaced.
4889         *
4890         * @param {object} env The environment of the `before-tokenize` hook.
4891         * @param {string} language The language id.
4892         * @param {RegExp} placeholderPattern The matches of this pattern will be replaced by placeholders.
4893         * @param {(match: string) => boolean} [replaceFilter]
4894         */
4895        value: function(env, language, placeholderPattern, replaceFilter) {
4896          if (env.language !== language) {
4897            return;
4898          }
4899          var tokenStack = env.tokenStack = [];
4900          env.code = env.code.replace(placeholderPattern, function(match) {
4901            if (typeof replaceFilter === "function" && !replaceFilter(match)) {
4902              return match;
4903            }
4904            var i2 = tokenStack.length;
4905            var placeholder;
4906            while (env.code.indexOf(placeholder = getPlaceholder(language, i2)) !== -1) {
4907              ++i2;
4908            }
4909            tokenStack[i2] = match;
4910            return placeholder;
4911          });
4912          env.grammar = Prism3.languages.markup;
4913        }
4914      },
4915      tokenizePlaceholders: {
4916        /**
4917         * Replace placeholders with proper tokens after tokenizing.
4918         *
4919         * @param {object} env The environment of the `after-tokenize` hook.
4920         * @param {string} language The language id.
4921         */
4922        value: function(env, language) {
4923          if (env.language !== language || !env.tokenStack) {
4924            return;
4925          }
4926          env.grammar = Prism3.languages[language];
4927          var j3 = 0;
4928          var keys = Object.keys(env.tokenStack);
4929          function walkTokens(tokens) {
4930            for (var i2 = 0; i2 < tokens.length; i2++) {
4931              if (j3 >= keys.length) {
4932                break;
4933              }
4934              var token = tokens[i2];
4935              if (typeof token === "string" || token.content && typeof token.content === "string") {
4936                var k2 = keys[j3];
4937                var t2 = env.tokenStack[k2];
4938                var s2 = typeof token === "string" ? token : token.content;
4939                var placeholder = getPlaceholder(language, k2);
4940                var index = s2.indexOf(placeholder);
4941                if (index > -1) {
4942                  ++j3;
4943                  var before = s2.substring(0, index);
4944                  var middle = new Prism3.Token(language, Prism3.tokenize(t2, env.grammar), "language-" + language, t2);
4945                  var after = s2.substring(index + placeholder.length);
4946                  var replacement = [];
4947                  if (before) {
4948                    replacement.push.apply(replacement, walkTokens([before]));
4949                  }
4950                  replacement.push(middle);
4951                  if (after) {
4952                    replacement.push.apply(replacement, walkTokens([after]));
4953                  }
4954                  if (typeof token === "string") {
4955                    tokens.splice.apply(tokens, [i2, 1].concat(replacement));
4956                  } else {
4957                    token.content = replacement;
4958                  }
4959                }
4960              } else if (token.content) {
4961                walkTokens(token.content);
4962              }
4963            }
4964            return tokens;
4965          }
4966          walkTokens(env.tokens);
4967        }
4968      }
4969    });
4970  })(Prism);
4971
4972  
vendor: 5,803 bytes, lines 4972-5147
4972// node_modules/prismjs/components/prism-ruby.js
4973  (function(Prism3) {
4974    Prism3.languages.ruby = Prism3.languages.extend("clike", {
4975      "comment": {
4976        pattern: /#.*|^=begin\s[\s\S]*?^=end/m,
4977        greedy: true
4978      },
4979      "class-name": {
4980        pattern: /(\b(?:class|module)\s+|\bcatch\s+\()[\w.\\]+|\b[A-Z_]\w*(?=\s*\.\s*new\b)/,
4981        lookbehind: true,
4982        inside: {
4983          "punctuation": /[.\\]/
4984        }
4985      },
4986      "keyword": /\b(?:BEGIN|END|alias|and|begin|break|case|class|def|define_method|defined|do|each|else|elsif|end|ensure|extend|for|if|in|include|module|new|next|nil|not|or|prepend|private|protected|public|raise|redo|require|rescue|retry|return|self|super|then|throw|undef|unless|until|when|while|yield)\b/,
4987      "operator": /\.{2,3}|&\.|===|<?=>|[!=]?~|(?:&&|\|\||<<|>>|\*\*|[+\-*/%<>!^&|=])=?|[?:]/,
4988      "punctuation": /[(){}[\].,;]/
4989    });
4990    Prism3.languages.insertBefore("ruby", "operator", {
4991      "double-colon": {
4992        pattern: /::/,
4993        alias: "punctuation"
4994      }
4995    });
4996    var interpolation = {
4997      pattern: /((?:^|[^\\])(?:\\{2})*)#\{(?:[^{}]|\{[^{}]*\})*\}/,
4998      lookbehind: true,
4999      inside: {
5000        "content": {
5001          pattern: /^(#\{)[\s\S]+(?=\}$)/,
5002          lookbehind: true,
5003          inside: Prism3.languages.ruby
5004        },
5005        "delimiter": {
5006          pattern: /^#\{|\}$/,
5007          alias: "punctuation"
5008        }
5009      }
5010    };
5011    delete Prism3.languages.ruby.function;
5012    var percentExpression = "(?:" + [
5013      /([^a-zA-Z0-9\s{(\[<=])(?:(?!\1)[^\\]|\\[\s\S])*\1/.source,
5014      /\((?:[^()\\]|\\[\s\S]|\((?:[^()\\]|\\[\s\S])*\))*\)/.source,
5015      /\{(?:[^{}\\]|\\[\s\S]|\{(?:[^{}\\]|\\[\s\S])*\})*\}/.source,
5016      /\[(?:[^\[\]\\]|\\[\s\S]|\[(?:[^\[\]\\]|\\[\s\S])*\])*\]/.source,
5017      /<(?:[^<>\\]|\\[\s\S]|<(?:[^<>\\]|\\[\s\S])*>)*>/.source
5018    ].join("|") + ")";
5019    var symbolName = /(?:"(?:\\.|[^"\\\r\n])*"|(?:\b[a-zA-Z_]\w*|[^\s\0-\x7F]+)[?!]?|\$.)/.source;
5020    Prism3.languages.insertBefore("ruby", "keyword", {
5021      "regex-literal": [
5022        {
5023          pattern: RegExp(/%r/.source + percentExpression + /[egimnosux]{0,6}/.source),
5024          greedy: true,
5025          inside: {
5026            "interpolation": interpolation,
5027            "regex": /[\s\S]+/
5028          }
5029        },
5030        {
5031          pattern: /(^|[^/])\/(?!\/)(?:\[[^\r\n\]]+\]|\\.|[^[/\\\r\n])+\/[egimnosux]{0,6}(?=\s*(?:$|[\r\n,.;})#]))/,
5032          lookbehind: true,
5033          greedy: true,
5034          inside: {
5035            "interpolation": interpolation,
5036            "regex": /[\s\S]+/
5037          }
5038        }
5039      ],
5040      "variable": /[@$]+[a-zA-Z_]\w*(?:[?!]|\b)/,
5041      "symbol": [
5042        {
5043          pattern: RegExp(/(^|[^:]):/.source + symbolName),
5044          lookbehind: true,
5045          greedy: true
5046        },
5047        {
5048          pattern: RegExp(/([\r\n{(,][ \t]*)/.source + symbolName + /(?=:(?!:))/.source),
5049          lookbehind: true,
5050          greedy: true
5051        }
5052      ],
5053      "method-definition": {
5054        pattern: /(\bdef\s+)\w+(?:\s*\.\s*\w+)?/,
5055        lookbehind: true,
5056        inside: {
5057          "function": /\b\w+$/,
5058          "keyword": /^self\b/,
5059          "class-name": /^\w+/,
5060          "punctuation": /\./
5061        }
5062      }
5063    });
5064    Prism3.languages.insertBefore("ruby", "string", {
5065      "string-literal": [
5066        {
5067          pattern: RegExp(/%[qQiIwWs]?/.source + percentExpression),
5068          greedy: true,
5069          inside: {
5070            "interpolation": interpolation,
5071            "string": /[\s\S]+/
5072          }
5073        },
5074        {
5075          pattern: /("|')(?:#\{[^}]+\}|#(?!\{)|\\(?:\r\n|[\s\S])|(?!\1)[^\\#\r\n])*\1/,
5076          greedy: true,
5077          inside: {
5078            "interpolation": interpolation,
5079            "string": /[\s\S]+/
5080          }
5081        },
5082        {
5083          pattern: /<<[-~]?([a-z_]\w*)[\r\n](?:.*[\r\n])*?[\t ]*\1/i,
5084          alias: "heredoc-string",
5085          greedy: true,
5086          inside: {
5087            "delimiter": {
5088              pattern: /^<<[-~]?[a-z_]\w*|\b[a-z_]\w*$/i,
5089              inside: {
5090                "symbol": /\b\w+/,
5091                "punctuation": /^<<[-~]?/
5092              }
5093            },
5094            "interpolation": interpolation,
5095            "string": /[\s\S]+/
5096          }
5097        },
5098        {
5099          pattern: /<<[-~]?'([a-z_]\w*)'[\r\n](?:.*[\r\n])*?[\t ]*\1/i,
5100          alias: "heredoc-string",
5101          greedy: true,
5102          inside: {
5103            "delimiter": {
5104              pattern: /^<<[-~]?'[a-z_]\w*'|\b[a-z_]\w*$/i,
5105              inside: {
5106                "symbol": /\b\w+/,
5107                "punctuation": /^<<[-~]?'|'$/
5108              }
5109            },
5110            "string": /[\s\S]+/
5111          }
5112        }
5113      ],
5114      "command-literal": [
5115        {
5116          pattern: RegExp(/%x/.source + percentExpression),
5117          greedy: true,
5118          inside: {
5119            "interpolation": interpolation,
5120            "command": {
5121              pattern: /[\s\S]+/,
5122              alias: "string"
5123            }
5124          }
5125        },
5126        {
5127          pattern: /`(?:#\{[^}]+\}|#(?!\{)|\\(?:\r\n|[\s\S])|[^\\`#\r\n])*`/,
5128          greedy: true,
5129          inside: {
5130            "interpolation": interpolation,
5131            "command": {
5132              pattern: /[\s\S]+/,
5133              alias: "string"
5134            }
5135          }
5136        }
5137      ]
5138    });
5139    delete Prism3.languages.ruby.string;
5140    Prism3.languages.insertBefore("ruby", "number", {
5141      "builtin": /\b(?:Array|Bignum|Binding|Class|Continuation|Dir|Exception|FalseClass|File|Fixnum|Float|Hash|IO|Integer|MatchData|Method|Module|NilClass|Numeric|Object|Proc|Range|Regexp|Stat|String|Struct|Symbol|TMS|Thread|ThreadGroup|Time|TrueClass)\b/,
5142      "constant": /\b[A-Z][A-Z0-9_]*(?:[?!]|\b)/
5143    });
5144    Prism3.languages.rb = Prism3.languages.ruby;
5145  })(Prism);
5146
5147  
vendor: 10,604 bytes, lines 5147-5476
5147// node_modules/prismjs/components/prism-php.js
5148  (function(Prism3) {
5149    var comment = /\/\*[\s\S]*?\*\/|\/\/.*|#(?!\[).*/;
5150    var constant = [
5151      {
5152        pattern: /\b(?:false|true)\b/i,
5153        alias: "boolean"
5154      },
5155      {
5156        pattern: /(::\s*)\b[a-z_]\w*\b(?!\s*\()/i,
5157        greedy: true,
5158        lookbehind: true
5159      },
5160      {
5161        pattern: /(\b(?:case|const)\s+)\b[a-z_]\w*(?=\s*[;=])/i,
5162        greedy: true,
5163        lookbehind: true
5164      },
5165      /\b(?:null)\b/i,
5166      /\b[A-Z_][A-Z0-9_]*\b(?!\s*\()/
5167    ];
5168    var number = /\b0b[01]+(?:_[01]+)*\b|\b0o[0-7]+(?:_[0-7]+)*\b|\b0x[\da-f]+(?:_[\da-f]+)*\b|(?:\b\d+(?:_\d+)*\.?(?:\d+(?:_\d+)*)?|\B\.\d+)(?:e[+-]?\d+)?/i;
5169    var operator = /<?=>|\?\?=?|\.{3}|\??->|[!=]=?=?|::|\*\*=?|--|\+\+|&&|\|\||<<|>>|[?~]|[/^|%*&<>.+-]=?/;
5170    var punctuation = /[{}\[\](),:;]/;
5171    Prism3.languages.php = {
5172      "delimiter": {
5173        pattern: /\?>$|^<\?(?:php(?=\s)|=)?/i,
5174        alias: "important"
5175      },
5176      "comment": comment,
5177      "variable": /\$+(?:\w+\b|(?=\{))/,
5178      "package": {
5179        pattern: /(namespace\s+|use\s+(?:function\s+)?)(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,
5180        lookbehind: true,
5181        inside: {
5182          "punctuation": /\\/
5183        }
5184      },
5185      "class-name-definition": {
5186        pattern: /(\b(?:class|enum|interface|trait)\s+)\b[a-z_]\w*(?!\\)\b/i,
5187        lookbehind: true,
5188        alias: "class-name"
5189      },
5190      "function-definition": {
5191        pattern: /(\bfunction\s+)[a-z_]\w*(?=\s*\()/i,
5192        lookbehind: true,
5193        alias: "function"
5194      },
5195      "keyword": [
5196        {
5197          pattern: /(\(\s*)\b(?:array|bool|boolean|float|int|integer|object|string)\b(?=\s*\))/i,
5198          alias: "type-casting",
5199          greedy: true,
5200          lookbehind: true
5201        },
5202        {
5203          pattern: /([(,?]\s*)\b(?:array(?!\s*\()|bool|callable|(?:false|null)(?=\s*\|)|float|int|iterable|mixed|object|self|static|string)\b(?=\s*\$)/i,
5204          alias: "type-hint",
5205          greedy: true,
5206          lookbehind: true
5207        },
5208        {
5209          pattern: /(\)\s*:\s*(?:\?\s*)?)\b(?:array(?!\s*\()|bool|callable|(?:false|null)(?=\s*\|)|float|int|iterable|mixed|never|object|self|static|string|void)\b/i,
5210          alias: "return-type",
5211          greedy: true,
5212          lookbehind: true
5213        },
5214        {
5215          pattern: /\b(?:array(?!\s*\()|bool|float|int|iterable|mixed|object|string|void)\b/i,
5216          alias: "type-declaration",
5217          greedy: true
5218        },
5219        {
5220          pattern: /(\|\s*)(?:false|null)\b|\b(?:false|null)(?=\s*\|)/i,
5221          alias: "type-declaration",
5222          greedy: true,
5223          lookbehind: true
5224        },
5225        {
5226          pattern: /\b(?:parent|self|static)(?=\s*::)/i,
5227          alias: "static-context",
5228          greedy: true
5229        },
5230        {
5231          // yield from
5232          pattern: /(\byield\s+)from\b/i,
5233          lookbehind: true
5234        },
5235        // `class` is always a keyword unlike other keywords
5236        /\bclass\b/i,
5237        {
5238          // https://www.php.net/manual/en/reserved.keywords.php
5239          //
5240          // keywords cannot be preceded by "->"
5241          // the complex lookbehind means `(?<!(?:->|::)\s*)`
5242          pattern: /((?:^|[^\s>:]|(?:^|[^-])>|(?:^|[^:]):)\s*)\b(?:abstract|and|array|as|break|callable|case|catch|clone|const|continue|declare|default|die|do|echo|else|elseif|empty|enddeclare|endfor|endforeach|endif|endswitch|endwhile|enum|eval|exit|extends|final|finally|fn|for|foreach|function|global|goto|if|implements|include|include_once|instanceof|insteadof|interface|isset|list|match|namespace|never|new|or|parent|print|private|protected|public|readonly|require|require_once|return|self|static|switch|throw|trait|try|unset|use|var|while|xor|yield|__halt_compiler)\b/i,
5243          lookbehind: true
5244        }
5245      ],
5246      "argument-name": {
5247        pattern: /([(,]\s*)\b[a-z_]\w*(?=\s*:(?!:))/i,
5248        lookbehind: true
5249      },
5250      "class-name": [
5251        {
5252          pattern: /(\b(?:extends|implements|instanceof|new(?!\s+self|\s+static))\s+|\bcatch\s*\()\b[a-z_]\w*(?!\\)\b/i,
5253          greedy: true,
5254          lookbehind: true
5255        },
5256        {
5257          pattern: /(\|\s*)\b[a-z_]\w*(?!\\)\b/i,
5258          greedy: true,
5259          lookbehind: true
5260        },
5261        {
5262          pattern: /\b[a-z_]\w*(?!\\)\b(?=\s*\|)/i,
5263          greedy: true
5264        },
5265        {
5266          pattern: /(\|\s*)(?:\\?\b[a-z_]\w*)+\b/i,
5267          alias: "class-name-fully-qualified",
5268          greedy: true,
5269          lookbehind: true,
5270          inside: {
5271            "punctuation": /\\/
5272          }
5273        },
5274        {
5275          pattern: /(?:\\?\b[a-z_]\w*)+\b(?=\s*\|)/i,
5276          alias: "class-name-fully-qualified",
5277          greedy: true,
5278          inside: {
5279            "punctuation": /\\/
5280          }
5281        },
5282        {
5283          pattern: /(\b(?:extends|implements|instanceof|new(?!\s+self\b|\s+static\b))\s+|\bcatch\s*\()(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,
5284          alias: "class-name-fully-qualified",
5285          greedy: true,
5286          lookbehind: true,
5287          inside: {
5288            "punctuation": /\\/
5289          }
5290        },
5291        {
5292          pattern: /\b[a-z_]\w*(?=\s*\$)/i,
5293          alias: "type-declaration",
5294          greedy: true
5295        },
5296        {
5297          pattern: /(?:\\?\b[a-z_]\w*)+(?=\s*\$)/i,
5298          alias: ["class-name-fully-qualified", "type-declaration"],
5299          greedy: true,
5300          inside: {
5301            "punctuation": /\\/
5302          }
5303        },
5304        {
5305          pattern: /\b[a-z_]\w*(?=\s*::)/i,
5306          alias: "static-context",
5307          greedy: true
5308        },
5309        {
5310          pattern: /(?:\\?\b[a-z_]\w*)+(?=\s*::)/i,
5311          alias: ["class-name-fully-qualified", "static-context"],
5312          greedy: true,
5313          inside: {
5314            "punctuation": /\\/
5315          }
5316        },
5317        {
5318          pattern: /([(,?]\s*)[a-z_]\w*(?=\s*\$)/i,
5319          alias: "type-hint",
5320          greedy: true,
5321          lookbehind: true
5322        },
5323        {
5324          pattern: /([(,?]\s*)(?:\\?\b[a-z_]\w*)+(?=\s*\$)/i,
5325          alias: ["class-name-fully-qualified", "type-hint"],
5326          greedy: true,
5327          lookbehind: true,
5328          inside: {
5329            "punctuation": /\\/
5330          }
5331        },
5332        {
5333          pattern: /(\)\s*:\s*(?:\?\s*)?)\b[a-z_]\w*(?!\\)\b/i,
5334          alias: "return-type",
5335          greedy: true,
5336          lookbehind: true
5337        },
5338        {
5339          pattern: /(\)\s*:\s*(?:\?\s*)?)(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,
5340          alias: ["class-name-fully-qualified", "return-type"],
5341          greedy: true,
5342          lookbehind: true,
5343          inside: {
5344            "punctuation": /\\/
5345          }
5346        }
5347      ],
5348      "constant": constant,
5349      "function": {
5350        pattern: /(^|[^\\\w])\\?[a-z_](?:[\w\\]*\w)?(?=\s*\()/i,
5351        lookbehind: true,
5352        inside: {
5353          "punctuation": /\\/
5354        }
5355      },
5356      "property": {
5357        pattern: /(->\s*)\w+/,
5358        lookbehind: true
5359      },
5360      "number": number,
5361      "operator": operator,
5362      "punctuation": punctuation
5363    };
5364    var string_interpolation = {
5365      pattern: /\{\$(?:\{(?:\{[^{}]+\}|[^{}]+)\}|[^{}])+\}|(^|[^\\{])\$+(?:\w+(?:\[[^\r\n\[\]]+\]|->\w+)?)/,
5366      lookbehind: true,
5367      inside: Prism3.languages.php
5368    };
5369    var string = [
5370      {
5371        pattern: /<<<'([^']+)'[\r\n](?:.*[\r\n])*?\1;/,
5372        alias: "nowdoc-string",
5373        greedy: true,
5374        inside: {
5375          "delimiter": {
5376            pattern: /^<<<'[^']+'|[a-z_]\w*;$/i,
5377            alias: "symbol",
5378            inside: {
5379              "punctuation": /^<<<'?|[';]$/
5380            }
5381          }
5382        }
5383      },
5384      {
5385        pattern: /<<<(?:"([^"]+)"[\r\n](?:.*[\r\n])*?\1;|([a-z_]\w*)[\r\n](?:.*[\r\n])*?\2;)/i,
5386        alias: "heredoc-string",
5387        greedy: true,
5388        inside: {
5389          "delimiter": {
5390            pattern: /^<<<(?:"[^"]+"|[a-z_]\w*)|[a-z_]\w*;$/i,
5391            alias: "symbol",
5392            inside: {
5393              "punctuation": /^<<<"?|[";]$/
5394            }
5395          },
5396          "interpolation": string_interpolation
5397        }
5398      },
5399      {
5400        pattern: /`(?:\\[\s\S]|[^\\`])*`/,
5401        alias: "backtick-quoted-string",
5402        greedy: true
5403      },
5404      {
5405        pattern: /'(?:\\[\s\S]|[^\\'])*'/,
5406        alias: "single-quoted-string",
5407        greedy: true
5408      },
5409      {
5410        pattern: /"(?:\\[\s\S]|[^\\"])*"/,
5411        alias: "double-quoted-string",
5412        greedy: true,
5413        inside: {
5414          "interpolation": string_interpolation
5415        }
5416      }
5417    ];
5418    Prism3.languages.insertBefore("php", "variable", {
5419      "string": string,
5420      "attribute": {
5421        pattern: /#\[(?:[^"'\/#]|\/(?![*/])|\/\/.*$|#(?!\[).*$|\/\*(?:[^*]|\*(?!\/))*\*\/|"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*')+\](?=\s*[a-z$#])/im,
5422        greedy: true,
5423        inside: {
5424          "attribute-content": {
5425            pattern: /^(#\[)[\s\S]+(?=\]$)/,
5426            lookbehind: true,
5427            // inside can appear subset of php
5428            inside: {
5429              "comment": comment,
5430              "string": string,
5431              "attribute-class-name": [
5432                {
5433                  pattern: /([^:]|^)\b[a-z_]\w*(?!\\)\b/i,
5434                  alias: "class-name",
5435                  greedy: true,
5436                  lookbehind: true
5437                },
5438                {
5439                  pattern: /([^:]|^)(?:\\?\b[a-z_]\w*)+/i,
5440                  alias: [
5441                    "class-name",
5442                    "class-name-fully-qualified"
5443                  ],
5444                  greedy: true,
5445                  lookbehind: true,
5446                  inside: {
5447                    "punctuation": /\\/
5448                  }
5449                }
5450              ],
5451              "constant": constant,
5452              "number": number,
5453              "operator": operator,
5454              "punctuation": punctuation
5455            }
5456          },
5457          "delimiter": {
5458            pattern: /^#\[|\]$/,
5459            alias: "punctuation"
5460          }
5461        }
5462      }
5463    });
5464    Prism3.hooks.add("before-tokenize", function(env) {
5465      if (!/<\?/.test(env.code)) {
5466        return;
5467      }
5468      var phpPattern = /<\?(?:[^"'/#]|\/(?![*/])|("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|(?:\/\/|#(?!\[))(?:[^?\n\r]|\?(?!>))*(?=$|\?>|[\r\n])|#\[|\/\*(?:[^*]|\*(?!\/))*(?:\*\/|$))*?(?:\?>|$)/g;
5469      Prism3.languages["markup-templating"].buildPlaceholders(env, "php", phpPattern);
5470    });
5471    Prism3.hooks.add("after-tokenize", function(env) {
5472      Prism3.languages["markup-templating"].tokenizePlaceholders(env, "php");
5473    });
5474  })(Prism);
5475
5476  
vendor: 1,291 bytes, lines 5476-5504
5476// node_modules/prismjs/components/prism-go.js
5477  Prism.languages.go = Prism.languages.extend("clike", {
5478    "string": {
5479      pattern: /(^|[^\\])"(?:\\.|[^"\\\r\n])*"|`[^`]*`/,
5480      lookbehind: true,
5481      greedy: true
5482    },
5483    "keyword": /\b(?:break|case|chan|const|continue|default|defer|else|fallthrough|for|func|go(?:to)?|if|import|interface|map|package|range|return|select|struct|switch|type|var)\b/,
5484    "boolean": /\b(?:_|false|iota|nil|true)\b/,
5485    "number": [
5486      // binary and octal integers
5487      /\b0(?:b[01_]+|o[0-7_]+)i?\b/i,
5488      // hexadecimal integers and floats
5489      /\b0x(?:[a-f\d_]+(?:\.[a-f\d_]*)?|\.[a-f\d_]+)(?:p[+-]?\d+(?:_\d+)*)?i?(?!\w)/i,
5490      // decimal integers and floats
5491      /(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?[\d_]+)?i?(?!\w)/i
5492    ],
5493    "operator": /[*\/%^!=]=?|\+[=+]?|-[=-]?|\|[=|]?|&(?:=|&|\^=?)?|>(?:>=?|=)?|<(?:<=?|=|-)?|:=|\.\.\./,
5494    "builtin": /\b(?:append|bool|byte|cap|close|complex|complex(?:64|128)|copy|delete|error|float(?:32|64)|u?int(?:8|16|32|64)?|imag|len|make|new|panic|print(?:ln)?|real|recover|rune|string|uintptr)\b/
5495  });
5496  Prism.languages.insertBefore("go", "string", {
5497    "char": {
5498      pattern: /'(?:\\.|[^'\\\r\n]){0,10}'/,
5499      greedy: true
5500    }
5501  });
5502  delete Prism.languages.go["class-name"];
5503
5504  
vendor: 10,138 bytes, lines 5504-5732
5504// node_modules/prismjs/components/prism-bash.js
5505  (function(Prism3) {
5506    var envVars = "\\b(?:BASH|BASHOPTS|BASH_ALIASES|BASH_ARGC|BASH_ARGV|BASH_CMDS|BASH_COMPLETION_COMPAT_DIR|BASH_LINENO|BASH_REMATCH|BASH_SOURCE|BASH_VERSINFO|BASH_VERSION|COLORTERM|COLUMNS|COMP_WORDBREAKS|DBUS_SESSION_BUS_ADDRESS|DEFAULTS_PATH|DESKTOP_SESSION|DIRSTACK|DISPLAY|EUID|GDMSESSION|GDM_LANG|GNOME_KEYRING_CONTROL|GNOME_KEYRING_PID|GPG_AGENT_INFO|GROUPS|HISTCONTROL|HISTFILE|HISTFILESIZE|HISTSIZE|HOME|HOSTNAME|HOSTTYPE|IFS|INSTANCE|JOB|LANG|LANGUAGE|LC_ADDRESS|LC_ALL|LC_IDENTIFICATION|LC_MEASUREMENT|LC_MONETARY|LC_NAME|LC_NUMERIC|LC_PAPER|LC_TELEPHONE|LC_TIME|LESSCLOSE|LESSOPEN|LINES|LOGNAME|LS_COLORS|MACHTYPE|MAILCHECK|MANDATORY_PATH|NO_AT_BRIDGE|OLDPWD|OPTERR|OPTIND|ORBIT_SOCKETDIR|OSTYPE|PAPERSIZE|PATH|PIPESTATUS|PPID|PS1|PS2|PS3|PS4|PWD|RANDOM|REPLY|SECONDS|SELINUX_INIT|SESSION|SESSIONTYPE|SESSION_MANAGER|SHELL|SHELLOPTS|SHLVL|SSH_AUTH_SOCK|TERM|UID|UPSTART_EVENTS|UPSTART_INSTANCE|UPSTART_JOB|UPSTART_SESSION|USER|WINDOWID|XAUTHORITY|XDG_CONFIG_DIRS|XDG_CURRENT_DESKTOP|XDG_DATA_DIRS|XDG_GREETER_DATA_DIR|XDG_MENU_PREFIX|XDG_RUNTIME_DIR|XDG_SEAT|XDG_SEAT_PATH|XDG_SESSION_DESKTOP|XDG_SESSION_ID|XDG_SESSION_PATH|XDG_SESSION_TYPE|XDG_VTNR|XMODIFIERS)\\b";
5507    var commandAfterHeredoc = {
5508      pattern: /(^(["']?)\w+\2)[ \t]+\S.*/,
5509      lookbehind: true,
5510      alias: "punctuation",
5511      // this looks reasonably well in all themes
5512      inside: null
5513      // see below
5514    };
5515    var insideString = {
5516      "bash": commandAfterHeredoc,
5517      "environment": {
5518        pattern: RegExp("\\$" + envVars),
5519        alias: "constant"
5520      },
5521      "variable": [
5522        // [0]: Arithmetic Environment
5523        {
5524          pattern: /\$?\(\([\s\S]+?\)\)/,
5525          greedy: true,
5526          inside: {
5527            // If there is a $ sign at the beginning highlight $(( and )) as variable
5528            "variable": [
5529              {
5530                pattern: /(^\$\(\([\s\S]+)\)\)/,
5531                lookbehind: true
5532              },
5533              /^\$\(\(/
5534            ],
5535            "number": /\b0x[\dA-Fa-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee]-?\d+)?/,
5536            // Operators according to https://www.gnu.org/software/bash/manual/bashref.html#Shell-Arithmetic
5537            "operator": /--|\+\+|\*\*=?|<<=?|>>=?|&&|\|\||[=!+\-*/%<>^&|]=?|[?~:]/,
5538            // If there is no $ sign at the beginning highlight (( and )) as punctuation
5539            "punctuation": /\(\(?|\)\)?|,|;/
5540          }
5541        },
5542        // [1]: Command Substitution
5543        {
5544          pattern: /\$\((?:\([^)]+\)|[^()])+\)|`[^`]+`/,
5545          greedy: true,
5546          inside: {
5547            "variable": /^\$\(|^`|\)$|`$/
5548          }
5549        },
5550        // [2]: Brace expansion
5551        {
5552          pattern: /\$\{[^}]+\}/,
5553          greedy: true,
5554          inside: {
5555            "operator": /:[-=?+]?|[!\/]|##?|%%?|\^\^?|,,?/,
5556            "punctuation": /[\[\]]/,
5557            "environment": {
5558              pattern: RegExp("(\\{)" + envVars),
5559              lookbehind: true,
5560              alias: "constant"
5561            }
5562          }
5563        },
5564        /\$(?:\w+|[#?*!@$])/
5565      ],
5566      // Escape sequences from echo and printf's manuals, and escaped quotes.
5567      "entity": /\\(?:[abceEfnrtv\\"]|O?[0-7]{1,3}|U[0-9a-fA-F]{8}|u[0-9a-fA-F]{4}|x[0-9a-fA-F]{1,2})/
5568    };
5569    Prism3.languages.bash = {
5570      "shebang": {
5571        pattern: /^#!\s*\/.*/,
5572        alias: "important"
5573      },
5574      "comment": {
5575        pattern: /(^|[^"{\\$])#.*/,
5576        lookbehind: true
5577      },
5578      "function-name": [
5579        // a) function foo {
5580        // b) foo() {
5581        // c) function foo() {
5582        // but not “foo {”
5583        {
5584          // a) and c)
5585          pattern: /(\bfunction\s+)[\w-]+(?=(?:\s*\(?:\s*\))?\s*\{)/,
5586          lookbehind: true,
5587          alias: "function"
5588        },
5589        {
5590          // b)
5591          pattern: /\b[\w-]+(?=\s*\(\s*\)\s*\{)/,
5592          alias: "function"
5593        }
5594      ],
5595      // Highlight variable names as variables in for and select beginnings.
5596      "for-or-select": {
5597        pattern: /(\b(?:for|select)\s+)\w+(?=\s+in\s)/,
5598        alias: "variable",
5599        lookbehind: true
5600      },
5601      // Highlight variable names as variables in the left-hand part
5602      // of assignments (“=” and “+=”).
5603      "assign-left": {
5604        pattern: /(^|[\s;|&]|[<>]\()\w+(?:\.\w+)*(?=\+?=)/,
5605        inside: {
5606          "environment": {
5607            pattern: RegExp("(^|[\\s;|&]|[<>]\\()" + envVars),
5608            lookbehind: true,
5609            alias: "constant"
5610          }
5611        },
5612        alias: "variable",
5613        lookbehind: true
5614      },
5615      // Highlight parameter names as variables
5616      "parameter": {
5617        pattern: /(^|\s)-{1,2}(?:\w+:[+-]?)?\w+(?:\.\w+)*(?=[=\s]|$)/,
5618        alias: "variable",
5619        lookbehind: true
5620      },
5621      "string": [
5622        // Support for Here-documents https://en.wikipedia.org/wiki/Here_document
5623        {
5624          pattern: /((?:^|[^<])<<-?\s*)(\w+)\s[\s\S]*?(?:\r?\n|\r)\2/,
5625          lookbehind: true,
5626          greedy: true,
5627          inside: insideString
5628        },
5629        // Here-document with quotes around the tag
5630        // → No expansion (so no “inside”).
5631        {
5632          pattern: /((?:^|[^<])<<-?\s*)(["'])(\w+)\2\s[\s\S]*?(?:\r?\n|\r)\3/,
5633          lookbehind: true,
5634          greedy: true,
5635          inside: {
5636            "bash": commandAfterHeredoc
5637          }
5638        },
5639        // “Normal” string
5640        {
5641          // https://www.gnu.org/software/bash/manual/html_node/Double-Quotes.html
5642          pattern: /(^|[^\\](?:\\\\)*)"(?:\\[\s\S]|\$\([^)]+\)|\$(?!\()|`[^`]+`|[^"\\`$])*"/,
5643          lookbehind: true,
5644          greedy: true,
5645          inside: insideString
5646        },
5647        {
5648          // https://www.gnu.org/software/bash/manual/html_node/Single-Quotes.html
5649          pattern: /(^|[^$\\])'[^']*'/,
5650          lookbehind: true,
5651          greedy: true
5652        },
5653        {
5654          // https://www.gnu.org/software/bash/manual/html_node/ANSI_002dC-Quoting.html
5655          pattern: /\$'(?:[^'\\]|\\[\s\S])*'/,
5656          greedy: true,
5657          inside: {
5658            "entity": insideString.entity
5659          }
5660        }
5661      ],
5662      "environment": {
5663        pattern: RegExp("\\$?" + envVars),
5664        alias: "constant"
5665      },
5666      "variable": insideString.variable,
5667      "function": {
5668        pattern: /(^|[\s;|&]|[<>]\()(?:add|apropos|apt|apt-cache|apt-get|aptitude|aspell|automysqlbackup|awk|basename|bash|bc|bconsole|bg|bzip2|cal|cargo|cat|cfdisk|chgrp|chkconfig|chmod|chown|chroot|cksum|clear|cmp|column|comm|composer|cp|cron|crontab|csplit|curl|cut|date|dc|dd|ddrescue|debootstrap|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|docker|docker-compose|du|egrep|eject|env|ethtool|expand|expect|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|git|gparted|grep|groupadd|groupdel|groupmod|groups|grub-mkconfig|gzip|halt|head|hg|history|host|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|ip|java|jobs|join|kill|killall|less|link|ln|locate|logname|logrotate|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|lynx|make|man|mc|mdadm|mkconfig|mkdir|mke2fs|mkfifo|mkfs|mkisofs|mknod|mkswap|mmv|more|most|mount|mtools|mtr|mutt|mv|nano|nc|netstat|nice|nl|node|nohup|notify-send|npm|nslookup|op|open|parted|passwd|paste|pathchk|ping|pkill|pnpm|podman|podman-compose|popd|pr|printcap|printenv|ps|pushd|pv|quota|quotacheck|quotactl|ram|rar|rcp|reboot|remsync|rename|renice|rev|rm|rmdir|rpm|rsync|scp|screen|sdiff|sed|sendmail|seq|service|sftp|sh|shellcheck|shuf|shutdown|sleep|slocate|sort|split|ssh|stat|strace|su|sudo|sum|suspend|swapon|sync|sysctl|tac|tail|tar|tee|time|timeout|top|touch|tr|traceroute|tsort|tty|umount|uname|unexpand|uniq|units|unrar|unshar|unzip|update-grub|uptime|useradd|userdel|usermod|users|uudecode|uuencode|v|vcpkg|vdir|vi|vim|virsh|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yarn|yes|zenity|zip|zsh|zypper)(?=$|[)\s;|&])/,
5669        lookbehind: true
5670      },
5671      "keyword": {
5672        pattern: /(^|[\s;|&]|[<>]\()(?:case|do|done|elif|else|esac|fi|for|function|if|in|select|then|until|while)(?=$|[)\s;|&])/,
5673        lookbehind: true
5674      },
5675      // https://www.gnu.org/software/bash/manual/html_node/Shell-Builtin-Commands.html
5676      "builtin": {
5677        pattern: /(^|[\s;|&]|[<>]\()(?:\.|:|alias|bind|break|builtin|caller|cd|command|continue|declare|echo|enable|eval|exec|exit|export|getopts|hash|help|let|local|logout|mapfile|printf|pwd|read|readarray|readonly|return|set|shift|shopt|source|test|times|trap|type|typeset|ulimit|umask|unalias|unset)(?=$|[)\s;|&])/,
5678        lookbehind: true,
5679        // Alias added to make those easier to distinguish from strings.
5680        alias: "class-name"
5681      },
5682      "boolean": {
5683        pattern: /(^|[\s;|&]|[<>]\()(?:false|true)(?=$|[)\s;|&])/,
5684        lookbehind: true
5685      },
5686      "file-descriptor": {
5687        pattern: /\B&\d\b/,
5688        alias: "important"
5689      },
5690      "operator": {
5691        // Lots of redirections here, but not just that.
5692        pattern: /\d?<>|>\||\+=|=[=~]?|!=?|<<[<-]?|[&\d]?>>|\d[<>]&?|[<>][&=]?|&[>&]?|\|[&|]?/,
5693        inside: {
5694          "file-descriptor": {
5695            pattern: /^\d/,
5696            alias: "important"
5697          }
5698        }
5699      },
5700      "punctuation": /\$?\(\(?|\)\)?|\.\.|[{}[\];\\]/,
5701      "number": {
5702        pattern: /(^|\s)(?:[1-9]\d*|0)(?:[.,]\d+)?\b/,
5703        lookbehind: true
5704      }
5705    };
5706    commandAfterHeredoc.inside = Prism3.languages.bash;
5707    var toBeCopied = [
5708      "comment",
5709      "function-name",
5710      "for-or-select",
5711      "assign-left",
5712      "parameter",
5713      "string",
5714      "environment",
5715      "function",
5716      "keyword",
5717      "builtin",
5718      "boolean",
5719      "file-descriptor",
5720      "operator",
5721      "punctuation",
5722      "number"
5723    ];
5724    var inside = insideString.variable[1].inside;
5725    for (var i2 = 0; i2 < toBeCopied.length; i2++) {
5726      inside[toBeCopied[i2]] = Prism3.languages.bash[toBeCopied[i2]];
5727    }
5728    Prism3.languages.sh = Prism3.languages.bash;
5729    Prism3.languages.shell = Prism3.languages.bash;
5730  })(Prism);
5731
5732  
vendor: 688 bytes, lines 5732-5759
5732// node_modules/prismjs/components/prism-json.js
5733  Prism.languages.json = {
5734    "property": {
5735      pattern: /(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?=\s*:)/,
5736      lookbehind: true,
5737      greedy: true
5738    },
5739    "string": {
5740      pattern: /(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?!\s*:)/,
5741      lookbehind: true,
5742      greedy: true
5743    },
5744    "comment": {
5745      pattern: /\/\/.*|\/\*[\s\S]*?(?:\*\/|$)/,
5746      greedy: true
5747    },
5748    "number": /-?\b\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,
5749    "punctuation": /[{}[\],]/,
5750    "operator": /:/,
5751    "boolean": /\b(?:false|true)\b/,
5752    "null": {
5753      pattern: /\bnull\b/,
5754      alias: "keyword"
5755    }
5756  };
5757  Prism.languages.webmanifest = Prism.languages.json;
5758
5759  
vendor: 3,117 bytes, lines 5759-5842
5759// node_modules/prismjs/components/prism-kotlin.js
5760  (function(Prism3) {
5761    Prism3.languages.kotlin = Prism3.languages.extend("clike", {
5762      "keyword": {
5763        // The lookbehind prevents wrong highlighting of e.g. kotlin.properties.get
5764        pattern: /(^|[^.])\b(?:abstract|actual|annotation|as|break|by|catch|class|companion|const|constructor|continue|crossinline|data|do|dynamic|else|enum|expect|external|final|finally|for|fun|get|if|import|in|infix|init|inline|inner|interface|internal|is|lateinit|noinline|null|object|open|operator|out|override|package|private|protected|public|reified|return|sealed|set|super|suspend|tailrec|this|throw|to|try|typealias|val|var|vararg|when|where|while)\b/,
5765        lookbehind: true
5766      },
5767      "function": [
5768        {
5769          pattern: /(?:`[^\r\n`]+`|\b\w+)(?=\s*\()/,
5770          greedy: true
5771        },
5772        {
5773          pattern: /(\.)(?:`[^\r\n`]+`|\w+)(?=\s*\{)/,
5774          lookbehind: true,
5775          greedy: true
5776        }
5777      ],
5778      "number": /\b(?:0[xX][\da-fA-F]+(?:_[\da-fA-F]+)*|0[bB][01]+(?:_[01]+)*|\d+(?:_\d+)*(?:\.\d+(?:_\d+)*)?(?:[eE][+-]?\d+(?:_\d+)*)?[fFL]?)\b/,
5779      "operator": /\+[+=]?|-[-=>]?|==?=?|!(?:!|==?)?|[\/*%<>]=?|[?:]:?|\.\.|&&|\|\||\b(?:and|inv|or|shl|shr|ushr|xor)\b/
5780    });
5781    delete Prism3.languages.kotlin["class-name"];
5782    var interpolationInside = {
5783      "interpolation-punctuation": {
5784        pattern: /^\$\{?|\}$/,
5785        alias: "punctuation"
5786      },
5787      "expression": {
5788        pattern: /[\s\S]+/,
5789        inside: Prism3.languages.kotlin
5790      }
5791    };
5792    Prism3.languages.insertBefore("kotlin", "string", {
5793      // https://kotlinlang.org/spec/expressions.html#string-interpolation-expressions
5794      "string-literal": [
5795        {
5796          pattern: /"""(?:[^$]|\$(?:(?!\{)|\{[^{}]*\}))*?"""/,
5797          alias: "multiline",
5798          inside: {
5799            "interpolation": {
5800              pattern: /\$(?:[a-z_]\w*|\{[^{}]*\})/i,
5801              inside: interpolationInside
5802            },
5803            "string": /[\s\S]+/
5804          }
5805        },
5806        {
5807          pattern: /"(?:[^"\\\r\n$]|\\.|\$(?:(?!\{)|\{[^{}]*\}))*"/,
5808          alias: "singleline",
5809          inside: {
5810            "interpolation": {
5811              pattern: /((?:^|[^\\])(?:\\{2})*)\$(?:[a-z_]\w*|\{[^{}]*\})/i,
5812              lookbehind: true,
5813              inside: interpolationInside
5814            },
5815            "string": /[\s\S]+/
5816          }
5817        }
5818      ],
5819      "char": {
5820        // https://kotlinlang.org/spec/expressions.html#character-literals
5821        pattern: /'(?:[^'\\\r\n]|\\(?:.|u[a-fA-F0-9]{0,4}))'/,
5822        greedy: true
5823      }
5824    });
5825    delete Prism3.languages.kotlin["string"];
5826    Prism3.languages.insertBefore("kotlin", "keyword", {
5827      "annotation": {
5828        pattern: /\B@(?:\w+:)?(?:[A-Z]\w*|\[[^\]]+\])/,
5829        alias: "builtin"
5830      }
5831    });
5832    Prism3.languages.insertBefore("kotlin", "function", {
5833      "label": {
5834        pattern: /\b\w+@|@\w+\b/,
5835        alias: "symbol"
5836      }
5837    });
5838    Prism3.languages.kt = Prism3.languages.kotlin;
5839    Prism3.languages.kts = Prism3.languages.kotlin;
5840  })(Prism);
5841
5842  
vendor: 3,801 bytes, lines 5842-5948
5842// node_modules/@37signals/lexxy/dist/lexxy_helpers.esm.js
5843  window.Prism ||= {};
5844  window.Prism.manual = true;
5845  function highlightCode(root = document) {
5846    const elements = root.querySelectorAll("pre[data-language]:not([data-highlighted])");
5847    elements.forEach((preElement) => {
5848      highlightElement(preElement);
5849    });
5850  }
5851  function highlightElement(preElement) {
5852    if (preElement.dataset.highlighted === "true") return;
5853    const language = preElement.getAttribute("data-language");
5854    const grammar = import_prismjs.default.languages?.[language];
5855    if (!grammar) return;
5856    const { code, highlights } = extractCodeAndHighlights(preElement);
5857    const highlightedHtml = import_prismjs.default.highlight(code, grammar, language);
5858    preElement.innerHTML = highlightedHtml;
5859    if (highlights.length > 0) {
5860      applyHighlightRanges(preElement, highlights);
5861    }
5862    preElement.dataset.highlighted = "true";
5863  }
5864  function extractCodeAndHighlights(preElement) {
5865    const root = preElement.querySelector("code") || preElement;
5866    const highlights = [];
5867    let code = "";
5868    function walk(node) {
5869      if (node.nodeType === Node.TEXT_NODE) {
5870        code += node.textContent;
5871      } else if (node.nodeType === Node.ELEMENT_NODE) {
5872        if (node.tagName === "BR") {
5873          code += "\n";
5874        } else if (node.tagName === "MARK") {
5875          const start3 = code.length;
5876          for (const child of node.childNodes) {
5877            walk(child);
5878          }
5879          const style = extractStyle(node);
5880          if (style) {
5881            highlights.push({ start: start3, end: code.length, style });
5882          }
5883        } else {
5884          for (const child of node.childNodes) {
5885            walk(child);
5886          }
5887        }
5888      }
5889    }
5890    for (const child of root.childNodes) {
5891      walk(child);
5892    }
5893    return { code, highlights };
5894  }
5895  function extractStyle(element) {
5896    const parts = [];
5897    if (element.style?.color) parts.push(`color: ${element.style.color};`);
5898    if (element.style?.backgroundColor) parts.push(`background-color: ${element.style.backgroundColor};`);
5899    return parts.length > 0 ? parts.join(" ") : null;
5900  }
5901  function applyHighlightRanges(element, highlights) {
5902    for (const { start: start3, end, style } of highlights) {
5903      wrapRange(element, start3, end, style);
5904    }
5905  }
5906  function wrapRange(container, rangeStart, rangeEnd, style) {
5907    const textNodes = collectTextNodes(container);
5908    for (let i2 = textNodes.length - 1; i2 >= 0; i2--) {
5909      const { node, start: nodeStart, end: nodeEnd } = textNodes[i2];
5910      const overlapStart = Math.max(rangeStart, nodeStart);
5911      const overlapEnd = Math.min(rangeEnd, nodeEnd);
5912      if (overlapStart >= overlapEnd) continue;
5913      const relStart = overlapStart - nodeStart;
5914      const relEnd = overlapEnd - nodeStart;
5915      const text2 = node.textContent;
5916      const parent = node.parentNode;
5917      const mark = document.createElement("mark");
5918      mark.setAttribute("style", style);
5919      mark.textContent = text2.slice(relStart, relEnd);
5920      if (relEnd < text2.length) {
5921        parent.insertBefore(document.createTextNode(text2.slice(relEnd)), node.nextSibling);
5922      }
5923      parent.insertBefore(mark, node.nextSibling);
5924      if (relStart > 0) {
5925        node.textContent = text2.slice(0, relStart);
5926      } else {
5927        parent.removeChild(node);
5928      }
5929    }
5930  }
5931  function collectTextNodes(root) {
5932    const nodes = [];
5933    let offset3 = 0;
5934    const walker = document.createTreeWalker(
5935      root,
5936      4
5937      /* NodeFilter.SHOW_TEXT */
5938    );
5939    let node;
5940    while (node = walker.nextNode()) {
5941      const length = node.textContent.length;
5942      nodes.push({ node, start: offset3, end: offset3 + length });
5943      offset3 += length;
5944    }
5945    return nodes;
5946  }
5947
5948  
vendor: 66,780 bytes, lines 5948-7395
5948// node_modules/dompurify/dist/purify.es.mjs
5949  function _arrayLikeToArray(r2, a2) {
5950    (null == a2 || a2 > r2.length) && (a2 = r2.length);
5951    for (var e2 = 0, n2 = Array(a2); e2 < a2; e2++) n2[e2] = r2[e2];
5952    return n2;
5953  }
5954  function _arrayWithHoles(r2) {
5955    if (Array.isArray(r2)) return r2;
5956  }
5957  function _iterableToArrayLimit(r2, l4) {
5958    var t2 = null == r2 ? null : "undefined" != typeof Symbol && r2[Symbol.iterator] || r2["@@iterator"];
5959    if (null != t2) {
5960      var e2, n2, i2, u2, a2 = [], f = true, o2 = false;
5961      try {
5962        if (i2 = (t2 = t2.call(r2)).next, 0 === l4) ;
5963        else for (; !(f = (e2 = i2.call(t2)).done) && (a2.push(e2.value), a2.length !== l4); f = true) ;
5964      } catch (r3) {
5965        o2 = true, n2 = r3;
5966      } finally {
5967        try {
5968          if (!f && null != t2.return && (u2 = t2.return(), Object(u2) !== u2)) return;
5969        } finally {
5970          if (o2) throw n2;
5971        }
5972      }
5973      return a2;
5974    }
5975  }
5976  function _nonIterableRest() {
5977    throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
5978  }
5979  function _slicedToArray(r2, e2) {
5980    return _arrayWithHoles(r2) || _iterableToArrayLimit(r2, e2) || _unsupportedIterableToArray(r2, e2) || _nonIterableRest();
5981  }
5982  function _unsupportedIterableToArray(r2, a2) {
5983    if (r2) {
5984      if ("string" == typeof r2) return _arrayLikeToArray(r2, a2);
5985      var t2 = {}.toString.call(r2).slice(8, -1);
5986      return "Object" === t2 && r2.constructor && (t2 = r2.constructor.name), "Map" === t2 || "Set" === t2 ? Array.from(r2) : "Arguments" === t2 || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t2) ? _arrayLikeToArray(r2, a2) : void 0;
5987    }
5988  }
5989  var entries = Object.entries;
5990  var setPrototypeOf = Object.setPrototypeOf;
5991  var isFrozen = Object.isFrozen;
5992  var getPrototypeOf = Object.getPrototypeOf;
5993  var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
5994  var freeze = Object.freeze;
5995  var seal = Object.seal;
5996  var create = Object.create;
5997  var _ref = typeof Reflect !== "undefined" && Reflect;
5998  var apply = _ref.apply;
5999  var construct = _ref.construct;
6000  if (!freeze) {
6001    freeze = function freeze2(x3) {
6002      return x3;
6003    };
6004  }
6005  if (!seal) {
6006    seal = function seal2(x3) {
6007      return x3;
6008    };
6009  }
6010  if (!apply) {
6011    apply = function apply2(func, thisArg) {
6012      for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
6013        args[_key - 2] = arguments[_key];
6014      }
6015      return func.apply(thisArg, args);
6016    };
6017  }
6018  if (!construct) {
6019    construct = function construct2(Func) {
6020      for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
6021        args[_key2 - 1] = arguments[_key2];
6022      }
6023      return new Func(...args);
6024    };
6025  }
6026  var arrayForEach = unapply(Array.prototype.forEach);
6027  var arrayLastIndexOf = unapply(Array.prototype.lastIndexOf);
6028  var arrayPop = unapply(Array.prototype.pop);
6029  var arrayPush = unapply(Array.prototype.push);
6030  var arraySplice = unapply(Array.prototype.splice);
6031  var arrayIsArray = Array.isArray;
6032  var stringToLowerCase = unapply(String.prototype.toLowerCase);
6033  var stringToString = unapply(String.prototype.toString);
6034  var stringMatch = unapply(String.prototype.match);
6035  var stringReplace = unapply(String.prototype.replace);
6036  var stringIndexOf = unapply(String.prototype.indexOf);
6037  var stringTrim = unapply(String.prototype.trim);
6038  var numberToString = unapply(Number.prototype.toString);
6039  var booleanToString = unapply(Boolean.prototype.toString);
6040  var bigintToString = typeof BigInt === "undefined" ? null : unapply(BigInt.prototype.toString);
6041  var symbolToString = typeof Symbol === "undefined" ? null : unapply(Symbol.prototype.toString);
6042  var objectHasOwnProperty = unapply(Object.prototype.hasOwnProperty);
6043  var objectToString = unapply(Object.prototype.toString);
6044  var regExpTest = unapply(RegExp.prototype.test);
6045  var typeErrorCreate = unconstruct(TypeError);
6046  function unapply(func) {
6047    return function(thisArg) {
6048      if (thisArg instanceof RegExp) {
6049        thisArg.lastIndex = 0;
6050      }
6051      for (var _len3 = arguments.length, args = new Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) {
6052        args[_key3 - 1] = arguments[_key3];
6053      }
6054      return apply(func, thisArg, args);
6055    };
6056  }
6057  function unconstruct(Func) {
6058    return function() {
6059      for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {
6060        args[_key4] = arguments[_key4];
6061      }
6062      return construct(Func, args);
6063    };
6064  }
6065  function addToSet(set, array) {
6066    let transformCaseFunc = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : stringToLowerCase;
6067    if (setPrototypeOf) {
6068      setPrototypeOf(set, null);
6069    }
6070    if (!arrayIsArray(array)) {
6071      return set;
6072    }
6073    let l4 = array.length;
6074    while (l4--) {
6075      let element = array[l4];
6076      if (typeof element === "string") {
6077        const lcElement = transformCaseFunc(element);
6078        if (lcElement !== element) {
6079          if (!isFrozen(array)) {
6080            array[l4] = lcElement;
6081          }
6082          element = lcElement;
6083        }
6084      }
6085      set[element] = true;
6086    }
6087    return set;
6088  }
6089  function cleanArray(array) {
6090    for (let index = 0; index < array.length; index++) {
6091      const isPropertyExist = objectHasOwnProperty(array, index);
6092      if (!isPropertyExist) {
6093        array[index] = null;
6094      }
6095    }
6096    return array;
6097  }
6098  function clone(object) {
6099    const newObject = create(null);
6100    for (const _ref2 of entries(object)) {
6101      var _ref3 = _slicedToArray(_ref2, 2);
6102      const property = _ref3[0];
6103      const value = _ref3[1];
6104      const isPropertyExist = objectHasOwnProperty(object, property);
6105      if (isPropertyExist) {
6106        if (arrayIsArray(value)) {
6107          newObject[property] = cleanArray(value);
6108        } else if (value && typeof value === "object" && value.constructor === Object) {
6109          newObject[property] = clone(value);
6110        } else {
6111          newObject[property] = value;
6112        }
6113      }
6114    }
6115    return newObject;
6116  }
6117  function stringifyValue(value) {
6118    switch (typeof value) {
6119      case "string": {
6120        return value;
6121      }
6122      case "number": {
6123        return numberToString(value);
6124      }
6125      case "boolean": {
6126        return booleanToString(value);
6127      }
6128      case "bigint": {
6129        return bigintToString ? bigintToString(value) : "0";
6130      }
6131      case "symbol": {
6132        return symbolToString ? symbolToString(value) : "Symbol()";
6133      }
6134      case "undefined": {
6135        return objectToString(value);
6136      }
6137      case "function":
6138      case "object": {
6139        if (value === null) {
6140          return objectToString(value);
6141        }
6142        const valueAsRecord = value;
6143        const valueToString = lookupGetter(valueAsRecord, "toString");
6144        if (typeof valueToString === "function") {
6145          const stringified = valueToString(valueAsRecord);
6146          return typeof stringified === "string" ? stringified : objectToString(stringified);
6147        }
6148        return objectToString(value);
6149      }
6150      default: {
6151        return objectToString(value);
6152      }
6153    }
6154  }
6155  function lookupGetter(object, prop) {
6156    while (object !== null) {
6157      const desc = getOwnPropertyDescriptor(object, prop);
6158      if (desc) {
6159        if (desc.get) {
6160          return unapply(desc.get);
6161        }
6162        if (typeof desc.value === "function") {
6163          return unapply(desc.value);
6164        }
6165      }
6166      object = getPrototypeOf(object);
6167    }
6168    function fallbackValue() {
6169      return null;
6170    }
6171    return fallbackValue;
6172  }
6173  function isRegex(value) {
6174    try {
6175      regExpTest(value, "");
6176      return true;
6177    } catch (_unused) {
6178      return false;
6179    }
6180  }
6181  var html$1 = freeze(["a", "abbr", "acronym", "address", "area", "article", "aside", "audio", "b", "bdi", "bdo", "big", "blink", "blockquote", "body", "br", "button", "canvas", "caption", "center", "cite", "code", "col", "colgroup", "content", "data", "datalist", "dd", "decorator", "del", "details", "dfn", "dialog", "dir", "div", "dl", "dt", "element", "em", "fieldset", "figcaption", "figure", "font", "footer", "form", "h1", "h2", "h3", "h4", "h5", "h6", "head", "header", "hgroup", "hr", "html", "i", "img", "input", "ins", "kbd", "label", "legend", "li", "main", "map", "mark", "marquee", "menu", "menuitem", "meter", "nav", "nobr", "ol", "optgroup", "option", "output", "p", "picture", "pre", "progress", "q", "rp", "rt", "ruby", "s", "samp", "search", "section", "select", "shadow", "slot", "small", "source", "spacer", "span", "strike", "strong", "style", "sub", "summary", "sup", "table", "tbody", "td", "template", "textarea", "tfoot", "th", "thead", "time", "tr", "track", "tt", "u", "ul", "var", "video", "wbr"]);
6182  var svg$1 = freeze(["svg", "a", "altglyph", "altglyphdef", "altglyphitem", "animatecolor", "animatemotion", "animatetransform", "circle", "clippath", "defs", "desc", "ellipse", "enterkeyhint", "exportparts", "filter", "font", "g", "glyph", "glyphref", "hkern", "image", "inputmode", "line", "lineargradient", "marker", "mask", "metadata", "mpath", "part", "path", "pattern", "polygon", "polyline", "radialgradient", "rect", "stop", "style", "switch", "symbol", "text", "textpath", "title", "tref", "tspan", "view", "vkern"]);
6183  var svgFilters = freeze(["feBlend", "feColorMatrix", "feComponentTransfer", "feComposite", "feConvolveMatrix", "feDiffuseLighting", "feDisplacementMap", "feDistantLight", "feDropShadow", "feFlood", "feFuncA", "feFuncB", "feFuncG", "feFuncR", "feGaussianBlur", "feImage", "feMerge", "feMergeNode", "feMorphology", "feOffset", "fePointLight", "feSpecularLighting", "feSpotLight", "feTile", "feTurbulence"]);
6184  var svgDisallowed = freeze(["animate", "color-profile", "cursor", "discard", "font-face", "font-face-format", "font-face-name", "font-face-src", "font-face-uri", "foreignobject", "hatch", "hatchpath", "mesh", "meshgradient", "meshpatch", "meshrow", "missing-glyph", "script", "set", "solidcolor", "unknown", "use"]);
6185  var mathMl$1 = freeze(["math", "menclose", "merror", "mfenced", "mfrac", "mglyph", "mi", "mlabeledtr", "mmultiscripts", "mn", "mo", "mover", "mpadded", "mphantom", "mroot", "mrow", "ms", "mspace", "msqrt", "mstyle", "msub", "msup", "msubsup", "mtable", "mtd", "mtext", "mtr", "munder", "munderover", "mprescripts"]);
6186  var mathMlDisallowed = freeze(["maction", "maligngroup", "malignmark", "mlongdiv", "mscarries", "mscarry", "msgroup", "mstack", "msline", "msrow", "semantics", "annotation", "annotation-xml", "mprescripts", "none"]);
6187  var text = freeze(["#text"]);
6188  var html = freeze(["accept", "action", "align", "alt", "autocapitalize", "autocomplete", "autopictureinpicture", "autoplay", "background", "bgcolor", "border", "capture", "cellpadding", "cellspacing", "checked", "cite", "class", "clear", "color", "cols", "colspan", "command", "commandfor", "controls", "controlslist", "coords", "crossorigin", "datetime", "decoding", "default", "dir", "disabled", "disablepictureinpicture", "disableremoteplayback", "download", "draggable", "enctype", "enterkeyhint", "exportparts", "face", "for", "headers", "height", "hidden", "high", "href", "hreflang", "id", "inert", "inputmode", "integrity", "ismap", "kind", "label", "lang", "list", "loading", "loop", "low", "max", "maxlength", "media", "method", "min", "minlength", "multiple", "muted", "name", "nonce", "noshade", "novalidate", "nowrap", "open", "optimum", "part", "pattern", "placeholder", "playsinline", "popover", "popovertarget", "popovertargetaction", "poster", "preload", "pubdate", "radiogroup", "readonly", "rel", "required", "rev", "reversed", "role", "rows", "rowspan", "spellcheck", "scope", "selected", "shape", "size", "sizes", "slot", "span", "srclang", "start", "src", "srcset", "step", "style", "summary", "tabindex", "title", "translate", "type", "usemap", "valign", "value", "width", "wrap", "xmlns"]);
6189  var svg = freeze(["accent-height", "accumulate", "additive", "alignment-baseline", "amplitude", "ascent", "attributename", "attributetype", "azimuth", "basefrequency", "baseline-shift", "begin", "bias", "by", "class", "clip", "clippathunits", "clip-path", "clip-rule", "color", "color-interpolation", "color-interpolation-filters", "color-profile", "color-rendering", "cx", "cy", "d", "dx", "dy", "diffuseconstant", "direction", "display", "divisor", "dur", "edgemode", "elevation", "end", "exponent", "fill", "fill-opacity", "fill-rule", "filter", "filterunits", "flood-color", "flood-opacity", "font-family", "font-size", "font-size-adjust", "font-stretch", "font-style", "font-variant", "font-weight", "fx", "fy", "g1", "g2", "glyph-name", "glyphref", "gradientunits", "gradienttransform", "height", "href", "id", "image-rendering", "in", "in2", "intercept", "k", "k1", "k2", "k3", "k4", "kerning", "keypoints", "keysplines", "keytimes", "lang", "lengthadjust", "letter-spacing", "kernelmatrix", "kernelunitlength", "lighting-color", "local", "marker-end", "marker-mid", "marker-start", "markerheight", "markerunits", "markerwidth", "maskcontentunits", "maskunits", "max", "mask", "mask-type", "media", "method", "mode", "min", "name", "numoctaves", "offset", "operator", "opacity", "order", "orient", "orientation", "origin", "overflow", "paint-order", "path", "pathlength", "patterncontentunits", "patterntransform", "patternunits", "points", "preservealpha", "preserveaspectratio", "primitiveunits", "r", "rx", "ry", "radius", "refx", "refy", "repeatcount", "repeatdur", "restart", "result", "rotate", "scale", "seed", "shape-rendering", "slope", "specularconstant", "specularexponent", "spreadmethod", "startoffset", "stddeviation", "stitchtiles", "stop-color", "stop-opacity", "stroke-dasharray", "stroke-dashoffset", "stroke-linecap", "stroke-linejoin", "stroke-miterlimit", "stroke-opacity", "stroke", "stroke-width", "style", "surfacescale", "systemlanguage", "tabindex", "tablevalues", "targetx", "targety", "transform", "transform-origin", "text-anchor", "text-decoration", "text-rendering", "textlength", "type", "u1", "u2", "unicode", "values", "viewbox", "visibility", "version", "vert-adv-y", "vert-origin-x", "vert-origin-y", "width", "word-spacing", "wrap", "writing-mode", "xchannelselector", "ychannelselector", "x", "x1", "x2", "xmlns", "y", "y1", "y2", "z", "zoomandpan"]);
6190  var mathMl = freeze(["accent", "accentunder", "align", "bevelled", "close", "columnalign", "columnlines", "columnspacing", "columnspan", "denomalign", "depth", "dir", "display", "displaystyle", "encoding", "fence", "frame", "height", "href", "id", "largeop", "length", "linethickness", "lquote", "lspace", "mathbackground", "mathcolor", "mathsize", "mathvariant", "maxsize", "minsize", "movablelimits", "notation", "numalign", "open", "rowalign", "rowlines", "rowspacing", "rowspan", "rspace", "rquote", "scriptlevel", "scriptminsize", "scriptsizemultiplier", "selection", "separator", "separators", "stretchy", "subscriptshift", "supscriptshift", "symmetric", "voffset", "width", "xmlns"]);
6191  var xml = freeze(["xlink:href", "xml:id", "xlink:title", "xml:space", "xmlns:xlink"]);
6192  var MUSTACHE_EXPR = seal(/{{[\w\W]*|^[\w\W]*}}/g);
6193  var ERB_EXPR = seal(/<%[\w\W]*|^[\w\W]*%>/g);
6194  var TMPLIT_EXPR = seal(/\${[\w\W]*/g);
6195  var DATA_ATTR = seal(/^data-[\-\w.\u00B7-\uFFFF]+$/);
6196  var ARIA_ATTR = seal(/^aria-[\-\w]+$/);
6197  var IS_ALLOWED_URI = seal(
6198    /^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i
6199    // eslint-disable-line no-useless-escape
6200  );
6201  var IS_SCRIPT_OR_DATA = seal(/^(?:\w+script|data):/i);
6202  var ATTR_WHITESPACE = seal(
6203    /[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g
6204    // eslint-disable-line no-control-regex
6205  );
6206  var DOCTYPE_NAME = seal(/^html$/i);
6207  var CUSTOM_ELEMENT = seal(/^[a-z][.\w]*(-[.\w]+)+$/i);
6208  var ELEMENT_MARKUP_PROBE = seal(/<[/\w!]/g);
6209  var COMMENT_MARKUP_PROBE = seal(/<[/\w]/g);
6210  var FALLBACK_TAG_CLOSE = seal(/<\/no(script|embed|frames)/i);
6211  var SELF_CLOSING_TAG = seal(/\/>/i);
6212  var NODE_TYPE = {
6213    element: 1,
6214    attribute: 2,
6215    text: 3,
6216    cdataSection: 4,
6217    entityReference: 5,
6218    // Deprecated
6219    entityNode: 6,
6220    // Deprecated
6221    processingInstruction: 7,
6222    comment: 8,
6223    document: 9,
6224    documentType: 10,
6225    documentFragment: 11,
6226    notation: 12
6227    // Deprecated
6228  };
6229  var getGlobal = function getGlobal2() {
6230    return typeof window === "undefined" ? null : window;
6231  };
6232  var _createTrustedTypesPolicy = function _createTrustedTypesPolicy2(trustedTypes, purifyHostElement) {
6233    if (typeof trustedTypes !== "object" || typeof trustedTypes.createPolicy !== "function") {
6234      return null;
6235    }
6236    let suffix = null;
6237    const ATTR_NAME = "data-tt-policy-suffix";
6238    if (purifyHostElement && purifyHostElement.hasAttribute(ATTR_NAME)) {
6239      suffix = purifyHostElement.getAttribute(ATTR_NAME);
6240    }
6241    const policyName = "dompurify" + (suffix ? "#" + suffix : "");
6242    try {
6243      return trustedTypes.createPolicy(policyName, {
6244        createHTML(html2) {
6245          return html2;
6246        },
6247        createScriptURL(scriptUrl) {
6248          return scriptUrl;
6249        }
6250      });
6251    } catch (_3) {
6252      console.warn("TrustedTypes policy " + policyName + " could not be created.");
6253      return null;
6254    }
6255  };
6256  var _createHooksMap = function _createHooksMap2() {
6257    return {
6258      afterSanitizeAttributes: [],
6259      afterSanitizeElements: [],
6260      afterSanitizeShadowDOM: [],
6261      beforeSanitizeAttributes: [],
6262      beforeSanitizeElements: [],
6263      beforeSanitizeShadowDOM: [],
6264      uponSanitizeAttribute: [],
6265      uponSanitizeElement: [],
6266      uponSanitizeShadowNode: []
6267    };
6268  };
6269  var _resolveSetOption = function _resolveSetOption2(cfg, key, fallback, options) {
6270    return objectHasOwnProperty(cfg, key) && arrayIsArray(cfg[key]) ? addToSet(options.base ? clone(options.base) : {}, cfg[key], options.transform) : fallback;
6271  };
6272  function createDOMPurify() {
6273    let window2 = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : getGlobal();
6274    const DOMPurify = (root) => createDOMPurify(root);
6275    DOMPurify.version = "3.4.11";
6276    DOMPurify.removed = [];
6277    if (!window2 || !window2.document || window2.document.nodeType !== NODE_TYPE.document || !window2.Element) {
6278      DOMPurify.isSupported = false;
6279      return DOMPurify;
6280    }
6281    let document2 = window2.document;
6282    const originalDocument = document2;
6283    const currentScript = originalDocument.currentScript;
6284    window2.DocumentFragment;
6285    const HTMLTemplateElement = window2.HTMLTemplateElement, Node2 = window2.Node, Element2 = window2.Element, NodeFilter2 = window2.NodeFilter, _window$NamedNodeMap = window2.NamedNodeMap;
6286    _window$NamedNodeMap === void 0 ? window2.NamedNodeMap || window2.MozNamedAttrMap : _window$NamedNodeMap;
6287    window2.HTMLFormElement;
6288    const DOMParser2 = window2.DOMParser, trustedTypes = window2.trustedTypes;
6289    const ElementPrototype = Element2.prototype;
6290    const cloneNode = lookupGetter(ElementPrototype, "cloneNode");
6291    const remove = lookupGetter(ElementPrototype, "remove");
6292    const getNextSibling2 = lookupGetter(ElementPrototype, "nextSibling");
6293    const getChildNodes = lookupGetter(ElementPrototype, "childNodes");
6294    const getParentNode2 = lookupGetter(ElementPrototype, "parentNode");
6295    const getShadowRoot = lookupGetter(ElementPrototype, "shadowRoot");
6296    const getAttributes = lookupGetter(ElementPrototype, "attributes");
6297    const getNodeType = Node2 && Node2.prototype ? lookupGetter(Node2.prototype, "nodeType") : null;
6298    const getNodeName2 = Node2 && Node2.prototype ? lookupGetter(Node2.prototype, "nodeName") : null;
6299    if (typeof HTMLTemplateElement === "function") {
6300      const template = document2.createElement("template");
6301      if (template.content && template.content.ownerDocument) {
6302        document2 = template.content.ownerDocument;
6303      }
6304    }
6305    let trustedTypesPolicy;
6306    let emptyHTML = "";
6307    let defaultTrustedTypesPolicy;
6308    let defaultTrustedTypesPolicyResolved = false;
6309    let IN_TRUSTED_TYPES_POLICY = 0;
6310    const _assertNotInTrustedTypesPolicy = function _assertNotInTrustedTypesPolicy2() {
6311      if (IN_TRUSTED_TYPES_POLICY > 0) {
6312        throw typeErrorCreate('A configured TRUSTED_TYPES_POLICY callback (createHTML or createScriptURL) must not call DOMPurify.sanitize, as that causes infinite recursion. Do not pass a policy whose callbacks wrap DOMPurify as TRUSTED_TYPES_POLICY; see the "DOMPurify and Trusted Types" section of the README.');
6313      }
6314    };
6315    const _createTrustedHTML = function _createTrustedHTML2(html2) {
6316      _assertNotInTrustedTypesPolicy();
6317      IN_TRUSTED_TYPES_POLICY++;
6318      try {
6319        return trustedTypesPolicy.createHTML(html2);
6320      } finally {
6321        IN_TRUSTED_TYPES_POLICY--;
6322      }
6323    };
6324    const _createTrustedScriptURL = function _createTrustedScriptURL2(scriptUrl) {
6325      _assertNotInTrustedTypesPolicy();
6326      IN_TRUSTED_TYPES_POLICY++;
6327      try {
6328        return trustedTypesPolicy.createScriptURL(scriptUrl);
6329      } finally {
6330        IN_TRUSTED_TYPES_POLICY--;
6331      }
6332    };
6333    const _getDefaultTrustedTypesPolicy = function _getDefaultTrustedTypesPolicy2() {
6334      if (!defaultTrustedTypesPolicyResolved) {
6335        defaultTrustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, currentScript);
6336        defaultTrustedTypesPolicyResolved = true;
6337      }
6338      return defaultTrustedTypesPolicy;
6339    };
6340    const _document = document2, implementation = _document.implementation, createNodeIterator = _document.createNodeIterator, createDocumentFragment = _document.createDocumentFragment, getElementsByTagName = _document.getElementsByTagName;
6341    const importNode = originalDocument.importNode;
6342    let hooks = _createHooksMap();
6343    DOMPurify.isSupported = typeof entries === "function" && typeof getParentNode2 === "function" && implementation && implementation.createHTMLDocument !== void 0;
6344    const MUSTACHE_EXPR$1 = MUSTACHE_EXPR, ERB_EXPR$1 = ERB_EXPR, TMPLIT_EXPR$1 = TMPLIT_EXPR, DATA_ATTR$1 = DATA_ATTR, ARIA_ATTR$1 = ARIA_ATTR, IS_SCRIPT_OR_DATA$1 = IS_SCRIPT_OR_DATA, ATTR_WHITESPACE$1 = ATTR_WHITESPACE, CUSTOM_ELEMENT$1 = CUSTOM_ELEMENT;
6345    let IS_ALLOWED_URI$1 = IS_ALLOWED_URI;
6346    let ALLOWED_TAGS = null;
6347    const DEFAULT_ALLOWED_TAGS = addToSet({}, [...html$1, ...svg$1, ...svgFilters, ...mathMl$1, ...text]);
6348    let ALLOWED_ATTR = null;
6349    const DEFAULT_ALLOWED_ATTR = addToSet({}, [...html, ...svg, ...mathMl, ...xml]);
6350    let CUSTOM_ELEMENT_HANDLING = Object.seal(create(null, {
6351      tagNameCheck: {
6352        writable: true,
6353        configurable: false,
6354        enumerable: true,
6355        value: null
6356      },
6357      attributeNameCheck: {
6358        writable: true,
6359        configurable: false,
6360        enumerable: true,
6361        value: null
6362      },
6363      allowCustomizedBuiltInElements: {
6364        writable: true,
6365        configurable: false,
6366        enumerable: true,
6367        value: false
6368      }
6369    }));
6370    let FORBID_TAGS = null;
6371    let FORBID_ATTR = null;
6372    const EXTRA_ELEMENT_HANDLING = Object.seal(create(null, {
6373      tagCheck: {
6374        writable: true,
6375        configurable: false,
6376        enumerable: true,
6377        value: null
6378      },
6379      attributeCheck: {
6380        writable: true,
6381        configurable: false,
6382        enumerable: true,
6383        value: null
6384      }
6385    }));
6386    let ALLOW_ARIA_ATTR = true;
6387    let ALLOW_DATA_ATTR = true;
6388    let ALLOW_UNKNOWN_PROTOCOLS = false;
6389    let ALLOW_SELF_CLOSE_IN_ATTR = true;
6390    let SAFE_FOR_TEMPLATES = false;
6391    let SAFE_FOR_XML = true;
6392    let WHOLE_DOCUMENT = false;
6393    let SET_CONFIG = false;
6394    let SET_CONFIG_ALLOWED_TAGS = null;
6395    let SET_CONFIG_ALLOWED_ATTR = null;
6396    let FORCE_BODY = false;
6397    let RETURN_DOM = false;
6398    let RETURN_DOM_FRAGMENT = false;
6399    let RETURN_TRUSTED_TYPE = false;
6400    let SANITIZE_DOM = true;
6401    let SANITIZE_NAMED_PROPS = false;
6402    const SANITIZE_NAMED_PROPS_PREFIX = "user-content-";
6403    let KEEP_CONTENT = true;
6404    let IN_PLACE = false;
6405    let USE_PROFILES = {};
6406    let FORBID_CONTENTS = null;
6407    const DEFAULT_FORBID_CONTENTS = addToSet({}, [
6408      "annotation-xml",
6409      "audio",
6410      "colgroup",
6411      "desc",
6412      "foreignobject",
6413      "head",
6414      "iframe",
6415      "math",
6416      "mi",
6417      "mn",
6418      "mo",
6419      "ms",
6420      "mtext",
6421      "noembed",
6422      "noframes",
6423      "noscript",
6424      "plaintext",
6425      "script",
6426      // <selectedcontent> mirrors the selected <option>'s subtree, cloned by
6427      // the UA (customizable <select>) — including any on* handlers — and the
6428      // engine re-mirrors synchronously whenever a removal changes which
6429      // option/selectedcontent is current, even inside DOMPurify's inert
6430      // DOMParser document. Hoisting its children on removal re-inserts a fresh
6431      // mirror target ahead of the walk, which the engine refills, looping
6432      // forever (DoS) and amplifying output. Dropping its content on removal
6433      // (rather than hoisting) breaks that cascade; the content is a duplicate
6434      // of the option, which is sanitized on its own. See campaign-3 F1/F6.
6435      "selectedcontent",
6436      "style",
6437      "svg",
6438      "template",
6439      "thead",
6440      "title",
6441      "video",
6442      "xmp"
6443    ]);
6444    let DATA_URI_TAGS = null;
6445    const DEFAULT_DATA_URI_TAGS = addToSet({}, ["audio", "video", "img", "source", "image", "track"]);
6446    let URI_SAFE_ATTRIBUTES = null;
6447    const DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ["alt", "class", "for", "id", "label", "name", "pattern", "placeholder", "role", "summary", "title", "value", "style", "xmlns"]);
6448    const MATHML_NAMESPACE = "http://www.w3.org/1998/Math/MathML";
6449    const SVG_NAMESPACE = "http://www.w3.org/2000/svg";
6450    const HTML_NAMESPACE = "http://www.w3.org/1999/xhtml";
6451    let NAMESPACE = HTML_NAMESPACE;
6452    let IS_EMPTY_INPUT = false;
6453    let ALLOWED_NAMESPACES = null;
6454    const DEFAULT_ALLOWED_NAMESPACES = addToSet({}, [MATHML_NAMESPACE, SVG_NAMESPACE, HTML_NAMESPACE], stringToString);
6455    const DEFAULT_MATHML_TEXT_INTEGRATION_POINTS = freeze(["mi", "mo", "mn", "ms", "mtext"]);
6456    let MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, DEFAULT_MATHML_TEXT_INTEGRATION_POINTS);
6457    const DEFAULT_HTML_INTEGRATION_POINTS = freeze(["annotation-xml"]);
6458    let HTML_INTEGRATION_POINTS = addToSet({}, DEFAULT_HTML_INTEGRATION_POINTS);
6459    const COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, ["title", "style", "font", "a", "script"]);
6460    let PARSER_MEDIA_TYPE = null;
6461    const SUPPORTED_PARSER_MEDIA_TYPES = ["application/xhtml+xml", "text/html"];
6462    const DEFAULT_PARSER_MEDIA_TYPE = "text/html";
6463    let transformCaseFunc = null;
6464    let CONFIG = null;
6465    const formElement = document2.createElement("form");
6466    const isRegexOrFunction = function isRegexOrFunction2(testValue) {
6467      return testValue instanceof RegExp || testValue instanceof Function;
6468    };
6469    const _parseConfig = function _parseConfig2() {
6470      let cfg = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
6471      if (CONFIG && CONFIG === cfg) {
6472        return;
6473      }
6474      if (!cfg || typeof cfg !== "object") {
6475        cfg = {};
6476      }
6477      cfg = clone(cfg);
6478      PARSER_MEDIA_TYPE = // eslint-disable-next-line unicorn/prefer-includes
6479      SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? DEFAULT_PARSER_MEDIA_TYPE : cfg.PARSER_MEDIA_TYPE;
6480      transformCaseFunc = PARSER_MEDIA_TYPE === "application/xhtml+xml" ? stringToString : stringToLowerCase;
6481      ALLOWED_TAGS = _resolveSetOption(cfg, "ALLOWED_TAGS", DEFAULT_ALLOWED_TAGS, {
6482        transform: transformCaseFunc
6483      });
6484      ALLOWED_ATTR = _resolveSetOption(cfg, "ALLOWED_ATTR", DEFAULT_ALLOWED_ATTR, {
6485        transform: transformCaseFunc
6486      });
6487      ALLOWED_NAMESPACES = _resolveSetOption(cfg, "ALLOWED_NAMESPACES", DEFAULT_ALLOWED_NAMESPACES, {
6488        transform: stringToString
6489      });
6490      URI_SAFE_ATTRIBUTES = _resolveSetOption(cfg, "ADD_URI_SAFE_ATTR", DEFAULT_URI_SAFE_ATTRIBUTES, {
6491        transform: transformCaseFunc,
6492        base: DEFAULT_URI_SAFE_ATTRIBUTES
6493      });
6494      DATA_URI_TAGS = _resolveSetOption(cfg, "ADD_DATA_URI_TAGS", DEFAULT_DATA_URI_TAGS, {
6495        transform: transformCaseFunc,
6496        base: DEFAULT_DATA_URI_TAGS
6497      });
6498      FORBID_CONTENTS = _resolveSetOption(cfg, "FORBID_CONTENTS", DEFAULT_FORBID_CONTENTS, {
6499        transform: transformCaseFunc
6500      });
6501      FORBID_TAGS = _resolveSetOption(cfg, "FORBID_TAGS", clone({}), {
6502        transform: transformCaseFunc
6503      });
6504      FORBID_ATTR = _resolveSetOption(cfg, "FORBID_ATTR", clone({}), {
6505        transform: transformCaseFunc
6506      });
6507      USE_PROFILES = objectHasOwnProperty(cfg, "USE_PROFILES") ? cfg.USE_PROFILES && typeof cfg.USE_PROFILES === "object" ? clone(cfg.USE_PROFILES) : cfg.USE_PROFILES : false;
6508      ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false;
6509      ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false;
6510      ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false;
6511      ALLOW_SELF_CLOSE_IN_ATTR = cfg.ALLOW_SELF_CLOSE_IN_ATTR !== false;
6512      SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false;
6513      SAFE_FOR_XML = cfg.SAFE_FOR_XML !== false;
6514      WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false;
6515      RETURN_DOM = cfg.RETURN_DOM || false;
6516      RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false;
6517      RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false;
6518      FORCE_BODY = cfg.FORCE_BODY || false;
6519      SANITIZE_DOM = cfg.SANITIZE_DOM !== false;
6520      SANITIZE_NAMED_PROPS = cfg.SANITIZE_NAMED_PROPS || false;
6521      KEEP_CONTENT = cfg.KEEP_CONTENT !== false;
6522      IN_PLACE = cfg.IN_PLACE || false;
6523      IS_ALLOWED_URI$1 = isRegex(cfg.ALLOWED_URI_REGEXP) ? cfg.ALLOWED_URI_REGEXP : IS_ALLOWED_URI;
6524      NAMESPACE = typeof cfg.NAMESPACE === "string" ? cfg.NAMESPACE : HTML_NAMESPACE;
6525      MATHML_TEXT_INTEGRATION_POINTS = objectHasOwnProperty(cfg, "MATHML_TEXT_INTEGRATION_POINTS") && cfg.MATHML_TEXT_INTEGRATION_POINTS && typeof cfg.MATHML_TEXT_INTEGRATION_POINTS === "object" ? clone(cfg.MATHML_TEXT_INTEGRATION_POINTS) : addToSet({}, DEFAULT_MATHML_TEXT_INTEGRATION_POINTS);
6526      HTML_INTEGRATION_POINTS = objectHasOwnProperty(cfg, "HTML_INTEGRATION_POINTS") && cfg.HTML_INTEGRATION_POINTS && typeof cfg.HTML_INTEGRATION_POINTS === "object" ? clone(cfg.HTML_INTEGRATION_POINTS) : addToSet({}, DEFAULT_HTML_INTEGRATION_POINTS);
6527      const customElementHandling = objectHasOwnProperty(cfg, "CUSTOM_ELEMENT_HANDLING") && cfg.CUSTOM_ELEMENT_HANDLING && typeof cfg.CUSTOM_ELEMENT_HANDLING === "object" ? clone(cfg.CUSTOM_ELEMENT_HANDLING) : create(null);
6528      CUSTOM_ELEMENT_HANDLING = create(null);
6529      if (objectHasOwnProperty(customElementHandling, "tagNameCheck") && isRegexOrFunction(customElementHandling.tagNameCheck)) {
6530        CUSTOM_ELEMENT_HANDLING.tagNameCheck = customElementHandling.tagNameCheck;
6531      }
6532      if (objectHasOwnProperty(customElementHandling, "attributeNameCheck") && isRegexOrFunction(customElementHandling.attributeNameCheck)) {
6533        CUSTOM_ELEMENT_HANDLING.attributeNameCheck = customElementHandling.attributeNameCheck;
6534      }
6535      if (objectHasOwnProperty(customElementHandling, "allowCustomizedBuiltInElements") && typeof customElementHandling.allowCustomizedBuiltInElements === "boolean") {
6536        CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = customElementHandling.allowCustomizedBuiltInElements;
6537      }
6538      seal(CUSTOM_ELEMENT_HANDLING);
6539      if (SAFE_FOR_TEMPLATES) {
6540        ALLOW_DATA_ATTR = false;
6541      }
6542      if (RETURN_DOM_FRAGMENT) {
6543        RETURN_DOM = true;
6544      }
6545      if (USE_PROFILES) {
6546        ALLOWED_TAGS = addToSet({}, text);
6547        ALLOWED_ATTR = create(null);
6548        if (USE_PROFILES.html === true) {
6549          addToSet(ALLOWED_TAGS, html$1);
6550          addToSet(ALLOWED_ATTR, html);
6551        }
6552        if (USE_PROFILES.svg === true) {
6553          addToSet(ALLOWED_TAGS, svg$1);
6554          addToSet(ALLOWED_ATTR, svg);
6555          addToSet(ALLOWED_ATTR, xml);
6556        }
6557        if (USE_PROFILES.svgFilters === true) {
6558          addToSet(ALLOWED_TAGS, svgFilters);
6559          addToSet(ALLOWED_ATTR, svg);
6560          addToSet(ALLOWED_ATTR, xml);
6561        }
6562        if (USE_PROFILES.mathMl === true) {
6563          addToSet(ALLOWED_TAGS, mathMl$1);
6564          addToSet(ALLOWED_ATTR, mathMl);
6565          addToSet(ALLOWED_ATTR, xml);
6566        }
6567      }
6568      EXTRA_ELEMENT_HANDLING.tagCheck = null;
6569      EXTRA_ELEMENT_HANDLING.attributeCheck = null;
6570      if (objectHasOwnProperty(cfg, "ADD_TAGS")) {
6571        if (typeof cfg.ADD_TAGS === "function") {
6572          EXTRA_ELEMENT_HANDLING.tagCheck = cfg.ADD_TAGS;
6573        } else if (arrayIsArray(cfg.ADD_TAGS)) {
6574          if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {
6575            ALLOWED_TAGS = clone(ALLOWED_TAGS);
6576          }
6577          addToSet(ALLOWED_TAGS, cfg.ADD_TAGS, transformCaseFunc);
6578        }
6579      }
6580      if (objectHasOwnProperty(cfg, "ADD_ATTR")) {
6581        if (typeof cfg.ADD_ATTR === "function") {
6582          EXTRA_ELEMENT_HANDLING.attributeCheck = cfg.ADD_ATTR;
6583        } else if (arrayIsArray(cfg.ADD_ATTR)) {
6584          if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {
6585            ALLOWED_ATTR = clone(ALLOWED_ATTR);
6586          }
6587          addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc);
6588        }
6589      }
6590      if (objectHasOwnProperty(cfg, "ADD_URI_SAFE_ATTR") && arrayIsArray(cfg.ADD_URI_SAFE_ATTR)) {
6591        addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR, transformCaseFunc);
6592      }
6593      if (objectHasOwnProperty(cfg, "FORBID_CONTENTS") && arrayIsArray(cfg.FORBID_CONTENTS)) {
6594        if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {
6595          FORBID_CONTENTS = clone(FORBID_CONTENTS);
6596        }
6597        addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS, transformCaseFunc);
6598      }
6599      if (objectHasOwnProperty(cfg, "ADD_FORBID_CONTENTS") && arrayIsArray(cfg.ADD_FORBID_CONTENTS)) {
6600        if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {
6601          FORBID_CONTENTS = clone(FORBID_CONTENTS);
6602        }
6603        addToSet(FORBID_CONTENTS, cfg.ADD_FORBID_CONTENTS, transformCaseFunc);
6604      }
6605      if (KEEP_CONTENT) {
6606        ALLOWED_TAGS["#text"] = true;
6607      }
6608      if (WHOLE_DOCUMENT) {
6609        addToSet(ALLOWED_TAGS, ["html", "head", "body"]);
6610      }
6611      if (ALLOWED_TAGS.table) {
6612        addToSet(ALLOWED_TAGS, ["tbody"]);
6613        delete FORBID_TAGS.tbody;
6614      }
6615      if (cfg.TRUSTED_TYPES_POLICY) {
6616        if (typeof cfg.TRUSTED_TYPES_POLICY.createHTML !== "function") {
6617          throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a "createHTML" hook.');
6618        }
6619        if (typeof cfg.TRUSTED_TYPES_POLICY.createScriptURL !== "function") {
6620          throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a "createScriptURL" hook.');
6621        }
6622        const previousTrustedTypesPolicy = trustedTypesPolicy;
6623        trustedTypesPolicy = cfg.TRUSTED_TYPES_POLICY;
6624        try {
6625          emptyHTML = _createTrustedHTML("");
6626        } catch (error) {
6627          trustedTypesPolicy = previousTrustedTypesPolicy;
6628          throw error;
6629        }
6630      } else if (cfg.TRUSTED_TYPES_POLICY === null) {
6631        trustedTypesPolicy = void 0;
6632        emptyHTML = "";
6633      } else {
6634        if (trustedTypesPolicy === void 0) {
6635          trustedTypesPolicy = _getDefaultTrustedTypesPolicy();
6636        }
6637        if (trustedTypesPolicy && typeof emptyHTML === "string") {
6638          emptyHTML = _createTrustedHTML("");
6639        }
6640      }
6641      if (freeze) {
6642        freeze(cfg);
6643      }
6644      CONFIG = cfg;
6645    };
6646    const ALL_SVG_TAGS = addToSet({}, [...svg$1, ...svgFilters, ...svgDisallowed]);
6647    const ALL_MATHML_TAGS = addToSet({}, [...mathMl$1, ...mathMlDisallowed]);
6648    const _checkSvgNamespace = function _checkSvgNamespace2(tagName, parent, parentTagName) {
6649      if (parent.namespaceURI === HTML_NAMESPACE) {
6650        return tagName === "svg";
6651      }
6652      if (parent.namespaceURI === MATHML_NAMESPACE) {
6653        return tagName === "svg" && (parentTagName === "annotation-xml" || MATHML_TEXT_INTEGRATION_POINTS[parentTagName]);
6654      }
6655      return Boolean(ALL_SVG_TAGS[tagName]);
6656    };
6657    const _checkMathMlNamespace = function _checkMathMlNamespace2(tagName, parent, parentTagName) {
6658      if (parent.namespaceURI === HTML_NAMESPACE) {
6659        return tagName === "math";
6660      }
6661      if (parent.namespaceURI === SVG_NAMESPACE) {
6662        return tagName === "math" && HTML_INTEGRATION_POINTS[parentTagName];
6663      }
6664      return Boolean(ALL_MATHML_TAGS[tagName]);
6665    };
6666    const _checkHtmlNamespace = function _checkHtmlNamespace2(tagName, parent, parentTagName) {
6667      if (parent.namespaceURI === SVG_NAMESPACE && !HTML_INTEGRATION_POINTS[parentTagName]) {
6668        return false;
6669      }
6670      if (parent.namespaceURI === MATHML_NAMESPACE && !MATHML_TEXT_INTEGRATION_POINTS[parentTagName]) {
6671        return false;
6672      }
6673      return !ALL_MATHML_TAGS[tagName] && (COMMON_SVG_AND_HTML_ELEMENTS[tagName] || !ALL_SVG_TAGS[tagName]);
6674    };
6675    const _checkValidNamespace = function _checkValidNamespace2(element) {
6676      let parent = getParentNode2(element);
6677      if (!parent || !parent.tagName) {
6678        parent = {
6679          namespaceURI: NAMESPACE,
6680          tagName: "template"
6681        };
6682      }
6683      const tagName = stringToLowerCase(element.tagName);
6684      const parentTagName = stringToLowerCase(parent.tagName);
6685      if (!ALLOWED_NAMESPACES[element.namespaceURI]) {
6686        return false;
6687      }
6688      if (element.namespaceURI === SVG_NAMESPACE) {
6689        return _checkSvgNamespace(tagName, parent, parentTagName);
6690      }
6691      if (element.namespaceURI === MATHML_NAMESPACE) {
6692        return _checkMathMlNamespace(tagName, parent, parentTagName);
6693      }
6694      if (element.namespaceURI === HTML_NAMESPACE) {
6695        return _checkHtmlNamespace(tagName, parent, parentTagName);
6696      }
6697      if (PARSER_MEDIA_TYPE === "application/xhtml+xml" && ALLOWED_NAMESPACES[element.namespaceURI]) {
6698        return true;
6699      }
6700      return false;
6701    };
6702    const _forceRemove = function _forceRemove2(node) {
6703      arrayPush(DOMPurify.removed, {
6704        element: node
6705      });
6706      try {
6707        getParentNode2(node).removeChild(node);
6708      } catch (_3) {
6709        remove(node);
6710        if (!getParentNode2(node)) {
6711          throw typeErrorCreate("a node selected for removal could not be detached from its tree and cannot be safely returned; refusing to sanitize in place");
6712        }
6713      }
6714    };
6715    const _neutralizeRoot = function _neutralizeRoot2(root) {
6716      const childNodes = getChildNodes(root);
6717      if (childNodes) {
6718        const snapshot = [];
6719        arrayForEach(childNodes, (child) => {
6720          arrayPush(snapshot, child);
6721        });
6722        arrayForEach(snapshot, (child) => {
6723          try {
6724            remove(child);
6725          } catch (_3) {
6726          }
6727        });
6728      }
6729      const attributes = getAttributes(root);
6730      if (attributes) {
6731        for (let i2 = attributes.length - 1; i2 >= 0; --i2) {
6732          const attribute = attributes[i2];
6733          const name = attribute && attribute.name;
6734          if (typeof name === "string") {
6735            try {
6736              root.removeAttribute(name);
6737            } catch (_3) {
6738            }
6739          }
6740        }
6741      }
6742    };
6743    const _removeAttribute = function _removeAttribute2(name, element) {
6744      try {
6745        arrayPush(DOMPurify.removed, {
6746          attribute: element.getAttributeNode(name),
6747          from: element
6748        });
6749      } catch (_3) {
6750        arrayPush(DOMPurify.removed, {
6751          attribute: null,
6752          from: element
6753        });
6754      }
6755      element.removeAttribute(name);
6756      if (name === "is") {
6757        if (RETURN_DOM || RETURN_DOM_FRAGMENT) {
6758          try {
6759            _forceRemove(element);
6760          } catch (_3) {
6761          }
6762        } else {
6763          try {
6764            element.setAttribute(name, "");
6765          } catch (_3) {
6766          }
6767        }
6768      }
6769    };
6770    const _stripDisallowedAttributes = function _stripDisallowedAttributes2(element) {
6771      const attributes = getAttributes(element);
6772      if (!attributes) {
6773        return;
6774      }
6775      for (let i2 = attributes.length - 1; i2 >= 0; --i2) {
6776        const attribute = attributes[i2];
6777        const name = attribute && attribute.name;
6778        if (typeof name !== "string" || ALLOWED_ATTR[transformCaseFunc(name)]) {
6779          continue;
6780        }
6781        try {
6782          element.removeAttribute(name);
6783        } catch (_3) {
6784        }
6785      }
6786    };
6787    const _neutralizeSubtree = function _neutralizeSubtree2(root) {
6788      const stack = [root];
6789      while (stack.length > 0) {
6790        const node = stack.pop();
6791        const nodeType = getNodeType ? getNodeType(node) : node.nodeType;
6792        if (nodeType === NODE_TYPE.element) {
6793          _stripDisallowedAttributes(node);
6794        }
6795        const childNodes = getChildNodes(node);
6796        if (childNodes) {
6797          for (let i2 = childNodes.length - 1; i2 >= 0; --i2) {
6798            stack.push(childNodes[i2]);
6799          }
6800        }
6801      }
6802    };
6803    const _initDocument = function _initDocument2(dirty) {
6804      let doc = null;
6805      let leadingWhitespace = null;
6806      if (FORCE_BODY) {
6807        dirty = "<remove></remove>" + dirty;
6808      } else {
6809        const matches = stringMatch(dirty, /^[\r\n\t ]+/);
6810        leadingWhitespace = matches && matches[0];
6811      }
6812      if (PARSER_MEDIA_TYPE === "application/xhtml+xml" && NAMESPACE === HTML_NAMESPACE) {
6813        dirty = '<html xmlns="http://www.w3.org/1999/xhtml"><head></head><body>' + dirty + "</body></html>";
6814      }
6815      const dirtyPayload = trustedTypesPolicy ? _createTrustedHTML(dirty) : dirty;
6816      if (NAMESPACE === HTML_NAMESPACE) {
6817        try {
6818          doc = new DOMParser2().parseFromString(dirtyPayload, PARSER_MEDIA_TYPE);
6819        } catch (_3) {
6820        }
6821      }
6822      if (!doc || !doc.documentElement) {
6823        doc = implementation.createDocument(NAMESPACE, "template", null);
6824        try {
6825          doc.documentElement.innerHTML = IS_EMPTY_INPUT ? emptyHTML : dirtyPayload;
6826        } catch (_3) {
6827        }
6828      }
6829      const body = doc.body || doc.documentElement;
6830      if (dirty && leadingWhitespace) {
6831        body.insertBefore(document2.createTextNode(leadingWhitespace), body.childNodes[0] || null);
6832      }
6833      if (NAMESPACE === HTML_NAMESPACE) {
6834        return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? "html" : "body")[0];
6835      }
6836      return WHOLE_DOCUMENT ? doc.documentElement : body;
6837    };
6838    const _createNodeIterator = function _createNodeIterator2(root) {
6839      return createNodeIterator.call(
6840        root.ownerDocument || root,
6841        root,
6842        // eslint-disable-next-line no-bitwise
6843        NodeFilter2.SHOW_ELEMENT | NodeFilter2.SHOW_COMMENT | NodeFilter2.SHOW_TEXT | NodeFilter2.SHOW_PROCESSING_INSTRUCTION | NodeFilter2.SHOW_CDATA_SECTION,
6844        null
6845      );
6846    };
6847    const _stripTemplateExpressions = function _stripTemplateExpressions2(value) {
6848      value = stringReplace(value, MUSTACHE_EXPR$1, " ");
6849      value = stringReplace(value, ERB_EXPR$1, " ");
6850      value = stringReplace(value, TMPLIT_EXPR$1, " ");
6851      return value;
6852    };
6853    const _scrubTemplateExpressions2 = function _scrubTemplateExpressions(node) {
6854      var _node$querySelectorAl;
6855      node.normalize();
6856      const walker = createNodeIterator.call(
6857        node.ownerDocument || node,
6858        node,
6859        // eslint-disable-next-line no-bitwise
6860        NodeFilter2.SHOW_TEXT | NodeFilter2.SHOW_COMMENT | NodeFilter2.SHOW_CDATA_SECTION | NodeFilter2.SHOW_PROCESSING_INSTRUCTION,
6861        null
6862      );
6863      let currentNode = walker.nextNode();
6864      while (currentNode) {
6865        currentNode.data = _stripTemplateExpressions(currentNode.data);
6866        currentNode = walker.nextNode();
6867      }
6868      const templates = (_node$querySelectorAl = node.querySelectorAll) === null || _node$querySelectorAl === void 0 ? void 0 : _node$querySelectorAl.call(node, "template");
6869      if (templates) {
6870        arrayForEach(templates, (tmpl) => {
6871          if (_isDocumentFragment(tmpl.content)) {
6872            _scrubTemplateExpressions2(tmpl.content);
6873          }
6874        });
6875      }
6876    };
6877    const _isClobbered = function _isClobbered2(element) {
6878      const realTagName = getNodeName2 ? getNodeName2(element) : null;
6879      if (typeof realTagName !== "string") {
6880        return false;
6881      }
6882      if (transformCaseFunc(realTagName) !== "form") {
6883        return false;
6884      }
6885      return typeof element.nodeName !== "string" || typeof element.textContent !== "string" || typeof element.removeChild !== "function" || // Realm-safe NamedNodeMap detection: equality against the cached
6886      // prototype getter. Clobbered .attributes (e.g. <input name="attributes">)
6887      // makes the direct read diverge from the cached read; a clean form
6888      // (same-realm OR foreign-realm) has both reads pointing at the same
6889      // canonical NamedNodeMap.
6890      element.attributes !== getAttributes(element) || typeof element.removeAttribute !== "function" || typeof element.setAttribute !== "function" || typeof element.namespaceURI !== "string" || typeof element.insertBefore !== "function" || typeof element.hasChildNodes !== "function" || // NodeType clobbering probe. Cached Node.prototype.nodeType getter
6891      // returns the integer 1 for any Element regardless of realm; direct
6892      // read on a clobbered form (e.g. <input name="nodeType">) returns
6893      // the named child element. Cheap addition — nodeType is read from
6894      // an internal slot, no serialization cost — and removes a residual
6895      // clobbering surface used by several mXSS / PI / comment branches
6896      // in _sanitizeElements that compare currentNode.nodeType directly.
6897      element.nodeType !== getNodeType(element) || // HTMLFormElement has [LegacyOverrideBuiltIns]: a descendant named
6898      // "childNodes" shadows the prototype getter. Direct reads of
6899      // form.childNodes from a clobbered form return the named child
6900      // instead of the real NodeList, so any walk that reads it directly
6901      // skips the form's real children. Compare the direct read to the
6902      // cached Node.prototype getter — when the form's named-property
6903      // getter intercepts the read, the two values differ and we flag
6904      // the form. This catches every clobbering child type (input,
6905      // select, etc.) regardless of whether the named child happens to
6906      // carry a numeric .length, which a typeof-based probe would miss
6907      // (e.g. HTMLSelectElement.length is a defined unsigned-long).
6908      element.childNodes !== getChildNodes(element);
6909    };
6910    const _isDocumentFragment = function _isDocumentFragment2(value) {
6911      if (!getNodeType || typeof value !== "object" || value === null) {
6912        return false;
6913      }
6914      try {
6915        return getNodeType(value) === NODE_TYPE.documentFragment;
6916      } catch (_3) {
6917        return false;
6918      }
6919    };
6920    const _isNode = function _isNode2(value) {
6921      if (!getNodeType || typeof value !== "object" || value === null) {
6922        return false;
6923      }
6924      try {
6925        return typeof getNodeType(value) === "number";
6926      } catch (_3) {
6927        return false;
6928      }
6929    };
6930    function _executeHooks(hooks2, currentNode, data) {
6931      if (hooks2.length === 0) {
6932        return;
6933      }
6934      arrayForEach(hooks2, (hook) => {
6935        hook.call(DOMPurify, currentNode, data, CONFIG);
6936      });
6937    }
6938    const _isUnsafeNode = function _isUnsafeNode2(currentNode, tagName) {
6939      if (SAFE_FOR_XML && currentNode.hasChildNodes() && !_isNode(currentNode.firstElementChild) && regExpTest(ELEMENT_MARKUP_PROBE, currentNode.textContent) && regExpTest(ELEMENT_MARKUP_PROBE, currentNode.innerHTML)) {
6940        return true;
6941      }
6942      if (SAFE_FOR_XML && currentNode.namespaceURI === HTML_NAMESPACE && tagName === "style" && _isNode(currentNode.firstElementChild)) {
6943        return true;
6944      }
6945      if (currentNode.nodeType === NODE_TYPE.processingInstruction) {
6946        return true;
6947      }
6948      if (SAFE_FOR_XML && currentNode.nodeType === NODE_TYPE.comment && regExpTest(COMMENT_MARKUP_PROBE, currentNode.data)) {
6949        return true;
6950      }
6951      return false;
6952    };
6953    const _sanitizeDisallowedNode = function _sanitizeDisallowedNode2(currentNode, tagName) {
6954      if (!FORBID_TAGS[tagName] && _isBasicCustomElement(tagName)) {
6955        if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) {
6956          return false;
6957        }
6958        if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(tagName)) {
6959          return false;
6960        }
6961      }
6962      if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]) {
6963        const parentNode = getParentNode2(currentNode);
6964        const childNodes = getChildNodes(currentNode);
6965        if (childNodes && parentNode) {
6966          const childCount = childNodes.length;
6967          for (let i2 = childCount - 1; i2 >= 0; --i2) {
6968            const hoisted = IN_PLACE ? childNodes[i2] : cloneNode(childNodes[i2], true);
6969            parentNode.insertBefore(hoisted, getNextSibling2(currentNode));
6970          }
6971        }
6972      }
6973      _forceRemove(currentNode);
6974      return true;
6975    };
6976    const _sanitizeElements = function _sanitizeElements2(currentNode) {
6977      _executeHooks(hooks.beforeSanitizeElements, currentNode, null);
6978      if (_isClobbered(currentNode)) {
6979        _forceRemove(currentNode);
6980        return true;
6981      }
6982      const tagName = transformCaseFunc(getNodeName2 ? getNodeName2(currentNode) : currentNode.nodeName);
6983      _executeHooks(hooks.uponSanitizeElement, currentNode, {
6984        tagName,
6985        allowedTags: ALLOWED_TAGS
6986      });
6987      if (_isUnsafeNode(currentNode, tagName)) {
6988        _forceRemove(currentNode);
6989        return true;
6990      }
6991      if (FORBID_TAGS[tagName] || !(EXTRA_ELEMENT_HANDLING.tagCheck instanceof Function && EXTRA_ELEMENT_HANDLING.tagCheck(tagName)) && !ALLOWED_TAGS[tagName]) {
6992        return _sanitizeDisallowedNode(currentNode, tagName);
6993      }
6994      const nt = getNodeType ? getNodeType(currentNode) : currentNode.nodeType;
6995      if (nt === NODE_TYPE.element && !_checkValidNamespace(currentNode)) {
6996        _forceRemove(currentNode);
6997        return true;
6998      }
6999      if ((tagName === "noscript" || tagName === "noembed" || tagName === "noframes") && regExpTest(FALLBACK_TAG_CLOSE, currentNode.innerHTML)) {
7000        _forceRemove(currentNode);
7001        return true;
7002      }
7003      if (SAFE_FOR_TEMPLATES && currentNode.nodeType === NODE_TYPE.text) {
7004        const content = _stripTemplateExpressions(currentNode.textContent);
7005        if (currentNode.textContent !== content) {
7006          arrayPush(DOMPurify.removed, {
7007            element: currentNode.cloneNode()
7008          });
7009          currentNode.textContent = content;
7010        }
7011      }
7012      _executeHooks(hooks.afterSanitizeElements, currentNode, null);
7013      return false;
7014    };
7015    const _isValidAttribute = function _isValidAttribute2(lcTag, lcName, value) {
7016      if (FORBID_ATTR[lcName]) {
7017        return false;
7018      }
7019      if (SANITIZE_DOM && (lcName === "id" || lcName === "name") && (value in document2 || value in formElement)) {
7020        return false;
7021      }
7022      const nameIsPermitted = ALLOWED_ATTR[lcName] || EXTRA_ELEMENT_HANDLING.attributeCheck instanceof Function && EXTRA_ELEMENT_HANDLING.attributeCheck(lcName, lcTag);
7023      if (ALLOW_DATA_ATTR && regExpTest(DATA_ATTR$1, lcName)) ;
7024      else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$1, lcName)) ;
7025      else if (!nameIsPermitted) {
7026        if (
7027          // First condition does a very basic check if a) it's basically a valid custom element tagname AND
7028          // b) if the tagName passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
7029          // and c) if the attribute name passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.attributeNameCheck
7030          _isBasicCustomElement(lcTag) && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, lcTag) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(lcTag)) && (CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.attributeNameCheck, lcName) || CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.attributeNameCheck(lcName, lcTag)) || // Alternative, second condition checks if it's an `is`-attribute, AND
7031          // the value passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck
7032          lcName === "is" && CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements && (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp && regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, value) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function && CUSTOM_ELEMENT_HANDLING.tagNameCheck(value))
7033        ) ;
7034        else {
7035          return false;
7036        }
7037      } else if (URI_SAFE_ATTRIBUTES[lcName]) ;
7038      else if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE$1, ""))) ;
7039      else if ((lcName === "src" || lcName === "xlink:href" || lcName === "href") && lcTag !== "script" && stringIndexOf(value, "data:") === 0 && DATA_URI_TAGS[lcTag]) ;
7040      else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA$1, stringReplace(value, ATTR_WHITESPACE$1, ""))) ;
7041      else if (value) {
7042        return false;
7043      } else ;
7044      return true;
7045    };
7046    const RESERVED_CUSTOM_ELEMENT_NAMES = addToSet({}, ["annotation-xml", "color-profile", "font-face", "font-face-format", "font-face-name", "font-face-src", "font-face-uri", "missing-glyph"]);
7047    const _isBasicCustomElement = function _isBasicCustomElement2(tagName) {
7048      return !RESERVED_CUSTOM_ELEMENT_NAMES[stringToLowerCase(tagName)] && regExpTest(CUSTOM_ELEMENT$1, tagName);
7049    };
7050    const _applyTrustedTypesToAttribute = function _applyTrustedTypesToAttribute2(lcTag, lcName, namespaceURI, value) {
7051      if (trustedTypesPolicy && typeof trustedTypes === "object" && typeof trustedTypes.getAttributeType === "function" && !namespaceURI) {
7052        switch (trustedTypes.getAttributeType(lcTag, lcName)) {
7053          case "TrustedHTML": {
7054            return _createTrustedHTML(value);
7055          }
7056          case "TrustedScriptURL": {
7057            return _createTrustedScriptURL(value);
7058          }
7059        }
7060      }
7061      return value;
7062    };
7063    const _setAttributeValue = function _setAttributeValue2(currentNode, name, namespaceURI, value) {
7064      try {
7065        if (namespaceURI) {
7066          currentNode.setAttributeNS(namespaceURI, name, value);
7067        } else {
7068          currentNode.setAttribute(name, value);
7069        }
7070        if (_isClobbered(currentNode)) {
7071          _forceRemove(currentNode);
7072        } else {
7073          arrayPop(DOMPurify.removed);
7074        }
7075      } catch (_3) {
7076        _removeAttribute(name, currentNode);
7077      }
7078    };
7079    const _sanitizeAttributes = function _sanitizeAttributes2(currentNode) {
7080      _executeHooks(hooks.beforeSanitizeAttributes, currentNode, null);
7081      const attributes = currentNode.attributes;
7082      if (!attributes || _isClobbered(currentNode)) {
7083        return;
7084      }
7085      const hookEvent = {
7086        attrName: "",
7087        attrValue: "",
7088        keepAttr: true,
7089        allowedAttributes: ALLOWED_ATTR,
7090        forceKeepAttr: void 0
7091      };
7092      let l4 = attributes.length;
7093      const lcTag = transformCaseFunc(currentNode.nodeName);
7094      while (l4--) {
7095        const attr = attributes[l4];
7096        const name = attr.name, namespaceURI = attr.namespaceURI, attrValue = attr.value;
7097        const lcName = transformCaseFunc(name);
7098        const initValue = attrValue;
7099        let value = name === "value" ? initValue : stringTrim(initValue);
7100        hookEvent.attrName = lcName;
7101        hookEvent.attrValue = value;
7102        hookEvent.keepAttr = true;
7103        hookEvent.forceKeepAttr = void 0;
7104        _executeHooks(hooks.uponSanitizeAttribute, currentNode, hookEvent);
7105        value = hookEvent.attrValue;
7106        if (SANITIZE_NAMED_PROPS && (lcName === "id" || lcName === "name") && stringIndexOf(value, SANITIZE_NAMED_PROPS_PREFIX) !== 0) {
7107          _removeAttribute(name, currentNode);
7108          value = SANITIZE_NAMED_PROPS_PREFIX + value;
7109        }
7110        if (SAFE_FOR_XML && regExpTest(/((--!?|])>)|<\/(style|script|title|xmp|textarea|noscript|iframe|noembed|noframes)/i, value)) {
7111          _removeAttribute(name, currentNode);
7112          continue;
7113        }
7114        if (lcName === "attributename" && stringMatch(value, "href")) {
7115          _removeAttribute(name, currentNode);
7116          continue;
7117        }
7118        if (hookEvent.forceKeepAttr) {
7119          continue;
7120        }
7121        if (!hookEvent.keepAttr) {
7122          _removeAttribute(name, currentNode);
7123          continue;
7124        }
7125        if (!ALLOW_SELF_CLOSE_IN_ATTR && regExpTest(SELF_CLOSING_TAG, value)) {
7126          _removeAttribute(name, currentNode);
7127          continue;
7128        }
7129        if (SAFE_FOR_TEMPLATES) {
7130          value = _stripTemplateExpressions(value);
7131        }
7132        if (!_isValidAttribute(lcTag, lcName, value)) {
7133          _removeAttribute(name, currentNode);
7134          continue;
7135        }
7136        value = _applyTrustedTypesToAttribute(lcTag, lcName, namespaceURI, value);
7137        if (value !== initValue) {
7138          _setAttributeValue(currentNode, name, namespaceURI, value);
7139        }
7140      }
7141      _executeHooks(hooks.afterSanitizeAttributes, currentNode, null);
7142    };
7143    const _sanitizeShadowDOM2 = function _sanitizeShadowDOM(fragment) {
7144      let shadowNode = null;
7145      const shadowIterator = _createNodeIterator(fragment);
7146      _executeHooks(hooks.beforeSanitizeShadowDOM, fragment, null);
7147      while (shadowNode = shadowIterator.nextNode()) {
7148        _executeHooks(hooks.uponSanitizeShadowNode, shadowNode, null);
7149        _sanitizeElements(shadowNode);
7150        _sanitizeAttributes(shadowNode);
7151        if (_isDocumentFragment(shadowNode.content)) {
7152          _sanitizeShadowDOM2(shadowNode.content);
7153        }
7154        const shadowNodeType = getNodeType ? getNodeType(shadowNode) : shadowNode.nodeType;
7155        if (shadowNodeType === NODE_TYPE.element) {
7156          const innerSr = getShadowRoot(shadowNode);
7157          if (_isDocumentFragment(innerSr)) {
7158            _sanitizeAttachedShadowRoots(innerSr);
7159            _sanitizeShadowDOM2(innerSr);
7160          }
7161        }
7162      }
7163      _executeHooks(hooks.afterSanitizeShadowDOM, fragment, null);
7164    };
7165    const _sanitizeAttachedShadowRoots = function _sanitizeAttachedShadowRoots2(root) {
7166      const stack = [{
7167        node: root,
7168        shadow: null
7169      }];
7170      while (stack.length > 0) {
7171        const item = stack.pop();
7172        if (item.shadow) {
7173          _sanitizeShadowDOM2(item.shadow);
7174          continue;
7175        }
7176        const node = item.node;
7177        const nodeType = getNodeType ? getNodeType(node) : node.nodeType;
7178        const isElement2 = nodeType === NODE_TYPE.element;
7179        const childNodes = getChildNodes(node);
7180        if (childNodes) {
7181          for (let i2 = childNodes.length - 1; i2 >= 0; --i2) {
7182            stack.push({
7183              node: childNodes[i2],
7184              shadow: null
7185            });
7186          }
7187        }
7188        if (isElement2) {
7189          const rootName = getNodeName2 ? getNodeName2(node) : null;
7190          if (typeof rootName === "string" && transformCaseFunc(rootName) === "template") {
7191            const content = node.content;
7192            if (_isDocumentFragment(content)) {
7193              stack.push({
7194                node: content,
7195                shadow: null
7196              });
7197            }
7198          }
7199        }
7200        if (isElement2) {
7201          const sr = getShadowRoot(node);
7202          if (_isDocumentFragment(sr)) {
7203            stack.push({
7204              node: null,
7205              shadow: sr
7206            }, {
7207              node: sr,
7208              shadow: null
7209            });
7210          }
7211        }
7212      }
7213    };
7214    DOMPurify.sanitize = function(dirty) {
7215      let cfg = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {};
7216      let body = null;
7217      let importedNode = null;
7218      let currentNode = null;
7219      let returnNode = null;
7220      IS_EMPTY_INPUT = !dirty;
7221      if (IS_EMPTY_INPUT) {
7222        dirty = "<!-->";
7223      }
7224      if (typeof dirty !== "string" && !_isNode(dirty)) {
7225        dirty = stringifyValue(dirty);
7226        if (typeof dirty !== "string") {
7227          throw typeErrorCreate("dirty is not a string, aborting");
7228        }
7229      }
7230      if (!DOMPurify.isSupported) {
7231        return dirty;
7232      }
7233      if (SET_CONFIG) {
7234        ALLOWED_TAGS = SET_CONFIG_ALLOWED_TAGS;
7235        ALLOWED_ATTR = SET_CONFIG_ALLOWED_ATTR;
7236      } else {
7237        _parseConfig(cfg);
7238      }
7239      if (hooks.uponSanitizeElement.length > 0 || hooks.uponSanitizeAttribute.length > 0) {
7240        ALLOWED_TAGS = clone(ALLOWED_TAGS);
7241      }
7242      if (hooks.uponSanitizeAttribute.length > 0) {
7243        ALLOWED_ATTR = clone(ALLOWED_ATTR);
7244      }
7245      DOMPurify.removed = [];
7246      const inPlace = IN_PLACE && typeof dirty !== "string" && _isNode(dirty);
7247      if (inPlace) {
7248        const nn = getNodeName2 ? getNodeName2(dirty) : dirty.nodeName;
7249        if (typeof nn === "string") {
7250          const tagName = transformCaseFunc(nn);
7251          if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
7252            throw typeErrorCreate("root node is forbidden and cannot be sanitized in-place");
7253          }
7254        }
7255        if (_isClobbered(dirty)) {
7256          throw typeErrorCreate("root node is clobbered and cannot be sanitized in-place");
7257        }
7258        try {
7259          _sanitizeAttachedShadowRoots(dirty);
7260        } catch (error) {
7261          _neutralizeRoot(dirty);
7262          throw error;
7263        }
7264      } else if (_isNode(dirty)) {
7265        body = _initDocument("<!---->");
7266        importedNode = body.ownerDocument.importNode(dirty, true);
7267        if (importedNode.nodeType === NODE_TYPE.element && importedNode.nodeName === "BODY") {
7268          body = importedNode;
7269        } else if (importedNode.nodeName === "HTML") {
7270          body = importedNode;
7271        } else {
7272          body.appendChild(importedNode);
7273        }
7274        _sanitizeAttachedShadowRoots(importedNode);
7275      } else {
7276        if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT && // eslint-disable-next-line unicorn/prefer-includes
7277        dirty.indexOf("<") === -1) {
7278          return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? _createTrustedHTML(dirty) : dirty;
7279        }
7280        body = _initDocument(dirty);
7281        if (!body) {
7282          return RETURN_DOM ? null : RETURN_TRUSTED_TYPE ? emptyHTML : "";
7283        }
7284      }
7285      if (body && FORCE_BODY) {
7286        _forceRemove(body.firstChild);
7287      }
7288      const nodeIterator = _createNodeIterator(inPlace ? dirty : body);
7289      try {
7290        while (currentNode = nodeIterator.nextNode()) {
7291          _sanitizeElements(currentNode);
7292          _sanitizeAttributes(currentNode);
7293          if (_isDocumentFragment(currentNode.content)) {
7294            _sanitizeShadowDOM2(currentNode.content);
7295          }
7296        }
7297      } catch (error) {
7298        if (inPlace) {
7299          _neutralizeRoot(dirty);
7300        }
7301        throw error;
7302      }
7303      if (inPlace) {
7304        arrayForEach(DOMPurify.removed, (entry) => {
7305          if (entry.element) {
7306            _neutralizeSubtree(entry.element);
7307          }
7308        });
7309        if (SAFE_FOR_TEMPLATES) {
7310          _scrubTemplateExpressions2(dirty);
7311        }
7312        return dirty;
7313      }
7314      if (RETURN_DOM) {
7315        if (SAFE_FOR_TEMPLATES) {
7316          _scrubTemplateExpressions2(body);
7317        }
7318        if (RETURN_DOM_FRAGMENT) {
7319          returnNode = createDocumentFragment.call(body.ownerDocument);
7320          while (body.firstChild) {
7321            returnNode.appendChild(body.firstChild);
7322          }
7323        } else {
7324          returnNode = body;
7325        }
7326        if (ALLOWED_ATTR.shadowroot || ALLOWED_ATTR.shadowrootmode) {
7327          returnNode = importNode.call(originalDocument, returnNode, true);
7328        }
7329        return returnNode;
7330      }
7331      let serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;
7332      if (WHOLE_DOCUMENT && ALLOWED_TAGS["!doctype"] && body.ownerDocument && body.ownerDocument.doctype && body.ownerDocument.doctype.name && regExpTest(DOCTYPE_NAME, body.ownerDocument.doctype.name)) {
7333        serializedHTML = "<!DOCTYPE " + body.ownerDocument.doctype.name + ">\n" + serializedHTML;
7334      }
7335      if (SAFE_FOR_TEMPLATES) {
7336        serializedHTML = _stripTemplateExpressions(serializedHTML);
7337      }
7338      return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? _createTrustedHTML(serializedHTML) : serializedHTML;
7339    };
7340    DOMPurify.setConfig = function() {
7341      let cfg = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
7342      _parseConfig(cfg);
7343      SET_CONFIG = true;
7344      SET_CONFIG_ALLOWED_TAGS = ALLOWED_TAGS;
7345      SET_CONFIG_ALLOWED_ATTR = ALLOWED_ATTR;
7346    };
7347    DOMPurify.clearConfig = function() {
7348      CONFIG = null;
7349      SET_CONFIG = false;
7350      SET_CONFIG_ALLOWED_TAGS = null;
7351      SET_CONFIG_ALLOWED_ATTR = null;
7352      trustedTypesPolicy = defaultTrustedTypesPolicy;
7353      emptyHTML = "";
7354    };
7355    DOMPurify.isValidAttribute = function(tag, attr, value) {
7356      if (!CONFIG) {
7357        _parseConfig({});
7358      }
7359      const lcTag = transformCaseFunc(tag);
7360      const lcName = transformCaseFunc(attr);
7361      return _isValidAttribute(lcTag, lcName, value);
7362    };
7363    DOMPurify.addHook = function(entryPoint, hookFunction) {
7364      if (typeof hookFunction !== "function") {
7365        return;
7366      }
7367      if (!objectHasOwnProperty(hooks, entryPoint)) {
7368        return;
7369      }
7370      arrayPush(hooks[entryPoint], hookFunction);
7371    };
7372    DOMPurify.removeHook = function(entryPoint, hookFunction) {
7373      if (!objectHasOwnProperty(hooks, entryPoint)) {
7374        return void 0;
7375      }
7376      if (hookFunction !== void 0) {
7377        const index = arrayLastIndexOf(hooks[entryPoint], hookFunction);
7378        return index === -1 ? void 0 : arraySplice(hooks[entryPoint], index, 1)[0];
7379      }
7380      return arrayPop(hooks[entryPoint]);
7381    };
7382    DOMPurify.removeHooks = function(entryPoint) {
7383      if (!objectHasOwnProperty(hooks, entryPoint)) {
7384        return;
7385      }
7386      hooks[entryPoint] = [];
7387    };
7388    DOMPurify.removeAllHooks = function() {
7389      hooks = _createHooksMap();
7390    };
7391    return DOMPurify;
7392  }
7393  var purify = createDOMPurify();
7394
7395  
vendor: 1,541 bytes, lines 7395-7425
7395// node_modules/@lexical/selection/LexicalSelection.dev.mjs
7396  var LexicalSelection_dev_exports = {};
7397  __export(LexicalSelection_dev_exports, {
7398    $addNodeStyle: () => $addNodeStyle,
7399    $cloneWithProperties: () => $cloneWithProperties2,
7400    $copyBlockFormatIndent: () => $copyBlockFormatIndent,
7401    $ensureForwardRangeSelection: () => $ensureForwardRangeSelection,
7402    $forEachSelectedTextNode: () => $forEachSelectedTextNode,
7403    $getComputedStyleForElement: () => $getComputedStyleForElement,
7404    $getComputedStyleForParent: () => $getComputedStyleForParent,
7405    $getSelectionStyleValueForProperty: () => $getSelectionStyleValueForProperty,
7406    $isAtNodeEnd: () => $isAtNodeEnd,
7407    $isParentElementRTL: () => $isParentElementRTL,
7408    $isParentRTL: () => $isParentRTL,
7409    $moveCaretSelection: () => $moveCaretSelection,
7410    $moveCharacter: () => $moveCharacter,
7411    $patchStyleText: () => $patchStyleText,
7412    $selectAll: () => $selectAll2,
7413    $setBlocksType: () => $setBlocksType,
7414    $shouldOverrideDefaultCharacterSelection: () => $shouldOverrideDefaultCharacterSelection,
7415    $sliceSelectedTextNodeContent: () => $sliceSelectedTextNodeContent,
7416    $trimTextContentFromAnchor: () => $trimTextContentFromAnchor,
7417    $wrapNodes: () => $wrapNodes,
7418    createDOMRange: () => createDOMRange,
7419    createRectsFromDOMRange: () => createRectsFromDOMRange,
7420    getCSSFromStyleObject: () => getCSSFromStyleObject,
7421    getStyleObjectFromCSS: () => getStyleObjectFromCSS3,
7422    trimTextContentFromAnchor: () => trimTextContentFromAnchor
7423  });
7424
7425  
vendor: 12,053 bytes, lines 7425-7664
7425// node_modules/lexical/Lexical.mjs
7426  var Lexical_exports = {};
7427  __export(Lexical_exports, {
7428    $addUpdateTag: () => $addUpdateTag2,
7429    $applyNodeReplacement: () => $applyNodeReplacement2,
7430    $caretFromPoint: () => $caretFromPoint2,
7431    $caretRangeFromSelection: () => $caretRangeFromSelection2,
7432    $cloneWithProperties: () => $cloneWithProperties2,
7433    $cloneWithPropertiesEphemeral: () => $cloneWithPropertiesEphemeral2,
7434    $comparePointCaretNext: () => $comparePointCaretNext2,
7435    $copyNode: () => $copyNode2,
7436    $create: () => $create2,
7437    $createChildrenArray: () => $createChildrenArray2,
7438    $createLineBreakNode: () => $createLineBreakNode2,
7439    $createNodeSelection: () => $createNodeSelection2,
7440    $createParagraphNode: () => $createParagraphNode2,
7441    $createPoint: () => $createPoint2,
7442    $createRangeSelection: () => $createRangeSelection2,
7443    $createRangeSelectionFromDom: () => $createRangeSelectionFromDom2,
7444    $createTabNode: () => $createTabNode2,
7445    $createTextNode: () => $createTextNode2,
7446    $extendCaretToRange: () => $extendCaretToRange2,
7447    $findMatchingParent: () => $findMatchingParent2,
7448    $getAdjacentChildCaret: () => $getAdjacentChildCaret2,
7449    $getAdjacentNode: () => $getAdjacentNode2,
7450    $getAdjacentSiblingOrParentSiblingCaret: () => $getAdjacentSiblingOrParentSiblingCaret2,
7451    $getCaretInDirection: () => $getCaretInDirection2,
7452    $getCaretRange: () => $getCaretRange2,
7453    $getCaretRangeInDirection: () => $getCaretRangeInDirection2,
7454    $getCharacterOffsets: () => $getCharacterOffsets2,
7455    $getChildCaret: () => $getChildCaret2,
7456    $getChildCaretAtIndex: () => $getChildCaretAtIndex2,
7457    $getChildCaretOrSelf: () => $getChildCaretOrSelf2,
7458    $getCollapsedCaretRange: () => $getCollapsedCaretRange2,
7459    $getCommonAncestor: () => $getCommonAncestor2,
7460    $getCommonAncestorResultBranchOrder: () => $getCommonAncestorResultBranchOrder2,
7461    $getEditor: () => $getEditor2,
7462    $getEditorDOMRenderConfig: () => $getEditorDOMRenderConfig2,
7463    $getNearestNodeFromDOMNode: () => $getNearestNodeFromDOMNode2,
7464    $getNearestRootOrShadowRoot: () => $getNearestRootOrShadowRoot2,
7465    $getNodeByKey: () => $getNodeByKey2,
7466    $getNodeByKeyOrThrow: () => $getNodeByKeyOrThrow2,
7467    $getNodeFromDOMNode: () => $getNodeFromDOMNode2,
7468    $getPreviousSelection: () => $getPreviousSelection2,
7469    $getRoot: () => $getRoot2,
7470    $getSelection: () => $getSelection2,
7471    $getSiblingCaret: () => $getSiblingCaret2,
7472    $getState: () => $getState2,
7473    $getStateChange: () => $getStateChange2,
7474    $getTextContent: () => $getTextContent2,
7475    $getTextNodeOffset: () => $getTextNodeOffset2,
7476    $getTextPointCaret: () => $getTextPointCaret2,
7477    $getTextPointCaretSlice: () => $getTextPointCaretSlice2,
7478    $getWritableNodeState: () => $getWritableNodeState2,
7479    $hasAncestor: () => $hasAncestor2,
7480    $hasUpdateTag: () => $hasUpdateTag2,
7481    $insertNodes: () => $insertNodes2,
7482    $isBlockElementNode: () => $isBlockElementNode2,
7483    $isChildCaret: () => $isChildCaret2,
7484    $isDecoratorNode: () => $isDecoratorNode2,
7485    $isEditorState: () => $isEditorState2,
7486    $isElementNode: () => $isElementNode2,
7487    $isExtendableTextPointCaret: () => $isExtendableTextPointCaret2,
7488    $isInlineElementOrDecoratorNode: () => $isInlineElementOrDecoratorNode2,
7489    $isLeafNode: () => $isLeafNode2,
7490    $isLexicalNode: () => $isLexicalNode2,
7491    $isLineBreakNode: () => $isLineBreakNode2,
7492    $isNodeCaret: () => $isNodeCaret2,
7493    $isNodeSelection: () => $isNodeSelection2,
7494    $isParagraphNode: () => $isParagraphNode2,
7495    $isRangeSelection: () => $isRangeSelection2,
7496    $isRootNode: () => $isRootNode2,
7497    $isRootOrShadowRoot: () => $isRootOrShadowRoot2,
7498    $isSiblingCaret: () => $isSiblingCaret2,
7499    $isTabNode: () => $isTabNode2,
7500    $isTextNode: () => $isTextNode2,
7501    $isTextPointCaret: () => $isTextPointCaret2,
7502    $isTextPointCaretSlice: () => $isTextPointCaretSlice2,
7503    $isTokenOrSegmented: () => $isTokenOrSegmented2,
7504    $isTokenOrTab: () => $isTokenOrTab2,
7505    $nodesOfType: () => $nodesOfType2,
7506    $normalizeCaret: () => $normalizeCaret2,
7507    $normalizeSelection__EXPERIMENTAL: () => $normalizeSelection__EXPERIMENTAL,
7508    $onUpdate: () => $onUpdate2,
7509    $parseSerializedNode: () => $parseSerializedNode2,
7510    $removeTextFromCaretRange: () => $removeTextFromCaretRange2,
7511    $rewindSiblingCaret: () => $rewindSiblingCaret2,
7512    $selectAll: () => $selectAll2,
7513    $setCompositionKey: () => $setCompositionKey2,
7514    $setPointFromCaret: () => $setPointFromCaret2,
7515    $setSelection: () => $setSelection2,
7516    $setSelectionFromCaretRange: () => $setSelectionFromCaretRange2,
7517    $setState: () => $setState2,
7518    $splitAtPointCaretNext: () => $splitAtPointCaretNext2,
7519    $splitNode: () => $splitNode2,
7520    $updateRangeSelectionFromCaretRange: () => $updateRangeSelectionFromCaretRange2,
7521    ArtificialNode__DO_NOT_USE: () => ArtificialNode__DO_NOT_USE2,
7522    BEFORE_INPUT_COMMAND: () => BEFORE_INPUT_COMMAND2,
7523    BLUR_COMMAND: () => BLUR_COMMAND2,
7524    CAN_REDO_COMMAND: () => CAN_REDO_COMMAND2,
7525    CAN_UNDO_COMMAND: () => CAN_UNDO_COMMAND2,
7526    CLEAR_EDITOR_COMMAND: () => CLEAR_EDITOR_COMMAND2,
7527    CLEAR_HISTORY_COMMAND: () => CLEAR_HISTORY_COMMAND2,
7528    CLICK_COMMAND: () => CLICK_COMMAND2,
7529    COLLABORATION_TAG: () => COLLABORATION_TAG2,
7530    COMMAND_PRIORITY_BEFORE_CRITICAL: () => COMMAND_PRIORITY_BEFORE_CRITICAL2,
7531    COMMAND_PRIORITY_BEFORE_EDITOR: () => COMMAND_PRIORITY_BEFORE_EDITOR2,
7532    COMMAND_PRIORITY_BEFORE_HIGH: () => COMMAND_PRIORITY_BEFORE_HIGH2,
7533    COMMAND_PRIORITY_BEFORE_LOW: () => COMMAND_PRIORITY_BEFORE_LOW2,
7534    COMMAND_PRIORITY_BEFORE_NORMAL: () => COMMAND_PRIORITY_BEFORE_NORMAL2,
7535    COMMAND_PRIORITY_CRITICAL: () => COMMAND_PRIORITY_CRITICAL2,
7536    COMMAND_PRIORITY_EDITOR: () => COMMAND_PRIORITY_EDITOR2,
7537    COMMAND_PRIORITY_HIGH: () => COMMAND_PRIORITY_HIGH2,
7538    COMMAND_PRIORITY_LOW: () => COMMAND_PRIORITY_LOW2,
7539    COMMAND_PRIORITY_NORMAL: () => COMMAND_PRIORITY_NORMAL2,
7540    COMPOSITION_END_COMMAND: () => COMPOSITION_END_COMMAND2,
7541    COMPOSITION_END_TAG: () => COMPOSITION_END_TAG2,
7542    COMPOSITION_START_COMMAND: () => COMPOSITION_START_COMMAND2,
7543    COMPOSITION_START_TAG: () => COMPOSITION_START_TAG2,
7544    CONTROLLED_TEXT_INSERTION_COMMAND: () => CONTROLLED_TEXT_INSERTION_COMMAND2,
7545    COPY_COMMAND: () => COPY_COMMAND2,
7546    CUT_COMMAND: () => CUT_COMMAND2,
7547    DEFAULT_EDITOR_DOM_CONFIG: () => DEFAULT_EDITOR_DOM_CONFIG2,
7548    DELETE_CHARACTER_COMMAND: () => DELETE_CHARACTER_COMMAND2,
7549    DELETE_LINE_COMMAND: () => DELETE_LINE_COMMAND2,
7550    DELETE_WORD_COMMAND: () => DELETE_WORD_COMMAND2,
7551    DRAGEND_COMMAND: () => DRAGEND_COMMAND2,
7552    DRAGOVER_COMMAND: () => DRAGOVER_COMMAND2,
7553    DRAGSTART_COMMAND: () => DRAGSTART_COMMAND2,
7554    DROP_COMMAND: () => DROP_COMMAND2,
7555    DecoratorNode: () => DecoratorNode2,
7556    ElementNode: () => ElementNode2,
7557    FOCUS_COMMAND: () => FOCUS_COMMAND2,
7558    FORMAT_ELEMENT_COMMAND: () => FORMAT_ELEMENT_COMMAND2,
7559    FORMAT_TEXT_COMMAND: () => FORMAT_TEXT_COMMAND2,
7560    HISTORIC_TAG: () => HISTORIC_TAG2,
7561    HISTORY_MERGE_TAG: () => HISTORY_MERGE_TAG2,
7562    HISTORY_PUSH_TAG: () => HISTORY_PUSH_TAG2,
7563    INDENT_CONTENT_COMMAND: () => INDENT_CONTENT_COMMAND2,
7564    INPUT_COMMAND: () => INPUT_COMMAND2,
7565    INSERT_LINE_BREAK_COMMAND: () => INSERT_LINE_BREAK_COMMAND2,
7566    INSERT_PARAGRAPH_COMMAND: () => INSERT_PARAGRAPH_COMMAND2,
7567    INSERT_TAB_COMMAND: () => INSERT_TAB_COMMAND2,
7568    INTERNAL_$isBlock: () => INTERNAL_$isBlock2,
7569    IS_ALL_FORMATTING: () => IS_ALL_FORMATTING2,
7570    IS_BOLD: () => IS_BOLD2,
7571    IS_CODE: () => IS_CODE2,
7572    IS_HIGHLIGHT: () => IS_HIGHLIGHT2,
7573    IS_ITALIC: () => IS_ITALIC2,
7574    IS_STRIKETHROUGH: () => IS_STRIKETHROUGH2,
7575    IS_SUBSCRIPT: () => IS_SUBSCRIPT2,
7576    IS_SUPERSCRIPT: () => IS_SUPERSCRIPT2,
7577    IS_UNDERLINE: () => IS_UNDERLINE2,
7578    KEY_ARROW_DOWN_COMMAND: () => KEY_ARROW_DOWN_COMMAND2,
7579    KEY_ARROW_LEFT_COMMAND: () => KEY_ARROW_LEFT_COMMAND2,
7580    KEY_ARROW_RIGHT_COMMAND: () => KEY_ARROW_RIGHT_COMMAND2,
7581    KEY_ARROW_UP_COMMAND: () => KEY_ARROW_UP_COMMAND2,
7582    KEY_BACKSPACE_COMMAND: () => KEY_BACKSPACE_COMMAND2,
7583    KEY_DELETE_COMMAND: () => KEY_DELETE_COMMAND2,
7584    KEY_DOWN_COMMAND: () => KEY_DOWN_COMMAND2,
7585    KEY_ENTER_COMMAND: () => KEY_ENTER_COMMAND2,
7586    KEY_ESCAPE_COMMAND: () => KEY_ESCAPE_COMMAND2,
7587    KEY_MODIFIER_COMMAND: () => KEY_MODIFIER_COMMAND2,
7588    KEY_SPACE_COMMAND: () => KEY_SPACE_COMMAND2,
7589    KEY_TAB_COMMAND: () => KEY_TAB_COMMAND2,
7590    LineBreakNode: () => LineBreakNode2,
7591    MOVE_TO_END: () => MOVE_TO_END2,
7592    MOVE_TO_START: () => MOVE_TO_START2,
7593    NODE_STATE_KEY: () => NODE_STATE_KEY2,
7594    OUTDENT_CONTENT_COMMAND: () => OUTDENT_CONTENT_COMMAND2,
7595    PASTE_COMMAND: () => PASTE_COMMAND2,
7596    PASTE_TAG: () => PASTE_TAG2,
7597    ParagraphNode: () => ParagraphNode2,
7598    REDO_COMMAND: () => REDO_COMMAND2,
7599    REMOVE_TEXT_COMMAND: () => REMOVE_TEXT_COMMAND2,
7600    RootNode: () => RootNode2,
7601    SELECTION_CHANGE_COMMAND: () => SELECTION_CHANGE_COMMAND2,
7602    SELECTION_INSERT_CLIPBOARD_NODES_COMMAND: () => SELECTION_INSERT_CLIPBOARD_NODES_COMMAND2,
7603    SELECT_ALL_COMMAND: () => SELECT_ALL_COMMAND2,
7604    SKIP_COLLAB_TAG: () => SKIP_COLLAB_TAG2,
7605    SKIP_DOM_SELECTION_TAG: () => SKIP_DOM_SELECTION_TAG2,
7606    SKIP_SCROLL_INTO_VIEW_TAG: () => SKIP_SCROLL_INTO_VIEW_TAG2,
7607    SKIP_SELECTION_FOCUS_TAG: () => SKIP_SELECTION_FOCUS_TAG2,
7608    TEXT_TYPE_TO_FORMAT: () => TEXT_TYPE_TO_FORMAT2,
7609    TabNode: () => TabNode2,
7610    TextNode: () => TextNode2,
7611    UNDO_COMMAND: () => UNDO_COMMAND2,
7612    addClassNamesToElement: () => addClassNamesToElement2,
7613    buildImportMap: () => buildImportMap2,
7614    configExtension: () => configExtension2,
7615    createCommand: () => createCommand2,
7616    createEditor: () => createEditor2,
7617    createSharedNodeState: () => createSharedNodeState2,
7618    createState: () => createState2,
7619    declarePeerDependency: () => declarePeerDependency2,
7620    defineExtension: () => defineExtension2,
7621    flipDirection: () => flipDirection2,
7622    getDOMOwnerDocument: () => getDOMOwnerDocument2,
7623    getDOMSelection: () => getDOMSelection2,
7624    getDOMSelectionFromTarget: () => getDOMSelectionFromTarget2,
7625    getDOMTextNode: () => getDOMTextNode2,
7626    getEditorPropertyFromDOMNode: () => getEditorPropertyFromDOMNode2,
7627    getNearestEditorFromDOMNode: () => getNearestEditorFromDOMNode2,
7628    getRegisteredNode: () => getRegisteredNode2,
7629    getRegisteredNodeOrThrow: () => getRegisteredNodeOrThrow2,
7630    getStaticNodeConfig: () => getStaticNodeConfig2,
7631    getStyleObjectFromCSS: () => getStyleObjectFromCSS2,
7632    getTextDirection: () => getTextDirection2,
7633    getTransformSetFromKlass: () => getTransformSetFromKlass2,
7634    isBlockDomNode: () => isBlockDomNode2,
7635    isCurrentlyReadOnlyMode: () => isCurrentlyReadOnlyMode2,
7636    isDOMDocumentNode: () => isDOMDocumentNode2,
7637    isDOMNode: () => isDOMNode2,
7638    isDOMTextNode: () => isDOMTextNode2,
7639    isDOMUnmanaged: () => isDOMUnmanaged2,
7640    isDocumentFragment: () => isDocumentFragment2,
7641    isExactShortcutMatch: () => isExactShortcutMatch2,
7642    isHTMLAnchorElement: () => isHTMLAnchorElement2,
7643    isHTMLElement: () => isHTMLElement2,
7644    isInlineDomNode: () => isInlineDomNode2,
7645    isLexicalEditor: () => isLexicalEditor2,
7646    isModifierMatch: () => isModifierMatch2,
7647    isSelectionCapturedInDecoratorInput: () => isSelectionCapturedInDecoratorInput2,
7648    isSelectionWithinEditor: () => isSelectionWithinEditor2,
7649    makeStepwiseIterator: () => makeStepwiseIterator2,
7650    mergeRegister: () => mergeRegister2,
7651    normalizeClassNames: () => normalizeClassNames2,
7652    removeClassNamesFromElement: () => removeClassNamesFromElement2,
7653    removeFromParent: () => removeFromParent2,
7654    resetRandomKey: () => resetRandomKey2,
7655    safeCast: () => safeCast2,
7656    setDOMStyleFromCSS: () => setDOMStyleFromCSS2,
7657    setDOMStyleObject: () => setDOMStyleObject2,
7658    setDOMUnmanaged: () => setDOMUnmanaged2,
7659    setNodeIndentFromDOM: () => setNodeIndentFromDOM2,
7660    shallowMergeConfig: () => shallowMergeConfig2,
7661    toggleTextFormatType: () => toggleTextFormatType2
7662  });
7663
7664  
vendor: 446,113 bytes, lines 7664-19555
7664// node_modules/lexical/Lexical.dev.mjs
7665  var Lexical_dev_exports = {};
7666  __export(Lexical_dev_exports, {
7667    $addUpdateTag: () => $addUpdateTag,
7668    $applyNodeReplacement: () => $applyNodeReplacement,
7669    $caretFromPoint: () => $caretFromPoint,
7670    $caretRangeFromSelection: () => $caretRangeFromSelection,
7671    $cloneWithProperties: () => $cloneWithProperties,
7672    $cloneWithPropertiesEphemeral: () => $cloneWithPropertiesEphemeral,
7673    $comparePointCaretNext: () => $comparePointCaretNext,
7674    $copyNode: () => $copyNode,
7675    $create: () => $create,
7676    $createChildrenArray: () => $createChildrenArray,
7677    $createLineBreakNode: () => $createLineBreakNode,
7678    $createNodeSelection: () => $createNodeSelection,
7679    $createParagraphNode: () => $createParagraphNode,
7680    $createPoint: () => $createPoint,
7681    $createRangeSelection: () => $createRangeSelection,
7682    $createRangeSelectionFromDom: () => $createRangeSelectionFromDom,
7683    $createTabNode: () => $createTabNode,
7684    $createTextNode: () => $createTextNode,
7685    $extendCaretToRange: () => $extendCaretToRange,
7686    $findMatchingParent: () => $findMatchingParent,
7687    $getAdjacentChildCaret: () => $getAdjacentChildCaret,
7688    $getAdjacentNode: () => $getAdjacentNode,
7689    $getAdjacentSiblingOrParentSiblingCaret: () => $getAdjacentSiblingOrParentSiblingCaret,
7690    $getCaretInDirection: () => $getCaretInDirection,
7691    $getCaretRange: () => $getCaretRange,
7692    $getCaretRangeInDirection: () => $getCaretRangeInDirection,
7693    $getCharacterOffsets: () => $getCharacterOffsets,
7694    $getChildCaret: () => $getChildCaret,
7695    $getChildCaretAtIndex: () => $getChildCaretAtIndex,
7696    $getChildCaretOrSelf: () => $getChildCaretOrSelf,
7697    $getCollapsedCaretRange: () => $getCollapsedCaretRange,
7698    $getCommonAncestor: () => $getCommonAncestor,
7699    $getCommonAncestorResultBranchOrder: () => $getCommonAncestorResultBranchOrder,
7700    $getEditor: () => $getEditor,
7701    $getEditorDOMRenderConfig: () => $getEditorDOMRenderConfig,
7702    $getNearestNodeFromDOMNode: () => $getNearestNodeFromDOMNode,
7703    $getNearestRootOrShadowRoot: () => $getNearestRootOrShadowRoot,
7704    $getNodeByKey: () => $getNodeByKey,
7705    $getNodeByKeyOrThrow: () => $getNodeByKeyOrThrow,
7706    $getNodeFromDOMNode: () => $getNodeFromDOMNode,
7707    $getPreviousSelection: () => $getPreviousSelection,
7708    $getRoot: () => $getRoot,
7709    $getSelection: () => $getSelection,
7710    $getSiblingCaret: () => $getSiblingCaret,
7711    $getState: () => $getState,
7712    $getStateChange: () => $getStateChange,
7713    $getTextContent: () => $getTextContent,
7714    $getTextNodeOffset: () => $getTextNodeOffset,
7715    $getTextPointCaret: () => $getTextPointCaret,
7716    $getTextPointCaretSlice: () => $getTextPointCaretSlice,
7717    $getWritableNodeState: () => $getWritableNodeState,
7718    $hasAncestor: () => $hasAncestor,
7719    $hasUpdateTag: () => $hasUpdateTag,
7720    $insertNodes: () => $insertNodes,
7721    $isBlockElementNode: () => $isBlockElementNode,
7722    $isChildCaret: () => $isChildCaret,
7723    $isDecoratorNode: () => $isDecoratorNode,
7724    $isEditorState: () => $isEditorState,
7725    $isElementNode: () => $isElementNode,
7726    $isExtendableTextPointCaret: () => $isExtendableTextPointCaret,
7727    $isInlineElementOrDecoratorNode: () => $isInlineElementOrDecoratorNode,
7728    $isLeafNode: () => $isLeafNode,
7729    $isLexicalNode: () => $isLexicalNode,
7730    $isLineBreakNode: () => $isLineBreakNode,
7731    $isNodeCaret: () => $isNodeCaret,
7732    $isNodeSelection: () => $isNodeSelection,
7733    $isParagraphNode: () => $isParagraphNode,
7734    $isRangeSelection: () => $isRangeSelection,
7735    $isRootNode: () => $isRootNode,
7736    $isRootOrShadowRoot: () => $isRootOrShadowRoot,
7737    $isSiblingCaret: () => $isSiblingCaret,
7738    $isTabNode: () => $isTabNode,
7739    $isTextNode: () => $isTextNode,
7740    $isTextPointCaret: () => $isTextPointCaret,
7741    $isTextPointCaretSlice: () => $isTextPointCaretSlice,
7742    $isTokenOrSegmented: () => $isTokenOrSegmented,
7743    $isTokenOrTab: () => $isTokenOrTab,
7744    $nodesOfType: () => $nodesOfType,
7745    $normalizeCaret: () => $normalizeCaret,
7746    $normalizeSelection__EXPERIMENTAL: () => $normalizeSelection,
7747    $onUpdate: () => $onUpdate,
7748    $parseSerializedNode: () => $parseSerializedNode,
7749    $removeTextFromCaretRange: () => $removeTextFromCaretRange,
7750    $rewindSiblingCaret: () => $rewindSiblingCaret,
7751    $selectAll: () => $selectAll,
7752    $setCompositionKey: () => $setCompositionKey,
7753    $setPointFromCaret: () => $setPointFromCaret,
7754    $setSelection: () => $setSelection,
7755    $setSelectionFromCaretRange: () => $setSelectionFromCaretRange,
7756    $setState: () => $setState,
7757    $splitAtPointCaretNext: () => $splitAtPointCaretNext,
7758    $splitNode: () => $splitNode,
7759    $updateRangeSelectionFromCaretRange: () => $updateRangeSelectionFromCaretRange,
7760    ArtificialNode__DO_NOT_USE: () => ArtificialNode__DO_NOT_USE,
7761    BEFORE_INPUT_COMMAND: () => BEFORE_INPUT_COMMAND,
7762    BLUR_COMMAND: () => BLUR_COMMAND,
7763    CAN_REDO_COMMAND: () => CAN_REDO_COMMAND,
7764    CAN_UNDO_COMMAND: () => CAN_UNDO_COMMAND,
7765    CLEAR_EDITOR_COMMAND: () => CLEAR_EDITOR_COMMAND,
7766    CLEAR_HISTORY_COMMAND: () => CLEAR_HISTORY_COMMAND,
7767    CLICK_COMMAND: () => CLICK_COMMAND,
7768    COLLABORATION_TAG: () => COLLABORATION_TAG,
7769    COMMAND_PRIORITY_BEFORE_CRITICAL: () => COMMAND_PRIORITY_BEFORE_CRITICAL,
7770    COMMAND_PRIORITY_BEFORE_EDITOR: () => COMMAND_PRIORITY_BEFORE_EDITOR,
7771    COMMAND_PRIORITY_BEFORE_HIGH: () => COMMAND_PRIORITY_BEFORE_HIGH,
7772    COMMAND_PRIORITY_BEFORE_LOW: () => COMMAND_PRIORITY_BEFORE_LOW,
7773    COMMAND_PRIORITY_BEFORE_NORMAL: () => COMMAND_PRIORITY_BEFORE_NORMAL,
7774    COMMAND_PRIORITY_CRITICAL: () => COMMAND_PRIORITY_CRITICAL,
7775    COMMAND_PRIORITY_EDITOR: () => COMMAND_PRIORITY_EDITOR,
7776    COMMAND_PRIORITY_HIGH: () => COMMAND_PRIORITY_HIGH,
7777    COMMAND_PRIORITY_LOW: () => COMMAND_PRIORITY_LOW,
7778    COMMAND_PRIORITY_NORMAL: () => COMMAND_PRIORITY_NORMAL,
7779    COMPOSITION_END_COMMAND: () => COMPOSITION_END_COMMAND,
7780    COMPOSITION_END_TAG: () => COMPOSITION_END_TAG,
7781    COMPOSITION_START_COMMAND: () => COMPOSITION_START_COMMAND,
7782    COMPOSITION_START_TAG: () => COMPOSITION_START_TAG,
7783    CONTROLLED_TEXT_INSERTION_COMMAND: () => CONTROLLED_TEXT_INSERTION_COMMAND,
7784    COPY_COMMAND: () => COPY_COMMAND,
7785    CUT_COMMAND: () => CUT_COMMAND,
7786    DEFAULT_EDITOR_DOM_CONFIG: () => DEFAULT_EDITOR_DOM_CONFIG,
7787    DELETE_CHARACTER_COMMAND: () => DELETE_CHARACTER_COMMAND,
7788    DELETE_LINE_COMMAND: () => DELETE_LINE_COMMAND,
7789    DELETE_WORD_COMMAND: () => DELETE_WORD_COMMAND,
7790    DRAGEND_COMMAND: () => DRAGEND_COMMAND,
7791    DRAGOVER_COMMAND: () => DRAGOVER_COMMAND,
7792    DRAGSTART_COMMAND: () => DRAGSTART_COMMAND,
7793    DROP_COMMAND: () => DROP_COMMAND,
7794    DecoratorNode: () => DecoratorNode,
7795    ElementNode: () => ElementNode,
7796    FOCUS_COMMAND: () => FOCUS_COMMAND,
7797    FORMAT_ELEMENT_COMMAND: () => FORMAT_ELEMENT_COMMAND,
7798    FORMAT_TEXT_COMMAND: () => FORMAT_TEXT_COMMAND,
7799    HISTORIC_TAG: () => HISTORIC_TAG,
7800    HISTORY_MERGE_TAG: () => HISTORY_MERGE_TAG,
7801    HISTORY_PUSH_TAG: () => HISTORY_PUSH_TAG,
7802    INDENT_CONTENT_COMMAND: () => INDENT_CONTENT_COMMAND,
7803    INPUT_COMMAND: () => INPUT_COMMAND,
7804    INSERT_LINE_BREAK_COMMAND: () => INSERT_LINE_BREAK_COMMAND,
7805    INSERT_PARAGRAPH_COMMAND: () => INSERT_PARAGRAPH_COMMAND,
7806    INSERT_TAB_COMMAND: () => INSERT_TAB_COMMAND,
7807    INTERNAL_$isBlock: () => INTERNAL_$isBlock,
7808    IS_ALL_FORMATTING: () => IS_ALL_FORMATTING,
7809    IS_BOLD: () => IS_BOLD,
7810    IS_CODE: () => IS_CODE,
7811    IS_HIGHLIGHT: () => IS_HIGHLIGHT,
7812    IS_ITALIC: () => IS_ITALIC,
7813    IS_STRIKETHROUGH: () => IS_STRIKETHROUGH,
7814    IS_SUBSCRIPT: () => IS_SUBSCRIPT,
7815    IS_SUPERSCRIPT: () => IS_SUPERSCRIPT,
7816    IS_UNDERLINE: () => IS_UNDERLINE,
7817    KEY_ARROW_DOWN_COMMAND: () => KEY_ARROW_DOWN_COMMAND,
7818    KEY_ARROW_LEFT_COMMAND: () => KEY_ARROW_LEFT_COMMAND,
7819    KEY_ARROW_RIGHT_COMMAND: () => KEY_ARROW_RIGHT_COMMAND,
7820    KEY_ARROW_UP_COMMAND: () => KEY_ARROW_UP_COMMAND,
7821    KEY_BACKSPACE_COMMAND: () => KEY_BACKSPACE_COMMAND,
7822    KEY_DELETE_COMMAND: () => KEY_DELETE_COMMAND,
7823    KEY_DOWN_COMMAND: () => KEY_DOWN_COMMAND,
7824    KEY_ENTER_COMMAND: () => KEY_ENTER_COMMAND,
7825    KEY_ESCAPE_COMMAND: () => KEY_ESCAPE_COMMAND,
7826    KEY_MODIFIER_COMMAND: () => KEY_MODIFIER_COMMAND,
7827    KEY_SPACE_COMMAND: () => KEY_SPACE_COMMAND,
7828    KEY_TAB_COMMAND: () => KEY_TAB_COMMAND,
7829    LineBreakNode: () => LineBreakNode,
7830    MOVE_TO_END: () => MOVE_TO_END,
7831    MOVE_TO_START: () => MOVE_TO_START,
7832    NODE_STATE_KEY: () => NODE_STATE_KEY,
7833    OUTDENT_CONTENT_COMMAND: () => OUTDENT_CONTENT_COMMAND,
7834    PASTE_COMMAND: () => PASTE_COMMAND,
7835    PASTE_TAG: () => PASTE_TAG,
7836    ParagraphNode: () => ParagraphNode,
7837    REDO_COMMAND: () => REDO_COMMAND,
7838    REMOVE_TEXT_COMMAND: () => REMOVE_TEXT_COMMAND,
7839    RootNode: () => RootNode,
7840    SELECTION_CHANGE_COMMAND: () => SELECTION_CHANGE_COMMAND,
7841    SELECTION_INSERT_CLIPBOARD_NODES_COMMAND: () => SELECTION_INSERT_CLIPBOARD_NODES_COMMAND,
7842    SELECT_ALL_COMMAND: () => SELECT_ALL_COMMAND,
7843    SKIP_COLLAB_TAG: () => SKIP_COLLAB_TAG,
7844    SKIP_DOM_SELECTION_TAG: () => SKIP_DOM_SELECTION_TAG,
7845    SKIP_SCROLL_INTO_VIEW_TAG: () => SKIP_SCROLL_INTO_VIEW_TAG,
7846    SKIP_SELECTION_FOCUS_TAG: () => SKIP_SELECTION_FOCUS_TAG,
7847    TEXT_TYPE_TO_FORMAT: () => TEXT_TYPE_TO_FORMAT,
7848    TabNode: () => TabNode,
7849    TextNode: () => TextNode,
7850    UNDO_COMMAND: () => UNDO_COMMAND,
7851    addClassNamesToElement: () => addClassNamesToElement,
7852    buildImportMap: () => buildImportMap,
7853    configExtension: () => configExtension,
7854    createCommand: () => createCommand,
7855    createEditor: () => createEditor,
7856    createSharedNodeState: () => createSharedNodeState,
7857    createState: () => createState,
7858    declarePeerDependency: () => declarePeerDependency,
7859    defineExtension: () => defineExtension,
7860    flipDirection: () => flipDirection,
7861    getDOMOwnerDocument: () => getDOMOwnerDocument,
7862    getDOMSelection: () => getDOMSelection,
7863    getDOMSelectionFromTarget: () => getDOMSelectionFromTarget,
7864    getDOMTextNode: () => getDOMTextNode,
7865    getEditorPropertyFromDOMNode: () => getEditorPropertyFromDOMNode,
7866    getNearestEditorFromDOMNode: () => getNearestEditorFromDOMNode,
7867    getRegisteredNode: () => getRegisteredNode,
7868    getRegisteredNodeOrThrow: () => getRegisteredNodeOrThrow,
7869    getStaticNodeConfig: () => getStaticNodeConfig,
7870    getStyleObjectFromCSS: () => getStyleObjectFromCSS,
7871    getTextDirection: () => getTextDirection,
7872    getTransformSetFromKlass: () => getTransformSetFromKlass,
7873    isBlockDomNode: () => isBlockDomNode,
7874    isCurrentlyReadOnlyMode: () => isCurrentlyReadOnlyMode,
7875    isDOMDocumentNode: () => isDOMDocumentNode,
7876    isDOMNode: () => isDOMNode,
7877    isDOMTextNode: () => isDOMTextNode,
7878    isDOMUnmanaged: () => isDOMUnmanaged,
7879    isDocumentFragment: () => isDocumentFragment,
7880    isExactShortcutMatch: () => isExactShortcutMatch,
7881    isHTMLAnchorElement: () => isHTMLAnchorElement,
7882    isHTMLElement: () => isHTMLElement,
7883    isInlineDomNode: () => isInlineDomNode,
7884    isLexicalEditor: () => isLexicalEditor,
7885    isModifierMatch: () => isModifierMatch,
7886    isSelectionCapturedInDecoratorInput: () => isSelectionCapturedInDecoratorInput,
7887    isSelectionWithinEditor: () => isSelectionWithinEditor,
7888    makeStepwiseIterator: () => makeStepwiseIterator,
7889    mergeRegister: () => mergeRegister,
7890    normalizeClassNames: () => normalizeClassNames,
7891    removeClassNamesFromElement: () => removeClassNamesFromElement,
7892    removeFromParent: () => removeFromParent,
7893    resetRandomKey: () => resetRandomKey,
7894    safeCast: () => safeCast,
7895    setDOMStyleFromCSS: () => setDOMStyleFromCSS,
7896    setDOMStyleObject: () => setDOMStyleObject,
7897    setDOMUnmanaged: () => setDOMUnmanaged,
7898    setNodeIndentFromDOM: () => setNodeIndentFromDOM,
7899    shallowMergeConfig: () => shallowMergeConfig,
7900    toggleTextFormatType: () => toggleTextFormatType
7901  });
7902  function formatDevErrorMessage(message) {
7903    throw new Error(message);
7904  }
7905  var CAN_USE_DOM = typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.document.createElement !== "undefined";
7906  var documentMode = CAN_USE_DOM && "documentMode" in document ? document.documentMode : null;
7907  var IS_APPLE = CAN_USE_DOM && /Mac|iPod|iPhone|iPad/.test(navigator.platform);
7908  var IS_FIREFOX = CAN_USE_DOM && /^(?!.*Seamonkey)(?=.*Firefox).*/i.test(navigator.userAgent);
7909  var CAN_USE_BEFORE_INPUT = CAN_USE_DOM && "InputEvent" in window && !documentMode ? "getTargetRanges" in new window.InputEvent("input") : false;
7910  var IS_IOS = CAN_USE_DOM && /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
7911  var IS_ANDROID = CAN_USE_DOM && /Android/.test(navigator.userAgent);
7912  var IS_SAFARI = CAN_USE_DOM && /Version\/[\d.]+.*Safari/.test(navigator.userAgent) && !IS_ANDROID;
7913  var IS_CHROME = CAN_USE_DOM && /^(?=.*Chrome).*/i.test(navigator.userAgent);
7914  var IS_ANDROID_CHROME = CAN_USE_DOM && IS_ANDROID && IS_CHROME;
7915  var IS_APPLE_WEBKIT = CAN_USE_DOM && /AppleWebKit\/[\d.]+/.test(navigator.userAgent) && IS_APPLE && !IS_CHROME;
7916  var DOM_ELEMENT_TYPE = 1;
7917  var DOM_TEXT_TYPE = 3;
7918  var DOM_DOCUMENT_TYPE = 9;
7919  var DOM_DOCUMENT_FRAGMENT_TYPE = 11;
7920  var NO_DIRTY_NODES = 0;
7921  var HAS_DIRTY_NODES = 1;
7922  var FULL_RECONCILE = 2;
7923  var IS_NORMAL = 0;
7924  var IS_TOKEN = 1;
7925  var IS_SEGMENTED = 2;
7926  var IS_BOLD = 1;
7927  var IS_ITALIC = 1 << 1;
7928  var IS_STRIKETHROUGH = 1 << 2;
7929  var IS_UNDERLINE = 1 << 3;
7930  var IS_CODE = 1 << 4;
7931  var IS_SUBSCRIPT = 1 << 5;
7932  var IS_SUPERSCRIPT = 1 << 6;
7933  var IS_HIGHLIGHT = 1 << 7;
7934  var IS_LOWERCASE = 1 << 8;
7935  var IS_UPPERCASE = 1 << 9;
7936  var IS_CAPITALIZE = 1 << 10;
7937  var IS_ALL_FORMATTING = IS_BOLD | IS_ITALIC | IS_STRIKETHROUGH | IS_UNDERLINE | IS_CODE | IS_SUBSCRIPT | IS_SUPERSCRIPT | IS_HIGHLIGHT | IS_LOWERCASE | IS_UPPERCASE | IS_CAPITALIZE;
7938  var IS_DIRECTIONLESS = 1;
7939  var IS_UNMERGEABLE = 1 << 1;
7940  var IS_ALIGN_LEFT = 1;
7941  var IS_ALIGN_CENTER = 2;
7942  var IS_ALIGN_RIGHT = 3;
7943  var IS_ALIGN_JUSTIFY = 4;
7944  var IS_ALIGN_START = 5;
7945  var IS_ALIGN_END = 6;
7946  var NON_BREAKING_SPACE = "\xA0";
7947  var ZERO_WIDTH_SPACE = "\u200B";
7948  var COMPOSITION_SUFFIX = IS_SAFARI || IS_IOS || IS_APPLE_WEBKIT ? NON_BREAKING_SPACE : ZERO_WIDTH_SPACE;
7949  var DOUBLE_LINE_BREAK = "\n\n";
7950  var COMPOSITION_START_CHAR = IS_FIREFOX ? NON_BREAKING_SPACE : COMPOSITION_SUFFIX;
7951  var RTL = "\u0591-\u07FF\uFB1D-\uFDFD\uFE70-\uFEFC";
7952  var LTR = "A-Za-z\xC0-\xD6\xD8-\xF6\xF8-\u02B8\u0300-\u0590\u0800-\u1FFF\u200E\u2C00-\uFB1C\uFE00-\uFE6F\uFEFD-\uFFFF";
7953  var RTL_REGEX = new RegExp("^[^" + LTR + "]*[" + RTL + "]");
7954  var LTR_REGEX = new RegExp("^[^" + RTL + "]*[" + LTR + "]");
7955  var TEXT_TYPE_TO_FORMAT = {
7956    bold: IS_BOLD,
7957    capitalize: IS_CAPITALIZE,
7958    code: IS_CODE,
7959    highlight: IS_HIGHLIGHT,
7960    italic: IS_ITALIC,
7961    lowercase: IS_LOWERCASE,
7962    strikethrough: IS_STRIKETHROUGH,
7963    subscript: IS_SUBSCRIPT,
7964    superscript: IS_SUPERSCRIPT,
7965    underline: IS_UNDERLINE,
7966    uppercase: IS_UPPERCASE
7967  };
7968  var DETAIL_TYPE_TO_DETAIL = {
7969    directionless: IS_DIRECTIONLESS,
7970    unmergeable: IS_UNMERGEABLE
7971  };
7972  var ELEMENT_TYPE_TO_FORMAT = {
7973    center: IS_ALIGN_CENTER,
7974    end: IS_ALIGN_END,
7975    justify: IS_ALIGN_JUSTIFY,
7976    left: IS_ALIGN_LEFT,
7977    right: IS_ALIGN_RIGHT,
7978    start: IS_ALIGN_START
7979  };
7980  var ELEMENT_FORMAT_TO_TYPE = {
7981    [IS_ALIGN_CENTER]: "center",
7982    [IS_ALIGN_END]: "end",
7983    [IS_ALIGN_JUSTIFY]: "justify",
7984    [IS_ALIGN_LEFT]: "left",
7985    [IS_ALIGN_RIGHT]: "right",
7986    [IS_ALIGN_START]: "start"
7987  };
7988  var TEXT_MODE_TO_TYPE = {
7989    normal: IS_NORMAL,
7990    segmented: IS_SEGMENTED,
7991    token: IS_TOKEN
7992  };
7993  var TEXT_TYPE_TO_MODE = {
7994    [IS_NORMAL]: "normal",
7995    [IS_SEGMENTED]: "segmented",
7996    [IS_TOKEN]: "token"
7997  };
7998  var NODE_STATE_KEY = "$";
7999  var PROTOTYPE_CONFIG_METHOD = "$config";
8000  var DequeSet = class {
8001    _front = /* @__PURE__ */ new Set();
8002    _back = /* @__PURE__ */ new Set();
8003    _cache;
8004    get size() {
8005      return this._front.size + this._back.size;
8006    }
8007    addBack(v3) {
8008      delete this._cache;
8009      if (!this._front.has(v3)) {
8010        this._back.add(v3);
8011      }
8012      return this;
8013    }
8014    addFront(v3) {
8015      delete this._cache;
8016      if (!this._back.has(v3)) {
8017        this._front.add(v3);
8018      }
8019      return this;
8020    }
8021    delete(v3) {
8022      delete this._cache;
8023      return this._front.delete(v3) || this._back.delete(v3);
8024    }
8025    toArray() {
8026      const arr = Array.from(this._front).reverse();
8027      for (const v3 of this._back) {
8028        arr.push(v3);
8029      }
8030      return arr;
8031    }
8032    toReadonlyArray() {
8033      this._cache = this._cache || this.toArray();
8034      return this._cache;
8035    }
8036    [Symbol.iterator]() {
8037      return this.toReadonlyArray()[Symbol.iterator]();
8038    }
8039  };
8040  function $garbageCollectDetachedDecorators(editor, pendingEditorState) {
8041    const currentDecorators = editor._decorators;
8042    const pendingDecorators = editor._pendingDecorators;
8043    let decorators = pendingDecorators || currentDecorators;
8044    const nodeMap = pendingEditorState._nodeMap;
8045    let key;
8046    for (key in decorators) {
8047      if (!nodeMap.has(key)) {
8048        if (decorators === currentDecorators) {
8049          decorators = cloneDecorators(editor);
8050        }
8051        delete decorators[key];
8052      }
8053    }
8054  }
8055  function $garbageCollectDetachedDeepChildNodes(node, parentKey, prevNodeMap, nodeMap, nodeMapDelete, dirtyNodes) {
8056    let child = node.getFirstChild();
8057    while (child !== null) {
8058      const childKey = child.__key;
8059      if (child.__parent === parentKey) {
8060        if ($isElementNode(child)) {
8061          $garbageCollectDetachedDeepChildNodes(child, childKey, prevNodeMap, nodeMap, nodeMapDelete, dirtyNodes);
8062        }
8063        if (!prevNodeMap.has(childKey)) {
8064          dirtyNodes.delete(childKey);
8065        }
8066        nodeMapDelete.push(childKey);
8067      }
8068      child = child.getNextSibling();
8069    }
8070  }
8071  function $garbageCollectDetachedNodes(prevEditorState, editorState, dirtyLeaves, dirtyElements) {
8072    const prevNodeMap = prevEditorState._nodeMap;
8073    const nodeMap = editorState._nodeMap;
8074    const nodeMapDelete = [];
8075    for (const [nodeKey] of dirtyElements) {
8076      const node = nodeMap.get(nodeKey);
8077      if (node !== void 0) {
8078        if (!node.isAttached()) {
8079          if ($isElementNode(node)) {
8080            $garbageCollectDetachedDeepChildNodes(node, nodeKey, prevNodeMap, nodeMap, nodeMapDelete, dirtyElements);
8081          }
8082          if (!prevNodeMap.has(nodeKey)) {
8083            dirtyElements.delete(nodeKey);
8084          }
8085          nodeMapDelete.push(nodeKey);
8086        }
8087      }
8088    }
8089    for (const nodeKey of nodeMapDelete) {
8090      nodeMap.delete(nodeKey);
8091    }
8092    for (const nodeKey of dirtyLeaves) {
8093      const node = nodeMap.get(nodeKey);
8094      if (node !== void 0 && !node.isAttached()) {
8095        if (!prevNodeMap.has(nodeKey)) {
8096          dirtyLeaves.delete(nodeKey);
8097        }
8098        nodeMap.delete(nodeKey);
8099      }
8100    }
8101  }
8102  var TEXT_MUTATION_VARIANCE = 100;
8103  var isProcessingMutations = false;
8104  var lastTextEntryTimeStamp = 0;
8105  function getIsProcessingMutations() {
8106    return isProcessingMutations;
8107  }
8108  function updateTimeStamp(event) {
8109    lastTextEntryTimeStamp = event.timeStamp;
8110  }
8111  function initTextEntryListener(editor) {
8112    if (lastTextEntryTimeStamp === 0) {
8113      getWindow(editor).addEventListener("textInput", updateTimeStamp, true);
8114    }
8115  }
8116  function isManagedLineBreak(dom, target, editor) {
8117    const isBR = dom.nodeName === "BR";
8118    const lexicalLineBreak = target.__lexicalLineBreak;
8119    return lexicalLineBreak && (dom === lexicalLineBreak || isBR && dom.previousSibling === lexicalLineBreak) || isBR && getNodeKeyFromDOMNode(dom, editor) !== void 0;
8120  }
8121  function getLastSelection(editor) {
8122    return editor.getEditorState().read(() => {
8123      const selection = $getSelection();
8124      return selection !== null ? selection.clone() : null;
8125    });
8126  }
8127  function $handleTextMutation(target, node, editor) {
8128    const domSelection = getDOMSelection(getWindow(editor));
8129    let anchorOffset = null;
8130    let focusOffset = null;
8131    if (domSelection !== null && domSelection.anchorNode === target) {
8132      anchorOffset = domSelection.anchorOffset;
8133      focusOffset = domSelection.focusOffset;
8134    }
8135    const text2 = target.nodeValue;
8136    if (text2 !== null) {
8137      $updateTextNodeFromDOMContent(node, text2, anchorOffset, focusOffset, false);
8138    }
8139  }
8140  function shouldUpdateTextNodeFromMutation(selection, targetDOM, targetNode) {
8141    if ($isRangeSelection(selection)) {
8142      const anchorNode = selection.anchor.getNode();
8143      if (anchorNode.is(targetNode) && selection.format !== anchorNode.getFormat()) {
8144        return false;
8145      }
8146    }
8147    return isDOMTextNode(targetDOM) && targetNode.isAttached();
8148  }
8149  function $getNearestManagedNodePairFromDOMNode(startingDOM, editor, editorState, rootElement) {
8150    for (let dom = startingDOM; dom && !isDOMUnmanaged(dom); dom = getParentElement(dom)) {
8151      const key = getNodeKeyFromDOMNode(dom, editor);
8152      if (key !== void 0) {
8153        const node = $getNodeByKey(key, editorState);
8154        if (node) {
8155          return $isDecoratorNode(node) || !isHTMLElement(dom) ? void 0 : [dom, node];
8156        }
8157      } else if (dom === rootElement) {
8158        return [rootElement, internalGetRoot(editorState)];
8159      }
8160    }
8161  }
8162  function flushMutations(editor, mutations, observer) {
8163    isProcessingMutations = true;
8164    const shouldFlushTextMutations = performance.now() - lastTextEntryTimeStamp > TEXT_MUTATION_VARIANCE;
8165    try {
8166      updateEditorSync(editor, () => {
8167        const selection = $getSelection() || getLastSelection(editor);
8168        const badDOMTargets = /* @__PURE__ */ new Map();
8169        const rootElement = editor.getRootElement();
8170        const currentEditorState = editor._editorState;
8171        const blockCursorElement = editor._blockCursorElement;
8172        let shouldRevertSelection = false;
8173        let possibleTextForFirefoxPaste = "";
8174        for (let i2 = 0; i2 < mutations.length; i2++) {
8175          const mutation = mutations[i2];
8176          const type = mutation.type;
8177          const targetDOM = mutation.target;
8178          const pair = $getNearestManagedNodePairFromDOMNode(targetDOM, editor, currentEditorState, rootElement);
8179          if (!pair) {
8180            continue;
8181          }
8182          const [nodeDOM, targetNode] = pair;
8183          if (type === "characterData") {
8184            if (
8185              // TODO there is an edge case here if a mutation happens too quickly
8186              //      after text input, it may never be handled since we do not
8187              //      track the ignored mutations in any way
8188              shouldFlushTextMutations && $isTextNode(targetNode) && isDOMTextNode(targetDOM) && shouldUpdateTextNodeFromMutation(selection, targetDOM, targetNode)
8189            ) {
8190              $handleTextMutation(targetDOM, targetNode, editor);
8191            }
8192          } else if (type === "childList") {
8193            shouldRevertSelection = true;
8194            const addedDOMs = mutation.addedNodes;
8195            for (let s2 = 0; s2 < addedDOMs.length; s2++) {
8196              const addedDOM = addedDOMs[s2];
8197              const node = $getNodeFromDOMNode(addedDOM);
8198              const parentDOM = addedDOM.parentNode;
8199              if (parentDOM != null && addedDOM !== blockCursorElement && node === null && !isManagedLineBreak(addedDOM, parentDOM, editor)) {
8200                if (IS_FIREFOX) {
8201                  const possibleText = (isHTMLElement(addedDOM) ? addedDOM.innerText : null) || addedDOM.nodeValue;
8202                  if (possibleText) {
8203                    possibleTextForFirefoxPaste += possibleText;
8204                  }
8205                }
8206                parentDOM.removeChild(addedDOM);
8207              }
8208            }
8209            const removedDOMs = mutation.removedNodes;
8210            const removedDOMsLength = removedDOMs.length;
8211            if (removedDOMsLength > 0) {
8212              let unremovedBRs = 0;
8213              for (let s2 = 0; s2 < removedDOMsLength; s2++) {
8214                const removedDOM = removedDOMs[s2];
8215                if (isManagedLineBreak(removedDOM, targetDOM, editor) || blockCursorElement === removedDOM) {
8216                  targetDOM.appendChild(removedDOM);
8217                  unremovedBRs++;
8218                }
8219              }
8220              if (removedDOMsLength !== unremovedBRs) {
8221                badDOMTargets.set(nodeDOM, targetNode);
8222              }
8223            }
8224          }
8225        }
8226        if (badDOMTargets.size > 0) {
8227          for (const [nodeDOM, targetNode] of badDOMTargets) {
8228            targetNode.reconcileObservedMutation(nodeDOM, editor);
8229          }
8230        }
8231        const records = observer.takeRecords();
8232        if (records.length > 0) {
8233          for (let i2 = 0; i2 < records.length; i2++) {
8234            const record = records[i2];
8235            const addedNodes = record.addedNodes;
8236            const target = record.target;
8237            for (let s2 = 0; s2 < addedNodes.length; s2++) {
8238              const addedDOM = addedNodes[s2];
8239              const parentDOM = addedDOM.parentNode;
8240              if (parentDOM != null && addedDOM.nodeName === "BR" && !isManagedLineBreak(addedDOM, target, editor)) {
8241                parentDOM.removeChild(addedDOM);
8242              }
8243            }
8244          }
8245          observer.takeRecords();
8246        }
8247        if (selection !== null) {
8248          if (shouldRevertSelection) {
8249            $setSelection(selection);
8250          }
8251          if (IS_FIREFOX && isFirefoxClipboardEvents(editor)) {
8252            selection.insertRawText(possibleTextForFirefoxPaste);
8253          }
8254        }
8255      });
8256    } finally {
8257      isProcessingMutations = false;
8258    }
8259  }
8260  function flushRootMutations(editor) {
8261    const observer = editor._observer;
8262    if (observer !== null) {
8263      const mutations = observer.takeRecords();
8264      flushMutations(editor, mutations, observer);
8265    }
8266  }
8267  function initMutationObserver(editor) {
8268    initTextEntryListener(editor);
8269    editor._observer = new MutationObserver((mutations, observer) => {
8270      flushMutations(editor, mutations, observer);
8271    });
8272  }
8273  var StateConfig = class {
8274    /** The string key used when serializing this state to JSON */
8275    key;
8276    /** The parse function from the StateValueConfig passed to createState */
8277    parse;
8278    /**
8279     * The unparse function from the StateValueConfig passed to createState,
8280     * with a default that is simply a pass-through that assumes the value is
8281     * JSON serializable.
8282     */
8283    unparse;
8284    /**
8285     * An equality function from the StateValueConfig, with a default of
8286     * Object.is.
8287     */
8288    isEqual;
8289    /**
8290     * The result of `stateValueConfig.parse(undefined)`, which is computed only
8291     * once and used as the default value. When the current value `isEqual` to
8292     * the `defaultValue`, it will not be serialized to JSON.
8293     */
8294    defaultValue;
8295    resetOnCopyNode;
8296    constructor(key, stateValueConfig) {
8297      this.key = key;
8298      this.parse = stateValueConfig.parse.bind(stateValueConfig);
8299      this.unparse = (stateValueConfig.unparse || coerceToJSON).bind(stateValueConfig);
8300      this.isEqual = (stateValueConfig.isEqual || Object.is).bind(stateValueConfig);
8301      this.defaultValue = this.parse(void 0);
8302      this.resetOnCopyNode = stateValueConfig.resetOnCopyNode || false;
8303    }
8304  };
8305  // @__NO_SIDE_EFFECTS__
8306  function createState(key, valueConfig) {
8307    return new StateConfig(key, valueConfig);
8308  }
8309  function $getState(node, stateConfig, version = "latest") {
8310    const latestOrDirectNode = version === "latest" ? node.getLatest() : node;
8311    const state = latestOrDirectNode.__state;
8312    if (state) {
8313      $checkCollision(node, stateConfig, state);
8314      return state.getValue(stateConfig);
8315    }
8316    return stateConfig.defaultValue;
8317  }
8318  function $getStateChange(node, prevNode, stateConfig) {
8319    const value = $getState(node, stateConfig, "direct");
8320    const prevValue = $getState(prevNode, stateConfig, "direct");
8321    return stateConfig.isEqual(value, prevValue) ? null : [value, prevValue];
8322  }
8323  function $setState(node, stateConfig, valueOrUpdater) {
8324    errorOnReadOnly();
8325    let value;
8326    if (typeof valueOrUpdater === "function") {
8327      const latest = node.getLatest();
8328      const prevValue = $getState(latest, stateConfig);
8329      value = valueOrUpdater(prevValue);
8330      if (stateConfig.isEqual(prevValue, value)) {
8331        return latest;
8332      }
8333    } else {
8334      value = valueOrUpdater;
8335    }
8336    const writable = node.getWritable();
8337    const state = $getWritableNodeState(writable);
8338    $checkCollision(node, stateConfig, state);
8339    state.updateFromKnown(stateConfig, value);
8340    return writable;
8341  }
8342  function $checkCollision(node, stateConfig, state) {
8343    {
8344      const collision = state.sharedNodeState.sharedConfigMap.get(stateConfig.key);
8345      if (collision !== void 0 && collision !== stateConfig) {
8346        {
8347          formatDevErrorMessage(`$setState: State key collision ${JSON.stringify(stateConfig.key)} detected in ${node.constructor.name} node with type ${node.getType()} and key ${node.getKey()}. Only one StateConfig with a given key should be used on a node.`);
8348        }
8349      }
8350    }
8351  }
8352  function createSharedNodeState(nodeConfig) {
8353    const sharedConfigMap = /* @__PURE__ */ new Map();
8354    const flatKeys = /* @__PURE__ */ new Set();
8355    for (let klass = typeof nodeConfig === "function" ? nodeConfig : nodeConfig.replace; klass.prototype && klass.prototype.getType !== void 0; klass = Object.getPrototypeOf(klass)) {
8356      const {
8357        ownNodeConfig
8358      } = getStaticNodeConfig(klass);
8359      if (ownNodeConfig && ownNodeConfig.stateConfigs) {
8360        for (const requiredStateConfig of ownNodeConfig.stateConfigs) {
8361          let stateConfig;
8362          if ("stateConfig" in requiredStateConfig) {
8363            stateConfig = requiredStateConfig.stateConfig;
8364            if (requiredStateConfig.flat) {
8365              flatKeys.add(stateConfig.key);
8366            }
8367          } else {
8368            stateConfig = requiredStateConfig;
8369          }
8370          sharedConfigMap.set(stateConfig.key, stateConfig);
8371        }
8372      }
8373    }
8374    return {
8375      flatKeys,
8376      sharedConfigMap
8377    };
8378  }
8379  var NodeState = class _NodeState {
8380    /**
8381     * @internal
8382     *
8383     * Track the (versioned) node that this NodeState was created for, to
8384     * facilitate copy-on-write for NodeState. When a LexicalNode is cloned,
8385     * it will *reference* the NodeState from its prevNode. From the nextNode
8386     * you can continue to read state without copying, but the first $setState
8387     * will trigger a copy of the prevNode's NodeState with the node property
8388     * updated.
8389     */
8390    node;
8391    /**
8392     * @internal
8393     *
8394     * State that has already been parsed in a get state, so it is safe. (can be returned with
8395     * just a cast since the proof was given before).
8396     *
8397     * Note that it uses StateConfig, so in addition to (1) the CURRENT VALUE, it has access to
8398     * (2) the State key (3) the DEFAULT VALUE and (4) the PARSE FUNCTION
8399     */
8400    knownState;
8401    /**
8402     * @internal
8403     *
8404     * A copy of serializedNode[NODE_STATE_KEY] that is made when JSON is
8405     * imported but has not been parsed yet.
8406     *
8407     * It stays here until a get state requires us to parse it, and since we
8408     * then know the value is safe we move it to knownState.
8409     *
8410     * Note that since only string keys are used here, we can only allow this
8411     * state to pass-through on export or on the next version since there is
8412     * no known value configuration. This pass-through is to support scenarios
8413     * where multiple versions of the editor code are working in parallel so
8414     * an old version of your code doesnt erase metadata that was
8415     * set by a newer version of your code.
8416     */
8417    unknownState;
8418    /**
8419     * @internal
8420     *
8421     * This sharedNodeState is preserved across all instances of a given
8422     * node type in an editor and remains writable. It is how keys are resolved
8423     * to configuration.
8424     */
8425    sharedNodeState;
8426    /**
8427     * @internal
8428     *
8429     * The count of known or unknown keys in this state, ignoring the
8430     * intersection between the two sets.
8431     */
8432    size;
8433    /**
8434     * @internal
8435     */
8436    constructor(node, sharedNodeState, unknownState = void 0, knownState = /* @__PURE__ */ new Map(), size2 = void 0) {
8437      this.node = node;
8438      this.sharedNodeState = sharedNodeState;
8439      this.unknownState = unknownState;
8440      this.knownState = knownState;
8441      const {
8442        sharedConfigMap
8443      } = this.sharedNodeState;
8444      const computedSize = size2 !== void 0 ? size2 : computeSize(sharedConfigMap, unknownState, knownState);
8445      {
8446        if (!(size2 === void 0 || computedSize === size2)) {
8447          formatDevErrorMessage(`NodeState: size != computedSize (${String(size2)} != ${String(computedSize)})`);
8448        }
8449        for (const stateConfig of knownState.keys()) {
8450          if (!sharedConfigMap.has(stateConfig.key)) {
8451            formatDevErrorMessage(`NodeState: sharedConfigMap missing knownState key ${stateConfig.key}`);
8452          }
8453        }
8454      }
8455      this.size = computedSize;
8456    }
8457    /**
8458     * @internal
8459     *
8460     * Get the value from knownState, or parse it from unknownState
8461     * if it contains the given key.
8462     *
8463     * Updates the sharedConfigMap when no known state is found.
8464     * Updates unknownState and knownState when an unknownState is parsed.
8465     */
8466    getValue(stateConfig) {
8467      const known = this.knownState.get(stateConfig);
8468      if (known !== void 0) {
8469        return known;
8470      }
8471      this.sharedNodeState.sharedConfigMap.set(stateConfig.key, stateConfig);
8472      let parsed = stateConfig.defaultValue;
8473      if (this.unknownState && stateConfig.key in this.unknownState) {
8474        const jsonValue = this.unknownState[stateConfig.key];
8475        if (jsonValue !== void 0) {
8476          parsed = stateConfig.parse(jsonValue);
8477        }
8478        this.updateFromKnown(stateConfig, parsed);
8479      }
8480      return parsed;
8481    }
8482    /**
8483     * @internal
8484     *
8485     * Used only for advanced use cases, such as collab. The intent here is to
8486     * allow you to diff states with a more stable interface than the properties
8487     * of this class.
8488     */
8489    getInternalState() {
8490      return [this.unknownState, this.knownState];
8491    }
8492    /**
8493     * Encode this NodeState to JSON in the format that its node expects.
8494     * This returns `{[NODE_STATE_KEY]?: UnknownStateRecord}` rather than
8495     * `UnknownStateRecord | undefined` so that we can support flattening
8496     * specific entries in the future when nodes can declare what
8497     * their required StateConfigs are.
8498     */
8499    toJSON() {
8500      const state = {
8501        ...this.unknownState
8502      };
8503      const flatState = {};
8504      for (const [stateConfig, v3] of this.knownState) {
8505        if (stateConfig.isEqual(v3, stateConfig.defaultValue)) {
8506          delete state[stateConfig.key];
8507        } else {
8508          state[stateConfig.key] = stateConfig.unparse(v3);
8509        }
8510      }
8511      for (const key of this.sharedNodeState.flatKeys) {
8512        if (key in state) {
8513          flatState[key] = state[key];
8514          delete state[key];
8515        }
8516      }
8517      if (undefinedIfEmpty(state)) {
8518        flatState[NODE_STATE_KEY] = state;
8519      }
8520      return flatState;
8521    }
8522    /**
8523     * @internal
8524     *
8525     * A NodeState is writable when the node to update matches
8526     * the node associated with the NodeState. This basically
8527     * mirrors how the EditorState NodeMap works, but in a
8528     * bottom-up organization rather than a top-down organization.
8529     *
8530     * This allows us to implement the same "copy on write"
8531     * pattern for state, without having the state version
8532     * update every time the node version changes (e.g. when
8533     * its parent or siblings change).
8534     *
8535     * @param node The node to associate with the state
8536     * @returns The next writable state
8537     */
8538    getWritable(node) {
8539      if (this.node === node) {
8540        return this;
8541      }
8542      const {
8543        sharedNodeState,
8544        unknownState
8545      } = this;
8546      const nextKnownState = new Map(this.knownState);
8547      return new _NodeState(node, sharedNodeState, parseAndPruneNextUnknownState(sharedNodeState.sharedConfigMap, nextKnownState, unknownState), nextKnownState, this.size);
8548    }
8549    /** @internal */
8550    resetOnCopyNode() {
8551      for (const stateConfig of this.knownState.keys()) {
8552        if (stateConfig.resetOnCopyNode) {
8553          this.knownState.set(stateConfig, stateConfig.defaultValue);
8554        }
8555      }
8556      return this;
8557    }
8558    /** @internal */
8559    updateFromKnown(stateConfig, value) {
8560      const key = stateConfig.key;
8561      this.sharedNodeState.sharedConfigMap.set(key, stateConfig);
8562      const {
8563        knownState,
8564        unknownState
8565      } = this;
8566      if (!(knownState.has(stateConfig) || unknownState && key in unknownState)) {
8567        if (unknownState) {
8568          delete unknownState[key];
8569          this.unknownState = undefinedIfEmpty(unknownState);
8570        }
8571        this.size++;
8572      }
8573      knownState.set(stateConfig, value);
8574    }
8575    /**
8576     * @internal
8577     *
8578     * This is intended for advanced use cases only, such
8579     * as collab or dev tools.
8580     *
8581     * Update a single key value pair from unknown state,
8582     * parsing it if the key is known to this node. This is
8583     * basically like updateFromJSON, but the effect is
8584     * isolated to a single entry.
8585     *
8586     * @param k The string key from an UnknownStateRecord
8587     * @param v The unknown value from an UnknownStateRecord
8588     */
8589    updateFromUnknown(k2, v3) {
8590      const stateConfig = this.sharedNodeState.sharedConfigMap.get(k2);
8591      if (stateConfig) {
8592        this.updateFromKnown(stateConfig, stateConfig.parse(v3));
8593      } else {
8594        this.unknownState = this.unknownState || {};
8595        if (!(k2 in this.unknownState)) {
8596          this.size++;
8597        }
8598        this.unknownState[k2] = v3;
8599      }
8600    }
8601    /**
8602     * @internal
8603     *
8604     * Reset all existing state to default or empty values,
8605     * and perform any updates from the given unknownState.
8606     *
8607     * This is used when initializing a node's state from JSON,
8608     * or when resetting a node's state from JSON.
8609     *
8610     * @param unknownState The new state in serialized form
8611     */
8612    updateFromJSON(unknownState) {
8613      const {
8614        knownState
8615      } = this;
8616      for (const stateConfig of knownState.keys()) {
8617        knownState.set(stateConfig, stateConfig.defaultValue);
8618      }
8619      this.size = knownState.size;
8620      this.unknownState = void 0;
8621      if (unknownState) {
8622        for (const [k2, v3] of Object.entries(unknownState)) {
8623          this.updateFromUnknown(k2, v3);
8624        }
8625      }
8626    }
8627  };
8628  function $getWritableNodeState(node) {
8629    const writable = node.getWritable();
8630    const state = writable.__state ? writable.__state.getWritable(writable) : new NodeState(writable, $getSharedNodeState(writable));
8631    writable.__state = state;
8632    return state;
8633  }
8634  function $getSharedNodeState(node) {
8635    return node.__state ? node.__state.sharedNodeState : getRegisteredNodeOrThrow($getEditor(), node.getType()).sharedNodeState;
8636  }
8637  function $updateStateFromJSON(node, serialized) {
8638    const writable = node.getWritable();
8639    const unknownState = serialized[NODE_STATE_KEY];
8640    let parseState = unknownState;
8641    for (const k2 of $getSharedNodeState(writable).flatKeys) {
8642      if (k2 in serialized) {
8643        if (parseState === void 0 || parseState === unknownState) {
8644          parseState = {
8645            ...unknownState
8646          };
8647        }
8648        parseState[k2] = serialized[k2];
8649      }
8650    }
8651    if (writable.__state || parseState) {
8652      $getWritableNodeState(node).updateFromJSON(parseState);
8653    }
8654    return writable;
8655  }
8656  function nodeStatesAreEquivalent(a2, b3) {
8657    if (a2 === b3) {
8658      return true;
8659    }
8660    const keys = /* @__PURE__ */ new Set();
8661    return !(a2 && hasUnequalMapEntry(keys, a2, b3) || b3 && hasUnequalMapEntry(keys, b3, a2) || a2 && hasUnequalRecordEntry(keys, a2, b3) || b3 && hasUnequalRecordEntry(keys, b3, a2));
8662  }
8663  function computeSize(sharedConfigMap, unknownState, knownState) {
8664    let size2 = knownState.size;
8665    if (unknownState) {
8666      for (const k2 in unknownState) {
8667        const sharedConfig = sharedConfigMap.get(k2);
8668        if (!sharedConfig || !knownState.has(sharedConfig)) {
8669          size2++;
8670        }
8671      }
8672    }
8673    return size2;
8674  }
8675  function undefinedIfEmpty(obj) {
8676    if (obj) {
8677      for (const key in obj) {
8678        return obj;
8679      }
8680    }
8681    return void 0;
8682  }
8683  function coerceToJSON(v3) {
8684    return v3;
8685  }
8686  function parseAndPruneNextUnknownState(sharedConfigMap, nextKnownState, unknownState) {
8687    let nextUnknownState = void 0;
8688    if (unknownState) {
8689      for (const [k2, v3] of Object.entries(unknownState)) {
8690        const stateConfig = sharedConfigMap.get(k2);
8691        if (stateConfig) {
8692          if (!nextKnownState.has(stateConfig)) {
8693            nextKnownState.set(stateConfig, stateConfig.parse(v3));
8694          }
8695        } else {
8696          nextUnknownState = nextUnknownState || {};
8697          nextUnknownState[k2] = v3;
8698        }
8699      }
8700    }
8701    return nextUnknownState;
8702  }
8703  function hasUnequalMapEntry(keys, sourceState, otherState) {
8704    for (const [stateConfig, value] of sourceState.knownState) {
8705      if (keys.has(stateConfig.key)) {
8706        continue;
8707      }
8708      keys.add(stateConfig.key);
8709      const otherValue = otherState ? otherState.getValue(stateConfig) : stateConfig.defaultValue;
8710      if (otherValue !== value && !stateConfig.isEqual(otherValue, value)) {
8711        return true;
8712      }
8713    }
8714    return false;
8715  }
8716  function hasUnequalRecordEntry(keys, sourceState, otherState) {
8717    const {
8718      unknownState
8719    } = sourceState;
8720    const otherUnknownState = otherState ? otherState.unknownState : void 0;
8721    if (unknownState) {
8722      for (const [key, value] of Object.entries(unknownState)) {
8723        if (keys.has(key)) {
8724          continue;
8725        }
8726        keys.add(key);
8727        const otherValue = otherUnknownState ? otherUnknownState[key] : void 0;
8728        if (value !== otherValue) {
8729          return true;
8730        }
8731      }
8732    }
8733    return false;
8734  }
8735  function $cloneNodeState(from, to) {
8736    const state = from.__state;
8737    return state && state.node === from ? state.getWritable(to) : state;
8738  }
8739  function $canSimpleTextNodesBeMerged(node1, node2) {
8740    const node1Mode = node1.__mode;
8741    const node1Format = node1.__format;
8742    const node1Style = node1.__style;
8743    const node2Mode = node2.__mode;
8744    const node2Format = node2.__format;
8745    const node2Style = node2.__style;
8746    const node1State = node1.__state;
8747    const node2State = node2.__state;
8748    return (node1Mode === null || node1Mode === node2Mode) && (node1Format === null || node1Format === node2Format) && (node1Style === null || node1Style === node2Style) && (node1.__state === null || node1State === node2State || nodeStatesAreEquivalent(node1State, node2State));
8749  }
8750  function $mergeTextNodes(node1, node2) {
8751    const writableNode1 = node1.mergeWithSibling(node2);
8752    const normalizedNodes = getActiveEditor()._normalizedNodes;
8753    normalizedNodes.add(node1.__key);
8754    normalizedNodes.add(node2.__key);
8755    return writableNode1;
8756  }
8757  function $normalizeTextNode(textNode) {
8758    let node = textNode;
8759    if (node.__text === "" && node.isSimpleText() && !node.isUnmergeable()) {
8760      node.remove();
8761      return;
8762    }
8763    let previousNode;
8764    while ((previousNode = node.getPreviousSibling()) !== null && $isTextNode(previousNode) && previousNode.isSimpleText() && !previousNode.isUnmergeable()) {
8765      if (previousNode.__text === "") {
8766        previousNode.remove();
8767      } else if ($canSimpleTextNodesBeMerged(previousNode, node)) {
8768        node = $mergeTextNodes(previousNode, node);
8769        break;
8770      } else {
8771        break;
8772      }
8773    }
8774    let nextNode;
8775    while ((nextNode = node.getNextSibling()) !== null && $isTextNode(nextNode) && nextNode.isSimpleText() && !nextNode.isUnmergeable()) {
8776      if (nextNode.__text === "") {
8777        nextNode.remove();
8778      } else if ($canSimpleTextNodesBeMerged(node, nextNode)) {
8779        node = $mergeTextNodes(node, nextNode);
8780        break;
8781      } else {
8782        break;
8783      }
8784    }
8785  }
8786  function $normalizeSelection(selection) {
8787    $normalizePoint(selection.anchor);
8788    $normalizePoint(selection.focus);
8789    return selection;
8790  }
8791  function $normalizePoint(point) {
8792    while (point.type === "element") {
8793      const node = point.getNode();
8794      const offset3 = point.offset;
8795      let nextNode;
8796      let nextOffsetAtEnd;
8797      if (offset3 === node.getChildrenSize()) {
8798        nextNode = node.getChildAtIndex(offset3 - 1);
8799        nextOffsetAtEnd = true;
8800      } else {
8801        nextNode = node.getChildAtIndex(offset3);
8802        nextOffsetAtEnd = false;
8803      }
8804      if ($isTextNode(nextNode)) {
8805        point.set(nextNode.__key, nextOffsetAtEnd ? nextNode.getTextContentSize() : 0, "text", true);
8806        break;
8807      } else if (!$isElementNode(nextNode)) {
8808        break;
8809      }
8810      point.set(nextNode.__key, nextOffsetAtEnd ? nextNode.getChildrenSize() : 0, "element", true);
8811    }
8812  }
8813  var subTreeTextContent = "";
8814  var subTreeTextFormat = null;
8815  var subTreeTextStyle = null;
8816  var activeEditorConfig;
8817  var activeEditor$1;
8818  var activeEditorNodes;
8819  var treatAllNodesAsDirty = false;
8820  var activeEditorStateReadOnly = false;
8821  var activeMutationListeners;
8822  var activeDirtyElements;
8823  var activeDirtyLeaves;
8824  var activePrevNodeMap;
8825  var activeNextNodeMap;
8826  var activePrevKeyToDOMMap;
8827  var mutatedNodes;
8828  var activeEditorDOMRenderConfig;
8829  function $destroyNode(key, parentDOM) {
8830    const node = activePrevNodeMap.get(key);
8831    if (parentDOM !== null) {
8832      const dom = getPrevElementByKeyOrThrow(key);
8833      if (dom.parentNode === parentDOM) {
8834        parentDOM.removeChild(dom);
8835      }
8836    }
8837    if (!activeNextNodeMap.has(key)) {
8838      activeEditor$1._keyToDOMMap.delete(key);
8839    }
8840    if ($isElementNode(node)) {
8841      const children = $createChildrenArray(node, activePrevNodeMap);
8842      $destroyChildren(children, 0, children.length - 1, null);
8843    }
8844    if (node !== void 0) {
8845      setMutatedNode(mutatedNodes, activeEditorNodes, activeMutationListeners, node, "destroyed");
8846    }
8847  }
8848  function $destroyChildren(children, _startIndex, endIndex, dom) {
8849    for (let startIndex = _startIndex; startIndex <= endIndex; ++startIndex) {
8850      const child = children[startIndex];
8851      if (child !== void 0) {
8852        $destroyNode(child, dom);
8853      }
8854    }
8855  }
8856  function setTextAlign(domStyle, value) {
8857    domStyle.setProperty("text-align", value);
8858  }
8859  var DEFAULT_INDENT_VALUE = "40px";
8860  function setElementIndent(dom, indent) {
8861    const indentClassName = activeEditorConfig.theme.indent;
8862    if (typeof indentClassName === "string") {
8863      const elementHasClassName = dom.classList.contains(indentClassName);
8864      if (indent > 0 && !elementHasClassName) {
8865        dom.classList.add(indentClassName);
8866      } else if (indent < 1 && elementHasClassName) {
8867        dom.classList.remove(indentClassName);
8868      }
8869    }
8870    if (indent === 0) {
8871      dom.style.setProperty("padding-inline-start", "");
8872      return;
8873    }
8874    const indentationBaseValue = getComputedStyle(activeEditor$1._rootElement || dom).getPropertyValue("--lexical-indent-base-value") || DEFAULT_INDENT_VALUE;
8875    dom.style.setProperty("padding-inline-start", `calc(${indent} * ${indentationBaseValue})`);
8876  }
8877  function setElementFormat(dom, format) {
8878    const domStyle = dom.style;
8879    if (format === 0) {
8880      setTextAlign(domStyle, "");
8881    } else if (format === IS_ALIGN_LEFT) {
8882      setTextAlign(domStyle, "left");
8883    } else if (format === IS_ALIGN_CENTER) {
8884      setTextAlign(domStyle, "center");
8885    } else if (format === IS_ALIGN_RIGHT) {
8886      setTextAlign(domStyle, "right");
8887    } else if (format === IS_ALIGN_JUSTIFY) {
8888      setTextAlign(domStyle, "justify");
8889    } else if (format === IS_ALIGN_START) {
8890      setTextAlign(domStyle, "start");
8891    } else if (format === IS_ALIGN_END) {
8892      setTextAlign(domStyle, "end");
8893    }
8894  }
8895  function $getReconciledDirection(node) {
8896    const direction = node.__dir;
8897    if (direction !== null) {
8898      return direction;
8899    }
8900    if ($isRootNode(node)) {
8901      return null;
8902    }
8903    const parent = node.getParentOrThrow();
8904    if (!$isRootNode(parent) || parent.__dir !== null) {
8905      return null;
8906    }
8907    return "auto";
8908  }
8909  function $setElementDirection(dom, node) {
8910    const direction = $getReconciledDirection(node);
8911    if (direction !== null) {
8912      dom.dir = direction;
8913    } else {
8914      dom.removeAttribute("dir");
8915    }
8916  }
8917  function $createNode(key, slot) {
8918    const node = activeNextNodeMap.get(key);
8919    if (node === void 0) {
8920      {
8921        formatDevErrorMessage(`createNode: node does not exist in nodeMap`);
8922      }
8923    }
8924    const dom = activeEditorDOMRenderConfig.$createDOM(node, activeEditor$1);
8925    storeDOMWithKey(key, dom, activeEditor$1);
8926    if ($isTextNode(node)) {
8927      dom.setAttribute("data-lexical-text", "true");
8928    } else if ($isDecoratorNode(node)) {
8929      dom.setAttribute("data-lexical-decorator", "true");
8930    }
8931    if ($isElementNode(node)) {
8932      const indent = node.__indent;
8933      const childrenSize = node.__size;
8934      $setElementDirection(dom, node);
8935      if (indent !== 0) {
8936        setElementIndent(dom, indent);
8937      }
8938      if (childrenSize !== 0) {
8939        const endIndex = childrenSize - 1;
8940        const children = $createChildrenArray(node, activeNextNodeMap);
8941        $createChildren(children, node, 0, endIndex, activeEditorDOMRenderConfig.$getDOMSlot(node, dom, activeEditor$1));
8942      }
8943      const format = node.__format;
8944      if (format !== 0) {
8945        setElementFormat(dom, format);
8946      }
8947      if (!node.isInline()) {
8948        $reconcileElementTerminatingLineBreak(null, node, dom);
8949      }
8950    } else {
8951      const text2 = node.getTextContent();
8952      if ($isDecoratorNode(node)) {
8953        const decorator = node.decorate(activeEditor$1, activeEditorConfig);
8954        if (decorator !== null) {
8955          reconcileDecorator(key, decorator);
8956        }
8957        dom.contentEditable = "false";
8958      }
8959      subTreeTextContent += text2;
8960    }
8961    if (slot !== null) {
8962      slot.insertChild(dom);
8963    }
8964    activeEditorDOMRenderConfig.$decorateDOM(node, null, dom, activeEditor$1);
8965    {
8966      Object.freeze(node);
8967    }
8968    setMutatedNode(mutatedNodes, activeEditorNodes, activeMutationListeners, node, "created");
8969    return dom;
8970  }
8971  function $createChildren(children, element, _startIndex, endIndex, slot) {
8972    const previousSubTreeTextContent = subTreeTextContent;
8973    subTreeTextContent = "";
8974    let startIndex = _startIndex;
8975    for (; startIndex <= endIndex; ++startIndex) {
8976      $createNode(children[startIndex], slot);
8977      const node = activeNextNodeMap.get(children[startIndex]);
8978      if (node !== null && $isTextNode(node)) {
8979        if (subTreeTextFormat === null) {
8980          subTreeTextFormat = node.getFormat();
8981          subTreeTextStyle = node.getStyle();
8982        }
8983      } else if (
8984        // inline $textContentRequiresDoubleLinebreakAtEnd
8985        $isElementNode(node) && startIndex < endIndex && !node.isInline()
8986      ) {
8987        subTreeTextContent += DOUBLE_LINE_BREAK;
8988      }
8989    }
8990    const dom = slot.element;
8991    dom.__lexicalTextContent = subTreeTextContent;
8992    subTreeTextContent = previousSubTreeTextContent + subTreeTextContent;
8993  }
8994  function isLastChildLineBreakOrDecorator(element, nodeMap) {
8995    if (element) {
8996      const lastKey = element.__last;
8997      if (lastKey) {
8998        const node = nodeMap.get(lastKey);
8999        if (node) {
9000          return $isLineBreakNode(node) ? "line-break" : $isDecoratorNode(node) && node.isInline() ? "decorator" : null;
9001        }
9002      }
9003      return "empty";
9004    }
9005    return null;
9006  }
9007  function $reconcileElementTerminatingLineBreak(prevElement, nextElement, dom) {
9008    const prevLineBreak = isLastChildLineBreakOrDecorator(prevElement, activePrevNodeMap);
9009    const nextLineBreak = isLastChildLineBreakOrDecorator(nextElement, activeNextNodeMap);
9010    if (prevLineBreak !== nextLineBreak) {
9011      activeEditorDOMRenderConfig.$getDOMSlot(nextElement, dom, activeEditor$1).setManagedLineBreak(nextLineBreak);
9012    }
9013  }
9014  function reconcileTextFormat(element) {
9015    if (subTreeTextFormat != null && subTreeTextFormat !== element.__textFormat && !activeEditorStateReadOnly) {
9016      element.setTextFormat(subTreeTextFormat);
9017    }
9018  }
9019  function reconcileTextStyle(element) {
9020    if (subTreeTextStyle != null && subTreeTextStyle !== element.__textStyle && !activeEditorStateReadOnly) {
9021      element.setTextStyle(subTreeTextStyle);
9022    }
9023  }
9024  function $reconcileChildrenWithDirection(prevElement, nextElement, dom) {
9025    subTreeTextFormat = null;
9026    subTreeTextStyle = null;
9027    $reconcileChildren(prevElement, nextElement, activeEditorDOMRenderConfig.$getDOMSlot(nextElement, dom, activeEditor$1));
9028    reconcileTextFormat(nextElement);
9029    reconcileTextStyle(nextElement);
9030  }
9031  function $reconcileChildren(prevElement, nextElement, slot) {
9032    const previousSubTreeTextContent = subTreeTextContent;
9033    const prevChildrenSize = prevElement.__size;
9034    const nextChildrenSize = nextElement.__size;
9035    subTreeTextContent = "";
9036    const dom = slot.element;
9037    if (prevChildrenSize === 1 && nextChildrenSize === 1) {
9038      const prevFirstChildKey = prevElement.__first;
9039      const nextFirstChildKey = nextElement.__first;
9040      if (prevFirstChildKey === nextFirstChildKey) {
9041        $reconcileNode(prevFirstChildKey, dom);
9042      } else {
9043        const lastDOM = getPrevElementByKeyOrThrow(prevFirstChildKey);
9044        const replacementDOM = $createNode(nextFirstChildKey, null);
9045        try {
9046          dom.replaceChild(replacementDOM, lastDOM);
9047        } catch (error) {
9048          if (typeof error === "object" && error != null) {
9049            const msg = `${error.toString()} Parent: ${dom.tagName}, new child: {tag: ${replacementDOM.tagName} key: ${nextFirstChildKey}}, old child: {tag: ${lastDOM.tagName}, key: ${prevFirstChildKey}}.`;
9050            throw new Error(msg);
9051          } else {
9052            throw error;
9053          }
9054        }
9055        $destroyNode(prevFirstChildKey, null);
9056      }
9057      const nextChildNode = activeNextNodeMap.get(nextFirstChildKey);
9058      if ($isTextNode(nextChildNode)) {
9059        if (subTreeTextFormat === null) {
9060          subTreeTextFormat = nextChildNode.getFormat();
9061          subTreeTextStyle = nextChildNode.getStyle();
9062        }
9063      }
9064    } else {
9065      const prevChildren = $createChildrenArray(prevElement, activePrevNodeMap);
9066      const nextChildren = $createChildrenArray(nextElement, activeNextNodeMap);
9067      if (!(prevChildren.length === prevChildrenSize)) {
9068        formatDevErrorMessage(`$reconcileChildren: prevChildren.length !== prevChildrenSize`);
9069      }
9070      if (!(nextChildren.length === nextChildrenSize)) {
9071        formatDevErrorMessage(`$reconcileChildren: nextChildren.length !== nextChildrenSize`);
9072      }
9073      if (prevChildrenSize === 0) {
9074        if (nextChildrenSize !== 0) {
9075          $createChildren(nextChildren, nextElement, 0, nextChildrenSize - 1, slot);
9076        }
9077      } else if (nextChildrenSize === 0) {
9078        if (prevChildrenSize !== 0) {
9079          const canUseFastPath = slot.after == null && slot.before == null && slot.element.__lexicalLineBreak == null;
9080          $destroyChildren(prevChildren, 0, prevChildrenSize - 1, canUseFastPath ? null : dom);
9081          if (canUseFastPath) {
9082            dom.textContent = "";
9083          }
9084        }
9085      } else {
9086        $reconcileNodeChildren(nextElement, prevChildren, nextChildren, prevChildrenSize, nextChildrenSize, slot);
9087      }
9088    }
9089    dom.__lexicalTextContent = subTreeTextContent;
9090    subTreeTextContent = previousSubTreeTextContent + subTreeTextContent;
9091  }
9092  function $reconcileNode(key, parentDOM) {
9093    const prevNode = activePrevNodeMap.get(key);
9094    let nextNode = activeNextNodeMap.get(key);
9095    if (prevNode === void 0 || nextNode === void 0) {
9096      {
9097        formatDevErrorMessage(`reconcileNode: prevNode or nextNode does not exist in nodeMap`);
9098      }
9099    }
9100    const isDirty = treatAllNodesAsDirty || activeDirtyLeaves.has(key) || activeDirtyElements.has(key);
9101    const dom = getElementByKeyOrThrow(activeEditor$1, key);
9102    if (prevNode === nextNode && !isDirty) {
9103      let text2;
9104      if ($isElementNode(prevNode)) {
9105        const previousSubTreeTextContent = dom.__lexicalTextContent;
9106        if (typeof previousSubTreeTextContent === "string") {
9107          text2 = previousSubTreeTextContent;
9108        } else {
9109          text2 = prevNode.getTextContent();
9110          dom.__lexicalTextContent = text2;
9111        }
9112      } else {
9113        text2 = prevNode.getTextContent();
9114      }
9115      subTreeTextContent += text2;
9116      return dom;
9117    }
9118    if (prevNode !== nextNode && isDirty) {
9119      setMutatedNode(mutatedNodes, activeEditorNodes, activeMutationListeners, nextNode, "updated");
9120    }
9121    if (activeEditorDOMRenderConfig.$updateDOM(nextNode, prevNode, dom, activeEditor$1)) {
9122      const replacementDOM = $createNode(key, null);
9123      if (parentDOM === null) {
9124        {
9125          formatDevErrorMessage(`reconcileNode: parentDOM is null`);
9126        }
9127      }
9128      parentDOM.replaceChild(replacementDOM, dom);
9129      $destroyNode(key, null);
9130      return replacementDOM;
9131    }
9132    if ($isElementNode(prevNode)) {
9133      if (!$isElementNode(nextNode)) {
9134        formatDevErrorMessage(`Node with key ${key} changed from ElementNode to !ElementNode`);
9135      }
9136      const nextIndent = nextNode.__indent;
9137      if (treatAllNodesAsDirty || nextIndent !== prevNode.__indent) {
9138        setElementIndent(dom, nextIndent);
9139      }
9140      const nextFormat = nextNode.__format;
9141      if (treatAllNodesAsDirty || nextFormat !== prevNode.__format) {
9142        setElementFormat(dom, nextFormat);
9143      }
9144      if (isDirty) {
9145        $reconcileChildrenWithDirection(prevNode, nextNode, dom);
9146        if (!$isRootNode(nextNode) && !nextNode.isInline()) {
9147          $reconcileElementTerminatingLineBreak(prevNode, nextNode, dom);
9148        }
9149      } else {
9150        const previousSubTreeTextContent = dom.__lexicalTextContent;
9151        let text2;
9152        if (typeof previousSubTreeTextContent === "string") {
9153          text2 = previousSubTreeTextContent;
9154        } else {
9155          text2 = prevNode.getTextContent();
9156          dom.__lexicalTextContent = text2;
9157        }
9158        subTreeTextContent += text2;
9159      }
9160      if (treatAllNodesAsDirty || nextNode.__dir !== prevNode.__dir) {
9161        $setElementDirection(dom, nextNode);
9162        if (
9163          // Root node direction changing from set to unset (or vice versa)
9164          // changes how children's direction is calculated.
9165          $isRootNode(nextNode) && // Can skip if all children already reconciled.
9166          !treatAllNodesAsDirty
9167        ) {
9168          for (const child of nextNode.getChildren()) {
9169            if ($isElementNode(child)) {
9170              const childDom = getElementByKeyOrThrow(activeEditor$1, child.getKey());
9171              $setElementDirection(childDom, child);
9172            }
9173          }
9174        }
9175      }
9176    } else {
9177      const text2 = nextNode.getTextContent();
9178      if ($isDecoratorNode(nextNode)) {
9179        const decorator = nextNode.decorate(activeEditor$1, activeEditorConfig);
9180        if (decorator !== null) {
9181          reconcileDecorator(key, decorator);
9182        }
9183      }
9184      subTreeTextContent += text2;
9185    }
9186    if (!activeEditorStateReadOnly && $isRootNode(nextNode) && nextNode.__cachedText !== subTreeTextContent) {
9187      const nextRootNode = nextNode.getWritable();
9188      nextRootNode.__cachedText = subTreeTextContent;
9189      nextNode = nextRootNode;
9190    }
9191    activeEditorDOMRenderConfig.$decorateDOM(nextNode, prevNode, dom, activeEditor$1);
9192    {
9193      Object.freeze(nextNode);
9194    }
9195    return dom;
9196  }
9197  function reconcileDecorator(key, decorator) {
9198    let pendingDecorators = activeEditor$1._pendingDecorators;
9199    const currentDecorators = activeEditor$1._decorators;
9200    if (pendingDecorators === null) {
9201      if (currentDecorators[key] === decorator) {
9202        return;
9203      }
9204      pendingDecorators = cloneDecorators(activeEditor$1);
9205    }
9206    pendingDecorators[key] = decorator;
9207  }
9208  function getNextSibling(element) {
9209    let nextSibling = element.nextSibling;
9210    if (nextSibling !== null && nextSibling === activeEditor$1._blockCursorElement) {
9211      nextSibling = nextSibling.nextSibling;
9212    }
9213    return nextSibling;
9214  }
9215  function childrenSet(children, start3) {
9216    const s2 = /* @__PURE__ */ new Set();
9217    for (let i2 = start3; i2 < children.length; i2++) {
9218      s2.add(children[i2]);
9219    }
9220    return s2;
9221  }
9222  function $reconcileNodeChildren(nextElement, prevChildren, nextChildren, prevChildrenLength, nextChildrenLength, slot) {
9223    const prevEndIndex = prevChildrenLength - 1;
9224    const nextEndIndex = nextChildrenLength - 1;
9225    let prevChildrenSet;
9226    let nextChildrenSet;
9227    let siblingDOM = slot.getFirstChild();
9228    let prevIndex = 0;
9229    let nextIndex = 0;
9230    while (prevIndex <= prevEndIndex && nextIndex <= nextEndIndex) {
9231      const prevKey = prevChildren[prevIndex];
9232      const nextKey = nextChildren[nextIndex];
9233      if (prevKey === nextKey) {
9234        siblingDOM = getNextSibling($reconcileNode(nextKey, slot.element));
9235        prevIndex++;
9236        nextIndex++;
9237      } else {
9238        if (nextChildrenSet === void 0) {
9239          nextChildrenSet = childrenSet(nextChildren, nextIndex);
9240        }
9241        if (prevChildrenSet === void 0) {
9242          prevChildrenSet = childrenSet(prevChildren, prevIndex);
9243        } else if (!prevChildrenSet.has(prevKey)) {
9244          prevIndex++;
9245          continue;
9246        }
9247        if (!nextChildrenSet.has(prevKey)) {
9248          siblingDOM = getNextSibling(getPrevElementByKeyOrThrow(prevKey));
9249          $destroyNode(prevKey, slot.element);
9250          prevIndex++;
9251          prevChildrenSet.delete(prevKey);
9252          continue;
9253        }
9254        if (!prevChildrenSet.has(nextKey)) {
9255          $createNode(nextKey, slot.withBefore(siblingDOM));
9256          nextIndex++;
9257        } else {
9258          const childDOM = getElementByKeyOrThrow(activeEditor$1, nextKey);
9259          if (childDOM !== siblingDOM) {
9260            slot.withBefore(siblingDOM).insertChild(childDOM);
9261          }
9262          siblingDOM = getNextSibling($reconcileNode(nextKey, slot.element));
9263          prevIndex++;
9264          nextIndex++;
9265        }
9266      }
9267      const node = activeNextNodeMap.get(nextKey);
9268      if (node !== null && $isTextNode(node)) {
9269        if (subTreeTextFormat === null) {
9270          subTreeTextFormat = node.getFormat();
9271          subTreeTextStyle = node.getStyle();
9272        }
9273      } else if (
9274        // inline $textContentRequiresDoubleLinebreakAtEnd
9275        $isElementNode(node) && nextIndex <= nextEndIndex && !node.isInline()
9276      ) {
9277        subTreeTextContent += DOUBLE_LINE_BREAK;
9278      }
9279    }
9280    const appendNewChildren = prevIndex > prevEndIndex;
9281    const removeOldChildren = nextIndex > nextEndIndex;
9282    if (appendNewChildren && !removeOldChildren) {
9283      const previousNode = nextChildren[nextEndIndex + 1];
9284      const insertDOM = previousNode === void 0 ? null : activeEditor$1.getElementByKey(previousNode);
9285      $createChildren(nextChildren, nextElement, nextIndex, nextEndIndex, slot.withBefore(insertDOM));
9286    } else if (removeOldChildren && !appendNewChildren) {
9287      $destroyChildren(prevChildren, prevIndex, prevEndIndex, slot.element);
9288    }
9289  }
9290  function $reconcileRoot(prevEditorState, nextEditorState, editor, dirtyType, dirtyElements, dirtyLeaves) {
9291    subTreeTextContent = "";
9292    treatAllNodesAsDirty = dirtyType === FULL_RECONCILE;
9293    activeEditor$1 = editor;
9294    activeEditorConfig = editor._config;
9295    activeEditorDOMRenderConfig = editor._config.dom || DEFAULT_EDITOR_DOM_CONFIG;
9296    activeEditorNodes = editor._nodes;
9297    activeMutationListeners = activeEditor$1._listeners.mutation;
9298    activeDirtyElements = dirtyElements;
9299    activeDirtyLeaves = dirtyLeaves;
9300    activePrevNodeMap = prevEditorState._nodeMap;
9301    activeNextNodeMap = nextEditorState._nodeMap;
9302    activeEditorStateReadOnly = nextEditorState._readOnly;
9303    activePrevKeyToDOMMap = new Map(editor._keyToDOMMap);
9304    const currentMutatedNodes = /* @__PURE__ */ new Map();
9305    mutatedNodes = currentMutatedNodes;
9306    $reconcileNode("root", null);
9307    activeEditor$1 = void 0;
9308    activeEditorNodes = void 0;
9309    activeDirtyElements = void 0;
9310    activeDirtyLeaves = void 0;
9311    activePrevNodeMap = void 0;
9312    activeNextNodeMap = void 0;
9313    activeEditorConfig = void 0;
9314    activePrevKeyToDOMMap = void 0;
9315    mutatedNodes = void 0;
9316    activeEditorDOMRenderConfig = DEFAULT_EDITOR_DOM_CONFIG;
9317    return currentMutatedNodes;
9318  }
9319  function storeDOMWithKey(key, dom, editor) {
9320    const keyToDOMMap = editor._keyToDOMMap;
9321    setNodeKeyOnDOMNode(dom, editor, key);
9322    keyToDOMMap.set(key, dom);
9323  }
9324  function getPrevElementByKeyOrThrow(key) {
9325    const element = activePrevKeyToDOMMap.get(key);
9326    if (element === void 0) {
9327      {
9328        formatDevErrorMessage(`Reconciliation: could not find DOM element for node key ${key}`);
9329      }
9330    }
9331    return element;
9332  }
9333  function warnOnlyOnce(message) {
9334    {
9335      let run = false;
9336      return () => {
9337        if (!run) {
9338          console.warn(message);
9339        }
9340        run = true;
9341      };
9342    }
9343  }
9344  // @__NO_SIDE_EFFECTS__
9345  function createCommand(type) {
9346    return {
9347      type
9348    };
9349  }
9350  var SELECTION_CHANGE_COMMAND = /* @__PURE__ */ createCommand("SELECTION_CHANGE_COMMAND");
9351  var SELECTION_INSERT_CLIPBOARD_NODES_COMMAND = /* @__PURE__ */ createCommand("SELECTION_INSERT_CLIPBOARD_NODES_COMMAND");
9352  var CLICK_COMMAND = /* @__PURE__ */ createCommand("CLICK_COMMAND");
9353  var BEFORE_INPUT_COMMAND = /* @__PURE__ */ createCommand("BEFORE_INPUT_COMMAND");
9354  var INPUT_COMMAND = /* @__PURE__ */ createCommand("INPUT_COMMAND");
9355  var COMPOSITION_START_COMMAND = /* @__PURE__ */ createCommand("COMPOSITION_START_COMMAND");
9356  var COMPOSITION_END_COMMAND = /* @__PURE__ */ createCommand("COMPOSITION_END_COMMAND");
9357  var DELETE_CHARACTER_COMMAND = /* @__PURE__ */ createCommand("DELETE_CHARACTER_COMMAND");
9358  var INSERT_LINE_BREAK_COMMAND = /* @__PURE__ */ createCommand("INSERT_LINE_BREAK_COMMAND");
9359  var INSERT_PARAGRAPH_COMMAND = /* @__PURE__ */ createCommand("INSERT_PARAGRAPH_COMMAND");
9360  var CONTROLLED_TEXT_INSERTION_COMMAND = /* @__PURE__ */ createCommand("CONTROLLED_TEXT_INSERTION_COMMAND");
9361  var PASTE_COMMAND = /* @__PURE__ */ createCommand("PASTE_COMMAND");
9362  var REMOVE_TEXT_COMMAND = /* @__PURE__ */ createCommand("REMOVE_TEXT_COMMAND");
9363  var DELETE_WORD_COMMAND = /* @__PURE__ */ createCommand("DELETE_WORD_COMMAND");
9364  var DELETE_LINE_COMMAND = /* @__PURE__ */ createCommand("DELETE_LINE_COMMAND");
9365  var FORMAT_TEXT_COMMAND = /* @__PURE__ */ createCommand("FORMAT_TEXT_COMMAND");
9366  var UNDO_COMMAND = /* @__PURE__ */ createCommand("UNDO_COMMAND");
9367  var REDO_COMMAND = /* @__PURE__ */ createCommand("REDO_COMMAND");
9368  var KEY_DOWN_COMMAND = /* @__PURE__ */ createCommand("KEYDOWN_COMMAND");
9369  var KEY_ARROW_RIGHT_COMMAND = /* @__PURE__ */ createCommand("KEY_ARROW_RIGHT_COMMAND");
9370  var MOVE_TO_END = /* @__PURE__ */ createCommand("MOVE_TO_END");
9371  var KEY_ARROW_LEFT_COMMAND = /* @__PURE__ */ createCommand("KEY_ARROW_LEFT_COMMAND");
9372  var MOVE_TO_START = /* @__PURE__ */ createCommand("MOVE_TO_START");
9373  var KEY_ARROW_UP_COMMAND = /* @__PURE__ */ createCommand("KEY_ARROW_UP_COMMAND");
9374  var KEY_ARROW_DOWN_COMMAND = /* @__PURE__ */ createCommand("KEY_ARROW_DOWN_COMMAND");
9375  var KEY_ENTER_COMMAND = /* @__PURE__ */ createCommand("KEY_ENTER_COMMAND");
9376  var KEY_SPACE_COMMAND = /* @__PURE__ */ createCommand("KEY_SPACE_COMMAND");
9377  var KEY_BACKSPACE_COMMAND = /* @__PURE__ */ createCommand("KEY_BACKSPACE_COMMAND");
9378  var KEY_ESCAPE_COMMAND = /* @__PURE__ */ createCommand("KEY_ESCAPE_COMMAND");
9379  var KEY_DELETE_COMMAND = /* @__PURE__ */ createCommand("KEY_DELETE_COMMAND");
9380  var KEY_TAB_COMMAND = /* @__PURE__ */ createCommand("KEY_TAB_COMMAND");
9381  var INSERT_TAB_COMMAND = /* @__PURE__ */ createCommand("INSERT_TAB_COMMAND");
9382  var INDENT_CONTENT_COMMAND = /* @__PURE__ */ createCommand("INDENT_CONTENT_COMMAND");
9383  var OUTDENT_CONTENT_COMMAND = /* @__PURE__ */ createCommand("OUTDENT_CONTENT_COMMAND");
9384  var DROP_COMMAND = /* @__PURE__ */ createCommand("DROP_COMMAND");
9385  var FORMAT_ELEMENT_COMMAND = /* @__PURE__ */ createCommand("FORMAT_ELEMENT_COMMAND");
9386  var DRAGSTART_COMMAND = /* @__PURE__ */ createCommand("DRAGSTART_COMMAND");
9387  var DRAGOVER_COMMAND = /* @__PURE__ */ createCommand("DRAGOVER_COMMAND");
9388  var DRAGEND_COMMAND = /* @__PURE__ */ createCommand("DRAGEND_COMMAND");
9389  var COPY_COMMAND = /* @__PURE__ */ createCommand("COPY_COMMAND");
9390  var CUT_COMMAND = /* @__PURE__ */ createCommand("CUT_COMMAND");
9391  var SELECT_ALL_COMMAND = /* @__PURE__ */ createCommand("SELECT_ALL_COMMAND");
9392  var CLEAR_EDITOR_COMMAND = /* @__PURE__ */ createCommand("CLEAR_EDITOR_COMMAND");
9393  var CLEAR_HISTORY_COMMAND = /* @__PURE__ */ createCommand("CLEAR_HISTORY_COMMAND");
9394  var CAN_REDO_COMMAND = /* @__PURE__ */ createCommand("CAN_REDO_COMMAND");
9395  var CAN_UNDO_COMMAND = /* @__PURE__ */ createCommand("CAN_UNDO_COMMAND");
9396  var FOCUS_COMMAND = /* @__PURE__ */ createCommand("FOCUS_COMMAND");
9397  var BLUR_COMMAND = /* @__PURE__ */ createCommand("BLUR_COMMAND");
9398  var KEY_MODIFIER_COMMAND = /* @__PURE__ */ createCommand("KEY_MODIFIER_COMMAND");
9399  var PASS_THROUGH_COMMAND = Object.freeze({});
9400  var ANDROID_COMPOSITION_LATENCY = 30;
9401  var rootElementEvents = [["keydown", onKeyDown], ["pointerdown", onPointerDown], ["compositionstart", onCompositionStart], ["compositionend", onCompositionEnd], ["input", onInput], ["click", onClick], ["cut", PASS_THROUGH_COMMAND], ["copy", PASS_THROUGH_COMMAND], ["dragstart", PASS_THROUGH_COMMAND], ["dragover", PASS_THROUGH_COMMAND], ["dragend", PASS_THROUGH_COMMAND], ["paste", PASS_THROUGH_COMMAND], ["focus", PASS_THROUGH_COMMAND], ["blur", PASS_THROUGH_COMMAND], ["drop", PASS_THROUGH_COMMAND]];
9402  if (CAN_USE_BEFORE_INPUT) {
9403    rootElementEvents.push(["beforeinput", (event, editor) => onBeforeInput(event, editor)]);
9404  }
9405  var lastKeyDownTimeStamp = 0;
9406  var lastKeyCode = null;
9407  var lastBeforeInputInsertTextTimeStamp = 0;
9408  var unprocessedBeforeInputData = null;
9409  var rootElementToDocument = /* @__PURE__ */ new WeakMap();
9410  var rootElementsRegistered = /* @__PURE__ */ new WeakMap();
9411  var isSelectionChangeFromDOMUpdate = false;
9412  var isSelectionChangeFromMouseDown = false;
9413  var isInsertLineBreak = false;
9414  var isFirefoxEndingComposition = false;
9415  var isSafariEndingComposition = false;
9416  var safariEndCompositionEventData = "";
9417  var postDeleteSelectionToRestore = null;
9418  var collapsedSelectionFormat = [0, "", 0, "root", 0];
9419  function $shouldPreventDefaultAndInsertText(selection, domTargetRange, text2, timeStamp, isBeforeInput) {
9420    const anchor = selection.anchor;
9421    const focus = selection.focus;
9422    const anchorNode = anchor.getNode();
9423    const editor = getActiveEditor();
9424    const domSelection = getDOMSelection(getWindow(editor));
9425    const domAnchorNode = domSelection !== null ? domSelection.anchorNode : null;
9426    const anchorKey = anchor.key;
9427    const backingAnchorElement = editor.getElementByKey(anchorKey);
9428    const textLength = text2.length;
9429    return anchorKey !== focus.key || // If we're working with a non-text node.
9430    !$isTextNode(anchorNode) || // If we are replacing a range with a single character or grapheme, and not composing.
9431    (!isBeforeInput && (!CAN_USE_BEFORE_INPUT || // We check to see if there has been
9432    // a recent beforeinput event for "textInput". If there has been one in the last
9433    // 50ms then we proceed as normal. However, if there is not, then this is likely
9434    // a dangling `input` event caused by execCommand('insertText').
9435    lastBeforeInputInsertTextTimeStamp < timeStamp + 50) || anchorNode.isDirty() && textLength < 2 || // TODO consider if there are other scenarios when multiple code units
9436    //      should be addressed here
9437    doesContainSurrogatePair(text2)) && anchor.offset !== focus.offset && !anchorNode.isComposing() || // Any non standard text node.
9438    $isTokenOrSegmented(anchorNode) || // If the text length is more than a single character and we're either
9439    // dealing with this in "beforeinput" or where the node has already recently
9440    // been changed (thus is dirty).
9441    anchorNode.isDirty() && textLength > 1 || // If the DOM selection element is not the same as the backing node during beforeinput.
9442    (isBeforeInput || !CAN_USE_BEFORE_INPUT) && backingAnchorElement !== null && !anchorNode.isComposing() && domAnchorNode !== getDOMTextNode(backingAnchorElement) || // If TargetRange is not the same as the DOM selection; browser trying to edit random parts
9443    // of the editor.
9444    domSelection !== null && domTargetRange !== null && (!domTargetRange.collapsed || domTargetRange.startContainer !== domSelection.anchorNode || domTargetRange.startOffset !== domSelection.anchorOffset) || // Check if we're changing from bold to italics, or some other format.
9445    !anchorNode.isComposing() && (anchorNode.getFormat() !== selection.format || anchorNode.getStyle() !== selection.style) || // One last set of heuristics to check against.
9446    $shouldInsertTextAfterOrBeforeTextNode(selection, anchorNode);
9447  }
9448  function shouldSkipSelectionChange(domNode, offset3) {
9449    return isDOMTextNode(domNode) && domNode.nodeValue !== null && offset3 !== 0 && offset3 !== domNode.nodeValue.length;
9450  }
9451  function onSelectionChange(domSelection, editor, isActive) {
9452    const {
9453      anchorNode: anchorDOM,
9454      anchorOffset,
9455      focusNode: focusDOM,
9456      focusOffset
9457    } = domSelection;
9458    if (isSelectionChangeFromDOMUpdate) {
9459      isSelectionChangeFromDOMUpdate = false;
9460      if (shouldSkipSelectionChange(anchorDOM, anchorOffset) && shouldSkipSelectionChange(focusDOM, focusOffset) && !postDeleteSelectionToRestore) {
9461        return;
9462      }
9463    }
9464    updateEditorSync(editor, () => {
9465      if (!isActive) {
9466        $setSelection(null);
9467        return;
9468      }
9469      if (!isSelectionWithinEditor(editor, anchorDOM, focusDOM)) {
9470        return;
9471      }
9472      let selection = $getSelection();
9473      if (postDeleteSelectionToRestore && $isRangeSelection(selection) && selection.isCollapsed()) {
9474        const curAnchor = selection.anchor;
9475        const prevAnchor = postDeleteSelectionToRestore.anchor;
9476        if (
9477          // Rightward shift in same node
9478          curAnchor.key === prevAnchor.key && curAnchor.offset === prevAnchor.offset + 1 || // Or rightward shift into sibling node
9479          curAnchor.offset === 1 && prevAnchor.getNode().is(curAnchor.getNode().getPreviousSibling())
9480        ) {
9481          selection = postDeleteSelectionToRestore.clone();
9482          $setSelection(selection);
9483        }
9484      }
9485      postDeleteSelectionToRestore = null;
9486      if ($isRangeSelection(selection)) {
9487        const anchor = selection.anchor;
9488        const anchorNode = anchor.getNode();
9489        if (selection.isCollapsed()) {
9490          if (domSelection.type === "Range" && domSelection.anchorNode === domSelection.focusNode) {
9491            selection.dirty = true;
9492          }
9493          const windowEvent = getWindow(editor).event;
9494          const currentTimeStamp = windowEvent ? windowEvent.timeStamp : performance.now();
9495          const [lastFormat, lastStyle, lastOffset, lastKey, timeStamp] = collapsedSelectionFormat;
9496          const root = $getRoot();
9497          const isRootTextContentEmpty = editor.isComposing() === false && root.getTextContent() === "";
9498          if (currentTimeStamp < timeStamp + 200 && anchor.offset === lastOffset && anchor.key === lastKey) {
9499            $updateSelectionFormatStyle(selection, lastFormat, lastStyle);
9500          } else {
9501            if (anchor.type === "text") {
9502              if (!$isTextNode(anchorNode)) {
9503                formatDevErrorMessage(`Point.getNode() must return TextNode when type is text`);
9504              }
9505              $updateSelectionFormatStyleFromTextNode(selection, anchorNode);
9506            } else if (anchor.type === "element" && !isRootTextContentEmpty) {
9507              if (!$isElementNode(anchorNode)) {
9508                formatDevErrorMessage(`Point.getNode() must return ElementNode when type is element`);
9509              }
9510              const lastNode = anchor.getNode();
9511              if (
9512                // This previously applied to all ParagraphNode
9513                lastNode.isEmpty()
9514              ) {
9515                $updateSelectionFormatStyleFromElementNode(selection, lastNode);
9516              } else {
9517                $updateSelectionFormatStyle(selection, selection.format, "");
9518              }
9519            }
9520          }
9521        } else {
9522          const anchorKey = anchor.key;
9523          const focus = selection.focus;
9524          const focusKey = focus.key;
9525          const nodes = selection.getNodes();
9526          const nodesLength = nodes.length;
9527          const isBackward = selection.isBackward();
9528          const startOffset = isBackward ? focusOffset : anchorOffset;
9529          const endOffset = isBackward ? anchorOffset : focusOffset;
9530          const startKey = isBackward ? focusKey : anchorKey;
9531          const endKey = isBackward ? anchorKey : focusKey;
9532          let combinedFormat = IS_ALL_FORMATTING;
9533          let hasTextNodes = false;
9534          for (let i2 = 0; i2 < nodesLength; i2++) {
9535            const node = nodes[i2];
9536            const textContentSize = node.getTextContentSize();
9537            if ($isTextNode(node) && textContentSize !== 0 && // Exclude empty text nodes at boundaries resulting from user's selection
9538            !(i2 === 0 && node.__key === startKey && startOffset === textContentSize || i2 === nodesLength - 1 && node.__key === endKey && endOffset === 0)) {
9539              hasTextNodes = true;
9540              combinedFormat &= node.getFormat();
9541              if (combinedFormat === 0) {
9542                break;
9543              }
9544            }
9545          }
9546          selection.format = hasTextNodes ? combinedFormat : 0;
9547        }
9548      }
9549      dispatchCommand(editor, SELECTION_CHANGE_COMMAND, void 0);
9550    });
9551  }
9552  function $updateSelectionFormatStyle(selection, format, style) {
9553    if (selection.format !== format || selection.style !== style) {
9554      selection.format = format;
9555      selection.style = style;
9556      selection.dirty = true;
9557    }
9558  }
9559  function $updateSelectionFormatStyleFromTextNode(selection, node) {
9560    const format = node.getFormat();
9561    const style = node.getStyle();
9562    $updateSelectionFormatStyle(selection, format, style);
9563  }
9564  function $updateSelectionFormatStyleFromElementNode(selection, node) {
9565    const format = node.getTextFormat();
9566    const style = node.getTextStyle();
9567    $updateSelectionFormatStyle(selection, format, style);
9568  }
9569  function onClick(event, editor) {
9570    updateEditorSync(editor, () => {
9571      const selection = $getSelection();
9572      const domSelection = getDOMSelection(getWindow(editor));
9573      const lastSelection = $getPreviousSelection();
9574      if (domSelection) {
9575        if ($isRangeSelection(selection)) {
9576          const anchor = selection.anchor;
9577          const anchorNode = anchor.getNode();
9578          if (anchor.type === "element" && anchor.offset === 0 && selection.isCollapsed() && !$isRootNode(anchorNode) && $getRoot().getChildrenSize() === 1 && anchorNode.getTopLevelElementOrThrow().isEmpty() && lastSelection !== null && selection.is(lastSelection)) {
9579            domSelection.removeAllRanges();
9580            selection.dirty = true;
9581          } else if (event.detail === 3 && !selection.isCollapsed()) {
9582            const focus = selection.focus;
9583            const focusNode = focus.getNode();
9584            if (anchorNode !== focusNode) {
9585              const parentNode = $findMatchingParent(anchorNode, (node) => $isElementNode(node) && !node.isInline());
9586              if ($isElementNode(parentNode)) {
9587                parentNode.select(0);
9588              }
9589            }
9590          }
9591        } else if (event.pointerType === "touch" || event.pointerType === "pen") {
9592          const domAnchorNode = domSelection.anchorNode;
9593          if (isHTMLElement(domAnchorNode) || isDOMTextNode(domAnchorNode)) {
9594            const newSelection = $internalCreateRangeSelection(lastSelection, domSelection, editor, event);
9595            $setSelection(newSelection);
9596          }
9597        }
9598      }
9599      dispatchCommand(editor, CLICK_COMMAND, event);
9600    });
9601  }
9602  function onPointerDown(event, editor) {
9603    const target = event.target;
9604    const pointerType = event.pointerType;
9605    if (isDOMNode(target) && pointerType !== "touch" && pointerType !== "pen" && event.button === 0) {
9606      updateEditorSync(editor, () => {
9607        if (!$isSelectionCapturedInDecorator(target)) {
9608          isSelectionChangeFromMouseDown = true;
9609        }
9610      });
9611    }
9612  }
9613  function getTargetRange(event) {
9614    if (!event.getTargetRanges) {
9615      return null;
9616    }
9617    const targetRanges = event.getTargetRanges();
9618    if (targetRanges.length === 0) {
9619      return null;
9620    }
9621    return targetRanges[0];
9622  }
9623  function $canRemoveText(anchorNode, focusNode) {
9624    return anchorNode !== focusNode || $isElementNode(anchorNode) || $isElementNode(focusNode) || !$isTokenOrTab(anchorNode) || !$isTokenOrTab(focusNode);
9625  }
9626  function isPossiblyAndroidKeyPress(timeStamp) {
9627    return lastKeyCode === "MediaLast" && timeStamp < lastKeyDownTimeStamp + ANDROID_COMPOSITION_LATENCY;
9628  }
9629  function registerDefaultCommandHandlers(editor) {
9630    editor.registerCommand(BEFORE_INPUT_COMMAND, $handleBeforeInput, COMMAND_PRIORITY_EDITOR);
9631    editor.registerCommand(INPUT_COMMAND, $handleInput, COMMAND_PRIORITY_EDITOR);
9632    editor.registerCommand(COMPOSITION_START_COMMAND, $handleCompositionStart, COMMAND_PRIORITY_EDITOR);
9633    editor.registerCommand(COMPOSITION_END_COMMAND, $handleCompositionEnd, COMMAND_PRIORITY_EDITOR);
9634    editor.registerCommand(KEY_DOWN_COMMAND, $handleKeyDown, COMMAND_PRIORITY_EDITOR);
9635  }
9636  function onBeforeInput(event, editor) {
9637    const inputType = event.inputType;
9638    if (inputType === "deleteCompositionText" || // If we're pasting in FF, we shouldn't get this event
9639    // as the `paste` event should have triggered, unless the
9640    // user has dom.event.clipboardevents.enabled disabled in
9641    // about:config. In that case, we need to process the
9642    // pasted content in the DOM mutation phase.
9643    IS_FIREFOX && isFirefoxClipboardEvents(editor)) {
9644      return;
9645    } else if (inputType === "insertCompositionText") {
9646      return;
9647    }
9648    dispatchCommand(editor, BEFORE_INPUT_COMMAND, event);
9649  }
9650  function $handleBeforeInput(event) {
9651    const inputType = event.inputType;
9652    const targetRange = getTargetRange(event);
9653    const editor = getActiveEditor();
9654    const selection = $getSelection();
9655    if (inputType === "deleteContentBackward") {
9656      if (selection === null) {
9657        const prevSelection = $getPreviousSelection();
9658        if (!$isRangeSelection(prevSelection)) {
9659          return true;
9660        }
9661        $setSelection(prevSelection.clone());
9662      }
9663      if ($isRangeSelection(selection)) {
9664        const isSelectionAnchorSameAsFocus = selection.anchor.key === selection.focus.key;
9665        if (isPossiblyAndroidKeyPress(event.timeStamp) && editor.isComposing() && isSelectionAnchorSameAsFocus) {
9666          $setCompositionKey(null);
9667          lastKeyDownTimeStamp = 0;
9668          setTimeout(() => {
9669            updateEditorSync(editor, () => {
9670              $setCompositionKey(null);
9671            });
9672          }, ANDROID_COMPOSITION_LATENCY);
9673          if ($isRangeSelection(selection)) {
9674            const anchorNode2 = selection.anchor.getNode();
9675            anchorNode2.markDirty();
9676            if (!$isTextNode(anchorNode2)) {
9677              formatDevErrorMessage(`Anchor node must be a TextNode`);
9678            }
9679            $updateSelectionFormatStyleFromTextNode(selection, anchorNode2);
9680          }
9681        } else {
9682          $setCompositionKey(null);
9683          event.preventDefault();
9684          const selectedNode = selection.anchor.getNode();
9685          const selectedNodeText = selectedNode.getTextContent();
9686          const selectedNodeCanInsertTextAfter = selectedNode.canInsertTextAfter();
9687          const hasSelectedAllTextInNode = selection.anchor.offset === 0 && selection.focus.offset === selectedNodeText.length;
9688          let shouldLetBrowserHandleDelete = IS_ANDROID_CHROME && isSelectionAnchorSameAsFocus && !hasSelectedAllTextInNode && selectedNodeCanInsertTextAfter;
9689          if (shouldLetBrowserHandleDelete && selection.isCollapsed()) {
9690            shouldLetBrowserHandleDelete = !$isDecoratorNode($getAdjacentNode(selection.anchor, true));
9691          }
9692          if (!shouldLetBrowserHandleDelete) {
9693            dispatchCommand(editor, DELETE_CHARACTER_COMMAND, true);
9694            const selectionAfterDelete = $getSelection();
9695            if (IS_ANDROID_CHROME && $isRangeSelection(selectionAfterDelete) && selectionAfterDelete.isCollapsed()) {
9696              postDeleteSelectionToRestore = selectionAfterDelete;
9697              setTimeout(() => postDeleteSelectionToRestore = null);
9698            }
9699          }
9700        }
9701        return true;
9702      }
9703    }
9704    if (!$isRangeSelection(selection)) {
9705      return true;
9706    }
9707    const data = event.data;
9708    if (unprocessedBeforeInputData !== null) {
9709      $updateSelectedTextFromDOM(false, editor, unprocessedBeforeInputData);
9710    }
9711    if ((!selection.dirty || unprocessedBeforeInputData !== null) && selection.isCollapsed() && !$isRootNode(selection.anchor.getNode()) && targetRange !== null) {
9712      selection.applyDOMRange(targetRange);
9713    }
9714    unprocessedBeforeInputData = null;
9715    const anchor = selection.anchor;
9716    const focus = selection.focus;
9717    const anchorNode = anchor.getNode();
9718    const focusNode = focus.getNode();
9719    if (inputType === "insertText" || inputType === "insertTranspose") {
9720      if (data === "\n") {
9721        event.preventDefault();
9722        dispatchCommand(editor, INSERT_LINE_BREAK_COMMAND, false);
9723      } else if (data === DOUBLE_LINE_BREAK) {
9724        event.preventDefault();
9725        dispatchCommand(editor, INSERT_PARAGRAPH_COMMAND, void 0);
9726      } else if (data == null && event.dataTransfer) {
9727        const text2 = event.dataTransfer.getData("text/plain");
9728        event.preventDefault();
9729        selection.insertRawText(text2);
9730      } else if (data != null && $shouldPreventDefaultAndInsertText(selection, targetRange, data, event.timeStamp, true)) {
9731        event.preventDefault();
9732        dispatchCommand(editor, CONTROLLED_TEXT_INSERTION_COMMAND, data);
9733      } else {
9734        unprocessedBeforeInputData = data;
9735      }
9736      lastBeforeInputInsertTextTimeStamp = event.timeStamp;
9737      return true;
9738    }
9739    event.preventDefault();
9740    switch (inputType) {
9741      case "insertFromYank":
9742      case "insertFromDrop":
9743      case "insertReplacementText": {
9744        dispatchCommand(editor, CONTROLLED_TEXT_INSERTION_COMMAND, event);
9745        break;
9746      }
9747      case "insertFromComposition": {
9748        $setCompositionKey(null);
9749        dispatchCommand(editor, CONTROLLED_TEXT_INSERTION_COMMAND, event);
9750        break;
9751      }
9752      case "insertLineBreak": {
9753        $setCompositionKey(null);
9754        dispatchCommand(editor, INSERT_LINE_BREAK_COMMAND, false);
9755        break;
9756      }
9757      case "insertParagraph": {
9758        $setCompositionKey(null);
9759        if (isInsertLineBreak && !IS_IOS) {
9760          isInsertLineBreak = false;
9761          dispatchCommand(editor, INSERT_LINE_BREAK_COMMAND, false);
9762        } else {
9763          dispatchCommand(editor, INSERT_PARAGRAPH_COMMAND, void 0);
9764        }
9765        break;
9766      }
9767      case "insertFromPaste":
9768      case "insertFromPasteAsQuotation": {
9769        dispatchCommand(editor, PASTE_COMMAND, event);
9770        break;
9771      }
9772      case "deleteByComposition": {
9773        if ($canRemoveText(anchorNode, focusNode)) {
9774          dispatchCommand(editor, REMOVE_TEXT_COMMAND, event);
9775        }
9776        break;
9777      }
9778      case "deleteByDrag": {
9779        $addUpdateTag(SKIP_SELECTION_FOCUS_TAG);
9780        dispatchCommand(editor, REMOVE_TEXT_COMMAND, event);
9781        break;
9782      }
9783      case "deleteByCut": {
9784        dispatchCommand(editor, REMOVE_TEXT_COMMAND, event);
9785        break;
9786      }
9787      case "deleteContent": {
9788        dispatchCommand(editor, DELETE_CHARACTER_COMMAND, false);
9789        break;
9790      }
9791      case "deleteWordBackward": {
9792        dispatchCommand(editor, DELETE_WORD_COMMAND, true);
9793        break;
9794      }
9795      case "deleteWordForward": {
9796        dispatchCommand(editor, DELETE_WORD_COMMAND, false);
9797        break;
9798      }
9799      case "deleteHardLineBackward":
9800      case "deleteSoftLineBackward": {
9801        dispatchCommand(editor, DELETE_LINE_COMMAND, true);
9802        break;
9803      }
9804      case "deleteContentForward":
9805      case "deleteHardLineForward":
9806      case "deleteSoftLineForward": {
9807        dispatchCommand(editor, DELETE_LINE_COMMAND, false);
9808        break;
9809      }
9810      case "formatStrikeThrough": {
9811        dispatchCommand(editor, FORMAT_TEXT_COMMAND, "strikethrough");
9812        break;
9813      }
9814      case "formatBold": {
9815        dispatchCommand(editor, FORMAT_TEXT_COMMAND, "bold");
9816        break;
9817      }
9818      case "formatItalic": {
9819        dispatchCommand(editor, FORMAT_TEXT_COMMAND, "italic");
9820        break;
9821      }
9822      case "formatUnderline": {
9823        dispatchCommand(editor, FORMAT_TEXT_COMMAND, "underline");
9824        break;
9825      }
9826      case "historyUndo": {
9827        dispatchCommand(editor, UNDO_COMMAND, void 0);
9828        break;
9829      }
9830      case "historyRedo": {
9831        dispatchCommand(editor, REDO_COMMAND, void 0);
9832        break;
9833      }
9834    }
9835    return true;
9836  }
9837  function onInput(event, editor) {
9838    event.stopPropagation();
9839    updateEditorSync(editor, () => {
9840      editor.dispatchCommand(INPUT_COMMAND, event);
9841    }, {
9842      event
9843    });
9844    unprocessedBeforeInputData = null;
9845  }
9846  function $handleInput(event) {
9847    if (isHTMLElement(event.target) && $isSelectionCapturedInDecorator(event.target)) {
9848      return true;
9849    }
9850    const editor = getActiveEditor();
9851    const selection = $getSelection();
9852    const data = event.data;
9853    const targetRange = getTargetRange(event);
9854    if (data != null && $isRangeSelection(selection) && $shouldPreventDefaultAndInsertText(selection, targetRange, data, event.timeStamp, false)) {
9855      if (isFirefoxEndingComposition) {
9856        $onCompositionEndImpl(editor, data);
9857        isFirefoxEndingComposition = false;
9858      }
9859      const anchor = selection.anchor;
9860      const anchorNode = anchor.getNode();
9861      const domSelection = getDOMSelection(getWindow(editor));
9862      if (domSelection === null) {
9863        return true;
9864      }
9865      const isBackward = selection.isBackward();
9866      const startOffset = isBackward ? selection.anchor.offset : selection.focus.offset;
9867      const endOffset = isBackward ? selection.focus.offset : selection.anchor.offset;
9868      if (!CAN_USE_BEFORE_INPUT || selection.isCollapsed() || !$isTextNode(anchorNode) || domSelection.anchorNode === null || anchorNode.getTextContent().slice(0, startOffset) + data + anchorNode.getTextContent().slice(startOffset + endOffset) !== getAnchorTextFromDOM(domSelection.anchorNode)) {
9869        dispatchCommand(editor, CONTROLLED_TEXT_INSERTION_COMMAND, data);
9870      }
9871      const textLength = data.length;
9872      if (IS_FIREFOX && textLength > 1 && event.inputType === "insertCompositionText" && !editor.isComposing()) {
9873        selection.anchor.offset -= textLength;
9874      }
9875      if (IS_ANDROID_CHROME && editor.isComposing()) {
9876        lastKeyDownTimeStamp = 0;
9877        $setCompositionKey(null);
9878      }
9879    } else {
9880      const characterData = data !== null ? data : void 0;
9881      $updateSelectedTextFromDOM(false, editor, characterData);
9882      if (isFirefoxEndingComposition) {
9883        $onCompositionEndImpl(editor, data || void 0);
9884        isFirefoxEndingComposition = false;
9885      }
9886    }
9887    $flushMutations();
9888    return true;
9889  }
9890  function onCompositionStart(event, editor) {
9891    dispatchCommand(editor, COMPOSITION_START_COMMAND, event);
9892  }
9893  function $handleCompositionStart(event) {
9894    const editor = getActiveEditor();
9895    const selection = $getSelection();
9896    if ($isRangeSelection(selection) && !editor.isComposing()) {
9897      const anchor = selection.anchor;
9898      const node = selection.anchor.getNode();
9899      $setCompositionKey(anchor.key);
9900      $addUpdateTag(COMPOSITION_START_TAG);
9901      if (
9902        // If it has been 30ms since the last keydown, then we should
9903        // apply the empty space heuristic. We can't do this for Safari,
9904        // as the keydown fires after composition start.
9905        event.timeStamp < lastKeyDownTimeStamp + ANDROID_COMPOSITION_LATENCY || // FF has issues around composing multibyte characters, so we also
9906        // need to invoke the empty space heuristic below.
9907        anchor.type === "element" || !selection.isCollapsed() || node.getFormat() !== selection.format || $isTextNode(node) && node.getStyle() !== selection.style
9908      ) {
9909        dispatchCommand(editor, CONTROLLED_TEXT_INSERTION_COMMAND, COMPOSITION_START_CHAR);
9910      }
9911    }
9912    return true;
9913  }
9914  function $handleCompositionEnd(event) {
9915    const editor = getActiveEditor();
9916    $onCompositionEndImpl(editor, event.data);
9917    $addUpdateTag(COMPOSITION_END_TAG);
9918    return true;
9919  }
9920  function $onCompositionEndImpl(editor, data) {
9921    const compositionKey = editor._compositionKey;
9922    $setCompositionKey(null);
9923    if (compositionKey !== null && data != null) {
9924      if (data === "") {
9925        const node = $getNodeByKey(compositionKey);
9926        const domElement = editor.getElementByKey(compositionKey);
9927        const textNode = getDOMTextNode(domElement);
9928        if (textNode !== null && textNode.nodeValue !== null && $isTextNode(node)) {
9929          const domSelection = getDOMSelection(getWindow(editor));
9930          let anchorOffset = null;
9931          let focusOffset = null;
9932          if (domSelection !== null && domSelection.anchorNode === textNode) {
9933            anchorOffset = domSelection.anchorOffset;
9934            focusOffset = domSelection.focusOffset;
9935          }
9936          $updateTextNodeFromDOMContent(node, textNode.nodeValue, anchorOffset, focusOffset, true);
9937        }
9938        return;
9939      } else if (data[data.length - 1] === "\n") {
9940        const selection = $getSelection();
9941        if ($isRangeSelection(selection) || $isNodeSelection(selection)) {
9942          if ($isRangeSelection(selection)) {
9943            const focus = selection.focus;
9944            selection.anchor.set(focus.key, focus.offset, focus.type);
9945          }
9946          dispatchCommand(editor, KEY_ENTER_COMMAND, null);
9947          return;
9948        }
9949      }
9950    }
9951    $updateSelectedTextFromDOM(true, editor, data);
9952  }
9953  function onCompositionEnd(event, editor) {
9954    if (IS_FIREFOX) {
9955      isFirefoxEndingComposition = true;
9956    } else if (!IS_IOS && (IS_SAFARI || IS_APPLE_WEBKIT)) {
9957      isSafariEndingComposition = true;
9958      safariEndCompositionEventData = event.data;
9959    } else {
9960      dispatchCommand(editor, COMPOSITION_END_COMMAND, event);
9961    }
9962  }
9963  function onKeyDown(event, editor) {
9964    lastKeyDownTimeStamp = event.timeStamp;
9965    lastKeyCode = event.key;
9966    if (editor.isComposing()) {
9967      return;
9968    }
9969    dispatchCommand(editor, KEY_DOWN_COMMAND, event);
9970  }
9971  function $handleKeyDown(event) {
9972    const editor = getActiveEditor();
9973    if (event.key == null) {
9974      return true;
9975    }
9976    if (isSafariEndingComposition) {
9977      if (isBackspace(event)) {
9978        updateEditorSync(editor, () => {
9979          $onCompositionEndImpl(editor, safariEndCompositionEventData);
9980        });
9981        isSafariEndingComposition = false;
9982        safariEndCompositionEventData = "";
9983        return true;
9984      }
9985      isSafariEndingComposition = false;
9986      safariEndCompositionEventData = "";
9987    }
9988    if (isMoveForward(event)) {
9989      dispatchCommand(editor, KEY_ARROW_RIGHT_COMMAND, event);
9990    } else if (isMoveToEnd(event)) {
9991      dispatchCommand(editor, MOVE_TO_END, event);
9992    } else if (isMoveBackward(event)) {
9993      dispatchCommand(editor, KEY_ARROW_LEFT_COMMAND, event);
9994    } else if (isMoveToStart(event)) {
9995      dispatchCommand(editor, MOVE_TO_START, event);
9996    } else if (isMoveUp(event)) {
9997      dispatchCommand(editor, KEY_ARROW_UP_COMMAND, event);
9998    } else if (isMoveDown(event)) {
9999      dispatchCommand(editor, KEY_ARROW_DOWN_COMMAND, event);
10000    } else if (isLineBreak(event)) {
10001      isInsertLineBreak = true;
10002      dispatchCommand(editor, KEY_ENTER_COMMAND, event);
10003    } else if (isSpace(event)) {
10004      dispatchCommand(editor, KEY_SPACE_COMMAND, event);
10005    } else if (isOpenLineBreak(event)) {
10006      event.preventDefault();
10007      isInsertLineBreak = true;
10008      dispatchCommand(editor, INSERT_LINE_BREAK_COMMAND, true);
10009    } else if (isParagraph(event)) {
10010      isInsertLineBreak = false;
10011      dispatchCommand(editor, KEY_ENTER_COMMAND, event);
10012    } else if (isDeleteBackward(event)) {
10013      if (isBackspace(event)) {
10014        dispatchCommand(editor, KEY_BACKSPACE_COMMAND, event);
10015      } else {
10016        event.preventDefault();
10017        dispatchCommand(editor, DELETE_CHARACTER_COMMAND, true);
10018      }
10019    } else if (isEscape(event)) {
10020      dispatchCommand(editor, KEY_ESCAPE_COMMAND, event);
10021    } else if (isDeleteForward(event)) {
10022      if (isDelete(event)) {
10023        dispatchCommand(editor, KEY_DELETE_COMMAND, event);
10024      } else {
10025        event.preventDefault();
10026        dispatchCommand(editor, DELETE_CHARACTER_COMMAND, false);
10027      }
10028    } else if (isDeleteWordBackward(event)) {
10029      event.preventDefault();
10030      dispatchCommand(editor, DELETE_WORD_COMMAND, true);
10031    } else if (isDeleteWordForward(event)) {
10032      event.preventDefault();
10033      dispatchCommand(editor, DELETE_WORD_COMMAND, false);
10034    } else if (isDeleteLineBackward(event)) {
10035      event.preventDefault();
10036      dispatchCommand(editor, DELETE_LINE_COMMAND, true);
10037    } else if (isDeleteLineForward(event)) {
10038      event.preventDefault();
10039      dispatchCommand(editor, DELETE_LINE_COMMAND, false);
10040    } else if (isBold(event)) {
10041      event.preventDefault();
10042      dispatchCommand(editor, FORMAT_TEXT_COMMAND, "bold");
10043    } else if (isUnderline(event)) {
10044      event.preventDefault();
10045      dispatchCommand(editor, FORMAT_TEXT_COMMAND, "underline");
10046    } else if (isItalic(event)) {
10047      event.preventDefault();
10048      dispatchCommand(editor, FORMAT_TEXT_COMMAND, "italic");
10049    } else if (isTab(event)) {
10050      dispatchCommand(editor, KEY_TAB_COMMAND, event);
10051    } else if (isUndo(event)) {
10052      event.preventDefault();
10053      dispatchCommand(editor, UNDO_COMMAND, void 0);
10054    } else if (isRedo(event)) {
10055      event.preventDefault();
10056      dispatchCommand(editor, REDO_COMMAND, void 0);
10057    } else {
10058      const prevSelection = editor._editorState._selection;
10059      if (prevSelection !== null && !$isRangeSelection(prevSelection)) {
10060        if (isCopy(event)) {
10061          event.preventDefault();
10062          dispatchCommand(editor, COPY_COMMAND, event);
10063        } else if (isCut(event)) {
10064          event.preventDefault();
10065          dispatchCommand(editor, CUT_COMMAND, event);
10066        } else if (isSelectAll(event)) {
10067          event.preventDefault();
10068          dispatchCommand(editor, SELECT_ALL_COMMAND, event);
10069        }
10070      } else if (isSelectAll(event)) {
10071        event.preventDefault();
10072        dispatchCommand(editor, SELECT_ALL_COMMAND, event);
10073      }
10074    }
10075    if (isModifier(event)) {
10076      editor.dispatchCommand(KEY_MODIFIER_COMMAND, event);
10077    }
10078    return true;
10079  }
10080  function getRootElementRemoveHandles(rootElement) {
10081    let eventHandles = rootElement.__lexicalEventHandles;
10082    if (eventHandles === void 0) {
10083      eventHandles = [];
10084      rootElement.__lexicalEventHandles = eventHandles;
10085    }
10086    return eventHandles;
10087  }
10088  var activeNestedEditorsMap = /* @__PURE__ */ new Map();
10089  function onDocumentSelectionChange(event) {
10090    const domSelection = getDOMSelectionFromTarget(event.target);
10091    if (domSelection === null) {
10092      return;
10093    }
10094    const nextActiveEditor = getNearestEditorFromDOMNode(domSelection.anchorNode);
10095    if (nextActiveEditor === null) {
10096      return;
10097    }
10098    if (isSelectionChangeFromMouseDown) {
10099      isSelectionChangeFromMouseDown = false;
10100      updateEditorSync(nextActiveEditor, () => {
10101        const lastSelection = $getPreviousSelection();
10102        const domAnchorNode = domSelection.anchorNode;
10103        if (isHTMLElement(domAnchorNode) || isDOMTextNode(domAnchorNode)) {
10104          const newSelection = $internalCreateRangeSelection(lastSelection, domSelection, nextActiveEditor, event);
10105          $setSelection(newSelection);
10106        }
10107      });
10108    }
10109    const editors = getEditorsToPropagate(nextActiveEditor);
10110    const rootEditor = editors[editors.length - 1];
10111    const rootEditorKey = rootEditor._key;
10112    const activeNestedEditor = activeNestedEditorsMap.get(rootEditorKey);
10113    const prevActiveEditor = activeNestedEditor || rootEditor;
10114    if (prevActiveEditor !== nextActiveEditor) {
10115      onSelectionChange(domSelection, prevActiveEditor, false);
10116    }
10117    onSelectionChange(domSelection, nextActiveEditor, true);
10118    if (nextActiveEditor !== rootEditor) {
10119      activeNestedEditorsMap.set(rootEditorKey, nextActiveEditor);
10120    } else if (activeNestedEditor) {
10121      activeNestedEditorsMap.delete(rootEditorKey);
10122    }
10123  }
10124  function stopLexicalPropagation(event) {
10125    event._lexicalHandled = true;
10126  }
10127  function hasStoppedLexicalPropagation(event) {
10128    const stopped = event._lexicalHandled === true;
10129    return stopped;
10130  }
10131  function addRootElementEvents(rootElement, editor) {
10132    const doc = rootElement.ownerDocument;
10133    rootElementToDocument.set(rootElement, doc);
10134    const documentRootElementsCount = rootElementsRegistered.get(doc) ?? 0;
10135    if (documentRootElementsCount < 1) {
10136      doc.addEventListener("selectionchange", onDocumentSelectionChange);
10137    }
10138    rootElementsRegistered.set(doc, documentRootElementsCount + 1);
10139    rootElement.__lexicalEditor = editor;
10140    const removeHandles = getRootElementRemoveHandles(rootElement);
10141    for (let i2 = 0; i2 < rootElementEvents.length; i2++) {
10142      const [eventName, onEvent] = rootElementEvents[i2];
10143      const eventHandler = typeof onEvent === "function" ? (event) => {
10144        if (hasStoppedLexicalPropagation(event)) {
10145          return;
10146        }
10147        stopLexicalPropagation(event);
10148        if (editor.isEditable() || eventName === "click") {
10149          onEvent(event, editor);
10150        }
10151      } : (event) => {
10152        if (hasStoppedLexicalPropagation(event)) {
10153          return;
10154        }
10155        stopLexicalPropagation(event);
10156        const isEditable = editor.isEditable();
10157        switch (eventName) {
10158          case "cut":
10159            return isEditable && dispatchCommand(editor, CUT_COMMAND, event);
10160          case "copy":
10161            return dispatchCommand(editor, COPY_COMMAND, event);
10162          case "paste":
10163            return isEditable && dispatchCommand(editor, PASTE_COMMAND, event);
10164          case "dragstart":
10165            return isEditable && dispatchCommand(editor, DRAGSTART_COMMAND, event);
10166          case "dragover":
10167            return isEditable && dispatchCommand(editor, DRAGOVER_COMMAND, event);
10168          case "dragend":
10169            return isEditable && dispatchCommand(editor, DRAGEND_COMMAND, event);
10170          case "focus":
10171            return isEditable && dispatchCommand(editor, FOCUS_COMMAND, event);
10172          case "blur": {
10173            return isEditable && dispatchCommand(editor, BLUR_COMMAND, event);
10174          }
10175          case "drop":
10176            return isEditable && dispatchCommand(editor, DROP_COMMAND, event);
10177        }
10178      };
10179      rootElement.addEventListener(eventName, eventHandler);
10180      removeHandles.push(() => {
10181        rootElement.removeEventListener(eventName, eventHandler);
10182      });
10183    }
10184  }
10185  var rootElementNotRegisteredWarning = warnOnlyOnce("Root element not registered");
10186  function removeRootElementEvents(rootElement) {
10187    const doc = rootElementToDocument.get(rootElement);
10188    if (doc === void 0) {
10189      rootElementNotRegisteredWarning();
10190      return;
10191    }
10192    const documentRootElementsCount = rootElementsRegistered.get(doc);
10193    if (documentRootElementsCount === void 0) {
10194      rootElementNotRegisteredWarning();
10195      return;
10196    }
10197    const newCount = documentRootElementsCount - 1;
10198    if (!(newCount >= 0)) {
10199      formatDevErrorMessage(`Root element count less than 0`);
10200    }
10201    rootElementToDocument.delete(rootElement);
10202    rootElementsRegistered.set(doc, newCount);
10203    if (newCount === 0) {
10204      doc.removeEventListener("selectionchange", onDocumentSelectionChange);
10205    }
10206    const editor = getEditorPropertyFromDOMNode(rootElement);
10207    if (isLexicalEditor(editor)) {
10208      cleanActiveNestedEditorsMap(editor);
10209      rootElement.__lexicalEditor = null;
10210    } else if (editor) {
10211      {
10212        formatDevErrorMessage(`Attempted to remove event handlers from a node that does not belong to this build of Lexical`);
10213      }
10214    }
10215    const removeHandles = getRootElementRemoveHandles(rootElement);
10216    for (let i2 = 0; i2 < removeHandles.length; i2++) {
10217      removeHandles[i2]();
10218    }
10219    rootElement.__lexicalEventHandles = [];
10220  }
10221  function cleanActiveNestedEditorsMap(editor) {
10222    if (editor._parentEditor !== null) {
10223      const editors = getEditorsToPropagate(editor);
10224      const rootEditor = editors[editors.length - 1];
10225      const rootEditorKey = rootEditor._key;
10226      if (activeNestedEditorsMap.get(rootEditorKey) === editor) {
10227        activeNestedEditorsMap.delete(rootEditorKey);
10228      }
10229    } else {
10230      activeNestedEditorsMap.delete(editor._key);
10231    }
10232  }
10233  function markSelectionChangeFromDOMUpdate() {
10234    isSelectionChangeFromDOMUpdate = true;
10235  }
10236  function markCollapsedSelectionFormat(format, style, offset3, key, timeStamp) {
10237    collapsedSelectionFormat = [format, style, offset3, key, timeStamp];
10238  }
10239  function $removeNode(nodeToRemove, restoreSelection, preserveEmptyParent) {
10240    errorOnReadOnly();
10241    const key = nodeToRemove.__key;
10242    const parent = nodeToRemove.getParent();
10243    if (parent === null) {
10244      return;
10245    }
10246    const selection = $maybeMoveChildrenSelectionToParent(nodeToRemove);
10247    let selectionMoved = false;
10248    if ($isRangeSelection(selection) && restoreSelection) {
10249      const anchor = selection.anchor;
10250      const focus = selection.focus;
10251      if (anchor.key === key) {
10252        moveSelectionPointToSibling(anchor, nodeToRemove, parent, nodeToRemove.getPreviousSibling(), nodeToRemove.getNextSibling());
10253        selectionMoved = true;
10254      }
10255      if (focus.key === key) {
10256        moveSelectionPointToSibling(focus, nodeToRemove, parent, nodeToRemove.getPreviousSibling(), nodeToRemove.getNextSibling());
10257        selectionMoved = true;
10258      }
10259    } else if ($isNodeSelection(selection) && restoreSelection && nodeToRemove.isSelected()) {
10260      nodeToRemove.selectPrevious();
10261    }
10262    if ($isRangeSelection(selection) && restoreSelection && !selectionMoved) {
10263      const index = nodeToRemove.getIndexWithinParent();
10264      removeFromParent(nodeToRemove);
10265      $updateElementSelectionOnCreateDeleteNode(selection, parent, index, -1);
10266    } else {
10267      removeFromParent(nodeToRemove);
10268    }
10269    if (!preserveEmptyParent && !$isRootOrShadowRoot(parent) && !parent.canBeEmpty() && parent.isEmpty()) {
10270      $removeNode(parent, restoreSelection);
10271    }
10272    if (restoreSelection && selection && $isRootNode(parent) && parent.isEmpty()) {
10273      parent.selectEnd();
10274    }
10275  }
10276  function buildImportMap(importMap) {
10277    return importMap;
10278  }
10279  var EPHEMERAL = Symbol.for("ephemeral");
10280  function $isEphemeral(node) {
10281    return node[EPHEMERAL] || false;
10282  }
10283  function $markEphemeral(node) {
10284    node[EPHEMERAL] = true;
10285    return node;
10286  }
10287  var LexicalNode = class {
10288    /** @internal Allow us to look up the type including static props */
10289    /** @internal */
10290    __type;
10291    /** @internal */
10292    //@ts-ignore We set the key in the constructor.
10293    __key;
10294    /** @internal */
10295    __parent;
10296    /** @internal */
10297    __prev;
10298    /** @internal */
10299    __next;
10300    /** @internal */
10301    __state;
10302    // Flow doesn't support abstract classes unfortunately, so we can't _force_
10303    // subclasses of Node to implement statics. All subclasses of Node should have
10304    // a static getType and clone method though. We define getType and clone here so we can call it
10305    // on any  Node, and we throw this error by default since the subclass should provide
10306    // their own implementation.
10307    /**
10308     * Returns the string type of this node. Every node must
10309     * implement this and it MUST BE UNIQUE amongst nodes registered
10310     * on the editor.
10311     *
10312     */
10313    static getType() {
10314      const {
10315        ownNodeType
10316      } = getStaticNodeConfig(this);
10317      if (!(ownNodeType !== void 0)) {
10318        formatDevErrorMessage(`LexicalNode: Node ${this.name} does not implement .getType().`);
10319      }
10320      return ownNodeType;
10321    }
10322    /**
10323     * Clones this node, creating a new node with a different key
10324     * and adding it to the EditorState (but not attaching it anywhere!). All nodes must
10325     * implement this method.
10326     *
10327     */
10328    static clone(_data) {
10329      {
10330        formatDevErrorMessage(`LexicalNode: Node ${this.name} does not implement .clone().`);
10331      }
10332    }
10333    /**
10334     * Override this to implement the new static node configuration protocol,
10335     * this method is called directly on the prototype and must not depend
10336     * on anything initialized in the constructor. Generally it should be
10337     * a trivial implementation.
10338     *
10339     * @example
10340     * ```ts
10341     * class MyNode extends TextNode {
10342     *   $config() {
10343     *     return this.config('my-node', {extends: TextNode});
10344     *   }
10345     * }
10346     * ```
10347     */
10348    $config() {
10349      return {};
10350    }
10351    /**
10352     * This is a convenience method for $config that
10353     * aids in type inference. See {@link LexicalNode.$config}
10354     * for example usage.
10355     */
10356    config(type, config) {
10357      const parentKlass = config.extends || Object.getPrototypeOf(this.constructor);
10358      Object.assign(config, {
10359        extends: parentKlass,
10360        type
10361      });
10362      return {
10363        [type]: config
10364      };
10365    }
10366    /**
10367     * Perform any state updates on the clone of prevNode that are not already
10368     * handled by the constructor call in the static clone method. If you have
10369     * state to update in your clone that is not handled directly by the
10370     * constructor, it is advisable to override this method but it is required
10371     * to include a call to `super.afterCloneFrom(prevNode)` in your
10372     * implementation. This is only intended to be called by
10373     * {@link $cloneWithProperties} function or via a super call.
10374     *
10375     * @example
10376     * ```ts
10377     * class ClassesTextNode extends TextNode {
10378     *   // Not shown: static getType, static importJSON, exportJSON, createDOM, updateDOM
10379     *   __classes = new Set<string>();
10380     *   static clone(node: ClassesTextNode): ClassesTextNode {
10381     *     // The inherited TextNode constructor is used here, so
10382     *     // classes is not set by this method.
10383     *     return new ClassesTextNode(node.__text, node.__key);
10384     *   }
10385     *   afterCloneFrom(node: this): void {
10386     *     // This calls TextNode.afterCloneFrom and LexicalNode.afterCloneFrom
10387     *     // for necessary state updates
10388     *     super.afterCloneFrom(node);
10389     *     this.__addClasses(node.__classes);
10390     *   }
10391     *   // This method is a private implementation detail, it is not
10392     *   // suitable for the public API because it does not call getWritable
10393     *   __addClasses(classNames: Iterable<string>): this {
10394     *     for (const className of classNames) {
10395     *       this.__classes.add(className);
10396     *     }
10397     *     return this;
10398     *   }
10399     *   addClass(...classNames: string[]): this {
10400     *     return this.getWritable().__addClasses(classNames);
10401     *   }
10402     *   removeClass(...classNames: string[]): this {
10403     *     const node = this.getWritable();
10404     *     for (const className of classNames) {
10405     *       this.__classes.delete(className);
10406     *     }
10407     *     return this;
10408     *   }
10409     *   getClasses(): Set<string> {
10410     *     return this.getLatest().__classes;
10411     *   }
10412     * }
10413     * ```
10414     *
10415     */
10416    afterCloneFrom(prevNode) {
10417      if (this.__key === prevNode.__key) {
10418        this.__parent = prevNode.__parent;
10419        this.__next = prevNode.__next;
10420        this.__prev = prevNode.__prev;
10421        this.__state = prevNode.__state;
10422      } else if (prevNode.__state) {
10423        this.__state = prevNode.__state.getWritable(this);
10424      }
10425    }
10426    /**
10427     * Reset state in this copy of originalNode, if necessary
10428     *
10429     * @param originalNode
10430     */
10431    resetOnCopyNodeFrom(originalNode) {
10432      if (this.__state) {
10433        this.__state = this.__state.getWritable(this).resetOnCopyNode();
10434      }
10435    }
10436    // eslint-disable-next-line @typescript-eslint/no-explicit-any
10437    static importDOM;
10438    constructor(key) {
10439      this.__type = this.constructor.getType();
10440      this.__parent = null;
10441      this.__prev = null;
10442      this.__next = null;
10443      Object.defineProperty(this, "__state", {
10444        configurable: true,
10445        enumerable: false,
10446        value: void 0,
10447        writable: true
10448      });
10449      $setNodeKey(this, key);
10450      {
10451        if (this.__type !== "root") {
10452          errorOnTypeKlassMismatch(this.__type, this.constructor);
10453        }
10454      }
10455    }
10456    // Getters and Traversers
10457    /**
10458     * Returns the string type of this node.
10459     */
10460    getType() {
10461      return this.__type;
10462    }
10463    isInline() {
10464      {
10465        formatDevErrorMessage(`LexicalNode: Node ${this.constructor.name} does not implement .isInline().`);
10466      }
10467    }
10468    /**
10469     * Returns true if there is a path between this node and the RootNode, false otherwise.
10470     * This is a way of determining if the node is "attached" EditorState. Unattached nodes
10471     * won't be reconciled and will ultimately be cleaned up by the Lexical GC.
10472     */
10473    isAttached() {
10474      let nodeKey = this.__key;
10475      while (nodeKey !== null) {
10476        if (nodeKey === "root") {
10477          return true;
10478        }
10479        const node = $getNodeByKey(nodeKey);
10480        if (node === null) {
10481          break;
10482        }
10483        nodeKey = node.__parent;
10484      }
10485      return false;
10486    }
10487    /**
10488     * Returns true if this node is contained within the provided Selection., false otherwise.
10489     * Relies on the algorithms implemented in {@link BaseSelection.getNodes} to determine
10490     * what's included.
10491     *
10492     * @param selection - The selection that we want to determine if the node is in.
10493     */
10494    isSelected(selection) {
10495      const targetSelection = selection || $getSelection();
10496      if (targetSelection == null) {
10497        return false;
10498      }
10499      const isSelected = targetSelection.getNodes().some((n2) => n2.__key === this.__key);
10500      if ($isTextNode(this)) {
10501        return isSelected;
10502      }
10503      const isElementRangeSelection = $isRangeSelection(targetSelection) && targetSelection.anchor.type === "element" && targetSelection.focus.type === "element";
10504      if (isElementRangeSelection) {
10505        if (targetSelection.isCollapsed()) {
10506          return false;
10507        }
10508        const parentNode = this.getParent();
10509        if ($isDecoratorNode(this) && this.isInline() && parentNode) {
10510          const firstPoint = targetSelection.isBackward() ? targetSelection.focus : targetSelection.anchor;
10511          if (parentNode.is(firstPoint.getNode()) && firstPoint.offset === parentNode.getChildrenSize() && this.is(parentNode.getLastChild())) {
10512            return false;
10513          }
10514        }
10515      }
10516      return isSelected;
10517    }
10518    /**
10519     * Returns this nodes key.
10520     */
10521    getKey() {
10522      return this.__key;
10523    }
10524    /**
10525     * Returns the zero-based index of this node within the parent.
10526     */
10527    getIndexWithinParent() {
10528      const parent = this.getParent();
10529      if (parent === null) {
10530        return -1;
10531      }
10532      let node = parent.getFirstChild();
10533      let index = 0;
10534      while (node !== null) {
10535        if (this.is(node)) {
10536          return index;
10537        }
10538        index++;
10539        node = node.getNextSibling();
10540      }
10541      return -1;
10542    }
10543    /**
10544     * Returns the parent of this node, or null if none is found.
10545     */
10546    getParent() {
10547      const parent = this.getLatest().__parent;
10548      if (parent === null) {
10549        return null;
10550      }
10551      return $getNodeByKey(parent);
10552    }
10553    /**
10554     * Returns the parent of this node, or throws if none is found.
10555     */
10556    getParentOrThrow() {
10557      const parent = this.getParent();
10558      if (parent === null) {
10559        {
10560          formatDevErrorMessage(`Expected node ${this.__key} to have a parent.`);
10561        }
10562      }
10563      return parent;
10564    }
10565    /**
10566     * Returns the highest (in the EditorState tree)
10567     * non-root ancestor of this node, or null if none is found. See {@link lexical!$isRootOrShadowRoot}
10568     * for more information on which Elements comprise "roots".
10569     */
10570    getTopLevelElement() {
10571      let node = this;
10572      while (node !== null) {
10573        const parent = node.getParent();
10574        if ($isRootOrShadowRoot(parent)) {
10575          if (!($isElementNode(node) || node === this && $isDecoratorNode(node))) {
10576            formatDevErrorMessage(`Children of root nodes must be elements or decorators`);
10577          }
10578          return node;
10579        }
10580        node = parent;
10581      }
10582      return null;
10583    }
10584    /**
10585     * Returns the highest (in the EditorState tree)
10586     * non-root ancestor of this node, or throws if none is found. See {@link lexical!$isRootOrShadowRoot}
10587     * for more information on which Elements comprise "roots".
10588     */
10589    getTopLevelElementOrThrow() {
10590      const parent = this.getTopLevelElement();
10591      if (parent === null) {
10592        {
10593          formatDevErrorMessage(`Expected node ${this.__key} to have a top parent element.`);
10594        }
10595      }
10596      return parent;
10597    }
10598    /**
10599     * Returns a list of the every ancestor of this node,
10600     * all the way up to the RootNode.
10601     *
10602     */
10603    getParents() {
10604      const parents = [];
10605      let node = this.getParent();
10606      while (node !== null) {
10607        parents.push(node);
10608        node = node.getParent();
10609      }
10610      return parents;
10611    }
10612    /**
10613     * Returns a list of the keys of every ancestor of this node,
10614     * all the way up to the RootNode.
10615     *
10616     */
10617    getParentKeys() {
10618      const parents = [];
10619      let node = this.getParent();
10620      while (node !== null) {
10621        parents.push(node.__key);
10622        node = node.getParent();
10623      }
10624      return parents;
10625    }
10626    /**
10627     * Returns the "previous" siblings - that is, the node that comes
10628     * before this one in the same parent.
10629     *
10630     */
10631    getPreviousSibling() {
10632      const self2 = this.getLatest();
10633      const prevKey = self2.__prev;
10634      return prevKey === null ? null : $getNodeByKey(prevKey);
10635    }
10636    /**
10637     * Returns the "previous" siblings - that is, the nodes that come between
10638     * this one and the first child of it's parent, inclusive.
10639     *
10640     */
10641    getPreviousSiblings() {
10642      const siblings = [];
10643      const parent = this.getParent();
10644      if (parent === null) {
10645        return siblings;
10646      }
10647      let node = parent.getFirstChild();
10648      while (node !== null) {
10649        if (node.is(this)) {
10650          break;
10651        }
10652        siblings.push(node);
10653        node = node.getNextSibling();
10654      }
10655      return siblings;
10656    }
10657    /**
10658     * Returns the "next" siblings - that is, the node that comes
10659     * after this one in the same parent
10660     *
10661     */
10662    getNextSibling() {
10663      const self2 = this.getLatest();
10664      const nextKey = self2.__next;
10665      return nextKey === null ? null : $getNodeByKey(nextKey);
10666    }
10667    /**
10668     * Returns all "next" siblings - that is, the nodes that come between this
10669     * one and the last child of it's parent, inclusive.
10670     *
10671     */
10672    getNextSiblings() {
10673      const siblings = [];
10674      let node = this.getNextSibling();
10675      while (node !== null) {
10676        siblings.push(node);
10677        node = node.getNextSibling();
10678      }
10679      return siblings;
10680    }
10681    /**
10682     * @deprecated use {@link $getCommonAncestor}
10683     *
10684     * Returns the closest common ancestor of this node and the provided one or null
10685     * if one cannot be found.
10686     *
10687     * @param node - the other node to find the common ancestor of.
10688     */
10689    getCommonAncestor(node) {
10690      const a2 = $isElementNode(this) ? this : this.getParent();
10691      const b3 = $isElementNode(node) ? node : node.getParent();
10692      const result = a2 && b3 ? $getCommonAncestor(a2, b3) : null;
10693      return result ? result.commonAncestor : null;
10694    }
10695    /**
10696     * Returns true if the provided node is the exact same one as this node, from Lexical's perspective.
10697     * Always use this instead of referential equality.
10698     *
10699     * @param object - the node to perform the equality comparison on.
10700     */
10701    is(object) {
10702      if (object == null) {
10703        return false;
10704      }
10705      return this.__key === object.__key;
10706    }
10707    /**
10708     * Returns true if this node logically precedes the target node in the
10709     * editor state, false otherwise (including if there is no common ancestor).
10710     *
10711     * Note that this notion of isBefore is based on post-order; a descendant
10712     * node is always before its ancestors. See also
10713     * {@link $getCommonAncestor} and {@link $comparePointCaretNext} for
10714     * more flexible ways to determine the relative positions of nodes.
10715     *
10716     * @param targetNode - the node we're testing to see if it's after this one.
10717     */
10718    isBefore(targetNode) {
10719      const compare = $getCommonAncestor(this, targetNode);
10720      if (compare === null) {
10721        return false;
10722      }
10723      if (compare.type === "descendant") {
10724        return true;
10725      }
10726      if (compare.type === "branch") {
10727        return $getCommonAncestorResultBranchOrder(compare) === -1;
10728      }
10729      if (!(compare.type === "same" || compare.type === "ancestor")) {
10730        formatDevErrorMessage(`LexicalNode.isBefore: exhaustiveness check`);
10731      }
10732      return false;
10733    }
10734    /**
10735     * Returns true if this node is an ancestor of and distinct from the target node, false otherwise.
10736     *
10737     * @param targetNode - the would-be child node.
10738     */
10739    isParentOf(targetNode) {
10740      const result = $getCommonAncestor(this, targetNode);
10741      return result !== null && result.type === "ancestor";
10742    }
10743    // TO-DO: this function can be simplified a lot
10744    /**
10745     * Returns a list of nodes that are between this node and
10746     * the target node in the EditorState.
10747     *
10748     * @param targetNode - the node that marks the other end of the range of nodes to be returned.
10749     */
10750    getNodesBetween(targetNode) {
10751      const isBefore = this.isBefore(targetNode);
10752      const nodes = [];
10753      const visited = /* @__PURE__ */ new Set();
10754      let node = this;
10755      while (true) {
10756        if (node === null) {
10757          break;
10758        }
10759        const key = node.__key;
10760        if (!visited.has(key)) {
10761          visited.add(key);
10762          nodes.push(node);
10763        }
10764        if (node === targetNode) {
10765          break;
10766        }
10767        const child = $isElementNode(node) ? isBefore ? node.getFirstChild() : node.getLastChild() : null;
10768        if (child !== null) {
10769          node = child;
10770          continue;
10771        }
10772        const nextSibling = isBefore ? node.getNextSibling() : node.getPreviousSibling();
10773        if (nextSibling !== null) {
10774          node = nextSibling;
10775          continue;
10776        }
10777        const parent = node.getParentOrThrow();
10778        if (!visited.has(parent.__key)) {
10779          nodes.push(parent);
10780        }
10781        if (parent === targetNode) {
10782          break;
10783        }
10784        let parentSibling = null;
10785        let ancestor = parent;
10786        do {
10787          if (ancestor === null) {
10788            {
10789              formatDevErrorMessage(`getNodesBetween: ancestor is null`);
10790            }
10791          }
10792          parentSibling = isBefore ? ancestor.getNextSibling() : ancestor.getPreviousSibling();
10793          ancestor = ancestor.getParent();
10794          if (ancestor !== null) {
10795            if (parentSibling === null && !visited.has(ancestor.__key)) {
10796              nodes.push(ancestor);
10797            }
10798          } else {
10799            break;
10800          }
10801        } while (parentSibling === null);
10802        node = parentSibling;
10803      }
10804      if (!isBefore) {
10805        nodes.reverse();
10806      }
10807      return nodes;
10808    }
10809    /**
10810     * Returns true if this node has been marked dirty during this update cycle.
10811     *
10812     */
10813    isDirty() {
10814      const editor = getActiveEditor();
10815      const dirtyLeaves = editor._dirtyLeaves;
10816      return dirtyLeaves !== null && dirtyLeaves.has(this.__key);
10817    }
10818    /**
10819     * Returns the latest version of the node from the active EditorState.
10820     * This is used to avoid getting values from stale node references.
10821     *
10822     */
10823    getLatest() {
10824      if ($isEphemeral(this)) {
10825        return this;
10826      }
10827      const latest = $getNodeByKey(this.__key);
10828      if (latest === null) {
10829        {
10830          formatDevErrorMessage(`Lexical node does not exist in active editor state. Avoid using the same node references between nested closures from editorState.read/editor.update.`);
10831        }
10832      }
10833      return latest;
10834    }
10835    /**
10836     * Returns a mutable version of the node using {@link $cloneWithProperties}
10837     * if necessary. Will throw an error if called outside of a Lexical Editor
10838     * {@link LexicalEditor.update} callback.
10839     *
10840     */
10841    getWritable() {
10842      if ($isEphemeral(this)) {
10843        return this;
10844      }
10845      errorOnReadOnly();
10846      const editorState = getActiveEditorState();
10847      const editor = getActiveEditor();
10848      const nodeMap = editorState._nodeMap;
10849      const key = this.__key;
10850      const latestNode = this.getLatest();
10851      const cloneNotNeeded = editor._cloneNotNeeded;
10852      const selection = $getSelection();
10853      if (selection !== null) {
10854        selection.setCachedNodes(null);
10855      }
10856      if (cloneNotNeeded.has(key)) {
10857        internalMarkNodeAsDirty(latestNode);
10858        return latestNode;
10859      }
10860      const mutableNode = $cloneWithProperties(latestNode);
10861      cloneNotNeeded.add(key);
10862      internalMarkNodeAsDirty(mutableNode);
10863      nodeMap.set(key, mutableNode);
10864      return mutableNode;
10865    }
10866    /**
10867     * Returns the text content of the node. Override this for
10868     * custom nodes that should have a representation in plain text
10869     * format (for copy + paste, for example)
10870     *
10871     */
10872    getTextContent() {
10873      return "";
10874    }
10875    /**
10876     * Returns the length of the string produced by calling getTextContent on this node.
10877     *
10878     */
10879    getTextContentSize() {
10880      return this.getTextContent().length;
10881    }
10882    // View
10883    /**
10884     * Called during the reconciliation process to determine which nodes
10885     * to insert into the DOM for this Lexical Node.
10886     *
10887     * This method must return exactly one HTMLElement. Nested elements are not supported.
10888     *
10889     * Do not attempt to update the Lexical EditorState during this phase of the update lifecycle.
10890     *
10891     * @param _config - allows access to things like the EditorTheme (to apply classes) during reconciliation.
10892     * @param _editor - allows access to the editor for context during reconciliation.
10893     *
10894     * */
10895    createDOM(_config, _editor) {
10896      {
10897        formatDevErrorMessage(`createDOM: base method not extended`);
10898      }
10899    }
10900    /**
10901     * Called when a node changes and should update the DOM
10902     * in whatever way is necessary to make it align with any changes that might
10903     * have happened during the update.
10904     *
10905     * Returning "true" here will cause lexical to unmount and recreate the DOM node
10906     * (by calling createDOM). You would need to do this if the element tag changes,
10907     * for instance.
10908     *
10909     * */
10910    updateDOM(_prevNode, _dom, _config) {
10911      {
10912        formatDevErrorMessage(`updateDOM: base method not extended`);
10913      }
10914    }
10915    /**
10916     * Controls how the this node is serialized to HTML. This is important for
10917     * copy and paste between Lexical and non-Lexical editors, or Lexical editors with different namespaces,
10918     * in which case the primary transfer format is HTML. It's also important if you're serializing
10919     * to HTML for any other reason via {@link @lexical/html!$generateHtmlFromNodes}. You could
10920     * also use this method to build your own HTML renderer.
10921     *
10922     * */
10923    exportDOM(editor) {
10924      const element = this.createDOM(editor._config, editor);
10925      return {
10926        element
10927      };
10928    }
10929    /**
10930     * Controls how the this node is serialized to JSON. This is important for
10931     * copy and paste between Lexical editors sharing the same namespace. It's also important
10932     * if you're serializing to JSON for persistent storage somewhere.
10933     * See [Serialization & Deserialization](https://lexical.dev/docs/concepts/serialization#lexical---html).
10934     *
10935     * */
10936    exportJSON() {
10937      const state = this.__state ? this.__state.toJSON() : void 0;
10938      return {
10939        type: this.__type,
10940        version: 1,
10941        ...state
10942      };
10943    }
10944    /**
10945     * Controls how the this node is deserialized from JSON. This is usually boilerplate,
10946     * but provides an abstraction between the node implementation and serialized interface that can
10947     * be important if you ever make breaking changes to a node schema (by adding or removing properties).
10948     * See [Serialization & Deserialization](https://lexical.dev/docs/concepts/serialization#lexical---html).
10949     *
10950     * */
10951    static importJSON(_serializedNode) {
10952      {
10953        formatDevErrorMessage(`LexicalNode: Node ${this.name} does not implement .importJSON().`);
10954      }
10955    }
10956    /**
10957     * Update this LexicalNode instance from serialized JSON. It's recommended
10958     * to implement as much logic as possible in this method instead of the
10959     * static importJSON method, so that the functionality can be inherited in subclasses.
10960     *
10961     * The LexicalUpdateJSON utility type should be used to ignore any type, version,
10962     * or children properties in the JSON so that the extended JSON from subclasses
10963     * are acceptable parameters for the super call.
10964     *
10965     * If overridden, this method must call super.
10966     *
10967     * @example
10968     * ```ts
10969     * class MyTextNode extends TextNode {
10970     *   // ...
10971     *   static importJSON(serializedNode: SerializedMyTextNode): MyTextNode {
10972     *     return $createMyTextNode()
10973     *       .updateFromJSON(serializedNode);
10974     *   }
10975     *   updateFromJSON(
10976     *     serializedNode: LexicalUpdateJSON<SerializedMyTextNode>,
10977     *   ): this {
10978     *     return super.updateFromJSON(serializedNode)
10979     *       .setMyProperty(serializedNode.myProperty);
10980     *   }
10981     * }
10982     * ```
10983     **/
10984    updateFromJSON(serializedNode) {
10985      return $updateStateFromJSON(this, serializedNode);
10986    }
10987    /**
10988     * @experimental
10989     *
10990     * Registers the returned function as a transform on the node during
10991     * Editor initialization. Most such use cases should be addressed via
10992     * the {@link LexicalEditor.registerNodeTransform} API.
10993     *
10994     * Experimental - use at your own risk.
10995     */
10996    static transform() {
10997      return null;
10998    }
10999    // Setters and mutators
11000    /**
11001     * Removes this LexicalNode from the EditorState. If the node isn't re-inserted
11002     * somewhere, the Lexical garbage collector will eventually clean it up.
11003     *
11004     * @param preserveEmptyParent - If falsy, the node's parent will be removed if
11005     * it's empty after the removal operation. This is the default behavior, subject to
11006     * other node heuristics such as {@link ElementNode#canBeEmpty}
11007     * */
11008    remove(preserveEmptyParent) {
11009      $removeNode(this, true, preserveEmptyParent);
11010    }
11011    /**
11012     * Replaces this LexicalNode with the provided node, optionally transferring the children
11013     * of the replaced node to the replacing node.
11014     *
11015     * @param replaceWith - The node to replace this one with.
11016     * @param includeChildren - Whether or not to transfer the children of this node to the replacing node.
11017     * */
11018    replace(replaceWith, includeChildren) {
11019      errorOnReadOnly();
11020      let selection = $getSelection();
11021      if (selection !== null) {
11022        selection = selection.clone();
11023      }
11024      errorOnInsertTextNodeOnRoot(this, replaceWith);
11025      const self2 = this.getLatest();
11026      const toReplaceKey = this.__key;
11027      const key = replaceWith.__key;
11028      const writableReplaceWith = replaceWith.getWritable();
11029      const writableParent = this.getParentOrThrow().getWritable();
11030      const size2 = writableParent.__size;
11031      removeFromParent(writableReplaceWith);
11032      const prevSibling = self2.getPreviousSibling();
11033      const nextSibling = self2.getNextSibling();
11034      const prevKey = self2.__prev;
11035      const nextKey = self2.__next;
11036      const parentKey = self2.__parent;
11037      $removeNode(self2, false, true);
11038      if (prevSibling === null) {
11039        writableParent.__first = key;
11040      } else {
11041        const writablePrevSibling = prevSibling.getWritable();
11042        writablePrevSibling.__next = key;
11043      }
11044      writableReplaceWith.__prev = prevKey;
11045      if (nextSibling === null) {
11046        writableParent.__last = key;
11047      } else {
11048        const writableNextSibling = nextSibling.getWritable();
11049        writableNextSibling.__prev = key;
11050      }
11051      writableReplaceWith.__next = nextKey;
11052      writableReplaceWith.__parent = parentKey;
11053      writableParent.__size = size2;
11054      if (includeChildren) {
11055        if (!($isElementNode(this) && $isElementNode(writableReplaceWith))) {
11056          formatDevErrorMessage(`includeChildren should only be true for ElementNodes`);
11057        }
11058        this.getChildren().forEach((child) => {
11059          writableReplaceWith.append(child);
11060        });
11061      }
11062      if ($isRangeSelection(selection)) {
11063        $setSelection(selection);
11064        const anchor = selection.anchor;
11065        const focus = selection.focus;
11066        if (anchor.key === toReplaceKey) {
11067          $moveSelectionPointToEnd(anchor, writableReplaceWith);
11068        }
11069        if (focus.key === toReplaceKey) {
11070          $moveSelectionPointToEnd(focus, writableReplaceWith);
11071        }
11072      }
11073      if ($getCompositionKey() === toReplaceKey) {
11074        $setCompositionKey(key);
11075      }
11076      return writableReplaceWith;
11077    }
11078    /**
11079     * Inserts a node after this LexicalNode (as the next sibling).
11080     *
11081     * @param nodeToInsert - The node to insert after this one.
11082     * @param restoreSelection - Whether or not to attempt to resolve the
11083     * selection to the appropriate place after the operation is complete.
11084     * */
11085    insertAfter(nodeToInsert, restoreSelection = true) {
11086      errorOnReadOnly();
11087      errorOnInsertTextNodeOnRoot(this, nodeToInsert);
11088      const writableSelf = this.getWritable();
11089      const writableNodeToInsert = nodeToInsert.getWritable();
11090      const oldParent = writableNodeToInsert.getParent();
11091      const selection = $getSelection();
11092      let elementAnchorSelectionOnNode = false;
11093      let elementFocusSelectionOnNode = false;
11094      if (oldParent !== null) {
11095        const oldIndex = nodeToInsert.getIndexWithinParent();
11096        removeFromParent(writableNodeToInsert);
11097        if ($isRangeSelection(selection)) {
11098          const oldParentKey = oldParent.__key;
11099          const anchor = selection.anchor;
11100          const focus = selection.focus;
11101          elementAnchorSelectionOnNode = anchor.type === "element" && anchor.key === oldParentKey && anchor.offset === oldIndex + 1;
11102          elementFocusSelectionOnNode = focus.type === "element" && focus.key === oldParentKey && focus.offset === oldIndex + 1;
11103        }
11104      }
11105      const nextSibling = this.getNextSibling();
11106      const writableParent = this.getParentOrThrow().getWritable();
11107      const insertKey = writableNodeToInsert.__key;
11108      const nextKey = writableSelf.__next;
11109      if (nextSibling === null) {
11110        writableParent.__last = insertKey;
11111      } else {
11112        const writableNextSibling = nextSibling.getWritable();
11113        writableNextSibling.__prev = insertKey;
11114      }
11115      writableParent.__size++;
11116      writableSelf.__next = insertKey;
11117      writableNodeToInsert.__next = nextKey;
11118      writableNodeToInsert.__prev = writableSelf.__key;
11119      writableNodeToInsert.__parent = writableSelf.__parent;
11120      if (restoreSelection && $isRangeSelection(selection)) {
11121        const index = this.getIndexWithinParent();
11122        $updateElementSelectionOnCreateDeleteNode(selection, writableParent, index + 1);
11123        const writableParentKey = writableParent.__key;
11124        if (elementAnchorSelectionOnNode) {
11125          selection.anchor.set(writableParentKey, index + 2, "element");
11126        }
11127        if (elementFocusSelectionOnNode) {
11128          selection.focus.set(writableParentKey, index + 2, "element");
11129        }
11130      }
11131      return nodeToInsert;
11132    }
11133    /**
11134     * Inserts a node before this LexicalNode (as the previous sibling).
11135     *
11136     * @param nodeToInsert - The node to insert before this one.
11137     * @param restoreSelection - Whether or not to attempt to resolve the
11138     * selection to the appropriate place after the operation is complete.
11139     * */
11140    insertBefore(nodeToInsert, restoreSelection = true) {
11141      errorOnReadOnly();
11142      errorOnInsertTextNodeOnRoot(this, nodeToInsert);
11143      const writableSelf = this.getWritable();
11144      const writableNodeToInsert = nodeToInsert.getWritable();
11145      const insertKey = writableNodeToInsert.__key;
11146      removeFromParent(writableNodeToInsert);
11147      const prevSibling = this.getPreviousSibling();
11148      const writableParent = this.getParentOrThrow().getWritable();
11149      const prevKey = writableSelf.__prev;
11150      const index = this.getIndexWithinParent();
11151      if (prevSibling === null) {
11152        writableParent.__first = insertKey;
11153      } else {
11154        const writablePrevSibling = prevSibling.getWritable();
11155        writablePrevSibling.__next = insertKey;
11156      }
11157      writableParent.__size++;
11158      writableSelf.__prev = insertKey;
11159      writableNodeToInsert.__prev = prevKey;
11160      writableNodeToInsert.__next = writableSelf.__key;
11161      writableNodeToInsert.__parent = writableSelf.__parent;
11162      const selection = $getSelection();
11163      if (restoreSelection && $isRangeSelection(selection)) {
11164        const parent = this.getParentOrThrow();
11165        $updateElementSelectionOnCreateDeleteNode(selection, parent, index);
11166      }
11167      return nodeToInsert;
11168    }
11169    /**
11170     * Whether or not this node has a required parent. Used during copy + paste operations
11171     * to normalize nodes that would otherwise be orphaned. For example, ListItemNodes without
11172     * a ListNode parent or TextNodes with a ParagraphNode parent.
11173     *
11174     * */
11175    isParentRequired() {
11176      return false;
11177    }
11178    /**
11179     * The creation logic for any required parent. Should be implemented if {@link isParentRequired} returns true.
11180     *
11181     * */
11182    createParentElementNode() {
11183      return $createParagraphNode();
11184    }
11185    selectStart() {
11186      return this.selectPrevious();
11187    }
11188    selectEnd() {
11189      return this.selectNext(0, 0);
11190    }
11191    /**
11192     * Moves selection to the previous sibling of this node, at the specified offsets.
11193     *
11194     * @param anchorOffset - The anchor offset for selection.
11195     * @param focusOffset -  The focus offset for selection
11196     * */
11197    selectPrevious(anchorOffset, focusOffset) {
11198      errorOnReadOnly();
11199      const prevSibling = this.getPreviousSibling();
11200      const parent = this.getParentOrThrow();
11201      if (prevSibling === null) {
11202        return parent.select(0, 0);
11203      }
11204      if ($isElementNode(prevSibling)) {
11205        return prevSibling.select();
11206      } else if (!$isTextNode(prevSibling)) {
11207        const index = prevSibling.getIndexWithinParent() + 1;
11208        return parent.select(index, index);
11209      }
11210      return prevSibling.select(anchorOffset, focusOffset);
11211    }
11212    /**
11213     * Moves selection to the next sibling of this node, at the specified offsets.
11214     *
11215     * @param anchorOffset - The anchor offset for selection.
11216     * @param focusOffset -  The focus offset for selection
11217     * */
11218    selectNext(anchorOffset, focusOffset) {
11219      errorOnReadOnly();
11220      const nextSibling = this.getNextSibling();
11221      const parent = this.getParentOrThrow();
11222      if (nextSibling === null) {
11223        return parent.select();
11224      }
11225      if ($isElementNode(nextSibling)) {
11226        return nextSibling.select(0, 0);
11227      } else if (!$isTextNode(nextSibling)) {
11228        const index = nextSibling.getIndexWithinParent();
11229        return parent.select(index, index);
11230      }
11231      return nextSibling.select(anchorOffset, focusOffset);
11232    }
11233    /**
11234     * Marks a node dirty, triggering transforms and
11235     * forcing it to be reconciled during the update cycle.
11236     *
11237     * */
11238    markDirty() {
11239      this.getWritable();
11240    }
11241    /**
11242     * @internal
11243     *
11244     * When the reconciler detects that a node was mutated, this method
11245     * may be called to restore the node to a known good state.
11246     */
11247    reconcileObservedMutation(dom, editor) {
11248      this.markDirty();
11249    }
11250  };
11251  function errorOnTypeKlassMismatch(type, klass) {
11252    const registeredNode = getRegisteredNode(getActiveEditor(), type);
11253    if (registeredNode === void 0) {
11254      {
11255        formatDevErrorMessage(`Create node: Attempted to create node ${klass.name} that was not configured to be used on the editor.`);
11256      }
11257    }
11258    const editorKlass = registeredNode.klass;
11259    if (editorKlass !== klass) {
11260      {
11261        formatDevErrorMessage(`Create node: Type ${type} in node ${klass.name} does not match registered node ${editorKlass.name} with the same type`);
11262      }
11263    }
11264  }
11265  function insertRangeAfter(node, firstToInsert, lastToInsert) {
11266    const lastToInsert2 = firstToInsert.getParentOrThrow().getLastChild();
11267    let current = firstToInsert;
11268    const nodesToInsert = [firstToInsert];
11269    while (current !== lastToInsert2) {
11270      if (!current.getNextSibling()) {
11271        {
11272          formatDevErrorMessage(`insertRangeAfter: lastToInsert must be a later sibling of firstToInsert`);
11273        }
11274      }
11275      current = current.getNextSibling();
11276      nodesToInsert.push(current);
11277    }
11278    let currentNode = node;
11279    for (const nodeToInsert of nodesToInsert) {
11280      currentNode = currentNode.insertAfter(nodeToInsert);
11281    }
11282  }
11283  function $isLexicalNode(node) {
11284    return node instanceof LexicalNode;
11285  }
11286  var HISTORIC_TAG = "historic";
11287  var HISTORY_PUSH_TAG = "history-push";
11288  var HISTORY_MERGE_TAG = "history-merge";
11289  var PASTE_TAG = "paste";
11290  var COLLABORATION_TAG = "collaboration";
11291  var SKIP_COLLAB_TAG = "skip-collab";
11292  var SKIP_SCROLL_INTO_VIEW_TAG = "skip-scroll-into-view";
11293  var SKIP_DOM_SELECTION_TAG = "skip-dom-selection";
11294  var SKIP_SELECTION_FOCUS_TAG = "skip-selection-focus";
11295  var FOCUS_TAG = "focus";
11296  var COMPOSITION_START_TAG = "composition-start";
11297  var COMPOSITION_END_TAG = "composition-end";
11298  var IMPORTANT_REG_EXP = /\s*!important\s*$/i;
11299  function getStyleObjectFromCSS(css) {
11300    const styles = {};
11301    if (!css) {
11302      return styles;
11303    }
11304    let currentProperty = "";
11305    let currentValue = "";
11306    let currentQuote = null;
11307    let inComment = false;
11308    let isEscaped = false;
11309    let isParsingValue = false;
11310    let parenthesisDepth = 0;
11311    for (let i2 = 0; i2 < css.length; i2++) {
11312      const char = css[i2];
11313      if (inComment) {
11314        if (char === "*" && css[i2 + 1] === "/") {
11315          inComment = false;
11316          i2++;
11317        }
11318        continue;
11319      }
11320      if (isEscaped) {
11321        if (isParsingValue) {
11322          currentValue += char;
11323        } else {
11324          currentProperty += char;
11325        }
11326        isEscaped = false;
11327        continue;
11328      }
11329      if (currentQuote !== null) {
11330        if (isParsingValue) {
11331          currentValue += char;
11332        } else {
11333          currentProperty += char;
11334        }
11335        if (char === "\\") {
11336          isEscaped = true;
11337        } else if (char === currentQuote) {
11338          currentQuote = null;
11339        }
11340        continue;
11341      }
11342      if (char === "/" && css[i2 + 1] === "*") {
11343        inComment = true;
11344        i2++;
11345        continue;
11346      }
11347      if (char === '"' || char === "'") {
11348        currentQuote = char;
11349        if (isParsingValue) {
11350          currentValue += char;
11351        } else {
11352          currentProperty += char;
11353        }
11354        continue;
11355      }
11356      if (char === "(") {
11357        parenthesisDepth++;
11358        if (isParsingValue) {
11359          currentValue += char;
11360        } else {
11361          currentProperty += char;
11362        }
11363        continue;
11364      }
11365      if (char === ")") {
11366        parenthesisDepth = Math.max(0, parenthesisDepth - 1);
11367        if (isParsingValue) {
11368          currentValue += char;
11369        } else {
11370          currentProperty += char;
11371        }
11372        continue;
11373      }
11374      if (!isParsingValue && char === ":" && parenthesisDepth === 0) {
11375        isParsingValue = true;
11376        continue;
11377      }
11378      if (char === ";" && parenthesisDepth === 0) {
11379        const property2 = currentProperty.trim();
11380        const value2 = currentValue.trim();
11381        if (property2 !== "" && value2 !== "") {
11382          styles[property2] = value2;
11383        }
11384        currentProperty = "";
11385        currentValue = "";
11386        isParsingValue = false;
11387        continue;
11388      }
11389      if (isParsingValue) {
11390        currentValue += char;
11391      } else {
11392        currentProperty += char;
11393      }
11394    }
11395    const property = currentProperty.trim();
11396    const value = currentValue.trim();
11397    if (property !== "" && value !== "") {
11398      styles[property] = value;
11399    }
11400    return styles;
11401  }
11402  function setDOMStyleProperty(domStyle, property, value) {
11403    const priority = IMPORTANT_REG_EXP.test(value) ? "important" : "";
11404    const nextValue = priority === "" ? value : value.replace(IMPORTANT_REG_EXP, "").trim();
11405    domStyle.setProperty(property, nextValue, priority);
11406  }
11407  function setDOMStyleObject(domStyle, styleObject) {
11408    for (const property in styleObject) {
11409      const value = styleObject[property];
11410      if (value == null) {
11411        domStyle.removeProperty(property);
11412      } else {
11413        setDOMStyleProperty(domStyle, property, value);
11414      }
11415    }
11416  }
11417  function setDOMStyleFromCSS(domStyle, cssText, prevCSSText = "") {
11418    if (cssText === prevCSSText) {
11419      return;
11420    }
11421    const prevCSS = getStyleObjectFromCSS(prevCSSText);
11422    const nextCSS = getStyleObjectFromCSS(cssText);
11423    for (const property in nextCSS) {
11424      delete prevCSS[property];
11425      setDOMStyleProperty(domStyle, property, nextCSS[property]);
11426    }
11427    for (const property in prevCSS) {
11428      domStyle.removeProperty(property);
11429    }
11430  }
11431  var LineBreakNode = class _LineBreakNode extends LexicalNode {
11432    /** @internal */
11433    static getType() {
11434      return "linebreak";
11435    }
11436    static clone(node) {
11437      return new _LineBreakNode(node.__key);
11438    }
11439    constructor(key) {
11440      super(key);
11441    }
11442    getTextContent() {
11443      return "\n";
11444    }
11445    createDOM() {
11446      return document.createElement("br");
11447    }
11448    updateDOM() {
11449      return false;
11450    }
11451    isInline() {
11452      return true;
11453    }
11454    static importDOM() {
11455      return {
11456        br: (node) => {
11457          if (isOnlyChildInBlockNode(node) || isLastChildInBlockNode(node)) {
11458            return null;
11459          }
11460          return {
11461            conversion: $convertLineBreakElement,
11462            priority: 0
11463          };
11464        }
11465      };
11466    }
11467    static importJSON(serializedLineBreakNode) {
11468      return $createLineBreakNode().updateFromJSON(serializedLineBreakNode);
11469    }
11470  };
11471  function $convertLineBreakElement(node) {
11472    return {
11473      node: $createLineBreakNode()
11474    };
11475  }
11476  function $createLineBreakNode() {
11477    return $applyNodeReplacement(new LineBreakNode());
11478  }
11479  function $isLineBreakNode(node) {
11480    return node instanceof LineBreakNode;
11481  }
11482  function isOnlyChildInBlockNode(node) {
11483    const parentElement = node.parentElement;
11484    if (parentElement !== null && isBlockDomNode(parentElement)) {
11485      const firstChild = parentElement.firstChild;
11486      if (firstChild === node || firstChild.nextSibling === node && isWhitespaceDomTextNode(firstChild)) {
11487        const lastChild = parentElement.lastChild;
11488        if (lastChild === node || lastChild.previousSibling === node && isWhitespaceDomTextNode(lastChild)) {
11489          return true;
11490        }
11491      }
11492    }
11493    return false;
11494  }
11495  function isLastChildInBlockNode(node) {
11496    const parentElement = node.parentElement;
11497    if (parentElement !== null && isBlockDomNode(parentElement)) {
11498      const firstChild = parentElement.firstChild;
11499      if (firstChild === node || firstChild.nextSibling === node && isWhitespaceDomTextNode(firstChild)) {
11500        return false;
11501      }
11502      const lastChild = parentElement.lastChild;
11503      if (lastChild === node || lastChild.previousSibling === node && isWhitespaceDomTextNode(lastChild)) {
11504        return true;
11505      }
11506    }
11507    return false;
11508  }
11509  function isWhitespaceDomTextNode(node) {
11510    return isDOMTextNode(node) && /^( |\t|\r?\n)+$/.test(node.textContent || "");
11511  }
11512  function getElementOuterTag(node, format) {
11513    if (format & IS_CODE) {
11514      return "code";
11515    }
11516    if (format & IS_HIGHLIGHT) {
11517      return "mark";
11518    }
11519    if (format & IS_SUBSCRIPT) {
11520      return "sub";
11521    }
11522    if (format & IS_SUPERSCRIPT) {
11523      return "sup";
11524    }
11525    return null;
11526  }
11527  function getElementInnerTag(node, format) {
11528    if (format & IS_BOLD) {
11529      return "strong";
11530    }
11531    if (format & IS_ITALIC) {
11532      return "em";
11533    }
11534    return "span";
11535  }
11536  function setTextThemeClassNames(tag, prevFormat, nextFormat, dom, textClassNames) {
11537    const domClassList = dom.classList;
11538    let classNames = getCachedClassNameArray(textClassNames, "base");
11539    if (classNames !== void 0) {
11540      domClassList.add(...classNames);
11541    }
11542    classNames = getCachedClassNameArray(textClassNames, "underlineStrikethrough");
11543    let hasUnderlineStrikethrough = false;
11544    const prevUnderlineStrikethrough = prevFormat & IS_UNDERLINE && prevFormat & IS_STRIKETHROUGH;
11545    const nextUnderlineStrikethrough = nextFormat & IS_UNDERLINE && nextFormat & IS_STRIKETHROUGH;
11546    if (classNames !== void 0) {
11547      if (nextUnderlineStrikethrough) {
11548        hasUnderlineStrikethrough = true;
11549        if (!prevUnderlineStrikethrough) {
11550          domClassList.add(...classNames);
11551        }
11552      } else if (prevUnderlineStrikethrough) {
11553        domClassList.remove(...classNames);
11554      }
11555    }
11556    for (const key in TEXT_TYPE_TO_FORMAT) {
11557      const format = key;
11558      const flag = TEXT_TYPE_TO_FORMAT[format];
11559      classNames = getCachedClassNameArray(textClassNames, key);
11560      if (classNames !== void 0) {
11561        if (nextFormat & flag) {
11562          if (hasUnderlineStrikethrough && (key === "underline" || key === "strikethrough")) {
11563            if (prevFormat & flag) {
11564              domClassList.remove(...classNames);
11565            }
11566            continue;
11567          }
11568          if ((prevFormat & flag) === 0 || prevUnderlineStrikethrough && key === "underline" || key === "strikethrough") {
11569            domClassList.add(...classNames);
11570          }
11571        } else if (prevFormat & flag) {
11572          domClassList.remove(...classNames);
11573        }
11574      }
11575    }
11576  }
11577  function diffComposedText(a2, b3) {
11578    const aLength = a2.length;
11579    const bLength = b3.length;
11580    let left = 0;
11581    let right = 0;
11582    while (left < aLength && left < bLength && a2[left] === b3[left]) {
11583      left++;
11584    }
11585    while (right + left < aLength && right + left < bLength && a2[aLength - right - 1] === b3[bLength - right - 1]) {
11586      right++;
11587    }
11588    return [left, aLength - left - right, b3.slice(left, bLength - right)];
11589  }
11590  function setTextContent(nextText, dom, node) {
11591    const firstChild = dom.firstChild;
11592    const isComposing = node.isComposing();
11593    const suffix = isComposing ? COMPOSITION_SUFFIX : "";
11594    const text2 = nextText + suffix;
11595    if (firstChild == null) {
11596      dom.textContent = text2;
11597    } else {
11598      const nodeValue = firstChild.nodeValue;
11599      if (nodeValue !== text2) {
11600        if (isComposing || IS_FIREFOX) {
11601          const [index, remove, insert] = diffComposedText(nodeValue, text2);
11602          if (remove !== 0) {
11603            firstChild.deleteData(index, remove);
11604          }
11605          firstChild.insertData(index, insert);
11606        } else {
11607          firstChild.nodeValue = text2;
11608        }
11609      }
11610    }
11611  }
11612  function createTextInnerDOM(innerDOM, node, innerTag, format, text2, config) {
11613    setTextContent(text2, innerDOM, node);
11614    const theme2 = config.theme;
11615    const textClassNames = theme2.text;
11616    if (textClassNames !== void 0) {
11617      setTextThemeClassNames(innerTag, 0, format, innerDOM, textClassNames);
11618    }
11619  }
11620  function wrapElementWith(element, tag) {
11621    const el = document.createElement(tag);
11622    el.appendChild(element);
11623    return el;
11624  }
11625  var TextNode = class _TextNode extends LexicalNode {
11626    /** @internal */
11627    __text;
11628    /** @internal */
11629    __format;
11630    /** @internal */
11631    __style;
11632    /** @internal */
11633    __mode;
11634    /** @internal */
11635    __detail;
11636    static getType() {
11637      return "text";
11638    }
11639    static clone(node) {
11640      return new _TextNode(node.__text, node.__key);
11641    }
11642    afterCloneFrom(prevNode) {
11643      super.afterCloneFrom(prevNode);
11644      this.__text = prevNode.__text;
11645      this.__format = prevNode.__format;
11646      this.__style = prevNode.__style;
11647      this.__mode = prevNode.__mode;
11648      this.__detail = prevNode.__detail;
11649    }
11650    constructor(text2 = "", key) {
11651      super(key);
11652      this.__text = text2;
11653      this.__format = 0;
11654      this.__style = "";
11655      this.__mode = 0;
11656      this.__detail = 0;
11657    }
11658    /**
11659     * Returns a 32-bit integer that represents the TextFormatTypes currently applied to the
11660     * TextNode. You probably don't want to use this method directly - consider using TextNode.hasFormat instead.
11661     *
11662     * @returns a number representing the format of the text node.
11663     */
11664    getFormat() {
11665      const self2 = this.getLatest();
11666      return self2.__format;
11667    }
11668    /**
11669     * Returns a 32-bit integer that represents the TextDetailTypes currently applied to the
11670     * TextNode. You probably don't want to use this method directly - consider using TextNode.isDirectionless
11671     * or TextNode.isUnmergeable instead.
11672     *
11673     * @returns a number representing the detail of the text node.
11674     */
11675    getDetail() {
11676      const self2 = this.getLatest();
11677      return self2.__detail;
11678    }
11679    /**
11680     * Returns the mode (TextModeType) of the TextNode, which may be "normal", "token", or "segmented"
11681     *
11682     * @returns TextModeType.
11683     */
11684    getMode() {
11685      const self2 = this.getLatest();
11686      return TEXT_TYPE_TO_MODE[self2.__mode];
11687    }
11688    /**
11689     * Returns the styles currently applied to the node. This is analogous to CSSText in the DOM.
11690     *
11691     * @returns CSSText-like string of styles applied to the underlying DOM node.
11692     */
11693    getStyle() {
11694      const self2 = this.getLatest();
11695      return self2.__style;
11696    }
11697    /**
11698     * Returns whether or not the node is in "token" mode. TextNodes in token mode can be navigated through character-by-character
11699     * with a RangeSelection, but are deleted as a single entity (not individually by character).
11700     *
11701     * @returns true if the node is in token mode, false otherwise.
11702     */
11703    isToken() {
11704      const self2 = this.getLatest();
11705      return self2.__mode === IS_TOKEN;
11706    }
11707    /**
11708     *
11709     * @returns true if Lexical detects that an IME or other 3rd-party script is attempting to
11710     * mutate the TextNode, false otherwise.
11711     */
11712    isComposing() {
11713      return this.__key === $getCompositionKey();
11714    }
11715    /**
11716     * Returns whether or not the node is in "segmented" mode. TextNodes in segmented mode can be navigated through character-by-character
11717     * with a RangeSelection, but are deleted in space-delimited "segments".
11718     *
11719     * @returns true if the node is in segmented mode, false otherwise.
11720     */
11721    isSegmented() {
11722      const self2 = this.getLatest();
11723      return self2.__mode === IS_SEGMENTED;
11724    }
11725    /**
11726     * Returns whether or not the node is "directionless". Directionless nodes don't respect changes between RTL and LTR modes.
11727     *
11728     * @returns true if the node is directionless, false otherwise.
11729     */
11730    isDirectionless() {
11731      const self2 = this.getLatest();
11732      return (self2.__detail & IS_DIRECTIONLESS) !== 0;
11733    }
11734    /**
11735     * Returns whether or not the node is unmergeable. In some scenarios, Lexical tries to merge
11736     * adjacent TextNodes into a single TextNode. If a TextNode is unmergeable, this won't happen.
11737     *
11738     * @returns true if the node is unmergeable, false otherwise.
11739     */
11740    isUnmergeable() {
11741      const self2 = this.getLatest();
11742      return (self2.__detail & IS_UNMERGEABLE) !== 0;
11743    }
11744    /**
11745     * Returns whether or not the node has the provided format applied. Use this with the human-readable TextFormatType
11746     * string values to get the format of a TextNode.
11747     *
11748     * @param type - the TextFormatType to check for.
11749     *
11750     * @returns true if the node has the provided format, false otherwise.
11751     */
11752    hasFormat(type) {
11753      const formatFlag = TEXT_TYPE_TO_FORMAT[type];
11754      return (this.getFormat() & formatFlag) !== 0;
11755    }
11756    /**
11757     * Returns whether or not the node is simple text. Simple text is defined as a TextNode that has the string type "text"
11758     * (i.e., not a subclass) and has no mode applied to it (i.e., not segmented or token).
11759     *
11760     * @returns true if the node is simple text, false otherwise.
11761     */
11762    isSimpleText() {
11763      return this.__type === "text" && this.__mode === 0;
11764    }
11765    /**
11766     * Returns the text content of the node as a string.
11767     *
11768     * @returns a string representing the text content of the node.
11769     */
11770    getTextContent() {
11771      const self2 = this.getLatest();
11772      return self2.__text;
11773    }
11774    /**
11775     * Returns the format flags applied to the node as a 32-bit integer.
11776     *
11777     * @returns a number representing the TextFormatTypes applied to the node.
11778     */
11779    getFormatFlags(type, alignWithFormat) {
11780      const self2 = this.getLatest();
11781      const format = self2.__format;
11782      return toggleTextFormatType(format, type, alignWithFormat);
11783    }
11784    /**
11785     *
11786     * @returns true if the text node supports font styling, false otherwise.
11787     */
11788    canHaveFormat() {
11789      return true;
11790    }
11791    /**
11792     * @returns true if the text node is inline, false otherwise.
11793     */
11794    isInline() {
11795      return true;
11796    }
11797    // View
11798    createDOM(config, editor) {
11799      const format = this.__format;
11800      const outerTag = getElementOuterTag(this, format);
11801      const innerTag = getElementInnerTag(this, format);
11802      const tag = outerTag === null ? innerTag : outerTag;
11803      const dom = document.createElement(tag);
11804      let innerDOM = dom;
11805      if (this.hasFormat("code")) {
11806        dom.setAttribute("spellcheck", "false");
11807      }
11808      if (outerTag !== null) {
11809        innerDOM = document.createElement(innerTag);
11810        dom.appendChild(innerDOM);
11811      }
11812      const text2 = this.__text;
11813      createTextInnerDOM(innerDOM, this, innerTag, format, text2, config);
11814      const style = this.__style;
11815      if (style !== "") {
11816        setDOMStyleFromCSS(dom.style, style);
11817      }
11818      return dom;
11819    }
11820    updateDOM(prevNode, dom, config) {
11821      const nextText = this.__text;
11822      const prevFormat = prevNode.__format;
11823      const nextFormat = this.__format;
11824      const prevOuterTag = getElementOuterTag(this, prevFormat);
11825      const nextOuterTag = getElementOuterTag(this, nextFormat);
11826      const prevInnerTag = getElementInnerTag(this, prevFormat);
11827      const nextInnerTag = getElementInnerTag(this, nextFormat);
11828      const prevTag = prevOuterTag === null ? prevInnerTag : prevOuterTag;
11829      const nextTag = nextOuterTag === null ? nextInnerTag : nextOuterTag;
11830      if (prevTag !== nextTag) {
11831        return true;
11832      }
11833      if (prevOuterTag === nextOuterTag && prevInnerTag !== nextInnerTag) {
11834        const prevInnerDOM = dom.firstChild;
11835        if (prevInnerDOM == null) {
11836          {
11837            formatDevErrorMessage(`updateDOM: prevInnerDOM is null or undefined`);
11838          }
11839        }
11840        const nextInnerDOM = document.createElement(nextInnerTag);
11841        createTextInnerDOM(nextInnerDOM, this, nextInnerTag, nextFormat, nextText, config);
11842        dom.replaceChild(nextInnerDOM, prevInnerDOM);
11843        return false;
11844      }
11845      let innerDOM = dom;
11846      if (nextOuterTag !== null) {
11847        if (prevOuterTag !== null) {
11848          innerDOM = dom.firstChild;
11849          if (innerDOM == null) {
11850            {
11851              formatDevErrorMessage(`updateDOM: innerDOM is null or undefined`);
11852            }
11853          }
11854        }
11855      }
11856      setTextContent(nextText, innerDOM, this);
11857      const theme2 = config.theme;
11858      const textClassNames = theme2.text;
11859      if (textClassNames !== void 0 && prevFormat !== nextFormat) {
11860        setTextThemeClassNames(nextInnerTag, prevFormat, nextFormat, innerDOM, textClassNames);
11861      }
11862      const prevStyle = prevNode.__style;
11863      const nextStyle = this.__style;
11864      if (prevStyle !== nextStyle) {
11865        setDOMStyleFromCSS(dom.style, nextStyle, prevStyle);
11866      }
11867      return false;
11868    }
11869    static importDOM() {
11870      return {
11871        "#text": () => ({
11872          conversion: $convertTextDOMNode,
11873          priority: 0
11874        }),
11875        b: () => ({
11876          conversion: convertBringAttentionToElement,
11877          priority: 0
11878        }),
11879        code: () => ({
11880          conversion: convertTextFormatElement,
11881          priority: 0
11882        }),
11883        em: () => ({
11884          conversion: convertTextFormatElement,
11885          priority: 0
11886        }),
11887        i: () => ({
11888          conversion: convertTextFormatElement,
11889          priority: 0
11890        }),
11891        mark: () => ({
11892          conversion: convertTextFormatElement,
11893          priority: 0
11894        }),
11895        s: () => ({
11896          conversion: convertTextFormatElement,
11897          priority: 0
11898        }),
11899        span: () => ({
11900          conversion: convertSpanElement,
11901          priority: 0
11902        }),
11903        strong: () => ({
11904          conversion: convertTextFormatElement,
11905          priority: 0
11906        }),
11907        sub: () => ({
11908          conversion: convertTextFormatElement,
11909          priority: 0
11910        }),
11911        sup: () => ({
11912          conversion: convertTextFormatElement,
11913          priority: 0
11914        }),
11915        u: () => ({
11916          conversion: convertTextFormatElement,
11917          priority: 0
11918        })
11919      };
11920    }
11921    static importJSON(serializedNode) {
11922      return $createTextNode().updateFromJSON(serializedNode);
11923    }
11924    updateFromJSON(serializedNode) {
11925      return super.updateFromJSON(serializedNode).setTextContent(serializedNode.text).setFormat(serializedNode.format).setDetail(serializedNode.detail).setMode(serializedNode.mode).setStyle(serializedNode.style);
11926    }
11927    // This improves Lexical's basic text output in copy+paste plus
11928    // for headless mode where people might use Lexical to generate
11929    // HTML content and not have the ability to use CSS classes.
11930    exportDOM(editor) {
11931      let {
11932        element
11933      } = super.exportDOM(editor);
11934      if (!isHTMLElement(element)) {
11935        formatDevErrorMessage(`Expected TextNode createDOM to always return a HTMLElement`);
11936      }
11937      element.style.whiteSpace = "pre-wrap";
11938      if (this.hasFormat("lowercase")) {
11939        element.style.textTransform = "lowercase";
11940      } else if (this.hasFormat("uppercase")) {
11941        element.style.textTransform = "uppercase";
11942      } else if (this.hasFormat("capitalize")) {
11943        element.style.textTransform = "capitalize";
11944      }
11945      if (this.hasFormat("bold")) {
11946        element = wrapElementWith(element, "b");
11947      }
11948      if (this.hasFormat("italic")) {
11949        element = wrapElementWith(element, "i");
11950      }
11951      if (this.hasFormat("strikethrough")) {
11952        element = wrapElementWith(element, "s");
11953      }
11954      if (this.hasFormat("underline")) {
11955        element = wrapElementWith(element, "u");
11956      }
11957      return {
11958        element
11959      };
11960    }
11961    exportJSON() {
11962      return {
11963        detail: this.getDetail(),
11964        format: this.getFormat(),
11965        mode: this.getMode(),
11966        style: this.getStyle(),
11967        text: this.getTextContent(),
11968        // As an exception here we invoke super at the end for historical reasons.
11969        // Namely, to preserve the order of the properties and not to break the tests
11970        // that use the serialized string representation.
11971        ...super.exportJSON()
11972      };
11973    }
11974    // Mutators
11975    selectionTransform(prevSelection, nextSelection) {
11976      return;
11977    }
11978    /**
11979     * Sets the node format to the provided TextFormatType or 32-bit integer. Note that the TextFormatType
11980     * version of the argument can only specify one format and doing so will remove all other formats that
11981     * may be applied to the node. For toggling behavior, consider using {@link TextNode.toggleFormat}
11982     *
11983     * @param format - TextFormatType or 32-bit integer representing the node format.
11984     *
11985     * @returns this TextNode.
11986     * // TODO 0.12 This should just be a `string`.
11987     */
11988    setFormat(format) {
11989      const self2 = this.getWritable();
11990      self2.__format = typeof format === "string" ? TEXT_TYPE_TO_FORMAT[format] : format;
11991      return self2;
11992    }
11993    /**
11994     * Sets the node detail to the provided TextDetailType or 32-bit integer. Note that the TextDetailType
11995     * version of the argument can only specify one detail value and doing so will remove all other detail values that
11996     * may be applied to the node. For toggling behavior, consider using {@link TextNode.toggleDirectionless}
11997     * or {@link TextNode.toggleUnmergeable}
11998     *
11999     * @param detail - TextDetailType or 32-bit integer representing the node detail.
12000     *
12001     * @returns this TextNode.
12002     * // TODO 0.12 This should just be a `string`.
12003     */
12004    setDetail(detail) {
12005      const self2 = this.getWritable();
12006      self2.__detail = typeof detail === "string" ? DETAIL_TYPE_TO_DETAIL[detail] : detail;
12007      return self2;
12008    }
12009    /**
12010     * Sets the node style to the provided CSSText-like string. Set this property as you
12011     * would an HTMLElement style attribute to apply inline styles to the underlying DOM Element.
12012     *
12013     * @param style - CSSText to be applied to the underlying HTMLElement.
12014     *
12015     * @returns this TextNode.
12016     */
12017    setStyle(style) {
12018      const self2 = this.getWritable();
12019      self2.__style = style;
12020      return self2;
12021    }
12022    /**
12023     * Applies the provided format to this TextNode if it's not present. Removes it if it's present.
12024     * The subscript and superscript formats are mutually exclusive.
12025     * Prefer using this method to turn specific formats on and off.
12026     *
12027     * @param type - TextFormatType to toggle.
12028     *
12029     * @returns this TextNode.
12030     */
12031    toggleFormat(type) {
12032      const format = this.getFormat();
12033      const newFormat = toggleTextFormatType(format, type, null);
12034      return this.setFormat(newFormat);
12035    }
12036    /**
12037     * Toggles the directionless detail value of the node. Prefer using this method over setDetail.
12038     *
12039     * @returns this TextNode.
12040     */
12041    toggleDirectionless() {
12042      const self2 = this.getWritable();
12043      self2.__detail ^= IS_DIRECTIONLESS;
12044      return self2;
12045    }
12046    /**
12047     * Toggles the unmergeable detail value of the node. Prefer using this method over setDetail.
12048     *
12049     * @returns this TextNode.
12050     */
12051    toggleUnmergeable() {
12052      const self2 = this.getWritable();
12053      self2.__detail ^= IS_UNMERGEABLE;
12054      return self2;
12055    }
12056    /**
12057     * Sets the mode of the node.
12058     *
12059     * @returns this TextNode.
12060     */
12061    setMode(type) {
12062      const mode = TEXT_MODE_TO_TYPE[type];
12063      if (this.__mode === mode) {
12064        return this;
12065      }
12066      const self2 = this.getWritable();
12067      self2.__mode = mode;
12068      return self2;
12069    }
12070    /**
12071     * Sets the text content of the node.
12072     *
12073     * @param text - the string to set as the text value of the node.
12074     *
12075     * @returns this TextNode.
12076     */
12077    setTextContent(text2) {
12078      if (this.__text === text2) {
12079        return this;
12080      }
12081      const self2 = this.getWritable();
12082      self2.__text = text2;
12083      return self2;
12084    }
12085    /**
12086     * Sets the current Lexical selection to be a RangeSelection with anchor and focus on this TextNode at the provided offsets.
12087     *
12088     * @param _anchorOffset - the offset at which the Selection anchor will be placed.
12089     * @param _focusOffset - the offset at which the Selection focus will be placed.
12090     *
12091     * @returns the new RangeSelection.
12092     */
12093    select(_anchorOffset, _focusOffset) {
12094      errorOnReadOnly();
12095      let anchorOffset = _anchorOffset;
12096      let focusOffset = _focusOffset;
12097      const selection = $getSelection();
12098      const text2 = this.getTextContent();
12099      const key = this.__key;
12100      if (typeof text2 === "string") {
12101        const lastOffset = text2.length;
12102        if (anchorOffset === void 0) {
12103          anchorOffset = lastOffset;
12104        }
12105        if (focusOffset === void 0) {
12106          focusOffset = lastOffset;
12107        }
12108      } else {
12109        anchorOffset = 0;
12110        focusOffset = 0;
12111      }
12112      if (!$isRangeSelection(selection)) {
12113        return $internalMakeRangeSelection(key, anchorOffset, key, focusOffset, "text", "text");
12114      } else {
12115        const compositionKey = $getCompositionKey();
12116        if (compositionKey === selection.anchor.key || compositionKey === selection.focus.key) {
12117          $setCompositionKey(key);
12118        }
12119        selection.setTextNodeRange(this, anchorOffset, this, focusOffset);
12120      }
12121      return selection;
12122    }
12123    selectStart() {
12124      return this.select(0, 0);
12125    }
12126    selectEnd() {
12127      const size2 = this.getTextContentSize();
12128      return this.select(size2, size2);
12129    }
12130    /**
12131     * Inserts the provided text into this TextNode at the provided offset, deleting the number of characters
12132     * specified. Can optionally calculate a new selection after the operation is complete.
12133     *
12134     * @param offset - the offset at which the splice operation should begin.
12135     * @param delCount - the number of characters to delete, starting from the offset.
12136     * @param newText - the text to insert into the TextNode at the offset.
12137     * @param moveSelection - optional, whether or not to move selection to the end of the inserted substring.
12138     *
12139     * @returns this TextNode.
12140     */
12141    spliceText(offset3, delCount, newText, moveSelection) {
12142      const writableSelf = this.getWritable();
12143      const text2 = writableSelf.__text;
12144      const handledTextLength = newText.length;
12145      let index = offset3;
12146      if (index < 0) {
12147        index = handledTextLength + index;
12148        if (index < 0) {
12149          index = 0;
12150        }
12151      }
12152      const selection = $getSelection();
12153      if (moveSelection && $isRangeSelection(selection)) {
12154        const newOffset = offset3 + handledTextLength;
12155        selection.setTextNodeRange(writableSelf, newOffset, writableSelf, newOffset);
12156      }
12157      const updatedText = text2.slice(0, index) + newText + text2.slice(index + delCount);
12158      writableSelf.__text = updatedText;
12159      return writableSelf;
12160    }
12161    /**
12162     * This method is meant to be overridden by TextNode subclasses to control the behavior of those nodes
12163     * when a user event would cause text to be inserted before them in the editor. If true, Lexical will attempt
12164     * to insert text into this node. If false, it will insert the text in a new sibling node.
12165     *
12166     * @returns true if text can be inserted before the node, false otherwise.
12167     */
12168    canInsertTextBefore() {
12169      return true;
12170    }
12171    /**
12172     * This method is meant to be overridden by TextNode subclasses to control the behavior of those nodes
12173     * when a user event would cause text to be inserted after them in the editor. If true, Lexical will attempt
12174     * to insert text into this node. If false, it will insert the text in a new sibling node.
12175     *
12176     * @returns true if text can be inserted after the node, false otherwise.
12177     */
12178    canInsertTextAfter() {
12179      return true;
12180    }
12181    /**
12182     * Splits this TextNode at the provided character offsets, forming new TextNodes from the substrings
12183     * formed by the split, and inserting those new TextNodes into the editor, replacing the one that was split.
12184     *
12185     * @param splitOffsets - rest param of the text content character offsets at which this node should be split.
12186     *
12187     * @returns an Array containing the newly-created TextNodes.
12188     */
12189    splitText(...splitOffsets) {
12190      errorOnReadOnly();
12191      const self2 = this.getLatest();
12192      const textContent = self2.getTextContent();
12193      if (textContent === "") {
12194        return [];
12195      }
12196      const key = self2.__key;
12197      const compositionKey = $getCompositionKey();
12198      const textLength = textContent.length;
12199      splitOffsets.sort((a2, b3) => a2 - b3);
12200      splitOffsets.push(textLength);
12201      const parts = [];
12202      const splitOffsetsLength = splitOffsets.length;
12203      for (let start3 = 0, offsetIndex = 0; start3 < textLength && offsetIndex <= splitOffsetsLength; offsetIndex++) {
12204        const end = splitOffsets[offsetIndex];
12205        if (end > start3) {
12206          parts.push(textContent.slice(start3, end));
12207          start3 = end;
12208        }
12209      }
12210      const partsLength = parts.length;
12211      if (partsLength === 1) {
12212        return [self2];
12213      }
12214      const firstPart = parts[0];
12215      const parent = self2.getParent();
12216      let writableNode;
12217      const format = self2.getFormat();
12218      const style = self2.getStyle();
12219      const detail = self2.__detail;
12220      let hasReplacedSelf = false;
12221      let startTextPoint = null;
12222      let endTextPoint = null;
12223      const selection = $getSelection();
12224      if ($isRangeSelection(selection)) {
12225        const [startPoint, endPoint] = selection.isBackward() ? [selection.focus, selection.anchor] : [selection.anchor, selection.focus];
12226        if (startPoint.type === "text" && startPoint.key === key) {
12227          startTextPoint = startPoint;
12228        }
12229        if (endPoint.type === "text" && endPoint.key === key) {
12230          endTextPoint = endPoint;
12231        }
12232      }
12233      if (self2.isSegmented()) {
12234        writableNode = $createTextNode(firstPart);
12235        writableNode.__format = format;
12236        writableNode.__style = style;
12237        writableNode.__detail = detail;
12238        writableNode.__state = $cloneNodeState(self2, writableNode);
12239        hasReplacedSelf = true;
12240      } else {
12241        writableNode = self2.setTextContent(firstPart);
12242      }
12243      const splitNodes = [writableNode];
12244      for (let i2 = 1; i2 < partsLength; i2++) {
12245        const part = parts[i2];
12246        const sibling = $createTextNode(part);
12247        sibling.__format = format;
12248        sibling.__style = style;
12249        sibling.__detail = detail;
12250        sibling.__state = $cloneNodeState(self2, sibling);
12251        const siblingKey = sibling.__key;
12252        if (compositionKey === key) {
12253          $setCompositionKey(siblingKey);
12254        }
12255        splitNodes.push(sibling);
12256      }
12257      const originalStartOffset = startTextPoint ? startTextPoint.offset : null;
12258      const originalEndOffset = endTextPoint ? endTextPoint.offset : null;
12259      let startOffset = 0;
12260      for (const node of splitNodes) {
12261        if (!(startTextPoint || endTextPoint)) {
12262          break;
12263        }
12264        const endOffset = startOffset + node.getTextContentSize();
12265        if (startTextPoint !== null && originalStartOffset !== null && originalStartOffset <= endOffset && originalStartOffset >= startOffset) {
12266          startTextPoint.set(node.getKey(), originalStartOffset - startOffset, "text");
12267          if (originalStartOffset < endOffset) {
12268            startTextPoint = null;
12269          }
12270        }
12271        if (endTextPoint !== null && originalEndOffset !== null && originalEndOffset <= endOffset && originalEndOffset >= startOffset) {
12272          endTextPoint.set(node.getKey(), originalEndOffset - startOffset, "text");
12273          break;
12274        }
12275        startOffset = endOffset;
12276      }
12277      if (parent !== null) {
12278        internalMarkSiblingsAsDirty(this);
12279        const writableParent = parent.getWritable();
12280        const insertionIndex = this.getIndexWithinParent();
12281        if (hasReplacedSelf) {
12282          writableParent.splice(insertionIndex, 0, splitNodes);
12283          this.remove();
12284        } else {
12285          writableParent.splice(insertionIndex, 1, splitNodes);
12286        }
12287        if ($isRangeSelection(selection)) {
12288          $updateElementSelectionOnCreateDeleteNode(selection, parent, insertionIndex, partsLength - 1);
12289        }
12290      }
12291      return splitNodes;
12292    }
12293    /**
12294     * Merges the target TextNode into this TextNode, removing the target node.
12295     *
12296     * @param target - the TextNode to merge into this one.
12297     *
12298     * @returns this TextNode.
12299     */
12300    mergeWithSibling(target) {
12301      const isBefore = target === this.getPreviousSibling();
12302      if (!isBefore && target !== this.getNextSibling()) {
12303        {
12304          formatDevErrorMessage(`mergeWithSibling: sibling must be a previous or next sibling`);
12305        }
12306      }
12307      const key = this.__key;
12308      const targetKey = target.__key;
12309      const text2 = this.__text;
12310      const textLength = text2.length;
12311      const compositionKey = $getCompositionKey();
12312      if (compositionKey === targetKey) {
12313        $setCompositionKey(key);
12314      }
12315      const selection = $getSelection();
12316      if ($isRangeSelection(selection)) {
12317        const anchor = selection.anchor;
12318        const focus = selection.focus;
12319        if (anchor !== null && anchor.key === targetKey) {
12320          adjustPointOffsetForMergedSibling(anchor, isBefore, key, target, textLength);
12321        }
12322        if (focus !== null && focus.key === targetKey) {
12323          adjustPointOffsetForMergedSibling(focus, isBefore, key, target, textLength);
12324        }
12325      }
12326      const targetText = target.__text;
12327      const newText = isBefore ? targetText + text2 : text2 + targetText;
12328      this.setTextContent(newText);
12329      const writableSelf = this.getWritable();
12330      target.remove();
12331      return writableSelf;
12332    }
12333    /**
12334     * This method is meant to be overridden by TextNode subclasses to control the behavior of those nodes
12335     * when used with the registerLexicalTextEntity function. If you're using registerLexicalTextEntity, the
12336     * node class that you create and replace matched text with should return true from this method.
12337     *
12338     * @returns true if the node is to be treated as a "text entity", false otherwise.
12339     */
12340    isTextEntity() {
12341      return false;
12342    }
12343  };
12344  function convertSpanElement(domNode) {
12345    const span = domNode;
12346    const style = span.style;
12347    return {
12348      forChild: applyTextFormatFromStyle(style),
12349      node: null
12350    };
12351  }
12352  function convertBringAttentionToElement(domNode) {
12353    const b3 = domNode;
12354    const hasNormalFontWeight = b3.style.fontWeight === "normal";
12355    return {
12356      forChild: applyTextFormatFromStyle(b3.style, hasNormalFontWeight ? void 0 : "bold"),
12357      node: null
12358    };
12359  }
12360  var preParentCache = /* @__PURE__ */ new WeakMap();
12361  function isNodePre(node) {
12362    if (!isHTMLElement(node)) {
12363      return false;
12364    } else if (node.nodeName === "PRE") {
12365      return true;
12366    }
12367    const whiteSpace = node.style.whiteSpace;
12368    return typeof whiteSpace === "string" && whiteSpace.startsWith("pre");
12369  }
12370  function findParentPreDOMNode(node) {
12371    let cached;
12372    let parent = node.parentNode;
12373    const visited = [node];
12374    while (parent !== null && (cached = preParentCache.get(parent)) === void 0 && !isNodePre(parent)) {
12375      visited.push(parent);
12376      parent = parent.parentNode;
12377    }
12378    const resultNode = cached === void 0 ? parent : cached;
12379    for (let i2 = 0; i2 < visited.length; i2++) {
12380      preParentCache.set(visited[i2], resultNode);
12381    }
12382    return resultNode;
12383  }
12384  function $convertTextDOMNode(domNode) {
12385    const domNode_ = domNode;
12386    const parentDom = domNode.parentElement;
12387    if (!(parentDom !== null)) {
12388      formatDevErrorMessage(`Expected parentElement of Text not to be null`);
12389    }
12390    let textContent = domNode_.textContent || "";
12391    if (findParentPreDOMNode(domNode_) !== null) {
12392      const parts = textContent.split(/(\r?\n|\t)/);
12393      const nodes = [];
12394      const length = parts.length;
12395      for (let i2 = 0; i2 < length; i2++) {
12396        const part = parts[i2];
12397        if (part === "\n" || part === "\r\n") {
12398          nodes.push($createLineBreakNode());
12399        } else if (part === "	") {
12400          nodes.push($createTabNode());
12401        } else if (part !== "") {
12402          nodes.push($createTextNode(part));
12403        }
12404      }
12405      return {
12406        node: nodes
12407      };
12408    }
12409    textContent = textContent.replace(/\r/g, "").replace(/[ \t\n]+/g, " ");
12410    if (textContent === "") {
12411      return {
12412        node: null
12413      };
12414    }
12415    if (textContent[0] === " ") {
12416      let previousText = domNode_;
12417      let isStartOfLine = true;
12418      while (previousText !== null && (previousText = findTextInLine(previousText, false)) !== null) {
12419        const previousTextContent = previousText.textContent || "";
12420        if (previousTextContent.length > 0) {
12421          if (/[ \t\n]$/.test(previousTextContent)) {
12422            textContent = textContent.slice(1);
12423          }
12424          isStartOfLine = false;
12425          break;
12426        }
12427      }
12428      if (isStartOfLine) {
12429        textContent = textContent.slice(1);
12430      }
12431    }
12432    if (textContent[textContent.length - 1] === " ") {
12433      let nextText = domNode_;
12434      let isEndOfLine = true;
12435      while (nextText !== null && (nextText = findTextInLine(nextText, true)) !== null) {
12436        const nextTextContent = (nextText.textContent || "").replace(/^( |\t|\r?\n)+/, "");
12437        if (nextTextContent.length > 0) {
12438          isEndOfLine = false;
12439          break;
12440        }
12441      }
12442      if (isEndOfLine) {
12443        textContent = textContent.slice(0, textContent.length - 1);
12444      }
12445    }
12446    if (textContent === "") {
12447      return {
12448        node: null
12449      };
12450    }
12451    return {
12452      node: $createTextNode(textContent)
12453    };
12454  }
12455  function findTextInLine(text2, forward) {
12456    let node = text2;
12457    while (true) {
12458      let sibling;
12459      while ((sibling = forward ? node.nextSibling : node.previousSibling) === null) {
12460        const parentElement = node.parentElement;
12461        if (parentElement === null) {
12462          return null;
12463        }
12464        node = parentElement;
12465      }
12466      node = sibling;
12467      if (isHTMLElement(node)) {
12468        const display = node.style.display;
12469        if (display === "" && !isInlineDomNode(node) || display !== "" && !display.startsWith("inline")) {
12470          return null;
12471        }
12472      }
12473      let descendant = node;
12474      while ((descendant = forward ? node.firstChild : node.lastChild) !== null) {
12475        node = descendant;
12476      }
12477      if (isDOMTextNode(node)) {
12478        return node;
12479      } else if (node.nodeName === "BR") {
12480        return null;
12481      }
12482    }
12483  }
12484  var nodeNameToTextFormat = {
12485    code: "code",
12486    em: "italic",
12487    i: "italic",
12488    mark: "highlight",
12489    s: "strikethrough",
12490    strong: "bold",
12491    sub: "subscript",
12492    sup: "superscript",
12493    u: "underline"
12494  };
12495  function convertTextFormatElement(domNode) {
12496    const format = nodeNameToTextFormat[domNode.nodeName.toLowerCase()];
12497    if (format === void 0) {
12498      return {
12499        node: null
12500      };
12501    }
12502    return {
12503      forChild: applyTextFormatFromStyle(domNode.style, format),
12504      node: null
12505    };
12506  }
12507  function $createTextNode(text2 = "") {
12508    return $applyNodeReplacement(new TextNode(text2));
12509  }
12510  function $isTextNode(node) {
12511    return node instanceof TextNode;
12512  }
12513  function applyTextFormatFromStyle(style, shouldApply) {
12514    const fontWeight = style.fontWeight;
12515    const textDecoration = style.textDecoration.split(" ");
12516    const hasBoldFontWeight = fontWeight === "700" || fontWeight === "bold";
12517    const hasLinethroughTextDecoration = textDecoration.includes("line-through");
12518    const hasItalicFontStyle = style.fontStyle === "italic";
12519    const hasUnderlineTextDecoration = textDecoration.includes("underline");
12520    const verticalAlign = style.verticalAlign;
12521    return (lexicalNode) => {
12522      if (!$isTextNode(lexicalNode)) {
12523        return lexicalNode;
12524      }
12525      if (hasBoldFontWeight && !lexicalNode.hasFormat("bold")) {
12526        lexicalNode.toggleFormat("bold");
12527      }
12528      if (hasLinethroughTextDecoration && !lexicalNode.hasFormat("strikethrough")) {
12529        lexicalNode.toggleFormat("strikethrough");
12530      }
12531      if (hasItalicFontStyle && !lexicalNode.hasFormat("italic")) {
12532        lexicalNode.toggleFormat("italic");
12533      }
12534      if (hasUnderlineTextDecoration && !lexicalNode.hasFormat("underline")) {
12535        lexicalNode.toggleFormat("underline");
12536      }
12537      if (verticalAlign === "sub" && !lexicalNode.hasFormat("subscript")) {
12538        lexicalNode.toggleFormat("subscript");
12539      }
12540      if (verticalAlign === "super" && !lexicalNode.hasFormat("superscript")) {
12541        lexicalNode.toggleFormat("superscript");
12542      }
12543      if (shouldApply && !lexicalNode.hasFormat(shouldApply)) {
12544        lexicalNode.toggleFormat(shouldApply);
12545      }
12546      return lexicalNode;
12547    };
12548  }
12549  var TabNode = class _TabNode extends TextNode {
12550    static getType() {
12551      return "tab";
12552    }
12553    static clone(node) {
12554      return new _TabNode(node.__key);
12555    }
12556    constructor(key) {
12557      super("	", key);
12558      this.__detail = IS_UNMERGEABLE;
12559    }
12560    static importDOM() {
12561      return null;
12562    }
12563    createDOM(config) {
12564      const dom = super.createDOM(config);
12565      const classNames = getCachedClassNameArray(config.theme, "tab");
12566      if (classNames !== void 0) {
12567        const domClassList = dom.classList;
12568        domClassList.add(...classNames);
12569      }
12570      return dom;
12571    }
12572    static importJSON(serializedTabNode) {
12573      return $createTabNode().updateFromJSON(serializedTabNode);
12574    }
12575    setTextContent(text2) {
12576      if (!(text2 === "	" || text2 === "")) {
12577        formatDevErrorMessage(`TabNode does not support setTextContent`);
12578      }
12579      return super.setTextContent("	");
12580    }
12581    spliceText(offset3, delCount, newText, moveSelection) {
12582      if (!(newText === "" && delCount === 0 || newText === "	" && delCount === 1)) {
12583        formatDevErrorMessage(`TabNode does not support spliceText`);
12584      }
12585      return this;
12586    }
12587    setDetail(detail) {
12588      if (!(detail === IS_UNMERGEABLE)) {
12589        formatDevErrorMessage(`TabNode does not support setDetail`);
12590      }
12591      return this;
12592    }
12593    setMode(type) {
12594      if (!(type === "normal")) {
12595        formatDevErrorMessage(`TabNode does not support setMode`);
12596      }
12597      return this;
12598    }
12599    canInsertTextBefore() {
12600      return false;
12601    }
12602    canInsertTextAfter() {
12603      return false;
12604    }
12605  };
12606  function $createTabNode() {
12607    return $applyNodeReplacement(new TabNode());
12608  }
12609  function $isTabNode(node) {
12610    return node instanceof TabNode;
12611  }
12612  var Point = class {
12613    key;
12614    offset;
12615    type;
12616    _selection;
12617    constructor(key, offset3, type) {
12618      {
12619        Object.defineProperty(this, "_selection", {
12620          enumerable: false,
12621          writable: true
12622        });
12623      }
12624      this._selection = null;
12625      this.key = key;
12626      this.offset = offset3;
12627      this.type = type;
12628    }
12629    is(point) {
12630      return this.key === point.key && this.offset === point.offset && this.type === point.type;
12631    }
12632    isBefore(b3) {
12633      if (this.key === b3.key) {
12634        return this.offset < b3.offset;
12635      }
12636      const aCaret = $normalizeCaret($caretFromPoint(this, "next"));
12637      const bCaret = $normalizeCaret($caretFromPoint(b3, "next"));
12638      return $comparePointCaretNext(aCaret, bCaret) < 0;
12639    }
12640    getNode() {
12641      const key = this.key;
12642      const node = $getNodeByKey(key);
12643      if (node === null) {
12644        {
12645          formatDevErrorMessage(`Point.getNode: node not found`);
12646        }
12647      }
12648      return node;
12649    }
12650    set(key, offset3, type, onlyIfChanged) {
12651      const selection = this._selection;
12652      const oldKey = this.key;
12653      if (onlyIfChanged && this.key === key && this.offset === offset3 && this.type === type) {
12654        return;
12655      }
12656      this.key = key;
12657      this.offset = offset3;
12658      this.type = type;
12659      {
12660        const node = $getNodeByKey(key);
12661        if (!(type === "text" ? $isTextNode(node) : $isElementNode(node))) {
12662          formatDevErrorMessage(`PointType.set: node with key ${key} is ${node ? node.__type : "[not found]"} and can not be used for a ${type} point`);
12663        }
12664      }
12665      if (!isCurrentlyReadOnlyMode()) {
12666        if ($getCompositionKey() === oldKey) {
12667          $setCompositionKey(key);
12668        }
12669        if (selection !== null) {
12670          selection.setCachedNodes(null);
12671          selection.dirty = true;
12672        }
12673      }
12674    }
12675  };
12676  function $createPoint(key, offset3, type) {
12677    return new Point(key, offset3, type);
12678  }
12679  function selectPointOnNode(point, node) {
12680    let key = node.__key;
12681    let offset3 = point.offset;
12682    let type = "element";
12683    if ($isTextNode(node)) {
12684      type = "text";
12685      const textContentLength = node.getTextContentSize();
12686      if (offset3 > textContentLength) {
12687        offset3 = textContentLength;
12688      }
12689    } else if (!$isElementNode(node)) {
12690      const nextSibling = node.getNextSibling();
12691      if ($isTextNode(nextSibling)) {
12692        key = nextSibling.__key;
12693        offset3 = 0;
12694        type = "text";
12695      } else {
12696        const parentNode = node.getParent();
12697        if (parentNode) {
12698          key = parentNode.__key;
12699          offset3 = node.getIndexWithinParent() + 1;
12700        }
12701      }
12702    }
12703    point.set(key, offset3, type);
12704  }
12705  function $moveSelectionPointToEnd(point, node) {
12706    if ($isElementNode(node)) {
12707      const lastNode = node.getLastDescendant();
12708      if ($isElementNode(lastNode) || $isTextNode(lastNode)) {
12709        selectPointOnNode(point, lastNode);
12710      } else {
12711        selectPointOnNode(point, node);
12712      }
12713    } else {
12714      selectPointOnNode(point, node);
12715    }
12716  }
12717  function $transferStartingElementPointToTextPoint(start3, end, format, style) {
12718    const element = start3.getNode();
12719    const placementNode = element.getChildAtIndex(start3.offset);
12720    const textNode = $createTextNode();
12721    textNode.setFormat(format);
12722    textNode.setStyle(style);
12723    if ($isParagraphNode(placementNode)) {
12724      placementNode.splice(0, 0, [textNode]);
12725    } else {
12726      const target = $isRootNode(element) ? $createParagraphNode().append(textNode) : textNode;
12727      if (placementNode === null) {
12728        element.append(target);
12729      } else {
12730        placementNode.insertBefore(target);
12731      }
12732    }
12733    if (start3.is(end)) {
12734      end.set(textNode.__key, 0, "text");
12735    }
12736    start3.set(textNode.__key, 0, "text");
12737  }
12738  var NodeSelection = class _NodeSelection {
12739    _nodes;
12740    _cachedNodes;
12741    dirty;
12742    constructor(objects) {
12743      this._cachedNodes = null;
12744      this._nodes = objects;
12745      this.dirty = false;
12746    }
12747    getCachedNodes() {
12748      return this._cachedNodes;
12749    }
12750    setCachedNodes(nodes) {
12751      this._cachedNodes = nodes;
12752    }
12753    is(selection) {
12754      if (!$isNodeSelection(selection)) {
12755        return false;
12756      }
12757      const a2 = this._nodes;
12758      const b3 = selection._nodes;
12759      return a2.size === b3.size && Array.from(a2).every((key) => b3.has(key));
12760    }
12761    isCollapsed() {
12762      return false;
12763    }
12764    isBackward() {
12765      return false;
12766    }
12767    getStartEndPoints() {
12768      return null;
12769    }
12770    add(key) {
12771      this.dirty = true;
12772      this._nodes.add(key);
12773      this._cachedNodes = null;
12774    }
12775    delete(key) {
12776      this.dirty = true;
12777      this._nodes.delete(key);
12778      this._cachedNodes = null;
12779    }
12780    clear() {
12781      this.dirty = true;
12782      this._nodes.clear();
12783      this._cachedNodes = null;
12784    }
12785    has(key) {
12786      return this._nodes.has(key);
12787    }
12788    clone() {
12789      return new _NodeSelection(new Set(this._nodes));
12790    }
12791    extract() {
12792      return this.getNodes();
12793    }
12794    insertRawText(text2) {
12795    }
12796    insertText() {
12797    }
12798    insertNodes(nodes) {
12799      const selectedNodes = this.getNodes();
12800      const selectedNodesLength = selectedNodes.length;
12801      const lastSelectedNode = selectedNodes[selectedNodesLength - 1];
12802      let selectionAtEnd;
12803      if ($isTextNode(lastSelectedNode)) {
12804        selectionAtEnd = lastSelectedNode.select();
12805      } else {
12806        const index = lastSelectedNode.getIndexWithinParent() + 1;
12807        selectionAtEnd = lastSelectedNode.getParentOrThrow().select(index, index);
12808      }
12809      selectionAtEnd.insertNodes(nodes);
12810      for (let i2 = 0; i2 < selectedNodesLength; i2++) {
12811        selectedNodes[i2].remove();
12812      }
12813    }
12814    getNodes() {
12815      const cachedNodes = this._cachedNodes;
12816      if (cachedNodes !== null) {
12817        return cachedNodes;
12818      }
12819      const objects = this._nodes;
12820      const nodes = [];
12821      for (const object of objects) {
12822        const node = $getNodeByKey(object);
12823        if (node !== null) {
12824          nodes.push(node);
12825        }
12826      }
12827      if (!isCurrentlyReadOnlyMode()) {
12828        this._cachedNodes = nodes;
12829      }
12830      return nodes;
12831    }
12832    getTextContent() {
12833      const nodes = this.getNodes();
12834      let textContent = "";
12835      for (let i2 = 0; i2 < nodes.length; i2++) {
12836        textContent += nodes[i2].getTextContent();
12837      }
12838      return textContent;
12839    }
12840    /**
12841     * Remove all nodes in the NodeSelection. If there were any nodes,
12842     * replace the selection with a new RangeSelection at the previous
12843     * location of the first node.
12844     */
12845    deleteNodes() {
12846      const nodes = this.getNodes();
12847      if (($getSelection() || $getPreviousSelection()) === this && nodes[0]) {
12848        const firstCaret = $getSiblingCaret(nodes[0], "next");
12849        $setSelectionFromCaretRange($getCaretRange(firstCaret, firstCaret));
12850      }
12851      for (const node of nodes) {
12852        node.remove();
12853      }
12854    }
12855  };
12856  function $isRangeSelection(x3) {
12857    return x3 instanceof RangeSelection;
12858  }
12859  var RangeSelection = class _RangeSelection {
12860    format;
12861    style;
12862    anchor;
12863    focus;
12864    _cachedNodes;
12865    dirty;
12866    constructor(anchor, focus, format, style) {
12867      this.anchor = anchor;
12868      this.focus = focus;
12869      anchor._selection = this;
12870      focus._selection = this;
12871      this._cachedNodes = null;
12872      this.format = format;
12873      this.style = style;
12874      this.dirty = false;
12875    }
12876    getCachedNodes() {
12877      return this._cachedNodes;
12878    }
12879    setCachedNodes(nodes) {
12880      this._cachedNodes = nodes;
12881    }
12882    /**
12883     * Used to check if the provided selections is equal to this one by value,
12884     * including anchor, focus, format, and style properties.
12885     * @param selection - the Selection to compare this one to.
12886     * @returns true if the Selections are equal, false otherwise.
12887     */
12888    is(selection) {
12889      if (!$isRangeSelection(selection)) {
12890        return false;
12891      }
12892      return this.anchor.is(selection.anchor) && this.focus.is(selection.focus) && this.format === selection.format && this.style === selection.style;
12893    }
12894    /**
12895     * Returns whether the Selection is "collapsed", meaning the anchor and focus are
12896     * the same node and have the same offset.
12897     *
12898     * @returns true if the Selection is collapsed, false otherwise.
12899     */
12900    isCollapsed() {
12901      return this.anchor.is(this.focus);
12902    }
12903    /**
12904     * Gets all the nodes in the Selection. Uses caching to make it generally suitable
12905     * for use in hot paths.
12906     *
12907     * See also the {@link CaretRange} APIs (starting with
12908     * {@link $caretRangeFromSelection}), which are likely to provide a better
12909     * foundation for any operation where partial selection is relevant
12910     * (e.g. the anchor or focus are inside an ElementNode and TextNode)
12911     *
12912     * @returns an Array containing all the nodes in the Selection
12913     */
12914    getNodes() {
12915      const cachedNodes = this._cachedNodes;
12916      if (cachedNodes !== null) {
12917        return cachedNodes;
12918      }
12919      const range2 = $getCaretRangeInDirection($caretRangeFromSelection(this), "next");
12920      const nodes = $getNodesFromCaretRangeCompat(range2);
12921      {
12922        if (this.isCollapsed() && nodes.length > 1) {
12923          {
12924            formatDevErrorMessage(`RangeSelection.getNodes() returned ${String(nodes.length)} > 1 nodes in a collapsed selection`);
12925          }
12926        }
12927      }
12928      if (!isCurrentlyReadOnlyMode()) {
12929        this._cachedNodes = nodes;
12930      }
12931      return nodes;
12932    }
12933    /**
12934     * Sets this Selection to be of type "text" at the provided anchor and focus values.
12935     *
12936     * @param anchorNode - the anchor node to set on the Selection
12937     * @param anchorOffset - the offset to set on the Selection
12938     * @param focusNode - the focus node to set on the Selection
12939     * @param focusOffset - the focus offset to set on the Selection
12940     */
12941    setTextNodeRange(anchorNode, anchorOffset, focusNode, focusOffset) {
12942      this.anchor.set(anchorNode.__key, anchorOffset, "text");
12943      this.focus.set(focusNode.__key, focusOffset, "text");
12944    }
12945    /**
12946     * Gets the (plain) text content of all the nodes in the selection.
12947     *
12948     * @returns a string representing the text content of all the nodes in the Selection
12949     */
12950    getTextContent() {
12951      const nodes = this.getNodes();
12952      if (nodes.length === 0) {
12953        return "";
12954      }
12955      const firstNode = nodes[0];
12956      const lastNode = nodes[nodes.length - 1];
12957      const anchor = this.anchor;
12958      const focus = this.focus;
12959      const isBefore = anchor.isBefore(focus);
12960      const [anchorOffset, focusOffset] = $getCharacterOffsets(this);
12961      let textContent = "";
12962      let prevWasElement = true;
12963      for (let i2 = 0; i2 < nodes.length; i2++) {
12964        const node = nodes[i2];
12965        if ($isElementNode(node) && !node.isInline()) {
12966          if (!prevWasElement) {
12967            textContent += "\n";
12968          }
12969          if (node.isEmpty()) {
12970            prevWasElement = false;
12971          } else {
12972            prevWasElement = true;
12973          }
12974        } else {
12975          prevWasElement = false;
12976          if ($isTextNode(node)) {
12977            let text2 = node.getTextContent();
12978            if (node === firstNode) {
12979              if (node === lastNode) {
12980                if (anchor.type !== "element" || focus.type !== "element" || focus.offset === anchor.offset) {
12981                  text2 = anchorOffset < focusOffset ? text2.slice(anchorOffset, focusOffset) : text2.slice(focusOffset, anchorOffset);
12982                }
12983              } else {
12984                text2 = isBefore ? text2.slice(anchorOffset) : text2.slice(focusOffset);
12985              }
12986            } else if (node === lastNode) {
12987              text2 = isBefore ? text2.slice(0, focusOffset) : text2.slice(0, anchorOffset);
12988            }
12989            textContent += text2;
12990          } else if (($isDecoratorNode(node) || $isLineBreakNode(node)) && (node !== lastNode || !this.isCollapsed())) {
12991            textContent += node.getTextContent();
12992          }
12993        }
12994      }
12995      return textContent;
12996    }
12997    /**
12998     * Attempts to map a DOM selection range onto this Lexical Selection,
12999     * setting the anchor, focus, and type accordingly
13000     *
13001     * @param range a DOM Selection range conforming to the StaticRange interface.
13002     */
13003    applyDOMRange(range2) {
13004      const editor = getActiveEditor();
13005      const currentEditorState = editor.getEditorState();
13006      const lastSelection = currentEditorState._selection;
13007      const resolvedSelectionPoints = $internalResolveSelectionPoints(range2.startContainer, range2.startOffset, range2.endContainer, range2.endOffset, editor, lastSelection);
13008      if (resolvedSelectionPoints === null) {
13009        return;
13010      }
13011      const [anchorPoint, focusPoint] = resolvedSelectionPoints;
13012      this.anchor.set(anchorPoint.key, anchorPoint.offset, anchorPoint.type, true);
13013      this.focus.set(focusPoint.key, focusPoint.offset, focusPoint.type, true);
13014      $normalizeSelection(this);
13015    }
13016    /**
13017     * Creates a new RangeSelection, copying over all the property values from this one.
13018     *
13019     * @returns a new RangeSelection with the same property values as this one.
13020     */
13021    clone() {
13022      const anchor = this.anchor;
13023      const focus = this.focus;
13024      const selection = new _RangeSelection($createPoint(anchor.key, anchor.offset, anchor.type), $createPoint(focus.key, focus.offset, focus.type), this.format, this.style);
13025      return selection;
13026    }
13027    /**
13028     * Toggles the provided format on all the TextNodes in the Selection.
13029     *
13030     * @param format a string TextFormatType to toggle on the TextNodes in the selection
13031     */
13032    toggleFormat(format) {
13033      this.format = toggleTextFormatType(this.format, format, null);
13034      this.dirty = true;
13035    }
13036    /**
13037     * Sets the value of the format property on the Selection
13038     *
13039     * @param format - the format to set at the value of the format property.
13040     */
13041    setFormat(format) {
13042      this.format = format;
13043      this.dirty = true;
13044    }
13045    /**
13046     * Sets the value of the style property on the Selection
13047     *
13048     * @param style - the style to set at the value of the style property.
13049     */
13050    setStyle(style) {
13051      this.style = style;
13052      this.dirty = true;
13053    }
13054    /**
13055     * Returns whether the provided TextFormatType is present on the Selection. This will be true if any node in the Selection
13056     * has the specified format.
13057     *
13058     * @param type the TextFormatType to check for.
13059     * @returns true if the provided format is currently toggled on on the Selection, false otherwise.
13060     */
13061    hasFormat(type) {
13062      const formatFlag = TEXT_TYPE_TO_FORMAT[type];
13063      return (this.format & formatFlag) !== 0;
13064    }
13065    /**
13066     * Attempts to insert the provided text into the EditorState at the current Selection.
13067     * converts tabs, newlines, and carriage returns into LexicalNodes.
13068     *
13069     * @param text the text to insert into the Selection
13070     */
13071    insertRawText(text2) {
13072      const parts = text2.split(/(\r?\n|\t)/);
13073      const nodes = [];
13074      const length = parts.length;
13075      for (let i2 = 0; i2 < length; i2++) {
13076        const part = parts[i2];
13077        if (part === "\n" || part === "\r\n") {
13078          nodes.push($createLineBreakNode());
13079        } else if (part === "	") {
13080          nodes.push($createTabNode());
13081        } else {
13082          nodes.push($createTextNode(part));
13083        }
13084      }
13085      this.insertNodes(nodes);
13086    }
13087    /**
13088     * Insert the provided text into the EditorState at the current Selection.
13089     *
13090     * @param text the text to insert into the Selection
13091     */
13092    insertText(text2) {
13093      const anchor = this.anchor;
13094      const focus = this.focus;
13095      const format = this.format;
13096      const style = this.style;
13097      let firstPoint = anchor;
13098      let endPoint = focus;
13099      if (!this.isCollapsed() && focus.isBefore(anchor)) {
13100        firstPoint = focus;
13101        endPoint = anchor;
13102      }
13103      if (firstPoint.type === "element") {
13104        $transferStartingElementPointToTextPoint(firstPoint, endPoint, format, style);
13105      }
13106      if (endPoint.type === "element") {
13107        $setPointFromCaret(endPoint, $normalizeCaret($caretFromPoint(endPoint, "next")));
13108      }
13109      const startOffset = firstPoint.offset;
13110      let endOffset = endPoint.offset;
13111      const selectedNodes = this.getNodes();
13112      const selectedNodesLength = selectedNodes.length;
13113      let firstNode = selectedNodes[0];
13114      if (!$isTextNode(firstNode)) {
13115        {
13116          formatDevErrorMessage(`insertText: first node is not a text node`);
13117        }
13118      }
13119      const firstNodeText = firstNode.getTextContent();
13120      const firstNodeTextLength = firstNodeText.length;
13121      const firstNodeParent = firstNode.getParentOrThrow();
13122      const lastIndex = selectedNodesLength - 1;
13123      let lastNode = selectedNodes[lastIndex];
13124      if (selectedNodesLength === 1 && endPoint.type === "element") {
13125        endOffset = firstNodeTextLength;
13126        endPoint.set(firstPoint.key, endOffset, "text");
13127      }
13128      if (this.isCollapsed() && startOffset === firstNodeTextLength && ($isTokenOrSegmented(firstNode) || !firstNode.canInsertTextAfter() || !firstNodeParent.canInsertTextAfter() && firstNode.getNextSibling() === null)) {
13129        let nextSibling = firstNode.getNextSibling();
13130        if (!$isTextNode(nextSibling) || !nextSibling.canInsertTextBefore() || $isTokenOrSegmented(nextSibling)) {
13131          nextSibling = $createTextNode();
13132          nextSibling.setFormat(format);
13133          nextSibling.setStyle(style);
13134          if (!firstNodeParent.canInsertTextAfter()) {
13135            firstNodeParent.insertAfter(nextSibling);
13136          } else {
13137            firstNode.insertAfter(nextSibling);
13138          }
13139        }
13140        nextSibling.select(0, 0);
13141        firstNode = nextSibling;
13142        if (text2 !== "") {
13143          this.insertText(text2);
13144          return;
13145        }
13146      } else if (this.isCollapsed() && startOffset === 0 && ($isTokenOrSegmented(firstNode) || !firstNode.canInsertTextBefore() || !firstNodeParent.canInsertTextBefore() && firstNode.getPreviousSibling() === null)) {
13147        let prevSibling = firstNode.getPreviousSibling();
13148        if (!$isTextNode(prevSibling) || $isTokenOrSegmented(prevSibling)) {
13149          prevSibling = $createTextNode();
13150          prevSibling.setFormat(format);
13151          if (!firstNodeParent.canInsertTextBefore()) {
13152            firstNodeParent.insertBefore(prevSibling);
13153          } else {
13154            firstNode.insertBefore(prevSibling);
13155          }
13156        }
13157        prevSibling.select();
13158        firstNode = prevSibling;
13159        if (text2 !== "") {
13160          this.insertText(text2);
13161          return;
13162        }
13163      } else if (firstNode.isSegmented() && startOffset !== firstNodeTextLength) {
13164        const textNode = $createTextNode(firstNode.getTextContent());
13165        textNode.setFormat(format);
13166        firstNode.replace(textNode);
13167        firstNode = textNode;
13168      } else if (!this.isCollapsed() && text2 !== "") {
13169        const lastNodeParent = lastNode.getParent();
13170        if (!firstNodeParent.canInsertTextBefore() || !firstNodeParent.canInsertTextAfter() || $isElementNode(lastNodeParent) && (!lastNodeParent.canInsertTextBefore() || !lastNodeParent.canInsertTextAfter())) {
13171          this.insertText("");
13172          $normalizeSelectionPointsForBoundaries(this.anchor, this.focus);
13173          this.insertText(text2);
13174          return;
13175        }
13176      }
13177      if (selectedNodesLength === 1) {
13178        if ($isTokenOrTab(firstNode)) {
13179          const textNode = $createTextNode(text2);
13180          textNode.select();
13181          firstNode.replace(textNode);
13182          return;
13183        }
13184        const firstNodeFormat = firstNode.getFormat();
13185        const firstNodeStyle = firstNode.getStyle();
13186        if (startOffset === endOffset && (firstNodeFormat !== format || firstNodeStyle !== style)) {
13187          if (firstNode.getTextContent() === "") {
13188            firstNode.setFormat(format);
13189            firstNode.setStyle(style);
13190          } else {
13191            const textNode = $createTextNode(text2);
13192            textNode.setFormat(format);
13193            textNode.setStyle(style);
13194            textNode.select();
13195            if (startOffset === 0) {
13196              firstNode.insertBefore(textNode, false);
13197            } else {
13198              const [targetNode] = firstNode.splitText(startOffset);
13199              targetNode.insertAfter(textNode, false);
13200            }
13201            if (textNode.isComposing() && this.anchor.type === "text") {
13202              this.anchor.offset -= text2.length;
13203            }
13204            return;
13205          }
13206        } else if ($isTabNode(firstNode)) {
13207          const textNode = $createTextNode(text2);
13208          textNode.setFormat(format);
13209          textNode.setStyle(style);
13210          textNode.select();
13211          firstNode.replace(textNode);
13212          return;
13213        }
13214        const delCount = endOffset - startOffset;
13215        firstNode = firstNode.spliceText(startOffset, delCount, text2, true);
13216        if (firstNode.getTextContent() === "") {
13217          firstNode.remove();
13218        } else if (this.anchor.type === "text") {
13219          this.format = firstNodeFormat;
13220          this.style = firstNodeStyle;
13221          if (firstNode.isComposing()) {
13222            this.anchor.offset -= text2.length;
13223          }
13224        }
13225      } else {
13226        const markedNodeKeysForKeep = /* @__PURE__ */ new Set([...firstNode.getParentKeys(), ...lastNode.getParentKeys()]);
13227        const firstElement = $isElementNode(firstNode) ? firstNode : firstNode.getParentOrThrow();
13228        let lastElement = $isElementNode(lastNode) ? lastNode : lastNode.getParentOrThrow();
13229        let lastElementChild = lastNode;
13230        if (!firstElement.is(lastElement) && lastElement.isInline()) {
13231          do {
13232            lastElementChild = lastElement;
13233            lastElement = lastElement.getParentOrThrow();
13234          } while (lastElement.isInline());
13235        }
13236        if (endPoint.type === "text" && (endOffset !== 0 || lastNode.getTextContent() === "") || endPoint.type === "element" && lastNode.getIndexWithinParent() < endOffset) {
13237          if ($isTextNode(lastNode) && !$isTokenOrTab(lastNode) && endOffset !== lastNode.getTextContentSize()) {
13238            if (lastNode.isSegmented()) {
13239              const textNode = $createTextNode(lastNode.getTextContent());
13240              lastNode.replace(textNode);
13241              lastNode = textNode;
13242            }
13243            if (!$isRootNode(endPoint.getNode()) && endPoint.type === "text") {
13244              lastNode = lastNode.spliceText(0, endOffset, "");
13245            }
13246            markedNodeKeysForKeep.add(lastNode.__key);
13247          } else {
13248            const lastNodeParent = lastNode.getParentOrThrow();
13249            if (!lastNodeParent.canBeEmpty() && lastNodeParent.getChildrenSize() === 1) {
13250              lastNodeParent.remove();
13251            } else {
13252              lastNode.remove();
13253            }
13254          }
13255        } else {
13256          markedNodeKeysForKeep.add(lastNode.__key);
13257        }
13258        const lastNodeChildren = lastElement.getChildren();
13259        const selectedNodesSet = new Set(selectedNodes);
13260        const firstAndLastElementsAreEqual = firstElement.is(lastElement);
13261        const insertionTarget = firstElement.isInline() && firstNode.getNextSibling() === null ? firstElement : firstNode;
13262        for (let i2 = lastNodeChildren.length - 1; i2 >= 0; i2--) {
13263          const lastNodeChild = lastNodeChildren[i2];
13264          if (lastNodeChild.is(firstNode) || $isElementNode(lastNodeChild) && lastNodeChild.isParentOf(firstNode)) {
13265            break;
13266          }
13267          if (lastNodeChild.isAttached()) {
13268            if (!selectedNodesSet.has(lastNodeChild) || lastNodeChild.is(lastElementChild)) {
13269              if (!firstAndLastElementsAreEqual) {
13270                insertionTarget.insertAfter(lastNodeChild, false);
13271              }
13272            } else {
13273              lastNodeChild.remove();
13274            }
13275          }
13276        }
13277        if (!firstAndLastElementsAreEqual) {
13278          let parent = lastElement;
13279          let lastRemovedParent = null;
13280          while (parent !== null) {
13281            const children = parent.getChildren();
13282            const childrenLength = children.length;
13283            if (childrenLength === 0 || children[childrenLength - 1].is(lastRemovedParent)) {
13284              markedNodeKeysForKeep.delete(parent.__key);
13285              lastRemovedParent = parent;
13286            }
13287            parent = parent.getParent();
13288          }
13289        }
13290        if (!$isTokenOrTab(firstNode)) {
13291          firstNode = firstNode.spliceText(startOffset, firstNodeTextLength - startOffset, text2, true);
13292          if (firstNode.getTextContent() === "") {
13293            firstNode.remove();
13294          } else if (this.anchor.type === "text") {
13295            this.format = firstNode.getFormat();
13296            this.style = firstNode.getStyle();
13297            if (firstNode.isComposing()) {
13298              this.anchor.offset -= text2.length;
13299            }
13300          }
13301        } else if (startOffset === firstNodeTextLength) {
13302          firstNode.select();
13303        } else {
13304          const textNode = $createTextNode(text2);
13305          textNode.select();
13306          firstNode.replace(textNode);
13307        }
13308        for (let i2 = 1; i2 < selectedNodesLength; i2++) {
13309          const selectedNode = selectedNodes[i2];
13310          const key = selectedNode.__key;
13311          if (!markedNodeKeysForKeep.has(key)) {
13312            selectedNode.remove();
13313          }
13314        }
13315      }
13316    }
13317    /**
13318     * Removes the text in the Selection, adjusting the EditorState accordingly.
13319     */
13320    removeText() {
13321      const isCurrentSelection = $getSelection() === this;
13322      const newRange = $removeTextFromCaretRange($caretRangeFromSelection(this));
13323      $updateRangeSelectionFromCaretRange(this, newRange);
13324      if (isCurrentSelection && $getSelection() !== this) {
13325        $setSelection(this);
13326      }
13327    }
13328    // TO-DO: Migrate this method to the new utility function $forEachSelectedTextNode (share similar logic)
13329    /**
13330     * Applies the provided format to the TextNodes in the Selection, splitting or
13331     * merging nodes as necessary.
13332     *
13333     * @param formatType the format type to apply to the nodes in the Selection.
13334     * @param alignWithFormat a 32-bit integer representing formatting flags to align with.
13335     */
13336    formatText(formatType, alignWithFormat = null) {
13337      if (this.isCollapsed()) {
13338        this.toggleFormat(formatType);
13339        $setCompositionKey(null);
13340        return;
13341      }
13342      const selectedNodes = this.getNodes();
13343      const selectedTextNodes = [];
13344      for (const selectedNode of selectedNodes) {
13345        if ($isTextNode(selectedNode)) {
13346          selectedTextNodes.push(selectedNode);
13347        }
13348      }
13349      const applyFormatToElements = (alignWith) => {
13350        selectedNodes.forEach((node) => {
13351          if ($isElementNode(node)) {
13352            const newFormat = node.getFormatFlags(formatType, alignWith);
13353            node.setTextFormat(newFormat);
13354          }
13355        });
13356      };
13357      const selectedTextNodesLength = selectedTextNodes.length;
13358      if (selectedTextNodesLength === 0) {
13359        this.toggleFormat(formatType);
13360        $setCompositionKey(null);
13361        applyFormatToElements(alignWithFormat);
13362        return;
13363      }
13364      const anchor = this.anchor;
13365      const focus = this.focus;
13366      const isBackward = this.isBackward();
13367      const startPoint = isBackward ? focus : anchor;
13368      const endPoint = isBackward ? anchor : focus;
13369      let firstIndex = 0;
13370      let firstNode = selectedTextNodes[0];
13371      let startOffset = startPoint.type === "element" ? 0 : startPoint.offset;
13372      if (startPoint.type === "text" && startOffset === firstNode.getTextContentSize()) {
13373        firstIndex = 1;
13374        firstNode = selectedTextNodes[1];
13375        startOffset = 0;
13376      }
13377      if (firstNode == null) {
13378        return;
13379      }
13380      const firstNextFormat = firstNode.getFormatFlags(formatType, alignWithFormat);
13381      applyFormatToElements(firstNextFormat);
13382      const lastIndex = selectedTextNodesLength - 1;
13383      let lastNode = selectedTextNodes[lastIndex];
13384      const endOffset = endPoint.type === "text" ? endPoint.offset : lastNode.getTextContentSize();
13385      if (firstNode.is(lastNode)) {
13386        if (startOffset === endOffset) {
13387          return;
13388        }
13389        if ($isTokenOrSegmented(firstNode) || startOffset === 0 && endOffset === firstNode.getTextContentSize()) {
13390          firstNode.setFormat(firstNextFormat);
13391        } else {
13392          const splitNodes = firstNode.splitText(startOffset, endOffset);
13393          const replacement = startOffset === 0 ? splitNodes[0] : splitNodes[1];
13394          replacement.setFormat(firstNextFormat);
13395          if (startPoint.type === "text") {
13396            startPoint.set(replacement.__key, 0, "text");
13397          }
13398          if (endPoint.type === "text") {
13399            endPoint.set(replacement.__key, endOffset - startOffset, "text");
13400          }
13401        }
13402        this.format = firstNextFormat;
13403        return;
13404      }
13405      if (startOffset !== 0 && !$isTokenOrSegmented(firstNode)) {
13406        [, firstNode] = firstNode.splitText(startOffset);
13407        startOffset = 0;
13408      }
13409      firstNode.setFormat(firstNextFormat);
13410      const lastNextFormat = lastNode.getFormatFlags(formatType, firstNextFormat);
13411      if (endOffset > 0) {
13412        if (endOffset !== lastNode.getTextContentSize() && !$isTokenOrSegmented(lastNode)) {
13413          [lastNode] = lastNode.splitText(endOffset);
13414        }
13415        lastNode.setFormat(lastNextFormat);
13416      }
13417      for (let i2 = firstIndex + 1; i2 < lastIndex; i2++) {
13418        const textNode = selectedTextNodes[i2];
13419        const nextFormat = textNode.getFormatFlags(formatType, lastNextFormat);
13420        textNode.setFormat(nextFormat);
13421      }
13422      if (startPoint.type === "text") {
13423        startPoint.set(firstNode.__key, startOffset, "text");
13424      }
13425      if (endPoint.type === "text") {
13426        endPoint.set(lastNode.__key, endOffset, "text");
13427      }
13428      this.format = firstNextFormat | lastNextFormat;
13429    }
13430    /**
13431     * Attempts to "intelligently" insert an arbitrary list of Lexical nodes into the EditorState at the
13432     * current Selection according to a set of heuristics that determine how surrounding nodes
13433     * should be changed, replaced, or moved to accommodate the incoming ones.
13434     *
13435     * @param nodes - the nodes to insert
13436     */
13437    insertNodes(nodes) {
13438      if (nodes.length === 0) {
13439        return;
13440      }
13441      if (!this.isCollapsed()) {
13442        this.removeText();
13443      }
13444      if (this.anchor.key === "root") {
13445        this.insertParagraph();
13446        const selection = $getSelection();
13447        if (!$isRangeSelection(selection)) {
13448          formatDevErrorMessage(`Expected RangeSelection after insertParagraph`);
13449        }
13450        return selection.insertNodes(nodes);
13451      }
13452      const firstPoint = this.isBackward() ? this.focus : this.anchor;
13453      const firstNode = firstPoint.getNode();
13454      const firstBlock = $findMatchingParent(firstNode, INTERNAL_$isBlock);
13455      const last = nodes[nodes.length - 1];
13456      if ($isElementNode(firstBlock) && "__language" in firstBlock) {
13457        if ("__language" in nodes[0]) {
13458          this.insertText(nodes[0].getTextContent());
13459        } else {
13460          const index = $removeTextAndSplitBlock(this);
13461          firstBlock.splice(index, 0, nodes);
13462          last.selectEnd();
13463        }
13464        return;
13465      }
13466      const notInline = (node) => ($isElementNode(node) || $isDecoratorNode(node)) && !node.isInline();
13467      if (!nodes.some(notInline)) {
13468        if (!$isElementNode(firstBlock)) {
13469          formatDevErrorMessage(`Expected node ${firstNode.constructor.name} of type ${firstNode.getType()} to have a block ElementNode ancestor`);
13470        }
13471        const index = $removeTextAndSplitBlock(this);
13472        firstBlock.splice(index, 0, nodes);
13473        last.selectEnd();
13474        return;
13475      }
13476      const blocksParent = $wrapInlineNodes(nodes);
13477      const nodeToSelect = blocksParent.getLastDescendant();
13478      const blocks = blocksParent.getChildren();
13479      const isMergeable = (node) => $isElementNode(node) && INTERNAL_$isBlock(node) && !node.isEmpty() && $isElementNode(firstBlock) && (!firstBlock.isEmpty() || firstBlock.canMergeWhenEmpty());
13480      const shouldInsert = !$isElementNode(firstBlock) || !firstBlock.isEmpty();
13481      const insertedParagraph = shouldInsert ? this.insertParagraph() : null;
13482      const lastToInsert = blocks[blocks.length - 1];
13483      let firstToInsert = blocks[0];
13484      if (isMergeable(firstToInsert)) {
13485        if (!$isElementNode(firstBlock)) {
13486          formatDevErrorMessage(`Expected node ${firstNode.constructor.name} of type ${firstNode.getType()} to have a block ElementNode ancestor`);
13487        }
13488        firstBlock.append(...firstToInsert.getChildren());
13489        firstToInsert = blocks[1];
13490      }
13491      if (firstToInsert) {
13492        if (!(firstBlock !== null)) {
13493          formatDevErrorMessage(`Expected node ${firstNode.constructor.name} of type ${firstNode.getType()} to have a block ancestor`);
13494        }
13495        insertRangeAfter(firstBlock, firstToInsert);
13496      }
13497      const lastInsertedBlock = $findMatchingParent(nodeToSelect, INTERNAL_$isBlock);
13498      if (insertedParagraph && $isElementNode(lastInsertedBlock) && (insertedParagraph.canMergeWhenEmpty() || INTERNAL_$isBlock(lastToInsert))) {
13499        lastInsertedBlock.append(...insertedParagraph.getChildren());
13500        insertedParagraph.remove();
13501      }
13502      if ($isElementNode(firstBlock) && firstBlock.isEmpty()) {
13503        firstBlock.remove();
13504      }
13505      nodeToSelect.selectEnd();
13506      const lastChild = $isElementNode(firstBlock) ? firstBlock.getLastChild() : null;
13507      if ($isLineBreakNode(lastChild) && lastInsertedBlock !== firstBlock) {
13508        lastChild.remove();
13509      }
13510    }
13511    /**
13512     * Inserts a new ParagraphNode into the EditorState at the current Selection
13513     *
13514     * @returns the newly inserted node.
13515     */
13516    insertParagraph() {
13517      if (this.anchor.key === "root") {
13518        const paragraph = $createParagraphNode();
13519        $getRoot().splice(this.anchor.offset, 0, [paragraph]);
13520        paragraph.select();
13521        return paragraph;
13522      }
13523      const index = $removeTextAndSplitBlock(this);
13524      const block = $findMatchingParent(this.anchor.getNode(), INTERNAL_$isBlock);
13525      if (!$isElementNode(block)) {
13526        formatDevErrorMessage(`Expected ancestor to be a block ElementNode`);
13527      }
13528      const firstToAppend = block.getChildAtIndex(index);
13529      const nodesToInsert = firstToAppend ? [firstToAppend, ...firstToAppend.getNextSiblings()] : [];
13530      const newBlock = block.insertNewAfter(this, false);
13531      if (newBlock) {
13532        newBlock.append(...nodesToInsert);
13533        newBlock.selectStart();
13534        return newBlock;
13535      }
13536      return null;
13537    }
13538    /**
13539     * Inserts a logical linebreak, which may be a new LineBreakNode or a new ParagraphNode, into the EditorState at the
13540     * current Selection.
13541     */
13542    insertLineBreak(selectStart) {
13543      const lineBreak = $createLineBreakNode();
13544      this.insertNodes([lineBreak]);
13545      if (selectStart) {
13546        const parent = lineBreak.getParentOrThrow();
13547        const index = lineBreak.getIndexWithinParent();
13548        parent.select(index, index);
13549      }
13550    }
13551    /**
13552     * Extracts the nodes in the Selection, splitting nodes where necessary
13553     * to get offset-level precision.
13554     *
13555     * @returns The nodes in the Selection
13556     */
13557    extract() {
13558      const selectedNodes = [...this.getNodes()];
13559      const selectedNodesLength = selectedNodes.length;
13560      let firstNode = selectedNodes[0];
13561      let lastNode = selectedNodes[selectedNodesLength - 1];
13562      const [anchorOffset, focusOffset] = $getCharacterOffsets(this);
13563      const isBackward = this.isBackward();
13564      const [startPoint, endPoint] = isBackward ? [this.focus, this.anchor] : [this.anchor, this.focus];
13565      const [startOffset, endOffset] = isBackward ? [focusOffset, anchorOffset] : [anchorOffset, focusOffset];
13566      if (selectedNodesLength === 0) {
13567        return [];
13568      } else if (selectedNodesLength === 1) {
13569        if ($isTextNode(firstNode) && !this.isCollapsed()) {
13570          const splitNodes = firstNode.splitText(startOffset, endOffset);
13571          const node = startOffset === 0 ? splitNodes[0] : splitNodes[1];
13572          if (node) {
13573            startPoint.set(node.getKey(), 0, "text");
13574            endPoint.set(node.getKey(), node.getTextContentSize(), "text");
13575            return [node];
13576          }
13577          return [];
13578        }
13579        return [firstNode];
13580      }
13581      if ($isTextNode(firstNode)) {
13582        if (startOffset === firstNode.getTextContentSize()) {
13583          selectedNodes.shift();
13584        } else if (startOffset !== 0) {
13585          [, firstNode] = firstNode.splitText(startOffset);
13586          selectedNodes[0] = firstNode;
13587          startPoint.set(firstNode.getKey(), 0, "text");
13588        }
13589      }
13590      if ($isTextNode(lastNode)) {
13591        const lastNodeText = lastNode.getTextContent();
13592        const lastNodeTextLength = lastNodeText.length;
13593        if (endOffset === 0) {
13594          selectedNodes.pop();
13595        } else if (endOffset !== lastNodeTextLength) {
13596          [lastNode] = lastNode.splitText(endOffset);
13597          selectedNodes[selectedNodes.length - 1] = lastNode;
13598          endPoint.set(lastNode.getKey(), lastNode.getTextContentSize(), "text");
13599        }
13600      }
13601      return selectedNodes;
13602    }
13603    /**
13604     * Modifies the Selection according to the parameters and a set of heuristics that account for
13605     * various node types. Can be used to safely move or extend selection by one logical "unit" without
13606     * dealing explicitly with all the possible node types.
13607     *
13608     * @param alter the type of modification to perform
13609     * @param isBackward whether or not selection is backwards
13610     * @param granularity the granularity at which to apply the modification
13611     */
13612    modify(alter, isBackward, granularity) {
13613      if ($modifySelectionAroundDecoratorsAndBlocks(this, alter, isBackward, granularity)) {
13614        return;
13615      }
13616      const collapse = alter === "move";
13617      const editor = getActiveEditor();
13618      const domSelection = getDOMSelection(getWindow(editor));
13619      if (!domSelection) {
13620        return;
13621      }
13622      const blockCursorElement = editor._blockCursorElement;
13623      const rootElement = editor._rootElement;
13624      const focusNode = this.focus.getNode();
13625      if (rootElement !== null && blockCursorElement !== null && $isElementNode(focusNode) && !focusNode.isInline() && !focusNode.canBeEmpty()) {
13626        removeDOMBlockCursorElement(blockCursorElement, editor, rootElement);
13627      }
13628      if (this.dirty) {
13629        let nextAnchorDOM = getElementByKeyOrThrow(editor, this.anchor.key);
13630        let nextFocusDOM = getElementByKeyOrThrow(editor, this.focus.key);
13631        if (this.anchor.type === "text") {
13632          nextAnchorDOM = getDOMTextNode(nextAnchorDOM);
13633        }
13634        if (this.focus.type === "text") {
13635          nextFocusDOM = getDOMTextNode(nextFocusDOM);
13636        }
13637        if (nextAnchorDOM && nextFocusDOM) {
13638          setDOMSelectionBaseAndExtent(domSelection, nextAnchorDOM, this.anchor.offset, nextFocusDOM, this.focus.offset);
13639        }
13640      }
13641      moveNativeSelection(domSelection, alter, isBackward ? "backward" : "forward", granularity);
13642      if (domSelection.rangeCount > 0) {
13643        const range2 = domSelection.getRangeAt(0);
13644        const anchorNode = this.anchor.getNode();
13645        const root = $isRootNode(anchorNode) ? anchorNode : $getNearestRootOrShadowRoot(anchorNode);
13646        this.applyDOMRange(range2);
13647        this.dirty = true;
13648        if (!collapse) {
13649          const nodes = this.getNodes();
13650          const validNodes = [];
13651          let shrinkSelection = false;
13652          for (let i2 = 0; i2 < nodes.length; i2++) {
13653            const nextNode = nodes[i2];
13654            if ($hasAncestor(nextNode, root)) {
13655              validNodes.push(nextNode);
13656            } else {
13657              shrinkSelection = true;
13658            }
13659          }
13660          if (shrinkSelection && validNodes.length > 0) {
13661            if (isBackward) {
13662              const firstValidNode = validNodes[0];
13663              if ($isElementNode(firstValidNode)) {
13664                firstValidNode.selectStart();
13665              } else {
13666                firstValidNode.getParentOrThrow().selectStart();
13667              }
13668            } else {
13669              const lastValidNode = validNodes[validNodes.length - 1];
13670              if ($isElementNode(lastValidNode)) {
13671                lastValidNode.selectEnd();
13672              } else {
13673                lastValidNode.getParentOrThrow().selectEnd();
13674              }
13675            }
13676          }
13677          if (domSelection.anchorNode !== range2.startContainer || domSelection.anchorOffset !== range2.startOffset) {
13678            $swapPoints(this);
13679          }
13680        }
13681      }
13682      if (granularity === "lineboundary") {
13683        $modifySelectionAroundDecoratorsAndBlocks(this, alter, isBackward, granularity, "decorators");
13684      }
13685    }
13686    /**
13687     * Helper for handling forward character and word deletion that prevents element nodes
13688     * like a table, columns layout being destroyed
13689     *
13690     * @param anchor the anchor
13691     * @param anchorNode the anchor node in the selection
13692     * @param isBackward whether or not selection is backwards
13693     */
13694    forwardDeletion(anchor, anchorNode, isBackward) {
13695      if (!isBackward && // Delete forward handle case
13696      (anchor.type === "element" && $isElementNode(anchorNode) && anchor.offset === anchorNode.getChildrenSize() || anchor.type === "text" && anchor.offset === anchorNode.getTextContentSize())) {
13697        const parent = anchorNode.getParent();
13698        const nextSibling = anchorNode.getNextSibling() || (parent === null ? null : parent.getNextSibling());
13699        if ($isElementNode(nextSibling) && nextSibling.isShadowRoot()) {
13700          return true;
13701        }
13702      }
13703      return false;
13704    }
13705    /**
13706     * Performs one logical character deletion operation on the EditorState based on the current Selection.
13707     * Handles different node types.
13708     *
13709     * @param isBackward whether or not the selection is backwards.
13710     */
13711    deleteCharacter(isBackward) {
13712      const wasCollapsed = this.isCollapsed();
13713      if (this.isCollapsed()) {
13714        const anchor = this.anchor;
13715        let anchorNode = anchor.getNode();
13716        if (this.forwardDeletion(anchor, anchorNode, isBackward)) {
13717          return;
13718        }
13719        const direction = isBackward ? "previous" : "next";
13720        const initialCaret = $caretFromPoint(anchor, direction);
13721        const initialRange = $extendCaretToRange(initialCaret);
13722        if (initialRange.getTextSlices().every((slice) => slice === null || slice.distance === 0)) {
13723          let state = {
13724            type: "initial"
13725          };
13726          for (const caret of initialRange.iterNodeCarets("shadowRoot")) {
13727            if ($isChildCaret(caret)) {
13728              if (caret.origin.isInline()) ;
13729              else if (caret.origin.isShadowRoot()) {
13730                if (state.type === "merge-block") {
13731                  break;
13732                }
13733                if ($isElementNode(initialRange.anchor.origin) && initialRange.anchor.origin.isEmpty()) {
13734                  const normCaret = $normalizeCaret(caret);
13735                  $updateRangeSelectionFromCaretRange(this, $getCaretRange(normCaret, normCaret));
13736                  initialRange.anchor.origin.remove();
13737                }
13738                return;
13739              } else if (state.type === "merge-next-block" || state.type === "merge-block") {
13740                state = {
13741                  block: state.block,
13742                  caret,
13743                  type: "merge-block"
13744                };
13745              }
13746            } else if (state.type === "merge-block") {
13747              break;
13748            } else if ($isSiblingCaret(caret)) {
13749              if ($isElementNode(caret.origin)) {
13750                if (!caret.origin.isInline()) {
13751                  state = {
13752                    block: caret.origin,
13753                    type: "merge-next-block"
13754                  };
13755                } else if (!caret.origin.isParentOf(initialRange.anchor.origin)) {
13756                  break;
13757                }
13758                continue;
13759              } else if ($isDecoratorNode(caret.origin)) {
13760                if (caret.origin.isIsolated()) ;
13761                else if (state.type === "merge-next-block" && (caret.origin.isKeyboardSelectable() || !caret.origin.isInline()) && $isElementNode(initialRange.anchor.origin) && initialRange.anchor.origin.isEmpty()) {
13762                  initialRange.anchor.origin.remove();
13763                  const nodeSelection = $createNodeSelection();
13764                  nodeSelection.add(caret.origin.getKey());
13765                  $setSelection(nodeSelection);
13766                } else {
13767                  caret.origin.remove();
13768                }
13769                return;
13770              }
13771              break;
13772            }
13773          }
13774          if (state.type === "merge-block") {
13775            const {
13776              caret,
13777              block
13778            } = state;
13779            $updateRangeSelectionFromCaretRange(this, $getCaretRange(!caret.origin.isEmpty() && block.isEmpty() ? $rewindSiblingCaret($getSiblingCaret(block, caret.direction)) : initialRange.anchor, caret));
13780            return this.removeText();
13781          }
13782        }
13783        const focus = this.focus;
13784        this.modify("extend", isBackward, "character");
13785        if (!this.isCollapsed()) {
13786          const focusNode = focus.type === "text" ? focus.getNode() : null;
13787          anchorNode = anchor.type === "text" ? anchor.getNode() : null;
13788          if (focusNode !== null && focusNode.isSegmented()) {
13789            const offset3 = focus.offset;
13790            const textContentSize = focusNode.getTextContentSize();
13791            if (focusNode.is(anchorNode) || isBackward && offset3 !== textContentSize || !isBackward && offset3 !== 0) {
13792              $removeSegment(focusNode, isBackward, offset3);
13793              return;
13794            }
13795          } else if (anchorNode !== null && anchorNode.isSegmented()) {
13796            const offset3 = anchor.offset;
13797            const textContentSize = anchorNode.getTextContentSize();
13798            if (anchorNode.is(focusNode) || isBackward && offset3 !== 0 || !isBackward && offset3 !== textContentSize) {
13799              $removeSegment(anchorNode, isBackward, offset3);
13800              return;
13801            }
13802          }
13803          $updateCaretSelectionForUnicodeCharacter(this, isBackward);
13804        } else if (isBackward && anchor.offset === 0) {
13805          if ($collapseAtStart(this, anchor.getNode())) {
13806            return;
13807          }
13808        }
13809      }
13810      this.removeText();
13811      if (isBackward && !wasCollapsed && this.isCollapsed() && this.anchor.type === "element" && this.anchor.offset === 0) {
13812        const anchorNode = this.anchor.getNode();
13813        if (anchorNode.isEmpty() && $isRootNode(anchorNode.getParent()) && anchorNode.getPreviousSibling() === null) {
13814          $collapseAtStart(this, anchorNode);
13815        }
13816      }
13817    }
13818    /**
13819     * Performs one logical line deletion operation on the EditorState based on the current Selection.
13820     * Handles different node types.
13821     *
13822     * @param isBackward whether or not the selection is backwards.
13823     */
13824    deleteLine(isBackward) {
13825      if (this.isCollapsed()) {
13826        this.modify("extend", isBackward, "lineboundary");
13827      }
13828      if (this.isCollapsed()) {
13829        this.deleteCharacter(isBackward);
13830      } else {
13831        this.removeText();
13832      }
13833    }
13834    /**
13835     * Performs one logical word deletion operation on the EditorState based on the current Selection.
13836     * Handles different node types.
13837     *
13838     * @param isBackward whether or not the selection is backwards.
13839     */
13840    deleteWord(isBackward) {
13841      if (this.isCollapsed()) {
13842        const anchor = this.anchor;
13843        const anchorNode = anchor.getNode();
13844        if (this.forwardDeletion(anchor, anchorNode, isBackward)) {
13845          return;
13846        }
13847        this.modify("extend", isBackward, "word");
13848      }
13849      if (this.isCollapsed()) {
13850        this.deleteCharacter(isBackward);
13851      } else {
13852        this.removeText();
13853      }
13854    }
13855    /**
13856     * Returns whether the Selection is "backwards", meaning the focus
13857     * logically precedes the anchor in the EditorState.
13858     * @returns true if the Selection is backwards, false otherwise.
13859     */
13860    isBackward() {
13861      return this.focus.isBefore(this.anchor);
13862    }
13863    getStartEndPoints() {
13864      return [this.anchor, this.focus];
13865    }
13866  };
13867  function $isNodeSelection(x3) {
13868    return x3 instanceof NodeSelection;
13869  }
13870  function getCharacterOffset(point) {
13871    const offset3 = point.offset;
13872    if (point.type === "text") {
13873      return offset3;
13874    }
13875    const parent = point.getNode();
13876    return offset3 === parent.getChildrenSize() ? parent.getTextContent().length : 0;
13877  }
13878  function $getCharacterOffsets(selection) {
13879    const anchorAndFocus = selection.getStartEndPoints();
13880    if (anchorAndFocus === null) {
13881      return [0, 0];
13882    }
13883    const [anchor, focus] = anchorAndFocus;
13884    if (anchor.type === "element" && focus.type === "element" && anchor.key === focus.key && anchor.offset === focus.offset) {
13885      return [0, 0];
13886    }
13887    return [getCharacterOffset(anchor), getCharacterOffset(focus)];
13888  }
13889  function $collapseAtStart(selection, startNode) {
13890    for (let node = startNode; node; node = node.getParent()) {
13891      if ($isElementNode(node)) {
13892        if (node.collapseAtStart(selection)) {
13893          return true;
13894        }
13895        if ($isRootOrShadowRoot(node)) {
13896          break;
13897        }
13898      }
13899      if (node.getPreviousSibling()) {
13900        break;
13901      }
13902    }
13903    return false;
13904  }
13905  function $swapPoints(selection) {
13906    const focus = selection.focus;
13907    const anchor = selection.anchor;
13908    const anchorKey = anchor.key;
13909    const anchorOffset = anchor.offset;
13910    const anchorType = anchor.type;
13911    anchor.set(focus.key, focus.offset, focus.type, true);
13912    focus.set(anchorKey, anchorOffset, anchorType, true);
13913  }
13914  function moveNativeSelection(domSelection, alter, direction, granularity) {
13915    domSelection.modify(alter, direction, granularity);
13916  }
13917  function $updateCaretSelectionForUnicodeCharacter(selection, isBackward) {
13918    const anchor = selection.anchor;
13919    const focus = selection.focus;
13920    const anchorNode = anchor.getNode();
13921    const focusNode = focus.getNode();
13922    if (anchorNode === focusNode && anchor.type === "text" && focus.type === "text") {
13923      const anchorOffset = anchor.offset;
13924      const focusOffset = focus.offset;
13925      const isBefore = anchorOffset < focusOffset;
13926      const startOffset = isBefore ? anchorOffset : focusOffset;
13927      const endOffset = isBefore ? focusOffset : anchorOffset;
13928      const characterOffset = endOffset - 1;
13929      if (startOffset !== characterOffset) {
13930        const text2 = anchorNode.getTextContent().slice(startOffset, endOffset);
13931        if (shouldDeleteExactlyOneCodeUnit(text2)) {
13932          if (isBackward) {
13933            focus.set(focus.key, characterOffset, focus.type);
13934          } else {
13935            anchor.set(anchor.key, characterOffset, anchor.type);
13936          }
13937        }
13938      }
13939    }
13940  }
13941  function shouldDeleteExactlyOneCodeUnit(text2) {
13942    {
13943      if (!(text2.length > 1)) {
13944        formatDevErrorMessage(`shouldDeleteExactlyOneCodeUnit: expecting to be called only with sequences of two or more code units`);
13945      }
13946    }
13947    return !(doesContainSurrogatePair(text2) || doesContainEmoji(text2));
13948  }
13949  var doesContainEmoji = (() => {
13950    try {
13951      const re3 = new RegExp("\\p{Emoji}", "u");
13952      const test = re3.test.bind(re3);
13953      if (
13954        // Emoji in the BMP (heart) with variation selector
13955        test("\u2764\uFE0F") && // Emoji in the BMP (#) with variation selector
13956        test("#\uFE0F\u20E3") && // Emoji outside the BMP (thumbs up) that is encoded with a surrogate pair
13957        test("\u{1F44D}")
13958      ) {
13959        return test;
13960      }
13961    } catch (_e2) {
13962    }
13963    return () => false;
13964  })();
13965  function $removeSegment(node, isBackward, offset3) {
13966    const textNode = node;
13967    const textContent = textNode.getTextContent();
13968    const split = textContent.split(/(?=\s)/g);
13969    const splitLength = split.length;
13970    let segmentOffset = 0;
13971    let restoreOffset = 0;
13972    for (let i2 = 0; i2 < splitLength; i2++) {
13973      const text2 = split[i2];
13974      const isLast = i2 === splitLength - 1;
13975      restoreOffset = segmentOffset;
13976      segmentOffset += text2.length;
13977      if (isBackward && segmentOffset === offset3 || segmentOffset > offset3 || isLast) {
13978        split.splice(i2, 1);
13979        if (isLast) {
13980          restoreOffset = void 0;
13981        }
13982        break;
13983      }
13984    }
13985    const nextTextContent = split.join("").trim();
13986    if (nextTextContent === "") {
13987      textNode.remove();
13988    } else {
13989      textNode.setTextContent(nextTextContent);
13990      textNode.select(restoreOffset, restoreOffset);
13991    }
13992  }
13993  function shouldResolveAncestor(resolvedElement, resolvedOffset, lastPoint) {
13994    const parent = resolvedElement.getParent();
13995    return lastPoint === null || parent === null || !parent.canBeEmpty() || parent !== lastPoint.getNode();
13996  }
13997  function $internalResolveSelectionPoint(dom, offset3, lastPoint, editor) {
13998    let resolvedOffset = offset3;
13999    let resolvedNode;
14000    if (isHTMLElement(dom)) {
14001      let moveSelectionToEnd = false;
14002      const childNodes = dom.childNodes;
14003      const childNodesLength = childNodes.length;
14004      const blockCursorElement = editor._blockCursorElement;
14005      if (resolvedOffset === childNodesLength) {
14006        moveSelectionToEnd = true;
14007        resolvedOffset = childNodesLength - 1;
14008      }
14009      let childDOM = childNodes[resolvedOffset];
14010      let hasBlockCursor = false;
14011      if (childDOM === blockCursorElement) {
14012        childDOM = childNodes[resolvedOffset + 1];
14013        hasBlockCursor = true;
14014      } else if (blockCursorElement !== null) {
14015        const blockCursorElementParent = blockCursorElement.parentNode;
14016        if (dom === blockCursorElementParent) {
14017          const blockCursorOffset = Array.prototype.indexOf.call(blockCursorElementParent.children, blockCursorElement);
14018          if (offset3 > blockCursorOffset) {
14019            resolvedOffset--;
14020          }
14021        }
14022      }
14023      resolvedNode = $getNodeFromDOM(childDOM);
14024      if ($isTextNode(resolvedNode)) {
14025        resolvedOffset = $getTextNodeOffset(resolvedNode, moveSelectionToEnd ? "next" : "previous");
14026      } else {
14027        let resolvedElement = $getNodeFromDOM(dom);
14028        if (resolvedElement === null) {
14029          return null;
14030        }
14031        if ($isElementNode(resolvedElement)) {
14032          const elementDOM = editor.getElementByKey(resolvedElement.getKey());
14033          if (!(elementDOM !== null)) {
14034            formatDevErrorMessage(`$internalResolveSelectionPoint: node in DOM but not keyToDOMMap`);
14035          }
14036          const slot = $getEditorDOMRenderConfig(editor).$getDOMSlot(resolvedElement, elementDOM, editor);
14037          [resolvedElement, resolvedOffset] = slot.resolveChildIndex(resolvedElement, elementDOM, dom, offset3);
14038          if (!$isElementNode(resolvedElement)) {
14039            formatDevErrorMessage(`$internalResolveSelectionPoint: resolvedElement is not an ElementNode`);
14040          }
14041          if (moveSelectionToEnd && resolvedOffset >= resolvedElement.getChildrenSize()) {
14042            resolvedOffset = Math.max(0, resolvedElement.getChildrenSize() - 1);
14043          }
14044          let child = resolvedElement.getChildAtIndex(resolvedOffset);
14045          if ($isElementNode(child) && shouldResolveAncestor(child, resolvedOffset, lastPoint)) {
14046            const descendant = moveSelectionToEnd ? child.getLastDescendant() : child.getFirstDescendant();
14047            if (descendant === null) {
14048              resolvedElement = child;
14049            } else {
14050              child = descendant;
14051              resolvedElement = $isElementNode(child) ? child : child.getParentOrThrow();
14052            }
14053            resolvedOffset = 0;
14054          }
14055          if ($isTextNode(child)) {
14056            resolvedNode = child;
14057            resolvedElement = null;
14058            resolvedOffset = $getTextNodeOffset(child, moveSelectionToEnd ? "next" : "previous");
14059          } else if (child !== resolvedElement && moveSelectionToEnd && !hasBlockCursor) {
14060            if (!$isElementNode(resolvedElement)) {
14061              formatDevErrorMessage(`invariant`);
14062            }
14063            resolvedOffset = Math.min(resolvedElement.getChildrenSize(), resolvedOffset + 1);
14064          }
14065        } else {
14066          const index = resolvedElement.getIndexWithinParent();
14067          if (offset3 === 0 && $isDecoratorNode(resolvedElement) && $getNodeFromDOM(dom) === resolvedElement) {
14068            resolvedOffset = index;
14069          } else {
14070            resolvedOffset = index + 1;
14071          }
14072          resolvedElement = resolvedElement.getParentOrThrow();
14073        }
14074        if ($isElementNode(resolvedElement)) {
14075          return $createPoint(resolvedElement.__key, resolvedOffset, "element");
14076        }
14077      }
14078    } else {
14079      resolvedNode = $getNodeFromDOM(dom);
14080    }
14081    if (!$isTextNode(resolvedNode)) {
14082      return null;
14083    }
14084    return $createPoint(resolvedNode.__key, $getTextNodeOffset(resolvedNode, resolvedOffset, "clamp"), "text");
14085  }
14086  function resolveSelectionPointOnBoundary(point, isBackward, isCollapsed) {
14087    const offset3 = point.offset;
14088    const node = point.getNode();
14089    if (offset3 === 0) {
14090      const prevSibling = node.getPreviousSibling();
14091      const parent = node.getParent();
14092      if (!isBackward) {
14093        if ($isElementNode(prevSibling) && !isCollapsed && prevSibling.isInline()) {
14094          point.set(prevSibling.__key, prevSibling.getChildrenSize(), "element");
14095        } else if ($isTextNode(prevSibling)) {
14096          point.set(prevSibling.__key, prevSibling.getTextContent().length, "text");
14097        }
14098      } else if ((isCollapsed || !isBackward) && prevSibling === null && $isElementNode(parent) && parent.isInline()) {
14099        const parentSibling = parent.getPreviousSibling();
14100        if ($isTextNode(parentSibling)) {
14101          point.set(parentSibling.__key, parentSibling.getTextContent().length, "text");
14102        }
14103      }
14104    } else if (offset3 === node.getTextContent().length) {
14105      const nextSibling = node.getNextSibling();
14106      const parent = node.getParent();
14107      if (isBackward && $isElementNode(nextSibling) && nextSibling.isInline()) {
14108        point.set(nextSibling.__key, 0, "element");
14109      } else if ((isCollapsed || isBackward) && nextSibling === null && $isElementNode(parent) && parent.isInline() && !parent.canInsertTextAfter()) {
14110        const parentSibling = parent.getNextSibling();
14111        if ($isTextNode(parentSibling)) {
14112          point.set(parentSibling.__key, 0, "text");
14113        }
14114      }
14115    }
14116  }
14117  function $normalizeSelectionPointsForBoundaries(anchor, focus, lastSelection) {
14118    if (anchor.type === "text" && focus.type === "text") {
14119      const isBackward = anchor.isBefore(focus);
14120      const isCollapsed = anchor.is(focus);
14121      resolveSelectionPointOnBoundary(anchor, isBackward, isCollapsed);
14122      resolveSelectionPointOnBoundary(focus, !isBackward, isCollapsed);
14123      if (isCollapsed) {
14124        focus.set(anchor.key, anchor.offset, anchor.type);
14125      }
14126    }
14127  }
14128  function $internalResolveSelectionPoints(anchorDOM, anchorOffset, focusDOM, focusOffset, editor, lastSelection) {
14129    if (anchorDOM === null || focusDOM === null || !isSelectionWithinEditor(editor, anchorDOM, focusDOM)) {
14130      return null;
14131    }
14132    const resolvedAnchorPoint = $internalResolveSelectionPoint(anchorDOM, anchorOffset, $isRangeSelection(lastSelection) ? lastSelection.anchor : null, editor);
14133    if (resolvedAnchorPoint === null) {
14134      return null;
14135    }
14136    const resolvedFocusPoint = $internalResolveSelectionPoint(focusDOM, focusOffset, $isRangeSelection(lastSelection) ? lastSelection.focus : null, editor);
14137    if (resolvedFocusPoint === null) {
14138      return null;
14139    }
14140    {
14141      $validatePoint("anchor", resolvedAnchorPoint);
14142      $validatePoint("focus", resolvedFocusPoint);
14143    }
14144    if (resolvedAnchorPoint.type === "element" && resolvedFocusPoint.type === "element") {
14145      const anchorNode = $getNodeFromDOM(anchorDOM);
14146      const focusNode = $getNodeFromDOM(focusDOM);
14147      if ($isDecoratorNode(anchorNode) && $isDecoratorNode(focusNode)) {
14148        return null;
14149      }
14150    }
14151    $normalizeSelectionPointsForBoundaries(resolvedAnchorPoint, resolvedFocusPoint);
14152    return [resolvedAnchorPoint, resolvedFocusPoint];
14153  }
14154  function $isBlockElementNode(node) {
14155    return $isElementNode(node) && !node.isInline();
14156  }
14157  function $internalMakeRangeSelection(anchorKey, anchorOffset, focusKey, focusOffset, anchorType, focusType) {
14158    const editorState = getActiveEditorState();
14159    const selection = new RangeSelection($createPoint(anchorKey, anchorOffset, anchorType), $createPoint(focusKey, focusOffset, focusType), 0, "");
14160    selection.dirty = true;
14161    editorState._selection = selection;
14162    return selection;
14163  }
14164  function $createRangeSelection() {
14165    const anchor = $createPoint("root", 0, "element");
14166    const focus = $createPoint("root", 0, "element");
14167    return new RangeSelection(anchor, focus, 0, "");
14168  }
14169  function $createNodeSelection() {
14170    return new NodeSelection(/* @__PURE__ */ new Set());
14171  }
14172  function $internalCreateSelection(editor, event) {
14173    const currentEditorState = editor.getEditorState();
14174    const lastSelection = currentEditorState._selection;
14175    const domSelection = getDOMSelection(getWindow(editor));
14176    if ($isRangeSelection(lastSelection) || lastSelection == null) {
14177      return $internalCreateRangeSelection(lastSelection, domSelection, editor, event);
14178    }
14179    return lastSelection.clone();
14180  }
14181  function $createRangeSelectionFromDom(domSelection, editor) {
14182    return $internalCreateRangeSelection(null, domSelection, editor, null);
14183  }
14184  function $internalCreateRangeSelection(lastSelection, domSelection, editor, event) {
14185    const windowObj = editor._window;
14186    if (windowObj === null) {
14187      return null;
14188    }
14189    const windowEvent = event || windowObj.event;
14190    const eventType = windowEvent ? windowEvent.type : void 0;
14191    const isSelectionChange = eventType === "selectionchange";
14192    const useDOMSelection = !getIsProcessingMutations() && (isSelectionChange || eventType === "beforeinput" || eventType === "compositionstart" || eventType === "compositionend" || eventType === "click" && windowEvent && windowEvent.detail === 3 || eventType === "drop" || eventType === void 0);
14193    let anchorDOM, focusDOM, anchorOffset, focusOffset;
14194    if (!$isRangeSelection(lastSelection) || useDOMSelection) {
14195      if (domSelection === null) {
14196        return null;
14197      }
14198      anchorDOM = domSelection.anchorNode;
14199      focusDOM = domSelection.focusNode;
14200      anchorOffset = domSelection.anchorOffset;
14201      focusOffset = domSelection.focusOffset;
14202      if ((isSelectionChange || eventType === void 0) && $isRangeSelection(lastSelection) && !isSelectionWithinEditor(editor, anchorDOM, focusDOM)) {
14203        return lastSelection.clone();
14204      }
14205    } else {
14206      return lastSelection.clone();
14207    }
14208    const resolvedSelectionPoints = $internalResolveSelectionPoints(anchorDOM, anchorOffset, focusDOM, focusOffset, editor, lastSelection);
14209    if (resolvedSelectionPoints === null) {
14210      return null;
14211    }
14212    const [resolvedAnchorPoint, resolvedFocusPoint] = resolvedSelectionPoints;
14213    let format = 0;
14214    let style = "";
14215    if ($isRangeSelection(lastSelection)) {
14216      const lastAnchor = lastSelection.anchor;
14217      if (resolvedAnchorPoint.key === lastAnchor.key) {
14218        format = lastSelection.format;
14219        style = lastSelection.style;
14220      } else {
14221        const anchorNode = resolvedAnchorPoint.getNode();
14222        if ($isTextNode(anchorNode)) {
14223          format = anchorNode.getFormat();
14224          style = anchorNode.getStyle();
14225        } else if ($isElementNode(anchorNode)) {
14226          format = anchorNode.getTextFormat();
14227          style = anchorNode.getTextStyle();
14228        }
14229      }
14230    }
14231    return new RangeSelection(resolvedAnchorPoint, resolvedFocusPoint, format, style);
14232  }
14233  function $validatePoint(name, point) {
14234    const node = $getNodeByKey(point.key);
14235    if (!(node !== void 0)) {
14236      formatDevErrorMessage(`$validatePoint: ${name} key ${point.key} not found in current editorState`);
14237    }
14238    if (point.type === "text") {
14239      if (!$isTextNode(node)) {
14240        formatDevErrorMessage(`$validatePoint: ${name} key ${point.key} is not a TextNode`);
14241      }
14242      const size2 = node.getTextContentSize();
14243      if (!(point.offset <= size2)) {
14244        formatDevErrorMessage(`$validatePoint: ${name} point.offset > node.getTextContentSize() (${String(point.offset)} > ${String(size2)})`);
14245      }
14246    } else {
14247      if (!$isElementNode(node)) {
14248        formatDevErrorMessage(`$validatePoint: ${name} key ${point.key} is not an ElementNode`);
14249      }
14250      const size2 = node.getChildrenSize();
14251      if (!(point.offset <= size2)) {
14252        formatDevErrorMessage(`$validatePoint: ${name} point.offset > node.getChildrenSize() (${String(point.offset)} > ${String(size2)})`);
14253      }
14254    }
14255  }
14256  function $getSelection() {
14257    const editorState = getActiveEditorState();
14258    return editorState._selection;
14259  }
14260  function $getPreviousSelection() {
14261    const editor = getActiveEditor();
14262    return editor._editorState._selection;
14263  }
14264  function $updateElementSelectionOnCreateDeleteNode(selection, parentNode, nodeOffset, times = 1) {
14265    const anchor = selection.anchor;
14266    const focus = selection.focus;
14267    const anchorNode = anchor.getNode();
14268    const focusNode = focus.getNode();
14269    if (!parentNode.is(anchorNode) && !parentNode.is(focusNode)) {
14270      return;
14271    }
14272    const parentKey = parentNode.__key;
14273    if (selection.isCollapsed()) {
14274      const selectionOffset = anchor.offset;
14275      if (nodeOffset <= selectionOffset && times > 0 || nodeOffset < selectionOffset && times < 0) {
14276        const newSelectionOffset = Math.max(0, selectionOffset + times);
14277        anchor.set(parentKey, newSelectionOffset, "element");
14278        focus.set(parentKey, newSelectionOffset, "element");
14279        $updateSelectionResolveTextNodes(selection);
14280      }
14281    } else {
14282      const isBackward = selection.isBackward();
14283      const firstPoint = isBackward ? focus : anchor;
14284      const firstPointNode = firstPoint.getNode();
14285      const lastPoint = isBackward ? anchor : focus;
14286      const lastPointNode = lastPoint.getNode();
14287      if (parentNode.is(firstPointNode)) {
14288        const firstPointOffset = firstPoint.offset;
14289        if (nodeOffset <= firstPointOffset && times > 0 || nodeOffset < firstPointOffset && times < 0) {
14290          firstPoint.set(parentKey, Math.max(0, firstPointOffset + times), "element");
14291        }
14292      }
14293      if (parentNode.is(lastPointNode)) {
14294        const lastPointOffset = lastPoint.offset;
14295        if (nodeOffset <= lastPointOffset && times > 0 || nodeOffset < lastPointOffset && times < 0) {
14296          lastPoint.set(parentKey, Math.max(0, lastPointOffset + times), "element");
14297        }
14298      }
14299    }
14300    $updateSelectionResolveTextNodes(selection);
14301  }
14302  function $updateSelectionResolveTextNodes(selection) {
14303    const anchor = selection.anchor;
14304    const anchorOffset = anchor.offset;
14305    const focus = selection.focus;
14306    const focusOffset = focus.offset;
14307    const anchorNode = anchor.getNode();
14308    const focusNode = focus.getNode();
14309    if (selection.isCollapsed()) {
14310      if (!$isElementNode(anchorNode)) {
14311        return;
14312      }
14313      const childSize = anchorNode.getChildrenSize();
14314      const anchorOffsetAtEnd = anchorOffset >= childSize;
14315      const child = anchorOffsetAtEnd ? anchorNode.getChildAtIndex(childSize - 1) : anchorNode.getChildAtIndex(anchorOffset);
14316      if ($isTextNode(child)) {
14317        let newOffset = 0;
14318        if (anchorOffsetAtEnd) {
14319          newOffset = child.getTextContentSize();
14320        }
14321        anchor.set(child.__key, newOffset, "text");
14322        focus.set(child.__key, newOffset, "text");
14323      }
14324      return;
14325    }
14326    if ($isElementNode(anchorNode)) {
14327      const childSize = anchorNode.getChildrenSize();
14328      const anchorOffsetAtEnd = anchorOffset >= childSize;
14329      const child = anchorOffsetAtEnd ? anchorNode.getChildAtIndex(childSize - 1) : anchorNode.getChildAtIndex(anchorOffset);
14330      if ($isTextNode(child)) {
14331        let newOffset = 0;
14332        if (anchorOffsetAtEnd) {
14333          newOffset = child.getTextContentSize();
14334        }
14335        anchor.set(child.__key, newOffset, "text");
14336      }
14337    }
14338    if ($isElementNode(focusNode)) {
14339      const childSize = focusNode.getChildrenSize();
14340      const focusOffsetAtEnd = focusOffset >= childSize;
14341      const child = focusOffsetAtEnd ? focusNode.getChildAtIndex(childSize - 1) : focusNode.getChildAtIndex(focusOffset);
14342      if ($isTextNode(child)) {
14343        let newOffset = 0;
14344        if (focusOffsetAtEnd) {
14345          newOffset = child.getTextContentSize();
14346        }
14347        focus.set(child.__key, newOffset, "text");
14348      }
14349    }
14350  }
14351  function applySelectionTransforms(nextEditorState, editor) {
14352    const prevEditorState = editor.getEditorState();
14353    const prevSelection = prevEditorState._selection;
14354    const nextSelection = nextEditorState._selection;
14355    if ($isRangeSelection(nextSelection)) {
14356      const anchor = nextSelection.anchor;
14357      const focus = nextSelection.focus;
14358      let anchorNode;
14359      if (anchor.type === "text") {
14360        anchorNode = anchor.getNode();
14361        anchorNode.selectionTransform(prevSelection, nextSelection);
14362      }
14363      if (focus.type === "text") {
14364        const focusNode = focus.getNode();
14365        if (anchorNode !== focusNode) {
14366          focusNode.selectionTransform(prevSelection, nextSelection);
14367        }
14368      }
14369    }
14370  }
14371  function moveSelectionPointToSibling(point, node, parent, prevSibling, nextSibling) {
14372    let siblingKey = null;
14373    let offset3 = 0;
14374    let type = null;
14375    if (prevSibling !== null) {
14376      siblingKey = prevSibling.__key;
14377      if ($isTextNode(prevSibling)) {
14378        offset3 = prevSibling.getTextContentSize();
14379        type = "text";
14380      } else if ($isElementNode(prevSibling)) {
14381        offset3 = prevSibling.getChildrenSize();
14382        type = "element";
14383      }
14384    } else {
14385      if (nextSibling !== null) {
14386        siblingKey = nextSibling.__key;
14387        if ($isTextNode(nextSibling)) {
14388          type = "text";
14389        } else if ($isElementNode(nextSibling)) {
14390          type = "element";
14391        }
14392      }
14393    }
14394    if (siblingKey !== null && type !== null) {
14395      point.set(siblingKey, offset3, type);
14396    } else {
14397      offset3 = node.getIndexWithinParent();
14398      if (offset3 === -1) {
14399        offset3 = parent.getChildrenSize();
14400      }
14401      point.set(parent.__key, offset3, "element");
14402    }
14403  }
14404  function adjustPointOffsetForMergedSibling(point, isBefore, key, target, textLength) {
14405    if (point.type === "text") {
14406      point.set(key, point.offset + (isBefore ? 0 : textLength), "text");
14407    } else if (point.offset > target.getIndexWithinParent()) {
14408      point.set(point.key, point.offset - 1, "element");
14409    }
14410  }
14411  function setDOMSelectionBaseAndExtent(domSelection, nextAnchorDOM, nextAnchorOffset, nextFocusDOM, nextFocusOffset) {
14412    try {
14413      domSelection.setBaseAndExtent(nextAnchorDOM, nextAnchorOffset, nextFocusDOM, nextFocusOffset);
14414    } catch (error) {
14415      {
14416        console.warn(error);
14417      }
14418    }
14419  }
14420  function $getElementAndOffsetForPoint(editor, node, offset3) {
14421    const element = getElementByKeyOrThrow(editor, node.getKey());
14422    if ($isElementNode(node)) {
14423      const slot = $getEditorDOMRenderConfig(editor).$getDOMSlot(node, element, editor);
14424      return [slot.element, offset3 + slot.getFirstChildOffset()];
14425    }
14426    return [element, offset3];
14427  }
14428  function $updateDOMSelection(prevSelection, nextSelection, editor, domSelection, tags, rootElement, nodeCount) {
14429    const anchorDOMNode = domSelection.anchorNode;
14430    const focusDOMNode = domSelection.focusNode;
14431    const anchorOffset = domSelection.anchorOffset;
14432    const focusOffset = domSelection.focusOffset;
14433    const activeElement = document.activeElement;
14434    if (tags.has(COLLABORATION_TAG) && activeElement !== rootElement || activeElement !== null && isSelectionCapturedInDecoratorInput(activeElement)) {
14435      return;
14436    }
14437    if (!$isRangeSelection(nextSelection)) {
14438      if (prevSelection !== null && isSelectionWithinEditor(editor, anchorDOMNode, focusDOMNode)) {
14439        domSelection.removeAllRanges();
14440      }
14441      return;
14442    }
14443    const anchor = nextSelection.anchor;
14444    const focus = nextSelection.focus;
14445    const anchorNode = anchor.getNode();
14446    const focusNode = focus.getNode();
14447    const [anchorDOM, nextAnchorOffset] = $getElementAndOffsetForPoint(editor, anchorNode, anchor.offset);
14448    const [focusDOM, nextFocusOffset] = $getElementAndOffsetForPoint(editor, focusNode, focus.offset);
14449    const nextFormat = nextSelection.format;
14450    const nextStyle = nextSelection.style;
14451    const isCollapsed = nextSelection.isCollapsed();
14452    let nextAnchorNode = anchorDOM;
14453    let nextFocusNode = focusDOM;
14454    let anchorFormatOrStyleChanged = false;
14455    if (anchor.type === "text") {
14456      nextAnchorNode = getDOMTextNode(anchorDOM);
14457      anchorFormatOrStyleChanged = anchorNode.getFormat() !== nextFormat || anchorNode.getStyle() !== nextStyle;
14458    } else if ($isRangeSelection(prevSelection) && prevSelection.anchor.type === "text") {
14459      anchorFormatOrStyleChanged = true;
14460    }
14461    if (focus.type === "text") {
14462      nextFocusNode = getDOMTextNode(focusDOM);
14463    }
14464    if (nextAnchorNode === null || nextFocusNode === null) {
14465      return;
14466    }
14467    if (isCollapsed && (prevSelection === null || anchorFormatOrStyleChanged || $isRangeSelection(prevSelection) && (prevSelection.format !== nextFormat || prevSelection.style !== nextStyle))) {
14468      markCollapsedSelectionFormat(nextFormat, nextStyle, nextAnchorOffset, anchor.key, performance.now());
14469    }
14470    if (anchorOffset === nextAnchorOffset && focusOffset === nextFocusOffset && anchorDOMNode === nextAnchorNode && focusDOMNode === nextFocusNode && // Badly interpreted range selection when collapsed - #1482
14471    !(domSelection.type === "Range" && isCollapsed)) {
14472      if (activeElement === null || !rootElement.contains(activeElement)) {
14473        if (!tags.has(SKIP_SELECTION_FOCUS_TAG)) {
14474          rootElement.focus({
14475            preventScroll: true
14476          });
14477        }
14478      }
14479      if (anchor.type !== "element") {
14480        return;
14481      }
14482    }
14483    setDOMSelectionBaseAndExtent(domSelection, nextAnchorNode, nextAnchorOffset, nextFocusNode, nextFocusOffset);
14484    if (IS_FIREFOX && nextSelection.isCollapsed() && rootElement !== null && !tags.has(SKIP_SELECTION_FOCUS_TAG) && (document.activeElement === null || !rootElement.contains(document.activeElement))) {
14485      rootElement.focus({
14486        preventScroll: true
14487      });
14488    }
14489    if (!tags.has(SKIP_SCROLL_INTO_VIEW_TAG) && nextSelection.isCollapsed() && rootElement !== null && rootElement === document.activeElement) {
14490      const selectionTarget = $isRangeSelection(nextSelection) && nextSelection.anchor.type === "element" ? nextAnchorNode.childNodes[nextAnchorOffset] || null : domSelection.rangeCount > 0 ? domSelection.getRangeAt(0) : null;
14491      if (selectionTarget !== null) {
14492        let selectionRect;
14493        if (selectionTarget instanceof Text) {
14494          const range2 = document.createRange();
14495          range2.selectNode(selectionTarget);
14496          selectionRect = range2.getBoundingClientRect();
14497        } else {
14498          selectionRect = selectionTarget.getBoundingClientRect();
14499        }
14500        scrollIntoViewIfNeeded(editor, selectionRect, rootElement);
14501      }
14502    }
14503    markSelectionChangeFromDOMUpdate();
14504  }
14505  function $insertNodes(nodes) {
14506    let selection = $getSelection() || $getPreviousSelection();
14507    if (selection === null) {
14508      selection = $getRoot().selectEnd();
14509    }
14510    selection.insertNodes(nodes);
14511  }
14512  function $getTextContent() {
14513    const selection = $getSelection();
14514    if (selection === null) {
14515      return "";
14516    }
14517    return selection.getTextContent();
14518  }
14519  function $removeTextAndSplitBlock(selection) {
14520    let selection_ = selection;
14521    if (!selection.isCollapsed()) {
14522      selection_.removeText();
14523    }
14524    const newSelection = $getSelection();
14525    if ($isRangeSelection(newSelection)) {
14526      selection_ = newSelection;
14527    }
14528    if (!$isRangeSelection(selection_)) {
14529      formatDevErrorMessage(`Unexpected dirty selection to be null`);
14530    }
14531    const anchor = selection_.anchor;
14532    let node = anchor.getNode();
14533    let offset3 = anchor.offset;
14534    while (!INTERNAL_$isBlock(node)) {
14535      const prevNode = node;
14536      [node, offset3] = $splitNodeAtPoint(node, offset3);
14537      if (prevNode.is(node)) {
14538        break;
14539      }
14540    }
14541    return offset3;
14542  }
14543  function $splitNodeAtPoint(node, offset3) {
14544    const parent = node.getParent();
14545    if (!parent) {
14546      const paragraph = $createParagraphNode();
14547      $getRoot().append(paragraph);
14548      paragraph.select();
14549      return [$getRoot(), 0];
14550    }
14551    if ($isTextNode(node)) {
14552      const split = node.splitText(offset3);
14553      if (split.length === 0) {
14554        return [parent, node.getIndexWithinParent()];
14555      }
14556      const x3 = offset3 === 0 ? 0 : 1;
14557      const index = split[0].getIndexWithinParent() + x3;
14558      return [parent, index];
14559    }
14560    if (!$isElementNode(node) || offset3 === 0) {
14561      return [parent, node.getIndexWithinParent()];
14562    }
14563    const firstToAppend = node.getChildAtIndex(offset3);
14564    if (firstToAppend) {
14565      const insertPoint = new RangeSelection($createPoint(node.__key, offset3, "element"), $createPoint(node.__key, offset3, "element"), 0, "");
14566      const newElement = node.insertNewAfter(insertPoint);
14567      if (newElement) {
14568        newElement.append(firstToAppend, ...firstToAppend.getNextSiblings());
14569      }
14570    }
14571    return [parent, node.getIndexWithinParent() + 1];
14572  }
14573  function $wrapInlineNodes(nodes) {
14574    const virtualRoot = $createParagraphNode();
14575    let currentBlock = null;
14576    for (let i2 = 0; i2 < nodes.length; i2++) {
14577      const node = nodes[i2];
14578      const isLineBreakNode = $isLineBreakNode(node);
14579      if (isLineBreakNode || $isDecoratorNode(node) && node.isInline() || $isElementNode(node) && node.isInline() || $isTextNode(node) || node.isParentRequired()) {
14580        if (currentBlock === null) {
14581          currentBlock = node.createParentElementNode();
14582          virtualRoot.append(currentBlock);
14583          if (isLineBreakNode) {
14584            continue;
14585          }
14586        }
14587        if (currentBlock !== null) {
14588          currentBlock.append(node);
14589        }
14590      } else {
14591        virtualRoot.append(node);
14592        currentBlock = null;
14593      }
14594    }
14595    return virtualRoot;
14596  }
14597  function $getNodesFromCaretRangeCompat(range2) {
14598    const nodes = [];
14599    const [beforeSlice, afterSlice] = range2.getTextSlices();
14600    if (beforeSlice) {
14601      nodes.push(beforeSlice.caret.origin);
14602    }
14603    const seenAncestors = /* @__PURE__ */ new Set();
14604    const seenElements = /* @__PURE__ */ new Set();
14605    for (const caret of range2) {
14606      if ($isChildCaret(caret)) {
14607        const {
14608          origin
14609        } = caret;
14610        if (nodes.length === 0) {
14611          seenAncestors.add(origin);
14612        } else {
14613          seenElements.add(origin);
14614          nodes.push(origin);
14615        }
14616      } else {
14617        const {
14618          origin
14619        } = caret;
14620        if (!$isElementNode(origin) || !seenElements.has(origin)) {
14621          nodes.push(origin);
14622        }
14623      }
14624    }
14625    if (afterSlice) {
14626      nodes.push(afterSlice.caret.origin);
14627    }
14628    if ($isSiblingCaret(range2.focus) && $isElementNode(range2.focus.origin) && range2.focus.getNodeAtCaret() === null) {
14629      for (let reverseCaret = $getChildCaret(range2.focus.origin, "previous"); $isChildCaret(reverseCaret) && seenAncestors.has(reverseCaret.origin) && !reverseCaret.origin.isEmpty() && reverseCaret.origin.is(nodes[nodes.length - 1]); reverseCaret = $getAdjacentChildCaret(reverseCaret)) {
14630        seenAncestors.delete(reverseCaret.origin);
14631        nodes.pop();
14632      }
14633    }
14634    while (nodes.length > 1) {
14635      const lastIncludedNode = nodes[nodes.length - 1];
14636      if ($isElementNode(lastIncludedNode)) {
14637        if (seenElements.has(lastIncludedNode) || lastIncludedNode.isEmpty() || seenAncestors.has(lastIncludedNode)) ;
14638        else {
14639          nodes.pop();
14640          continue;
14641        }
14642      }
14643      break;
14644    }
14645    if (nodes.length === 0 && range2.isCollapsed()) {
14646      const normCaret = $normalizeCaret(range2.anchor);
14647      const flippedNormCaret = $normalizeCaret(range2.anchor.getFlipped());
14648      const $getCandidate = (caret) => $isTextPointCaret(caret) ? caret.origin : caret.getNodeAtCaret();
14649      const node = $getCandidate(normCaret) || $getCandidate(flippedNormCaret) || (range2.anchor.getNodeAtCaret() ? normCaret.origin : flippedNormCaret.origin);
14650      nodes.push(node);
14651    }
14652    return nodes;
14653  }
14654  function $modifySelectionAroundDecoratorsAndBlocks(selection, alter, isBackward, granularity, mode = "decorators-and-blocks") {
14655    if (alter === "move" && granularity === "character" && !selection.isCollapsed()) {
14656      const [src, dst] = isBackward === selection.isBackward() ? [selection.focus, selection.anchor] : [selection.anchor, selection.focus];
14657      dst.set(src.key, src.offset, src.type);
14658      return true;
14659    }
14660    const initialFocus = $caretFromPoint(selection.focus, isBackward ? "previous" : "next");
14661    const isLineBoundary = granularity === "lineboundary";
14662    const collapse = alter === "move";
14663    let focus = initialFocus;
14664    let checkForBlock = mode === "decorators-and-blocks";
14665    if (!$isExtendableTextPointCaret(focus)) {
14666      for (const siblingCaret of focus) {
14667        checkForBlock = false;
14668        const {
14669          origin
14670        } = siblingCaret;
14671        if ($isDecoratorNode(origin) && !origin.isIsolated()) {
14672          focus = siblingCaret;
14673          if (isLineBoundary && origin.isInline()) {
14674            continue;
14675          }
14676        }
14677        break;
14678      }
14679      if (checkForBlock) {
14680        for (const nextCaret of $extendCaretToRange(initialFocus).iterNodeCarets(alter === "extend" ? "shadowRoot" : "root")) {
14681          if ($isChildCaret(nextCaret)) {
14682            if (!nextCaret.origin.isInline()) {
14683              focus = nextCaret;
14684            }
14685          } else if ($isElementNode(nextCaret.origin)) {
14686            continue;
14687          } else if ($isDecoratorNode(nextCaret.origin) && !nextCaret.origin.isInline()) {
14688            focus = nextCaret;
14689          }
14690          break;
14691        }
14692      }
14693    }
14694    if (focus === initialFocus) {
14695      return false;
14696    }
14697    if (collapse && !isLineBoundary && $isDecoratorNode(focus.origin) && focus.origin.isKeyboardSelectable()) {
14698      const nodeSelection = $createNodeSelection();
14699      nodeSelection.add(focus.origin.getKey());
14700      $setSelection(nodeSelection);
14701      return true;
14702    }
14703    focus = $normalizeCaret(focus);
14704    if (collapse) {
14705      $setPointFromCaret(selection.anchor, focus);
14706    }
14707    $setPointFromCaret(selection.focus, focus);
14708    return checkForBlock || !isLineBoundary;
14709  }
14710  var activeEditorState = null;
14711  var activeEditor = null;
14712  var isReadOnlyMode = false;
14713  var isAttemptingToRecoverFromReconcilerError = false;
14714  var infiniteTransformCount = 0;
14715  var observerOptions = {
14716    characterData: true,
14717    childList: true,
14718    subtree: true
14719  };
14720  function isCurrentlyReadOnlyMode() {
14721    return isReadOnlyMode || activeEditorState !== null && activeEditorState._readOnly;
14722  }
14723  function errorOnReadOnly() {
14724    if (isReadOnlyMode) {
14725      {
14726        formatDevErrorMessage(`Cannot use method in read-only mode.`);
14727      }
14728    }
14729  }
14730  function errorOnInfiniteTransforms() {
14731    if (infiniteTransformCount > 99) {
14732      {
14733        formatDevErrorMessage(`One or more transforms are endlessly triggering additional transforms. May have encountered infinite recursion caused by transforms that have their preconditions too lose and/or conflict with each other.`);
14734      }
14735    }
14736  }
14737  function getActiveEditorState() {
14738    if (activeEditorState === null) {
14739      {
14740        formatDevErrorMessage(`Unable to find an active editor state. State helpers or node methods can only be used synchronously during the callback of editor.update(), editor.read(), or editorState.read().${collectBuildInformation()}`);
14741      }
14742    }
14743    return activeEditorState;
14744  }
14745  function getActiveEditor() {
14746    if (activeEditor === null) {
14747      {
14748        formatDevErrorMessage(`Unable to find an active editor. This method can only be used synchronously during the callback of editor.update(), editor.read(), or editor.getEditorState().read(..., {editor}).${collectBuildInformation()}`);
14749      }
14750    }
14751    return activeEditor;
14752  }
14753  function collectBuildInformation() {
14754    let compatibleEditors = 0;
14755    const incompatibleEditors = /* @__PURE__ */ new Set();
14756    const thisVersion = LexicalEditor.version;
14757    if (typeof window !== "undefined") {
14758      for (const node of document.querySelectorAll("[contenteditable]")) {
14759        const editor = getEditorPropertyFromDOMNode(node);
14760        if (isLexicalEditor(editor)) {
14761          compatibleEditors++;
14762        } else if (editor) {
14763          let version = String(editor.constructor.version || "<0.17.1");
14764          if (version === thisVersion) {
14765            version += " (separately built, likely a bundler configuration issue)";
14766          }
14767          incompatibleEditors.add(version);
14768        }
14769      }
14770    }
14771    let output = ` Detected on the page: ${compatibleEditors} compatible editor(s) with version ${thisVersion}`;
14772    if (incompatibleEditors.size) {
14773      output += ` and incompatible editors with versions ${Array.from(incompatibleEditors).join(", ")}`;
14774    }
14775    return output;
14776  }
14777  function internalGetActiveEditor() {
14778    return activeEditor;
14779  }
14780  function internalGetActiveEditorState() {
14781    return activeEditorState;
14782  }
14783  function $applyTransforms(editor, node, transformsCache) {
14784    const type = node.__type;
14785    const registeredNode = getRegisteredNodeOrThrow(editor, type);
14786    let transformsArr = transformsCache.get(type);
14787    if (transformsArr === void 0) {
14788      transformsArr = Array.from(registeredNode.transforms);
14789      transformsCache.set(type, transformsArr);
14790    }
14791    const transformsArrLength = transformsArr.length;
14792    for (let i2 = 0; i2 < transformsArrLength; i2++) {
14793      transformsArr[i2](node);
14794      if (!node.isAttached()) {
14795        break;
14796      }
14797    }
14798  }
14799  function $isNodeValidForTransform(node, compositionKey) {
14800    return node !== void 0 && // We don't want to transform nodes being composed
14801    node.__key !== compositionKey && node.isAttached();
14802  }
14803  function $normalizeAllDirtyTextNodes(editorState, editor) {
14804    const dirtyLeaves = editor._dirtyLeaves;
14805    const nodeMap = editorState._nodeMap;
14806    for (const nodeKey of dirtyLeaves) {
14807      const node = nodeMap.get(nodeKey);
14808      if ($isTextNode(node) && node.isAttached() && node.isSimpleText() && !node.isUnmergeable()) {
14809        $normalizeTextNode(node);
14810      }
14811    }
14812  }
14813  function addTags(editor, tags) {
14814    if (!tags) {
14815      return;
14816    }
14817    const updateTags = editor._updateTags;
14818    let tags_ = tags;
14819    if (!Array.isArray(tags)) {
14820      tags_ = [tags];
14821    }
14822    for (const tag of tags_) {
14823      updateTags.add(tag);
14824    }
14825  }
14826  function $applyAllTransforms(editorState, editor) {
14827    const dirtyLeaves = editor._dirtyLeaves;
14828    const dirtyElements = editor._dirtyElements;
14829    const nodeMap = editorState._nodeMap;
14830    const compositionKey = $getCompositionKey();
14831    const transformsCache = /* @__PURE__ */ new Map();
14832    let untransformedDirtyLeaves = dirtyLeaves;
14833    let untransformedDirtyLeavesLength = untransformedDirtyLeaves.size;
14834    let untransformedDirtyElements = dirtyElements;
14835    let untransformedDirtyElementsLength = untransformedDirtyElements.size;
14836    while (untransformedDirtyLeavesLength > 0 || untransformedDirtyElementsLength > 0) {
14837      if (untransformedDirtyLeavesLength > 0) {
14838        editor._dirtyLeaves = /* @__PURE__ */ new Set();
14839        for (const nodeKey of untransformedDirtyLeaves) {
14840          const node = nodeMap.get(nodeKey);
14841          if ($isTextNode(node) && node.isAttached() && node.isSimpleText() && !node.isUnmergeable()) {
14842            $normalizeTextNode(node);
14843          }
14844          if (node !== void 0 && $isNodeValidForTransform(node, compositionKey)) {
14845            $applyTransforms(editor, node, transformsCache);
14846          }
14847          dirtyLeaves.add(nodeKey);
14848        }
14849        untransformedDirtyLeaves = editor._dirtyLeaves;
14850        untransformedDirtyLeavesLength = untransformedDirtyLeaves.size;
14851        if (untransformedDirtyLeavesLength > 0) {
14852          infiniteTransformCount++;
14853          continue;
14854        }
14855      }
14856      editor._dirtyLeaves = /* @__PURE__ */ new Set();
14857      editor._dirtyElements = /* @__PURE__ */ new Map();
14858      const rootDirty = untransformedDirtyElements.delete("root");
14859      if (rootDirty) {
14860        untransformedDirtyElements.set("root", true);
14861      }
14862      for (const currentUntransformedDirtyElement of untransformedDirtyElements) {
14863        const nodeKey = currentUntransformedDirtyElement[0];
14864        const intentionallyMarkedAsDirty = currentUntransformedDirtyElement[1];
14865        dirtyElements.set(nodeKey, intentionallyMarkedAsDirty);
14866        if (!intentionallyMarkedAsDirty) {
14867          continue;
14868        }
14869        const node = nodeMap.get(nodeKey);
14870        if (node !== void 0 && $isNodeValidForTransform(node, compositionKey)) {
14871          $applyTransforms(editor, node, transformsCache);
14872        }
14873      }
14874      untransformedDirtyLeaves = editor._dirtyLeaves;
14875      untransformedDirtyLeavesLength = untransformedDirtyLeaves.size;
14876      untransformedDirtyElements = editor._dirtyElements;
14877      untransformedDirtyElementsLength = untransformedDirtyElements.size;
14878      infiniteTransformCount++;
14879    }
14880    editor._dirtyLeaves = dirtyLeaves;
14881    editor._dirtyElements = dirtyElements;
14882  }
14883  function $parseSerializedNode(serializedNode) {
14884    const internalSerializedNode = serializedNode;
14885    return $parseSerializedNodeImpl(internalSerializedNode, getActiveEditor()._nodes);
14886  }
14887  function $parseSerializedNodeImpl(serializedNode, registeredNodes) {
14888    const type = serializedNode.type;
14889    const registeredNode = registeredNodes.get(type);
14890    if (registeredNode === void 0) {
14891      {
14892        formatDevErrorMessage(`parseEditorState: type "${type}" + not found`);
14893      }
14894    }
14895    const nodeClass = registeredNode.klass;
14896    if (serializedNode.type !== nodeClass.getType()) {
14897      {
14898        formatDevErrorMessage(`LexicalNode: Node ${nodeClass.name} does not implement .importJSON().`);
14899      }
14900    }
14901    const node = nodeClass.importJSON(serializedNode);
14902    const children = serializedNode.children;
14903    if ($isElementNode(node) && Array.isArray(children)) {
14904      for (let i2 = 0; i2 < children.length; i2++) {
14905        const serializedJSONChildNode = children[i2];
14906        const childNode = $parseSerializedNodeImpl(serializedJSONChildNode, registeredNodes);
14907        node.append(childNode);
14908      }
14909    }
14910    return node;
14911  }
14912  function parseEditorState(serializedEditorState, editor, updateFn) {
14913    const editorState = createEmptyEditorState();
14914    const previousActiveEditorState = activeEditorState;
14915    const previousReadOnlyMode = isReadOnlyMode;
14916    const previousActiveEditor = activeEditor;
14917    const previousDirtyElements = editor._dirtyElements;
14918    const previousDirtyLeaves = editor._dirtyLeaves;
14919    const previousCloneNotNeeded = editor._cloneNotNeeded;
14920    const previousDirtyType = editor._dirtyType;
14921    editor._dirtyElements = /* @__PURE__ */ new Map();
14922    editor._dirtyLeaves = /* @__PURE__ */ new Set();
14923    editor._cloneNotNeeded = /* @__PURE__ */ new Set();
14924    editor._dirtyType = 0;
14925    activeEditorState = editorState;
14926    isReadOnlyMode = false;
14927    activeEditor = editor;
14928    setPendingNodeToClone(null);
14929    try {
14930      const registeredNodes = editor._nodes;
14931      const serializedNode = serializedEditorState.root;
14932      $parseSerializedNodeImpl(serializedNode, registeredNodes);
14933      if (updateFn) {
14934        updateFn();
14935      }
14936      editorState._readOnly = true;
14937      {
14938        handleDEVOnlyPendingUpdateGuarantees(editorState);
14939      }
14940    } catch (error) {
14941      if (error instanceof Error) {
14942        editor._onError(error);
14943      }
14944    } finally {
14945      editor._dirtyElements = previousDirtyElements;
14946      editor._dirtyLeaves = previousDirtyLeaves;
14947      editor._cloneNotNeeded = previousCloneNotNeeded;
14948      editor._dirtyType = previousDirtyType;
14949      activeEditorState = previousActiveEditorState;
14950      isReadOnlyMode = previousReadOnlyMode;
14951      activeEditor = previousActiveEditor;
14952    }
14953    return editorState;
14954  }
14955  function readEditorState(editor, editorState, callbackFn) {
14956    const previousActiveEditorState = activeEditorState;
14957    const previousReadOnlyMode = isReadOnlyMode;
14958    const previousActiveEditor = activeEditor;
14959    activeEditorState = editorState;
14960    isReadOnlyMode = true;
14961    activeEditor = editor;
14962    try {
14963      return callbackFn();
14964    } finally {
14965      activeEditorState = previousActiveEditorState;
14966      isReadOnlyMode = previousReadOnlyMode;
14967      activeEditor = previousActiveEditor;
14968    }
14969  }
14970  function handleDEVOnlyPendingUpdateGuarantees(pendingEditorState) {
14971    const nodeMap = pendingEditorState._nodeMap;
14972    nodeMap.set = () => {
14973      throw new Error("Cannot call set() on a frozen Lexical node map");
14974    };
14975    nodeMap.clear = () => {
14976      throw new Error("Cannot call clear() on a frozen Lexical node map");
14977    };
14978    nodeMap.delete = () => {
14979      throw new Error("Cannot call delete() on a frozen Lexical node map");
14980    };
14981  }
14982  function $commitPendingUpdates(editor, recoveryEditorState) {
14983    const pendingEditorState = editor._pendingEditorState;
14984    const rootElement = editor._rootElement;
14985    const shouldSkipDOM = editor._headless || rootElement === null;
14986    if (pendingEditorState === null) {
14987      if (editor._deferred.length > 0) {
14988        triggerDeferredUpdateCallbacks(editor, editor._deferred);
14989      }
14990      return;
14991    }
14992    const currentEditorState = editor._editorState;
14993    const currentSelection = currentEditorState._selection;
14994    const pendingSelection = pendingEditorState._selection;
14995    const needsUpdate = editor._dirtyType !== NO_DIRTY_NODES;
14996    const previousActiveEditorState = activeEditorState;
14997    const previousReadOnlyMode = isReadOnlyMode;
14998    const previousActiveEditor = activeEditor;
14999    const previouslyUpdating = editor._updating;
15000    const observer = editor._observer;
15001    let mutatedNodes2 = null;
15002    editor._pendingEditorState = null;
15003    editor._editorState = pendingEditorState;
15004    if (!shouldSkipDOM && needsUpdate && observer !== null) {
15005      activeEditor = editor;
15006      activeEditorState = pendingEditorState;
15007      isReadOnlyMode = false;
15008      editor._updating = true;
15009      try {
15010        const dirtyType = editor._dirtyType;
15011        const dirtyElements2 = editor._dirtyElements;
15012        const dirtyLeaves2 = editor._dirtyLeaves;
15013        observer.disconnect();
15014        mutatedNodes2 = $reconcileRoot(currentEditorState, pendingEditorState, editor, dirtyType, dirtyElements2, dirtyLeaves2);
15015      } catch (error) {
15016        if (error instanceof Error) {
15017          editor._onError(error);
15018        }
15019        if (!isAttemptingToRecoverFromReconcilerError) {
15020          resetEditor(editor, null, rootElement, pendingEditorState);
15021          initMutationObserver(editor);
15022          editor._dirtyType = FULL_RECONCILE;
15023          isAttemptingToRecoverFromReconcilerError = true;
15024          $commitPendingUpdates(editor, currentEditorState);
15025          isAttemptingToRecoverFromReconcilerError = false;
15026        } else {
15027          throw error;
15028        }
15029        return;
15030      } finally {
15031        observer.observe(rootElement, observerOptions);
15032        editor._updating = previouslyUpdating;
15033        activeEditorState = previousActiveEditorState;
15034        isReadOnlyMode = previousReadOnlyMode;
15035        activeEditor = previousActiveEditor;
15036      }
15037    }
15038    if (!pendingEditorState._readOnly) {
15039      pendingEditorState._readOnly = true;
15040      {
15041        handleDEVOnlyPendingUpdateGuarantees(pendingEditorState);
15042        if ($isRangeSelection(pendingSelection)) {
15043          Object.freeze(pendingSelection.anchor);
15044          Object.freeze(pendingSelection.focus);
15045        }
15046        Object.freeze(pendingSelection);
15047      }
15048    }
15049    const dirtyLeaves = editor._dirtyLeaves;
15050    const dirtyElements = editor._dirtyElements;
15051    const normalizedNodes = editor._normalizedNodes;
15052    const tags = editor._updateTags;
15053    const deferred = editor._deferred;
15054    if (needsUpdate) {
15055      editor._dirtyType = NO_DIRTY_NODES;
15056      editor._cloneNotNeeded.clear();
15057      editor._dirtyLeaves = /* @__PURE__ */ new Set();
15058      editor._dirtyElements = /* @__PURE__ */ new Map();
15059      editor._normalizedNodes = /* @__PURE__ */ new Set();
15060      editor._updateTags = /* @__PURE__ */ new Set();
15061    }
15062    $garbageCollectDetachedDecorators(editor, pendingEditorState);
15063    const domSelection = shouldSkipDOM ? null : getDOMSelection(getWindow(editor));
15064    if (editor._editable && // domSelection will be null in headless
15065    domSelection !== null && (needsUpdate || pendingSelection === null || pendingSelection.dirty || !pendingSelection.is(currentSelection)) && rootElement !== null && !tags.has(SKIP_DOM_SELECTION_TAG)) {
15066      activeEditor = editor;
15067      activeEditorState = pendingEditorState;
15068      try {
15069        if (observer !== null) {
15070          observer.disconnect();
15071        }
15072        if (needsUpdate || pendingSelection === null || pendingSelection.dirty) {
15073          const blockCursorElement = editor._blockCursorElement;
15074          if (blockCursorElement !== null) {
15075            removeDOMBlockCursorElement(blockCursorElement, editor, rootElement);
15076          }
15077          $updateDOMSelection(currentSelection, pendingSelection, editor, domSelection, tags, rootElement);
15078        }
15079        updateDOMBlockCursorElement(editor, rootElement, pendingSelection);
15080      } finally {
15081        if (observer !== null) {
15082          observer.observe(rootElement, observerOptions);
15083        }
15084        activeEditor = previousActiveEditor;
15085        activeEditorState = previousActiveEditorState;
15086      }
15087    }
15088    if (mutatedNodes2 !== null) {
15089      triggerMutationListeners(editor, mutatedNodes2, tags, dirtyLeaves, currentEditorState);
15090    }
15091    if (!$isRangeSelection(pendingSelection) && pendingSelection !== null && (currentSelection === null || !currentSelection.is(pendingSelection))) {
15092      editor.dispatchCommand(SELECTION_CHANGE_COMMAND, void 0);
15093    }
15094    const pendingDecorators = editor._pendingDecorators;
15095    if (pendingDecorators !== null) {
15096      editor._decorators = pendingDecorators;
15097      editor._pendingDecorators = null;
15098      triggerListeners("decorator", editor, true, pendingDecorators);
15099    }
15100    triggerTextContentListeners(editor, recoveryEditorState || currentEditorState, pendingEditorState);
15101    triggerListeners("update", editor, true, {
15102      dirtyElements,
15103      dirtyLeaves,
15104      editorState: pendingEditorState,
15105      mutatedNodes: mutatedNodes2,
15106      normalizedNodes,
15107      prevEditorState: recoveryEditorState || currentEditorState,
15108      tags
15109    });
15110    triggerDeferredUpdateCallbacks(editor, deferred);
15111    $triggerEnqueuedUpdates(editor);
15112  }
15113  function triggerTextContentListeners(editor, currentEditorState, pendingEditorState) {
15114    const currentTextContent = getEditorStateTextContent(currentEditorState);
15115    const latestTextContent = getEditorStateTextContent(pendingEditorState);
15116    if (currentTextContent !== latestTextContent) {
15117      triggerListeners("textcontent", editor, true, latestTextContent);
15118    }
15119  }
15120  function triggerMutationListeners(editor, mutatedNodes2, updateTags, dirtyLeaves, prevEditorState) {
15121    const listeners = Array.from(editor._listeners.mutation);
15122    const listenersLength = listeners.length;
15123    for (let i2 = 0; i2 < listenersLength; i2++) {
15124      const [listener, klassSet] = listeners[i2];
15125      for (const klass of klassSet) {
15126        const mutatedNodesByType = mutatedNodes2.get(klass);
15127        if (mutatedNodesByType !== void 0) {
15128          listener(mutatedNodesByType, {
15129            dirtyLeaves,
15130            prevEditorState,
15131            updateTags
15132          });
15133        }
15134      }
15135    }
15136  }
15137  function triggerListeners(type, editor, isCurrentlyEnqueuingUpdates, ...payload) {
15138    const previouslyUpdating = editor._updating;
15139    editor._updating = isCurrentlyEnqueuingUpdates;
15140    try {
15141      const listenerMap = editor._listeners[type];
15142      const listeners = Array.from(listenerMap);
15143      for (const [listener, unregister] of listeners) {
15144        if (unregister) {
15145          unregister();
15146        }
15147        const nextUnregister = listener(...payload);
15148        if (listenerMap.has(listener)) {
15149          listenerMap.set(listener, nextUnregister);
15150        } else if (nextUnregister) {
15151          nextUnregister();
15152        }
15153      }
15154    } finally {
15155      editor._updating = previouslyUpdating;
15156    }
15157  }
15158  function triggerCommandListeners(editor, type, payload, fromEditor) {
15159    const editors = getEditorsToPropagate(editor);
15160    let updatingParentEditor;
15161    for (let i2 = 4; i2 >= 0; i2--) {
15162      for (let e2 = 0; e2 < editors.length; e2++) {
15163        const currentEditor = editors[e2];
15164        if (e2 > 0 && currentEditor._updating) {
15165          updatingParentEditor = currentEditor;
15166          break;
15167        }
15168        const commandListeners = currentEditor._commands;
15169        const listenerInPriorityOrder = commandListeners.get(type);
15170        if (listenerInPriorityOrder !== void 0) {
15171          const listenersSet = listenerInPriorityOrder[i2];
15172          if (listenersSet.size > 0) {
15173            let returnVal = false;
15174            updateEditorSync(currentEditor, () => {
15175              for (const listener of listenersSet) {
15176                if (listener(payload, fromEditor)) {
15177                  returnVal = true;
15178                  return;
15179                }
15180              }
15181            });
15182            if (returnVal) {
15183              return returnVal;
15184            }
15185          }
15186        }
15187      }
15188    }
15189    if (updatingParentEditor) {
15190      updatingParentEditor.update(() => {
15191        triggerCommandListeners(updatingParentEditor, type, payload, fromEditor);
15192      });
15193    }
15194    return false;
15195  }
15196  function $triggerEnqueuedUpdates(editor) {
15197    const queuedUpdates = editor._updates;
15198    if (queuedUpdates.length !== 0) {
15199      const queuedUpdate = queuedUpdates.shift();
15200      if (queuedUpdate) {
15201        const [updateFn, options] = queuedUpdate;
15202        $beginUpdate(editor, updateFn, options);
15203      }
15204    }
15205  }
15206  function triggerDeferredUpdateCallbacks(editor, deferred) {
15207    editor._deferred = [];
15208    if (deferred.length !== 0) {
15209      const previouslyUpdating = editor._updating;
15210      editor._updating = true;
15211      try {
15212        for (let i2 = 0; i2 < deferred.length; i2++) {
15213          deferred[i2]();
15214        }
15215      } finally {
15216        editor._updating = previouslyUpdating;
15217      }
15218    }
15219  }
15220  function $processNestedUpdates(editor, initialSkipTransforms) {
15221    const queuedUpdates = editor._updates;
15222    let skipTransforms = initialSkipTransforms || false;
15223    while (queuedUpdates.length !== 0) {
15224      const queuedUpdate = queuedUpdates.shift();
15225      if (queuedUpdate) {
15226        const [nextUpdateFn, options] = queuedUpdate;
15227        const pendingEditorState = editor._pendingEditorState;
15228        let onUpdate;
15229        if (options !== void 0) {
15230          onUpdate = options.onUpdate;
15231          if (options.skipTransforms) {
15232            skipTransforms = true;
15233          }
15234          if (options.discrete) {
15235            if (!(pendingEditorState !== null)) {
15236              formatDevErrorMessage(`Unexpected empty pending editor state on discrete nested update`);
15237            }
15238            pendingEditorState._flushSync = true;
15239          }
15240          if (onUpdate) {
15241            editor._deferred.push(onUpdate);
15242          }
15243          addTags(editor, options.tag);
15244        }
15245        if (pendingEditorState == null) {
15246          $beginUpdate(editor, nextUpdateFn, options);
15247        } else {
15248          nextUpdateFn();
15249        }
15250      }
15251    }
15252    return skipTransforms;
15253  }
15254  function $beginUpdate(editor, updateFn, options) {
15255    const updateTags = editor._updateTags;
15256    let onUpdate;
15257    let skipTransforms = false;
15258    let discrete = false;
15259    if (options !== void 0) {
15260      onUpdate = options.onUpdate;
15261      addTags(editor, options.tag);
15262      skipTransforms = options.skipTransforms || false;
15263      discrete = options.discrete || false;
15264    }
15265    if (onUpdate) {
15266      editor._deferred.push(onUpdate);
15267    }
15268    const currentEditorState = editor._editorState;
15269    let pendingEditorState = editor._pendingEditorState;
15270    let editorStateWasCloned = false;
15271    if (pendingEditorState === null || pendingEditorState._readOnly) {
15272      pendingEditorState = editor._pendingEditorState = cloneEditorState(pendingEditorState || currentEditorState);
15273      editorStateWasCloned = true;
15274    }
15275    pendingEditorState._flushSync = discrete;
15276    const previousActiveEditorState = activeEditorState;
15277    const previousReadOnlyMode = isReadOnlyMode;
15278    const previousActiveEditor = activeEditor;
15279    const previouslyUpdating = editor._updating;
15280    activeEditorState = pendingEditorState;
15281    isReadOnlyMode = false;
15282    editor._updating = true;
15283    activeEditor = editor;
15284    const headless = editor._headless || editor.getRootElement() === null;
15285    setPendingNodeToClone(null);
15286    try {
15287      if (editorStateWasCloned) {
15288        if (headless) {
15289          if (currentEditorState._selection !== null) {
15290            pendingEditorState._selection = currentEditorState._selection.clone();
15291          }
15292        } else {
15293          pendingEditorState._selection = $internalCreateSelection(editor, options && options.event || null);
15294        }
15295      }
15296      const startingCompositionKey = editor._compositionKey;
15297      updateFn();
15298      skipTransforms = $processNestedUpdates(editor, skipTransforms);
15299      applySelectionTransforms(pendingEditorState, editor);
15300      if (editor._dirtyType !== NO_DIRTY_NODES) {
15301        if (skipTransforms) {
15302          $normalizeAllDirtyTextNodes(pendingEditorState, editor);
15303        } else {
15304          $applyAllTransforms(pendingEditorState, editor);
15305        }
15306        $processNestedUpdates(editor);
15307        $garbageCollectDetachedNodes(currentEditorState, pendingEditorState, editor._dirtyLeaves, editor._dirtyElements);
15308      }
15309      const endingCompositionKey = editor._compositionKey;
15310      if (startingCompositionKey !== endingCompositionKey) {
15311        pendingEditorState._flushSync = true;
15312      }
15313      const pendingSelection = pendingEditorState._selection;
15314      if ($isRangeSelection(pendingSelection)) {
15315        const pendingNodeMap = pendingEditorState._nodeMap;
15316        const anchorKey = pendingSelection.anchor.key;
15317        const focusKey = pendingSelection.focus.key;
15318        if (pendingNodeMap.get(anchorKey) === void 0 || pendingNodeMap.get(focusKey) === void 0) {
15319          {
15320            formatDevErrorMessage(`updateEditor: selection has been lost because the previously selected nodes have been removed and selection wasn't moved to another node. Ensure selection changes after removing/replacing a selected node.`);
15321          }
15322        }
15323      } else if ($isNodeSelection(pendingSelection)) {
15324        if (pendingSelection._nodes.size === 0) {
15325          pendingEditorState._selection = null;
15326        }
15327      }
15328    } catch (error) {
15329      if (error instanceof Error) {
15330        editor._onError(error);
15331      }
15332      editor._pendingEditorState = currentEditorState;
15333      editor._dirtyType = FULL_RECONCILE;
15334      editor._cloneNotNeeded.clear();
15335      editor._dirtyLeaves = /* @__PURE__ */ new Set();
15336      editor._dirtyElements.clear();
15337      $commitPendingUpdates(editor);
15338      return;
15339    } finally {
15340      activeEditorState = previousActiveEditorState;
15341      isReadOnlyMode = previousReadOnlyMode;
15342      activeEditor = previousActiveEditor;
15343      editor._updating = previouslyUpdating;
15344      infiniteTransformCount = 0;
15345    }
15346    const shouldUpdate = editor._dirtyType !== NO_DIRTY_NODES || editor._deferred.length > 0 || editorStateHasDirtySelection(pendingEditorState, editor);
15347    if (shouldUpdate) {
15348      if (pendingEditorState._flushSync) {
15349        pendingEditorState._flushSync = false;
15350        $commitPendingUpdates(editor);
15351      } else if (editorStateWasCloned) {
15352        scheduleMicroTask(() => {
15353          $commitPendingUpdates(editor);
15354        });
15355      }
15356    } else {
15357      pendingEditorState._flushSync = false;
15358      if (editorStateWasCloned) {
15359        updateTags.clear();
15360        editor._deferred = [];
15361        editor._pendingEditorState = null;
15362      }
15363    }
15364  }
15365  function updateEditorSync(editor, updateFn, options) {
15366    if (activeEditor === editor && options === void 0) {
15367      updateFn();
15368    } else {
15369      $beginUpdate(editor, updateFn, options);
15370    }
15371  }
15372  function updateEditor(editor, updateFn, options) {
15373    if (editor._updating) {
15374      editor._updates.push([updateFn, options]);
15375    } else {
15376      $beginUpdate(editor, updateFn, options);
15377    }
15378  }
15379  var ElementDOMSlot = class _ElementDOMSlot {
15380    element;
15381    before;
15382    after;
15383    constructor(element, before, after) {
15384      this.element = element;
15385      this.before = before || null;
15386      this.after = after || null;
15387    }
15388    /**
15389     * Return a new ElementDOMSlot where all managed children will be inserted before this node
15390     */
15391    withBefore(before) {
15392      return new _ElementDOMSlot(this.element, before, this.after);
15393    }
15394    /**
15395     * Return a new ElementDOMSlot where all managed children will be inserted after this node
15396     */
15397    withAfter(after) {
15398      return new _ElementDOMSlot(this.element, this.before, after);
15399    }
15400    /**
15401     * Return a new ElementDOMSlot with an updated root element
15402     */
15403    withElement(element) {
15404      if (this.element === element) {
15405        return this;
15406      }
15407      return new _ElementDOMSlot(element, this.before, this.after);
15408    }
15409    /**
15410     * Insert the given child before this.before and any reconciler managed line break node,
15411     * or append it if this.before is not defined
15412     */
15413    insertChild(dom) {
15414      const before = this.before || this.getManagedLineBreak();
15415      if (!(before === null || before.parentElement === this.element)) {
15416        formatDevErrorMessage(`ElementDOMSlot.insertChild: before is not in element`);
15417      }
15418      this.element.insertBefore(dom, before);
15419      return this;
15420    }
15421    /**
15422     * Remove the managed child from this container, will throw if it was not already there
15423     */
15424    removeChild(dom) {
15425      if (!(dom.parentElement === this.element)) {
15426        formatDevErrorMessage(`ElementDOMSlot.removeChild: dom is not in element`);
15427      }
15428      this.element.removeChild(dom);
15429      return this;
15430    }
15431    /**
15432     * Replace managed child prevDom with dom. Will throw if prevDom is not a child
15433     *
15434     * @param dom The new node to replace prevDom
15435     * @param prevDom the node that will be replaced
15436     */
15437    replaceChild(dom, prevDom) {
15438      if (!(prevDom.parentElement === this.element)) {
15439        formatDevErrorMessage(`ElementDOMSlot.replaceChild: prevDom is not in element`);
15440      }
15441      this.element.replaceChild(dom, prevDom);
15442      return this;
15443    }
15444    /**
15445     * Returns the first managed child of this node,
15446     * which will either be this.after.nextSibling or this.element.firstChild,
15447     * and will never be this.before if it is defined.
15448     */
15449    getFirstChild() {
15450      const firstChild = this.after ? this.after.nextSibling : this.element.firstChild;
15451      return firstChild === this.before || firstChild === this.getManagedLineBreak() ? null : firstChild;
15452    }
15453    /**
15454     * @internal
15455     */
15456    getManagedLineBreak() {
15457      const element = this.element;
15458      return element.__lexicalLineBreak || null;
15459    }
15460    /** @internal */
15461    setManagedLineBreak(lineBreakType) {
15462      if (lineBreakType === null) {
15463        this.removeManagedLineBreak();
15464      } else {
15465        const webkitHack = lineBreakType === "decorator" && (IS_APPLE_WEBKIT || IS_IOS || IS_SAFARI);
15466        this.insertManagedLineBreak(webkitHack);
15467      }
15468    }
15469    /** @internal */
15470    removeManagedLineBreak() {
15471      const br = this.getManagedLineBreak();
15472      if (br) {
15473        const element = this.element;
15474        const sibling = br.nodeName === "IMG" ? br.nextSibling : null;
15475        if (sibling) {
15476          element.removeChild(sibling);
15477        }
15478        element.removeChild(br);
15479        element.__lexicalLineBreak = void 0;
15480      }
15481    }
15482    /** @internal */
15483    insertManagedLineBreak(webkitHack) {
15484      const prevBreak = this.getManagedLineBreak();
15485      if (prevBreak) {
15486        if (webkitHack === (prevBreak.nodeName === "IMG")) {
15487          return;
15488        }
15489        this.removeManagedLineBreak();
15490      }
15491      const element = this.element;
15492      const before = this.before;
15493      const br = document.createElement("br");
15494      element.insertBefore(br, before);
15495      if (webkitHack) {
15496        const img = document.createElement("img");
15497        img.setAttribute("data-lexical-linebreak", "true");
15498        img.style.setProperty("display", "inline", "important");
15499        img.style.setProperty("border", "0px", "important");
15500        img.style.setProperty("margin", "0px", "important");
15501        img.alt = "";
15502        element.insertBefore(img, br);
15503        element.__lexicalLineBreak = img;
15504      } else {
15505        element.__lexicalLineBreak = br;
15506      }
15507    }
15508    /**
15509     * @internal
15510     *
15511     * Returns the offset of the first child
15512     */
15513    getFirstChildOffset() {
15514      let i2 = 0;
15515      for (let node = this.after; node !== null; node = node.previousSibling) {
15516        i2++;
15517      }
15518      return i2;
15519    }
15520    /**
15521     * @internal
15522     */
15523    resolveChildIndex(element, elementDOM, initialDOM, initialOffset) {
15524      if (initialDOM === this.element) {
15525        const firstChildOffset = this.getFirstChildOffset();
15526        return [element, Math.min(firstChildOffset + element.getChildrenSize(), Math.max(firstChildOffset, initialOffset))];
15527      }
15528      const initialPath = indexPath(elementDOM, initialDOM);
15529      initialPath.push(initialOffset);
15530      const elementPath = indexPath(elementDOM, this.element);
15531      let offset3 = element.getIndexWithinParent();
15532      for (let i2 = 0; i2 < elementPath.length; i2++) {
15533        const target = initialPath[i2];
15534        const source = elementPath[i2];
15535        if (target === void 0 || target < source) {
15536          break;
15537        } else if (target > source) {
15538          offset3 += 1;
15539          break;
15540        }
15541      }
15542      return [element.getParentOrThrow(), offset3];
15543    }
15544  };
15545  function indexPath(root, child) {
15546    const path = [];
15547    let node = child;
15548    for (; node !== root && node !== null; node = node.parentNode) {
15549      let i2 = 0;
15550      for (let sibling = node.previousSibling; sibling !== null; sibling = sibling.previousSibling) {
15551        i2++;
15552      }
15553      path.push(i2);
15554    }
15555    if (!(node === root)) {
15556      formatDevErrorMessage(`indexPath: root is not a parent of child`);
15557    }
15558    return path.reverse();
15559  }
15560  var ElementNode = class extends LexicalNode {
15561    /** @internal */
15562    /** @internal */
15563    __first;
15564    /** @internal */
15565    __last;
15566    /** @internal */
15567    __size;
15568    /** @internal */
15569    __format;
15570    /** @internal */
15571    __style;
15572    /** @internal */
15573    __indent;
15574    /** @internal */
15575    __dir;
15576    /** @internal */
15577    __textFormat;
15578    /** @internal */
15579    __textStyle;
15580    constructor(key) {
15581      super(key);
15582      this.__first = null;
15583      this.__last = null;
15584      this.__size = 0;
15585      this.__format = 0;
15586      this.__style = "";
15587      this.__indent = 0;
15588      this.__dir = null;
15589      this.__textFormat = 0;
15590      this.__textStyle = "";
15591    }
15592    afterCloneFrom(prevNode) {
15593      super.afterCloneFrom(prevNode);
15594      if (this.__key === prevNode.__key) {
15595        this.__first = prevNode.__first;
15596        this.__last = prevNode.__last;
15597        this.__size = prevNode.__size;
15598      }
15599      this.__indent = prevNode.__indent;
15600      this.__format = prevNode.__format;
15601      this.__style = prevNode.__style;
15602      this.__dir = prevNode.__dir;
15603      this.__textFormat = prevNode.__textFormat;
15604      this.__textStyle = prevNode.__textStyle;
15605    }
15606    getFormat() {
15607      const self2 = this.getLatest();
15608      return self2.__format;
15609    }
15610    getFormatType() {
15611      const format = this.getFormat();
15612      return ELEMENT_FORMAT_TO_TYPE[format] || "";
15613    }
15614    getStyle() {
15615      const self2 = this.getLatest();
15616      return self2.__style;
15617    }
15618    getIndent() {
15619      const self2 = this.getLatest();
15620      return self2.__indent;
15621    }
15622    getChildren() {
15623      const children = [];
15624      let child = this.getFirstChild();
15625      while (child !== null) {
15626        children.push(child);
15627        child = child.getNextSibling();
15628      }
15629      return children;
15630    }
15631    getChildrenKeys() {
15632      const children = [];
15633      let child = this.getFirstChild();
15634      while (child !== null) {
15635        children.push(child.__key);
15636        child = child.getNextSibling();
15637      }
15638      return children;
15639    }
15640    getChildrenSize() {
15641      const self2 = this.getLatest();
15642      return self2.__size;
15643    }
15644    isEmpty() {
15645      return this.getChildrenSize() === 0;
15646    }
15647    isDirty() {
15648      const editor = getActiveEditor();
15649      const dirtyElements = editor._dirtyElements;
15650      return dirtyElements !== null && dirtyElements.has(this.__key);
15651    }
15652    isLastChild() {
15653      const self2 = this.getLatest();
15654      const parentLastChild = this.getParentOrThrow().getLastChild();
15655      return parentLastChild !== null && parentLastChild.is(self2);
15656    }
15657    getAllTextNodes() {
15658      const textNodes = [];
15659      let child = this.getFirstChild();
15660      while (child !== null) {
15661        if ($isTextNode(child)) {
15662          textNodes.push(child);
15663        }
15664        if ($isElementNode(child)) {
15665          const subChildrenNodes = child.getAllTextNodes();
15666          textNodes.push(...subChildrenNodes);
15667        }
15668        child = child.getNextSibling();
15669      }
15670      return textNodes;
15671    }
15672    getFirstDescendant() {
15673      let node = this.getFirstChild();
15674      while ($isElementNode(node)) {
15675        const child = node.getFirstChild();
15676        if (child === null) {
15677          break;
15678        }
15679        node = child;
15680      }
15681      return node;
15682    }
15683    getLastDescendant() {
15684      let node = this.getLastChild();
15685      while ($isElementNode(node)) {
15686        const child = node.getLastChild();
15687        if (child === null) {
15688          break;
15689        }
15690        node = child;
15691      }
15692      return node;
15693    }
15694    getDescendantByIndex(index) {
15695      const children = this.getChildren();
15696      const childrenLength = children.length;
15697      if (index >= childrenLength) {
15698        const resolvedNode2 = children[childrenLength - 1];
15699        return $isElementNode(resolvedNode2) && resolvedNode2.getLastDescendant() || resolvedNode2 || null;
15700      }
15701      const resolvedNode = children[index];
15702      return $isElementNode(resolvedNode) && resolvedNode.getFirstDescendant() || resolvedNode || null;
15703    }
15704    getFirstChild() {
15705      const self2 = this.getLatest();
15706      const firstKey = self2.__first;
15707      return firstKey === null ? null : $getNodeByKey(firstKey);
15708    }
15709    getFirstChildOrThrow() {
15710      const firstChild = this.getFirstChild();
15711      if (firstChild === null) {
15712        {
15713          formatDevErrorMessage(`Expected node ${this.__key} to have a first child.`);
15714        }
15715      }
15716      return firstChild;
15717    }
15718    getLastChild() {
15719      const self2 = this.getLatest();
15720      const lastKey = self2.__last;
15721      return lastKey === null ? null : $getNodeByKey(lastKey);
15722    }
15723    getLastChildOrThrow() {
15724      const lastChild = this.getLastChild();
15725      if (lastChild === null) {
15726        {
15727          formatDevErrorMessage(`Expected node ${this.__key} to have a last child.`);
15728        }
15729      }
15730      return lastChild;
15731    }
15732    getChildAtIndex(index) {
15733      const size2 = this.getChildrenSize();
15734      let node;
15735      let i2;
15736      if (index < size2 / 2) {
15737        node = this.getFirstChild();
15738        i2 = 0;
15739        while (node !== null && i2 <= index) {
15740          if (i2 === index) {
15741            return node;
15742          }
15743          node = node.getNextSibling();
15744          i2++;
15745        }
15746        return null;
15747      }
15748      node = this.getLastChild();
15749      i2 = size2 - 1;
15750      while (node !== null && i2 >= index) {
15751        if (i2 === index) {
15752          return node;
15753        }
15754        node = node.getPreviousSibling();
15755        i2--;
15756      }
15757      return null;
15758    }
15759    getTextContent() {
15760      let textContent = "";
15761      const children = this.getChildren();
15762      const childrenLength = children.length;
15763      for (let i2 = 0; i2 < childrenLength; i2++) {
15764        const child = children[i2];
15765        textContent += child.getTextContent();
15766        if (
15767          // this is an inline $textContentRequiresDoubleLinebreakAtEnd(child)
15768          $isElementNode(child) && i2 !== childrenLength - 1 && !child.isInline()
15769        ) {
15770          textContent += DOUBLE_LINE_BREAK;
15771        }
15772      }
15773      return textContent;
15774    }
15775    getTextContentSize() {
15776      let textContentSize = 0;
15777      const children = this.getChildren();
15778      const childrenLength = children.length;
15779      for (let i2 = 0; i2 < childrenLength; i2++) {
15780        const child = children[i2];
15781        textContentSize += child.getTextContentSize();
15782        if (
15783          // This is an inline $textContentRequiresDoubleLinebreakAtEnd(child)
15784          $isElementNode(child) && i2 !== childrenLength - 1 && !child.isInline()
15785        ) {
15786          textContentSize += DOUBLE_LINE_BREAK.length;
15787        }
15788      }
15789      return textContentSize;
15790    }
15791    getDirection() {
15792      const self2 = this.getLatest();
15793      return self2.__dir;
15794    }
15795    getTextFormat() {
15796      const self2 = this.getLatest();
15797      return self2.__textFormat;
15798    }
15799    hasFormat(type) {
15800      if (type !== "") {
15801        const formatFlag = ELEMENT_TYPE_TO_FORMAT[type];
15802        return (this.getFormat() & formatFlag) !== 0;
15803      }
15804      return false;
15805    }
15806    hasTextFormat(type) {
15807      const formatFlag = TEXT_TYPE_TO_FORMAT[type];
15808      return (this.getTextFormat() & formatFlag) !== 0;
15809    }
15810    /**
15811     * Returns the format flags applied to the node as a 32-bit integer.
15812     *
15813     * @returns a number representing the TextFormatTypes applied to the node.
15814     */
15815    getFormatFlags(type, alignWithFormat) {
15816      const self2 = this.getLatest();
15817      const format = self2.__textFormat;
15818      return toggleTextFormatType(format, type, alignWithFormat);
15819    }
15820    getTextStyle() {
15821      const self2 = this.getLatest();
15822      return self2.__textStyle;
15823    }
15824    // Mutators
15825    select(_anchorOffset, _focusOffset) {
15826      errorOnReadOnly();
15827      const selection = $getSelection();
15828      let anchorOffset = _anchorOffset;
15829      let focusOffset = _focusOffset;
15830      const childrenCount = this.getChildrenSize();
15831      if (!this.canBeEmpty()) {
15832        if (_anchorOffset === 0 && _focusOffset === 0) {
15833          const firstChild = this.getFirstChild();
15834          if ($isTextNode(firstChild) || $isElementNode(firstChild)) {
15835            return firstChild.select(0, 0);
15836          }
15837        } else if ((_anchorOffset === void 0 || _anchorOffset === childrenCount) && (_focusOffset === void 0 || _focusOffset === childrenCount)) {
15838          const lastChild = this.getLastChild();
15839          if ($isTextNode(lastChild) || $isElementNode(lastChild)) {
15840            return lastChild.select();
15841          }
15842        }
15843      }
15844      if (anchorOffset === void 0) {
15845        anchorOffset = childrenCount;
15846      }
15847      if (focusOffset === void 0) {
15848        focusOffset = childrenCount;
15849      }
15850      const key = this.__key;
15851      if (!$isRangeSelection(selection)) {
15852        return $internalMakeRangeSelection(key, anchorOffset, key, focusOffset, "element", "element");
15853      } else {
15854        selection.anchor.set(key, anchorOffset, "element");
15855        selection.focus.set(key, focusOffset, "element");
15856        selection.dirty = true;
15857      }
15858      return selection;
15859    }
15860    selectStart() {
15861      const firstNode = this.getFirstDescendant();
15862      return firstNode ? firstNode.selectStart() : this.select();
15863    }
15864    selectEnd() {
15865      const lastNode = this.getLastDescendant();
15866      return lastNode ? lastNode.selectEnd() : this.select();
15867    }
15868    clear() {
15869      const writableSelf = this.getWritable();
15870      const children = this.getChildren();
15871      children.forEach((child) => child.remove());
15872      return writableSelf;
15873    }
15874    append(...nodesToAppend) {
15875      return this.splice(this.getChildrenSize(), 0, nodesToAppend);
15876    }
15877    setDirection(direction) {
15878      const self2 = this.getWritable();
15879      self2.__dir = direction;
15880      return self2;
15881    }
15882    setFormat(type) {
15883      const self2 = this.getWritable();
15884      self2.__format = type !== "" ? ELEMENT_TYPE_TO_FORMAT[type] || 0 : 0;
15885      return this;
15886    }
15887    setStyle(style) {
15888      const self2 = this.getWritable();
15889      self2.__style = style || "";
15890      return this;
15891    }
15892    setTextFormat(type) {
15893      const self2 = this.getWritable();
15894      self2.__textFormat = type;
15895      return self2;
15896    }
15897    setTextStyle(style) {
15898      const self2 = this.getWritable();
15899      self2.__textStyle = style;
15900      return self2;
15901    }
15902    setIndent(indentLevel) {
15903      const self2 = this.getWritable();
15904      self2.__indent = indentLevel;
15905      return this;
15906    }
15907    splice(start3, deleteCount, nodesToInsert) {
15908      if (!!$isEphemeral(this)) {
15909        formatDevErrorMessage(`ElementNode.splice: Ephemeral nodes can not mutate their children (key ${this.__key} type ${this.__type})`);
15910      }
15911      const oldSize = this.getChildrenSize();
15912      const writableSelf = this.getWritable();
15913      if (!(start3 + deleteCount <= oldSize)) {
15914        formatDevErrorMessage(`ElementNode.splice: start + deleteCount > oldSize (${String(start3)} + ${String(deleteCount)} > ${String(oldSize)})`);
15915      }
15916      const writableSelfKey = writableSelf.__key;
15917      const nodesToInsertKeys = [];
15918      const nodesToRemoveKeys = [];
15919      const nodeAfterRange = this.getChildAtIndex(start3 + deleteCount);
15920      let nodeBeforeRange = null;
15921      let newSize = oldSize - deleteCount + nodesToInsert.length;
15922      if (start3 !== 0) {
15923        if (start3 === oldSize) {
15924          nodeBeforeRange = this.getLastChild();
15925        } else {
15926          const node = this.getChildAtIndex(start3);
15927          if (node !== null) {
15928            nodeBeforeRange = node.getPreviousSibling();
15929          }
15930        }
15931      }
15932      if (deleteCount > 0) {
15933        let nodeToDelete = nodeBeforeRange === null ? this.getFirstChild() : nodeBeforeRange.getNextSibling();
15934        for (let i2 = 0; i2 < deleteCount; i2++) {
15935          if (nodeToDelete === null) {
15936            {
15937              formatDevErrorMessage(`splice: sibling not found`);
15938            }
15939          }
15940          const nextSibling = nodeToDelete.getNextSibling();
15941          const nodeKeyToDelete = nodeToDelete.__key;
15942          const writableNodeToDelete = nodeToDelete.getWritable();
15943          removeFromParent(writableNodeToDelete);
15944          nodesToRemoveKeys.push(nodeKeyToDelete);
15945          nodeToDelete = nextSibling;
15946        }
15947      }
15948      let prevNode = nodeBeforeRange;
15949      for (const nodeToInsert of nodesToInsert) {
15950        if (prevNode !== null && nodeToInsert.is(prevNode)) {
15951          nodeBeforeRange = prevNode = prevNode.getPreviousSibling();
15952        }
15953        const writableNodeToInsert = nodeToInsert.getWritable();
15954        if (writableNodeToInsert.__parent === writableSelfKey) {
15955          newSize--;
15956        }
15957        removeFromParent(writableNodeToInsert);
15958        const nodeKeyToInsert = nodeToInsert.__key;
15959        if (prevNode === null) {
15960          writableSelf.__first = nodeKeyToInsert;
15961          writableNodeToInsert.__prev = null;
15962        } else {
15963          const writablePrevNode = prevNode.getWritable();
15964          writablePrevNode.__next = nodeKeyToInsert;
15965          writableNodeToInsert.__prev = writablePrevNode.__key;
15966        }
15967        if (nodeToInsert.__key === writableSelfKey) {
15968          {
15969            formatDevErrorMessage(`append: attempting to append self`);
15970          }
15971        }
15972        writableNodeToInsert.__parent = writableSelfKey;
15973        nodesToInsertKeys.push(nodeKeyToInsert);
15974        prevNode = nodeToInsert;
15975      }
15976      if (start3 + deleteCount === oldSize) {
15977        if (prevNode !== null) {
15978          const writablePrevNode = prevNode.getWritable();
15979          writablePrevNode.__next = null;
15980          writableSelf.__last = prevNode.__key;
15981        }
15982      } else if (nodeAfterRange !== null) {
15983        const writableNodeAfterRange = nodeAfterRange.getWritable();
15984        if (prevNode !== null) {
15985          const writablePrevNode = prevNode.getWritable();
15986          writableNodeAfterRange.__prev = prevNode.__key;
15987          writablePrevNode.__next = nodeAfterRange.__key;
15988        } else {
15989          writableNodeAfterRange.__prev = null;
15990        }
15991      }
15992      writableSelf.__size = newSize;
15993      if (nodesToRemoveKeys.length) {
15994        const selection = $getSelection();
15995        if ($isRangeSelection(selection)) {
15996          const nodesToRemoveKeySet = new Set(nodesToRemoveKeys);
15997          const nodesToInsertKeySet = new Set(nodesToInsertKeys);
15998          const {
15999            anchor,
16000            focus
16001          } = selection;
16002          if (isPointRemoved(anchor, nodesToRemoveKeySet, nodesToInsertKeySet)) {
16003            moveSelectionPointToSibling(anchor, anchor.getNode(), this, nodeBeforeRange, nodeAfterRange);
16004          }
16005          if (isPointRemoved(focus, nodesToRemoveKeySet, nodesToInsertKeySet)) {
16006            moveSelectionPointToSibling(focus, focus.getNode(), this, nodeBeforeRange, nodeAfterRange);
16007          }
16008          if (newSize === 0 && !this.canBeEmpty() && !$isRootOrShadowRoot(this)) {
16009            this.remove();
16010          }
16011        }
16012      }
16013      return writableSelf;
16014    }
16015    /**
16016     * @internal
16017     *
16018     * An experimental API that an ElementNode can override to control where its
16019     * children are inserted into the DOM, this is useful to add a wrapping node
16020     * or accessory nodes before or after the children. The root of the node returned
16021     * by createDOM must still be exactly one HTMLElement.
16022     */
16023    getDOMSlot(element) {
16024      return new ElementDOMSlot(element);
16025    }
16026    exportDOM(editor) {
16027      const {
16028        element
16029      } = super.exportDOM(editor);
16030      if (isHTMLElement(element)) {
16031        const indent = this.getIndent();
16032        if (indent > 0) {
16033          element.style.paddingInlineStart = `${indent * 40}px`;
16034        }
16035        const direction = this.getDirection();
16036        if (direction) {
16037          element.dir = direction;
16038        }
16039      }
16040      return {
16041        element
16042      };
16043    }
16044    // JSON serialization
16045    exportJSON() {
16046      const json = {
16047        children: [],
16048        direction: this.getDirection(),
16049        format: this.getFormatType(),
16050        indent: this.getIndent(),
16051        // As an exception here we invoke super at the end for historical reasons.
16052        // Namely, to preserve the order of the properties and not to break the tests
16053        // that use the serialized string representation.
16054        ...super.exportJSON()
16055      };
16056      const textFormat = this.getTextFormat();
16057      const textStyle = this.getTextStyle();
16058      if ((textFormat !== 0 || textStyle !== "") && !$isRootOrShadowRoot(this) && !this.getChildren().some($isTextNode)) {
16059        if (textFormat !== 0) {
16060          json.textFormat = textFormat;
16061        }
16062        if (textStyle !== "") {
16063          json.textStyle = textStyle;
16064        }
16065      }
16066      return json;
16067    }
16068    updateFromJSON(serializedNode) {
16069      return super.updateFromJSON(serializedNode).setFormat(serializedNode.format).setIndent(serializedNode.indent).setDirection(serializedNode.direction).setTextFormat(serializedNode.textFormat || 0).setTextStyle(serializedNode.textStyle || "");
16070    }
16071    // These are intended to be extends for specific element heuristics.
16072    insertNewAfter(selection, restoreSelection) {
16073      return null;
16074    }
16075    canIndent() {
16076      return true;
16077    }
16078    /*
16079     * This method controls the behavior of the node during backwards
16080     * deletion (i.e., backspace) when selection is at the beginning of
16081     * the node (offset 0). You may use this to have the node replace
16082     * itself, change its state, or do nothing. When you do make such
16083     * a change, you should return true.
16084     *
16085     * When true is returned, the collapse phase will stop.
16086     * When false is returned, and isInline() is true, and getPreviousSibling() is null,
16087     * then this function will be called on its parent.
16088     */
16089    collapseAtStart(selection) {
16090      return false;
16091    }
16092    excludeFromCopy(destination) {
16093      return false;
16094    }
16095    /** @deprecated @internal */
16096    canReplaceWith(replacement) {
16097      return true;
16098    }
16099    /** @deprecated @internal */
16100    canInsertAfter(node) {
16101      return true;
16102    }
16103    canBeEmpty() {
16104      return true;
16105    }
16106    canInsertTextBefore() {
16107      return true;
16108    }
16109    canInsertTextAfter() {
16110      return true;
16111    }
16112    isInline() {
16113      return false;
16114    }
16115    // A shadow root is a Node that behaves like RootNode. The shadow root (and RootNode) mark the
16116    // end of the hierarchy, most implementations should treat it as there's nothing (upwards)
16117    // beyond this point. For example, node.getTopLevelElement(), when performed inside a TableCellNode
16118    // will return the immediate first child underneath TableCellNode instead of RootNode.
16119    isShadowRoot() {
16120      return false;
16121    }
16122    /** @deprecated @internal */
16123    canMergeWith(node) {
16124      return false;
16125    }
16126    extractWithChild(child, selection, destination) {
16127      return false;
16128    }
16129    /**
16130     * Determines whether this node, when empty, can merge with a first block
16131     * of nodes being inserted.
16132     *
16133     * This method is specifically called in {@link RangeSelection.insertNodes}
16134     * to determine merging behavior during nodes insertion.
16135     *
16136     * @example
16137     * // In a ListItemNode or QuoteNode implementation:
16138     * canMergeWhenEmpty(): true {
16139     *  return true;
16140     * }
16141     */
16142    canMergeWhenEmpty() {
16143      return false;
16144    }
16145    /** @internal */
16146    reconcileObservedMutation(dom, editor) {
16147      const slot = $getEditorDOMRenderConfig(editor).$getDOMSlot(this, dom, editor);
16148      let currentDOM = slot.getFirstChild();
16149      for (let currentNode = this.getFirstChild(); currentNode; currentNode = currentNode.getNextSibling()) {
16150        const correctDOM = editor.getElementByKey(currentNode.getKey());
16151        if (correctDOM === null) {
16152          continue;
16153        }
16154        if (currentDOM == null) {
16155          slot.insertChild(correctDOM);
16156          currentDOM = correctDOM;
16157        } else if (currentDOM !== correctDOM) {
16158          slot.replaceChild(correctDOM, currentDOM);
16159        }
16160        currentDOM = currentDOM.nextSibling;
16161      }
16162    }
16163  };
16164  function $isElementNode(node) {
16165    return node instanceof ElementNode;
16166  }
16167  function isPointRemoved(point, nodesToRemoveKeySet, nodesToInsertKeySet) {
16168    let node = point.getNode();
16169    while (node) {
16170      const nodeKey = node.__key;
16171      if (nodesToRemoveKeySet.has(nodeKey) && !nodesToInsertKeySet.has(nodeKey)) {
16172        return true;
16173      }
16174      node = node.getParent();
16175    }
16176    return false;
16177  }
16178  var DecoratorNode = class extends LexicalNode {
16179    /** @internal */
16180    /**
16181     * The returned value is added to the LexicalEditor._decorators
16182     */
16183    decorate(editor, config) {
16184      return null;
16185    }
16186    isIsolated() {
16187      return false;
16188    }
16189    isInline() {
16190      return true;
16191    }
16192    isKeyboardSelectable() {
16193      return true;
16194    }
16195  };
16196  function $isDecoratorNode(node) {
16197    return node instanceof DecoratorNode;
16198  }
16199  var RootNode = class _RootNode extends ElementNode {
16200    /** @internal */
16201    __cachedText;
16202    static getType() {
16203      return "root";
16204    }
16205    static clone() {
16206      return new _RootNode();
16207    }
16208    constructor() {
16209      super("root");
16210      this.__cachedText = null;
16211    }
16212    getTopLevelElementOrThrow() {
16213      {
16214        formatDevErrorMessage(`getTopLevelElementOrThrow: root nodes are not top level elements`);
16215      }
16216    }
16217    getTextContent() {
16218      const cachedText = this.__cachedText;
16219      if (isCurrentlyReadOnlyMode() || getActiveEditor()._dirtyType === NO_DIRTY_NODES) {
16220        if (cachedText !== null) {
16221          return cachedText;
16222        }
16223      }
16224      return super.getTextContent();
16225    }
16226    remove() {
16227      {
16228        formatDevErrorMessage(`remove: cannot be called on root nodes`);
16229      }
16230    }
16231    replace(node) {
16232      {
16233        formatDevErrorMessage(`replace: cannot be called on root nodes`);
16234      }
16235    }
16236    insertBefore(nodeToInsert) {
16237      {
16238        formatDevErrorMessage(`insertBefore: cannot be called on root nodes`);
16239      }
16240    }
16241    insertAfter(nodeToInsert) {
16242      {
16243        formatDevErrorMessage(`insertAfter: cannot be called on root nodes`);
16244      }
16245    }
16246    // View
16247    updateDOM(prevNode, dom) {
16248      return false;
16249    }
16250    // Mutate
16251    splice(start3, deleteCount, nodesToInsert) {
16252      for (const node of nodesToInsert) {
16253        if (!($isElementNode(node) || $isDecoratorNode(node))) {
16254          formatDevErrorMessage(`rootNode.splice: Only element or decorator nodes can be inserted to the root node`);
16255        }
16256      }
16257      return super.splice(start3, deleteCount, nodesToInsert);
16258    }
16259    static importJSON(serializedNode) {
16260      return $getRoot().updateFromJSON(serializedNode);
16261    }
16262    collapseAtStart() {
16263      return true;
16264    }
16265  };
16266  function $createRootNode() {
16267    return new RootNode();
16268  }
16269  function $isRootNode(node) {
16270    return node instanceof RootNode;
16271  }
16272  function editorStateHasDirtySelection(editorState, editor) {
16273    const currentSelection = editor.getEditorState()._selection;
16274    const pendingSelection = editorState._selection;
16275    if (pendingSelection !== null) {
16276      if (pendingSelection.dirty || !pendingSelection.is(currentSelection)) {
16277        return true;
16278      }
16279    } else if (currentSelection !== null) {
16280      return true;
16281    }
16282    return false;
16283  }
16284  function cloneEditorState(current) {
16285    return new EditorState(new Map(current._nodeMap));
16286  }
16287  function createEmptyEditorState() {
16288    return new EditorState(/* @__PURE__ */ new Map([["root", $createRootNode()]]));
16289  }
16290  function exportNodeToJSON(node) {
16291    const serializedNode = node.exportJSON();
16292    const nodeClass = node.constructor;
16293    if (serializedNode.type !== nodeClass.getType()) {
16294      {
16295        formatDevErrorMessage(`LexicalNode: Node ${nodeClass.name} does not match the serialized type. Check if .exportJSON() is implemented and it is returning the correct type.`);
16296      }
16297    }
16298    if ($isElementNode(node)) {
16299      const serializedChildren = serializedNode.children;
16300      if (!Array.isArray(serializedChildren)) {
16301        {
16302          formatDevErrorMessage(`LexicalNode: Node ${nodeClass.name} is an element but .exportJSON() does not have a children array.`);
16303        }
16304      }
16305      const children = node.getChildren();
16306      for (let i2 = 0; i2 < children.length; i2++) {
16307        const child = children[i2];
16308        const serializedChildNode = exportNodeToJSON(child);
16309        serializedChildren.push(serializedChildNode);
16310      }
16311    }
16312    return serializedNode;
16313  }
16314  function $isEditorState(x3) {
16315    return x3 instanceof EditorState;
16316  }
16317  var EditorState = class _EditorState {
16318    _nodeMap;
16319    _selection;
16320    _flushSync;
16321    _readOnly;
16322    constructor(nodeMap, selection) {
16323      this._nodeMap = nodeMap;
16324      this._selection = selection || null;
16325      this._flushSync = false;
16326      this._readOnly = false;
16327    }
16328    isEmpty() {
16329      return this._nodeMap.size === 1 && this._selection === null;
16330    }
16331    read(callbackFn, options) {
16332      return readEditorState(options && options.editor || null, this, callbackFn);
16333    }
16334    clone(selection) {
16335      const editorState = new _EditorState(this._nodeMap, selection === void 0 ? this._selection : selection);
16336      editorState._readOnly = true;
16337      return editorState;
16338    }
16339    toJSON() {
16340      return readEditorState(null, this, () => ({
16341        root: exportNodeToJSON($getRoot())
16342      }));
16343    }
16344  };
16345  var ArtificialNode__DO_NOT_USE = class extends ElementNode {
16346    static getType() {
16347      return "artificial";
16348    }
16349    createDOM(config) {
16350      const dom = document.createElement("div");
16351      return dom;
16352    }
16353  };
16354  var ParagraphNode = class _ParagraphNode extends ElementNode {
16355    /** @internal */
16356    static getType() {
16357      return "paragraph";
16358    }
16359    static clone(node) {
16360      return new _ParagraphNode(node.__key);
16361    }
16362    // View
16363    createDOM(config) {
16364      const dom = document.createElement("p");
16365      const classNames = getCachedClassNameArray(config.theme, "paragraph");
16366      if (classNames !== void 0) {
16367        const domClassList = dom.classList;
16368        domClassList.add(...classNames);
16369      }
16370      return dom;
16371    }
16372    updateDOM(prevNode, dom, config) {
16373      return false;
16374    }
16375    static importDOM() {
16376      return {
16377        p: (node) => ({
16378          conversion: $convertParagraphElement,
16379          priority: 0
16380        })
16381      };
16382    }
16383    exportDOM(editor) {
16384      const {
16385        element
16386      } = super.exportDOM(editor);
16387      if (isHTMLElement(element)) {
16388        if (this.isEmpty()) {
16389          element.append(document.createElement("br"));
16390        }
16391        const formatType = this.getFormatType();
16392        if (formatType) {
16393          element.style.textAlign = formatType;
16394        }
16395      }
16396      return {
16397        element
16398      };
16399    }
16400    static importJSON(serializedNode) {
16401      return $createParagraphNode().updateFromJSON(serializedNode);
16402    }
16403    exportJSON() {
16404      const json = super.exportJSON();
16405      if (json.textFormat === void 0 || json.textStyle === void 0) {
16406        const firstTextNode = this.getChildren().find($isTextNode);
16407        if (firstTextNode) {
16408          json.textFormat = firstTextNode.getFormat();
16409          json.textStyle = firstTextNode.getStyle();
16410        } else {
16411          json.textFormat = this.getTextFormat();
16412          json.textStyle = this.getTextStyle();
16413        }
16414      }
16415      return json;
16416    }
16417    // Mutation
16418    insertNewAfter(rangeSelection, restoreSelection) {
16419      const newElement = $createParagraphNode();
16420      newElement.setTextFormat(rangeSelection.format);
16421      newElement.setTextStyle(rangeSelection.style);
16422      const direction = this.getDirection();
16423      newElement.setDirection(direction);
16424      newElement.setFormat(this.getFormatType());
16425      newElement.setStyle(this.getStyle());
16426      this.insertAfter(newElement, restoreSelection);
16427      return newElement;
16428    }
16429    collapseAtStart() {
16430      const children = this.getChildren();
16431      if (children.length === 0 || $isTextNode(children[0]) && children[0].getTextContent().trim() === "") {
16432        const nextSibling = this.getNextSibling();
16433        if (nextSibling !== null) {
16434          this.selectNext();
16435          this.remove();
16436          return true;
16437        }
16438        const prevSibling = this.getPreviousSibling();
16439        if (prevSibling !== null) {
16440          this.selectPrevious();
16441          this.remove();
16442          return true;
16443        }
16444      }
16445      return false;
16446    }
16447  };
16448  function $convertParagraphElement(element) {
16449    const node = $createParagraphNode();
16450    if (element.style) {
16451      node.setFormat(element.style.textAlign);
16452      setNodeIndentFromDOM(element, node);
16453    }
16454    if (node.getFormatType() === "") {
16455      const align = element.getAttribute("align");
16456      if (align) {
16457        if (align && align in ELEMENT_TYPE_TO_FORMAT) {
16458          node.setFormat(align);
16459        }
16460      }
16461    }
16462    return {
16463      node
16464    };
16465  }
16466  function $createParagraphNode() {
16467    return $applyNodeReplacement(new ParagraphNode());
16468  }
16469  function $isParagraphNode(node) {
16470    return node instanceof ParagraphNode;
16471  }
16472  var DEFAULT_SKIP_INITIALIZATION = false;
16473  var COMMAND_PRIORITY_EDITOR = 0;
16474  var COMMAND_PRIORITY_LOW = 1;
16475  var COMMAND_PRIORITY_NORMAL = 2;
16476  var COMMAND_PRIORITY_HIGH = 3;
16477  var COMMAND_PRIORITY_CRITICAL = 4;
16478  var COMMAND_PRIORITY_BEFORE_EDITOR = -8;
16479  var COMMAND_PRIORITY_BEFORE_LOW = -7;
16480  var COMMAND_PRIORITY_BEFORE_NORMAL = -6;
16481  var COMMAND_PRIORITY_BEFORE_HIGH = -5;
16482  var COMMAND_PRIORITY_BEFORE_CRITICAL = -4;
16483  function normalizePriority(priority) {
16484    return priority & 7;
16485  }
16486  function resetEditor(editor, prevRootElement, nextRootElement, pendingEditorState) {
16487    const keyNodeMap = editor._keyToDOMMap;
16488    keyNodeMap.clear();
16489    editor._editorState = createEmptyEditorState();
16490    editor._pendingEditorState = pendingEditorState;
16491    editor._compositionKey = null;
16492    editor._dirtyType = NO_DIRTY_NODES;
16493    editor._cloneNotNeeded.clear();
16494    editor._dirtyLeaves = /* @__PURE__ */ new Set();
16495    editor._dirtyElements.clear();
16496    editor._normalizedNodes = /* @__PURE__ */ new Set();
16497    editor._updateTags = /* @__PURE__ */ new Set();
16498    editor._updates = [];
16499    editor._blockCursorElement = null;
16500    const observer = editor._observer;
16501    if (observer !== null) {
16502      observer.disconnect();
16503      editor._observer = null;
16504    }
16505    if (prevRootElement !== null) {
16506      prevRootElement.textContent = "";
16507    }
16508    if (nextRootElement !== null) {
16509      nextRootElement.textContent = "";
16510      keyNodeMap.set("root", nextRootElement);
16511    }
16512  }
16513  function initializeConversionCache(nodes, additionalConversions) {
16514    const conversionCache = /* @__PURE__ */ new Map();
16515    const handledConversions = /* @__PURE__ */ new Set();
16516    const addConversionsToCache = (map) => {
16517      Object.keys(map).forEach((key) => {
16518        let currentCache = conversionCache.get(key);
16519        if (currentCache === void 0) {
16520          currentCache = [];
16521          conversionCache.set(key, currentCache);
16522        }
16523        currentCache.push(map[key]);
16524      });
16525    };
16526    nodes.forEach((node) => {
16527      const importDOM = node.klass.importDOM;
16528      if (importDOM == null || handledConversions.has(importDOM)) {
16529        return;
16530      }
16531      handledConversions.add(importDOM);
16532      const map = importDOM.call(node.klass);
16533      if (map !== null) {
16534        addConversionsToCache(map);
16535      }
16536    });
16537    if (additionalConversions) {
16538      addConversionsToCache(additionalConversions);
16539    }
16540    return conversionCache;
16541  }
16542  function getTransformSetFromKlass(klass) {
16543    const transforms = /* @__PURE__ */ new Set();
16544    const staticTransforms = /* @__PURE__ */ new Set();
16545    let currentKlass = klass;
16546    while (currentKlass) {
16547      const {
16548        ownNodeConfig
16549      } = getStaticNodeConfig(currentKlass);
16550      const staticTransform = currentKlass.transform;
16551      if (!staticTransforms.has(staticTransform)) {
16552        staticTransforms.add(staticTransform);
16553        const transform = currentKlass.transform();
16554        if (transform) {
16555          transforms.add(transform);
16556        }
16557      }
16558      if (ownNodeConfig) {
16559        const $transform = ownNodeConfig.$transform;
16560        if ($transform) {
16561          transforms.add($transform);
16562        }
16563        currentKlass = ownNodeConfig.extends;
16564      } else {
16565        const parent = Object.getPrototypeOf(currentKlass);
16566        currentKlass = parent.prototype instanceof LexicalNode && parent !== LexicalNode ? parent : void 0;
16567      }
16568    }
16569    return transforms;
16570  }
16571  var DEFAULT_EDITOR_DOM_CONFIG = {
16572    $createDOM: (node, editor) => node.createDOM(editor._config, editor),
16573    $decorateDOM: (_node, _prevNode, _dom, _editor) => {
16574    },
16575    $exportDOM: (node, editor) => {
16576      const registeredNode = getRegisteredNode(editor, node.getType());
16577      return registeredNode && registeredNode.exportDOM !== void 0 ? registeredNode.exportDOM(editor, node) : node.exportDOM(editor);
16578    },
16579    $extractWithChild: (node, childNode, selection, destination, _editor) => $isElementNode(node) && node.extractWithChild(childNode, selection, destination),
16580    $getDOMSlot: (node, dom, _editor) => {
16581      if (!$isElementNode(node)) {
16582        formatDevErrorMessage(`$getDOMSlot called on a non-ElementNode (key ${node.getKey()} type ${node.getType()})`);
16583      }
16584      return node.getDOMSlot(dom);
16585    },
16586    $shouldExclude: (node, _selection, _editor) => $isElementNode(node) && node.excludeFromCopy("html"),
16587    $shouldInclude: (node, selection, _editor) => selection ? node.isSelected(selection) : true,
16588    $updateDOM: (nextNode, prevNode, dom, editor) => nextNode.updateDOM(prevNode, dom, editor._config)
16589  };
16590  function createEditor(editorConfig) {
16591    const config = editorConfig || {};
16592    const activeEditor2 = internalGetActiveEditor();
16593    const theme2 = config.theme || {};
16594    const parentEditor = editorConfig === void 0 ? activeEditor2 : config.parentEditor || null;
16595    const disableEvents = config.disableEvents || false;
16596    const editorState = createEmptyEditorState();
16597    const namespace = config.namespace || (parentEditor !== null ? parentEditor._config.namespace : createUID());
16598    const initialEditorState = config.editorState;
16599    const nodes = [RootNode, TextNode, LineBreakNode, TabNode, ParagraphNode, ArtificialNode__DO_NOT_USE, ...config.nodes || []];
16600    const {
16601      onError,
16602      html: html2
16603    } = config;
16604    const isEditable = config.editable !== void 0 ? config.editable : true;
16605    let registeredNodes;
16606    if (editorConfig === void 0 && activeEditor2 !== null) {
16607      registeredNodes = activeEditor2._nodes;
16608    } else {
16609      registeredNodes = /* @__PURE__ */ new Map();
16610      for (let i2 = 0; i2 < nodes.length; i2++) {
16611        let klass = nodes[i2];
16612        let replace = null;
16613        let replaceWithKlass = null;
16614        if (typeof klass !== "function") {
16615          const options = klass;
16616          klass = options.replace;
16617          replace = options.with;
16618          replaceWithKlass = options.withKlass || null;
16619        }
16620        void getStaticNodeConfig(klass);
16621        {
16622          const name = klass.name;
16623          const nodeType = hasOwnStaticMethod(klass, "getType") && klass.getType();
16624          if (replaceWithKlass) {
16625            if (!(replaceWithKlass.prototype instanceof klass)) {
16626              formatDevErrorMessage(`${replaceWithKlass.name} doesn't extend the ${name}`);
16627            }
16628          } else if (replace) {
16629            console.warn(`Override for ${name} specifies 'replace' without 'withKlass'. 'withKlass' will be required in a future version.`);
16630          }
16631          if (name !== "RootNode" && nodeType !== "root" && nodeType !== "artificial" && // This is mostly for the unit test suite which
16632          // uses LexicalNode in an otherwise incorrect way
16633          // by mocking its static getType
16634          klass !== LexicalNode) {
16635            ["getType", "clone"].forEach((method) => {
16636              if (!hasOwnStaticMethod(klass, method)) {
16637                console.warn(`${name} must implement static "${method}" method`);
16638              }
16639            });
16640            if (!hasOwnStaticMethod(klass, "importDOM") && hasOwnExportDOM(klass)) {
16641              console.warn(`${name} should implement "importDOM" if using a custom "exportDOM" method to ensure HTML serialization (important for copy & paste) works as expected`);
16642            }
16643            if (!hasOwnStaticMethod(klass, "importJSON")) {
16644              console.warn(`${name} should implement "importJSON" method to ensure JSON and default HTML serialization works as expected`);
16645            }
16646          }
16647        }
16648        const type = klass.getType();
16649        const transforms = getTransformSetFromKlass(klass);
16650        registeredNodes.set(type, {
16651          exportDOM: html2 && html2.export ? html2.export.get(klass) : void 0,
16652          klass,
16653          replace,
16654          replaceWithKlass,
16655          sharedNodeState: createSharedNodeState(nodes[i2]),
16656          transforms
16657        });
16658      }
16659    }
16660    const editor = new LexicalEditor(editorState, parentEditor, registeredNodes, {
16661      disableEvents,
16662      dom: {
16663        ...DEFAULT_EDITOR_DOM_CONFIG,
16664        ...editorConfig && editorConfig.dom
16665      },
16666      namespace,
16667      theme: theme2
16668    }, onError ? onError : console.error, initializeConversionCache(registeredNodes, html2 ? html2.import : void 0), isEditable, editorConfig);
16669    if (initialEditorState !== void 0) {
16670      editor._pendingEditorState = initialEditorState;
16671      editor._dirtyType = FULL_RECONCILE;
16672    }
16673    registerDefaultCommandHandlers(editor);
16674    return editor;
16675  }
16676  function triggerListener(listenerMap, listener, args) {
16677    const unregister = listenerMap.get(listener);
16678    if (unregister) {
16679      unregister();
16680    }
16681    listenerMap.set(listener, listener(...args) || void 0);
16682  }
16683  function unregisterListener(listenerMap, listener) {
16684    const unregister = listenerMap.get(listener);
16685    listenerMap.delete(listener);
16686    if (unregister) {
16687      unregister();
16688    }
16689  }
16690  function registerListener(listenerMap, listener, unregister) {
16691    listenerMap.set(listener, unregister);
16692    return unregisterListener.bind(null, listenerMap, listener);
16693  }
16694  var LexicalEditor = class {
16695    /** @internal */
16696    /** The version with build identifiers for this editor (since 0.17.1) */
16697    static version;
16698    /** @internal */
16699    _headless;
16700    /** @internal */
16701    _parentEditor;
16702    /** @internal */
16703    _rootElement;
16704    /** @internal */
16705    _editorState;
16706    /** @internal */
16707    _pendingEditorState;
16708    /** @internal */
16709    _compositionKey;
16710    /** @internal */
16711    _deferred;
16712    /** @internal */
16713    _keyToDOMMap;
16714    /** @internal */
16715    _updates;
16716    /** @internal */
16717    _updating;
16718    /** @internal */
16719    _listeners;
16720    /** @internal */
16721    _commands;
16722    /** @internal */
16723    _nodes;
16724    /** @internal */
16725    _decorators;
16726    /** @internal */
16727    _pendingDecorators;
16728    /** @internal */
16729    _config;
16730    /** @internal */
16731    _dirtyType;
16732    /** @internal */
16733    _cloneNotNeeded;
16734    /** @internal */
16735    _dirtyLeaves;
16736    /** @internal */
16737    _dirtyElements;
16738    /** @internal */
16739    _normalizedNodes;
16740    /** @internal */
16741    _updateTags;
16742    /** @internal */
16743    _observer;
16744    /** @internal */
16745    _key;
16746    /** @internal */
16747    _onError;
16748    /** @internal */
16749    _htmlConversions;
16750    /** @internal */
16751    _window;
16752    /** @internal */
16753    _editable;
16754    /** @internal */
16755    _blockCursorElement;
16756    /** @internal */
16757    _createEditorArgs;
16758    /** @internal */
16759    constructor(editorState, parentEditor, nodes, config, onError, htmlConversions, editable, createEditorArgs) {
16760      this._createEditorArgs = createEditorArgs;
16761      this._parentEditor = parentEditor;
16762      this._rootElement = null;
16763      this._editorState = editorState;
16764      this._pendingEditorState = null;
16765      this._compositionKey = null;
16766      this._deferred = [];
16767      this._keyToDOMMap = /* @__PURE__ */ new Map();
16768      this._updates = [];
16769      this._updating = false;
16770      this._listeners = {
16771        decorator: /* @__PURE__ */ new Map(),
16772        editable: /* @__PURE__ */ new Map(),
16773        mutation: /* @__PURE__ */ new Map(),
16774        root: /* @__PURE__ */ new Map(),
16775        textcontent: /* @__PURE__ */ new Map(),
16776        update: /* @__PURE__ */ new Map()
16777      };
16778      this._commands = /* @__PURE__ */ new Map();
16779      this._config = config;
16780      this._nodes = nodes;
16781      this._decorators = {};
16782      this._pendingDecorators = null;
16783      this._dirtyType = NO_DIRTY_NODES;
16784      this._cloneNotNeeded = /* @__PURE__ */ new Set();
16785      this._dirtyLeaves = /* @__PURE__ */ new Set();
16786      this._dirtyElements = /* @__PURE__ */ new Map();
16787      this._normalizedNodes = /* @__PURE__ */ new Set();
16788      this._updateTags = /* @__PURE__ */ new Set();
16789      this._observer = null;
16790      this._key = createUID();
16791      this._onError = onError;
16792      this._htmlConversions = htmlConversions;
16793      this._editable = editable;
16794      this._headless = parentEditor !== null && parentEditor._headless;
16795      this._window = null;
16796      this._blockCursorElement = null;
16797    }
16798    /**
16799     *
16800     * @returns true if the editor is currently in "composition" mode due to receiving input
16801     * through an IME, or 3P extension, for example. Returns false otherwise.
16802     */
16803    isComposing() {
16804      return this._compositionKey != null;
16805    }
16806    /**
16807     * Registers a listener for Editor update event. Will trigger the provided callback
16808     * each time the editor goes through an update (via {@link LexicalEditor.update}) until the
16809     * teardown function is called.
16810     *
16811     * @returns a teardown function that can be used to cleanup the listener.
16812     */
16813    registerUpdateListener(listener) {
16814      return registerListener(this._listeners.update, listener);
16815    }
16816    /**
16817     * Registers a listener for for when the editor changes between editable and non-editable states.
16818     * Will trigger the provided callback each time the editor transitions between these states until the
16819     * teardown function is called.
16820     *
16821     * If the listener returns a function, that function will be called before the next transition or
16822     * teardown.
16823     *
16824     * @returns a teardown function that can be used to cleanup the listener.
16825     */
16826    registerEditableListener(listener) {
16827      return registerListener(this._listeners.editable, listener);
16828    }
16829    /**
16830     * Registers a listener for when the editor's decorator object changes. The decorator object contains
16831     * all DecoratorNode keys -> their decorated value. This is primarily used with external UI frameworks.
16832     *
16833     * Will trigger the provided callback each time the editor transitions between these states until the
16834     * teardown function is called.
16835     *
16836     * @returns a teardown function that can be used to cleanup the listener.
16837     */
16838    registerDecoratorListener(listener) {
16839      return registerListener(this._listeners.decorator, listener);
16840    }
16841    /**
16842     * Registers a listener for when Lexical commits an update to the DOM and the text content of
16843     * the editor changes from the previous state of the editor. If the text content is the
16844     * same between updates, no notifications to the listeners will happen.
16845     *
16846     * Will trigger the provided callback each time the editor transitions between these states until the
16847     * teardown function is called.
16848     *
16849     * @returns a teardown function that can be used to cleanup the listener.
16850     */
16851    registerTextContentListener(listener) {
16852      return registerListener(this._listeners.textcontent, listener);
16853    }
16854    /**
16855     * Registers a listener for when the editor's root DOM element (the content editable
16856     * Lexical attaches to) changes. This is primarily used to attach event listeners to the root
16857     *  element. The root listener function is executed directly upon registration and then on
16858     * any subsequent update.
16859     *
16860     * Will trigger the provided callback each time the editor transitions between these states until the
16861     * teardown function is called.
16862     *
16863     * If the listener returns a function, that function will be called before the next transition or
16864     * teardown.
16865     *
16866     * @returns a teardown function that can be used to cleanup the listener.
16867     */
16868    registerRootListener(listener) {
16869      const listenerMap = this._listeners.root;
16870      return mergeRegister(registerListener(listenerMap, listener, listener(this._rootElement, null) || void 0), () => triggerListener(listenerMap, listener, [null, this._rootElement]));
16871    }
16872    /**
16873     * Registers a listener that will trigger anytime the provided command
16874     * is dispatched with {@link LexicalEditor.dispatch}, subject to priority.
16875     * Listeners that run at a higher priority can "intercept" commands and
16876     * prevent them from propagating to other handlers by returning true.
16877     *
16878     * Listeners are always invoked in an {@link LexicalEditor.update} and can
16879     * call dollar functions.
16880     *
16881     * Listeners registered at the same priority level will run
16882     * deterministically in the order of registration.
16883     *
16884     * @param command - the command that will trigger the callback.
16885     * @param listener - the function that will execute when the command is dispatched.
16886     * @param priority - the relative priority of the listener. 0 | 1 | 2 | 3 | 4
16887     *   (or {@link COMMAND_PRIORITY_EDITOR} |
16888     *     {@link COMMAND_PRIORITY_LOW} |
16889     *     {@link COMMAND_PRIORITY_NORMAL} |
16890     *     {@link COMMAND_PRIORITY_HIGH} |
16891     *     {@link COMMAND_PRIORITY_CRITICAL})
16892     * @returns a teardown function that can be used to cleanup the listener.
16893     */
16894    registerCommand(command, listener, priority) {
16895      if (priority === void 0) {
16896        {
16897          formatDevErrorMessage(`Listener for type "command" requires a "priority".`);
16898        }
16899      }
16900      const commandsMap = this._commands;
16901      if (!commandsMap.has(command)) {
16902        commandsMap.set(command, [new DequeSet(), new DequeSet(), new DequeSet(), new DequeSet(), new DequeSet()]);
16903      }
16904      const listenersInPriorityOrder = commandsMap.get(command);
16905      if (listenersInPriorityOrder === void 0) {
16906        {
16907          formatDevErrorMessage(`registerCommand: Command ${String(command)} not found in command map`);
16908        }
16909      }
16910      const normalizedPriority = normalizePriority(priority);
16911      const listeners = listenersInPriorityOrder[normalizedPriority];
16912      if (normalizedPriority !== priority) {
16913        listeners.addFront(listener);
16914      } else {
16915        listeners.addBack(listener);
16916      }
16917      return () => {
16918        listeners.delete(listener);
16919        if (listenersInPriorityOrder.every((listenersSet) => listenersSet.size === 0)) {
16920          commandsMap.delete(command);
16921        }
16922      };
16923    }
16924    /**
16925     * Registers a listener that will run when a Lexical node of the provided class is
16926     * mutated. The listener will receive a list of nodes along with the type of mutation
16927     * that was performed on each: created, destroyed, or updated.
16928     *
16929     * One common use case for this is to attach DOM event listeners to the underlying DOM nodes as Lexical nodes are created.
16930     * {@link LexicalEditor.getElementByKey} can be used for this.
16931     *
16932     * If any existing nodes are in the DOM, and skipInitialization is not true, the listener
16933     * will be called immediately with an updateTag of 'registerMutationListener' where all
16934     * nodes have the 'created' NodeMutation. This can be controlled with the skipInitialization option
16935     * (whose default was previously true for backwards compatibility with &lt;=0.16.1 but has been changed to false as of 0.21.0).
16936     *
16937     * @param klass - The class of the node that you want to listen to mutations on.
16938     * @param listener - The logic you want to run when the node is mutated.
16939     * @param options - see {@link MutationListenerOptions}
16940     * @returns a teardown function that can be used to cleanup the listener.
16941     */
16942    registerMutationListener(klass, listener, options) {
16943      const klassToMutate = this.resolveRegisteredNodeAfterReplacements(this.getRegisteredNode(klass)).klass;
16944      const mutations = this._listeners.mutation;
16945      let klassSet = mutations.get(listener);
16946      if (klassSet === void 0) {
16947        klassSet = /* @__PURE__ */ new Set();
16948        mutations.set(listener, klassSet);
16949      }
16950      klassSet.add(klassToMutate);
16951      const skipInitialization = options && options.skipInitialization;
16952      if (!(skipInitialization === void 0 ? DEFAULT_SKIP_INITIALIZATION : skipInitialization)) {
16953        this.initializeMutationListener(listener, klassToMutate);
16954      }
16955      return () => {
16956        klassSet.delete(klassToMutate);
16957        if (klassSet.size === 0) {
16958          mutations.delete(listener);
16959        }
16960      };
16961    }
16962    /** @internal */
16963    getRegisteredNode(klass) {
16964      const registeredNode = this._nodes.get(klass.getType());
16965      if (registeredNode === void 0) {
16966        {
16967          formatDevErrorMessage(`Node ${klass.name} has not been registered. Ensure node has been passed to createEditor.`);
16968        }
16969      }
16970      return registeredNode;
16971    }
16972    /** @internal */
16973    resolveRegisteredNodeAfterReplacements(registeredNode) {
16974      while (registeredNode.replaceWithKlass) {
16975        registeredNode = this.getRegisteredNode(registeredNode.replaceWithKlass);
16976      }
16977      return registeredNode;
16978    }
16979    /** @internal */
16980    initializeMutationListener(listener, klass) {
16981      const prevEditorState = this._editorState;
16982      const nodeMap = getCachedTypeToNodeMap(prevEditorState).get(klass.getType());
16983      if (!nodeMap) {
16984        return;
16985      }
16986      const nodeMutationMap = /* @__PURE__ */ new Map();
16987      for (const k2 of nodeMap.keys()) {
16988        nodeMutationMap.set(k2, "created");
16989      }
16990      if (nodeMutationMap.size > 0) {
16991        listener(nodeMutationMap, {
16992          dirtyLeaves: /* @__PURE__ */ new Set(),
16993          prevEditorState,
16994          updateTags: /* @__PURE__ */ new Set(["registerMutationListener"])
16995        });
16996      }
16997    }
16998    /** @internal */
16999    registerNodeTransformToKlass(klass, listener) {
17000      const registeredNode = this.getRegisteredNode(klass);
17001      registeredNode.transforms.add(listener);
17002      return registeredNode;
17003    }
17004    /**
17005     * Registers a listener that will run when a Lexical node of the provided class is
17006     * marked dirty during an update. The listener will continue to run as long as the node
17007     * is marked dirty. There are no guarantees around the order of transform execution!
17008     *
17009     * Watch out for infinite loops. See [Node Transforms](https://lexical.dev/docs/concepts/transforms)
17010     * @param klass - The class of the node that you want to run transforms on.
17011     * @param listener - The logic you want to run when the node is updated.
17012     * @returns a teardown function that can be used to cleanup the listener.
17013     */
17014    registerNodeTransform(klass, listener) {
17015      const registeredNode = this.registerNodeTransformToKlass(klass, listener);
17016      const registeredNodes = [registeredNode];
17017      const replaceWithKlass = registeredNode.replaceWithKlass;
17018      if (replaceWithKlass != null) {
17019        const registeredReplaceWithNode = this.registerNodeTransformToKlass(replaceWithKlass, listener);
17020        registeredNodes.push(registeredReplaceWithNode);
17021      }
17022      markNodesWithTypesAsDirty(this, registeredNodes.map((node) => node.klass.getType()));
17023      return () => {
17024        registeredNodes.forEach((node) => node.transforms.delete(listener));
17025      };
17026    }
17027    /**
17028     * Used to assert that a certain node is registered, usually by plugins to ensure nodes that they
17029     * depend on have been registered.
17030     * @returns True if the editor has registered the provided node type, false otherwise.
17031     */
17032    hasNode(node) {
17033      return this._nodes.has(node.getType());
17034    }
17035    /**
17036     * Used to assert that certain nodes are registered, usually by plugins to ensure nodes that they
17037     * depend on have been registered.
17038     * @returns True if the editor has registered all of the provided node types, false otherwise.
17039     */
17040    hasNodes(nodes) {
17041      return nodes.every(this.hasNode.bind(this));
17042    }
17043    /**
17044     * Dispatches a command of the specified type with the specified payload.
17045     * This triggers all command listeners (set by {@link LexicalEditor.registerCommand})
17046     * for this type, passing them the provided payload. The command listeners
17047     * will be triggered in an implicit {@link LexicalEditor.update}, unless
17048     * this was invoked from inside an update in which case that update context
17049     * will be re-used (as if this was a dollar function itself).
17050     * @param type - the type of command listeners to trigger.
17051     * @param payload - the data to pass as an argument to the command listeners.
17052     */
17053    dispatchCommand(type, payload) {
17054      return dispatchCommand(this, type, payload);
17055    }
17056    /**
17057     * Gets a map of all decorators in the editor.
17058     * @returns A mapping of call decorator keys to their decorated content
17059     */
17060    getDecorators() {
17061      return this._decorators;
17062    }
17063    /**
17064     *
17065     * @returns the current root element of the editor. If you want to register
17066     * an event listener, do it via {@link LexicalEditor.registerRootListener}, since
17067     * this reference may not be stable.
17068     */
17069    getRootElement() {
17070      return this._rootElement;
17071    }
17072    /**
17073     * Gets the key of the editor
17074     * @returns The editor key
17075     */
17076    getKey() {
17077      return this._key;
17078    }
17079    /**
17080     * Imperatively set the root contenteditable element that Lexical listens
17081     * for events on.
17082     */
17083    setRootElement(nextRootElement) {
17084      const prevRootElement = this._rootElement;
17085      if (nextRootElement !== prevRootElement) {
17086        const classNames = getCachedClassNameArray(this._config.theme, "root");
17087        const pendingEditorState = this._pendingEditorState || this._editorState;
17088        this._rootElement = nextRootElement;
17089        resetEditor(this, prevRootElement, nextRootElement, pendingEditorState);
17090        if (prevRootElement !== null) {
17091          if (!this._config.disableEvents) {
17092            removeRootElementEvents(prevRootElement);
17093          }
17094          if (classNames != null) {
17095            prevRootElement.classList.remove(...classNames);
17096          }
17097        }
17098        if (nextRootElement !== null) {
17099          const windowObj = getDefaultView(nextRootElement);
17100          const style = nextRootElement.style;
17101          style.userSelect = "text";
17102          style.whiteSpace = "pre-wrap";
17103          style.wordBreak = "break-word";
17104          nextRootElement.setAttribute("data-lexical-editor", "true");
17105          this._window = windowObj;
17106          this._dirtyType = FULL_RECONCILE;
17107          initMutationObserver(this);
17108          this._updateTags.add(HISTORY_MERGE_TAG);
17109          $commitPendingUpdates(this);
17110          if (!this._config.disableEvents) {
17111            addRootElementEvents(nextRootElement, this);
17112          }
17113          if (classNames != null) {
17114            nextRootElement.classList.add(...classNames);
17115          }
17116          {
17117            const nextRootElementParent = nextRootElement.parentElement;
17118            if (nextRootElementParent != null && ["flex", "inline-flex"].includes(getComputedStyle(nextRootElementParent).display)) {
17119              console.warn(`When using "display: flex" or "display: inline-flex" on an element containing content editable, Chrome may have unwanted focusing behavior when clicking outside of it. Consider wrapping the content editable within a non-flex element.`);
17120            }
17121          }
17122        } else {
17123          this._window = null;
17124          this._updateTags.add(HISTORY_MERGE_TAG);
17125          $commitPendingUpdates(this);
17126        }
17127        triggerListeners("root", this, false, nextRootElement, prevRootElement);
17128      }
17129    }
17130    /**
17131     * Gets the underlying HTMLElement associated with the LexicalNode for the given key.
17132     * @returns the HTMLElement rendered by the LexicalNode associated with the key.
17133     * @param key - the key of the LexicalNode.
17134     */
17135    getElementByKey(key) {
17136      return this._keyToDOMMap.get(key) || null;
17137    }
17138    /**
17139     * Gets the active editor state.
17140     * @returns The editor state
17141     */
17142    getEditorState() {
17143      return this._editorState;
17144    }
17145    /**
17146     * Imperatively set the EditorState. Triggers reconciliation like an update.
17147     * @param editorState - the state to set the editor
17148     * @param options - options for the update.
17149     */
17150    setEditorState(editorState, options) {
17151      if (editorState.isEmpty()) {
17152        {
17153          formatDevErrorMessage(`setEditorState: the editor state is empty. Ensure the editor state's root node never becomes empty.`);
17154        }
17155      }
17156      let writableEditorState = editorState;
17157      if (writableEditorState._readOnly) {
17158        writableEditorState = cloneEditorState(editorState);
17159        writableEditorState._selection = editorState._selection ? editorState._selection.clone() : null;
17160      }
17161      flushRootMutations(this);
17162      const pendingEditorState = this._pendingEditorState;
17163      const tags = this._updateTags;
17164      const tag = options !== void 0 ? options.tag : null;
17165      if (pendingEditorState !== null && !pendingEditorState.isEmpty()) {
17166        if (tag != null) {
17167          tags.add(tag);
17168        }
17169        $commitPendingUpdates(this);
17170      }
17171      this._pendingEditorState = writableEditorState;
17172      this._dirtyType = FULL_RECONCILE;
17173      this._dirtyElements.set("root", false);
17174      this._compositionKey = null;
17175      if (tag != null) {
17176        tags.add(tag);
17177      }
17178      if (!this._updating) {
17179        $commitPendingUpdates(this);
17180      }
17181    }
17182    /**
17183     * Parses a SerializedEditorState (usually produced by {@link EditorState.toJSON}) and returns
17184     * and EditorState object that can be, for example, passed to {@link LexicalEditor.setEditorState}. Typically,
17185     * deserialization from JSON stored in a database uses this method.
17186     * @param maybeStringifiedEditorState
17187     * @param updateFn
17188     * @returns
17189     */
17190    parseEditorState(maybeStringifiedEditorState, updateFn) {
17191      const serializedEditorState = typeof maybeStringifiedEditorState === "string" ? JSON.parse(maybeStringifiedEditorState) : maybeStringifiedEditorState;
17192      return parseEditorState(serializedEditorState, this, updateFn);
17193    }
17194    /**
17195     * Executes a read of the editor's state, with the
17196     * editor context available (useful for exporting and read-only DOM
17197     * operations). Much like update, but prevents any mutation of the
17198     * editor's state. Any pending updates will be flushed immediately before
17199     * the read.
17200     * @param callbackFn - A function that has access to read-only editor state.
17201     */
17202    read(callbackFn) {
17203      $commitPendingUpdates(this);
17204      return this.getEditorState().read(callbackFn, {
17205        editor: this
17206      });
17207    }
17208    /**
17209     * Executes an update to the editor state. The updateFn callback is the ONLY place
17210     * where Lexical editor state can be safely mutated.
17211     * @param updateFn - A function that has access to writable editor state.
17212     * @param options - A bag of options to control the behavior of the update.
17213     */
17214    update(updateFn, options) {
17215      updateEditor(this, updateFn, options);
17216    }
17217    /**
17218     * Focuses the editor by marking the existing selection as dirty, or by
17219     * creating a new selection at `defaultSelection` if one does not already
17220     * exist. If you want to force a specific selection, you should call
17221     * `root.selectStart()` or `root.selectEnd()` in an update.
17222     *
17223     * @param callbackFn - A function to run after the editor is focused.
17224     * @param options - A bag of options
17225     */
17226    focus(callbackFn, options = {}) {
17227      const rootElement = this._rootElement;
17228      if (rootElement !== null) {
17229        rootElement.setAttribute("autocapitalize", "off");
17230        updateEditorSync(this, () => {
17231          const selection = $getSelection();
17232          const root = $getRoot();
17233          if (selection !== null) {
17234            if (!selection.dirty) {
17235              $setSelection(selection.clone());
17236            }
17237          } else if (root.getChildrenSize() !== 0) {
17238            if (options.defaultSelection === "rootStart") {
17239              root.selectStart();
17240            } else {
17241              root.selectEnd();
17242            }
17243          }
17244          $addUpdateTag(FOCUS_TAG);
17245          $onUpdate(() => {
17246            rootElement.removeAttribute("autocapitalize");
17247            if (callbackFn) {
17248              callbackFn();
17249            }
17250          });
17251        });
17252        if (this._pendingEditorState === null) {
17253          rootElement.removeAttribute("autocapitalize");
17254        }
17255      }
17256    }
17257    /**
17258     * Removes focus from the editor.
17259     */
17260    blur() {
17261      const rootElement = this._rootElement;
17262      if (rootElement !== null) {
17263        rootElement.blur();
17264      }
17265      const domSelection = getDOMSelection(this._window);
17266      if (domSelection !== null) {
17267        domSelection.removeAllRanges();
17268      }
17269    }
17270    /**
17271     * Returns true if the editor is editable, false otherwise.
17272     * @returns True if the editor is editable, false otherwise.
17273     */
17274    isEditable() {
17275      return this._editable;
17276    }
17277    /**
17278     * Sets the editable property of the editor. When false, the
17279     * editor will not listen for user events on the underling contenteditable.
17280     * @param editable - the value to set the editable mode to.
17281     */
17282    setEditable(editable) {
17283      if (this._editable !== editable) {
17284        this._editable = editable;
17285        triggerListeners("editable", this, true, editable);
17286      }
17287    }
17288    /**
17289     * Returns a JSON-serializable javascript object NOT a JSON string.
17290     * You still must call JSON.stringify (or something else) to turn the
17291     * state into a string you can transfer over the wire and store in a database.
17292     *
17293     * See {@link LexicalNode.exportJSON}
17294     *
17295     * @returns A JSON-serializable javascript object
17296     */
17297    toJSON() {
17298      return {
17299        editorState: this._editorState.toJSON()
17300      };
17301    }
17302  };
17303  LexicalEditor.version = "0.44.0+dev.esm";
17304  var pendingNodeToClone = null;
17305  function setPendingNodeToClone(pendingNode) {
17306    pendingNodeToClone = pendingNode;
17307  }
17308  function getPendingNodeToClone() {
17309    const node = pendingNodeToClone;
17310    pendingNodeToClone = null;
17311    return node;
17312  }
17313  var keyCounter = 1;
17314  function resetRandomKey() {
17315    keyCounter = 1;
17316  }
17317  function generateRandomKey() {
17318    return "" + keyCounter++;
17319  }
17320  function getRegisteredNodeOrThrow(editor, nodeType) {
17321    const registeredNode = getRegisteredNode(editor, nodeType);
17322    if (registeredNode === void 0) {
17323      {
17324        formatDevErrorMessage(`registeredNode: Type ${nodeType} not found`);
17325      }
17326    }
17327    return registeredNode;
17328  }
17329  function getRegisteredNode(editor, nodeType) {
17330    return editor._nodes.get(nodeType);
17331  }
17332  var scheduleMicroTask = typeof queueMicrotask === "function" ? queueMicrotask : (fn) => {
17333    Promise.resolve().then(fn);
17334  };
17335  function $isSelectionCapturedInDecorator(node) {
17336    return $isDecoratorNode($getNearestNodeFromDOMNode(node));
17337  }
17338  function isSelectionCapturedInDecoratorInput(anchorDOM) {
17339    const activeElement = document.activeElement;
17340    if (!isHTMLElement(activeElement)) {
17341      return false;
17342    }
17343    const nodeName = activeElement.nodeName;
17344    return $isDecoratorNode($getNearestNodeFromDOMNode(anchorDOM)) && (nodeName === "INPUT" || nodeName === "TEXTAREA" || activeElement.contentEditable === "true" && getEditorPropertyFromDOMNode(activeElement) == null);
17345  }
17346  function isSelectionWithinEditor(editor, anchorDOM, focusDOM) {
17347    const rootElement = editor.getRootElement();
17348    try {
17349      return rootElement !== null && rootElement.contains(anchorDOM) && rootElement.contains(focusDOM) && // Ignore if selection is within nested editor
17350      anchorDOM !== null && !isSelectionCapturedInDecoratorInput(anchorDOM) && getNearestEditorFromDOMNode(anchorDOM) === editor;
17351    } catch (_error) {
17352      return false;
17353    }
17354  }
17355  function isLexicalEditor(editor) {
17356    return editor instanceof LexicalEditor;
17357  }
17358  function getNearestEditorFromDOMNode(node) {
17359    let currentNode = node;
17360    while (currentNode != null) {
17361      const editor = getEditorPropertyFromDOMNode(currentNode);
17362      if (isLexicalEditor(editor)) {
17363        return editor;
17364      }
17365      currentNode = getParentElement(currentNode);
17366    }
17367    return null;
17368  }
17369  function getEditorPropertyFromDOMNode(node) {
17370    return node ? node.__lexicalEditor : null;
17371  }
17372  function getTextDirection(text2) {
17373    if (RTL_REGEX.test(text2)) {
17374      return "rtl";
17375    }
17376    if (LTR_REGEX.test(text2)) {
17377      return "ltr";
17378    }
17379    return null;
17380  }
17381  function $isTokenOrTab(node) {
17382    return $isTabNode(node) || node.isToken();
17383  }
17384  function $isTokenOrSegmented(node) {
17385    return $isTokenOrTab(node) || node.isSegmented();
17386  }
17387  function isDOMTextNode(node) {
17388    return isDOMNode(node) && node.nodeType === DOM_TEXT_TYPE;
17389  }
17390  function isDOMDocumentNode(node) {
17391    return isDOMNode(node) && node.nodeType === DOM_DOCUMENT_TYPE;
17392  }
17393  function getDOMTextNode(element) {
17394    let node = element;
17395    while (node != null) {
17396      if (isDOMTextNode(node)) {
17397        return node;
17398      }
17399      node = node.firstChild;
17400    }
17401    return null;
17402  }
17403  function toggleTextFormatType(format, type, alignWithFormat) {
17404    const activeFormat = TEXT_TYPE_TO_FORMAT[type];
17405    if (alignWithFormat !== null && (format & activeFormat) === (alignWithFormat & activeFormat)) {
17406      return format;
17407    }
17408    let newFormat = format ^ activeFormat;
17409    if (type === "subscript") {
17410      newFormat &= ~TEXT_TYPE_TO_FORMAT.superscript;
17411    } else if (type === "superscript") {
17412      newFormat &= ~TEXT_TYPE_TO_FORMAT.subscript;
17413    } else if (type === "lowercase") {
17414      newFormat &= ~TEXT_TYPE_TO_FORMAT.uppercase;
17415      newFormat &= ~TEXT_TYPE_TO_FORMAT.capitalize;
17416    } else if (type === "uppercase") {
17417      newFormat &= ~TEXT_TYPE_TO_FORMAT.lowercase;
17418      newFormat &= ~TEXT_TYPE_TO_FORMAT.capitalize;
17419    } else if (type === "capitalize") {
17420      newFormat &= ~TEXT_TYPE_TO_FORMAT.lowercase;
17421      newFormat &= ~TEXT_TYPE_TO_FORMAT.uppercase;
17422    }
17423    return newFormat;
17424  }
17425  function $isLeafNode(node) {
17426    return $isTextNode(node) || $isLineBreakNode(node) || $isDecoratorNode(node);
17427  }
17428  function $setNodeKey(node, existingKey) {
17429    const pendingNode = getPendingNodeToClone();
17430    existingKey = existingKey || pendingNode && pendingNode.__key;
17431    if (existingKey != null) {
17432      {
17433        errorOnNodeKeyConstructorMismatch(node, existingKey, pendingNode);
17434      }
17435      node.__key = existingKey;
17436      return;
17437    }
17438    errorOnReadOnly();
17439    errorOnInfiniteTransforms();
17440    const editor = getActiveEditor();
17441    const editorState = getActiveEditorState();
17442    const key = generateRandomKey();
17443    editorState._nodeMap.set(key, node);
17444    if ($isElementNode(node)) {
17445      editor._dirtyElements.set(key, true);
17446    } else {
17447      editor._dirtyLeaves.add(key);
17448    }
17449    editor._cloneNotNeeded.add(key);
17450    editor._dirtyType = HAS_DIRTY_NODES;
17451    node.__key = key;
17452  }
17453  function errorOnNodeKeyConstructorMismatch(node, existingKey, pendingNode) {
17454    const editorState = internalGetActiveEditorState();
17455    if (!editorState) {
17456      return;
17457    }
17458    const existingNode = editorState._nodeMap.get(existingKey);
17459    if (pendingNode) {
17460      if (!(existingKey === pendingNode.__key)) {
17461        formatDevErrorMessage(`Lexical node with constructor ${node.constructor.name} (type ${node.getType()}) has an incorrect clone implementation, got ${String(existingKey)} for nodeKey when expecting ${pendingNode.__key}`);
17462      }
17463    }
17464    if (existingNode && existingNode.constructor !== node.constructor) {
17465      if (node.constructor.name !== existingNode.constructor.name) {
17466        {
17467          formatDevErrorMessage(`Lexical node with constructor ${node.constructor.name} attempted to re-use key from node in active editor state with constructor ${existingNode.constructor.name}. Keys must not be re-used when the type is changed.`);
17468        }
17469      } else {
17470        {
17471          formatDevErrorMessage(`Lexical node with constructor ${node.constructor.name} attempted to re-use key from node in active editor state with different constructor with the same name (possibly due to invalid Hot Module Replacement). Keys must not be re-used when the type is changed.`);
17472        }
17473      }
17474    }
17475  }
17476  function internalMarkParentElementsAsDirty(parentKey, nodeMap, dirtyElements) {
17477    let nextParentKey = parentKey;
17478    while (nextParentKey !== null) {
17479      if (dirtyElements.has(nextParentKey)) {
17480        return;
17481      }
17482      const node = nodeMap.get(nextParentKey);
17483      if (node === void 0) {
17484        break;
17485      }
17486      dirtyElements.set(nextParentKey, false);
17487      nextParentKey = node.__parent;
17488    }
17489  }
17490  function removeFromParent(node) {
17491    const oldParent = node.getParent();
17492    if (oldParent !== null) {
17493      const writableNode = node.getWritable();
17494      const writableParent = oldParent.getWritable();
17495      const prevSibling = node.getPreviousSibling();
17496      const nextSibling = node.getNextSibling();
17497      const nextSiblingKey = nextSibling !== null ? nextSibling.__key : null;
17498      const prevSiblingKey = prevSibling !== null ? prevSibling.__key : null;
17499      const writablePrevSibling = prevSibling !== null ? prevSibling.getWritable() : null;
17500      const writableNextSibling = nextSibling !== null ? nextSibling.getWritable() : null;
17501      if (prevSibling === null) {
17502        writableParent.__first = nextSiblingKey;
17503      }
17504      if (nextSibling === null) {
17505        writableParent.__last = prevSiblingKey;
17506      }
17507      if (writablePrevSibling !== null) {
17508        writablePrevSibling.__next = nextSiblingKey;
17509      }
17510      if (writableNextSibling !== null) {
17511        writableNextSibling.__prev = prevSiblingKey;
17512      }
17513      writableNode.__prev = null;
17514      writableNode.__next = null;
17515      writableNode.__parent = null;
17516      writableParent.__size--;
17517    }
17518  }
17519  function internalMarkNodeAsDirty(node) {
17520    errorOnInfiniteTransforms();
17521    if (!!$isEphemeral(node)) {
17522      formatDevErrorMessage(`internalMarkNodeAsDirty: Ephemeral nodes must not be marked as dirty (key ${node.__key} type ${node.__type})`);
17523    }
17524    const latest = node.getLatest();
17525    const parent = latest.__parent;
17526    const editorState = getActiveEditorState();
17527    const editor = getActiveEditor();
17528    const nodeMap = editorState._nodeMap;
17529    const dirtyElements = editor._dirtyElements;
17530    if (parent !== null) {
17531      internalMarkParentElementsAsDirty(parent, nodeMap, dirtyElements);
17532    }
17533    const key = latest.__key;
17534    editor._dirtyType = HAS_DIRTY_NODES;
17535    if ($isElementNode(node)) {
17536      dirtyElements.set(key, true);
17537    } else {
17538      editor._dirtyLeaves.add(key);
17539    }
17540  }
17541  function internalMarkSiblingsAsDirty(node) {
17542    const previousNode = node.getPreviousSibling();
17543    const nextNode = node.getNextSibling();
17544    if (previousNode !== null) {
17545      internalMarkNodeAsDirty(previousNode);
17546    }
17547    if (nextNode !== null) {
17548      internalMarkNodeAsDirty(nextNode);
17549    }
17550  }
17551  function $setCompositionKey(compositionKey) {
17552    errorOnReadOnly();
17553    const editor = getActiveEditor();
17554    const previousCompositionKey = editor._compositionKey;
17555    if (compositionKey !== previousCompositionKey) {
17556      editor._compositionKey = compositionKey;
17557      if (previousCompositionKey !== null) {
17558        const node = $getNodeByKey(previousCompositionKey);
17559        if (node !== null) {
17560          node.getWritable();
17561        }
17562      }
17563      if (compositionKey !== null) {
17564        const node = $getNodeByKey(compositionKey);
17565        if (node !== null) {
17566          node.getWritable();
17567        }
17568      }
17569    }
17570  }
17571  function $getCompositionKey() {
17572    if (isCurrentlyReadOnlyMode()) {
17573      return null;
17574    }
17575    const editor = getActiveEditor();
17576    return editor._compositionKey;
17577  }
17578  function $getNodeByKey(key, _editorState) {
17579    const editorState = _editorState || getActiveEditorState();
17580    const node = editorState._nodeMap.get(key);
17581    if (node === void 0) {
17582      return null;
17583    }
17584    return node;
17585  }
17586  function $getNodeFromDOMNode(dom, editorState) {
17587    const editor = getActiveEditor();
17588    const key = getNodeKeyFromDOMNode(dom, editor);
17589    if (key !== void 0) {
17590      return $getNodeByKey(key, editorState);
17591    }
17592    return null;
17593  }
17594  function setNodeKeyOnDOMNode(dom, editor, key) {
17595    const prop = `__lexicalKey_${editor._key}`;
17596    dom[prop] = key;
17597  }
17598  function getNodeKeyFromDOMNode(dom, editor) {
17599    const prop = `__lexicalKey_${editor._key}`;
17600    return dom[prop];
17601  }
17602  function $getNearestNodeFromDOMNode(startingDOM, editorState) {
17603    let dom = startingDOM;
17604    while (dom != null) {
17605      const node = $getNodeFromDOMNode(dom, editorState);
17606      if (node !== null) {
17607        return node;
17608      }
17609      dom = getParentElement(dom);
17610    }
17611    return null;
17612  }
17613  function cloneDecorators(editor) {
17614    const currentDecorators = editor._decorators;
17615    const pendingDecorators = Object.assign({}, currentDecorators);
17616    editor._pendingDecorators = pendingDecorators;
17617    return pendingDecorators;
17618  }
17619  function getEditorStateTextContent(editorState) {
17620    return editorState.read(() => $getRoot().getTextContent());
17621  }
17622  function markNodesWithTypesAsDirty(editor, types) {
17623    const cachedMap = getCachedTypeToNodeMap(editor.getEditorState());
17624    const dirtyNodeMaps = [];
17625    for (const type of types) {
17626      const nodeMap = cachedMap.get(type);
17627      if (nodeMap) {
17628        dirtyNodeMaps.push(nodeMap);
17629      }
17630    }
17631    if (dirtyNodeMaps.length === 0) {
17632      return;
17633    }
17634    editor.update(() => {
17635      for (const nodeMap of dirtyNodeMaps) {
17636        for (const nodeKey of nodeMap.keys()) {
17637          const latest = $getNodeByKey(nodeKey);
17638          if (latest) {
17639            latest.markDirty();
17640          }
17641        }
17642      }
17643    }, editor._pendingEditorState === null ? {
17644      tag: HISTORY_MERGE_TAG
17645    } : void 0);
17646  }
17647  function $getRoot() {
17648    return internalGetRoot(getActiveEditorState());
17649  }
17650  function internalGetRoot(editorState) {
17651    return editorState._nodeMap.get("root");
17652  }
17653  function $setSelection(selection) {
17654    errorOnReadOnly();
17655    const editorState = getActiveEditorState();
17656    if (selection !== null) {
17657      {
17658        if (Object.isFrozen(selection)) {
17659          {
17660            formatDevErrorMessage(`$setSelection called on frozen selection object. Ensure selection is cloned before passing in.`);
17661          }
17662        }
17663      }
17664      selection.dirty = true;
17665      selection.setCachedNodes(null);
17666    }
17667    editorState._selection = selection;
17668  }
17669  function $flushMutations() {
17670    errorOnReadOnly();
17671    const editor = getActiveEditor();
17672    flushRootMutations(editor);
17673  }
17674  function $getNodeFromDOM(dom) {
17675    const editor = getActiveEditor();
17676    const nodeKey = getNodeKeyFromDOMTree(dom, editor);
17677    if (nodeKey === null) {
17678      const rootElement = editor.getRootElement();
17679      if (dom === rootElement) {
17680        return $getNodeByKey("root");
17681      }
17682      return null;
17683    }
17684    return $getNodeByKey(nodeKey);
17685  }
17686  function getNodeKeyFromDOMTree(dom, editor) {
17687    let node = dom;
17688    while (node != null) {
17689      const key = getNodeKeyFromDOMNode(node, editor);
17690      if (key !== void 0) {
17691        return key;
17692      }
17693      node = getParentElement(node);
17694    }
17695    return null;
17696  }
17697  function doesContainSurrogatePair(str) {
17698    return /[\uD800-\uDBFF][\uDC00-\uDFFF]/g.test(str);
17699  }
17700  function getEditorsToPropagate(editor) {
17701    const editorsToPropagate = [];
17702    for (let currentEditor = editor; currentEditor !== null; currentEditor = currentEditor._parentEditor) {
17703      editorsToPropagate.push(currentEditor);
17704    }
17705    return editorsToPropagate;
17706  }
17707  function createUID() {
17708    return Math.random().toString(36).replace(/[^a-z]+/g, "").substring(0, 5);
17709  }
17710  function getAnchorTextFromDOM(anchorNode) {
17711    return isDOMTextNode(anchorNode) ? anchorNode.nodeValue : null;
17712  }
17713  function $updateSelectedTextFromDOM(isCompositionEnd, editor, data) {
17714    const domSelection = getDOMSelection(getWindow(editor));
17715    if (domSelection === null) {
17716      return;
17717    }
17718    const anchorNode = domSelection.anchorNode;
17719    let {
17720      anchorOffset,
17721      focusOffset
17722    } = domSelection;
17723    if (anchorNode !== null) {
17724      let textContent = getAnchorTextFromDOM(anchorNode);
17725      const node = $getNearestNodeFromDOMNode(anchorNode);
17726      if (textContent !== null && $isTextNode(node)) {
17727        if ((textContent === COMPOSITION_SUFFIX || textContent === COMPOSITION_START_CHAR) && data) {
17728          const offset3 = data.length;
17729          textContent = data;
17730          anchorOffset = offset3;
17731          focusOffset = offset3;
17732        }
17733        if (textContent !== null) {
17734          $updateTextNodeFromDOMContent(node, textContent, anchorOffset, focusOffset, isCompositionEnd);
17735        }
17736      }
17737    }
17738  }
17739  function $updateTextNodeFromDOMContent(textNode, textContent, anchorOffset, focusOffset, compositionEnd) {
17740    let node = textNode;
17741    if (node.isAttached() && (compositionEnd || !node.isDirty())) {
17742      const isComposing = node.isComposing();
17743      let normalizedTextContent = textContent;
17744      if (isComposing || compositionEnd) {
17745        if (textContent.endsWith(COMPOSITION_SUFFIX)) {
17746          normalizedTextContent = textContent.slice(0, -COMPOSITION_SUFFIX.length);
17747        }
17748        if (compositionEnd) {
17749          const char = COMPOSITION_START_CHAR;
17750          let index;
17751          while ((index = normalizedTextContent.indexOf(char)) !== -1) {
17752            normalizedTextContent = normalizedTextContent.slice(0, index) + normalizedTextContent.slice(index + char.length);
17753            if (anchorOffset !== null && anchorOffset > index) {
17754              anchorOffset = Math.max(index, anchorOffset - char.length);
17755            }
17756            if (focusOffset !== null && focusOffset > index) {
17757              focusOffset = Math.max(index, focusOffset - char.length);
17758            }
17759          }
17760        }
17761      }
17762      const prevTextContent = node.getTextContent();
17763      if (compositionEnd || normalizedTextContent !== prevTextContent) {
17764        if (normalizedTextContent === "") {
17765          $setCompositionKey(null);
17766          if (!IS_SAFARI && !IS_IOS && !IS_APPLE_WEBKIT) {
17767            const editor = getActiveEditor();
17768            setTimeout(() => {
17769              editor.update(() => {
17770                if (node.isAttached()) {
17771                  node.remove();
17772                }
17773              });
17774            }, 20);
17775          } else {
17776            node.remove();
17777          }
17778          return;
17779        }
17780        const parent = node.getParent();
17781        const prevSelection = $getPreviousSelection();
17782        const prevTextContentSize = node.getTextContentSize();
17783        const compositionKey = $getCompositionKey();
17784        const nodeKey = node.getKey();
17785        if (node.isToken() || compositionKey !== null && nodeKey === compositionKey && !isComposing || // Check if character was added at the start or boundaries when not insertable, and we need
17786        // to clear this input from occurring as that action wasn't permitted.
17787        $isRangeSelection(prevSelection) && (parent !== null && !parent.canInsertTextBefore() && prevSelection.anchor.offset === 0 || prevSelection.anchor.key === textNode.__key && prevSelection.anchor.offset === 0 && !node.canInsertTextBefore() && !isComposing || prevSelection.focus.key === textNode.__key && prevSelection.focus.offset === prevTextContentSize && !node.canInsertTextAfter() && !isComposing)) {
17788          node.markDirty();
17789          return;
17790        }
17791        const selection = $getSelection();
17792        if (!$isRangeSelection(selection) || anchorOffset === null || focusOffset === null) {
17793          $setTextContentWithSelection(node, normalizedTextContent, selection);
17794          return;
17795        }
17796        selection.setTextNodeRange(node, anchorOffset, node, focusOffset);
17797        if (node.isSegmented()) {
17798          const originalTextContent = node.getTextContent();
17799          const replacement = $createTextNode(originalTextContent);
17800          node.replace(replacement);
17801          node = replacement;
17802        }
17803        $setTextContentWithSelection(node, normalizedTextContent, selection);
17804      }
17805    }
17806  }
17807  function $setTextContentWithSelection(node, textContent, selection) {
17808    node.setTextContent(textContent);
17809    if ($isRangeSelection(selection)) {
17810      const key = node.getKey();
17811      for (const k2 of ["anchor", "focus"]) {
17812        const pt = selection[k2];
17813        if (pt.type === "text" && pt.key === key) {
17814          pt.offset = $getTextNodeOffset(node, pt.offset, "clamp");
17815        }
17816      }
17817    }
17818  }
17819  function $previousSiblingDoesNotAcceptText(node) {
17820    const previousSibling = node.getPreviousSibling();
17821    return ($isTextNode(previousSibling) || $isElementNode(previousSibling) && previousSibling.isInline()) && !previousSibling.canInsertTextAfter();
17822  }
17823  function $shouldInsertTextAfterOrBeforeTextNode(selection, node) {
17824    if (node.isSegmented()) {
17825      return true;
17826    }
17827    if (!selection.isCollapsed()) {
17828      return false;
17829    }
17830    const offset3 = selection.anchor.offset;
17831    const parent = node.getParentOrThrow();
17832    const isToken = $isTokenOrTab(node);
17833    if (offset3 === 0) {
17834      return !node.canInsertTextBefore() || !parent.canInsertTextBefore() && !node.isComposing() || isToken || $previousSiblingDoesNotAcceptText(node);
17835    } else if (offset3 === node.getTextContentSize()) {
17836      return !node.canInsertTextAfter() || !parent.canInsertTextAfter() && !node.isComposing() || isToken;
17837    } else {
17838      return false;
17839    }
17840  }
17841  function matchModifier(event, mask, prop) {
17842    const expected = mask[prop] || false;
17843    return expected === "any" || expected === event[prop];
17844  }
17845  function isModifierMatch(event, mask) {
17846    return matchModifier(event, mask, "altKey") && matchModifier(event, mask, "ctrlKey") && matchModifier(event, mask, "shiftKey") && matchModifier(event, mask, "metaKey");
17847  }
17848  function isExactShortcutMatch(event, expectedKey, mask) {
17849    if (!isModifierMatch(event, mask)) {
17850      return false;
17851    }
17852    if (event.key.toLowerCase() === expectedKey.toLowerCase()) {
17853      return true;
17854    }
17855    if (expectedKey.length > 1) {
17856      return false;
17857    }
17858    if (event.key.length === 1 && event.key.charCodeAt(0) <= 127) {
17859      return false;
17860    }
17861    if (event.code.startsWith("Digit") && /^\d$/.test(expectedKey)) {
17862      return event.code === `Digit${expectedKey}`;
17863    }
17864    const expectedCode = "Key" + expectedKey.toUpperCase();
17865    return event.code === expectedCode;
17866  }
17867  var CONTROL_OR_META = {
17868    ctrlKey: !IS_APPLE,
17869    metaKey: IS_APPLE
17870  };
17871  var CONTROL_OR_ALT = {
17872    altKey: IS_APPLE,
17873    ctrlKey: !IS_APPLE
17874  };
17875  function isTab(event) {
17876    return isExactShortcutMatch(event, "Tab", {
17877      shiftKey: "any"
17878    });
17879  }
17880  function isBold(event) {
17881    return isExactShortcutMatch(event, "b", CONTROL_OR_META);
17882  }
17883  function isItalic(event) {
17884    return isExactShortcutMatch(event, "i", CONTROL_OR_META);
17885  }
17886  function isUnderline(event) {
17887    return isExactShortcutMatch(event, "u", CONTROL_OR_META);
17888  }
17889  function isParagraph(event) {
17890    return isExactShortcutMatch(event, "Enter", {
17891      altKey: "any",
17892      ctrlKey: "any",
17893      metaKey: "any"
17894    });
17895  }
17896  function isLineBreak(event) {
17897    return isExactShortcutMatch(event, "Enter", {
17898      altKey: "any",
17899      ctrlKey: "any",
17900      metaKey: "any",
17901      shiftKey: true
17902    });
17903  }
17904  function isOpenLineBreak(event) {
17905    return IS_APPLE && isExactShortcutMatch(event, "o", {
17906      ctrlKey: true
17907    });
17908  }
17909  function isDeleteWordBackward(event) {
17910    return isExactShortcutMatch(event, "Backspace", CONTROL_OR_ALT);
17911  }
17912  function isDeleteWordForward(event) {
17913    return isExactShortcutMatch(event, "Delete", CONTROL_OR_ALT);
17914  }
17915  function isDeleteLineBackward(event) {
17916    return IS_APPLE && isExactShortcutMatch(event, "Backspace", {
17917      metaKey: true
17918    });
17919  }
17920  function isDeleteLineForward(event) {
17921    return IS_APPLE && (isExactShortcutMatch(event, "Delete", {
17922      metaKey: true
17923    }) || isExactShortcutMatch(event, "k", {
17924      ctrlKey: true
17925    }));
17926  }
17927  function isDeleteBackward(event) {
17928    return isExactShortcutMatch(event, "Backspace", {
17929      shiftKey: "any"
17930    }) || IS_APPLE && isExactShortcutMatch(event, "h", {
17931      ctrlKey: true
17932    });
17933  }
17934  function isDeleteForward(event) {
17935    return isExactShortcutMatch(event, "Delete", {}) || IS_APPLE && isExactShortcutMatch(event, "d", {
17936      ctrlKey: true
17937    });
17938  }
17939  function isUndo(event) {
17940    return isExactShortcutMatch(event, "z", CONTROL_OR_META);
17941  }
17942  function isRedo(event) {
17943    if (IS_APPLE) {
17944      return isExactShortcutMatch(event, "z", {
17945        metaKey: true,
17946        shiftKey: true
17947      });
17948    }
17949    return isExactShortcutMatch(event, "y", {
17950      ctrlKey: true
17951    }) || isExactShortcutMatch(event, "z", {
17952      ctrlKey: true,
17953      shiftKey: true
17954    });
17955  }
17956  function isCopy(event) {
17957    return isExactShortcutMatch(event, "c", CONTROL_OR_META);
17958  }
17959  function isCut(event) {
17960    return isExactShortcutMatch(event, "x", CONTROL_OR_META);
17961  }
17962  function isMoveBackward(event) {
17963    return isExactShortcutMatch(event, "ArrowLeft", {
17964      shiftKey: "any"
17965    });
17966  }
17967  function isMoveToStart(event) {
17968    return isExactShortcutMatch(event, "ArrowLeft", CONTROL_OR_META);
17969  }
17970  function isMoveForward(event) {
17971    return isExactShortcutMatch(event, "ArrowRight", {
17972      shiftKey: "any"
17973    });
17974  }
17975  function isMoveToEnd(event) {
17976    return isExactShortcutMatch(event, "ArrowRight", CONTROL_OR_META);
17977  }
17978  function isMoveUp(event) {
17979    return isExactShortcutMatch(event, "ArrowUp", {
17980      altKey: "any",
17981      shiftKey: "any"
17982    });
17983  }
17984  function isMoveDown(event) {
17985    return isExactShortcutMatch(event, "ArrowDown", {
17986      altKey: "any",
17987      shiftKey: "any"
17988    });
17989  }
17990  function isModifier(event) {
17991    return event.ctrlKey || event.shiftKey || event.altKey || event.metaKey;
17992  }
17993  function isSpace(event) {
17994    return event.key === " ";
17995  }
17996  function isBackspace(event) {
17997    return event.key === "Backspace";
17998  }
17999  function isEscape(event) {
18000    return event.key === "Escape";
18001  }
18002  function isDelete(event) {
18003    return event.key === "Delete";
18004  }
18005  function isSelectAll(event) {
18006    return isExactShortcutMatch(event, "a", CONTROL_OR_META);
18007  }
18008  function $selectAll(selection) {
18009    const root = $getRoot();
18010    if ($isRangeSelection(selection)) {
18011      const anchor = selection.anchor;
18012      const focus = selection.focus;
18013      const anchorNode = anchor.getNode();
18014      const topParent = anchorNode.getTopLevelElementOrThrow();
18015      const rootNode = topParent.getParentOrThrow();
18016      anchor.set(rootNode.getKey(), 0, "element");
18017      focus.set(rootNode.getKey(), rootNode.getChildrenSize(), "element");
18018      $normalizeSelection(selection);
18019      return selection;
18020    } else {
18021      const newSelection = root.select(0, root.getChildrenSize());
18022      $setSelection($normalizeSelection(newSelection));
18023      return newSelection;
18024    }
18025  }
18026  function getCachedClassNameArray(classNamesTheme, classNameThemeType) {
18027    if (classNamesTheme.__lexicalClassNameCache === void 0) {
18028      classNamesTheme.__lexicalClassNameCache = {};
18029    }
18030    const classNamesCache = classNamesTheme.__lexicalClassNameCache;
18031    const cachedClassNames = classNamesCache[classNameThemeType];
18032    if (cachedClassNames !== void 0) {
18033      return cachedClassNames;
18034    }
18035    const classNames = classNamesTheme[classNameThemeType];
18036    if (typeof classNames === "string") {
18037      const classNamesArr = normalizeClassNames(classNames);
18038      classNamesCache[classNameThemeType] = classNamesArr;
18039      return classNamesArr;
18040    }
18041    return classNames;
18042  }
18043  function setMutatedNode(mutatedNodes2, registeredNodes, mutationListeners, node, mutation) {
18044    if (mutationListeners.size === 0) {
18045      return;
18046    }
18047    const nodeType = node.__type;
18048    const nodeKey = node.__key;
18049    const registeredNode = registeredNodes.get(nodeType);
18050    if (registeredNode === void 0) {
18051      {
18052        formatDevErrorMessage(`Type ${nodeType} not in registeredNodes`);
18053      }
18054    }
18055    const klass = registeredNode.klass;
18056    let mutatedNodesByType = mutatedNodes2.get(klass);
18057    if (mutatedNodesByType === void 0) {
18058      mutatedNodesByType = /* @__PURE__ */ new Map();
18059      mutatedNodes2.set(klass, mutatedNodesByType);
18060    }
18061    const prevMutation = mutatedNodesByType.get(nodeKey);
18062    const isMove = prevMutation === "destroyed" && mutation === "created";
18063    if (prevMutation === void 0 || isMove) {
18064      mutatedNodesByType.set(nodeKey, isMove ? "updated" : mutation);
18065    }
18066  }
18067  function $nodesOfType(klass) {
18068    const klassType = klass.getType();
18069    const editorState = getActiveEditorState();
18070    if (editorState._readOnly) {
18071      const nodes2 = getCachedTypeToNodeMap(editorState).get(klassType);
18072      return nodes2 ? Array.from(nodes2.values()) : [];
18073    }
18074    const nodes = editorState._nodeMap;
18075    const nodesOfType = [];
18076    for (const [, node] of nodes) {
18077      if (node instanceof klass && node.__type === klassType && node.isAttached()) {
18078        nodesOfType.push(node);
18079      }
18080    }
18081    return nodesOfType;
18082  }
18083  function resolveElement(element, isBackward, focusOffset) {
18084    const parent = element.getParent();
18085    let offset3 = focusOffset;
18086    let block = element;
18087    if (parent !== null) {
18088      if (isBackward && focusOffset === 0) {
18089        offset3 = block.getIndexWithinParent();
18090        block = parent;
18091      } else if (!isBackward && focusOffset === block.getChildrenSize()) {
18092        offset3 = block.getIndexWithinParent() + 1;
18093        block = parent;
18094      }
18095    }
18096    return block.getChildAtIndex(isBackward ? offset3 - 1 : offset3);
18097  }
18098  function $getAdjacentNode(focus, isBackward) {
18099    const focusOffset = focus.offset;
18100    if (focus.type === "element") {
18101      const block = focus.getNode();
18102      return resolveElement(block, isBackward, focusOffset);
18103    } else {
18104      const focusNode = focus.getNode();
18105      if (isBackward && focusOffset === 0 || !isBackward && focusOffset === focusNode.getTextContentSize()) {
18106        const possibleNode = isBackward ? focusNode.getPreviousSibling() : focusNode.getNextSibling();
18107        if (possibleNode === null) {
18108          return resolveElement(focusNode.getParentOrThrow(), isBackward, focusNode.getIndexWithinParent() + (isBackward ? 0 : 1));
18109        }
18110        return possibleNode;
18111      }
18112    }
18113    return null;
18114  }
18115  function isFirefoxClipboardEvents(editor) {
18116    const event = getWindow(editor).event;
18117    const inputType = event && event.inputType;
18118    return inputType === "insertFromPaste" || inputType === "insertFromPasteAsQuotation";
18119  }
18120  function dispatchCommand(editor, command, payload) {
18121    return triggerCommandListeners(editor, command, payload, editor);
18122  }
18123  function getElementByKeyOrThrow(editor, key) {
18124    const element = editor._keyToDOMMap.get(key);
18125    if (element === void 0) {
18126      {
18127        formatDevErrorMessage(`Reconciliation: could not find DOM element for node key ${key}`);
18128      }
18129    }
18130    return element;
18131  }
18132  function getParentElement(node) {
18133    const parentElement = node.assignedSlot || node.parentElement;
18134    return isDocumentFragment(parentElement) ? parentElement.host : parentElement;
18135  }
18136  function getDOMOwnerDocument(target) {
18137    return isDOMDocumentNode(target) ? target : isHTMLElement(target) ? target.ownerDocument : null;
18138  }
18139  function scrollIntoViewIfNeeded(editor, selectionRect, rootElement) {
18140    const doc = getDOMOwnerDocument(rootElement);
18141    const defaultView = getDefaultView(doc);
18142    if (doc === null || defaultView === null) {
18143      return;
18144    }
18145    let {
18146      top: currentTop,
18147      bottom: currentBottom
18148    } = selectionRect;
18149    let targetTop = 0;
18150    let targetBottom = 0;
18151    let element = rootElement;
18152    while (element !== null) {
18153      const isBodyElement = element === doc.body;
18154      if (isBodyElement) {
18155        targetTop = 0;
18156        targetBottom = getWindow(editor).innerHeight;
18157        const computedStyle = defaultView.getComputedStyle(doc.documentElement);
18158        const scrollPaddingTop = parseFloat(computedStyle.scrollPaddingTop);
18159        const scrollPaddingBottom = parseFloat(computedStyle.scrollPaddingBottom);
18160        if (isFinite(scrollPaddingTop)) {
18161          targetTop += scrollPaddingTop;
18162        }
18163        if (isFinite(scrollPaddingBottom)) {
18164          targetBottom -= scrollPaddingBottom;
18165        }
18166      } else {
18167        const targetRect = element.getBoundingClientRect();
18168        targetTop = targetRect.top;
18169        targetBottom = targetRect.bottom;
18170      }
18171      let diff = 0;
18172      if (currentTop < targetTop) {
18173        diff = -(targetTop - currentTop);
18174      } else if (currentBottom > targetBottom) {
18175        diff = currentBottom - targetBottom;
18176      }
18177      if (diff !== 0) {
18178        if (isBodyElement) {
18179          defaultView.scrollBy(0, diff);
18180        } else {
18181          const scrollTop = element.scrollTop;
18182          element.scrollTop += diff;
18183          const yOffset = element.scrollTop - scrollTop;
18184          currentTop -= yOffset;
18185          currentBottom -= yOffset;
18186        }
18187      }
18188      if (isBodyElement) {
18189        break;
18190      }
18191      element = getParentElement(element);
18192    }
18193  }
18194  function $hasUpdateTag(tag) {
18195    const editor = getActiveEditor();
18196    return editor._updateTags.has(tag);
18197  }
18198  function $addUpdateTag(tag) {
18199    errorOnReadOnly();
18200    const editor = getActiveEditor();
18201    editor._updateTags.add(tag);
18202  }
18203  function $onUpdate(updateFn) {
18204    errorOnReadOnly();
18205    const editor = getActiveEditor();
18206    editor._deferred.push(updateFn);
18207  }
18208  function $maybeMoveChildrenSelectionToParent(parentNode) {
18209    const selection = $getSelection();
18210    if (!$isRangeSelection(selection) || !$isElementNode(parentNode)) {
18211      return selection;
18212    }
18213    const {
18214      anchor,
18215      focus
18216    } = selection;
18217    const anchorNode = anchor.getNode();
18218    const focusNode = focus.getNode();
18219    if ($hasAncestor(anchorNode, parentNode)) {
18220      anchor.set(parentNode.__key, 0, "element");
18221    }
18222    if ($hasAncestor(focusNode, parentNode)) {
18223      focus.set(parentNode.__key, 0, "element");
18224    }
18225    return selection;
18226  }
18227  function $hasAncestor(child, targetNode) {
18228    let parent = child.getParent();
18229    while (parent !== null) {
18230      if (parent.is(targetNode)) {
18231        return true;
18232      }
18233      parent = parent.getParent();
18234    }
18235    return false;
18236  }
18237  function getDefaultView(domElem) {
18238    const ownerDoc = getDOMOwnerDocument(domElem);
18239    return ownerDoc ? ownerDoc.defaultView : null;
18240  }
18241  function getWindow(editor) {
18242    const windowObj = editor._window;
18243    if (windowObj === null) {
18244      {
18245        formatDevErrorMessage(`window object not found`);
18246      }
18247    }
18248    return windowObj;
18249  }
18250  function $isInlineElementOrDecoratorNode(node) {
18251    return $isElementNode(node) && node.isInline() || $isDecoratorNode(node) && node.isInline();
18252  }
18253  function $getNearestRootOrShadowRoot(node) {
18254    let parent = node.getParentOrThrow();
18255    while (parent !== null) {
18256      if ($isRootOrShadowRoot(parent)) {
18257        return parent;
18258      }
18259      parent = parent.getParentOrThrow();
18260    }
18261    return parent;
18262  }
18263  function $isRootOrShadowRoot(node) {
18264    return $isRootNode(node) || $isElementNode(node) && node.isShadowRoot();
18265  }
18266  function $copyNode(node, skipReset = false) {
18267    const copy = node.constructor.clone(node);
18268    $setNodeKey(copy, null);
18269    copy.afterCloneFrom(node);
18270    if (!skipReset) {
18271      copy.resetOnCopyNodeFrom(node);
18272    }
18273    return copy;
18274  }
18275  function $applyNodeReplacement(node) {
18276    const editor = getActiveEditor();
18277    const nodeType = node.getType();
18278    const registeredNode = getRegisteredNode(editor, nodeType);
18279    if (!(registeredNode !== void 0)) {
18280      formatDevErrorMessage(`$applyNodeReplacement node ${node.constructor.name} with type ${nodeType} must be registered to the editor. You can do this by passing the node class via the "nodes" array in the editor config.`);
18281    }
18282    const {
18283      replace,
18284      replaceWithKlass
18285    } = registeredNode;
18286    if (replace !== null) {
18287      const replacementNode = replace(node);
18288      const replacementNodeKlass = replacementNode.constructor;
18289      if (replaceWithKlass !== null) {
18290        if (!(replacementNode instanceof replaceWithKlass)) {
18291          formatDevErrorMessage(`$applyNodeReplacement failed. Expected replacement node to be an instance of ${replaceWithKlass.name} with type ${replaceWithKlass.getType()} but returned ${replacementNodeKlass.name} with type ${replacementNodeKlass.getType()} from original node ${node.constructor.name} with type ${nodeType}`);
18292        }
18293      } else {
18294        if (!(replacementNode instanceof node.constructor && replacementNodeKlass !== node.constructor)) {
18295          formatDevErrorMessage(`$applyNodeReplacement failed. Ensure replacement node ${replacementNodeKlass.name} with type ${replacementNodeKlass.getType()} is a subclass of the original node ${node.constructor.name} with type ${nodeType}.`);
18296        }
18297      }
18298      if (!(replacementNode.__key !== node.__key)) {
18299        formatDevErrorMessage(`$applyNodeReplacement failed. Ensure that the key argument is *not* used in your replace function (from node ${node.constructor.name} with type ${nodeType} to node ${replacementNodeKlass.name} with type ${replacementNodeKlass.getType()}), Node keys must never be re-used except by the static clone method.`);
18300      }
18301      return replacementNode;
18302    }
18303    return node;
18304  }
18305  function errorOnInsertTextNodeOnRoot(node, insertNode) {
18306    const parentNode = node.getParent();
18307    if ($isRootNode(parentNode) && !$isElementNode(insertNode) && !$isDecoratorNode(insertNode)) {
18308      {
18309        formatDevErrorMessage(`Only element or decorator nodes can be inserted in to the root node`);
18310      }
18311    }
18312  }
18313  function $getNodeByKeyOrThrow(key) {
18314    const node = $getNodeByKey(key);
18315    if (node === null) {
18316      {
18317        formatDevErrorMessage(`Expected node with key ${key} to exist but it's not in the nodeMap.`);
18318      }
18319    }
18320    return node;
18321  }
18322  function createBlockCursorElement(editorConfig) {
18323    const theme2 = editorConfig.theme;
18324    const element = document.createElement("div");
18325    element.contentEditable = "false";
18326    element.setAttribute("data-lexical-cursor", "true");
18327    let blockCursorTheme = theme2.blockCursor;
18328    if (blockCursorTheme !== void 0) {
18329      if (typeof blockCursorTheme === "string") {
18330        const classNamesArr = normalizeClassNames(blockCursorTheme);
18331        blockCursorTheme = theme2.blockCursor = classNamesArr;
18332      }
18333      if (blockCursorTheme !== void 0) {
18334        element.classList.add(...blockCursorTheme);
18335      }
18336    }
18337    return element;
18338  }
18339  function needsBlockCursor(node) {
18340    return ($isDecoratorNode(node) || $isElementNode(node) && !node.canBeEmpty()) && !node.isInline();
18341  }
18342  function removeDOMBlockCursorElement(blockCursorElement, editor, rootElement) {
18343    rootElement.style.removeProperty("caret-color");
18344    editor._blockCursorElement = null;
18345    const parentElement = blockCursorElement.parentElement;
18346    if (parentElement !== null) {
18347      parentElement.removeChild(blockCursorElement);
18348    }
18349  }
18350  function updateDOMBlockCursorElement(editor, rootElement, nextSelection) {
18351    let blockCursorElement = editor._blockCursorElement;
18352    if ($isRangeSelection(nextSelection) && nextSelection.isCollapsed() && nextSelection.anchor.type === "element" && rootElement.contains(document.activeElement)) {
18353      const anchor = nextSelection.anchor;
18354      const elementNode = anchor.getNode();
18355      const offset3 = anchor.offset;
18356      const elementNodeSize = elementNode.getChildrenSize();
18357      let isBlockCursor = false;
18358      let insertBeforeElement = null;
18359      if (offset3 === elementNodeSize) {
18360        const child = elementNode.getChildAtIndex(offset3 - 1);
18361        if (needsBlockCursor(child)) {
18362          isBlockCursor = true;
18363        }
18364      } else {
18365        const child = elementNode.getChildAtIndex(offset3);
18366        if (child !== null && needsBlockCursor(child)) {
18367          const sibling = child.getPreviousSibling();
18368          if (sibling === null || needsBlockCursor(sibling)) {
18369            isBlockCursor = true;
18370            insertBeforeElement = editor.getElementByKey(child.__key);
18371          }
18372        }
18373      }
18374      if (isBlockCursor) {
18375        const elementDOM = editor.getElementByKey(elementNode.__key);
18376        if (blockCursorElement === null) {
18377          editor._blockCursorElement = blockCursorElement = createBlockCursorElement(editor._config);
18378        }
18379        rootElement.style.caretColor = "transparent";
18380        if (insertBeforeElement === null) {
18381          elementDOM.appendChild(blockCursorElement);
18382        } else {
18383          elementDOM.insertBefore(blockCursorElement, insertBeforeElement);
18384        }
18385        return;
18386      }
18387    }
18388    if (blockCursorElement !== null) {
18389      removeDOMBlockCursorElement(blockCursorElement, editor, rootElement);
18390    }
18391  }
18392  function getDOMSelection(targetWindow) {
18393    return !CAN_USE_DOM ? null : (targetWindow || window).getSelection();
18394  }
18395  function getDOMSelectionFromTarget(eventTarget) {
18396    const defaultView = getDefaultView(eventTarget);
18397    return defaultView ? defaultView.getSelection() : null;
18398  }
18399  function $splitNode(node, offset3) {
18400    let startNode = node.getChildAtIndex(offset3);
18401    if (startNode == null) {
18402      startNode = node;
18403    }
18404    if (!!$isRootOrShadowRoot(node)) {
18405      formatDevErrorMessage(`Can not call $splitNode() on root element`);
18406    }
18407    const recurse = (currentNode) => {
18408      const parent = currentNode.getParentOrThrow();
18409      const isParentRoot = $isRootOrShadowRoot(parent);
18410      const nodeToMove = currentNode === startNode && !isParentRoot ? currentNode : $copyNode(currentNode);
18411      if (isParentRoot) {
18412        if (!($isElementNode(currentNode) && $isElementNode(nodeToMove))) {
18413          formatDevErrorMessage(`Children of a root must be ElementNode`);
18414        }
18415        currentNode.insertAfter(nodeToMove);
18416        return [currentNode, nodeToMove, nodeToMove];
18417      } else {
18418        const [leftTree2, rightTree2, newParent] = recurse(parent);
18419        const nextSiblings = currentNode.getNextSiblings();
18420        newParent.append(nodeToMove, ...nextSiblings);
18421        return [leftTree2, rightTree2, nodeToMove];
18422      }
18423    };
18424    const [leftTree, rightTree] = recurse(startNode);
18425    return [leftTree, rightTree];
18426  }
18427  function isHTMLAnchorElement(x3) {
18428    return isHTMLElement(x3) && x3.tagName === "A";
18429  }
18430  function isHTMLElement(x3) {
18431    return isDOMNode(x3) && x3.nodeType === DOM_ELEMENT_TYPE;
18432  }
18433  function isDOMNode(x3) {
18434    return typeof x3 === "object" && x3 !== null && "nodeType" in x3 && typeof x3.nodeType === "number";
18435  }
18436  function isDocumentFragment(x3) {
18437    return isDOMNode(x3) && x3.nodeType === DOM_DOCUMENT_FRAGMENT_TYPE;
18438  }
18439  function isInlineDomNode(node) {
18440    const inlineNodes = new RegExp(/^(a|abbr|acronym|b|cite|code|del|em|i|ins|kbd|label|mark|output|q|ruby|s|samp|span|strong|sub|sup|time|u|tt|var|#text)$/, "i");
18441    return node.nodeName.match(inlineNodes) !== null;
18442  }
18443  function isBlockDomNode(node) {
18444    const blockNodes = new RegExp(/^(address|article|aside|blockquote|canvas|dd|div|dl|dt|fieldset|figcaption|figure|footer|form|h1|h2|h3|h4|h5|h6|header|hr|li|main|nav|noscript|ol|p|pre|section|table|td|tfoot|ul|video)$/, "i");
18445    return node.nodeName.match(blockNodes) !== null;
18446  }
18447  function INTERNAL_$isBlock(node) {
18448    if ($isDecoratorNode(node) && !node.isInline()) {
18449      return true;
18450    }
18451    if (!$isElementNode(node) || $isRootOrShadowRoot(node)) {
18452      return false;
18453    }
18454    const firstChild = node.getFirstChild();
18455    const isLeafElement = firstChild === null || $isLineBreakNode(firstChild) || $isTextNode(firstChild) || firstChild.isInline();
18456    return !node.isInline() && node.canBeEmpty() !== false && isLeafElement;
18457  }
18458  function $getEditor() {
18459    return getActiveEditor();
18460  }
18461  function $getEditorDOMRenderConfig(editor = $getEditor()) {
18462    return editor._config.dom || DEFAULT_EDITOR_DOM_CONFIG;
18463  }
18464  var cachedNodeMaps = /* @__PURE__ */ new WeakMap();
18465  var EMPTY_TYPE_TO_NODE_MAP = /* @__PURE__ */ new Map();
18466  function getCachedTypeToNodeMap(editorState) {
18467    if (!editorState._readOnly && editorState.isEmpty()) {
18468      return EMPTY_TYPE_TO_NODE_MAP;
18469    }
18470    if (!editorState._readOnly) {
18471      formatDevErrorMessage(`getCachedTypeToNodeMap called with a writable EditorState`);
18472    }
18473    let typeToNodeMap = cachedNodeMaps.get(editorState);
18474    if (!typeToNodeMap) {
18475      typeToNodeMap = computeTypeToNodeMap(editorState);
18476      cachedNodeMaps.set(editorState, typeToNodeMap);
18477    }
18478    return typeToNodeMap;
18479  }
18480  function computeTypeToNodeMap(editorState) {
18481    const typeToNodeMap = /* @__PURE__ */ new Map();
18482    for (const [nodeKey, node] of editorState._nodeMap) {
18483      const nodeType = node.__type;
18484      let nodeMap = typeToNodeMap.get(nodeType);
18485      if (!nodeMap) {
18486        nodeMap = /* @__PURE__ */ new Map();
18487        typeToNodeMap.set(nodeType, nodeMap);
18488      }
18489      nodeMap.set(nodeKey, node);
18490    }
18491    return typeToNodeMap;
18492  }
18493  function $cloneWithProperties(latestNode) {
18494    const constructor = latestNode.constructor;
18495    const mutableNode = constructor.clone(latestNode);
18496    mutableNode.afterCloneFrom(latestNode);
18497    {
18498      if (!(mutableNode.__key === latestNode.__key)) {
18499        formatDevErrorMessage(`$cloneWithProperties: ${constructor.name}.clone(node) (with type '${constructor.getType()}') did not return a node with the same key, make sure to specify node.__key as the last argument to the constructor`);
18500      }
18501      if (!(mutableNode.__parent === latestNode.__parent && mutableNode.__next === latestNode.__next && mutableNode.__prev === latestNode.__prev)) {
18502        formatDevErrorMessage(`$cloneWithProperties: ${constructor.name}.clone(node) (with type '${constructor.getType()}') overrode afterCloneFrom but did not call super.afterCloneFrom(prevNode)`);
18503      }
18504    }
18505    return mutableNode;
18506  }
18507  function $cloneWithPropertiesEphemeral(latestNode) {
18508    return $markEphemeral($cloneWithProperties(latestNode));
18509  }
18510  function setNodeIndentFromDOM(elementDom, elementNode) {
18511    const indentSize = parseInt(elementDom.style.paddingInlineStart, 10) || 0;
18512    const indent = Math.round(indentSize / 40);
18513    elementNode.setIndent(indent);
18514  }
18515  function setDOMUnmanaged(elementDom) {
18516    const el = elementDom;
18517    el.__lexicalUnmanaged = true;
18518  }
18519  function isDOMUnmanaged(elementDom) {
18520    const el = elementDom;
18521    return el.__lexicalUnmanaged === true;
18522  }
18523  function hasOwn(o2, k2) {
18524    return Object.prototype.hasOwnProperty.call(o2, k2);
18525  }
18526  function hasOwnStaticMethod(klass, k2) {
18527    return hasOwn(klass, k2) && klass[k2] !== LexicalNode[k2];
18528  }
18529  function hasOwnExportDOM(klass) {
18530    return hasOwn(klass.prototype, "exportDOM");
18531  }
18532  function isAbstractNodeClass(klass) {
18533    if (!(klass === LexicalNode || klass.prototype instanceof LexicalNode)) {
18534      let ownNodeType = "<unknown>";
18535      let version = "<unknown>";
18536      try {
18537        ownNodeType = klass.getType();
18538      } catch (_err) {
18539      }
18540      try {
18541        if (LexicalEditor.version) {
18542          version = JSON.parse(LexicalEditor.version);
18543        }
18544      } catch (_err) {
18545      }
18546      {
18547        formatDevErrorMessage(`${klass.name} (type ${ownNodeType}) does not subclass LexicalNode from the lexical package used by this editor (version ${version}). All lexical and @lexical/* packages used by an editor must have identical versions. If you suspect the version does match, then the problem may be caused by multiple copies of the same lexical module (e.g. both esm and cjs, or included directly in multiple entrypoints).`);
18548      }
18549    }
18550    return klass === DecoratorNode || klass === ElementNode || klass === LexicalNode;
18551  }
18552  function getStaticNodeConfig(klass) {
18553    const nodeConfigRecord = PROTOTYPE_CONFIG_METHOD in klass.prototype ? klass.prototype[PROTOTYPE_CONFIG_METHOD]() : void 0;
18554    const isAbstract = isAbstractNodeClass(klass);
18555    const nodeType = !isAbstract && hasOwnStaticMethod(klass, "getType") ? klass.getType() : void 0;
18556    let ownNodeConfig;
18557    let ownNodeType = nodeType;
18558    if (nodeConfigRecord) {
18559      if (nodeType) {
18560        ownNodeConfig = nodeConfigRecord[nodeType];
18561      } else {
18562        for (const [k2, v3] of Object.entries(nodeConfigRecord)) {
18563          ownNodeType = k2;
18564          ownNodeConfig = v3;
18565        }
18566      }
18567    }
18568    if (!isAbstract && ownNodeType) {
18569      if (!hasOwnStaticMethod(klass, "getType")) {
18570        klass.getType = () => ownNodeType;
18571      }
18572      if (!hasOwnStaticMethod(klass, "clone")) {
18573        if (TextNode.length === 0) {
18574          if (!(klass.length === 0)) {
18575            formatDevErrorMessage(`${klass.name} (type ${ownNodeType}) must implement a static clone method since its constructor has ${String(klass.length)} required arguments (expecting 0). Use an explicit default in the first argument of your constructor(prop: T=X, nodeKey?: NodeKey).`);
18576          }
18577        }
18578        klass.clone = (prevNode) => {
18579          setPendingNodeToClone(prevNode);
18580          return new klass();
18581        };
18582      }
18583      if (!hasOwnStaticMethod(klass, "importJSON")) {
18584        if (TextNode.length === 0) {
18585          if (!(klass.length === 0)) {
18586            formatDevErrorMessage(`${klass.name} (type ${ownNodeType}) must implement a static importJSON method since its constructor has ${String(klass.length)} required arguments (expecting 0). Use an explicit default in the first argument of your constructor(prop: T=X, nodeKey?: NodeKey).`);
18587          }
18588        }
18589        klass.importJSON = ownNodeConfig && ownNodeConfig.$importJSON || ((serializedNode) => new klass().updateFromJSON(serializedNode));
18590      }
18591      if (!hasOwnStaticMethod(klass, "importDOM") && ownNodeConfig) {
18592        const {
18593          importDOM
18594        } = ownNodeConfig;
18595        if (importDOM) {
18596          klass.importDOM = () => importDOM;
18597        }
18598      }
18599    }
18600    return {
18601      ownNodeConfig,
18602      ownNodeType
18603    };
18604  }
18605  function $create(klass) {
18606    const editor = $getEditor();
18607    errorOnReadOnly();
18608    const registeredNode = editor.resolveRegisteredNodeAfterReplacements(editor.getRegisteredNode(klass));
18609    return new registeredNode.klass();
18610  }
18611  var $findMatchingParent = (startingNode, findFn) => {
18612    let curr = startingNode;
18613    while (curr != null && !$isRootNode(curr)) {
18614      if (findFn(curr)) {
18615        return curr;
18616      }
18617      curr = curr.getParent();
18618    }
18619    return null;
18620  };
18621  function $createChildrenArray(element, nodeMap) {
18622    const children = [];
18623    let nodeKey = element.__first;
18624    while (nodeKey !== null) {
18625      const node = nodeMap === null ? $getNodeByKey(nodeKey) : nodeMap.get(nodeKey);
18626      if (node === null || node === void 0) {
18627        {
18628          formatDevErrorMessage(`$createChildrenArray: node does not exist in nodeMap`);
18629        }
18630      }
18631      children.push(nodeKey);
18632      nodeKey = node.__next;
18633    }
18634    return children;
18635  }
18636  var FLIP_DIRECTION = {
18637    next: "previous",
18638    previous: "next"
18639  };
18640  var AbstractCaret = class {
18641    origin;
18642    constructor(origin) {
18643      this.origin = origin;
18644    }
18645    [Symbol.iterator]() {
18646      return makeStepwiseIterator({
18647        hasNext: $isSiblingCaret,
18648        initial: this.getAdjacentCaret(),
18649        map: (caret) => caret,
18650        step: (caret) => caret.getAdjacentCaret()
18651      });
18652    }
18653    getAdjacentCaret() {
18654      return $getSiblingCaret(this.getNodeAtCaret(), this.direction);
18655    }
18656    getSiblingCaret() {
18657      return $getSiblingCaret(this.origin, this.direction);
18658    }
18659    remove() {
18660      const node = this.getNodeAtCaret();
18661      if (node) {
18662        node.remove();
18663      }
18664      return this;
18665    }
18666    replaceOrInsert(node, includeChildren) {
18667      const target = this.getNodeAtCaret();
18668      if (node.is(this.origin) || node.is(target)) ;
18669      else if (target === null) {
18670        this.insert(node);
18671      } else {
18672        target.replace(node, includeChildren);
18673      }
18674      return this;
18675    }
18676    splice(deleteCount, nodes, nodesDirection = "next") {
18677      const nodeIter = nodesDirection === this.direction ? nodes : Array.from(nodes).reverse();
18678      let caret = this;
18679      const parent = this.getParentAtCaret();
18680      const nodesToRemove = /* @__PURE__ */ new Map();
18681      for (let removeCaret = caret.getAdjacentCaret(); removeCaret !== null && nodesToRemove.size < deleteCount; removeCaret = removeCaret.getAdjacentCaret()) {
18682        const writableNode = removeCaret.origin.getWritable();
18683        nodesToRemove.set(writableNode.getKey(), writableNode);
18684      }
18685      for (const node of nodeIter) {
18686        if (nodesToRemove.size > 0) {
18687          const target = caret.getNodeAtCaret();
18688          if (target) {
18689            nodesToRemove.delete(target.getKey());
18690            nodesToRemove.delete(node.getKey());
18691            if (target.is(node) || caret.origin.is(node)) ;
18692            else {
18693              const nodeParent = node.getParent();
18694              if (nodeParent && nodeParent.is(parent)) {
18695                node.remove();
18696              }
18697              target.replace(node);
18698            }
18699          } else {
18700            if (!(target !== null)) {
18701              formatDevErrorMessage(`NodeCaret.splice: Underflow of expected nodesToRemove during splice (keys: ${Array.from(nodesToRemove).join(" ")})`);
18702            }
18703          }
18704        } else {
18705          caret.insert(node);
18706        }
18707        caret = $getSiblingCaret(node, this.direction);
18708      }
18709      for (const node of nodesToRemove.values()) {
18710        node.remove();
18711      }
18712      return this;
18713    }
18714  };
18715  var AbstractChildCaret = class _AbstractChildCaret extends AbstractCaret {
18716    type = "child";
18717    getLatest() {
18718      const origin = this.origin.getLatest();
18719      return origin === this.origin ? this : $getChildCaret(origin, this.direction);
18720    }
18721    /**
18722     * Get the SiblingCaret from this origin in the same direction.
18723     *
18724     * @param mode 'root' to return null at the root, 'shadowRoot' to return null at the root or any shadow root
18725     * @returns A SiblingCaret with this origin, or null if origin is a root according to mode.
18726     */
18727    getParentCaret(mode = "root") {
18728      return $getSiblingCaret($filterByMode(this.getParentAtCaret(), mode), this.direction);
18729    }
18730    getFlipped() {
18731      const dir = flipDirection(this.direction);
18732      return $getSiblingCaret(this.getNodeAtCaret(), dir) || $getChildCaret(this.origin, dir);
18733    }
18734    getParentAtCaret() {
18735      return this.origin;
18736    }
18737    getChildCaret() {
18738      return this;
18739    }
18740    isSameNodeCaret(other) {
18741      return other instanceof _AbstractChildCaret && this.direction === other.direction && this.origin.is(other.origin);
18742    }
18743    isSamePointCaret(other) {
18744      return this.isSameNodeCaret(other);
18745    }
18746  };
18747  var ChildCaretFirst = class extends AbstractChildCaret {
18748    direction = "next";
18749    getNodeAtCaret() {
18750      return this.origin.getFirstChild();
18751    }
18752    insert(node) {
18753      this.origin.splice(0, 0, [node]);
18754      return this;
18755    }
18756  };
18757  var ChildCaretLast = class extends AbstractChildCaret {
18758    direction = "previous";
18759    getNodeAtCaret() {
18760      return this.origin.getLastChild();
18761    }
18762    insert(node) {
18763      this.origin.splice(this.origin.getChildrenSize(), 0, [node]);
18764      return this;
18765    }
18766  };
18767  var MODE_PREDICATE = {
18768    root: $isRootNode,
18769    shadowRoot: $isRootOrShadowRoot
18770  };
18771  function flipDirection(direction) {
18772    return FLIP_DIRECTION[direction];
18773  }
18774  function $filterByMode(node, mode = "root") {
18775    return MODE_PREDICATE[mode](node) ? null : node;
18776  }
18777  var AbstractSiblingCaret = class _AbstractSiblingCaret extends AbstractCaret {
18778    type = "sibling";
18779    getLatest() {
18780      const origin = this.origin.getLatest();
18781      return origin === this.origin ? this : $getSiblingCaret(origin, this.direction);
18782    }
18783    getSiblingCaret() {
18784      return this;
18785    }
18786    getParentAtCaret() {
18787      return this.origin.getParent();
18788    }
18789    getChildCaret() {
18790      return $isElementNode(this.origin) ? $getChildCaret(this.origin, this.direction) : null;
18791    }
18792    getParentCaret(mode = "root") {
18793      return $getSiblingCaret($filterByMode(this.getParentAtCaret(), mode), this.direction);
18794    }
18795    getFlipped() {
18796      const dir = flipDirection(this.direction);
18797      return $getSiblingCaret(this.getNodeAtCaret(), dir) || $getChildCaret(this.origin.getParentOrThrow(), dir);
18798    }
18799    isSamePointCaret(other) {
18800      return other instanceof _AbstractSiblingCaret && this.direction === other.direction && this.origin.is(other.origin);
18801    }
18802    isSameNodeCaret(other) {
18803      return (other instanceof _AbstractSiblingCaret || other instanceof AbstractTextPointCaret) && this.direction === other.direction && this.origin.is(other.origin);
18804    }
18805  };
18806  var AbstractTextPointCaret = class _AbstractTextPointCaret extends AbstractCaret {
18807    type = "text";
18808    offset;
18809    constructor(origin, offset3) {
18810      super(origin);
18811      this.offset = offset3;
18812    }
18813    getLatest() {
18814      const origin = this.origin.getLatest();
18815      return origin === this.origin ? this : $getTextPointCaret(origin, this.direction, this.offset);
18816    }
18817    getParentAtCaret() {
18818      return this.origin.getParent();
18819    }
18820    getChildCaret() {
18821      return null;
18822    }
18823    getParentCaret(mode = "root") {
18824      return $getSiblingCaret($filterByMode(this.getParentAtCaret(), mode), this.direction);
18825    }
18826    getFlipped() {
18827      return $getTextPointCaret(this.origin, flipDirection(this.direction), this.offset);
18828    }
18829    isSamePointCaret(other) {
18830      return other instanceof _AbstractTextPointCaret && this.direction === other.direction && this.origin.is(other.origin) && this.offset === other.offset;
18831    }
18832    isSameNodeCaret(other) {
18833      return (other instanceof AbstractSiblingCaret || other instanceof _AbstractTextPointCaret) && this.direction === other.direction && this.origin.is(other.origin);
18834    }
18835    getSiblingCaret() {
18836      return $getSiblingCaret(this.origin, this.direction);
18837    }
18838  };
18839  function $isTextPointCaret(caret) {
18840    return caret instanceof AbstractTextPointCaret;
18841  }
18842  function $isNodeCaret(caret) {
18843    return caret instanceof AbstractCaret;
18844  }
18845  function $isSiblingCaret(caret) {
18846    return caret instanceof AbstractSiblingCaret;
18847  }
18848  function $isChildCaret(caret) {
18849    return caret instanceof AbstractChildCaret;
18850  }
18851  var SiblingCaretNext = class extends AbstractSiblingCaret {
18852    direction = "next";
18853    getNodeAtCaret() {
18854      return this.origin.getNextSibling();
18855    }
18856    insert(node) {
18857      this.origin.insertAfter(node);
18858      return this;
18859    }
18860  };
18861  var SiblingCaretPrevious = class extends AbstractSiblingCaret {
18862    direction = "previous";
18863    getNodeAtCaret() {
18864      return this.origin.getPreviousSibling();
18865    }
18866    insert(node) {
18867      this.origin.insertBefore(node);
18868      return this;
18869    }
18870  };
18871  var TextPointCaretNext = class extends AbstractTextPointCaret {
18872    direction = "next";
18873    getNodeAtCaret() {
18874      return this.origin.getNextSibling();
18875    }
18876    insert(node) {
18877      this.origin.insertAfter(node);
18878      return this;
18879    }
18880  };
18881  var TextPointCaretPrevious = class extends AbstractTextPointCaret {
18882    direction = "previous";
18883    getNodeAtCaret() {
18884      return this.origin.getPreviousSibling();
18885    }
18886    insert(node) {
18887      this.origin.insertBefore(node);
18888      return this;
18889    }
18890  };
18891  var TEXT_CTOR = {
18892    next: TextPointCaretNext,
18893    previous: TextPointCaretPrevious
18894  };
18895  var SIBLING_CTOR = {
18896    next: SiblingCaretNext,
18897    previous: SiblingCaretPrevious
18898  };
18899  var CHILD_CTOR = {
18900    next: ChildCaretFirst,
18901    previous: ChildCaretLast
18902  };
18903  function $getSiblingCaret(origin, direction) {
18904    return origin ? new SIBLING_CTOR[direction](origin) : null;
18905  }
18906  function $getTextPointCaret(origin, direction, offset3) {
18907    return origin ? new TEXT_CTOR[direction](origin, $getTextNodeOffset(origin, offset3)) : null;
18908  }
18909  function $getTextNodeOffset(origin, offset3, mode = "error") {
18910    const size2 = origin.getTextContentSize();
18911    let numericOffset = offset3 === "next" ? size2 : offset3 === "previous" ? 0 : offset3;
18912    if (numericOffset < 0 || numericOffset > size2) {
18913      if (!(mode === "clamp")) {
18914        formatDevErrorMessage(`$getTextNodeOffset: invalid offset ${String(offset3)} for size ${String(size2)} at key ${origin.getKey()}`);
18915      }
18916      numericOffset = numericOffset < 0 ? 0 : size2;
18917    }
18918    return numericOffset;
18919  }
18920  function $getTextPointCaretSlice(caret, distance) {
18921    return new TextPointCaretSliceImpl(caret, distance);
18922  }
18923  function $getChildCaret(origin, direction) {
18924    return $isElementNode(origin) ? new CHILD_CTOR[direction](origin) : null;
18925  }
18926  function $getChildCaretOrSelf(caret) {
18927    return caret && caret.getChildCaret() || caret;
18928  }
18929  function $getAdjacentChildCaret(caret) {
18930    return caret && $getChildCaretOrSelf(caret.getAdjacentCaret());
18931  }
18932  var CaretRangeImpl = class _CaretRangeImpl {
18933    type = "node-caret-range";
18934    direction;
18935    anchor;
18936    focus;
18937    constructor(anchor, focus, direction) {
18938      this.anchor = anchor;
18939      this.focus = focus;
18940      this.direction = direction;
18941    }
18942    getLatest() {
18943      const anchor = this.anchor.getLatest();
18944      const focus = this.focus.getLatest();
18945      return anchor === this.anchor && focus === this.focus ? this : new _CaretRangeImpl(anchor, focus, this.direction);
18946    }
18947    isCollapsed() {
18948      return this.anchor.isSamePointCaret(this.focus);
18949    }
18950    getTextSlices() {
18951      const getSlice = (k2) => {
18952        const caret = this[k2].getLatest();
18953        return $isTextPointCaret(caret) ? $getSliceFromTextPointCaret(caret, k2) : null;
18954      };
18955      const anchorSlice = getSlice("anchor");
18956      const focusSlice = getSlice("focus");
18957      if (anchorSlice && focusSlice) {
18958        const {
18959          caret: anchorCaret
18960        } = anchorSlice;
18961        const {
18962          caret: focusCaret
18963        } = focusSlice;
18964        if (anchorCaret.isSameNodeCaret(focusCaret)) {
18965          return [$getTextPointCaretSlice(anchorCaret, focusCaret.offset - anchorCaret.offset), null];
18966        }
18967      }
18968      return [anchorSlice, focusSlice];
18969    }
18970    iterNodeCarets(rootMode = "root") {
18971      const anchor = $isTextPointCaret(this.anchor) ? this.anchor.getSiblingCaret() : this.anchor.getLatest();
18972      const focus = this.focus.getLatest();
18973      const isTextFocus = $isTextPointCaret(focus);
18974      const step = (state) => state.isSameNodeCaret(focus) ? null : $getAdjacentChildCaret(state) || state.getParentCaret(rootMode);
18975      return makeStepwiseIterator({
18976        hasNext: (state) => state !== null && !(isTextFocus && focus.isSameNodeCaret(state)),
18977        initial: anchor.isSameNodeCaret(focus) ? null : step(anchor),
18978        map: (state) => state,
18979        step
18980      });
18981    }
18982    [Symbol.iterator]() {
18983      return this.iterNodeCarets("root");
18984    }
18985  };
18986  var TextPointCaretSliceImpl = class {
18987    type = "slice";
18988    caret;
18989    distance;
18990    constructor(caret, distance) {
18991      this.caret = caret;
18992      this.distance = distance;
18993    }
18994    getSliceIndices() {
18995      const {
18996        distance,
18997        caret: {
18998          offset: offset3
18999        }
19000      } = this;
19001      const offsetB = offset3 + distance;
19002      return offsetB < offset3 ? [offsetB, offset3] : [offset3, offsetB];
19003    }
19004    getTextContent() {
19005      const [startIndex, endIndex] = this.getSliceIndices();
19006      return this.caret.origin.getTextContent().slice(startIndex, endIndex);
19007    }
19008    getTextContentSize() {
19009      return Math.abs(this.distance);
19010    }
19011    removeTextSlice() {
19012      const {
19013        caret: {
19014          origin,
19015          direction
19016        }
19017      } = this;
19018      const [indexStart, indexEnd] = this.getSliceIndices();
19019      const text2 = origin.getTextContent();
19020      return $getTextPointCaret(origin.setTextContent(text2.slice(0, indexStart) + text2.slice(indexEnd)), direction, indexStart);
19021    }
19022  };
19023  function $getSliceFromTextPointCaret(caret, anchorOrFocus) {
19024    const {
19025      direction,
19026      origin
19027    } = caret;
19028    const offsetB = $getTextNodeOffset(origin, anchorOrFocus === "focus" ? flipDirection(direction) : direction);
19029    return $getTextPointCaretSlice(caret, offsetB - caret.offset);
19030  }
19031  function $isTextPointCaretSlice(caretOrSlice) {
19032    return caretOrSlice instanceof TextPointCaretSliceImpl;
19033  }
19034  function $extendCaretToRange(anchor) {
19035    return $getCaretRange(anchor, $getSiblingCaret($getRoot(), anchor.direction));
19036  }
19037  function $getCollapsedCaretRange(anchor) {
19038    return $getCaretRange(anchor, anchor);
19039  }
19040  function $getCaretRange(anchor, focus) {
19041    if (!(anchor.direction === focus.direction)) {
19042      formatDevErrorMessage(`$getCaretRange: anchor and focus must be in the same direction`);
19043    }
19044    return new CaretRangeImpl(anchor, focus, anchor.direction);
19045  }
19046  function makeStepwiseIterator(config) {
19047    const {
19048      initial,
19049      hasNext,
19050      step,
19051      map
19052    } = config;
19053    let state = initial;
19054    return {
19055      [Symbol.iterator]() {
19056        return this;
19057      },
19058      next() {
19059        if (!hasNext(state)) {
19060          return {
19061            done: true,
19062            value: void 0
19063          };
19064        }
19065        const rval = {
19066          done: false,
19067          value: map(state)
19068        };
19069        state = step(state);
19070        return rval;
19071      }
19072    };
19073  }
19074  function compareNumber(a2, b3) {
19075    return Math.sign(a2 - b3);
19076  }
19077  function $comparePointCaretNext(a2, b3) {
19078    const compare = $getCommonAncestor(a2.origin, b3.origin);
19079    if (!(compare !== null)) {
19080      formatDevErrorMessage(`$comparePointCaretNext: a (key ${a2.origin.getKey()}) and b (key ${b3.origin.getKey()}) do not have a common ancestor`);
19081    }
19082    switch (compare.type) {
19083      case "same": {
19084        const aIsText = a2.type === "text";
19085        const bIsText = b3.type === "text";
19086        return aIsText && bIsText ? compareNumber(a2.offset, b3.offset) : a2.type === b3.type ? 0 : aIsText ? -1 : bIsText ? 1 : a2.type === "child" ? -1 : 1;
19087      }
19088      case "ancestor": {
19089        return a2.type === "child" ? -1 : 1;
19090      }
19091      case "descendant": {
19092        return b3.type === "child" ? 1 : -1;
19093      }
19094      case "branch": {
19095        return $getCommonAncestorResultBranchOrder(compare);
19096      }
19097    }
19098  }
19099  function $getCommonAncestorResultBranchOrder(compare) {
19100    const {
19101      a: a2,
19102      b: b3
19103    } = compare;
19104    const aKey = a2.__key;
19105    const bKey = b3.__key;
19106    let na = a2;
19107    let nb = b3;
19108    for (; na && nb; na = na.getNextSibling(), nb = nb.getNextSibling()) {
19109      if (na.__key === bKey) {
19110        return -1;
19111      } else if (nb.__key === aKey) {
19112        return 1;
19113      }
19114    }
19115    return na === null ? 1 : -1;
19116  }
19117  function $isSameNode(reference, other) {
19118    return other.is(reference);
19119  }
19120  function $initialElementTuple(node) {
19121    return $isElementNode(node) ? [node.getLatest(), null] : [node.getParent(), node.getLatest()];
19122  }
19123  function $getCommonAncestor(a2, b3) {
19124    if (a2.is(b3)) {
19125      return {
19126        commonAncestor: a2,
19127        type: "same"
19128      };
19129    }
19130    const aMap = /* @__PURE__ */ new Map();
19131    for (let [parent, child] = $initialElementTuple(a2); parent; child = parent, parent = parent.getParent()) {
19132      aMap.set(parent, child);
19133    }
19134    for (let [parent, child] = $initialElementTuple(b3); parent; child = parent, parent = parent.getParent()) {
19135      const aChild = aMap.get(parent);
19136      if (aChild === void 0) ;
19137      else if (aChild === null) {
19138        if (!$isSameNode(a2, parent)) {
19139          formatDevErrorMessage(`$originComparison: ancestor logic error`);
19140        }
19141        return {
19142          commonAncestor: parent,
19143          type: "ancestor"
19144        };
19145      } else if (child === null) {
19146        if (!$isSameNode(b3, parent)) {
19147          formatDevErrorMessage(`$originComparison: descendant logic error`);
19148        }
19149        return {
19150          commonAncestor: parent,
19151          type: "descendant"
19152        };
19153      } else {
19154        if (!(($isElementNode(aChild) || $isSameNode(a2, aChild)) && ($isElementNode(child) || $isSameNode(b3, child)) && parent.is(aChild.getParent()) && parent.is(child.getParent()))) {
19155          formatDevErrorMessage(`$originComparison: branch logic error`);
19156        }
19157        return {
19158          a: aChild,
19159          b: child,
19160          commonAncestor: parent,
19161          type: "branch"
19162        };
19163      }
19164    }
19165    return null;
19166  }
19167  function $caretFromPoint(point, direction) {
19168    const {
19169      type,
19170      key,
19171      offset: offset3
19172    } = point;
19173    const node = $getNodeByKeyOrThrow(point.key);
19174    if (type === "text") {
19175      if (!$isTextNode(node)) {
19176        formatDevErrorMessage(`$caretFromPoint: Node with type ${node.getType()} and key ${key} that does not inherit from TextNode encountered for text point`);
19177      }
19178      return $getTextPointCaret(node, direction, offset3);
19179    }
19180    if (!$isElementNode(node)) {
19181      formatDevErrorMessage(`$caretFromPoint: Node with type ${node.getType()} and key ${key} that does not inherit from ElementNode encountered for element point`);
19182    }
19183    return $getChildCaretAtIndex(node, point.offset, direction);
19184  }
19185  function $setPointFromCaret(point, caret) {
19186    const {
19187      origin,
19188      direction
19189    } = caret;
19190    const isNext = direction === "next";
19191    if ($isTextPointCaret(caret)) {
19192      point.set(origin.getKey(), caret.offset, "text");
19193    } else if ($isSiblingCaret(caret)) {
19194      if ($isTextNode(origin)) {
19195        point.set(origin.getKey(), $getTextNodeOffset(origin, direction), "text");
19196      } else {
19197        point.set(origin.getParentOrThrow().getKey(), origin.getIndexWithinParent() + (isNext ? 1 : 0), "element");
19198      }
19199    } else {
19200      if (!($isChildCaret(caret) && $isElementNode(origin))) {
19201        formatDevErrorMessage(`$setPointFromCaret: exhaustiveness check`);
19202      }
19203      point.set(origin.getKey(), isNext ? 0 : origin.getChildrenSize(), "element");
19204    }
19205  }
19206  function $setSelectionFromCaretRange(caretRange) {
19207    const currentSelection = $getSelection();
19208    const selection = $isRangeSelection(currentSelection) ? currentSelection : $createRangeSelection();
19209    $updateRangeSelectionFromCaretRange(selection, caretRange);
19210    $setSelection(selection);
19211    return selection;
19212  }
19213  function $updateRangeSelectionFromCaretRange(selection, caretRange) {
19214    $setPointFromCaret(selection.anchor, caretRange.anchor);
19215    $setPointFromCaret(selection.focus, caretRange.focus);
19216  }
19217  function $caretRangeFromSelection(selection) {
19218    const {
19219      anchor,
19220      focus
19221    } = selection;
19222    const anchorCaret = $caretFromPoint(anchor, "next");
19223    const focusCaret = $caretFromPoint(focus, "next");
19224    const direction = $comparePointCaretNext(anchorCaret, focusCaret) <= 0 ? "next" : "previous";
19225    return $getCaretRange($getCaretInDirection(anchorCaret, direction), $getCaretInDirection(focusCaret, direction));
19226  }
19227  function $rewindSiblingCaret(caret) {
19228    const {
19229      direction,
19230      origin
19231    } = caret;
19232    const rewindOrigin = $getSiblingCaret(origin, flipDirection(direction)).getNodeAtCaret();
19233    return rewindOrigin ? $getSiblingCaret(rewindOrigin, direction) : $getChildCaret(origin.getParentOrThrow(), direction);
19234  }
19235  function $getAnchorCandidates(anchor, rootMode = "root") {
19236    const carets = [anchor];
19237    for (let parent = $isChildCaret(anchor) ? anchor.getParentCaret(rootMode) : anchor.getSiblingCaret(); parent !== null; parent = parent.getParentCaret(rootMode)) {
19238      carets.push($rewindSiblingCaret(parent));
19239    }
19240    return carets;
19241  }
19242  function $isCaretAttached(caret) {
19243    return !!caret && caret.origin.isAttached();
19244  }
19245  function $removeTextFromCaretRange(initialRange, sliceMode = "removeEmptySlices") {
19246    if (initialRange.isCollapsed()) {
19247      return initialRange;
19248    }
19249    const rootMode = "root";
19250    const nextDirection = "next";
19251    let sliceState = sliceMode;
19252    const range2 = $getCaretRangeInDirection(initialRange, nextDirection);
19253    const anchorCandidates = $getAnchorCandidates(range2.anchor, rootMode);
19254    const focusCandidates = $getAnchorCandidates(range2.focus.getFlipped(), rootMode);
19255    const seenStart = /* @__PURE__ */ new Set();
19256    const removedNodes = [];
19257    for (const caret of range2.iterNodeCarets(rootMode)) {
19258      if ($isChildCaret(caret)) {
19259        seenStart.add(caret.origin.getKey());
19260      } else if ($isSiblingCaret(caret)) {
19261        const {
19262          origin
19263        } = caret;
19264        if (!$isElementNode(origin) || seenStart.has(origin.getKey())) {
19265          removedNodes.push(origin);
19266        }
19267      }
19268    }
19269    for (const node of removedNodes) {
19270      node.remove();
19271    }
19272    for (const slice of range2.getTextSlices()) {
19273      if (!slice) {
19274        continue;
19275      }
19276      const {
19277        origin
19278      } = slice.caret;
19279      const contentSize = origin.getTextContentSize();
19280      const caretBefore = $rewindSiblingCaret($getSiblingCaret(origin, nextDirection));
19281      const mode = origin.getMode();
19282      if (Math.abs(slice.distance) === contentSize && sliceState === "removeEmptySlices" || mode === "token" && slice.distance !== 0) {
19283        caretBefore.remove();
19284      } else if (slice.distance !== 0) {
19285        sliceState = "removeEmptySlices";
19286        let nextCaret = slice.removeTextSlice();
19287        const sliceOrigin = slice.caret.origin;
19288        if (mode === "segmented") {
19289          const src = nextCaret.origin;
19290          const plainTextNode = $createTextNode(src.getTextContent()).setStyle(src.getStyle()).setFormat(src.getFormat());
19291          caretBefore.replaceOrInsert(plainTextNode);
19292          nextCaret = $getTextPointCaret(plainTextNode, nextDirection, nextCaret.offset);
19293        }
19294        if (sliceOrigin.is(anchorCandidates[0].origin)) {
19295          anchorCandidates[0] = nextCaret;
19296        }
19297        if (sliceOrigin.is(focusCandidates[0].origin)) {
19298          focusCandidates[0] = nextCaret.getFlipped();
19299        }
19300      }
19301    }
19302    let anchorCandidate;
19303    let focusCandidate;
19304    for (const candidate of anchorCandidates) {
19305      if ($isCaretAttached(candidate)) {
19306        anchorCandidate = $normalizeCaret(candidate);
19307        break;
19308      }
19309    }
19310    for (const candidate of focusCandidates) {
19311      if ($isCaretAttached(candidate)) {
19312        focusCandidate = $normalizeCaret(candidate);
19313        break;
19314      }
19315    }
19316    const mergeTargets = $getBlockMergeTargets(anchorCandidate, focusCandidate, seenStart);
19317    if (mergeTargets) {
19318      const [anchorBlock, focusBlock] = mergeTargets;
19319      $getChildCaret(anchorBlock, "previous").splice(0, focusBlock.getChildren());
19320      let parent = focusBlock.getParent();
19321      focusBlock.remove(true);
19322      while (parent && parent.isEmpty()) {
19323        const element = parent;
19324        parent = parent.getParent();
19325        element.remove(true);
19326      }
19327    }
19328    const bestCandidate = [anchorCandidate, focusCandidate, ...anchorCandidates, ...focusCandidates].find($isCaretAttached);
19329    if (bestCandidate) {
19330      const anchor = $getCaretInDirection($normalizeCaret(bestCandidate), initialRange.direction);
19331      return $getCollapsedCaretRange(anchor);
19332    }
19333    {
19334      formatDevErrorMessage(`$removeTextFromCaretRange: selection was lost, could not find a new anchor given candidates with keys: ${JSON.stringify(anchorCandidates.map((n2) => n2.origin.__key))}`);
19335    }
19336  }
19337  function $getBlockMergeTargets(anchor, focus, seenStart) {
19338    if (!anchor || !focus) {
19339      return null;
19340    }
19341    const anchorParent = anchor.getParentAtCaret();
19342    const focusParent = focus.getParentAtCaret();
19343    if (!anchorParent || !focusParent) {
19344      return null;
19345    }
19346    const anchorElements = anchorParent.getParents().reverse();
19347    anchorElements.push(anchorParent);
19348    const focusElements = focusParent.getParents().reverse();
19349    focusElements.push(focusParent);
19350    const maxLen = Math.min(anchorElements.length, focusElements.length);
19351    let commonAncestorCount;
19352    for (commonAncestorCount = 0; commonAncestorCount < maxLen && anchorElements[commonAncestorCount] === focusElements[commonAncestorCount]; commonAncestorCount++) {
19353    }
19354    const $getBlock = (arr, predicate) => {
19355      let block;
19356      for (let i2 = commonAncestorCount; i2 < arr.length; i2++) {
19357        const ancestor = arr[i2];
19358        if ($isRootOrShadowRoot(ancestor)) {
19359          return;
19360        } else if (!block && predicate(ancestor)) {
19361          block = ancestor;
19362        }
19363      }
19364      return block;
19365    };
19366    const anchorBlock = $getBlock(anchorElements, INTERNAL_$isBlock);
19367    const focusBlock = anchorBlock && $getBlock(focusElements, (node) => seenStart.has(node.getKey()) && INTERNAL_$isBlock(node));
19368    return anchorBlock && focusBlock ? [anchorBlock, focusBlock] : null;
19369  }
19370  function $getDeepestChildOrSelf(initialCaret) {
19371    let caret = initialCaret;
19372    while ($isChildCaret(caret)) {
19373      const adjacent = $getAdjacentChildCaret(caret);
19374      if (!$isChildCaret(adjacent)) {
19375        break;
19376      }
19377      caret = adjacent;
19378    }
19379    return caret;
19380  }
19381  function $normalizeCaret(initialCaret) {
19382    const caret = $getDeepestChildOrSelf(initialCaret.getLatest());
19383    const {
19384      direction
19385    } = caret;
19386    if ($isTextNode(caret.origin)) {
19387      return $isTextPointCaret(caret) ? caret : $getTextPointCaret(caret.origin, direction, direction);
19388    }
19389    const adj = caret.getAdjacentCaret();
19390    return $isSiblingCaret(adj) && $isTextNode(adj.origin) ? $getTextPointCaret(adj.origin, direction, flipDirection(direction)) : caret;
19391  }
19392  function $isExtendableTextPointCaret(caret) {
19393    return $isTextPointCaret(caret) && caret.offset !== $getTextNodeOffset(caret.origin, caret.direction);
19394  }
19395  function $getCaretInDirection(caret, direction) {
19396    return caret.direction === direction ? caret : caret.getFlipped();
19397  }
19398  function $getCaretRangeInDirection(range2, direction) {
19399    if (range2.direction === direction) {
19400      return range2;
19401    }
19402    return $getCaretRange(
19403      // focus and anchor get flipped here
19404      $getCaretInDirection(range2.focus, direction),
19405      $getCaretInDirection(range2.anchor, direction)
19406    );
19407  }
19408  function $getChildCaretAtIndex(parent, index, direction) {
19409    let caret = $getChildCaret(parent, "next");
19410    for (let i2 = 0; i2 < index; i2++) {
19411      const nextCaret = caret.getAdjacentCaret();
19412      if (nextCaret === null) {
19413        break;
19414      }
19415      caret = nextCaret;
19416    }
19417    return $getCaretInDirection(caret, direction);
19418  }
19419  function $getAdjacentSiblingOrParentSiblingCaret(startCaret, rootMode = "root") {
19420    let depthDiff = 0;
19421    let caret = startCaret;
19422    let nextCaret = $getAdjacentChildCaret(caret);
19423    while (nextCaret === null) {
19424      depthDiff--;
19425      nextCaret = caret.getParentCaret(rootMode);
19426      if (!nextCaret) {
19427        return null;
19428      }
19429      caret = nextCaret;
19430      nextCaret = $getAdjacentChildCaret(caret);
19431    }
19432    return nextCaret && [nextCaret, depthDiff];
19433  }
19434  function $getAdjacentNodes(initialCaret) {
19435    const siblings = [];
19436    for (let caret = initialCaret.getAdjacentCaret(); caret; caret = caret.getAdjacentCaret()) {
19437      siblings.push(caret.origin);
19438    }
19439    return siblings;
19440  }
19441  function $splitTextPointCaret(textPointCaret) {
19442    const {
19443      origin,
19444      offset: offset3,
19445      direction
19446    } = textPointCaret;
19447    if (offset3 === $getTextNodeOffset(origin, direction)) {
19448      return textPointCaret.getSiblingCaret();
19449    } else if (offset3 === $getTextNodeOffset(origin, flipDirection(direction))) {
19450      return $rewindSiblingCaret(textPointCaret.getSiblingCaret());
19451    }
19452    const [textNode] = origin.splitText(offset3);
19453    if (!$isTextNode(textNode)) {
19454      formatDevErrorMessage(`$splitTextPointCaret: splitText must return at least one TextNode`);
19455    }
19456    return $getCaretInDirection($getSiblingCaret(textNode, "next"), direction);
19457  }
19458  function $alwaysSplit(_node, _edge) {
19459    return true;
19460  }
19461  function $splitAtPointCaretNext(pointCaret, {
19462    $copyElementNode = $copyNode,
19463    $splitTextPointCaretNext = $splitTextPointCaret,
19464    rootMode = "shadowRoot",
19465    $shouldSplit = $alwaysSplit,
19466    removeEmptyDestination = false
19467  } = {}) {
19468    if ($isTextPointCaret(pointCaret)) {
19469      return $splitTextPointCaretNext(pointCaret);
19470    }
19471    const parentCaret = pointCaret.getParentCaret(rootMode);
19472    if (parentCaret) {
19473      const {
19474        origin
19475      } = parentCaret;
19476      if ($isChildCaret(pointCaret)) {
19477        const beforeParentCaret = $rewindSiblingCaret(parentCaret);
19478        if (removeEmptyDestination && origin.isEmpty()) {
19479          origin.remove();
19480          return beforeParentCaret;
19481        }
19482        if (!(origin.canBeEmpty() && $shouldSplit(origin, "first"))) {
19483          return beforeParentCaret;
19484        }
19485      }
19486      const siblings = $getAdjacentNodes(pointCaret);
19487      if (siblings.length > 0 || !removeEmptyDestination && origin.canBeEmpty() && $shouldSplit(origin, "last")) {
19488        parentCaret.insert($copyElementNode(origin).splice(0, 0, siblings));
19489      }
19490    }
19491    return parentCaret;
19492  }
19493  // @__NO_SIDE_EFFECTS__
19494  function defineExtension(extension) {
19495    return extension;
19496  }
19497  // @__NO_SIDE_EFFECTS__
19498  function configExtension(...args) {
19499    return args;
19500  }
19501  // @__NO_SIDE_EFFECTS__
19502  function declarePeerDependency(name, config) {
19503    return [name, config];
19504  }
19505  // @__NO_SIDE_EFFECTS__
19506  function safeCast(value) {
19507    return value;
19508  }
19509  function shallowMergeConfig(config, overrides) {
19510    if (!overrides || config === overrides) {
19511      return config;
19512    }
19513    for (const k2 in overrides) {
19514      if (config[k2] !== overrides[k2]) {
19515        return {
19516          ...config,
19517          ...overrides
19518        };
19519      }
19520    }
19521    return config;
19522  }
19523  function normalizeClassNames(...classNames) {
19524    const rval = [];
19525    for (const className of classNames) {
19526      if (className && typeof className === "string") {
19527        for (const [s2] of className.matchAll(/\S+/g)) {
19528          rval.push(s2);
19529        }
19530      }
19531    }
19532    return rval;
19533  }
19534  function addClassNamesToElement(element, ...classNames) {
19535    const classesToAdd = normalizeClassNames(...classNames);
19536    if (classesToAdd.length > 0) {
19537      element.classList.add(...classesToAdd);
19538    }
19539  }
19540  function removeClassNamesFromElement(element, ...classNames) {
19541    const classesToRemove = normalizeClassNames(...classNames);
19542    if (classesToRemove.length > 0) {
19543      element.classList.remove(...classesToRemove);
19544    }
19545  }
19546  function mergeRegister(...func) {
19547    return () => {
19548      for (let i2 = func.length - 1; i2 >= 0; i2--) {
19549        func[i2]();
19550      }
19551      func.length = 0;
19552    };
19553  }
19554
19555  
vendor: 12,287 bytes, lines 19555-19792
19555// node_modules/lexical/Lexical.mjs
19556  var mod = true ? Lexical_dev_exports : Lexical_prod_exports;
19557  var $addUpdateTag2 = mod.$addUpdateTag;
19558  var $applyNodeReplacement2 = mod.$applyNodeReplacement;
19559  var $caretFromPoint2 = mod.$caretFromPoint;
19560  var $caretRangeFromSelection2 = mod.$caretRangeFromSelection;
19561  var $cloneWithProperties2 = mod.$cloneWithProperties;
19562  var $cloneWithPropertiesEphemeral2 = mod.$cloneWithPropertiesEphemeral;
19563  var $comparePointCaretNext2 = mod.$comparePointCaretNext;
19564  var $copyNode2 = mod.$copyNode;
19565  var $create2 = mod.$create;
19566  var $createChildrenArray2 = mod.$createChildrenArray;
19567  var $createLineBreakNode2 = mod.$createLineBreakNode;
19568  var $createNodeSelection2 = mod.$createNodeSelection;
19569  var $createParagraphNode2 = mod.$createParagraphNode;
19570  var $createPoint2 = mod.$createPoint;
19571  var $createRangeSelection2 = mod.$createRangeSelection;
19572  var $createRangeSelectionFromDom2 = mod.$createRangeSelectionFromDom;
19573  var $createTabNode2 = mod.$createTabNode;
19574  var $createTextNode2 = mod.$createTextNode;
19575  var $extendCaretToRange2 = mod.$extendCaretToRange;
19576  var $findMatchingParent2 = mod.$findMatchingParent;
19577  var $getAdjacentChildCaret2 = mod.$getAdjacentChildCaret;
19578  var $getAdjacentNode2 = mod.$getAdjacentNode;
19579  var $getAdjacentSiblingOrParentSiblingCaret2 = mod.$getAdjacentSiblingOrParentSiblingCaret;
19580  var $getCaretInDirection2 = mod.$getCaretInDirection;
19581  var $getCaretRange2 = mod.$getCaretRange;
19582  var $getCaretRangeInDirection2 = mod.$getCaretRangeInDirection;
19583  var $getCharacterOffsets2 = mod.$getCharacterOffsets;
19584  var $getChildCaret2 = mod.$getChildCaret;
19585  var $getChildCaretAtIndex2 = mod.$getChildCaretAtIndex;
19586  var $getChildCaretOrSelf2 = mod.$getChildCaretOrSelf;
19587  var $getCollapsedCaretRange2 = mod.$getCollapsedCaretRange;
19588  var $getCommonAncestor2 = mod.$getCommonAncestor;
19589  var $getCommonAncestorResultBranchOrder2 = mod.$getCommonAncestorResultBranchOrder;
19590  var $getEditor2 = mod.$getEditor;
19591  var $getEditorDOMRenderConfig2 = mod.$getEditorDOMRenderConfig;
19592  var $getNearestNodeFromDOMNode2 = mod.$getNearestNodeFromDOMNode;
19593  var $getNearestRootOrShadowRoot2 = mod.$getNearestRootOrShadowRoot;
19594  var $getNodeByKey2 = mod.$getNodeByKey;
19595  var $getNodeByKeyOrThrow2 = mod.$getNodeByKeyOrThrow;
19596  var $getNodeFromDOMNode2 = mod.$getNodeFromDOMNode;
19597  var $getPreviousSelection2 = mod.$getPreviousSelection;
19598  var $getRoot2 = mod.$getRoot;
19599  var $getSelection2 = mod.$getSelection;
19600  var $getSiblingCaret2 = mod.$getSiblingCaret;
19601  var $getState2 = mod.$getState;
19602  var $getStateChange2 = mod.$getStateChange;
19603  var $getTextContent2 = mod.$getTextContent;
19604  var $getTextNodeOffset2 = mod.$getTextNodeOffset;
19605  var $getTextPointCaret2 = mod.$getTextPointCaret;
19606  var $getTextPointCaretSlice2 = mod.$getTextPointCaretSlice;
19607  var $getWritableNodeState2 = mod.$getWritableNodeState;
19608  var $hasAncestor2 = mod.$hasAncestor;
19609  var $hasUpdateTag2 = mod.$hasUpdateTag;
19610  var $insertNodes2 = mod.$insertNodes;
19611  var $isBlockElementNode2 = mod.$isBlockElementNode;
19612  var $isChildCaret2 = mod.$isChildCaret;
19613  var $isDecoratorNode2 = mod.$isDecoratorNode;
19614  var $isEditorState2 = mod.$isEditorState;
19615  var $isElementNode2 = mod.$isElementNode;
19616  var $isExtendableTextPointCaret2 = mod.$isExtendableTextPointCaret;
19617  var $isInlineElementOrDecoratorNode2 = mod.$isInlineElementOrDecoratorNode;
19618  var $isLeafNode2 = mod.$isLeafNode;
19619  var $isLexicalNode2 = mod.$isLexicalNode;
19620  var $isLineBreakNode2 = mod.$isLineBreakNode;
19621  var $isNodeCaret2 = mod.$isNodeCaret;
19622  var $isNodeSelection2 = mod.$isNodeSelection;
19623  var $isParagraphNode2 = mod.$isParagraphNode;
19624  var $isRangeSelection2 = mod.$isRangeSelection;
19625  var $isRootNode2 = mod.$isRootNode;
19626  var $isRootOrShadowRoot2 = mod.$isRootOrShadowRoot;
19627  var $isSiblingCaret2 = mod.$isSiblingCaret;
19628  var $isTabNode2 = mod.$isTabNode;
19629  var $isTextNode2 = mod.$isTextNode;
19630  var $isTextPointCaret2 = mod.$isTextPointCaret;
19631  var $isTextPointCaretSlice2 = mod.$isTextPointCaretSlice;
19632  var $isTokenOrSegmented2 = mod.$isTokenOrSegmented;
19633  var $isTokenOrTab2 = mod.$isTokenOrTab;
19634  var $nodesOfType2 = mod.$nodesOfType;
19635  var $normalizeCaret2 = mod.$normalizeCaret;
19636  var $normalizeSelection__EXPERIMENTAL = mod.$normalizeSelection__EXPERIMENTAL;
19637  var $onUpdate2 = mod.$onUpdate;
19638  var $parseSerializedNode2 = mod.$parseSerializedNode;
19639  var $removeTextFromCaretRange2 = mod.$removeTextFromCaretRange;
19640  var $rewindSiblingCaret2 = mod.$rewindSiblingCaret;
19641  var $selectAll2 = mod.$selectAll;
19642  var $setCompositionKey2 = mod.$setCompositionKey;
19643  var $setPointFromCaret2 = mod.$setPointFromCaret;
19644  var $setSelection2 = mod.$setSelection;
19645  var $setSelectionFromCaretRange2 = mod.$setSelectionFromCaretRange;
19646  var $setState2 = mod.$setState;
19647  var $splitAtPointCaretNext2 = mod.$splitAtPointCaretNext;
19648  var $splitNode2 = mod.$splitNode;
19649  var $updateRangeSelectionFromCaretRange2 = mod.$updateRangeSelectionFromCaretRange;
19650  var ArtificialNode__DO_NOT_USE2 = mod.ArtificialNode__DO_NOT_USE;
19651  var BEFORE_INPUT_COMMAND2 = mod.BEFORE_INPUT_COMMAND;
19652  var BLUR_COMMAND2 = mod.BLUR_COMMAND;
19653  var CAN_REDO_COMMAND2 = mod.CAN_REDO_COMMAND;
19654  var CAN_UNDO_COMMAND2 = mod.CAN_UNDO_COMMAND;
19655  var CLEAR_EDITOR_COMMAND2 = mod.CLEAR_EDITOR_COMMAND;
19656  var CLEAR_HISTORY_COMMAND2 = mod.CLEAR_HISTORY_COMMAND;
19657  var CLICK_COMMAND2 = mod.CLICK_COMMAND;
19658  var COLLABORATION_TAG2 = mod.COLLABORATION_TAG;
19659  var COMMAND_PRIORITY_BEFORE_CRITICAL2 = mod.COMMAND_PRIORITY_BEFORE_CRITICAL;
19660  var COMMAND_PRIORITY_BEFORE_EDITOR2 = mod.COMMAND_PRIORITY_BEFORE_EDITOR;
19661  var COMMAND_PRIORITY_BEFORE_HIGH2 = mod.COMMAND_PRIORITY_BEFORE_HIGH;
19662  var COMMAND_PRIORITY_BEFORE_LOW2 = mod.COMMAND_PRIORITY_BEFORE_LOW;
19663  var COMMAND_PRIORITY_BEFORE_NORMAL2 = mod.COMMAND_PRIORITY_BEFORE_NORMAL;
19664  var COMMAND_PRIORITY_CRITICAL2 = mod.COMMAND_PRIORITY_CRITICAL;
19665  var COMMAND_PRIORITY_EDITOR2 = mod.COMMAND_PRIORITY_EDITOR;
19666  var COMMAND_PRIORITY_HIGH2 = mod.COMMAND_PRIORITY_HIGH;
19667  var COMMAND_PRIORITY_LOW2 = mod.COMMAND_PRIORITY_LOW;
19668  var COMMAND_PRIORITY_NORMAL2 = mod.COMMAND_PRIORITY_NORMAL;
19669  var COMPOSITION_END_COMMAND2 = mod.COMPOSITION_END_COMMAND;
19670  var COMPOSITION_END_TAG2 = mod.COMPOSITION_END_TAG;
19671  var COMPOSITION_START_COMMAND2 = mod.COMPOSITION_START_COMMAND;
19672  var COMPOSITION_START_TAG2 = mod.COMPOSITION_START_TAG;
19673  var CONTROLLED_TEXT_INSERTION_COMMAND2 = mod.CONTROLLED_TEXT_INSERTION_COMMAND;
19674  var COPY_COMMAND2 = mod.COPY_COMMAND;
19675  var CUT_COMMAND2 = mod.CUT_COMMAND;
19676  var DEFAULT_EDITOR_DOM_CONFIG2 = mod.DEFAULT_EDITOR_DOM_CONFIG;
19677  var DELETE_CHARACTER_COMMAND2 = mod.DELETE_CHARACTER_COMMAND;
19678  var DELETE_LINE_COMMAND2 = mod.DELETE_LINE_COMMAND;
19679  var DELETE_WORD_COMMAND2 = mod.DELETE_WORD_COMMAND;
19680  var DRAGEND_COMMAND2 = mod.DRAGEND_COMMAND;
19681  var DRAGOVER_COMMAND2 = mod.DRAGOVER_COMMAND;
19682  var DRAGSTART_COMMAND2 = mod.DRAGSTART_COMMAND;
19683  var DROP_COMMAND2 = mod.DROP_COMMAND;
19684  var DecoratorNode2 = mod.DecoratorNode;
19685  var ElementNode2 = mod.ElementNode;
19686  var FOCUS_COMMAND2 = mod.FOCUS_COMMAND;
19687  var FORMAT_ELEMENT_COMMAND2 = mod.FORMAT_ELEMENT_COMMAND;
19688  var FORMAT_TEXT_COMMAND2 = mod.FORMAT_TEXT_COMMAND;
19689  var HISTORIC_TAG2 = mod.HISTORIC_TAG;
19690  var HISTORY_MERGE_TAG2 = mod.HISTORY_MERGE_TAG;
19691  var HISTORY_PUSH_TAG2 = mod.HISTORY_PUSH_TAG;
19692  var INDENT_CONTENT_COMMAND2 = mod.INDENT_CONTENT_COMMAND;
19693  var INPUT_COMMAND2 = mod.INPUT_COMMAND;
19694  var INSERT_LINE_BREAK_COMMAND2 = mod.INSERT_LINE_BREAK_COMMAND;
19695  var INSERT_PARAGRAPH_COMMAND2 = mod.INSERT_PARAGRAPH_COMMAND;
19696  var INSERT_TAB_COMMAND2 = mod.INSERT_TAB_COMMAND;
19697  var INTERNAL_$isBlock2 = mod.INTERNAL_$isBlock;
19698  var IS_ALL_FORMATTING2 = mod.IS_ALL_FORMATTING;
19699  var IS_BOLD2 = mod.IS_BOLD;
19700  var IS_CODE2 = mod.IS_CODE;
19701  var IS_HIGHLIGHT2 = mod.IS_HIGHLIGHT;
19702  var IS_ITALIC2 = mod.IS_ITALIC;
19703  var IS_STRIKETHROUGH2 = mod.IS_STRIKETHROUGH;
19704  var IS_SUBSCRIPT2 = mod.IS_SUBSCRIPT;
19705  var IS_SUPERSCRIPT2 = mod.IS_SUPERSCRIPT;
19706  var IS_UNDERLINE2 = mod.IS_UNDERLINE;
19707  var KEY_ARROW_DOWN_COMMAND2 = mod.KEY_ARROW_DOWN_COMMAND;
19708  var KEY_ARROW_LEFT_COMMAND2 = mod.KEY_ARROW_LEFT_COMMAND;
19709  var KEY_ARROW_RIGHT_COMMAND2 = mod.KEY_ARROW_RIGHT_COMMAND;
19710  var KEY_ARROW_UP_COMMAND2 = mod.KEY_ARROW_UP_COMMAND;
19711  var KEY_BACKSPACE_COMMAND2 = mod.KEY_BACKSPACE_COMMAND;
19712  var KEY_DELETE_COMMAND2 = mod.KEY_DELETE_COMMAND;
19713  var KEY_DOWN_COMMAND2 = mod.KEY_DOWN_COMMAND;
19714  var KEY_ENTER_COMMAND2 = mod.KEY_ENTER_COMMAND;
19715  var KEY_ESCAPE_COMMAND2 = mod.KEY_ESCAPE_COMMAND;
19716  var KEY_MODIFIER_COMMAND2 = mod.KEY_MODIFIER_COMMAND;
19717  var KEY_SPACE_COMMAND2 = mod.KEY_SPACE_COMMAND;
19718  var KEY_TAB_COMMAND2 = mod.KEY_TAB_COMMAND;
19719  var LineBreakNode2 = mod.LineBreakNode;
19720  var MOVE_TO_END2 = mod.MOVE_TO_END;
19721  var MOVE_TO_START2 = mod.MOVE_TO_START;
19722  var NODE_STATE_KEY2 = mod.NODE_STATE_KEY;
19723  var OUTDENT_CONTENT_COMMAND2 = mod.OUTDENT_CONTENT_COMMAND;
19724  var PASTE_COMMAND2 = mod.PASTE_COMMAND;
19725  var PASTE_TAG2 = mod.PASTE_TAG;
19726  var ParagraphNode2 = mod.ParagraphNode;
19727  var REDO_COMMAND2 = mod.REDO_COMMAND;
19728  var REMOVE_TEXT_COMMAND2 = mod.REMOVE_TEXT_COMMAND;
19729  var RootNode2 = mod.RootNode;
19730  var SELECTION_CHANGE_COMMAND2 = mod.SELECTION_CHANGE_COMMAND;
19731  var SELECTION_INSERT_CLIPBOARD_NODES_COMMAND2 = mod.SELECTION_INSERT_CLIPBOARD_NODES_COMMAND;
19732  var SELECT_ALL_COMMAND2 = mod.SELECT_ALL_COMMAND;
19733  var SKIP_COLLAB_TAG2 = mod.SKIP_COLLAB_TAG;
19734  var SKIP_DOM_SELECTION_TAG2 = mod.SKIP_DOM_SELECTION_TAG;
19735  var SKIP_SCROLL_INTO_VIEW_TAG2 = mod.SKIP_SCROLL_INTO_VIEW_TAG;
19736  var SKIP_SELECTION_FOCUS_TAG2 = mod.SKIP_SELECTION_FOCUS_TAG;
19737  var TEXT_TYPE_TO_FORMAT2 = mod.TEXT_TYPE_TO_FORMAT;
19738  var TabNode2 = mod.TabNode;
19739  var TextNode2 = mod.TextNode;
19740  var UNDO_COMMAND2 = mod.UNDO_COMMAND;
19741  var addClassNamesToElement2 = mod.addClassNamesToElement;
19742  var buildImportMap2 = mod.buildImportMap;
19743  var configExtension2 = mod.configExtension;
19744  var createCommand2 = mod.createCommand;
19745  var createEditor2 = mod.createEditor;
19746  var createSharedNodeState2 = mod.createSharedNodeState;
19747  var createState2 = mod.createState;
19748  var declarePeerDependency2 = mod.declarePeerDependency;
19749  var defineExtension2 = mod.defineExtension;
19750  var flipDirection2 = mod.flipDirection;
19751  var getDOMOwnerDocument2 = mod.getDOMOwnerDocument;
19752  var getDOMSelection2 = mod.getDOMSelection;
19753  var getDOMSelectionFromTarget2 = mod.getDOMSelectionFromTarget;
19754  var getDOMTextNode2 = mod.getDOMTextNode;
19755  var getEditorPropertyFromDOMNode2 = mod.getEditorPropertyFromDOMNode;
19756  var getNearestEditorFromDOMNode2 = mod.getNearestEditorFromDOMNode;
19757  var getRegisteredNode2 = mod.getRegisteredNode;
19758  var getRegisteredNodeOrThrow2 = mod.getRegisteredNodeOrThrow;
19759  var getStaticNodeConfig2 = mod.getStaticNodeConfig;
19760  var getStyleObjectFromCSS2 = mod.getStyleObjectFromCSS;
19761  var getTextDirection2 = mod.getTextDirection;
19762  var getTransformSetFromKlass2 = mod.getTransformSetFromKlass;
19763  var isBlockDomNode2 = mod.isBlockDomNode;
19764  var isCurrentlyReadOnlyMode2 = mod.isCurrentlyReadOnlyMode;
19765  var isDOMDocumentNode2 = mod.isDOMDocumentNode;
19766  var isDOMNode2 = mod.isDOMNode;
19767  var isDOMTextNode2 = mod.isDOMTextNode;
19768  var isDOMUnmanaged2 = mod.isDOMUnmanaged;
19769  var isDocumentFragment2 = mod.isDocumentFragment;
19770  var isExactShortcutMatch2 = mod.isExactShortcutMatch;
19771  var isHTMLAnchorElement2 = mod.isHTMLAnchorElement;
19772  var isHTMLElement2 = mod.isHTMLElement;
19773  var isInlineDomNode2 = mod.isInlineDomNode;
19774  var isLexicalEditor2 = mod.isLexicalEditor;
19775  var isModifierMatch2 = mod.isModifierMatch;
19776  var isSelectionCapturedInDecoratorInput2 = mod.isSelectionCapturedInDecoratorInput;
19777  var isSelectionWithinEditor2 = mod.isSelectionWithinEditor;
19778  var makeStepwiseIterator2 = mod.makeStepwiseIterator;
19779  var mergeRegister2 = mod.mergeRegister;
19780  var normalizeClassNames2 = mod.normalizeClassNames;
19781  var removeClassNamesFromElement2 = mod.removeClassNamesFromElement;
19782  var removeFromParent2 = mod.removeFromParent;
19783  var resetRandomKey2 = mod.resetRandomKey;
19784  var safeCast2 = mod.safeCast;
19785  var setDOMStyleFromCSS2 = mod.setDOMStyleFromCSS;
19786  var setDOMStyleObject2 = mod.setDOMStyleObject;
19787  var setDOMUnmanaged2 = mod.setDOMUnmanaged;
19788  var setNodeIndentFromDOM2 = mod.setNodeIndentFromDOM;
19789  var shallowMergeConfig2 = mod.shallowMergeConfig;
19790  var toggleTextFormatType2 = mod.toggleTextFormatType;
19791
19792  
vendor: 26,913 bytes, lines 19792-20507
19792// node_modules/@lexical/selection/LexicalSelection.dev.mjs
19793  function formatDevErrorMessage2(message) {
19794    throw new Error(message);
19795  }
19796  function warnOnlyOnce2(message) {
19797    {
19798      let run = false;
19799      return () => {
19800        if (!run) {
19801          console.warn(message);
19802        }
19803        run = true;
19804      };
19805    }
19806  }
19807  function getDOMTextNode3(element) {
19808    let node = element;
19809    while (node != null) {
19810      if (node.nodeType === Node.TEXT_NODE) {
19811        return node;
19812      }
19813      node = node.firstChild;
19814    }
19815    return null;
19816  }
19817  function getDOMIndexWithinParent(node) {
19818    const parent = node.parentNode;
19819    if (parent == null) {
19820      throw new Error("Should never happen");
19821    }
19822    return [parent, Array.from(parent.childNodes).indexOf(node)];
19823  }
19824  function createDOMRange(editor, anchorNode, _anchorOffset, focusNode, _focusOffset) {
19825    const anchorKey = anchorNode.getKey();
19826    const focusKey = focusNode.getKey();
19827    const range2 = document.createRange();
19828    let anchorDOM = editor.getElementByKey(anchorKey);
19829    let focusDOM = editor.getElementByKey(focusKey);
19830    let anchorOffset = _anchorOffset;
19831    let focusOffset = _focusOffset;
19832    if ($isTextNode2(anchorNode)) {
19833      anchorDOM = getDOMTextNode3(anchorDOM);
19834    }
19835    if ($isTextNode2(focusNode)) {
19836      focusDOM = getDOMTextNode3(focusDOM);
19837    }
19838    if (anchorNode === void 0 || focusNode === void 0 || anchorDOM === null || focusDOM === null) {
19839      return null;
19840    }
19841    if (anchorDOM.nodeName === "BR") {
19842      [anchorDOM, anchorOffset] = getDOMIndexWithinParent(anchorDOM);
19843    }
19844    if (focusDOM.nodeName === "BR") {
19845      [focusDOM, focusOffset] = getDOMIndexWithinParent(focusDOM);
19846    }
19847    const firstChild = anchorDOM.firstChild;
19848    if (anchorDOM === focusDOM && firstChild != null && firstChild.nodeName === "BR" && anchorOffset === 0 && focusOffset === 0) {
19849      focusOffset = 1;
19850    }
19851    try {
19852      range2.setStart(anchorDOM, anchorOffset);
19853      range2.setEnd(focusDOM, focusOffset);
19854    } catch (_e2) {
19855      return null;
19856    }
19857    if (range2.collapsed && (anchorOffset !== focusOffset || anchorKey !== focusKey)) {
19858      range2.setStart(focusDOM, focusOffset);
19859      range2.setEnd(anchorDOM, anchorOffset);
19860    }
19861    return range2;
19862  }
19863  function createRectsFromDOMRange(editor, range2) {
19864    const rootElement = editor.getRootElement();
19865    if (rootElement === null) {
19866      return [];
19867    }
19868    const rootRect = rootElement.getBoundingClientRect();
19869    const computedStyle = getComputedStyle(rootElement);
19870    const rootPadding = parseFloat(computedStyle.paddingLeft) + parseFloat(computedStyle.paddingRight);
19871    const selectionRects = Array.from(range2.getClientRects());
19872    let selectionRectsLength = selectionRects.length;
19873    selectionRects.sort((a2, b3) => {
19874      const top = a2.top - b3.top;
19875      if (Math.abs(top) <= 3) {
19876        return a2.left - b3.left;
19877      }
19878      return top;
19879    });
19880    let prevRect;
19881    for (let i2 = 0; i2 < selectionRectsLength; i2++) {
19882      const selectionRect = selectionRects[i2];
19883      const isOverlappingRect = prevRect && prevRect.top <= selectionRect.top && prevRect.top + prevRect.height > selectionRect.top && prevRect.left + prevRect.width > selectionRect.left;
19884      const selectionSpansElement = selectionRect.width + rootPadding === rootRect.width;
19885      if (isOverlappingRect || selectionSpansElement) {
19886        selectionRects.splice(i2--, 1);
19887        selectionRectsLength--;
19888        continue;
19889      }
19890      prevRect = selectionRect;
19891    }
19892    return selectionRects;
19893  }
19894  function getCSSFromStyleObject(styles) {
19895    let css = "";
19896    for (const style in styles) {
19897      if (style) {
19898        css += `${style}: ${styles[style]};`;
19899      }
19900    }
19901    return css;
19902  }
19903  function $getComputedStyleForElement(element) {
19904    const editor = $getEditor2();
19905    const domElement = editor.getElementByKey(element.getKey());
19906    if (domElement === null) {
19907      return null;
19908    }
19909    const view = domElement.ownerDocument.defaultView;
19910    if (view === null) {
19911      return null;
19912    }
19913    return view.getComputedStyle(domElement);
19914  }
19915  function $getComputedStyleForParent(node) {
19916    const parent = $isRootNode2(node) ? node : node.getParentOrThrow();
19917    return $getComputedStyleForElement(parent);
19918  }
19919  function $isParentRTL(node) {
19920    const styles = $getComputedStyleForParent(node);
19921    return styles !== null && styles.direction === "rtl";
19922  }
19923  function $sliceSelectedTextNodeContent(selection, textNode, mutates = "self") {
19924    const anchorAndFocus = selection.getStartEndPoints();
19925    if (textNode.isSelected(selection) && !$isTokenOrSegmented2(textNode) && anchorAndFocus !== null) {
19926      const [anchor, focus] = anchorAndFocus;
19927      const isBackward = selection.isBackward();
19928      const anchorNode = anchor.getNode();
19929      const focusNode = focus.getNode();
19930      const isAnchor = textNode.is(anchorNode);
19931      const isFocus = textNode.is(focusNode);
19932      if (isAnchor || isFocus) {
19933        const [anchorOffset, focusOffset] = $getCharacterOffsets2(selection);
19934        const isSame = anchorNode.is(focusNode);
19935        const isFirst = textNode.is(isBackward ? focusNode : anchorNode);
19936        const isLast = textNode.is(isBackward ? anchorNode : focusNode);
19937        let startOffset = 0;
19938        let endOffset = void 0;
19939        if (isSame) {
19940          startOffset = anchorOffset > focusOffset ? focusOffset : anchorOffset;
19941          endOffset = anchorOffset > focusOffset ? anchorOffset : focusOffset;
19942        } else if (isFirst) {
19943          const offset3 = isBackward ? focusOffset : anchorOffset;
19944          startOffset = offset3;
19945          endOffset = void 0;
19946        } else if (isLast) {
19947          const offset3 = isBackward ? anchorOffset : focusOffset;
19948          startOffset = 0;
19949          endOffset = offset3;
19950        }
19951        const text2 = textNode.__text.slice(startOffset, endOffset);
19952        if (text2 !== textNode.__text) {
19953          if (mutates === "clone") {
19954            textNode = $cloneWithPropertiesEphemeral2(textNode);
19955          }
19956          textNode.__text = text2;
19957        }
19958      }
19959    }
19960    return textNode;
19961  }
19962  function $isAtNodeEnd(point) {
19963    if (point.type === "text") {
19964      return point.offset === point.getNode().getTextContentSize();
19965    }
19966    const node = point.getNode();
19967    if (!$isElementNode2(node)) {
19968      formatDevErrorMessage2(`isAtNodeEnd: node must be a TextNode or ElementNode`);
19969    }
19970    return point.offset === node.getChildrenSize();
19971  }
19972  function $trimTextContentFromAnchor(editor, anchor, delCount) {
19973    let currentNode = anchor.getNode();
19974    let remaining = delCount;
19975    if ($isElementNode2(currentNode)) {
19976      const descendantNode = currentNode.getDescendantByIndex(anchor.offset);
19977      if (descendantNode !== null) {
19978        currentNode = descendantNode;
19979      }
19980    }
19981    while (remaining > 0 && currentNode !== null) {
19982      if ($isElementNode2(currentNode)) {
19983        const lastDescendant = currentNode.getLastDescendant();
19984        if (lastDescendant !== null) {
19985          currentNode = lastDescendant;
19986        }
19987      }
19988      let nextNode = currentNode.getPreviousSibling();
19989      let additionalElementWhitespace = 0;
19990      if (nextNode === null) {
19991        let parent = currentNode.getParentOrThrow();
19992        let parentSibling = parent.getPreviousSibling();
19993        while (parentSibling === null) {
19994          parent = parent.getParent();
19995          if (parent === null) {
19996            nextNode = null;
19997            break;
19998          }
19999          parentSibling = parent.getPreviousSibling();
20000        }
20001        if (parent !== null) {
20002          additionalElementWhitespace = parent.isInline() ? 0 : 2;
20003          nextNode = parentSibling;
20004        }
20005      }
20006      let text2 = currentNode.getTextContent();
20007      if (text2 === "" && $isElementNode2(currentNode) && !currentNode.isInline()) {
20008        text2 = "\n\n";
20009      }
20010      const currentNodeSize = text2.length;
20011      if (!$isTextNode2(currentNode) || remaining >= currentNodeSize) {
20012        const parent = currentNode.getParent();
20013        currentNode.remove();
20014        if (parent != null && parent.getChildrenSize() === 0 && !$isRootNode2(parent)) {
20015          parent.remove();
20016        }
20017        remaining -= currentNodeSize + additionalElementWhitespace;
20018        currentNode = nextNode;
20019      } else {
20020        const key = currentNode.getKey();
20021        const prevTextContent = editor.getEditorState().read(() => {
20022          const prevNode = $getNodeByKey2(key);
20023          if ($isTextNode2(prevNode) && prevNode.isSimpleText()) {
20024            return prevNode.getTextContent();
20025          }
20026          return null;
20027        });
20028        const offset3 = currentNodeSize - remaining;
20029        const slicedText = text2.slice(0, offset3);
20030        if (prevTextContent !== null && prevTextContent !== text2) {
20031          const prevSelection = $getPreviousSelection2();
20032          let target = currentNode;
20033          if (!currentNode.isSimpleText()) {
20034            const textNode = $createTextNode2(prevTextContent);
20035            currentNode.replace(textNode);
20036            target = textNode;
20037          } else {
20038            currentNode.setTextContent(prevTextContent);
20039          }
20040          if ($isRangeSelection2(prevSelection) && prevSelection.isCollapsed()) {
20041            const prevOffset = prevSelection.anchor.offset;
20042            target.select(prevOffset, prevOffset);
20043          }
20044        } else if (currentNode.isSimpleText()) {
20045          const isSelected = anchor.key === key;
20046          let anchorOffset = anchor.offset;
20047          if (anchorOffset < remaining) {
20048            anchorOffset = currentNodeSize;
20049          }
20050          const splitStart = isSelected ? anchorOffset - remaining : 0;
20051          const splitEnd = isSelected ? anchorOffset : offset3;
20052          if (isSelected && splitStart === 0) {
20053            const [excessNode] = currentNode.splitText(splitStart, splitEnd);
20054            excessNode.remove();
20055          } else {
20056            const [, excessNode] = currentNode.splitText(splitStart, splitEnd);
20057            excessNode.remove();
20058          }
20059        } else {
20060          const textNode = $createTextNode2(slicedText);
20061          currentNode.replace(textNode);
20062        }
20063        remaining = 0;
20064      }
20065    }
20066  }
20067  var $addNodeStyle = warnOnlyOnce2("$addNodeStyle is a deprecated no-op and calls should be removed");
20068  function $patchStyle(target, patch2) {
20069    if (!($isRangeSelection2(target) ? target.isCollapsed() : $isTextNode2(target) || $isElementNode2(target))) {
20070      formatDevErrorMessage2(`$patchStyle must only be called with a TextNode, ElementNode, or collapsed RangeSelection`);
20071    }
20072    const prevStyles = getStyleObjectFromCSS2($isRangeSelection2(target) ? target.style : $isTextNode2(target) ? target.getStyle() : target.getTextStyle());
20073    const newStyles = Object.entries(patch2).reduce((styles, [key, value]) => {
20074      if (typeof value === "function") {
20075        styles[key] = value(prevStyles[key], target);
20076      } else if (value === null) {
20077        delete styles[key];
20078      } else {
20079        styles[key] = value;
20080      }
20081      return styles;
20082    }, {
20083      ...prevStyles
20084    });
20085    const newCSSText = getCSSFromStyleObject(newStyles);
20086    if ($isRangeSelection2(target) || $isTextNode2(target)) {
20087      target.setStyle(newCSSText);
20088    } else {
20089      target.setTextStyle(newCSSText);
20090    }
20091  }
20092  function $patchStyleText(selection, patch2) {
20093    if ($isRangeSelection2(selection) && selection.isCollapsed()) {
20094      $patchStyle(selection, patch2);
20095      const emptyNode = selection.anchor.getNode();
20096      if ($isElementNode2(emptyNode) && emptyNode.isEmpty()) {
20097        $patchStyle(emptyNode, patch2);
20098      }
20099    }
20100    $forEachSelectedTextNode((textNode) => {
20101      $patchStyle(textNode, patch2);
20102    });
20103    const nodes = selection.getNodes();
20104    if (nodes.length > 0) {
20105      const patchedElementKeys = /* @__PURE__ */ new Set();
20106      for (const node of nodes) {
20107        if (!$isElementNode2(node) || !node.canBeEmpty() || node.getChildrenSize() !== 0) {
20108          continue;
20109        }
20110        const key = node.getKey();
20111        if (patchedElementKeys.has(key)) {
20112          continue;
20113        }
20114        patchedElementKeys.add(key);
20115        $patchStyle(node, patch2);
20116      }
20117    }
20118  }
20119  function $forEachSelectedTextNode(fn) {
20120    const selection = $getSelection2();
20121    if (!selection) {
20122      return;
20123    }
20124    const slicedTextNodes = /* @__PURE__ */ new Map();
20125    const getSliceIndices = (node) => slicedTextNodes.get(node.getKey()) || [0, node.getTextContentSize()];
20126    if ($isRangeSelection2(selection)) {
20127      for (const slice of $caretRangeFromSelection2(selection).getTextSlices()) {
20128        if (slice) {
20129          slicedTextNodes.set(slice.caret.origin.getKey(), slice.getSliceIndices());
20130        }
20131      }
20132    }
20133    const selectedNodes = selection.getNodes();
20134    for (const selectedNode of selectedNodes) {
20135      if (!($isTextNode2(selectedNode) && selectedNode.canHaveFormat())) {
20136        continue;
20137      }
20138      const [startOffset, endOffset] = getSliceIndices(selectedNode);
20139      if (endOffset === startOffset) {
20140        continue;
20141      }
20142      if ($isTokenOrSegmented2(selectedNode) || startOffset === 0 && endOffset === selectedNode.getTextContentSize()) {
20143        fn(selectedNode);
20144      } else {
20145        const splitNodes = selectedNode.splitText(startOffset, endOffset);
20146        const replacement = splitNodes[startOffset === 0 ? 0 : 1];
20147        fn(replacement);
20148      }
20149    }
20150    if ($isRangeSelection2(selection) && selection.anchor.type === "text" && selection.focus.type === "text" && selection.anchor.key === selection.focus.key) {
20151      $ensureForwardRangeSelection(selection);
20152    }
20153  }
20154  function $ensureForwardRangeSelection(selection) {
20155    if (selection.isBackward()) {
20156      const {
20157        anchor,
20158        focus
20159      } = selection;
20160      const {
20161        key,
20162        offset: offset3,
20163        type
20164      } = anchor;
20165      anchor.set(focus.key, focus.offset, focus.type);
20166      focus.set(key, offset3, type);
20167    }
20168  }
20169  function $copyBlockFormatIndent(srcNode, destNode) {
20170    const format = srcNode.getFormatType();
20171    const indent = srcNode.getIndent();
20172    if (format !== destNode.getFormatType()) {
20173      destNode.setFormat(format);
20174    }
20175    if (indent !== destNode.getIndent()) {
20176      destNode.setIndent(indent);
20177    }
20178  }
20179  function $setBlocksType(selection, $createElement, $afterCreateElement = $copyBlockFormatIndent) {
20180    if (selection === null) {
20181      return;
20182    }
20183    const anchorAndFocus = selection.getStartEndPoints();
20184    const blockMap = /* @__PURE__ */ new Map();
20185    let newSelection = null;
20186    if (anchorAndFocus) {
20187      const [anchor, focus] = anchorAndFocus;
20188      newSelection = $createRangeSelection2();
20189      newSelection.anchor.set(anchor.key, anchor.offset, anchor.type);
20190      newSelection.focus.set(focus.key, focus.offset, focus.type);
20191      const anchorBlock = $findMatchingParent2(anchor.getNode(), INTERNAL_$isBlock2);
20192      const focusBlock = $findMatchingParent2(focus.getNode(), INTERNAL_$isBlock2);
20193      if ($isElementNode2(anchorBlock)) {
20194        blockMap.set(anchorBlock.getKey(), anchorBlock);
20195      }
20196      if ($isElementNode2(focusBlock)) {
20197        blockMap.set(focusBlock.getKey(), focusBlock);
20198      }
20199    }
20200    for (const node of selection.getNodes()) {
20201      if ($isElementNode2(node) && INTERNAL_$isBlock2(node)) {
20202        blockMap.set(node.getKey(), node);
20203      } else if (anchorAndFocus === null) {
20204        const ancestorBlock = $findMatchingParent2(node, INTERNAL_$isBlock2);
20205        if ($isElementNode2(ancestorBlock)) {
20206          blockMap.set(ancestorBlock.getKey(), ancestorBlock);
20207        }
20208      }
20209    }
20210    for (const [key, prevNode] of blockMap) {
20211      const element = $createElement();
20212      $afterCreateElement(prevNode, element);
20213      prevNode.replace(element, true);
20214      if (newSelection) {
20215        if (key === newSelection.anchor.key) {
20216          newSelection.anchor.set(element.getKey(), newSelection.anchor.offset, newSelection.anchor.type);
20217        }
20218        if (key === newSelection.focus.key) {
20219          newSelection.focus.set(element.getKey(), newSelection.focus.offset, newSelection.focus.type);
20220        }
20221      }
20222    }
20223    if (newSelection && selection.is($getSelection2())) {
20224      $setSelection2(newSelection);
20225    }
20226  }
20227  function isPointAttached(point) {
20228    return point.getNode().isAttached();
20229  }
20230  function $removeParentEmptyElements(startingNode) {
20231    let node = startingNode;
20232    while (node !== null && !$isRootOrShadowRoot2(node)) {
20233      const latest = node.getLatest();
20234      const parentNode = node.getParent();
20235      if (latest.getChildrenSize() === 0) {
20236        node.remove(true);
20237      }
20238      node = parentNode;
20239    }
20240  }
20241  function $wrapNodes(selection, createElement2, wrappingElement = null) {
20242    const anchorAndFocus = selection.getStartEndPoints();
20243    const anchor = anchorAndFocus ? anchorAndFocus[0] : null;
20244    const nodes = selection.getNodes();
20245    const nodesLength = nodes.length;
20246    if (anchor !== null && (nodesLength === 0 || nodesLength === 1 && anchor.type === "element" && anchor.getNode().getChildrenSize() === 0)) {
20247      const target = anchor.type === "text" ? anchor.getNode().getParentOrThrow() : anchor.getNode();
20248      const children = target.getChildren();
20249      let element = createElement2();
20250      element.setFormat(target.getFormatType());
20251      element.setIndent(target.getIndent());
20252      children.forEach((child) => element.append(child));
20253      if (wrappingElement) {
20254        element = wrappingElement.append(element);
20255      }
20256      target.replace(element);
20257      return;
20258    }
20259    let topLevelNode = null;
20260    let descendants = [];
20261    for (let i2 = 0; i2 < nodesLength; i2++) {
20262      const node = nodes[i2];
20263      if ($isRootOrShadowRoot2(node)) {
20264        $wrapNodesImpl(selection, descendants, descendants.length, createElement2, wrappingElement);
20265        descendants = [];
20266        topLevelNode = node;
20267      } else if (topLevelNode === null || topLevelNode !== null && $hasAncestor2(node, topLevelNode)) {
20268        descendants.push(node);
20269      } else {
20270        $wrapNodesImpl(selection, descendants, descendants.length, createElement2, wrappingElement);
20271        descendants = [node];
20272      }
20273    }
20274    $wrapNodesImpl(selection, descendants, descendants.length, createElement2, wrappingElement);
20275  }
20276  function $wrapNodesImpl(selection, nodes, nodesLength, createElement2, wrappingElement = null) {
20277    if (nodes.length === 0) {
20278      return;
20279    }
20280    const firstNode = nodes[0];
20281    const elementMapping = /* @__PURE__ */ new Map();
20282    const elements = [];
20283    let target = $isElementNode2(firstNode) ? firstNode : firstNode.getParentOrThrow();
20284    if (target.isInline()) {
20285      target = target.getParentOrThrow();
20286    }
20287    let targetIsPrevSibling = false;
20288    while (target !== null) {
20289      const prevSibling = target.getPreviousSibling();
20290      if (prevSibling !== null) {
20291        target = prevSibling;
20292        targetIsPrevSibling = true;
20293        break;
20294      }
20295      target = target.getParentOrThrow();
20296      if ($isRootOrShadowRoot2(target)) {
20297        break;
20298      }
20299    }
20300    const emptyElements = /* @__PURE__ */ new Set();
20301    for (let i2 = 0; i2 < nodesLength; i2++) {
20302      const node = nodes[i2];
20303      if ($isElementNode2(node) && node.getChildrenSize() === 0) {
20304        emptyElements.add(node.getKey());
20305      }
20306    }
20307    const movedNodes = /* @__PURE__ */ new Set();
20308    for (let i2 = 0; i2 < nodesLength; i2++) {
20309      const node = nodes[i2];
20310      let parent = node.getParent();
20311      if (parent !== null && parent.isInline()) {
20312        parent = parent.getParent();
20313      }
20314      if (parent !== null && $isLeafNode2(node) && !movedNodes.has(node.getKey())) {
20315        const parentKey = parent.getKey();
20316        if (elementMapping.get(parentKey) === void 0) {
20317          const targetElement = createElement2();
20318          targetElement.setFormat(parent.getFormatType());
20319          targetElement.setIndent(parent.getIndent());
20320          elements.push(targetElement);
20321          elementMapping.set(parentKey, targetElement);
20322          parent.getChildren().forEach((child) => {
20323            targetElement.append(child);
20324            movedNodes.add(child.getKey());
20325            if ($isElementNode2(child)) {
20326              child.getChildrenKeys().forEach((key) => movedNodes.add(key));
20327            }
20328          });
20329          $removeParentEmptyElements(parent);
20330        }
20331      } else if (emptyElements.has(node.getKey())) {
20332        if (!$isElementNode2(node)) {
20333          formatDevErrorMessage2(`Expected node in emptyElements to be an ElementNode`);
20334        }
20335        const targetElement = createElement2();
20336        targetElement.setFormat(node.getFormatType());
20337        targetElement.setIndent(node.getIndent());
20338        elements.push(targetElement);
20339        node.remove(true);
20340      }
20341    }
20342    if (wrappingElement !== null) {
20343      for (let i2 = 0; i2 < elements.length; i2++) {
20344        const element = elements[i2];
20345        wrappingElement.append(element);
20346      }
20347    }
20348    let lastElement = null;
20349    if ($isRootOrShadowRoot2(target)) {
20350      if (targetIsPrevSibling) {
20351        if (wrappingElement !== null) {
20352          target.insertAfter(wrappingElement);
20353        } else {
20354          for (let i2 = elements.length - 1; i2 >= 0; i2--) {
20355            const element = elements[i2];
20356            target.insertAfter(element);
20357          }
20358        }
20359      } else {
20360        const firstChild = target.getFirstChild();
20361        if ($isElementNode2(firstChild)) {
20362          target = firstChild;
20363        }
20364        if (firstChild === null) {
20365          if (wrappingElement) {
20366            target.append(wrappingElement);
20367          } else {
20368            for (let i2 = 0; i2 < elements.length; i2++) {
20369              const element = elements[i2];
20370              target.append(element);
20371              lastElement = element;
20372            }
20373          }
20374        } else {
20375          if (wrappingElement !== null) {
20376            firstChild.insertBefore(wrappingElement);
20377          } else {
20378            for (let i2 = 0; i2 < elements.length; i2++) {
20379              const element = elements[i2];
20380              firstChild.insertBefore(element);
20381              lastElement = element;
20382            }
20383          }
20384        }
20385      }
20386    } else {
20387      if (wrappingElement) {
20388        target.insertAfter(wrappingElement);
20389      } else {
20390        for (let i2 = elements.length - 1; i2 >= 0; i2--) {
20391          const element = elements[i2];
20392          target.insertAfter(element);
20393          lastElement = element;
20394        }
20395      }
20396    }
20397    const prevSelection = $getPreviousSelection2();
20398    if ($isRangeSelection2(prevSelection) && isPointAttached(prevSelection.anchor) && isPointAttached(prevSelection.focus)) {
20399      $setSelection2(prevSelection.clone());
20400    } else if (lastElement !== null) {
20401      lastElement.selectEnd();
20402    } else {
20403      selection.dirty = true;
20404    }
20405  }
20406  function $isEditorVerticalOrientation(selection) {
20407    const computedStyle = $getComputedStyle(selection);
20408    return computedStyle !== null && computedStyle.writingMode === "vertical-rl";
20409  }
20410  function $getComputedStyle(selection) {
20411    const anchorNode = selection.anchor.getNode();
20412    if ($isElementNode2(anchorNode)) {
20413      return $getComputedStyleForElement(anchorNode);
20414    }
20415    return $getComputedStyleForParent(anchorNode);
20416  }
20417  function $shouldOverrideDefaultCharacterSelection(selection, isBackward) {
20418    const isVertical = $isEditorVerticalOrientation(selection);
20419    let adjustedIsBackward = isVertical ? !isBackward : isBackward;
20420    if ($isParentElementRTL(selection)) {
20421      adjustedIsBackward = !adjustedIsBackward;
20422    }
20423    const focusCaret = $caretFromPoint2(selection.focus, adjustedIsBackward ? "previous" : "next");
20424    if ($isExtendableTextPointCaret2(focusCaret)) {
20425      return false;
20426    }
20427    for (const nextCaret of $extendCaretToRange2(focusCaret)) {
20428      if ($isChildCaret2(nextCaret)) {
20429        return !nextCaret.origin.isInline();
20430      } else if ($isElementNode2(nextCaret.origin)) {
20431        continue;
20432      } else if ($isDecoratorNode2(nextCaret.origin)) {
20433        return true;
20434      }
20435      break;
20436    }
20437    return false;
20438  }
20439  function $moveCaretSelection(selection, isHoldingShift, isBackward, granularity) {
20440    selection.modify(isHoldingShift ? "extend" : "move", isBackward, granularity);
20441  }
20442  function $isParentElementRTL(selection) {
20443    const computedStyle = $getComputedStyle(selection);
20444    return computedStyle !== null && computedStyle.direction === "rtl";
20445  }
20446  function $moveCharacter(selection, isHoldingShift, isBackward) {
20447    const isRTL2 = $isParentElementRTL(selection);
20448    const isVertical = $isEditorVerticalOrientation(selection);
20449    let adjustedIsBackward;
20450    if (isVertical) {
20451      adjustedIsBackward = !isBackward;
20452    } else if (isRTL2) {
20453      adjustedIsBackward = !isBackward;
20454    } else {
20455      adjustedIsBackward = isBackward;
20456    }
20457    $moveCaretSelection(selection, isHoldingShift, adjustedIsBackward, "character");
20458  }
20459  function $getNodeStyleValueForProperty(node, styleProperty, defaultValue) {
20460    const css = node.getStyle();
20461    const styleObject = getStyleObjectFromCSS2(css);
20462    if (styleObject !== null) {
20463      return styleObject[styleProperty] || defaultValue;
20464    }
20465    return defaultValue;
20466  }
20467  function $getSelectionStyleValueForProperty(selection, styleProperty, defaultValue = "") {
20468    let styleValue = null;
20469    const nodes = selection.getNodes();
20470    const anchor = selection.anchor;
20471    const focus = selection.focus;
20472    const isBackward = selection.isBackward();
20473    const startNode = isBackward ? focus.getNode() : anchor.getNode();
20474    const endNode = isBackward ? anchor.getNode() : focus.getNode();
20475    const startOffset = isBackward ? focus.offset : anchor.offset;
20476    const endOffset = isBackward ? anchor.offset : focus.offset;
20477    if ($isRangeSelection2(selection) && selection.isCollapsed() && selection.style !== "") {
20478      const css = selection.style;
20479      const styleObject = getStyleObjectFromCSS2(css);
20480      if (styleObject !== null && styleProperty in styleObject) {
20481        return styleObject[styleProperty];
20482      }
20483    }
20484    for (let i2 = 0; i2 < nodes.length; i2++) {
20485      const node = nodes[i2];
20486      if (i2 === 0 && node.is(startNode) && $isTextNode2(node) && startOffset === node.getTextContentSize()) {
20487        continue;
20488      }
20489      if (i2 !== 0 && node.is(endNode) && endOffset === 0) {
20490        continue;
20491      }
20492      if ($isTextNode2(node)) {
20493        const nodeStyleValue = $getNodeStyleValueForProperty(node, styleProperty, defaultValue);
20494        if (styleValue === null) {
20495          styleValue = nodeStyleValue;
20496        } else if (styleValue !== nodeStyleValue) {
20497          styleValue = "";
20498          break;
20499        }
20500      }
20501    }
20502    return styleValue === null ? defaultValue : styleValue;
20503  }
20504  var getStyleObjectFromCSS3 = getStyleObjectFromCSS2;
20505  var trimTextContentFromAnchor = $trimTextContentFromAnchor;
20506
20507  
vendor: 1,602 bytes, lines 20507-20535
20507// node_modules/@lexical/selection/LexicalSelection.mjs
20508  var mod2 = true ? LexicalSelection_dev_exports : LexicalSelection_prod_exports;
20509  var $addNodeStyle2 = mod2.$addNodeStyle;
20510  var $cloneWithProperties3 = mod2.$cloneWithProperties;
20511  var $copyBlockFormatIndent2 = mod2.$copyBlockFormatIndent;
20512  var $ensureForwardRangeSelection2 = mod2.$ensureForwardRangeSelection;
20513  var $forEachSelectedTextNode2 = mod2.$forEachSelectedTextNode;
20514  var $getComputedStyleForElement2 = mod2.$getComputedStyleForElement;
20515  var $getComputedStyleForParent2 = mod2.$getComputedStyleForParent;
20516  var $getSelectionStyleValueForProperty2 = mod2.$getSelectionStyleValueForProperty;
20517  var $isAtNodeEnd2 = mod2.$isAtNodeEnd;
20518  var $isParentElementRTL2 = mod2.$isParentElementRTL;
20519  var $isParentRTL2 = mod2.$isParentRTL;
20520  var $moveCaretSelection2 = mod2.$moveCaretSelection;
20521  var $moveCharacter2 = mod2.$moveCharacter;
20522  var $patchStyleText2 = mod2.$patchStyleText;
20523  var $selectAll3 = mod2.$selectAll;
20524  var $setBlocksType2 = mod2.$setBlocksType;
20525  var $shouldOverrideDefaultCharacterSelection2 = mod2.$shouldOverrideDefaultCharacterSelection;
20526  var $sliceSelectedTextNodeContent2 = mod2.$sliceSelectedTextNodeContent;
20527  var $trimTextContentFromAnchor2 = mod2.$trimTextContentFromAnchor;
20528  var $wrapNodes2 = mod2.$wrapNodes;
20529  var createDOMRange2 = mod2.createDOMRange;
20530  var createRectsFromDOMRange2 = mod2.createRectsFromDOMRange;
20531  var getCSSFromStyleObject2 = mod2.getCSSFromStyleObject;
20532  var getStyleObjectFromCSS4 = mod2.getStyleObjectFromCSS;
20533  var trimTextContentFromAnchor2 = mod2.trimTextContentFromAnchor;
20534
20535  
vendor: 884 bytes, lines 20535-20557
20535// node_modules/@lexical/link/LexicalLink.dev.mjs
20536  var LexicalLink_dev_exports = {};
20537  __export(LexicalLink_dev_exports, {
20538    $createAutoLinkNode: () => $createAutoLinkNode,
20539    $createLinkNode: () => $createLinkNode,
20540    $isAutoLinkNode: () => $isAutoLinkNode,
20541    $isLinkNode: () => $isLinkNode,
20542    $toggleLink: () => $toggleLink,
20543    AutoLinkExtension: () => AutoLinkExtension,
20544    AutoLinkNode: () => AutoLinkNode,
20545    ClickableLinkExtension: () => ClickableLinkExtension,
20546    LinkExtension: () => LinkExtension,
20547    LinkNode: () => LinkNode,
20548    TOGGLE_LINK_COMMAND: () => TOGGLE_LINK_COMMAND,
20549    createLinkMatcherWithRegExp: () => createLinkMatcherWithRegExp,
20550    formatUrl: () => formatUrl,
20551    registerAutoLink: () => registerAutoLink,
20552    registerClickableLink: () => registerClickableLink,
20553    registerLink: () => registerLink,
20554    toggleLink: () => toggleLink
20555  });
20556
20557  
vendor: 28,232 bytes, lines 20557-21302
20557// node_modules/@lexical/utils/LexicalUtils.dev.mjs
20558  var LexicalUtils_dev_exports = {};
20559  __export(LexicalUtils_dev_exports, {
20560    $descendantsMatching: () => $descendantsMatching,
20561    $dfs: () => $dfs,
20562    $dfsIterator: () => $dfsIterator,
20563    $filter: () => $filter,
20564    $findMatchingParent: () => $findMatchingParent2,
20565    $firstToLastIterator: () => $firstToLastIterator,
20566    $getAdjacentCaret: () => $getAdjacentCaret,
20567    $getAdjacentSiblingOrParentSiblingCaret: () => $getAdjacentSiblingOrParentSiblingCaret2,
20568    $getDepth: () => $getDepth,
20569    $getNearestBlockElementAncestorOrThrow: () => $getNearestBlockElementAncestorOrThrow,
20570    $getNearestNodeOfType: () => $getNearestNodeOfType,
20571    $getNextRightPreorderNode: () => $getNextRightPreorderNode,
20572    $getNextSiblingOrParentSibling: () => $getNextSiblingOrParentSibling,
20573    $handleIndentAndOutdent: () => $handleIndentAndOutdent,
20574    $insertFirst: () => $insertFirst,
20575    $insertNodeIntoLeaf: () => $insertNodeIntoLeaf,
20576    $insertNodeToNearestRoot: () => $insertNodeToNearestRoot,
20577    $insertNodeToNearestRootAtCaret: () => $insertNodeToNearestRootAtCaret,
20578    $isEditorIsNestedEditor: () => $isEditorIsNestedEditor,
20579    $lastToFirstIterator: () => $lastToFirstIterator,
20580    $restoreEditorState: () => $restoreEditorState,
20581    $reverseDfs: () => $reverseDfs,
20582    $reverseDfsIterator: () => $reverseDfsIterator,
20583    $splitNode: () => $splitNode2,
20584    $unwrapAndFilterDescendants: () => $unwrapAndFilterDescendants,
20585    $unwrapNode: () => $unwrapNode,
20586    $wrapNodeInElement: () => $wrapNodeInElement,
20587    CAN_USE_BEFORE_INPUT: () => CAN_USE_BEFORE_INPUT2,
20588    CAN_USE_DOM: () => CAN_USE_DOM2,
20589    IS_ANDROID: () => IS_ANDROID2,
20590    IS_ANDROID_CHROME: () => IS_ANDROID_CHROME2,
20591    IS_APPLE: () => IS_APPLE2,
20592    IS_APPLE_WEBKIT: () => IS_APPLE_WEBKIT2,
20593    IS_CHROME: () => IS_CHROME2,
20594    IS_FIREFOX: () => IS_FIREFOX2,
20595    IS_IOS: () => IS_IOS2,
20596    IS_SAFARI: () => IS_SAFARI2,
20597    addClassNamesToElement: () => addClassNamesToElement2,
20598    calculateZoomLevel: () => calculateZoomLevel,
20599    isBlockDomNode: () => isBlockDomNode2,
20600    isHTMLAnchorElement: () => isHTMLAnchorElement2,
20601    isHTMLElement: () => isHTMLElement2,
20602    isInlineDomNode: () => isInlineDomNode2,
20603    isMimeType: () => isMimeType,
20604    makeStateWrapper: () => makeStateWrapper,
20605    markSelection: () => markSelection,
20606    mediaFileReader: () => mediaFileReader,
20607    mergeRegister: () => mergeRegister2,
20608    objectKlassEquals: () => objectKlassEquals,
20609    positionNodeOnRange: () => mlcPositionNodeOnRange,
20610    registerNestedElementResolver: () => registerNestedElementResolver,
20611    removeClassNamesFromElement: () => removeClassNamesFromElement2,
20612    selectionAlwaysOnDisplay: () => selectionAlwaysOnDisplay
20613  });
20614  function formatDevErrorMessage3(message) {
20615    throw new Error(message);
20616  }
20617  var CAN_USE_DOM$1 = typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.document.createElement !== "undefined";
20618  var documentMode2 = CAN_USE_DOM$1 && "documentMode" in document ? document.documentMode : null;
20619  var IS_APPLE$1 = CAN_USE_DOM$1 && /Mac|iPod|iPhone|iPad/.test(navigator.platform);
20620  var IS_FIREFOX$1 = CAN_USE_DOM$1 && /^(?!.*Seamonkey)(?=.*Firefox).*/i.test(navigator.userAgent);
20621  var CAN_USE_BEFORE_INPUT$1 = CAN_USE_DOM$1 && "InputEvent" in window && !documentMode2 ? "getTargetRanges" in new window.InputEvent("input") : false;
20622  var IS_IOS$1 = CAN_USE_DOM$1 && /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
20623  var IS_ANDROID$1 = CAN_USE_DOM$1 && /Android/.test(navigator.userAgent);
20624  var IS_SAFARI$1 = CAN_USE_DOM$1 && /Version\/[\d.]+.*Safari/.test(navigator.userAgent) && !IS_ANDROID$1;
20625  var IS_CHROME$1 = CAN_USE_DOM$1 && /^(?=.*Chrome).*/i.test(navigator.userAgent);
20626  var IS_ANDROID_CHROME$1 = CAN_USE_DOM$1 && IS_ANDROID$1 && IS_CHROME$1;
20627  var IS_APPLE_WEBKIT$1 = CAN_USE_DOM$1 && /AppleWebKit\/[\d.]+/.test(navigator.userAgent) && IS_APPLE$1 && !IS_CHROME$1;
20628  function px(value) {
20629    return `${value}px`;
20630  }
20631  var mutationObserverConfig = {
20632    attributes: true,
20633    characterData: true,
20634    childList: true,
20635    subtree: true
20636  };
20637  function prependDOMNode(parent, node) {
20638    parent.insertBefore(node, parent.firstChild);
20639  }
20640  function mlcPositionNodeOnRange(editor, range2, onReposition) {
20641    let rootDOMNode = null;
20642    let parentDOMNode = null;
20643    let observer = null;
20644    let lastNodes = [];
20645    const wrapperNode = document.createElement("div");
20646    wrapperNode.style.position = "relative";
20647    function position() {
20648      if (!(rootDOMNode !== null)) {
20649        formatDevErrorMessage3(`Unexpected null rootDOMNode`);
20650      }
20651      if (!(parentDOMNode !== null)) {
20652        formatDevErrorMessage3(`Unexpected null parentDOMNode`);
20653      }
20654      const {
20655        left: parentLeft,
20656        top: parentTop
20657      } = parentDOMNode.getBoundingClientRect();
20658      const rects = createRectsFromDOMRange2(editor, range2);
20659      if (!wrapperNode.isConnected) {
20660        prependDOMNode(parentDOMNode, wrapperNode);
20661      }
20662      let hasRepositioned = false;
20663      for (let i2 = 0; i2 < rects.length; i2++) {
20664        const rect = rects[i2];
20665        const rectNode = lastNodes[i2] || document.createElement("div");
20666        const rectNodeStyle = rectNode.style;
20667        if (rectNodeStyle.position !== "absolute") {
20668          rectNodeStyle.position = "absolute";
20669          hasRepositioned = true;
20670        }
20671        const left = px(rect.left - parentLeft);
20672        if (rectNodeStyle.left !== left) {
20673          rectNodeStyle.left = left;
20674          hasRepositioned = true;
20675        }
20676        const top = px(rect.top - parentTop);
20677        if (rectNodeStyle.top !== top) {
20678          rectNode.style.top = top;
20679          hasRepositioned = true;
20680        }
20681        const width = px(rect.width);
20682        if (rectNodeStyle.width !== width) {
20683          rectNode.style.width = width;
20684          hasRepositioned = true;
20685        }
20686        const height = px(rect.height);
20687        if (rectNodeStyle.height !== height) {
20688          rectNode.style.height = height;
20689          hasRepositioned = true;
20690        }
20691        if (rectNode.parentNode !== wrapperNode) {
20692          wrapperNode.append(rectNode);
20693          hasRepositioned = true;
20694        }
20695        lastNodes[i2] = rectNode;
20696      }
20697      while (lastNodes.length > rects.length) {
20698        lastNodes.pop();
20699      }
20700      if (hasRepositioned) {
20701        onReposition(lastNodes);
20702      }
20703    }
20704    function stop() {
20705      parentDOMNode = null;
20706      rootDOMNode = null;
20707      if (observer !== null) {
20708        observer.disconnect();
20709      }
20710      observer = null;
20711      wrapperNode.remove();
20712      for (const node of lastNodes) {
20713        node.remove();
20714      }
20715      lastNodes = [];
20716    }
20717    function restart() {
20718      const currentRootDOMNode = editor.getRootElement();
20719      if (currentRootDOMNode === null) {
20720        return stop();
20721      }
20722      const currentParentDOMNode = currentRootDOMNode.parentElement;
20723      if (!isHTMLElement2(currentParentDOMNode)) {
20724        return stop();
20725      }
20726      stop();
20727      rootDOMNode = currentRootDOMNode;
20728      parentDOMNode = currentParentDOMNode;
20729      observer = new MutationObserver((mutations) => {
20730        const nextRootDOMNode = editor.getRootElement();
20731        const nextParentDOMNode = nextRootDOMNode && nextRootDOMNode.parentElement;
20732        if (nextRootDOMNode !== rootDOMNode || nextParentDOMNode !== parentDOMNode) {
20733          return restart();
20734        }
20735        for (const mutation of mutations) {
20736          if (!wrapperNode.contains(mutation.target)) {
20737            return position();
20738          }
20739        }
20740      });
20741      observer.observe(currentParentDOMNode, mutationObserverConfig);
20742      position();
20743    }
20744    const removeRootListener = editor.registerRootListener(restart);
20745    return () => {
20746      removeRootListener();
20747      stop();
20748    };
20749  }
20750  function $getOrderedSelectionPoints(selection) {
20751    const points = selection.getStartEndPoints();
20752    return selection.isBackward() ? [points[1], points[0]] : points;
20753  }
20754  function $rangeTargetFromPoint(point, node, dom) {
20755    if (point.type === "text" || !$isElementNode2(node)) {
20756      const textDOM = getDOMTextNode2(dom) || dom;
20757      return [textDOM, point.offset];
20758    } else {
20759      const editor = $getEditor2();
20760      const slot = $getEditorDOMRenderConfig2(editor).$getDOMSlot(node, dom, editor);
20761      return [slot.element, slot.getFirstChildOffset() + point.offset];
20762    }
20763  }
20764  function $rangeFromPoints(editor, start3, startNode, startDOM, end, endNode, endDOM) {
20765    const editorDocument = editor._window ? editor._window.document : document;
20766    const range2 = editorDocument.createRange();
20767    range2.setStart(...$rangeTargetFromPoint(start3, startNode, startDOM));
20768    range2.setEnd(...$rangeTargetFromPoint(end, endNode, endDOM));
20769    return range2;
20770  }
20771  function defaultOnReposition(domNodes) {
20772    for (const domNode of domNodes) {
20773      const domNodeStyle = domNode.style;
20774      if (domNodeStyle.background !== "Highlight") {
20775        domNodeStyle.background = "Highlight";
20776      }
20777      if (domNodeStyle.color !== "HighlightText") {
20778        domNodeStyle.color = "HighlightText";
20779      }
20780      if (domNodeStyle.marginTop !== px(-1.5)) {
20781        domNodeStyle.marginTop = px(-1.5);
20782      }
20783      if (domNodeStyle.paddingTop !== px(4)) {
20784        domNodeStyle.paddingTop = px(4);
20785      }
20786      if (domNodeStyle.paddingBottom !== px(0)) {
20787        domNodeStyle.paddingBottom = px(0);
20788      }
20789    }
20790  }
20791  function markSelection(editor, onReposition = defaultOnReposition) {
20792    let previousAnchorNode = null;
20793    let previousAnchorNodeDOM = null;
20794    let previousAnchorOffset = null;
20795    let previousFocusNode = null;
20796    let previousFocusNodeDOM = null;
20797    let previousFocusOffset = null;
20798    let removeRangeListener = () => {
20799    };
20800    function compute(editorState) {
20801      editorState.read(() => {
20802        const selection = $getSelection2();
20803        if (!$isRangeSelection2(selection)) {
20804          previousAnchorNode = null;
20805          previousAnchorOffset = null;
20806          previousFocusNode = null;
20807          previousFocusOffset = null;
20808          removeRangeListener();
20809          removeRangeListener = () => {
20810          };
20811          return;
20812        }
20813        const [start3, end] = $getOrderedSelectionPoints(selection);
20814        const currentStartNode = start3.getNode();
20815        const currentStartNodeKey = currentStartNode.getKey();
20816        const currentStartOffset = start3.offset;
20817        const currentEndNode = end.getNode();
20818        const currentEndNodeKey = currentEndNode.getKey();
20819        const currentEndOffset = end.offset;
20820        const currentStartNodeDOM = editor.getElementByKey(currentStartNodeKey);
20821        const currentEndNodeDOM = editor.getElementByKey(currentEndNodeKey);
20822        const differentStartDOM = previousAnchorNode === null || currentStartNodeDOM !== previousAnchorNodeDOM || currentStartOffset !== previousAnchorOffset || currentStartNodeKey !== previousAnchorNode.getKey();
20823        const differentEndDOM = previousFocusNode === null || currentEndNodeDOM !== previousFocusNodeDOM || currentEndOffset !== previousFocusOffset || currentEndNodeKey !== previousFocusNode.getKey();
20824        if ((differentStartDOM || differentEndDOM) && currentStartNodeDOM !== null && currentEndNodeDOM !== null) {
20825          const range2 = $rangeFromPoints(editor, start3, currentStartNode, currentStartNodeDOM, end, currentEndNode, currentEndNodeDOM);
20826          removeRangeListener();
20827          removeRangeListener = mlcPositionNodeOnRange(editor, range2, onReposition);
20828        }
20829        previousAnchorNode = currentStartNode;
20830        previousAnchorNodeDOM = currentStartNodeDOM;
20831        previousAnchorOffset = currentStartOffset;
20832        previousFocusNode = currentEndNode;
20833        previousFocusNodeDOM = currentEndNodeDOM;
20834        previousFocusOffset = currentEndOffset;
20835      });
20836    }
20837    compute(editor.getEditorState());
20838    return mergeRegister2(editor.registerUpdateListener(({
20839      editorState
20840    }) => compute(editorState)), () => {
20841      removeRangeListener();
20842    });
20843  }
20844  function selectionAlwaysOnDisplay(editor, onReposition) {
20845    let removeSelectionMark = null;
20846    const onSelectionChange2 = () => {
20847      const domSelection = getSelection();
20848      const domAnchorNode = domSelection && domSelection.anchorNode;
20849      const editorRootElement = editor.getRootElement();
20850      const isSelectionInsideEditor = domAnchorNode !== null && editorRootElement !== null && editorRootElement.contains(domAnchorNode);
20851      if (isSelectionInsideEditor) {
20852        if (removeSelectionMark !== null) {
20853          removeSelectionMark();
20854          removeSelectionMark = null;
20855        }
20856      } else {
20857        if (removeSelectionMark === null) {
20858          removeSelectionMark = markSelection(editor, onReposition);
20859        }
20860      }
20861    };
20862    return editor.registerRootListener((rootElement) => {
20863      if (rootElement) {
20864        const document2 = rootElement.ownerDocument;
20865        document2.addEventListener("selectionchange", onSelectionChange2);
20866        onSelectionChange2();
20867        return () => {
20868          if (removeSelectionMark !== null) {
20869            removeSelectionMark();
20870          }
20871          document2.removeEventListener("selectionchange", onSelectionChange2);
20872        };
20873      }
20874    });
20875  }
20876  var CAN_USE_BEFORE_INPUT2 = CAN_USE_BEFORE_INPUT$1;
20877  var CAN_USE_DOM2 = CAN_USE_DOM$1;
20878  var IS_ANDROID2 = IS_ANDROID$1;
20879  var IS_ANDROID_CHROME2 = IS_ANDROID_CHROME$1;
20880  var IS_APPLE2 = IS_APPLE$1;
20881  var IS_APPLE_WEBKIT2 = IS_APPLE_WEBKIT$1;
20882  var IS_CHROME2 = IS_CHROME$1;
20883  var IS_FIREFOX2 = IS_FIREFOX$1;
20884  var IS_IOS2 = IS_IOS$1;
20885  var IS_SAFARI2 = IS_SAFARI$1;
20886  function isMimeType(file, acceptableMimeTypes) {
20887    for (const acceptableType of acceptableMimeTypes) {
20888      if (file.type.startsWith(acceptableType)) {
20889        return true;
20890      }
20891    }
20892    return false;
20893  }
20894  function mediaFileReader(files, acceptableMimeTypes) {
20895    const filesIterator = files[Symbol.iterator]();
20896    return new Promise((resolve, reject) => {
20897      const processed = [];
20898      const handleNextFile = () => {
20899        const {
20900          done,
20901          value: file
20902        } = filesIterator.next();
20903        if (done) {
20904          return resolve(processed);
20905        }
20906        const fileReader = new FileReader();
20907        fileReader.addEventListener("error", reject);
20908        fileReader.addEventListener("load", () => {
20909          const result = fileReader.result;
20910          if (typeof result === "string") {
20911            processed.push({
20912              file,
20913              result
20914            });
20915          }
20916          handleNextFile();
20917        });
20918        if (isMimeType(file, acceptableMimeTypes)) {
20919          fileReader.readAsDataURL(file);
20920        } else {
20921          handleNextFile();
20922        }
20923      };
20924      handleNextFile();
20925    });
20926  }
20927  function $dfs(startNode, endNode) {
20928    return Array.from($dfsIterator(startNode, endNode));
20929  }
20930  function $getAdjacentCaret(caret) {
20931    return caret ? caret.getAdjacentCaret() : null;
20932  }
20933  function $reverseDfs(startNode, endNode) {
20934    return Array.from($reverseDfsIterator(startNode, endNode));
20935  }
20936  function $dfsIterator(startNode, endNode) {
20937    return $dfsCaretIterator("next", startNode, endNode);
20938  }
20939  function $getEndCaret(startNode, direction) {
20940    const rval = $getAdjacentSiblingOrParentSiblingCaret2($getSiblingCaret2(startNode, direction));
20941    return rval && rval[0];
20942  }
20943  function $dfsCaretIterator(direction, startNode, endNode) {
20944    const root = $getRoot2();
20945    const start3 = startNode || root;
20946    const startCaret = $isElementNode2(start3) ? $getChildCaret2(start3, direction) : $getSiblingCaret2(start3, direction);
20947    const startDepth = $getDepth(start3);
20948    const endCaret = endNode ? $getAdjacentChildCaret2($getChildCaretOrSelf2($getSiblingCaret2(endNode, direction))) || $getEndCaret(endNode, direction) : $getEndCaret(start3, direction);
20949    let depth = startDepth;
20950    return makeStepwiseIterator2({
20951      hasNext: (state) => state !== null,
20952      initial: startCaret,
20953      map: (state) => ({
20954        depth,
20955        node: state.origin
20956      }),
20957      step: (state) => {
20958        if (state.isSameNodeCaret(endCaret)) {
20959          return null;
20960        }
20961        if ($isChildCaret2(state)) {
20962          depth++;
20963        }
20964        const rval = $getAdjacentSiblingOrParentSiblingCaret2(state);
20965        if (!rval || rval[0].isSameNodeCaret(endCaret)) {
20966          return null;
20967        }
20968        depth += rval[1];
20969        return rval[0];
20970      }
20971    });
20972  }
20973  function $getNextSiblingOrParentSibling(node) {
20974    const rval = $getAdjacentSiblingOrParentSiblingCaret2($getSiblingCaret2(node, "next"));
20975    return rval && [rval[0].origin, rval[1]];
20976  }
20977  function $getDepth(node) {
20978    let depth = -1;
20979    for (let innerNode = node; innerNode !== null; innerNode = innerNode.getParent()) {
20980      depth++;
20981    }
20982    return depth;
20983  }
20984  function $getNextRightPreorderNode(startingNode) {
20985    const startCaret = $getChildCaretOrSelf2($getSiblingCaret2(startingNode, "previous"));
20986    const next = $getAdjacentSiblingOrParentSiblingCaret2(startCaret, "root");
20987    return next && next[0].origin;
20988  }
20989  function $reverseDfsIterator(startNode, endNode) {
20990    return $dfsCaretIterator("previous", startNode, endNode);
20991  }
20992  function $getNearestNodeOfType(node, klass) {
20993    let parent = node;
20994    while (parent != null) {
20995      if (parent instanceof klass) {
20996        return parent;
20997      }
20998      parent = parent.getParent();
20999    }
21000    return null;
21001  }
21002  function $getNearestBlockElementAncestorOrThrow(startNode) {
21003    const blockNode = $findMatchingParent2(startNode, (node) => $isElementNode2(node) && !node.isInline());
21004    if (!$isElementNode2(blockNode)) {
21005      {
21006        formatDevErrorMessage3(`Expected node ${startNode.__key} to have closest block element node.`);
21007      }
21008    }
21009    return blockNode;
21010  }
21011  function registerNestedElementResolver(editor, targetNode, cloneNode, handleOverlap) {
21012    const $isTargetNode = (node) => {
21013      return node instanceof targetNode;
21014    };
21015    const $findMatch = (node) => {
21016      const children = node.getChildren();
21017      for (let i2 = 0; i2 < children.length; i2++) {
21018        const child = children[i2];
21019        if ($isTargetNode(child)) {
21020          return null;
21021        }
21022      }
21023      let parentNode = node;
21024      let childNode = node;
21025      while (parentNode !== null) {
21026        childNode = parentNode;
21027        parentNode = parentNode.getParent();
21028        if ($isTargetNode(parentNode)) {
21029          return {
21030            child: childNode,
21031            parent: parentNode
21032          };
21033        }
21034      }
21035      return null;
21036    };
21037    const $elementNodeTransform = (node) => {
21038      const match = $findMatch(node);
21039      if (match !== null) {
21040        const {
21041          child,
21042          parent
21043        } = match;
21044        if (child.is(node)) {
21045          handleOverlap(parent, node);
21046          const nextSiblings = child.getNextSiblings();
21047          const nextSiblingsLength = nextSiblings.length;
21048          parent.insertAfter(child);
21049          if (nextSiblingsLength !== 0) {
21050            const newParent = cloneNode(parent);
21051            child.insertAfter(newParent);
21052            for (let i2 = 0; i2 < nextSiblingsLength; i2++) {
21053              newParent.append(nextSiblings[i2]);
21054            }
21055          }
21056          if (!parent.canBeEmpty() && parent.getChildrenSize() === 0) {
21057            parent.remove();
21058          }
21059        }
21060      }
21061    };
21062    return editor.registerNodeTransform(targetNode, $elementNodeTransform);
21063  }
21064  function $restoreEditorState(editor, editorState) {
21065    const FULL_RECONCILE2 = 2;
21066    const nodeMap = /* @__PURE__ */ new Map();
21067    const activeEditorState2 = editor._pendingEditorState;
21068    for (const [key, node] of editorState._nodeMap) {
21069      nodeMap.set(key, $cloneWithProperties2(node));
21070    }
21071    if (activeEditorState2) {
21072      activeEditorState2._nodeMap = nodeMap;
21073    }
21074    editor._dirtyType = FULL_RECONCILE2;
21075    const selection = editorState._selection;
21076    $setSelection2(selection === null ? null : selection.clone());
21077  }
21078  function $insertNodeToNearestRoot(node) {
21079    const selection = $getSelection2() || $getPreviousSelection2();
21080    let initialCaret;
21081    if ($isRangeSelection2(selection)) {
21082      initialCaret = $caretFromPoint2(selection.focus, "next");
21083    } else {
21084      if (selection != null) {
21085        const nodes = selection.getNodes();
21086        const lastNode = nodes[nodes.length - 1];
21087        if (lastNode) {
21088          initialCaret = $getSiblingCaret2(lastNode, "next");
21089        }
21090      }
21091      initialCaret = initialCaret || $getChildCaret2($getRoot2(), "previous").getFlipped().insert($createParagraphNode2());
21092    }
21093    const insertCaret = $insertNodeToNearestRootAtCaret(node, initialCaret);
21094    const adjacent = $getAdjacentChildCaret2(insertCaret);
21095    const selectionCaret = $isChildCaret2(adjacent) ? $normalizeCaret2(adjacent) : insertCaret;
21096    $setSelectionFromCaretRange2($getCollapsedCaretRange2(selectionCaret));
21097    return node.getLatest();
21098  }
21099  function $insertNodeToNearestRootAtCaret(node, caret, options) {
21100    let insertCaret = $getCaretInDirection2(caret, "next");
21101    if ($isTextPointCaret2(insertCaret)) {
21102      if (insertCaret.offset === 0) {
21103        insertCaret = $getSiblingCaret2(insertCaret.origin, "previous").getFlipped();
21104      } else if (insertCaret.offset === insertCaret.origin.getTextContentSize()) {
21105        insertCaret = $getSiblingCaret2(insertCaret.origin, "next");
21106      }
21107    }
21108    if (insertCaret.origin.is(node)) {
21109      if (!$isSiblingCaret2(insertCaret)) {
21110        formatDevErrorMessage3(`$insertNodeToNearestRootAtCaret node ${node.getKey()} of type ${node.getType()} can not be inserted into itself`);
21111      }
21112      insertCaret = $rewindSiblingCaret2(insertCaret);
21113    }
21114    if (node.is(insertCaret.getNodeAtCaret()) || node.is(insertCaret.getFlipped().getNodeAtCaret())) {
21115      node.remove(true);
21116    }
21117    for (let nextCaret = insertCaret; nextCaret; nextCaret = $splitAtPointCaretNext2(nextCaret, options)) {
21118      insertCaret = nextCaret;
21119    }
21120    if (!!$isTextPointCaret2(insertCaret)) {
21121      formatDevErrorMessage3(`$insertNodeToNearestRootAtCaret: An unattached TextNode can not be split`);
21122    }
21123    insertCaret.insert(node.isInline() ? $createParagraphNode2().append(node) : node);
21124    return $getCaretInDirection2($getSiblingCaret2(node.getLatest(), "next"), caret.direction);
21125  }
21126  function $insertNodeIntoLeaf(node) {
21127    const selection = $getSelection2();
21128    if (!$isRangeSelection2(selection)) {
21129      if (selection) {
21130        selection.insertNodes([node]);
21131      }
21132      return;
21133    }
21134    const caretRange = $caretRangeFromSelection2(selection);
21135    let insertCaret = $getCaretRangeInDirection2($removeTextFromCaretRange2(caretRange), "next").anchor;
21136    if ($isTextPointCaret2(insertCaret)) {
21137      const nextAnchor = $splitAtPointCaretNext2(insertCaret);
21138      if (!nextAnchor) {
21139        return;
21140      }
21141      insertCaret = nextAnchor;
21142    }
21143    const focus = insertCaret.getFlipped();
21144    focus.insert(node);
21145    $setSelectionFromCaretRange2($getCaretRange2(focus, focus));
21146  }
21147  function $wrapNodeInElement(node, createElementNode) {
21148    const elementNode = createElementNode();
21149    node.replace(elementNode);
21150    elementNode.append(node);
21151    return elementNode;
21152  }
21153  function objectKlassEquals(object, objectClass) {
21154    return object !== null ? Object.getPrototypeOf(object).constructor.name === objectClass.name : false;
21155  }
21156  function $filter(nodes, filterFn) {
21157    const result = [];
21158    for (let i2 = 0; i2 < nodes.length; i2++) {
21159      const node = filterFn(nodes[i2]);
21160      if (node !== null) {
21161        result.push(node);
21162      }
21163    }
21164    return result;
21165  }
21166  function $handleIndentAndOutdent(indentOrOutdent) {
21167    const selection = $getSelection2();
21168    if (!$isRangeSelection2(selection)) {
21169      return false;
21170    }
21171    const alreadyHandled = /* @__PURE__ */ new Set();
21172    const nodes = selection.getNodes();
21173    for (let i2 = 0; i2 < nodes.length; i2++) {
21174      const node = nodes[i2];
21175      const key = node.getKey();
21176      if (alreadyHandled.has(key)) {
21177        continue;
21178      }
21179      const parentBlock = $findMatchingParent2(node, (parentNode) => $isElementNode2(parentNode) && !parentNode.isInline());
21180      if (parentBlock === null) {
21181        continue;
21182      }
21183      const parentKey = parentBlock.getKey();
21184      if (parentBlock.canIndent() && !alreadyHandled.has(parentKey)) {
21185        alreadyHandled.add(parentKey);
21186        indentOrOutdent(parentBlock);
21187      }
21188    }
21189    return alreadyHandled.size > 0;
21190  }
21191  function $insertFirst(parent, node) {
21192    $getChildCaret2(parent, "next").insert(node);
21193  }
21194  var NEEDS_MANUAL_ZOOM = IS_FIREFOX2 || !CAN_USE_DOM2 ? false : void 0;
21195  function needsManualZoom() {
21196    if (NEEDS_MANUAL_ZOOM === void 0) {
21197      const div = document.createElement("div");
21198      div.style.position = "absolute";
21199      div.style.opacity = "0";
21200      div.style.width = "100px";
21201      div.style.left = "-1000px";
21202      document.body.appendChild(div);
21203      const noZoom = div.getBoundingClientRect();
21204      div.style.setProperty("zoom", "2");
21205      NEEDS_MANUAL_ZOOM = div.getBoundingClientRect().width === noZoom.width;
21206      document.body.removeChild(div);
21207    }
21208    return NEEDS_MANUAL_ZOOM;
21209  }
21210  function calculateZoomLevel(element, useManualZoom = false) {
21211    let zoom = 1;
21212    if (needsManualZoom() || useManualZoom) {
21213      while (element) {
21214        zoom *= Number(window.getComputedStyle(element).getPropertyValue("zoom"));
21215        element = element.parentElement;
21216      }
21217    }
21218    return zoom;
21219  }
21220  function $isEditorIsNestedEditor(editor) {
21221    return editor._parentEditor !== null;
21222  }
21223  function $unwrapAndFilterDescendants(root, $predicate) {
21224    return $unwrapAndFilterDescendantsImpl(root, $predicate, null);
21225  }
21226  function $unwrapAndFilterDescendantsImpl(root, $predicate, $onSuccess) {
21227    let didMutate = false;
21228    for (const node of $lastToFirstIterator(root)) {
21229      if ($predicate(node)) {
21230        if ($onSuccess !== null) {
21231          $onSuccess(node);
21232        }
21233        continue;
21234      }
21235      didMutate = true;
21236      if ($isElementNode2(node)) {
21237        $unwrapAndFilterDescendantsImpl(node, $predicate, $onSuccess || ((child) => node.insertAfter(child)));
21238      }
21239      node.remove();
21240    }
21241    return didMutate;
21242  }
21243  function $descendantsMatching(children, $predicate) {
21244    const result = [];
21245    const stack = Array.from(children).reverse();
21246    for (let child = stack.pop(); child !== void 0; child = stack.pop()) {
21247      if ($predicate(child)) {
21248        result.push(child);
21249      } else if ($isElementNode2(child)) {
21250        for (const grandchild of $lastToFirstIterator(child)) {
21251          stack.push(grandchild);
21252        }
21253      }
21254    }
21255    return result;
21256  }
21257  function $firstToLastIterator(node) {
21258    return $childIterator($getChildCaret2(node, "next"));
21259  }
21260  function $lastToFirstIterator(node) {
21261    return $childIterator($getChildCaret2(node, "previous"));
21262  }
21263  function $childIterator(startCaret) {
21264    const seen = /* @__PURE__ */ new Set();
21265    return makeStepwiseIterator2({
21266      hasNext: $isSiblingCaret2,
21267      initial: startCaret.getAdjacentCaret(),
21268      map: (caret) => {
21269        const origin = caret.origin.getLatest();
21270        if (seen !== null) {
21271          const key = origin.getKey();
21272          if (!!seen.has(key)) {
21273            formatDevErrorMessage3(`$childIterator: Cycle detected, node with key ${String(key)} has already been traversed`);
21274          }
21275          seen.add(key);
21276        }
21277        return origin;
21278      },
21279      step: (caret) => caret.getAdjacentCaret()
21280    });
21281  }
21282  function $unwrapNode(node) {
21283    $rewindSiblingCaret2($getSiblingCaret2(node, "next")).splice(1, node.getChildren());
21284  }
21285  function makeStateWrapper(stateConfig) {
21286    const $get = (node) => $getState2(node, stateConfig);
21287    const $set = (node, valueOrUpdater) => $setState2(node, stateConfig, valueOrUpdater);
21288    return {
21289      $get,
21290      $set,
21291      accessors: [$get, $set],
21292      makeGetterMethod: () => function $getter() {
21293        return $get(this);
21294      },
21295      makeSetterMethod: () => function $setter(valueOrUpdater) {
21296        return $set(this, valueOrUpdater);
21297      },
21298      stateConfig
21299    };
21300  }
21301
21302  
vendor: 2,879 bytes, lines 21302-21358
21302// node_modules/@lexical/utils/LexicalUtils.mjs
21303  var mod3 = true ? LexicalUtils_dev_exports : LexicalUtils_prod_exports;
21304  var $descendantsMatching2 = mod3.$descendantsMatching;
21305  var $dfs2 = mod3.$dfs;
21306  var $dfsIterator2 = mod3.$dfsIterator;
21307  var $filter2 = mod3.$filter;
21308  var $findMatchingParent3 = mod3.$findMatchingParent;
21309  var $firstToLastIterator2 = mod3.$firstToLastIterator;
21310  var $getAdjacentCaret2 = mod3.$getAdjacentCaret;
21311  var $getAdjacentSiblingOrParentSiblingCaret3 = mod3.$getAdjacentSiblingOrParentSiblingCaret;
21312  var $getDepth2 = mod3.$getDepth;
21313  var $getNearestBlockElementAncestorOrThrow2 = mod3.$getNearestBlockElementAncestorOrThrow;
21314  var $getNearestNodeOfType2 = mod3.$getNearestNodeOfType;
21315  var $getNextRightPreorderNode2 = mod3.$getNextRightPreorderNode;
21316  var $getNextSiblingOrParentSibling2 = mod3.$getNextSiblingOrParentSibling;
21317  var $handleIndentAndOutdent2 = mod3.$handleIndentAndOutdent;
21318  var $insertFirst2 = mod3.$insertFirst;
21319  var $insertNodeIntoLeaf2 = mod3.$insertNodeIntoLeaf;
21320  var $insertNodeToNearestRoot2 = mod3.$insertNodeToNearestRoot;
21321  var $insertNodeToNearestRootAtCaret2 = mod3.$insertNodeToNearestRootAtCaret;
21322  var $isEditorIsNestedEditor2 = mod3.$isEditorIsNestedEditor;
21323  var $lastToFirstIterator2 = mod3.$lastToFirstIterator;
21324  var $restoreEditorState2 = mod3.$restoreEditorState;
21325  var $reverseDfs2 = mod3.$reverseDfs;
21326  var $reverseDfsIterator2 = mod3.$reverseDfsIterator;
21327  var $splitNode3 = mod3.$splitNode;
21328  var $unwrapAndFilterDescendants2 = mod3.$unwrapAndFilterDescendants;
21329  var $unwrapNode2 = mod3.$unwrapNode;
21330  var $wrapNodeInElement2 = mod3.$wrapNodeInElement;
21331  var CAN_USE_BEFORE_INPUT3 = mod3.CAN_USE_BEFORE_INPUT;
21332  var CAN_USE_DOM3 = mod3.CAN_USE_DOM;
21333  var IS_ANDROID3 = mod3.IS_ANDROID;
21334  var IS_ANDROID_CHROME3 = mod3.IS_ANDROID_CHROME;
21335  var IS_APPLE3 = mod3.IS_APPLE;
21336  var IS_APPLE_WEBKIT3 = mod3.IS_APPLE_WEBKIT;
21337  var IS_CHROME3 = mod3.IS_CHROME;
21338  var IS_FIREFOX3 = mod3.IS_FIREFOX;
21339  var IS_IOS3 = mod3.IS_IOS;
21340  var IS_SAFARI3 = mod3.IS_SAFARI;
21341  var addClassNamesToElement3 = mod3.addClassNamesToElement;
21342  var calculateZoomLevel2 = mod3.calculateZoomLevel;
21343  var isBlockDomNode3 = mod3.isBlockDomNode;
21344  var isHTMLAnchorElement3 = mod3.isHTMLAnchorElement;
21345  var isHTMLElement3 = mod3.isHTMLElement;
21346  var isInlineDomNode3 = mod3.isInlineDomNode;
21347  var isMimeType2 = mod3.isMimeType;
21348  var makeStateWrapper2 = mod3.makeStateWrapper;
21349  var markSelection2 = mod3.markSelection;
21350  var mediaFileReader2 = mod3.mediaFileReader;
21351  var mergeRegister3 = mod3.mergeRegister;
21352  var objectKlassEquals2 = mod3.objectKlassEquals;
21353  var positionNodeOnRange = mod3.positionNodeOnRange;
21354  var registerNestedElementResolver2 = mod3.registerNestedElementResolver;
21355  var removeClassNamesFromElement3 = mod3.removeClassNamesFromElement;
21356  var selectionAlwaysOnDisplay2 = mod3.selectionAlwaysOnDisplay;
21357
21358  
vendor: 54,201 bytes, lines 21358-23024
21358// node_modules/@lexical/extension/LexicalExtension.dev.mjs
21359  var LexicalExtension_dev_exports = {};
21360  __export(LexicalExtension_dev_exports, {
21361    $createHorizontalRuleNode: () => $createHorizontalRuleNode,
21362    $isDecoratorTextNode: () => $isDecoratorTextNode,
21363    $isHorizontalRuleNode: () => $isHorizontalRuleNode,
21364    AutoFocusExtension: () => AutoFocusExtension,
21365    ClearEditorExtension: () => ClearEditorExtension,
21366    DecoratorTextExtension: () => DecoratorTextExtension,
21367    DecoratorTextNode: () => DecoratorTextNode,
21368    EditorStateExtension: () => EditorStateExtension,
21369    HorizontalRuleExtension: () => HorizontalRuleExtension,
21370    HorizontalRuleNode: () => HorizontalRuleNode,
21371    INSERT_HORIZONTAL_RULE_COMMAND: () => INSERT_HORIZONTAL_RULE_COMMAND,
21372    InitialStateExtension: () => InitialStateExtension,
21373    LexicalBuilder: () => LexicalBuilder,
21374    NestedEditorExtension: () => NestedEditorExtension,
21375    NodeSelectionExtension: () => NodeSelectionExtension,
21376    SelectionAlwaysOnDisplayExtension: () => SelectionAlwaysOnDisplayExtension,
21377    TabIndentationExtension: () => TabIndentationExtension,
21378    applyFormatFromStyle: () => applyFormatFromStyle,
21379    applyFormatToDom: () => applyFormatToDom,
21380    batch: () => n,
21381    buildEditorFromExtensions: () => buildEditorFromExtensions,
21382    computed: () => g,
21383    configExtension: () => configExtension2,
21384    declarePeerDependency: () => declarePeerDependency2,
21385    defineExtension: () => defineExtension2,
21386    effect: () => j,
21387    getExtensionDependencyFromEditor: () => getExtensionDependencyFromEditor,
21388    getKnownTypesAndNodes: () => getKnownTypesAndNodes,
21389    getPeerDependencyFromEditor: () => getPeerDependencyFromEditor,
21390    getPeerDependencyFromEditorOrThrow: () => getPeerDependencyFromEditorOrThrow,
21391    namedSignals: () => namedSignals,
21392    registerClearEditor: () => registerClearEditor,
21393    registerTabIndentation: () => registerTabIndentation,
21394    safeCast: () => safeCast2,
21395    shallowMergeConfig: () => shallowMergeConfig2,
21396    signal: () => a,
21397    untracked: () => h,
21398    watchedSignal: () => watchedSignal
21399  });
21400  var i = Symbol.for("preact-signals");
21401  function t() {
21402    if (e > 1) {
21403      e--;
21404      return;
21405    }
21406    let i2, t2 = false;
21407    !function() {
21408      let i3 = r;
21409      r = void 0;
21410      while (void 0 !== i3) {
21411        if (i3.S.v === i3.v) i3.S.i = i3.i;
21412        i3 = i3.o;
21413      }
21414    }();
21415    while (void 0 !== s) {
21416      let n2 = s;
21417      s = void 0;
21418      u++;
21419      while (void 0 !== n2) {
21420        const o2 = n2.u;
21421        n2.u = void 0;
21422        n2.f &= -3;
21423        if (!(8 & n2.f) && w(n2)) try {
21424          n2.c();
21425        } catch (n3) {
21426          if (!t2) {
21427            i2 = n3;
21428            t2 = true;
21429          }
21430        }
21431        n2 = o2;
21432      }
21433    }
21434    u = 0;
21435    e--;
21436    if (t2) throw i2;
21437  }
21438  function n(i2) {
21439    if (e > 0) return i2();
21440    d = ++c;
21441    e++;
21442    try {
21443      return i2();
21444    } finally {
21445      t();
21446    }
21447  }
21448  var o;
21449  var s;
21450  function h(i2) {
21451    const t2 = o;
21452    o = void 0;
21453    try {
21454      return i2();
21455    } finally {
21456      o = t2;
21457    }
21458  }
21459  var r;
21460  var e = 0;
21461  var u = 0;
21462  var c = 0;
21463  var d = 0;
21464  var v = 0;
21465  function l(i2) {
21466    if (void 0 === o) return;
21467    let t2 = i2.n;
21468    if (void 0 === t2 || t2.t !== o) {
21469      t2 = { i: 0, S: i2, p: o.s, n: void 0, t: o, e: void 0, x: void 0, r: t2 };
21470      if (void 0 !== o.s) o.s.n = t2;
21471      o.s = t2;
21472      i2.n = t2;
21473      if (32 & o.f) i2.S(t2);
21474      return t2;
21475    } else if (-1 === t2.i) {
21476      t2.i = 0;
21477      if (void 0 !== t2.n) {
21478        t2.n.p = t2.p;
21479        if (void 0 !== t2.p) t2.p.n = t2.n;
21480        t2.p = o.s;
21481        t2.n = void 0;
21482        o.s.n = t2;
21483        o.s = t2;
21484      }
21485      return t2;
21486    }
21487  }
21488  function y(i2, t2) {
21489    this.v = i2;
21490    this.i = 0;
21491    this.n = void 0;
21492    this.t = void 0;
21493    this.l = 0;
21494    this.W = null == t2 ? void 0 : t2.watched;
21495    this.Z = null == t2 ? void 0 : t2.unwatched;
21496    this.name = null == t2 ? void 0 : t2.name;
21497  }
21498  y.prototype.brand = i;
21499  y.prototype.h = function() {
21500    return true;
21501  };
21502  y.prototype.S = function(i2) {
21503    const t2 = this.t;
21504    if (t2 !== i2 && void 0 === i2.e) {
21505      i2.x = t2;
21506      this.t = i2;
21507      if (void 0 !== t2) t2.e = i2;
21508      else h(() => {
21509        var i3;
21510        null == (i3 = this.W) || i3.call(this);
21511      });
21512    }
21513  };
21514  y.prototype.U = function(i2) {
21515    if (void 0 !== this.t) {
21516      const t2 = i2.e, n2 = i2.x;
21517      if (void 0 !== t2) {
21518        t2.x = n2;
21519        i2.e = void 0;
21520      }
21521      if (void 0 !== n2) {
21522        n2.e = t2;
21523        i2.x = void 0;
21524      }
21525      if (i2 === this.t) {
21526        this.t = n2;
21527        if (void 0 === n2) h(() => {
21528          var i3;
21529          null == (i3 = this.Z) || i3.call(this);
21530        });
21531      }
21532    }
21533  };
21534  y.prototype.subscribe = function(i2) {
21535    return j(() => {
21536      const t2 = this.value, n2 = o;
21537      o = void 0;
21538      try {
21539        i2(t2);
21540      } finally {
21541        o = n2;
21542      }
21543    }, { name: "sub" });
21544  };
21545  y.prototype.valueOf = function() {
21546    return this.value;
21547  };
21548  y.prototype.toString = function() {
21549    return this.value + "";
21550  };
21551  y.prototype.toJSON = function() {
21552    return this.value;
21553  };
21554  y.prototype.peek = function() {
21555    const i2 = o;
21556    o = void 0;
21557    try {
21558      return this.value;
21559    } finally {
21560      o = i2;
21561    }
21562  };
21563  Object.defineProperty(y.prototype, "value", { get() {
21564    const i2 = l(this);
21565    if (void 0 !== i2) i2.i = this.i;
21566    return this.v;
21567  }, set(i2) {
21568    if (i2 !== this.v) {
21569      if (u > 100) throw new Error("Cycle detected");
21570      !function(i3) {
21571        if (0 !== e && 0 === u) {
21572          if (i3.l !== d) {
21573            i3.l = d;
21574            r = { S: i3, v: i3.v, i: i3.i, o: r };
21575          }
21576        }
21577      }(this);
21578      this.v = i2;
21579      this.i++;
21580      v++;
21581      e++;
21582      try {
21583        for (let i3 = this.t; void 0 !== i3; i3 = i3.x) i3.t.N();
21584      } finally {
21585        t();
21586      }
21587    }
21588  } });
21589  function a(i2, t2) {
21590    return new y(i2, t2);
21591  }
21592  function w(i2) {
21593    for (let t2 = i2.s; void 0 !== t2; t2 = t2.n) if (t2.S.i !== t2.i || !t2.S.h() || t2.S.i !== t2.i) return true;
21594    return false;
21595  }
21596  function _(i2) {
21597    for (let t2 = i2.s; void 0 !== t2; t2 = t2.n) {
21598      const n2 = t2.S.n;
21599      if (void 0 !== n2) t2.r = n2;
21600      t2.S.n = t2;
21601      t2.i = -1;
21602      if (void 0 === t2.n) {
21603        i2.s = t2;
21604        break;
21605      }
21606    }
21607  }
21608  function b(i2) {
21609    let t2, n2 = i2.s;
21610    while (void 0 !== n2) {
21611      const i3 = n2.p;
21612      if (-1 === n2.i) {
21613        n2.S.U(n2);
21614        if (void 0 !== i3) i3.n = n2.n;
21615        if (void 0 !== n2.n) n2.n.p = i3;
21616      } else t2 = n2;
21617      n2.S.n = n2.r;
21618      if (void 0 !== n2.r) n2.r = void 0;
21619      n2 = i3;
21620    }
21621    i2.s = t2;
21622  }
21623  function p(i2, t2) {
21624    y.call(this, void 0);
21625    this.x = i2;
21626    this.s = void 0;
21627    this.g = v - 1;
21628    this.f = 4;
21629    this.W = null == t2 ? void 0 : t2.watched;
21630    this.Z = null == t2 ? void 0 : t2.unwatched;
21631    this.name = null == t2 ? void 0 : t2.name;
21632  }
21633  p.prototype = new y();
21634  p.prototype.h = function() {
21635    this.f &= -3;
21636    if (1 & this.f) return false;
21637    if (32 == (36 & this.f)) return true;
21638    this.f &= -5;
21639    if (this.g === v) return true;
21640    this.g = v;
21641    this.f |= 1;
21642    if (this.i > 0 && !w(this)) {
21643      this.f &= -2;
21644      return true;
21645    }
21646    const i2 = o;
21647    try {
21648      _(this);
21649      o = this;
21650      const i3 = this.x();
21651      if (16 & this.f || this.v !== i3 || 0 === this.i) {
21652        this.v = i3;
21653        this.f &= -17;
21654        this.i++;
21655      }
21656    } catch (i3) {
21657      this.v = i3;
21658      this.f |= 16;
21659      this.i++;
21660    }
21661    o = i2;
21662    b(this);
21663    this.f &= -2;
21664    return true;
21665  };
21666  p.prototype.S = function(i2) {
21667    if (void 0 === this.t) {
21668      this.f |= 36;
21669      for (let i3 = this.s; void 0 !== i3; i3 = i3.n) i3.S.S(i3);
21670    }
21671    y.prototype.S.call(this, i2);
21672  };
21673  p.prototype.U = function(i2) {
21674    if (void 0 !== this.t) {
21675      y.prototype.U.call(this, i2);
21676      if (void 0 === this.t) {
21677        this.f &= -33;
21678        for (let i3 = this.s; void 0 !== i3; i3 = i3.n) i3.S.U(i3);
21679      }
21680    }
21681  };
21682  p.prototype.N = function() {
21683    if (!(2 & this.f)) {
21684      this.f |= 6;
21685      for (let i2 = this.t; void 0 !== i2; i2 = i2.x) i2.t.N();
21686    }
21687  };
21688  Object.defineProperty(p.prototype, "value", { get() {
21689    if (1 & this.f) throw new Error("Cycle detected");
21690    const i2 = l(this);
21691    this.h();
21692    if (void 0 !== i2) i2.i = this.i;
21693    if (16 & this.f) throw this.v;
21694    return this.v;
21695  } });
21696  function g(i2, t2) {
21697    return new p(i2, t2);
21698  }
21699  function S(i2) {
21700    const n2 = i2.m;
21701    i2.m = void 0;
21702    if ("function" == typeof n2) {
21703      e++;
21704      const s2 = o;
21705      o = void 0;
21706      try {
21707        n2();
21708      } catch (t2) {
21709        i2.f &= -2;
21710        i2.f |= 8;
21711        m(i2);
21712        throw t2;
21713      } finally {
21714        o = s2;
21715        t();
21716      }
21717    }
21718  }
21719  function m(i2) {
21720    for (let t2 = i2.s; void 0 !== t2; t2 = t2.n) t2.S.U(t2);
21721    i2.x = void 0;
21722    i2.s = void 0;
21723    S(i2);
21724  }
21725  function x(i2) {
21726    if (o !== this) throw new Error("Out-of-order effect");
21727    b(this);
21728    o = i2;
21729    this.f &= -2;
21730    if (8 & this.f) m(this);
21731    t();
21732  }
21733  function E(i2, t2) {
21734    this.x = i2;
21735    this.m = void 0;
21736    this.s = void 0;
21737    this.u = void 0;
21738    this.f = 32;
21739    this.name = null == t2 ? void 0 : t2.name;
21740  }
21741  E.prototype.c = function() {
21742    const i2 = this.S();
21743    try {
21744      if (8 & this.f) return;
21745      if (void 0 === this.x) return;
21746      const t2 = this.x();
21747      if ("function" == typeof t2) this.m = t2;
21748    } finally {
21749      i2();
21750    }
21751  };
21752  E.prototype.S = function() {
21753    if (1 & this.f) throw new Error("Cycle detected");
21754    this.f |= 1;
21755    this.f &= -9;
21756    S(this);
21757    _(this);
21758    e++;
21759    const i2 = o;
21760    o = this;
21761    return x.bind(this, i2);
21762  };
21763  E.prototype.N = function() {
21764    if (!(2 & this.f)) {
21765      this.f |= 2;
21766      this.u = s;
21767      s = this;
21768    }
21769  };
21770  E.prototype.d = function() {
21771    this.f |= 8;
21772    if (!(1 & this.f)) m(this);
21773  };
21774  E.prototype.dispose = function() {
21775    this.d();
21776  };
21777  function j(i2, t2) {
21778    const n2 = new E(i2, t2);
21779    try {
21780      n2.c();
21781    } catch (i3) {
21782      n2.d();
21783      throw i3;
21784    }
21785    const o2 = n2.d.bind(n2);
21786    o2[Symbol.dispose] = o2;
21787    return o2;
21788  }
21789  function namedSignals(defaults, opts = {}) {
21790    const initial = {};
21791    for (const k2 in defaults) {
21792      const v3 = opts[k2];
21793      const store = a(v3 === void 0 ? defaults[k2] : v3);
21794      initial[k2] = store;
21795    }
21796    return initial;
21797  }
21798  var AutoFocusExtension = defineExtension2({
21799    build: (editor, config, state) => {
21800      return namedSignals(config);
21801    },
21802    config: safeCast2({
21803      defaultSelection: "rootEnd",
21804      disabled: false
21805    }),
21806    name: "@lexical/extension/AutoFocus",
21807    register(editor, config, state) {
21808      const stores = state.getOutput();
21809      return j(() => stores.disabled.value ? void 0 : editor.registerRootListener((rootElement) => {
21810        editor.focus(() => {
21811          const activeElement = document.activeElement;
21812          if (rootElement !== null && (activeElement === null || !rootElement.contains(activeElement))) {
21813            rootElement.focus({
21814              preventScroll: true
21815            });
21816          }
21817        }, {
21818          defaultSelection: stores.defaultSelection.peek()
21819        });
21820      }));
21821    }
21822  });
21823  function $defaultOnClear() {
21824    const root = $getRoot2();
21825    const selection = $getSelection2();
21826    const paragraph = $createParagraphNode2();
21827    root.clear();
21828    root.append(paragraph);
21829    if (selection !== null) {
21830      paragraph.select();
21831    }
21832    if ($isRangeSelection2(selection)) {
21833      selection.format = 0;
21834    }
21835  }
21836  function registerClearEditor(editor, $onClear = $defaultOnClear) {
21837    return editor.registerCommand(CLEAR_EDITOR_COMMAND2, (payload) => {
21838      editor.update($onClear);
21839      return true;
21840    }, COMMAND_PRIORITY_EDITOR2);
21841  }
21842  var ClearEditorExtension = defineExtension2({
21843    build(editor, config, state) {
21844      return namedSignals(config);
21845    },
21846    config: safeCast2({
21847      $onClear: $defaultOnClear
21848    }),
21849    name: "@lexical/extension/ClearEditor",
21850    register(editor, config, state) {
21851      const {
21852        $onClear
21853      } = state.getOutput();
21854      return j(() => registerClearEditor(editor, $onClear.value));
21855    }
21856  });
21857  function getKnownTypesAndNodes(config) {
21858    const types = /* @__PURE__ */ new Set();
21859    const nodes = /* @__PURE__ */ new Set();
21860    for (const klassOrReplacement of getNodeConfig(config)) {
21861      const klass = typeof klassOrReplacement === "function" ? klassOrReplacement : klassOrReplacement.replace;
21862      void getStaticNodeConfig2(klass);
21863      types.add(klass.getType());
21864      nodes.add(klass);
21865    }
21866    return {
21867      nodes,
21868      types
21869    };
21870  }
21871  function getNodeConfig(config) {
21872    return (typeof config.nodes === "function" ? config.nodes() : config.nodes) || [];
21873  }
21874  var formatState = createState2("format", {
21875    parse: (value) => typeof value === "number" ? value : 0
21876  });
21877  var DecoratorTextNode = class extends DecoratorNode2 {
21878    $config() {
21879      return this.config("decorator-text", {
21880        extends: DecoratorNode2,
21881        stateConfigs: [{
21882          flat: true,
21883          stateConfig: formatState
21884        }]
21885      });
21886    }
21887    getFormat() {
21888      return $getState2(this, formatState);
21889    }
21890    getFormatFlags(type, alignWithFormat) {
21891      return toggleTextFormatType2(this.getFormat(), type, alignWithFormat);
21892    }
21893    hasFormat(type) {
21894      const formatFlag = TEXT_TYPE_TO_FORMAT2[type];
21895      return (this.getFormat() & formatFlag) !== 0;
21896    }
21897    setFormat(type) {
21898      return $setState2(this, formatState, type);
21899    }
21900    toggleFormat(type) {
21901      const format = this.getFormat();
21902      const newFormat = toggleTextFormatType2(format, type, null);
21903      return this.setFormat(newFormat);
21904    }
21905    isInline() {
21906      return true;
21907    }
21908    createDOM() {
21909      return document.createElement("span");
21910    }
21911    updateDOM() {
21912      return false;
21913    }
21914  };
21915  function $isDecoratorTextNode(node) {
21916    return node instanceof DecoratorTextNode;
21917  }
21918  function applyFormatFromStyle(lexicalNode, style, shouldApply) {
21919    const fontWeight = style.fontWeight;
21920    const textDecoration = style.textDecoration.split(" ");
21921    const hasBoldFontWeight = fontWeight === "700" || fontWeight === "bold";
21922    const hasLinethroughTextDecoration = textDecoration.includes("line-through");
21923    const hasItalicFontStyle = style.fontStyle === "italic";
21924    const hasUnderlineTextDecoration = textDecoration.includes("underline");
21925    const verticalAlign = style.verticalAlign;
21926    if (hasBoldFontWeight && !lexicalNode.hasFormat("bold")) {
21927      lexicalNode.toggleFormat("bold");
21928    }
21929    if (hasLinethroughTextDecoration && !lexicalNode.hasFormat("strikethrough")) {
21930      lexicalNode.toggleFormat("strikethrough");
21931    }
21932    if (hasItalicFontStyle && !lexicalNode.hasFormat("italic")) {
21933      lexicalNode.toggleFormat("italic");
21934    }
21935    if (hasUnderlineTextDecoration && !lexicalNode.hasFormat("underline")) {
21936      lexicalNode.toggleFormat("underline");
21937    }
21938    if (verticalAlign === "sub" && !lexicalNode.hasFormat("subscript")) {
21939      lexicalNode.toggleFormat("subscript");
21940    }
21941    if (verticalAlign === "super" && !lexicalNode.hasFormat("superscript")) {
21942      lexicalNode.toggleFormat("superscript");
21943    }
21944    if (shouldApply && !lexicalNode.hasFormat(shouldApply)) {
21945      lexicalNode.toggleFormat(shouldApply);
21946    }
21947    return lexicalNode;
21948  }
21949  function applyFormatToDom(lexicalNode, domNode, tagNameToFormat = DEFAULT_TAG_NAME_TO_FORMAT) {
21950    for (const [tag, format] of Object.entries(tagNameToFormat)) {
21951      if (lexicalNode.hasFormat(format)) {
21952        domNode = wrapElementWith2(domNode, tag);
21953      }
21954    }
21955    return domNode;
21956  }
21957  function wrapElementWith2(element, tag) {
21958    const el = document.createElement(tag);
21959    el.appendChild(element);
21960    return el;
21961  }
21962  var DEFAULT_TAG_NAME_TO_FORMAT = {
21963    b: "bold",
21964    code: "code",
21965    em: "italic",
21966    i: "italic",
21967    mark: "highlight",
21968    s: "strikethrough",
21969    strong: "bold",
21970    sub: "subscript",
21971    sup: "superscript",
21972    u: "underline"
21973  };
21974  var DecoratorTextExtension = defineExtension2({
21975    name: "@lexical/extension/DecoratorText",
21976    nodes: () => [DecoratorTextNode],
21977    register(editor, config, state) {
21978      return editor.registerCommand(FORMAT_TEXT_COMMAND2, (formatType) => {
21979        const selection = $getSelection2();
21980        if ($isNodeSelection2(selection) || $isRangeSelection2(selection)) {
21981          for (const node of selection.getNodes()) {
21982            if ($isDecoratorTextNode(node)) {
21983              node.toggleFormat(formatType);
21984            }
21985          }
21986        }
21987        return false;
21988      }, COMMAND_PRIORITY_LOW2);
21989    }
21990  });
21991  function watchedSignal(getSnapshot, register) {
21992    let dispose;
21993    return a(getSnapshot(), {
21994      unwatched() {
21995        if (dispose) {
21996          dispose();
21997          dispose = void 0;
21998        }
21999      },
22000      watched() {
22001        this.value = getSnapshot();
22002        dispose = register(this);
22003      }
22004    });
22005  }
22006  var EditorStateExtension = defineExtension2({
22007    build(editor) {
22008      return watchedSignal(() => editor.getEditorState(), (editorStateSignal) => editor.registerUpdateListener((payload) => {
22009        editorStateSignal.value = payload.editorState;
22010      }));
22011    },
22012    name: "@lexical/extension/EditorState"
22013  });
22014  function formatDevErrorMessage4(message) {
22015    throw new Error(message);
22016  }
22017  function deepThemeMergeInPlace(a2, b3) {
22018    if (a2 && b3 && !Array.isArray(b3) && typeof a2 === "object" && typeof b3 === "object") {
22019      const aObj = a2;
22020      const bObj = b3;
22021      for (const k2 in bObj) {
22022        aObj[k2] = deepThemeMergeInPlace(aObj[k2], bObj[k2]);
22023      }
22024      return a2;
22025    }
22026    return b3;
22027  }
22028  var ExtensionRepStateIds = {
22029    /* eslint-disable sort-keys-fix/sort-keys-fix */
22030    unmarked: 0,
22031    temporary: 1,
22032    permanent: 2,
22033    configured: 3,
22034    initialized: 4,
22035    built: 5,
22036    registered: 6,
22037    afterRegistration: 7
22038    /* eslint-enable sort-keys-fix/sort-keys-fix */
22039  };
22040  function isExactlyUnmarkedExtensionRepState(state) {
22041    return state.id === ExtensionRepStateIds.unmarked;
22042  }
22043  function isExactlyTemporaryExtensionRepState(state) {
22044    return state.id === ExtensionRepStateIds.temporary;
22045  }
22046  function isExactlyPermanentExtensionRepState(state) {
22047    return state.id === ExtensionRepStateIds.permanent;
22048  }
22049  function isConfiguredExtensionRepState(state) {
22050    return state.id >= ExtensionRepStateIds.configured;
22051  }
22052  function isInitializedExtensionRepState(state) {
22053    return state.id >= ExtensionRepStateIds.initialized;
22054  }
22055  function isBuiltExtensionRepState(state) {
22056    return state.id >= ExtensionRepStateIds.built;
22057  }
22058  function isAfterRegistrationState(state) {
22059    return state.id >= ExtensionRepStateIds.afterRegistration;
22060  }
22061  function applyTemporaryMark(state) {
22062    if (!isExactlyUnmarkedExtensionRepState(state)) {
22063      formatDevErrorMessage4(`LexicalBuilder: Can not apply a temporary mark from state id ${String(state.id)} (expected ${String(ExtensionRepStateIds.unmarked)} unmarked)`);
22064    }
22065    return Object.assign(state, {
22066      id: ExtensionRepStateIds.temporary
22067    });
22068  }
22069  function applyPermanentMark(state) {
22070    if (!isExactlyTemporaryExtensionRepState(state)) {
22071      formatDevErrorMessage4(`LexicalBuilder: Can not apply a permanent mark from state id ${String(state.id)} (expected ${String(ExtensionRepStateIds.temporary)} temporary)`);
22072    }
22073    return Object.assign(state, {
22074      id: ExtensionRepStateIds.permanent
22075    });
22076  }
22077  function applyConfiguredState(state, config, registerState) {
22078    return Object.assign(state, {
22079      config,
22080      id: ExtensionRepStateIds.configured,
22081      registerState
22082    });
22083  }
22084  function applyInitializedState(state, initResult, registerState) {
22085    return Object.assign(state, {
22086      id: ExtensionRepStateIds.initialized,
22087      initResult,
22088      registerState
22089    });
22090  }
22091  function applyBuiltState(state, output, registerState) {
22092    return Object.assign(state, {
22093      id: ExtensionRepStateIds.built,
22094      output,
22095      registerState
22096    });
22097  }
22098  function applyRegisteredState(state) {
22099    return Object.assign(state, {
22100      id: ExtensionRepStateIds.registered
22101    });
22102  }
22103  function applyAfterRegistrationState(state) {
22104    return Object.assign(state, {
22105      id: ExtensionRepStateIds.afterRegistration
22106    });
22107  }
22108  function rollbackToBuiltState(state) {
22109    return Object.assign(state, {
22110      id: ExtensionRepStateIds.built
22111    });
22112  }
22113  var emptySet = /* @__PURE__ */ new Set();
22114  var ExtensionRep = class {
22115    builder;
22116    configs;
22117    _dependency;
22118    _peerNameSet;
22119    extension;
22120    state;
22121    _signal;
22122    constructor(builder, extension) {
22123      this.builder = builder;
22124      this.extension = extension;
22125      this.configs = /* @__PURE__ */ new Set();
22126      this.state = {
22127        id: ExtensionRepStateIds.unmarked
22128      };
22129    }
22130    mergeConfigs() {
22131      let config = this.extension.config || {};
22132      const mergeConfig = this.extension.mergeConfig ? this.extension.mergeConfig.bind(this.extension) : shallowMergeConfig2;
22133      for (const cfg of this.configs) {
22134        config = mergeConfig(config, cfg);
22135      }
22136      return config;
22137    }
22138    init(editorConfig) {
22139      const initialState = this.state;
22140      if (!isExactlyPermanentExtensionRepState(initialState)) {
22141        formatDevErrorMessage4(`ExtensionRep: Can not configure from state id ${String(initialState.id)}`);
22142      }
22143      const initState = {
22144        getDependency: this.getInitDependency.bind(this),
22145        getDirectDependentNames: this.getDirectDependentNames.bind(this),
22146        getPeer: this.getInitPeer.bind(this),
22147        getPeerNameSet: this.getPeerNameSet.bind(this)
22148      };
22149      const buildState = {
22150        ...initState,
22151        getDependency: this.getDependency.bind(this),
22152        getInitResult: this.getInitResult.bind(this),
22153        getPeer: this.getPeer.bind(this)
22154      };
22155      const state = applyConfiguredState(initialState, this.mergeConfigs(), initState);
22156      this.state = state;
22157      let initResult;
22158      if (this.extension.init) {
22159        initResult = this.extension.init(editorConfig, state.config, initState);
22160      }
22161      this.state = applyInitializedState(state, initResult, buildState);
22162    }
22163    build(editor) {
22164      const state = this.state;
22165      if (!(state.id === ExtensionRepStateIds.initialized)) {
22166        formatDevErrorMessage4(`ExtensionRep: register called in state id ${String(state.id)} (expected ${String(ExtensionRepStateIds.built)} initialized)`);
22167      }
22168      let output;
22169      if (this.extension.build) {
22170        output = this.extension.build(editor, state.config, state.registerState);
22171      }
22172      const registerState = {
22173        ...state.registerState,
22174        getOutput: () => output,
22175        getSignal: this.getSignal.bind(this)
22176      };
22177      this.state = applyBuiltState(state, output, registerState);
22178    }
22179    register(editor, signal2) {
22180      this._signal = signal2;
22181      const state = this.state;
22182      if (!(state.id === ExtensionRepStateIds.built)) {
22183        formatDevErrorMessage4(`ExtensionRep: register called in state id ${String(state.id)} (expected ${String(ExtensionRepStateIds.built)} built)`);
22184      }
22185      const cleanup = this.extension.register && this.extension.register(editor, state.config, state.registerState);
22186      this.state = applyRegisteredState(state);
22187      return () => {
22188        const afterRegistrationState = this.state;
22189        if (!(afterRegistrationState.id === ExtensionRepStateIds.afterRegistration)) {
22190          formatDevErrorMessage4(`ExtensionRep: rollbackToBuiltState called in state id ${String(state.id)} (expected ${String(ExtensionRepStateIds.afterRegistration)} afterRegistration)`);
22191        }
22192        this.state = rollbackToBuiltState(afterRegistrationState);
22193        if (cleanup) {
22194          cleanup();
22195        }
22196      };
22197    }
22198    afterRegistration(editor) {
22199      const state = this.state;
22200      if (!(state.id === ExtensionRepStateIds.registered)) {
22201        formatDevErrorMessage4(`ExtensionRep: afterRegistration called in state id ${String(state.id)} (expected ${String(ExtensionRepStateIds.registered)} registered)`);
22202      }
22203      let rval;
22204      if (this.extension.afterRegistration) {
22205        rval = this.extension.afterRegistration(editor, state.config, state.registerState);
22206      }
22207      this.state = applyAfterRegistrationState(state);
22208      return rval;
22209    }
22210    getSignal() {
22211      if (!(this._signal !== void 0)) {
22212        formatDevErrorMessage4(`ExtensionRep.getSignal() called before register`);
22213      }
22214      return this._signal;
22215    }
22216    getInitResult() {
22217      if (!(this.extension.init !== void 0)) {
22218        formatDevErrorMessage4(`ExtensionRep: getInitResult() called for Extension ${this.extension.name} that does not define init`);
22219      }
22220      const state = this.state;
22221      if (!isInitializedExtensionRepState(state)) {
22222        formatDevErrorMessage4(`ExtensionRep: getInitResult() called for ExtensionRep in state id ${String(state.id)} < ${String(ExtensionRepStateIds.initialized)} (initialized)`);
22223      }
22224      return state.initResult;
22225    }
22226    getInitPeer(name) {
22227      const rep = this.builder.extensionNameMap.get(name);
22228      return rep ? rep.getExtensionInitDependency() : void 0;
22229    }
22230    getExtensionInitDependency() {
22231      const state = this.state;
22232      if (!isConfiguredExtensionRepState(state)) {
22233        formatDevErrorMessage4(`ExtensionRep: getExtensionInitDependency called in state id ${String(state.id)} (expected >= ${String(ExtensionRepStateIds.configured)} configured)`);
22234      }
22235      return {
22236        config: state.config
22237      };
22238    }
22239    getPeer(name) {
22240      const rep = this.builder.extensionNameMap.get(name);
22241      return rep ? rep.getExtensionDependency() : void 0;
22242    }
22243    getInitDependency(dep) {
22244      const rep = this.builder.getExtensionRep(dep);
22245      if (!(rep !== void 0)) {
22246        formatDevErrorMessage4(`LexicalExtensionBuilder: Extension ${this.extension.name} missing dependency extension ${dep.name} to be in registry`);
22247      }
22248      return rep.getExtensionInitDependency();
22249    }
22250    getDependency(dep) {
22251      const rep = this.builder.getExtensionRep(dep);
22252      if (!(rep !== void 0)) {
22253        formatDevErrorMessage4(`LexicalExtensionBuilder: Extension ${this.extension.name} missing dependency extension ${dep.name} to be in registry`);
22254      }
22255      return rep.getExtensionDependency();
22256    }
22257    getState() {
22258      const state = this.state;
22259      if (!isAfterRegistrationState(state)) {
22260        formatDevErrorMessage4(`ExtensionRep getState called in state id ${String(state.id)} (expected ${String(ExtensionRepStateIds.afterRegistration)} afterRegistration)`);
22261      }
22262      return state;
22263    }
22264    getDirectDependentNames() {
22265      return this.builder.incomingEdges.get(this.extension.name) || emptySet;
22266    }
22267    getPeerNameSet() {
22268      let s2 = this._peerNameSet;
22269      if (!s2) {
22270        s2 = new Set((this.extension.peerDependencies || []).map(([name]) => name));
22271        this._peerNameSet = s2;
22272      }
22273      return s2;
22274    }
22275    getExtensionDependency() {
22276      if (!this._dependency) {
22277        const state = this.state;
22278        if (!isBuiltExtensionRepState(state)) {
22279          formatDevErrorMessage4(`Extension ${this.extension.name} used as a dependency before build`);
22280        }
22281        this._dependency = {
22282          config: state.config,
22283          init: state.initResult,
22284          output: state.output
22285        };
22286      }
22287      return this._dependency;
22288    }
22289  };
22290  var HISTORY_MERGE_OPTIONS = {
22291    tag: HISTORY_MERGE_TAG2
22292  };
22293  function $defaultInitializer() {
22294    const root = $getRoot2();
22295    if (root.isEmpty()) {
22296      root.append($createParagraphNode2());
22297    }
22298  }
22299  var InitialStateExtension = defineExtension2({
22300    config: safeCast2({
22301      setOptions: HISTORY_MERGE_OPTIONS,
22302      updateOptions: HISTORY_MERGE_OPTIONS
22303    }),
22304    init({
22305      $initialEditorState = $defaultInitializer
22306    }) {
22307      return {
22308        $initialEditorState,
22309        initialized: false
22310      };
22311    },
22312    // eslint-disable-next-line sort-keys-fix/sort-keys-fix -- typescript inference is order dependent here for some reason
22313    afterRegistration(editor, {
22314      updateOptions,
22315      setOptions
22316    }, state) {
22317      const initResult = state.getInitResult();
22318      if (!initResult.initialized) {
22319        initResult.initialized = true;
22320        const {
22321          $initialEditorState
22322        } = initResult;
22323        if ($isEditorState2($initialEditorState)) {
22324          editor.setEditorState($initialEditorState, setOptions);
22325        } else if (typeof $initialEditorState === "function") {
22326          editor.update(() => {
22327            $initialEditorState(editor);
22328          }, updateOptions);
22329        } else if ($initialEditorState && (typeof $initialEditorState === "string" || typeof $initialEditorState === "object")) {
22330          const parsedEditorState = editor.parseEditorState($initialEditorState);
22331          editor.setEditorState(parsedEditorState, setOptions);
22332        }
22333      }
22334      return () => {
22335      };
22336    },
22337    name: "@lexical/extension/InitialState",
22338    // These are automatically added by createEditor, we add them here so they are
22339    // visible during extensionRep.init so extensions can see all known types before the
22340    // editor is created.
22341    // (excluding ArtificialNode__DO_NOT_USE because it isn't really public API
22342    // and shouldn't change anything)
22343    nodes: [RootNode2, TextNode2, LineBreakNode2, TabNode2, ParagraphNode2]
22344  });
22345  var builderSymbol = Symbol.for("@lexical/extension/LexicalBuilder");
22346  function buildEditorFromExtensions(...extensions) {
22347    return LexicalBuilder.fromExtensions(extensions).buildEditor();
22348  }
22349  function noop() {
22350  }
22351  function defaultOnError(err) {
22352    throw err;
22353  }
22354  function maybeWithBuilder(editor) {
22355    return editor;
22356  }
22357  function normalizeExtensionArgument(arg) {
22358    return Array.isArray(arg) ? arg : [arg];
22359  }
22360  var PACKAGE_VERSION = "0.44.0+dev.esm";
22361  var LexicalBuilder = class _LexicalBuilder {
22362    roots;
22363    extensionNameMap;
22364    outgoingConfigEdges;
22365    incomingEdges;
22366    conflicts;
22367    _sortedExtensionReps;
22368    PACKAGE_VERSION;
22369    constructor(roots) {
22370      this.outgoingConfigEdges = /* @__PURE__ */ new Map();
22371      this.incomingEdges = /* @__PURE__ */ new Map();
22372      this.extensionNameMap = /* @__PURE__ */ new Map();
22373      this.conflicts = /* @__PURE__ */ new Map();
22374      this.PACKAGE_VERSION = PACKAGE_VERSION;
22375      this.roots = roots;
22376      for (const extension of roots) {
22377        this.addExtension(extension);
22378      }
22379    }
22380    static fromExtensions(extensions) {
22381      const roots = [normalizeExtensionArgument(InitialStateExtension)];
22382      for (const extension of extensions) {
22383        roots.push(normalizeExtensionArgument(extension));
22384      }
22385      return new _LexicalBuilder(roots);
22386    }
22387    static maybeFromEditor(editor) {
22388      const builder = maybeWithBuilder(editor)[builderSymbol];
22389      if (builder) {
22390        if (!(builder.PACKAGE_VERSION === PACKAGE_VERSION)) {
22391          formatDevErrorMessage4(`LexicalBuilder.fromEditor: The given editor was created with LexicalBuilder ${builder.PACKAGE_VERSION} but this version is ${PACKAGE_VERSION}. A project should have exactly one copy of LexicalBuilder`);
22392        }
22393        if (!(builder instanceof _LexicalBuilder)) {
22394          formatDevErrorMessage4(`LexicalBuilder.fromEditor: There are multiple copies of the same version of LexicalBuilder in your project, and this editor was created with another one. Your project, or one of its dependencies, has its package.json and/or bundler configured incorrectly.`);
22395        }
22396      }
22397      return builder;
22398    }
22399    /** Look up the editor that was created by this LexicalBuilder or throw */
22400    static fromEditor(editor) {
22401      const builder = _LexicalBuilder.maybeFromEditor(editor);
22402      if (!(builder !== void 0)) {
22403        formatDevErrorMessage4(`LexicalBuilder.fromEditor: The given editor was not created with LexicalBuilder`);
22404      }
22405      return builder;
22406    }
22407    constructEditor() {
22408      const {
22409        $initialEditorState: _$initialEditorState,
22410        onError,
22411        ...editorConfig
22412      } = this.buildCreateEditorArgs();
22413      const editor = Object.assign(createEditor2({
22414        ...editorConfig,
22415        ...onError ? {
22416          onError: (err) => {
22417            onError(err, editor);
22418          }
22419        } : {}
22420      }), {
22421        [builderSymbol]: this
22422      });
22423      for (const extensionRep of this.sortedExtensionReps()) {
22424        extensionRep.build(editor);
22425      }
22426      return editor;
22427    }
22428    buildEditor() {
22429      let disposeOnce = noop;
22430      function dispose() {
22431        try {
22432          disposeOnce();
22433        } finally {
22434          disposeOnce = noop;
22435        }
22436      }
22437      const editor = Object.assign(this.constructEditor(), {
22438        dispose,
22439        [Symbol.dispose]: dispose
22440      });
22441      disposeOnce = mergeRegister2(this.registerEditor(editor), () => editor.setRootElement(null));
22442      return editor;
22443    }
22444    hasExtensionByName(name) {
22445      return this.extensionNameMap.has(name);
22446    }
22447    getExtensionRep(extension) {
22448      const rep = this.extensionNameMap.get(extension.name);
22449      if (rep) {
22450        if (!(rep.extension === extension)) {
22451          formatDevErrorMessage4(`LexicalBuilder: A registered extension with name ${extension.name} exists but does not match the given extension`);
22452        }
22453        return rep;
22454      }
22455    }
22456    addEdge(fromExtensionName, toExtensionName, configs) {
22457      const outgoing = this.outgoingConfigEdges.get(fromExtensionName);
22458      if (outgoing) {
22459        outgoing.set(toExtensionName, configs);
22460      } else {
22461        this.outgoingConfigEdges.set(fromExtensionName, /* @__PURE__ */ new Map([[toExtensionName, configs]]));
22462      }
22463      const incoming = this.incomingEdges.get(toExtensionName);
22464      if (incoming) {
22465        incoming.add(fromExtensionName);
22466      } else {
22467        this.incomingEdges.set(toExtensionName, /* @__PURE__ */ new Set([fromExtensionName]));
22468      }
22469    }
22470    addExtension(arg) {
22471      if (!(this._sortedExtensionReps === void 0)) {
22472        formatDevErrorMessage4(`LexicalBuilder: addExtension called after finalization`);
22473      }
22474      const normalized = normalizeExtensionArgument(arg);
22475      const [extension] = normalized;
22476      if (!(typeof extension.name === "string")) {
22477        formatDevErrorMessage4(`LexicalBuilder: extension name must be string, not ${typeof extension.name}`);
22478      }
22479      let extensionRep = this.extensionNameMap.get(extension.name);
22480      if (!(extensionRep === void 0 || extensionRep.extension === extension)) {
22481        formatDevErrorMessage4(`LexicalBuilder: Multiple extensions registered with name ${extension.name}, names must be unique`);
22482      }
22483      if (!extensionRep) {
22484        extensionRep = new ExtensionRep(this, extension);
22485        this.extensionNameMap.set(extension.name, extensionRep);
22486        const hasConflict = this.conflicts.get(extension.name);
22487        if (typeof hasConflict === "string") {
22488          {
22489            formatDevErrorMessage4(`LexicalBuilder: extension ${extension.name} conflicts with ${hasConflict}`);
22490          }
22491        }
22492        for (const name of extension.conflictsWith || []) {
22493          if (!!this.extensionNameMap.has(name)) {
22494            formatDevErrorMessage4(`LexicalBuilder: extension ${extension.name} conflicts with ${name}`);
22495          }
22496          this.conflicts.set(name, extension.name);
22497        }
22498        for (const dep of extension.dependencies || []) {
22499          const normDep = normalizeExtensionArgument(dep);
22500          this.addEdge(extension.name, normDep[0].name, normDep.slice(1));
22501          this.addExtension(normDep);
22502        }
22503        for (const [depName, config] of extension.peerDependencies || []) {
22504          this.addEdge(extension.name, depName, config ? [config] : []);
22505        }
22506      }
22507    }
22508    sortedExtensionReps() {
22509      if (this._sortedExtensionReps) {
22510        return this._sortedExtensionReps;
22511      }
22512      const sortedExtensionReps = [];
22513      const visit = (rep, fromExtensionName) => {
22514        let mark = rep.state;
22515        if (isExactlyPermanentExtensionRepState(mark)) {
22516          return;
22517        }
22518        const extensionName = rep.extension.name;
22519        if (!isExactlyUnmarkedExtensionRepState(mark)) {
22520          formatDevErrorMessage4(`LexicalBuilder: Circular dependency detected for Extension ${extensionName} from ${fromExtensionName || "[unknown]"}`);
22521        }
22522        mark = applyTemporaryMark(mark);
22523        rep.state = mark;
22524        const outgoingConfigEdges = this.outgoingConfigEdges.get(extensionName);
22525        if (outgoingConfigEdges) {
22526          for (const toExtensionName of outgoingConfigEdges.keys()) {
22527            const toRep = this.extensionNameMap.get(toExtensionName);
22528            if (toRep) {
22529              visit(toRep, extensionName);
22530            }
22531          }
22532        }
22533        mark = applyPermanentMark(mark);
22534        rep.state = mark;
22535        sortedExtensionReps.push(rep);
22536      };
22537      for (const rep of this.extensionNameMap.values()) {
22538        if (isExactlyUnmarkedExtensionRepState(rep.state)) {
22539          visit(rep);
22540        }
22541      }
22542      for (const rep of sortedExtensionReps) {
22543        for (const [toExtensionName, configs] of this.outgoingConfigEdges.get(rep.extension.name) || []) {
22544          if (configs.length > 0) {
22545            const toRep = this.extensionNameMap.get(toExtensionName);
22546            if (toRep) {
22547              for (const config of configs) {
22548                toRep.configs.add(config);
22549              }
22550            }
22551          }
22552        }
22553      }
22554      for (const [extension, ...configs] of this.roots) {
22555        if (configs.length > 0) {
22556          const toRep = this.extensionNameMap.get(extension.name);
22557          if (!(toRep !== void 0)) {
22558            formatDevErrorMessage4(`LexicalBuilder: Expecting existing ExtensionRep for ${extension.name}`);
22559          }
22560          for (const config of configs) {
22561            toRep.configs.add(config);
22562          }
22563        }
22564      }
22565      this._sortedExtensionReps = sortedExtensionReps;
22566      return this._sortedExtensionReps;
22567    }
22568    registerEditor(editor) {
22569      const extensionReps = this.sortedExtensionReps();
22570      const controller = new AbortController();
22571      const cleanups = [() => controller.abort()];
22572      const signal2 = controller.signal;
22573      for (const extensionRep of extensionReps) {
22574        const cleanup = extensionRep.register(editor, signal2);
22575        if (cleanup) {
22576          cleanups.push(cleanup);
22577        }
22578      }
22579      for (const extensionRep of extensionReps) {
22580        const cleanup = extensionRep.afterRegistration(editor);
22581        if (cleanup) {
22582          cleanups.push(cleanup);
22583        }
22584      }
22585      return mergeRegister2(...cleanups);
22586    }
22587    buildCreateEditorArgs() {
22588      const config = {};
22589      const nodes = /* @__PURE__ */ new Set();
22590      const replacedNodes = /* @__PURE__ */ new Map();
22591      const htmlExport = /* @__PURE__ */ new Map();
22592      const htmlImport = {};
22593      const theme2 = {};
22594      const extensionReps = this.sortedExtensionReps();
22595      for (const extensionRep of extensionReps) {
22596        const {
22597          extension
22598        } = extensionRep;
22599        if (extension.onError !== void 0) {
22600          config.onError = extension.onError;
22601        }
22602        if (extension.disableEvents !== void 0) {
22603          config.disableEvents = extension.disableEvents;
22604        }
22605        if (extension.parentEditor !== void 0) {
22606          config.parentEditor = extension.parentEditor;
22607        }
22608        if (extension.editable !== void 0) {
22609          config.editable = extension.editable;
22610        }
22611        if (extension.namespace !== void 0) {
22612          config.namespace = extension.namespace;
22613        }
22614        if (extension.$initialEditorState !== void 0) {
22615          config.$initialEditorState = extension.$initialEditorState;
22616        }
22617        if (extension.nodes) {
22618          for (const node of getNodeConfig(extension)) {
22619            if (typeof node !== "function") {
22620              const conflictExtension = replacedNodes.get(node.replace);
22621              if (conflictExtension) {
22622                {
22623                  formatDevErrorMessage4(`LexicalBuilder: Extension ${extension.name} can not register replacement for node ${node.replace.name} because ${conflictExtension.extension.name} already did`);
22624                }
22625              }
22626              replacedNodes.set(node.replace, extensionRep);
22627            }
22628            nodes.add(node);
22629          }
22630        }
22631        if (extension.html) {
22632          if (extension.html.export) {
22633            for (const [k2, v3] of extension.html.export.entries()) {
22634              htmlExport.set(k2, v3);
22635            }
22636          }
22637          if (extension.html.import) {
22638            Object.assign(htmlImport, extension.html.import);
22639          }
22640        }
22641        if (extension.theme) {
22642          deepThemeMergeInPlace(theme2, extension.theme);
22643        }
22644      }
22645      if (Object.keys(theme2).length > 0) {
22646        config.theme = theme2;
22647      }
22648      if (nodes.size) {
22649        config.nodes = [...nodes];
22650      }
22651      const hasImport = Object.keys(htmlImport).length > 0;
22652      const hasExport = htmlExport.size > 0;
22653      if (hasImport || hasExport) {
22654        config.html = {};
22655        if (hasImport) {
22656          config.html.import = htmlImport;
22657        }
22658        if (hasExport) {
22659          config.html.export = htmlExport;
22660        }
22661      }
22662      for (const extensionRep of extensionReps) {
22663        extensionRep.init(config);
22664      }
22665      if (!config.onError) {
22666        config.onError = defaultOnError;
22667      }
22668      return config;
22669    }
22670  };
22671  function getExtensionDependencyFromEditor(editor, extension) {
22672    const builder = LexicalBuilder.fromEditor(editor);
22673    const rep = builder.getExtensionRep(extension);
22674    if (!(rep !== void 0)) {
22675      formatDevErrorMessage4(`getExtensionDependencyFromEditor: Extension ${extension.name} was not built when creating this editor`);
22676    }
22677    return rep.getExtensionDependency();
22678  }
22679  function getPeerDependencyFromEditor(editor, extensionName) {
22680    const builder = LexicalBuilder.maybeFromEditor(editor);
22681    if (!builder) return void 0;
22682    const peer = builder.extensionNameMap.get(extensionName);
22683    return peer ? peer.getExtensionDependency() : void 0;
22684  }
22685  function getPeerDependencyFromEditorOrThrow(editor, extensionName) {
22686    const dep = getPeerDependencyFromEditor(editor, extensionName);
22687    if (!(dep !== void 0)) {
22688      formatDevErrorMessage4(`getPeerDependencyFromEditorOrThrow: Editor was not built with Extension ${extensionName}`);
22689    }
22690    return dep;
22691  }
22692  var EMPTY_SET = /* @__PURE__ */ new Set();
22693  var NodeSelectionExtension = defineExtension2({
22694    build(editor, config, state) {
22695      const editorStateStore = state.getDependency(EditorStateExtension).output;
22696      const watchedNodeStore = a({
22697        watchedNodeKeys: /* @__PURE__ */ new Map()
22698      });
22699      const selectedNodeKeys = watchedSignal(() => void 0, () => j(() => {
22700        const prevSelectedNodeKeys = selectedNodeKeys.peek();
22701        const {
22702          watchedNodeKeys
22703        } = watchedNodeStore.value;
22704        let nextSelectedNodeKeys;
22705        let didChange = false;
22706        editorStateStore.value.read(() => {
22707          const selection = $getSelection2();
22708          if (selection) {
22709            for (const [key, listeners] of watchedNodeKeys.entries()) {
22710              if (listeners.size === 0) {
22711                watchedNodeKeys.delete(key);
22712                continue;
22713              }
22714              const node = $getNodeByKey2(key);
22715              const isSelected = node && node.isSelected() || false;
22716              didChange = didChange || isSelected !== (prevSelectedNodeKeys ? prevSelectedNodeKeys.has(key) : false);
22717              if (isSelected) {
22718                nextSelectedNodeKeys = nextSelectedNodeKeys || /* @__PURE__ */ new Set();
22719                nextSelectedNodeKeys.add(key);
22720              }
22721            }
22722          }
22723        });
22724        if (!(!didChange && nextSelectedNodeKeys && prevSelectedNodeKeys && nextSelectedNodeKeys.size === prevSelectedNodeKeys.size)) {
22725          selectedNodeKeys.value = nextSelectedNodeKeys;
22726        }
22727      }));
22728      function watchNodeKey(key) {
22729        const watcher = g(() => (selectedNodeKeys.value || EMPTY_SET).has(key));
22730        const {
22731          watchedNodeKeys
22732        } = watchedNodeStore.peek();
22733        let listeners = watchedNodeKeys.get(key);
22734        const hadListener = listeners !== void 0;
22735        listeners = listeners || /* @__PURE__ */ new Set();
22736        listeners.add(watcher);
22737        if (!hadListener) {
22738          watchedNodeKeys.set(key, listeners);
22739          watchedNodeStore.value = {
22740            watchedNodeKeys
22741          };
22742        }
22743        return watcher;
22744      }
22745      return {
22746        watchNodeKey
22747      };
22748    },
22749    dependencies: [EditorStateExtension],
22750    name: "@lexical/extension/NodeSelection"
22751  });
22752  var INSERT_HORIZONTAL_RULE_COMMAND = createCommand2("INSERT_HORIZONTAL_RULE_COMMAND");
22753  var HorizontalRuleNode = class _HorizontalRuleNode extends DecoratorNode2 {
22754    static getType() {
22755      return "horizontalrule";
22756    }
22757    static clone(node) {
22758      return new _HorizontalRuleNode(node.__key);
22759    }
22760    static importJSON(serializedNode) {
22761      return $createHorizontalRuleNode().updateFromJSON(serializedNode);
22762    }
22763    static importDOM() {
22764      return {
22765        hr: () => ({
22766          conversion: $convertHorizontalRuleElement,
22767          priority: 0
22768        })
22769      };
22770    }
22771    exportDOM() {
22772      return {
22773        element: document.createElement("hr")
22774      };
22775    }
22776    createDOM(config) {
22777      const element = document.createElement("hr");
22778      addClassNamesToElement2(element, config.theme.hr);
22779      return element;
22780    }
22781    getTextContent() {
22782      return "\n";
22783    }
22784    isInline() {
22785      return false;
22786    }
22787    updateDOM() {
22788      return false;
22789    }
22790  };
22791  function $convertHorizontalRuleElement() {
22792    return {
22793      node: $createHorizontalRuleNode()
22794    };
22795  }
22796  function $createHorizontalRuleNode() {
22797    return $create2(HorizontalRuleNode);
22798  }
22799  function $isHorizontalRuleNode(node) {
22800    return node instanceof HorizontalRuleNode;
22801  }
22802  function $toggleNodeSelection(node, shiftKey = false) {
22803    const selection = $getSelection2();
22804    const wasSelected = node.isSelected();
22805    const key = node.getKey();
22806    let nodeSelection;
22807    if (shiftKey && $isNodeSelection2(selection)) {
22808      nodeSelection = selection;
22809    } else {
22810      nodeSelection = $createNodeSelection2();
22811      $setSelection2(nodeSelection);
22812    }
22813    if (wasSelected) {
22814      nodeSelection.delete(key);
22815    } else {
22816      nodeSelection.add(key);
22817    }
22818  }
22819  var HorizontalRuleExtension = defineExtension2({
22820    dependencies: [EditorStateExtension, NodeSelectionExtension],
22821    name: "@lexical/extension/HorizontalRule",
22822    nodes: () => [HorizontalRuleNode],
22823    register(editor, config, state) {
22824      const {
22825        watchNodeKey
22826      } = state.getDependency(NodeSelectionExtension).output;
22827      const nodeSelectionStore = a({
22828        nodeSelections: /* @__PURE__ */ new Map()
22829      });
22830      const isSelectedClassName = editor._config.theme.hrSelected ?? "selected";
22831      return mergeRegister2(editor.registerCommand(INSERT_HORIZONTAL_RULE_COMMAND, (type) => {
22832        const selection = $getSelection2();
22833        if (!$isRangeSelection2(selection)) {
22834          return false;
22835        }
22836        const focusNode = selection.focus.getNode();
22837        if (focusNode !== null) {
22838          const horizontalRuleNode = $createHorizontalRuleNode();
22839          $insertNodeToNearestRoot2(horizontalRuleNode);
22840        }
22841        return true;
22842      }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(CLICK_COMMAND2, (event) => {
22843        if (isDOMNode2(event.target)) {
22844          const node = $getNodeFromDOMNode2(event.target);
22845          if ($isHorizontalRuleNode(node)) {
22846            $toggleNodeSelection(node, event.shiftKey);
22847            return true;
22848          }
22849        }
22850        return false;
22851      }, COMMAND_PRIORITY_LOW2), editor.registerMutationListener(HorizontalRuleNode, (nodes, payload) => {
22852        n(() => {
22853          let didChange = false;
22854          const {
22855            nodeSelections
22856          } = nodeSelectionStore.peek();
22857          for (const [k2, v3] of nodes.entries()) {
22858            if (v3 === "destroyed") {
22859              nodeSelections.delete(k2);
22860              didChange = true;
22861            } else {
22862              const prev = nodeSelections.get(k2);
22863              const dom = editor.getElementByKey(k2);
22864              if (prev) {
22865                prev.domNode.value = dom;
22866              } else {
22867                didChange = true;
22868                nodeSelections.set(k2, {
22869                  domNode: a(dom),
22870                  selectedSignal: watchNodeKey(k2)
22871                });
22872              }
22873            }
22874          }
22875          if (didChange) {
22876            nodeSelectionStore.value = {
22877              nodeSelections
22878            };
22879          }
22880        });
22881      }), j(() => {
22882        const effects = [];
22883        for (const {
22884          domNode,
22885          selectedSignal
22886        } of nodeSelectionStore.value.nodeSelections.values()) {
22887          effects.push(j(() => {
22888            const dom = domNode.value;
22889            if (dom) {
22890              const isSelected = selectedSignal.value;
22891              if (isSelected) {
22892                addClassNamesToElement2(dom, isSelectedClassName);
22893              } else {
22894                removeClassNamesFromElement2(dom, isSelectedClassName);
22895              }
22896            }
22897          }));
22898        }
22899        return mergeRegister2(...effects);
22900      }));
22901    }
22902  });
22903  function $defaultGetParentEditor() {
22904    const editor = $getEditor2();
22905    LexicalBuilder.fromEditor(editor);
22906    return editor;
22907  }
22908  var NestedEditorExtension = defineExtension2({
22909    build: (editor, config) => namedSignals({
22910      inheritEditableFromParent: config.inheritEditableFromParent
22911    }),
22912    config: safeCast2({
22913      $getParentEditor: $defaultGetParentEditor,
22914      inheritEditableFromParent: false
22915    }),
22916    init: (editorConfig, config, state) => {
22917      const parentEditor = config.$getParentEditor();
22918      editorConfig.parentEditor = parentEditor;
22919      editorConfig.theme = editorConfig.theme || parentEditor._config.theme;
22920    },
22921    name: "@lexical/extension/NestedEditor",
22922    register: (editor, config, state) => j(() => {
22923      const parentEditor = editor._parentEditor;
22924      if (parentEditor) {
22925        if (state.getOutput().inheritEditableFromParent.value) {
22926          editor.setEditable(parentEditor.isEditable());
22927          return parentEditor.registerEditableListener(editor.setEditable.bind(editor));
22928        }
22929      }
22930    })
22931  });
22932  var SelectionAlwaysOnDisplayExtension = defineExtension2({
22933    build: (editor, config, state) => namedSignals(config),
22934    config: safeCast2({
22935      disabled: false,
22936      onReposition: void 0
22937    }),
22938    name: "@lexical/utils/SelectionAlwaysOnDisplay",
22939    register: (editor, config, state) => {
22940      const stores = state.getOutput();
22941      return j(() => {
22942        if (!stores.disabled.value) {
22943          return selectionAlwaysOnDisplay2(editor, stores.onReposition.value);
22944        }
22945      });
22946    }
22947  });
22948  function $indentOverTab(selection) {
22949    const nodes = selection.getNodes();
22950    const canIndentBlockNodes = nodes.filter((node) => $isBlockElementNode2(node) && node.canIndent());
22951    if (canIndentBlockNodes.length > 0) {
22952      return true;
22953    }
22954    const anchor = selection.anchor;
22955    const focus = selection.focus;
22956    const first = focus.isBefore(anchor) ? focus : anchor;
22957    const firstNode = first.getNode();
22958    const firstBlock = $getNearestBlockElementAncestorOrThrow2(firstNode);
22959    if (firstBlock.canIndent()) {
22960      const firstBlockKey = firstBlock.getKey();
22961      let selectionAtStart = $createRangeSelection2();
22962      selectionAtStart.anchor.set(firstBlockKey, 0, "element");
22963      selectionAtStart.focus.set(firstBlockKey, 0, "element");
22964      selectionAtStart = $normalizeSelection__EXPERIMENTAL(selectionAtStart);
22965      if (selectionAtStart.anchor.is(first)) {
22966        return true;
22967      }
22968    }
22969    return false;
22970  }
22971  function $defaultCanIndent(node) {
22972    return node.canBeEmpty();
22973  }
22974  function registerTabIndentation(editor, maxIndent, $canIndent = $defaultCanIndent) {
22975    return mergeRegister2(editor.registerCommand(KEY_TAB_COMMAND2, (event) => {
22976      const selection = $getSelection2();
22977      if (!$isRangeSelection2(selection)) {
22978        return false;
22979      }
22980      event.preventDefault();
22981      const command = $indentOverTab(selection) ? event.shiftKey ? OUTDENT_CONTENT_COMMAND2 : INDENT_CONTENT_COMMAND2 : INSERT_TAB_COMMAND2;
22982      return editor.dispatchCommand(command, void 0);
22983    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(INDENT_CONTENT_COMMAND2, () => {
22984      const currentMaxIndent = typeof maxIndent === "number" ? maxIndent : maxIndent ? maxIndent.peek() : null;
22985      const selection = $getSelection2();
22986      if (!$isRangeSelection2(selection)) {
22987        return false;
22988      }
22989      const $currentCanIndent = typeof $canIndent === "function" ? $canIndent : $canIndent.peek();
22990      return $handleIndentAndOutdent2((block) => {
22991        if ($currentCanIndent(block)) {
22992          const newIndent = block.getIndent() + 1;
22993          if (!currentMaxIndent || newIndent < currentMaxIndent) {
22994            block.setIndent(newIndent);
22995          }
22996        }
22997      });
22998    }, COMMAND_PRIORITY_CRITICAL2));
22999  }
23000  var TabIndentationExtension = defineExtension2({
23001    build(editor, config, state) {
23002      return namedSignals(config);
23003    },
23004    config: safeCast2({
23005      $canIndent: $defaultCanIndent,
23006      disabled: false,
23007      maxIndent: null
23008    }),
23009    name: "@lexical/extension/TabIndentation",
23010    register(editor, config, state) {
23011      const {
23012        disabled,
23013        maxIndent,
23014        $canIndent
23015      } = state.getOutput();
23016      return j(() => {
23017        if (!disabled.value) {
23018          return registerTabIndentation(editor, maxIndent, $canIndent);
23019        }
23020      });
23021    }
23022  });
23023
23024  
vendor: 2,222 bytes, lines 23024-23065
23024// node_modules/@lexical/extension/LexicalExtension.mjs
23025  var mod4 = true ? LexicalExtension_dev_exports : LexicalExtension_prod_exports;
23026  var $createHorizontalRuleNode2 = mod4.$createHorizontalRuleNode;
23027  var $isDecoratorTextNode2 = mod4.$isDecoratorTextNode;
23028  var $isHorizontalRuleNode2 = mod4.$isHorizontalRuleNode;
23029  var AutoFocusExtension2 = mod4.AutoFocusExtension;
23030  var ClearEditorExtension2 = mod4.ClearEditorExtension;
23031  var DecoratorTextExtension2 = mod4.DecoratorTextExtension;
23032  var DecoratorTextNode2 = mod4.DecoratorTextNode;
23033  var EditorStateExtension2 = mod4.EditorStateExtension;
23034  var HorizontalRuleExtension2 = mod4.HorizontalRuleExtension;
23035  var HorizontalRuleNode2 = mod4.HorizontalRuleNode;
23036  var INSERT_HORIZONTAL_RULE_COMMAND2 = mod4.INSERT_HORIZONTAL_RULE_COMMAND;
23037  var InitialStateExtension2 = mod4.InitialStateExtension;
23038  var LexicalBuilder2 = mod4.LexicalBuilder;
23039  var NestedEditorExtension2 = mod4.NestedEditorExtension;
23040  var NodeSelectionExtension2 = mod4.NodeSelectionExtension;
23041  var SelectionAlwaysOnDisplayExtension2 = mod4.SelectionAlwaysOnDisplayExtension;
23042  var TabIndentationExtension2 = mod4.TabIndentationExtension;
23043  var applyFormatFromStyle2 = mod4.applyFormatFromStyle;
23044  var applyFormatToDom2 = mod4.applyFormatToDom;
23045  var batch = mod4.batch;
23046  var buildEditorFromExtensions2 = mod4.buildEditorFromExtensions;
23047  var computed = mod4.computed;
23048  var configExtension3 = mod4.configExtension;
23049  var declarePeerDependency3 = mod4.declarePeerDependency;
23050  var defineExtension3 = mod4.defineExtension;
23051  var effect = mod4.effect;
23052  var getExtensionDependencyFromEditor2 = mod4.getExtensionDependencyFromEditor;
23053  var getKnownTypesAndNodes2 = mod4.getKnownTypesAndNodes;
23054  var getPeerDependencyFromEditor2 = mod4.getPeerDependencyFromEditor;
23055  var getPeerDependencyFromEditorOrThrow2 = mod4.getPeerDependencyFromEditorOrThrow;
23056  var namedSignals2 = mod4.namedSignals;
23057  var registerClearEditor2 = mod4.registerClearEditor;
23058  var registerTabIndentation2 = mod4.registerTabIndentation;
23059  var safeCast3 = mod4.safeCast;
23060  var shallowMergeConfig3 = mod4.shallowMergeConfig;
23061  var signal = mod4.signal;
23062  var untracked = mod4.untracked;
23063  var watchedSignal2 = mod4.watchedSignal;
23064
23065  
vendor: 39,032 bytes, lines 23065-24196
23065// node_modules/@lexical/link/LexicalLink.dev.mjs
23066  function formatDevErrorMessage5(message) {
23067    throw new Error(message);
23068  }
23069  var SUPPORTED_URL_PROTOCOLS = /* @__PURE__ */ new Set(["http:", "https:", "mailto:", "sms:", "tel:"]);
23070  var LinkNode = class _LinkNode extends ElementNode2 {
23071    /** @internal */
23072    __url;
23073    /** @internal */
23074    __target;
23075    /** @internal */
23076    __rel;
23077    /** @internal */
23078    __title;
23079    static getType() {
23080      return "link";
23081    }
23082    static clone(node) {
23083      return new _LinkNode(node.__url, {
23084        rel: node.__rel,
23085        target: node.__target,
23086        title: node.__title
23087      }, node.__key);
23088    }
23089    constructor(url = "", attributes = {}, key) {
23090      super(key);
23091      const {
23092        target = null,
23093        rel = null,
23094        title = null
23095      } = attributes;
23096      this.__url = url;
23097      this.__target = target;
23098      this.__rel = rel;
23099      this.__title = title;
23100    }
23101    afterCloneFrom(prevNode) {
23102      super.afterCloneFrom(prevNode);
23103      this.__url = prevNode.__url;
23104      this.__rel = prevNode.__rel;
23105      this.__target = prevNode.__target;
23106      this.__title = prevNode.__title;
23107    }
23108    createDOM(config) {
23109      const element = document.createElement("a");
23110      this.updateLinkDOM(null, element, config);
23111      addClassNamesToElement3(element, config.theme.link);
23112      return element;
23113    }
23114    updateLinkDOM(prevNode, anchor, config) {
23115      if (isHTMLAnchorElement3(anchor)) {
23116        if (!prevNode || prevNode.__url !== this.__url) {
23117          anchor.href = this.sanitizeUrl(this.__url);
23118        }
23119        for (const attr of ["target", "rel", "title"]) {
23120          const key = `__${attr}`;
23121          const value = this[key];
23122          if (!prevNode || prevNode[key] !== value) {
23123            if (value) {
23124              anchor[attr] = value;
23125            } else {
23126              anchor.removeAttribute(attr);
23127            }
23128          }
23129        }
23130      }
23131    }
23132    updateDOM(prevNode, anchor, config) {
23133      this.updateLinkDOM(prevNode, anchor, config);
23134      return false;
23135    }
23136    static importDOM() {
23137      return {
23138        a: (node) => ({
23139          conversion: $convertAnchorElement,
23140          priority: 1
23141        })
23142      };
23143    }
23144    static importJSON(serializedNode) {
23145      return $createLinkNode().updateFromJSON(serializedNode);
23146    }
23147    updateFromJSON(serializedNode) {
23148      return super.updateFromJSON(serializedNode).setURL(serializedNode.url).setRel(serializedNode.rel || null).setTarget(serializedNode.target || null).setTitle(serializedNode.title || null);
23149    }
23150    sanitizeUrl(url) {
23151      url = formatUrl(url);
23152      try {
23153        const parsedUrl = new URL(formatUrl(url));
23154        if (!SUPPORTED_URL_PROTOCOLS.has(parsedUrl.protocol)) {
23155          return "about:blank";
23156        }
23157      } catch (_unused) {
23158        return url;
23159      }
23160      return url;
23161    }
23162    exportJSON() {
23163      return {
23164        ...super.exportJSON(),
23165        rel: this.getRel(),
23166        target: this.getTarget(),
23167        title: this.getTitle(),
23168        url: this.getURL()
23169      };
23170    }
23171    getURL() {
23172      return this.getLatest().__url;
23173    }
23174    setURL(url) {
23175      const writable = this.getWritable();
23176      writable.__url = url;
23177      return writable;
23178    }
23179    getTarget() {
23180      return this.getLatest().__target;
23181    }
23182    setTarget(target) {
23183      const writable = this.getWritable();
23184      writable.__target = target;
23185      return writable;
23186    }
23187    getRel() {
23188      return this.getLatest().__rel;
23189    }
23190    setRel(rel) {
23191      const writable = this.getWritable();
23192      writable.__rel = rel;
23193      return writable;
23194    }
23195    getTitle() {
23196      return this.getLatest().__title;
23197    }
23198    setTitle(title) {
23199      const writable = this.getWritable();
23200      writable.__title = title;
23201      return writable;
23202    }
23203    insertNewAfter(_3, restoreSelection = true) {
23204      const linkNode = $copyNode2(this);
23205      this.insertAfter(linkNode, restoreSelection);
23206      return linkNode;
23207    }
23208    canInsertTextBefore() {
23209      return false;
23210    }
23211    canInsertTextAfter() {
23212      return false;
23213    }
23214    canBeEmpty() {
23215      return false;
23216    }
23217    isInline() {
23218      return true;
23219    }
23220    extractWithChild(child, selection, destination) {
23221      if (!$isRangeSelection2(selection)) {
23222        return false;
23223      }
23224      const anchorNode = selection.anchor.getNode();
23225      const focusNode = selection.focus.getNode();
23226      return this.isParentOf(anchorNode) && this.isParentOf(focusNode) && selection.getTextContent().length > 0;
23227    }
23228    isEmailURI() {
23229      return this.__url.startsWith("mailto:");
23230    }
23231    isWebSiteURI() {
23232      return this.__url.startsWith("https://") || this.__url.startsWith("http://");
23233    }
23234    shouldMergeAdjacentLink(otherLink) {
23235      return this.getType() === otherLink.getType() && this.__url === otherLink.__url && this.__target === otherLink.__target && this.__rel === otherLink.__rel && this.__title === otherLink.__title;
23236    }
23237  };
23238  function $saveCaretPair(point) {
23239    const next = $caretFromPoint2(point, "next");
23240    return [next, next.getFlipped()];
23241  }
23242  function $restoreCaretPair(point, pair) {
23243    for (const caret of pair) {
23244      if (caret.origin.isAttached()) {
23245        const normalized = $normalizeCaret2(caret);
23246        $setPointFromCaret2(point, normalized);
23247        return;
23248      }
23249    }
23250  }
23251  function $linkNodeTransform(link) {
23252    const selection = $getSelection2();
23253    let anchorPair = null;
23254    let focusPair = null;
23255    if ($isRangeSelection2(selection)) {
23256      anchorPair = $saveCaretPair(selection.anchor);
23257      focusPair = $saveCaretPair(selection.focus);
23258    }
23259    function $restoreSelection() {
23260      if ($isRangeSelection2(selection)) {
23261        $restoreCaretPair(selection.anchor, anchorPair);
23262        $restoreCaretPair(selection.focus, focusPair);
23263        $normalizeSelection__EXPERIMENTAL(selection);
23264      }
23265    }
23266    let transformed = false;
23267    for (const caret of $getChildCaret2(link, "next")) {
23268      const node = caret.origin;
23269      if ($isElementNode2(node) && !node.isInline()) {
23270        const blockChildren = node.getChildren();
23271        if (blockChildren.length > 0) {
23272          const innerLink = $copyNode2(link);
23273          innerLink.append(...blockChildren);
23274          node.append(innerLink);
23275          transformed = true;
23276        }
23277        $insertNodeToNearestRootAtCaret2(node, $rewindSiblingCaret2(caret), {
23278          $shouldSplit: () => false
23279        });
23280      }
23281    }
23282    function $fixMergeBoundaryCaret(pair, absorbingLink, mergingLink) {
23283      const [next, prev] = pair;
23284      const $isAffected = (caret) => $isSiblingCaret2(caret) && caret.origin.is(absorbingLink);
23285      if (!$isAffected(next) && !$isAffected(prev)) {
23286        return pair;
23287      }
23288      const fixed = $normalizeCaret2($getChildCaret2(mergingLink, "next"));
23289      return [fixed, fixed.getFlipped()];
23290    }
23291    if (link.isAttached()) {
23292      const prevSibling = link.getPreviousSibling();
23293      if ($isLinkNode(prevSibling) && prevSibling.shouldMergeAdjacentLink(link)) {
23294        if (anchorPair) {
23295          anchorPair = $fixMergeBoundaryCaret(anchorPair, prevSibling, link);
23296        }
23297        if (focusPair) {
23298          focusPair = $fixMergeBoundaryCaret(focusPair, prevSibling, link);
23299        }
23300        prevSibling.append(...link.getChildren());
23301        link.remove();
23302        $restoreSelection();
23303        return;
23304      }
23305      const nextSibling = link.getNextSibling();
23306      if ($isLinkNode(nextSibling) && link.shouldMergeAdjacentLink(nextSibling)) {
23307        if (anchorPair) {
23308          anchorPair = $fixMergeBoundaryCaret(anchorPair, link, nextSibling);
23309        }
23310        if (focusPair) {
23311          focusPair = $fixMergeBoundaryCaret(focusPair, link, nextSibling);
23312        }
23313        link.append(...nextSibling.getChildren());
23314        nextSibling.remove();
23315        transformed = true;
23316      }
23317    }
23318    if (!transformed) {
23319      return;
23320    }
23321    if (!link.canBeEmpty() && link.isEmpty()) {
23322      const parent = link.getParent();
23323      link.remove();
23324      if (parent && parent.isEmpty()) {
23325        parent.remove();
23326      }
23327    }
23328    $restoreSelection();
23329  }
23330  function $convertAnchorElement(domNode) {
23331    let node = null;
23332    if (isHTMLAnchorElement3(domNode)) {
23333      const content = domNode.textContent;
23334      if (content !== null && content !== "" || domNode.children.length > 0) {
23335        node = $createLinkNode(domNode.getAttribute("href") || "", {
23336          rel: domNode.getAttribute("rel"),
23337          target: domNode.getAttribute("target"),
23338          title: domNode.getAttribute("title")
23339        });
23340      }
23341    }
23342    return {
23343      node
23344    };
23345  }
23346  function $createLinkNode(url = "", attributes) {
23347    return $applyNodeReplacement2(new LinkNode(url, attributes));
23348  }
23349  function $isLinkNode(node) {
23350    return node instanceof LinkNode;
23351  }
23352  var AutoLinkNode = class _AutoLinkNode extends LinkNode {
23353    /** @internal */
23354    /** Indicates whether the autolink was ever unlinked. **/
23355    __isUnlinked;
23356    constructor(url = "", attributes = {}, key) {
23357      super(url, attributes, key);
23358      this.__isUnlinked = attributes.isUnlinked !== void 0 && attributes.isUnlinked !== null ? attributes.isUnlinked : false;
23359    }
23360    afterCloneFrom(prevNode) {
23361      super.afterCloneFrom(prevNode);
23362      this.__isUnlinked = prevNode.__isUnlinked;
23363    }
23364    static getType() {
23365      return "autolink";
23366    }
23367    static clone(node) {
23368      return new _AutoLinkNode(node.__url, {
23369        isUnlinked: node.__isUnlinked,
23370        rel: node.__rel,
23371        target: node.__target,
23372        title: node.__title
23373      }, node.__key);
23374    }
23375    shouldMergeAdjacentLink(_otherLink) {
23376      return false;
23377    }
23378    getIsUnlinked() {
23379      return this.__isUnlinked;
23380    }
23381    setIsUnlinked(value) {
23382      const self2 = this.getWritable();
23383      self2.__isUnlinked = value;
23384      return self2;
23385    }
23386    createDOM(config) {
23387      if (this.__isUnlinked) {
23388        return document.createElement("span");
23389      } else {
23390        return super.createDOM(config);
23391      }
23392    }
23393    updateDOM(prevNode, anchor, config) {
23394      return super.updateDOM(prevNode, anchor, config) || prevNode.__isUnlinked !== this.__isUnlinked;
23395    }
23396    static importJSON(serializedNode) {
23397      return $createAutoLinkNode().updateFromJSON(serializedNode);
23398    }
23399    updateFromJSON(serializedNode) {
23400      return super.updateFromJSON(serializedNode).setIsUnlinked(serializedNode.isUnlinked || false);
23401    }
23402    static importDOM() {
23403      return null;
23404    }
23405    exportJSON() {
23406      return {
23407        ...super.exportJSON(),
23408        isUnlinked: this.__isUnlinked
23409      };
23410    }
23411    insertNewAfter(_3, restoreSelection = true) {
23412      const linkNode = $createAutoLinkNode(this.__url, {
23413        isUnlinked: this.__isUnlinked,
23414        rel: this.__rel,
23415        target: this.__target,
23416        title: this.__title
23417      });
23418      this.insertAfter(linkNode, restoreSelection);
23419      return linkNode;
23420    }
23421  };
23422  function $createAutoLinkNode(url = "", attributes) {
23423    return $applyNodeReplacement2(new AutoLinkNode(url, attributes));
23424  }
23425  function $isAutoLinkNode(node) {
23426    return node instanceof AutoLinkNode;
23427  }
23428  var TOGGLE_LINK_COMMAND = createCommand2("TOGGLE_LINK_COMMAND");
23429  function $getPointNode(point, offset3) {
23430    if (point.type === "element") {
23431      const node = point.getNode();
23432      if (!$isElementNode2(node)) {
23433        formatDevErrorMessage5(`$getPointNode: element point is not an ElementNode`);
23434      }
23435      const childNode = node.getChildren()[point.offset + offset3];
23436      return childNode || null;
23437    }
23438    return null;
23439  }
23440  function $withSelectedNodes($fn) {
23441    const initialSelection = $getSelection2();
23442    if (!$isRangeSelection2(initialSelection)) {
23443      return $fn();
23444    }
23445    const normalized = $normalizeSelection__EXPERIMENTAL(initialSelection);
23446    const isBackwards = normalized.isBackward();
23447    const anchorNode = $getPointNode(normalized.anchor, isBackwards ? -1 : 0);
23448    const focusNode = $getPointNode(normalized.focus, isBackwards ? 0 : -1);
23449    const rval = $fn();
23450    if (anchorNode || focusNode) {
23451      const updatedSelection = $getSelection2();
23452      if ($isRangeSelection2(updatedSelection)) {
23453        const finalSelection = updatedSelection.clone();
23454        if (anchorNode) {
23455          const anchorParent = anchorNode.getParent();
23456          if (anchorParent) {
23457            finalSelection.anchor.set(anchorParent.getKey(), anchorNode.getIndexWithinParent() + (isBackwards ? 1 : 0), "element");
23458          }
23459        }
23460        if (focusNode) {
23461          const focusParent = focusNode.getParent();
23462          if (focusParent) {
23463            finalSelection.focus.set(focusParent.getKey(), focusNode.getIndexWithinParent() + (isBackwards ? 0 : 1), "element");
23464          }
23465        }
23466        $setSelection2($normalizeSelection__EXPERIMENTAL(finalSelection));
23467      }
23468    }
23469    return rval;
23470  }
23471  function $splitLinkAtSelection(parentLink, extractedNodes) {
23472    const extractedKeys = new Set(extractedNodes.filter((n2) => parentLink.isParentOf(n2)).map((n2) => n2.getKey()));
23473    const allChildren = parentLink.getChildren();
23474    const isExtractedChild = (child) => extractedKeys.has(child.getKey()) || $isElementNode2(child) && extractedNodes.some((n2) => parentLink.isParentOf(n2) && child.isParentOf(n2));
23475    const extractedChildren = allChildren.filter(isExtractedChild);
23476    if (extractedChildren.length === allChildren.length) {
23477      allChildren.forEach((child) => parentLink.insertBefore(child));
23478      parentLink.remove();
23479      return;
23480    }
23481    const firstExtractedIndex = allChildren.findIndex(isExtractedChild);
23482    const lastExtractedIndex = allChildren.findLastIndex(isExtractedChild);
23483    const isAtStart = firstExtractedIndex === 0;
23484    const isAtEnd = lastExtractedIndex === allChildren.length - 1;
23485    if (isAtStart) {
23486      extractedChildren.forEach((child) => parentLink.insertBefore(child));
23487    } else if (isAtEnd) {
23488      for (let i2 = extractedChildren.length - 1; i2 >= 0; i2--) {
23489        parentLink.insertAfter(extractedChildren[i2]);
23490      }
23491    } else {
23492      for (let i2 = extractedChildren.length - 1; i2 >= 0; i2--) {
23493        parentLink.insertAfter(extractedChildren[i2]);
23494      }
23495      const trailingChildren = allChildren.slice(lastExtractedIndex + 1);
23496      if (trailingChildren.length > 0) {
23497        const newLink = $copyNode2(parentLink);
23498        extractedChildren[extractedChildren.length - 1].insertAfter(newLink);
23499        trailingChildren.forEach((child) => newLink.append(child));
23500      }
23501    }
23502  }
23503  function $toggleLink(urlOrAttributes, attributes = {}) {
23504    let url;
23505    if (urlOrAttributes && typeof urlOrAttributes === "object") {
23506      const {
23507        url: urlProp,
23508        ...rest
23509      } = urlOrAttributes;
23510      url = urlProp;
23511      attributes = {
23512        ...rest,
23513        ...attributes
23514      };
23515    } else {
23516      url = urlOrAttributes;
23517    }
23518    const {
23519      target,
23520      title
23521    } = attributes;
23522    const rel = attributes.rel === void 0 ? "noreferrer" : attributes.rel;
23523    const selection = $getSelection2();
23524    if (selection === null || !$isRangeSelection2(selection) && !$isNodeSelection2(selection)) {
23525      return;
23526    }
23527    if ($isNodeSelection2(selection)) {
23528      const nodes2 = selection.getNodes();
23529      if (nodes2.length === 0) {
23530        return;
23531      }
23532      nodes2.forEach((node) => {
23533        if (url === null) {
23534          const linkParent = $findMatchingParent3(node, (parent) => !$isAutoLinkNode(parent) && $isLinkNode(parent));
23535          if (linkParent) {
23536            linkParent.insertBefore(node);
23537            if (linkParent.getChildren().length === 0) {
23538              linkParent.remove();
23539            }
23540          }
23541        } else {
23542          const existingLink = $findMatchingParent3(node, (parent) => !$isAutoLinkNode(parent) && $isLinkNode(parent));
23543          if (existingLink) {
23544            existingLink.setURL(url);
23545            if (target !== void 0) {
23546              existingLink.setTarget(target);
23547            }
23548            if (rel !== void 0) {
23549              existingLink.setRel(rel);
23550            }
23551          } else {
23552            const linkNode = $createLinkNode(url, {
23553              rel,
23554              target
23555            });
23556            node.insertBefore(linkNode);
23557            linkNode.append(node);
23558          }
23559        }
23560      });
23561      return;
23562    }
23563    if (selection.isCollapsed() && url === null) {
23564      for (const node of selection.getNodes()) {
23565        const parentLink = $findMatchingParent3(node, (parent) => !$isAutoLinkNode(parent) && $isLinkNode(parent));
23566        if (parentLink !== null) {
23567          parentLink.getChildren().forEach((child) => {
23568            parentLink.insertBefore(child);
23569          });
23570          parentLink.remove();
23571        }
23572        return;
23573      }
23574    }
23575    const nodes = selection.extract();
23576    if (url === null) {
23577      const processedLinks = /* @__PURE__ */ new Set();
23578      nodes.forEach((node) => {
23579        const parentLink = $findMatchingParent3(node, (parent) => !$isAutoLinkNode(parent) && $isLinkNode(parent));
23580        if (parentLink !== null) {
23581          const linkKey = parentLink.getKey();
23582          if (processedLinks.has(linkKey)) {
23583            return;
23584          }
23585          $splitLinkAtSelection(parentLink, nodes);
23586          processedLinks.add(linkKey);
23587        }
23588      });
23589      return;
23590    }
23591    const updatedNodes = /* @__PURE__ */ new Set();
23592    const updateLinkNode = (linkNode) => {
23593      if (updatedNodes.has(linkNode.getKey())) {
23594        return;
23595      }
23596      updatedNodes.add(linkNode.getKey());
23597      linkNode.setURL(url);
23598      if (target !== void 0) {
23599        linkNode.setTarget(target);
23600      }
23601      if (rel !== void 0) {
23602        linkNode.setRel(rel);
23603      }
23604      if (title !== void 0) {
23605        linkNode.setTitle(title);
23606      }
23607    };
23608    if (nodes.length === 1) {
23609      const firstNode = nodes[0];
23610      const linkNode = $findMatchingParent3(firstNode, $isLinkNode);
23611      if (linkNode !== null) {
23612        return updateLinkNode(linkNode);
23613      }
23614    }
23615    $withSelectedNodes(() => {
23616      let linkNode = null;
23617      for (const node of nodes) {
23618        if (!node.isAttached()) {
23619          continue;
23620        }
23621        const parentLinkNode = $findMatchingParent3(node, $isLinkNode);
23622        if (parentLinkNode) {
23623          updateLinkNode(parentLinkNode);
23624          continue;
23625        }
23626        if ($isElementNode2(node)) {
23627          if (!node.isInline()) {
23628            continue;
23629          }
23630          if ($isLinkNode(node)) {
23631            if (!$isAutoLinkNode(node) && (linkNode === null || !linkNode.getParentOrThrow().isParentOf(node))) {
23632              updateLinkNode(node);
23633              linkNode = node;
23634              continue;
23635            }
23636            for (const child of node.getChildren()) {
23637              node.insertBefore(child);
23638            }
23639            node.remove();
23640            continue;
23641          }
23642        }
23643        const prevLinkNode = node.getPreviousSibling();
23644        if ($isLinkNode(prevLinkNode) && prevLinkNode.is(linkNode)) {
23645          prevLinkNode.append(node);
23646          continue;
23647        }
23648        linkNode = $createLinkNode(url, {
23649          rel,
23650          target,
23651          title
23652        });
23653        node.insertAfter(linkNode);
23654        linkNode.append(node);
23655      }
23656    });
23657  }
23658  var PHONE_NUMBER_REGEX = /^\+?[0-9\s()-]{5,}$/;
23659  function formatUrl(url) {
23660    if (url.match(/^[a-z][a-z0-9+.-]*:/i)) {
23661      return url;
23662    } else if (url.match(/^[/#.]/)) {
23663      return url;
23664    } else if (url.includes("@")) {
23665      return `mailto:${url}`;
23666    } else if (PHONE_NUMBER_REGEX.test(url)) {
23667      return `tel:${url}`;
23668    }
23669    return `https://${url}`;
23670  }
23671  var defaultProps = {
23672    attributes: void 0,
23673    validateUrl: void 0
23674  };
23675  function registerLink(editor, stores) {
23676    return mergeRegister3(editor.registerNodeTransform(LinkNode, $linkNodeTransform), editor.registerCommand(TOGGLE_LINK_COMMAND, (payload) => {
23677      const validateUrl = stores.validateUrl.peek();
23678      const attributes = stores.attributes.peek();
23679      if (payload === null) {
23680        $toggleLink(null);
23681        return true;
23682      } else if (typeof payload === "string") {
23683        if (validateUrl === void 0 || validateUrl(payload)) {
23684          $toggleLink(payload, attributes);
23685          return true;
23686        }
23687        return false;
23688      } else {
23689        const {
23690          url,
23691          target,
23692          rel,
23693          title
23694        } = payload;
23695        $toggleLink(url, {
23696          ...attributes,
23697          rel,
23698          target,
23699          title
23700        });
23701        return true;
23702      }
23703    }, COMMAND_PRIORITY_EDITOR2), effect(() => {
23704      const validateUrl = stores.validateUrl.value;
23705      if (!validateUrl) {
23706        return;
23707      }
23708      const attributes = stores.attributes.value;
23709      return editor.registerCommand(PASTE_COMMAND2, (event) => {
23710        const selection = $getSelection2();
23711        if (!$isRangeSelection2(selection) || selection.isCollapsed() || !objectKlassEquals2(event, ClipboardEvent)) {
23712          return false;
23713        }
23714        if (event.clipboardData === null) {
23715          return false;
23716        }
23717        const clipboardText = event.clipboardData.getData("text");
23718        if (!validateUrl(clipboardText)) {
23719          return false;
23720        }
23721        if (!selection.getNodes().some((node) => $isElementNode2(node))) {
23722          editor.dispatchCommand(TOGGLE_LINK_COMMAND, {
23723            ...attributes,
23724            url: clipboardText
23725          });
23726          event.preventDefault();
23727          return true;
23728        }
23729        return false;
23730      }, COMMAND_PRIORITY_LOW2);
23731    }));
23732  }
23733  var LinkExtension = defineExtension2({
23734    build(editor, config, state) {
23735      return namedSignals2(config);
23736    },
23737    config: defaultProps,
23738    mergeConfig(config, overrides) {
23739      const merged = shallowMergeConfig2(config, overrides);
23740      if (config.attributes) {
23741        merged.attributes = shallowMergeConfig2(config.attributes, merged.attributes);
23742      }
23743      return merged;
23744    },
23745    name: "@lexical/link/Link",
23746    nodes: () => [LinkNode],
23747    register(editor, config, state) {
23748      return registerLink(editor, state.getOutput());
23749    }
23750  });
23751  function findMatchingDOM(startNode, predicate) {
23752    let node = startNode;
23753    while (node != null) {
23754      if (predicate(node)) {
23755        return node;
23756      }
23757      node = node.parentNode;
23758    }
23759    return null;
23760  }
23761  function registerClickableLink(editor, stores, eventOptions = {}) {
23762    const onClick2 = (event) => {
23763      const target = event.target;
23764      if (!isDOMNode2(target)) {
23765        return;
23766      }
23767      const nearestEditor = getNearestEditorFromDOMNode2(target);
23768      if (nearestEditor === null) {
23769        return;
23770      }
23771      let url = null;
23772      let urlTarget = null;
23773      nearestEditor.update(() => {
23774        const clickedNode = $getNearestNodeFromDOMNode2(target);
23775        if (clickedNode !== null) {
23776          const maybeLinkNode = $findMatchingParent3(clickedNode, $isElementNode2);
23777          if (!stores.disabled.peek()) {
23778            if ($isLinkNode(maybeLinkNode)) {
23779              url = maybeLinkNode.sanitizeUrl(maybeLinkNode.getURL());
23780              urlTarget = maybeLinkNode.getTarget();
23781            } else {
23782              const a2 = findMatchingDOM(target, isHTMLAnchorElement3);
23783              if (a2 !== null) {
23784                url = a2.href;
23785                urlTarget = a2.target;
23786              }
23787            }
23788          }
23789        }
23790      });
23791      if (url === null || url === "") {
23792        return;
23793      }
23794      const selection = editor.getEditorState().read($getSelection2, {
23795        editor
23796      });
23797      if ($isRangeSelection2(selection) && !selection.isCollapsed()) {
23798        event.preventDefault();
23799        return;
23800      }
23801      const isMiddle = event.type === "auxclick" && event.button === 1;
23802      window.open(url, stores.newTab.peek() || isMiddle || event.metaKey || event.ctrlKey || urlTarget === "_blank" ? "_blank" : "_self");
23803      event.preventDefault();
23804    };
23805    const onMouseUp = (event) => {
23806      if (event.button === 1) {
23807        onClick2(event);
23808      }
23809    };
23810    return editor.registerRootListener((rootElement) => {
23811      if (rootElement) {
23812        rootElement.addEventListener("click", onClick2, eventOptions);
23813        rootElement.addEventListener("mouseup", onMouseUp, eventOptions);
23814        return () => {
23815          rootElement.removeEventListener("click", onClick2);
23816          rootElement.removeEventListener("mouseup", onMouseUp);
23817        };
23818      }
23819    });
23820  }
23821  var ClickableLinkExtension = defineExtension2({
23822    build(editor, config, state) {
23823      return namedSignals2(config);
23824    },
23825    config: safeCast2({
23826      disabled: false,
23827      newTab: false
23828    }),
23829    dependencies: [LinkExtension],
23830    name: "@lexical/link/ClickableLink",
23831    register(editor, config, state) {
23832      return registerClickableLink(editor, state.getOutput());
23833    }
23834  });
23835  function createLinkMatcherWithRegExp(regExp, urlTransformer = (text2) => text2) {
23836    return (text2) => {
23837      const match = regExp.exec(text2);
23838      if (match === null) {
23839        return null;
23840      }
23841      return {
23842        index: match.index,
23843        length: match[0].length,
23844        text: match[0],
23845        url: urlTransformer(match[0])
23846      };
23847    };
23848  }
23849  function findFirstMatch(text2, matchers) {
23850    for (let i2 = 0; i2 < matchers.length; i2++) {
23851      const match = matchers[i2](text2);
23852      if (match) {
23853        return match;
23854      }
23855    }
23856    return null;
23857  }
23858  var PUNCTUATION_OR_SPACE = /[.,;\s]/;
23859  function isSeparator(char, separatorRegex) {
23860    return separatorRegex.test(char);
23861  }
23862  function endsWithSeparator(textContent, separatorRegex) {
23863    return isSeparator(textContent[textContent.length - 1], separatorRegex);
23864  }
23865  function startsWithSeparator(textContent, separatorRegex) {
23866    return isSeparator(textContent[0], separatorRegex);
23867  }
23868  function startsWithTLD(textContent, isEmail) {
23869    if (isEmail) {
23870      return /^\.[a-zA-Z]{2,}/.test(textContent);
23871    } else {
23872      return /^\.[a-zA-Z0-9]{1,}/.test(textContent);
23873    }
23874  }
23875  function isPreviousNodeValid(node, separatorRegex) {
23876    let previousNode = node.getPreviousSibling();
23877    if ($isElementNode2(previousNode)) {
23878      previousNode = previousNode.getLastDescendant();
23879    }
23880    return previousNode === null || $isLineBreakNode2(previousNode) || $isTextNode2(previousNode) && endsWithSeparator(previousNode.getTextContent(), separatorRegex);
23881  }
23882  function isNextNodeValid(node, separatorRegex) {
23883    let nextNode = node.getNextSibling();
23884    if ($isElementNode2(nextNode)) {
23885      nextNode = nextNode.getFirstDescendant();
23886    }
23887    return nextNode === null || $isLineBreakNode2(nextNode) || $isTextNode2(nextNode) && startsWithSeparator(nextNode.getTextContent(), separatorRegex);
23888  }
23889  function isContentAroundIsValid(matchStart, matchEnd, separatorRegex, text2, nodes) {
23890    const contentBeforeIsValid = matchStart > 0 ? isSeparator(text2[matchStart - 1], separatorRegex) : isPreviousNodeValid(nodes[0], separatorRegex);
23891    if (!contentBeforeIsValid) {
23892      return false;
23893    }
23894    const contentAfterIsValid = matchEnd < text2.length ? isSeparator(text2[matchEnd], separatorRegex) : isNextNodeValid(nodes[nodes.length - 1], separatorRegex);
23895    return contentAfterIsValid;
23896  }
23897  function extractMatchingNodes(nodes, startIndex, endIndex) {
23898    const unmodifiedBeforeNodes = [];
23899    const matchingNodes = [];
23900    const unmodifiedAfterNodes = [];
23901    let matchingOffset = 0;
23902    let currentOffset = 0;
23903    const currentNodes = [...nodes];
23904    while (currentNodes.length > 0) {
23905      const currentNode = currentNodes[0];
23906      const currentNodeText = currentNode.getTextContent();
23907      const currentNodeLength = currentNodeText.length;
23908      const currentNodeStart = currentOffset;
23909      const currentNodeEnd = currentOffset + currentNodeLength;
23910      if (currentNodeEnd <= startIndex) {
23911        unmodifiedBeforeNodes.push(currentNode);
23912        matchingOffset += currentNodeLength;
23913      } else if (currentNodeStart >= endIndex) {
23914        unmodifiedAfterNodes.push(currentNode);
23915      } else {
23916        matchingNodes.push(currentNode);
23917      }
23918      currentOffset += currentNodeLength;
23919      currentNodes.shift();
23920    }
23921    return [matchingOffset, unmodifiedBeforeNodes, matchingNodes, unmodifiedAfterNodes];
23922  }
23923  function $createAutoLinkNode_(nodes, startIndex, endIndex, match) {
23924    const linkNode = $createAutoLinkNode(match.url, match.attributes);
23925    if (nodes.length === 1) {
23926      let remainingTextNode = nodes[0];
23927      let linkTextNode;
23928      if (startIndex === 0) {
23929        [linkTextNode, remainingTextNode] = remainingTextNode.splitText(endIndex);
23930      } else {
23931        [, linkTextNode, remainingTextNode] = remainingTextNode.splitText(startIndex, endIndex);
23932      }
23933      const textNode = $createTextNode2(match.text);
23934      textNode.setFormat(linkTextNode.getFormat());
23935      textNode.setDetail(linkTextNode.getDetail());
23936      textNode.setStyle(linkTextNode.getStyle());
23937      linkNode.append(textNode);
23938      linkTextNode.replace(linkNode);
23939      return remainingTextNode;
23940    } else if (nodes.length > 1) {
23941      const firstTextNode = nodes[0];
23942      let offset3 = firstTextNode.getTextContent().length;
23943      let firstLinkTextNode;
23944      if (startIndex === 0) {
23945        firstLinkTextNode = firstTextNode;
23946      } else {
23947        [, firstLinkTextNode] = firstTextNode.splitText(startIndex);
23948      }
23949      const linkNodes = [];
23950      let remainingTextNode;
23951      for (let i2 = 1; i2 < nodes.length; i2++) {
23952        const currentNode = nodes[i2];
23953        const currentNodeText = currentNode.getTextContent();
23954        const currentNodeLength = currentNodeText.length;
23955        const currentNodeStart = offset3;
23956        const currentNodeEnd = offset3 + currentNodeLength;
23957        if (currentNodeStart < endIndex) {
23958          if (currentNodeEnd <= endIndex) {
23959            linkNodes.push(currentNode);
23960          } else {
23961            const [linkTextNode, endNode] = currentNode.splitText(endIndex - currentNodeStart);
23962            linkNodes.push(linkTextNode);
23963            remainingTextNode = endNode;
23964          }
23965        }
23966        offset3 += currentNodeLength;
23967      }
23968      const selection = $getSelection2();
23969      const selectedTextNode = selection ? selection.getNodes().find($isTextNode2) : void 0;
23970      const textNode = $createTextNode2(firstLinkTextNode.getTextContent());
23971      textNode.setFormat(firstLinkTextNode.getFormat());
23972      textNode.setDetail(firstLinkTextNode.getDetail());
23973      textNode.setStyle(firstLinkTextNode.getStyle());
23974      linkNode.append(textNode, ...linkNodes);
23975      if (selectedTextNode && selectedTextNode === firstLinkTextNode) {
23976        if ($isRangeSelection2(selection)) {
23977          textNode.select(selection.anchor.offset, selection.focus.offset);
23978        } else if ($isNodeSelection2(selection)) {
23979          textNode.select(0, textNode.getTextContent().length);
23980        }
23981      }
23982      firstLinkTextNode.replace(linkNode);
23983      return remainingTextNode;
23984    }
23985    return void 0;
23986  }
23987  function $handleLinkCreation(nodes, matchers, onChange, separatorRegex) {
23988    for (const node of nodes) {
23989      const parent = node.getParent();
23990      if ($isAutoLinkNode(parent) && !parent.getIsUnlinked()) {
23991        return;
23992      }
23993    }
23994    let currentNodes = [...nodes];
23995    const initialText = currentNodes.map((node) => node.getTextContent()).join("");
23996    let text2 = initialText;
23997    let match;
23998    let invalidMatchEnd = 0;
23999    while ((match = findFirstMatch(text2, matchers)) && match !== null) {
24000      const matchStart = match.index;
24001      const matchLength = match.length;
24002      const matchEnd = matchStart + matchLength;
24003      const isValid = isContentAroundIsValid(invalidMatchEnd + matchStart, invalidMatchEnd + matchEnd, separatorRegex, initialText, currentNodes);
24004      if (isValid) {
24005        const [matchingOffset, , matchingNodes, unmodifiedAfterNodes] = extractMatchingNodes(currentNodes, invalidMatchEnd + matchStart, invalidMatchEnd + matchEnd);
24006        let alreadyLinked = false;
24007        for (const node of matchingNodes) {
24008          const parent = node.getParent();
24009          if ($isAutoLinkNode(parent) && !parent.getIsUnlinked()) {
24010            alreadyLinked = true;
24011            break;
24012          }
24013        }
24014        if (alreadyLinked) {
24015          invalidMatchEnd += matchEnd;
24016          text2 = text2.substring(matchEnd);
24017          continue;
24018        }
24019        const actualMatchStart = invalidMatchEnd + matchStart - matchingOffset;
24020        const actualMatchEnd = invalidMatchEnd + matchEnd - matchingOffset;
24021        const remainingTextNode = $createAutoLinkNode_(matchingNodes, actualMatchStart, actualMatchEnd, match);
24022        currentNodes = remainingTextNode ? [remainingTextNode, ...unmodifiedAfterNodes] : unmodifiedAfterNodes;
24023        onChange(match.url, null);
24024        invalidMatchEnd = 0;
24025      } else {
24026        invalidMatchEnd += matchEnd;
24027      }
24028      text2 = text2.substring(matchEnd);
24029    }
24030  }
24031  function handleLinkEdit(linkNode, matchers, onChange, separatorRegex) {
24032    const children = linkNode.getChildren();
24033    const childrenLength = children.length;
24034    for (let i2 = 0; i2 < childrenLength; i2++) {
24035      const child = children[i2];
24036      if (!$isTextNode2(child) || !child.isSimpleText()) {
24037        replaceWithChildren(linkNode);
24038        onChange(null, linkNode.getURL());
24039        return;
24040      }
24041    }
24042    const text2 = linkNode.getTextContent();
24043    const match = findFirstMatch(text2, matchers);
24044    if (match === null || match.text !== text2) {
24045      replaceWithChildren(linkNode);
24046      onChange(null, linkNode.getURL());
24047      return;
24048    }
24049    if (!isPreviousNodeValid(linkNode, separatorRegex) || !isNextNodeValid(linkNode, separatorRegex)) {
24050      replaceWithChildren(linkNode);
24051      onChange(null, linkNode.getURL());
24052      return;
24053    }
24054    const url = linkNode.getURL();
24055    if (url !== match.url) {
24056      linkNode.setURL(match.url);
24057      onChange(match.url, url);
24058    }
24059    if (match.attributes) {
24060      const rel = linkNode.getRel();
24061      if (rel !== match.attributes.rel) {
24062        linkNode.setRel(match.attributes.rel || null);
24063        onChange(match.attributes.rel || null, rel);
24064      }
24065      const target = linkNode.getTarget();
24066      if (target !== match.attributes.target) {
24067        linkNode.setTarget(match.attributes.target || null);
24068        onChange(match.attributes.target || null, target);
24069      }
24070    }
24071  }
24072  function handleBadNeighbors(textNode, matchers, onChange, separatorRegex) {
24073    const parent = textNode.getParent();
24074    const previousSibling = textNode.getPreviousSibling();
24075    const nextSibling = textNode.getNextSibling();
24076    const text2 = textNode.getTextContent();
24077    if ($isAutoLinkNode(parent) && !parent.getIsUnlinked()) {
24078      return;
24079    }
24080    if ($isAutoLinkNode(previousSibling) && !previousSibling.getIsUnlinked()) {
24081      if (previousSibling.is(textNode.getPreviousSibling()) && textNode.getParent() === previousSibling.getParent()) {
24082        if (!startsWithSeparator(text2, separatorRegex)) {
24083          replaceWithChildren(previousSibling);
24084          onChange(null, previousSibling.getURL());
24085          return;
24086        }
24087        if (startsWithTLD(text2, previousSibling.isEmailURI())) {
24088          const combinedText = previousSibling.getTextContent() + text2;
24089          const match = findFirstMatch(combinedText, matchers);
24090          if (match !== null && match.text === combinedText) {
24091            previousSibling.append(textNode);
24092            handleLinkEdit(previousSibling, matchers, onChange, separatorRegex);
24093            onChange(null, previousSibling.getURL());
24094          }
24095        }
24096      }
24097    }
24098    if ($isAutoLinkNode(nextSibling) && !nextSibling.getIsUnlinked() && !endsWithSeparator(text2, separatorRegex)) {
24099      if (nextSibling.is(textNode.getNextSibling()) && textNode.getParent() === nextSibling.getParent()) {
24100        replaceWithChildren(nextSibling);
24101        onChange(null, nextSibling.getURL());
24102      }
24103    }
24104  }
24105  function replaceWithChildren(node) {
24106    const children = node.getChildren();
24107    const childrenLength = children.length;
24108    for (let j3 = childrenLength - 1; j3 >= 0; j3--) {
24109      node.insertAfter(children[j3]);
24110    }
24111    node.remove();
24112    return children.map((child) => child.getLatest());
24113  }
24114  function getTextNodesToMatch(textNode) {
24115    const textNodesToMatch = [textNode];
24116    let nextSibling = textNode.getNextSibling();
24117    while (nextSibling !== null && $isTextNode2(nextSibling) && nextSibling.isSimpleText()) {
24118      textNodesToMatch.push(nextSibling);
24119      if (/[\s]/.test(nextSibling.getTextContent())) {
24120        break;
24121      }
24122      nextSibling = nextSibling.getNextSibling();
24123    }
24124    return textNodesToMatch;
24125  }
24126  var defaultConfig = {
24127    changeHandlers: [],
24128    excludeParents: [],
24129    matchers: [],
24130    separatorRegex: PUNCTUATION_OR_SPACE
24131  };
24132  function registerAutoLink(editor, config = defaultConfig) {
24133    const {
24134      matchers,
24135      changeHandlers,
24136      excludeParents,
24137      separatorRegex = PUNCTUATION_OR_SPACE
24138    } = config;
24139    const onChange = (url, prevUrl) => {
24140      for (const handler of changeHandlers) {
24141        handler(url, prevUrl);
24142      }
24143    };
24144    return mergeRegister3(editor.registerNodeTransform(TextNode2, (textNode) => {
24145      const parent = textNode.getParentOrThrow();
24146      const previous = textNode.getPreviousSibling();
24147      if ($isAutoLinkNode(parent)) {
24148        handleLinkEdit(parent, matchers, onChange, separatorRegex);
24149      } else if (!$isLinkNode(parent) && !excludeParents.some((pred) => pred(parent))) {
24150        if (textNode.isSimpleText() && (startsWithSeparator(textNode.getTextContent(), separatorRegex) || !$isAutoLinkNode(previous))) {
24151          const textNodesToMatch = getTextNodesToMatch(textNode);
24152          $handleLinkCreation(textNodesToMatch, matchers, onChange, separatorRegex);
24153        }
24154        handleBadNeighbors(textNode, matchers, onChange, separatorRegex);
24155      }
24156    }), editor.registerCommand(
24157      TOGGLE_LINK_COMMAND,
24158      (payload) => {
24159        const selection = $getSelection2();
24160        if (payload !== null || !$isRangeSelection2(selection)) {
24161          return false;
24162        }
24163        const nodes = selection.extract();
24164        nodes.forEach((node) => {
24165          const parent = node.getParent();
24166          if ($isAutoLinkNode(parent)) {
24167            parent.setIsUnlinked(!parent.getIsUnlinked());
24168            parent.markDirty();
24169          }
24170        });
24171        return false;
24172      },
24173      // Has to be higher than TOGGLE_LINK_COMMAND in LinkExtension
24174      COMMAND_PRIORITY_LOW2
24175    ));
24176  }
24177  var AutoLinkExtension = defineExtension2({
24178    config: defaultConfig,
24179    dependencies: [LinkExtension],
24180    mergeConfig(config, overrides) {
24181      const merged = shallowMergeConfig2(config, overrides);
24182      for (const k2 of ["matchers", "changeHandlers", "excludeParents"]) {
24183        const v3 = overrides[k2];
24184        if (Array.isArray(v3)) {
24185          merged[k2] = [...config[k2], ...v3];
24186        }
24187      }
24188      return merged;
24189    },
24190    name: "@lexical/link/AutoLink",
24191    nodes: [AutoLinkNode],
24192    register: registerAutoLink
24193  });
24194  var toggleLink = $toggleLink;
24195
24196  
vendor: 924 bytes, lines 24196-24216
24196// node_modules/@lexical/link/LexicalLink.mjs
24197  var mod5 = true ? LexicalLink_dev_exports : LexicalLink_prod_exports;
24198  var $createAutoLinkNode2 = mod5.$createAutoLinkNode;
24199  var $createLinkNode2 = mod5.$createLinkNode;
24200  var $isAutoLinkNode2 = mod5.$isAutoLinkNode;
24201  var $isLinkNode2 = mod5.$isLinkNode;
24202  var $toggleLink2 = mod5.$toggleLink;
24203  var AutoLinkExtension2 = mod5.AutoLinkExtension;
24204  var AutoLinkNode2 = mod5.AutoLinkNode;
24205  var ClickableLinkExtension2 = mod5.ClickableLinkExtension;
24206  var LinkExtension2 = mod5.LinkExtension;
24207  var LinkNode2 = mod5.LinkNode;
24208  var TOGGLE_LINK_COMMAND2 = mod5.TOGGLE_LINK_COMMAND;
24209  var createLinkMatcherWithRegExp2 = mod5.createLinkMatcherWithRegExp;
24210  var formatUrl2 = mod5.formatUrl;
24211  var registerAutoLink2 = mod5.registerAutoLink;
24212  var registerClickableLink2 = mod5.registerClickableLink;
24213  var registerLink2 = mod5.registerLink;
24214  var toggleLink2 = mod5.toggleLink;
24215
24216  
vendor: 54,913 bytes, lines 24216-25724
24216// node_modules/@lexical/list/LexicalList.dev.mjs
24217  var LexicalList_dev_exports = {};
24218  __export(LexicalList_dev_exports, {
24219    $createListItemNode: () => $createListItemNode,
24220    $createListNode: () => $createListNode,
24221    $getListDepth: () => $getListDepth,
24222    $handleListInsertParagraph: () => $handleListInsertParagraph,
24223    $insertList: () => $insertList,
24224    $isListItemNode: () => $isListItemNode,
24225    $isListNode: () => $isListNode,
24226    $removeList: () => $removeList,
24227    CheckListExtension: () => CheckListExtension,
24228    INSERT_CHECK_LIST_COMMAND: () => INSERT_CHECK_LIST_COMMAND,
24229    INSERT_ORDERED_LIST_COMMAND: () => INSERT_ORDERED_LIST_COMMAND,
24230    INSERT_UNORDERED_LIST_COMMAND: () => INSERT_UNORDERED_LIST_COMMAND,
24231    ListExtension: () => ListExtension,
24232    ListItemNode: () => ListItemNode,
24233    ListNode: () => ListNode,
24234    REMOVE_LIST_COMMAND: () => REMOVE_LIST_COMMAND,
24235    UPDATE_LIST_START_COMMAND: () => UPDATE_LIST_START_COMMAND,
24236    insertList: () => insertList,
24237    registerCheckList: () => registerCheckList,
24238    registerList: () => registerList,
24239    registerListStrictIndentTransform: () => registerListStrictIndentTransform,
24240    removeList: () => removeList
24241  });
24242  function formatDevErrorMessage6(message) {
24243    throw new Error(message);
24244  }
24245  function $getListDepth(listNode) {
24246    let depth = 1;
24247    let parent = listNode.getParent();
24248    while (parent != null) {
24249      if ($isListItemNode(parent)) {
24250        const parentList = parent.getParent();
24251        if ($isListNode(parentList)) {
24252          depth++;
24253          parent = parentList.getParent();
24254          continue;
24255        }
24256        {
24257          formatDevErrorMessage6(`A ListItemNode must have a ListNode for a parent.`);
24258        }
24259      }
24260      return depth;
24261    }
24262    return depth;
24263  }
24264  function $getTopListNode(listItem) {
24265    let list = listItem.getParent();
24266    if (!$isListNode(list)) {
24267      {
24268        formatDevErrorMessage6(`A ListItemNode must have a ListNode for a parent.`);
24269      }
24270    }
24271    let parent = list;
24272    while (parent !== null) {
24273      parent = parent.getParent();
24274      if ($isListNode(parent)) {
24275        list = parent;
24276      }
24277    }
24278    return list;
24279  }
24280  function $getAllListItems(node) {
24281    let listItemNodes = [];
24282    const listChildren = node.getChildren().filter($isListItemNode);
24283    for (let i2 = 0; i2 < listChildren.length; i2++) {
24284      const listItemNode = listChildren[i2];
24285      const firstChild = listItemNode.getFirstChild();
24286      if ($isListNode(firstChild)) {
24287        listItemNodes = listItemNodes.concat($getAllListItems(firstChild));
24288      } else {
24289        listItemNodes.push(listItemNode);
24290      }
24291    }
24292    return listItemNodes;
24293  }
24294  function isNestedListNode(node) {
24295    return $isListItemNode(node) && $isListNode(node.getFirstChild());
24296  }
24297  function $removeHighestEmptyListParent(sublist) {
24298    let emptyListPtr = sublist;
24299    while (emptyListPtr.getNextSibling() == null && emptyListPtr.getPreviousSibling() == null) {
24300      const parent = emptyListPtr.getParent();
24301      if (parent == null || !($isListItemNode(parent) || $isListNode(parent))) {
24302        break;
24303      }
24304      emptyListPtr = parent;
24305    }
24306    emptyListPtr.remove();
24307  }
24308  function $wrapInListItem(node) {
24309    const listItemWrapper = $createListItemNode();
24310    return listItemWrapper.append(node);
24311  }
24312  function $getNewListStart(list, listItem) {
24313    return list.getStart() + listItem.getIndexWithinParent();
24314  }
24315  function $isSelectingEmptyListItem(anchorNode, nodes) {
24316    return $isListItemNode(anchorNode) && (nodes.length === 0 || nodes.length === 1 && anchorNode.is(nodes[0]) && anchorNode.getChildrenSize() === 0);
24317  }
24318  function $insertList(listType) {
24319    const selection = $getSelection2();
24320    if (selection !== null) {
24321      let nodes = selection.getNodes();
24322      if ($isRangeSelection2(selection)) {
24323        const anchorAndFocus = selection.getStartEndPoints();
24324        if (!(anchorAndFocus !== null)) {
24325          formatDevErrorMessage6(`insertList: anchor should be defined`);
24326        }
24327        const [anchor] = anchorAndFocus;
24328        const anchorNode = anchor.getNode();
24329        const anchorNodeParent = anchorNode.getParent();
24330        if ($isRootOrShadowRoot2(anchorNode)) {
24331          const firstChild = anchorNode.getFirstChild();
24332          if (firstChild) {
24333            nodes = firstChild.selectStart().getNodes();
24334          } else {
24335            const paragraph = $createParagraphNode2();
24336            anchorNode.append(paragraph);
24337            nodes = paragraph.select().getNodes();
24338          }
24339        } else if ($isSelectingEmptyListItem(anchorNode, nodes)) {
24340          const list = $createListNode(listType);
24341          if ($isRootOrShadowRoot2(anchorNodeParent)) {
24342            anchorNode.replace(list);
24343            const listItem = $createListItemNode();
24344            if ($isElementNode2(anchorNode)) {
24345              listItem.setFormat(anchorNode.getFormatType());
24346              listItem.setIndent(anchorNode.getIndent());
24347            }
24348            list.append(listItem);
24349          } else if ($isListItemNode(anchorNode)) {
24350            const parent = anchorNode.getParentOrThrow();
24351            append(list, parent.getChildren());
24352            parent.replace(list);
24353          }
24354          return;
24355        }
24356      }
24357      const handled = /* @__PURE__ */ new Set();
24358      for (let i2 = 0; i2 < nodes.length; i2++) {
24359        const node = nodes[i2];
24360        if ($isElementNode2(node) && node.isEmpty() && !$isListItemNode(node) && !handled.has(node.getKey())) {
24361          $createListOrMerge(node, listType);
24362          continue;
24363        }
24364        let parent = $isLeafNode2(node) ? node.getParent() : $isListItemNode(node) && node.isEmpty() ? node : null;
24365        while (parent != null) {
24366          const parentKey = parent.getKey();
24367          if ($isListNode(parent)) {
24368            if (!handled.has(parentKey)) {
24369              const newListNode = $createListNode(listType);
24370              append(newListNode, parent.getChildren());
24371              parent.replace(newListNode);
24372              handled.add(parentKey);
24373            }
24374            break;
24375          } else {
24376            const nextParent = parent.getParent();
24377            if ($isRootOrShadowRoot2(nextParent) && !handled.has(parentKey)) {
24378              handled.add(parentKey);
24379              $createListOrMerge(parent, listType);
24380              break;
24381            }
24382            parent = nextParent;
24383          }
24384        }
24385      }
24386    }
24387  }
24388  function append(node, nodesToAppend) {
24389    node.splice(node.getChildrenSize(), 0, nodesToAppend);
24390  }
24391  function $createListOrMerge(node, listType) {
24392    if ($isListNode(node)) {
24393      return node;
24394    }
24395    const previousSibling = node.getPreviousSibling();
24396    const nextSibling = node.getNextSibling();
24397    const listItem = $createListItemNode();
24398    append(listItem, node.getChildren());
24399    let targetList;
24400    if ($isListNode(previousSibling) && listType === previousSibling.getListType()) {
24401      previousSibling.append(listItem);
24402      if ($isListNode(nextSibling) && listType === nextSibling.getListType()) {
24403        append(previousSibling, nextSibling.getChildren());
24404        nextSibling.remove();
24405      }
24406      targetList = previousSibling;
24407    } else if ($isListNode(nextSibling) && listType === nextSibling.getListType()) {
24408      nextSibling.getFirstChildOrThrow().insertBefore(listItem);
24409      targetList = nextSibling;
24410    } else {
24411      const list = $createListNode(listType);
24412      list.append(listItem);
24413      node.replace(list);
24414      targetList = list;
24415    }
24416    listItem.setFormat(node.getFormatType());
24417    listItem.setIndent(node.getIndent());
24418    const selection = $getSelection2();
24419    if ($isRangeSelection2(selection)) {
24420      if (targetList.getKey() === selection.anchor.key) {
24421        selection.anchor.set(listItem.getKey(), selection.anchor.offset, "element");
24422      }
24423      if (targetList.getKey() === selection.focus.key) {
24424        selection.focus.set(listItem.getKey(), selection.focus.offset, "element");
24425      }
24426    }
24427    node.remove();
24428    return targetList;
24429  }
24430  function mergeLists(list1, list2) {
24431    const listItem1 = list1.getLastChild();
24432    const listItem2 = list2.getFirstChild();
24433    if (listItem1 && listItem2 && isNestedListNode(listItem1) && isNestedListNode(listItem2)) {
24434      mergeLists(listItem1.getFirstChild(), listItem2.getFirstChild());
24435      listItem2.remove();
24436    }
24437    const toMerge = list2.getChildren();
24438    if (toMerge.length > 0) {
24439      list1.append(...toMerge);
24440    }
24441    list2.remove();
24442  }
24443  function $removeList() {
24444    const selection = $getSelection2();
24445    if ($isRangeSelection2(selection)) {
24446      const listNodes = /* @__PURE__ */ new Set();
24447      const nodes = selection.getNodes();
24448      const anchorNode = selection.anchor.getNode();
24449      if ($isSelectingEmptyListItem(anchorNode, nodes)) {
24450        listNodes.add($getTopListNode(anchorNode));
24451      } else {
24452        for (let i2 = 0; i2 < nodes.length; i2++) {
24453          const node = nodes[i2];
24454          if ($isLeafNode2(node)) {
24455            const listItemNode = $getNearestNodeOfType2(node, ListItemNode);
24456            if (listItemNode != null) {
24457              listNodes.add($getTopListNode(listItemNode));
24458            }
24459          }
24460        }
24461      }
24462      for (const listNode of listNodes) {
24463        let insertionPoint = listNode;
24464        const listItems = $getAllListItems(listNode);
24465        for (const listItemNode of listItems) {
24466          const paragraph = $createParagraphNode2().setTextStyle(selection.style).setTextFormat(selection.format);
24467          append(paragraph, listItemNode.getChildren());
24468          insertionPoint.insertAfter(paragraph);
24469          insertionPoint = paragraph;
24470          if (listItemNode.__key === selection.anchor.key) {
24471            $setPointFromCaret2(selection.anchor, $normalizeCaret2($getChildCaret2(paragraph, "next")));
24472          }
24473          if (listItemNode.__key === selection.focus.key) {
24474            $setPointFromCaret2(selection.focus, $normalizeCaret2($getChildCaret2(paragraph, "next")));
24475          }
24476          listItemNode.remove();
24477        }
24478        listNode.remove();
24479      }
24480    }
24481  }
24482  function updateChildrenListItemValue(list) {
24483    const isNotChecklist = list.getListType() !== "check";
24484    let value = list.getStart();
24485    for (const child of list.getChildren()) {
24486      if ($isListItemNode(child)) {
24487        if (child.getValue() !== value) {
24488          child.setValue(value);
24489        }
24490        if (isNotChecklist && child.getLatest().__checked != null) {
24491          child.setChecked(void 0);
24492        }
24493        if (!$isListNode(child.getFirstChild())) {
24494          value++;
24495        }
24496      }
24497    }
24498  }
24499  function mergeNextSiblingListIfSameType(list) {
24500    const nextSibling = list.getNextSibling();
24501    if ($isListNode(nextSibling) && list.getListType() === nextSibling.getListType()) {
24502      mergeLists(list, nextSibling);
24503    }
24504  }
24505  function $handleIndent(listItemNode) {
24506    const removed = /* @__PURE__ */ new Set();
24507    if (isNestedListNode(listItemNode) || removed.has(listItemNode.getKey())) {
24508      return;
24509    }
24510    const parent = listItemNode.getParent();
24511    const nextSibling = listItemNode.getNextSibling();
24512    const previousSibling = listItemNode.getPreviousSibling();
24513    if (isNestedListNode(nextSibling) && isNestedListNode(previousSibling)) {
24514      const innerList = previousSibling.getFirstChild();
24515      if ($isListNode(innerList)) {
24516        innerList.append(listItemNode);
24517        const nextInnerList = nextSibling.getFirstChild();
24518        if ($isListNode(nextInnerList)) {
24519          const children = nextInnerList.getChildren();
24520          append(innerList, children);
24521          nextSibling.remove();
24522          removed.add(nextSibling.getKey());
24523        }
24524      }
24525    } else if (isNestedListNode(nextSibling)) {
24526      const innerList = nextSibling.getFirstChild();
24527      if ($isListNode(innerList)) {
24528        const firstChild = innerList.getFirstChild();
24529        if (firstChild !== null) {
24530          firstChild.insertBefore(listItemNode);
24531        }
24532      }
24533    } else if (isNestedListNode(previousSibling)) {
24534      const innerList = previousSibling.getFirstChild();
24535      if ($isListNode(innerList)) {
24536        innerList.append(listItemNode);
24537      }
24538    } else {
24539      if ($isListNode(parent)) {
24540        const newListItem = $copyNode2(listItemNode);
24541        const newList = $copyNode2(parent);
24542        newListItem.append(newList);
24543        newList.append(listItemNode);
24544        if (previousSibling) {
24545          previousSibling.insertAfter(newListItem);
24546        } else if (nextSibling) {
24547          nextSibling.insertBefore(newListItem);
24548        } else {
24549          parent.append(newListItem);
24550        }
24551      }
24552    }
24553  }
24554  function $handleOutdent(listItemNode) {
24555    if (isNestedListNode(listItemNode)) {
24556      return;
24557    }
24558    const parentList = listItemNode.getParent();
24559    const grandparentListItem = parentList ? parentList.getParent() : void 0;
24560    const greatGrandparentList = grandparentListItem ? grandparentListItem.getParent() : void 0;
24561    if ($isListNode(greatGrandparentList) && $isListItemNode(grandparentListItem) && $isListNode(parentList)) {
24562      const firstChild = parentList ? parentList.getFirstChild() : void 0;
24563      const lastChild = parentList ? parentList.getLastChild() : void 0;
24564      if (listItemNode.is(firstChild)) {
24565        grandparentListItem.insertBefore(listItemNode);
24566        if (parentList.isEmpty()) {
24567          grandparentListItem.remove();
24568        }
24569      } else if (listItemNode.is(lastChild)) {
24570        grandparentListItem.insertAfter(listItemNode);
24571        if (parentList.isEmpty()) {
24572          grandparentListItem.remove();
24573        }
24574      } else {
24575        const previousSiblingsListItem = $copyNode2(listItemNode);
24576        const previousSiblingsList = $copyNode2(parentList);
24577        previousSiblingsListItem.append(previousSiblingsList);
24578        listItemNode.getPreviousSiblings().forEach((sibling) => previousSiblingsList.append(sibling));
24579        const nextSiblingsListItem = $copyNode2(listItemNode);
24580        const nextSiblingsList = $copyNode2(parentList);
24581        nextSiblingsListItem.append(nextSiblingsList);
24582        append(nextSiblingsList, listItemNode.getNextSiblings());
24583        grandparentListItem.insertBefore(previousSiblingsListItem);
24584        grandparentListItem.insertAfter(nextSiblingsListItem);
24585        grandparentListItem.replace(listItemNode);
24586      }
24587    }
24588  }
24589  function $handleListInsertParagraph(restoreNumbering = false) {
24590    const selection = $getSelection2();
24591    if (!$isRangeSelection2(selection) || !selection.isCollapsed()) {
24592      return false;
24593    }
24594    const anchor = selection.anchor.getNode();
24595    let listItem = null;
24596    if ($isListItemNode(anchor) && anchor.getChildrenSize() === 0) {
24597      listItem = anchor;
24598    } else if ($isTextNode2(anchor)) {
24599      const parentListItem = anchor.getParent();
24600      if ($isListItemNode(parentListItem) && parentListItem.getChildren().every((node) => $isTextNode2(node) && node.getTextContent().trim() === "")) {
24601        listItem = parentListItem;
24602      }
24603    }
24604    if (listItem === null) {
24605      return false;
24606    }
24607    const topListNode = $getTopListNode(listItem);
24608    const parent = listItem.getParent();
24609    if (!$isListNode(parent)) {
24610      formatDevErrorMessage6(`A ListItemNode must have a ListNode for a parent.`);
24611    }
24612    const grandparent = parent.getParent();
24613    let replacementNode;
24614    if ($isRootOrShadowRoot2(grandparent)) {
24615      replacementNode = $createParagraphNode2();
24616      topListNode.insertAfter(replacementNode);
24617    } else if ($isListItemNode(grandparent)) {
24618      replacementNode = $copyNode2(grandparent);
24619      grandparent.insertAfter(replacementNode);
24620    } else {
24621      return false;
24622    }
24623    replacementNode.setTextStyle(selection.style).setTextFormat(selection.format).select();
24624    const nextSiblings = listItem.getNextSiblings();
24625    if (nextSiblings.length > 0) {
24626      const newStart = restoreNumbering ? $getNewListStart(parent, listItem) : 1;
24627      const newList = $copyNode2(parent).setStart(newStart);
24628      if ($isListItemNode(replacementNode)) {
24629        const newListItem = $copyNode2(replacementNode);
24630        newListItem.append(newList);
24631        replacementNode.insertAfter(newListItem);
24632      } else {
24633        replacementNode.insertAfter(newList);
24634      }
24635      newList.append(...nextSiblings);
24636    }
24637    $removeHighestEmptyListParent(listItem);
24638    return true;
24639  }
24640  function applyMarkerStyles(dom, node, prevNode) {
24641    const nextTextStyle = node.__textStyle;
24642    const prevTextStyle = prevNode ? prevNode.__textStyle : "";
24643    if (prevNode !== null && prevTextStyle === nextTextStyle) {
24644      return;
24645    }
24646    const styles = getStyleObjectFromCSS2(nextTextStyle);
24647    for (const k2 in styles) {
24648      dom.style.setProperty(`--listitem-marker-${k2}`, styles[k2]);
24649    }
24650    if (prevTextStyle !== "") {
24651      for (const k2 in getStyleObjectFromCSS2(prevTextStyle)) {
24652        if (!(k2 in styles)) {
24653          dom.style.removeProperty(`--listitem-marker-${k2}`);
24654        }
24655      }
24656    }
24657  }
24658  var ListItemNode = class extends ElementNode2 {
24659    /** @internal */
24660    __value;
24661    /** @internal */
24662    __checked;
24663    /** @internal */
24664    $config() {
24665      return this.config("listitem", {
24666        $transform: (node) => {
24667          const parent = node.getParent();
24668          if ($isListNode(parent)) {
24669            if (parent.getListType() !== "check" && node.getChecked() != null) {
24670              node.setChecked(void 0);
24671            }
24672          } else if (parent) {
24673            const newParent = node.createParentElementNode();
24674            if (!$isListNode(newParent)) {
24675              formatDevErrorMessage6(`ListItemNode.createParentElementNode() must return a ListNode`);
24676            }
24677            const children = [node];
24678            for (const dir of ["previous", "next"]) {
24679              children.reverse();
24680              for (const {
24681                origin
24682              } of $getSiblingCaret2(node, dir)) {
24683                if (!$isListItemNode(origin)) {
24684                  break;
24685                }
24686                children.push(origin);
24687              }
24688            }
24689            node.insertBefore(newParent);
24690            newParent.splice(0, 0, children);
24691            if (!$isRootOrShadowRoot2(parent)) {
24692              $insertNodeToNearestRootAtCaret2(newParent, $rewindSiblingCaret2($getSiblingCaret2(newParent, "next")), {
24693                $shouldSplit: () => false,
24694                removeEmptyDestination: true
24695              });
24696              if (parent.isEmpty() && parent.isAttached()) {
24697                parent.remove();
24698              }
24699            }
24700          }
24701        },
24702        extends: ElementNode2,
24703        importDOM: buildImportMap2({
24704          li: () => ({
24705            conversion: $convertListItemElement,
24706            priority: 0
24707          })
24708        })
24709      });
24710    }
24711    constructor(value = 1, checked = void 0, key) {
24712      super(key);
24713      this.__value = value === void 0 ? 1 : value;
24714      this.__checked = checked;
24715    }
24716    afterCloneFrom(prevNode) {
24717      super.afterCloneFrom(prevNode);
24718      this.__value = prevNode.__value;
24719      this.__checked = prevNode.__checked;
24720    }
24721    createDOM(config) {
24722      const element = document.createElement("li");
24723      this.updateListItemDOM(null, element, config);
24724      return element;
24725    }
24726    updateListItemDOM(prevNode, dom, config) {
24727      updateListItemChecked(dom, this, prevNode);
24728      dom.value = this.__value;
24729      $setListItemThemeClassNames(dom, config.theme, this);
24730      const prevStyle = prevNode ? prevNode.__style : "";
24731      const nextStyle = this.__style;
24732      if (prevStyle !== nextStyle) {
24733        setDOMStyleFromCSS2(dom.style, nextStyle, prevStyle);
24734      }
24735      applyMarkerStyles(dom, this, prevNode);
24736    }
24737    updateDOM(prevNode, dom, config) {
24738      const element = dom;
24739      this.updateListItemDOM(prevNode, element, config);
24740      return false;
24741    }
24742    updateFromJSON(serializedNode) {
24743      return super.updateFromJSON(serializedNode).setValue(serializedNode.value).setChecked(serializedNode.checked);
24744    }
24745    exportDOM(editor) {
24746      const element = this.createDOM(editor._config);
24747      const formatType = this.getFormatType();
24748      if (formatType) {
24749        element.style.textAlign = formatType;
24750      }
24751      const direction = this.getDirection();
24752      if (direction) {
24753        element.dir = direction;
24754      }
24755      if (isNestedListNode(this)) {
24756        return {
24757          after(containerElement) {
24758            if (isHTMLElement2(containerElement)) {
24759              const prevSibling = containerElement.previousElementSibling;
24760              if (isHTMLElement2(prevSibling) && prevSibling.nodeName === "LI") {
24761                while (containerElement.firstChild) {
24762                  prevSibling.append(containerElement.firstChild);
24763                }
24764                containerElement.remove();
24765              }
24766            }
24767            return containerElement;
24768          },
24769          element
24770        };
24771      }
24772      return {
24773        element
24774      };
24775    }
24776    exportJSON() {
24777      return {
24778        ...super.exportJSON(),
24779        checked: this.getChecked(),
24780        value: this.getValue()
24781      };
24782    }
24783    append(...nodes) {
24784      for (let i2 = 0; i2 < nodes.length; i2++) {
24785        const node = nodes[i2];
24786        if ($isElementNode2(node) && this.canMergeWith(node)) {
24787          const children = node.getChildren();
24788          this.append(...children);
24789          node.remove();
24790        } else {
24791          super.append(node);
24792        }
24793      }
24794      return this;
24795    }
24796    replace(replaceWithNode, includeChildren) {
24797      if ($isListItemNode(replaceWithNode)) {
24798        return super.replace(replaceWithNode);
24799      }
24800      this.setIndent(0);
24801      const list = this.getParentOrThrow();
24802      if (!$isListNode(list)) {
24803        return replaceWithNode;
24804      }
24805      if (list.__first === this.getKey()) {
24806        list.insertBefore(replaceWithNode);
24807      } else if (list.__last === this.getKey()) {
24808        list.insertAfter(replaceWithNode);
24809      } else {
24810        const newList = $copyNode2(list);
24811        let nextSibling = this.getNextSibling();
24812        while (nextSibling) {
24813          const nodeToAppend = nextSibling;
24814          nextSibling = nextSibling.getNextSibling();
24815          newList.append(nodeToAppend);
24816        }
24817        list.insertAfter(replaceWithNode);
24818        replaceWithNode.insertAfter(newList);
24819      }
24820      if (includeChildren) {
24821        if (!$isElementNode2(replaceWithNode)) {
24822          formatDevErrorMessage6(`includeChildren should only be true for ElementNodes`);
24823        }
24824        this.getChildren().forEach((child) => {
24825          replaceWithNode.append(child);
24826        });
24827      }
24828      this.remove();
24829      if (list.getChildrenSize() === 0) {
24830        list.remove();
24831      }
24832      return replaceWithNode;
24833    }
24834    insertAfter(node, restoreSelection = true) {
24835      const listNode = this.getParentOrThrow();
24836      if (!$isListNode(listNode)) {
24837        {
24838          formatDevErrorMessage6(`insertAfter: list node is not parent of list item node`);
24839        }
24840      }
24841      if ($isListItemNode(node)) {
24842        return super.insertAfter(node, restoreSelection);
24843      }
24844      const siblings = this.getNextSiblings();
24845      listNode.insertAfter(node, restoreSelection);
24846      if (siblings.length !== 0) {
24847        const newListNode = $copyNode2(listNode);
24848        siblings.forEach((sibling) => newListNode.append(sibling));
24849        node.insertAfter(newListNode, restoreSelection);
24850      }
24851      return node;
24852    }
24853    remove(preserveEmptyParent) {
24854      const prevSibling = this.getPreviousSibling();
24855      const nextSibling = this.getNextSibling();
24856      super.remove(preserveEmptyParent);
24857      if (prevSibling && nextSibling && isNestedListNode(prevSibling) && isNestedListNode(nextSibling)) {
24858        mergeLists(prevSibling.getFirstChild(), nextSibling.getFirstChild());
24859        nextSibling.remove();
24860      }
24861    }
24862    resetOnCopyNodeFrom(original) {
24863      super.resetOnCopyNodeFrom(original);
24864      if (original.getChecked()) {
24865        this.setChecked(false);
24866      }
24867    }
24868    insertNewAfter(_3, restoreSelection = true) {
24869      const newElement = $copyNode2(this);
24870      this.insertAfter(newElement, restoreSelection);
24871      return newElement;
24872    }
24873    collapseAtStart(selection) {
24874      const paragraph = $createParagraphNode2();
24875      const children = this.getChildren();
24876      children.forEach((child) => paragraph.append(child));
24877      const listNode = this.getParentOrThrow();
24878      const listNodeParent = listNode.getParentOrThrow();
24879      const isIndented = $isListItemNode(listNodeParent);
24880      if (listNode.getChildrenSize() === 1) {
24881        if (isIndented) {
24882          listNode.remove();
24883          listNodeParent.select();
24884        } else {
24885          listNode.insertBefore(paragraph);
24886          listNode.remove();
24887          const anchor = selection.anchor;
24888          const focus = selection.focus;
24889          const key = paragraph.getKey();
24890          if (anchor.type === "element" && anchor.getNode().is(this)) {
24891            anchor.set(key, anchor.offset, "element");
24892          }
24893          if (focus.type === "element" && focus.getNode().is(this)) {
24894            focus.set(key, focus.offset, "element");
24895          }
24896        }
24897      } else {
24898        listNode.insertBefore(paragraph);
24899        this.remove();
24900      }
24901      return true;
24902    }
24903    getValue() {
24904      const self2 = this.getLatest();
24905      return self2.__value;
24906    }
24907    setValue(value) {
24908      const self2 = this.getWritable();
24909      self2.__value = value;
24910      return self2;
24911    }
24912    getChecked() {
24913      const self2 = this.getLatest();
24914      let listType;
24915      const parent = this.getParent();
24916      if ($isListNode(parent)) {
24917        listType = parent.getListType();
24918      }
24919      return listType === "check" ? Boolean(self2.__checked) : void 0;
24920    }
24921    setChecked(checked) {
24922      const self2 = this.getWritable();
24923      self2.__checked = checked;
24924      return self2;
24925    }
24926    toggleChecked() {
24927      const self2 = this.getWritable();
24928      return self2.setChecked(!self2.__checked);
24929    }
24930    getIndent() {
24931      const parent = this.getParent();
24932      if (parent === null || !this.isAttached()) {
24933        return this.getLatest().__indent;
24934      }
24935      let listNodeParent = parent.getParentOrThrow();
24936      let indentLevel = 0;
24937      while ($isListItemNode(listNodeParent)) {
24938        listNodeParent = listNodeParent.getParentOrThrow().getParentOrThrow();
24939        indentLevel++;
24940      }
24941      return indentLevel;
24942    }
24943    setIndent(indent) {
24944      if (!(typeof indent === "number")) {
24945        formatDevErrorMessage6(`Invalid indent value.`);
24946      }
24947      indent = Math.floor(indent);
24948      if (!(indent >= 0)) {
24949        formatDevErrorMessage6(`Indent value must be non-negative.`);
24950      }
24951      let currentIndent = this.getIndent();
24952      while (currentIndent !== indent) {
24953        if (currentIndent < indent) {
24954          $handleIndent(this);
24955          currentIndent++;
24956        } else {
24957          $handleOutdent(this);
24958          currentIndent--;
24959        }
24960      }
24961      return this;
24962    }
24963    /** @deprecated @internal */
24964    canInsertAfter(node) {
24965      return $isListItemNode(node);
24966    }
24967    /** @deprecated @internal */
24968    canReplaceWith(replacement) {
24969      return $isListItemNode(replacement);
24970    }
24971    canMergeWith(node) {
24972      return $isListItemNode(node) || $isParagraphNode2(node);
24973    }
24974    extractWithChild(child, selection) {
24975      if (!$isRangeSelection2(selection)) {
24976        return false;
24977      }
24978      const anchorNode = selection.anchor.getNode();
24979      const focusNode = selection.focus.getNode();
24980      return this.isParentOf(anchorNode) && this.isParentOf(focusNode) && this.getTextContent().length === selection.getTextContent().length;
24981    }
24982    isParentRequired() {
24983      return true;
24984    }
24985    createParentElementNode() {
24986      return $createListNode("bullet");
24987    }
24988    canMergeWhenEmpty() {
24989      return true;
24990    }
24991  };
24992  function $setListItemThemeClassNames(dom, editorThemeClasses, node) {
24993    const classesToAdd = [];
24994    const classesToRemove = [];
24995    const listTheme = editorThemeClasses.list;
24996    const listItemClassName = listTheme ? listTheme.listitem : void 0;
24997    let nestedListItemClassName;
24998    if (listTheme && listTheme.nested) {
24999      nestedListItemClassName = listTheme.nested.listitem;
25000    }
25001    if (listItemClassName !== void 0) {
25002      classesToAdd.push(...normalizeClassNames2(listItemClassName));
25003    }
25004    if (listTheme) {
25005      const parentNode = node.getParent();
25006      const isCheckList = $isListNode(parentNode) && parentNode.getListType() === "check";
25007      const checked = node.getChecked();
25008      if (!isCheckList || checked) {
25009        classesToRemove.push(listTheme.listitemUnchecked);
25010      }
25011      if (!isCheckList || !checked) {
25012        classesToRemove.push(listTheme.listitemChecked);
25013      }
25014      if (isCheckList) {
25015        classesToAdd.push(checked ? listTheme.listitemChecked : listTheme.listitemUnchecked);
25016      }
25017    }
25018    if (nestedListItemClassName !== void 0) {
25019      const nestedListItemClasses = normalizeClassNames2(nestedListItemClassName);
25020      if (node.getChildren().some((child) => $isListNode(child))) {
25021        classesToAdd.push(...nestedListItemClasses);
25022      } else {
25023        classesToRemove.push(...nestedListItemClasses);
25024      }
25025    }
25026    if (classesToRemove.length > 0) {
25027      removeClassNamesFromElement3(dom, ...classesToRemove);
25028    }
25029    if (classesToAdd.length > 0) {
25030      addClassNamesToElement3(dom, ...classesToAdd);
25031    }
25032  }
25033  function updateListItemChecked(dom, listItemNode, prevListItemNode) {
25034    const parent = listItemNode.getParent();
25035    const isCheckbox = $isListNode(parent) && parent.getListType() === "check" && // Only add attributes for leaf list items
25036    !$isListNode(listItemNode.getFirstChild());
25037    if (!isCheckbox) {
25038      dom.removeAttribute("role");
25039      dom.removeAttribute("tabIndex");
25040      dom.removeAttribute("aria-checked");
25041    } else {
25042      dom.setAttribute("role", "checkbox");
25043      dom.setAttribute("tabIndex", "-1");
25044      if (!prevListItemNode || listItemNode.__checked !== prevListItemNode.__checked) {
25045        dom.setAttribute("aria-checked", listItemNode.getChecked() ? "true" : "false");
25046      }
25047    }
25048  }
25049  function $convertListItemElement(domNode) {
25050    const isGitHubCheckList = domNode.classList.contains("task-list-item");
25051    if (isGitHubCheckList) {
25052      for (const child of domNode.children) {
25053        if (child.tagName === "INPUT") {
25054          return $convertCheckboxInput(child);
25055        }
25056      }
25057    }
25058    const isJoplinCheckList = domNode.classList.contains("joplin-checkbox");
25059    if (isJoplinCheckList) {
25060      for (const child of domNode.children) {
25061        if (child.classList.contains("checkbox-wrapper") && child.children.length > 0 && child.children[0].tagName === "INPUT") {
25062          return $convertCheckboxInput(child.children[0]);
25063        }
25064      }
25065    }
25066    const ariaCheckedAttr = domNode.getAttribute("aria-checked");
25067    const checked = ariaCheckedAttr === "true" ? true : ariaCheckedAttr === "false" ? false : void 0;
25068    return {
25069      node: $createListItemNode(checked)
25070    };
25071  }
25072  function $convertCheckboxInput(domNode) {
25073    const isCheckboxInput = domNode.getAttribute("type") === "checkbox";
25074    if (!isCheckboxInput) {
25075      return {
25076        node: null
25077      };
25078    }
25079    const checked = domNode.hasAttribute("checked");
25080    return {
25081      node: $createListItemNode(checked)
25082    };
25083  }
25084  function $createListItemNode(checked) {
25085    return $applyNodeReplacement2(new ListItemNode(void 0, checked));
25086  }
25087  function $isListItemNode(node) {
25088    return node instanceof ListItemNode;
25089  }
25090  var ListNode = class extends ElementNode2 {
25091    /** @internal */
25092    __tag;
25093    /** @internal */
25094    __start;
25095    /** @internal */
25096    __listType;
25097    /** @internal */
25098    $config() {
25099      return this.config("list", {
25100        $transform: (node) => {
25101          mergeNextSiblingListIfSameType(node);
25102          updateChildrenListItemValue(node);
25103        },
25104        extends: ElementNode2,
25105        importDOM: buildImportMap2({
25106          ol: () => ({
25107            conversion: $convertListNode,
25108            priority: 0
25109          }),
25110          ul: () => ({
25111            conversion: $convertListNode,
25112            priority: 0
25113          })
25114        })
25115      });
25116    }
25117    constructor(listType = "number", start3 = 1, key) {
25118      super(key);
25119      const _listType = TAG_TO_LIST_TYPE[listType] || listType;
25120      this.__listType = _listType;
25121      this.__tag = _listType === "number" ? "ol" : "ul";
25122      this.__start = start3;
25123    }
25124    afterCloneFrom(prevNode) {
25125      super.afterCloneFrom(prevNode);
25126      this.__listType = prevNode.__listType;
25127      this.__tag = prevNode.__tag;
25128      this.__start = prevNode.__start;
25129    }
25130    getTag() {
25131      return this.getLatest().__tag;
25132    }
25133    setListType(type) {
25134      const writable = this.getWritable();
25135      writable.__listType = type;
25136      writable.__tag = type === "number" ? "ol" : "ul";
25137      return writable;
25138    }
25139    getListType() {
25140      return this.getLatest().__listType;
25141    }
25142    getStart() {
25143      return this.getLatest().__start;
25144    }
25145    setStart(start3) {
25146      const self2 = this.getWritable();
25147      self2.__start = start3;
25148      return self2;
25149    }
25150    // View
25151    createDOM(config, _editor) {
25152      const tag = this.__tag;
25153      const dom = document.createElement(tag);
25154      if (this.__start !== 1) {
25155        dom.setAttribute("start", String(this.__start));
25156      }
25157      dom.__lexicalListType = this.__listType;
25158      $setListThemeClassNames(dom, config.theme, this);
25159      return dom;
25160    }
25161    updateDOM(prevNode, dom, config) {
25162      if (prevNode.__tag !== this.__tag || prevNode.__listType !== this.__listType) {
25163        return true;
25164      }
25165      $setListThemeClassNames(dom, config.theme, this);
25166      if (prevNode.__start !== this.__start) {
25167        dom.setAttribute("start", String(this.__start));
25168      }
25169      return false;
25170    }
25171    updateFromJSON(serializedNode) {
25172      return super.updateFromJSON(serializedNode).setListType(serializedNode.listType).setStart(serializedNode.start);
25173    }
25174    exportDOM(editor) {
25175      const element = this.createDOM(editor._config, editor);
25176      if (isHTMLElement3(element)) {
25177        if (this.__start !== 1) {
25178          element.setAttribute("start", String(this.__start));
25179        }
25180        if (this.__listType === "check") {
25181          element.setAttribute("__lexicalListType", "check");
25182        }
25183      }
25184      return {
25185        element
25186      };
25187    }
25188    exportJSON() {
25189      return {
25190        ...super.exportJSON(),
25191        listType: this.getListType(),
25192        start: this.getStart(),
25193        tag: this.getTag()
25194      };
25195    }
25196    canBeEmpty() {
25197      return false;
25198    }
25199    canIndent() {
25200      return false;
25201    }
25202    splice(start3, deleteCount, nodesToInsert) {
25203      const exampleListItem = nodesToInsert.find($isListItemNode) ?? this.getChildren().find($isListItemNode);
25204      const $newListItem = exampleListItem ? () => $copyNode2(exampleListItem) : $createListItemNode;
25205      let listItemNodesToInsert = nodesToInsert;
25206      for (let i2 = 0; i2 < nodesToInsert.length; i2++) {
25207        const node = nodesToInsert[i2];
25208        if (!$isListItemNode(node)) {
25209          if (listItemNodesToInsert === nodesToInsert) {
25210            listItemNodesToInsert = [...nodesToInsert];
25211          }
25212          listItemNodesToInsert[i2] = $newListItem().append($isElementNode2(node) && !($isListNode(node) || node.isInline()) ? $createTextNode2(node.getTextContent()) : node);
25213        }
25214      }
25215      return super.splice(start3, deleteCount, listItemNodesToInsert);
25216    }
25217    extractWithChild(child) {
25218      return $isListItemNode(child);
25219    }
25220  };
25221  function $setListThemeClassNames(dom, editorThemeClasses, node) {
25222    const classesToAdd = [];
25223    const classesToRemove = [];
25224    const listTheme = editorThemeClasses.list;
25225    if (listTheme !== void 0) {
25226      const listLevelsClassNames = listTheme[`${node.__tag}Depth`] || [];
25227      const listDepth = $getListDepth(node) - 1;
25228      const normalizedListDepth = listDepth % listLevelsClassNames.length;
25229      const listLevelClassName = listLevelsClassNames[normalizedListDepth];
25230      const listClassName = listTheme[node.__tag];
25231      let nestedListClassName;
25232      const nestedListTheme = listTheme.nested;
25233      const checklistClassName = listTheme.checklist;
25234      if (nestedListTheme !== void 0 && nestedListTheme.list) {
25235        nestedListClassName = nestedListTheme.list;
25236      }
25237      if (listClassName !== void 0) {
25238        classesToAdd.push(listClassName);
25239      }
25240      if (checklistClassName !== void 0 && node.__listType === "check") {
25241        classesToAdd.push(checklistClassName);
25242      }
25243      if (listLevelClassName !== void 0) {
25244        classesToAdd.push(...normalizeClassNames2(listLevelClassName));
25245        for (let i2 = 0; i2 < listLevelsClassNames.length; i2++) {
25246          if (i2 !== normalizedListDepth) {
25247            classesToRemove.push(node.__tag + i2);
25248          }
25249        }
25250      }
25251      if (nestedListClassName !== void 0) {
25252        const nestedListItemClasses = normalizeClassNames2(nestedListClassName);
25253        if (listDepth > 1) {
25254          classesToAdd.push(...nestedListItemClasses);
25255        } else {
25256          classesToRemove.push(...nestedListItemClasses);
25257        }
25258      }
25259    }
25260    if (classesToRemove.length > 0) {
25261      removeClassNamesFromElement3(dom, ...classesToRemove);
25262    }
25263    if (classesToAdd.length > 0) {
25264      addClassNamesToElement3(dom, ...classesToAdd);
25265    }
25266  }
25267  function $normalizeChildren(nodes) {
25268    const normalizedListItems = [];
25269    for (let i2 = 0; i2 < nodes.length; i2++) {
25270      const node = nodes[i2];
25271      if ($isListItemNode(node)) {
25272        normalizedListItems.push(node);
25273        const children = node.getChildren();
25274        if (children.length > 1) {
25275          children.forEach((child) => {
25276            if ($isListNode(child)) {
25277              normalizedListItems.push($wrapInListItem(child));
25278            }
25279          });
25280        }
25281      } else {
25282        normalizedListItems.push($wrapInListItem(node));
25283      }
25284    }
25285    return normalizedListItems;
25286  }
25287  function isDomChecklist(domNode) {
25288    if (domNode.getAttribute("__lexicallisttype") === "check" || // is github checklist
25289    domNode.classList.contains("contains-task-list") || // is joplin checklist
25290    domNode.getAttribute("data-is-checklist") === "1") {
25291      return true;
25292    }
25293    for (const child of domNode.childNodes) {
25294      if (isHTMLElement3(child) && child.hasAttribute("aria-checked")) {
25295        return true;
25296      }
25297    }
25298    return false;
25299  }
25300  function $convertListNode(domNode) {
25301    const nodeName = domNode.nodeName.toLowerCase();
25302    let node = null;
25303    if (nodeName === "ol") {
25304      const start3 = domNode.start;
25305      node = $createListNode("number", start3);
25306    } else if (nodeName === "ul") {
25307      if (isDomChecklist(domNode)) {
25308        node = $createListNode("check");
25309      } else {
25310        node = $createListNode("bullet");
25311      }
25312    }
25313    return {
25314      after: $normalizeChildren,
25315      node
25316    };
25317  }
25318  var TAG_TO_LIST_TYPE = {
25319    ol: "number",
25320    ul: "bullet"
25321  };
25322  function $createListNode(listType = "number", start3 = 1) {
25323    return $applyNodeReplacement2(new ListNode(listType, start3));
25324  }
25325  function $isListNode(node) {
25326    return node instanceof ListNode;
25327  }
25328  var INSERT_CHECK_LIST_COMMAND = createCommand2("INSERT_CHECK_LIST_COMMAND");
25329  function registerCheckList(editor, options) {
25330    const disableTakeFocusOnClick = options && options.disableTakeFocusOnClick || false;
25331    const peekDisableTakeFocusOnClick = typeof disableTakeFocusOnClick === "boolean" ? () => disableTakeFocusOnClick : disableTakeFocusOnClick.peek.bind(disableTakeFocusOnClick);
25332    const DEDUP_WINDOW_MS = 500;
25333    const isWithinDedupWindow = (event) => {
25334      const target = event.target;
25335      if (!isHTMLElement3(target)) {
25336        return false;
25337      }
25338      const last = target.__lexicalCheckListLastHandled;
25339      return last !== void 0 && event.timeStamp - last < DEDUP_WINDOW_MS;
25340    };
25341    const recordHandled = (event) => {
25342      const target = event.target;
25343      if (isHTMLElement3(target)) {
25344        target.__lexicalCheckListLastHandled = event.timeStamp;
25345      }
25346    };
25347    const configHandleClick = (event) => {
25348      if (isWithinDedupWindow(event)) {
25349        return;
25350      }
25351      recordHandled(event);
25352      handleClick(event, peekDisableTakeFocusOnClick());
25353    };
25354    const configHandlePointerUp = (event) => {
25355      if (event.pointerType !== "touch") {
25356        return;
25357      }
25358      if (isWithinDedupWindow(event)) {
25359        return;
25360      }
25361      recordHandled(event);
25362      handleClick(event, peekDisableTakeFocusOnClick());
25363    };
25364    const configHandleSelectDefaults = (event) => {
25365      handleSelectDefaults(event, peekDisableTakeFocusOnClick());
25366    };
25367    return mergeRegister3(editor.registerCommand(INSERT_CHECK_LIST_COMMAND, () => {
25368      $insertList("check");
25369      return true;
25370    }, COMMAND_PRIORITY_LOW2), editor.registerCommand(KEY_ARROW_DOWN_COMMAND2, (event) => {
25371      return handleArrowUpOrDown(event, editor, false);
25372    }, COMMAND_PRIORITY_LOW2), editor.registerCommand(KEY_ARROW_UP_COMMAND2, (event) => {
25373      return handleArrowUpOrDown(event, editor, true);
25374    }, COMMAND_PRIORITY_LOW2), editor.registerCommand(KEY_ESCAPE_COMMAND2, () => {
25375      const activeItem = getActiveCheckListItem();
25376      if (activeItem != null) {
25377        const rootElement = editor.getRootElement();
25378        if (rootElement != null) {
25379          rootElement.focus();
25380        }
25381        return true;
25382      }
25383      return false;
25384    }, COMMAND_PRIORITY_LOW2), editor.registerCommand(KEY_SPACE_COMMAND2, (event) => {
25385      const activeItem = getActiveCheckListItem();
25386      if (activeItem != null && editor.isEditable()) {
25387        editor.update(() => {
25388          const listItemNode = $getNearestNodeFromDOMNode2(activeItem);
25389          if ($isListItemNode(listItemNode)) {
25390            event.preventDefault();
25391            listItemNode.toggleChecked();
25392          }
25393        });
25394        return true;
25395      }
25396      return false;
25397    }, COMMAND_PRIORITY_LOW2), editor.registerCommand(KEY_ARROW_LEFT_COMMAND2, (event) => {
25398      return editor.getEditorState().read(() => {
25399        const selection = $getSelection2();
25400        if ($isRangeSelection2(selection) && selection.isCollapsed()) {
25401          const {
25402            anchor
25403          } = selection;
25404          const isElement2 = anchor.type === "element";
25405          if (isElement2 || anchor.offset === 0) {
25406            const anchorNode = anchor.getNode();
25407            const elementNode = $findMatchingParent3(anchorNode, (node) => $isElementNode2(node) && !node.isInline());
25408            if ($isListItemNode(elementNode)) {
25409              const parent = elementNode.getParent();
25410              if ($isListNode(parent) && parent.getListType() === "check" && (isElement2 || elementNode.getFirstDescendant() === anchorNode)) {
25411                const domNode = editor.getElementByKey(elementNode.__key);
25412                if (domNode != null && document.activeElement !== domNode) {
25413                  domNode.focus();
25414                  event.preventDefault();
25415                  return true;
25416                }
25417              }
25418            }
25419          }
25420        }
25421        return false;
25422      });
25423    }, COMMAND_PRIORITY_LOW2), editor.registerRootListener((rootElement) => {
25424      if (rootElement !== null) {
25425        rootElement.addEventListener("click", configHandleClick);
25426        rootElement.addEventListener("pointerup", configHandlePointerUp);
25427        rootElement.addEventListener("pointerdown", configHandleSelectDefaults, {
25428          capture: true
25429        });
25430        rootElement.addEventListener("mousedown", configHandleSelectDefaults, {
25431          capture: true
25432        });
25433        rootElement.addEventListener("touchstart", configHandleSelectDefaults, {
25434          capture: true,
25435          passive: false
25436        });
25437        return () => {
25438          rootElement.removeEventListener("click", configHandleClick);
25439          rootElement.removeEventListener("pointerup", configHandlePointerUp);
25440          rootElement.removeEventListener("pointerdown", configHandleSelectDefaults, {
25441            capture: true
25442          });
25443          rootElement.removeEventListener("mousedown", configHandleSelectDefaults, {
25444            capture: true
25445          });
25446          rootElement.removeEventListener("touchstart", configHandleSelectDefaults, {
25447            capture: true
25448          });
25449        };
25450      }
25451    }));
25452  }
25453  function handleCheckItemEvent(event, callback) {
25454    const target = event.target;
25455    if (!isHTMLElement3(target)) {
25456      return;
25457    }
25458    const firstChild = target.firstChild;
25459    if (isHTMLElement3(firstChild) && (firstChild.tagName === "UL" || firstChild.tagName === "OL")) {
25460      return;
25461    }
25462    const parentNode = target.parentNode;
25463    if (!parentNode || parentNode.__lexicalListType !== "check") {
25464      return;
25465    }
25466    let clientX = null;
25467    let pointerType = null;
25468    if ("clientX" in event) {
25469      clientX = event.clientX;
25470    } else if ("touches" in event) {
25471      const touches = event.touches;
25472      if (touches.length > 0) {
25473        clientX = touches[0].clientX;
25474        pointerType = "touch";
25475      }
25476    }
25477    if (clientX == null) {
25478      return;
25479    }
25480    const rect = target.getBoundingClientRect();
25481    const zoom = calculateZoomLevel2(target);
25482    const clientXInPixels = clientX / zoom;
25483    const beforeStyles = window.getComputedStyle ? window.getComputedStyle(target, "::before") : {
25484      width: "0px"
25485    };
25486    const beforeWidthInPixels = parseFloat(beforeStyles.width);
25487    const isTouchEvent = pointerType === "touch" || "pointerType" in event && event.pointerType === "touch";
25488    const clickAreaPadding = isTouchEvent ? 32 : 0;
25489    if (target.dir === "rtl" ? clientXInPixels < rect.right + clickAreaPadding && clientXInPixels > rect.right - beforeWidthInPixels - clickAreaPadding : clientXInPixels > rect.left - clickAreaPadding && clientXInPixels < rect.left + beforeWidthInPixels + clickAreaPadding) {
25490      callback();
25491    }
25492  }
25493  function handleClick(event, disableFocusOnClick) {
25494    handleCheckItemEvent(event, () => {
25495      if (isHTMLElement3(event.target)) {
25496        const domNode = event.target;
25497        const editor = getNearestEditorFromDOMNode2(domNode);
25498        if (editor != null && editor.isEditable()) {
25499          editor.update(() => {
25500            const node = $getNearestNodeFromDOMNode2(domNode);
25501            if ($isListItemNode(node)) {
25502              if (disableFocusOnClick) {
25503                $addUpdateTag2(SKIP_SELECTION_FOCUS_TAG2);
25504                $addUpdateTag2(SKIP_DOM_SELECTION_TAG2);
25505              } else {
25506                domNode.focus();
25507              }
25508              node.toggleChecked();
25509            }
25510          });
25511        }
25512      }
25513    });
25514  }
25515  function handleSelectDefaults(event, disableTakeFocusOnClick) {
25516    handleCheckItemEvent(event, () => {
25517      event.preventDefault();
25518      if (disableTakeFocusOnClick) {
25519        event.stopPropagation();
25520      }
25521    });
25522  }
25523  function getActiveCheckListItem() {
25524    const activeElement = document.activeElement;
25525    return isHTMLElement3(activeElement) && activeElement.tagName === "LI" && activeElement.parentNode != null && // @ts-ignore internal field
25526    activeElement.parentNode.__lexicalListType === "check" ? activeElement : null;
25527  }
25528  function findCheckListItemSibling(node, backward) {
25529    let sibling = backward ? node.getPreviousSibling() : node.getNextSibling();
25530    let parent = node;
25531    while (sibling == null && $isListItemNode(parent)) {
25532      parent = parent.getParentOrThrow().getParent();
25533      if (parent != null) {
25534        sibling = backward ? parent.getPreviousSibling() : parent.getNextSibling();
25535      }
25536    }
25537    while ($isListItemNode(sibling)) {
25538      const firstChild = backward ? sibling.getLastChild() : sibling.getFirstChild();
25539      if (!$isListNode(firstChild)) {
25540        return sibling;
25541      }
25542      sibling = backward ? firstChild.getLastChild() : firstChild.getFirstChild();
25543    }
25544    return null;
25545  }
25546  function handleArrowUpOrDown(event, editor, backward) {
25547    const activeItem = getActiveCheckListItem();
25548    if (activeItem != null) {
25549      editor.update(() => {
25550        const listItem = $getNearestNodeFromDOMNode2(activeItem);
25551        if (!$isListItemNode(listItem)) {
25552          return;
25553        }
25554        const nextListItem = findCheckListItemSibling(listItem, backward);
25555        if (nextListItem != null) {
25556          nextListItem.selectStart();
25557          const dom = editor.getElementByKey(nextListItem.__key);
25558          if (dom != null) {
25559            event.preventDefault();
25560            setTimeout(() => {
25561              dom.focus();
25562            }, 0);
25563          }
25564        }
25565      });
25566    }
25567    return false;
25568  }
25569  var UPDATE_LIST_START_COMMAND = createCommand2("UPDATE_LIST_START_COMMAND");
25570  var INSERT_UNORDERED_LIST_COMMAND = createCommand2("INSERT_UNORDERED_LIST_COMMAND");
25571  var INSERT_ORDERED_LIST_COMMAND = createCommand2("INSERT_ORDERED_LIST_COMMAND");
25572  var REMOVE_LIST_COMMAND = createCommand2("REMOVE_LIST_COMMAND");
25573  function registerList(editor, options) {
25574    const removeListener = mergeRegister3(editor.registerCommand(INSERT_ORDERED_LIST_COMMAND, () => {
25575      $insertList("number");
25576      return true;
25577    }, COMMAND_PRIORITY_LOW2), editor.registerCommand(UPDATE_LIST_START_COMMAND, (payload) => {
25578      const {
25579        listNodeKey,
25580        newStart
25581      } = payload;
25582      const listNode = $getNodeByKey2(listNodeKey);
25583      if (!$isListNode(listNode)) {
25584        return false;
25585      }
25586      if (listNode.getListType() === "number") {
25587        listNode.setStart(newStart);
25588        updateChildrenListItemValue(listNode);
25589      }
25590      return true;
25591    }, COMMAND_PRIORITY_LOW2), editor.registerCommand(INSERT_UNORDERED_LIST_COMMAND, () => {
25592      $insertList("bullet");
25593      return true;
25594    }, COMMAND_PRIORITY_LOW2), editor.registerCommand(REMOVE_LIST_COMMAND, () => {
25595      $removeList();
25596      return true;
25597    }, COMMAND_PRIORITY_LOW2), editor.registerCommand(INSERT_PARAGRAPH_COMMAND2, () => {
25598      const shouldRestore = options && options.restoreNumbering;
25599      return $handleListInsertParagraph(!!shouldRestore);
25600    }, COMMAND_PRIORITY_LOW2), editor.registerNodeTransform(ListItemNode, (node) => {
25601      const firstChild = node.getFirstChild();
25602      if (firstChild) {
25603        if ($isTextNode2(firstChild)) {
25604          const style = firstChild.getStyle();
25605          const format = firstChild.getFormat();
25606          if (node.getTextStyle() !== style) {
25607            node.setTextStyle(style);
25608          }
25609          if (node.getTextFormat() !== format) {
25610            node.setTextFormat(format);
25611          }
25612        }
25613      } else {
25614        const selection = $getSelection2();
25615        if ($isRangeSelection2(selection) && (selection.style !== node.getTextStyle() || selection.format !== node.getTextFormat()) && selection.isCollapsed() && node.is(selection.anchor.getNode())) {
25616          node.setTextStyle(selection.style).setTextFormat(selection.format);
25617        }
25618      }
25619    }), editor.registerNodeTransform(TextNode2, (node) => {
25620      const listItemParentNode = node.getParent();
25621      if ($isListItemNode(listItemParentNode) && node.is(listItemParentNode.getFirstChild())) {
25622        const style = node.getStyle();
25623        const format = node.getFormat();
25624        if (style !== listItemParentNode.getTextStyle() || format !== listItemParentNode.getTextFormat()) {
25625          listItemParentNode.setTextStyle(style).setTextFormat(format);
25626        }
25627      }
25628    }));
25629    return removeListener;
25630  }
25631  function registerListStrictIndentTransform(editor) {
25632    const $formatListIndentStrict = (listItemNode) => {
25633      const listNode = listItemNode.getParent();
25634      if ($isListNode(listItemNode.getFirstChild()) || !$isListNode(listNode)) {
25635        return;
25636      }
25637      const startingListItemNode = $findMatchingParent3(listItemNode, (node) => $isListItemNode(node) && $isListNode(node.getParent()) && $isListItemNode(node.getPreviousSibling()));
25638      if (startingListItemNode === null && listItemNode.getIndent() > 0) {
25639        listItemNode.setIndent(0);
25640      } else if ($isListItemNode(startingListItemNode)) {
25641        const prevListItemNode = startingListItemNode.getPreviousSibling();
25642        if ($isListItemNode(prevListItemNode)) {
25643          const endListItemNode = $findChildrenEndListItemNode(prevListItemNode);
25644          const endListNode = endListItemNode.getParent();
25645          if ($isListNode(endListNode)) {
25646            const prevDepth = $getListDepth(endListNode);
25647            const depth = $getListDepth(listNode);
25648            if (prevDepth + 1 < depth) {
25649              listItemNode.setIndent(prevDepth);
25650            }
25651          }
25652        }
25653      }
25654    };
25655    const $processListWithStrictIndent = (listNode) => {
25656      const queue = [listNode];
25657      while (queue.length > 0) {
25658        const node = queue.shift();
25659        if (!$isListNode(node)) {
25660          continue;
25661        }
25662        for (const child of node.getChildren()) {
25663          if ($isListItemNode(child)) {
25664            $formatListIndentStrict(child);
25665            const firstChild = child.getFirstChild();
25666            if ($isListNode(firstChild)) {
25667              queue.push(firstChild);
25668            }
25669          }
25670        }
25671      }
25672    };
25673    return editor.registerNodeTransform(ListNode, $processListWithStrictIndent);
25674  }
25675  function $findChildrenEndListItemNode(listItemNode) {
25676    let current = listItemNode;
25677    let firstChild = current.getFirstChild();
25678    while ($isListNode(firstChild)) {
25679      const lastChild = firstChild.getLastChild();
25680      if ($isListItemNode(lastChild)) {
25681        current = lastChild;
25682        firstChild = current.getFirstChild();
25683      } else {
25684        break;
25685      }
25686    }
25687    return current;
25688  }
25689  function insertList(editor, listType) {
25690    editor.update(() => $insertList(listType));
25691  }
25692  function removeList(editor) {
25693    editor.update(() => $removeList());
25694  }
25695  var ListExtension = defineExtension2({
25696    build(editor, config, state) {
25697      return namedSignals2(config);
25698    },
25699    config: safeCast2({
25700      hasStrictIndent: false,
25701      shouldPreserveNumbering: false
25702    }),
25703    name: "@lexical/list/List",
25704    nodes: () => [ListNode, ListItemNode],
25705    register(editor, config, state) {
25706      const stores = state.getOutput();
25707      return mergeRegister3(effect(() => {
25708        return registerList(editor, {
25709          restoreNumbering: stores.shouldPreserveNumbering.value
25710        });
25711      }), effect(() => stores.hasStrictIndent.value ? registerListStrictIndentTransform(editor) : void 0));
25712    }
25713  });
25714  var CheckListExtension = defineExtension2({
25715    build: (editor, config) => namedSignals2(config),
25716    config: safeCast2({
25717      disableTakeFocusOnClick: false
25718    }),
25719    dependencies: [ListExtension],
25720    name: "@lexical/list/CheckList",
25721    register: (editor, config, state) => registerCheckList(editor, state.getOutput())
25722  });
25723
25724  
vendor: 1,253 bytes, lines 25724-25749
25724// node_modules/@lexical/list/LexicalList.mjs
25725  var mod6 = true ? LexicalList_dev_exports : LexicalList_prod_exports;
25726  var $createListItemNode2 = mod6.$createListItemNode;
25727  var $createListNode2 = mod6.$createListNode;
25728  var $getListDepth2 = mod6.$getListDepth;
25729  var $handleListInsertParagraph2 = mod6.$handleListInsertParagraph;
25730  var $insertList2 = mod6.$insertList;
25731  var $isListItemNode2 = mod6.$isListItemNode;
25732  var $isListNode2 = mod6.$isListNode;
25733  var $removeList2 = mod6.$removeList;
25734  var CheckListExtension2 = mod6.CheckListExtension;
25735  var INSERT_CHECK_LIST_COMMAND2 = mod6.INSERT_CHECK_LIST_COMMAND;
25736  var INSERT_ORDERED_LIST_COMMAND2 = mod6.INSERT_ORDERED_LIST_COMMAND;
25737  var INSERT_UNORDERED_LIST_COMMAND2 = mod6.INSERT_UNORDERED_LIST_COMMAND;
25738  var ListExtension2 = mod6.ListExtension;
25739  var ListItemNode2 = mod6.ListItemNode;
25740  var ListNode2 = mod6.ListNode;
25741  var REMOVE_LIST_COMMAND2 = mod6.REMOVE_LIST_COMMAND;
25742  var UPDATE_LIST_START_COMMAND2 = mod6.UPDATE_LIST_START_COMMAND;
25743  var insertList2 = mod6.insertList;
25744  var registerCheckList2 = mod6.registerCheckList;
25745  var registerList2 = mod6.registerList;
25746  var registerListStrictIndentTransform2 = mod6.registerListStrictIndentTransform;
25747  var removeList2 = mod6.removeList;
25748
25749  
vendor: 251 bytes, lines 25749-25756
25749// node_modules/@lexical/plain-text/LexicalPlainText.dev.mjs
25750  var LexicalPlainText_dev_exports = {};
25751  __export(LexicalPlainText_dev_exports, {
25752    PlainTextExtension: () => PlainTextExtension,
25753    registerPlainText: () => registerPlainText
25754  });
25755
25756  
vendor: 980 bytes, lines 25756-25774
25756// node_modules/@lexical/clipboard/LexicalClipboard.dev.mjs
25757  var LexicalClipboard_dev_exports = {};
25758  __export(LexicalClipboard_dev_exports, {
25759    $generateJSONFromSelectedNodes: () => $generateJSONFromSelectedNodes,
25760    $generateNodesFromSerializedNodes: () => $generateNodesFromSerializedNodes,
25761    $getClipboardDataFromSelection: () => $getClipboardDataFromSelection,
25762    $getHtmlContent: () => $getHtmlContent,
25763    $getLexicalContent: () => $getLexicalContent,
25764    $handlePlainTextDrop: () => $handlePlainTextDrop,
25765    $handleRichTextDrop: () => $handleRichTextDrop,
25766    $insertDataTransferForPlainText: () => $insertDataTransferForPlainText,
25767    $insertDataTransferForRichText: () => $insertDataTransferForRichText,
25768    $insertGeneratedNodes: () => $insertGeneratedNodes,
25769    $writeDragSourceToDataTransfer: () => $writeDragSourceToDataTransfer,
25770    copyToClipboard: () => copyToClipboard,
25771    setLexicalClipboardDataTransfer: () => setLexicalClipboardDataTransfer
25772  });
25773
25774  
vendor: 24,728 bytes, lines 25774-26476
25774// node_modules/@lexical/html/LexicalHtml.dev.mjs
25775  var LexicalHtml_dev_exports = {};
25776  __export(LexicalHtml_dev_exports, {
25777    $generateDOMFromNodes: () => $generateDOMFromNodes,
25778    $generateDOMFromRoot: () => $generateDOMFromRoot,
25779    $generateHtmlFromNodes: () => $generateHtmlFromNodes,
25780    $generateNodesFromDOM: () => $generateNodesFromDOM,
25781    $getRenderContextValue: () => $getRenderContextValue,
25782    $withRenderContext: () => $withRenderContext,
25783    DOMRenderExtension: () => DOMRenderExtension,
25784    RenderContextExport: () => RenderContextExport,
25785    RenderContextRoot: () => RenderContextRoot,
25786    contextUpdater: () => contextUpdater,
25787    contextValue: () => contextValue,
25788    createRenderState: () => createRenderState,
25789    domOverride: () => domOverride
25790  });
25791  function formatDevErrorMessage7(message) {
25792    throw new Error(message);
25793  }
25794  var activeContext;
25795  function getContextValue(contextRecord, cfg) {
25796    const {
25797      key
25798    } = cfg;
25799    return contextRecord && key in contextRecord ? contextRecord[key] : cfg.defaultValue;
25800  }
25801  function getEditorContext(editor) {
25802    return activeContext && activeContext.editor === editor ? activeContext : void 0;
25803  }
25804  function getContextRecord(sym, editor) {
25805    const editorContext = getEditorContext(editor);
25806    return editorContext && editorContext[sym];
25807  }
25808  function toPair(contextRecord, pairOrUpdater) {
25809    if ("cfg" in pairOrUpdater) {
25810      const {
25811        cfg,
25812        updater
25813      } = pairOrUpdater;
25814      return [cfg, updater(getContextValue(contextRecord, cfg))];
25815    }
25816    return pairOrUpdater;
25817  }
25818  function contextFromPairs(pairs, parent) {
25819    let rval = parent;
25820    for (const pairOrUpdater of pairs) {
25821      const [k2, v3] = toPair(rval, pairOrUpdater);
25822      const key = k2.key;
25823      if (rval === parent && getContextValue(rval, k2) === v3) {
25824        continue;
25825      }
25826      const ctx = rval || createChildContext(parent);
25827      ctx[key] = v3;
25828      rval = ctx;
25829    }
25830    return rval;
25831  }
25832  function createChildContext(parent) {
25833    return Object.create(parent || null);
25834  }
25835  function contextValue(cfg, value) {
25836    return [cfg, value];
25837  }
25838  function contextUpdater(cfg, updater) {
25839    return {
25840      cfg,
25841      updater
25842    };
25843  }
25844  // @__NO_SIDE_EFFECTS__
25845  function $withFullContext(sym, contextRecord, f, editor = $getEditor2()) {
25846    const prevDOMContext = activeContext;
25847    const parentEditorContext = getEditorContext(editor);
25848    try {
25849      activeContext = {
25850        ...parentEditorContext,
25851        editor,
25852        [sym]: contextRecord
25853      };
25854      return f();
25855    } finally {
25856      activeContext = prevDOMContext;
25857    }
25858  }
25859  // @__NO_SIDE_EFFECTS__
25860  function $withContext(sym, $defaults = () => void 0) {
25861    return (cfg, editor = $getEditor2()) => {
25862      return (f) => {
25863        const parentEditorContext = getEditorContext(editor);
25864        const parentContextRecord = parentEditorContext && parentEditorContext[sym];
25865        const contextRecord = contextFromPairs(cfg, parentContextRecord || $defaults(editor));
25866        if (!contextRecord || contextRecord === parentContextRecord) {
25867          return f();
25868        }
25869        return /* @__PURE__ */ $withFullContext(sym, contextRecord, f, editor);
25870      };
25871    };
25872  }
25873  // @__NO_SIDE_EFFECTS__
25874  function createContextState(tag, name, getDefaultValue, isEqual2) {
25875    return Object.assign(createState2(Symbol(name), {
25876      isEqual: isEqual2,
25877      parse: getDefaultValue
25878    }), {
25879      [tag]: true
25880    });
25881  }
25882  var DOMRenderExtensionName = "@lexical/html/DOM";
25883  var DOMRenderContextSymbol = Symbol.for("@lexical/html/DOMExportContext");
25884  var ALWAYS_TRUE = () => true;
25885  function buildTypeTree(editorConfig) {
25886    const t2 = {};
25887    const {
25888      nodes
25889    } = getKnownTypesAndNodes2(editorConfig);
25890    for (const klass of nodes) {
25891      const type = klass.getType();
25892      t2[type] = {
25893        klass,
25894        types: {}
25895      };
25896    }
25897    for (const baseRec of Object.values(t2)) {
25898      if (baseRec) {
25899        const baseType = baseRec.klass.getType();
25900        for (let {
25901          klass
25902        } = baseRec; $isLexicalNode2(klass.prototype); klass = Object.getPrototypeOf(klass)) {
25903          const {
25904            ownNodeType
25905          } = getStaticNodeConfig2(klass);
25906          const superRec = ownNodeType && t2[ownNodeType];
25907          if (superRec) {
25908            superRec.types[baseType] = true;
25909          }
25910        }
25911      }
25912    }
25913    return t2;
25914  }
25915  function buildNodePredicate(klass) {
25916    return (node) => node instanceof klass;
25917  }
25918  function getPredicate(typeTree, {
25919    nodes
25920  }) {
25921    if (nodes === "*") {
25922      return ALWAYS_TRUE;
25923    }
25924    let types = {};
25925    const predicates = [];
25926    for (const klassOrPredicate of nodes) {
25927      if ("getType" in klassOrPredicate) {
25928        const type = klassOrPredicate.getType();
25929        if (types) {
25930          const tree = typeTree[type];
25931          if (!(tree !== void 0)) {
25932            formatDevErrorMessage7(`Node class ${klassOrPredicate.name} with type ${type} not registered in editor`);
25933          }
25934          types = Object.assign(types, tree.types);
25935        }
25936        predicates.push(buildNodePredicate(klassOrPredicate));
25937      } else {
25938        types = void 0;
25939        predicates.push(klassOrPredicate);
25940      }
25941    }
25942    if (types) {
25943      return types;
25944    } else if (predicates.length === 1) {
25945      return predicates[0];
25946    }
25947    return (node) => {
25948      for (const predicate of predicates) {
25949        if (predicate(node)) {
25950          return true;
25951        }
25952      }
25953      return false;
25954    };
25955  }
25956  function makePrerender() {
25957    return {
25958      $createDOM: [],
25959      $decorateDOM: [],
25960      $exportDOM: [],
25961      $extractWithChild: [],
25962      $getDOMSlot: [],
25963      $shouldExclude: [],
25964      $shouldInclude: [],
25965      $updateDOM: []
25966    };
25967  }
25968  function ignoreNext2(acc) {
25969    return (node, _$next, editor) => acc(node, editor);
25970  }
25971  function ignoreNext3(acc) {
25972    return (node, a2, _$next, editor) => acc(node, a2, editor);
25973  }
25974  function ignoreNext4(acc) {
25975    return (node, a2, b3, _$next, editor) => acc(node, a2, b3, editor);
25976  }
25977  function ignoreNext5(acc) {
25978    return (node, a2, b3, c2, _$next, editor) => acc(node, a2, b3, c2, editor);
25979  }
25980  function merge2($acc, $getOverride) {
25981    return (node, editor) => {
25982      const $next = () => $acc(node, editor);
25983      const $override = $getOverride(node);
25984      return $override ? $override(node, $next, editor) : $next();
25985    };
25986  }
25987  function merge3(acc, $getOverride) {
25988    return (node, a2, editor) => {
25989      const $next = () => acc(node, a2, editor);
25990      const $override = $getOverride(node);
25991      return $override ? $override(node, a2, $next, editor) : $next();
25992    };
25993  }
25994  function merge4($acc, $getOverride) {
25995    return (node, a2, b3, editor) => {
25996      const $next = () => $acc(node, a2, b3, editor);
25997      const $override = $getOverride(node);
25998      return $override ? $override(node, a2, b3, $next, editor) : $next();
25999    };
26000  }
26001  function merge5(acc, $getOverride) {
26002    return (node, a2, b3, c2, editor) => {
26003      const $next = () => acc(node, a2, b3, c2, editor);
26004      const $override = $getOverride(node);
26005      return $override ? $override(node, a2, b3, c2, $next, editor) : $next();
26006    };
26007  }
26008  function sequence4($acc, $getOverride) {
26009    return (node, a2, b3, editor) => {
26010      $acc(node, a2, b3, editor);
26011      const $override = $getOverride(node);
26012      if ($override) {
26013        $override(node, a2, b3, editor);
26014      }
26015    };
26016  }
26017  function compilePrerenderKey(prerender, k2, defaults, mergeFunction, ignoreNextFunction) {
26018    let acc = defaults[k2];
26019    for (const pair of prerender[k2]) {
26020      if (typeof pair[0] === "function") {
26021        const [$predicate, $override] = pair;
26022        acc = mergeFunction(acc, (node) => $predicate(node) && $override || void 0);
26023      } else {
26024        const typeOverrides = pair[1];
26025        const compiled = {};
26026        for (const type in typeOverrides) {
26027          const arr = typeOverrides[type];
26028          if (arr) {
26029            compiled[type] = arr.reduce(($acc, $override) => mergeFunction($acc, () => $override), acc);
26030          }
26031        }
26032        acc = mergeFunction(acc, (node) => {
26033          const f = compiled[node.getType()];
26034          return f && ignoreNextFunction(f);
26035        });
26036      }
26037    }
26038    defaults[k2] = acc;
26039  }
26040  function addOverride(prerender, k2, predicateOrTypes, override) {
26041    if (!override) {
26042      return;
26043    }
26044    const arr = prerender[k2];
26045    if (typeof predicateOrTypes === "function") {
26046      arr.push([predicateOrTypes, override]);
26047    } else {
26048      const last = arr[arr.length - 1];
26049      let types;
26050      if (last && last[0] === "types") {
26051        types = last[1];
26052      } else {
26053        types = {};
26054        arr.push(["types", types]);
26055      }
26056      for (const type in predicateOrTypes) {
26057        const typeArr = types[type] || [];
26058        types[type] = typeArr;
26059        typeArr.push(override);
26060      }
26061    }
26062  }
26063  function isWildcard(override) {
26064    return override.nodes === "*";
26065  }
26066  function sortedOverrides(overrides) {
26067    const byWildcard = [];
26068    const byPredicate = [];
26069    const byNode = [];
26070    for (const override of overrides) {
26071      if (isWildcard(override)) {
26072        byWildcard.push(override);
26073      } else if (Array.isArray(override.nodes)) {
26074        for (const klassOrPredicate of override.nodes) {
26075          if ($isLexicalNode2(klassOrPredicate.prototype)) {
26076            byNode.push(override.nodes.length === 1 ? override : {
26077              ...override,
26078              nodes: [klassOrPredicate]
26079            });
26080          } else {
26081            byPredicate.push(override.nodes.length === 1 ? override : {
26082              ...override,
26083              nodes: [klassOrPredicate]
26084            });
26085          }
26086        }
26087      }
26088    }
26089    const depths = /* @__PURE__ */ new Map();
26090    const depthOf = (klass) => {
26091      let depth = depths.get(klass);
26092      if (depth === void 0) {
26093        depth = 0;
26094        for (let k2 = klass; $isLexicalNode2(k2.prototype); k2 = Object.getPrototypeOf(k2)) {
26095          depth++;
26096        }
26097        depths.set(klass, depth);
26098      }
26099      return depth;
26100    };
26101    byNode.sort((a2, b3) => depthOf(a2.nodes[0]) - depthOf(b3.nodes[0]));
26102    return [...byNode, ...byPredicate, ...byWildcard];
26103  }
26104  function precompileDOMRenderConfigOverrides(editorConfig, overrides) {
26105    const typeTree = buildTypeTree(editorConfig);
26106    const prerender = makePrerender();
26107    for (const override of sortedOverrides(overrides)) {
26108      const predicateOrTypes = getPredicate(typeTree, override);
26109      for (const k_ in prerender) {
26110        const k2 = k_;
26111        addOverride(prerender, k2, predicateOrTypes, override[k2]);
26112      }
26113    }
26114    return prerender;
26115  }
26116  function identity(v3) {
26117    return v3;
26118  }
26119  function compileDOMRenderConfigOverrides(editorConfig, {
26120    overrides
26121  }) {
26122    const prerender = precompileDOMRenderConfigOverrides(editorConfig, overrides);
26123    const dom = {
26124      ...DEFAULT_EDITOR_DOM_CONFIG2,
26125      ...editorConfig.dom
26126    };
26127    compilePrerenderKey(prerender, "$createDOM", dom, merge2, ignoreNext2);
26128    compilePrerenderKey(prerender, "$exportDOM", dom, merge2, ignoreNext2);
26129    compilePrerenderKey(prerender, "$extractWithChild", dom, merge5, ignoreNext5);
26130    compilePrerenderKey(prerender, "$getDOMSlot", dom, merge3, ignoreNext3);
26131    compilePrerenderKey(prerender, "$shouldExclude", dom, merge3, ignoreNext3);
26132    compilePrerenderKey(prerender, "$shouldInclude", dom, merge3, ignoreNext3);
26133    compilePrerenderKey(prerender, "$updateDOM", dom, merge4, ignoreNext4);
26134    compilePrerenderKey(prerender, "$decorateDOM", dom, sequence4, identity);
26135    return dom;
26136  }
26137  var DOMRenderExtension = defineExtension2({
26138    build(editor, config, state) {
26139      return {
26140        defaults: contextFromPairs(config.contextDefaults, void 0)
26141      };
26142    },
26143    config: {
26144      contextDefaults: [],
26145      overrides: []
26146    },
26147    html: {
26148      // Define a RootNode export for $generateDOMFromRoot
26149      export: /* @__PURE__ */ new Map([[RootNode2, () => {
26150        const element = document.createElement("div");
26151        element.role = "textbox";
26152        return {
26153          element
26154        };
26155      }]])
26156    },
26157    init(editorConfig, config) {
26158      editorConfig.dom = compileDOMRenderConfigOverrides(editorConfig, config);
26159    },
26160    mergeConfig(config, partial) {
26161      const merged = shallowMergeConfig2(config, partial);
26162      for (const k2 of ["overrides", "contextDefaults"]) {
26163        if (partial[k2]) {
26164          merged[k2] = [...config[k2], ...partial[k2]];
26165        }
26166      }
26167      return merged;
26168    },
26169    name: DOMRenderExtensionName
26170  });
26171  // @__NO_SIDE_EFFECTS__
26172  function createRenderState(name, getDefaultValue, isEqual2) {
26173    return /* @__PURE__ */ createContextState(DOMRenderContextSymbol, name, getDefaultValue, isEqual2);
26174  }
26175  var RenderContextRoot = /* @__PURE__ */ createRenderState("root", Boolean);
26176  var RenderContextExport = /* @__PURE__ */ createRenderState("isExport", Boolean);
26177  function getDefaultRenderContext(editor) {
26178    const builder = LexicalBuilder2.maybeFromEditor(editor);
26179    return builder && builder.hasExtensionByName(DOMRenderExtensionName) ? getExtensionDependencyFromEditor2(editor, DOMRenderExtension).output.defaults : void 0;
26180  }
26181  function getRenderContext(editor) {
26182    return getContextRecord(DOMRenderContextSymbol, editor) || getDefaultRenderContext(editor);
26183  }
26184  function $getRenderContextValue(cfg, editor = $getEditor2()) {
26185    return getContextValue(getRenderContext(editor), cfg);
26186  }
26187  var $withRenderContext = /* @__PURE__ */ $withContext(DOMRenderContextSymbol, getDefaultRenderContext);
26188  // @__NO_SIDE_EFFECTS__
26189  function domOverride(nodes, config) {
26190    return {
26191      ...config,
26192      nodes
26193    };
26194  }
26195  function isStyleRule(rule) {
26196    return rule.constructor.name === CSSStyleRule.name;
26197  }
26198  function inlineStylesFromStyleSheets(doc) {
26199    if (doc.querySelector("style") === null) {
26200      return;
26201    }
26202    const originalInlineStyles = /* @__PURE__ */ new Map();
26203    function getOriginalInlineProps(el) {
26204      let props = originalInlineStyles.get(el);
26205      if (props === void 0) {
26206        props = /* @__PURE__ */ new Set();
26207        for (let i2 = 0; i2 < el.style.length; i2++) {
26208          props.add(el.style[i2]);
26209        }
26210        originalInlineStyles.set(el, props);
26211      }
26212      return props;
26213    }
26214    try {
26215      for (const sheet of Array.from(doc.styleSheets)) {
26216        let rules;
26217        try {
26218          rules = sheet.cssRules;
26219        } catch (_unused) {
26220          continue;
26221        }
26222        for (const rule of Array.from(rules)) {
26223          if (!isStyleRule(rule)) {
26224            continue;
26225          }
26226          let elements;
26227          try {
26228            elements = doc.querySelectorAll(rule.selectorText);
26229          } catch (_unused2) {
26230            continue;
26231          }
26232          for (const el of Array.from(elements)) {
26233            if (!isHTMLElement2(el)) {
26234              continue;
26235            }
26236            const originalProps = getOriginalInlineProps(el);
26237            for (let i2 = 0; i2 < rule.style.length; i2++) {
26238              const prop = rule.style[i2];
26239              if (!originalProps.has(prop)) {
26240                el.style.setProperty(prop, rule.style.getPropertyValue(prop), rule.style.getPropertyPriority(prop));
26241              }
26242            }
26243          }
26244        }
26245      }
26246    } catch (_unused3) {
26247    }
26248  }
26249  var IGNORE_TAGS = /* @__PURE__ */ new Set(["STYLE", "SCRIPT"]);
26250  function $generateNodesFromDOM(editor, dom) {
26251    if (isDOMDocumentNode2(dom)) {
26252      inlineStylesFromStyleSheets(dom);
26253    }
26254    const elements = isDOMDocumentNode2(dom) ? dom.body.childNodes : dom.childNodes;
26255    const lexicalNodes = [];
26256    const allArtificialNodes = [];
26257    for (const element of elements) {
26258      if (!IGNORE_TAGS.has(element.nodeName)) {
26259        const lexicalNode = $createNodesFromDOM(element, editor, allArtificialNodes, false);
26260        if (lexicalNode !== null) {
26261          for (const node of lexicalNode) {
26262            lexicalNodes.push(node);
26263          }
26264        }
26265      }
26266    }
26267    $unwrapArtificialNodes(allArtificialNodes);
26268    return lexicalNodes;
26269  }
26270  function $generateDOMFromNodes(container, selection = null, editor = $getEditor2()) {
26271    return $withRenderContext([contextValue(RenderContextExport, true)], editor)(() => {
26272      const root = $getRoot2();
26273      const domConfig = $getEditorDOMRenderConfig2(editor);
26274      const parentElementAppend = container.append.bind(container);
26275      for (const topLevelNode of root.getChildren()) {
26276        $appendNodesToHTML(editor, topLevelNode, parentElementAppend, selection, domConfig);
26277      }
26278      return container;
26279    });
26280  }
26281  function $generateDOMFromRoot(container, root = $getRoot2()) {
26282    const editor = $getEditor2();
26283    return $withRenderContext([contextValue(RenderContextExport, true), contextValue(RenderContextRoot, true)], editor)(() => {
26284      const selection = null;
26285      const domConfig = $getEditorDOMRenderConfig2(editor);
26286      const parentElementAppend = container.append.bind(container);
26287      $appendNodesToHTML(editor, root, parentElementAppend, selection, domConfig);
26288      return container;
26289    });
26290  }
26291  function $generateHtmlFromNodes(editor, selection = null) {
26292    if (typeof document === "undefined" || typeof window === "undefined" && typeof global.window === "undefined") {
26293      {
26294        formatDevErrorMessage7(`To use $generateHtmlFromNodes in headless mode please initialize a headless browser implementation such as JSDom or use withDOM from @lexical/headless/dom before calling this function.`);
26295      }
26296    }
26297    return $generateDOMFromNodes(document.createElement("div"), selection, editor).innerHTML;
26298  }
26299  function $appendNodesToHTML(editor, currentNode, parentElementAppend, selection = null, domConfig = $getEditorDOMRenderConfig2(editor)) {
26300    let shouldInclude = domConfig.$shouldInclude(currentNode, selection, editor);
26301    const shouldExclude = domConfig.$shouldExclude(currentNode, selection, editor);
26302    let target = currentNode;
26303    if (selection !== null && $isTextNode2(currentNode)) {
26304      target = $sliceSelectedTextNodeContent2(selection, currentNode, "clone");
26305    }
26306    const exportProps = domConfig.$exportDOM(target, editor);
26307    const {
26308      element,
26309      after,
26310      append: append2,
26311      $getChildNodes
26312    } = exportProps;
26313    if (!element) {
26314      return false;
26315    }
26316    const fragment = document.createDocumentFragment();
26317    const children = $getChildNodes ? $getChildNodes() : $isElementNode2(target) ? target.getChildren() : [];
26318    const fragmentAppend = fragment.append.bind(fragment);
26319    for (const childNode of children) {
26320      const shouldIncludeChild = $appendNodesToHTML(editor, childNode, fragmentAppend, selection, domConfig);
26321      if (!shouldInclude && shouldIncludeChild && domConfig.$extractWithChild(currentNode, childNode, selection, "html", editor)) {
26322        shouldInclude = true;
26323      }
26324    }
26325    if (shouldInclude && !shouldExclude) {
26326      if (isHTMLElement2(element) || isDocumentFragment2(element)) {
26327        if (append2) {
26328          append2(fragment);
26329        } else {
26330          element.append(fragment);
26331        }
26332      }
26333      parentElementAppend(element);
26334      if (after) {
26335        const newElement = after.call(target, element);
26336        if (newElement) {
26337          if (isDocumentFragment2(element)) {
26338            element.replaceChildren(newElement);
26339          } else {
26340            element.replaceWith(newElement);
26341          }
26342        }
26343      }
26344    } else {
26345      parentElementAppend(fragment);
26346    }
26347    return shouldInclude;
26348  }
26349  function getConversionFunction(domNode, editor) {
26350    const {
26351      nodeName
26352    } = domNode;
26353    const cachedConversions = editor._htmlConversions.get(nodeName.toLowerCase());
26354    let currentConversion = null;
26355    if (cachedConversions !== void 0) {
26356      for (const cachedConversion of cachedConversions) {
26357        const domConversion = cachedConversion(domNode);
26358        if (domConversion !== null && (currentConversion === null || // Given equal priority, prefer the last registered importer
26359        // which is typically an application custom node or HTMLConfig['import']
26360        (currentConversion.priority || 0) <= (domConversion.priority || 0))) {
26361          currentConversion = domConversion;
26362        }
26363      }
26364    }
26365    return currentConversion !== null ? currentConversion.conversion : null;
26366  }
26367  function $createNodesFromDOM(node, editor, allArtificialNodes, hasBlockAncestorLexicalNode, forChildMap = /* @__PURE__ */ new Map(), parentLexicalNode) {
26368    const lexicalNodes = [];
26369    if (IGNORE_TAGS.has(node.nodeName)) {
26370      return lexicalNodes;
26371    }
26372    let currentLexicalNode = null;
26373    const transformFunction = getConversionFunction(node, editor);
26374    const transformOutput = transformFunction ? transformFunction(node) : null;
26375    let postTransform = null;
26376    if (transformOutput !== null) {
26377      postTransform = transformOutput.after;
26378      const transformNodes = transformOutput.node;
26379      currentLexicalNode = Array.isArray(transformNodes) ? transformNodes[transformNodes.length - 1] : transformNodes;
26380      if (currentLexicalNode !== null) {
26381        for (const [, forChildFunction] of forChildMap) {
26382          currentLexicalNode = forChildFunction(currentLexicalNode, parentLexicalNode);
26383          if (!currentLexicalNode) {
26384            break;
26385          }
26386        }
26387        if (currentLexicalNode) {
26388          lexicalNodes.push(...Array.isArray(transformNodes) ? transformNodes : [currentLexicalNode]);
26389        }
26390      }
26391      if (transformOutput.forChild != null) {
26392        forChildMap.set(node.nodeName, transformOutput.forChild);
26393      }
26394    }
26395    const children = node.childNodes;
26396    let childLexicalNodes = [];
26397    const hasBlockAncestorLexicalNodeForChildren = currentLexicalNode != null && $isRootOrShadowRoot2(currentLexicalNode) ? false : currentLexicalNode != null && $isBlockElementNode2(currentLexicalNode) || hasBlockAncestorLexicalNode;
26398    for (let i2 = 0; i2 < children.length; i2++) {
26399      childLexicalNodes.push(...$createNodesFromDOM(children[i2], editor, allArtificialNodes, hasBlockAncestorLexicalNodeForChildren, new Map(forChildMap), currentLexicalNode));
26400    }
26401    if (postTransform != null) {
26402      childLexicalNodes = postTransform(childLexicalNodes);
26403    }
26404    if (isBlockDomNode2(node)) {
26405      if (!hasBlockAncestorLexicalNodeForChildren) {
26406        childLexicalNodes = wrapContinuousInlines(node, childLexicalNodes, $createParagraphNode2);
26407      } else {
26408        childLexicalNodes = wrapContinuousInlines(node, childLexicalNodes, () => {
26409          const artificialNode = new ArtificialNode__DO_NOT_USE2();
26410          allArtificialNodes.push(artificialNode);
26411          return artificialNode;
26412        });
26413      }
26414    }
26415    if (currentLexicalNode == null) {
26416      if (childLexicalNodes.length > 0) {
26417        for (const childNode of childLexicalNodes) {
26418          lexicalNodes.push(childNode);
26419        }
26420      } else {
26421        if (isBlockDomNode2(node) && isDomNodeBetweenTwoInlineNodes(node)) {
26422          lexicalNodes.push($createLineBreakNode2());
26423        }
26424      }
26425    } else {
26426      if ($isElementNode2(currentLexicalNode)) {
26427        currentLexicalNode.append(...childLexicalNodes);
26428      }
26429    }
26430    return lexicalNodes;
26431  }
26432  function wrapContinuousInlines(domNode, nodes, createWrapperFn) {
26433    const textAlign = domNode.style.textAlign;
26434    const out = [];
26435    let continuousInlines = [];
26436    for (let i2 = 0; i2 < nodes.length; i2++) {
26437      const node = nodes[i2];
26438      if ($isBlockElementNode2(node)) {
26439        if (textAlign && !node.getFormat()) {
26440          node.setFormat(textAlign);
26441        }
26442        out.push(node);
26443      } else {
26444        continuousInlines.push(node);
26445        if (i2 === nodes.length - 1 || i2 < nodes.length - 1 && $isBlockElementNode2(nodes[i2 + 1])) {
26446          const wrapper = createWrapperFn();
26447          wrapper.setFormat(textAlign);
26448          wrapper.append(...continuousInlines);
26449          out.push(wrapper);
26450          continuousInlines = [];
26451        }
26452      }
26453    }
26454    return out;
26455  }
26456  function $unwrapArtificialNodes(allArtificialNodes) {
26457    for (const node of allArtificialNodes) {
26458      if (node.getParent() && node.getNextSibling() instanceof ArtificialNode__DO_NOT_USE2) {
26459        node.insertAfter($createLineBreakNode2());
26460      }
26461    }
26462    for (const node of allArtificialNodes) {
26463      const parent = node.getParent();
26464      if (parent) {
26465        parent.splice(node.getIndexWithinParent(), 1, node.getChildren());
26466      }
26467    }
26468  }
26469  function isDomNodeBetweenTwoInlineNodes(node) {
26470    if (node.nextSibling == null || node.previousSibling == null) {
26471      return false;
26472    }
26473    return isInlineDomNode2(node.nextSibling) && isInlineDomNode2(node.previousSibling);
26474  }
26475
26476  
vendor: 806 bytes, lines 26476-26492
26476// node_modules/@lexical/html/LexicalHtml.mjs
26477  var mod7 = true ? LexicalHtml_dev_exports : LexicalHtml_prod_exports;
26478  var $generateDOMFromNodes2 = mod7.$generateDOMFromNodes;
26479  var $generateDOMFromRoot2 = mod7.$generateDOMFromRoot;
26480  var $generateHtmlFromNodes2 = mod7.$generateHtmlFromNodes;
26481  var $generateNodesFromDOM2 = mod7.$generateNodesFromDOM;
26482  var $getRenderContextValue2 = mod7.$getRenderContextValue;
26483  var $withRenderContext2 = mod7.$withRenderContext;
26484  var DOMRenderExtension2 = mod7.DOMRenderExtension;
26485  var RenderContextExport2 = mod7.RenderContextExport;
26486  var RenderContextRoot2 = mod7.RenderContextRoot;
26487  var contextUpdater2 = mod7.contextUpdater;
26488  var contextValue2 = mod7.contextValue;
26489  var createRenderState2 = mod7.createRenderState;
26490  var domOverride2 = mod7.domOverride;
26491
26492  
vendor: 17,374 bytes, lines 26492-26978
26492// node_modules/@lexical/clipboard/LexicalClipboard.dev.mjs
26493  function formatDevErrorMessage8(message) {
26494    throw new Error(message);
26495  }
26496  function caretFromPoint(x3, y3) {
26497    if (typeof document.caretRangeFromPoint !== "undefined") {
26498      const range2 = document.caretRangeFromPoint(x3, y3);
26499      if (range2 === null) {
26500        return null;
26501      }
26502      return {
26503        node: range2.startContainer,
26504        offset: range2.startOffset
26505      };
26506    } else if (document.caretPositionFromPoint !== "undefined") {
26507      const range2 = document.caretPositionFromPoint(x3, y3);
26508      if (range2 === null) {
26509        return null;
26510      }
26511      return {
26512        node: range2.offsetNode,
26513        offset: range2.offset
26514      };
26515    } else {
26516      return null;
26517    }
26518  }
26519  function $getHtmlContent(editor, selection = $getSelection2()) {
26520    if (selection == null) {
26521      {
26522        formatDevErrorMessage8(`Expected valid LexicalSelection`);
26523      }
26524    }
26525    if ($isRangeSelection2(selection) && selection.isCollapsed() || selection.getNodes().length === 0) {
26526      return "";
26527    }
26528    return $generateHtmlFromNodes2(editor, selection);
26529  }
26530  function $getLexicalContent(editor, selection = $getSelection2()) {
26531    if (selection == null) {
26532      {
26533        formatDevErrorMessage8(`Expected valid LexicalSelection`);
26534      }
26535    }
26536    if ($isRangeSelection2(selection) && selection.isCollapsed() || selection.getNodes().length === 0) {
26537      return null;
26538    }
26539    return JSON.stringify($generateJSONFromSelectedNodes(editor, selection));
26540  }
26541  function $insertDataTransferForPlainText(dataTransfer, selection) {
26542    const text2 = dataTransfer.getData("text/plain") || dataTransfer.getData("text/uri-list");
26543    if (text2 != null) {
26544      selection.insertRawText(text2);
26545    }
26546  }
26547  function $insertDataTransferForRichText(dataTransfer, selection, editor) {
26548    const lexicalString = dataTransfer.getData("application/x-lexical-editor");
26549    if (lexicalString) {
26550      try {
26551        const payload = JSON.parse(lexicalString);
26552        if (payload.namespace === editor._config.namespace && Array.isArray(payload.nodes)) {
26553          const nodes = $generateNodesFromSerializedNodes(payload.nodes);
26554          return $insertGeneratedNodes(editor, nodes, selection);
26555        }
26556      } catch (error) {
26557        console.error(error);
26558      }
26559    }
26560    const htmlString = dataTransfer.getData("text/html");
26561    const plainString = dataTransfer.getData("text/plain");
26562    if (htmlString && plainString !== htmlString) {
26563      try {
26564        const parser = new DOMParser();
26565        const dom = parser.parseFromString(trustHTML(htmlString), "text/html");
26566        const nodes = $generateNodesFromDOM2(editor, dom);
26567        return $insertGeneratedNodes(editor, nodes, selection);
26568      } catch (error) {
26569        console.error(error);
26570      }
26571    }
26572    const text2 = plainString || dataTransfer.getData("text/uri-list");
26573    if (text2 != null) {
26574      if ($isRangeSelection2(selection)) {
26575        const parts = text2.split(/(\r?\n|\t)/);
26576        if (parts[parts.length - 1] === "") {
26577          parts.pop();
26578        }
26579        for (let i2 = 0; i2 < parts.length; i2++) {
26580          const currentSelection = $getSelection2();
26581          if ($isRangeSelection2(currentSelection)) {
26582            const part = parts[i2];
26583            if (part === "\n" || part === "\r\n") {
26584              currentSelection.insertParagraph();
26585            } else if (part === "	") {
26586              currentSelection.insertNodes([$createTabNode2()]);
26587            } else {
26588              currentSelection.insertText(part);
26589            }
26590          }
26591        }
26592      } else {
26593        selection.insertRawText(text2);
26594      }
26595    }
26596  }
26597  var LEXICAL_DRAG_MIME_TYPE = "application/x-lexical-drag";
26598  function $writeDragSourceToDataTransfer(dataTransfer, editor) {
26599    const marker = {
26600      editorKey: editor.getKey()
26601    };
26602    dataTransfer.setData(LEXICAL_DRAG_MIME_TYPE, JSON.stringify(marker));
26603  }
26604  function isLexicalDragMarker(value) {
26605    return value !== null && typeof value === "object" && "editorKey" in value && typeof value.editorKey === "string";
26606  }
26607  function readDragMarker(dataTransfer) {
26608    const raw = dataTransfer.getData(LEXICAL_DRAG_MIME_TYPE);
26609    if (!raw) {
26610      return null;
26611    }
26612    let parsed;
26613    try {
26614      parsed = JSON.parse(raw);
26615    } catch (_unused) {
26616      return null;
26617    }
26618    return isLexicalDragMarker(parsed) ? parsed : null;
26619  }
26620  function findEditorRootByKey(key, doc) {
26621    const elements = doc.querySelectorAll('[data-lexical-editor="true"]');
26622    for (const el of Array.from(elements)) {
26623      const editor = el.__lexicalEditor;
26624      if (editor && editor.getKey() === key) {
26625        return el;
26626      }
26627    }
26628    return null;
26629  }
26630  function $resolveDropPointCaret(event) {
26631    const hit = caretFromPoint(event.clientX, event.clientY);
26632    if (hit === null) {
26633      return null;
26634    }
26635    const node = $getNearestNodeFromDOMNode2(hit.node);
26636    if (node === null) {
26637      return null;
26638    }
26639    if ($isTextNode2(node)) {
26640      return $getTextPointCaret2(node, "next", hit.offset);
26641    }
26642    if ($isElementNode2(node)) {
26643      return $getChildCaretAtIndex2(node, hit.offset, "next");
26644    }
26645    const parent = node.getParent();
26646    if (parent === null) {
26647      return null;
26648    }
26649    return $getChildCaretAtIndex2(parent, node.getIndexWithinParent() + 1, "next");
26650  }
26651  function $isDropCaretInsideSelection(dropCaret, selection) {
26652    const {
26653      anchor: start3,
26654      focus: end
26655    } = $getCaretRangeInDirection2($caretRangeFromSelection2(selection), "next");
26656    return $comparePointCaretNext2(start3, dropCaret) < 0 && $comparePointCaretNext2(dropCaret, end) < 0;
26657  }
26658  function $doDrop(event, editor, $insertDataTransfer) {
26659    const dataTransfer = event.dataTransfer;
26660    if (dataTransfer === null) {
26661      return false;
26662    }
26663    const marker = readDragMarker(dataTransfer);
26664    if (marker === null) {
26665      return false;
26666    }
26667    const dropCaret = $resolveDropPointCaret(event);
26668    if (dropCaret === null) {
26669      return false;
26670    }
26671    const stableDropCaret = $splitAtPointCaretNext2(dropCaret);
26672    if (stableDropCaret === null) {
26673      return false;
26674    }
26675    const isSameEditorDrag = marker.editorKey === editor.getKey();
26676    const currentSelection = $getSelection2();
26677    if (isSameEditorDrag) {
26678      if (!$isRangeSelection2(currentSelection) || currentSelection.isCollapsed()) {
26679        return false;
26680      }
26681      if ($isDropCaretInsideSelection(dropCaret, currentSelection)) {
26682        event.preventDefault();
26683        return true;
26684      }
26685      currentSelection.removeText();
26686    }
26687    if (!stableDropCaret.origin.isAttached()) {
26688      event.preventDefault();
26689      return true;
26690    }
26691    const dropSelection = $setSelectionFromCaretRange2($getCollapsedCaretRange2(stableDropCaret));
26692    $insertDataTransfer(dataTransfer, dropSelection, editor);
26693    if (!isSameEditorDrag) {
26694      const rootElement = editor.getRootElement();
26695      const doc = rootElement ? rootElement.ownerDocument : null;
26696      const sourceRoot = doc ? findEditorRootByKey(marker.editorKey, doc) : null;
26697      if (sourceRoot !== null) {
26698        sourceRoot.dispatchEvent(new InputEvent("beforeinput", {
26699          bubbles: true,
26700          cancelable: true,
26701          inputType: "deleteByDrag"
26702        }));
26703      }
26704    }
26705    event.preventDefault();
26706    return true;
26707  }
26708  function $handleRichTextDrop(event, editor) {
26709    return $doDrop(event, editor, $insertDataTransferForRichText);
26710  }
26711  function $handlePlainTextDrop(event, editor) {
26712    return $doDrop(event, editor, (dataTransfer, selection) => $insertDataTransferForPlainText(dataTransfer, selection));
26713  }
26714  function trustHTML(html2) {
26715    if (window.trustedTypes && window.trustedTypes.createPolicy) {
26716      const policy = window.trustedTypes.createPolicy("lexical", {
26717        createHTML: (input) => input
26718      });
26719      return policy.createHTML(html2);
26720    }
26721    return html2;
26722  }
26723  function $insertGeneratedNodes(editor, nodes, selection) {
26724    if (!editor.dispatchCommand(SELECTION_INSERT_CLIPBOARD_NODES_COMMAND2, {
26725      nodes,
26726      selection
26727    })) {
26728      selection.insertNodes(nodes);
26729      $updateSelectionOnInsert(selection);
26730    }
26731    return;
26732  }
26733  function $updateSelectionOnInsert(selection) {
26734    if ($isRangeSelection2(selection) && selection.isCollapsed()) {
26735      const anchor = selection.anchor;
26736      let nodeToInspect = null;
26737      const anchorCaret = $caretFromPoint2(anchor, "previous");
26738      if (anchorCaret) {
26739        if ($isTextPointCaret2(anchorCaret)) {
26740          nodeToInspect = anchorCaret.origin;
26741        } else {
26742          const range2 = $getCaretRange2(anchorCaret, $getChildCaret2($getRoot2(), "next").getFlipped());
26743          for (const caret of range2) {
26744            if ($isTextNode2(caret.origin)) {
26745              nodeToInspect = caret.origin;
26746              break;
26747            } else if ($isElementNode2(caret.origin) && !caret.origin.isInline()) {
26748              break;
26749            }
26750          }
26751        }
26752      }
26753      if (nodeToInspect && $isTextNode2(nodeToInspect)) {
26754        const newFormat = nodeToInspect.getFormat();
26755        const newStyle = nodeToInspect.getStyle();
26756        if (selection.format !== newFormat || selection.style !== newStyle) {
26757          selection.format = newFormat;
26758          selection.style = newStyle;
26759          selection.dirty = true;
26760        }
26761      }
26762    }
26763  }
26764  function exportNodeToJSON2(node) {
26765    const serializedNode = node.exportJSON();
26766    const nodeClass = node.constructor;
26767    if (serializedNode.type !== nodeClass.getType()) {
26768      {
26769        formatDevErrorMessage8(`LexicalNode: Node ${nodeClass.name} does not implement .exportJSON().`);
26770      }
26771    }
26772    if ($isElementNode2(node)) {
26773      const serializedChildren = serializedNode.children;
26774      if (!Array.isArray(serializedChildren)) {
26775        {
26776          formatDevErrorMessage8(`LexicalNode: Node ${nodeClass.name} is an element but .exportJSON() does not have a children array.`);
26777        }
26778      }
26779    }
26780    return serializedNode;
26781  }
26782  function $appendNodesToJSON(editor, selection, currentNode, targetArray = []) {
26783    let shouldInclude = selection !== null ? currentNode.isSelected(selection) : true;
26784    const shouldExclude = $isElementNode2(currentNode) && currentNode.excludeFromCopy("html");
26785    let target = currentNode;
26786    if (selection !== null && $isTextNode2(target)) {
26787      target = $sliceSelectedTextNodeContent2(selection, target, "clone");
26788    }
26789    const children = $isElementNode2(target) ? target.getChildren() : [];
26790    const serializedNode = exportNodeToJSON2(target);
26791    if ($isTextNode2(target) && target.getTextContentSize() === 0) {
26792      shouldInclude = false;
26793    }
26794    for (let i2 = 0; i2 < children.length; i2++) {
26795      const childNode = children[i2];
26796      const shouldIncludeChild = $appendNodesToJSON(editor, selection, childNode, serializedNode.children);
26797      if (!shouldInclude && $isElementNode2(currentNode) && shouldIncludeChild && currentNode.extractWithChild(childNode, selection, "clone")) {
26798        shouldInclude = true;
26799      }
26800    }
26801    if (shouldInclude && !shouldExclude) {
26802      targetArray.push(serializedNode);
26803    } else if (Array.isArray(serializedNode.children)) {
26804      for (let i2 = 0; i2 < serializedNode.children.length; i2++) {
26805        const serializedChildNode = serializedNode.children[i2];
26806        targetArray.push(serializedChildNode);
26807      }
26808    }
26809    return shouldInclude;
26810  }
26811  function $generateJSONFromSelectedNodes(editor, selection) {
26812    const nodes = [];
26813    const root = $getRoot2();
26814    const topLevelChildren = root.getChildren();
26815    for (let i2 = 0; i2 < topLevelChildren.length; i2++) {
26816      const topLevelNode = topLevelChildren[i2];
26817      $appendNodesToJSON(editor, selection, topLevelNode, nodes);
26818    }
26819    return {
26820      namespace: editor._config.namespace,
26821      nodes
26822    };
26823  }
26824  function $generateNodesFromSerializedNodes(serializedNodes) {
26825    const nodes = [];
26826    for (let i2 = 0; i2 < serializedNodes.length; i2++) {
26827      const serializedNode = serializedNodes[i2];
26828      const node = $parseSerializedNode2(serializedNode);
26829      nodes.push(node);
26830    }
26831    return nodes;
26832  }
26833  var EVENT_LATENCY = 50;
26834  var clipboardEventTimeout = null;
26835  async function copyToClipboard(editor, event, data) {
26836    if (clipboardEventTimeout !== null) {
26837      return false;
26838    }
26839    if (event !== null) {
26840      return new Promise((resolve, reject) => {
26841        editor.update(() => {
26842          resolve($copyToClipboardEvent(editor, event, data));
26843        });
26844      });
26845    }
26846    const rootElement = editor.getRootElement();
26847    const editorWindow = editor._window || window;
26848    const windowDocument = editorWindow.document;
26849    const domSelection = getDOMSelection2(editorWindow);
26850    if (rootElement === null || domSelection === null) {
26851      return false;
26852    }
26853    const element = windowDocument.createElement("span");
26854    element.style.position = "fixed";
26855    element.style.top = "-1000px";
26856    element.append(windowDocument.createTextNode("#"));
26857    rootElement.append(element);
26858    const range2 = new Range();
26859    range2.setStart(element, 0);
26860    range2.setEnd(element, 1);
26861    domSelection.removeAllRanges();
26862    domSelection.addRange(range2);
26863    return new Promise((resolve, reject) => {
26864      const removeListener = editor.registerCommand(COPY_COMMAND2, (secondEvent) => {
26865        if (objectKlassEquals2(secondEvent, ClipboardEvent)) {
26866          removeListener();
26867          if (clipboardEventTimeout !== null) {
26868            editorWindow.clearTimeout(clipboardEventTimeout);
26869            clipboardEventTimeout = null;
26870          }
26871          resolve($copyToClipboardEvent(editor, secondEvent, data));
26872        }
26873        return true;
26874      }, COMMAND_PRIORITY_CRITICAL2);
26875      clipboardEventTimeout = editorWindow.setTimeout(() => {
26876        removeListener();
26877        clipboardEventTimeout = null;
26878        resolve(false);
26879      }, EVENT_LATENCY);
26880      windowDocument.execCommand("copy");
26881      element.remove();
26882    });
26883  }
26884  function $copyToClipboardEvent(editor, event, data) {
26885    if (data === void 0) {
26886      const domSelection = getDOMSelection2(editor._window);
26887      const selection = $getSelection2();
26888      if (!selection || selection.isCollapsed()) {
26889        return false;
26890      }
26891      if (!domSelection) {
26892        return false;
26893      }
26894      const anchorDOM = domSelection.anchorNode;
26895      const focusDOM = domSelection.focusNode;
26896      if (anchorDOM !== null && focusDOM !== null && !isSelectionWithinEditor2(editor, anchorDOM, focusDOM)) {
26897        return false;
26898      }
26899      data = $getClipboardDataFromSelection(selection);
26900    }
26901    event.preventDefault();
26902    const clipboardData = event.clipboardData;
26903    if (clipboardData === null) {
26904      return false;
26905    }
26906    setLexicalClipboardDataTransfer(clipboardData, data);
26907    return true;
26908  }
26909  var clipboardDataFunctions = [["text/html", $getHtmlContent], ["application/x-lexical-editor", $getLexicalContent]];
26910  function $getClipboardDataFromSelection(selection = $getSelection2()) {
26911    return $getClipboardDataWithConfigFromSelection($getExportConfig(), selection);
26912  }
26913  function setLexicalClipboardDataTransfer(clipboardData, data) {
26914    for (const [k2] of clipboardDataFunctions) {
26915      if (data[k2] === void 0) {
26916        clipboardData.setData(k2, "");
26917      }
26918    }
26919    for (const k2 in data) {
26920      const v3 = data[k2];
26921      if (v3 !== void 0) {
26922        clipboardData.setData(k2, v3);
26923      }
26924    }
26925  }
26926  function $getExportConfig() {
26927    const editor = $getEditor2();
26928    const builder = LexicalBuilder2.maybeFromEditor(editor);
26929    if (builder && builder.hasExtensionByName(GetClipboardDataExtension.name)) {
26930      return getExtensionDependencyFromEditor2(editor, GetClipboardDataExtension).output;
26931    }
26932    return DEFAULT_EXPORT_MIME_TYPE;
26933  }
26934  var DEFAULT_EXPORT_MIME_TYPE = {
26935    "application/x-lexical-editor": [(sel, next) => sel ? $getLexicalContent($getEditor2(), sel) : next()],
26936    "text/html": [(sel, next) => sel ? $getHtmlContent($getEditor2(), sel) : next()],
26937    "text/plain": [(sel, next) => sel ? sel.getTextContent() : next()]
26938  };
26939  function $getClipboardDataWithConfigFromSelection($exportMimeType, selection) {
26940    const clipboardData = {
26941      "text/plain": ""
26942    };
26943    for (const [k2, fns] of Object.entries($exportMimeType)) {
26944      const v3 = callExportMimeTypeFunctionStack(fns, selection);
26945      if (v3 !== null) {
26946        clipboardData[k2] = v3;
26947      }
26948    }
26949    return clipboardData;
26950  }
26951  function callExportMimeTypeFunctionStack(fns, selection) {
26952    const callAt = (i2) => fns[i2] ? fns[i2](selection, callAt.bind(null, i2 - 1)) : null;
26953    return callAt(fns.length - 1);
26954  }
26955  var GetClipboardDataExtension = defineExtension2({
26956    build(editor, config, state) {
26957      return config.$exportMimeType;
26958    },
26959    config: safeCast2({
26960      $exportMimeType: DEFAULT_EXPORT_MIME_TYPE
26961    }),
26962    mergeConfig(config, partial) {
26963      const merged = shallowMergeConfig2(config, partial);
26964      if (partial.$exportMimeType) {
26965        const $exportMimeType = {
26966          ...config.$exportMimeType
26967        };
26968        for (const [k2, v3] of Object.entries(partial.$exportMimeType)) {
26969          $exportMimeType[k2] = [...$exportMimeType[k2], ...v3];
26970        }
26971        merged.$exportMimeType = $exportMimeType;
26972      }
26973      return merged;
26974    },
26975    name: "@lexical/clipboard/GetClipboardData"
26976  });
26977
26978  
vendor: 1,008 bytes, lines 26978-26994
26978// node_modules/@lexical/clipboard/LexicalClipboard.mjs
26979  var mod8 = true ? LexicalClipboard_dev_exports : LexicalClipboard_prod_exports;
26980  var $generateJSONFromSelectedNodes2 = mod8.$generateJSONFromSelectedNodes;
26981  var $generateNodesFromSerializedNodes2 = mod8.$generateNodesFromSerializedNodes;
26982  var $getClipboardDataFromSelection2 = mod8.$getClipboardDataFromSelection;
26983  var $getHtmlContent2 = mod8.$getHtmlContent;
26984  var $getLexicalContent2 = mod8.$getLexicalContent;
26985  var $handlePlainTextDrop2 = mod8.$handlePlainTextDrop;
26986  var $handleRichTextDrop2 = mod8.$handleRichTextDrop;
26987  var $insertDataTransferForPlainText2 = mod8.$insertDataTransferForPlainText;
26988  var $insertDataTransferForRichText2 = mod8.$insertDataTransferForRichText;
26989  var $insertGeneratedNodes2 = mod8.$insertGeneratedNodes;
26990  var $writeDragSourceToDataTransfer2 = mod8.$writeDragSourceToDataTransfer;
26991  var copyToClipboard2 = mod8.copyToClipboard;
26992  var setLexicalClipboardDataTransfer2 = mod8.setLexicalClipboardDataTransfer;
26993
26994  
vendor: 3,179 bytes, lines 26994-27072
26994// node_modules/@lexical/dragon/LexicalDragon.dev.mjs
26995  var LexicalDragon_dev_exports = {};
26996  __export(LexicalDragon_dev_exports, {
26997    DragonExtension: () => DragonExtension,
26998    registerDragonSupport: () => registerDragonSupport
26999  });
27000  function registerDragonSupport(editor) {
27001    const origin = window.location.origin;
27002    const handler = (event) => {
27003      if (event.origin !== origin) {
27004        return;
27005      }
27006      const rootElement = editor.getRootElement();
27007      if (document.activeElement !== rootElement) {
27008        return;
27009      }
27010      const data = event.data;
27011      if (typeof data === "string") {
27012        let parsedData;
27013        try {
27014          parsedData = JSON.parse(data);
27015        } catch (_e2) {
27016          return;
27017        }
27018        if (parsedData && parsedData.protocol === "nuanria_messaging" && parsedData.type === "request") {
27019          const payload = parsedData.payload;
27020          if (payload && payload.functionId === "makeChanges") {
27021            const args = payload.args;
27022            if (args) {
27023              const [elementStart, elementLength, text2, selStart, selLength] = args;
27024              editor.update(() => {
27025                const selection = $getSelection2();
27026                if ($isRangeSelection2(selection)) {
27027                  const anchor = selection.anchor;
27028                  let anchorNode = anchor.getNode();
27029                  let setSelStart = 0;
27030                  let setSelEnd = 0;
27031                  if ($isTextNode2(anchorNode)) {
27032                    if (elementStart >= 0 && elementLength >= 0) {
27033                      setSelStart = elementStart;
27034                      setSelEnd = elementStart + elementLength;
27035                      selection.setTextNodeRange(anchorNode, setSelStart, anchorNode, setSelEnd);
27036                    }
27037                  }
27038                  if (setSelStart !== setSelEnd || text2 !== "") {
27039                    selection.insertRawText(text2);
27040                    anchorNode = anchor.getNode();
27041                  }
27042                  if ($isTextNode2(anchorNode)) {
27043                    setSelStart = selStart;
27044                    setSelEnd = selStart + selLength;
27045                    const anchorNodeTextLength = anchorNode.getTextContentSize();
27046                    setSelStart = setSelStart > anchorNodeTextLength ? anchorNodeTextLength : setSelStart;
27047                    setSelEnd = setSelEnd > anchorNodeTextLength ? anchorNodeTextLength : setSelEnd;
27048                    selection.setTextNodeRange(anchorNode, setSelStart, anchorNode, setSelEnd);
27049                  }
27050                  event.stopImmediatePropagation();
27051                }
27052              });
27053            }
27054          }
27055        }
27056      }
27057    };
27058    window.addEventListener("message", handler, true);
27059    return () => {
27060      window.removeEventListener("message", handler, true);
27061    };
27062  }
27063  var DragonExtension = defineExtension2({
27064    build: (editor, config, state) => namedSignals2(config),
27065    config: safeCast2({
27066      disabled: typeof window === "undefined"
27067    }),
27068    name: "@lexical/dragon",
27069    register: (editor, config, state) => effect(() => state.getOutput().disabled.value ? void 0 : registerDragonSupport(editor))
27070  });
27071
27072  
vendor: 235 bytes, lines 27072-27077
27072// node_modules/@lexical/dragon/LexicalDragon.mjs
27073  var mod9 = true ? LexicalDragon_dev_exports : LexicalDragon_prod_exports;
27074  var DragonExtension2 = mod9.DragonExtension;
27075  var registerDragonSupport2 = mod9.registerDragonSupport;
27076
27077  
vendor: 8,489 bytes, lines 27077-27284
27077// node_modules/@lexical/plain-text/LexicalPlainText.dev.mjs
27078  var CAN_USE_DOM4 = typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.document.createElement !== "undefined";
27079  var documentMode3 = CAN_USE_DOM4 && "documentMode" in document ? document.documentMode : null;
27080  var IS_APPLE4 = CAN_USE_DOM4 && /Mac|iPod|iPhone|iPad/.test(navigator.platform);
27081  var CAN_USE_BEFORE_INPUT4 = CAN_USE_DOM4 && "InputEvent" in window && !documentMode3 ? "getTargetRanges" in new window.InputEvent("input") : false;
27082  var IS_IOS4 = CAN_USE_DOM4 && /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
27083  var IS_ANDROID4 = CAN_USE_DOM4 && /Android/.test(navigator.userAgent);
27084  var IS_SAFARI4 = CAN_USE_DOM4 && /Version\/[\d.]+.*Safari/.test(navigator.userAgent) && !IS_ANDROID4;
27085  var IS_CHROME4 = CAN_USE_DOM4 && /^(?=.*Chrome).*/i.test(navigator.userAgent);
27086  var IS_APPLE_WEBKIT4 = CAN_USE_DOM4 && /AppleWebKit\/[\d.]+/.test(navigator.userAgent) && IS_APPLE4 && !IS_CHROME4;
27087  function onCopyForPlainText(event, editor) {
27088    editor.update(() => {
27089      if (event !== null) {
27090        const clipboardData = objectKlassEquals2(event, KeyboardEvent) ? null : event.clipboardData;
27091        const selection = $getSelection2();
27092        if (selection !== null && !selection.isCollapsed() && clipboardData != null) {
27093          event.preventDefault();
27094          const htmlString = $getHtmlContent2(editor);
27095          if (htmlString !== null) {
27096            clipboardData.setData("text/html", htmlString);
27097          }
27098          clipboardData.setData("text/plain", selection.getTextContent());
27099        }
27100      }
27101    });
27102  }
27103  function onPasteForPlainText(event, editor) {
27104    event.preventDefault();
27105    editor.update(() => {
27106      const selection = $getSelection2();
27107      const clipboardData = objectKlassEquals2(event, ClipboardEvent) ? event.clipboardData : null;
27108      if (clipboardData != null && $isRangeSelection2(selection)) {
27109        $insertDataTransferForPlainText2(clipboardData, selection);
27110      }
27111    }, {
27112      tag: PASTE_TAG2
27113    });
27114  }
27115  function onCutForPlainText(event, editor) {
27116    onCopyForPlainText(event, editor);
27117    editor.update(() => {
27118      const selection = $getSelection2();
27119      if ($isRangeSelection2(selection)) {
27120        selection.removeText();
27121      }
27122    });
27123  }
27124  function registerPlainText(editor) {
27125    const removeListener = mergeRegister3(editor.registerCommand(DELETE_CHARACTER_COMMAND2, (isBackward) => {
27126      const selection = $getSelection2();
27127      if (!$isRangeSelection2(selection)) {
27128        return false;
27129      }
27130      selection.deleteCharacter(isBackward);
27131      return true;
27132    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(DELETE_WORD_COMMAND2, (isBackward) => {
27133      const selection = $getSelection2();
27134      if (!$isRangeSelection2(selection)) {
27135        return false;
27136      }
27137      selection.deleteWord(isBackward);
27138      return true;
27139    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(DELETE_LINE_COMMAND2, (isBackward) => {
27140      const selection = $getSelection2();
27141      if (!$isRangeSelection2(selection)) {
27142        return false;
27143      }
27144      selection.deleteLine(isBackward);
27145      return true;
27146    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(CONTROLLED_TEXT_INSERTION_COMMAND2, (eventOrText) => {
27147      const selection = $getSelection2();
27148      if (!$isRangeSelection2(selection)) {
27149        return false;
27150      }
27151      if (typeof eventOrText === "string") {
27152        selection.insertText(eventOrText);
27153      } else {
27154        const dataTransfer = eventOrText.dataTransfer;
27155        if (dataTransfer != null) {
27156          $insertDataTransferForPlainText2(dataTransfer, selection);
27157        } else {
27158          const data = eventOrText.data;
27159          if (data) {
27160            selection.insertText(data);
27161          }
27162        }
27163      }
27164      return true;
27165    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(REMOVE_TEXT_COMMAND2, () => {
27166      const selection = $getSelection2();
27167      if (!$isRangeSelection2(selection)) {
27168        return false;
27169      }
27170      selection.removeText();
27171      return true;
27172    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(INSERT_LINE_BREAK_COMMAND2, (selectStart) => {
27173      const selection = $getSelection2();
27174      if (!$isRangeSelection2(selection)) {
27175        return false;
27176      }
27177      selection.insertLineBreak(selectStart);
27178      return true;
27179    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(INSERT_PARAGRAPH_COMMAND2, () => {
27180      const selection = $getSelection2();
27181      if (!$isRangeSelection2(selection)) {
27182        return false;
27183      }
27184      selection.insertLineBreak();
27185      return true;
27186    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(KEY_ARROW_LEFT_COMMAND2, (payload) => {
27187      const selection = $getSelection2();
27188      if (!$isRangeSelection2(selection)) {
27189        return false;
27190      }
27191      const event = payload;
27192      const isHoldingShift = event.shiftKey;
27193      if ($shouldOverrideDefaultCharacterSelection2(selection, true)) {
27194        event.preventDefault();
27195        $moveCharacter2(selection, isHoldingShift, true);
27196        return true;
27197      }
27198      return false;
27199    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(KEY_ARROW_RIGHT_COMMAND2, (payload) => {
27200      const selection = $getSelection2();
27201      if (!$isRangeSelection2(selection)) {
27202        return false;
27203      }
27204      const event = payload;
27205      const isHoldingShift = event.shiftKey;
27206      if ($shouldOverrideDefaultCharacterSelection2(selection, false)) {
27207        event.preventDefault();
27208        $moveCharacter2(selection, isHoldingShift, false);
27209        return true;
27210      }
27211      return false;
27212    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(KEY_BACKSPACE_COMMAND2, (event) => {
27213      const selection = $getSelection2();
27214      if (!$isRangeSelection2(selection)) {
27215        return false;
27216      }
27217      if (IS_IOS4 && navigator.language === "ko-KR") {
27218        return false;
27219      }
27220      event.preventDefault();
27221      return editor.dispatchCommand(DELETE_CHARACTER_COMMAND2, true);
27222    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(KEY_DELETE_COMMAND2, (event) => {
27223      const selection = $getSelection2();
27224      if (!$isRangeSelection2(selection)) {
27225        return false;
27226      }
27227      event.preventDefault();
27228      return editor.dispatchCommand(DELETE_CHARACTER_COMMAND2, false);
27229    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(KEY_ENTER_COMMAND2, (event) => {
27230      const selection = $getSelection2();
27231      if (!$isRangeSelection2(selection)) {
27232        return false;
27233      }
27234      if (event !== null) {
27235        if ((IS_IOS4 || IS_SAFARI4 || IS_APPLE_WEBKIT4) && CAN_USE_BEFORE_INPUT4) {
27236          return false;
27237        }
27238        event.preventDefault();
27239      }
27240      return editor.dispatchCommand(INSERT_LINE_BREAK_COMMAND2, false);
27241    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(SELECT_ALL_COMMAND2, () => {
27242      $selectAll2();
27243      return true;
27244    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(COPY_COMMAND2, (event) => {
27245      const selection = $getSelection2();
27246      if (!$isRangeSelection2(selection)) {
27247        return false;
27248      }
27249      onCopyForPlainText(event, editor);
27250      return true;
27251    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(CUT_COMMAND2, (event) => {
27252      const selection = $getSelection2();
27253      if (!$isRangeSelection2(selection)) {
27254        return false;
27255      }
27256      onCutForPlainText(event, editor);
27257      return true;
27258    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(PASTE_COMMAND2, (event) => {
27259      const selection = $getSelection2();
27260      if (!$isRangeSelection2(selection)) {
27261        return false;
27262      }
27263      onPasteForPlainText(event, editor);
27264      return true;
27265    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(DROP_COMMAND2, (event) => $handlePlainTextDrop2(event, editor), COMMAND_PRIORITY_EDITOR2), editor.registerCommand(DRAGSTART_COMMAND2, (event) => {
27266      const selection = $getSelection2();
27267      if (!$isRangeSelection2(selection)) {
27268        return false;
27269      }
27270      if (!selection.isCollapsed() && event.dataTransfer !== null) {
27271        $writeDragSourceToDataTransfer2(event.dataTransfer, editor);
27272      }
27273      return true;
27274    }, COMMAND_PRIORITY_EDITOR2));
27275    return removeListener;
27276  }
27277  var PlainTextExtension = defineExtension2({
27278    conflictsWith: ["@lexical/rich-text"],
27279    dependencies: [DragonExtension2],
27280    name: "@lexical/plain-text",
27281    register: registerPlainText
27282  });
27283
27284  
vendor: 249 bytes, lines 27284-27289
27284// node_modules/@lexical/plain-text/LexicalPlainText.mjs
27285  var mod10 = true ? LexicalPlainText_dev_exports : LexicalPlainText_prod_exports;
27286  var PlainTextExtension2 = mod10.PlainTextExtension;
27287  var registerPlainText2 = mod10.registerPlainText;
27288
27289  
vendor: 26,248 bytes, lines 27289-28030
27289// node_modules/@lexical/rich-text/LexicalRichText.dev.mjs
27290  var LexicalRichText_dev_exports = {};
27291  __export(LexicalRichText_dev_exports, {
27292    $createHeadingNode: () => $createHeadingNode,
27293    $createQuoteNode: () => $createQuoteNode,
27294    $isHeadingNode: () => $isHeadingNode,
27295    $isQuoteNode: () => $isQuoteNode,
27296    DRAG_DROP_PASTE: () => DRAG_DROP_PASTE,
27297    HeadingNode: () => HeadingNode,
27298    QuoteNode: () => QuoteNode,
27299    RichTextExtension: () => RichTextExtension,
27300    eventFiles: () => eventFiles,
27301    registerRichText: () => registerRichText
27302  });
27303  function caretFromPoint2(x3, y3) {
27304    if (typeof document.caretRangeFromPoint !== "undefined") {
27305      const range2 = document.caretRangeFromPoint(x3, y3);
27306      if (range2 === null) {
27307        return null;
27308      }
27309      return {
27310        node: range2.startContainer,
27311        offset: range2.startOffset
27312      };
27313    } else if (document.caretPositionFromPoint !== "undefined") {
27314      const range2 = document.caretPositionFromPoint(x3, y3);
27315      if (range2 === null) {
27316        return null;
27317      }
27318      return {
27319        node: range2.offsetNode,
27320        offset: range2.offset
27321      };
27322    } else {
27323      return null;
27324    }
27325  }
27326  var CAN_USE_DOM5 = typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.document.createElement !== "undefined";
27327  var documentMode4 = CAN_USE_DOM5 && "documentMode" in document ? document.documentMode : null;
27328  var IS_APPLE5 = CAN_USE_DOM5 && /Mac|iPod|iPhone|iPad/.test(navigator.platform);
27329  var CAN_USE_BEFORE_INPUT5 = CAN_USE_DOM5 && "InputEvent" in window && !documentMode4 ? "getTargetRanges" in new window.InputEvent("input") : false;
27330  var IS_IOS5 = CAN_USE_DOM5 && /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
27331  var IS_ANDROID5 = CAN_USE_DOM5 && /Android/.test(navigator.userAgent);
27332  var IS_SAFARI5 = CAN_USE_DOM5 && /Version\/[\d.]+.*Safari/.test(navigator.userAgent) && !IS_ANDROID5;
27333  var IS_CHROME5 = CAN_USE_DOM5 && /^(?=.*Chrome).*/i.test(navigator.userAgent);
27334  var IS_APPLE_WEBKIT5 = CAN_USE_DOM5 && /AppleWebKit\/[\d.]+/.test(navigator.userAgent) && IS_APPLE5 && !IS_CHROME5;
27335  var DRAG_DROP_PASTE = createCommand2("DRAG_DROP_PASTE_FILE");
27336  var QuoteNode = class _QuoteNode extends ElementNode2 {
27337    static getType() {
27338      return "quote";
27339    }
27340    static clone(node) {
27341      return new _QuoteNode(node.__key);
27342    }
27343    // View
27344    createDOM(config) {
27345      const element = document.createElement("blockquote");
27346      addClassNamesToElement3(element, config.theme.quote);
27347      return element;
27348    }
27349    updateDOM(prevNode, dom) {
27350      return false;
27351    }
27352    static importDOM() {
27353      return {
27354        blockquote: (node) => ({
27355          conversion: $convertBlockquoteElement,
27356          priority: 0
27357        })
27358      };
27359    }
27360    exportDOM(editor) {
27361      const {
27362        element
27363      } = super.exportDOM(editor);
27364      if (isHTMLElement3(element)) {
27365        if (this.isEmpty()) {
27366          element.append(document.createElement("br"));
27367        }
27368        const formatType = this.getFormatType();
27369        if (formatType) {
27370          element.style.textAlign = formatType;
27371        }
27372        const direction = this.getDirection();
27373        if (direction) {
27374          element.dir = direction;
27375        }
27376      }
27377      return {
27378        element
27379      };
27380    }
27381    static importJSON(serializedNode) {
27382      return $createQuoteNode().updateFromJSON(serializedNode);
27383    }
27384    // Mutation
27385    insertNewAfter(_3, restoreSelection) {
27386      const newBlock = $createParagraphNode2();
27387      const direction = this.getDirection();
27388      newBlock.setDirection(direction);
27389      this.insertAfter(newBlock, restoreSelection);
27390      return newBlock;
27391    }
27392    collapseAtStart() {
27393      const paragraph = $createParagraphNode2();
27394      const children = this.getChildren();
27395      children.forEach((child) => paragraph.append(child));
27396      this.replace(paragraph);
27397      return true;
27398    }
27399    canMergeWhenEmpty() {
27400      return true;
27401    }
27402  };
27403  function $createQuoteNode() {
27404    return $applyNodeReplacement2(new QuoteNode());
27405  }
27406  function $isQuoteNode(node) {
27407    return node instanceof QuoteNode;
27408  }
27409  var HeadingNode = class _HeadingNode extends ElementNode2 {
27410    /** @internal */
27411    __tag;
27412    static getType() {
27413      return "heading";
27414    }
27415    static clone(node) {
27416      return new _HeadingNode(node.__tag, node.__key);
27417    }
27418    afterCloneFrom(prevNode) {
27419      super.afterCloneFrom(prevNode);
27420      this.__tag = prevNode.__tag;
27421    }
27422    constructor(tag = "h1", key) {
27423      super(key);
27424      this.__tag = tag;
27425    }
27426    getTag() {
27427      return this.getLatest().__tag;
27428    }
27429    setTag(tag) {
27430      const self2 = this.getWritable();
27431      self2.__tag = tag;
27432      return self2;
27433    }
27434    // View
27435    createDOM(config) {
27436      const tag = this.__tag;
27437      const element = document.createElement(tag);
27438      const theme2 = config.theme;
27439      const classNames = theme2.heading;
27440      if (classNames !== void 0) {
27441        const className = classNames[tag];
27442        addClassNamesToElement3(element, className);
27443      }
27444      return element;
27445    }
27446    updateDOM(prevNode, dom, config) {
27447      return prevNode.__tag !== this.__tag;
27448    }
27449    static importDOM() {
27450      return {
27451        h1: (node) => ({
27452          conversion: $convertHeadingElement,
27453          priority: 0
27454        }),
27455        h2: (node) => ({
27456          conversion: $convertHeadingElement,
27457          priority: 0
27458        }),
27459        h3: (node) => ({
27460          conversion: $convertHeadingElement,
27461          priority: 0
27462        }),
27463        h4: (node) => ({
27464          conversion: $convertHeadingElement,
27465          priority: 0
27466        }),
27467        h5: (node) => ({
27468          conversion: $convertHeadingElement,
27469          priority: 0
27470        }),
27471        h6: (node) => ({
27472          conversion: $convertHeadingElement,
27473          priority: 0
27474        }),
27475        p: (node) => {
27476          const paragraph = node;
27477          const firstChild = paragraph.firstChild;
27478          if (firstChild !== null && isGoogleDocsTitle(firstChild)) {
27479            return {
27480              conversion: () => ({
27481                node: null
27482              }),
27483              priority: 3
27484            };
27485          }
27486          return null;
27487        },
27488        span: (node) => {
27489          if (isGoogleDocsTitle(node)) {
27490            return {
27491              conversion: (domNode) => {
27492                return {
27493                  node: $createHeadingNode("h1")
27494                };
27495              },
27496              priority: 3
27497            };
27498          }
27499          return null;
27500        }
27501      };
27502    }
27503    exportDOM(editor) {
27504      const {
27505        element
27506      } = super.exportDOM(editor);
27507      if (isHTMLElement3(element)) {
27508        if (this.isEmpty()) {
27509          element.append(document.createElement("br"));
27510        }
27511        const formatType = this.getFormatType();
27512        if (formatType) {
27513          element.style.textAlign = formatType;
27514        }
27515        const direction = this.getDirection();
27516        if (direction) {
27517          element.dir = direction;
27518        }
27519      }
27520      return {
27521        element
27522      };
27523    }
27524    static importJSON(serializedNode) {
27525      return $createHeadingNode(serializedNode.tag).updateFromJSON(serializedNode);
27526    }
27527    updateFromJSON(serializedNode) {
27528      return super.updateFromJSON(serializedNode).setTag(serializedNode.tag);
27529    }
27530    exportJSON() {
27531      return {
27532        ...super.exportJSON(),
27533        tag: this.getTag()
27534      };
27535    }
27536    // Mutation
27537    insertNewAfter(selection, restoreSelection = true) {
27538      const anchorOffet = selection ? selection.anchor.offset : 0;
27539      const lastDesc = this.getLastDescendant();
27540      const isAtEnd = !lastDesc || selection && selection.anchor.key === lastDesc.getKey() && anchorOffet === lastDesc.getTextContentSize();
27541      const newElement = isAtEnd || !selection ? $createParagraphNode2() : $createHeadingNode(this.getTag());
27542      const direction = this.getDirection();
27543      newElement.setDirection(direction);
27544      this.insertAfter(newElement, restoreSelection);
27545      if (anchorOffet === 0 && !this.isEmpty() && selection) {
27546        const paragraph = $createParagraphNode2();
27547        paragraph.select();
27548        this.replace(paragraph, true);
27549      }
27550      return newElement;
27551    }
27552    collapseAtStart() {
27553      const newElement = !this.isEmpty() ? $createHeadingNode(this.getTag()) : $createParagraphNode2();
27554      const children = this.getChildren();
27555      children.forEach((child) => newElement.append(child));
27556      this.replace(newElement);
27557      return true;
27558    }
27559    extractWithChild() {
27560      return true;
27561    }
27562  };
27563  function isGoogleDocsTitle(domNode) {
27564    if (domNode.nodeName.toLowerCase() === "span") {
27565      return domNode.style.fontSize === "26pt";
27566    }
27567    return false;
27568  }
27569  function $convertHeadingElement(element) {
27570    const nodeName = element.nodeName.toLowerCase();
27571    let node = null;
27572    if (nodeName === "h1" || nodeName === "h2" || nodeName === "h3" || nodeName === "h4" || nodeName === "h5" || nodeName === "h6") {
27573      node = $createHeadingNode(nodeName);
27574      if (element.style !== null) {
27575        setNodeIndentFromDOM2(element, node);
27576        node.setFormat(element.style.textAlign);
27577      }
27578    }
27579    return {
27580      node
27581    };
27582  }
27583  function $convertBlockquoteElement(element) {
27584    const node = $createQuoteNode();
27585    if (element.style !== null) {
27586      node.setFormat(element.style.textAlign);
27587      setNodeIndentFromDOM2(element, node);
27588    }
27589    return {
27590      node
27591    };
27592  }
27593  function $createHeadingNode(headingTag = "h1") {
27594    return $applyNodeReplacement2(new HeadingNode(headingTag));
27595  }
27596  function $isHeadingNode(node) {
27597    return node instanceof HeadingNode;
27598  }
27599  function onPasteForRichText(event, editor) {
27600    event.preventDefault();
27601    editor.update(() => {
27602      const selection = $getSelection2();
27603      const clipboardData = objectKlassEquals2(event, InputEvent) || objectKlassEquals2(event, KeyboardEvent) ? null : event.clipboardData;
27604      if (clipboardData != null && selection !== null) {
27605        $insertDataTransferForRichText2(clipboardData, selection, editor);
27606      }
27607    }, {
27608      tag: PASTE_TAG2
27609    });
27610  }
27611  async function onCutForRichText(event, editor) {
27612    await copyToClipboard2(editor, objectKlassEquals2(event, ClipboardEvent) ? event : null);
27613    editor.update(() => {
27614      const selection = $getSelection2();
27615      if ($isRangeSelection2(selection)) {
27616        selection.removeText();
27617      } else if ($isNodeSelection2(selection)) {
27618        selection.getNodes().forEach((node) => node.remove());
27619      }
27620    });
27621  }
27622  function eventFiles(event) {
27623    let dataTransfer = null;
27624    if (objectKlassEquals2(event, DragEvent)) {
27625      dataTransfer = event.dataTransfer;
27626    } else if (objectKlassEquals2(event, ClipboardEvent)) {
27627      dataTransfer = event.clipboardData;
27628    }
27629    if (dataTransfer === null) {
27630      return [false, [], false];
27631    }
27632    const types = dataTransfer.types;
27633    const hasFiles = types.includes("Files");
27634    const hasContent = types.includes("text/html") || types.includes("text/plain");
27635    return [hasFiles, Array.from(dataTransfer.files), hasContent];
27636  }
27637  function $isTargetWithinDecorator(target) {
27638    const node = $getNearestNodeFromDOMNode2(target);
27639    return $isDecoratorNode2(node);
27640  }
27641  function $isSelectionAtEndOfRoot(selection) {
27642    const focus = selection.focus;
27643    return focus.key === "root" && focus.offset === $getRoot2().getChildrenSize();
27644  }
27645  function $isSelectionCollapsedAtFrontOfIndentedBlock(selection) {
27646    if (!selection.isCollapsed()) {
27647      return false;
27648    }
27649    const {
27650      anchor
27651    } = selection;
27652    if (anchor.offset !== 0) {
27653      return false;
27654    }
27655    const anchorNode = anchor.getNode();
27656    if ($isRootNode2(anchorNode)) {
27657      return false;
27658    }
27659    const element = $getNearestBlockElementAncestorOrThrow2(anchorNode);
27660    return element.getIndent() > 0 && (element.is(anchorNode) || anchorNode.is(element.getFirstDescendant()));
27661  }
27662  function $resetCapitalization(selection) {
27663    for (const format of ["lowercase", "uppercase", "capitalize"]) {
27664      if (selection.hasFormat(format)) {
27665        selection.toggleFormat(format);
27666      }
27667    }
27668  }
27669  function registerRichText(editor) {
27670    const removeListener = mergeRegister3(editor.registerCommand(CLICK_COMMAND2, (payload) => {
27671      const selection = $getSelection2();
27672      if ($isNodeSelection2(selection)) {
27673        selection.clear();
27674        return true;
27675      }
27676      return false;
27677    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(DELETE_CHARACTER_COMMAND2, (isBackward) => {
27678      const selection = $getSelection2();
27679      if ($isRangeSelection2(selection)) {
27680        selection.deleteCharacter(isBackward);
27681        return true;
27682      } else if ($isNodeSelection2(selection)) {
27683        selection.deleteNodes();
27684        return true;
27685      }
27686      return false;
27687    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(DELETE_WORD_COMMAND2, (isBackward) => {
27688      const selection = $getSelection2();
27689      if (!$isRangeSelection2(selection)) {
27690        return false;
27691      }
27692      selection.deleteWord(isBackward);
27693      return true;
27694    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(DELETE_LINE_COMMAND2, (isBackward) => {
27695      const selection = $getSelection2();
27696      if (!$isRangeSelection2(selection)) {
27697        return false;
27698      }
27699      selection.deleteLine(isBackward);
27700      return true;
27701    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(CONTROLLED_TEXT_INSERTION_COMMAND2, (eventOrText) => {
27702      const selection = $getSelection2();
27703      if (typeof eventOrText === "string") {
27704        if (selection !== null) {
27705          selection.insertText(eventOrText);
27706        }
27707      } else {
27708        if (selection === null) {
27709          return false;
27710        }
27711        const dataTransfer = eventOrText.dataTransfer;
27712        if (dataTransfer != null) {
27713          $insertDataTransferForRichText2(dataTransfer, selection, editor);
27714        } else if ($isRangeSelection2(selection)) {
27715          const data = eventOrText.data;
27716          if (data) {
27717            selection.insertText(data);
27718          }
27719          return true;
27720        }
27721      }
27722      return true;
27723    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(REMOVE_TEXT_COMMAND2, () => {
27724      const selection = $getSelection2();
27725      if (!$isRangeSelection2(selection)) {
27726        return false;
27727      }
27728      selection.removeText();
27729      return true;
27730    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(FORMAT_TEXT_COMMAND2, (format) => {
27731      const selection = $getSelection2();
27732      if (!$isRangeSelection2(selection)) {
27733        return false;
27734      }
27735      selection.formatText(format);
27736      return true;
27737    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(FORMAT_ELEMENT_COMMAND2, (format) => {
27738      const selection = $getSelection2();
27739      if (!$isRangeSelection2(selection) && !$isNodeSelection2(selection)) {
27740        return false;
27741      }
27742      const nodes = selection.getNodes();
27743      for (const node of nodes) {
27744        const element = $findMatchingParent3(node, (parentNode) => $isElementNode2(parentNode) && !parentNode.isInline());
27745        if (element !== null) {
27746          element.setFormat(format);
27747        }
27748      }
27749      return true;
27750    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(INSERT_LINE_BREAK_COMMAND2, (selectStart) => {
27751      const selection = $getSelection2();
27752      if (!$isRangeSelection2(selection)) {
27753        return false;
27754      }
27755      selection.insertLineBreak(selectStart);
27756      return true;
27757    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(INSERT_PARAGRAPH_COMMAND2, () => {
27758      const selection = $getSelection2();
27759      if (!$isRangeSelection2(selection)) {
27760        return false;
27761      }
27762      selection.insertParagraph();
27763      return true;
27764    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(INSERT_TAB_COMMAND2, () => {
27765      const tabNode = $createTabNode2();
27766      const selection = $getSelection2();
27767      if ($isRangeSelection2(selection)) {
27768        tabNode.setFormat(selection.format);
27769        tabNode.setStyle(selection.style);
27770      }
27771      $insertNodes2([tabNode]);
27772      return true;
27773    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(INDENT_CONTENT_COMMAND2, () => {
27774      return $handleIndentAndOutdent2((block) => {
27775        const indent = block.getIndent();
27776        block.setIndent(indent + 1);
27777      });
27778    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(OUTDENT_CONTENT_COMMAND2, () => {
27779      return $handleIndentAndOutdent2((block) => {
27780        const indent = block.getIndent();
27781        if (indent > 0) {
27782          block.setIndent(Math.max(0, indent - 1));
27783        }
27784      });
27785    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(KEY_ARROW_UP_COMMAND2, (event) => {
27786      const selection = $getSelection2();
27787      if ($isNodeSelection2(selection)) {
27788        const nodes = selection.getNodes();
27789        if (nodes.length > 0) {
27790          event.preventDefault();
27791          nodes[0].selectPrevious();
27792          return true;
27793        }
27794      } else if ($isRangeSelection2(selection)) {
27795        const possibleNode = $getAdjacentNode2(selection.focus, true);
27796        if (!event.shiftKey && $isDecoratorNode2(possibleNode) && !possibleNode.isIsolated() && !possibleNode.isInline()) {
27797          possibleNode.selectPrevious();
27798          event.preventDefault();
27799          return true;
27800        }
27801      }
27802      return false;
27803    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(KEY_ARROW_DOWN_COMMAND2, (event) => {
27804      const selection = $getSelection2();
27805      if ($isNodeSelection2(selection)) {
27806        const nodes = selection.getNodes();
27807        if (nodes.length > 0) {
27808          event.preventDefault();
27809          nodes[0].selectNext(0, 0);
27810          return true;
27811        }
27812      } else if ($isRangeSelection2(selection)) {
27813        if ($isSelectionAtEndOfRoot(selection)) {
27814          event.preventDefault();
27815          return true;
27816        }
27817        const possibleNode = $getAdjacentNode2(selection.focus, false);
27818        if (!event.shiftKey && $isDecoratorNode2(possibleNode) && !possibleNode.isIsolated() && !possibleNode.isInline()) {
27819          possibleNode.selectNext();
27820          event.preventDefault();
27821          return true;
27822        }
27823      }
27824      return false;
27825    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(KEY_ARROW_LEFT_COMMAND2, (event) => {
27826      const selection = $getSelection2();
27827      if ($isNodeSelection2(selection)) {
27828        const nodes = selection.getNodes();
27829        if (nodes.length > 0) {
27830          event.preventDefault();
27831          if ($isParentRTL2(nodes[0])) {
27832            nodes[0].selectNext(0, 0);
27833          } else {
27834            nodes[0].selectPrevious();
27835          }
27836          return true;
27837        }
27838      }
27839      if (!$isRangeSelection2(selection)) {
27840        return false;
27841      }
27842      if ($shouldOverrideDefaultCharacterSelection2(selection, true)) {
27843        const isHoldingShift = event.shiftKey;
27844        event.preventDefault();
27845        $moveCharacter2(selection, isHoldingShift, true);
27846        return true;
27847      }
27848      return false;
27849    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(KEY_ARROW_RIGHT_COMMAND2, (event) => {
27850      const selection = $getSelection2();
27851      if ($isNodeSelection2(selection)) {
27852        const nodes = selection.getNodes();
27853        if (nodes.length > 0) {
27854          event.preventDefault();
27855          if ($isParentRTL2(nodes[0])) {
27856            nodes[0].selectPrevious();
27857          } else {
27858            nodes[0].selectNext(0, 0);
27859          }
27860          return true;
27861        }
27862      }
27863      if (!$isRangeSelection2(selection)) {
27864        return false;
27865      }
27866      const isHoldingShift = event.shiftKey;
27867      if ($shouldOverrideDefaultCharacterSelection2(selection, false)) {
27868        event.preventDefault();
27869        $moveCharacter2(selection, isHoldingShift, false);
27870        return true;
27871      }
27872      return false;
27873    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(KEY_BACKSPACE_COMMAND2, (event) => {
27874      if ($isTargetWithinDecorator(event.target)) {
27875        return false;
27876      }
27877      const selection = $getSelection2();
27878      if ($isRangeSelection2(selection)) {
27879        if ($isSelectionCollapsedAtFrontOfIndentedBlock(selection)) {
27880          event.preventDefault();
27881          return editor.dispatchCommand(OUTDENT_CONTENT_COMMAND2, void 0);
27882        }
27883        if (IS_IOS5 && navigator.language === "ko-KR") {
27884          return false;
27885        }
27886      } else if (!$isNodeSelection2(selection)) {
27887        return false;
27888      }
27889      event.preventDefault();
27890      return editor.dispatchCommand(DELETE_CHARACTER_COMMAND2, true);
27891    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(KEY_DELETE_COMMAND2, (event) => {
27892      if ($isTargetWithinDecorator(event.target)) {
27893        return false;
27894      }
27895      const selection = $getSelection2();
27896      if (!($isRangeSelection2(selection) || $isNodeSelection2(selection))) {
27897        return false;
27898      }
27899      event.preventDefault();
27900      return editor.dispatchCommand(DELETE_CHARACTER_COMMAND2, false);
27901    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(KEY_ENTER_COMMAND2, (event) => {
27902      const selection = $getSelection2();
27903      if (!$isRangeSelection2(selection)) {
27904        return false;
27905      }
27906      $resetCapitalization(selection);
27907      if (event !== null) {
27908        if ((IS_IOS5 || IS_SAFARI5 || IS_APPLE_WEBKIT5) && CAN_USE_BEFORE_INPUT5) {
27909          return false;
27910        }
27911        event.preventDefault();
27912        if (event.shiftKey) {
27913          return editor.dispatchCommand(INSERT_LINE_BREAK_COMMAND2, false);
27914        }
27915      }
27916      return editor.dispatchCommand(INSERT_PARAGRAPH_COMMAND2, void 0);
27917    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(KEY_ESCAPE_COMMAND2, () => {
27918      const selection = $getSelection2();
27919      if (!$isRangeSelection2(selection)) {
27920        return false;
27921      }
27922      editor.blur();
27923      return true;
27924    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(DROP_COMMAND2, (event) => {
27925      const [, files] = eventFiles(event);
27926      if (files.length > 0) {
27927        const x3 = event.clientX;
27928        const y3 = event.clientY;
27929        const eventRange = caretFromPoint2(x3, y3);
27930        if (eventRange !== null) {
27931          const {
27932            offset: domOffset,
27933            node: domNode
27934          } = eventRange;
27935          const node = $getNearestNodeFromDOMNode2(domNode);
27936          if (node !== null) {
27937            const selection = $createRangeSelection2();
27938            if ($isTextNode2(node)) {
27939              selection.anchor.set(node.getKey(), domOffset, "text");
27940              selection.focus.set(node.getKey(), domOffset, "text");
27941            } else {
27942              const parentKey = node.getParentOrThrow().getKey();
27943              const offset3 = node.getIndexWithinParent() + 1;
27944              selection.anchor.set(parentKey, offset3, "element");
27945              selection.focus.set(parentKey, offset3, "element");
27946            }
27947            const normalizedSelection = $normalizeSelection__EXPERIMENTAL(selection);
27948            $setSelection2(normalizedSelection);
27949          }
27950          editor.dispatchCommand(DRAG_DROP_PASTE, files);
27951        }
27952        event.preventDefault();
27953        return true;
27954      }
27955      return $handleRichTextDrop2(event, editor);
27956    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(DRAGSTART_COMMAND2, (event) => {
27957      const [isFileTransfer] = eventFiles(event);
27958      const selection = $getSelection2();
27959      if (isFileTransfer && !$isRangeSelection2(selection)) {
27960        return false;
27961      }
27962      if ($isRangeSelection2(selection) && !selection.isCollapsed() && event.dataTransfer !== null) {
27963        setLexicalClipboardDataTransfer2(event.dataTransfer, $getClipboardDataFromSelection2(selection));
27964        $writeDragSourceToDataTransfer2(event.dataTransfer, editor);
27965      }
27966      return true;
27967    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(DRAGOVER_COMMAND2, (event) => {
27968      const [isFileTransfer] = eventFiles(event);
27969      const selection = $getSelection2();
27970      if (isFileTransfer && !$isRangeSelection2(selection)) {
27971        return false;
27972      }
27973      const x3 = event.clientX;
27974      const y3 = event.clientY;
27975      const eventRange = caretFromPoint2(x3, y3);
27976      if (eventRange !== null) {
27977        const node = $getNearestNodeFromDOMNode2(eventRange.node);
27978        if ($isDecoratorNode2(node)) {
27979          event.preventDefault();
27980        }
27981      }
27982      return true;
27983    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(SELECT_ALL_COMMAND2, () => {
27984      $selectAll2();
27985      return true;
27986    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(COPY_COMMAND2, (event) => {
27987      copyToClipboard2(editor, objectKlassEquals2(event, ClipboardEvent) ? event : null);
27988      return true;
27989    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(CUT_COMMAND2, (event) => {
27990      onCutForRichText(event, editor);
27991      return true;
27992    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(PASTE_COMMAND2, (event) => {
27993      const [, files, hasTextContent] = eventFiles(event);
27994      if (files.length > 0 && !hasTextContent) {
27995        editor.dispatchCommand(DRAG_DROP_PASTE, files);
27996        return true;
27997      }
27998      if (isDOMNode2(event.target) && isSelectionCapturedInDecoratorInput2(event.target)) {
27999        return false;
28000      }
28001      const selection = $getSelection2();
28002      if (selection !== null) {
28003        onPasteForRichText(event, editor);
28004        return true;
28005      }
28006      return false;
28007    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(KEY_SPACE_COMMAND2, (_3) => {
28008      const selection = $getSelection2();
28009      if ($isRangeSelection2(selection)) {
28010        $resetCapitalization(selection);
28011      }
28012      return false;
28013    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(KEY_TAB_COMMAND2, (_3) => {
28014      const selection = $getSelection2();
28015      if ($isRangeSelection2(selection)) {
28016        $resetCapitalization(selection);
28017      }
28018      return false;
28019    }, COMMAND_PRIORITY_EDITOR2));
28020    return removeListener;
28021  }
28022  var RichTextExtension = defineExtension2({
28023    conflictsWith: ["@lexical/plain-text"],
28024    dependencies: [DragonExtension2],
28025    name: "@lexical/rich-text",
28026    nodes: () => [HeadingNode, QuoteNode],
28027    register: registerRichText
28028  });
28029
28030  
vendor: 595 bytes, lines 28030-28043
28030// node_modules/@lexical/rich-text/LexicalRichText.mjs
28031  var mod11 = true ? LexicalRichText_dev_exports : LexicalRichText_prod_exports;
28032  var $createHeadingNode2 = mod11.$createHeadingNode;
28033  var $createQuoteNode2 = mod11.$createQuoteNode;
28034  var $isHeadingNode2 = mod11.$isHeadingNode;
28035  var $isQuoteNode2 = mod11.$isQuoteNode;
28036  var DRAG_DROP_PASTE2 = mod11.DRAG_DROP_PASTE;
28037  var HeadingNode2 = mod11.HeadingNode;
28038  var QuoteNode2 = mod11.QuoteNode;
28039  var RichTextExtension2 = mod11.RichTextExtension;
28040  var eventFiles2 = mod11.eventFiles;
28041  var registerRichText2 = mod11.registerRichText;
28042
28043  
vendor: 13,026 bytes, lines 28043-28383
28043// node_modules/@lexical/history/LexicalHistory.dev.mjs
28044  var LexicalHistory_dev_exports = {};
28045  __export(LexicalHistory_dev_exports, {
28046    HistoryExtension: () => HistoryExtension,
28047    SharedHistoryExtension: () => SharedHistoryExtension,
28048    createEmptyHistoryState: () => createEmptyHistoryState,
28049    registerHistory: () => registerHistory
28050  });
28051  var HISTORY_MERGE = 0;
28052  var HISTORY_PUSH = 1;
28053  var DISCARD_HISTORY_CANDIDATE = 2;
28054  var OTHER = 0;
28055  var COMPOSING_CHARACTER = 1;
28056  var INSERT_CHARACTER_AFTER_SELECTION = 2;
28057  var DELETE_CHARACTER_BEFORE_SELECTION = 3;
28058  var DELETE_CHARACTER_AFTER_SELECTION = 4;
28059  function getDirtyNodes(editorState, dirtyLeaves, dirtyElements) {
28060    const nodeMap = editorState._nodeMap;
28061    const nodes = [];
28062    for (const dirtyLeafKey of dirtyLeaves) {
28063      const dirtyLeaf = nodeMap.get(dirtyLeafKey);
28064      if (dirtyLeaf !== void 0) {
28065        nodes.push(dirtyLeaf);
28066      }
28067    }
28068    for (const [dirtyElementKey, intentionallyMarkedAsDirty] of dirtyElements) {
28069      if (!intentionallyMarkedAsDirty) {
28070        continue;
28071      }
28072      const dirtyElement = nodeMap.get(dirtyElementKey);
28073      if (dirtyElement !== void 0 && !$isRootNode2(dirtyElement)) {
28074        nodes.push(dirtyElement);
28075      }
28076    }
28077    return nodes;
28078  }
28079  function getChangeType(prevEditorState, nextEditorState, dirtyLeavesSet, dirtyElementsSet, isComposing) {
28080    if (prevEditorState === null || dirtyLeavesSet.size === 0 && dirtyElementsSet.size === 0 && !isComposing) {
28081      return OTHER;
28082    }
28083    const nextSelection = nextEditorState._selection;
28084    const prevSelection = prevEditorState._selection;
28085    if (isComposing) {
28086      return COMPOSING_CHARACTER;
28087    }
28088    if (!$isRangeSelection2(nextSelection) || !$isRangeSelection2(prevSelection) || !prevSelection.isCollapsed() || !nextSelection.isCollapsed()) {
28089      return OTHER;
28090    }
28091    const dirtyNodes = getDirtyNodes(nextEditorState, dirtyLeavesSet, dirtyElementsSet);
28092    if (dirtyNodes.length === 0) {
28093      return OTHER;
28094    }
28095    if (dirtyNodes.length > 1) {
28096      const nextNodeMap = nextEditorState._nodeMap;
28097      const nextAnchorNode = nextNodeMap.get(nextSelection.anchor.key);
28098      const prevAnchorNode = nextNodeMap.get(prevSelection.anchor.key);
28099      if (nextAnchorNode && prevAnchorNode && !prevEditorState._nodeMap.has(nextAnchorNode.__key) && $isTextNode2(nextAnchorNode) && nextAnchorNode.__text.length === 1 && nextSelection.anchor.offset === 1) {
28100        return INSERT_CHARACTER_AFTER_SELECTION;
28101      }
28102      return OTHER;
28103    }
28104    const nextDirtyNode = dirtyNodes[0];
28105    const prevDirtyNode = prevEditorState._nodeMap.get(nextDirtyNode.__key);
28106    if (!$isTextNode2(prevDirtyNode) || !$isTextNode2(nextDirtyNode) || prevDirtyNode.__mode !== nextDirtyNode.__mode) {
28107      return OTHER;
28108    }
28109    const prevText = prevDirtyNode.__text;
28110    const nextText = nextDirtyNode.__text;
28111    if (prevText === nextText) {
28112      return OTHER;
28113    }
28114    const nextAnchor = nextSelection.anchor;
28115    const prevAnchor = prevSelection.anchor;
28116    if (nextAnchor.key !== prevAnchor.key || nextAnchor.type !== "text") {
28117      return OTHER;
28118    }
28119    const nextAnchorOffset = nextAnchor.offset;
28120    const prevAnchorOffset = prevAnchor.offset;
28121    const textDiff = nextText.length - prevText.length;
28122    if (textDiff === 1 && prevAnchorOffset === nextAnchorOffset - 1) {
28123      return INSERT_CHARACTER_AFTER_SELECTION;
28124    }
28125    if (textDiff === -1 && prevAnchorOffset === nextAnchorOffset + 1) {
28126      return DELETE_CHARACTER_BEFORE_SELECTION;
28127    }
28128    if (textDiff === -1 && prevAnchorOffset === nextAnchorOffset) {
28129      return DELETE_CHARACTER_AFTER_SELECTION;
28130    }
28131    return OTHER;
28132  }
28133  function isTextNodeUnchanged(key, prevEditorState, nextEditorState) {
28134    const prevNode = prevEditorState._nodeMap.get(key);
28135    const nextNode = nextEditorState._nodeMap.get(key);
28136    const prevSelection = prevEditorState._selection;
28137    const nextSelection = nextEditorState._selection;
28138    const isDeletingLine = $isRangeSelection2(prevSelection) && $isRangeSelection2(nextSelection) && prevSelection.anchor.type === "element" && prevSelection.focus.type === "element" && nextSelection.anchor.type === "text" && nextSelection.focus.type === "text";
28139    if (!isDeletingLine && $isTextNode2(prevNode) && $isTextNode2(nextNode) && prevNode.__parent === nextNode.__parent) {
28140      return JSON.stringify(prevEditorState.read(() => prevNode.exportJSON())) === JSON.stringify(nextEditorState.read(() => nextNode.exportJSON()));
28141    }
28142    return false;
28143  }
28144  function createMergeActionGetter(editor, delayOrStore, dateNow) {
28145    let prevChangeTime = dateNow();
28146    let prevChangeType = OTHER;
28147    let compositionStartTime = prevChangeTime;
28148    let compositionStartChangeType = OTHER;
28149    let compositionStartState = null;
28150    return (prevEditorState, nextEditorState, currentHistoryEntry, dirtyLeaves, dirtyElements, tags) => {
28151      const changeTime = dateNow();
28152      if (tags.has(COMPOSITION_START_TAG2)) {
28153        compositionStartTime = prevChangeTime;
28154        compositionStartChangeType = prevChangeType;
28155        compositionStartState = prevEditorState;
28156      }
28157      if (tags.has(HISTORIC_TAG2)) {
28158        prevChangeType = OTHER;
28159        prevChangeTime = changeTime;
28160        return DISCARD_HISTORY_CANDIDATE;
28161      }
28162      const isCompositionEnd = tags.has(COMPOSITION_END_TAG2);
28163      if (isCompositionEnd && compositionStartState) {
28164        prevChangeTime = compositionStartTime;
28165        prevChangeType = compositionStartChangeType;
28166        prevEditorState = compositionStartState;
28167      }
28168      const changeType = getChangeType(prevEditorState, nextEditorState, dirtyLeaves, dirtyElements, editor.isComposing());
28169      const mergeAction = (() => {
28170        const isSameEditor = currentHistoryEntry === null || currentHistoryEntry.editor === editor;
28171        const shouldPushHistory = tags.has(HISTORY_PUSH_TAG2);
28172        const shouldMergeHistory = !shouldPushHistory && isSameEditor && tags.has(HISTORY_MERGE_TAG2);
28173        if (shouldMergeHistory) {
28174          return HISTORY_MERGE;
28175        }
28176        if (changeType === COMPOSING_CHARACTER) {
28177          return DISCARD_HISTORY_CANDIDATE;
28178        }
28179        if (prevEditorState === null) {
28180          return HISTORY_PUSH;
28181        }
28182        const selection = nextEditorState._selection;
28183        const hasDirtyNodes = dirtyLeaves.size > 0 || dirtyElements.size > 0;
28184        if (!hasDirtyNodes) {
28185          if (selection !== null) {
28186            return HISTORY_MERGE;
28187          }
28188          return DISCARD_HISTORY_CANDIDATE;
28189        }
28190        const delay2 = typeof delayOrStore === "number" ? delayOrStore : delayOrStore.peek();
28191        if (shouldPushHistory === false && changeType !== OTHER && changeType === prevChangeType && changeTime < prevChangeTime + delay2 && isSameEditor) {
28192          return HISTORY_MERGE;
28193        }
28194        if (dirtyLeaves.size === 1) {
28195          const dirtyLeafKey = Array.from(dirtyLeaves)[0];
28196          if (isTextNodeUnchanged(dirtyLeafKey, prevEditorState, nextEditorState)) {
28197            return HISTORY_MERGE;
28198          }
28199        }
28200        return HISTORY_PUSH;
28201      })();
28202      prevChangeTime = changeTime;
28203      prevChangeType = changeType;
28204      return mergeAction;
28205    };
28206  }
28207  function redo(editor, historyState) {
28208    const redoStack = historyState.redoStack;
28209    const undoStack = historyState.undoStack;
28210    if (redoStack.length !== 0) {
28211      const current = historyState.current;
28212      if (current !== null) {
28213        undoStack.push(current);
28214        editor.dispatchCommand(CAN_UNDO_COMMAND2, true);
28215      }
28216      const historyStateEntry = redoStack.pop();
28217      if (redoStack.length === 0) {
28218        editor.dispatchCommand(CAN_REDO_COMMAND2, false);
28219      }
28220      historyState.current = historyStateEntry || null;
28221      if (historyStateEntry) {
28222        historyStateEntry.editor.setEditorState(historyStateEntry.editorState, {
28223          tag: HISTORIC_TAG2
28224        });
28225      }
28226    }
28227  }
28228  function undo(editor, historyState) {
28229    const redoStack = historyState.redoStack;
28230    const undoStack = historyState.undoStack;
28231    const undoStackLength = undoStack.length;
28232    if (undoStackLength !== 0) {
28233      const current = historyState.current;
28234      const historyStateEntry = undoStack.pop();
28235      if (current !== null) {
28236        redoStack.push(current);
28237        editor.dispatchCommand(CAN_REDO_COMMAND2, true);
28238      }
28239      if (undoStack.length === 0) {
28240        editor.dispatchCommand(CAN_UNDO_COMMAND2, false);
28241      }
28242      historyState.current = historyStateEntry || null;
28243      if (historyStateEntry) {
28244        historyStateEntry.editor.setEditorState(historyStateEntry.editorState, {
28245          tag: HISTORIC_TAG2
28246        });
28247      }
28248    }
28249  }
28250  function clearHistory(historyState) {
28251    historyState.undoStack = [];
28252    historyState.redoStack = [];
28253    historyState.current = null;
28254  }
28255  function registerHistory(editor, historyState, delay2, dateNow = Date.now) {
28256    const getMergeAction = createMergeActionGetter(editor, delay2, dateNow);
28257    const applyChange = ({
28258      editorState,
28259      prevEditorState,
28260      dirtyLeaves,
28261      dirtyElements,
28262      tags
28263    }) => {
28264      const current = historyState.current;
28265      const redoStack = historyState.redoStack;
28266      const undoStack = historyState.undoStack;
28267      const currentEditorState = current === null ? null : current.editorState;
28268      if (current !== null && editorState === currentEditorState) {
28269        return;
28270      }
28271      const mergeAction = getMergeAction(prevEditorState, editorState, current, dirtyLeaves, dirtyElements, tags);
28272      if (mergeAction === HISTORY_PUSH) {
28273        if (redoStack.length !== 0) {
28274          historyState.redoStack = [];
28275          editor.dispatchCommand(CAN_REDO_COMMAND2, false);
28276        }
28277        if (current !== null) {
28278          undoStack.push({
28279            ...current
28280          });
28281          editor.dispatchCommand(CAN_UNDO_COMMAND2, true);
28282        }
28283      } else if (mergeAction === DISCARD_HISTORY_CANDIDATE) {
28284        return;
28285      }
28286      historyState.current = {
28287        editor,
28288        editorState
28289      };
28290    };
28291    return mergeRegister3(editor.registerCommand(UNDO_COMMAND2, () => {
28292      undo(editor, historyState);
28293      return true;
28294    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(REDO_COMMAND2, () => {
28295      redo(editor, historyState);
28296      return true;
28297    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(CLEAR_EDITOR_COMMAND2, () => {
28298      clearHistory(historyState);
28299      return false;
28300    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(CLEAR_HISTORY_COMMAND2, () => {
28301      clearHistory(historyState);
28302      editor.dispatchCommand(CAN_REDO_COMMAND2, false);
28303      editor.dispatchCommand(CAN_UNDO_COMMAND2, false);
28304      return true;
28305    }, COMMAND_PRIORITY_EDITOR2), editor.registerUpdateListener(applyChange));
28306  }
28307  function createEmptyHistoryState() {
28308    return {
28309      current: null,
28310      redoStack: [],
28311      undoStack: []
28312    };
28313  }
28314  var HistoryExtension = defineExtension2({
28315    build: (editor, {
28316      delay: delay2,
28317      createInitialHistoryState,
28318      disabled,
28319      now
28320    }) => namedSignals2({
28321      delay: delay2,
28322      disabled,
28323      historyState: createInitialHistoryState(editor),
28324      now
28325    }),
28326    config: safeCast2({
28327      createInitialHistoryState: createEmptyHistoryState,
28328      delay: 300,
28329      disabled: typeof window === "undefined",
28330      now: Date.now
28331    }),
28332    name: "@lexical/history/History",
28333    register: (editor, config, state) => {
28334      const stores = state.getOutput();
28335      return effect(() => stores.disabled.value ? void 0 : registerHistory(editor, stores.historyState.value, stores.delay, () => stores.now.peek()()));
28336    }
28337  });
28338  function getHistoryPeer(editor) {
28339    return editor ? getPeerDependencyFromEditor2(editor, HistoryExtension.name) : null;
28340  }
28341  var SharedHistoryExtension = defineExtension2({
28342    build: (editor, {
28343      disabled,
28344      parentEditor
28345    }) => namedSignals2({
28346      disabled,
28347      parentEditor: parentEditor || editor._parentEditor
28348    }),
28349    config: safeCast2({
28350      disabled: false,
28351      parentEditor: null
28352    }),
28353    dependencies: [configExtension2(HistoryExtension, {
28354      disabled: true
28355    })],
28356    name: "@lexical/history/SharedHistory",
28357    register(editor, _config, state) {
28358      return effect(() => {
28359        const {
28360          disabled,
28361          parentEditor
28362        } = state.getOutput();
28363        if (!disabled.value) {
28364          const {
28365            output
28366          } = state.getDependency(HistoryExtension);
28367          const parentPeer = getHistoryPeer(parentEditor.value);
28368          if (!parentPeer) {
28369            return;
28370          }
28371          const parentOutput = parentPeer.output;
28372          batch(() => {
28373            output.delay.value = parentOutput.delay.value;
28374            output.historyState.value = parentOutput.historyState.value;
28375            output.now.value = parentOutput.now.value;
28376            output.disabled.value = parentOutput.disabled.value;
28377          });
28378        }
28379      });
28380    }
28381  });
28382
28383  
vendor: 358 bytes, lines 28383-28390
28383// node_modules/@lexical/history/LexicalHistory.mjs
28384  var mod12 = true ? LexicalHistory_dev_exports : LexicalHistory_prod_exports;
28385  var HistoryExtension2 = mod12.HistoryExtension;
28386  var SharedHistoryExtension2 = mod12.SharedHistoryExtension;
28387  var createEmptyHistoryState2 = mod12.createEmptyHistoryState;
28388  var registerHistory2 = mod12.registerHistory;
28389
28390  
vendor: 1,413 bytes, lines 28390-28419
28390// node_modules/@lexical/code/LexicalCode.dev.mjs
28391  var LexicalCode_dev_exports = {};
28392  __export(LexicalCode_dev_exports, {
28393    $createCodeHighlightNode: () => $createCodeHighlightNode2,
28394    $createCodeNode: () => $createCodeNode2,
28395    $getCodeLineDirection: () => $getCodeLineDirection2,
28396    $getEndOfCodeInLine: () => $getEndOfCodeInLine2,
28397    $getFirstCodeNodeOfLine: () => $getFirstCodeNodeOfLine2,
28398    $getLastCodeNodeOfLine: () => $getLastCodeNodeOfLine2,
28399    $getStartOfCodeInLine: () => $getStartOfCodeInLine2,
28400    $isCodeHighlightNode: () => $isCodeHighlightNode2,
28401    $isCodeNode: () => $isCodeNode2,
28402    CODE_LANGUAGE_FRIENDLY_NAME_MAP: () => CODE_LANGUAGE_FRIENDLY_NAME_MAP3,
28403    CODE_LANGUAGE_MAP: () => CODE_LANGUAGE_MAP3,
28404    CodeExtension: () => CodeExtension2,
28405    CodeHighlightNode: () => CodeHighlightNode2,
28406    CodeNode: () => CodeNode2,
28407    DEFAULT_CODE_LANGUAGE: () => DEFAULT_CODE_LANGUAGE2,
28408    PrismTokenizer: () => PrismTokenizer3,
28409    getCodeLanguageOptions: () => getCodeLanguageOptions3,
28410    getCodeLanguages: () => getCodeLanguages3,
28411    getCodeThemeOptions: () => getCodeThemeOptions3,
28412    getDefaultCodeLanguage: () => getDefaultCodeLanguage2,
28413    getLanguageFriendlyName: () => getLanguageFriendlyName3,
28414    normalizeCodeLang: () => normalizeCodeLang,
28415    normalizeCodeLanguage: () => normalizeCodeLanguage3,
28416    registerCodeHighlighting: () => registerCodeHighlighting3
28417  });
28418
28419  
vendor: 803 bytes, lines 28419-28436
28419// node_modules/@lexical/code-prism/LexicalCodePrism.dev.mjs
28420  var LexicalCodePrism_dev_exports = {};
28421  __export(LexicalCodePrism_dev_exports, {
28422    CODE_LANGUAGE_FRIENDLY_NAME_MAP: () => CODE_LANGUAGE_FRIENDLY_NAME_MAP,
28423    CODE_LANGUAGE_MAP: () => CODE_LANGUAGE_MAP,
28424    CodePrismExtension: () => CodePrismExtension,
28425    PrismTokenizer: () => PrismTokenizer,
28426    getCodeLanguageOptions: () => getCodeLanguageOptions,
28427    getCodeLanguages: () => getCodeLanguages,
28428    getCodeThemeOptions: () => getCodeThemeOptions,
28429    getLanguageFriendlyName: () => getLanguageFriendlyName,
28430    isCodeLanguageLoaded: () => isCodeLanguageLoaded,
28431    loadCodeLanguage: () => loadCodeLanguage,
28432    normalizeCodeLanguage: () => normalizeCodeLanguage,
28433    registerCodeHighlighting: () => registerCodeHighlighting
28434  });
28435
28436  
vendor: 20,219 bytes, lines 28436-29061
28436// node_modules/@lexical/code-core/LexicalCodeCore.dev.mjs
28437  var LexicalCodeCore_dev_exports = {};
28438  __export(LexicalCodeCore_dev_exports, {
28439    $createCodeHighlightNode: () => $createCodeHighlightNode,
28440    $createCodeNode: () => $createCodeNode,
28441    $getCodeLineDirection: () => $getCodeLineDirection,
28442    $getEndOfCodeInLine: () => $getEndOfCodeInLine,
28443    $getFirstCodeNodeOfLine: () => $getFirstCodeNodeOfLine,
28444    $getLastCodeNodeOfLine: () => $getLastCodeNodeOfLine,
28445    $getStartOfCodeInLine: () => $getStartOfCodeInLine,
28446    $isCodeHighlightNode: () => $isCodeHighlightNode,
28447    $isCodeNode: () => $isCodeNode,
28448    CodeExtension: () => CodeExtension,
28449    CodeHighlightNode: () => CodeHighlightNode,
28450    CodeNode: () => CodeNode,
28451    DEFAULT_CODE_LANGUAGE: () => DEFAULT_CODE_LANGUAGE,
28452    getDefaultCodeLanguage: () => getDefaultCodeLanguage
28453  });
28454  function warnOnlyOnce3(message) {
28455    {
28456      let run = false;
28457      return () => {
28458        if (!run) {
28459          console.warn(message);
28460        }
28461        run = true;
28462      };
28463    }
28464  }
28465  function formatDevErrorMessage9(message) {
28466    throw new Error(message);
28467  }
28468  function $getLastMatchingCodeNode(anchor, direction) {
28469    let matchingNode = anchor;
28470    for (let caret = $getSiblingCaret2(anchor, direction); caret && ($isCodeHighlightNode(caret.origin) || $isTabNode2(caret.origin)); caret = caret.getAdjacentCaret()) {
28471      matchingNode = caret.origin;
28472    }
28473    return matchingNode;
28474  }
28475  function $getFirstCodeNodeOfLine(anchor) {
28476    return $getLastMatchingCodeNode(anchor, "previous");
28477  }
28478  function $getLastCodeNodeOfLine(anchor) {
28479    return $getLastMatchingCodeNode(anchor, "next");
28480  }
28481  function $getCodeLineDirection(anchor) {
28482    const start3 = $getFirstCodeNodeOfLine(anchor);
28483    const end = $getLastCodeNodeOfLine(anchor);
28484    let node = start3;
28485    while (node !== null) {
28486      if ($isCodeHighlightNode(node)) {
28487        const direction = getTextDirection2(node.getTextContent());
28488        if (direction !== null) {
28489          return direction;
28490        }
28491      }
28492      if (node === end) {
28493        break;
28494      }
28495      node = node.getNextSibling();
28496    }
28497    const parent = start3.getParent();
28498    if ($isElementNode2(parent)) {
28499      const parentDirection = parent.getDirection();
28500      if (parentDirection === "ltr" || parentDirection === "rtl") {
28501        return parentDirection;
28502      }
28503    }
28504    return null;
28505  }
28506  function $getStartOfCodeInLine(anchor, offset3) {
28507    let last = null;
28508    let lastNonBlank = null;
28509    let node = anchor;
28510    let nodeOffset = offset3;
28511    let nodeTextContent = anchor.getTextContent();
28512    while (true) {
28513      if (nodeOffset === 0) {
28514        node = node.getPreviousSibling();
28515        if (node === null) {
28516          break;
28517        }
28518        if (!($isCodeHighlightNode(node) || $isTabNode2(node) || $isLineBreakNode2(node))) {
28519          formatDevErrorMessage9(`Expected a valid Code Node: CodeHighlightNode, TabNode, LineBreakNode`);
28520        }
28521        if ($isLineBreakNode2(node)) {
28522          last = {
28523            node,
28524            offset: 1
28525          };
28526          break;
28527        }
28528        nodeOffset = Math.max(0, node.getTextContentSize() - 1);
28529        nodeTextContent = node.getTextContent();
28530      } else {
28531        nodeOffset--;
28532      }
28533      const character = nodeTextContent[nodeOffset];
28534      if ($isCodeHighlightNode(node) && character !== " ") {
28535        lastNonBlank = {
28536          node,
28537          offset: nodeOffset
28538        };
28539      }
28540    }
28541    if (lastNonBlank !== null) {
28542      return lastNonBlank;
28543    }
28544    let codeCharacterAtAnchorOffset = null;
28545    if (offset3 < anchor.getTextContentSize()) {
28546      if ($isCodeHighlightNode(anchor)) {
28547        codeCharacterAtAnchorOffset = anchor.getTextContent()[offset3];
28548      }
28549    } else {
28550      const nextSibling = anchor.getNextSibling();
28551      if ($isCodeHighlightNode(nextSibling)) {
28552        codeCharacterAtAnchorOffset = nextSibling.getTextContent()[0];
28553      }
28554    }
28555    if (codeCharacterAtAnchorOffset !== null && codeCharacterAtAnchorOffset !== " ") {
28556      return last;
28557    } else {
28558      const nextNonBlank = findNextNonBlankInLine(anchor, offset3);
28559      if (nextNonBlank !== null) {
28560        return nextNonBlank;
28561      } else {
28562        return last;
28563      }
28564    }
28565  }
28566  function findNextNonBlankInLine(anchor, offset3) {
28567    let node = anchor;
28568    let nodeOffset = offset3;
28569    let nodeTextContent = anchor.getTextContent();
28570    let nodeTextContentSize = anchor.getTextContentSize();
28571    while (true) {
28572      if (!$isCodeHighlightNode(node) || nodeOffset === nodeTextContentSize) {
28573        node = node.getNextSibling();
28574        if (node === null || $isLineBreakNode2(node)) {
28575          return null;
28576        }
28577        if ($isCodeHighlightNode(node)) {
28578          nodeOffset = 0;
28579          nodeTextContent = node.getTextContent();
28580          nodeTextContentSize = node.getTextContentSize();
28581        }
28582      }
28583      if ($isCodeHighlightNode(node)) {
28584        if (nodeTextContent[nodeOffset] !== " ") {
28585          return {
28586            node,
28587            offset: nodeOffset
28588          };
28589        }
28590        nodeOffset++;
28591      }
28592    }
28593  }
28594  function $getEndOfCodeInLine(anchor) {
28595    const lastNode = $getLastCodeNodeOfLine(anchor);
28596    if (!!$isLineBreakNode2(lastNode)) {
28597      formatDevErrorMessage9(`Unexpected lineBreakNode in getEndOfCodeInLine`);
28598    }
28599    return lastNode;
28600  }
28601  var DEFAULT_CODE_LANGUAGE = "javascript";
28602  var getDefaultCodeLanguage = () => DEFAULT_CODE_LANGUAGE;
28603  function hasChildDOMNodeTag(node, tagName) {
28604    for (const child of node.childNodes) {
28605      if (isHTMLElement2(child) && child.tagName === tagName) {
28606        return true;
28607      }
28608      hasChildDOMNodeTag(child, tagName);
28609    }
28610    return false;
28611  }
28612  var LANGUAGE_DATA_ATTRIBUTE = "data-language";
28613  var HIGHLIGHT_LANGUAGE_DATA_ATTRIBUTE = "data-highlight-language";
28614  var THEME_DATA_ATTRIBUTE = "data-theme";
28615  var noExtensionDeprecation = warnOnlyOnce3("Using CodeNode without CodeExtension is deprecated");
28616  var CodeNode = class _CodeNode extends ElementNode2 {
28617    /** @internal */
28618    __language;
28619    /** @internal */
28620    __theme;
28621    /** @internal */
28622    __isSyntaxHighlightSupported;
28623    static getType() {
28624      return "code";
28625    }
28626    static clone(node) {
28627      return new _CodeNode(node.__language, node.__key);
28628    }
28629    constructor(language, key) {
28630      super(key);
28631      this.__language = language || void 0;
28632      this.__isSyntaxHighlightSupported = false;
28633      this.__theme = void 0;
28634    }
28635    afterCloneFrom(prevNode) {
28636      super.afterCloneFrom(prevNode);
28637      this.__language = prevNode.__language;
28638      this.__theme = prevNode.__theme;
28639      this.__isSyntaxHighlightSupported = prevNode.__isSyntaxHighlightSupported;
28640    }
28641    // View
28642    createDOM(config) {
28643      const element = document.createElement("code");
28644      addClassNamesToElement2(element, config.theme.code);
28645      element.setAttribute("spellcheck", "false");
28646      const language = this.getLanguage();
28647      if (language) {
28648        element.setAttribute(LANGUAGE_DATA_ATTRIBUTE, language);
28649        if (this.getIsSyntaxHighlightSupported()) {
28650          element.setAttribute(HIGHLIGHT_LANGUAGE_DATA_ATTRIBUTE, language);
28651        }
28652      }
28653      const theme2 = this.getTheme();
28654      if (theme2) {
28655        element.setAttribute(THEME_DATA_ATTRIBUTE, theme2);
28656      }
28657      const style = this.getStyle();
28658      if (style) {
28659        setDOMStyleFromCSS2(element.style, style);
28660      }
28661      return element;
28662    }
28663    updateDOM(prevNode, dom, config) {
28664      const language = this.__language;
28665      const prevLanguage = prevNode.__language;
28666      if (language) {
28667        if (language !== prevLanguage) {
28668          dom.setAttribute(LANGUAGE_DATA_ATTRIBUTE, language);
28669        }
28670      } else if (prevLanguage) {
28671        dom.removeAttribute(LANGUAGE_DATA_ATTRIBUTE);
28672      }
28673      const isSyntaxHighlightSupported = this.__isSyntaxHighlightSupported;
28674      const prevIsSyntaxHighlightSupported = prevNode.__isSyntaxHighlightSupported;
28675      if (prevIsSyntaxHighlightSupported && prevLanguage) {
28676        if (isSyntaxHighlightSupported && language) {
28677          if (language !== prevLanguage) {
28678            dom.setAttribute(HIGHLIGHT_LANGUAGE_DATA_ATTRIBUTE, language);
28679          }
28680        } else {
28681          dom.removeAttribute(HIGHLIGHT_LANGUAGE_DATA_ATTRIBUTE);
28682        }
28683      } else if (isSyntaxHighlightSupported && language) {
28684        dom.setAttribute(HIGHLIGHT_LANGUAGE_DATA_ATTRIBUTE, language);
28685      }
28686      const theme2 = this.__theme;
28687      const prevTheme = prevNode.__theme;
28688      if (theme2) {
28689        if (theme2 !== prevTheme) {
28690          dom.setAttribute(THEME_DATA_ATTRIBUTE, theme2);
28691        }
28692      } else if (prevTheme) {
28693        dom.removeAttribute(THEME_DATA_ATTRIBUTE);
28694      }
28695      const style = this.__style;
28696      const prevStyle = prevNode.__style;
28697      if (style !== prevStyle) {
28698        setDOMStyleFromCSS2(dom.style, style, prevStyle);
28699      }
28700      return false;
28701    }
28702    exportDOM(editor) {
28703      const element = document.createElement("pre");
28704      addClassNamesToElement2(element, editor._config.theme.code);
28705      element.setAttribute("spellcheck", "false");
28706      const language = this.getLanguage();
28707      if (language) {
28708        element.setAttribute(LANGUAGE_DATA_ATTRIBUTE, language);
28709        if (this.getIsSyntaxHighlightSupported()) {
28710          element.setAttribute(HIGHLIGHT_LANGUAGE_DATA_ATTRIBUTE, language);
28711        }
28712      }
28713      const theme2 = this.getTheme();
28714      if (theme2) {
28715        element.setAttribute(THEME_DATA_ATTRIBUTE, theme2);
28716      }
28717      const style = this.getStyle();
28718      if (style) {
28719        setDOMStyleFromCSS2(element.style, style);
28720      }
28721      return {
28722        element
28723      };
28724    }
28725    static importDOM() {
28726      return {
28727        // Typically <pre> is used for code blocks, and <code> for inline code styles
28728        // but if it's a multi line <code> we'll create a block. Pass through to
28729        // inline format handled by TextNode otherwise.
28730        code: (node) => {
28731          const isMultiLine = node.textContent != null && (/\r?\n/.test(node.textContent) || hasChildDOMNodeTag(node, "BR"));
28732          return isMultiLine ? {
28733            conversion: $convertPreElement,
28734            priority: 1
28735          } : null;
28736        },
28737        div: () => ({
28738          conversion: $convertDivElement,
28739          priority: 1
28740        }),
28741        pre: () => ({
28742          conversion: $convertPreElement,
28743          priority: 0
28744        }),
28745        table: (node) => {
28746          const table = node;
28747          if (isGitHubCodeTable(table)) {
28748            return {
28749              conversion: $convertTableElement,
28750              priority: 3
28751            };
28752          }
28753          return null;
28754        },
28755        td: (node) => {
28756          const td = node;
28757          const table = td.closest("table");
28758          if (isGitHubCodeCell(td) || table && isGitHubCodeTable(table)) {
28759            return {
28760              conversion: convertCodeNoop,
28761              priority: 3
28762            };
28763          }
28764          return null;
28765        },
28766        tr: (node) => {
28767          const tr = node;
28768          const table = tr.closest("table");
28769          if (table && isGitHubCodeTable(table)) {
28770            return {
28771              conversion: convertCodeNoop,
28772              priority: 3
28773            };
28774          }
28775          return null;
28776        }
28777      };
28778    }
28779    static importJSON(serializedNode) {
28780      return $createCodeNode().updateFromJSON(serializedNode);
28781    }
28782    updateFromJSON(serializedNode) {
28783      return super.updateFromJSON(serializedNode).setLanguage(serializedNode.language).setTheme(serializedNode.theme);
28784    }
28785    exportJSON() {
28786      return {
28787        ...super.exportJSON(),
28788        language: this.getLanguage(),
28789        theme: this.getTheme()
28790      };
28791    }
28792    // Mutation
28793    insertNewAfter(selection, restoreSelection = true) {
28794      if (!getPeerDependencyFromEditor2($getEditor2(), "@lexical/code")) {
28795        noExtensionDeprecation();
28796        const el = $exitCodeNodeOnEnter(selection);
28797        if (el) {
28798          return el;
28799        }
28800      }
28801      const {
28802        anchor,
28803        focus
28804      } = selection;
28805      const firstPoint = anchor.isBefore(focus) ? anchor : focus;
28806      const firstSelectionNode = firstPoint.getNode();
28807      if ($isTextNode2(firstSelectionNode)) {
28808        let node = $getFirstCodeNodeOfLine(firstSelectionNode);
28809        const insertNodes = [];
28810        while (true) {
28811          if ($isTabNode2(node)) {
28812            insertNodes.push($createTabNode2());
28813            node = node.getNextSibling();
28814          } else if ($isCodeHighlightNode(node)) {
28815            let spaces = 0;
28816            const text2 = node.getTextContent();
28817            const textSize = node.getTextContentSize();
28818            while (spaces < textSize && text2[spaces] === " ") {
28819              spaces++;
28820            }
28821            if (spaces !== 0) {
28822              insertNodes.push($createCodeHighlightNode(" ".repeat(spaces)));
28823            }
28824            if (spaces !== textSize) {
28825              break;
28826            }
28827            node = node.getNextSibling();
28828          } else {
28829            break;
28830          }
28831        }
28832        const split = firstSelectionNode.splitText(anchor.offset)[0];
28833        const x3 = anchor.offset === 0 ? 0 : 1;
28834        const index = split.getIndexWithinParent() + x3;
28835        const codeNode = firstSelectionNode.getParentOrThrow();
28836        const nodesToInsert = [$createLineBreakNode2(), ...insertNodes];
28837        codeNode.splice(index, 0, nodesToInsert);
28838        const last = insertNodes[insertNodes.length - 1];
28839        if (last) {
28840          last.select();
28841        } else if (anchor.offset === 0) {
28842          split.selectPrevious();
28843        } else {
28844          split.getNextSibling().selectNext(0, 0);
28845        }
28846      }
28847      if ($isCodeNode(firstSelectionNode)) {
28848        const {
28849          offset: offset3
28850        } = selection.anchor;
28851        firstSelectionNode.splice(offset3, 0, [$createLineBreakNode2()]);
28852        firstSelectionNode.select(offset3 + 1, offset3 + 1);
28853      }
28854      return null;
28855    }
28856    canIndent() {
28857      return false;
28858    }
28859    collapseAtStart() {
28860      const paragraph = $createParagraphNode2();
28861      const children = this.getChildren();
28862      children.forEach((child) => paragraph.append(child));
28863      this.replace(paragraph);
28864      return true;
28865    }
28866    setLanguage(language) {
28867      const writable = this.getWritable();
28868      writable.__language = language || void 0;
28869      return writable;
28870    }
28871    getLanguage() {
28872      return this.getLatest().__language;
28873    }
28874    setIsSyntaxHighlightSupported(isSupported) {
28875      const writable = this.getWritable();
28876      writable.__isSyntaxHighlightSupported = isSupported;
28877      return writable;
28878    }
28879    getIsSyntaxHighlightSupported() {
28880      return this.getLatest().__isSyntaxHighlightSupported;
28881    }
28882    setTheme(theme2) {
28883      const writable = this.getWritable();
28884      writable.__theme = theme2 || void 0;
28885      return writable;
28886    }
28887    getTheme() {
28888      return this.getLatest().__theme;
28889    }
28890  };
28891  function $createCodeNode(language, theme2) {
28892    return $create2(CodeNode).setLanguage(language).setTheme(theme2);
28893  }
28894  function $isCodeNode(node) {
28895    return node instanceof CodeNode;
28896  }
28897  function $convertPreElement(domNode) {
28898    const language = domNode.getAttribute(LANGUAGE_DATA_ATTRIBUTE);
28899    return {
28900      node: $createCodeNode(language)
28901    };
28902  }
28903  function $convertDivElement(domNode) {
28904    const div = domNode;
28905    const isCode = isCodeElement(div);
28906    if (!isCode && !isCodeChildElement(div)) {
28907      return {
28908        node: null
28909      };
28910    }
28911    return {
28912      node: isCode ? $createCodeNode() : null
28913    };
28914  }
28915  function $convertTableElement() {
28916    return {
28917      node: $createCodeNode()
28918    };
28919  }
28920  function convertCodeNoop() {
28921    return {
28922      node: null
28923    };
28924  }
28925  function isCodeElement(div) {
28926    return div.style.fontFamily.match("monospace") !== null;
28927  }
28928  function isCodeChildElement(node) {
28929    let parent = node.parentElement;
28930    while (parent !== null) {
28931      if (isCodeElement(parent)) {
28932        return true;
28933      }
28934      parent = parent.parentElement;
28935    }
28936    return false;
28937  }
28938  function isGitHubCodeCell(cell) {
28939    return cell.classList.contains("js-file-line");
28940  }
28941  function isGitHubCodeTable(table) {
28942    return table.classList.contains("js-file-line-container");
28943  }
28944  function $exitCodeNodeOnEnter(selection) {
28945    const {
28946      anchor
28947    } = selection;
28948    if (selection.isCollapsed() && anchor.type === "element") {
28949      const codeNode = anchor.getNode();
28950      if ($isCodeNode(codeNode)) {
28951        const childrenSize = codeNode.getChildrenSize();
28952        if (childrenSize >= 2 && anchor.offset === childrenSize) {
28953          const lastChild = codeNode.getLastChild();
28954          if ($isLineBreakNode2(lastChild) && $isLineBreakNode2(lastChild.getPreviousSibling())) {
28955            const newElement = $createParagraphNode2();
28956            codeNode.splice(childrenSize - 2, 2, []).insertAfter(newElement, false);
28957            newElement.select();
28958            return newElement;
28959          }
28960        }
28961      }
28962    }
28963    return null;
28964  }
28965  var CodeHighlightNode = class _CodeHighlightNode extends TextNode2 {
28966    /** @internal */
28967    __highlightType;
28968    constructor(text2 = "", highlightType, key) {
28969      super(text2, key);
28970      this.__highlightType = highlightType;
28971    }
28972    static getType() {
28973      return "code-highlight";
28974    }
28975    static clone(node) {
28976      return new _CodeHighlightNode(node.__text, node.__highlightType || void 0, node.__key);
28977    }
28978    afterCloneFrom(prevNode) {
28979      super.afterCloneFrom(prevNode);
28980      this.__highlightType = prevNode.__highlightType;
28981    }
28982    getHighlightType() {
28983      const self2 = this.getLatest();
28984      return self2.__highlightType;
28985    }
28986    setHighlightType(highlightType) {
28987      const self2 = this.getWritable();
28988      self2.__highlightType = highlightType || void 0;
28989      return self2;
28990    }
28991    canHaveFormat() {
28992      return false;
28993    }
28994    createDOM(config) {
28995      const element = super.createDOM(config);
28996      const className = getHighlightThemeClass(config.theme, this.__highlightType);
28997      addClassNamesToElement2(element, className);
28998      return element;
28999    }
29000    updateDOM(prevNode, dom, config) {
29001      const update = super.updateDOM(prevNode, dom, config);
29002      const prevClassName = getHighlightThemeClass(config.theme, prevNode.__highlightType);
29003      const nextClassName = getHighlightThemeClass(config.theme, this.__highlightType);
29004      if (prevClassName !== nextClassName) {
29005        if (prevClassName) {
29006          removeClassNamesFromElement2(dom, prevClassName);
29007        }
29008        if (nextClassName) {
29009          addClassNamesToElement2(dom, nextClassName);
29010        }
29011      }
29012      return update;
29013    }
29014    static importJSON(serializedNode) {
29015      return $createCodeHighlightNode().updateFromJSON(serializedNode);
29016    }
29017    updateFromJSON(serializedNode) {
29018      return super.updateFromJSON(serializedNode).setHighlightType(serializedNode.highlightType);
29019    }
29020    exportJSON() {
29021      return {
29022        ...super.exportJSON(),
29023        highlightType: this.getHighlightType()
29024      };
29025    }
29026    // Prevent formatting (bold, underline, etc)
29027    setFormat(format) {
29028      return this;
29029    }
29030    isParentRequired() {
29031      return true;
29032    }
29033    createParentElementNode() {
29034      return $createCodeNode();
29035    }
29036  };
29037  function getHighlightThemeClass(theme2, highlightType) {
29038    return highlightType && theme2 && theme2.codeHighlight && theme2.codeHighlight[highlightType];
29039  }
29040  function $createCodeHighlightNode(text2 = "", highlightType) {
29041    return $applyNodeReplacement2(new CodeHighlightNode(text2, highlightType));
29042  }
29043  function $isCodeHighlightNode(node) {
29044    return node instanceof CodeHighlightNode;
29045  }
29046  var CodeExtension = defineExtension2({
29047    name: "@lexical/code",
29048    nodes: () => [CodeNode, CodeHighlightNode],
29049    register(editor) {
29050      return editor.registerCommand(KEY_ENTER_COMMAND2, (event) => {
29051        const selection = $getSelection2();
29052        if ($isRangeSelection2(selection) && $exitCodeNodeOnEnter(selection)) {
29053          event.preventDefault();
29054          return true;
29055        }
29056        return false;
29057      }, COMMAND_PRIORITY_LOW2);
29058    }
29059  });
29060
29061  
vendor: 905 bytes, lines 29061-29078
29061// node_modules/@lexical/code-core/LexicalCodeCore.mjs
29062  var mod13 = true ? LexicalCodeCore_dev_exports : LexicalCodeCore_prod_exports;
29063  var $createCodeHighlightNode2 = mod13.$createCodeHighlightNode;
29064  var $createCodeNode2 = mod13.$createCodeNode;
29065  var $getCodeLineDirection2 = mod13.$getCodeLineDirection;
29066  var $getEndOfCodeInLine2 = mod13.$getEndOfCodeInLine;
29067  var $getFirstCodeNodeOfLine2 = mod13.$getFirstCodeNodeOfLine;
29068  var $getLastCodeNodeOfLine2 = mod13.$getLastCodeNodeOfLine;
29069  var $getStartOfCodeInLine2 = mod13.$getStartOfCodeInLine;
29070  var $isCodeHighlightNode2 = mod13.$isCodeHighlightNode;
29071  var $isCodeNode2 = mod13.$isCodeNode;
29072  var CodeExtension2 = mod13.CodeExtension;
29073  var CodeHighlightNode2 = mod13.CodeHighlightNode;
29074  var CodeNode2 = mod13.CodeNode;
29075  var DEFAULT_CODE_LANGUAGE2 = mod13.DEFAULT_CODE_LANGUAGE;
29076  var getDefaultCodeLanguage2 = mod13.getDefaultCodeLanguage;
29077
29078  
vendor: 27,232 bytes, lines 29078-29828
29078// node_modules/@lexical/code-prism/LexicalCodePrism.dev.mjs
29079  var import_prismjs2 = __toESM(require_prism(), 1);
29080  function formatDevErrorMessage10(message) {
29081    throw new Error(message);
29082  }
29083  (function(Prism3) {
29084    Prism3.languages.diff = {
29085      "coord": [
29086        // Match all kinds of coord lines (prefixed by "+++", "---" or "***").
29087        /^(?:\*{3}|-{3}|\+{3}).*$/m,
29088        // Match "@@ ... @@" coord lines in unified diff.
29089        /^@@.*@@$/m,
29090        // Match coord lines in normal diff (starts with a number).
29091        /^\d.*$/m
29092      ]
29093      // deleted, inserted, unchanged, diff
29094    };
29095    var PREFIXES = {
29096      "deleted-sign": "-",
29097      "deleted-arrow": "<",
29098      "inserted-sign": "+",
29099      "inserted-arrow": ">",
29100      "unchanged": " ",
29101      "diff": "!"
29102    };
29103    Object.keys(PREFIXES).forEach(function(name) {
29104      var prefix = PREFIXES[name];
29105      var alias = [];
29106      if (!/^\w+$/.test(name)) {
29107        alias.push(/\w+/.exec(name)[0]);
29108      }
29109      if (name === "diff") {
29110        alias.push("bold");
29111      }
29112      Prism3.languages.diff[name] = {
29113        pattern: RegExp("^(?:[" + prefix + "].*(?:\r\n?|\n|(?![\\s\\S])))+", "m"),
29114        alias,
29115        inside: {
29116          "line": {
29117            pattern: /(.)(?=[\s\S]).*(?:\r\n?|\n)?/,
29118            lookbehind: true
29119          },
29120          "prefix": {
29121            pattern: /[\s\S]/,
29122            alias: /\w+/.exec(name)[0]
29123          }
29124        }
29125      };
29126    });
29127    Object.defineProperty(Prism3.languages.diff, "PREFIXES", {
29128      value: PREFIXES
29129    });
29130  })(Prism);
29131  var Prism$1 = globalThis.Prism || window.Prism;
29132  var CODE_LANGUAGE_FRIENDLY_NAME_MAP = {
29133    c: "C",
29134    clike: "C-like",
29135    cpp: "C++",
29136    css: "CSS",
29137    html: "HTML",
29138    java: "Java",
29139    js: "JavaScript",
29140    markdown: "Markdown",
29141    objc: "Objective-C",
29142    plain: "Plain Text",
29143    powershell: "PowerShell",
29144    py: "Python",
29145    rust: "Rust",
29146    sql: "SQL",
29147    swift: "Swift",
29148    typescript: "TypeScript",
29149    xml: "XML"
29150  };
29151  var CODE_LANGUAGE_MAP = {
29152    cpp: "cpp",
29153    java: "java",
29154    javascript: "js",
29155    md: "markdown",
29156    plaintext: "plain",
29157    python: "py",
29158    text: "plain",
29159    ts: "typescript"
29160  };
29161  function normalizeCodeLanguage(lang) {
29162    return CODE_LANGUAGE_MAP[lang] || lang;
29163  }
29164  function getLanguageFriendlyName(lang) {
29165    const _lang = normalizeCodeLanguage(lang);
29166    return CODE_LANGUAGE_FRIENDLY_NAME_MAP[_lang] || _lang;
29167  }
29168  var getCodeLanguages = () => Object.keys(Prism$1.languages).filter(
29169    // Prism has several language helpers mixed into languages object
29170    // so filtering them out here to get langs list
29171    (language) => typeof Prism$1.languages[language] !== "function"
29172  ).sort();
29173  function getCodeLanguageOptions() {
29174    const options = [];
29175    for (const [lang, friendlyName] of Object.entries(CODE_LANGUAGE_FRIENDLY_NAME_MAP)) {
29176      options.push([lang, friendlyName]);
29177    }
29178    return options;
29179  }
29180  function getCodeThemeOptions() {
29181    const options = [];
29182    return options;
29183  }
29184  function getDiffedLanguage(language) {
29185    const DIFF_LANGUAGE_REGEX = /^diff-([\w-]+)/i;
29186    const diffLanguageMatch = DIFF_LANGUAGE_REGEX.exec(language);
29187    return diffLanguageMatch ? diffLanguageMatch[1] : null;
29188  }
29189  function isCodeLanguageLoaded(language) {
29190    const diffedLanguage = getDiffedLanguage(language);
29191    const langId = diffedLanguage ? diffedLanguage : language;
29192    try {
29193      return langId ? Prism$1.languages.hasOwnProperty(langId) : false;
29194    } catch (_unused) {
29195      return false;
29196    }
29197  }
29198  async function loadCodeLanguage(language, editor, codeNodeKey) {
29199  }
29200  function getTextContent(token) {
29201    if (typeof token === "string") {
29202      return token;
29203    } else if (Array.isArray(token)) {
29204      return token.map(getTextContent).join("");
29205    } else {
29206      return getTextContent(token.content);
29207    }
29208  }
29209  function tokenizeDiffHighlight(tokens, language) {
29210    const diffLanguage = language;
29211    const diffGrammar = Prism$1.languages[diffLanguage];
29212    const env = {
29213      tokens
29214    };
29215    const PREFIXES = Prism$1.languages.diff.PREFIXES;
29216    for (const token of env.tokens) {
29217      if (typeof token === "string" || !(token.type in PREFIXES) || !Array.isArray(token.content)) {
29218        continue;
29219      }
29220      const type = token.type;
29221      let insertedPrefixes = 0;
29222      const getPrefixToken = () => {
29223        insertedPrefixes++;
29224        return new Prism$1.Token("prefix", PREFIXES[type], type.replace(/^(\w+).*/, "$1"));
29225      };
29226      const withoutPrefixes = token.content.filter((t2) => typeof t2 === "string" || t2.type !== "prefix");
29227      const prefixCount = token.content.length - withoutPrefixes.length;
29228      const diffTokens = Prism$1.tokenize(getTextContent(withoutPrefixes), diffGrammar);
29229      diffTokens.unshift(getPrefixToken());
29230      const LINE_BREAK = /\r\n|\n/g;
29231      const insertAfterLineBreakString = (text2) => {
29232        const result = [];
29233        LINE_BREAK.lastIndex = 0;
29234        let last = 0;
29235        let m3;
29236        while (insertedPrefixes < prefixCount && (m3 = LINE_BREAK.exec(text2))) {
29237          const end = m3.index + m3[0].length;
29238          result.push(text2.slice(last, end));
29239          last = end;
29240          result.push(getPrefixToken());
29241        }
29242        if (result.length === 0) {
29243          return void 0;
29244        }
29245        if (last < text2.length) {
29246          result.push(text2.slice(last));
29247        }
29248        return result;
29249      };
29250      const insertAfterLineBreak = (toks) => {
29251        for (let i2 = 0; i2 < toks.length && insertedPrefixes < prefixCount; i2++) {
29252          const tok = toks[i2];
29253          if (typeof tok === "string") {
29254            const inserted = insertAfterLineBreakString(tok);
29255            if (inserted) {
29256              toks.splice(i2, 1, ...inserted);
29257              i2 += inserted.length - 1;
29258            }
29259          } else if (typeof tok.content === "string") {
29260            const inserted = insertAfterLineBreakString(tok.content);
29261            if (inserted) {
29262              tok.content = inserted;
29263            }
29264          } else if (Array.isArray(tok.content)) {
29265            insertAfterLineBreak(tok.content);
29266          } else {
29267            insertAfterLineBreak([tok.content]);
29268          }
29269        }
29270      };
29271      insertAfterLineBreak(diffTokens);
29272      if (insertedPrefixes < prefixCount) {
29273        diffTokens.push(getPrefixToken());
29274      }
29275      token.content = diffTokens;
29276    }
29277    return env.tokens;
29278  }
29279  function $getHighlightNodes(codeNode, language) {
29280    const DIFF_LANGUAGE_REGEX = /^diff-([\w-]+)/i;
29281    const diffLanguageMatch = DIFF_LANGUAGE_REGEX.exec(language);
29282    const code = codeNode.getTextContent();
29283    let tokens = Prism$1.tokenize(code, Prism$1.languages[diffLanguageMatch ? "diff" : language]);
29284    if (diffLanguageMatch) {
29285      tokens = tokenizeDiffHighlight(tokens, diffLanguageMatch[1]);
29286    }
29287    return $mapTokensToLexicalStructure(tokens);
29288  }
29289  function $mapTokensToLexicalStructure(tokens, type) {
29290    const nodes = [];
29291    for (const token of tokens) {
29292      if (typeof token === "string") {
29293        const partials = token.split(/(\n|\t)/);
29294        const partialsLength = partials.length;
29295        for (let i2 = 0; i2 < partialsLength; i2++) {
29296          const part = partials[i2];
29297          if (part === "\n" || part === "\r\n") {
29298            nodes.push($createLineBreakNode2());
29299          } else if (part === "	") {
29300            nodes.push($createTabNode2());
29301          } else if (part.length > 0) {
29302            nodes.push($createCodeHighlightNode2(part, type));
29303          }
29304        }
29305      } else {
29306        const {
29307          content,
29308          alias
29309        } = token;
29310        if (typeof content === "string") {
29311          nodes.push(...$mapTokensToLexicalStructure([content], token.type === "prefix" && typeof alias === "string" ? alias : token.type));
29312        } else if (Array.isArray(content)) {
29313          nodes.push(...$mapTokensToLexicalStructure(content, token.type === "unchanged" ? void 0 : token.type));
29314        }
29315      }
29316    }
29317    return nodes;
29318  }
29319  var PrismTokenizer = {
29320    $tokenize(codeNode, language) {
29321      return $getHighlightNodes(codeNode, language || this.defaultLanguage);
29322    },
29323    defaultLanguage: DEFAULT_CODE_LANGUAGE2,
29324    tokenize(code, language) {
29325      return Prism$1.tokenize(code, Prism$1.languages[language || ""] || Prism$1.languages[this.defaultLanguage]);
29326    }
29327  };
29328  function $textNodeTransform(editor, tokenizer, transformState, node) {
29329    const parentNode = node.getParent();
29330    if ($isCodeNode2(parentNode)) {
29331      $codeNodeTransform(editor, tokenizer, transformState, parentNode);
29332    } else if ($isCodeHighlightNode2(node)) {
29333      node.replace($createTextNode2(node.__text));
29334    }
29335  }
29336  function updateCodeGutter(node, editor) {
29337    const codeElement = editor.getElementByKey(node.getKey());
29338    if (codeElement === null) {
29339      return;
29340    }
29341    const children = node.getChildren();
29342    const childrenLength = children.length;
29343    if (childrenLength === codeElement.__cachedChildrenLength) {
29344      return;
29345    }
29346    codeElement.__cachedChildrenLength = childrenLength;
29347    let gutter = "1";
29348    let count = 1;
29349    for (let i2 = 0; i2 < childrenLength; i2++) {
29350      if ($isLineBreakNode2(children[i2])) {
29351        gutter += "\n" + ++count;
29352      }
29353    }
29354    codeElement.setAttribute("data-gutter", gutter);
29355  }
29356  function $codeNodeTransform(editor, tokenizer, transformState, node) {
29357    const {
29358      nodesCurrentlyHighlighting
29359    } = transformState;
29360    const nodeKey = node.getKey();
29361    if (node.getLanguage() === void 0) {
29362      node.setLanguage(tokenizer.defaultLanguage);
29363    }
29364    const language = node.getLanguage() || tokenizer.defaultLanguage;
29365    if (isCodeLanguageLoaded(language)) {
29366      if (!node.getIsSyntaxHighlightSupported()) {
29367        node.setIsSyntaxHighlightSupported(true);
29368      }
29369    } else {
29370      if (node.getIsSyntaxHighlightSupported()) {
29371        node.setIsSyntaxHighlightSupported(false);
29372      }
29373      loadCodeLanguage(language, editor, nodeKey);
29374      return;
29375    }
29376    if (nodesCurrentlyHighlighting.has(nodeKey)) {
29377      return;
29378    }
29379    nodesCurrentlyHighlighting.add(nodeKey);
29380    if (!transformState.didTransform) {
29381      transformState.didTransform = true;
29382      $onUpdate2(() => {
29383        transformState.didTransform = false;
29384        nodesCurrentlyHighlighting.clear();
29385      });
29386    }
29387    $updateAndRetainSelection(nodeKey, () => {
29388      const currentNode = $getNodeByKey2(nodeKey);
29389      if (!$isCodeNode2(currentNode) || !currentNode.isAttached()) {
29390        return false;
29391      }
29392      const currentLanguage = currentNode.getLanguage() || tokenizer.defaultLanguage;
29393      const highlightNodes = tokenizer.$tokenize(currentNode, currentLanguage);
29394      const diffRange = getDiffRange(currentNode.getChildren(), highlightNodes);
29395      const {
29396        from,
29397        to,
29398        nodesForReplacement
29399      } = diffRange;
29400      if (from !== to || nodesForReplacement.length) {
29401        node.splice(from, to - from, nodesForReplacement);
29402        return true;
29403      }
29404      return false;
29405    });
29406  }
29407  function $updateAndRetainSelection(nodeKey, updateFn) {
29408    const node = $getNodeByKey2(nodeKey);
29409    if (!$isCodeNode2(node) || !node.isAttached()) {
29410      return;
29411    }
29412    const selection = $getSelection2();
29413    if (!$isRangeSelection2(selection)) {
29414      updateFn();
29415      return;
29416    }
29417    const anchor = selection.anchor;
29418    const anchorOffset = anchor.offset;
29419    const isNewLineAnchor = anchor.type === "element" && $isLineBreakNode2(node.getChildAtIndex(anchor.offset - 1));
29420    let textOffset = 0;
29421    if (!isNewLineAnchor) {
29422      const anchorNode = anchor.getNode();
29423      textOffset = anchorOffset + anchorNode.getPreviousSiblings().reduce((offset3, _node) => {
29424        return offset3 + _node.getTextContentSize();
29425      }, 0);
29426    }
29427    const hasChanges = updateFn();
29428    if (!hasChanges) {
29429      return;
29430    }
29431    if (isNewLineAnchor) {
29432      anchor.getNode().select(anchorOffset, anchorOffset);
29433      return;
29434    }
29435    node.getChildren().some((_node) => {
29436      const isText = $isTextNode2(_node);
29437      if (isText || $isLineBreakNode2(_node)) {
29438        const textContentSize = _node.getTextContentSize();
29439        if (isText && textContentSize >= textOffset) {
29440          _node.select(textOffset, textOffset);
29441          return true;
29442        }
29443        textOffset -= textContentSize;
29444      }
29445      return false;
29446    });
29447  }
29448  function getDiffRange(prevNodes, nextNodes) {
29449    let leadingMatch = 0;
29450    while (leadingMatch < prevNodes.length) {
29451      if (!isEqual(prevNodes[leadingMatch], nextNodes[leadingMatch])) {
29452        break;
29453      }
29454      leadingMatch++;
29455    }
29456    const prevNodesLength = prevNodes.length;
29457    const nextNodesLength = nextNodes.length;
29458    const maxTrailingMatch = Math.min(prevNodesLength, nextNodesLength) - leadingMatch;
29459    let trailingMatch = 0;
29460    while (trailingMatch < maxTrailingMatch) {
29461      trailingMatch++;
29462      if (!isEqual(prevNodes[prevNodesLength - trailingMatch], nextNodes[nextNodesLength - trailingMatch])) {
29463        trailingMatch--;
29464        break;
29465      }
29466    }
29467    const from = leadingMatch;
29468    const to = prevNodesLength - trailingMatch;
29469    const nodesForReplacement = nextNodes.slice(leadingMatch, nextNodesLength - trailingMatch);
29470    return {
29471      from,
29472      nodesForReplacement,
29473      to
29474    };
29475  }
29476  function isEqual(nodeA, nodeB) {
29477    return $isCodeHighlightNode2(nodeA) && $isCodeHighlightNode2(nodeB) && nodeA.__text === nodeB.__text && nodeA.__highlightType === nodeB.__highlightType || $isTabNode2(nodeA) && $isTabNode2(nodeB) || $isLineBreakNode2(nodeA) && $isLineBreakNode2(nodeB);
29478  }
29479  function $isSelectionInCode(selection) {
29480    if (!$isRangeSelection2(selection)) {
29481      return false;
29482    }
29483    const anchorNode = selection.anchor.getNode();
29484    const maybeAnchorCodeNode = $isCodeNode2(anchorNode) ? anchorNode : anchorNode.getParent();
29485    const focusNode = selection.focus.getNode();
29486    const maybeFocusCodeNode = $isCodeNode2(focusNode) ? focusNode : focusNode.getParent();
29487    return $isCodeNode2(maybeAnchorCodeNode) && maybeAnchorCodeNode.is(maybeFocusCodeNode);
29488  }
29489  function $getCodeLines(selection) {
29490    const nodes = selection.getNodes();
29491    const lines = [];
29492    if (nodes.length === 1 && $isCodeNode2(nodes[0])) {
29493      return lines;
29494    }
29495    let lastLine = [];
29496    for (let i2 = 0; i2 < nodes.length; i2++) {
29497      const node = nodes[i2];
29498      if (!($isCodeHighlightNode2(node) || $isTabNode2(node) || $isLineBreakNode2(node))) {
29499        formatDevErrorMessage10(`Expected selection to be inside CodeBlock and consisting of CodeHighlightNode, TabNode and LineBreakNode`);
29500      }
29501      if ($isLineBreakNode2(node)) {
29502        if (lastLine.length > 0) {
29503          lines.push(lastLine);
29504          lastLine = [];
29505        }
29506      } else {
29507        lastLine.push(node);
29508      }
29509    }
29510    if (lastLine.length > 0) {
29511      const selectionEnd = selection.isBackward() ? selection.anchor : selection.focus;
29512      const lastPoint = $createPoint2(lastLine[0].getKey(), 0, "text");
29513      if (!selectionEnd.is(lastPoint)) {
29514        lines.push(lastLine);
29515      }
29516    }
29517    return lines;
29518  }
29519  function $handleTab(shiftKey) {
29520    const selection = $getSelection2();
29521    if (!$isRangeSelection2(selection) || !$isSelectionInCode(selection)) {
29522      return null;
29523    }
29524    const indentOrOutdent = !shiftKey ? INDENT_CONTENT_COMMAND2 : OUTDENT_CONTENT_COMMAND2;
29525    const tabOrOutdent = !shiftKey ? INSERT_TAB_COMMAND2 : OUTDENT_CONTENT_COMMAND2;
29526    const anchor = selection.anchor;
29527    const focus = selection.focus;
29528    if (anchor.is(focus)) {
29529      return tabOrOutdent;
29530    }
29531    const codeLines = $getCodeLines(selection);
29532    if (codeLines.length !== 1) {
29533      return indentOrOutdent;
29534    }
29535    const codeLine = codeLines[0];
29536    const codeLineLength = codeLine.length;
29537    if (!(codeLineLength !== 0)) {
29538      formatDevErrorMessage10(`$getCodeLines only extracts non-empty lines`);
29539    }
29540    let selectionFirst;
29541    let selectionLast;
29542    if (selection.isBackward()) {
29543      selectionFirst = focus;
29544      selectionLast = anchor;
29545    } else {
29546      selectionFirst = anchor;
29547      selectionLast = focus;
29548    }
29549    const firstOfLine = $getFirstCodeNodeOfLine2(codeLine[0]);
29550    const lastOfLine = $getLastCodeNodeOfLine2(codeLine[0]);
29551    const anchorOfLine = $createPoint2(firstOfLine.getKey(), 0, "text");
29552    const focusOfLine = $createPoint2(lastOfLine.getKey(), lastOfLine.getTextContentSize(), "text");
29553    if (selectionFirst.isBefore(anchorOfLine)) {
29554      return indentOrOutdent;
29555    }
29556    if (focusOfLine.isBefore(selectionLast)) {
29557      return indentOrOutdent;
29558    }
29559    if (anchorOfLine.isBefore(selectionFirst) || selectionLast.isBefore(focusOfLine)) {
29560      return tabOrOutdent;
29561    }
29562    return indentOrOutdent;
29563  }
29564  function $handleMultilineIndent(type) {
29565    const selection = $getSelection2();
29566    if (!$isRangeSelection2(selection) || !$isSelectionInCode(selection)) {
29567      return false;
29568    }
29569    const codeLines = $getCodeLines(selection);
29570    const codeLinesLength = codeLines.length;
29571    if (codeLinesLength === 0 && selection.isCollapsed()) {
29572      if (type === INDENT_CONTENT_COMMAND2) {
29573        selection.insertNodes([$createTabNode2()]);
29574      }
29575      return true;
29576    }
29577    if (codeLinesLength === 0 && type === INDENT_CONTENT_COMMAND2 && selection.getTextContent() === "\n") {
29578      const tabNode = $createTabNode2();
29579      const lineBreakNode = $createLineBreakNode2();
29580      const direction = selection.isBackward() ? "previous" : "next";
29581      selection.insertNodes([tabNode, lineBreakNode]);
29582      $setSelectionFromCaretRange2($getCaretRangeInDirection2($getCaretRange2($getTextPointCaret2(tabNode, "next", 0), $normalizeCaret2($getSiblingCaret2(lineBreakNode, "next"))), direction));
29583      return true;
29584    }
29585    for (let i2 = 0; i2 < codeLinesLength; i2++) {
29586      const line = codeLines[i2];
29587      if (line.length > 0) {
29588        let firstOfLine = line[0];
29589        if (i2 === 0) {
29590          firstOfLine = $getFirstCodeNodeOfLine2(firstOfLine);
29591        }
29592        if (type === INDENT_CONTENT_COMMAND2) {
29593          const tabNode = $createTabNode2();
29594          firstOfLine.insertBefore(tabNode);
29595          if (i2 === 0) {
29596            const anchorKey = selection.isBackward() ? "focus" : "anchor";
29597            const anchorLine = $createPoint2(firstOfLine.getKey(), 0, "text");
29598            if (selection[anchorKey].is(anchorLine)) {
29599              selection[anchorKey].set(tabNode.getKey(), 0, "text");
29600            }
29601          }
29602        } else if ($isTabNode2(firstOfLine)) {
29603          firstOfLine.remove();
29604        }
29605      }
29606    }
29607    return true;
29608  }
29609  function $handleShiftLines(type, event) {
29610    const selection = $getSelection2();
29611    if (!$isRangeSelection2(selection)) {
29612      return false;
29613    }
29614    const {
29615      anchor,
29616      focus
29617    } = selection;
29618    const anchorOffset = anchor.offset;
29619    const focusOffset = focus.offset;
29620    const anchorNode = anchor.getNode();
29621    const focusNode = focus.getNode();
29622    const arrowIsUp = type === KEY_ARROW_UP_COMMAND2;
29623    if (!$isSelectionInCode(selection) || !($isCodeHighlightNode2(anchorNode) || $isTabNode2(anchorNode)) || !($isCodeHighlightNode2(focusNode) || $isTabNode2(focusNode))) {
29624      return false;
29625    }
29626    if (!event.altKey) {
29627      if (selection.isCollapsed()) {
29628        const codeNode = anchorNode.getParentOrThrow();
29629        if (arrowIsUp && anchorOffset === 0 && anchorNode.getPreviousSibling() === null) {
29630          const codeNodeSibling = codeNode.getPreviousSibling();
29631          if (codeNodeSibling === null) {
29632            codeNode.selectPrevious();
29633            event.preventDefault();
29634            return true;
29635          }
29636        } else if (!arrowIsUp && anchorOffset === anchorNode.getTextContentSize() && anchorNode.getNextSibling() === null) {
29637          const codeNodeSibling = codeNode.getNextSibling();
29638          if (codeNodeSibling === null) {
29639            codeNode.selectNext();
29640            event.preventDefault();
29641            return true;
29642          }
29643        }
29644      }
29645      return false;
29646    }
29647    let start3;
29648    let end;
29649    if (anchorNode.isBefore(focusNode)) {
29650      start3 = $getFirstCodeNodeOfLine2(anchorNode);
29651      end = $getLastCodeNodeOfLine2(focusNode);
29652    } else {
29653      start3 = $getFirstCodeNodeOfLine2(focusNode);
29654      end = $getLastCodeNodeOfLine2(anchorNode);
29655    }
29656    if (start3 == null || end == null) {
29657      return false;
29658    }
29659    const range2 = start3.getNodesBetween(end);
29660    for (let i2 = 0; i2 < range2.length; i2++) {
29661      const node = range2[i2];
29662      if (!$isCodeHighlightNode2(node) && !$isTabNode2(node) && !$isLineBreakNode2(node)) {
29663        return false;
29664      }
29665    }
29666    event.preventDefault();
29667    event.stopPropagation();
29668    const linebreak = arrowIsUp ? start3.getPreviousSibling() : end.getNextSibling();
29669    if (!$isLineBreakNode2(linebreak)) {
29670      return true;
29671    }
29672    const sibling = arrowIsUp ? linebreak.getPreviousSibling() : linebreak.getNextSibling();
29673    if (sibling == null) {
29674      return true;
29675    }
29676    const maybeInsertionPoint = $isCodeHighlightNode2(sibling) || $isTabNode2(sibling) || $isLineBreakNode2(sibling) ? arrowIsUp ? $getFirstCodeNodeOfLine2(sibling) : $getLastCodeNodeOfLine2(sibling) : null;
29677    let insertionPoint = maybeInsertionPoint != null ? maybeInsertionPoint : sibling;
29678    linebreak.remove();
29679    range2.forEach((node) => node.remove());
29680    if (type === KEY_ARROW_UP_COMMAND2) {
29681      range2.forEach((node) => insertionPoint.insertBefore(node));
29682      insertionPoint.insertBefore(linebreak);
29683    } else {
29684      insertionPoint.insertAfter(linebreak);
29685      insertionPoint = linebreak;
29686      range2.forEach((node) => {
29687        insertionPoint.insertAfter(node);
29688        insertionPoint = node;
29689      });
29690    }
29691    selection.setTextNodeRange(anchorNode, anchorOffset, focusNode, focusOffset);
29692    return true;
29693  }
29694  function $handleMoveTo(type, event) {
29695    const selection = $getSelection2();
29696    if (!$isRangeSelection2(selection)) {
29697      return false;
29698    }
29699    const {
29700      anchor,
29701      focus
29702    } = selection;
29703    const anchorNode = anchor.getNode();
29704    const focusNode = focus.getNode();
29705    const isMoveToStart2 = type === MOVE_TO_START2;
29706    if (!$isSelectionInCode(selection) || !($isCodeHighlightNode2(anchorNode) || $isTabNode2(anchorNode)) || !($isCodeHighlightNode2(focusNode) || $isTabNode2(focusNode))) {
29707      return false;
29708    }
29709    const focusLineNode = focusNode;
29710    const direction = $getCodeLineDirection2(focusLineNode);
29711    const moveToStart = direction === "rtl" ? !isMoveToStart2 : isMoveToStart2;
29712    if (moveToStart) {
29713      const start3 = $getStartOfCodeInLine2(focusLineNode, focus.offset);
29714      if (start3 !== null) {
29715        const {
29716          node,
29717          offset: offset3
29718        } = start3;
29719        if ($isLineBreakNode2(node)) {
29720          node.selectNext(0, 0);
29721        } else {
29722          selection.setTextNodeRange(node, offset3, node, offset3);
29723        }
29724      } else {
29725        focusLineNode.getParentOrThrow().selectStart();
29726      }
29727    } else {
29728      const node = $getEndOfCodeInLine2(focusLineNode);
29729      node.select();
29730    }
29731    event.preventDefault();
29732    event.stopPropagation();
29733    return true;
29734  }
29735  function registerCodeHighlighting(editor, tokenizer) {
29736    if (!editor.hasNodes([CodeNode2, CodeHighlightNode2])) {
29737      throw new Error("CodeHighlightPlugin: CodeNode or CodeHighlightNode not registered on editor");
29738    }
29739    if (tokenizer == null) {
29740      tokenizer = PrismTokenizer;
29741    }
29742    const registrations = [];
29743    if (editor._headless !== true) {
29744      registrations.push(editor.registerMutationListener(CodeNode2, (mutations) => {
29745        editor.getEditorState().read(() => {
29746          for (const [key, type] of mutations) {
29747            if (type !== "destroyed") {
29748              const node = $getNodeByKey2(key);
29749              if (node !== null) {
29750                updateCodeGutter(node, editor);
29751              }
29752            }
29753          }
29754        });
29755      }, {
29756        skipInitialization: false
29757      }));
29758    }
29759    const transformState = {
29760      didTransform: false,
29761      nodesCurrentlyHighlighting: /* @__PURE__ */ new Set()
29762    };
29763    registrations.push(editor.registerNodeTransform(CodeNode2, $codeNodeTransform.bind(null, editor, tokenizer, transformState)), editor.registerNodeTransform(TextNode2, $textNodeTransform.bind(null, editor, tokenizer, transformState)), editor.registerNodeTransform(CodeHighlightNode2, $textNodeTransform.bind(null, editor, tokenizer, transformState)), editor.registerCommand(KEY_TAB_COMMAND2, (event) => {
29764      const command = $handleTab(event.shiftKey);
29765      if (command === null) {
29766        return false;
29767      }
29768      event.preventDefault();
29769      editor.dispatchCommand(command, void 0);
29770      return true;
29771    }, COMMAND_PRIORITY_LOW2), editor.registerCommand(INSERT_TAB_COMMAND2, () => {
29772      const selection = $getSelection2();
29773      if (!$isSelectionInCode(selection)) {
29774        return false;
29775      }
29776      $insertNodes2([$createTabNode2()]);
29777      return true;
29778    }, COMMAND_PRIORITY_LOW2), editor.registerCommand(INDENT_CONTENT_COMMAND2, (payload) => $handleMultilineIndent(INDENT_CONTENT_COMMAND2), COMMAND_PRIORITY_LOW2), editor.registerCommand(OUTDENT_CONTENT_COMMAND2, (payload) => $handleMultilineIndent(OUTDENT_CONTENT_COMMAND2), COMMAND_PRIORITY_LOW2), editor.registerCommand(KEY_ARROW_UP_COMMAND2, (event) => {
29779      const selection = $getSelection2();
29780      if (!$isRangeSelection2(selection) || !$isSelectionInCode(selection)) {
29781        return false;
29782      }
29783      const firstNode = $getRoot2().getFirstDescendant();
29784      const {
29785        anchor
29786      } = selection;
29787      const anchorNode = anchor.getNode();
29788      if (firstNode && anchorNode && firstNode.getKey() === anchorNode.getKey()) {
29789        return false;
29790      }
29791      return $handleShiftLines(KEY_ARROW_UP_COMMAND2, event);
29792    }, COMMAND_PRIORITY_LOW2), editor.registerCommand(KEY_ARROW_DOWN_COMMAND2, (event) => {
29793      const selection = $getSelection2();
29794      if (!$isRangeSelection2(selection) || !$isSelectionInCode(selection)) {
29795        return false;
29796      }
29797      const lastNode = $getRoot2().getLastDescendant();
29798      const {
29799        anchor
29800      } = selection;
29801      const anchorNode = anchor.getNode();
29802      if (lastNode && anchorNode && lastNode.getKey() === anchorNode.getKey()) {
29803        return false;
29804      }
29805      return $handleShiftLines(KEY_ARROW_DOWN_COMMAND2, event);
29806    }, COMMAND_PRIORITY_LOW2), editor.registerCommand(MOVE_TO_START2, (event) => $handleMoveTo(MOVE_TO_START2, event), COMMAND_PRIORITY_LOW2), editor.registerCommand(MOVE_TO_END2, (event) => $handleMoveTo(MOVE_TO_END2, event), COMMAND_PRIORITY_LOW2));
29807    return mergeRegister2(...registrations);
29808  }
29809  var CodePrismExtension = defineExtension2({
29810    build: (editor, config) => namedSignals2(config),
29811    config: safeCast2({
29812      disabled: false,
29813      tokenizer: PrismTokenizer
29814    }),
29815    dependencies: [CodeExtension2],
29816    name: "@lexical/code-prism",
29817    register: (editor, config, state) => {
29818      const stores = state.getOutput();
29819      return effect(() => {
29820        if (stores.disabled.value) {
29821          return;
29822        }
29823        return registerCodeHighlighting(editor, stores.tokenizer.value);
29824      });
29825    }
29826  });
29827
29828  
vendor: 15,907 bytes, lines 29828-30122
29828// node_modules/@lexical/code-prism/LexicalCodePrism.prod.mjs
29829  var import_prismjs3 = __toESM(require_prism(), 1);
29830  function J(e2, ...t2) {
29831    const n2 = new URL("https://lexical.dev/docs/error"), r2 = new URLSearchParams();
29832    r2.append("code", e2);
29833    for (const e3 of t2) r2.append("v", e3);
29834    throw n2.search = r2.toString(), Error(`Minified Lexical error #${e2}; visit ${n2.toString()} for the full message or use the non-minified dev environment for full errors and additional helpful warnings.`);
29835  }
29836  !function(e2) {
29837    e2.languages.diff = { coord: [/^(?:\*{3}|-{3}|\+{3}).*$/m, /^@@.*@@$/m, /^\d.*$/m] };
29838    var t2 = { "deleted-sign": "-", "deleted-arrow": "<", "inserted-sign": "+", "inserted-arrow": ">", unchanged: " ", diff: "!" };
29839    Object.keys(t2).forEach(function(n2) {
29840      var r2 = t2[n2], o2 = [];
29841      /^\w+$/.test(n2) || o2.push(/\w+/.exec(n2)[0]), "diff" === n2 && o2.push("bold"), e2.languages.diff[n2] = { pattern: RegExp("^(?:[" + r2 + "].*(?:\r\n?|\n|(?![\\s\\S])))+", "m"), alias: o2, inside: { line: { pattern: /(.)(?=[\s\S]).*(?:\r\n?|\n)?/, lookbehind: true }, prefix: { pattern: /[\s\S]/, alias: /\w+/.exec(n2)[0] } } };
29842    }), Object.defineProperty(e2.languages.diff, "PREFIXES", { value: t2 });
29843  }(Prism);
29844  var U = globalThis.Prism || window.Prism;
29845  function te(e2) {
29846    const t2 = function(e3) {
29847      const t3 = /^diff-([\w-]+)/i.exec(e3);
29848      return t3 ? t3[1] : null;
29849    }(e2), n2 = t2 || e2;
29850    try {
29851      return !!n2 && U.languages.hasOwnProperty(n2);
29852    } catch (e3) {
29853      return false;
29854    }
29855  }
29856  async function ne(e2, t2, n2) {
29857  }
29858  function re(e2) {
29859    return "string" == typeof e2 ? e2 : Array.isArray(e2) ? e2.map(re).join("") : re(e2.content);
29860  }
29861  function oe(e2, t2) {
29862    const n2 = /^diff-([\w-]+)/i.exec(t2), r2 = e2.getTextContent();
29863    let o2 = U.tokenize(r2, U.languages[n2 ? "diff" : t2]);
29864    return n2 && (o2 = function(e3, t3) {
29865      const n3 = t3, r3 = U.languages[n3], o3 = { tokens: e3 }, s2 = U.languages.diff.PREFIXES;
29866      for (const e4 of o3.tokens) {
29867        if ("string" == typeof e4 || !(e4.type in s2) || !Array.isArray(e4.content)) continue;
29868        const t4 = e4.type;
29869        let n4 = 0;
29870        const o4 = () => (n4++, new U.Token("prefix", s2[t4], t4.replace(/^(\w+).*/, "$1"))), i2 = e4.content.filter((e5) => "string" == typeof e5 || "prefix" !== e5.type), c2 = e4.content.length - i2.length, l4 = U.tokenize(re(i2), r3);
29871        l4.unshift(o4());
29872        const a2 = /\r\n|\n/g, f = (e5) => {
29873          const t5 = [];
29874          a2.lastIndex = 0;
29875          let r4, s3 = 0;
29876          for (; n4 < c2 && (r4 = a2.exec(e5)); ) {
29877            const n5 = r4.index + r4[0].length;
29878            t5.push(e5.slice(s3, n5)), s3 = n5, t5.push(o4());
29879          }
29880          if (0 !== t5.length) return s3 < e5.length && t5.push(e5.slice(s3)), t5;
29881        }, u2 = (e5) => {
29882          for (let t5 = 0; t5 < e5.length && n4 < c2; t5++) {
29883            const n5 = e5[t5];
29884            if ("string" == typeof n5) {
29885              const r4 = f(n5);
29886              r4 && (e5.splice(t5, 1, ...r4), t5 += r4.length - 1);
29887            } else if ("string" == typeof n5.content) {
29888              const e6 = f(n5.content);
29889              e6 && (n5.content = e6);
29890            } else Array.isArray(n5.content) ? u2(n5.content) : u2([n5.content]);
29891          }
29892        };
29893        u2(l4), n4 < c2 && l4.push(o4()), e4.content = l4;
29894      }
29895      return o3.tokens;
29896    }(o2, n2[1])), se(o2);
29897  }
29898  function se(t2, n2) {
29899    const r2 = [];
29900    for (const o2 of t2) if ("string" == typeof o2) {
29901      const t3 = o2.split(/(\n|\t)/), s2 = t3.length;
29902      for (let o3 = 0; o3 < s2; o3++) {
29903        const s3 = t3[o3];
29904        "\n" === s3 || "\r\n" === s3 ? r2.push($createLineBreakNode2()) : "	" === s3 ? r2.push($createTabNode2()) : s3.length > 0 && r2.push($createCodeHighlightNode2(s3, n2));
29905      }
29906    } else {
29907      const { content: e2, alias: t3 } = o2;
29908      "string" == typeof e2 ? r2.push(...se([e2], "prefix" === o2.type && "string" == typeof t3 ? t3 : o2.type)) : Array.isArray(e2) && r2.push(...se(e2, "unchanged" === o2.type ? void 0 : o2.type));
29909    }
29910    return r2;
29911  }
29912  var ie = { $tokenize(e2, t2) {
29913    return oe(e2, t2 || this.defaultLanguage);
29914  }, defaultLanguage: DEFAULT_CODE_LANGUAGE2, tokenize(e2, t2) {
29915    return U.tokenize(e2, U.languages[t2 || ""] || U.languages[this.defaultLanguage]);
29916  } };
29917  function ce(e2, t2, o2, s2) {
29918    const i2 = s2.getParent();
29919    $isCodeNode2(i2) ? ae(e2, t2, o2, i2) : $isCodeHighlightNode2(s2) && s2.replace($createTextNode2(s2.__text));
29920  }
29921  function le(e2, t2) {
29922    const n2 = t2.getElementByKey(e2.getKey());
29923    if (null === n2) return;
29924    const r2 = e2.getChildren(), o2 = r2.length;
29925    if (o2 === n2.__cachedChildrenLength) return;
29926    n2.__cachedChildrenLength = o2;
29927    let s2 = "1", i2 = 1;
29928    for (let e3 = 0; e3 < o2; e3++) $isLineBreakNode2(r2[e3]) && (s2 += "\n" + ++i2);
29929    n2.setAttribute("data-gutter", s2);
29930  }
29931  function ae(e2, t2, r2, o2) {
29932    const { nodesCurrentlyHighlighting: s2 } = r2, i2 = o2.getKey();
29933    void 0 === o2.getLanguage() && o2.setLanguage(t2.defaultLanguage);
29934    const c2 = o2.getLanguage() || t2.defaultLanguage;
29935    if (!te(c2)) return o2.getIsSyntaxHighlightSupported() && o2.setIsSyntaxHighlightSupported(false), void ne();
29936    o2.getIsSyntaxHighlightSupported() || o2.setIsSyntaxHighlightSupported(true), s2.has(i2) || (s2.add(i2), r2.didTransform || (r2.didTransform = true, $onUpdate2(() => {
29937      r2.didTransform = false, s2.clear();
29938    })), function(e3, t3) {
29939      const r3 = $getNodeByKey2(e3);
29940      if (!$isCodeNode2(r3) || !r3.isAttached()) return;
29941      const o3 = $getSelection2();
29942      if (!$isRangeSelection2(o3)) return void t3();
29943      const s3 = o3.anchor, i3 = s3.offset, c3 = "element" === s3.type && $isLineBreakNode2(r3.getChildAtIndex(s3.offset - 1));
29944      let l4 = 0;
29945      if (!c3) {
29946        const e4 = s3.getNode();
29947        l4 = i3 + e4.getPreviousSiblings().reduce((e5, t4) => e5 + t4.getTextContentSize(), 0);
29948      }
29949      if (!t3()) return;
29950      if (c3) return void s3.getNode().select(i3, i3);
29951      r3.getChildren().some((e4) => {
29952        const t4 = $isTextNode2(e4);
29953        if (t4 || $isLineBreakNode2(e4)) {
29954          const n2 = e4.getTextContentSize();
29955          if (t4 && n2 >= l4) return e4.select(l4, l4), true;
29956          l4 -= n2;
29957        }
29958        return false;
29959      });
29960    }(i2, () => {
29961      const e3 = $getNodeByKey2(i2);
29962      if (!$isCodeNode2(e3) || !e3.isAttached()) return false;
29963      const r3 = e3.getLanguage() || t2.defaultLanguage, s3 = t2.$tokenize(e3, r3), c3 = function(e4, t3) {
29964        let n2 = 0;
29965        for (; n2 < e4.length && fe(e4[n2], t3[n2]); ) n2++;
29966        const r4 = e4.length, o3 = t3.length, s4 = Math.min(r4, o3) - n2;
29967        let i3 = 0;
29968        for (; i3 < s4; ) if (i3++, !fe(e4[r4 - i3], t3[o3 - i3])) {
29969          i3--;
29970          break;
29971        }
29972        const c4 = n2, l5 = r4 - i3, a3 = t3.slice(n2, o3 - i3);
29973        return { from: c4, nodesForReplacement: a3, to: l5 };
29974      }(e3.getChildren(), s3), { from: l4, to: a2, nodesForReplacement: f } = c3;
29975      return !(l4 === a2 && !f.length) && (o2.splice(l4, a2 - l4, f), true);
29976    }));
29977  }
29978  function fe(e2, t2) {
29979    return $isCodeHighlightNode2(e2) && $isCodeHighlightNode2(t2) && e2.__text === t2.__text && e2.__highlightType === t2.__highlightType || $isTabNode2(e2) && $isTabNode2(t2) || $isLineBreakNode2(e2) && $isLineBreakNode2(t2);
29980  }
29981  function ue(e2) {
29982    if (!$isRangeSelection2(e2)) return false;
29983    const t2 = e2.anchor.getNode(), r2 = $isCodeNode2(t2) ? t2 : t2.getParent(), o2 = e2.focus.getNode(), s2 = $isCodeNode2(o2) ? o2 : o2.getParent();
29984    return $isCodeNode2(r2) && r2.is(s2);
29985  }
29986  function ge(e2) {
29987    const t2 = e2.getNodes(), o2 = [];
29988    if (1 === t2.length && $isCodeNode2(t2[0])) return o2;
29989    let s2 = [];
29990    for (let e3 = 0; e3 < t2.length; e3++) {
29991      const n2 = t2[e3];
29992      $isCodeHighlightNode2(n2) || $isTabNode2(n2) || $isLineBreakNode2(n2) || J(169), $isLineBreakNode2(n2) ? s2.length > 0 && (o2.push(s2), s2 = []) : s2.push(n2);
29993    }
29994    if (s2.length > 0) {
29995      const t3 = e2.isBackward() ? e2.anchor : e2.focus, n2 = $createPoint2(s2[0].getKey(), 0, "text");
29996      t3.is(n2) || o2.push(s2);
29997    }
29998    return o2;
29999  }
30000  function pe(e2) {
30001    const t2 = $getSelection2();
30002    if (!$isRangeSelection2(t2) || !ue(t2)) return false;
30003    const n2 = ge(t2), r2 = n2.length;
30004    if (0 === r2 && t2.isCollapsed()) return e2 === INDENT_CONTENT_COMMAND2 && t2.insertNodes([$createTabNode2()]), true;
30005    if (0 === r2 && e2 === INDENT_CONTENT_COMMAND2 && "\n" === t2.getTextContent()) {
30006      const e3 = $createTabNode2(), n3 = $createLineBreakNode2(), r3 = t2.isBackward() ? "previous" : "next";
30007      return t2.insertNodes([e3, n3]), $setSelectionFromCaretRange2($getCaretRangeInDirection2($getCaretRange2($getTextPointCaret2(e3, "next", 0), $normalizeCaret2($getSiblingCaret2(n3, "next"))), r3)), true;
30008    }
30009    for (let s2 = 0; s2 < r2; s2++) {
30010      const r3 = n2[s2];
30011      if (r3.length > 0) {
30012        let n3 = r3[0];
30013        if (0 === s2 && (n3 = $getFirstCodeNodeOfLine2(n3)), e2 === INDENT_CONTENT_COMMAND2) {
30014          const e3 = $createTabNode2();
30015          if (n3.insertBefore(e3), 0 === s2) {
30016            const r4 = t2.isBackward() ? "focus" : "anchor", o2 = $createPoint2(n3.getKey(), 0, "text");
30017            t2[r4].is(o2) && t2[r4].set(e3.getKey(), 0, "text");
30018          }
30019        } else $isTabNode2(n3) && n3.remove();
30020      }
30021    }
30022    return true;
30023  }
30024  function de(e2, t2) {
30025    const n2 = $getSelection2();
30026    if (!$isRangeSelection2(n2)) return false;
30027    const { anchor: i2, focus: c2 } = n2, l4 = i2.offset, a2 = c2.offset, f = i2.getNode(), u2 = c2.getNode(), g2 = e2 === KEY_ARROW_UP_COMMAND2;
30028    if (!ue(n2) || !$isCodeHighlightNode2(f) && !$isTabNode2(f) || !$isCodeHighlightNode2(u2) && !$isTabNode2(u2)) return false;
30029    if (!t2.altKey) {
30030      if (n2.isCollapsed()) {
30031        const e3 = f.getParentOrThrow();
30032        if (g2 && 0 === l4 && null === f.getPreviousSibling()) {
30033          if (null === e3.getPreviousSibling()) return e3.selectPrevious(), t2.preventDefault(), true;
30034        } else if (!g2 && l4 === f.getTextContentSize() && null === f.getNextSibling()) {
30035          if (null === e3.getNextSibling()) return e3.selectNext(), t2.preventDefault(), true;
30036        }
30037      }
30038      return false;
30039    }
30040    let p2, d3;
30041    if (f.isBefore(u2) ? (p2 = $getFirstCodeNodeOfLine2(f), d3 = $getLastCodeNodeOfLine2(u2)) : (p2 = $getFirstCodeNodeOfLine2(u2), d3 = $getLastCodeNodeOfLine2(f)), null == p2 || null == d3) return false;
30042    const m3 = p2.getNodesBetween(d3);
30043    for (let e3 = 0; e3 < m3.length; e3++) {
30044      const t3 = m3[e3];
30045      if (!$isCodeHighlightNode2(t3) && !$isTabNode2(t3) && !$isLineBreakNode2(t3)) return false;
30046    }
30047    t2.preventDefault(), t2.stopPropagation();
30048    const h2 = g2 ? p2.getPreviousSibling() : d3.getNextSibling();
30049    if (!$isLineBreakNode2(h2)) return true;
30050    const x3 = g2 ? h2.getPreviousSibling() : h2.getNextSibling();
30051    if (null == x3) return true;
30052    const j3 = $isCodeHighlightNode2(x3) || $isTabNode2(x3) || $isLineBreakNode2(x3) ? g2 ? $getFirstCodeNodeOfLine2(x3) : $getLastCodeNodeOfLine2(x3) : null;
30053    let w3 = null != j3 ? j3 : x3;
30054    return h2.remove(), m3.forEach((e3) => e3.remove()), e2 === KEY_ARROW_UP_COMMAND2 ? (m3.forEach((e3) => w3.insertBefore(e3)), w3.insertBefore(h2)) : (w3.insertAfter(h2), w3 = h2, m3.forEach((e3) => {
30055      w3.insertAfter(e3), w3 = e3;
30056    })), n2.setTextNodeRange(f, l4, u2, a2), true;
30057  }
30058  function me(e2, t2) {
30059    const n2 = $getSelection2();
30060    if (!$isRangeSelection2(n2)) return false;
30061    const { anchor: o2, focus: s2 } = n2, a2 = o2.getNode(), f = s2.getNode(), u2 = e2 === MOVE_TO_START2;
30062    if (!ue(n2) || !$isCodeHighlightNode2(a2) && !$isTabNode2(a2) || !$isCodeHighlightNode2(f) && !$isTabNode2(f)) return false;
30063    const g2 = f;
30064    if ("rtl" === $getCodeLineDirection2(g2) ? !u2 : u2) {
30065      const e3 = $getStartOfCodeInLine2(g2, s2.offset);
30066      if (null !== e3) {
30067        const { node: t3, offset: r2 } = e3;
30068        $isLineBreakNode2(t3) ? t3.selectNext(0, 0) : n2.setTextNodeRange(t3, r2, t3, r2);
30069      } else g2.getParentOrThrow().selectStart();
30070    } else {
30071      $getEndOfCodeInLine2(g2).select();
30072    }
30073    return t2.preventDefault(), t2.stopPropagation(), true;
30074  }
30075  function he(e2, t2) {
30076    if (!e2.hasNodes([CodeNode2, CodeHighlightNode2])) throw new Error("CodeHighlightPlugin: CodeNode or CodeHighlightNode not registered on editor");
30077    null == t2 && (t2 = ie);
30078    const n2 = [];
30079    true !== e2._headless && n2.push(e2.registerMutationListener(CodeNode2, (t3) => {
30080      e2.getEditorState().read(() => {
30081        for (const [n3, r3] of t3) if ("destroyed" !== r3) {
30082          const t4 = $getNodeByKey2(n3);
30083          null !== t4 && le(t4, e2);
30084        }
30085      });
30086    }, { skipInitialization: false }));
30087    const r2 = { didTransform: false, nodesCurrentlyHighlighting: /* @__PURE__ */ new Set() };
30088    return n2.push(e2.registerNodeTransform(CodeNode2, ae.bind(null, e2, t2, r2)), e2.registerNodeTransform(TextNode2, ce.bind(null, e2, t2, r2)), e2.registerNodeTransform(CodeHighlightNode2, ce.bind(null, e2, t2, r2)), e2.registerCommand(KEY_TAB_COMMAND2, (t3) => {
30089      const n3 = function(e3) {
30090        const t4 = $getSelection2();
30091        if (!$isRangeSelection2(t4) || !ue(t4)) return null;
30092        const n4 = e3 ? OUTDENT_CONTENT_COMMAND2 : INDENT_CONTENT_COMMAND2, r3 = e3 ? OUTDENT_CONTENT_COMMAND2 : INSERT_TAB_COMMAND2, i2 = t4.anchor, c2 = t4.focus;
30093        if (i2.is(c2)) return r3;
30094        const l4 = ge(t4);
30095        if (1 !== l4.length) return n4;
30096        const a2 = l4[0];
30097        let f, u2;
30098        0 === a2.length && J(285), t4.isBackward() ? (f = c2, u2 = i2) : (f = i2, u2 = c2);
30099        const g2 = $getFirstCodeNodeOfLine2(a2[0]), p2 = $getLastCodeNodeOfLine2(a2[0]), d3 = $createPoint2(g2.getKey(), 0, "text"), m3 = $createPoint2(p2.getKey(), p2.getTextContentSize(), "text");
30100        return f.isBefore(d3) || m3.isBefore(u2) ? n4 : d3.isBefore(f) || u2.isBefore(m3) ? r3 : n4;
30101      }(t3.shiftKey);
30102      return null !== n3 && (t3.preventDefault(), e2.dispatchCommand(n3, void 0), true);
30103    }, COMMAND_PRIORITY_LOW2), e2.registerCommand(INSERT_TAB_COMMAND2, () => !!ue($getSelection2()) && ($insertNodes2([$createTabNode2()]), true), COMMAND_PRIORITY_LOW2), e2.registerCommand(INDENT_CONTENT_COMMAND2, (e3) => pe(INDENT_CONTENT_COMMAND2), COMMAND_PRIORITY_LOW2), e2.registerCommand(OUTDENT_CONTENT_COMMAND2, (e3) => pe(OUTDENT_CONTENT_COMMAND2), COMMAND_PRIORITY_LOW2), e2.registerCommand(KEY_ARROW_UP_COMMAND2, (e3) => {
30104      const t3 = $getSelection2();
30105      if (!$isRangeSelection2(t3) || !ue(t3)) return false;
30106      const n3 = $getRoot2().getFirstDescendant(), { anchor: r3 } = t3, o2 = r3.getNode();
30107      return (!n3 || !o2 || n3.getKey() !== o2.getKey()) && de(KEY_ARROW_UP_COMMAND2, e3);
30108    }, COMMAND_PRIORITY_LOW2), e2.registerCommand(KEY_ARROW_DOWN_COMMAND2, (e3) => {
30109      const t3 = $getSelection2();
30110      if (!$isRangeSelection2(t3) || !ue(t3)) return false;
30111      const n3 = $getRoot2().getLastDescendant(), { anchor: r3 } = t3, o2 = r3.getNode();
30112      return (!n3 || !o2 || n3.getKey() !== o2.getKey()) && de(KEY_ARROW_DOWN_COMMAND2, e3);
30113    }, COMMAND_PRIORITY_LOW2), e2.registerCommand(MOVE_TO_START2, (e3) => me(MOVE_TO_START2, e3), COMMAND_PRIORITY_LOW2), e2.registerCommand(MOVE_TO_END2, (e3) => me(MOVE_TO_END2, e3), COMMAND_PRIORITY_LOW2)), mergeRegister2(...n2);
30114  }
30115  var ye = defineExtension2({ build: (e2, t2) => namedSignals2(t2), config: safeCast2({ disabled: false, tokenizer: ie }), dependencies: [CodeExtension2], name: "@lexical/code-prism", register: (e2, t2, n2) => {
30116    const r2 = n2.getOutput();
30117    return effect(() => {
30118      if (!r2.disabled.value) return he(e2, r2.tokenizer.value);
30119    });
30120  } });
30121
30122  
vendor: 841 bytes, lines 30122-30137
30122// node_modules/@lexical/code-prism/LexicalCodePrism.mjs
30123  var mod14 = true ? LexicalCodePrism_dev_exports : LexicalCodePrism_prod_exports;
30124  var CODE_LANGUAGE_FRIENDLY_NAME_MAP2 = mod14.CODE_LANGUAGE_FRIENDLY_NAME_MAP;
30125  var CODE_LANGUAGE_MAP2 = mod14.CODE_LANGUAGE_MAP;
30126  var CodePrismExtension2 = mod14.CodePrismExtension;
30127  var PrismTokenizer2 = mod14.PrismTokenizer;
30128  var getCodeLanguageOptions2 = mod14.getCodeLanguageOptions;
30129  var getCodeLanguages2 = mod14.getCodeLanguages;
30130  var getCodeThemeOptions2 = mod14.getCodeThemeOptions;
30131  var getLanguageFriendlyName2 = mod14.getLanguageFriendlyName;
30132  var isCodeLanguageLoaded2 = mod14.isCodeLanguageLoaded;
30133  var loadCodeLanguage2 = mod14.loadCodeLanguage;
30134  var normalizeCodeLanguage2 = mod14.normalizeCodeLanguage;
30135  var registerCodeHighlighting2 = mod14.registerCodeHighlighting;
30136
30137  
vendor: 594 bytes, lines 30137-30149
30137// node_modules/@lexical/code/LexicalCode.dev.mjs
30138  var CODE_LANGUAGE_FRIENDLY_NAME_MAP3 = CODE_LANGUAGE_FRIENDLY_NAME_MAP2;
30139  var CODE_LANGUAGE_MAP3 = CODE_LANGUAGE_MAP2;
30140  var getCodeLanguageOptions3 = getCodeLanguageOptions2;
30141  var getCodeLanguages3 = getCodeLanguages2;
30142  var getCodeThemeOptions3 = getCodeThemeOptions2;
30143  var getLanguageFriendlyName3 = getLanguageFriendlyName2;
30144  var normalizeCodeLang = normalizeCodeLanguage2;
30145  var normalizeCodeLanguage3 = normalizeCodeLanguage2;
30146  var PrismTokenizer3 = PrismTokenizer2;
30147  var registerCodeHighlighting3 = registerCodeHighlighting2;
30148
30149  
vendor: 1,476 bytes, lines 30149-30176
30149// node_modules/@lexical/code/LexicalCode.mjs
30150  var mod15 = true ? LexicalCode_dev_exports : LexicalCode_prod_exports;
30151  var $createCodeHighlightNode3 = mod15.$createCodeHighlightNode;
30152  var $createCodeNode3 = mod15.$createCodeNode;
30153  var $getCodeLineDirection3 = mod15.$getCodeLineDirection;
30154  var $getEndOfCodeInLine3 = mod15.$getEndOfCodeInLine;
30155  var $getFirstCodeNodeOfLine3 = mod15.$getFirstCodeNodeOfLine;
30156  var $getLastCodeNodeOfLine3 = mod15.$getLastCodeNodeOfLine;
30157  var $getStartOfCodeInLine3 = mod15.$getStartOfCodeInLine;
30158  var $isCodeHighlightNode3 = mod15.$isCodeHighlightNode;
30159  var $isCodeNode3 = mod15.$isCodeNode;
30160  var CODE_LANGUAGE_FRIENDLY_NAME_MAP4 = mod15.CODE_LANGUAGE_FRIENDLY_NAME_MAP;
30161  var CODE_LANGUAGE_MAP4 = mod15.CODE_LANGUAGE_MAP;
30162  var CodeExtension3 = mod15.CodeExtension;
30163  var CodeHighlightNode3 = mod15.CodeHighlightNode;
30164  var CodeNode3 = mod15.CodeNode;
30165  var DEFAULT_CODE_LANGUAGE3 = mod15.DEFAULT_CODE_LANGUAGE;
30166  var PrismTokenizer4 = mod15.PrismTokenizer;
30167  var getCodeLanguageOptions4 = mod15.getCodeLanguageOptions;
30168  var getCodeLanguages4 = mod15.getCodeLanguages;
30169  var getCodeThemeOptions4 = mod15.getCodeThemeOptions;
30170  var getDefaultCodeLanguage3 = mod15.getDefaultCodeLanguage;
30171  var getLanguageFriendlyName4 = mod15.getLanguageFriendlyName;
30172  var normalizeCodeLang2 = mod15.normalizeCodeLang;
30173  var normalizeCodeLanguage4 = mod15.normalizeCodeLanguage;
30174  var registerCodeHighlighting4 = mod15.registerCodeHighlighting;
30175
30176  
vendor: 57,908 bytes, lines 30176-31670
30176// node_modules/@lexical/markdown/LexicalMarkdown.dev.mjs
30177  var LexicalMarkdown_dev_exports = {};
30178  __export(LexicalMarkdown_dev_exports, {
30179    $convertFromMarkdownString: () => $convertFromMarkdownString,
30180    $convertToMarkdownString: () => $convertToMarkdownString,
30181    BOLD_ITALIC_STAR: () => BOLD_ITALIC_STAR,
30182    BOLD_ITALIC_UNDERSCORE: () => BOLD_ITALIC_UNDERSCORE,
30183    BOLD_STAR: () => BOLD_STAR,
30184    BOLD_UNDERSCORE: () => BOLD_UNDERSCORE,
30185    CHECK_LIST: () => CHECK_LIST,
30186    CODE: () => CODE,
30187    ELEMENT_TRANSFORMERS: () => ELEMENT_TRANSFORMERS,
30188    HEADING: () => HEADING,
30189    HIGHLIGHT: () => HIGHLIGHT,
30190    INLINE_CODE: () => INLINE_CODE,
30191    ITALIC_STAR: () => ITALIC_STAR,
30192    ITALIC_UNDERSCORE: () => ITALIC_UNDERSCORE,
30193    LINK: () => LINK,
30194    MULTILINE_ELEMENT_TRANSFORMERS: () => MULTILINE_ELEMENT_TRANSFORMERS,
30195    ORDERED_LIST: () => ORDERED_LIST,
30196    QUOTE: () => QUOTE,
30197    STRIKETHROUGH: () => STRIKETHROUGH,
30198    TEXT_FORMAT_TRANSFORMERS: () => TEXT_FORMAT_TRANSFORMERS,
30199    TEXT_MATCH_TRANSFORMERS: () => TEXT_MATCH_TRANSFORMERS,
30200    TRANSFORMERS: () => TRANSFORMERS,
30201    UNORDERED_LIST: () => UNORDERED_LIST,
30202    registerMarkdownShortcuts: () => registerMarkdownShortcuts
30203  });
30204  function indexBy(list, callback) {
30205    const index = {};
30206    for (const item of list) {
30207      const key = callback(item);
30208      if (!key) {
30209        continue;
30210      }
30211      if (index[key]) {
30212        index[key].push(item);
30213      } else {
30214        index[key] = [item];
30215      }
30216    }
30217    return index;
30218  }
30219  function transformersByType(transformers) {
30220    const byType = indexBy(transformers, (t2) => t2.type);
30221    return {
30222      element: byType.element || [],
30223      multilineElement: byType["multiline-element"] || [],
30224      textFormat: byType["text-format"] || [],
30225      textMatch: byType["text-match"] || []
30226    };
30227  }
30228  var PUNCTUATION_OR_SPACE2 = /[!-/:-@[-`{-~\s]/;
30229  var WHITESPACE = /[ \t\n\r\f]/;
30230  var PUNCTUATION = /[!"#$%&'()*+,\-./:;<=>?@[\]^_`{|}~]/;
30231  var MARKDOWN_EMPTY_LINE_REG_EXP = /^\s{0,3}$/;
30232  function isEmptyParagraph(node) {
30233    if (!$isParagraphNode2(node)) {
30234      return false;
30235    }
30236    const firstChild = node.getFirstChild();
30237    return firstChild == null || node.getChildrenSize() === 1 && $isTextNode2(firstChild) && MARKDOWN_EMPTY_LINE_REG_EXP.test(firstChild.getTextContent());
30238  }
30239  function unescapeText(value) {
30240    return value.replace(/\\([!-/:-@[-`{-~])/g, "$1").replace(/&#(\d+);/g, (_3, codePoint) => String.fromCodePoint(Number(codePoint)));
30241  }
30242  function createMarkdownExport(transformers, shouldPreserveNewLines = false) {
30243    const byType = transformersByType(transformers);
30244    const elementTransformers = [...byType.multilineElement, ...byType.element];
30245    const isNewlineDelimited = !shouldPreserveNewLines;
30246    const textFormatTransformers = byType.textFormat.filter((transformer) => transformer.format.length === 1).sort((a2, b3) => {
30247      return Number(a2.format.includes("code")) - Number(b3.format.includes("code"));
30248    });
30249    return (node) => {
30250      const output = [];
30251      const children = (node || $getRoot2()).getChildren();
30252      for (let i2 = 0; i2 < children.length; i2++) {
30253        const child = children[i2];
30254        const result = exportTopLevelElements(child, elementTransformers, textFormatTransformers, byType.textMatch, shouldPreserveNewLines);
30255        if (result != null) {
30256          output.push(
30257            // separate consecutive group of texts with a line break: eg. ["hello", "world"] -> ["hello", "/nworld"]
30258            isNewlineDelimited && i2 > 0 && !isEmptyParagraph(child) && !isEmptyParagraph(children[i2 - 1]) ? "\n".concat(result) : result
30259          );
30260        }
30261      }
30262      return output.join("\n");
30263    };
30264  }
30265  function exportTopLevelElements(node, elementTransformers, textTransformersIndex, textMatchTransformers, shouldPreserveNewLines) {
30266    for (const transformer of elementTransformers) {
30267      if (!transformer.export) {
30268        continue;
30269      }
30270      const result = transformer.export(node, (_node) => exportChildren(_node, textTransformersIndex, textMatchTransformers, void 0, void 0, shouldPreserveNewLines));
30271      if (result != null) {
30272        return result;
30273      }
30274    }
30275    if ($isElementNode2(node)) {
30276      return exportChildren(node, textTransformersIndex, textMatchTransformers, void 0, void 0, shouldPreserveNewLines);
30277    } else if ($isDecoratorNode2(node)) {
30278      return node.getTextContent();
30279    } else {
30280      return null;
30281    }
30282  }
30283  function exportChildren(node, textTransformersIndex, textMatchTransformers, unclosedTags, unclosableTags, shouldPreserveNewLines = false) {
30284    const output = [];
30285    const children = node.getChildren();
30286    if (!unclosedTags) {
30287      unclosedTags = [];
30288    }
30289    if (!unclosableTags) {
30290      unclosableTags = [];
30291    }
30292    mainLoop: for (const child of children) {
30293      for (const transformer of textMatchTransformers) {
30294        if (!transformer.export) {
30295          continue;
30296        }
30297        const result = transformer.export(child, (parentNode) => exportChildren(
30298          parentNode,
30299          textTransformersIndex,
30300          textMatchTransformers,
30301          unclosedTags,
30302          // Add current unclosed tags to the list of unclosable tags - we don't want nested tags from
30303          // textmatch transformers to close the outer ones, as that may result in invalid markdown.
30304          // E.g. **text [text**](https://lexical.io)
30305          // is invalid markdown, as the closing ** is inside the link.
30306          //
30307          [...unclosableTags, ...unclosedTags],
30308          shouldPreserveNewLines
30309        ), (textNode, textContent) => exportTextFormat(textNode, textContent, textTransformersIndex, unclosedTags, unclosableTags, shouldPreserveNewLines));
30310        if (result != null) {
30311          output.push(result);
30312          continue mainLoop;
30313        }
30314      }
30315      if ($isLineBreakNode2(child)) {
30316        output.push("\n");
30317      } else if ($isTextNode2(child)) {
30318        output.push(exportTextFormat(child, child.getTextContent(), textTransformersIndex, unclosedTags, unclosableTags, shouldPreserveNewLines));
30319      } else if ($isElementNode2(child)) {
30320        output.push(exportChildren(child, textTransformersIndex, textMatchTransformers, unclosedTags, unclosableTags, shouldPreserveNewLines));
30321      } else if ($isDecoratorNode2(child)) {
30322        output.push(child.getTextContent());
30323      }
30324    }
30325    return output.join("");
30326  }
30327  function exportTextFormat(node, textContent, textTransformers, unclosedTags, unclosableTags, shouldPreserveNewLines = false) {
30328    let output = textContent;
30329    if (!node.hasFormat("code")) {
30330      output = shouldPreserveNewLines ? output.replace(/([*_`~])/g, "\\$1") : output.replace(/([*_`~\\])/g, "\\$1");
30331    }
30332    const match = output.match(/^(\s*)(.*?)(\s*)$/s) || ["", "", output, ""];
30333    const leadingSpace = match[1];
30334    const trimmedOutput = match[2];
30335    const trailingSpace = match[3];
30336    const isWhitespaceOnly = trimmedOutput === "";
30337    let openingTags = "";
30338    let closingTagsBefore = "";
30339    let closingTagsAfter = "";
30340    const prevNode = getTextSibling(node, true);
30341    const nextNode = getTextSibling(node, false);
30342    const applied = /* @__PURE__ */ new Set();
30343    for (const transformer of textTransformers) {
30344      const format = transformer.format[0];
30345      const tag = transformer.tag;
30346      if (checkHasFormat(node, format) && !applied.has(format)) {
30347        applied.add(format);
30348        if (!checkHasFormat(prevNode, format) || !unclosedTags.find((element) => element.tag === tag)) {
30349          unclosedTags.push({
30350            format,
30351            tag
30352          });
30353          openingTags += tag;
30354        }
30355      }
30356    }
30357    for (let i2 = 0; i2 < unclosedTags.length; i2++) {
30358      const nodeHasFormat = hasFormat(node, unclosedTags[i2].format);
30359      const nextNodeHasFormat = hasFormat(nextNode, unclosedTags[i2].format);
30360      if (nodeHasFormat && nextNodeHasFormat) {
30361        continue;
30362      }
30363      const unhandledUnclosedTags = [...unclosedTags];
30364      while (unhandledUnclosedTags.length > i2) {
30365        const unclosedTag = unhandledUnclosedTags.pop();
30366        if (unclosableTags && unclosedTag && unclosableTags.find((element) => element.tag === unclosedTag.tag)) {
30367          continue;
30368        }
30369        if (unclosedTag && typeof unclosedTag.tag === "string") {
30370          if (!nodeHasFormat) {
30371            closingTagsBefore += unclosedTag.tag;
30372          } else if (!nextNodeHasFormat) {
30373            closingTagsAfter += unclosedTag.tag;
30374          }
30375        }
30376        unclosedTags.pop();
30377      }
30378      break;
30379    }
30380    if (isWhitespaceOnly && !node.hasFormat("code")) {
30381      return closingTagsBefore + output;
30382    }
30383    return closingTagsBefore + leadingSpace + openingTags + trimmedOutput + closingTagsAfter + trailingSpace;
30384  }
30385  function getTextSibling(node, backward) {
30386    const sibling = backward ? node.getPreviousSibling() : node.getNextSibling();
30387    if ($isTextNode2(sibling)) {
30388      return sibling;
30389    }
30390    return null;
30391  }
30392  function hasFormat(node, format) {
30393    return $isTextNode2(node) && node.hasFormat(format);
30394  }
30395  function checkHasFormat(n2, f) {
30396    if (!hasFormat(n2, f)) {
30397      return false;
30398    }
30399    if (f === "code") {
30400      return true;
30401    }
30402    if (n2 && /^\s*$/.test(n2.getTextContent())) {
30403      return false;
30404    }
30405    return true;
30406  }
30407  function findOutermostTextFormatTransformer(textNode, textFormatTransformersIndex) {
30408    const textContent = textNode.getTextContent();
30409    const codeRegex = textFormatTransformersIndex.fullMatchRegExpByTag["`"];
30410    const codeTransformer = textFormatTransformersIndex.transformersByTag["`"];
30411    const excludeRanges = [];
30412    let codeMatch = null;
30413    if (codeRegex && codeTransformer) {
30414      const globalRegex = new RegExp(codeRegex.source, "g");
30415      const matches = Array.from(textContent.matchAll(globalRegex));
30416      for (const match of matches) {
30417        const startIndex = match.index + match[1].length;
30418        const endIndex = match.index + match[0].length;
30419        if (!codeMatch) {
30420          codeMatch = {
30421            content: match[3],
30422            endIndex,
30423            startIndex,
30424            tag: "`"
30425          };
30426        }
30427        excludeRanges.push({
30428          end: endIndex,
30429          start: startIndex
30430        });
30431      }
30432    }
30433    const delimiters = scanDelimiters(textContent, textFormatTransformersIndex, excludeRanges);
30434    const emphasisMatch = delimiters.length > 0 ? processEmphasis(textContent, delimiters, textFormatTransformersIndex) : null;
30435    let resultMatch = null;
30436    let resultTransformer = null;
30437    if (codeMatch && emphasisMatch) {
30438      if (emphasisMatch.startIndex <= codeMatch.startIndex && emphasisMatch.endIndex >= codeMatch.endIndex) {
30439        resultMatch = emphasisMatch;
30440        resultTransformer = textFormatTransformersIndex.transformersByTag[emphasisMatch.tag];
30441      } else {
30442        resultMatch = codeMatch;
30443        resultTransformer = codeTransformer;
30444      }
30445    } else if (codeMatch) {
30446      resultMatch = codeMatch;
30447      resultTransformer = codeTransformer;
30448    } else if (emphasisMatch) {
30449      resultMatch = emphasisMatch;
30450      resultTransformer = textFormatTransformersIndex.transformersByTag[emphasisMatch.tag];
30451    }
30452    if (!resultMatch || !resultTransformer) {
30453      return null;
30454    }
30455    const regexMatch = [textContent.slice(resultMatch.startIndex, resultMatch.endIndex), resultMatch.tag, resultMatch.content];
30456    regexMatch.index = resultMatch.startIndex;
30457    regexMatch.input = textContent;
30458    return {
30459      endIndex: resultMatch.endIndex,
30460      match: regexMatch,
30461      startIndex: resultMatch.startIndex,
30462      transformer: resultTransformer
30463    };
30464  }
30465  function scanDelimiters(text2, transformersIndex, excludeRanges = []) {
30466    const delimiters = [];
30467    const delimiterChars = new Set(Object.keys(transformersIndex.transformersByTag).filter((tag) => tag[0] !== "`").map((tag) => tag[0]));
30468    const isEscaped = (index) => {
30469      let count = 0;
30470      for (let i3 = index - 1; i3 >= 0 && text2[i3] === "\\"; i3--) {
30471        count++;
30472      }
30473      return count % 2 === 1;
30474    };
30475    const isInExcludedRange = (index) => {
30476      return excludeRanges.some((range2) => index >= range2.start && index < range2.end);
30477    };
30478    let i2 = 0;
30479    while (i2 < text2.length) {
30480      const char = text2[i2];
30481      if (!delimiterChars.has(char) || isEscaped(i2) || isInExcludedRange(i2)) {
30482        i2++;
30483        continue;
30484      }
30485      let len = 1;
30486      while (i2 + len < text2.length && text2[i2 + len] === char) {
30487        len++;
30488      }
30489      const canOpen = canEmphasis(char, text2, i2, len, true);
30490      const canClose = canEmphasis(char, text2, i2, len, false);
30491      if (canOpen || canClose) {
30492        delimiters.push({
30493          active: true,
30494          canClose,
30495          canOpen,
30496          char,
30497          index: i2,
30498          length: len,
30499          originalLength: len
30500        });
30501      }
30502      i2 += len;
30503    }
30504    return delimiters;
30505  }
30506  function processEmphasis(text2, delimiters, transformersIndex) {
30507    const openersBottom = {};
30508    let currentPos = 0;
30509    let result = null;
30510    while (currentPos < delimiters.length) {
30511      const closer = delimiters[currentPos];
30512      if (!closer.active || !closer.canClose || closer.length === 0) {
30513        currentPos++;
30514        continue;
30515      }
30516      const bottomKey = `${closer.char}${closer.canOpen}`;
30517      const bottom = openersBottom[bottomKey] ?? -1;
30518      let foundOpener = false;
30519      for (let openIdx = currentPos - 1; openIdx > bottom; openIdx--) {
30520        const opener = delimiters[openIdx];
30521        if (!opener.active || !opener.canOpen || opener.length === 0 || opener.char !== closer.char) {
30522          continue;
30523        }
30524        if (opener.canClose || closer.canOpen) {
30525          const sum = opener.originalLength + closer.originalLength;
30526          if (sum % 3 === 0 && opener.originalLength % 3 !== 0 && closer.originalLength % 3 !== 0) {
30527            continue;
30528          }
30529        }
30530        const maxLen = Math.min(opener.length, closer.length);
30531        const matchedTag = Object.keys(transformersIndex.transformersByTag).filter((t2) => t2[0] === opener.char && t2.length <= maxLen).sort((a2, b3) => b3.length - a2.length)[0];
30532        if (!matchedTag) {
30533          continue;
30534        }
30535        foundOpener = true;
30536        const matchLen = matchedTag.length;
30537        const match = {
30538          content: text2.slice(opener.index + opener.length, closer.index),
30539          endIndex: closer.index + matchLen,
30540          startIndex: opener.index + (opener.length - matchLen),
30541          tag: matchedTag
30542        };
30543        if (!result || match.startIndex < result.startIndex || match.startIndex === result.startIndex && match.endIndex > result.endIndex) {
30544          result = match;
30545        }
30546        for (let j3 = openIdx + 1; j3 < currentPos; j3++) {
30547          delimiters[j3].active = false;
30548        }
30549        opener.length -= matchLen;
30550        closer.length -= matchLen;
30551        opener.active = opener.length > 0;
30552        if (closer.length > 0) {
30553          closer.index += matchLen;
30554        } else {
30555          closer.active = false;
30556          currentPos++;
30557        }
30558        break;
30559      }
30560      if (!foundOpener) {
30561        openersBottom[bottomKey] = currentPos - 1;
30562        if (!closer.canOpen) {
30563          closer.active = false;
30564        }
30565        currentPos++;
30566      }
30567    }
30568    return result;
30569  }
30570  function canEmphasis(char, text2, index, length, isOpen) {
30571    if (!isFlanking(text2, index, length, isOpen)) {
30572      return false;
30573    }
30574    if (char === "*") {
30575      return true;
30576    }
30577    if (char === "_") {
30578      if (!isFlanking(text2, index, length, !isOpen)) {
30579        return true;
30580      }
30581      const adjacentChar = isOpen ? text2[index - 1] : text2[index + length];
30582      return adjacentChar !== void 0 && PUNCTUATION.test(adjacentChar);
30583    }
30584    return true;
30585  }
30586  function isFlanking(text2, index, length, isLeft) {
30587    const charBefore = text2[index - 1];
30588    const charAfter = text2[index + length];
30589    const [primary, secondary] = isLeft ? [charAfter, charBefore] : [charBefore, charAfter];
30590    if (primary === void 0 || WHITESPACE.test(primary)) {
30591      return false;
30592    }
30593    if (!PUNCTUATION.test(primary)) {
30594      return true;
30595    }
30596    return secondary === void 0 || WHITESPACE.test(secondary) || PUNCTUATION.test(secondary);
30597  }
30598  function importTextFormatTransformer(textNode, startIndex, endIndex, transformer, match) {
30599    const textContent = textNode.getTextContent();
30600    let transformedNode, nodeAfter, nodeBefore;
30601    if (match[0] === textContent) {
30602      transformedNode = textNode;
30603    } else {
30604      if (startIndex === 0) {
30605        [transformedNode, nodeAfter] = textNode.splitText(endIndex);
30606      } else {
30607        [nodeBefore, transformedNode, nodeAfter] = textNode.splitText(startIndex, endIndex);
30608      }
30609    }
30610    transformedNode.setTextContent(match[2]);
30611    if (transformer) {
30612      for (const format of transformer.format) {
30613        if (!transformedNode.hasFormat(format)) {
30614          transformedNode.toggleFormat(format);
30615        }
30616      }
30617    }
30618    return {
30619      nodeAfter,
30620      nodeBefore,
30621      transformedNode
30622    };
30623  }
30624  function findOutermostTextMatchTransformer(textNode_, textMatchTransformers) {
30625    const textNode = textNode_;
30626    let foundMatchStartIndex = void 0;
30627    let foundMatchEndIndex = void 0;
30628    let foundMatchTransformer = void 0;
30629    let foundMatch = void 0;
30630    for (const transformer of textMatchTransformers) {
30631      if (!transformer.replace || !transformer.importRegExp) {
30632        continue;
30633      }
30634      const match = textNode.getTextContent().match(transformer.importRegExp);
30635      if (!match) {
30636        continue;
30637      }
30638      const startIndex = match.index || 0;
30639      const endIndex = transformer.getEndIndex ? transformer.getEndIndex(textNode, match) : startIndex + match[0].length;
30640      if (endIndex === false) {
30641        continue;
30642      }
30643      if (foundMatchStartIndex === void 0 || foundMatchEndIndex === void 0 || // Wraps previous match or is strictly before it.
30644      startIndex < foundMatchStartIndex && (endIndex > foundMatchEndIndex || endIndex <= foundMatchStartIndex)) {
30645        foundMatchStartIndex = startIndex;
30646        foundMatchEndIndex = endIndex;
30647        foundMatchTransformer = transformer;
30648        foundMatch = match;
30649      }
30650    }
30651    if (foundMatchStartIndex === void 0 || foundMatchEndIndex === void 0 || foundMatchTransformer === void 0 || foundMatch === void 0) {
30652      return null;
30653    }
30654    return {
30655      endIndex: foundMatchEndIndex,
30656      match: foundMatch,
30657      startIndex: foundMatchStartIndex,
30658      transformer: foundMatchTransformer
30659    };
30660  }
30661  function importFoundTextMatchTransformer(textNode, startIndex, endIndex, transformer, match) {
30662    let transformedNode, nodeAfter, nodeBefore;
30663    if (startIndex === 0) {
30664      [transformedNode, nodeAfter] = textNode.splitText(endIndex);
30665    } else {
30666      [nodeBefore, transformedNode, nodeAfter] = textNode.splitText(startIndex, endIndex);
30667    }
30668    if (!transformer.replace) {
30669      return null;
30670    }
30671    const potentialTransformedNode = transformer.replace(transformedNode, match);
30672    return {
30673      nodeAfter,
30674      nodeBefore,
30675      transformedNode: potentialTransformedNode || void 0
30676    };
30677  }
30678  function canContainTransformableMarkdown(node) {
30679    return $isTextNode2(node) && !node.hasFormat("code");
30680  }
30681  function importTextTransformers(textNode, textFormatTransformersIndex, textMatchTransformers) {
30682    let foundTextFormat = findOutermostTextFormatTransformer(textNode, textFormatTransformersIndex);
30683    let foundTextMatch = findOutermostTextMatchTransformer(textNode, textMatchTransformers);
30684    if (foundTextFormat && foundTextMatch) {
30685      if (foundTextFormat.startIndex <= foundTextMatch.startIndex && foundTextFormat.endIndex >= foundTextMatch.endIndex || // foundTextMatch is not contained within foundTextFormat
30686      foundTextMatch.startIndex > foundTextFormat.endIndex) {
30687        foundTextMatch = null;
30688      } else {
30689        foundTextFormat = null;
30690      }
30691    }
30692    if (foundTextFormat) {
30693      const result = importTextFormatTransformer(textNode, foundTextFormat.startIndex, foundTextFormat.endIndex, foundTextFormat.transformer, foundTextFormat.match);
30694      if (canContainTransformableMarkdown(result.nodeAfter)) {
30695        importTextTransformers(result.nodeAfter, textFormatTransformersIndex, textMatchTransformers);
30696      }
30697      if (canContainTransformableMarkdown(result.nodeBefore)) {
30698        importTextTransformers(result.nodeBefore, textFormatTransformersIndex, textMatchTransformers);
30699      }
30700      if (canContainTransformableMarkdown(result.transformedNode)) {
30701        importTextTransformers(result.transformedNode, textFormatTransformersIndex, textMatchTransformers);
30702      }
30703    } else if (foundTextMatch) {
30704      const result = importFoundTextMatchTransformer(textNode, foundTextMatch.startIndex, foundTextMatch.endIndex, foundTextMatch.transformer, foundTextMatch.match);
30705      if (!result) {
30706        return;
30707      }
30708      if (canContainTransformableMarkdown(result.nodeAfter)) {
30709        importTextTransformers(result.nodeAfter, textFormatTransformersIndex, textMatchTransformers);
30710      }
30711      if (canContainTransformableMarkdown(result.nodeBefore)) {
30712        importTextTransformers(result.nodeBefore, textFormatTransformersIndex, textMatchTransformers);
30713      }
30714      if (canContainTransformableMarkdown(result.transformedNode)) {
30715        importTextTransformers(result.transformedNode, textFormatTransformersIndex, textMatchTransformers);
30716      }
30717    }
30718    const textContent = textNode.getTextContent();
30719    const unescapedText = unescapeText(textContent);
30720    textNode.setTextContent(unescapedText);
30721  }
30722  function createMarkdownImport(transformers, shouldPreserveNewLines = false) {
30723    const byType = transformersByType(transformers);
30724    const textFormatTransformersIndex = createTextFormatTransformersIndex(byType.textFormat);
30725    return (markdownString, node) => {
30726      const lines = markdownString.split("\n");
30727      const linesLength = lines.length;
30728      const root = node || $getRoot2();
30729      root.clear();
30730      for (let i2 = 0; i2 < linesLength; i2++) {
30731        const lineText = lines[i2];
30732        const [imported, shiftedIndex] = $importMultiline(lines, i2, byType.multilineElement, root);
30733        if (imported) {
30734          i2 = shiftedIndex;
30735          continue;
30736        }
30737        $importBlocks(lineText, root, byType.element, textFormatTransformersIndex, byType.textMatch, shouldPreserveNewLines);
30738      }
30739      const children = root.getChildren();
30740      for (const child of children) {
30741        if (!shouldPreserveNewLines && isEmptyParagraph(child) && root.getChildrenSize() > 1) {
30742          child.remove();
30743          continue;
30744        }
30745        if ($isElementNode2(child)) {
30746          for (const textNode of child.getAllTextNodes()) {
30747            $normalizeMarkdownTextNode(textNode);
30748          }
30749        }
30750      }
30751      if ($getSelection2() !== null) {
30752        root.selectStart();
30753      }
30754    };
30755  }
30756  function $importMultiline(lines, startLineIndex, multilineElementTransformers, rootNode) {
30757    for (const transformer of multilineElementTransformers) {
30758      const {
30759        handleImportAfterStartMatch,
30760        regExpEnd,
30761        regExpStart,
30762        replace
30763      } = transformer;
30764      const startMatch = lines[startLineIndex].match(regExpStart);
30765      if (!startMatch) {
30766        continue;
30767      }
30768      if (handleImportAfterStartMatch) {
30769        const result = handleImportAfterStartMatch({
30770          lines,
30771          rootNode,
30772          startLineIndex,
30773          startMatch,
30774          transformer
30775        });
30776        if (result === null) {
30777          continue;
30778        } else if (result) {
30779          return result;
30780        }
30781      }
30782      const regexpEndRegex = typeof regExpEnd === "object" && "regExp" in regExpEnd ? regExpEnd.regExp : regExpEnd;
30783      const isEndOptional = regExpEnd && typeof regExpEnd === "object" && "optional" in regExpEnd ? regExpEnd.optional : !regExpEnd;
30784      let endLineIndex = startLineIndex;
30785      const linesLength = lines.length;
30786      while (endLineIndex < linesLength) {
30787        const endMatch = regexpEndRegex ? lines[endLineIndex].match(regexpEndRegex) : null;
30788        if (!endMatch) {
30789          if (!isEndOptional || isEndOptional && endLineIndex < linesLength - 1) {
30790            endLineIndex++;
30791            continue;
30792          }
30793        }
30794        if (endMatch && startLineIndex === endLineIndex && endMatch.index === startMatch.index) {
30795          endLineIndex++;
30796          continue;
30797        }
30798        const linesInBetween = [];
30799        if (endMatch && startLineIndex === endLineIndex) {
30800          linesInBetween.push(lines[startLineIndex].slice(startMatch[0].length, -endMatch[0].length));
30801        } else {
30802          for (let i2 = startLineIndex; i2 <= endLineIndex; i2++) {
30803            if (i2 === startLineIndex) {
30804              const text2 = lines[i2].slice(startMatch[0].length);
30805              linesInBetween.push(text2);
30806            } else if (i2 === endLineIndex && endMatch) {
30807              const text2 = lines[i2].slice(0, -endMatch[0].length);
30808              linesInBetween.push(text2);
30809            } else {
30810              linesInBetween.push(lines[i2]);
30811            }
30812          }
30813        }
30814        if (replace(rootNode, null, startMatch, endMatch, linesInBetween, true) !== false) {
30815          return [true, endLineIndex];
30816        }
30817        break;
30818      }
30819    }
30820    return [false, startLineIndex];
30821  }
30822  function $importBlocks(lineText, rootNode, elementTransformers, textFormatTransformersIndex, textMatchTransformers, shouldPreserveNewLines) {
30823    const textNode = $createTextNode2(lineText);
30824    const elementNode = $createParagraphNode2();
30825    elementNode.append(textNode);
30826    rootNode.append(elementNode);
30827    for (const {
30828      regExp,
30829      replace
30830    } of elementTransformers) {
30831      const match = lineText.match(regExp);
30832      if (match) {
30833        textNode.setTextContent(lineText.slice(match[0].length));
30834        if (replace(elementNode, [textNode], match, true) !== false) {
30835          break;
30836        }
30837      }
30838    }
30839    importTextTransformers(textNode, textFormatTransformersIndex, textMatchTransformers);
30840    if (elementNode.isAttached() && lineText.length > 0) {
30841      const previousNode = elementNode.getPreviousSibling();
30842      if (!shouldPreserveNewLines && // Only append if we're not preserving newlines
30843      ($isParagraphNode2(previousNode) || $isQuoteNode2(previousNode) || $isListNode2(previousNode))) {
30844        let targetNode = previousNode;
30845        if ($isListNode2(previousNode)) {
30846          const lastDescendant = previousNode.getLastDescendant();
30847          if (lastDescendant == null) {
30848            targetNode = null;
30849          } else {
30850            targetNode = $findMatchingParent3(lastDescendant, $isListItemNode2);
30851          }
30852        }
30853        if (targetNode != null && targetNode.getTextContentSize() > 0) {
30854          const lastChild = targetNode.getLastChild();
30855          if ($isTextNode2(lastChild)) {
30856            const lastText = lastChild.getTextContent();
30857            if (lastText.endsWith("\\")) {
30858              lastChild.setTextContent(lastText.slice(0, -1));
30859            } else if (/ {2,}$/.test(lastText)) {
30860              lastChild.setTextContent(lastText.replace(/ {2,}$/, ""));
30861            }
30862          }
30863          targetNode.splice(targetNode.getChildrenSize(), 0, [$createLineBreakNode2(), ...elementNode.getChildren()]);
30864          elementNode.remove();
30865        }
30866      }
30867    }
30868  }
30869  function $normalizeMarkdownTextNode(textNode) {
30870    const tabOffsets = /* @__PURE__ */ new Set();
30871    const text2 = textNode.getTextContent();
30872    let index = text2.indexOf("	");
30873    while (index !== -1) {
30874      tabOffsets.add(index);
30875      tabOffsets.add(index + 1);
30876      index = text2.indexOf("	", index + 1);
30877    }
30878    const splitNodes = textNode.splitText(...tabOffsets);
30879    splitNodes.forEach((node) => {
30880      if (node.getTextContent() === "	") {
30881        node.replace($createTabNode2());
30882      }
30883    });
30884  }
30885  function createTextFormatTransformersIndex(textTransformers) {
30886    const transformersByTag = {};
30887    const fullMatchRegExpByTag = {};
30888    const openTagsRegExp = [];
30889    for (const transformer of textTransformers) {
30890      const {
30891        tag
30892      } = transformer;
30893      transformersByTag[tag] = transformer;
30894      const tagRegExp = tag.replace(/(\*|\^|\+)/g, "\\$1");
30895      openTagsRegExp.push(tagRegExp);
30896      if (tag.length === 1) {
30897        if (tag === "`") {
30898          fullMatchRegExpByTag[tag] = new RegExp(`(^|[^\\\\\`])(\`)((?:\\\\\`|[^\`])+?)(\`)(?!\`)`);
30899        } else {
30900          fullMatchRegExpByTag[tag] = new RegExp(`(^|[^\\\\${tagRegExp}])(${tagRegExp})((\\\\${tagRegExp})?.*?[^${tagRegExp}\\s](\\\\${tagRegExp})?)(${tagRegExp})(?![\\\\${tagRegExp}])`);
30901        }
30902      } else {
30903        fullMatchRegExpByTag[tag] = new RegExp(`(^|[^\\\\])(${tagRegExp})((\\\\${tagRegExp})?.*?[^\\s](\\\\${tagRegExp})?)(${tagRegExp})(?!\\\\)`);
30904      }
30905    }
30906    return {
30907      // Reg exp to find open tag + content + close tag
30908      fullMatchRegExpByTag,
30909      // Regexp to locate *any* potential opening tag (longest first).
30910      // The former (?<!\\) escape guard has been removed — the delimiter
30911      // scanner's isEscaped() check handles escape filtering at match time.
30912      openTagsRegExp: new RegExp(`(${openTagsRegExp.join("|")})`, "g"),
30913      transformersByTag
30914    };
30915  }
30916  function formatDevErrorMessage11(message) {
30917    throw new Error(message);
30918  }
30919  var ORDERED_LIST_REGEX = /^(\s*)(\d{1,})\.\s/;
30920  var UNORDERED_LIST_REGEX = /^(\s*)[-*+]\s/;
30921  var CHECK_LIST_REGEX = /^(\s*)(?:[-*+]\s)?\s?(\[(\s|x)?\])\s/i;
30922  var HEADING_REGEX = /^(#{1,6})\s/;
30923  var QUOTE_REGEX = /^>\s/;
30924  var CODE_START_REGEX = /^([ \t]*`{3,})([\w-]+)?[ \t]?/;
30925  var CODE_END_REGEX = /^[ \t]*`{3,}$/;
30926  var CODE_SINGLE_LINE_REGEX = /^[ \t]*```[^`]+(?:(?:`{1,2}|`{4,})[^`]+)*```(?:[^`]|$)/;
30927  var TABLE_ROW_REG_EXP = /^(?:\|)(.+)(?:\|)\s?$/;
30928  var TABLE_ROW_DIVIDER_REG_EXP = /^(\| ?:?-*:? ?)+\|\s?$/;
30929  var TAG_START_REGEX = /^<[a-z_][\w-]*(?:\s[^<>]*)?\/?>/i;
30930  var TAG_END_REGEX = /^<\/[a-z_][\w-]*\s*>/i;
30931  var ENDS_WITH = (regex) => new RegExp(`(?:${regex.source})$`, regex.flags);
30932  var listMarkerState = createState2("mdListMarker", {
30933    parse: (v3) => typeof v3 === "string" && /^[-*+]$/.test(v3) ? v3 : "-",
30934    resetOnCopyNode: true
30935  });
30936  var codeFenceState = createState2("mdCodeFence", {
30937    parse: (val) => {
30938      if (typeof val === "string" && /^`{3,}$/.test(val)) {
30939        return val;
30940      }
30941      return "```";
30942    },
30943    resetOnCopyNode: true
30944  });
30945  var createBlockNode = (createNode) => {
30946    return (parentNode, children, match, isImport) => {
30947      const node = createNode(match);
30948      node.append(...children);
30949      parentNode.replace(node);
30950      if (!isImport) {
30951        node.select(0, 0);
30952      }
30953    };
30954  };
30955  var LIST_INDENT_SIZE = 4;
30956  function getIndent(whitespaces) {
30957    const tabs = whitespaces.match(/\t/g);
30958    const spaces = whitespaces.match(/ /g);
30959    let indent = 0;
30960    if (tabs) {
30961      indent += tabs.length;
30962    }
30963    if (spaces) {
30964      indent += Math.floor(spaces.length / LIST_INDENT_SIZE);
30965    }
30966    return indent;
30967  }
30968  var listReplace = (listType) => {
30969    return (parentNode, children, match, isImport) => {
30970      const previousNode = parentNode.getPreviousSibling();
30971      const nextNode = parentNode.getNextSibling();
30972      const listItem = $createListItemNode2(listType === "check" ? match[3] === "x" : void 0);
30973      const firstMatchChar = match[0].trim()[0];
30974      const listMarker = (listType === "bullet" || listType === "check") && firstMatchChar === listMarkerState.parse(firstMatchChar) ? firstMatchChar : void 0;
30975      if ($isListNode2(nextNode) && nextNode.getListType() === listType) {
30976        if (listMarker) {
30977          $setState2(nextNode, listMarkerState, listMarker);
30978        }
30979        const firstChild = nextNode.getFirstChild();
30980        if (firstChild !== null) {
30981          firstChild.insertBefore(listItem);
30982        } else {
30983          nextNode.append(listItem);
30984        }
30985        parentNode.remove();
30986      } else if ($isListNode2(previousNode) && previousNode.getListType() === listType) {
30987        if (listMarker) {
30988          $setState2(previousNode, listMarkerState, listMarker);
30989        }
30990        previousNode.append(listItem);
30991        parentNode.remove();
30992      } else {
30993        const list = $createListNode2(listType, listType === "number" ? Number(match[2]) : void 0);
30994        if (listMarker) {
30995          $setState2(list, listMarkerState, listMarker);
30996        }
30997        list.append(listItem);
30998        parentNode.replace(list);
30999      }
31000      listItem.append(...children);
31001      if (!isImport) {
31002        listItem.select(0, 0);
31003      }
31004      const indent = getIndent(match[1]);
31005      if (indent) {
31006        listItem.setIndent(indent);
31007      }
31008    };
31009  };
31010  var $listExport = (listNode, exportChildren2, depth) => {
31011    const output = [];
31012    const children = listNode.getChildren();
31013    let index = 0;
31014    for (const listItemNode of children) {
31015      if ($isListItemNode2(listItemNode)) {
31016        if (listItemNode.getChildrenSize() === 1) {
31017          const firstChild = listItemNode.getFirstChild();
31018          if ($isListNode2(firstChild)) {
31019            output.push($listExport(firstChild, exportChildren2, depth + 1));
31020            continue;
31021          }
31022        }
31023        const indent = " ".repeat(depth * LIST_INDENT_SIZE);
31024        const listType = listNode.getListType();
31025        const listMarker = $getState2(listNode, listMarkerState);
31026        const prefix = listType === "number" ? `${listNode.getStart() + index}. ` : listType === "check" ? `${listMarker} [${listItemNode.getChecked() ? "x" : " "}] ` : listMarker + " ";
31027        let childrenText = exportChildren2(listItemNode);
31028        if (listType !== "number") {
31029          childrenText = childrenText.replace(/^(\s{0,3}\d+)(\.\s)/, "$1\\$2");
31030        }
31031        output.push(indent + prefix + childrenText);
31032        index++;
31033      }
31034    }
31035    return output.join("\n");
31036  };
31037  var HEADING = {
31038    dependencies: [HeadingNode2],
31039    export: (node, exportChildren2) => {
31040      if (!$isHeadingNode2(node)) {
31041        return null;
31042      }
31043      const level = Number(node.getTag().slice(1));
31044      return "#".repeat(level) + " " + exportChildren2(node);
31045    },
31046    regExp: HEADING_REGEX,
31047    replace: createBlockNode((match) => {
31048      const tag = "h" + match[1].length;
31049      return $createHeadingNode2(tag);
31050    }),
31051    type: "element"
31052  };
31053  var QUOTE = {
31054    dependencies: [QuoteNode2],
31055    export: (node, exportChildren2) => {
31056      if (!$isQuoteNode2(node)) {
31057        return null;
31058      }
31059      const lines = exportChildren2(node).split("\n");
31060      const output = [];
31061      for (const line of lines) {
31062        output.push("> " + line);
31063      }
31064      return output.join("\n");
31065    },
31066    regExp: QUOTE_REGEX,
31067    replace: (parentNode, children, _match, isImport) => {
31068      if (isImport) {
31069        const previousNode = parentNode.getPreviousSibling();
31070        if ($isQuoteNode2(previousNode)) {
31071          previousNode.splice(previousNode.getChildrenSize(), 0, [$createLineBreakNode2(), ...children]);
31072          parentNode.remove();
31073          return;
31074        }
31075      }
31076      const node = $createQuoteNode2();
31077      node.append(...children);
31078      parentNode.replace(node);
31079      if (!isImport) {
31080        node.select(0, 0);
31081      }
31082    },
31083    type: "element"
31084  };
31085  var CODE = {
31086    dependencies: [CodeNode2],
31087    export: (node) => {
31088      if (!$isCodeNode2(node)) {
31089        return null;
31090      }
31091      const textContent = node.getTextContent();
31092      let fence = $getState2(node, codeFenceState);
31093      if (textContent.indexOf(fence) > -1) {
31094        const backticks = textContent.match(/`{3,}/g);
31095        if (backticks) {
31096          const maxLength = Math.max(...backticks.map((b3) => b3.length));
31097          fence = "`".repeat(maxLength + 1);
31098        }
31099      }
31100      return fence + (node.getLanguage() || "") + (textContent ? "\n" + textContent : "") + "\n" + fence;
31101    },
31102    handleImportAfterStartMatch: ({
31103      lines,
31104      rootNode,
31105      startLineIndex,
31106      startMatch
31107    }) => {
31108      const fence = startMatch[1];
31109      const fenceLength = fence.trim().length;
31110      const currentLine = lines[startLineIndex];
31111      const afterFenceIndex = startMatch.index + fence.length;
31112      const afterFence = currentLine.slice(afterFenceIndex);
31113      const singleLineEndRegex = new RegExp(`\`{${fenceLength},}$`);
31114      if (singleLineEndRegex.test(afterFence)) {
31115        const endMatch = afterFence.match(singleLineEndRegex);
31116        const content = afterFence.slice(0, afterFence.lastIndexOf(endMatch[0]));
31117        const fakeStartMatch = [...startMatch];
31118        fakeStartMatch[2] = "";
31119        CODE.replace(rootNode, null, fakeStartMatch, endMatch, [content], true);
31120        return [true, startLineIndex];
31121      }
31122      const multilineEndRegex = new RegExp(`^[ \\t]*\`{${fenceLength},}$`);
31123      for (let i2 = startLineIndex + 1; i2 < lines.length; i2++) {
31124        const line = lines[i2];
31125        if (multilineEndRegex.test(line)) {
31126          const endMatch = line.match(multilineEndRegex);
31127          const linesInBetween2 = lines.slice(startLineIndex + 1, i2);
31128          const afterFullMatch2 = currentLine.slice(startMatch[0].length);
31129          if (afterFullMatch2.length > 0) {
31130            linesInBetween2.unshift(afterFullMatch2);
31131          }
31132          CODE.replace(rootNode, null, startMatch, endMatch, linesInBetween2, true);
31133          return [true, i2];
31134        }
31135      }
31136      const linesInBetween = lines.slice(startLineIndex + 1);
31137      const afterFullMatch = currentLine.slice(startMatch[0].length);
31138      if (afterFullMatch.length > 0) {
31139        linesInBetween.unshift(afterFullMatch);
31140      }
31141      CODE.replace(rootNode, null, startMatch, null, linesInBetween, true);
31142      return [true, lines.length - 1];
31143    },
31144    regExpEnd: {
31145      optional: true,
31146      regExp: CODE_END_REGEX
31147    },
31148    regExpStart: CODE_START_REGEX,
31149    replace: (rootNode, children, startMatch, endMatch, linesInBetween, isImport) => {
31150      let codeBlockNode;
31151      let code;
31152      const fence = startMatch[1] ? startMatch[1].trim() : "```";
31153      const language = startMatch[2] || void 0;
31154      if (!children && linesInBetween) {
31155        if (linesInBetween.length === 1) {
31156          if (endMatch) {
31157            codeBlockNode = $createCodeNode2(language);
31158            code = linesInBetween[0];
31159          } else {
31160            codeBlockNode = $createCodeNode2(language);
31161            code = linesInBetween[0].startsWith(" ") ? linesInBetween[0].slice(1) : linesInBetween[0];
31162          }
31163        } else {
31164          codeBlockNode = $createCodeNode2(language);
31165          if (linesInBetween.length > 0) {
31166            if (linesInBetween[0].trim().length === 0) {
31167              linesInBetween.shift();
31168            } else if (linesInBetween[0].startsWith(" ")) {
31169              linesInBetween[0] = linesInBetween[0].slice(1);
31170            }
31171          }
31172          while (linesInBetween.length > 0 && !linesInBetween[linesInBetween.length - 1].length) {
31173            linesInBetween.pop();
31174          }
31175          code = linesInBetween.join("\n");
31176        }
31177        $setState2(codeBlockNode, codeFenceState, fence);
31178        const textNode = $createTextNode2(code);
31179        codeBlockNode.append(textNode);
31180        rootNode.append(codeBlockNode);
31181      } else if (children) {
31182        createBlockNode((match) => {
31183          return $createCodeNode2(match ? match[2] : void 0);
31184        })(rootNode, children, startMatch, isImport);
31185      }
31186    },
31187    type: "multiline-element"
31188  };
31189  var UNORDERED_LIST = {
31190    dependencies: [ListNode2, ListItemNode2],
31191    export: (node, exportChildren2) => {
31192      return $isListNode2(node) ? $listExport(node, exportChildren2, 0) : null;
31193    },
31194    regExp: UNORDERED_LIST_REGEX,
31195    replace: listReplace("bullet"),
31196    type: "element"
31197  };
31198  var CHECK_LIST = {
31199    dependencies: [ListNode2, ListItemNode2],
31200    export: (node, exportChildren2) => {
31201      return $isListNode2(node) ? $listExport(node, exportChildren2, 0) : null;
31202    },
31203    regExp: CHECK_LIST_REGEX,
31204    replace: listReplace("check"),
31205    type: "element"
31206  };
31207  var ORDERED_LIST = {
31208    dependencies: [ListNode2, ListItemNode2],
31209    export: (node, exportChildren2) => {
31210      return $isListNode2(node) ? $listExport(node, exportChildren2, 0) : null;
31211    },
31212    regExp: ORDERED_LIST_REGEX,
31213    replace: listReplace("number"),
31214    type: "element"
31215  };
31216  var INLINE_CODE = {
31217    format: ["code"],
31218    tag: "`",
31219    type: "text-format"
31220  };
31221  var HIGHLIGHT = {
31222    format: ["highlight"],
31223    tag: "==",
31224    type: "text-format"
31225  };
31226  var BOLD_ITALIC_STAR = {
31227    format: ["bold", "italic"],
31228    tag: "***",
31229    type: "text-format"
31230  };
31231  var BOLD_ITALIC_UNDERSCORE = {
31232    format: ["bold", "italic"],
31233    intraword: false,
31234    tag: "___",
31235    type: "text-format"
31236  };
31237  var BOLD_STAR = {
31238    format: ["bold"],
31239    tag: "**",
31240    type: "text-format"
31241  };
31242  var BOLD_UNDERSCORE = {
31243    format: ["bold"],
31244    intraword: false,
31245    tag: "__",
31246    type: "text-format"
31247  };
31248  var STRIKETHROUGH = {
31249    format: ["strikethrough"],
31250    tag: "~~",
31251    type: "text-format"
31252  };
31253  var ITALIC_STAR = {
31254    format: ["italic"],
31255    tag: "*",
31256    type: "text-format"
31257  };
31258  var ITALIC_UNDERSCORE = {
31259    format: ["italic"],
31260    intraword: false,
31261    tag: "_",
31262    type: "text-format"
31263  };
31264  var LINK = {
31265    dependencies: [LinkNode2],
31266    export: (node, exportChildren2, exportFormat) => {
31267      if (!$isLinkNode2(node) || $isAutoLinkNode2(node)) {
31268        return null;
31269      }
31270      const textContent = exportChildren2(node);
31271      let title = node.getTitle();
31272      if (title != null) {
31273        title = title.replace(/([\\"])/g, "\\$1");
31274      }
31275      const linkContent = title ? `[${textContent}](${node.getURL()} "${title}")` : `[${textContent}](${node.getURL()})`;
31276      return linkContent;
31277    },
31278    importRegExp: /(?:\[(.+?)\])(?:\((?:([^()\s]+)(?:\s"((?:[^"]*\\")*[^"]*)"\s*)?)\))/,
31279    regExp: /(?:\[([^[\]]*(?:\[[^[\]]*\][^[\]]*)*)\])(?:\((?:([^()\s]+)(?:\s"((?:[^"]*\\")*[^"]*)"\s*)?)\))$/,
31280    replace: (textNode, match) => {
31281      if ($findMatchingParent2(textNode, $isLinkNode2)) {
31282        return;
31283      }
31284      const [, linkText, rawLinkUrl, rawLinkTitle] = match;
31285      const linkUrl = rawLinkUrl != null ? unescapeText(rawLinkUrl) : void 0;
31286      const linkTitle = rawLinkTitle != null ? unescapeText(rawLinkTitle) : void 0;
31287      const linkNode = $createLinkNode2(linkUrl, {
31288        title: linkTitle
31289      });
31290      const openBracketAmount = linkText.split("[").length - 1;
31291      const closeBracketAmount = linkText.split("]").length - 1;
31292      let parsedLinkText = linkText;
31293      let outsideLinkText = "";
31294      if (openBracketAmount < closeBracketAmount) {
31295        return;
31296      } else if (openBracketAmount > closeBracketAmount) {
31297        const linkTextParts = linkText.split("[");
31298        outsideLinkText = "[" + linkTextParts[0];
31299        parsedLinkText = linkTextParts.slice(1).join("[");
31300      }
31301      const linkTextNode = $createTextNode2(parsedLinkText);
31302      linkTextNode.setFormat(textNode.getFormat());
31303      linkNode.append(linkTextNode);
31304      textNode.replace(linkNode);
31305      if (outsideLinkText) {
31306        linkNode.insertBefore($createTextNode2(outsideLinkText));
31307      }
31308      return linkTextNode;
31309    },
31310    trigger: ")",
31311    type: "text-match"
31312  };
31313  var ELEMENT_TRANSFORMERS = [HEADING, QUOTE, UNORDERED_LIST, ORDERED_LIST];
31314  var MULTILINE_ELEMENT_TRANSFORMERS = [CODE];
31315  var TEXT_FORMAT_TRANSFORMERS = [INLINE_CODE, BOLD_ITALIC_STAR, BOLD_ITALIC_UNDERSCORE, BOLD_STAR, BOLD_UNDERSCORE, HIGHLIGHT, ITALIC_STAR, ITALIC_UNDERSCORE, STRIKETHROUGH];
31316  var TEXT_MATCH_TRANSFORMERS = [LINK];
31317  var TRANSFORMERS = [...ELEMENT_TRANSFORMERS, ...MULTILINE_ELEMENT_TRANSFORMERS, ...TEXT_FORMAT_TRANSFORMERS, ...TEXT_MATCH_TRANSFORMERS];
31318  function normalizeMarkdown(input, shouldMergeAdjacentLines = false) {
31319    const lines = input.split("\n");
31320    let inCodeBlock = false;
31321    const sanitizedLines = [];
31322    for (let i2 = 0; i2 < lines.length; i2++) {
31323      const rawLine = lines[i2];
31324      const line = rawLine.trimEnd();
31325      const lastLine = sanitizedLines[sanitizedLines.length - 1];
31326      if (CODE_SINGLE_LINE_REGEX.test(line)) {
31327        sanitizedLines.push(line);
31328        continue;
31329      }
31330      if (CODE_START_REGEX.test(line) || CODE_END_REGEX.test(line)) {
31331        inCodeBlock = !inCodeBlock;
31332        sanitizedLines.push(line);
31333        continue;
31334      }
31335      if (inCodeBlock) {
31336        sanitizedLines.push(rawLine);
31337        continue;
31338      }
31339      if (line === "" || lastLine === "" || !lastLine || HEADING_REGEX.test(lastLine) || HEADING_REGEX.test(line) || QUOTE_REGEX.test(line) || ORDERED_LIST_REGEX.test(line) || UNORDERED_LIST_REGEX.test(line) || CHECK_LIST_REGEX.test(line) || TABLE_ROW_REG_EXP.test(line) || TABLE_ROW_DIVIDER_REG_EXP.test(line) || !shouldMergeAdjacentLines || TAG_START_REGEX.test(line) || TAG_END_REGEX.test(line) || ENDS_WITH(TAG_END_REGEX).test(lastLine) || ENDS_WITH(TAG_START_REGEX).test(lastLine) || CODE_END_REGEX.test(lastLine)) {
31340        sanitizedLines.push(!shouldMergeAdjacentLines && line !== "" ? rawLine : line);
31341      } else {
31342        sanitizedLines[sanitizedLines.length - 1] = lastLine + " " + line.trimStart();
31343      }
31344    }
31345    return sanitizedLines.join("\n");
31346  }
31347  function runElementTransformers(parentNode, anchorNode, anchorOffset, elementTransformers) {
31348    const grandParentNode = parentNode.getParent();
31349    if (!$isRootOrShadowRoot2(grandParentNode) || parentNode.getFirstChild() !== anchorNode) {
31350      return false;
31351    }
31352    const textContent = anchorNode.getTextContent();
31353    if (textContent[anchorOffset - 1] !== " ") {
31354      return false;
31355    }
31356    for (const {
31357      regExp,
31358      replace
31359    } of elementTransformers) {
31360      const match = textContent.match(regExp);
31361      if (match && match[0].length === (match[0].endsWith(" ") ? anchorOffset : anchorOffset - 1)) {
31362        const nextSiblings = anchorNode.getNextSiblings();
31363        const [leadingNode, remainderNode] = anchorNode.splitText(anchorOffset);
31364        const siblings = remainderNode ? [remainderNode, ...nextSiblings] : nextSiblings;
31365        if (replace(parentNode, siblings, match, false) !== false) {
31366          leadingNode.remove();
31367          return true;
31368        }
31369      }
31370    }
31371    return false;
31372  }
31373  function runMultilineElementTransformers(parentNode, anchorNode, anchorOffset, elementTransformers, triggerOnEnter) {
31374    const grandParentNode = parentNode.getParent();
31375    if (!$isRootOrShadowRoot2(grandParentNode) || parentNode.getFirstChild() !== anchorNode) {
31376      return false;
31377    }
31378    const textContent = anchorNode.getTextContent();
31379    if (!triggerOnEnter) {
31380      if (textContent[anchorOffset - 1] !== " ") {
31381        return false;
31382      }
31383    }
31384    for (const {
31385      regExpStart,
31386      replace,
31387      regExpEnd
31388    } of elementTransformers) {
31389      if (regExpEnd && !("optional" in regExpEnd) || regExpEnd && "optional" in regExpEnd && !regExpEnd.optional) {
31390        continue;
31391      }
31392      const match = textContent.match(regExpStart);
31393      if (match) {
31394        const matchLength = triggerOnEnter || match[0].endsWith(" ") ? anchorOffset : anchorOffset - 1;
31395        if (match[0].length !== matchLength) {
31396          continue;
31397        }
31398        const nextSiblings = anchorNode.getNextSiblings();
31399        const [leadingNode, remainderNode] = anchorNode.splitText(anchorOffset);
31400        const siblings = remainderNode ? [remainderNode, ...nextSiblings] : nextSiblings;
31401        if (replace(parentNode, siblings, match, null, null, false) !== false) {
31402          leadingNode.remove();
31403          return true;
31404        }
31405      }
31406    }
31407    return false;
31408  }
31409  function runTextMatchTransformers(anchorNode, anchorOffset, transformersByTrigger) {
31410    let textContent = anchorNode.getTextContent();
31411    const lastChar = textContent[anchorOffset - 1];
31412    const transformers = transformersByTrigger[lastChar];
31413    if (transformers == null) {
31414      return false;
31415    }
31416    if (anchorOffset < textContent.length) {
31417      textContent = textContent.slice(0, anchorOffset);
31418    }
31419    for (const transformer of transformers) {
31420      if (!transformer.replace || !transformer.regExp) {
31421        continue;
31422      }
31423      const match = textContent.match(transformer.regExp);
31424      if (match === null) {
31425        continue;
31426      }
31427      const startIndex = match.index || 0;
31428      const endIndex = startIndex + match[0].length;
31429      let replaceNode;
31430      if (startIndex === 0) {
31431        [replaceNode] = anchorNode.splitText(endIndex);
31432      } else {
31433        [, replaceNode] = anchorNode.splitText(startIndex, endIndex);
31434      }
31435      replaceNode.selectNext(0, 0);
31436      transformer.replace(replaceNode, match);
31437      return true;
31438    }
31439    return false;
31440  }
31441  function $runTextFormatTransformers(anchorNode, anchorOffset, textFormatTransformers) {
31442    const textContent = anchorNode.getTextContent();
31443    const closeTagEndIndex = anchorOffset - 1;
31444    const closeChar = textContent[closeTagEndIndex];
31445    const matchers = textFormatTransformers[closeChar];
31446    if (!matchers) {
31447      return false;
31448    }
31449    for (const matcher of matchers) {
31450      const {
31451        tag
31452      } = matcher;
31453      const tagLength = tag.length;
31454      const closeTagStartIndex = closeTagEndIndex - tagLength + 1;
31455      if (tagLength > 1) {
31456        if (!isEqualSubString(textContent, closeTagStartIndex, tag, 0, tagLength)) {
31457          continue;
31458        }
31459      }
31460      if (textContent[closeTagStartIndex - 1] === " ") {
31461        continue;
31462      }
31463      const afterCloseTagChar = textContent[closeTagEndIndex + 1];
31464      if (matcher.intraword === false && afterCloseTagChar && !PUNCTUATION_OR_SPACE2.test(afterCloseTagChar)) {
31465        continue;
31466      }
31467      const closeNode = anchorNode;
31468      let openNode = closeNode;
31469      let openTagStartIndex = getOpenTagStartIndex(textContent, closeTagStartIndex, tag);
31470      let sibling = openNode;
31471      while (openTagStartIndex < 0 && (sibling = sibling.getPreviousSibling())) {
31472        if ($isLineBreakNode2(sibling)) {
31473          break;
31474        }
31475        if ($isTextNode2(sibling)) {
31476          if (sibling.hasFormat("code")) {
31477            continue;
31478          }
31479          const siblingTextContent = sibling.getTextContent();
31480          openNode = sibling;
31481          openTagStartIndex = getOpenTagStartIndex(siblingTextContent, siblingTextContent.length, tag);
31482        }
31483      }
31484      if (openTagStartIndex < 0) {
31485        continue;
31486      }
31487      if (openNode === closeNode && openTagStartIndex + tagLength === closeTagStartIndex) {
31488        continue;
31489      }
31490      const prevOpenNodeText = openNode.getTextContent();
31491      if (openTagStartIndex > 0 && prevOpenNodeText[openTagStartIndex - 1] === closeChar) {
31492        continue;
31493      }
31494      const beforeOpenTagChar = prevOpenNodeText[openTagStartIndex - 1];
31495      if (matcher.intraword === false && beforeOpenTagChar && !PUNCTUATION_OR_SPACE2.test(beforeOpenTagChar)) {
31496        continue;
31497      }
31498      if (!matcher.format.includes("code") && $isInsideUnclosedCodeSpan(openNode, openTagStartIndex)) {
31499        continue;
31500      }
31501      const prevCloseNodeText = closeNode.getTextContent();
31502      const closeNodeText = prevCloseNodeText.slice(0, closeTagStartIndex) + prevCloseNodeText.slice(closeTagEndIndex + 1);
31503      closeNode.setTextContent(closeNodeText);
31504      const openNodeText = openNode === closeNode ? closeNodeText : prevOpenNodeText;
31505      openNode.setTextContent(openNodeText.slice(0, openTagStartIndex) + openNodeText.slice(openTagStartIndex + tagLength));
31506      const selection = $getSelection2();
31507      const nextSelection = $createRangeSelection2();
31508      $setSelection2(nextSelection);
31509      const newOffset = closeTagEndIndex - tagLength * (openNode === closeNode ? 2 : 1) + 1;
31510      nextSelection.anchor.set(openNode.__key, openTagStartIndex, "text");
31511      nextSelection.focus.set(closeNode.__key, newOffset, "text");
31512      for (const format of matcher.format) {
31513        if (!nextSelection.hasFormat(format)) {
31514          nextSelection.formatText(format);
31515        }
31516      }
31517      nextSelection.anchor.set(nextSelection.focus.key, nextSelection.focus.offset, nextSelection.focus.type);
31518      for (const format of matcher.format) {
31519        if (nextSelection.hasFormat(format)) {
31520          nextSelection.toggleFormat(format);
31521        }
31522      }
31523      if ($isRangeSelection2(selection)) {
31524        nextSelection.format = selection.format;
31525      }
31526      return true;
31527    }
31528    return false;
31529  }
31530  function $isInsideUnclosedCodeSpan(node, offset3) {
31531    let backtickCount = 0;
31532    const text2 = node.getTextContent();
31533    for (let i2 = 0; i2 < offset3; i2++) {
31534      if (text2[i2] === "`") {
31535        backtickCount++;
31536      }
31537    }
31538    return backtickCount % 2 !== 0;
31539  }
31540  function getOpenTagStartIndex(string, maxIndex, tag) {
31541    const tagLength = tag.length;
31542    for (let i2 = maxIndex; i2 >= tagLength; i2--) {
31543      const startIndex = i2 - tagLength;
31544      if (isEqualSubString(string, startIndex, tag, 0, tagLength) && // Space after opening tag cancels transformation
31545      string[startIndex + tagLength] !== " ") {
31546        return startIndex;
31547      }
31548    }
31549    return -1;
31550  }
31551  function isEqualSubString(stringA, aStart, stringB, bStart, length) {
31552    for (let i2 = 0; i2 < length; i2++) {
31553      if (stringA[aStart + i2] !== stringB[bStart + i2]) {
31554        return false;
31555      }
31556    }
31557    return true;
31558  }
31559  function registerMarkdownShortcuts(editor, transformers = TRANSFORMERS) {
31560    const byType = transformersByType(transformers);
31561    const textFormatTransformersByTrigger = indexBy(byType.textFormat, ({
31562      tag
31563    }) => tag[tag.length - 1]);
31564    const textMatchTransformersByTrigger = indexBy(byType.textMatch, ({
31565      trigger
31566    }) => trigger);
31567    for (const transformer of transformers) {
31568      const type = transformer.type;
31569      if (type === "element" || type === "text-match" || type === "multiline-element") {
31570        const dependencies = transformer.dependencies;
31571        for (const node of dependencies) {
31572          if (!editor.hasNode(node)) {
31573            {
31574              formatDevErrorMessage11(`MarkdownShortcuts: missing dependency ${node.getType()} for transformer. Ensure node dependency is included in editor initial config.`);
31575            }
31576          }
31577        }
31578      }
31579    }
31580    const $transform = (parentNode, anchorNode, anchorOffset) => {
31581      if (runElementTransformers(parentNode, anchorNode, anchorOffset, byType.element)) {
31582        return true;
31583      }
31584      if (runMultilineElementTransformers(parentNode, anchorNode, anchorOffset, byType.multilineElement)) {
31585        return true;
31586      }
31587      if (runTextMatchTransformers(anchorNode, anchorOffset, textMatchTransformersByTrigger)) {
31588        return true;
31589      }
31590      if ($runTextFormatTransformers(anchorNode, anchorOffset, textFormatTransformersByTrigger)) {
31591        return true;
31592      }
31593      return false;
31594    };
31595    return mergeRegister2(editor.registerUpdateListener(({
31596      tags,
31597      dirtyLeaves,
31598      editorState,
31599      prevEditorState
31600    }) => {
31601      if (tags.has(COLLABORATION_TAG2) || tags.has(HISTORIC_TAG2)) {
31602        return;
31603      }
31604      if (editor.isComposing()) {
31605        return;
31606      }
31607      const selection = editorState.read($getSelection2);
31608      const prevSelection = prevEditorState.read($getSelection2);
31609      if (!$isRangeSelection2(prevSelection) || !$isRangeSelection2(selection) || !selection.isCollapsed() || selection.is(prevSelection)) {
31610        return;
31611      }
31612      const anchorKey = selection.anchor.key;
31613      const anchorOffset = selection.anchor.offset;
31614      const anchorNode = editorState._nodeMap.get(anchorKey);
31615      if (!$isTextNode2(anchorNode) || !dirtyLeaves.has(anchorKey) || anchorOffset !== 1 && anchorOffset > prevSelection.anchor.offset + 1) {
31616        return;
31617      }
31618      editor.update(() => {
31619        if (!canContainTransformableMarkdown(anchorNode)) {
31620          return;
31621        }
31622        const parentNode = anchorNode.getParent();
31623        if (parentNode === null || $isCodeNode2(parentNode)) {
31624          return;
31625        }
31626        if ($transform(parentNode, anchorNode, selection.anchor.offset)) {
31627          $addUpdateTag2(HISTORY_PUSH_TAG2);
31628        }
31629      });
31630    }), editor.registerCommand(KEY_ENTER_COMMAND2, (event) => {
31631      if (event !== null && event.shiftKey) {
31632        return false;
31633      }
31634      const selection = $getSelection2();
31635      if (!$isRangeSelection2(selection) || !selection.isCollapsed()) {
31636        return false;
31637      }
31638      const anchorOffset = selection.anchor.offset;
31639      const anchorNode = selection.anchor.getNode();
31640      if (!$isTextNode2(anchorNode) || !canContainTransformableMarkdown(anchorNode)) {
31641        return false;
31642      }
31643      const parentNode = anchorNode.getParent();
31644      if (parentNode === null || $isCodeNode2(parentNode)) {
31645        return false;
31646      }
31647      const textContent = anchorNode.getTextContent();
31648      if (anchorOffset !== textContent.length) {
31649        return false;
31650      }
31651      if (runMultilineElementTransformers(parentNode, anchorNode, anchorOffset, byType.multilineElement, true)) {
31652        if (event !== null) {
31653          event.preventDefault();
31654        }
31655        return true;
31656      }
31657      return false;
31658    }, COMMAND_PRIORITY_LOW2));
31659  }
31660  function $convertFromMarkdownString(markdown, transformers = TRANSFORMERS, node, shouldPreserveNewLines = false, shouldMergeAdjacentLines = false) {
31661    const sanitizedMarkdown = shouldPreserveNewLines ? markdown : normalizeMarkdown(markdown, shouldMergeAdjacentLines);
31662    const importMarkdown = createMarkdownImport(transformers, shouldPreserveNewLines);
31663    return importMarkdown(sanitizedMarkdown, node);
31664  }
31665  function $convertToMarkdownString(transformers = TRANSFORMERS, node, shouldPreserveNewLines = false) {
31666    const exportMarkdown = createMarkdownExport(transformers, shouldPreserveNewLines);
31667    return exportMarkdown(node);
31668  }
31669
31670  
vendor: 1,296 bytes, lines 31670-31697
31670// node_modules/@lexical/markdown/LexicalMarkdown.mjs
31671  var mod16 = true ? LexicalMarkdown_dev_exports : LexicalMarkdown_prod_exports;
31672  var $convertFromMarkdownString2 = mod16.$convertFromMarkdownString;
31673  var $convertToMarkdownString2 = mod16.$convertToMarkdownString;
31674  var BOLD_ITALIC_STAR2 = mod16.BOLD_ITALIC_STAR;
31675  var BOLD_ITALIC_UNDERSCORE2 = mod16.BOLD_ITALIC_UNDERSCORE;
31676  var BOLD_STAR2 = mod16.BOLD_STAR;
31677  var BOLD_UNDERSCORE2 = mod16.BOLD_UNDERSCORE;
31678  var CHECK_LIST2 = mod16.CHECK_LIST;
31679  var CODE2 = mod16.CODE;
31680  var ELEMENT_TRANSFORMERS2 = mod16.ELEMENT_TRANSFORMERS;
31681  var HEADING2 = mod16.HEADING;
31682  var HIGHLIGHT2 = mod16.HIGHLIGHT;
31683  var INLINE_CODE2 = mod16.INLINE_CODE;
31684  var ITALIC_STAR2 = mod16.ITALIC_STAR;
31685  var ITALIC_UNDERSCORE2 = mod16.ITALIC_UNDERSCORE;
31686  var LINK2 = mod16.LINK;
31687  var MULTILINE_ELEMENT_TRANSFORMERS2 = mod16.MULTILINE_ELEMENT_TRANSFORMERS;
31688  var ORDERED_LIST2 = mod16.ORDERED_LIST;
31689  var QUOTE2 = mod16.QUOTE;
31690  var STRIKETHROUGH2 = mod16.STRIKETHROUGH;
31691  var TEXT_FORMAT_TRANSFORMERS2 = mod16.TEXT_FORMAT_TRANSFORMERS;
31692  var TEXT_MATCH_TRANSFORMERS2 = mod16.TEXT_MATCH_TRANSFORMERS;
31693  var TRANSFORMERS2 = mod16.TRANSFORMERS;
31694  var UNORDERED_LIST2 = mod16.UNORDERED_LIST;
31695  var registerMarkdownShortcuts2 = mod16.registerMarkdownShortcuts;
31696
31697  
vendor: 165,474 bytes, lines 31697-35877
31697// node_modules/@lexical/table/LexicalTable.dev.mjs
31698  var LexicalTable_dev_exports = {};
31699  __export(LexicalTable_dev_exports, {
31700    $computeTableMap: () => $computeTableMap,
31701    $computeTableMapSkipCellCheck: () => $computeTableMapSkipCellCheck,
31702    $createTableCellNode: () => $createTableCellNode,
31703    $createTableNode: () => $createTableNode,
31704    $createTableNodeWithDimensions: () => $createTableNodeWithDimensions,
31705    $createTableRowNode: () => $createTableRowNode,
31706    $createTableSelection: () => $createTableSelection,
31707    $createTableSelectionFrom: () => $createTableSelectionFrom,
31708    $deleteTableColumn: () => $deleteTableColumn,
31709    $deleteTableColumnAtSelection: () => $deleteTableColumnAtSelection,
31710    $deleteTableColumn__EXPERIMENTAL: () => $deleteTableColumn__EXPERIMENTAL,
31711    $deleteTableRowAtSelection: () => $deleteTableRowAtSelection,
31712    $deleteTableRow__EXPERIMENTAL: () => $deleteTableRow__EXPERIMENTAL,
31713    $findCellNode: () => $findCellNode,
31714    $findTableNode: () => $findTableNode,
31715    $getElementForTableNode: () => $getElementForTableNode,
31716    $getNodeTriplet: () => $getNodeTriplet,
31717    $getTableAndElementByKey: () => $getTableAndElementByKey,
31718    $getTableCellNodeFromLexicalNode: () => $getTableCellNodeFromLexicalNode,
31719    $getTableCellNodeRect: () => $getTableCellNodeRect,
31720    $getTableColumnIndexFromTableCellNode: () => $getTableColumnIndexFromTableCellNode,
31721    $getTableNodeFromLexicalNodeOrThrow: () => $getTableNodeFromLexicalNodeOrThrow,
31722    $getTableRowIndexFromTableCellNode: () => $getTableRowIndexFromTableCellNode,
31723    $getTableRowNodeFromTableCellNodeOrThrow: () => $getTableRowNodeFromTableCellNodeOrThrow,
31724    $insertTableColumn: () => $insertTableColumn,
31725    $insertTableColumnAtSelection: () => $insertTableColumnAtSelection,
31726    $insertTableColumn__EXPERIMENTAL: () => $insertTableColumn__EXPERIMENTAL,
31727    $insertTableRow: () => $insertTableRow,
31728    $insertTableRowAtSelection: () => $insertTableRowAtSelection,
31729    $insertTableRow__EXPERIMENTAL: () => $insertTableRow__EXPERIMENTAL,
31730    $isScrollableTablesActive: () => $isScrollableTablesActive,
31731    $isSimpleTable: () => $isSimpleTable,
31732    $isTableCellNode: () => $isTableCellNode,
31733    $isTableNode: () => $isTableNode,
31734    $isTableRowNode: () => $isTableRowNode,
31735    $isTableSelection: () => $isTableSelection,
31736    $mergeCells: () => $mergeCells,
31737    $moveTableColumn: () => $moveTableColumn,
31738    $removeTableRowAtIndex: () => $removeTableRowAtIndex,
31739    $unmergeCell: () => $unmergeCell,
31740    INSERT_TABLE_COMMAND: () => INSERT_TABLE_COMMAND,
31741    TableCellHeaderStates: () => TableCellHeaderStates,
31742    TableCellNode: () => TableCellNode,
31743    TableExtension: () => TableExtension,
31744    TableNode: () => TableNode,
31745    TableObserver: () => TableObserver,
31746    TableRowNode: () => TableRowNode,
31747    applyTableHandlers: () => applyTableHandlers,
31748    getDOMCellFromTarget: () => getDOMCellFromTarget,
31749    getTableElement: () => getTableElement,
31750    getTableObserverFromTableElement: () => getTableObserverFromTableElement,
31751    registerTableCellUnmergeTransform: () => registerTableCellUnmergeTransform,
31752    registerTablePlugin: () => registerTablePlugin,
31753    registerTableSelectionObserver: () => registerTableSelectionObserver,
31754    setScrollableTablesActive: () => setScrollableTablesActive
31755  });
31756  var PIXEL_VALUE_REG_EXP = /^(\d+(?:\.\d+)?)px$/;
31757  var COLUMN_WIDTH = 75;
31758  var TableCellHeaderStates = {
31759    BOTH: 3,
31760    COLUMN: 2,
31761    NO_STATUS: 0,
31762    ROW: 1
31763  };
31764  var TableCellNode = class _TableCellNode extends ElementNode2 {
31765    /** @internal */
31766    __colSpan;
31767    /** @internal */
31768    __rowSpan;
31769    /** @internal */
31770    __headerState;
31771    /** @internal */
31772    __width;
31773    /** @internal */
31774    __backgroundColor;
31775    /** @internal */
31776    __verticalAlign;
31777    static getType() {
31778      return "tablecell";
31779    }
31780    static clone(node) {
31781      return new _TableCellNode(node.__headerState, node.__colSpan, node.__width, node.__key);
31782    }
31783    afterCloneFrom(node) {
31784      super.afterCloneFrom(node);
31785      this.__rowSpan = node.__rowSpan;
31786      this.__backgroundColor = node.__backgroundColor;
31787      this.__verticalAlign = node.__verticalAlign;
31788      this.__colSpan = node.__colSpan;
31789      this.__headerState = node.__headerState;
31790      this.__width = node.__width;
31791    }
31792    static importDOM() {
31793      return {
31794        td: (node) => ({
31795          conversion: $convertTableCellNodeElement,
31796          priority: 0
31797        }),
31798        th: (node) => ({
31799          conversion: $convertTableCellNodeElement,
31800          priority: 0
31801        })
31802      };
31803    }
31804    static importJSON(serializedNode) {
31805      return $createTableCellNode().updateFromJSON(serializedNode);
31806    }
31807    updateFromJSON(serializedNode) {
31808      return super.updateFromJSON(serializedNode).setHeaderStyles(serializedNode.headerState).setColSpan(serializedNode.colSpan || 1).setRowSpan(serializedNode.rowSpan || 1).setWidth(serializedNode.width || void 0).setBackgroundColor(serializedNode.backgroundColor || null).setVerticalAlign(serializedNode.verticalAlign || void 0);
31809    }
31810    constructor(headerState = TableCellHeaderStates.NO_STATUS, colSpan = 1, width, key) {
31811      super(key);
31812      this.__colSpan = colSpan;
31813      this.__rowSpan = 1;
31814      this.__headerState = headerState;
31815      this.__width = width;
31816      this.__backgroundColor = null;
31817      this.__verticalAlign = void 0;
31818    }
31819    createDOM(config) {
31820      const element = document.createElement(this.getTag());
31821      if (this.__width) {
31822        element.style.width = `${this.__width}px`;
31823      }
31824      if (this.__colSpan > 1) {
31825        element.colSpan = this.__colSpan;
31826      }
31827      if (this.__rowSpan > 1) {
31828        element.rowSpan = this.__rowSpan;
31829      }
31830      if (this.__backgroundColor !== null) {
31831        element.style.backgroundColor = this.__backgroundColor;
31832      }
31833      if (isValidVerticalAlign(this.__verticalAlign)) {
31834        element.style.verticalAlign = this.__verticalAlign;
31835      }
31836      addClassNamesToElement3(element, config.theme.tableCell, this.hasHeader() && config.theme.tableCellHeader);
31837      return element;
31838    }
31839    exportDOM(editor) {
31840      const output = super.exportDOM(editor);
31841      if (isHTMLElement2(output.element)) {
31842        const element = output.element;
31843        element.setAttribute("data-temporary-table-cell-lexical-key", this.getKey());
31844        element.style.border = "1px solid black";
31845        if (this.__colSpan > 1) {
31846          element.colSpan = this.__colSpan;
31847        }
31848        if (this.__rowSpan > 1) {
31849          element.rowSpan = this.__rowSpan;
31850        }
31851        element.style.width = `${this.getWidth() || COLUMN_WIDTH}px`;
31852        element.style.verticalAlign = this.getVerticalAlign() || "top";
31853        element.style.textAlign = "start";
31854        if (this.__backgroundColor === null && this.hasHeader()) {
31855          element.style.backgroundColor = "#f2f3f5";
31856        }
31857      }
31858      return output;
31859    }
31860    exportJSON() {
31861      return {
31862        ...super.exportJSON(),
31863        ...isValidVerticalAlign(this.__verticalAlign) && {
31864          verticalAlign: this.__verticalAlign
31865        },
31866        backgroundColor: this.getBackgroundColor(),
31867        colSpan: this.__colSpan,
31868        headerState: this.__headerState,
31869        rowSpan: this.__rowSpan,
31870        width: this.getWidth()
31871      };
31872    }
31873    getColSpan() {
31874      return this.getLatest().__colSpan;
31875    }
31876    setColSpan(colSpan) {
31877      const self2 = this.getWritable();
31878      self2.__colSpan = colSpan;
31879      return self2;
31880    }
31881    getRowSpan() {
31882      return this.getLatest().__rowSpan;
31883    }
31884    setRowSpan(rowSpan) {
31885      const self2 = this.getWritable();
31886      self2.__rowSpan = rowSpan;
31887      return self2;
31888    }
31889    getTag() {
31890      return this.hasHeader() ? "th" : "td";
31891    }
31892    setHeaderStyles(headerState, mask = TableCellHeaderStates.BOTH) {
31893      const self2 = this.getWritable();
31894      self2.__headerState = headerState & mask | self2.__headerState & ~mask;
31895      return self2;
31896    }
31897    getHeaderStyles() {
31898      return this.getLatest().__headerState;
31899    }
31900    setWidth(width) {
31901      const self2 = this.getWritable();
31902      self2.__width = width;
31903      return self2;
31904    }
31905    getWidth() {
31906      return this.getLatest().__width;
31907    }
31908    getBackgroundColor() {
31909      return this.getLatest().__backgroundColor;
31910    }
31911    setBackgroundColor(newBackgroundColor) {
31912      const self2 = this.getWritable();
31913      self2.__backgroundColor = newBackgroundColor;
31914      return self2;
31915    }
31916    getVerticalAlign() {
31917      return this.getLatest().__verticalAlign;
31918    }
31919    setVerticalAlign(newVerticalAlign) {
31920      const self2 = this.getWritable();
31921      self2.__verticalAlign = newVerticalAlign || void 0;
31922      return self2;
31923    }
31924    toggleHeaderStyle(headerStateToToggle) {
31925      const self2 = this.getWritable();
31926      if ((self2.__headerState & headerStateToToggle) === headerStateToToggle) {
31927        self2.__headerState -= headerStateToToggle;
31928      } else {
31929        self2.__headerState += headerStateToToggle;
31930      }
31931      return self2;
31932    }
31933    hasHeaderState(headerState) {
31934      return (this.getHeaderStyles() & headerState) === headerState;
31935    }
31936    hasHeader() {
31937      return this.getLatest().__headerState !== TableCellHeaderStates.NO_STATUS;
31938    }
31939    updateDOM(prevNode) {
31940      return prevNode.__headerState !== this.__headerState || prevNode.__width !== this.__width || prevNode.__colSpan !== this.__colSpan || prevNode.__rowSpan !== this.__rowSpan || prevNode.__backgroundColor !== this.__backgroundColor || prevNode.__verticalAlign !== this.__verticalAlign;
31941    }
31942    isShadowRoot() {
31943      return true;
31944    }
31945    collapseAtStart() {
31946      return true;
31947    }
31948    canBeEmpty() {
31949      return false;
31950    }
31951    canIndent() {
31952      return false;
31953    }
31954  };
31955  function isValidVerticalAlign(verticalAlign) {
31956    return verticalAlign === "middle" || verticalAlign === "bottom";
31957  }
31958  function $convertTableCellNodeElement(domNode) {
31959    const domNode_ = domNode;
31960    const nodeName = domNode.nodeName.toLowerCase();
31961    let width = void 0;
31962    if (PIXEL_VALUE_REG_EXP.test(domNode_.style.width)) {
31963      width = parseFloat(domNode_.style.width);
31964    }
31965    let headerState = TableCellHeaderStates.NO_STATUS;
31966    if (nodeName === "th") {
31967      const scope = domNode_.getAttribute("scope");
31968      if (scope === "col") {
31969        headerState = TableCellHeaderStates.COLUMN;
31970      } else if (scope === "row") {
31971        headerState = TableCellHeaderStates.ROW;
31972      } else {
31973        const parentRow = domNode_.parentElement;
31974        const isInHeaderRow = isHTMLElement2(parentRow) && parentRow.nodeName.toLowerCase() === "tr" && isHTMLElement2(parentRow.parentElement) && (parentRow.parentElement.nodeName.toLowerCase() === "thead" || parentRow.rowIndex === 0);
31975        const isFirstColumn = domNode_.cellIndex === 0;
31976        if (isInHeaderRow) {
31977          headerState |= TableCellHeaderStates.ROW;
31978        }
31979        if (isFirstColumn) {
31980          headerState |= TableCellHeaderStates.COLUMN;
31981        }
31982        if (headerState === TableCellHeaderStates.NO_STATUS) {
31983          headerState = TableCellHeaderStates.ROW;
31984        }
31985      }
31986    }
31987    const tableCellNode = $createTableCellNode(headerState, domNode_.colSpan, width);
31988    tableCellNode.__rowSpan = domNode_.rowSpan;
31989    const backgroundColor = domNode_.style.backgroundColor;
31990    if (backgroundColor !== "") {
31991      tableCellNode.__backgroundColor = backgroundColor;
31992    }
31993    const verticalAlign = domNode_.style.verticalAlign;
31994    if (isValidVerticalAlign(verticalAlign)) {
31995      tableCellNode.__verticalAlign = verticalAlign;
31996    }
31997    const style = domNode_.style;
31998    const textDecoration = (style && style.textDecoration || "").split(" ");
31999    const hasBoldFontWeight = style.fontWeight === "700" || style.fontWeight === "bold";
32000    const hasLinethroughTextDecoration = textDecoration.includes("line-through");
32001    const hasItalicFontStyle = style.fontStyle === "italic";
32002    const hasUnderlineTextDecoration = textDecoration.includes("underline");
32003    const color = style.color;
32004    return {
32005      after: (childLexicalNodes) => {
32006        const result = [];
32007        let paragraphNode = null;
32008        const removeSingleLineBreakNode = () => {
32009          if (paragraphNode) {
32010            const firstChild = paragraphNode.getFirstChild();
32011            if ($isLineBreakNode2(firstChild) && paragraphNode.getChildrenSize() === 1) {
32012              firstChild.remove();
32013            }
32014          }
32015        };
32016        for (const child of childLexicalNodes) {
32017          if ($isInlineElementOrDecoratorNode2(child) || $isTextNode2(child) || $isLineBreakNode2(child)) {
32018            if ($isTextNode2(child)) {
32019              if (hasBoldFontWeight) {
32020                child.toggleFormat("bold");
32021              }
32022              if (hasLinethroughTextDecoration) {
32023                child.toggleFormat("strikethrough");
32024              }
32025              if (hasItalicFontStyle) {
32026                child.toggleFormat("italic");
32027              }
32028              if (hasUnderlineTextDecoration) {
32029                child.toggleFormat("underline");
32030              }
32031              if (color) {
32032                const existingStyle = child.getStyle();
32033                if (!existingStyle.includes("color:")) {
32034                  child.setStyle(existingStyle + `color: ${color};`);
32035                }
32036              }
32037            }
32038            if (paragraphNode) {
32039              paragraphNode.append(child);
32040            } else {
32041              paragraphNode = $createParagraphNode2().append(child);
32042              result.push(paragraphNode);
32043            }
32044          } else {
32045            result.push(child);
32046            removeSingleLineBreakNode();
32047            paragraphNode = null;
32048          }
32049        }
32050        removeSingleLineBreakNode();
32051        if (result.length === 0) {
32052          result.push($createParagraphNode2());
32053        }
32054        return result;
32055      },
32056      node: tableCellNode
32057    };
32058  }
32059  function $createTableCellNode(headerState = TableCellHeaderStates.NO_STATUS, colSpan = 1, width) {
32060    return $applyNodeReplacement2(new TableCellNode(headerState, colSpan, width));
32061  }
32062  function $isTableCellNode(node) {
32063    return node instanceof TableCellNode;
32064  }
32065  var INSERT_TABLE_COMMAND = createCommand2("INSERT_TABLE_COMMAND");
32066  function formatDevErrorMessage12(message) {
32067    throw new Error(message);
32068  }
32069  var TableRowNode = class _TableRowNode extends ElementNode2 {
32070    /** @internal */
32071    __height;
32072    static getType() {
32073      return "tablerow";
32074    }
32075    static clone(node) {
32076      return new _TableRowNode(node.__height, node.__key);
32077    }
32078    afterCloneFrom(prevNode) {
32079      super.afterCloneFrom(prevNode);
32080      this.__height = prevNode.__height;
32081    }
32082    static importDOM() {
32083      return {
32084        tr: (node) => ({
32085          conversion: $convertTableRowElement,
32086          priority: 0
32087        })
32088      };
32089    }
32090    static importJSON(serializedNode) {
32091      return $createTableRowNode().updateFromJSON(serializedNode);
32092    }
32093    updateFromJSON(serializedNode) {
32094      return super.updateFromJSON(serializedNode).setHeight(serializedNode.height);
32095    }
32096    constructor(height, key) {
32097      super(key);
32098      this.__height = height;
32099    }
32100    exportJSON() {
32101      const height = this.getHeight();
32102      return {
32103        ...super.exportJSON(),
32104        ...height === void 0 ? void 0 : {
32105          height
32106        }
32107      };
32108    }
32109    createDOM(config) {
32110      const element = document.createElement("tr");
32111      if (this.__height) {
32112        element.style.height = `${this.__height}px`;
32113      }
32114      addClassNamesToElement3(element, config.theme.tableRow);
32115      return element;
32116    }
32117    extractWithChild(child, selection, destination) {
32118      return destination === "html";
32119    }
32120    isShadowRoot() {
32121      return true;
32122    }
32123    setHeight(height) {
32124      const self2 = this.getWritable();
32125      self2.__height = height;
32126      return self2;
32127    }
32128    getHeight() {
32129      return this.getLatest().__height;
32130    }
32131    updateDOM(prevNode) {
32132      return prevNode.__height !== this.__height;
32133    }
32134    canBeEmpty() {
32135      return false;
32136    }
32137    canIndent() {
32138      return false;
32139    }
32140  };
32141  function $convertTableRowElement(domNode) {
32142    const domNode_ = domNode;
32143    let height = void 0;
32144    if (PIXEL_VALUE_REG_EXP.test(domNode_.style.height)) {
32145      height = parseFloat(domNode_.style.height);
32146    }
32147    return {
32148      after: (children) => $descendantsMatching2(children, $isTableCellNode),
32149      node: $createTableRowNode(height)
32150    };
32151  }
32152  function $createTableRowNode(height) {
32153    return $applyNodeReplacement2(new TableRowNode(height));
32154  }
32155  function $isTableRowNode(node) {
32156    return node instanceof TableRowNode;
32157  }
32158  var CAN_USE_DOM6 = typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.document.createElement !== "undefined";
32159  var documentMode5 = CAN_USE_DOM6 && "documentMode" in document ? document.documentMode : null;
32160  var IS_FIREFOX4 = CAN_USE_DOM6 && /^(?!.*Seamonkey)(?=.*Firefox).*/i.test(navigator.userAgent);
32161  CAN_USE_DOM6 && "InputEvent" in window && !documentMode5 ? "getTargetRanges" in new window.InputEvent("input") : false;
32162  function $createTableNodeWithDimensions(rowCount, columnCount, includeHeaders = true) {
32163    const tableNode = $createTableNode();
32164    for (let iRow = 0; iRow < rowCount; iRow++) {
32165      const tableRowNode = $createTableRowNode();
32166      for (let iColumn = 0; iColumn < columnCount; iColumn++) {
32167        let headerState = TableCellHeaderStates.NO_STATUS;
32168        if (typeof includeHeaders === "object") {
32169          if (iRow === 0 && includeHeaders.rows) {
32170            headerState |= TableCellHeaderStates.ROW;
32171          }
32172          if (iColumn === 0 && includeHeaders.columns) {
32173            headerState |= TableCellHeaderStates.COLUMN;
32174          }
32175        } else if (includeHeaders) {
32176          if (iRow === 0) {
32177            headerState |= TableCellHeaderStates.ROW;
32178          }
32179          if (iColumn === 0) {
32180            headerState |= TableCellHeaderStates.COLUMN;
32181          }
32182        }
32183        const tableCellNode = $createTableCellNode(headerState);
32184        const paragraphNode = $createParagraphNode2();
32185        paragraphNode.append($createTextNode2());
32186        tableCellNode.append(paragraphNode);
32187        tableRowNode.append(tableCellNode);
32188      }
32189      tableNode.append(tableRowNode);
32190    }
32191    return tableNode;
32192  }
32193  function $getTableCellNodeFromLexicalNode(startingNode) {
32194    const node = $findMatchingParent3(startingNode, (n2) => $isTableCellNode(n2));
32195    if ($isTableCellNode(node)) {
32196      return node;
32197    }
32198    return null;
32199  }
32200  function $getTableRowNodeFromTableCellNodeOrThrow(startingNode) {
32201    const node = $findMatchingParent3(startingNode, (n2) => $isTableRowNode(n2));
32202    if ($isTableRowNode(node)) {
32203      return node;
32204    }
32205    throw new Error("Expected table cell to be inside of table row.");
32206  }
32207  function $getTableNodeFromLexicalNodeOrThrow(startingNode) {
32208    const node = $findMatchingParent3(startingNode, (n2) => $isTableNode(n2));
32209    if ($isTableNode(node)) {
32210      return node;
32211    }
32212    throw new Error("Expected table cell to be inside of table.");
32213  }
32214  function $getTableRowIndexFromTableCellNode(tableCellNode) {
32215    const tableRowNode = $getTableRowNodeFromTableCellNodeOrThrow(tableCellNode);
32216    const tableNode = $getTableNodeFromLexicalNodeOrThrow(tableRowNode);
32217    return tableNode.getChildren().findIndex((n2) => n2.is(tableRowNode));
32218  }
32219  function $getTableColumnIndexFromTableCellNode(tableCellNode) {
32220    const tableRowNode = $getTableRowNodeFromTableCellNodeOrThrow(tableCellNode);
32221    return tableRowNode.getChildren().findIndex((n2) => n2.is(tableCellNode));
32222  }
32223  function $getTableCellSiblingsFromTableCellNode(tableCellNode, table) {
32224    const tableNode = $getTableNodeFromLexicalNodeOrThrow(tableCellNode);
32225    const {
32226      x: x3,
32227      y: y3
32228    } = tableNode.getCordsFromCellNode(tableCellNode, table);
32229    return {
32230      above: tableNode.getCellNodeFromCords(x3, y3 - 1, table),
32231      below: tableNode.getCellNodeFromCords(x3, y3 + 1, table),
32232      left: tableNode.getCellNodeFromCords(x3 - 1, y3, table),
32233      right: tableNode.getCellNodeFromCords(x3 + 1, y3, table)
32234    };
32235  }
32236  function $removeTableRowAtIndex(tableNode, indexToDelete) {
32237    const tableRows = tableNode.getChildren();
32238    if (indexToDelete >= tableRows.length || indexToDelete < 0) {
32239      throw new Error("Expected table cell to be inside of table row.");
32240    }
32241    const targetRowNode = tableRows[indexToDelete];
32242    targetRowNode.remove();
32243    return tableNode;
32244  }
32245  function $insertTableRow(tableNode, targetIndex, shouldInsertAfter = true, rowCount, table) {
32246    const tableRows = tableNode.getChildren();
32247    if (targetIndex >= tableRows.length || targetIndex < 0) {
32248      throw new Error("Table row target index out of range");
32249    }
32250    const targetRowNode = tableRows[targetIndex];
32251    if ($isTableRowNode(targetRowNode)) {
32252      for (let r2 = 0; r2 < rowCount; r2++) {
32253        const tableRowCells = targetRowNode.getChildren();
32254        const tableColumnCount = tableRowCells.length;
32255        const newTableRowNode = $createTableRowNode();
32256        for (let c2 = 0; c2 < tableColumnCount; c2++) {
32257          const tableCellFromTargetRow = tableRowCells[c2];
32258          if (!$isTableCellNode(tableCellFromTargetRow)) {
32259            formatDevErrorMessage12(`Expected table cell`);
32260          }
32261          const {
32262            above,
32263            below
32264          } = $getTableCellSiblingsFromTableCellNode(tableCellFromTargetRow, table);
32265          let headerState = TableCellHeaderStates.NO_STATUS;
32266          const width = above && above.getWidth() || below && below.getWidth() || void 0;
32267          if (above && above.hasHeaderState(TableCellHeaderStates.COLUMN) || below && below.hasHeaderState(TableCellHeaderStates.COLUMN)) {
32268            headerState |= TableCellHeaderStates.COLUMN;
32269          }
32270          const tableCellNode = $createTableCellNode(headerState, 1, width);
32271          tableCellNode.append($createParagraphNode2());
32272          newTableRowNode.append(tableCellNode);
32273        }
32274        if (shouldInsertAfter) {
32275          targetRowNode.insertAfter(newTableRowNode);
32276        } else {
32277          targetRowNode.insertBefore(newTableRowNode);
32278        }
32279      }
32280    } else {
32281      throw new Error("Row before insertion index does not exist.");
32282    }
32283    return tableNode;
32284  }
32285  var getHeaderState = (currentState, possibleState) => {
32286    if (currentState === TableCellHeaderStates.BOTH || currentState === possibleState) {
32287      return possibleState;
32288    }
32289    return TableCellHeaderStates.NO_STATUS;
32290  };
32291  function $insertTableRowAtSelection(insertAfter = true) {
32292    const selection = $getSelection2();
32293    if (!($isRangeSelection2(selection) || $isTableSelection(selection))) {
32294      formatDevErrorMessage12(`Expected a RangeSelection or TableSelection`);
32295    }
32296    const anchor = selection.anchor.getNode();
32297    const focus = selection.focus.getNode();
32298    const [anchorCell] = $getNodeTriplet(anchor);
32299    const [focusCell, , grid] = $getNodeTriplet(focus);
32300    const [, focusCellMap, anchorCellMap] = $computeTableMap(grid, focusCell, anchorCell);
32301    const {
32302      startRow: anchorStartRow
32303    } = anchorCellMap;
32304    const {
32305      startRow: focusStartRow
32306    } = focusCellMap;
32307    if (insertAfter) {
32308      return $insertTableRowAtNode(anchorStartRow + anchorCell.__rowSpan > focusStartRow + focusCell.__rowSpan ? anchorCell : focusCell, true);
32309    } else {
32310      return $insertTableRowAtNode(focusStartRow < anchorStartRow ? focusCell : anchorCell, false);
32311    }
32312  }
32313  var $insertTableRow__EXPERIMENTAL = $insertTableRowAtSelection;
32314  function $insertTableRowAtNode(cellNode, insertAfter = true) {
32315    const [, , grid] = $getNodeTriplet(cellNode);
32316    const [gridMap, cellMap] = $computeTableMap(grid, cellNode, cellNode);
32317    const columnCount = gridMap[0].length;
32318    const {
32319      startRow: cellStartRow
32320    } = cellMap;
32321    let insertedRow = null;
32322    if (insertAfter) {
32323      const insertAfterEndRow = cellStartRow + cellNode.__rowSpan - 1;
32324      const insertAfterEndRowMap = gridMap[insertAfterEndRow];
32325      const newRow = $createTableRowNode();
32326      for (let i2 = 0; i2 < columnCount; i2++) {
32327        const {
32328          cell,
32329          startRow
32330        } = insertAfterEndRowMap[i2];
32331        if (startRow + cell.__rowSpan - 1 <= insertAfterEndRow) {
32332          const currentCell = insertAfterEndRowMap[i2].cell;
32333          const currentCellHeaderState = currentCell.__headerState;
32334          const headerState = getHeaderState(currentCellHeaderState, TableCellHeaderStates.COLUMN);
32335          newRow.append($createTableCellNode(headerState).append($createParagraphNode2()));
32336        } else {
32337          cell.setRowSpan(cell.__rowSpan + 1);
32338        }
32339      }
32340      const insertAfterEndRowNode = grid.getChildAtIndex(insertAfterEndRow);
32341      if (!$isTableRowNode(insertAfterEndRowNode)) {
32342        formatDevErrorMessage12(`insertAfterEndRow is not a TableRowNode`);
32343      }
32344      insertAfterEndRowNode.insertAfter(newRow);
32345      insertedRow = newRow;
32346    } else {
32347      const insertBeforeStartRow = cellStartRow;
32348      const insertBeforeStartRowMap = gridMap[insertBeforeStartRow];
32349      const newRow = $createTableRowNode();
32350      for (let i2 = 0; i2 < columnCount; i2++) {
32351        const {
32352          cell,
32353          startRow
32354        } = insertBeforeStartRowMap[i2];
32355        if (startRow === insertBeforeStartRow) {
32356          const currentCell = insertBeforeStartRowMap[i2].cell;
32357          const currentCellHeaderState = currentCell.__headerState;
32358          const headerState = getHeaderState(currentCellHeaderState, TableCellHeaderStates.COLUMN);
32359          newRow.append($createTableCellNode(headerState).append($createParagraphNode2()));
32360        } else {
32361          cell.setRowSpan(cell.__rowSpan + 1);
32362        }
32363      }
32364      const insertBeforeStartRowNode = grid.getChildAtIndex(insertBeforeStartRow);
32365      if (!$isTableRowNode(insertBeforeStartRowNode)) {
32366        formatDevErrorMessage12(`insertBeforeStartRow is not a TableRowNode`);
32367      }
32368      insertBeforeStartRowNode.insertBefore(newRow);
32369      insertedRow = newRow;
32370    }
32371    return insertedRow;
32372  }
32373  function $insertTableColumn(tableNode, targetIndex, shouldInsertAfter = true, columnCount, table) {
32374    const tableRows = tableNode.getChildren();
32375    const tableCellsToBeInserted = [];
32376    for (let r2 = 0; r2 < tableRows.length; r2++) {
32377      const currentTableRowNode = tableRows[r2];
32378      if ($isTableRowNode(currentTableRowNode)) {
32379        for (let c2 = 0; c2 < columnCount; c2++) {
32380          const tableRowChildren = currentTableRowNode.getChildren();
32381          if (targetIndex >= tableRowChildren.length || targetIndex < 0) {
32382            throw new Error("Table column target index out of range");
32383          }
32384          const targetCell = tableRowChildren[targetIndex];
32385          if (!$isTableCellNode(targetCell)) {
32386            formatDevErrorMessage12(`Expected table cell`);
32387          }
32388          const {
32389            left,
32390            right
32391          } = $getTableCellSiblingsFromTableCellNode(targetCell, table);
32392          let headerState = TableCellHeaderStates.NO_STATUS;
32393          if (left && left.hasHeaderState(TableCellHeaderStates.ROW) || right && right.hasHeaderState(TableCellHeaderStates.ROW)) {
32394            headerState |= TableCellHeaderStates.ROW;
32395          }
32396          const newTableCell = $createTableCellNode(headerState);
32397          newTableCell.append($createParagraphNode2());
32398          tableCellsToBeInserted.push({
32399            newTableCell,
32400            targetCell
32401          });
32402        }
32403      }
32404    }
32405    tableCellsToBeInserted.forEach(({
32406      newTableCell,
32407      targetCell
32408    }) => {
32409      if (shouldInsertAfter) {
32410        targetCell.insertAfter(newTableCell);
32411      } else {
32412        targetCell.insertBefore(newTableCell);
32413      }
32414    });
32415    return tableNode;
32416  }
32417  function $insertTableColumnAtSelection(insertAfter = true) {
32418    const selection = $getSelection2();
32419    if (!($isRangeSelection2(selection) || $isTableSelection(selection))) {
32420      formatDevErrorMessage12(`Expected a RangeSelection or TableSelection`);
32421    }
32422    const anchor = selection.anchor.getNode();
32423    const focus = selection.focus.getNode();
32424    const [anchorCell] = $getNodeTriplet(anchor);
32425    const [focusCell, , grid] = $getNodeTriplet(focus);
32426    const [, focusCellMap, anchorCellMap] = $computeTableMap(grid, focusCell, anchorCell);
32427    const {
32428      startColumn: anchorStartColumn
32429    } = anchorCellMap;
32430    const {
32431      startColumn: focusStartColumn
32432    } = focusCellMap;
32433    if (insertAfter) {
32434      return $insertTableColumnAtNode(anchorStartColumn + anchorCell.__colSpan > focusStartColumn + focusCell.__colSpan ? anchorCell : focusCell, true);
32435    } else {
32436      return $insertTableColumnAtNode(focusStartColumn < anchorStartColumn ? focusCell : anchorCell, false);
32437    }
32438  }
32439  var $insertTableColumn__EXPERIMENTAL = $insertTableColumnAtSelection;
32440  function $insertTableColumnAtNode(cellNode, insertAfter = true, shouldSetSelection = true) {
32441    const [, , grid] = $getNodeTriplet(cellNode);
32442    const [gridMap, cellMap] = $computeTableMap(grid, cellNode, cellNode);
32443    const rowCount = gridMap.length;
32444    const {
32445      startColumn
32446    } = cellMap;
32447    const insertAfterColumn = insertAfter ? startColumn + cellNode.__colSpan - 1 : startColumn - 1;
32448    const gridFirstChild = grid.getFirstChild();
32449    if (!$isTableRowNode(gridFirstChild)) {
32450      formatDevErrorMessage12(`Expected firstTable child to be a row`);
32451    }
32452    let firstInsertedCell = null;
32453    function $createTableCellNodeForInsertTableColumn(headerState = TableCellHeaderStates.NO_STATUS) {
32454      const cell = $createTableCellNode(headerState).append($createParagraphNode2());
32455      if (firstInsertedCell === null) {
32456        firstInsertedCell = cell;
32457      }
32458      return cell;
32459    }
32460    let loopRow = gridFirstChild;
32461    rowLoop: for (let i2 = 0; i2 < rowCount; i2++) {
32462      if (i2 !== 0) {
32463        const currentRow = loopRow.getNextSibling();
32464        if (!$isTableRowNode(currentRow)) {
32465          formatDevErrorMessage12(`Expected row nextSibling to be a row`);
32466        }
32467        loopRow = currentRow;
32468      }
32469      const rowMap = gridMap[i2];
32470      const currentCellHeaderState = rowMap[insertAfterColumn < 0 ? 0 : insertAfterColumn].cell.__headerState;
32471      const headerState = getHeaderState(currentCellHeaderState, TableCellHeaderStates.ROW);
32472      if (insertAfterColumn < 0) {
32473        $insertFirst3(loopRow, $createTableCellNodeForInsertTableColumn(headerState));
32474        continue;
32475      }
32476      const {
32477        cell: currentCell,
32478        startColumn: currentStartColumn,
32479        startRow: currentStartRow
32480      } = rowMap[insertAfterColumn];
32481      if (currentStartColumn + currentCell.__colSpan - 1 <= insertAfterColumn) {
32482        let insertAfterCell = currentCell;
32483        let insertAfterCellRowStart = currentStartRow;
32484        let prevCellIndex = insertAfterColumn;
32485        while (insertAfterCellRowStart !== i2 && insertAfterCell.__rowSpan > 1) {
32486          prevCellIndex -= currentCell.__colSpan;
32487          if (prevCellIndex >= 0) {
32488            const {
32489              cell: cell_,
32490              startRow: startRow_
32491            } = rowMap[prevCellIndex];
32492            insertAfterCell = cell_;
32493            insertAfterCellRowStart = startRow_;
32494          } else {
32495            loopRow.append($createTableCellNodeForInsertTableColumn(headerState));
32496            continue rowLoop;
32497          }
32498        }
32499        insertAfterCell.insertAfter($createTableCellNodeForInsertTableColumn(headerState));
32500      } else {
32501        currentCell.setColSpan(currentCell.__colSpan + 1);
32502      }
32503    }
32504    if (firstInsertedCell !== null && shouldSetSelection) {
32505      $moveSelectionToCell(firstInsertedCell);
32506    }
32507    const colWidths = grid.getColWidths();
32508    if (colWidths) {
32509      const newColWidths = [...colWidths];
32510      const columnIndex = insertAfterColumn < 0 ? 0 : insertAfterColumn;
32511      const newWidth = newColWidths[columnIndex];
32512      newColWidths.splice(columnIndex, 0, newWidth);
32513      grid.setColWidths(newColWidths);
32514    }
32515    return firstInsertedCell;
32516  }
32517  function $deleteTableColumn(tableNode, targetIndex) {
32518    const tableRows = tableNode.getChildren();
32519    for (let i2 = 0; i2 < tableRows.length; i2++) {
32520      const currentTableRowNode = tableRows[i2];
32521      if ($isTableRowNode(currentTableRowNode)) {
32522        const tableRowChildren = currentTableRowNode.getChildren();
32523        if (targetIndex >= tableRowChildren.length || targetIndex < 0) {
32524          throw new Error("Table column target index out of range");
32525        }
32526        tableRowChildren[targetIndex].remove();
32527      }
32528    }
32529    return tableNode;
32530  }
32531  function $deleteTableRowAtSelection() {
32532    const selection = $getSelection2();
32533    if (!($isRangeSelection2(selection) || $isTableSelection(selection))) {
32534      formatDevErrorMessage12(`Expected a RangeSelection or TableSelection`);
32535    }
32536    const [anchor, focus] = selection.isBackward() ? [selection.focus.getNode(), selection.anchor.getNode()] : [selection.anchor.getNode(), selection.focus.getNode()];
32537    const [anchorCell, , grid] = $getNodeTriplet(anchor);
32538    const [focusCell] = $getNodeTriplet(focus);
32539    const [gridMap, anchorCellMap, focusCellMap] = $computeTableMap(grid, anchorCell, focusCell);
32540    const {
32541      startRow: anchorStartRow
32542    } = anchorCellMap;
32543    const {
32544      startRow: focusStartRow
32545    } = focusCellMap;
32546    const focusEndRow = focusStartRow + focusCell.__rowSpan - 1;
32547    if (gridMap.length === focusEndRow - anchorStartRow + 1) {
32548      grid.remove();
32549      return;
32550    }
32551    const columnCount = gridMap[0].length;
32552    const nextRow = gridMap[focusEndRow + 1];
32553    const nextRowNode = grid.getChildAtIndex(focusEndRow + 1);
32554    for (let row = focusEndRow; row >= anchorStartRow; row--) {
32555      for (let column = columnCount - 1; column >= 0; column--) {
32556        const {
32557          cell,
32558          startRow: cellStartRow,
32559          startColumn: cellStartColumn
32560        } = gridMap[row][column];
32561        if (cellStartColumn !== column) {
32562          continue;
32563        }
32564        if (cellStartRow < anchorStartRow || cellStartRow + cell.__rowSpan - 1 > focusEndRow) {
32565          const intersectionStart = Math.max(cellStartRow, anchorStartRow);
32566          const intersectionEnd = Math.min(cell.__rowSpan + cellStartRow - 1, focusEndRow);
32567          const overflowRowsCount = intersectionStart <= intersectionEnd ? intersectionEnd - intersectionStart + 1 : 0;
32568          cell.setRowSpan(cell.__rowSpan - overflowRowsCount);
32569        }
32570        if (cellStartRow >= anchorStartRow && cellStartRow + cell.__rowSpan - 1 > focusEndRow && // Handle overflow only once
32571        row === focusEndRow) {
32572          if (!(nextRowNode !== null)) {
32573            formatDevErrorMessage12(`Expected nextRowNode not to be null`);
32574          }
32575          let insertAfterCell = null;
32576          for (let columnIndex = 0; columnIndex < column; columnIndex++) {
32577            const currentCellMap = nextRow[columnIndex];
32578            const currentCell = currentCellMap.cell;
32579            if (currentCellMap.startRow === row + 1) {
32580              insertAfterCell = currentCell;
32581            }
32582            if (currentCell.__colSpan > 1) {
32583              columnIndex += currentCell.__colSpan - 1;
32584            }
32585          }
32586          if (insertAfterCell === null) {
32587            $insertFirst3(nextRowNode, cell);
32588          } else {
32589            insertAfterCell.insertAfter(cell);
32590          }
32591        }
32592      }
32593      const rowNode = grid.getChildAtIndex(row);
32594      if (!$isTableRowNode(rowNode)) {
32595        formatDevErrorMessage12(`Expected TableNode childAtIndex(${String(row)}) to be RowNode`);
32596      }
32597      rowNode.remove();
32598    }
32599    if (nextRow !== void 0) {
32600      const {
32601        cell
32602      } = nextRow[0];
32603      $moveSelectionToCell(cell);
32604    } else {
32605      const previousRow = gridMap[anchorStartRow - 1];
32606      const {
32607        cell
32608      } = previousRow[0];
32609      $moveSelectionToCell(cell);
32610    }
32611  }
32612  var $deleteTableRow__EXPERIMENTAL = $deleteTableRowAtSelection;
32613  function $deleteTableColumnAtSelection() {
32614    const selection = $getSelection2();
32615    if (!($isRangeSelection2(selection) || $isTableSelection(selection))) {
32616      formatDevErrorMessage12(`Expected a RangeSelection or TableSelection`);
32617    }
32618    const anchor = selection.anchor.getNode();
32619    const focus = selection.focus.getNode();
32620    const [anchorCell, , grid] = $getNodeTriplet(anchor);
32621    const [focusCell] = $getNodeTriplet(focus);
32622    const [gridMap, anchorCellMap, focusCellMap] = $computeTableMap(grid, anchorCell, focusCell);
32623    const {
32624      startColumn: anchorStartColumn
32625    } = anchorCellMap;
32626    const {
32627      startRow: focusStartRow,
32628      startColumn: focusStartColumn
32629    } = focusCellMap;
32630    const startColumn = Math.min(anchorStartColumn, focusStartColumn);
32631    const endColumn = Math.max(anchorStartColumn + anchorCell.__colSpan - 1, focusStartColumn + focusCell.__colSpan - 1);
32632    const selectedColumnCount = endColumn - startColumn + 1;
32633    const columnCount = gridMap[0].length;
32634    if (columnCount === endColumn - startColumn + 1) {
32635      grid.selectPrevious();
32636      grid.remove();
32637      return;
32638    }
32639    const rowCount = gridMap.length;
32640    for (let row = 0; row < rowCount; row++) {
32641      for (let column = startColumn; column <= endColumn; column++) {
32642        const {
32643          cell,
32644          startColumn: cellStartColumn
32645        } = gridMap[row][column];
32646        if (cellStartColumn < startColumn) {
32647          if (column === startColumn) {
32648            const overflowLeft = startColumn - cellStartColumn;
32649            cell.setColSpan(cell.__colSpan - // Possible overflow right too
32650            Math.min(selectedColumnCount, cell.__colSpan - overflowLeft));
32651          }
32652        } else if (cellStartColumn + cell.__colSpan - 1 > endColumn) {
32653          if (column === endColumn) {
32654            const inSelectedArea = endColumn - cellStartColumn + 1;
32655            cell.setColSpan(cell.__colSpan - inSelectedArea);
32656          }
32657        } else {
32658          cell.remove();
32659        }
32660      }
32661    }
32662    const focusRowMap = gridMap[focusStartRow];
32663    const nextColumn = anchorStartColumn > focusStartColumn ? focusRowMap[anchorStartColumn + anchorCell.__colSpan] : focusRowMap[focusStartColumn + focusCell.__colSpan];
32664    if (nextColumn !== void 0) {
32665      const {
32666        cell
32667      } = nextColumn;
32668      $moveSelectionToCell(cell);
32669    } else {
32670      const previousRow = focusStartColumn < anchorStartColumn ? focusRowMap[focusStartColumn - 1] : focusRowMap[anchorStartColumn - 1];
32671      const {
32672        cell
32673      } = previousRow;
32674      $moveSelectionToCell(cell);
32675    }
32676    const colWidths = grid.getColWidths();
32677    if (colWidths) {
32678      const newColWidths = [...colWidths];
32679      newColWidths.splice(startColumn, selectedColumnCount);
32680      grid.setColWidths(newColWidths);
32681    }
32682  }
32683  var $deleteTableColumn__EXPERIMENTAL = $deleteTableColumnAtSelection;
32684  function $moveSelectionToCell(cell) {
32685    const firstDescendant = cell.getFirstDescendant();
32686    if (firstDescendant == null) {
32687      cell.selectStart();
32688    } else {
32689      firstDescendant.getParentOrThrow().selectStart();
32690    }
32691  }
32692  function $insertFirst3(parent, node) {
32693    const firstChild = parent.getFirstChild();
32694    if (firstChild !== null) {
32695      firstChild.insertBefore(node);
32696    } else {
32697      parent.append(node);
32698    }
32699  }
32700  function $mergeCells(cellNodes) {
32701    if (cellNodes.length === 0) {
32702      return null;
32703    }
32704    const tableNode = $getTableNodeFromLexicalNodeOrThrow(cellNodes[0]);
32705    const [gridMap] = $computeTableMapSkipCellCheck(tableNode, null, null);
32706    let minRow = Infinity;
32707    let maxRow = -Infinity;
32708    let minCol = Infinity;
32709    let maxCol = -Infinity;
32710    const processedCells = /* @__PURE__ */ new Set();
32711    for (const row of gridMap) {
32712      for (const mapCell of row) {
32713        if (!mapCell || !mapCell.cell) {
32714          continue;
32715        }
32716        const cellKey = mapCell.cell.getKey();
32717        if (processedCells.has(cellKey)) {
32718          continue;
32719        }
32720        if (cellNodes.some((cell) => cell.is(mapCell.cell))) {
32721          processedCells.add(cellKey);
32722          const cellStartRow = mapCell.startRow;
32723          const cellStartCol = mapCell.startColumn;
32724          const cellRowSpan = mapCell.cell.__rowSpan || 1;
32725          const cellColSpan = mapCell.cell.__colSpan || 1;
32726          minRow = Math.min(minRow, cellStartRow);
32727          maxRow = Math.max(maxRow, cellStartRow + cellRowSpan - 1);
32728          minCol = Math.min(minCol, cellStartCol);
32729          maxCol = Math.max(maxCol, cellStartCol + cellColSpan - 1);
32730        }
32731      }
32732    }
32733    if (minRow === Infinity || minCol === Infinity) {
32734      return null;
32735    }
32736    const totalRowSpan = maxRow - minRow + 1;
32737    const totalColSpan = maxCol - minCol + 1;
32738    const targetCellMap = gridMap[minRow][minCol];
32739    if (!targetCellMap.cell) {
32740      return null;
32741    }
32742    const targetCell = targetCellMap.cell;
32743    targetCell.setColSpan(totalColSpan);
32744    targetCell.setRowSpan(totalRowSpan);
32745    const seenCells = /* @__PURE__ */ new Set([targetCell.getKey()]);
32746    for (let row = minRow; row <= maxRow; row++) {
32747      for (let col = minCol; col <= maxCol; col++) {
32748        const mapCell = gridMap[row][col];
32749        if (!mapCell.cell) {
32750          continue;
32751        }
32752        const currentCell = mapCell.cell;
32753        const key = currentCell.getKey();
32754        if (!seenCells.has(key)) {
32755          seenCells.add(key);
32756          const isEmpty = $cellContainsEmptyParagraph(currentCell);
32757          if (!isEmpty) {
32758            targetCell.append(...currentCell.getChildren());
32759          }
32760          currentCell.remove();
32761        }
32762      }
32763    }
32764    if (targetCell.getChildrenSize() === 0) {
32765      targetCell.append($createParagraphNode2());
32766    }
32767    return targetCell;
32768  }
32769  function $cellContainsEmptyParagraph(cell) {
32770    if (cell.getChildrenSize() !== 1) {
32771      return false;
32772    }
32773    const firstChild = cell.getFirstChildOrThrow();
32774    if (!$isParagraphNode2(firstChild) || !firstChild.isEmpty()) {
32775      return false;
32776    }
32777    return true;
32778  }
32779  function $unmergeCell() {
32780    const selection = $getSelection2();
32781    if (!($isRangeSelection2(selection) || $isTableSelection(selection))) {
32782      formatDevErrorMessage12(`Expected a RangeSelection or TableSelection`);
32783    }
32784    const anchor = selection.anchor.getNode();
32785    const cellNode = $findMatchingParent3(anchor, $isTableCellNode);
32786    if (!$isTableCellNode(cellNode)) {
32787      formatDevErrorMessage12(`Expected to find a parent TableCellNode`);
32788    }
32789    return $unmergeCellNode(cellNode);
32790  }
32791  function $unmergeCellNode(cellNode) {
32792    const [cell, row, grid] = $getNodeTriplet(cellNode);
32793    const colSpan = cell.__colSpan;
32794    const rowSpan = cell.__rowSpan;
32795    if (colSpan === 1 && rowSpan === 1) {
32796      return;
32797    }
32798    const [map, cellMap] = $computeTableMap(grid, cell, cell);
32799    const {
32800      startColumn,
32801      startRow
32802    } = cellMap;
32803    const baseColStyle = cell.__headerState & TableCellHeaderStates.COLUMN;
32804    const colStyles = Array.from({
32805      length: colSpan
32806    }, (_v, i2) => {
32807      let colStyle = baseColStyle;
32808      for (let rowIdx = 0; colStyle !== 0 && rowIdx < map.length; rowIdx++) {
32809        colStyle &= map[rowIdx][i2 + startColumn].cell.__headerState;
32810      }
32811      return colStyle;
32812    });
32813    const baseRowStyle = cell.__headerState & TableCellHeaderStates.ROW;
32814    const rowStyles = Array.from({
32815      length: rowSpan
32816    }, (_v, i2) => {
32817      let rowStyle = baseRowStyle;
32818      for (let colIdx = 0; rowStyle !== 0 && colIdx < map[0].length; colIdx++) {
32819        rowStyle &= map[i2 + startRow][colIdx].cell.__headerState;
32820      }
32821      return rowStyle;
32822    });
32823    if (colSpan > 1) {
32824      for (let i2 = 1; i2 < colSpan; i2++) {
32825        cell.insertAfter($createTableCellNode(colStyles[i2] | rowStyles[0]).append($createParagraphNode2()));
32826      }
32827      cell.setColSpan(1);
32828    }
32829    if (rowSpan > 1) {
32830      let currentRowNode;
32831      for (let i2 = 1; i2 < rowSpan; i2++) {
32832        const currentRow = startRow + i2;
32833        const currentRowMap = map[currentRow];
32834        currentRowNode = (currentRowNode || row).getNextSibling();
32835        if (!$isTableRowNode(currentRowNode)) {
32836          formatDevErrorMessage12(`Expected row next sibling to be a row`);
32837        }
32838        let insertAfterCell = null;
32839        for (let column = 0; column < startColumn; column++) {
32840          const currentCellMap = currentRowMap[column];
32841          const currentCell = currentCellMap.cell;
32842          if (currentCellMap.startRow === currentRow) {
32843            insertAfterCell = currentCell;
32844          }
32845          if (currentCell.__colSpan > 1) {
32846            column += currentCell.__colSpan - 1;
32847          }
32848        }
32849        if (insertAfterCell === null) {
32850          for (let j3 = colSpan - 1; j3 >= 0; j3--) {
32851            $insertFirst3(currentRowNode, $createTableCellNode(colStyles[j3] | rowStyles[i2]).append($createParagraphNode2()));
32852          }
32853        } else {
32854          for (let j3 = colSpan - 1; j3 >= 0; j3--) {
32855            insertAfterCell.insertAfter($createTableCellNode(colStyles[j3] | rowStyles[i2]).append($createParagraphNode2()));
32856          }
32857        }
32858      }
32859      cell.setRowSpan(1);
32860    }
32861  }
32862  function $computeTableMap(tableNode, cellA, cellB) {
32863    const [tableMap, cellAValue, cellBValue] = $computeTableMapSkipCellCheck(tableNode, cellA, cellB);
32864    if (!(cellAValue !== null)) {
32865      formatDevErrorMessage12(`Anchor not found in Table`);
32866    }
32867    if (!(cellBValue !== null)) {
32868      formatDevErrorMessage12(`Focus not found in Table`);
32869    }
32870    return [tableMap, cellAValue, cellBValue];
32871  }
32872  function $computeTableMapSkipCellCheck(tableNode, cellA, cellB) {
32873    const tableMap = [];
32874    let cellAValue = null;
32875    let cellBValue = null;
32876    function getMapRow(i2) {
32877      let row = tableMap[i2];
32878      if (row === void 0) {
32879        tableMap[i2] = row = [];
32880      }
32881      return row;
32882    }
32883    const gridChildren = tableNode.getChildren();
32884    for (let rowIdx = 0; rowIdx < gridChildren.length; rowIdx++) {
32885      const row = gridChildren[rowIdx];
32886      if (!$isTableRowNode(row)) {
32887        formatDevErrorMessage12(`Expected TableNode children to be TableRowNode`);
32888      }
32889      const startMapRow = getMapRow(rowIdx);
32890      for (let cell = row.getFirstChild(), colIdx = 0; cell != null; cell = cell.getNextSibling()) {
32891        if (!$isTableCellNode(cell)) {
32892          formatDevErrorMessage12(`Expected TableRowNode children to be TableCellNode`);
32893        }
32894        while (startMapRow[colIdx] !== void 0) {
32895          colIdx++;
32896        }
32897        const value = {
32898          cell,
32899          startColumn: colIdx,
32900          startRow: rowIdx
32901        };
32902        const {
32903          __rowSpan: rowSpan,
32904          __colSpan: colSpan
32905        } = cell;
32906        for (let j3 = 0; j3 < rowSpan; j3++) {
32907          if (rowIdx + j3 >= gridChildren.length) {
32908            break;
32909          }
32910          const mapRow = getMapRow(rowIdx + j3);
32911          for (let i2 = 0; i2 < colSpan; i2++) {
32912            mapRow[colIdx + i2] = value;
32913          }
32914        }
32915        if (cellA !== null && cellAValue === null && cellA.is(cell)) {
32916          cellAValue = value;
32917        }
32918        if (cellB !== null && cellBValue === null && cellB.is(cell)) {
32919          cellBValue = value;
32920        }
32921      }
32922    }
32923    return [tableMap, cellAValue, cellBValue];
32924  }
32925  function $getNodeTriplet(source) {
32926    let cell;
32927    if (source instanceof TableCellNode) {
32928      cell = source;
32929    } else if ("__type" in source) {
32930      const cell_ = $findMatchingParent3(source, $isTableCellNode);
32931      if (!$isTableCellNode(cell_)) {
32932        formatDevErrorMessage12(`Expected to find a parent TableCellNode`);
32933      }
32934      cell = cell_;
32935    } else {
32936      const cell_ = $findMatchingParent3(source.getNode(), $isTableCellNode);
32937      if (!$isTableCellNode(cell_)) {
32938        formatDevErrorMessage12(`Expected to find a parent TableCellNode`);
32939      }
32940      cell = cell_;
32941    }
32942    const row = cell.getParent();
32943    if (!$isTableRowNode(row)) {
32944      formatDevErrorMessage12(`Expected TableCellNode to have a parent TableRowNode`);
32945    }
32946    const grid = row.getParent();
32947    if (!$isTableNode(grid)) {
32948      formatDevErrorMessage12(`Expected TableRowNode to have a parent TableNode`);
32949    }
32950    return [cell, row, grid];
32951  }
32952  function $computeTableCellRectSpans(map, boundary) {
32953    const {
32954      minColumn,
32955      maxColumn,
32956      minRow,
32957      maxRow
32958    } = boundary;
32959    let topSpan = 1;
32960    let leftSpan = 1;
32961    let rightSpan = 1;
32962    let bottomSpan = 1;
32963    const topRow = map[minRow];
32964    const bottomRow = map[maxRow];
32965    for (let col = minColumn; col <= maxColumn; col++) {
32966      topSpan = Math.max(topSpan, topRow[col].cell.__rowSpan);
32967      bottomSpan = Math.max(bottomSpan, bottomRow[col].cell.__rowSpan);
32968    }
32969    for (let row = minRow; row <= maxRow; row++) {
32970      leftSpan = Math.max(leftSpan, map[row][minColumn].cell.__colSpan);
32971      rightSpan = Math.max(rightSpan, map[row][maxColumn].cell.__colSpan);
32972    }
32973    return {
32974      bottomSpan,
32975      leftSpan,
32976      rightSpan,
32977      topSpan
32978    };
32979  }
32980  function $computeTableCellRectBoundary(map, cellAMap, cellBMap) {
32981    let minColumn = Math.min(cellAMap.startColumn, cellBMap.startColumn);
32982    let minRow = Math.min(cellAMap.startRow, cellBMap.startRow);
32983    let maxColumn = Math.max(cellAMap.startColumn + cellAMap.cell.__colSpan - 1, cellBMap.startColumn + cellBMap.cell.__colSpan - 1);
32984    let maxRow = Math.max(cellAMap.startRow + cellAMap.cell.__rowSpan - 1, cellBMap.startRow + cellBMap.cell.__rowSpan - 1);
32985    let hasChanges;
32986    do {
32987      hasChanges = false;
32988      for (let row = 0; row < map.length; row++) {
32989        for (let col = 0; col < map[0].length; col++) {
32990          const cell = map[row][col];
32991          if (!cell) {
32992            continue;
32993          }
32994          const cellEndCol = cell.startColumn + cell.cell.__colSpan - 1;
32995          const cellEndRow = cell.startRow + cell.cell.__rowSpan - 1;
32996          const intersectsHorizontally = cell.startColumn <= maxColumn && cellEndCol >= minColumn;
32997          const intersectsVertically = cell.startRow <= maxRow && cellEndRow >= minRow;
32998          if (intersectsHorizontally && intersectsVertically) {
32999            const newMinColumn = Math.min(minColumn, cell.startColumn);
33000            const newMaxColumn = Math.max(maxColumn, cellEndCol);
33001            const newMinRow = Math.min(minRow, cell.startRow);
33002            const newMaxRow = Math.max(maxRow, cellEndRow);
33003            if (newMinColumn !== minColumn || newMaxColumn !== maxColumn || newMinRow !== minRow || newMaxRow !== maxRow) {
33004              minColumn = newMinColumn;
33005              maxColumn = newMaxColumn;
33006              minRow = newMinRow;
33007              maxRow = newMaxRow;
33008              hasChanges = true;
33009            }
33010          }
33011        }
33012      }
33013    } while (hasChanges);
33014    return {
33015      maxColumn,
33016      maxRow,
33017      minColumn,
33018      minRow
33019    };
33020  }
33021  function $isSimpleTable(table) {
33022    const rows = table.getChildren();
33023    let columns = null;
33024    for (const row of rows) {
33025      if (!$isTableRowNode(row)) {
33026        return false;
33027      }
33028      if (columns === null) {
33029        columns = row.getChildrenSize();
33030      }
33031      if (row.getChildrenSize() !== columns) {
33032        return false;
33033      }
33034      const cells = row.getChildren();
33035      for (const cell of cells) {
33036        if (!$isTableCellNode(cell) || cell.getRowSpan() !== 1 || cell.getColSpan() !== 1) {
33037          return false;
33038        }
33039      }
33040    }
33041    return (columns || 0) > 0;
33042  }
33043  function $moveTableColumn(tableNode, originColumn, targetColumn) {
33044    if (originColumn === targetColumn) {
33045      return;
33046    }
33047    const columnCount = tableNode.getColumnCount();
33048    if (originColumn < 0 || originColumn >= columnCount || targetColumn < 0 || targetColumn >= columnCount) {
33049      return;
33050    }
33051    if (!$isSimpleTable(tableNode)) {
33052      return;
33053    }
33054    const rows = tableNode.getChildren().filter($isTableRowNode);
33055    rows.forEach((row) => {
33056      const cells = row.getChildren();
33057      const [moved] = cells.splice(originColumn, 1);
33058      cells.splice(targetColumn, 0, moved);
33059      row.splice(0, cells.length, cells);
33060    });
33061    const colWidths = tableNode.getColWidths();
33062    if (colWidths && colWidths.length === columnCount) {
33063      const newWidths = [...colWidths];
33064      const [movedWidth] = newWidths.splice(originColumn, 1);
33065      newWidths.splice(targetColumn, 0, movedWidth);
33066      tableNode.setColWidths(newWidths);
33067    }
33068  }
33069  function $getTableCellNodeRect(tableCellNode) {
33070    const [cellNode, , gridNode] = $getNodeTriplet(tableCellNode);
33071    const rows = gridNode.getChildren();
33072    const rowCount = rows.length;
33073    const columnCount = rows[0].getChildren().length;
33074    const cellMatrix = new Array(rowCount);
33075    for (let i2 = 0; i2 < rowCount; i2++) {
33076      cellMatrix[i2] = new Array(columnCount);
33077    }
33078    for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) {
33079      const row = rows[rowIndex];
33080      const cells = row.getChildren();
33081      let columnIndex = 0;
33082      for (let cellIndex = 0; cellIndex < cells.length; cellIndex++) {
33083        while (cellMatrix[rowIndex][columnIndex]) {
33084          columnIndex++;
33085        }
33086        const cell = cells[cellIndex];
33087        const rowSpan = cell.__rowSpan || 1;
33088        const colSpan = cell.__colSpan || 1;
33089        for (let i2 = 0; i2 < rowSpan; i2++) {
33090          for (let j3 = 0; j3 < colSpan; j3++) {
33091            cellMatrix[rowIndex + i2][columnIndex + j3] = cell;
33092          }
33093        }
33094        if (cellNode === cell) {
33095          return {
33096            colSpan,
33097            columnIndex,
33098            rowIndex,
33099            rowSpan
33100          };
33101        }
33102        columnIndex += colSpan;
33103      }
33104    }
33105    return null;
33106  }
33107  function $getCellNodes(tableSelection) {
33108    const [[anchorNode, anchorCell, anchorRow, anchorTable], [focusNode, focusCell, focusRow, focusTable]] = ["anchor", "focus"].map((k2) => {
33109      const node = tableSelection[k2].getNode();
33110      const cellNode = $findMatchingParent3(node, $isTableCellNode);
33111      if (!$isTableCellNode(cellNode)) {
33112        formatDevErrorMessage12(`Expected TableSelection ${k2} to be (or a child of) TableCellNode, got key ${node.getKey()} of type ${node.getType()}`);
33113      }
33114      const rowNode = cellNode.getParent();
33115      if (!$isTableRowNode(rowNode)) {
33116        formatDevErrorMessage12(`Expected TableSelection ${k2} cell parent to be a TableRowNode`);
33117      }
33118      const tableNode = rowNode.getParent();
33119      if (!$isTableNode(tableNode)) {
33120        formatDevErrorMessage12(`Expected TableSelection ${k2} row parent to be a TableNode`);
33121      }
33122      return [node, cellNode, rowNode, tableNode];
33123    });
33124    if (!anchorTable.is(focusTable)) {
33125      formatDevErrorMessage12(`Expected TableSelection anchor and focus to be in the same table`);
33126    }
33127    return {
33128      anchorCell,
33129      anchorNode,
33130      anchorRow,
33131      anchorTable,
33132      focusCell,
33133      focusNode,
33134      focusRow,
33135      focusTable
33136    };
33137  }
33138  var TableSelection = class _TableSelection {
33139    tableKey;
33140    anchor;
33141    focus;
33142    _cachedNodes;
33143    dirty;
33144    constructor(tableKey, anchor, focus) {
33145      this.anchor = anchor;
33146      this.focus = focus;
33147      anchor._selection = this;
33148      focus._selection = this;
33149      this._cachedNodes = null;
33150      this.dirty = false;
33151      this.tableKey = tableKey;
33152    }
33153    getStartEndPoints() {
33154      return [this.anchor, this.focus];
33155    }
33156    /**
33157     * {@link $createTableSelection} unfortunately makes it very easy to create
33158     * nonsense selections, so we have a method to see if the selection probably
33159     * makes sense.
33160     *
33161     * @returns true if the TableSelection is (probably) valid
33162     */
33163    isValid() {
33164      if (this.tableKey === "root" || this.anchor.key === "root" || this.anchor.type !== "element" || this.focus.key === "root" || this.focus.type !== "element") {
33165        return false;
33166      }
33167      const tableNode = $getNodeByKey2(this.tableKey);
33168      const anchorNode = $getNodeByKey2(this.anchor.key);
33169      const focusNode = $getNodeByKey2(this.focus.key);
33170      return tableNode !== null && anchorNode !== null && focusNode !== null;
33171    }
33172    /**
33173     * Returns whether the Selection is "backwards", meaning the focus
33174     * logically precedes the anchor in the EditorState.
33175     * @returns true if the Selection is backwards, false otherwise.
33176     */
33177    isBackward() {
33178      return this.focus.isBefore(this.anchor);
33179    }
33180    getCachedNodes() {
33181      return this._cachedNodes;
33182    }
33183    setCachedNodes(nodes) {
33184      this._cachedNodes = nodes;
33185    }
33186    is(selection) {
33187      return $isTableSelection(selection) && this.tableKey === selection.tableKey && this.anchor.is(selection.anchor) && this.focus.is(selection.focus);
33188    }
33189    set(tableKey, anchorCellKey, focusCellKey) {
33190      this.dirty = this.dirty || tableKey !== this.tableKey || anchorCellKey !== this.anchor.key || focusCellKey !== this.focus.key;
33191      this.tableKey = tableKey;
33192      this.anchor.key = anchorCellKey;
33193      this.focus.key = focusCellKey;
33194      this._cachedNodes = null;
33195    }
33196    clone() {
33197      return new _TableSelection(this.tableKey, $createPoint2(this.anchor.key, this.anchor.offset, this.anchor.type), $createPoint2(this.focus.key, this.focus.offset, this.focus.type));
33198    }
33199    isCollapsed() {
33200      return false;
33201    }
33202    extract() {
33203      return this.getNodes();
33204    }
33205    insertRawText(text2) {
33206    }
33207    insertText() {
33208    }
33209    /**
33210     * Returns whether the provided TextFormatType is present on the Selection.
33211     * This will be true if any paragraph in table cells has the specified format.
33212     *
33213     * @param type the TextFormatType to check for.
33214     * @returns true if the provided format is currently toggled on on the Selection, false otherwise.
33215     */
33216    hasFormat(type) {
33217      let format = 0;
33218      const cellNodes = this.getNodes().filter($isTableCellNode);
33219      cellNodes.forEach((cellNode) => {
33220        const paragraph = cellNode.getFirstChild();
33221        if ($isParagraphNode2(paragraph)) {
33222          format |= paragraph.getTextFormat();
33223        }
33224      });
33225      const formatFlag = TEXT_TYPE_TO_FORMAT2[type];
33226      return (format & formatFlag) !== 0;
33227    }
33228    insertNodes(nodes) {
33229      const focusNode = this.focus.getNode();
33230      if (!$isElementNode2(focusNode)) {
33231        formatDevErrorMessage12(`Expected TableSelection focus to be an ElementNode`);
33232      }
33233      const selection = $normalizeSelection__EXPERIMENTAL(focusNode.select(0, focusNode.getChildrenSize()));
33234      selection.insertNodes(nodes);
33235    }
33236    // TODO Deprecate this method. It's confusing when used with colspan|rowspan
33237    getShape() {
33238      const {
33239        anchorCell,
33240        focusCell
33241      } = $getCellNodes(this);
33242      const anchorCellNodeRect = $getTableCellNodeRect(anchorCell);
33243      if (!(anchorCellNodeRect !== null)) {
33244        formatDevErrorMessage12(`getCellRect: expected to find AnchorNode`);
33245      }
33246      const focusCellNodeRect = $getTableCellNodeRect(focusCell);
33247      if (!(focusCellNodeRect !== null)) {
33248        formatDevErrorMessage12(`getCellRect: expected to find focusCellNode`);
33249      }
33250      const startX = Math.min(anchorCellNodeRect.columnIndex, focusCellNodeRect.columnIndex);
33251      const stopX = Math.max(anchorCellNodeRect.columnIndex + anchorCellNodeRect.colSpan - 1, focusCellNodeRect.columnIndex + focusCellNodeRect.colSpan - 1);
33252      const startY = Math.min(anchorCellNodeRect.rowIndex, focusCellNodeRect.rowIndex);
33253      const stopY = Math.max(anchorCellNodeRect.rowIndex + anchorCellNodeRect.rowSpan - 1, focusCellNodeRect.rowIndex + focusCellNodeRect.rowSpan - 1);
33254      return {
33255        fromX: Math.min(startX, stopX),
33256        fromY: Math.min(startY, stopY),
33257        toX: Math.max(startX, stopX),
33258        toY: Math.max(startY, stopY)
33259      };
33260    }
33261    getNodes() {
33262      if (!this.isValid()) {
33263        return [];
33264      }
33265      const cachedNodes = this._cachedNodes;
33266      if (cachedNodes !== null) {
33267        return cachedNodes;
33268      }
33269      const {
33270        anchorTable: tableNode,
33271        anchorCell,
33272        focusCell
33273      } = $getCellNodes(this);
33274      const focusCellGrid = focusCell.getParents()[1];
33275      if (focusCellGrid !== tableNode) {
33276        if (!tableNode.isParentOf(focusCell)) {
33277          const gridParent = tableNode.getParent();
33278          if (!(gridParent != null)) {
33279            formatDevErrorMessage12(`Expected gridParent to have a parent`);
33280          }
33281          this.set(this.tableKey, gridParent.getKey(), focusCell.getKey());
33282        } else {
33283          const focusCellParent = focusCellGrid.getParent();
33284          if (!(focusCellParent != null)) {
33285            formatDevErrorMessage12(`Expected focusCellParent to have a parent`);
33286          }
33287          this.set(this.tableKey, focusCell.getKey(), focusCellParent.getKey());
33288        }
33289        return this.getNodes();
33290      }
33291      const [map, cellAMap, cellBMap] = $computeTableMap(tableNode, anchorCell, focusCell);
33292      const {
33293        minColumn,
33294        maxColumn,
33295        minRow,
33296        maxRow
33297      } = $computeTableCellRectBoundary(map, cellAMap, cellBMap);
33298      const nodeMap = /* @__PURE__ */ new Map([[tableNode.getKey(), tableNode]]);
33299      let lastRow = null;
33300      for (let i2 = minRow; i2 <= maxRow; i2++) {
33301        for (let j3 = minColumn; j3 <= maxColumn; j3++) {
33302          const {
33303            cell
33304          } = map[i2][j3];
33305          const currentRow = cell.getParent();
33306          if (!$isTableRowNode(currentRow)) {
33307            formatDevErrorMessage12(`Expected TableCellNode parent to be a TableRowNode`);
33308          }
33309          if (currentRow !== lastRow) {
33310            nodeMap.set(currentRow.getKey(), currentRow);
33311            lastRow = currentRow;
33312          }
33313          if (!nodeMap.has(cell.getKey())) {
33314            $visitRecursively(cell, (childNode) => {
33315              nodeMap.set(childNode.getKey(), childNode);
33316            });
33317          }
33318        }
33319      }
33320      const nodes = Array.from(nodeMap.values());
33321      if (!isCurrentlyReadOnlyMode2()) {
33322        this._cachedNodes = nodes;
33323      }
33324      return nodes;
33325    }
33326    getTextContent() {
33327      const nodes = this.getNodes().filter((node) => $isTableCellNode(node));
33328      let textContent = "";
33329      for (let i2 = 0; i2 < nodes.length; i2++) {
33330        const node = nodes[i2];
33331        const row = node.__parent;
33332        const nextRow = (nodes[i2 + 1] || {}).__parent;
33333        textContent += node.getTextContent() + (nextRow !== row ? "\n" : "	");
33334      }
33335      return textContent;
33336    }
33337  };
33338  function $isTableSelection(x3) {
33339    return x3 instanceof TableSelection;
33340  }
33341  function $createTableSelection() {
33342    const anchor = $createPoint2("root", 0, "element");
33343    const focus = $createPoint2("root", 0, "element");
33344    return new TableSelection("root", anchor, focus);
33345  }
33346  function $createTableSelectionFrom(tableNode, anchorCell, focusCell) {
33347    const tableNodeKey = tableNode.getKey();
33348    const anchorCellKey = anchorCell.getKey();
33349    const focusCellKey = focusCell.getKey();
33350    {
33351      if (!tableNode.isAttached()) {
33352        formatDevErrorMessage12(`$createTableSelectionFrom: tableNode ${tableNodeKey} is not attached`);
33353      }
33354      if (!tableNode.is($findTableNode(anchorCell))) {
33355        formatDevErrorMessage12(`$createTableSelectionFrom: anchorCell ${anchorCellKey} is not in table ${tableNodeKey}`);
33356      }
33357      if (!tableNode.is($findTableNode(focusCell))) {
33358        formatDevErrorMessage12(`$createTableSelectionFrom: focusCell ${focusCellKey} is not in table ${tableNodeKey}`);
33359      }
33360    }
33361    const prevSelection = $getSelection2();
33362    const nextSelection = $isTableSelection(prevSelection) ? prevSelection.clone() : $createTableSelection();
33363    nextSelection.set(tableNode.getKey(), anchorCell.getKey(), focusCell.getKey());
33364    return nextSelection;
33365  }
33366  function $visitRecursively(node, $visit) {
33367    const stack = [[node]];
33368    for (let currentArray = stack.at(-1); currentArray !== void 0 && stack.length > 0; currentArray = stack.at(-1)) {
33369      const currentNode = currentArray.pop();
33370      if (currentNode === void 0) {
33371        stack.pop();
33372      } else if ($visit(currentNode) !== false && $isElementNode2(currentNode)) {
33373        stack.push(currentNode.getChildren());
33374      }
33375    }
33376  }
33377  function $getTableAndElementByKey(tableNodeKey, editor = $getEditor2()) {
33378    const tableNode = $getNodeByKey2(tableNodeKey);
33379    if (!$isTableNode(tableNode)) {
33380      formatDevErrorMessage12(`TableObserver: Expected tableNodeKey ${tableNodeKey} to be a TableNode`);
33381    }
33382    const tableElement = getTableElement(tableNode, editor.getElementByKey(tableNodeKey));
33383    if (!(tableElement !== null)) {
33384      formatDevErrorMessage12(`TableObserver: Expected to find TableElement in DOM for key ${tableNodeKey}`);
33385    }
33386    return {
33387      tableElement,
33388      tableNode
33389    };
33390  }
33391  var TableObservers = class {
33392    observers;
33393    nextFocus;
33394    shouldCheckSelectionForTable;
33395    constructor() {
33396      this.observers = /* @__PURE__ */ new Map();
33397      this.nextFocus = null;
33398      this.shouldCheckSelectionForTable = null;
33399    }
33400    /**
33401     * @internal
33402     * When handling mousemove events we track what the focus cell should be, but
33403     * the DOM selection may end up somewhere else entirely. We don't have an elegant
33404     * way to handle this after the DOM selection has been resolved in a
33405     * SELECTION_CHANGE_COMMAND callback.
33406     */
33407    setNextFocus(nextFocus) {
33408      this.nextFocus = nextFocus;
33409    }
33410    /** @internal */
33411    getAndClearNextFocus() {
33412      const {
33413        nextFocus
33414      } = this;
33415      if (nextFocus !== null) {
33416        this.nextFocus = null;
33417      }
33418      return nextFocus;
33419    }
33420    /**
33421     * @internal
33422     * Firefox has a strange behavior where pressing the down arrow key from
33423     * above the table will move the caret after the table and then lexical
33424     * will select the last cell instead of the first.
33425     * We do still want to let the browser handle caret movement but we will
33426     * use this property to "tag" the update so that we can recheck the
33427     * selection after the event is processed.
33428     */
33429    setShouldCheckSelectionForTable(tableKey) {
33430      this.shouldCheckSelectionForTable = tableKey;
33431    }
33432    /**
33433     * @internal
33434     */
33435    getAndClearShouldCheckSelectionForTable() {
33436      const {
33437        shouldCheckSelectionForTable
33438      } = this;
33439      if (shouldCheckSelectionForTable) {
33440        this.shouldCheckSelectionForTable = null;
33441        return shouldCheckSelectionForTable;
33442      }
33443      return null;
33444    }
33445  };
33446  var TableObserver = class {
33447    focusX;
33448    focusY;
33449    listenersToRemove;
33450    table;
33451    isHighlightingCells;
33452    anchorX;
33453    anchorY;
33454    tableNodeKey;
33455    anchorCell;
33456    focusCell;
33457    anchorCellNodeKey;
33458    focusCellNodeKey;
33459    editor;
33460    tableSelection;
33461    hasHijackedSelectionStyles;
33462    isSelecting;
33463    pointerType;
33464    abortController;
33465    listenerOptions;
33466    constructor(editor, tableNodeKey) {
33467      this.isHighlightingCells = false;
33468      this.anchorX = -1;
33469      this.anchorY = -1;
33470      this.focusX = -1;
33471      this.focusY = -1;
33472      this.listenersToRemove = /* @__PURE__ */ new Set();
33473      this.tableNodeKey = tableNodeKey;
33474      this.editor = editor;
33475      this.table = {
33476        columns: 0,
33477        domRows: [],
33478        rows: 0
33479      };
33480      this.tableSelection = null;
33481      this.anchorCellNodeKey = null;
33482      this.focusCellNodeKey = null;
33483      this.anchorCell = null;
33484      this.focusCell = null;
33485      this.hasHijackedSelectionStyles = false;
33486      this.isSelecting = false;
33487      this.pointerType = null;
33488      this.abortController = new AbortController();
33489      this.listenerOptions = {
33490        signal: this.abortController.signal
33491      };
33492      this.trackTable();
33493    }
33494    getTable() {
33495      return this.table;
33496    }
33497    removeListeners() {
33498      this.abortController.abort("removeListeners");
33499      Array.from(this.listenersToRemove).forEach((removeListener) => removeListener());
33500      this.listenersToRemove.clear();
33501    }
33502    $lookup() {
33503      return $getTableAndElementByKey(this.tableNodeKey, this.editor);
33504    }
33505    trackTable() {
33506      const observer = new MutationObserver((records) => {
33507        this.editor.getEditorState().read(() => {
33508          let gridNeedsRedraw = false;
33509          for (let i2 = 0; i2 < records.length; i2++) {
33510            const record = records[i2];
33511            const target = record.target;
33512            const nodeName = target.nodeName;
33513            if (nodeName === "TABLE" || nodeName === "TBODY" || nodeName === "THEAD" || nodeName === "TR") {
33514              gridNeedsRedraw = true;
33515              break;
33516            }
33517          }
33518          if (!gridNeedsRedraw) {
33519            return;
33520          }
33521          const {
33522            tableNode,
33523            tableElement
33524          } = this.$lookup();
33525          this.table = getTable(tableNode, tableElement);
33526        }, {
33527          editor: this.editor
33528        });
33529      });
33530      this.editor.getEditorState().read(() => {
33531        const {
33532          tableNode,
33533          tableElement
33534        } = this.$lookup();
33535        this.table = getTable(tableNode, tableElement);
33536        observer.observe(tableElement, {
33537          attributes: true,
33538          childList: true,
33539          subtree: true
33540        });
33541      }, {
33542        editor: this.editor
33543      });
33544    }
33545    $clearHighlight(setEmptySelection = true) {
33546      const editor = this.editor;
33547      this.isHighlightingCells = false;
33548      this.anchorX = -1;
33549      this.anchorY = -1;
33550      this.focusX = -1;
33551      this.focusY = -1;
33552      this.tableSelection = null;
33553      this.anchorCellNodeKey = null;
33554      this.focusCellNodeKey = null;
33555      this.anchorCell = null;
33556      this.focusCell = null;
33557      this.hasHijackedSelectionStyles = false;
33558      this.$enableHighlightStyle();
33559      const {
33560        tableNode,
33561        tableElement
33562      } = this.$lookup();
33563      const grid = getTable(tableNode, tableElement);
33564      $updateDOMForSelection(editor, grid, null);
33565      if (setEmptySelection && $getSelection2() !== null) {
33566        $setSelection2(null);
33567        editor.dispatchCommand(SELECTION_CHANGE_COMMAND2, void 0);
33568      }
33569    }
33570    $enableHighlightStyle() {
33571      const editor = this.editor;
33572      const {
33573        tableElement
33574      } = this.$lookup();
33575      removeClassNamesFromElement3(tableElement, editor._config.theme.tableSelection);
33576      tableElement.classList.remove("disable-selection");
33577      this.hasHijackedSelectionStyles = false;
33578    }
33579    $disableHighlightStyle() {
33580      const {
33581        tableElement
33582      } = this.$lookup();
33583      addClassNamesToElement3(tableElement, this.editor._config.theme.tableSelection);
33584      this.hasHijackedSelectionStyles = true;
33585    }
33586    $updateTableTableSelection(selection) {
33587      if (selection !== null) {
33588        if (!(selection.tableKey === this.tableNodeKey)) {
33589          formatDevErrorMessage12(`TableObserver.$updateTableTableSelection: selection.tableKey !== this.tableNodeKey ('${selection.tableKey}' !== '${this.tableNodeKey}')`);
33590        }
33591        const editor = this.editor;
33592        this.tableSelection = selection;
33593        this.isHighlightingCells = true;
33594        this.$disableHighlightStyle();
33595        this.updateDOMSelection();
33596        $updateDOMForSelection(editor, this.table, this.tableSelection);
33597      } else {
33598        this.$clearHighlight();
33599      }
33600    }
33601    /** @internal */
33602    updateDOMSelection() {
33603      if (this.anchorCell !== null && this.focusCell !== null) {
33604        const domSelection = getDOMSelection2(this.editor._window);
33605        if (domSelection && domSelection.rangeCount > 0) {
33606          domSelection.removeAllRanges();
33607        }
33608      }
33609    }
33610    $setFocusCellForSelection(cell, ignoreStart = false) {
33611      const editor = this.editor;
33612      const {
33613        tableNode
33614      } = this.$lookup();
33615      const cellX = cell.x;
33616      const cellY = cell.y;
33617      this.focusCell = cell;
33618      if (!this.isHighlightingCells) {
33619        const shouldEnable = ignoreStart || this.anchorX !== cellX || this.anchorY !== cellY || this.tableSelection != null && this.anchorCellNodeKey != null;
33620        if (shouldEnable) {
33621          this.isHighlightingCells = true;
33622          this.$disableHighlightStyle();
33623        }
33624      }
33625      if (this.focusX !== -1 && this.focusY !== -1 && cellX === this.focusX && cellY === this.focusY) {
33626        return false;
33627      }
33628      this.focusX = cellX;
33629      this.focusY = cellY;
33630      if (this.isHighlightingCells) {
33631        const focusTableCellNode = $getNearestTableCellInTableFromDOMNode(tableNode, cell.elem);
33632        if (this.tableSelection != null && this.anchorCellNodeKey != null) {
33633          let targetCellNode = focusTableCellNode;
33634          if (targetCellNode === null && ignoreStart) {
33635            targetCellNode = tableNode.getCellNodeFromCords(cellX, cellY, this.table);
33636          }
33637          if (targetCellNode !== null) {
33638            const anchorTableCell = this.$getAnchorTableCellOrThrow();
33639            this.focusCellNodeKey = targetCellNode.getKey();
33640            this.tableSelection = $createTableSelectionFrom(tableNode, anchorTableCell, targetCellNode);
33641            $setSelection2(this.tableSelection);
33642            editor.dispatchCommand(SELECTION_CHANGE_COMMAND2, void 0);
33643            $updateDOMForSelection(editor, this.table, this.tableSelection);
33644            return true;
33645          }
33646        }
33647      }
33648      return false;
33649    }
33650    $getAnchorTableCell() {
33651      return this.anchorCellNodeKey ? $getNodeByKey2(this.anchorCellNodeKey) : null;
33652    }
33653    $getAnchorTableCellOrThrow() {
33654      const anchorTableCell = this.$getAnchorTableCell();
33655      if (!(anchorTableCell !== null)) {
33656        formatDevErrorMessage12(`TableObserver anchorTableCell is null`);
33657      }
33658      return anchorTableCell;
33659    }
33660    $getFocusTableCell() {
33661      return this.focusCellNodeKey ? $getNodeByKey2(this.focusCellNodeKey) : null;
33662    }
33663    $getFocusTableCellOrThrow() {
33664      const focusTableCell = this.$getFocusTableCell();
33665      if (!(focusTableCell !== null)) {
33666        formatDevErrorMessage12(`TableObserver focusTableCell is null`);
33667      }
33668      return focusTableCell;
33669    }
33670    $setAnchorCellForSelection(cell) {
33671      this.isHighlightingCells = false;
33672      this.anchorCell = cell;
33673      this.anchorX = cell.x;
33674      this.anchorY = cell.y;
33675      this.focusX = -1;
33676      this.focusY = -1;
33677      this.focusCell = null;
33678      this.focusCellNodeKey = null;
33679      const {
33680        tableNode
33681      } = this.$lookup();
33682      const anchorTableCellNode = $getNearestTableCellInTableFromDOMNode(tableNode, cell.elem);
33683      if (anchorTableCellNode !== null) {
33684        const anchorNodeKey = anchorTableCellNode.getKey();
33685        if (this.tableSelection != null) {
33686          this.tableSelection = this.tableSelection.clone();
33687          this.tableSelection.set(tableNode.getKey(), anchorNodeKey, anchorNodeKey);
33688        } else {
33689          this.tableSelection = $createTableSelectionFrom(tableNode, anchorTableCellNode, anchorTableCellNode);
33690        }
33691        this.anchorCellNodeKey = anchorNodeKey;
33692      }
33693    }
33694    $formatCells(type) {
33695      const selection = $getSelection2();
33696      if (!$isTableSelection(selection)) {
33697        formatDevErrorMessage12(`Expected Table selection`);
33698      }
33699      const formatSelection = $createRangeSelection2();
33700      const anchor = formatSelection.anchor;
33701      const focus = formatSelection.focus;
33702      const cellNodes = selection.getNodes().filter($isTableCellNode);
33703      if (!(cellNodes.length > 0)) {
33704        formatDevErrorMessage12(`No table cells present`);
33705      }
33706      const paragraph = cellNodes[0].getFirstChild();
33707      const alignFormatWith = $isParagraphNode2(paragraph) ? paragraph.getFormatFlags(type, null) : null;
33708      cellNodes.forEach((cellNode) => {
33709        anchor.set(cellNode.getKey(), 0, "element");
33710        focus.set(cellNode.getKey(), cellNode.getChildrenSize(), "element");
33711        formatSelection.formatText(type, alignFormatWith);
33712      });
33713      $setSelection2(selection);
33714      this.editor.dispatchCommand(SELECTION_CHANGE_COMMAND2, void 0);
33715    }
33716    $clearText() {
33717      const {
33718        editor
33719      } = this;
33720      const tableNode = $getNodeByKey2(this.tableNodeKey);
33721      if (!$isTableNode(tableNode)) {
33722        throw new Error("Expected TableNode.");
33723      }
33724      const selection = $getSelection2();
33725      if (!$isTableSelection(selection)) {
33726        formatDevErrorMessage12(`Expected TableSelection`);
33727      }
33728      const selectedNodes = selection.getNodes().filter($isTableCellNode);
33729      const firstRow = tableNode.getFirstChild();
33730      const lastRow = tableNode.getLastChild();
33731      const isEntireTableSelected = selectedNodes.length > 0 && firstRow !== null && lastRow !== null && $isTableRowNode(firstRow) && $isTableRowNode(lastRow) && selectedNodes[0] === firstRow.getFirstChild() && selectedNodes[selectedNodes.length - 1] === lastRow.getLastChild();
33732      if (isEntireTableSelected) {
33733        tableNode.selectPrevious();
33734        const parent = tableNode.getParent();
33735        tableNode.remove();
33736        if ($isRootNode2(parent) && parent.isEmpty()) {
33737          editor.dispatchCommand(INSERT_PARAGRAPH_COMMAND2, void 0);
33738        }
33739        return;
33740      }
33741      selectedNodes.forEach((cellNode) => {
33742        if ($isElementNode2(cellNode)) {
33743          const paragraphNode = $createParagraphNode2();
33744          const textNode = $createTextNode2();
33745          paragraphNode.append(textNode);
33746          cellNode.append(paragraphNode);
33747          cellNode.getChildren().forEach((child) => {
33748            if (child !== paragraphNode) {
33749              child.remove();
33750            }
33751          });
33752        }
33753      });
33754      $updateDOMForSelection(editor, this.table, null);
33755      $setSelection2(null);
33756      editor.dispatchCommand(SELECTION_CHANGE_COMMAND2, void 0);
33757    }
33758  };
33759  var LEXICAL_ELEMENT_KEY = "__lexicalTableSelection";
33760  var isPointerDownOnEvent = (event) => {
33761    return (event.buttons & 1) === 1;
33762  };
33763  function isHTMLTableElement(el) {
33764    return isHTMLElement2(el) && el.nodeName === "TABLE";
33765  }
33766  function getTableElement(tableNode, dom) {
33767    if (!dom) {
33768      return dom;
33769    }
33770    const element = isHTMLTableElement(dom) ? dom : dom.querySelector("table");
33771    if (!isHTMLTableElement(element)) {
33772      formatDevErrorMessage12(`getTableElement: Expecting table in DOM node for ${tableNode.constructor.name} of type ${tableNode.getType()} with key ${tableNode.getKey()}, not ${dom.nodeName}`);
33773    }
33774    return element;
33775  }
33776  function getEditorWindow(editor) {
33777    return editor._window;
33778  }
33779  function $findParentTableCellNodeInTable(tableNode, node) {
33780    for (let currentNode = node, lastTableCellNode = null; currentNode !== null; currentNode = currentNode.getParent()) {
33781      if (tableNode.is(currentNode)) {
33782        return lastTableCellNode;
33783      } else if ($isTableCellNode(currentNode)) {
33784        lastTableCellNode = currentNode;
33785      }
33786    }
33787    return null;
33788  }
33789  var ARROW_KEY_COMMANDS_WITH_DIRECTION = [[KEY_ARROW_DOWN_COMMAND2, "down"], [KEY_ARROW_UP_COMMAND2, "up"], [KEY_ARROW_LEFT_COMMAND2, "backward"], [KEY_ARROW_RIGHT_COMMAND2, "forward"]];
33790  var DELETE_TEXT_COMMANDS = [DELETE_WORD_COMMAND2, DELETE_LINE_COMMAND2, DELETE_CHARACTER_COMMAND2];
33791  var DELETE_KEY_COMMANDS = [KEY_BACKSPACE_COMMAND2, KEY_DELETE_COMMAND2];
33792  function registerTableWindowHandlers(editor, tableObservers) {
33793    const rootElement = editor.getRootElement();
33794    const editorWindow = editor._window;
33795    if (!rootElement || !editorWindow) {
33796      return () => {
33797      };
33798    }
33799    const pointerDownCallback = (event) => {
33800      const target = event.target;
33801      if (event.button !== 0 || !isDOMNode2(target) || !rootElement.contains(target)) {
33802        return;
33803      }
33804      const selectionInfo = getTableObserverFromCellNode(target);
33805      editor.update(() => {
33806        const selection = $getSelection2();
33807        if ($isTableSelection(selection)) {
33808          for (const [observer] of tableObservers.observers.values()) {
33809            observer.$clearHighlight(false);
33810          }
33811          $setSelection2(null);
33812          editor.dispatchCommand(SELECTION_CHANGE_COMMAND2, void 0);
33813        }
33814        if (!selectionInfo) {
33815          return;
33816        }
33817        const {
33818          tableObserver,
33819          tableElement,
33820          cellElement
33821        } = selectionInfo;
33822        $handleTableClick(editor, event, cellElement, tableElement, tableObserver, tableObservers);
33823      });
33824    };
33825    editorWindow.addEventListener("pointerdown", pointerDownCallback);
33826    return () => {
33827      editorWindow.removeEventListener("pointerdown", pointerDownCallback);
33828    };
33829  }
33830  function $handleTableClick(editor, event, selectedDOMCell, tableElement, tableObserver, tableObservers) {
33831    const editorWindow = editor._window;
33832    if (!editorWindow) {
33833      return;
33834    }
33835    const createPointerHandlers = (startingCell) => {
33836      if (tableObserver.isSelecting) {
33837        return;
33838      }
33839      tableObserver.isSelecting = true;
33840      if (startingCell !== null && tableObserver.anchorCell === null) {
33841        editor.update(() => {
33842          tableObserver.$setAnchorCellForSelection(startingCell);
33843        });
33844      }
33845      const onPointerUp = () => {
33846        tableObserver.isSelecting = false;
33847        editorWindow.removeEventListener("pointerup", onPointerUp);
33848        editorWindow.removeEventListener("pointermove", onPointerMove);
33849      };
33850      const onPointerMove = (moveEvent) => {
33851        if (!isPointerDownOnEvent(moveEvent) && tableObserver.isSelecting) {
33852          tableObserver.isSelecting = false;
33853          editorWindow.removeEventListener("pointerup", onPointerUp);
33854          editorWindow.removeEventListener("pointermove", onPointerMove);
33855          return;
33856        }
33857        if (!isDOMNode2(moveEvent.target)) {
33858          return;
33859        }
33860        let focusCell = null;
33861        const override = !(IS_FIREFOX4 || tableElement.contains(moveEvent.target));
33862        if (override) {
33863          focusCell = getDOMCellInTableFromTarget(tableElement, moveEvent.target);
33864        } else {
33865          for (const el of document.elementsFromPoint(moveEvent.clientX, moveEvent.clientY)) {
33866            focusCell = getDOMCellInTableFromTarget(tableElement, el);
33867            if (focusCell) {
33868              break;
33869            }
33870          }
33871        }
33872        if (focusCell) {
33873          const anchorCell = focusCell;
33874          if (tableObserver.anchorCell === null) {
33875            editor.update(() => {
33876              tableObserver.$setAnchorCellForSelection(anchorCell);
33877            });
33878          }
33879          if (tableObserver.focusCell === null || focusCell.elem !== tableObserver.focusCell.elem) {
33880            tableObservers.setNextFocus({
33881              focusCell,
33882              override,
33883              tableKey: tableObserver.tableNodeKey
33884            });
33885            editor.dispatchCommand(SELECTION_CHANGE_COMMAND2, void 0);
33886          }
33887        }
33888      };
33889      editorWindow.addEventListener("pointerup", onPointerUp, tableObserver.listenerOptions);
33890      editorWindow.addEventListener("pointermove", onPointerMove, tableObserver.listenerOptions);
33891    };
33892    tableObserver.pointerType = event.pointerType;
33893    const tableNode = $getNodeByKeyOrThrow2(tableObserver.tableNodeKey);
33894    const prevSelection = $getPreviousSelection2();
33895    if (IS_FIREFOX4 && event.shiftKey && $isSelectionInTable(prevSelection, tableNode) && ($isRangeSelection2(prevSelection) || $isTableSelection(prevSelection))) {
33896      const prevAnchorNode = prevSelection.anchor.getNode();
33897      const prevAnchorCell = $findParentTableCellNodeInTable(tableNode, prevSelection.anchor.getNode());
33898      if (prevAnchorCell) {
33899        tableObserver.$setAnchorCellForSelection($getObserverCellFromCellNodeOrThrow(tableObserver, prevAnchorCell));
33900        tableObserver.$setFocusCellForSelection(selectedDOMCell);
33901        stopEvent(event);
33902      } else {
33903        const newSelection = tableNode.isBefore(prevAnchorNode) ? tableNode.selectStart() : tableNode.selectEnd();
33904        newSelection.anchor.set(prevSelection.anchor.key, prevSelection.anchor.offset, prevSelection.anchor.type);
33905      }
33906    } else {
33907      if (event.pointerType !== "touch") {
33908        tableObserver.$setAnchorCellForSelection(selectedDOMCell);
33909      }
33910    }
33911    createPointerHandlers(selectedDOMCell);
33912  }
33913  function applyTableHandlers(tableNode, element, editor, hasTabHandler, tableObservers) {
33914    const rootElement = editor.getRootElement();
33915    const editorWindow = getEditorWindow(editor);
33916    if (!(rootElement !== null && editorWindow !== null)) {
33917      formatDevErrorMessage12(`applyTableHandlers: editor has no root element set`);
33918    }
33919    const tableObserver = new TableObserver(editor, tableNode.getKey());
33920    const tableElement = getTableElement(tableNode, element);
33921    attachTableObserverToTableElement(tableElement, tableObserver);
33922    tableObserver.listenersToRemove.add(() => detachTableObserverFromTableElement(tableElement, tableObserver));
33923    const onTripleClick = (event) => {
33924      if (event.detail >= 3 && isDOMNode2(event.target)) {
33925        const targetCell = getDOMCellFromTarget(event.target);
33926        if (targetCell !== null) {
33927          event.preventDefault();
33928        }
33929      }
33930    };
33931    tableElement.addEventListener("mousedown", onTripleClick, tableObserver.listenerOptions);
33932    tableObserver.listenersToRemove.add(() => {
33933      tableElement.removeEventListener("mousedown", onTripleClick);
33934    });
33935    for (const [command, direction] of ARROW_KEY_COMMANDS_WITH_DIRECTION) {
33936      tableObserver.listenersToRemove.add(editor.registerCommand(command, (event) => $handleArrowKey(editor, event, direction, tableNode, tableObserver, tableObservers), COMMAND_PRIORITY_HIGH2));
33937    }
33938    tableObserver.listenersToRemove.add(editor.registerCommand(KEY_ESCAPE_COMMAND2, (event) => {
33939      const selection = $getSelection2();
33940      if ($isTableSelection(selection)) {
33941        const focusCellNode = $findParentTableCellNodeInTable(tableNode, selection.focus.getNode());
33942        if (focusCellNode !== null) {
33943          stopEvent(event);
33944          focusCellNode.selectEnd();
33945          return true;
33946        }
33947      }
33948      return false;
33949    }, COMMAND_PRIORITY_HIGH2));
33950    const deleteTextHandler = (command) => () => {
33951      const selection = $getSelection2();
33952      if (!$isSelectionInTable(selection, tableNode)) {
33953        return false;
33954      }
33955      if ($isTableSelection(selection)) {
33956        tableObserver.$clearText();
33957        return true;
33958      } else if ($isRangeSelection2(selection)) {
33959        const tableCellNode = $findParentTableCellNodeInTable(tableNode, selection.anchor.getNode());
33960        if (!$isTableCellNode(tableCellNode)) {
33961          return false;
33962        }
33963        const anchorNode = selection.anchor.getNode();
33964        const focusNode = selection.focus.getNode();
33965        const isAnchorInside = tableNode.isParentOf(anchorNode);
33966        const isFocusInside = tableNode.isParentOf(focusNode);
33967        const selectionContainsPartialTable = isAnchorInside && !isFocusInside || isFocusInside && !isAnchorInside;
33968        if (selectionContainsPartialTable) {
33969          tableObserver.$clearText();
33970          return true;
33971        }
33972        const nearestElementNode = $findMatchingParent3(selection.anchor.getNode(), (n2) => $isElementNode2(n2));
33973        const topLevelCellElementNode = nearestElementNode && $findMatchingParent3(nearestElementNode, (n2) => $isElementNode2(n2) && $isTableCellNode(n2.getParent()));
33974        if (!$isElementNode2(topLevelCellElementNode) || !$isElementNode2(nearestElementNode)) {
33975          return false;
33976        }
33977        if (command === DELETE_LINE_COMMAND2 && topLevelCellElementNode.getPreviousSibling() === null) {
33978          return true;
33979        }
33980      }
33981      return false;
33982    };
33983    for (const command of DELETE_TEXT_COMMANDS) {
33984      tableObserver.listenersToRemove.add(editor.registerCommand(command, deleteTextHandler(command), COMMAND_PRIORITY_HIGH2));
33985    }
33986    const $deleteCellHandler = (event) => {
33987      const selection = $getSelection2();
33988      if (!($isTableSelection(selection) || $isRangeSelection2(selection))) {
33989        return false;
33990      }
33991      const isAnchorInside = tableNode.isParentOf(selection.anchor.getNode());
33992      const isFocusInside = tableNode.isParentOf(selection.focus.getNode());
33993      if (isAnchorInside !== isFocusInside) {
33994        const tablePoint = isAnchorInside ? "anchor" : "focus";
33995        const outerPoint = isAnchorInside ? "focus" : "anchor";
33996        const {
33997          key,
33998          offset: offset3,
33999          type
34000        } = selection[outerPoint];
34001        const newSelection = tableNode[selection[tablePoint].isBefore(selection[outerPoint]) ? "selectPrevious" : "selectNext"]();
34002        newSelection[outerPoint].set(key, offset3, type);
34003        return false;
34004      }
34005      if (!$isSelectionInTable(selection, tableNode)) {
34006        return false;
34007      }
34008      if ($isTableSelection(selection)) {
34009        if (event) {
34010          event.preventDefault();
34011          event.stopPropagation();
34012        }
34013        tableObserver.$clearText();
34014        return true;
34015      }
34016      return false;
34017    };
34018    for (const command of DELETE_KEY_COMMANDS) {
34019      tableObserver.listenersToRemove.add(editor.registerCommand(command, $deleteCellHandler, COMMAND_PRIORITY_HIGH2));
34020    }
34021    tableObserver.listenersToRemove.add(editor.registerCommand(CUT_COMMAND2, (event) => {
34022      const selection = $getSelection2();
34023      if (selection) {
34024        if (!($isTableSelection(selection) || $isRangeSelection2(selection))) {
34025          return false;
34026        }
34027        void copyToClipboard2(editor, objectKlassEquals2(event, ClipboardEvent) ? event : null, $getClipboardDataFromSelection2(selection));
34028        const intercepted = $deleteCellHandler(event);
34029        if ($isRangeSelection2(selection)) {
34030          selection.removeText();
34031          return true;
34032        }
34033        return intercepted;
34034      }
34035      return false;
34036    }, COMMAND_PRIORITY_HIGH2));
34037    tableObserver.listenersToRemove.add(editor.registerCommand(FORMAT_TEXT_COMMAND2, (payload) => {
34038      const selection = $getSelection2();
34039      if (!$isSelectionInTable(selection, tableNode)) {
34040        return false;
34041      }
34042      if ($isTableSelection(selection)) {
34043        tableObserver.$formatCells(payload);
34044        return true;
34045      } else if ($isRangeSelection2(selection)) {
34046        const tableCellNode = $findMatchingParent3(selection.anchor.getNode(), (n2) => $isTableCellNode(n2));
34047        if (!$isTableCellNode(tableCellNode)) {
34048          return false;
34049        }
34050      }
34051      return false;
34052    }, COMMAND_PRIORITY_HIGH2));
34053    tableObserver.listenersToRemove.add(editor.registerCommand(FORMAT_ELEMENT_COMMAND2, (formatType) => {
34054      const selection = $getSelection2();
34055      if (!$isTableSelection(selection) || !$isSelectionInTable(selection, tableNode)) {
34056        return false;
34057      }
34058      const anchorNode = selection.anchor.getNode();
34059      const focusNode = selection.focus.getNode();
34060      if (!$isTableCellNode(anchorNode) || !$isTableCellNode(focusNode)) {
34061        return false;
34062      }
34063      if ($isFullTableSelection(selection, tableNode)) {
34064        tableNode.setFormat(formatType);
34065        return true;
34066      }
34067      const [tableMap, anchorCell, focusCell] = $computeTableMap(tableNode, anchorNode, focusNode);
34068      const maxRow = Math.max(anchorCell.startRow + anchorCell.cell.__rowSpan - 1, focusCell.startRow + focusCell.cell.__rowSpan - 1);
34069      const maxColumn = Math.max(anchorCell.startColumn + anchorCell.cell.__colSpan - 1, focusCell.startColumn + focusCell.cell.__colSpan - 1);
34070      const minRow = Math.min(anchorCell.startRow, focusCell.startRow);
34071      const minColumn = Math.min(anchorCell.startColumn, focusCell.startColumn);
34072      const visited = /* @__PURE__ */ new Set();
34073      for (let i2 = minRow; i2 <= maxRow; i2++) {
34074        for (let j3 = minColumn; j3 <= maxColumn; j3++) {
34075          const cell = tableMap[i2][j3].cell;
34076          if (visited.has(cell)) {
34077            continue;
34078          }
34079          visited.add(cell);
34080          cell.setFormat(formatType);
34081          const cellChildren = cell.getChildren();
34082          for (let k2 = 0; k2 < cellChildren.length; k2++) {
34083            const child = cellChildren[k2];
34084            if ($isElementNode2(child) && !child.isInline()) {
34085              child.setFormat(formatType);
34086            }
34087          }
34088        }
34089      }
34090      return true;
34091    }, COMMAND_PRIORITY_HIGH2));
34092    tableObserver.listenersToRemove.add(editor.registerCommand(CONTROLLED_TEXT_INSERTION_COMMAND2, (payload) => {
34093      const selection = $getSelection2();
34094      if (!$isSelectionInTable(selection, tableNode)) {
34095        return false;
34096      }
34097      if ($isTableSelection(selection)) {
34098        tableObserver.$clearHighlight();
34099        return false;
34100      } else if ($isRangeSelection2(selection)) {
34101        const tableCellNode = $findMatchingParent3(selection.anchor.getNode(), (n2) => $isTableCellNode(n2));
34102        if (!$isTableCellNode(tableCellNode)) {
34103          return false;
34104        }
34105        if (typeof payload === "string") {
34106          const edgePosition = $getTableEdgeCursorPosition(editor, selection, tableNode);
34107          if (edgePosition) {
34108            $insertParagraphAtTableEdge(edgePosition, tableNode, [$createTextNode2(payload)]);
34109            return true;
34110          }
34111        }
34112      }
34113      return false;
34114    }, COMMAND_PRIORITY_HIGH2));
34115    if (hasTabHandler) {
34116      tableObserver.listenersToRemove.add(editor.registerCommand(KEY_TAB_COMMAND2, (event) => {
34117        const selection = $getSelection2();
34118        if (!$isRangeSelection2(selection) || !selection.isCollapsed() || !$isSelectionInTable(selection, tableNode)) {
34119          return false;
34120        }
34121        const tableCellNode = $findCellNode(selection.anchor.getNode());
34122        if (tableCellNode === null || !tableNode.is($findTableNode(tableCellNode))) {
34123          return false;
34124        }
34125        stopEvent(event);
34126        $selectAdjacentCell(tableCellNode, event.shiftKey ? "previous" : "next");
34127        return true;
34128      }, COMMAND_PRIORITY_HIGH2));
34129    }
34130    tableObserver.listenersToRemove.add(editor.registerCommand(FOCUS_COMMAND2, (payload) => {
34131      return tableNode.isSelected();
34132    }, COMMAND_PRIORITY_HIGH2));
34133    tableObserver.listenersToRemove.add(editor.registerCommand(INSERT_PARAGRAPH_COMMAND2, () => {
34134      const selection = $getSelection2();
34135      if (!$isRangeSelection2(selection) || !selection.isCollapsed() || !$isSelectionInTable(selection, tableNode)) {
34136        return false;
34137      }
34138      const edgePosition = $getTableEdgeCursorPosition(editor, selection, tableNode);
34139      if (edgePosition) {
34140        $insertParagraphAtTableEdge(edgePosition, tableNode);
34141        return true;
34142      }
34143      return false;
34144    }, COMMAND_PRIORITY_HIGH2));
34145    return tableObserver;
34146  }
34147  function $handleTableSelectionChangeCommand(tableObservers, editor) {
34148    const selection = $getSelection2();
34149    const prevSelection = $getPreviousSelection2();
34150    const nextFocus = tableObservers.getAndClearNextFocus();
34151    if (nextFocus !== null) {
34152      const {
34153        tableKey,
34154        focusCell
34155      } = nextFocus;
34156      const observerAndTable = tableObservers.observers.get(tableKey);
34157      if (!!!observerAndTable) {
34158        formatDevErrorMessage12(`tableObserver not found for tableKey: ${tableKey}`);
34159      }
34160      const [tableObserver] = observerAndTable;
34161      if ($isTableSelection(selection) && selection.tableKey === tableObserver.tableNodeKey) {
34162        if (focusCell.x === tableObserver.focusX && focusCell.y === tableObserver.focusY) {
34163          return false;
34164        } else {
34165          tableObserver.$setFocusCellForSelection(focusCell);
34166          return true;
34167        }
34168      } else if (tableObserver.anchorCell !== null && tableObserver.anchorCellNodeKey !== null && focusCell.elem !== tableObserver.anchorCell.elem && tableObserver.tableSelection !== null) {
34169        tableObserver.$setFocusCellForSelection(focusCell, true);
34170        return true;
34171      }
34172    }
34173    const shouldCheckSelectionForTable = tableObservers.getAndClearShouldCheckSelectionForTable();
34174    if (!!shouldCheckSelectionForTable && $isRangeSelection2(prevSelection) && $isRangeSelection2(selection) && selection.isCollapsed()) {
34175      const tableNode = $getNodeByKeyOrThrow2(shouldCheckSelectionForTable);
34176      const anchor = selection.anchor.getNode();
34177      const firstRow = tableNode.getFirstChild();
34178      const anchorCell = $findCellNode(anchor);
34179      if (anchorCell !== null && $isTableRowNode(firstRow)) {
34180        const firstCell = firstRow.getFirstChild();
34181        if ($isTableCellNode(firstCell) && tableNode.is($findMatchingParent3(anchorCell, (node) => node.is(tableNode) || node.is(firstCell)))) {
34182          firstCell.selectStart();
34183          return true;
34184        }
34185      }
34186    }
34187    if ($isTableSelection(selection)) {
34188      $fixTableSelectionForSelectedTable(editor, selection);
34189    }
34190    if ($isRangeSelection2(selection)) {
34191      $fixRangeSelectionForSelectedTable(selection, tableObservers);
34192    }
34193    const tableNodesAndObservers = Array.from(tableObservers.observers.entries()).map(([tableKey, [tableObserver]]) => ({
34194      tableNode: $getNodeByKeyOrThrow2(tableKey),
34195      tableObserver
34196    }));
34197    for (const {
34198      tableNode,
34199      tableObserver
34200    } of tableNodesAndObservers) {
34201      $syncTableSelectionState(editor, tableNode, tableObserver);
34202    }
34203    return false;
34204  }
34205  function $fixRangeSelectionForSelectedTable(selection, tableObservers) {
34206    const prevSelection = $getPreviousSelection2();
34207    const {
34208      anchor,
34209      focus
34210    } = selection;
34211    const anchorNode = anchor.getNode();
34212    const focusNode = focus.getNode();
34213    const anchorCellNode = $findCellNode(anchorNode);
34214    const focusCellNode = $findCellNode(focusNode);
34215    const anchorCellTable = anchorCellNode ? $findTableNode(anchorCellNode) : null;
34216    const focusCellTable = focusCellNode ? $findTableNode(focusCellNode) : null;
34217    const isBackward = selection.isBackward();
34218    const isSameTable = anchorCellNode && focusCellNode && anchorCellTable && focusCellTable && anchorCellTable.is(focusCellTable);
34219    const shouldMoveFocus = focusCellTable && (!anchorCellTable || anchorCellTable.isParentOf(focusCellTable));
34220    const shouldMoveAnchor = anchorCellTable && (!focusCellTable || focusCellTable.isParentOf(anchorCellTable));
34221    if (shouldMoveFocus) {
34222      const newSelection = selection.clone();
34223      const [tableMap] = $computeTableMap(focusCellTable, focusCellNode, focusCellNode);
34224      const firstCell = tableMap[0][0].cell;
34225      const lastCell = tableMap[tableMap.length - 1].at(-1).cell;
34226      newSelection.focus.set(isBackward ? firstCell.getKey() : lastCell.getKey(), isBackward ? 0 : lastCell.getChildrenSize(), "element");
34227      $setSelection2(newSelection);
34228    } else if (shouldMoveAnchor) {
34229      const newSelection = selection.clone();
34230      const [tableMap] = $computeTableMap(anchorCellTable, anchorCellNode, anchorCellNode);
34231      const firstCell = tableMap[0][0].cell;
34232      const lastCell = tableMap[tableMap.length - 1].at(-1).cell;
34233      newSelection.anchor.set(isBackward ? lastCell.getKey() : firstCell.getKey(), isBackward ? lastCell.getChildrenSize() : 0, "element");
34234      $setSelection2(newSelection);
34235    } else if (isSameTable) {
34236      const observerInfo = tableObservers.observers.get(anchorCellTable.getKey());
34237      if (!!!observerInfo) {
34238        formatDevErrorMessage12(`tableObserver not found for tableKey: ${anchorCellTable.getKey()}`);
34239      }
34240      const [tableObserver] = observerInfo;
34241      if (!anchorCellNode.is(focusCellNode)) {
34242        tableObserver.$setAnchorCellForSelection($getObserverCellFromCellNodeOrThrow(tableObserver, anchorCellNode));
34243        tableObserver.$setFocusCellForSelection($getObserverCellFromCellNodeOrThrow(tableObserver, focusCellNode), true);
34244      }
34245      if (tableObserver.pointerType === "touch" && tableObserver.isSelecting && selection.isCollapsed() && $isRangeSelection2(prevSelection) && prevSelection.isCollapsed()) {
34246        const prevAnchorCellNode = $findCellNode(prevSelection.anchor.getNode());
34247        if (prevAnchorCellNode && !prevAnchorCellNode.is(focusCellNode)) {
34248          tableObserver.$setAnchorCellForSelection($getObserverCellFromCellNodeOrThrow(tableObserver, prevAnchorCellNode));
34249          tableObserver.$setFocusCellForSelection($getObserverCellFromCellNodeOrThrow(tableObserver, focusCellNode), true);
34250          tableObserver.pointerType = null;
34251        }
34252      }
34253    }
34254  }
34255  function $fixTableSelectionForSelectedTable(editor, selection) {
34256    const editorWindow = getEditorWindow(editor);
34257    const prevSelection = $getPreviousSelection2();
34258    if (!selection.is(prevSelection)) {
34259      return;
34260    }
34261    const tableNode = $getNodeByKeyOrThrow2(selection.tableKey);
34262    const domSelection = getDOMSelection2(editorWindow);
34263    if (domSelection && domSelection.anchorNode && domSelection.focusNode) {
34264      const focusNode = $getNearestNodeFromDOMNode2(domSelection.focusNode);
34265      const isFocusOutside = focusNode && !tableNode.isParentOf(focusNode);
34266      const anchorNode = $getNearestNodeFromDOMNode2(domSelection.anchorNode);
34267      const isAnchorInside = anchorNode && tableNode.isParentOf(anchorNode);
34268      if (isFocusOutside && isAnchorInside && domSelection.rangeCount > 0) {
34269        const newSelection = $createRangeSelectionFromDom2(domSelection, editor);
34270        if (newSelection) {
34271          newSelection.anchor.set(tableNode.getKey(), selection.isBackward() ? tableNode.getChildrenSize() : 0, "element");
34272          domSelection.removeAllRanges();
34273          $setSelection2(newSelection);
34274        }
34275      }
34276    }
34277  }
34278  function $syncTableSelectionState(editor, tableNode, tableObserver) {
34279    const selection = $getSelection2();
34280    const prevSelection = $getPreviousSelection2();
34281    if (selection && !selection.is(prevSelection) && ($isTableSelection(selection) || $isTableSelection(prevSelection)) && tableObserver.tableSelection && !tableObserver.tableSelection.is(prevSelection)) {
34282      if ($isTableSelection(selection) && selection.tableKey === tableObserver.tableNodeKey) {
34283        tableObserver.$updateTableTableSelection(selection);
34284      } else if (!$isTableSelection(selection) && $isTableSelection(prevSelection) && prevSelection.tableKey === tableObserver.tableNodeKey) {
34285        tableObserver.$updateTableTableSelection(null);
34286      }
34287    }
34288    if (tableObserver.hasHijackedSelectionStyles && !tableNode.isSelected()) {
34289      $removeHighlightStyleToTable(editor, tableObserver);
34290    } else if (!tableObserver.hasHijackedSelectionStyles && tableNode.isSelected()) {
34291      $addHighlightStyleToTable(editor, tableObserver);
34292    }
34293  }
34294  function detachTableObserverFromTableElement(tableElement, tableObserver) {
34295    if (getTableObserverFromTableElement(tableElement) === tableObserver) {
34296      delete tableElement[LEXICAL_ELEMENT_KEY];
34297    }
34298  }
34299  function attachTableObserverToTableElement(tableElement, tableObserver) {
34300    if (!(getTableObserverFromTableElement(tableElement) === null)) {
34301      formatDevErrorMessage12(`tableElement already has an attached TableObserver`);
34302    }
34303    tableElement[LEXICAL_ELEMENT_KEY] = tableObserver;
34304  }
34305  function getTableObserverFromTableElement(tableElement) {
34306    return tableElement[LEXICAL_ELEMENT_KEY] || null;
34307  }
34308  function getTableObserverFromCellNode(node) {
34309    const cellNode = getDOMCellFromTarget(node);
34310    if (cellNode === null) {
34311      return null;
34312    }
34313    let currentNode = cellNode.elem;
34314    while (currentNode != null) {
34315      const nodeName = currentNode.nodeName;
34316      if (nodeName === "TABLE" && LEXICAL_ELEMENT_KEY in currentNode && !!currentNode[LEXICAL_ELEMENT_KEY]) {
34317        return {
34318          cellElement: cellNode,
34319          tableElement: currentNode,
34320          tableObserver: currentNode[LEXICAL_ELEMENT_KEY]
34321        };
34322      }
34323      currentNode = currentNode.parentNode;
34324    }
34325    return null;
34326  }
34327  function getDOMCellFromTarget(node) {
34328    let currentNode = node;
34329    while (currentNode != null) {
34330      const nodeName = currentNode.nodeName;
34331      if (nodeName === "TD" || nodeName === "TH") {
34332        const cell = currentNode._cell;
34333        if (cell === void 0) {
34334          return null;
34335        }
34336        return cell;
34337      }
34338      currentNode = currentNode.parentNode;
34339    }
34340    return null;
34341  }
34342  function getDOMCellInTableFromTarget(table, node) {
34343    if (!table.contains(node)) {
34344      return null;
34345    }
34346    let cell = null;
34347    for (let currentNode = node; currentNode != null; currentNode = currentNode.parentNode) {
34348      if (currentNode === table) {
34349        return cell;
34350      }
34351      const nodeName = currentNode.nodeName;
34352      if (nodeName === "TD" || nodeName === "TH") {
34353        cell = currentNode._cell || null;
34354      }
34355    }
34356    return null;
34357  }
34358  function getTable(tableNode, dom) {
34359    const tableElement = getTableElement(tableNode, dom);
34360    const domRows = [];
34361    const grid = {
34362      columns: 0,
34363      domRows,
34364      rows: 0
34365    };
34366    let currentNode = tableElement.querySelector("tr");
34367    let x3 = 0;
34368    let y3 = 0;
34369    domRows.length = 0;
34370    while (currentNode != null) {
34371      const nodeMame = currentNode.nodeName;
34372      if (nodeMame === "TD" || nodeMame === "TH") {
34373        const elem = currentNode;
34374        const cell = {
34375          elem,
34376          hasBackgroundColor: elem.style.backgroundColor !== "",
34377          highlighted: false,
34378          x: x3,
34379          y: y3
34380        };
34381        currentNode._cell = cell;
34382        let row = domRows[y3];
34383        if (row === void 0) {
34384          row = domRows[y3] = [];
34385        }
34386        row[x3] = cell;
34387      } else {
34388        const child = currentNode.firstChild;
34389        if (child != null) {
34390          currentNode = child;
34391          continue;
34392        }
34393      }
34394      const sibling = currentNode.nextSibling;
34395      if (sibling != null) {
34396        x3++;
34397        currentNode = sibling;
34398        continue;
34399      }
34400      const parent = currentNode.parentNode;
34401      if (parent != null) {
34402        const parentSibling = parent.nextSibling;
34403        if (parentSibling == null) {
34404          break;
34405        }
34406        y3++;
34407        x3 = 0;
34408        currentNode = parentSibling;
34409      }
34410    }
34411    grid.columns = x3 + 1;
34412    grid.rows = y3 + 1;
34413    return grid;
34414  }
34415  function $updateDOMForSelection(editor, table, selection) {
34416    const selectedCellNodes = new Set(selection ? selection.getNodes() : []);
34417    $forEachTableCell(table, (cell, lexicalNode) => {
34418      const elem = cell.elem;
34419      if (selectedCellNodes.has(lexicalNode)) {
34420        cell.highlighted = true;
34421        $addHighlightToDOM(editor, cell);
34422      } else {
34423        cell.highlighted = false;
34424        $removeHighlightFromDOM(editor, cell);
34425        if (!elem.getAttribute("style")) {
34426          elem.removeAttribute("style");
34427        }
34428      }
34429    });
34430  }
34431  function $forEachTableCell(grid, cb) {
34432    const {
34433      domRows
34434    } = grid;
34435    for (let y3 = 0; y3 < domRows.length; y3++) {
34436      const row = domRows[y3];
34437      if (!row) {
34438        continue;
34439      }
34440      for (let x3 = 0; x3 < row.length; x3++) {
34441        const cell = row[x3];
34442        if (!cell) {
34443          continue;
34444        }
34445        const lexicalNode = $getNearestNodeFromDOMNode2(cell.elem);
34446        if (lexicalNode !== null) {
34447          cb(cell, lexicalNode, {
34448            x: x3,
34449            y: y3
34450          });
34451        }
34452      }
34453    }
34454  }
34455  function $addHighlightStyleToTable(editor, tableSelection) {
34456    tableSelection.$disableHighlightStyle();
34457    $forEachTableCell(tableSelection.table, (cell) => {
34458      cell.highlighted = true;
34459      $addHighlightToDOM(editor, cell);
34460    });
34461  }
34462  function $removeHighlightStyleToTable(editor, tableObserver) {
34463    tableObserver.$enableHighlightStyle();
34464    $forEachTableCell(tableObserver.table, (cell) => {
34465      const elem = cell.elem;
34466      cell.highlighted = false;
34467      $removeHighlightFromDOM(editor, cell);
34468      if (!elem.getAttribute("style")) {
34469        elem.removeAttribute("style");
34470      }
34471    });
34472  }
34473  function $selectAdjacentCell(tableCellNode, direction) {
34474    const siblingMethod = direction === "next" ? "getNextSibling" : "getPreviousSibling";
34475    const childMethod = direction === "next" ? "getFirstChild" : "getLastChild";
34476    const sibling = tableCellNode[siblingMethod]();
34477    if ($isElementNode2(sibling)) {
34478      return sibling.selectEnd();
34479    }
34480    const parentRow = $findMatchingParent3(tableCellNode, $isTableRowNode);
34481    if (!(parentRow !== null)) {
34482      formatDevErrorMessage12(`selectAdjacentCell: Cell not in table row`);
34483    }
34484    for (let nextRow = parentRow[siblingMethod](); $isTableRowNode(nextRow); nextRow = nextRow[siblingMethod]()) {
34485      const child = nextRow[childMethod]();
34486      if ($isElementNode2(child)) {
34487        return child.selectEnd();
34488      }
34489    }
34490    const parentTable = $findMatchingParent3(parentRow, $isTableNode);
34491    if (!(parentTable !== null)) {
34492      formatDevErrorMessage12(`selectAdjacentCell: Row not in table`);
34493    }
34494    return direction === "next" ? parentTable.selectNext() : parentTable.selectPrevious();
34495  }
34496  var selectTableNodeInDirection = (tableObserver, tableNode, x3, y3, direction) => {
34497    const isForward = direction === "forward";
34498    switch (direction) {
34499      case "backward":
34500      case "forward":
34501        if (x3 !== (isForward ? tableObserver.table.columns - 1 : 0)) {
34502          selectTableCellNode(tableNode.getCellNodeFromCordsOrThrow(x3 + (isForward ? 1 : -1), y3, tableObserver.table), isForward);
34503        } else {
34504          if (y3 !== (isForward ? tableObserver.table.rows - 1 : 0)) {
34505            selectTableCellNode(tableNode.getCellNodeFromCordsOrThrow(isForward ? 0 : tableObserver.table.columns - 1, y3 + (isForward ? 1 : -1), tableObserver.table), isForward);
34506          } else if (!isForward) {
34507            tableNode.selectPrevious();
34508          } else {
34509            tableNode.selectNext();
34510          }
34511        }
34512        return true;
34513      case "up":
34514        if (y3 !== 0) {
34515          selectTableCellNode(tableNode.getCellNodeFromCordsOrThrow(x3, y3 - 1, tableObserver.table), false);
34516        } else {
34517          tableNode.selectPrevious();
34518        }
34519        return true;
34520      case "down":
34521        if (y3 !== tableObserver.table.rows - 1) {
34522          selectTableCellNode(tableNode.getCellNodeFromCordsOrThrow(x3, y3 + 1, tableObserver.table), true);
34523        } else {
34524          tableNode.selectNext();
34525        }
34526        return true;
34527      default:
34528        return false;
34529    }
34530  };
34531  function getCorner(rect, cellValue) {
34532    let colName;
34533    let rowName;
34534    if (cellValue.startColumn === rect.minColumn) {
34535      colName = "minColumn";
34536    } else if (cellValue.startColumn + cellValue.cell.__colSpan - 1 === rect.maxColumn) {
34537      colName = "maxColumn";
34538    } else {
34539      return null;
34540    }
34541    if (cellValue.startRow === rect.minRow) {
34542      rowName = "minRow";
34543    } else if (cellValue.startRow + cellValue.cell.__rowSpan - 1 === rect.maxRow) {
34544      rowName = "maxRow";
34545    } else {
34546      return null;
34547    }
34548    return [colName, rowName];
34549  }
34550  function getCornerOrThrow(rect, cellValue) {
34551    const corner = getCorner(rect, cellValue);
34552    if (!(corner !== null)) {
34553      formatDevErrorMessage12(`getCornerOrThrow: cell ${cellValue.cell.getKey()} is not at a corner of rect`);
34554    }
34555    return corner;
34556  }
34557  function oppositeCorner([colName, rowName]) {
34558    return [colName === "minColumn" ? "maxColumn" : "minColumn", rowName === "minRow" ? "maxRow" : "minRow"];
34559  }
34560  function cellAtCornerOrThrow(tableMap, rect, [colName, rowName]) {
34561    const rowNum = rect[rowName];
34562    const rowMap = tableMap[rowNum];
34563    if (!(rowMap !== void 0)) {
34564      formatDevErrorMessage12(`cellAtCornerOrThrow: ${rowName} = ${String(rowNum)} missing in tableMap`);
34565    }
34566    const colNum = rect[colName];
34567    const cell = rowMap[colNum];
34568    if (!(cell !== void 0)) {
34569      formatDevErrorMessage12(`cellAtCornerOrThrow: ${colName} = ${String(colNum)} missing in tableMap`);
34570    }
34571    return cell;
34572  }
34573  function $extractRectCorners(tableMap, anchorCellValue, newFocusCellValue) {
34574    const rect = $computeTableCellRectBoundary(tableMap, anchorCellValue, newFocusCellValue);
34575    const anchorCorner = getCorner(rect, anchorCellValue);
34576    if (anchorCorner) {
34577      return [cellAtCornerOrThrow(tableMap, rect, anchorCorner), cellAtCornerOrThrow(tableMap, rect, oppositeCorner(anchorCorner))];
34578    }
34579    const newFocusCorner = getCorner(rect, newFocusCellValue);
34580    if (newFocusCorner) {
34581      return [cellAtCornerOrThrow(tableMap, rect, oppositeCorner(newFocusCorner)), cellAtCornerOrThrow(tableMap, rect, newFocusCorner)];
34582    }
34583    const newAnchorCorner = ["minColumn", "minRow"];
34584    return [cellAtCornerOrThrow(tableMap, rect, newAnchorCorner), cellAtCornerOrThrow(tableMap, rect, oppositeCorner(newAnchorCorner))];
34585  }
34586  function $adjustFocusInDirection(tableObserver, tableMap, anchorCellValue, focusCellValue, direction) {
34587    const rect = $computeTableCellRectBoundary(tableMap, anchorCellValue, focusCellValue);
34588    const spans = $computeTableCellRectSpans(tableMap, rect);
34589    const {
34590      topSpan,
34591      leftSpan,
34592      bottomSpan,
34593      rightSpan
34594    } = spans;
34595    const anchorCorner = getCornerOrThrow(rect, anchorCellValue);
34596    const [focusColumn, focusRow] = oppositeCorner(anchorCorner);
34597    let fCol = rect[focusColumn];
34598    let fRow = rect[focusRow];
34599    if (direction === "forward") {
34600      fCol += focusColumn === "maxColumn" ? 1 : leftSpan;
34601    } else if (direction === "backward") {
34602      fCol -= focusColumn === "minColumn" ? 1 : rightSpan;
34603    } else if (direction === "down") {
34604      fRow += focusRow === "maxRow" ? 1 : topSpan;
34605    } else if (direction === "up") {
34606      fRow -= focusRow === "minRow" ? 1 : bottomSpan;
34607    }
34608    const targetRowMap = tableMap[fRow];
34609    if (targetRowMap === void 0) {
34610      return false;
34611    }
34612    const newFocusCellValue = targetRowMap[fCol];
34613    if (newFocusCellValue === void 0) {
34614      return false;
34615    }
34616    const [finalAnchorCell, finalFocusCell] = $extractRectCorners(tableMap, anchorCellValue, newFocusCellValue);
34617    const anchorDOM = $getObserverCellFromCellNodeOrThrow(tableObserver, finalAnchorCell.cell);
34618    const focusDOM = $getObserverCellFromCellNodeOrThrow(tableObserver, finalFocusCell.cell);
34619    tableObserver.$setAnchorCellForSelection(anchorDOM);
34620    tableObserver.$setFocusCellForSelection(focusDOM, true);
34621    return true;
34622  }
34623  function $isSelectionInTable(selection, tableNode) {
34624    if ($isRangeSelection2(selection) || $isTableSelection(selection)) {
34625      const isAnchorInside = tableNode.isParentOf(selection.anchor.getNode());
34626      const isFocusInside = tableNode.isParentOf(selection.focus.getNode());
34627      return isAnchorInside && isFocusInside;
34628    }
34629    return false;
34630  }
34631  function $isFullTableSelection(selection, tableNode) {
34632    if ($isTableSelection(selection)) {
34633      const anchorNode = selection.anchor.getNode();
34634      const focusNode = selection.focus.getNode();
34635      if (tableNode && anchorNode && focusNode) {
34636        const [map] = $computeTableMap(tableNode, anchorNode, focusNode);
34637        return anchorNode.getKey() === map[0][0].cell.getKey() && focusNode.getKey() === map[map.length - 1].at(-1).cell.getKey();
34638      }
34639    }
34640    return false;
34641  }
34642  function selectTableCellNode(tableCell, fromStart) {
34643    if (fromStart) {
34644      tableCell.selectStart();
34645    } else {
34646      tableCell.selectEnd();
34647    }
34648  }
34649  function $addHighlightToDOM(editor, cell) {
34650    const element = cell.elem;
34651    const editorThemeClasses = editor._config.theme;
34652    const node = $getNearestNodeFromDOMNode2(element);
34653    if (!$isTableCellNode(node)) {
34654      formatDevErrorMessage12(`Expected to find LexicalNode from Table Cell DOMNode`);
34655    }
34656    addClassNamesToElement3(element, editorThemeClasses.tableCellSelected);
34657  }
34658  function $removeHighlightFromDOM(editor, cell) {
34659    const element = cell.elem;
34660    const node = $getNearestNodeFromDOMNode2(element);
34661    if (!$isTableCellNode(node)) {
34662      formatDevErrorMessage12(`Expected to find LexicalNode from Table Cell DOMNode`);
34663    }
34664    const editorThemeClasses = editor._config.theme;
34665    removeClassNamesFromElement3(element, editorThemeClasses.tableCellSelected);
34666  }
34667  function $findCellNode(node) {
34668    const cellNode = $findMatchingParent3(node, $isTableCellNode);
34669    return $isTableCellNode(cellNode) ? cellNode : null;
34670  }
34671  function $findTableNode(node) {
34672    const tableNode = $findMatchingParent3(node, $isTableNode);
34673    return $isTableNode(tableNode) ? tableNode : null;
34674  }
34675  function $getBlockParentIfFirstNode(node) {
34676    for (let prevNode = node, currentNode = node; currentNode !== null; prevNode = currentNode, currentNode = currentNode.getParent()) {
34677      if ($isElementNode2(currentNode)) {
34678        if (currentNode !== prevNode && currentNode.getFirstChild() !== prevNode) {
34679          return null;
34680        } else if (!currentNode.isInline()) {
34681          return currentNode;
34682        }
34683      }
34684    }
34685    return null;
34686  }
34687  function $handleHorizontalArrowKeyRangeSelection(editor, event, selection, alter, isBackward, tableNode, tableObserver) {
34688    const initialFocus = $caretFromPoint2(selection.focus, isBackward ? "previous" : "next");
34689    if ($isExtendableTextPointCaret2(initialFocus)) {
34690      return false;
34691    }
34692    let lastCaret = initialFocus;
34693    for (const nextCaret of $extendCaretToRange2(initialFocus).iterNodeCarets("shadowRoot")) {
34694      if (!($isSiblingCaret2(nextCaret) && $isElementNode2(nextCaret.origin))) {
34695        return false;
34696      }
34697      lastCaret = nextCaret;
34698    }
34699    const lastCaretParent = lastCaret.getParentAtCaret();
34700    if (!$isTableCellNode(lastCaretParent)) {
34701      return false;
34702    }
34703    const anchorCell = lastCaretParent;
34704    const focusCaret = $findNextTableCell($getSiblingCaret2(anchorCell, lastCaret.direction));
34705    const anchorCellTable = $findMatchingParent3(anchorCell, $isTableNode);
34706    if (!(anchorCellTable && anchorCellTable.is(tableNode))) {
34707      return false;
34708    }
34709    const anchorCellDOM = editor.getElementByKey(anchorCell.getKey());
34710    const anchorDOMCell = getDOMCellFromTarget(anchorCellDOM);
34711    if (!anchorCellDOM || !anchorDOMCell) {
34712      return false;
34713    }
34714    const anchorCellTableElement = $getElementForTableNode(editor, anchorCellTable);
34715    tableObserver.table = anchorCellTableElement;
34716    if (!focusCaret) {
34717      if (alter === "extend") {
34718        tableObserver.$setAnchorCellForSelection(anchorDOMCell);
34719        tableObserver.$setFocusCellForSelection(anchorDOMCell, true);
34720      } else {
34721        const outerFocusCaret = $getTableExitCaret($getSiblingCaret2(anchorCellTable, initialFocus.direction));
34722        $setPointFromCaret2(selection.anchor, outerFocusCaret);
34723        $setPointFromCaret2(selection.focus, outerFocusCaret);
34724      }
34725    } else if (alter === "extend") {
34726      const focusDOMCell = getDOMCellFromTarget(editor.getElementByKey(focusCaret.origin.getKey()));
34727      if (!focusDOMCell) {
34728        return false;
34729      }
34730      tableObserver.$setAnchorCellForSelection(anchorDOMCell);
34731      tableObserver.$setFocusCellForSelection(focusDOMCell, true);
34732    } else {
34733      const innerFocusCaret = $normalizeCaret2(focusCaret);
34734      $setPointFromCaret2(selection.anchor, innerFocusCaret);
34735      $setPointFromCaret2(selection.focus, innerFocusCaret);
34736    }
34737    stopEvent(event);
34738    return true;
34739  }
34740  function $getTableExitCaret(initialCaret) {
34741    const adjacent = $getAdjacentChildCaret2(initialCaret);
34742    return $isChildCaret2(adjacent) ? $normalizeCaret2(adjacent) : initialCaret;
34743  }
34744  function $findNextTableCell(initialCaret) {
34745    for (const nextCaret of $extendCaretToRange2(initialCaret).iterNodeCarets("root")) {
34746      const {
34747        origin
34748      } = nextCaret;
34749      if ($isTableCellNode(origin)) {
34750        if ($isChildCaret2(nextCaret)) {
34751          return $getChildCaret2(origin, initialCaret.direction);
34752        }
34753      } else if (!$isTableRowNode(origin)) {
34754        break;
34755      }
34756    }
34757    return null;
34758  }
34759  function $handleArrowKey(editor, event, direction, tableNode, tableObserver, tableObservers) {
34760    if ((direction === "up" || direction === "down") && isTypeaheadMenuInView(editor)) {
34761      return false;
34762    }
34763    const selection = $getSelection2();
34764    if (!$isSelectionInTable(selection, tableNode)) {
34765      if ($isRangeSelection2(selection)) {
34766        if (direction === "backward") {
34767          if (selection.focus.offset > 0) {
34768            return false;
34769          }
34770          const parentNode = $getBlockParentIfFirstNode(selection.focus.getNode());
34771          if (!parentNode) {
34772            return false;
34773          }
34774          const siblingNode = parentNode.getPreviousSibling();
34775          if (!$isTableNode(siblingNode)) {
34776            return false;
34777          }
34778          stopEvent(event);
34779          if (event.shiftKey) {
34780            selection.focus.set(siblingNode.getParentOrThrow().getKey(), siblingNode.getIndexWithinParent(), "element");
34781          } else {
34782            siblingNode.selectEnd();
34783          }
34784          return true;
34785        } else if (event.shiftKey && (direction === "up" || direction === "down")) {
34786          const focusNode = selection.focus.getNode();
34787          const isTableUnselect = !selection.isCollapsed() && (direction === "up" && !selection.isBackward() || direction === "down" && selection.isBackward());
34788          if (isTableUnselect) {
34789            let focusParentNode = $findMatchingParent3(focusNode, (n2) => $isTableNode(n2));
34790            if ($isTableCellNode(focusParentNode)) {
34791              focusParentNode = $findMatchingParent3(focusParentNode, $isTableNode);
34792            }
34793            if (focusParentNode !== tableNode) {
34794              return false;
34795            }
34796            if (!focusParentNode) {
34797              return false;
34798            }
34799            const sibling = direction === "down" ? focusParentNode.getNextSibling() : focusParentNode.getPreviousSibling();
34800            if (!sibling) {
34801              return false;
34802            }
34803            let newOffset = 0;
34804            if (direction === "up") {
34805              if ($isElementNode2(sibling)) {
34806                newOffset = sibling.getChildrenSize();
34807              }
34808            }
34809            let newFocusNode = sibling;
34810            if (direction === "up") {
34811              if ($isElementNode2(sibling)) {
34812                const lastCell = sibling.getLastChild();
34813                newFocusNode = lastCell ? lastCell : sibling;
34814                newOffset = $isTextNode2(newFocusNode) ? newFocusNode.getTextContentSize() : 0;
34815              }
34816            }
34817            const newSelection = selection.clone();
34818            newSelection.focus.set(newFocusNode.getKey(), newOffset, $isTextNode2(newFocusNode) ? "text" : "element");
34819            $setSelection2(newSelection);
34820            stopEvent(event);
34821            return true;
34822          } else if ($isRootOrShadowRoot2(focusNode)) {
34823            const selectedNode = direction === "up" ? selection.getNodes()[selection.getNodes().length - 1] : selection.getNodes()[0];
34824            if (selectedNode) {
34825              const tableCellNode = $findParentTableCellNodeInTable(tableNode, selectedNode);
34826              if (tableCellNode !== null) {
34827                const firstDescendant = tableNode.getFirstDescendant();
34828                const lastDescendant = tableNode.getLastDescendant();
34829                if (!firstDescendant || !lastDescendant) {
34830                  return false;
34831                }
34832                const [firstCellNode] = $getNodeTriplet(firstDescendant);
34833                const [lastCellNode] = $getNodeTriplet(lastDescendant);
34834                const firstCellCoords = tableNode.getCordsFromCellNode(firstCellNode, tableObserver.table);
34835                const lastCellCoords = tableNode.getCordsFromCellNode(lastCellNode, tableObserver.table);
34836                const firstCellDOM = tableNode.getDOMCellFromCordsOrThrow(firstCellCoords.x, firstCellCoords.y, tableObserver.table);
34837                const lastCellDOM = tableNode.getDOMCellFromCordsOrThrow(lastCellCoords.x, lastCellCoords.y, tableObserver.table);
34838                tableObserver.$setAnchorCellForSelection(firstCellDOM);
34839                tableObserver.$setFocusCellForSelection(lastCellDOM, true);
34840                return true;
34841              }
34842            }
34843            return false;
34844          } else {
34845            let focusParentNode = $findMatchingParent3(focusNode, (n2) => $isElementNode2(n2) && !n2.isInline());
34846            if ($isTableCellNode(focusParentNode)) {
34847              focusParentNode = $findMatchingParent3(focusParentNode, $isTableNode);
34848            }
34849            if (!focusParentNode) {
34850              return false;
34851            }
34852            const sibling = direction === "down" ? focusParentNode.getNextSibling() : focusParentNode.getPreviousSibling();
34853            if ($isTableNode(sibling) && tableObserver.tableNodeKey === sibling.getKey()) {
34854              const firstDescendant = sibling.getFirstDescendant();
34855              const lastDescendant = sibling.getLastDescendant();
34856              if (!firstDescendant || !lastDescendant) {
34857                return false;
34858              }
34859              const [firstCellNode] = $getNodeTriplet(firstDescendant);
34860              const [lastCellNode] = $getNodeTriplet(lastDescendant);
34861              const newSelection = selection.clone();
34862              newSelection.focus.set((direction === "up" ? firstCellNode : lastCellNode).getKey(), direction === "up" ? 0 : lastCellNode.getChildrenSize(), "element");
34863              stopEvent(event);
34864              $setSelection2(newSelection);
34865              return true;
34866            }
34867          }
34868        }
34869      }
34870      if (direction === "down" && $isScrollableTablesActive(editor)) {
34871        tableObservers.setShouldCheckSelectionForTable(tableNode.getKey());
34872      }
34873      return false;
34874    }
34875    if ($isRangeSelection2(selection)) {
34876      if (direction === "backward" || direction === "forward") {
34877        const alter = event.shiftKey ? "extend" : "move";
34878        return $handleHorizontalArrowKeyRangeSelection(editor, event, selection, alter, direction === "backward", tableNode, tableObserver);
34879      }
34880      if (selection.isCollapsed()) {
34881        const {
34882          anchor,
34883          focus
34884        } = selection;
34885        const anchorCellNode = $findMatchingParent3(anchor.getNode(), $isTableCellNode);
34886        const focusCellNode = $findMatchingParent3(focus.getNode(), $isTableCellNode);
34887        if (!$isTableCellNode(anchorCellNode) || !anchorCellNode.is(focusCellNode)) {
34888          return false;
34889        }
34890        const anchorCellTable = $findTableNode(anchorCellNode);
34891        if (anchorCellTable !== tableNode && anchorCellTable != null) {
34892          const anchorCellTableElement = getTableElement(anchorCellTable, editor.getElementByKey(anchorCellTable.getKey()));
34893          if (anchorCellTableElement != null) {
34894            tableObserver.table = getTable(anchorCellTable, anchorCellTableElement);
34895            return $handleArrowKey(editor, event, direction, anchorCellTable, tableObserver, tableObservers);
34896          }
34897        }
34898        const anchorCellDom = editor.getElementByKey(anchorCellNode.__key);
34899        const anchorDOM = editor.getElementByKey(anchor.key);
34900        if (anchorDOM == null || anchorCellDom == null) {
34901          return false;
34902        }
34903        let edgeSelectionRect;
34904        if (anchor.type === "element") {
34905          edgeSelectionRect = anchorDOM.getBoundingClientRect();
34906        } else {
34907          const domSelection = getDOMSelection2(getEditorWindow(editor));
34908          if (domSelection === null || domSelection.rangeCount === 0) {
34909            return false;
34910          }
34911          const range2 = domSelection.getRangeAt(0);
34912          edgeSelectionRect = range2.getBoundingClientRect();
34913        }
34914        const edgeChild = direction === "up" ? anchorCellNode.getFirstChild() : anchorCellNode.getLastChild();
34915        if (edgeChild == null) {
34916          return false;
34917        }
34918        const edgeChildDOM = editor.getElementByKey(edgeChild.__key);
34919        if (edgeChildDOM == null) {
34920          return false;
34921        }
34922        const edgeRect = edgeChildDOM.getBoundingClientRect();
34923        const isExiting = direction === "up" ? edgeRect.top > edgeSelectionRect.top - edgeSelectionRect.height : edgeSelectionRect.bottom + edgeSelectionRect.height > edgeRect.bottom;
34924        if (isExiting) {
34925          stopEvent(event);
34926          const cords = tableNode.getCordsFromCellNode(anchorCellNode, tableObserver.table);
34927          if (event.shiftKey) {
34928            const cell = tableNode.getDOMCellFromCordsOrThrow(cords.x, cords.y, tableObserver.table);
34929            tableObserver.$setAnchorCellForSelection(cell);
34930            tableObserver.$setFocusCellForSelection(cell, true);
34931          } else {
34932            return selectTableNodeInDirection(tableObserver, tableNode, cords.x, cords.y, direction);
34933          }
34934          return true;
34935        }
34936      }
34937    } else if ($isTableSelection(selection)) {
34938      const {
34939        anchor,
34940        focus
34941      } = selection;
34942      const anchorCellNode = $findMatchingParent3(anchor.getNode(), $isTableCellNode);
34943      const focusCellNode = $findMatchingParent3(focus.getNode(), $isTableCellNode);
34944      const [tableNodeFromSelection] = selection.getNodes();
34945      if (!$isTableNode(tableNodeFromSelection)) {
34946        formatDevErrorMessage12(`$handleArrowKey: TableSelection.getNodes()[0] expected to be TableNode`);
34947      }
34948      const tableElement = getTableElement(tableNodeFromSelection, editor.getElementByKey(tableNodeFromSelection.getKey()));
34949      if (!$isTableCellNode(anchorCellNode) || !$isTableCellNode(focusCellNode) || !$isTableNode(tableNodeFromSelection) || tableElement == null) {
34950        return false;
34951      }
34952      tableObserver.$updateTableTableSelection(selection);
34953      const grid = getTable(tableNodeFromSelection, tableElement);
34954      const cordsAnchor = tableNode.getCordsFromCellNode(anchorCellNode, grid);
34955      const anchorCell = tableNode.getDOMCellFromCordsOrThrow(cordsAnchor.x, cordsAnchor.y, grid);
34956      tableObserver.$setAnchorCellForSelection(anchorCell);
34957      stopEvent(event);
34958      if (event.shiftKey) {
34959        const [tableMap, anchorValue, focusValue] = $computeTableMap(tableNode, anchorCellNode, focusCellNode);
34960        return $adjustFocusInDirection(tableObserver, tableMap, anchorValue, focusValue, direction);
34961      } else {
34962        focusCellNode.selectEnd();
34963      }
34964      return true;
34965    }
34966    return false;
34967  }
34968  function stopEvent(event) {
34969    event.preventDefault();
34970    event.stopImmediatePropagation();
34971    event.stopPropagation();
34972  }
34973  function isTypeaheadMenuInView(editor) {
34974    const root = editor.getRootElement();
34975    if (!root) {
34976      return false;
34977    }
34978    return root.hasAttribute("aria-controls") && root.getAttribute("aria-controls") === "typeahead-menu";
34979  }
34980  function $insertParagraphAtTableEdge(edgePosition, tableNode, children) {
34981    const paragraphNode = $createParagraphNode2();
34982    if (edgePosition === "first") {
34983      tableNode.insertBefore(paragraphNode);
34984    } else {
34985      tableNode.insertAfter(paragraphNode);
34986    }
34987    paragraphNode.append(...children || []);
34988    paragraphNode.selectEnd();
34989  }
34990  function $getTableEdgeCursorPosition(editor, selection, tableNode) {
34991    const tableNodeParent = tableNode.getParent();
34992    if (!tableNodeParent) {
34993      return void 0;
34994    }
34995    const domSelection = getDOMSelection2(getEditorWindow(editor));
34996    if (!domSelection) {
34997      return void 0;
34998    }
34999    const domAnchorNode = domSelection.anchorNode;
35000    const tableNodeParentDOM = editor.getElementByKey(tableNodeParent.getKey());
35001    const tableElement = getTableElement(tableNode, editor.getElementByKey(tableNode.getKey()));
35002    if (!domAnchorNode || !tableNodeParentDOM || !tableElement || !tableNodeParentDOM.contains(domAnchorNode) || tableElement.contains(domAnchorNode)) {
35003      return void 0;
35004    }
35005    const anchorCellNode = $findMatchingParent3(selection.anchor.getNode(), (n2) => $isTableCellNode(n2));
35006    if (!anchorCellNode) {
35007      return void 0;
35008    }
35009    const parentTable = $findMatchingParent3(anchorCellNode, (n2) => $isTableNode(n2));
35010    if (!$isTableNode(parentTable) || !parentTable.is(tableNode)) {
35011      return void 0;
35012    }
35013    const [tableMap, cellValue] = $computeTableMap(tableNode, anchorCellNode, anchorCellNode);
35014    const firstCell = tableMap[0][0];
35015    const lastCell = tableMap[tableMap.length - 1][tableMap[0].length - 1];
35016    const {
35017      startRow,
35018      startColumn
35019    } = cellValue;
35020    const isAtFirstCell = startRow === firstCell.startRow && startColumn === firstCell.startColumn;
35021    const isAtLastCell = startRow === lastCell.startRow && startColumn === lastCell.startColumn;
35022    if (isAtFirstCell) {
35023      return "first";
35024    } else if (isAtLastCell) {
35025      return "last";
35026    } else {
35027      return void 0;
35028    }
35029  }
35030  function $getObserverCellFromCellNodeOrThrow(tableObserver, tableCellNode) {
35031    const {
35032      tableNode
35033    } = tableObserver.$lookup();
35034    const currentCords = tableNode.getCordsFromCellNode(tableCellNode, tableObserver.table);
35035    return tableNode.getDOMCellFromCordsOrThrow(currentCords.x, currentCords.y, tableObserver.table);
35036  }
35037  function $getNearestTableCellInTableFromDOMNode(tableNode, startingDOM, editorState) {
35038    return $findParentTableCellNodeInTable(tableNode, $getNearestNodeFromDOMNode2(startingDOM, editorState));
35039  }
35040  function isHTMLDivElement(element) {
35041    return isHTMLElement3(element) && element.nodeName === "DIV";
35042  }
35043  function updateColgroup(dom, colCount, colWidths) {
35044    const colGroup = dom.querySelector("colgroup");
35045    if (!colGroup) {
35046      return;
35047    }
35048    const cols = [];
35049    for (let i2 = 0; i2 < colCount; i2++) {
35050      const col = document.createElement("col");
35051      const width = colWidths && colWidths[i2];
35052      if (width) {
35053        col.style.width = `${width}px`;
35054      }
35055      cols.push(col);
35056    }
35057    colGroup.replaceChildren(...cols);
35058  }
35059  function setRowStriping(dom, config, rowStriping) {
35060    if (rowStriping) {
35061      addClassNamesToElement3(dom, config.theme.tableRowStriping);
35062      dom.setAttribute("data-lexical-row-striping", "true");
35063    } else {
35064      removeClassNamesFromElement3(dom, config.theme.tableRowStriping);
35065      dom.removeAttribute("data-lexical-row-striping");
35066    }
35067  }
35068  function setFrozenColumns(dom, tableElement, config, frozenColumnCount) {
35069    if (frozenColumnCount > 0) {
35070      addClassNamesToElement3(dom, config.theme.tableFrozenColumn);
35071      tableElement.setAttribute("data-lexical-frozen-column", "true");
35072    } else {
35073      removeClassNamesFromElement3(dom, config.theme.tableFrozenColumn);
35074      tableElement.removeAttribute("data-lexical-frozen-column");
35075    }
35076  }
35077  function setFrozenRows(dom, tableElement, config, frozenRowCount) {
35078    if (frozenRowCount > 0) {
35079      addClassNamesToElement3(dom, config.theme.tableFrozenRow);
35080      tableElement.setAttribute("data-lexical-frozen-row", "true");
35081    } else {
35082      removeClassNamesFromElement3(dom, config.theme.tableFrozenRow);
35083      tableElement.removeAttribute("data-lexical-frozen-row");
35084    }
35085  }
35086  function alignTableElement(dom, config, formatType) {
35087    if (!config.theme.tableAlignment) {
35088      return;
35089    }
35090    const removeClasses = [];
35091    const addClasses = [];
35092    for (const format of ["center", "right"]) {
35093      const classes = config.theme.tableAlignment[format];
35094      if (!classes) {
35095        continue;
35096      }
35097      (format === formatType ? addClasses : removeClasses).push(classes);
35098    }
35099    removeClassNamesFromElement3(dom, ...removeClasses);
35100    addClassNamesToElement3(dom, ...addClasses);
35101  }
35102  var scrollableEditors = /* @__PURE__ */ new WeakSet();
35103  function $isScrollableTablesActive(editor = $getEditor2()) {
35104    return scrollableEditors.has(editor);
35105  }
35106  function setScrollableTablesActive(editor, active) {
35107    if (active) {
35108      if (!editor._config.theme.tableScrollableWrapper) {
35109        console.warn("TableNode: hasHorizontalScroll is active but theme.tableScrollableWrapper is not defined.");
35110      }
35111      scrollableEditors.add(editor);
35112    } else {
35113      scrollableEditors.delete(editor);
35114    }
35115  }
35116  var TableNode = class _TableNode extends ElementNode2 {
35117    /** @internal */
35118    __rowStriping;
35119    __frozenColumnCount;
35120    __frozenRowCount;
35121    __colWidths;
35122    static getType() {
35123      return "table";
35124    }
35125    getColWidths() {
35126      const self2 = this.getLatest();
35127      return self2.__colWidths;
35128    }
35129    setColWidths(colWidths) {
35130      const self2 = this.getWritable();
35131      self2.__colWidths = colWidths !== void 0 && true ? Object.freeze(colWidths) : colWidths;
35132      return self2;
35133    }
35134    static clone(node) {
35135      return new _TableNode(node.__key);
35136    }
35137    afterCloneFrom(prevNode) {
35138      super.afterCloneFrom(prevNode);
35139      this.__colWidths = prevNode.__colWidths;
35140      this.__rowStriping = prevNode.__rowStriping;
35141      this.__frozenColumnCount = prevNode.__frozenColumnCount;
35142      this.__frozenRowCount = prevNode.__frozenRowCount;
35143    }
35144    static importDOM() {
35145      return {
35146        table: (_node) => ({
35147          conversion: $convertTableElement2,
35148          priority: 1
35149        })
35150      };
35151    }
35152    static importJSON(serializedNode) {
35153      return $createTableNode().updateFromJSON(serializedNode);
35154    }
35155    updateFromJSON(serializedNode) {
35156      return super.updateFromJSON(serializedNode).setRowStriping(serializedNode.rowStriping || false).setFrozenColumns(serializedNode.frozenColumnCount || 0).setFrozenRows(serializedNode.frozenRowCount || 0).setColWidths(serializedNode.colWidths);
35157    }
35158    constructor(key) {
35159      super(key);
35160      this.__rowStriping = false;
35161      this.__frozenColumnCount = 0;
35162      this.__frozenRowCount = 0;
35163      this.__colWidths = void 0;
35164    }
35165    exportJSON() {
35166      return {
35167        ...super.exportJSON(),
35168        colWidths: this.getColWidths(),
35169        frozenColumnCount: this.__frozenColumnCount ? this.__frozenColumnCount : void 0,
35170        frozenRowCount: this.__frozenRowCount ? this.__frozenRowCount : void 0,
35171        rowStriping: this.__rowStriping ? this.__rowStriping : void 0
35172      };
35173    }
35174    extractWithChild(child, selection, destination) {
35175      return destination === "html";
35176    }
35177    getDOMSlot(element) {
35178      const tableElement = !isHTMLTableElement(element) ? element.querySelector("table") : element;
35179      if (!isHTMLTableElement(tableElement)) {
35180        formatDevErrorMessage12(`TableNode.getDOMSlot: createDOM() did not return a table`);
35181      }
35182      return super.getDOMSlot(element).withElement(tableElement).withAfter(tableElement.querySelector("colgroup"));
35183    }
35184    createDOM(config, editor) {
35185      const tableElement = document.createElement("table");
35186      if (this.__style) {
35187        setDOMStyleFromCSS2(tableElement.style, this.__style);
35188      }
35189      const colGroup = document.createElement("colgroup");
35190      tableElement.appendChild(colGroup);
35191      setDOMUnmanaged2(colGroup);
35192      addClassNamesToElement3(tableElement, config.theme.table);
35193      this.updateTableElement(null, tableElement, config);
35194      if ($isScrollableTablesActive(editor)) {
35195        const wrapperElement = document.createElement("div");
35196        const classes = config.theme.tableScrollableWrapper;
35197        if (classes) {
35198          addClassNamesToElement3(wrapperElement, classes);
35199        } else {
35200          wrapperElement.style.overflowX = "auto";
35201        }
35202        wrapperElement.appendChild(tableElement);
35203        this.updateTableWrapper(null, wrapperElement, tableElement, config);
35204        return wrapperElement;
35205      }
35206      return tableElement;
35207    }
35208    updateTableWrapper(prevNode, tableWrapper, tableElement, config) {
35209      if (this.__frozenColumnCount !== (prevNode ? prevNode.__frozenColumnCount : 0)) {
35210        setFrozenColumns(tableWrapper, tableElement, config, this.__frozenColumnCount);
35211      }
35212      if (this.__frozenRowCount !== (prevNode ? prevNode.__frozenRowCount : 0)) {
35213        setFrozenRows(tableWrapper, tableElement, config, this.__frozenRowCount);
35214      }
35215    }
35216    updateTableElement(prevNode, tableElement, config) {
35217      if (this.__style !== (prevNode ? prevNode.__style : "")) {
35218        setDOMStyleFromCSS2(tableElement.style, this.__style, prevNode ? prevNode.__style : "");
35219      }
35220      if (this.__rowStriping !== (prevNode ? prevNode.__rowStriping : false)) {
35221        setRowStriping(tableElement, config, this.__rowStriping);
35222      }
35223      const prevColCount = prevNode ? prevNode.getColumnCount() : 0;
35224      const prevColWidths = prevNode ? prevNode.__colWidths : void 0;
35225      if (this.getColumnCount() !== prevColCount || this.getColWidths() !== prevColWidths) {
35226        updateColgroup(tableElement, this.getColumnCount(), this.getColWidths());
35227      }
35228      alignTableElement(tableElement, config, this.getFormatType());
35229    }
35230    updateDOM(prevNode, dom, config) {
35231      const tableElement = getTableElement(this, dom);
35232      if (dom === tableElement === $isScrollableTablesActive()) {
35233        return true;
35234      }
35235      if (isHTMLDivElement(dom)) {
35236        this.updateTableWrapper(prevNode, dom, tableElement, config);
35237      }
35238      this.updateTableElement(prevNode, tableElement, config);
35239      return false;
35240    }
35241    scaleDOMColWidths(dom, scale) {
35242      const colWidths = this.getColWidths();
35243      if (!colWidths) {
35244        return;
35245      }
35246      const tableElement = getTableElement(this, dom);
35247      updateColgroup(tableElement, this.getColumnCount(), colWidths.map((width) => width * scale));
35248    }
35249    exportDOM(editor) {
35250      const superExport = super.exportDOM(editor);
35251      const {
35252        element
35253      } = superExport;
35254      return {
35255        after: (tableElement) => {
35256          if (superExport.after) {
35257            tableElement = superExport.after(tableElement);
35258          }
35259          if (!isHTMLTableElement(tableElement) && isHTMLElement3(tableElement)) {
35260            tableElement = tableElement.querySelector("table");
35261          }
35262          if (!isHTMLTableElement(tableElement)) {
35263            return null;
35264          }
35265          alignTableElement(tableElement, editor._config, this.getFormatType());
35266          const [tableMap] = $computeTableMapSkipCellCheck(this, null, null);
35267          const cellValues = /* @__PURE__ */ new Map();
35268          for (const mapRow of tableMap) {
35269            for (const mapValue of mapRow) {
35270              const key = mapValue.cell.getKey();
35271              if (!cellValues.has(key)) {
35272                cellValues.set(key, {
35273                  colSpan: mapValue.cell.getColSpan(),
35274                  startColumn: mapValue.startColumn
35275                });
35276              }
35277            }
35278          }
35279          const knownColumns = /* @__PURE__ */ new Set();
35280          for (const cellDOM of tableElement.querySelectorAll(":scope > tr > [data-temporary-table-cell-lexical-key]")) {
35281            const key = cellDOM.getAttribute("data-temporary-table-cell-lexical-key");
35282            if (key) {
35283              const cellSpan = cellValues.get(key);
35284              cellDOM.removeAttribute("data-temporary-table-cell-lexical-key");
35285              if (cellSpan) {
35286                cellValues.delete(key);
35287                for (let i2 = 0; i2 < cellSpan.colSpan; i2++) {
35288                  knownColumns.add(i2 + cellSpan.startColumn);
35289                }
35290              }
35291            }
35292          }
35293          const colGroup = tableElement.querySelector(":scope > colgroup");
35294          if (colGroup) {
35295            const cols = Array.from(tableElement.querySelectorAll(":scope > colgroup > col")).filter((dom, i2) => knownColumns.has(i2));
35296            colGroup.replaceChildren(...cols);
35297          }
35298          const rows = tableElement.querySelectorAll(":scope > tr");
35299          if (rows.length > 0) {
35300            const tBody = document.createElement("tbody");
35301            for (const row of rows) {
35302              tBody.appendChild(row);
35303            }
35304            tableElement.append(tBody);
35305          }
35306          return tableElement;
35307        },
35308        element: !isHTMLTableElement(element) && isHTMLElement3(element) ? element.querySelector("table") : element
35309      };
35310    }
35311    canBeEmpty() {
35312      return false;
35313    }
35314    isShadowRoot() {
35315      return true;
35316    }
35317    getCordsFromCellNode(tableCellNode, table) {
35318      const {
35319        rows,
35320        domRows
35321      } = table;
35322      for (let y3 = 0; y3 < rows; y3++) {
35323        const row = domRows[y3];
35324        if (row == null) {
35325          continue;
35326        }
35327        for (let x3 = 0; x3 < row.length; x3++) {
35328          const cell = row[x3];
35329          if (cell == null) {
35330            continue;
35331          }
35332          const {
35333            elem
35334          } = cell;
35335          const cellNode = $getNearestTableCellInTableFromDOMNode(this, elem);
35336          if (cellNode !== null && tableCellNode.is(cellNode)) {
35337            return {
35338              x: x3,
35339              y: y3
35340            };
35341          }
35342        }
35343      }
35344      throw new Error("Cell not found in table.");
35345    }
35346    getDOMCellFromCords(x3, y3, table) {
35347      const {
35348        domRows
35349      } = table;
35350      const row = domRows[y3];
35351      if (row == null) {
35352        return null;
35353      }
35354      const index = x3 < row.length ? x3 : row.length - 1;
35355      const cell = row[index];
35356      if (cell == null) {
35357        return null;
35358      }
35359      return cell;
35360    }
35361    getDOMCellFromCordsOrThrow(x3, y3, table) {
35362      const cell = this.getDOMCellFromCords(x3, y3, table);
35363      if (!cell) {
35364        throw new Error("Cell not found at cords.");
35365      }
35366      return cell;
35367    }
35368    getCellNodeFromCords(x3, y3, table) {
35369      const cell = this.getDOMCellFromCords(x3, y3, table);
35370      if (cell == null) {
35371        return null;
35372      }
35373      const node = $getNearestNodeFromDOMNode2(cell.elem);
35374      if ($isTableCellNode(node)) {
35375        return node;
35376      }
35377      return null;
35378    }
35379    getCellNodeFromCordsOrThrow(x3, y3, table) {
35380      const node = this.getCellNodeFromCords(x3, y3, table);
35381      if (!node) {
35382        throw new Error("Node at cords not TableCellNode.");
35383      }
35384      return node;
35385    }
35386    getRowStriping() {
35387      return Boolean(this.getLatest().__rowStriping);
35388    }
35389    setRowStriping(newRowStriping) {
35390      const self2 = this.getWritable();
35391      self2.__rowStriping = newRowStriping;
35392      return self2;
35393    }
35394    setFrozenColumns(columnCount) {
35395      const self2 = this.getWritable();
35396      self2.__frozenColumnCount = columnCount;
35397      return self2;
35398    }
35399    getFrozenColumns() {
35400      return this.getLatest().__frozenColumnCount;
35401    }
35402    setFrozenRows(rowCount) {
35403      const self2 = this.getWritable();
35404      self2.__frozenRowCount = rowCount;
35405      return self2;
35406    }
35407    getFrozenRows() {
35408      return this.getLatest().__frozenRowCount;
35409    }
35410    canSelectBefore() {
35411      return true;
35412    }
35413    canIndent() {
35414      return false;
35415    }
35416    getColumnCount() {
35417      const firstRow = this.getFirstChild();
35418      if (!firstRow) {
35419        return 0;
35420      }
35421      let columnCount = 0;
35422      firstRow.getChildren().forEach((cell) => {
35423        if ($isTableCellNode(cell)) {
35424          columnCount += cell.getColSpan();
35425        }
35426      });
35427      return columnCount;
35428    }
35429  };
35430  function $getElementForTableNode(editor, tableNode) {
35431    const tableElement = editor.getElementByKey(tableNode.getKey());
35432    if (!(tableElement !== null)) {
35433      formatDevErrorMessage12(`$getElementForTableNode: Table Element Not Found`);
35434    }
35435    return getTable(tableNode, tableElement);
35436  }
35437  function $convertTableElement2(domNode) {
35438    const tableNode = $createTableNode();
35439    if (domNode.hasAttribute("data-lexical-row-striping")) {
35440      tableNode.setRowStriping(true);
35441    }
35442    if (domNode.hasAttribute("data-lexical-frozen-column")) {
35443      tableNode.setFrozenColumns(1);
35444    }
35445    if (domNode.hasAttribute("data-lexical-frozen-row")) {
35446      tableNode.setFrozenRows(1);
35447    }
35448    const colGroup = domNode.querySelector(":scope > colgroup");
35449    if (colGroup) {
35450      let columns = [];
35451      for (const col of colGroup.querySelectorAll(":scope > col")) {
35452        let width = col.style.width || "";
35453        if (!PIXEL_VALUE_REG_EXP.test(width)) {
35454          width = col.getAttribute("width") || "";
35455          if (!/^\d+$/.test(width)) {
35456            columns = void 0;
35457            break;
35458          }
35459        }
35460        columns.push(parseFloat(width));
35461      }
35462      if (columns) {
35463        tableNode.setColWidths(columns);
35464      }
35465    }
35466    return {
35467      after: (children) => $descendantsMatching2(children, $isTableRowNode),
35468      node: tableNode
35469    };
35470  }
35471  function $createTableNode() {
35472    return $applyNodeReplacement2(new TableNode());
35473  }
35474  function $isTableNode(node) {
35475    return node instanceof TableNode;
35476  }
35477  function $insertTable({
35478    rows,
35479    columns,
35480    includeHeaders
35481  }, hasNestedTables) {
35482    const selection = $getSelection2() || $getPreviousSelection2();
35483    if (!selection || !$isRangeSelection2(selection)) {
35484      return false;
35485    }
35486    if (!hasNestedTables && $findTableNode(selection.anchor.getNode())) {
35487      return false;
35488    }
35489    const tableNode = $createTableNodeWithDimensions(Number(rows), Number(columns), includeHeaders);
35490    $insertNodeToNearestRoot2(tableNode);
35491    const firstDescendant = tableNode.getFirstDescendant();
35492    if ($isTextNode2(firstDescendant)) {
35493      firstDescendant.select();
35494    }
35495    return true;
35496  }
35497  function $tableCellTransform(node) {
35498    if (!$isTableRowNode(node.getParent())) {
35499      node.remove();
35500    } else if (node.isEmpty()) {
35501      node.append($createParagraphNode2());
35502    }
35503  }
35504  function $tableRowTransform(node) {
35505    if (!$isTableNode(node.getParent())) {
35506      node.remove();
35507    } else {
35508      $unwrapAndFilterDescendants2(node, $isTableCellNode);
35509    }
35510  }
35511  function $tableTransform(node) {
35512    $unwrapAndFilterDescendants2(node, $isTableRowNode);
35513    const [gridMap] = $computeTableMapSkipCellCheck(node, null, null);
35514    const maxRowLength = gridMap.reduce((curLength, row) => {
35515      return Math.max(curLength, row.length);
35516    }, 0);
35517    const rowNodes = node.getChildren();
35518    for (let i2 = 0; i2 < gridMap.length; ++i2) {
35519      const rowNode = rowNodes[i2];
35520      if (!rowNode) {
35521        continue;
35522      }
35523      if (!$isTableRowNode(rowNode)) {
35524        formatDevErrorMessage12(`TablePlugin: Expecting all children of TableNode to be TableRowNode, found ${rowNode.constructor.name} (type ${rowNode.getType()})`);
35525      }
35526      const rowLength = gridMap[i2].reduce((acc, cell) => cell ? 1 + acc : acc, 0);
35527      if (rowLength === maxRowLength) {
35528        continue;
35529      }
35530      for (let j3 = rowLength; j3 < maxRowLength; ++j3) {
35531        const newCell = $createTableCellNode();
35532        newCell.append($createParagraphNode2());
35533        rowNode.append(newCell);
35534      }
35535    }
35536    const colWidths = node.getColWidths();
35537    const columnCount = node.getColumnCount();
35538    if (colWidths && colWidths.length !== columnCount) {
35539      let newColWidths = void 0;
35540      if (columnCount < colWidths.length) {
35541        newColWidths = colWidths.slice(0, columnCount);
35542      } else if (colWidths.length > 0) {
35543        const fillWidth = colWidths[colWidths.length - 1];
35544        newColWidths = [...colWidths, ...Array(columnCount - colWidths.length).fill(fillWidth)];
35545      }
35546      node.setColWidths(newColWidths);
35547    }
35548  }
35549  function $tableClickCommand(event) {
35550    if (event.detail < 3 || !isDOMNode2(event.target)) {
35551      return false;
35552    }
35553    const startNode = $getNearestNodeFromDOMNode2(event.target);
35554    if (startNode === null) {
35555      return false;
35556    }
35557    const blockNode = $findMatchingParent3(startNode, (node) => $isElementNode2(node) && !node.isInline());
35558    if (blockNode === null) {
35559      return false;
35560    }
35561    const rootNode = blockNode.getParent();
35562    if (!$isTableCellNode(rootNode)) {
35563      return false;
35564    }
35565    blockNode.select(0);
35566    return true;
35567  }
35568  function $tableSelectAllCommand() {
35569    const selection = $getSelection2();
35570    if (!$isRangeSelection2(selection)) {
35571      return false;
35572    }
35573    const anchorNode = selection.anchor.getNode();
35574    const tableNode = $findTableNode(anchorNode);
35575    if (tableNode === null) {
35576      return false;
35577    }
35578    const root = $getRoot2();
35579    if (!root.is(tableNode.getParent()) || root.getChildrenSize() !== 1) {
35580      return false;
35581    }
35582    const [tableMap] = $computeTableMapSkipCellCheck(tableNode, null, null);
35583    if (tableMap.length === 0 || tableMap[0].length === 0) {
35584      return false;
35585    }
35586    const firstCellMap = tableMap[0][0];
35587    if (!firstCellMap || !firstCellMap.cell) {
35588      return false;
35589    }
35590    const lastRow = tableMap[tableMap.length - 1];
35591    const lastCellMap = lastRow[lastRow.length - 1];
35592    if (!lastCellMap || !lastCellMap.cell) {
35593      return false;
35594    }
35595    const tableSelection = $createTableSelectionFrom(tableNode, firstCellMap.cell, lastCellMap.cell);
35596    $setSelection2(tableSelection);
35597    return true;
35598  }
35599  function registerTableCellUnmergeTransform(editor) {
35600    return editor.registerNodeTransform(TableCellNode, (node) => {
35601      if (node.getColSpan() > 1 || node.getRowSpan() > 1) {
35602        const [, , gridNode] = $getNodeTriplet(node);
35603        const [gridMap] = $computeTableMap(gridNode, node, node);
35604        const rowsCount = gridMap.length;
35605        const columnsCount = gridMap[0].length;
35606        let row = gridNode.getFirstChild();
35607        if (!$isTableRowNode(row)) {
35608          formatDevErrorMessage12(`Expected TableNode first child to be a RowNode`);
35609        }
35610        const unmerged = [];
35611        for (let i2 = 0; i2 < rowsCount; i2++) {
35612          if (i2 !== 0) {
35613            row = row.getNextSibling();
35614            if (!$isTableRowNode(row)) {
35615              formatDevErrorMessage12(`Expected TableNode first child to be a RowNode`);
35616            }
35617          }
35618          let lastRowCell = null;
35619          for (let j3 = 0; j3 < columnsCount; j3++) {
35620            const cellMap = gridMap[i2][j3];
35621            const cell = cellMap.cell;
35622            if (cellMap.startRow === i2 && cellMap.startColumn === j3) {
35623              lastRowCell = cell;
35624              unmerged.push(cell);
35625            } else if (cell.getColSpan() > 1 || cell.getRowSpan() > 1) {
35626              if (!$isTableCellNode(cell)) {
35627                formatDevErrorMessage12(`Expected TableNode cell to be a TableCellNode`);
35628              }
35629              const newCell = $createTableCellNode(cell.__headerState);
35630              if (lastRowCell !== null) {
35631                lastRowCell.insertAfter(newCell);
35632              } else {
35633                $insertFirst2(row, newCell);
35634              }
35635            }
35636          }
35637        }
35638        for (const cell of unmerged) {
35639          cell.setColSpan(1);
35640          cell.setRowSpan(1);
35641        }
35642      }
35643    });
35644  }
35645  function registerTableSelectionObserver(editor, hasTabHandler = true) {
35646    const tableObservers = new TableObservers();
35647    const initializeTableNode = (tableNode, nodeKey, dom) => {
35648      const tableElement = getTableElement(tableNode, dom);
35649      const tableSelection = applyTableHandlers(tableNode, tableElement, editor, hasTabHandler, tableObservers);
35650      tableObservers.observers.set(nodeKey, [tableSelection, tableElement]);
35651    };
35652    return mergeRegister3(registerTableWindowHandlers(editor, tableObservers), editor.registerCommand(SELECTION_CHANGE_COMMAND2, () => {
35653      return $handleTableSelectionChangeCommand(tableObservers, editor);
35654    }, COMMAND_PRIORITY_HIGH2), editor.registerMutationListener(TableNode, (nodeMutations) => {
35655      editor.getEditorState().read(() => {
35656        for (const [nodeKey, mutation] of nodeMutations) {
35657          const tableSelection = tableObservers.observers.get(nodeKey);
35658          if (mutation === "created" || mutation === "updated") {
35659            const {
35660              tableNode,
35661              tableElement
35662            } = $getTableAndElementByKey(nodeKey);
35663            if (tableSelection === void 0) {
35664              initializeTableNode(tableNode, nodeKey, tableElement);
35665            } else if (tableElement !== tableSelection[1]) {
35666              tableSelection[0].removeListeners();
35667              tableObservers.observers.delete(nodeKey);
35668              initializeTableNode(tableNode, nodeKey, tableElement);
35669            }
35670          } else if (mutation === "destroyed") {
35671            if (tableSelection !== void 0) {
35672              tableSelection[0].removeListeners();
35673              tableObservers.observers.delete(nodeKey);
35674            }
35675          }
35676        }
35677      }, {
35678        editor
35679      });
35680    }, {
35681      skipInitialization: false
35682    }), () => {
35683      for (const [, [tableSelection]] of tableObservers.observers) {
35684        tableSelection.removeListeners();
35685      }
35686    });
35687  }
35688  function registerTablePlugin(editor, options) {
35689    if (!editor.hasNodes([TableNode])) {
35690      {
35691        formatDevErrorMessage12(`TablePlugin: TableNode is not registered on editor`);
35692      }
35693    }
35694    const {
35695      hasNestedTables = signal(false)
35696    } = options ?? {};
35697    return mergeRegister3(editor.registerCommand(INSERT_TABLE_COMMAND, (payload) => {
35698      return $insertTable(payload, hasNestedTables.peek());
35699    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(SELECTION_INSERT_CLIPBOARD_NODES_COMMAND2, (payload, dispatchEditor) => {
35700      if (editor !== dispatchEditor) {
35701        return false;
35702      }
35703      return $tableSelectionInsertClipboardNodesCommand(payload, hasNestedTables);
35704    }, COMMAND_PRIORITY_EDITOR2), editor.registerCommand(SELECT_ALL_COMMAND2, $tableSelectAllCommand, COMMAND_PRIORITY_LOW2), editor.registerCommand(CLICK_COMMAND2, $tableClickCommand, COMMAND_PRIORITY_EDITOR2), editor.registerNodeTransform(TableNode, $tableTransform), editor.registerNodeTransform(TableRowNode, $tableRowTransform), editor.registerNodeTransform(TableCellNode, $tableCellTransform));
35705  }
35706  function $tableSelectionInsertClipboardNodesCommand(selectionPayload, hasNestedTables) {
35707    const {
35708      nodes,
35709      selection
35710    } = selectionPayload;
35711    const hasTables = nodes.some((n2) => $isTableNode(n2) || $dfs2(n2).some((d3) => $isTableNode(d3.node)));
35712    if (!hasTables) {
35713      return false;
35714    }
35715    const isTableSelection = $isTableSelection(selection);
35716    const isRangeSelection = $isRangeSelection2(selection);
35717    const isSelectionInsideOfGrid = isRangeSelection && $findMatchingParent3(selection.anchor.getNode(), (n2) => $isTableCellNode(n2)) !== null && $findMatchingParent3(selection.focus.getNode(), (n2) => $isTableCellNode(n2)) !== null || isTableSelection;
35718    if (!isSelectionInsideOfGrid) {
35719      return false;
35720    }
35721    if (nodes.length === 1 && $isTableNode(nodes[0])) {
35722      return $insertTableIntoGrid(nodes[0], selection);
35723    }
35724    if (isRangeSelection && hasNestedTables.peek() && !$isMultiCellTableSelection(selection)) {
35725      return false;
35726    }
35727    return true;
35728  }
35729  function $insertTableIntoGrid(tableNode, selection) {
35730    const anchorAndFocus = selection.getStartEndPoints();
35731    const isTableSelection = $isTableSelection(selection);
35732    if (anchorAndFocus === null) {
35733      return false;
35734    }
35735    const [anchor, focus] = anchorAndFocus;
35736    const [anchorCellNode, anchorRowNode, gridNode] = $getNodeTriplet(anchor);
35737    const focusCellNode = $findMatchingParent3(focus.getNode(), (n2) => $isTableCellNode(n2));
35738    if (!$isTableCellNode(anchorCellNode) || !$isTableCellNode(focusCellNode) || !$isTableRowNode(anchorRowNode) || !$isTableNode(gridNode)) {
35739      return false;
35740    }
35741    const [initialGridMap, anchorCellMap, focusCellMap] = $computeTableMap(gridNode, anchorCellNode, focusCellNode);
35742    const [templateGridMap] = $computeTableMapSkipCellCheck(tableNode, null, null);
35743    const initialRowCount = initialGridMap.length;
35744    const initialColCount = initialRowCount > 0 ? initialGridMap[0].length : 0;
35745    let startRow = anchorCellMap.startRow;
35746    let startCol = anchorCellMap.startColumn;
35747    let affectedRowCount = templateGridMap.length;
35748    let affectedColCount = affectedRowCount > 0 ? templateGridMap[0].length : 0;
35749    if (isTableSelection) {
35750      const selectionBoundary = $computeTableCellRectBoundary(initialGridMap, anchorCellMap, focusCellMap);
35751      const selectionRowCount = selectionBoundary.maxRow - selectionBoundary.minRow + 1;
35752      const selectionColCount = selectionBoundary.maxColumn - selectionBoundary.minColumn + 1;
35753      startRow = selectionBoundary.minRow;
35754      startCol = selectionBoundary.minColumn;
35755      affectedRowCount = Math.min(affectedRowCount, selectionRowCount);
35756      affectedColCount = Math.min(affectedColCount, selectionColCount);
35757    }
35758    let didPerformMergeOperations = false;
35759    const lastRowForUnmerge = Math.min(initialRowCount, startRow + affectedRowCount) - 1;
35760    const lastColForUnmerge = Math.min(initialColCount, startCol + affectedColCount) - 1;
35761    const unmergedKeys = /* @__PURE__ */ new Set();
35762    for (let row = startRow; row <= lastRowForUnmerge; row++) {
35763      for (let col = startCol; col <= lastColForUnmerge; col++) {
35764        const cellMap = initialGridMap[row][col];
35765        if (unmergedKeys.has(cellMap.cell.getKey())) {
35766          continue;
35767        }
35768        if (cellMap.cell.__rowSpan === 1 && cellMap.cell.__colSpan === 1) {
35769          continue;
35770        }
35771        $unmergeCellNode(cellMap.cell);
35772        unmergedKeys.add(cellMap.cell.getKey());
35773        didPerformMergeOperations = true;
35774      }
35775    }
35776    let [interimGridMap] = $computeTableMapSkipCellCheck(gridNode.getWritable(), null, null);
35777    const rowsToInsert = affectedRowCount - initialRowCount + startRow;
35778    for (let i2 = 0; i2 < rowsToInsert; i2++) {
35779      const cellMap = interimGridMap[initialRowCount - 1][0];
35780      $insertTableRowAtNode(cellMap.cell);
35781    }
35782    const colsToInsert = affectedColCount - initialColCount + startCol;
35783    for (let i2 = 0; i2 < colsToInsert; i2++) {
35784      const cellMap = interimGridMap[0][initialColCount - 1];
35785      $insertTableColumnAtNode(cellMap.cell, true, false);
35786    }
35787    [interimGridMap] = $computeTableMapSkipCellCheck(gridNode.getWritable(), null, null);
35788    for (let row = startRow; row < startRow + affectedRowCount; row++) {
35789      for (let col = startCol; col < startCol + affectedColCount; col++) {
35790        const templateRow = row - startRow;
35791        const templateCol = col - startCol;
35792        const templateCellMap = templateGridMap[templateRow][templateCol];
35793        if (templateCellMap.startRow !== templateRow || templateCellMap.startColumn !== templateCol) {
35794          continue;
35795        }
35796        const templateCell = templateCellMap.cell;
35797        if (templateCell.__rowSpan !== 1 || templateCell.__colSpan !== 1) {
35798          const cellsToMerge = [];
35799          const lastRowForMerge = Math.min(row + templateCell.__rowSpan, startRow + affectedRowCount) - 1;
35800          const lastColForMerge = Math.min(col + templateCell.__colSpan, startCol + affectedColCount) - 1;
35801          for (let r2 = row; r2 <= lastRowForMerge; r2++) {
35802            for (let c2 = col; c2 <= lastColForMerge; c2++) {
35803              const cellMap = interimGridMap[r2][c2];
35804              cellsToMerge.push(cellMap.cell);
35805            }
35806          }
35807          $mergeCells(cellsToMerge);
35808          didPerformMergeOperations = true;
35809        }
35810        const {
35811          cell
35812        } = interimGridMap[row][col];
35813        const backgroundColor = templateCell.getBackgroundColor();
35814        if (backgroundColor !== null && backgroundColor !== void 0) {
35815          cell.setBackgroundColor(backgroundColor);
35816        }
35817        const originalChildren = cell.getChildren();
35818        templateCell.getChildren().forEach((child) => {
35819          if ($isTextNode2(child)) {
35820            const paragraphNode = $createParagraphNode2();
35821            paragraphNode.append(child);
35822            cell.append(child);
35823          } else {
35824            cell.append(child);
35825          }
35826        });
35827        originalChildren.forEach((n2) => n2.remove());
35828      }
35829    }
35830    if (isTableSelection && didPerformMergeOperations) {
35831      const [finalGridMap] = $computeTableMapSkipCellCheck(gridNode.getWritable(), null, null);
35832      const newAnchorCellMap = finalGridMap[anchorCellMap.startRow][anchorCellMap.startColumn];
35833      newAnchorCellMap.cell.selectEnd();
35834    }
35835    return true;
35836  }
35837  function $isMultiCellTableSelection(selection) {
35838    if ($isTableSelection(selection) && !selection.focus.getNode().is(selection.anchor.getNode())) {
35839      return true;
35840    }
35841    if ($isRangeSelection2(selection) && $isTableCellNode(selection.anchor.getNode()) && !selection.anchor.getNode().is(selection.focus.getNode())) {
35842      return true;
35843    }
35844    return false;
35845  }
35846  var TableExtension = defineExtension2({
35847    build(editor, config, state) {
35848      return namedSignals2(config);
35849    },
35850    config: safeCast2({
35851      hasCellBackgroundColor: true,
35852      hasCellMerge: true,
35853      hasHorizontalScroll: true,
35854      hasNestedTables: false,
35855      hasTabHandler: true
35856    }),
35857    name: "@lexical/table/Table",
35858    nodes: () => [TableNode, TableRowNode, TableCellNode],
35859    register(editor, config, state) {
35860      const stores = state.getOutput();
35861      return mergeRegister3(effect(() => {
35862        const hasHorizontalScroll = stores.hasHorizontalScroll.value;
35863        const hadHorizontalScroll = $isScrollableTablesActive(editor);
35864        if (hadHorizontalScroll !== hasHorizontalScroll) {
35865          setScrollableTablesActive(editor, hasHorizontalScroll);
35866          editor.registerNodeTransform(TableNode, () => {
35867          })();
35868        }
35869      }), registerTablePlugin(editor, stores), effect(() => registerTableSelectionObserver(editor, stores.hasTabHandler.value)), effect(() => stores.hasCellMerge.value ? void 0 : registerTableCellUnmergeTransform(editor)), effect(() => stores.hasCellBackgroundColor.value ? void 0 : editor.registerNodeTransform(TableCellNode, (node) => {
35870        if (node.getBackgroundColor() !== null) {
35871          node.setBackgroundColor(null);
35872        }
35873      })));
35874    }
35875  });
35876
35877  
vendor: 3,518 bytes, lines 35877-35935
35877// node_modules/@lexical/table/LexicalTable.mjs
35878  var mod17 = true ? LexicalTable_dev_exports : LexicalTable_prod_exports;
35879  var $computeTableMap2 = mod17.$computeTableMap;
35880  var $computeTableMapSkipCellCheck2 = mod17.$computeTableMapSkipCellCheck;
35881  var $createTableCellNode2 = mod17.$createTableCellNode;
35882  var $createTableNode2 = mod17.$createTableNode;
35883  var $createTableNodeWithDimensions2 = mod17.$createTableNodeWithDimensions;
35884  var $createTableRowNode2 = mod17.$createTableRowNode;
35885  var $createTableSelection2 = mod17.$createTableSelection;
35886  var $createTableSelectionFrom2 = mod17.$createTableSelectionFrom;
35887  var $deleteTableColumn2 = mod17.$deleteTableColumn;
35888  var $deleteTableColumnAtSelection2 = mod17.$deleteTableColumnAtSelection;
35889  var $deleteTableColumn__EXPERIMENTAL2 = mod17.$deleteTableColumn__EXPERIMENTAL;
35890  var $deleteTableRowAtSelection2 = mod17.$deleteTableRowAtSelection;
35891  var $deleteTableRow__EXPERIMENTAL2 = mod17.$deleteTableRow__EXPERIMENTAL;
35892  var $findCellNode2 = mod17.$findCellNode;
35893  var $findTableNode2 = mod17.$findTableNode;
35894  var $getElementForTableNode2 = mod17.$getElementForTableNode;
35895  var $getNodeTriplet2 = mod17.$getNodeTriplet;
35896  var $getTableAndElementByKey2 = mod17.$getTableAndElementByKey;
35897  var $getTableCellNodeFromLexicalNode2 = mod17.$getTableCellNodeFromLexicalNode;
35898  var $getTableCellNodeRect2 = mod17.$getTableCellNodeRect;
35899  var $getTableColumnIndexFromTableCellNode2 = mod17.$getTableColumnIndexFromTableCellNode;
35900  var $getTableNodeFromLexicalNodeOrThrow2 = mod17.$getTableNodeFromLexicalNodeOrThrow;
35901  var $getTableRowIndexFromTableCellNode2 = mod17.$getTableRowIndexFromTableCellNode;
35902  var $getTableRowNodeFromTableCellNodeOrThrow2 = mod17.$getTableRowNodeFromTableCellNodeOrThrow;
35903  var $insertTableColumn2 = mod17.$insertTableColumn;
35904  var $insertTableColumnAtSelection2 = mod17.$insertTableColumnAtSelection;
35905  var $insertTableColumn__EXPERIMENTAL2 = mod17.$insertTableColumn__EXPERIMENTAL;
35906  var $insertTableRow2 = mod17.$insertTableRow;
35907  var $insertTableRowAtSelection2 = mod17.$insertTableRowAtSelection;
35908  var $insertTableRow__EXPERIMENTAL2 = mod17.$insertTableRow__EXPERIMENTAL;
35909  var $isScrollableTablesActive2 = mod17.$isScrollableTablesActive;
35910  var $isSimpleTable2 = mod17.$isSimpleTable;
35911  var $isTableCellNode2 = mod17.$isTableCellNode;
35912  var $isTableNode2 = mod17.$isTableNode;
35913  var $isTableRowNode2 = mod17.$isTableRowNode;
35914  var $isTableSelection2 = mod17.$isTableSelection;
35915  var $mergeCells2 = mod17.$mergeCells;
35916  var $moveTableColumn2 = mod17.$moveTableColumn;
35917  var $removeTableRowAtIndex2 = mod17.$removeTableRowAtIndex;
35918  var $unmergeCell2 = mod17.$unmergeCell;
35919  var INSERT_TABLE_COMMAND2 = mod17.INSERT_TABLE_COMMAND;
35920  var TableCellHeaderStates2 = mod17.TableCellHeaderStates;
35921  var TableCellNode2 = mod17.TableCellNode;
35922  var TableExtension2 = mod17.TableExtension;
35923  var TableNode2 = mod17.TableNode;
35924  var TableObserver2 = mod17.TableObserver;
35925  var TableRowNode2 = mod17.TableRowNode;
35926  var applyTableHandlers2 = mod17.applyTableHandlers;
35927  var getDOMCellFromTarget2 = mod17.getDOMCellFromTarget;
35928  var getTableElement2 = mod17.getTableElement;
35929  var getTableObserverFromTableElement2 = mod17.getTableObserverFromTableElement;
35930  var registerTableCellUnmergeTransform2 = mod17.registerTableCellUnmergeTransform;
35931  var registerTablePlugin2 = mod17.registerTablePlugin;
35932  var registerTableSelectionObserver2 = mod17.registerTableSelectionObserver;
35933  var setScrollableTablesActive2 = mod17.setScrollableTablesActive;
35934
35935  
vendor: 55,601 bytes, lines 35935-37092
35935// node_modules/marked/lib/marked.esm.js
35936  function L() {
35937    return { async: false, breaks: false, extensions: null, gfm: true, hooks: null, pedantic: false, renderer: null, silent: false, tokenizer: null, walkTokens: null };
35938  }
35939  var T = L();
35940  function G(l4) {
35941    T = l4;
35942  }
35943  var E2 = { exec: () => null };
35944  function d2(l4, e2 = "") {
35945    let t2 = typeof l4 == "string" ? l4 : l4.source, n2 = { replace: (r2, i2) => {
35946      let s2 = typeof i2 == "string" ? i2 : i2.source;
35947      return s2 = s2.replace(m2.caret, "$1"), t2 = t2.replace(r2, s2), n2;
35948    }, getRegex: () => new RegExp(t2, e2) };
35949    return n2;
35950  }
35951  var be = (() => {
35952    try {
35953      return !!new RegExp("(?<=1)(?<!1)");
35954    } catch {
35955      return false;
35956    }
35957  })();
35958  var m2 = { codeRemoveIndent: /^(?: {1,4}| {0,3}\t)/gm, outputLinkReplace: /\\([\[\]])/g, indentCodeCompensation: /^(\s+)(?:```)/, beginningSpace: /^\s+/, endingHash: /#$/, startingSpaceChar: /^ /, endingSpaceChar: / $/, nonSpaceChar: /[^ ]/, newLineCharGlobal: /\n/g, tabCharGlobal: /\t/g, multipleSpaceGlobal: /\s+/g, blankLine: /^[ \t]*$/, doubleBlankLine: /\n[ \t]*\n[ \t]*$/, blockquoteStart: /^ {0,3}>/, blockquoteSetextReplace: /\n {0,3}((?:=+|-+) *)(?=\n|$)/g, blockquoteSetextReplace2: /^ {0,3}>[ \t]?/gm, listReplaceTabs: /^\t+/, listReplaceNesting: /^ {1,4}(?=( {4})*[^ ])/g, listIsTask: /^\[[ xX]\] /, listReplaceTask: /^\[[ xX]\] +/, anyLine: /\n.*\n/, hrefBrackets: /^<(.*)>$/, tableDelimiter: /[:|]/, tableAlignChars: /^\||\| *$/g, tableRowBlankLine: /\n[ \t]*$/, tableAlignRight: /^ *-+: *$/, tableAlignCenter: /^ *:-+: *$/, tableAlignLeft: /^ *:-+ *$/, startATag: /^<a /i, endATag: /^<\/a>/i, startPreScriptTag: /^<(pre|code|kbd|script)(\s|>)/i, endPreScriptTag: /^<\/(pre|code|kbd|script)(\s|>)/i, startAngleBracket: /^</, endAngleBracket: />$/, pedanticHrefTitle: /^([^'"]*[^\s])\s+(['"])(.*)\2/, unicodeAlphaNumeric: /[\p{L}\p{N}]/u, escapeTest: /[&<>"']/, escapeReplace: /[&<>"']/g, escapeTestNoEncode: /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/, escapeReplaceNoEncode: /[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/g, unescapeTest: /&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/ig, caret: /(^|[^\[])\^/g, percentDecode: /%25/g, findPipe: /\|/g, splitPipe: / \|/, slashPipe: /\\\|/g, carriageReturn: /\r\n|\r/g, spaceLine: /^ +$/gm, notSpaceStart: /^\S*/, endingNewline: /\n$/, listItemRegex: (l4) => new RegExp(`^( {0,3}${l4})((?:[	 ][^\\n]*)?(?:\\n|$))`), nextBulletRegex: (l4) => new RegExp(`^ {0,${Math.min(3, l4 - 1)}}(?:[*+-]|\\d{1,9}[.)])((?:[ 	][^\\n]*)?(?:\\n|$))`), hrRegex: (l4) => new RegExp(`^ {0,${Math.min(3, l4 - 1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`), fencesBeginRegex: (l4) => new RegExp(`^ {0,${Math.min(3, l4 - 1)}}(?:\`\`\`|~~~)`), headingBeginRegex: (l4) => new RegExp(`^ {0,${Math.min(3, l4 - 1)}}#`), htmlBeginRegex: (l4) => new RegExp(`^ {0,${Math.min(3, l4 - 1)}}<(?:[a-z].*>|!--)`, "i") };
35959  var Re = /^(?:[ \t]*(?:\n|$))+/;
35960  var Te = /^((?: {4}| {0,3}\t)[^\n]+(?:\n(?:[ \t]*(?:\n|$))*)?)+/;
35961  var Oe = /^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/;
35962  var I = /^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/;
35963  var we = /^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/;
35964  var F = /(?:[*+-]|\d{1,9}[.)])/;
35965  var ie2 = /^(?!bull |blockCode|fences|blockquote|heading|html|table)((?:.|\n(?!\s*?\n|bull |blockCode|fences|blockquote|heading|html|table))+?)\n {0,3}(=+|-+) *(?:\n+|$)/;
35966  var oe2 = d2(ie2).replace(/bull/g, F).replace(/blockCode/g, /(?: {4}| {0,3}\t)/).replace(/fences/g, / {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g, / {0,3}>/).replace(/heading/g, / {0,3}#{1,6}/).replace(/html/g, / {0,3}<[^\n>]+>\n/).replace(/\|table/g, "").getRegex();
35967  var ye2 = d2(ie2).replace(/bull/g, F).replace(/blockCode/g, /(?: {4}| {0,3}\t)/).replace(/fences/g, / {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g, / {0,3}>/).replace(/heading/g, / {0,3}#{1,6}/).replace(/html/g, / {0,3}<[^\n>]+>\n/).replace(/table/g, / {0,3}\|?(?:[:\- ]*\|)+[\:\- ]*\n/).getRegex();
35968  var j2 = /^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/;
35969  var Pe = /^[^\n]+/;
35970  var Q = /(?!\s*\])(?:\\[\s\S]|[^\[\]\\])+/;
35971  var Se = d2(/^ {0,3}\[(label)\]: *(?:\n[ \t]*)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n[ \t]*)?| *\n[ \t]*)(title))? *(?:\n+|$)/).replace("label", Q).replace("title", /(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/).getRegex();
35972  var $e = d2(/^( {0,3}bull)([ \t][^\n]+?)?(?:\n|$)/).replace(/bull/g, F).getRegex();
35973  var v2 = "address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul";
35974  var U2 = /<!--(?:-?>|[\s\S]*?(?:-->|$))/;
35975  var _e = d2("^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:</\\1>[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>\\n*|$)|<![A-Z][\\s\\S]*?(?:>\\n*|$)|<!\\[CDATA\\[[\\s\\S]*?(?:\\]\\]>\\n*|$)|</?(tag)(?: +|\\n|/?>)[\\s\\S]*?(?:(?:\\n[ 	]*)+\\n|$)|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ 	]*)+\\n|$)|</(?!script|pre|style|textarea)[a-z][\\w-]*\\s*>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n[ 	]*)+\\n|$))", "i").replace("comment", U2).replace("tag", v2).replace("attribute", / +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex();
35976  var ae2 = d2(j2).replace("hr", I).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("|lheading", "").replace("|table", "").replace("blockquote", " {0,3}>").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)]) ").replace("html", "</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", v2).getRegex();
35977  var Le = d2(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/).replace("paragraph", ae2).getRegex();
35978  var K = { blockquote: Le, code: Te, def: Se, fences: Oe, heading: we, hr: I, html: _e, lheading: oe2, list: $e, newline: Re, paragraph: ae2, table: E2, text: Pe };
35979  var re2 = d2("^ *([^\\n ].*)\\n {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)").replace("hr", I).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("blockquote", " {0,3}>").replace("code", "(?: {4}| {0,3}	)[^\\n]").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)]) ").replace("html", "</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", v2).getRegex();
35980  var Me = { ...K, lheading: ye2, table: re2, paragraph: d2(j2).replace("hr", I).replace("heading", " {0,3}#{1,6}(?:\\s|$)").replace("|lheading", "").replace("table", re2).replace("blockquote", " {0,3}>").replace("fences", " {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list", " {0,3}(?:[*+-]|1[.)]) ").replace("html", "</?(?:tag)(?: +|\\n|/?>)|<(?:script|pre|style|textarea|!--)").replace("tag", v2).getRegex() };
35981  var ze = { ...K, html: d2(`^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+?</\\1> *(?:\\n{2,}|\\s*$)|<tag(?:"[^"]*"|'[^']*'|\\s[^'"/>\\s]*)*?/?> *(?:\\n{2,}|\\s*$))`).replace("comment", U2).replace(/tag/g, "(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(), def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/, heading: /^(#{1,6})(.*)(?:\n+|$)/, fences: E2, lheading: /^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/, paragraph: d2(j2).replace("hr", I).replace("heading", ` *#{1,6} *[^
35982]`).replace("lheading", oe2).replace("|table", "").replace("blockquote", " {0,3}>").replace("|fences", "").replace("|list", "").replace("|html", "").replace("|tag", "").getRegex() };
35983  var Ae = /^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/;
35984  var Ee = /^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/;
35985  var le2 = /^( {2,}|\\)\n(?!\s*$)/;
35986  var Ie = /^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\<!\[`*_]|\b_|$)|[^ ](?= {2,}\n)))/;
35987  var D = /[\p{P}\p{S}]/u;
35988  var W = /[\s\p{P}\p{S}]/u;
35989  var ue2 = /[^\s\p{P}\p{S}]/u;
35990  var Ce = d2(/^((?![*_])punctSpace)/, "u").replace(/punctSpace/g, W).getRegex();
35991  var pe2 = /(?!~)[\p{P}\p{S}]/u;
35992  var Be = /(?!~)[\s\p{P}\p{S}]/u;
35993  var qe = /(?:[^\s\p{P}\p{S}]|~)/u;
35994  var ve = d2(/link|precode-code|html/, "g").replace("link", /\[(?:[^\[\]`]|(?<a>`+)[^`]+\k<a>(?!`))*?\]\((?:\\[\s\S]|[^\\\(\)]|\((?:\\[\s\S]|[^\\\(\)])*\))*\)/).replace("precode-", be ? "(?<!`)()" : "(^^|[^`])").replace("code", /(?<b>`+)[^`]+\k<b>(?!`)/).replace("html", /<(?! )[^<>]*?>/).getRegex();
35995  var ce2 = /^(?:\*+(?:((?!\*)punct)|[^\s*]))|^_+(?:((?!_)punct)|([^\s_]))/;
35996  var De = d2(ce2, "u").replace(/punct/g, D).getRegex();
35997  var He = d2(ce2, "u").replace(/punct/g, pe2).getRegex();
35998  var he2 = "^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)punct(\\*+)(?=[\\s]|$)|notPunctSpace(\\*+)(?!\\*)(?=punctSpace|$)|(?!\\*)punctSpace(\\*+)(?=notPunctSpace)|[\\s](\\*+)(?!\\*)(?=punct)|(?!\\*)punct(\\*+)(?!\\*)(?=punct)|notPunctSpace(\\*+)(?=notPunctSpace)";
35999  var Ze = d2(he2, "gu").replace(/notPunctSpace/g, ue2).replace(/punctSpace/g, W).replace(/punct/g, D).getRegex();
36000  var Ge = d2(he2, "gu").replace(/notPunctSpace/g, qe).replace(/punctSpace/g, Be).replace(/punct/g, pe2).getRegex();
36001  var Ne = d2("^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)punct(_+)(?=[\\s]|$)|notPunctSpace(_+)(?!_)(?=punctSpace|$)|(?!_)punctSpace(_+)(?=notPunctSpace)|[\\s](_+)(?!_)(?=punct)|(?!_)punct(_+)(?!_)(?=punct)", "gu").replace(/notPunctSpace/g, ue2).replace(/punctSpace/g, W).replace(/punct/g, D).getRegex();
36002  var Fe = d2(/\\(punct)/, "gu").replace(/punct/g, D).getRegex();
36003  var je = d2(/^<(scheme:[^\s\x00-\x1f<>]*|email)>/).replace("scheme", /[a-zA-Z][a-zA-Z0-9+.-]{1,31}/).replace("email", /[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/).getRegex();
36004  var Qe = d2(U2).replace("(?:-->|$)", "-->").getRegex();
36005  var Ue = d2("^comment|^</[a-zA-Z][\\w:-]*\\s*>|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^<![a-zA-Z]+\\s[\\s\\S]*?>|^<!\\[CDATA\\[[\\s\\S]*?\\]\\]>").replace("comment", Qe).replace("attribute", /\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/).getRegex();
36006  var q = /(?:\[(?:\\[\s\S]|[^\[\]\\])*\]|\\[\s\S]|`+[^`]*?`+(?!`)|[^\[\]\\`])*?/;
36007  var Ke = d2(/^!?\[(label)\]\(\s*(href)(?:(?:[ \t]*(?:\n[ \t]*)?)(title))?\s*\)/).replace("label", q).replace("href", /<(?:\\.|[^\n<>\\])+>|[^ \t\n\x00-\x1f]*/).replace("title", /"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/).getRegex();
36008  var de2 = d2(/^!?\[(label)\]\[(ref)\]/).replace("label", q).replace("ref", Q).getRegex();
36009  var ke = d2(/^!?\[(ref)\](?:\[\])?/).replace("ref", Q).getRegex();
36010  var We = d2("reflink|nolink(?!\\()", "g").replace("reflink", de2).replace("nolink", ke).getRegex();
36011  var se2 = /[hH][tT][tT][pP][sS]?|[fF][tT][pP]/;
36012  var X = { _backpedal: E2, anyPunctuation: Fe, autolink: je, blockSkip: ve, br: le2, code: Ee, del: E2, emStrongLDelim: De, emStrongRDelimAst: Ze, emStrongRDelimUnd: Ne, escape: Ae, link: Ke, nolink: ke, punctuation: Ce, reflink: de2, reflinkSearch: We, tag: Ue, text: Ie, url: E2 };
36013  var Xe = { ...X, link: d2(/^!?\[(label)\]\((.*?)\)/).replace("label", q).getRegex(), reflink: d2(/^!?\[(label)\]\s*\[([^\]]*)\]/).replace("label", q).getRegex() };
36014  var N = { ...X, emStrongRDelimAst: Ge, emStrongLDelim: He, url: d2(/^((?:protocol):\/\/|www\.)(?:[a-zA-Z0-9\-]+\.?)+[^\s<]*|^email/).replace("protocol", se2).replace("email", /[A-Za-z0-9._+-]+(@)[a-zA-Z0-9-_]+(?:\.[a-zA-Z0-9-_]*[a-zA-Z0-9])+(?![-_])/).getRegex(), _backpedal: /(?:[^?!.,:;*_'"~()&]+|\([^)]*\)|&(?![a-zA-Z0-9]+;$)|[?!.,:;*_'"~)]+(?!$))+/, del: /^(~~?)(?=[^\s~])((?:\\[\s\S]|[^\\])*?(?:\\[\s\S]|[^\s~\\]))\1(?=[^~]|$)/, text: d2(/^([`~]+|[^`~])(?:(?= {2,}\n)|(?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)|[\s\S]*?(?:(?=[\\<!\[`*~_]|\b_|protocol:\/\/|www\.|$)|[^ ](?= {2,}\n)|[^a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-](?=[a-zA-Z0-9.!#$%&'*+\/=?_`{\|}~-]+@)))/).replace("protocol", se2).getRegex() };
36015  var Je = { ...N, br: d2(le2).replace("{2,}", "*").getRegex(), text: d2(N.text).replace("\\b_", "\\b_| {2,}\\n").replace(/\{2,\}/g, "*").getRegex() };
36016  var C = { normal: K, gfm: Me, pedantic: ze };
36017  var M = { normal: X, gfm: N, breaks: Je, pedantic: Xe };
36018  var Ve = { "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" };
36019  var ge2 = (l4) => Ve[l4];
36020  function w2(l4, e2) {
36021    if (e2) {
36022      if (m2.escapeTest.test(l4)) return l4.replace(m2.escapeReplace, ge2);
36023    } else if (m2.escapeTestNoEncode.test(l4)) return l4.replace(m2.escapeReplaceNoEncode, ge2);
36024    return l4;
36025  }
36026  function J2(l4) {
36027    try {
36028      l4 = encodeURI(l4).replace(m2.percentDecode, "%");
36029    } catch {
36030      return null;
36031    }
36032    return l4;
36033  }
36034  function V(l4, e2) {
36035    let t2 = l4.replace(m2.findPipe, (i2, s2, a2) => {
36036      let o2 = false, p2 = s2;
36037      for (; --p2 >= 0 && a2[p2] === "\\"; ) o2 = !o2;
36038      return o2 ? "|" : " |";
36039    }), n2 = t2.split(m2.splitPipe), r2 = 0;
36040    if (n2[0].trim() || n2.shift(), n2.length > 0 && !n2.at(-1)?.trim() && n2.pop(), e2) if (n2.length > e2) n2.splice(e2);
36041    else for (; n2.length < e2; ) n2.push("");
36042    for (; r2 < n2.length; r2++) n2[r2] = n2[r2].trim().replace(m2.slashPipe, "|");
36043    return n2;
36044  }
36045  function z(l4, e2, t2) {
36046    let n2 = l4.length;
36047    if (n2 === 0) return "";
36048    let r2 = 0;
36049    for (; r2 < n2; ) {
36050      let i2 = l4.charAt(n2 - r2 - 1);
36051      if (i2 === e2 && !t2) r2++;
36052      else if (i2 !== e2 && t2) r2++;
36053      else break;
36054    }
36055    return l4.slice(0, n2 - r2);
36056  }
36057  function fe2(l4, e2) {
36058    if (l4.indexOf(e2[1]) === -1) return -1;
36059    let t2 = 0;
36060    for (let n2 = 0; n2 < l4.length; n2++) if (l4[n2] === "\\") n2++;
36061    else if (l4[n2] === e2[0]) t2++;
36062    else if (l4[n2] === e2[1] && (t2--, t2 < 0)) return n2;
36063    return t2 > 0 ? -2 : -1;
36064  }
36065  function me2(l4, e2, t2, n2, r2) {
36066    let i2 = e2.href, s2 = e2.title || null, a2 = l4[1].replace(r2.other.outputLinkReplace, "$1");
36067    n2.state.inLink = true;
36068    let o2 = { type: l4[0].charAt(0) === "!" ? "image" : "link", raw: t2, href: i2, title: s2, text: a2, tokens: n2.inlineTokens(a2) };
36069    return n2.state.inLink = false, o2;
36070  }
36071  function Ye(l4, e2, t2) {
36072    let n2 = l4.match(t2.other.indentCodeCompensation);
36073    if (n2 === null) return e2;
36074    let r2 = n2[1];
36075    return e2.split(`
36076`).map((i2) => {
36077      let s2 = i2.match(t2.other.beginningSpace);
36078      if (s2 === null) return i2;
36079      let [a2] = s2;
36080      return a2.length >= r2.length ? i2.slice(r2.length) : i2;
36081    }).join(`
36082`);
36083  }
36084  var y2 = class {
36085    options;
36086    rules;
36087    lexer;
36088    constructor(e2) {
36089      this.options = e2 || T;
36090    }
36091    space(e2) {
36092      let t2 = this.rules.block.newline.exec(e2);
36093      if (t2 && t2[0].length > 0) return { type: "space", raw: t2[0] };
36094    }
36095    code(e2) {
36096      let t2 = this.rules.block.code.exec(e2);
36097      if (t2) {
36098        let n2 = t2[0].replace(this.rules.other.codeRemoveIndent, "");
36099        return { type: "code", raw: t2[0], codeBlockStyle: "indented", text: this.options.pedantic ? n2 : z(n2, `
36100`) };
36101      }
36102    }
36103    fences(e2) {
36104      let t2 = this.rules.block.fences.exec(e2);
36105      if (t2) {
36106        let n2 = t2[0], r2 = Ye(n2, t2[3] || "", this.rules);
36107        return { type: "code", raw: n2, lang: t2[2] ? t2[2].trim().replace(this.rules.inline.anyPunctuation, "$1") : t2[2], text: r2 };
36108      }
36109    }
36110    heading(e2) {
36111      let t2 = this.rules.block.heading.exec(e2);
36112      if (t2) {
36113        let n2 = t2[2].trim();
36114        if (this.rules.other.endingHash.test(n2)) {
36115          let r2 = z(n2, "#");
36116          (this.options.pedantic || !r2 || this.rules.other.endingSpaceChar.test(r2)) && (n2 = r2.trim());
36117        }
36118        return { type: "heading", raw: t2[0], depth: t2[1].length, text: n2, tokens: this.lexer.inline(n2) };
36119      }
36120    }
36121    hr(e2) {
36122      let t2 = this.rules.block.hr.exec(e2);
36123      if (t2) return { type: "hr", raw: z(t2[0], `
36124`) };
36125    }
36126    blockquote(e2) {
36127      let t2 = this.rules.block.blockquote.exec(e2);
36128      if (t2) {
36129        let n2 = z(t2[0], `
36130`).split(`
36131`), r2 = "", i2 = "", s2 = [];
36132        for (; n2.length > 0; ) {
36133          let a2 = false, o2 = [], p2;
36134          for (p2 = 0; p2 < n2.length; p2++) if (this.rules.other.blockquoteStart.test(n2[p2])) o2.push(n2[p2]), a2 = true;
36135          else if (!a2) o2.push(n2[p2]);
36136          else break;
36137          n2 = n2.slice(p2);
36138          let u2 = o2.join(`
36139`), c2 = u2.replace(this.rules.other.blockquoteSetextReplace, `
36140    $1`).replace(this.rules.other.blockquoteSetextReplace2, "");
36141          r2 = r2 ? `${r2}
36142${u2}` : u2, i2 = i2 ? `${i2}
36143${c2}` : c2;
36144          let g2 = this.lexer.state.top;
36145          if (this.lexer.state.top = true, this.lexer.blockTokens(c2, s2, true), this.lexer.state.top = g2, n2.length === 0) break;
36146          let h2 = s2.at(-1);
36147          if (h2?.type === "code") break;
36148          if (h2?.type === "blockquote") {
36149            let R = h2, f = R.raw + `
36150` + n2.join(`
36151`), O = this.blockquote(f);
36152            s2[s2.length - 1] = O, r2 = r2.substring(0, r2.length - R.raw.length) + O.raw, i2 = i2.substring(0, i2.length - R.text.length) + O.text;
36153            break;
36154          } else if (h2?.type === "list") {
36155            let R = h2, f = R.raw + `
36156` + n2.join(`
36157`), O = this.list(f);
36158            s2[s2.length - 1] = O, r2 = r2.substring(0, r2.length - h2.raw.length) + O.raw, i2 = i2.substring(0, i2.length - R.raw.length) + O.raw, n2 = f.substring(s2.at(-1).raw.length).split(`
36159`);
36160            continue;
36161          }
36162        }
36163        return { type: "blockquote", raw: r2, tokens: s2, text: i2 };
36164      }
36165    }
36166    list(e2) {
36167      let t2 = this.rules.block.list.exec(e2);
36168      if (t2) {
36169        let n2 = t2[1].trim(), r2 = n2.length > 1, i2 = { type: "list", raw: "", ordered: r2, start: r2 ? +n2.slice(0, -1) : "", loose: false, items: [] };
36170        n2 = r2 ? `\\d{1,9}\\${n2.slice(-1)}` : `\\${n2}`, this.options.pedantic && (n2 = r2 ? n2 : "[*+-]");
36171        let s2 = this.rules.other.listItemRegex(n2), a2 = false;
36172        for (; e2; ) {
36173          let p2 = false, u2 = "", c2 = "";
36174          if (!(t2 = s2.exec(e2)) || this.rules.block.hr.test(e2)) break;
36175          u2 = t2[0], e2 = e2.substring(u2.length);
36176          let g2 = t2[2].split(`
36177`, 1)[0].replace(this.rules.other.listReplaceTabs, (H) => " ".repeat(3 * H.length)), h2 = e2.split(`
36178`, 1)[0], R = !g2.trim(), f = 0;
36179          if (this.options.pedantic ? (f = 2, c2 = g2.trimStart()) : R ? f = t2[1].length + 1 : (f = t2[2].search(this.rules.other.nonSpaceChar), f = f > 4 ? 1 : f, c2 = g2.slice(f), f += t2[1].length), R && this.rules.other.blankLine.test(h2) && (u2 += h2 + `
36180`, e2 = e2.substring(h2.length + 1), p2 = true), !p2) {
36181            let H = this.rules.other.nextBulletRegex(f), ee = this.rules.other.hrRegex(f), te2 = this.rules.other.fencesBeginRegex(f), ne2 = this.rules.other.headingBeginRegex(f), xe = this.rules.other.htmlBeginRegex(f);
36182            for (; e2; ) {
36183              let Z = e2.split(`
36184`, 1)[0], A;
36185              if (h2 = Z, this.options.pedantic ? (h2 = h2.replace(this.rules.other.listReplaceNesting, "  "), A = h2) : A = h2.replace(this.rules.other.tabCharGlobal, "    "), te2.test(h2) || ne2.test(h2) || xe.test(h2) || H.test(h2) || ee.test(h2)) break;
36186              if (A.search(this.rules.other.nonSpaceChar) >= f || !h2.trim()) c2 += `
36187` + A.slice(f);
36188              else {
36189                if (R || g2.replace(this.rules.other.tabCharGlobal, "    ").search(this.rules.other.nonSpaceChar) >= 4 || te2.test(g2) || ne2.test(g2) || ee.test(g2)) break;
36190                c2 += `
36191` + h2;
36192              }
36193              !R && !h2.trim() && (R = true), u2 += Z + `
36194`, e2 = e2.substring(Z.length + 1), g2 = A.slice(f);
36195            }
36196          }
36197          i2.loose || (a2 ? i2.loose = true : this.rules.other.doubleBlankLine.test(u2) && (a2 = true));
36198          let O = null, Y;
36199          this.options.gfm && (O = this.rules.other.listIsTask.exec(c2), O && (Y = O[0] !== "[ ] ", c2 = c2.replace(this.rules.other.listReplaceTask, ""))), i2.items.push({ type: "list_item", raw: u2, task: !!O, checked: Y, loose: false, text: c2, tokens: [] }), i2.raw += u2;
36200        }
36201        let o2 = i2.items.at(-1);
36202        if (o2) o2.raw = o2.raw.trimEnd(), o2.text = o2.text.trimEnd();
36203        else return;
36204        i2.raw = i2.raw.trimEnd();
36205        for (let p2 = 0; p2 < i2.items.length; p2++) if (this.lexer.state.top = false, i2.items[p2].tokens = this.lexer.blockTokens(i2.items[p2].text, []), !i2.loose) {
36206          let u2 = i2.items[p2].tokens.filter((g2) => g2.type === "space"), c2 = u2.length > 0 && u2.some((g2) => this.rules.other.anyLine.test(g2.raw));
36207          i2.loose = c2;
36208        }
36209        if (i2.loose) for (let p2 = 0; p2 < i2.items.length; p2++) i2.items[p2].loose = true;
36210        return i2;
36211      }
36212    }
36213    html(e2) {
36214      let t2 = this.rules.block.html.exec(e2);
36215      if (t2) return { type: "html", block: true, raw: t2[0], pre: t2[1] === "pre" || t2[1] === "script" || t2[1] === "style", text: t2[0] };
36216    }
36217    def(e2) {
36218      let t2 = this.rules.block.def.exec(e2);
36219      if (t2) {
36220        let n2 = t2[1].toLowerCase().replace(this.rules.other.multipleSpaceGlobal, " "), r2 = t2[2] ? t2[2].replace(this.rules.other.hrefBrackets, "$1").replace(this.rules.inline.anyPunctuation, "$1") : "", i2 = t2[3] ? t2[3].substring(1, t2[3].length - 1).replace(this.rules.inline.anyPunctuation, "$1") : t2[3];
36221        return { type: "def", tag: n2, raw: t2[0], href: r2, title: i2 };
36222      }
36223    }
36224    table(e2) {
36225      let t2 = this.rules.block.table.exec(e2);
36226      if (!t2 || !this.rules.other.tableDelimiter.test(t2[2])) return;
36227      let n2 = V(t2[1]), r2 = t2[2].replace(this.rules.other.tableAlignChars, "").split("|"), i2 = t2[3]?.trim() ? t2[3].replace(this.rules.other.tableRowBlankLine, "").split(`
36228`) : [], s2 = { type: "table", raw: t2[0], header: [], align: [], rows: [] };
36229      if (n2.length === r2.length) {
36230        for (let a2 of r2) this.rules.other.tableAlignRight.test(a2) ? s2.align.push("right") : this.rules.other.tableAlignCenter.test(a2) ? s2.align.push("center") : this.rules.other.tableAlignLeft.test(a2) ? s2.align.push("left") : s2.align.push(null);
36231        for (let a2 = 0; a2 < n2.length; a2++) s2.header.push({ text: n2[a2], tokens: this.lexer.inline(n2[a2]), header: true, align: s2.align[a2] });
36232        for (let a2 of i2) s2.rows.push(V(a2, s2.header.length).map((o2, p2) => ({ text: o2, tokens: this.lexer.inline(o2), header: false, align: s2.align[p2] })));
36233        return s2;
36234      }
36235    }
36236    lheading(e2) {
36237      let t2 = this.rules.block.lheading.exec(e2);
36238      if (t2) return { type: "heading", raw: t2[0], depth: t2[2].charAt(0) === "=" ? 1 : 2, text: t2[1], tokens: this.lexer.inline(t2[1]) };
36239    }
36240    paragraph(e2) {
36241      let t2 = this.rules.block.paragraph.exec(e2);
36242      if (t2) {
36243        let n2 = t2[1].charAt(t2[1].length - 1) === `
36244` ? t2[1].slice(0, -1) : t2[1];
36245        return { type: "paragraph", raw: t2[0], text: n2, tokens: this.lexer.inline(n2) };
36246      }
36247    }
36248    text(e2) {
36249      let t2 = this.rules.block.text.exec(e2);
36250      if (t2) return { type: "text", raw: t2[0], text: t2[0], tokens: this.lexer.inline(t2[0]) };
36251    }
36252    escape(e2) {
36253      let t2 = this.rules.inline.escape.exec(e2);
36254      if (t2) return { type: "escape", raw: t2[0], text: t2[1] };
36255    }
36256    tag(e2) {
36257      let t2 = this.rules.inline.tag.exec(e2);
36258      if (t2) return !this.lexer.state.inLink && this.rules.other.startATag.test(t2[0]) ? this.lexer.state.inLink = true : this.lexer.state.inLink && this.rules.other.endATag.test(t2[0]) && (this.lexer.state.inLink = false), !this.lexer.state.inRawBlock && this.rules.other.startPreScriptTag.test(t2[0]) ? this.lexer.state.inRawBlock = true : this.lexer.state.inRawBlock && this.rules.other.endPreScriptTag.test(t2[0]) && (this.lexer.state.inRawBlock = false), { type: "html", raw: t2[0], inLink: this.lexer.state.inLink, inRawBlock: this.lexer.state.inRawBlock, block: false, text: t2[0] };
36259    }
36260    link(e2) {
36261      let t2 = this.rules.inline.link.exec(e2);
36262      if (t2) {
36263        let n2 = t2[2].trim();
36264        if (!this.options.pedantic && this.rules.other.startAngleBracket.test(n2)) {
36265          if (!this.rules.other.endAngleBracket.test(n2)) return;
36266          let s2 = z(n2.slice(0, -1), "\\");
36267          if ((n2.length - s2.length) % 2 === 0) return;
36268        } else {
36269          let s2 = fe2(t2[2], "()");
36270          if (s2 === -2) return;
36271          if (s2 > -1) {
36272            let o2 = (t2[0].indexOf("!") === 0 ? 5 : 4) + t2[1].length + s2;
36273            t2[2] = t2[2].substring(0, s2), t2[0] = t2[0].substring(0, o2).trim(), t2[3] = "";
36274          }
36275        }
36276        let r2 = t2[2], i2 = "";
36277        if (this.options.pedantic) {
36278          let s2 = this.rules.other.pedanticHrefTitle.exec(r2);
36279          s2 && (r2 = s2[1], i2 = s2[3]);
36280        } else i2 = t2[3] ? t2[3].slice(1, -1) : "";
36281        return r2 = r2.trim(), this.rules.other.startAngleBracket.test(r2) && (this.options.pedantic && !this.rules.other.endAngleBracket.test(n2) ? r2 = r2.slice(1) : r2 = r2.slice(1, -1)), me2(t2, { href: r2 && r2.replace(this.rules.inline.anyPunctuation, "$1"), title: i2 && i2.replace(this.rules.inline.anyPunctuation, "$1") }, t2[0], this.lexer, this.rules);
36282      }
36283    }
36284    reflink(e2, t2) {
36285      let n2;
36286      if ((n2 = this.rules.inline.reflink.exec(e2)) || (n2 = this.rules.inline.nolink.exec(e2))) {
36287        let r2 = (n2[2] || n2[1]).replace(this.rules.other.multipleSpaceGlobal, " "), i2 = t2[r2.toLowerCase()];
36288        if (!i2) {
36289          let s2 = n2[0].charAt(0);
36290          return { type: "text", raw: s2, text: s2 };
36291        }
36292        return me2(n2, i2, n2[0], this.lexer, this.rules);
36293      }
36294    }
36295    emStrong(e2, t2, n2 = "") {
36296      let r2 = this.rules.inline.emStrongLDelim.exec(e2);
36297      if (!r2 || r2[3] && n2.match(this.rules.other.unicodeAlphaNumeric)) return;
36298      if (!(r2[1] || r2[2] || "") || !n2 || this.rules.inline.punctuation.exec(n2)) {
36299        let s2 = [...r2[0]].length - 1, a2, o2, p2 = s2, u2 = 0, c2 = r2[0][0] === "*" ? this.rules.inline.emStrongRDelimAst : this.rules.inline.emStrongRDelimUnd;
36300        for (c2.lastIndex = 0, t2 = t2.slice(-1 * e2.length + s2); (r2 = c2.exec(t2)) != null; ) {
36301          if (a2 = r2[1] || r2[2] || r2[3] || r2[4] || r2[5] || r2[6], !a2) continue;
36302          if (o2 = [...a2].length, r2[3] || r2[4]) {
36303            p2 += o2;
36304            continue;
36305          } else if ((r2[5] || r2[6]) && s2 % 3 && !((s2 + o2) % 3)) {
36306            u2 += o2;
36307            continue;
36308          }
36309          if (p2 -= o2, p2 > 0) continue;
36310          o2 = Math.min(o2, o2 + p2 + u2);
36311          let g2 = [...r2[0]][0].length, h2 = e2.slice(0, s2 + r2.index + g2 + o2);
36312          if (Math.min(s2, o2) % 2) {
36313            let f = h2.slice(1, -1);
36314            return { type: "em", raw: h2, text: f, tokens: this.lexer.inlineTokens(f) };
36315          }
36316          let R = h2.slice(2, -2);
36317          return { type: "strong", raw: h2, text: R, tokens: this.lexer.inlineTokens(R) };
36318        }
36319      }
36320    }
36321    codespan(e2) {
36322      let t2 = this.rules.inline.code.exec(e2);
36323      if (t2) {
36324        let n2 = t2[2].replace(this.rules.other.newLineCharGlobal, " "), r2 = this.rules.other.nonSpaceChar.test(n2), i2 = this.rules.other.startingSpaceChar.test(n2) && this.rules.other.endingSpaceChar.test(n2);
36325        return r2 && i2 && (n2 = n2.substring(1, n2.length - 1)), { type: "codespan", raw: t2[0], text: n2 };
36326      }
36327    }
36328    br(e2) {
36329      let t2 = this.rules.inline.br.exec(e2);
36330      if (t2) return { type: "br", raw: t2[0] };
36331    }
36332    del(e2) {
36333      let t2 = this.rules.inline.del.exec(e2);
36334      if (t2) return { type: "del", raw: t2[0], text: t2[2], tokens: this.lexer.inlineTokens(t2[2]) };
36335    }
36336    autolink(e2) {
36337      let t2 = this.rules.inline.autolink.exec(e2);
36338      if (t2) {
36339        let n2, r2;
36340        return t2[2] === "@" ? (n2 = t2[1], r2 = "mailto:" + n2) : (n2 = t2[1], r2 = n2), { type: "link", raw: t2[0], text: n2, href: r2, tokens: [{ type: "text", raw: n2, text: n2 }] };
36341      }
36342    }
36343    url(e2) {
36344      let t2;
36345      if (t2 = this.rules.inline.url.exec(e2)) {
36346        let n2, r2;
36347        if (t2[2] === "@") n2 = t2[0], r2 = "mailto:" + n2;
36348        else {
36349          let i2;
36350          do
36351            i2 = t2[0], t2[0] = this.rules.inline._backpedal.exec(t2[0])?.[0] ?? "";
36352          while (i2 !== t2[0]);
36353          n2 = t2[0], t2[1] === "www." ? r2 = "http://" + t2[0] : r2 = t2[0];
36354        }
36355        return { type: "link", raw: t2[0], text: n2, href: r2, tokens: [{ type: "text", raw: n2, text: n2 }] };
36356      }
36357    }
36358    inlineText(e2) {
36359      let t2 = this.rules.inline.text.exec(e2);
36360      if (t2) {
36361        let n2 = this.lexer.state.inRawBlock;
36362        return { type: "text", raw: t2[0], text: t2[0], escaped: n2 };
36363      }
36364    }
36365  };
36366  var x2 = class l2 {
36367    tokens;
36368    options;
36369    state;
36370    tokenizer;
36371    inlineQueue;
36372    constructor(e2) {
36373      this.tokens = [], this.tokens.links = /* @__PURE__ */ Object.create(null), this.options = e2 || T, this.options.tokenizer = this.options.tokenizer || new y2(), this.tokenizer = this.options.tokenizer, this.tokenizer.options = this.options, this.tokenizer.lexer = this, this.inlineQueue = [], this.state = { inLink: false, inRawBlock: false, top: true };
36374      let t2 = { other: m2, block: C.normal, inline: M.normal };
36375      this.options.pedantic ? (t2.block = C.pedantic, t2.inline = M.pedantic) : this.options.gfm && (t2.block = C.gfm, this.options.breaks ? t2.inline = M.breaks : t2.inline = M.gfm), this.tokenizer.rules = t2;
36376    }
36377    static get rules() {
36378      return { block: C, inline: M };
36379    }
36380    static lex(e2, t2) {
36381      return new l2(t2).lex(e2);
36382    }
36383    static lexInline(e2, t2) {
36384      return new l2(t2).inlineTokens(e2);
36385    }
36386    lex(e2) {
36387      e2 = e2.replace(m2.carriageReturn, `
36388`), this.blockTokens(e2, this.tokens);
36389      for (let t2 = 0; t2 < this.inlineQueue.length; t2++) {
36390        let n2 = this.inlineQueue[t2];
36391        this.inlineTokens(n2.src, n2.tokens);
36392      }
36393      return this.inlineQueue = [], this.tokens;
36394    }
36395    blockTokens(e2, t2 = [], n2 = false) {
36396      for (this.options.pedantic && (e2 = e2.replace(m2.tabCharGlobal, "    ").replace(m2.spaceLine, "")); e2; ) {
36397        let r2;
36398        if (this.options.extensions?.block?.some((s2) => (r2 = s2.call({ lexer: this }, e2, t2)) ? (e2 = e2.substring(r2.raw.length), t2.push(r2), true) : false)) continue;
36399        if (r2 = this.tokenizer.space(e2)) {
36400          e2 = e2.substring(r2.raw.length);
36401          let s2 = t2.at(-1);
36402          r2.raw.length === 1 && s2 !== void 0 ? s2.raw += `
36403` : t2.push(r2);
36404          continue;
36405        }
36406        if (r2 = this.tokenizer.code(e2)) {
36407          e2 = e2.substring(r2.raw.length);
36408          let s2 = t2.at(-1);
36409          s2?.type === "paragraph" || s2?.type === "text" ? (s2.raw += (s2.raw.endsWith(`
36410`) ? "" : `
36411`) + r2.raw, s2.text += `
36412` + r2.text, this.inlineQueue.at(-1).src = s2.text) : t2.push(r2);
36413          continue;
36414        }
36415        if (r2 = this.tokenizer.fences(e2)) {
36416          e2 = e2.substring(r2.raw.length), t2.push(r2);
36417          continue;
36418        }
36419        if (r2 = this.tokenizer.heading(e2)) {
36420          e2 = e2.substring(r2.raw.length), t2.push(r2);
36421          continue;
36422        }
36423        if (r2 = this.tokenizer.hr(e2)) {
36424          e2 = e2.substring(r2.raw.length), t2.push(r2);
36425          continue;
36426        }
36427        if (r2 = this.tokenizer.blockquote(e2)) {
36428          e2 = e2.substring(r2.raw.length), t2.push(r2);
36429          continue;
36430        }
36431        if (r2 = this.tokenizer.list(e2)) {
36432          e2 = e2.substring(r2.raw.length), t2.push(r2);
36433          continue;
36434        }
36435        if (r2 = this.tokenizer.html(e2)) {
36436          e2 = e2.substring(r2.raw.length), t2.push(r2);
36437          continue;
36438        }
36439        if (r2 = this.tokenizer.def(e2)) {
36440          e2 = e2.substring(r2.raw.length);
36441          let s2 = t2.at(-1);
36442          s2?.type === "paragraph" || s2?.type === "text" ? (s2.raw += (s2.raw.endsWith(`
36443`) ? "" : `
36444`) + r2.raw, s2.text += `
36445` + r2.raw, this.inlineQueue.at(-1).src = s2.text) : this.tokens.links[r2.tag] || (this.tokens.links[r2.tag] = { href: r2.href, title: r2.title }, t2.push(r2));
36446          continue;
36447        }
36448        if (r2 = this.tokenizer.table(e2)) {
36449          e2 = e2.substring(r2.raw.length), t2.push(r2);
36450          continue;
36451        }
36452        if (r2 = this.tokenizer.lheading(e2)) {
36453          e2 = e2.substring(r2.raw.length), t2.push(r2);
36454          continue;
36455        }
36456        let i2 = e2;
36457        if (this.options.extensions?.startBlock) {
36458          let s2 = 1 / 0, a2 = e2.slice(1), o2;
36459          this.options.extensions.startBlock.forEach((p2) => {
36460            o2 = p2.call({ lexer: this }, a2), typeof o2 == "number" && o2 >= 0 && (s2 = Math.min(s2, o2));
36461          }), s2 < 1 / 0 && s2 >= 0 && (i2 = e2.substring(0, s2 + 1));
36462        }
36463        if (this.state.top && (r2 = this.tokenizer.paragraph(i2))) {
36464          let s2 = t2.at(-1);
36465          n2 && s2?.type === "paragraph" ? (s2.raw += (s2.raw.endsWith(`
36466`) ? "" : `
36467`) + r2.raw, s2.text += `
36468` + r2.text, this.inlineQueue.pop(), this.inlineQueue.at(-1).src = s2.text) : t2.push(r2), n2 = i2.length !== e2.length, e2 = e2.substring(r2.raw.length);
36469          continue;
36470        }
36471        if (r2 = this.tokenizer.text(e2)) {
36472          e2 = e2.substring(r2.raw.length);
36473          let s2 = t2.at(-1);
36474          s2?.type === "text" ? (s2.raw += (s2.raw.endsWith(`
36475`) ? "" : `
36476`) + r2.raw, s2.text += `
36477` + r2.text, this.inlineQueue.pop(), this.inlineQueue.at(-1).src = s2.text) : t2.push(r2);
36478          continue;
36479        }
36480        if (e2) {
36481          let s2 = "Infinite loop on byte: " + e2.charCodeAt(0);
36482          if (this.options.silent) {
36483            console.error(s2);
36484            break;
36485          } else throw new Error(s2);
36486        }
36487      }
36488      return this.state.top = true, t2;
36489    }
36490    inline(e2, t2 = []) {
36491      return this.inlineQueue.push({ src: e2, tokens: t2 }), t2;
36492    }
36493    inlineTokens(e2, t2 = []) {
36494      let n2 = e2, r2 = null;
36495      if (this.tokens.links) {
36496        let o2 = Object.keys(this.tokens.links);
36497        if (o2.length > 0) for (; (r2 = this.tokenizer.rules.inline.reflinkSearch.exec(n2)) != null; ) o2.includes(r2[0].slice(r2[0].lastIndexOf("[") + 1, -1)) && (n2 = n2.slice(0, r2.index) + "[" + "a".repeat(r2[0].length - 2) + "]" + n2.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex));
36498      }
36499      for (; (r2 = this.tokenizer.rules.inline.anyPunctuation.exec(n2)) != null; ) n2 = n2.slice(0, r2.index) + "++" + n2.slice(this.tokenizer.rules.inline.anyPunctuation.lastIndex);
36500      let i2;
36501      for (; (r2 = this.tokenizer.rules.inline.blockSkip.exec(n2)) != null; ) i2 = r2[2] ? r2[2].length : 0, n2 = n2.slice(0, r2.index + i2) + "[" + "a".repeat(r2[0].length - i2 - 2) + "]" + n2.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);
36502      n2 = this.options.hooks?.emStrongMask?.call({ lexer: this }, n2) ?? n2;
36503      let s2 = false, a2 = "";
36504      for (; e2; ) {
36505        s2 || (a2 = ""), s2 = false;
36506        let o2;
36507        if (this.options.extensions?.inline?.some((u2) => (o2 = u2.call({ lexer: this }, e2, t2)) ? (e2 = e2.substring(o2.raw.length), t2.push(o2), true) : false)) continue;
36508        if (o2 = this.tokenizer.escape(e2)) {
36509          e2 = e2.substring(o2.raw.length), t2.push(o2);
36510          continue;
36511        }
36512        if (o2 = this.tokenizer.tag(e2)) {
36513          e2 = e2.substring(o2.raw.length), t2.push(o2);
36514          continue;
36515        }
36516        if (o2 = this.tokenizer.link(e2)) {
36517          e2 = e2.substring(o2.raw.length), t2.push(o2);
36518          continue;
36519        }
36520        if (o2 = this.tokenizer.reflink(e2, this.tokens.links)) {
36521          e2 = e2.substring(o2.raw.length);
36522          let u2 = t2.at(-1);
36523          o2.type === "text" && u2?.type === "text" ? (u2.raw += o2.raw, u2.text += o2.text) : t2.push(o2);
36524          continue;
36525        }
36526        if (o2 = this.tokenizer.emStrong(e2, n2, a2)) {
36527          e2 = e2.substring(o2.raw.length), t2.push(o2);
36528          continue;
36529        }
36530        if (o2 = this.tokenizer.codespan(e2)) {
36531          e2 = e2.substring(o2.raw.length), t2.push(o2);
36532          continue;
36533        }
36534        if (o2 = this.tokenizer.br(e2)) {
36535          e2 = e2.substring(o2.raw.length), t2.push(o2);
36536          continue;
36537        }
36538        if (o2 = this.tokenizer.del(e2)) {
36539          e2 = e2.substring(o2.raw.length), t2.push(o2);
36540          continue;
36541        }
36542        if (o2 = this.tokenizer.autolink(e2)) {
36543          e2 = e2.substring(o2.raw.length), t2.push(o2);
36544          continue;
36545        }
36546        if (!this.state.inLink && (o2 = this.tokenizer.url(e2))) {
36547          e2 = e2.substring(o2.raw.length), t2.push(o2);
36548          continue;
36549        }
36550        let p2 = e2;
36551        if (this.options.extensions?.startInline) {
36552          let u2 = 1 / 0, c2 = e2.slice(1), g2;
36553          this.options.extensions.startInline.forEach((h2) => {
36554            g2 = h2.call({ lexer: this }, c2), typeof g2 == "number" && g2 >= 0 && (u2 = Math.min(u2, g2));
36555          }), u2 < 1 / 0 && u2 >= 0 && (p2 = e2.substring(0, u2 + 1));
36556        }
36557        if (o2 = this.tokenizer.inlineText(p2)) {
36558          e2 = e2.substring(o2.raw.length), o2.raw.slice(-1) !== "_" && (a2 = o2.raw.slice(-1)), s2 = true;
36559          let u2 = t2.at(-1);
36560          u2?.type === "text" ? (u2.raw += o2.raw, u2.text += o2.text) : t2.push(o2);
36561          continue;
36562        }
36563        if (e2) {
36564          let u2 = "Infinite loop on byte: " + e2.charCodeAt(0);
36565          if (this.options.silent) {
36566            console.error(u2);
36567            break;
36568          } else throw new Error(u2);
36569        }
36570      }
36571      return t2;
36572    }
36573  };
36574  var P = class {
36575    options;
36576    parser;
36577    constructor(e2) {
36578      this.options = e2 || T;
36579    }
36580    space(e2) {
36581      return "";
36582    }
36583    code({ text: e2, lang: t2, escaped: n2 }) {
36584      let r2 = (t2 || "").match(m2.notSpaceStart)?.[0], i2 = e2.replace(m2.endingNewline, "") + `
36585`;
36586      return r2 ? '<pre><code class="language-' + w2(r2) + '">' + (n2 ? i2 : w2(i2, true)) + `</code></pre>
36587` : "<pre><code>" + (n2 ? i2 : w2(i2, true)) + `</code></pre>
36588`;
36589    }
36590    blockquote({ tokens: e2 }) {
36591      return `<blockquote>
36592${this.parser.parse(e2)}</blockquote>
36593`;
36594    }
36595    html({ text: e2 }) {
36596      return e2;
36597    }
36598    def(e2) {
36599      return "";
36600    }
36601    heading({ tokens: e2, depth: t2 }) {
36602      return `<h${t2}>${this.parser.parseInline(e2)}</h${t2}>
36603`;
36604    }
36605    hr(e2) {
36606      return `<hr>
36607`;
36608    }
36609    list(e2) {
36610      let t2 = e2.ordered, n2 = e2.start, r2 = "";
36611      for (let a2 = 0; a2 < e2.items.length; a2++) {
36612        let o2 = e2.items[a2];
36613        r2 += this.listitem(o2);
36614      }
36615      let i2 = t2 ? "ol" : "ul", s2 = t2 && n2 !== 1 ? ' start="' + n2 + '"' : "";
36616      return "<" + i2 + s2 + `>
36617` + r2 + "</" + i2 + `>
36618`;
36619    }
36620    listitem(e2) {
36621      let t2 = "";
36622      if (e2.task) {
36623        let n2 = this.checkbox({ checked: !!e2.checked });
36624        e2.loose ? e2.tokens[0]?.type === "paragraph" ? (e2.tokens[0].text = n2 + " " + e2.tokens[0].text, e2.tokens[0].tokens && e2.tokens[0].tokens.length > 0 && e2.tokens[0].tokens[0].type === "text" && (e2.tokens[0].tokens[0].text = n2 + " " + w2(e2.tokens[0].tokens[0].text), e2.tokens[0].tokens[0].escaped = true)) : e2.tokens.unshift({ type: "text", raw: n2 + " ", text: n2 + " ", escaped: true }) : t2 += n2 + " ";
36625      }
36626      return t2 += this.parser.parse(e2.tokens, !!e2.loose), `<li>${t2}</li>
36627`;
36628    }
36629    checkbox({ checked: e2 }) {
36630      return "<input " + (e2 ? 'checked="" ' : "") + 'disabled="" type="checkbox">';
36631    }
36632    paragraph({ tokens: e2 }) {
36633      return `<p>${this.parser.parseInline(e2)}</p>
36634`;
36635    }
36636    table(e2) {
36637      let t2 = "", n2 = "";
36638      for (let i2 = 0; i2 < e2.header.length; i2++) n2 += this.tablecell(e2.header[i2]);
36639      t2 += this.tablerow({ text: n2 });
36640      let r2 = "";
36641      for (let i2 = 0; i2 < e2.rows.length; i2++) {
36642        let s2 = e2.rows[i2];
36643        n2 = "";
36644        for (let a2 = 0; a2 < s2.length; a2++) n2 += this.tablecell(s2[a2]);
36645        r2 += this.tablerow({ text: n2 });
36646      }
36647      return r2 && (r2 = `<tbody>${r2}</tbody>`), `<table>
36648<thead>
36649` + t2 + `</thead>
36650` + r2 + `</table>
36651`;
36652    }
36653    tablerow({ text: e2 }) {
36654      return `<tr>
36655${e2}</tr>
36656`;
36657    }
36658    tablecell(e2) {
36659      let t2 = this.parser.parseInline(e2.tokens), n2 = e2.header ? "th" : "td";
36660      return (e2.align ? `<${n2} align="${e2.align}">` : `<${n2}>`) + t2 + `</${n2}>
36661`;
36662    }
36663    strong({ tokens: e2 }) {
36664      return `<strong>${this.parser.parseInline(e2)}</strong>`;
36665    }
36666    em({ tokens: e2 }) {
36667      return `<em>${this.parser.parseInline(e2)}</em>`;
36668    }
36669    codespan({ text: e2 }) {
36670      return `<code>${w2(e2, true)}</code>`;
36671    }
36672    br(e2) {
36673      return "<br>";
36674    }
36675    del({ tokens: e2 }) {
36676      return `<del>${this.parser.parseInline(e2)}</del>`;
36677    }
36678    link({ href: e2, title: t2, tokens: n2 }) {
36679      let r2 = this.parser.parseInline(n2), i2 = J2(e2);
36680      if (i2 === null) return r2;
36681      e2 = i2;
36682      let s2 = '<a href="' + e2 + '"';
36683      return t2 && (s2 += ' title="' + w2(t2) + '"'), s2 += ">" + r2 + "</a>", s2;
36684    }
36685    image({ href: e2, title: t2, text: n2, tokens: r2 }) {
36686      r2 && (n2 = this.parser.parseInline(r2, this.parser.textRenderer));
36687      let i2 = J2(e2);
36688      if (i2 === null) return w2(n2);
36689      e2 = i2;
36690      let s2 = `<img src="${e2}" alt="${n2}"`;
36691      return t2 && (s2 += ` title="${w2(t2)}"`), s2 += ">", s2;
36692    }
36693    text(e2) {
36694      return "tokens" in e2 && e2.tokens ? this.parser.parseInline(e2.tokens) : "escaped" in e2 && e2.escaped ? e2.text : w2(e2.text);
36695    }
36696  };
36697  var $ = class {
36698    strong({ text: e2 }) {
36699      return e2;
36700    }
36701    em({ text: e2 }) {
36702      return e2;
36703    }
36704    codespan({ text: e2 }) {
36705      return e2;
36706    }
36707    del({ text: e2 }) {
36708      return e2;
36709    }
36710    html({ text: e2 }) {
36711      return e2;
36712    }
36713    text({ text: e2 }) {
36714      return e2;
36715    }
36716    link({ text: e2 }) {
36717      return "" + e2;
36718    }
36719    image({ text: e2 }) {
36720      return "" + e2;
36721    }
36722    br() {
36723      return "";
36724    }
36725  };
36726  var b2 = class l3 {
36727    options;
36728    renderer;
36729    textRenderer;
36730    constructor(e2) {
36731      this.options = e2 || T, this.options.renderer = this.options.renderer || new P(), this.renderer = this.options.renderer, this.renderer.options = this.options, this.renderer.parser = this, this.textRenderer = new $();
36732    }
36733    static parse(e2, t2) {
36734      return new l3(t2).parse(e2);
36735    }
36736    static parseInline(e2, t2) {
36737      return new l3(t2).parseInline(e2);
36738    }
36739    parse(e2, t2 = true) {
36740      let n2 = "";
36741      for (let r2 = 0; r2 < e2.length; r2++) {
36742        let i2 = e2[r2];
36743        if (this.options.extensions?.renderers?.[i2.type]) {
36744          let a2 = i2, o2 = this.options.extensions.renderers[a2.type].call({ parser: this }, a2);
36745          if (o2 !== false || !["space", "hr", "heading", "code", "table", "blockquote", "list", "html", "def", "paragraph", "text"].includes(a2.type)) {
36746            n2 += o2 || "";
36747            continue;
36748          }
36749        }
36750        let s2 = i2;
36751        switch (s2.type) {
36752          case "space": {
36753            n2 += this.renderer.space(s2);
36754            continue;
36755          }
36756          case "hr": {
36757            n2 += this.renderer.hr(s2);
36758            continue;
36759          }
36760          case "heading": {
36761            n2 += this.renderer.heading(s2);
36762            continue;
36763          }
36764          case "code": {
36765            n2 += this.renderer.code(s2);
36766            continue;
36767          }
36768          case "table": {
36769            n2 += this.renderer.table(s2);
36770            continue;
36771          }
36772          case "blockquote": {
36773            n2 += this.renderer.blockquote(s2);
36774            continue;
36775          }
36776          case "list": {
36777            n2 += this.renderer.list(s2);
36778            continue;
36779          }
36780          case "html": {
36781            n2 += this.renderer.html(s2);
36782            continue;
36783          }
36784          case "def": {
36785            n2 += this.renderer.def(s2);
36786            continue;
36787          }
36788          case "paragraph": {
36789            n2 += this.renderer.paragraph(s2);
36790            continue;
36791          }
36792          case "text": {
36793            let a2 = s2, o2 = this.renderer.text(a2);
36794            for (; r2 + 1 < e2.length && e2[r2 + 1].type === "text"; ) a2 = e2[++r2], o2 += `
36795` + this.renderer.text(a2);
36796            t2 ? n2 += this.renderer.paragraph({ type: "paragraph", raw: o2, text: o2, tokens: [{ type: "text", raw: o2, text: o2, escaped: true }] }) : n2 += o2;
36797            continue;
36798          }
36799          default: {
36800            let a2 = 'Token with "' + s2.type + '" type was not found.';
36801            if (this.options.silent) return console.error(a2), "";
36802            throw new Error(a2);
36803          }
36804        }
36805      }
36806      return n2;
36807    }
36808    parseInline(e2, t2 = this.renderer) {
36809      let n2 = "";
36810      for (let r2 = 0; r2 < e2.length; r2++) {
36811        let i2 = e2[r2];
36812        if (this.options.extensions?.renderers?.[i2.type]) {
36813          let a2 = this.options.extensions.renderers[i2.type].call({ parser: this }, i2);
36814          if (a2 !== false || !["escape", "html", "link", "image", "strong", "em", "codespan", "br", "del", "text"].includes(i2.type)) {
36815            n2 += a2 || "";
36816            continue;
36817          }
36818        }
36819        let s2 = i2;
36820        switch (s2.type) {
36821          case "escape": {
36822            n2 += t2.text(s2);
36823            break;
36824          }
36825          case "html": {
36826            n2 += t2.html(s2);
36827            break;
36828          }
36829          case "link": {
36830            n2 += t2.link(s2);
36831            break;
36832          }
36833          case "image": {
36834            n2 += t2.image(s2);
36835            break;
36836          }
36837          case "strong": {
36838            n2 += t2.strong(s2);
36839            break;
36840          }
36841          case "em": {
36842            n2 += t2.em(s2);
36843            break;
36844          }
36845          case "codespan": {
36846            n2 += t2.codespan(s2);
36847            break;
36848          }
36849          case "br": {
36850            n2 += t2.br(s2);
36851            break;
36852          }
36853          case "del": {
36854            n2 += t2.del(s2);
36855            break;
36856          }
36857          case "text": {
36858            n2 += t2.text(s2);
36859            break;
36860          }
36861          default: {
36862            let a2 = 'Token with "' + s2.type + '" type was not found.';
36863            if (this.options.silent) return console.error(a2), "";
36864            throw new Error(a2);
36865          }
36866        }
36867      }
36868      return n2;
36869    }
36870  };
36871  var S2 = class {
36872    options;
36873    block;
36874    constructor(e2) {
36875      this.options = e2 || T;
36876    }
36877    static passThroughHooks = /* @__PURE__ */ new Set(["preprocess", "postprocess", "processAllTokens", "emStrongMask"]);
36878    static passThroughHooksRespectAsync = /* @__PURE__ */ new Set(["preprocess", "postprocess", "processAllTokens"]);
36879    preprocess(e2) {
36880      return e2;
36881    }
36882    postprocess(e2) {
36883      return e2;
36884    }
36885    processAllTokens(e2) {
36886      return e2;
36887    }
36888    emStrongMask(e2) {
36889      return e2;
36890    }
36891    provideLexer() {
36892      return this.block ? x2.lex : x2.lexInline;
36893    }
36894    provideParser() {
36895      return this.block ? b2.parse : b2.parseInline;
36896    }
36897  };
36898  var B = class {
36899    defaults = L();
36900    options = this.setOptions;
36901    parse = this.parseMarkdown(true);
36902    parseInline = this.parseMarkdown(false);
36903    Parser = b2;
36904    Renderer = P;
36905    TextRenderer = $;
36906    Lexer = x2;
36907    Tokenizer = y2;
36908    Hooks = S2;
36909    constructor(...e2) {
36910      this.use(...e2);
36911    }
36912    walkTokens(e2, t2) {
36913      let n2 = [];
36914      for (let r2 of e2) switch (n2 = n2.concat(t2.call(this, r2)), r2.type) {
36915        case "table": {
36916          let i2 = r2;
36917          for (let s2 of i2.header) n2 = n2.concat(this.walkTokens(s2.tokens, t2));
36918          for (let s2 of i2.rows) for (let a2 of s2) n2 = n2.concat(this.walkTokens(a2.tokens, t2));
36919          break;
36920        }
36921        case "list": {
36922          let i2 = r2;
36923          n2 = n2.concat(this.walkTokens(i2.items, t2));
36924          break;
36925        }
36926        default: {
36927          let i2 = r2;
36928          this.defaults.extensions?.childTokens?.[i2.type] ? this.defaults.extensions.childTokens[i2.type].forEach((s2) => {
36929            let a2 = i2[s2].flat(1 / 0);
36930            n2 = n2.concat(this.walkTokens(a2, t2));
36931          }) : i2.tokens && (n2 = n2.concat(this.walkTokens(i2.tokens, t2)));
36932        }
36933      }
36934      return n2;
36935    }
36936    use(...e2) {
36937      let t2 = this.defaults.extensions || { renderers: {}, childTokens: {} };
36938      return e2.forEach((n2) => {
36939        let r2 = { ...n2 };
36940        if (r2.async = this.defaults.async || r2.async || false, n2.extensions && (n2.extensions.forEach((i2) => {
36941          if (!i2.name) throw new Error("extension name required");
36942          if ("renderer" in i2) {
36943            let s2 = t2.renderers[i2.name];
36944            s2 ? t2.renderers[i2.name] = function(...a2) {
36945              let o2 = i2.renderer.apply(this, a2);
36946              return o2 === false && (o2 = s2.apply(this, a2)), o2;
36947            } : t2.renderers[i2.name] = i2.renderer;
36948          }
36949          if ("tokenizer" in i2) {
36950            if (!i2.level || i2.level !== "block" && i2.level !== "inline") throw new Error("extension level must be 'block' or 'inline'");
36951            let s2 = t2[i2.level];
36952            s2 ? s2.unshift(i2.tokenizer) : t2[i2.level] = [i2.tokenizer], i2.start && (i2.level === "block" ? t2.startBlock ? t2.startBlock.push(i2.start) : t2.startBlock = [i2.start] : i2.level === "inline" && (t2.startInline ? t2.startInline.push(i2.start) : t2.startInline = [i2.start]));
36953          }
36954          "childTokens" in i2 && i2.childTokens && (t2.childTokens[i2.name] = i2.childTokens);
36955        }), r2.extensions = t2), n2.renderer) {
36956          let i2 = this.defaults.renderer || new P(this.defaults);
36957          for (let s2 in n2.renderer) {
36958            if (!(s2 in i2)) throw new Error(`renderer '${s2}' does not exist`);
36959            if (["options", "parser"].includes(s2)) continue;
36960            let a2 = s2, o2 = n2.renderer[a2], p2 = i2[a2];
36961            i2[a2] = (...u2) => {
36962              let c2 = o2.apply(i2, u2);
36963              return c2 === false && (c2 = p2.apply(i2, u2)), c2 || "";
36964            };
36965          }
36966          r2.renderer = i2;
36967        }
36968        if (n2.tokenizer) {
36969          let i2 = this.defaults.tokenizer || new y2(this.defaults);
36970          for (let s2 in n2.tokenizer) {
36971            if (!(s2 in i2)) throw new Error(`tokenizer '${s2}' does not exist`);
36972            if (["options", "rules", "lexer"].includes(s2)) continue;
36973            let a2 = s2, o2 = n2.tokenizer[a2], p2 = i2[a2];
36974            i2[a2] = (...u2) => {
36975              let c2 = o2.apply(i2, u2);
36976              return c2 === false && (c2 = p2.apply(i2, u2)), c2;
36977            };
36978          }
36979          r2.tokenizer = i2;
36980        }
36981        if (n2.hooks) {
36982          let i2 = this.defaults.hooks || new S2();
36983          for (let s2 in n2.hooks) {
36984            if (!(s2 in i2)) throw new Error(`hook '${s2}' does not exist`);
36985            if (["options", "block"].includes(s2)) continue;
36986            let a2 = s2, o2 = n2.hooks[a2], p2 = i2[a2];
36987            S2.passThroughHooks.has(s2) ? i2[a2] = (u2) => {
36988              if (this.defaults.async && S2.passThroughHooksRespectAsync.has(s2)) return (async () => {
36989                let g2 = await o2.call(i2, u2);
36990                return p2.call(i2, g2);
36991              })();
36992              let c2 = o2.call(i2, u2);
36993              return p2.call(i2, c2);
36994            } : i2[a2] = (...u2) => {
36995              if (this.defaults.async) return (async () => {
36996                let g2 = await o2.apply(i2, u2);
36997                return g2 === false && (g2 = await p2.apply(i2, u2)), g2;
36998              })();
36999              let c2 = o2.apply(i2, u2);
37000              return c2 === false && (c2 = p2.apply(i2, u2)), c2;
37001            };
37002          }
37003          r2.hooks = i2;
37004        }
37005        if (n2.walkTokens) {
37006          let i2 = this.defaults.walkTokens, s2 = n2.walkTokens;
37007          r2.walkTokens = function(a2) {
37008            let o2 = [];
37009            return o2.push(s2.call(this, a2)), i2 && (o2 = o2.concat(i2.call(this, a2))), o2;
37010          };
37011        }
37012        this.defaults = { ...this.defaults, ...r2 };
37013      }), this;
37014    }
37015    setOptions(e2) {
37016      return this.defaults = { ...this.defaults, ...e2 }, this;
37017    }
37018    lexer(e2, t2) {
37019      return x2.lex(e2, t2 ?? this.defaults);
37020    }
37021    parser(e2, t2) {
37022      return b2.parse(e2, t2 ?? this.defaults);
37023    }
37024    parseMarkdown(e2) {
37025      return (n2, r2) => {
37026        let i2 = { ...r2 }, s2 = { ...this.defaults, ...i2 }, a2 = this.onError(!!s2.silent, !!s2.async);
37027        if (this.defaults.async === true && i2.async === false) return a2(new Error("marked(): The async option was set to true by an extension. Remove async: false from the parse options object to return a Promise."));
37028        if (typeof n2 > "u" || n2 === null) return a2(new Error("marked(): input parameter is undefined or null"));
37029        if (typeof n2 != "string") return a2(new Error("marked(): input parameter is of type " + Object.prototype.toString.call(n2) + ", string expected"));
37030        if (s2.hooks && (s2.hooks.options = s2, s2.hooks.block = e2), s2.async) return (async () => {
37031          let o2 = s2.hooks ? await s2.hooks.preprocess(n2) : n2, u2 = await (s2.hooks ? await s2.hooks.provideLexer() : e2 ? x2.lex : x2.lexInline)(o2, s2), c2 = s2.hooks ? await s2.hooks.processAllTokens(u2) : u2;
37032          s2.walkTokens && await Promise.all(this.walkTokens(c2, s2.walkTokens));
37033          let h2 = await (s2.hooks ? await s2.hooks.provideParser() : e2 ? b2.parse : b2.parseInline)(c2, s2);
37034          return s2.hooks ? await s2.hooks.postprocess(h2) : h2;
37035        })().catch(a2);
37036        try {
37037          s2.hooks && (n2 = s2.hooks.preprocess(n2));
37038          let p2 = (s2.hooks ? s2.hooks.provideLexer() : e2 ? x2.lex : x2.lexInline)(n2, s2);
37039          s2.hooks && (p2 = s2.hooks.processAllTokens(p2)), s2.walkTokens && this.walkTokens(p2, s2.walkTokens);
37040          let c2 = (s2.hooks ? s2.hooks.provideParser() : e2 ? b2.parse : b2.parseInline)(p2, s2);
37041          return s2.hooks && (c2 = s2.hooks.postprocess(c2)), c2;
37042        } catch (o2) {
37043          return a2(o2);
37044        }
37045      };
37046    }
37047    onError(e2, t2) {
37048      return (n2) => {
37049        if (n2.message += `
37050Please report this to https://github.com/markedjs/marked.`, e2) {
37051          let r2 = "<p>An error occurred:</p><pre>" + w2(n2.message + "", true) + "</pre>";
37052          return t2 ? Promise.resolve(r2) : r2;
37053        }
37054        if (t2) return Promise.reject(n2);
37055        throw n2;
37056      };
37057    }
37058  };
37059  var _2 = new B();
37060  function k(l4, e2) {
37061    return _2.parse(l4, e2);
37062  }
37063  k.options = k.setOptions = function(l4) {
37064    return _2.setOptions(l4), k.defaults = _2.defaults, G(k.defaults), k;
37065  };
37066  k.getDefaults = L;
37067  k.defaults = T;
37068  k.use = function(...l4) {
37069    return _2.use(...l4), k.defaults = _2.defaults, G(k.defaults), k;
37070  };
37071  k.walkTokens = function(l4, e2) {
37072    return _2.walkTokens(l4, e2);
37073  };
37074  k.parseInline = _2.parseInline;
37075  k.Parser = b2;
37076  k.parser = b2.parse;
37077  k.Renderer = P;
37078  k.TextRenderer = $;
37079  k.Lexer = x2;
37080  k.lexer = x2.lex;
37081  k.Tokenizer = y2;
37082  k.Hooks = S2;
37083  k.parse = k;
37084  var Zt = k.options;
37085  var Gt = k.setOptions;
37086  var Nt = k.use;
37087  var Ft = k.walkTokens;
37088  var jt = k.parseInline;
37089  var Ut = b2.parse;
37090  var Kt = x2.lex;
37091
37092  
vendor: 378,521 bytes, lines 37092-46195
37092// node_modules/@37signals/lexxy/dist/lexxy.esm.js
37093  var import_prismjs4 = __toESM(require_prism(), 1);
37094  var ALLOWED_HTML_ATTRIBUTES = ["class", "contenteditable", "href", "src", "style", "title"];
37095  var ALLOWED_STYLE_PROPERTIES = ["color", "background-color"];
37096  function styleFilterHook(_currentNode, hookEvent) {
37097    if (hookEvent.attrName === "style" && hookEvent.attrValue) {
37098      const styles = { ...getStyleObjectFromCSS4(hookEvent.attrValue) };
37099      const sanitizedStyles = {};
37100      for (const property in styles) {
37101        if (ALLOWED_STYLE_PROPERTIES.includes(property)) {
37102          sanitizedStyles[property] = styles[property];
37103        }
37104      }
37105      if (Object.keys(sanitizedStyles).length) {
37106        hookEvent.attrValue = getCSSFromStyleObject2(sanitizedStyles);
37107      } else {
37108        hookEvent.keepAttr = false;
37109      }
37110    }
37111  }
37112  purify.addHook("uponSanitizeAttribute", styleFilterHook);
37113  purify.addHook("uponSanitizeElement", (node, data) => {
37114    if (data.tagName === "strong" || data.tagName === "em") {
37115      node.removeAttribute("class");
37116    }
37117  });
37118  function buildConfig(allowedElements) {
37119    const tagAttributes = {};
37120    for (const element of allowedElements) {
37121      if (typeof element === "string") {
37122        tagAttributes[element] ||= [];
37123      } else {
37124        tagAttributes[element.tag] ||= [];
37125        tagAttributes[element.tag].push(...element.attributes);
37126      }
37127    }
37128    return {
37129      ALLOWED_TAGS: Object.keys(tagAttributes),
37130      ALLOWED_ATTR: ALLOWED_HTML_ATTRIBUTES,
37131      ADD_ATTR: (attribute, tag) => tagAttributes[tag]?.includes(attribute),
37132      ADD_URI_SAFE_ATTR: ["caption", "filename"],
37133      SAFE_FOR_XML: false
37134      // So that it does not strip attributes that contains serialized HTML (like content)
37135    };
37136  }
37137  function getNonce() {
37138    const element = document.head.querySelector("meta[name=csp-nonce]");
37139    return element?.content;
37140  }
37141  function registerEventListener(element, type, listener, options) {
37142    element.addEventListener(type, listener, options);
37143    const elementRef = new WeakRef(element);
37144    const listenerRef = new WeakRef(listener);
37145    return function deregisterListener() {
37146      const listener2 = listenerRef.deref();
37147      if (listener2) elementRef.deref()?.removeEventListener(type, listener2, options);
37148    };
37149  }
37150  var ListenerBin = class {
37151    #listeners = [];
37152    track(...listeners) {
37153      this.#listeners.push(...listeners);
37154    }
37155    dispose() {
37156      while (this.#listeners.length) {
37157        const teardown = this.#listeners.pop();
37158        teardown();
37159      }
37160    }
37161  };
37162  function handlingDefault(handler) {
37163    return (event) => {
37164      const handled = handler(event);
37165      if (handled) event.preventDefault();
37166      return handled;
37167    };
37168  }
37169  function createElement(name, properties, content = "") {
37170    const element = document.createElement(name);
37171    for (const [key, value] of Object.entries(properties || {})) {
37172      if (key === "dataset") {
37173        Object.entries(value).forEach(([key2, value2]) => element.dataset[key2] = value2);
37174      } else if (key in element) {
37175        element[key] = value;
37176      } else if (value !== null && value !== void 0) {
37177        element.setAttribute(key, value);
37178      }
37179    }
37180    if (content) {
37181      element.innerHTML = content;
37182    }
37183    return element;
37184  }
37185  function parseHtml(html2) {
37186    const parser = new DOMParser();
37187    return parser.parseFromString(html2, "text/html");
37188  }
37189  function createAttachmentFigure(contentType, isPreviewable, fileName) {
37190    const extension = fileName ? fileName.split(".").pop().toLowerCase() : "unknown";
37191    return createElement("figure", {
37192      className: `attachment attachment--${isPreviewable ? "preview" : "file"} attachment--${extension}`,
37193      "data-content-type": contentType
37194    });
37195  }
37196  function isPreviewableImage(contentType, fileName = "") {
37197    return contentType.startsWith("image/") && !contentType.includes("svg") || fileName.toLowerCase().endsWith(".avif");
37198  }
37199  function isLexxyImageLayoutContent(content) {
37200    return content != null && typeof content === "object" && !Array.isArray(content) && "lexxyImage" in content;
37201  }
37202  function isLexxyImageLayoutString(content) {
37203    if (!content) return false;
37204    try {
37205      const parsed = typeof content === "string" ? JSON.parse(content) : content;
37206      return isLexxyImageLayoutContent(parsed);
37207    } catch {
37208      return false;
37209    }
37210  }
37211  function parseLexxyImageLayout(content) {
37212    if (!content) return {};
37213    try {
37214      const parsed = typeof content === "string" ? JSON.parse(content) : content;
37215      return parsed?.lexxyImage || {};
37216    } catch {
37217      return {};
37218    }
37219  }
37220  var LEXXY_IMAGE_SIZE_CLASSES = ["attachment--image-small", "attachment--image-medium", "attachment--image-full"];
37221  var LEXXY_IMAGE_ALIGN_CLASSES = ["attachment--align-left", "attachment--align-center", "attachment--align-right"];
37222  var CAPTION_ALLOWED_TAGS = ["a", "b", "strong", "i", "em", "s", "strike", "u", "br"];
37223  var CAPTION_ALLOWED_ATTRIBUTES = ["href", "title"];
37224  var CAPTION_EXEC_COMMANDS = {
37225    bold: "bold",
37226    italic: "italic",
37227    underline: "underline"
37228  };
37229  var CAPTION_TOOLBAR_ICONS = {
37230    bold: `<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" aria-hidden="true" focusable="false"><g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" stroke="currentColor"><path d="M6.75 2.25H10C11.795 2.25 13.25 3.71 13.25 5.5C13.25 7.29 11.795 8.75 10 8.75H6.75"></path><path d="M6.75 8.75H10.75C12.683 8.75 14.25 10.3199 14.25 12.25C14.25 14.1801 12.683 15.75 10.75 15.75H6.75"></path><path d="M6.75 15.75H4.75C4.198 15.75 3.75 15.3 3.75 14.75V3.25C3.75 2.7 4.198 2.25 4.75 2.25H6.75V15.75Z"></path></g></svg>`,
37231    italic: `<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><g stroke-linejoin="round" stroke-linecap="round" stroke-width="1.75" fill="none" stroke="currentColor"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M11 5l6 0"></path><path d="M7 19l6 0"></path><path d="M14 5l-4 14"></path></g></svg>`,
37232    underline: `<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" aria-hidden="true" focusable="false"><g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" stroke="currentColor"><path d="M12.75,2.75v5.75c0,2.071-1.679,3.75-3.75,3.75h0c-2.071,0-3.75-1.679-3.75-3.75V2.75"></path><line id="color" x1="2.75" y1="15.25" x2="15.25" y2="15.25"></line></g></svg>`,
37233    link: `<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" aria-hidden="true" focusable="false"><g fill="currentColor"><path fill-rule="evenodd" clip-rule="evenodd" d="M9.03166 6.54197C9.22575 6.9079 9.08644 7.36188 8.72052 7.55597C8.47184 7.68787 8.24717 7.85851 8.04832 8.05733C6.96021 9.14544 6.96021 10.9086 8.04832 11.9967L10.2233 14.1717C11.3114 15.2598 13.0746 15.2598 14.1627 14.1717C15.2507 13.0836 15.2608 11.3104 14.1727 10.2223L13.4103 9.45993C13.1174 9.16703 13.1174 8.69216 13.4103 8.39927C13.7032 8.10638 14.178 8.10638 14.4709 8.39927L15.2333 9.16167C16.9072 10.8356 16.9072 13.5484 15.2333 15.2223C13.5594 16.8962 10.8365 16.9062 9.16266 15.2323L6.98766 13.0573C5.31377 11.3834 5.31377 8.67056 6.98766 6.99667C7.29576 6.68747 7.64975 6.42597 8.01766 6.23083C8.38359 6.03674 8.83757 6.17604 9.03166 6.54197Z"></path><path fill-rule="evenodd" clip-rule="evenodd" d="M2.77868 2.76766C4.45257 1.09376 7.16544 1.09376 8.83934 2.76766L11.0143 4.94266C12.6882 6.61655 12.6882 9.32942 11.0143 11.0033C10.7101 11.3075 10.3647 11.5674 9.98433 11.7692C9.6184 11.9633 9.16442 11.824 8.97033 11.458C8.77624 11.0921 8.91554 10.6381 9.28147 10.444C9.53006 10.3122 9.7549 10.1414 9.95368 9.94267C11.0418 8.85455 11.0418 7.09142 9.95368 6.00332L7.77868 3.82832C6.69057 2.74021 4.92744 2.74021 3.83934 3.82832C2.76193 4.90573 2.74775 6.69607 3.82934 7.77766L4.59174 8.54006C4.88463 8.83295 4.88463 9.30782 4.59174 9.60072C4.29884 9.89361 3.82397 9.89361 3.53108 9.60072L2.76868 8.83832C1.10903 7.17867 1.1232 4.42314 2.77868 2.76766Z"></path></g></svg>`
37234  };
37235  function applyLexxyImageLayout(figure, content) {
37236    const { size: size2, align: storedAlign } = parseLexxyImageLayout(content);
37237    let align = storedAlign;
37238    if (["small", "medium", "full"].includes(size2)) {
37239      figure.classList.add(`attachment--image-${size2}`);
37240    }
37241    if (["small", "medium"].includes(size2) && !align) {
37242      align = "center";
37243    }
37244    if (["left", "center", "right"].includes(align)) {
37245      figure.classList.add(`attachment--align-${align}`);
37246    }
37247  }
37248  function syncLexxyImageLayoutClasses(figure, content) {
37249    figure.classList.remove(...LEXXY_IMAGE_SIZE_CLASSES, ...LEXXY_IMAGE_ALIGN_CLASSES);
37250    applyLexxyImageLayout(figure, content);
37251  }
37252  function sanitizeCaptionHtml(caption) {
37253    return purify.sanitize(caption || "", {
37254      ALLOWED_TAGS: CAPTION_ALLOWED_TAGS,
37255      ALLOWED_ATTR: CAPTION_ALLOWED_ATTRIBUTES,
37256      ALLOW_DATA_ATTR: false
37257    }).trim();
37258  }
37259  function captionTextContent(caption) {
37260    const container = document.createElement("div");
37261    container.innerHTML = sanitizeCaptionHtml(caption);
37262    return container.textContent || "";
37263  }
37264  function syncCaptionEditorEmptyState(input) {
37265    if (!input) return;
37266    if (!captionTextContent(input.innerHTML).trim()) {
37267      input.dataset.captionEmpty = "true";
37268    } else {
37269      delete input.dataset.captionEmpty;
37270    }
37271  }
37272  function normalizeCaptionHtml(html2) {
37273    const caption = sanitizeCaptionHtml(html2);
37274    if (!captionTextContent(caption).trim()) return "";
37275    return caption;
37276  }
37277  function escapeCaptionText(text2) {
37278    const container = document.createElement("div");
37279    container.textContent = text2;
37280    return container.innerHTML;
37281  }
37282  function normalizedCaptionUrl(url) {
37283    const value = url?.trim();
37284    if (!value) return null;
37285    const urlWithScheme = /^[a-z][a-z\d+.-]*:/i.test(value) ? value : `https://${value}`;
37286    try {
37287      const parsed = new URL(urlWithScheme);
37288      return ["http:", "https:"].includes(parsed.protocol) ? parsed.href : null;
37289    } catch {
37290      return null;
37291    }
37292  }
37293  function dispatch(element, eventName, detail = null, cancelable = false) {
37294    return element.dispatchEvent(new CustomEvent(eventName, { bubbles: true, detail, cancelable }));
37295  }
37296  function addBlockSpacing(doc) {
37297    const selector = "body > :not(h1, h2, h3, h4, h5, h6) + *, blockquote > :not(h1, h2, h3, h4, h5, h6) + *";
37298    for (const block of doc.querySelectorAll(selector)) {
37299      const spacer = doc.createElement("p");
37300      spacer.appendChild(doc.createElement("br"));
37301      block.before(spacer);
37302    }
37303  }
37304  function generateDomId(prefix) {
37305    const randomPart = Math.random().toString(36).slice(2, 10);
37306    return `${prefix}-${randomPart}`;
37307  }
37308  function extractPlainTextFromHtml(innerHtml = "") {
37309    return parseHtml(innerHtml).body.textContent.trim();
37310  }
37311  function isActiveAndVisible(element) {
37312    return element && !element.disabled && checkVisibility(element);
37313  }
37314  function checkVisibility(element, options) {
37315    if (element.checkVisibility) {
37316      return element.checkVisibility(options);
37317    } else {
37318      return Boolean(element.offsetParent);
37319    }
37320  }
37321  function handleRollingTabIndex(elements, event) {
37322    const previousActiveElement = document.activeElement;
37323    if (elements.includes(previousActiveElement)) {
37324      const finder = new NextElementFinder(elements, event.key);
37325      if (finder.selectNext(previousActiveElement)) {
37326        event.preventDefault();
37327      }
37328    }
37329  }
37330  var NextElementFinder = class {
37331    constructor(elements, key) {
37332      this.elements = elements;
37333      this.key = key;
37334    }
37335    selectNext(fromElement) {
37336      const nextElement = this.#findNextElement(fromElement);
37337      if (nextElement) {
37338        const inactiveElements = this.elements.filter((element) => element !== nextElement);
37339        this.#unsetTabIndex(inactiveElements);
37340        this.#focusWithActiveTabIndex(nextElement);
37341        return true;
37342      }
37343      return false;
37344    }
37345    #findNextElement(fromElement) {
37346      switch (this.key) {
37347        case "ArrowRight":
37348        case "ArrowDown":
37349          return this.#findNextSibling(fromElement);
37350        case "ArrowLeft":
37351        case "ArrowUp":
37352          return this.#findPreviousSibling(fromElement);
37353        case "Home":
37354          return this.#findFirst();
37355        case "End":
37356          return this.#findLast();
37357      }
37358    }
37359    #findFirst(elements = this.elements) {
37360      return elements.find(isActiveAndVisible);
37361    }
37362    #findLast(elements = this.elements) {
37363      return elements.findLast(isActiveAndVisible);
37364    }
37365    #findNextSibling(element) {
37366      const afterElements = this.elements.slice(this.#indexOf(element) + 1);
37367      return this.#findFirst(afterElements);
37368    }
37369    #findPreviousSibling(element) {
37370      const beforeElements = this.elements.slice(0, this.#indexOf(element));
37371      return this.#findLast(beforeElements);
37372    }
37373    #indexOf(element) {
37374      return this.elements.indexOf(element);
37375    }
37376    #focusWithActiveTabIndex(element) {
37377      if (isActiveAndVisible(element)) {
37378        element.tabIndex = 0;
37379        element.focus();
37380      }
37381    }
37382    #unsetTabIndex(elements) {
37383      elements.forEach((element) => element.tabIndex = -1);
37384    }
37385  };
37386  var ToolbarIcons = {
37387    "bold": `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
37388    <path fill-rule="evenodd" clip-rule="evenodd" d="M9.05273 1.88232C10.6866 1.88237 12.0033 2.20353 12.9529 2.89673L13.1272 3.0293C13.974 3.70864 14.4008 4.63245 14.4009 5.76562C14.4008 6.49354 14.2316 7.15281 13.8845 7.73145C13.6683 8.09188 13.3997 8.40162 13.0818 8.66016C13.5902 8.92606 14.0196 9.28599 14.3635 9.74121C14.8586 10.3834 15.0945 11.1743 15.0945 12.0879C15.0944 13.3698 14.5922 14.3931 13.5879 15.1106L13.5857 15.1128C12.5967 15.805 11.196 16.125 9.43799 16.125H3.10547V1.88232L9.05273 1.88232ZM6.36108 13.4084H9.28418C10.224 13.4084 10.8634 13.2491 11.2581 12.9851C11.6259 12.7389 11.8198 12.3768 11.8198 11.8367C11.8197 11.2968 11.6259 10.9351 11.2581 10.689C10.8634 10.425 10.2241 10.2649 9.28418 10.2649H6.36108V13.4084ZM6.36108 7.56812H8.78247C9.5163 7.56809 10.0547 7.45371 10.429 7.25757L10.5791 7.16895C10.9438 6.92178 11.1255 6.57934 11.1255 6.09302C11.1254 5.59017 10.9414 5.25227 10.5835 5.02002L10.5784 5.01636L10.5732 5.01343C10.1994 4.75387 9.61878 4.59818 8.78247 4.59814H6.36108V7.56812Z"/>
37389  </svg>`,
37390    "italic": `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
37391    <path d="M14.1379 3.91187L14.1086 4.06421H11.4668L9.49805 13.9431H12.0981L11.7473 15.7852L11.7188 15.9375H4.16675L4.51758 14.0955L4.54614 13.9431H7.18799L9.17505 4.06421H6.55664L6.90747 2.22217L6.93677 2.06982H14.4888L14.1379 3.91187Z"/>
37392  </svg>`,
37393    "strikethrough": `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
37394    <path d="M14.3723 11.8015C14.3771 11.8858 14.3811 11.9756 14.3811 12.0681C14.3811 12.811 14.1777 13.4959 13.7725 14.1174L13.7717 14.1189C13.3624 14.7329 12.7463 15.2162 11.9377 15.5742L11.9348 15.5757C11.1214 15.9223 10.1306 16.092 8.96997 16.092C7.9356 16.092 6.93308 15.9348 5.96338 15.6204L5.96045 15.6189C5.00593 15.292 4.24112 14.8699 3.67676 14.3459L3.57568 14.2522L3.63501 14.1277L4.45605 12.397L4.64282 12.5654C5.13492 13.0083 5.76733 13.3759 6.54492 13.6648C7.33475 13.9406 8.14322 14.0786 8.96997 14.0786C10.0731 14.0786 10.8638 13.8932 11.3708 13.5513C11.8757 13.1982 12.1172 12.7464 12.1172 12.1838C12.1172 12.0662 12.1049 11.9556 12.0828 11.8513L12.0344 11.625H14.3621L14.3723 11.8015Z"/>
37395    <path d="M9.2981 1.91602C10.111 1.91604 10.9109 2.02122 11.6975 2.23096C12.4855 2.44111 13.1683 2.74431 13.7417 3.14429L13.8655 3.23071L13.8083 3.36987L13.1726 4.91235L13.0869 5.1189L12.8987 4.99878C12.3487 4.64881 11.761 4.38633 11.1365 4.21143L11.1328 4.20996C10.585 4.04564 10.0484 3.95419 9.52295 3.93384L9.2981 3.92944C8.22329 3.92944 7.44693 4.12611 6.94043 4.49121C6.44619 4.85665 6.20874 5.31616 6.20874 5.88135L6.21533 6.03296C6.24495 6.37662 6.37751 6.65526 6.61011 6.87964L6.72144 6.97632C6.98746 7.19529 7.30625 7.37584 7.68018 7.51538L8.05151 7.63184C8.45325 7.75061 8.94669 7.87679 9.53247 8.01123L9.53467 8.01196C10.1213 8.15305 10.6426 8.29569 11.0991 8.4375H15C15.5178 8.4375 15.9375 8.85723 15.9375 9.375C15.9375 9.89277 15.5178 10.3125 15 10.3125H3C2.48223 10.3125 2.0625 9.89277 2.0625 9.375C2.0625 8.85723 2.48223 8.4375 3 8.4375H4.93726C4.83783 8.34526 4.74036 8.24896 4.64795 8.146L4.64502 8.14233C4.1721 7.58596 3.94482 6.85113 3.94482 5.95825C3.94483 5.20441 4.14059 4.51965 4.53369 3.90967L4.53516 3.90747C4.94397 3.29427 5.55262 2.81114 6.34863 2.45288C7.15081 2.0919 8.13683 1.91602 9.2981 1.91602Z"/>
37396  </svg>`,
37397    "underline": `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
37398    <path d="M14 14C14.5523 14 15 14.4477 15 15C15 15.5523 14.5523 16 14 16H4C3.44772 16 3 15.5523 3 15C3 14.4477 3.44772 14 4 14H14Z"/>
37399    <path d="M12.625 1.59375C13.25 1.59375 13.625 1.97656 13.625 2.64062V9.02344C13.625 11.4844 11.8516 13.1875 8.99219 13.1875C6.14062 13.1875 4.35938 11.4844 4.35938 9.02344V2.64062C4.35938 1.97656 4.74219 1.59375 5.36719 1.59375C6 1.59375 6.375 1.97656 6.375 2.64062V8.84375C6.375 10.3828 7.32031 11.4297 8.99219 11.4297C10.6641 11.4297 11.6172 10.3828 11.6172 8.84375V2.64062C11.6172 1.97656 11.9922 1.59375 12.625 1.59375Z"/>
37400  </svg>`,
37401    "heading": `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
37402    <path d="M11.5 2C12.0523 2 12.5 2.44772 12.5 3V3.5C12.5 4.05228 12.0523 4.5 11.5 4.5H8V15C8 15.5523 7.55228 16 7 16H6.5C5.94772 16 5.5 15.5523 5.5 15V4.5H2C1.44772 4.5 1 4.05228 1 3.5V3C1 2.44772 1.44772 2 2 2H11.5ZM16 7C16.5523 7 17 7.44772 17 8V8.5C17 9.05228 16.5523 9.5 16 9.5H15V15C15 15.5523 14.5523 16 14 16H13.5C12.9477 16 12.5 15.5523 12.5 15V9.5H11.5C10.9477 9.5 10.5 9.05228 10.5 8.5V8C10.5 7.44772 10.9477 7 11.5 7H16Z"/>
37403  </svg>`,
37404    "h1": `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
37405    <path d="M8.12207 4.30078C8.84668 4.30078 9.25684 4.74512 9.25684 5.51758V12.5518C9.25677 13.3241 8.84662 13.7686 8.12207 13.7686C7.39752 13.7686 6.9942 13.3309 6.99414 12.5518V9.87207H3.56934V12.5518C3.56927 13.3241 3.15912 13.7686 2.43457 13.7686C1.71002 13.7686 1.3067 13.3309 1.30664 12.5518V5.51758C1.30664 4.73828 1.70996 4.30078 2.43457 4.30078C3.15918 4.30078 3.56934 4.74512 3.56934 5.51758V8.07422H6.99414V5.51758C6.99414 4.73828 7.39746 4.30078 8.12207 4.30078ZM13.8418 4.125H14.8271C15.543 4.125 16.0449 4.56934 16.0449 5.23828V12.7207C16.0449 13.4111 15.6348 13.8486 14.9854 13.8486C14.336 13.8486 13.9395 13.418 13.9395 12.7207V6.11133H13.8887L12.9541 6.74219C12.7354 6.88574 12.5303 6.95312 12.3047 6.95312C11.7646 6.95312 11.3955 6.58398 11.3955 6.06445C11.3955 5.69531 11.5801 5.42578 11.9766 5.15625L13.4023 4.32031C13.5459 4.23633 13.6826 4.17578 13.8418 4.125Z"/>
37406  </svg>`,
37407    "h2": `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
37408    <path d="M8.12207 4.30078C8.84668 4.30078 9.25684 4.74512 9.25684 5.51758V12.5518C9.25677 13.3241 8.84662 13.7686 8.12207 13.7686C7.39752 13.7686 6.9942 13.3309 6.99414 12.5518V9.87207H3.56934V12.5518C3.56927 13.3241 3.15912 13.7686 2.43457 13.7686C1.71002 13.7686 1.3067 13.3309 1.30664 12.5518V5.51758C1.30664 4.73828 1.70996 4.30078 2.43457 4.30078C3.15918 4.30078 3.56934 4.74512 3.56934 5.51758V8.07422H6.99414V5.51758C6.99414 4.73828 7.39746 4.30078 8.12207 4.30078ZM13.6445 4.19824C15.5244 4.19824 16.8984 5.34668 16.8984 6.91211C16.8984 7.8759 16.4335 8.7237 15.292 9.84473L13.3438 11.8135V11.9092H16.1875C16.8232 11.9092 17.2197 12.251 17.2197 12.8115C17.2196 13.3651 16.83 13.7002 16.1875 13.7002H11.5117C10.8487 13.7002 10.4112 13.3241 10.4111 12.75C10.4111 12.3399 10.6368 11.9843 11.3203 11.3145L13.6855 8.88086C14.4169 8.13583 14.7245 7.64349 14.7246 7.12402C14.7246 6.4541 14.2393 6.00293 13.5215 6.00293C12.9404 6.00293 12.5166 6.29688 12.2158 6.90527C11.9151 7.37002 11.6552 7.54785 11.2588 7.54785C10.7188 7.54785 10.3429 7.17861 10.3428 6.65918C10.3428 5.3877 11.7783 4.19824 13.6445 4.19824Z"/>
37409  </svg>`,
37410    "h3": `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
37411    <path d="M13.5967 4.19824C15.5928 4.19824 16.9873 5.23047 16.9873 6.7002C16.9872 7.705 16.2421 8.60059 15.2988 8.7168V8.86719C16.4199 8.94923 17.2607 9.89942 17.2607 11.0889C17.2606 12.7362 15.7362 13.9053 13.583 13.9053C11.6827 13.9053 10.1925 12.873 10.1924 11.7041C10.1924 11.1846 10.5547 10.8154 11.0537 10.8154C11.3818 10.8154 11.6553 10.9727 11.9629 11.3555C12.3799 11.9159 12.92 12.2031 13.583 12.2031C14.4853 12.2031 15.0731 11.7313 15.0732 11C15.0732 10.2754 14.4785 9.7832 13.5898 9.7832H13.0361C12.5645 9.7832 12.2159 9.4208 12.2158 8.92188C12.2158 8.44336 12.5576 8.07422 13.0361 8.07422H13.5693C14.3075 8.07422 14.8544 7.60928 14.8545 6.97363C14.8545 6.33789 14.3213 5.90039 13.5557 5.90039C12.9678 5.90039 12.5029 6.16016 12.0859 6.71387C11.8399 7.03508 11.5527 7.17871 11.1973 7.17871C10.671 7.17871 10.295 6.82314 10.2949 6.31738C10.2949 5.18945 11.751 4.19824 13.5967 4.19824ZM8.0332 4.30078C8.75781 4.30078 9.16797 4.74512 9.16797 5.51758V12.5518C9.1679 13.3241 8.75776 13.7686 8.0332 13.7686C7.30865 13.7686 6.90534 13.3309 6.90527 12.5518V9.87207H3.48047V12.5518C3.4804 13.3241 3.07026 13.7686 2.3457 13.7686C1.62115 13.7686 1.21784 13.3309 1.21777 12.5518V5.51758C1.21777 4.73828 1.62109 4.30078 2.3457 4.30078C3.07031 4.30078 3.48047 4.74512 3.48047 5.51758V8.07422H6.90527V5.51758C6.90527 4.73828 7.30859 4.30078 8.0332 4.30078Z"/>
37412  </svg>`,
37413    "h4": `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
37414    <path d="M14.6357 4.22559C15.7432 4.22559 16.4336 4.80664 16.4336 5.73633V10.3164H16.7275C17.2881 10.3164 17.6436 10.6787 17.6436 11.2256C17.6435 11.7655 17.3017 12.1006 16.7275 12.1006H16.4336V12.6611C16.4335 13.3515 16.0234 13.7891 15.374 13.7891C14.7247 13.7891 14.3282 13.3583 14.3281 12.6611V12.1006H11.04C10.2335 12.1006 9.76863 11.6766 9.76855 10.918C9.76855 10.5762 9.85064 10.3026 10.1104 9.74219C10.7666 8.42289 11.5733 7.0146 12.5713 5.54492C13.2549 4.56738 13.7812 4.22559 14.6357 4.22559ZM7.88965 4.30078C8.61426 4.30078 9.02441 4.74512 9.02441 5.51758V12.5518C9.02435 13.3241 8.6142 13.7686 7.88965 13.7686C7.1651 13.7686 6.76178 13.3309 6.76172 12.5518V9.87207H3.33691V12.5518C3.33685 13.3241 2.9267 13.7686 2.20215 13.7686C1.4776 13.7686 1.07428 13.3309 1.07422 12.5518V5.51758C1.07422 4.73828 1.47754 4.30078 2.20215 4.30078C2.92676 4.30078 3.33691 4.74512 3.33691 5.51758V8.07422H6.76172V5.51758C6.76172 4.73828 7.16504 4.30078 7.88965 4.30078ZM14.2188 6.07812C13.6035 7.02841 12.2158 9.48929 11.7988 10.2686V10.3164H14.3281V6.07812H14.2188Z"/>
37415  </svg>`,
37416    "h5": `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
37417    <path d="M8.12207 4.30078C8.84668 4.30078 9.25684 4.74512 9.25684 5.51758V12.5518C9.25677 13.3241 8.84662 13.7686 8.12207 13.7686C7.39752 13.7686 6.9942 13.3309 6.99414 12.5518V9.87207H3.56934V12.5518C3.56927 13.3241 3.15912 13.7686 2.43457 13.7686C1.71002 13.7686 1.3067 13.3309 1.30664 12.5518V5.51758C1.30664 4.73828 1.70996 4.30078 2.43457 4.30078C3.15918 4.30078 3.56934 4.74512 3.56934 5.51758V8.07422H6.99414V5.51758C6.99414 4.73828 7.39746 4.30078 8.12207 4.30078ZM16.1191 4.30078C16.6934 4.30078 17.0762 4.63672 17.0762 5.16602C17.0762 5.69531 16.6934 6.03125 16.1191 6.03125H13.3457L12.9219 8.25586H13.0176C13.248 8.03711 13.6855 7.84375 14.2871 7.84375C15.9277 7.84375 17.1445 9.07422 17.1445 10.7832C17.1445 12.5605 15.8184 13.9053 13.7695 13.9053C11.9512 13.9053 10.6934 12.9277 10.5566 11.7178C10.5566 11.2021 10.9121 10.8193 11.4277 10.8193C11.8379 10.8193 12.1328 11.0244 12.3516 11.4893C12.625 12.0361 13.1133 12.2549 13.7285 12.2549C14.5488 12.2549 15.1367 11.6533 15.1367 10.7695C15.1367 9.92188 14.5625 9.31348 13.7559 9.31348C13.1953 9.31348 12.7578 9.56055 12.4629 10.0254C12.2168 10.3887 11.9355 10.5527 11.5527 10.5527C10.9648 10.5527 10.5684 10.1699 10.5684 9.55469C10.5684 9.42773 10.582 9.30762 10.6094 9.17383L11.2383 5.55273C11.3516 4.88379 11.7207 4.30078 12.6797 4.30078H16.1191Z"/>
37418  </svg>`,
37419    "h6": `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
37420    <path d="M8.12207 4.30078C8.84668 4.30078 9.25684 4.74512 9.25684 5.51758V12.5518C9.25677 13.3241 8.84662 13.7686 8.12207 13.7686C7.39752 13.7686 6.9942 13.3309 6.99414 12.5518V9.87207H3.56934V12.5518C3.56927 13.3241 3.15912 13.7686 2.43457 13.7686C1.71002 13.7686 1.3067 13.3309 1.30664 12.5518V5.51758C1.30664 4.73828 1.70996 4.30078 2.43457 4.30078C3.15918 4.30078 3.56934 4.74512 3.56934 5.51758V8.07422H6.99414V5.51758C6.99414 4.73828 7.39746 4.30078 8.12207 4.30078ZM13.6719 13.9258C15.5518 13.9258 17.1445 12.37306 17.1445 10.35451V10.05763C17.1445 8.10744 16.6016 6.59574 15.5928 5.58694C14.8613 4.85544 13.8975 4.42384 12.7285 4.25294C12.4199 4.21194 12.1592 4.19824 11.8643 4.19824C11.2627 4.19824 10.8389 4.59474 10.8389 5.14164C10.8389 5.65724 11.2354 6.02054 11.7783 6.04784C12.1758 6.06834 12.4844 6.10944 12.7656 6.19144C13.5176 6.42384 14.0742 6.95314 14.3965 7.75974L14.4922 8.00584H14.3828C14.0605 7.56834 13.4863 7.25974 12.6523 7.25974C11.1406 7.25974 10.0674 8.42384 10.0674 10.02345V10.27736C10.0674 12.2549 11.4668 13.9258 13.6719 13.9258ZM13.5215 12.24123C12.6797 12.24123 12.0918 11.48244 12.0918 10.4131V10.1592C12.0918 9.26174 12.6523 8.71291 13.5352 8.71291C14.3965 8.71291 14.9844 9.27638 14.9844 10.1592V10.4131C14.9844 11.48244 14.3828 12.24123 13.5215 12.24123Z"/>
37421  </svg>`,
37422    "paragraph": `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
37423    <path d="M9 12C9.55228 12 10 12.4477 10 13C10 13.5523 9.55228 14 9 14H3C2.44772 14 2 13.5523 2 13C2 12.4477 2.44772 12 3 12H9ZM15 8C15.5523 8 16 8.44772 16 9C16 9.55228 15.5523 10 15 10H3C2.44772 10 2 9.55228 2 9C2 8.44772 2.44772 8 3 8H15ZM15 4C15.5523 4 16 4.44772 16 5C16 5.55228 15.5523 6 15 6H3C2.44772 6 2 5.55228 2 5C2 4.44772 2.44772 4 3 4H15Z"/>
37424  </svg>`,
37425    "clearFormatting": `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
37426    <path d="M10.0607 2.07533C10.8417 1.29432 12.1078 1.2943 12.8888 2.07533L16.424 5.61049C17.205 6.39154 17.205 7.65854 16.424 8.43959L9.44937 15.4142C9.07435 15.7891 8.5656 16.0001 8.03531 16.0001H5.0148C4.55074 16.0001 4.10309 15.8385 3.74722 15.547L3.60074 15.4142L1.57534 13.3888C0.79431 12.6078 0.794336 11.3417 1.57534 10.5607L10.0607 2.07533ZM2.98941 11.9747L5.0148 14.0001H8.03531L9.71792 12.3165L6.18179 8.78139L2.98941 11.9747Z"/>
37427  </svg>`,
37428    "highlight": `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
37429    <path d="M16.4564 14.4272C17.1356 15.5592 16.3204 17.0002 15.0003 17.0004C13.68 17.0004 12.864 15.5593 13.5433 14.4272L15.0003 12.0004L16.4564 14.4272ZM5.1214 1.70746C5.51192 1.31693 6.14494 1.31693 6.53546 1.70746L9.7171 4.8891L13.2532 8.42426C14.2295 9.40056 14.2295 10.9841 13.2532 11.9604L9.7171 15.4955C8.74078 16.4718 7.15822 16.4718 6.18195 15.4955L2.64679 11.9604C1.67048 10.9841 1.67048 9.40057 2.64679 8.42426L6.18195 4.8891C6.30299 4.76805 6.43323 4.66177 6.57062 4.57074L5.1214 3.12152C4.73091 2.73104 4.73099 2.09799 5.1214 1.70746ZM8.30304 6.30316C8.10776 6.10815 7.79119 6.10799 7.59601 6.30316L4.06085 9.83929L3.9964 9.91742C3.88661 10.0838 3.88645 10.3019 3.9964 10.4682L4.02277 10.5004H11.8763C12.0312 10.3043 12.02 10.0205 11.8392 9.83929L8.30304 6.30316Z"/>
37430  </svg>`,
37431    "link": `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
37432    <path d="M12.8885 7.23091L13.9479 6.17155C14.5337 5.58576 14.5337 4.63602 13.9479 4.05023C13.3621 3.46444 12.4124 3.46444 11.8266 4.05023L8.29235 7.58446C7.9263 7.95051 7.90312 8.52994 8.2233 8.92271L8.36141 9.07463C8.68158 9.4674 8.65841 10.0468 8.29235 10.4129C7.90183 10.8034 7.26866 10.8034 6.87814 10.4129C5.70657 9.24131 5.70657 7.34182 6.87814 6.17025L10.4124 2.63602C11.7792 1.26918 13.9953 1.26918 15.3621 2.63602C16.729 4.00285 16.729 6.21893 15.3621 7.58576L14.3028 8.64512C13.9122 9.03564 13.2791 9.03564 12.8885 8.64512C12.498 8.2546 12.498 7.62143 12.8885 7.23091Z"/>
37433    <path d="M5.11038 10.7664L4.04843 11.8284C3.46264 12.4142 3.46264 13.3639 4.04842 13.9497C4.63421 14.5355 5.58396 14.5355 6.16975 13.9497L9.70657 10.4129C10.0726 10.0468 10.0958 9.46741 9.77563 9.07464L9.63752 8.92272C9.31734 8.52995 9.34052 7.95052 9.70657 7.58446C10.0971 7.19394 10.7303 7.19394 11.1208 7.58446C12.2924 8.75604 12.2924 10.6555 11.1208 11.8271L7.58396 15.3639C6.21712 16.7308 4.00105 16.7308 2.63421 15.3639C1.26738 13.9971 1.26738 11.781 2.63421 10.4142L3.69617 9.35223C4.08669 8.96171 4.71986 8.96171 5.11038 9.35223C5.5009 9.74275 5.5009 10.3759 5.11038 10.7664Z"/>
37434  </svg>`,
37435    "quote": `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
37436    <path d="M4.96387 4.23438C6.8769 4.23438 8.42767 5.78522 8.42773 7.69824C8.42773 8.32925 8.25769 8.92015 7.96289 9.42969L7.96387 9.43066L5.11816 14.3584C4.77659 14.95 4.02038 15.153 3.42871 14.8115C2.83701 14.4699 2.63397 13.7128 2.97559 13.1211L4.16113 11.0674C2.63532 10.7052 1.5 9.33485 1.5 7.69824C1.50006 5.78524 3.05086 4.2344 4.96387 4.23438ZM13.0361 4.23438C14.9491 4.23449 16.4999 5.7853 16.5 7.69824C16.5 8.32921 16.3299 8.92017 16.0352 9.42969L16.0361 9.43066L13.1904 14.3584C12.8488 14.9501 12.0917 15.1531 11.5 14.8115C10.9085 14.4698 10.7063 13.7127 11.0479 13.1211L12.2324 11.0674C10.7069 10.7049 9.57227 9.33461 9.57227 7.69824C9.57233 5.78522 11.1231 4.23438 13.0361 4.23438Z"/>
37437  </svg>`,
37438    "code": `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
37439    <path d="M6.29289 3.79295C6.68342 3.40243 7.31643 3.40243 7.70696 3.79295C8.09748 4.18348 8.09748 4.81649 7.70696 5.20702L3.91399 8.99999L7.70696 12.793C8.09748 13.1835 8.09748 13.8165 7.70696 14.207C7.31643 14.5975 6.68342 14.5975 6.29289 14.207L1.79289 9.70702C1.40237 9.31649 1.40237 8.68348 1.79289 8.29295L6.29289 3.79295Z"/>
37440    <path d="M11.707 3.79295C11.3164 3.40243 10.6834 3.40243 10.2929 3.79295C9.90237 4.18348 9.90237 4.81649 10.2929 5.20702L14.0859 8.99999L10.2929 12.793C9.90237 13.1835 9.90237 13.8165 10.2929 14.207C10.6834 14.5975 11.3164 14.5975 11.707 14.207L16.207 9.70702C16.5975 9.31649 16.5975 8.68348 16.207 8.29295L11.707 3.79295Z"/>
37441  </svg>`,
37442    "ul": `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
37443    <path d="M3 12.5C3.82843 12.5 4.5 13.1716 4.5 14C4.5 14.8284 3.82843 15.5 3 15.5C2.17157 15.5 1.5 14.8284 1.5 14C1.5 13.1716 2.17157 12.5 3 12.5ZM15.5 13C16.0523 13 16.5 13.4477 16.5 14C16.5 14.5523 16.0523 15 15.5 15H7C6.44772 15 6 14.5523 6 14C6 13.4477 6.44772 13 7 13H15.5ZM3 7.5C3.82843 7.5 4.5 8.17157 4.5 9C4.5 9.82843 3.82843 10.5 3 10.5C2.17157 10.5 1.5 9.82843 1.5 9C1.5 8.17157 2.17157 7.5 3 7.5ZM15.5 8C16.0523 8 16.5 8.44772 16.5 9C16.5 9.55228 16.0523 10 15.5 10H7C6.44772 10 6 9.55228 6 9C6 8.44772 6.44772 8 7 8H15.5ZM3 2.5C3.82843 2.5 4.5 3.17157 4.5 4C4.5 4.82843 3.82843 5.5 3 5.5C2.17157 5.5 1.5 4.82843 1.5 4C1.5 3.17157 2.17157 2.5 3 2.5ZM15.5 3C16.0523 3 16.5 3.44772 16.5 4C16.5 4.55228 16.0523 5 15.5 5H7C6.44772 5 6 4.55228 6 4C6 3.44772 6.44772 3 7 3H15.5Z"/>
37444  </svg>`,
37445    "ol": `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
37446    <path d="M15.5 13C16.0523 13 16.5 13.4477 16.5 14C16.5 14.5523 16.0523 15 15.5 15H7C6.44772 15 6 14.5523 6 14C6 13.4477 6.44772 13 7 13H15.5ZM15.5 8C16.0523 8 16.5 8.44772 16.5 9C16.5 9.55228 16.0523 10 15.5 10H7C6.44772 10 6 9.55228 6 9C6 8.44772 6.44772 8 7 8H15.5ZM15.5 3C16.0523 3 16.5 3.44772 16.5 4C16.5 4.55228 16.0523 5 15.5 5H7C6.44772 5 6 4.55228 6 4C6 3.44772 6.44772 3 7 3H15.5Z"/>
37447    <path d="M2.98657 16.0967C2.68042 16.0967 2.41187 16.0465 2.18091 15.9463C1.95174 15.846 1.77002 15.7046 1.63574 15.522C1.50146 15.3376 1.42448 15.1227 1.40479 14.8774L1.4021 14.8452H2.34204L2.34741 14.8748C2.35815 14.9589 2.39038 15.035 2.44409 15.103C2.49959 15.1711 2.5721 15.2248 2.66162 15.2642C2.75293 15.3035 2.86035 15.3232 2.98389 15.3232C3.10563 15.3232 3.21037 15.3027 3.2981 15.2615C3.38761 15.2185 3.45654 15.1603 3.50488 15.0869C3.55322 15.0135 3.57739 14.9294 3.57739 14.8345V14.8291C3.57739 14.6715 3.51921 14.5516 3.40283 14.4692C3.28646 14.3869 3.12085 14.3457 2.90601 14.3457H2.48706V13.677H2.90063C3.02775 13.677 3.13607 13.6582 3.22559 13.6206C3.31689 13.583 3.38672 13.5302 3.43506 13.4622C3.48519 13.3941 3.51025 13.3153 3.51025 13.2258V13.2205C3.51025 13.1256 3.48877 13.0441 3.4458 12.9761C3.40462 12.9062 3.34375 12.8534 3.26318 12.8176C3.18441 12.78 3.08952 12.7612 2.97852 12.7612C2.86572 12.7612 2.76636 12.7809 2.68042 12.8203C2.59627 12.8579 2.52913 12.9125 2.479 12.9841C2.43066 13.054 2.40112 13.1363 2.39038 13.2312L2.3877 13.2581H1.49341L1.49609 13.2205C1.514 12.977 1.58561 12.7666 1.71094 12.5894C1.83805 12.4103 2.00903 12.2725 2.22388 12.1758C2.44051 12.0773 2.69206 12.0281 2.97852 12.0281C3.27393 12.0281 3.52995 12.0728 3.74658 12.1624C3.96322 12.2501 4.13062 12.3727 4.24878 12.5303C4.36694 12.6878 4.42603 12.8722 4.42603 13.0835V13.0889C4.42603 13.2518 4.38932 13.3941 4.31592 13.5159C4.2443 13.6358 4.14762 13.7343 4.02588 13.8113C3.90592 13.8883 3.77254 13.942 3.62573 13.9724V13.9912C3.91756 14.0199 4.14941 14.1121 4.32129 14.2678C4.49316 14.4236 4.5791 14.6295 4.5791 14.8855V14.8909C4.5791 15.1344 4.51375 15.3474 4.38306 15.53C4.25236 15.7109 4.06795 15.8505 3.82983 15.949C3.59172 16.0474 3.31063 16.0967 2.98657 16.0967Z"/>
37448    <path d="M1.54443 11V10.342L2.76099 9.20874C2.95076 9.03507 3.09757 8.89274 3.20142 8.78174C3.30705 8.66895 3.37956 8.57316 3.41895 8.49438C3.46012 8.41382 3.48071 8.33415 3.48071 8.25537V8.24463C3.48071 8.14795 3.46012 8.0638 3.41895 7.99219C3.37777 7.92057 3.31779 7.86507 3.23901 7.82568C3.16024 7.7863 3.06714 7.7666 2.95972 7.7666C2.84692 7.7666 2.74756 7.78988 2.66162 7.83643C2.57747 7.88298 2.51123 7.94743 2.46289 8.02979C2.41455 8.11035 2.39038 8.20345 2.39038 8.30908V8.33057L1.48804 8.32788V8.31177C1.48804 8.05396 1.5507 7.82837 1.67603 7.63501C1.80314 7.44165 1.97949 7.29126 2.20508 7.18384C2.43245 7.07463 2.69653 7.02002 2.99731 7.02002C3.28556 7.02002 3.53711 7.06836 3.75195 7.16504C3.96859 7.25993 4.13688 7.39331 4.25684 7.56519C4.37858 7.73706 4.43945 7.93758 4.43945 8.16675V8.18018C4.43945 8.3252 4.40902 8.46932 4.34814 8.61255C4.28727 8.75578 4.18701 8.90885 4.04736 9.07178C3.90771 9.23291 3.71883 9.41642 3.48071 9.62231L2.58374 10.4092L2.85498 9.98486V10.4092L2.58374 10.2319H4.49048V11H1.54443Z"/>
37449    <path d="M2.84155 6V3.01367H2.79053L1.85596 3.64478V2.79614L2.84155 2.12476H3.82715V6H2.84155Z"/>
37450  </svg>`,
37451    "image": `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
37452    <path d="M14 2C15.6569 2 17 3.34315 17 5V13C17 14.6569 15.6569 16 14 16H4C2.34315 16 1 14.6569 1 13V5C1 3.34315 2.34315 2 4 2H14ZM3.06348 13.3496C3.2053 13.7294 3.57078 14 4 14H13.5859L11 11.4141L9.70703 12.707C9.31651 13.0976 8.68349 13.0976 8.29297 12.707C7.90244 12.3165 7.90244 11.6835 8.29297 11.293L8.58594 11L7 9.41406L3.06348 13.3496ZM4 4C3.44772 4 3 4.44772 3 5V10.5859L6.29297 7.29297L6.36914 7.22461C6.76191 6.90427 7.34092 6.92686 7.70703 7.29297L10 9.58594L10.293 9.29297L10.3691 9.22461C10.7619 8.90427 11.3409 8.92686 11.707 9.29297L15 12.5859V5C15 4.44772 14.5523 4 14 4H4ZM12.5 5C13.3284 5 14 5.67157 14 6.5C14 7.32843 13.3284 8 12.5 8C11.6716 8 11 7.32843 11 6.5C11 5.67157 11.6716 5 12.5 5Z"/>
37453  </svg>`,
37454    "attachment": `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
37455    <path d="M13 13.5V6C13 4.067 11.433 2.5 9.5 2.5C7.567 2.5 6 4.067 6 6V13.5C6 14.6046 6.89543 15.5 8 15.5H8.23047C9.20759 15.5 10 14.7076 10 13.7305V7C10 6.72386 9.77614 6.5 9.5 6.5C9.22386 6.5 9 6.72386 9 7V12.5C9 13.0523 8.55228 13.5 8 13.5C7.44772 13.5 7 13.0523 7 12.5V7C7 5.61929 8.11929 4.5 9.5 4.5C10.8807 4.5 12 5.61929 12 7V13.7305C12 15.8122 10.3122 17.5 8.23047 17.5H8C5.79086 17.5 4 15.7091 4 13.5V6C4 2.96243 6.46243 0.5 9.5 0.5C12.5376 0.5 15 2.96243 15 6V13.5C15 14.0523 14.5523 14.5 14 14.5C13.4477 14.5 13 14.0523 13 13.5Z"/>
37456  </svg>`,
37457    "table": `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
37458    <path d="M15 1C16.1046 1 17 1.89543 17 3V15C17 16.1046 16.1046 17 15 17H3C1.89543 17 1 16.1046 1 15V3C1 1.89543 1.89543 1 3 1H15ZM3 15H8V10H3V15ZM10 10V15H15V10H10ZM10 8H15V3H10V8ZM3 8H8V3H3V8Z"/>
37459  </svg>`,
37460    "hr": `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
37461    <path d="M12.75 12C13.1642 12 13.5 12.3358 13.5 12.75V14.25C13.5 14.6642 13.1642 15 12.75 15H5.25C4.83579 15 4.5 14.6642 4.5 14.25V12.75C4.5 12.3358 4.83579 12 5.25 12H12.75ZM15.4863 8C16.0461 8 16.5 8.44771 16.5 9C16.5 9.55229 16.0461 10 15.4863 10H2.51367C1.95392 10 1.5 9.55229 1.5 9C1.5 8.44771 1.95392 8 2.51367 8H15.4863ZM12.75 3C13.1642 3 13.5 3.33579 13.5 3.75V5.25C13.5 5.66421 13.1642 6 12.75 6H5.25C4.83579 6 4.5 5.66421 4.5 5.25V3.75C4.5 3.33579 4.83579 3 5.25 3H12.75Z"/>
37462  </svg>`,
37463    "undo": `<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
37464    <path d="M8.36612 5.36612C8.85427 4.87796 9.64554 4.87796 10.1337 5.36612C10.6218 5.85428 10.6218 6.64557 10.1337 7.13369L7.26748 9.9999H15.2499C18.1494 9.99996 20.4999 12.3504 20.4999 15.2499V19.2499C20.4999 19.9402 19.9402 20.4999 19.2499 20.4999C18.5596 20.4999 18 19.9402 17.9999 19.2499V15.2499C17.9999 13.7312 16.7686 12.5 15.2499 12.4999H7.26748L10.1337 15.3661C10.6218 15.8543 10.6218 16.6456 10.1337 17.1337C9.64557 17.6218 8.85428 17.6218 8.36612 17.1337L3.36612 12.1337C2.87796 11.6455 2.87796 10.8543 3.36612 10.3661L8.36612 5.36612Z"/>
37465  </svg>`,
37466    "redo": `<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
37467    <path d="M15.6338 5.1163C15.1456 4.62814 14.3543 4.62814 13.8662 5.1163C13.3781 5.60446 13.3781 6.39575 13.8662 6.88388L16.7324 9.75009H8.74997C5.85052 9.75014 3.49997 12.1006 3.49997 15.0001V19.0001C3.50002 19.6904 4.05969 20.25 4.74997 20.2501C5.4403 20.2501 5.99992 19.6904 5.99997 19.0001V15.0001C5.99997 13.4813 7.23123 12.2501 8.74997 12.2501H16.7324L13.8662 15.1163C13.3781 15.6045 13.3781 16.3958 13.8662 16.8839C14.3543 17.372 15.1456 17.3719 15.6338 16.8839L20.6338 11.8839C21.1219 11.3957 21.1219 10.6045 20.6338 10.1163L15.6338 5.1163Z" />
37468  </svg>`,
37469    "overflow": `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
37470    <path d="M3 6.75C4.24264 6.75 5.25 7.75736 5.25 9C5.25 10.2426 4.24264 11.25 3 11.25C1.75736 11.25 0.75 10.2426 0.75 9C0.75 7.75736 1.75736 6.75 3 6.75ZM9 6.75C10.2426 6.75 11.25 7.75736 11.25 9C11.25 10.2426 10.2426 11.25 9 11.25C7.75736 11.25 6.75 10.2426 6.75 9C6.75 7.75736 7.75736 6.75 9 6.75ZM15 6.75C16.2426 6.75 17.25 7.75736 17.25 9C17.25 10.2426 16.2426 11.25 15 11.25C13.7574 11.25 12.75 10.2426 12.75 9C12.75 7.75736 13.7574 6.75 15 6.75Z"/>
37471  </svg>`
37472  };
37473  var LexicalToolbarElement = class extends HTMLElement {
37474    static observedAttributes = ["connected"];
37475    #listeners = new ListenerBin();
37476    #refreshToolbarAF = null;
37477    constructor() {
37478      super();
37479      this.internals = this.attachInternals();
37480      this.internals.role = "toolbar";
37481      this.#createEditorPromise();
37482    }
37483    connectedCallback() {
37484      this.requestOverflowRefresh();
37485      this.setAttribute("role", "toolbar");
37486      this.#installResizeObserver();
37487    }
37488    disconnectedCallback() {
37489      this.dispose();
37490    }
37491    dispose() {
37492      this.#listeners.dispose();
37493      cancelAnimationFrame(this.#refreshToolbarAF);
37494      this.editorElement = null;
37495      this.editor = null;
37496      this.selection = null;
37497      this.#refreshToolbarAF = null;
37498      this.#createEditorPromise();
37499    }
37500    attributeChangedCallback(name, oldValue, newValue) {
37501      if (name === "connected" && this.isConnected && oldValue != null && oldValue !== newValue) {
37502        requestAnimationFrame(() => this.#reconnect());
37503      }
37504    }
37505    configure(config) {
37506      if (typeof config === "object" && config !== null) {
37507        for (const [button, value] of Object.entries(config)) {
37508          this.setAttribute(`data-${button}`, value);
37509        }
37510      }
37511    }
37512    setEditor(editorElement) {
37513      this.editorElement = editorElement;
37514      this.editor = editorElement.editor;
37515      this.selection = editorElement.selection;
37516      this.#bindButtons();
37517      this.#bindHotkeys();
37518      this.#resetTabIndexValues();
37519      this.#monitorSelectionChanges();
37520      this.#monitorHistoryChanges();
37521      this.requestOverflowRefresh();
37522      this.#bindFocusListeners();
37523      this.resolveEditorPromise(editorElement);
37524      this.toggleAttribute("connected", true);
37525    }
37526    async getEditorElement() {
37527      return this.editorElement || await this.editorPromise;
37528    }
37529    requestOverflowRefresh() {
37530      if (this.#refreshToolbarAF != null) return;
37531      this.#refreshToolbarAF = requestAnimationFrame(() => {
37532        this.#refreshOverflow();
37533        this.#refreshToolbarAF = null;
37534      });
37535    }
37536    closeDropdowns({ except } = {}) {
37537      this.#dropdowns.forEach((dropdown) => {
37538        if (dropdown !== except) {
37539          dropdown.close({ focusEditor: false });
37540        }
37541      });
37542    }
37543    #reconnect() {
37544      this.disconnectedCallback();
37545      this.connectedCallback();
37546    }
37547    async #createEditorPromise() {
37548      this.editorPromise = new Promise((resolve) => {
37549        this.resolveEditorPromise = resolve;
37550      });
37551      this.editorElement = await this.editorPromise;
37552    }
37553    #installResizeObserver() {
37554      const resizeObserver = new ResizeObserver(() => this.requestOverflowRefresh());
37555      resizeObserver.observe(this);
37556      this.#listeners.track(() => resizeObserver.disconnect());
37557    }
37558    #bindButtons() {
37559      this.#listeners.track(registerEventListener(this, "click", this.#handleButtonClicked));
37560    }
37561    #handleButtonClicked = (event) => {
37562      this.#handleTargetClicked(event, "[data-command]", this.#dispatchButtonCommand.bind(this));
37563    };
37564    #handleTargetClicked(event, selector, callback) {
37565      const button = event.target.closest(selector);
37566      if (button) {
37567        callback(event, button);
37568      }
37569    }
37570    #dispatchButtonCommand(event, { dataset: { command, payload } }) {
37571      const isKeyboard = event instanceof PointerEvent && event.pointerId === -1;
37572      this.editor.update(() => {
37573        this.editor.dispatchCommand(command, payload);
37574      }, { tag: isKeyboard ? SKIP_DOM_SELECTION_TAG2 : void 0 });
37575      if (!isKeyboard) this.editor.focus();
37576    }
37577    #bindHotkeys() {
37578      this.#listeners.track(registerEventListener(this.editorElement, "keydown", this.#handleHotkey));
37579    }
37580    #handleHotkey = (event) => {
37581      const buttons = this.querySelectorAll("[data-hotkey]");
37582      buttons.forEach((button) => {
37583        const hotkeys = button.dataset.hotkey.toLowerCase().split(/\s+/);
37584        if (hotkeys.includes(this.#keyCombinationFor(event))) {
37585          event.preventDefault();
37586          event.stopPropagation();
37587          button.click();
37588        }
37589      });
37590    };
37591    #keyCombinationFor(event) {
37592      const pressedKey = event.key.toLowerCase();
37593      const modifiers = [
37594        event.ctrlKey ? "ctrl" : null,
37595        event.metaKey ? "cmd" : null,
37596        event.altKey ? "alt" : null,
37597        event.shiftKey ? "shift" : null
37598      ].filter(Boolean);
37599      return [...modifiers, pressedKey].join("+");
37600    }
37601    #bindFocusListeners() {
37602      this.#listeners.track(
37603        registerEventListener(this.editorElement, "lexxy:focus", this.#handleEditorFocus),
37604        registerEventListener(this.editorElement, "lexxy:blur", this.#handleEditorBlur),
37605        registerEventListener(this, "keydown", this.#handleKeydown)
37606      );
37607    }
37608    #handleEditorFocus = () => {
37609      const firstVisible = this.#buttons.find(isActiveAndVisible);
37610      if (firstVisible) firstVisible.tabIndex = 0;
37611    };
37612    #handleEditorBlur = () => {
37613      this.#resetTabIndexValues();
37614    };
37615    #handleKeydown = (event) => {
37616      handleRollingTabIndex(this.#buttons, event);
37617    };
37618    #resetTabIndexValues() {
37619      this.#buttons.forEach((button) => {
37620        button.tabIndex = -1;
37621      });
37622    }
37623    #monitorSelectionChanges() {
37624      this.#listeners.track(this.editor.registerUpdateListener(({ editorState }) => {
37625        editorState.read(() => {
37626          this.#updateButtonStates();
37627          this.closeDropdowns();
37628        });
37629      }));
37630    }
37631    #monitorHistoryChanges() {
37632      this.#listeners.track(
37633        this.editor.registerCommand(CAN_UNDO_COMMAND2, (enabled) => {
37634          this.#setButtonDisabled("undo", !enabled);
37635        }, COMMAND_PRIORITY_LOW2),
37636        this.editor.registerCommand(CAN_REDO_COMMAND2, (enabled) => {
37637          this.#setButtonDisabled("redo", !enabled);
37638        }, COMMAND_PRIORITY_LOW2)
37639      );
37640    }
37641    #updateButtonStates() {
37642      const selection = $getSelection2();
37643      if (!$isRangeSelection2(selection)) return;
37644      const anchorNode = selection.anchor.getNode();
37645      if (!anchorNode.getParent()) {
37646        return;
37647      }
37648      const {
37649        isBold: isBold2,
37650        isItalic: isItalic2,
37651        isStrikethrough,
37652        isUnderline: isUnderline2,
37653        isHighlight,
37654        isInLink,
37655        isInQuote,
37656        isInHeading,
37657        headingTag,
37658        isInCode,
37659        isInList,
37660        listType,
37661        isInTable
37662      } = this.selection.getFormat();
37663      this.#setButtonPressed("bold", isBold2);
37664      this.#setButtonPressed("italic", isItalic2);
37665      this.#setButtonPressed("strikethrough", isStrikethrough);
37666      this.#setButtonPressed("underline", isUnderline2);
37667      this.#setButtonPressed("format", isInHeading);
37668      this.#setButtonPressed("paragraph", !isInHeading);
37669      this.querySelector("lexxy-heading-dropdown")?.updateActiveHeading(headingTag);
37670      this.#setButtonPressed("lists", isInList);
37671      this.#setButtonPressed("unordered-list", isInList && listType === "bullet");
37672      this.#setButtonPressed("ordered-list", isInList && listType === "number");
37673      this.#setButtonPressed("highlight", isHighlight);
37674      this.#setButtonPressed("link", isInLink);
37675      this.#setButtonPressed("quote", isInQuote);
37676      this.#setButtonPressed("code", isInCode);
37677      this.#setButtonPressed("table", isInTable);
37678    }
37679    #setButtonPressed(name, isPressed) {
37680      const button = this.querySelector(`[name="${name}"]`);
37681      if (button) {
37682        const next = isPressed.toString();
37683        if (button.getAttribute("aria-pressed") !== next) {
37684          button.setAttribute("aria-pressed", next);
37685        }
37686      }
37687    }
37688    #setButtonDisabled(name, isDisabled) {
37689      const button = this.querySelector(`[name="${name}"]`);
37690      if (button) {
37691        if (button.disabled !== isDisabled) {
37692          button.disabled = isDisabled;
37693        }
37694        const next = isDisabled.toString();
37695        if (button.getAttribute("aria-disabled") !== next) {
37696          button.setAttribute("aria-disabled", next);
37697        }
37698      }
37699    }
37700    #refreshOverflow() {
37701      this.#hideOverflowMenuButton();
37702      this.#resetToolbarOverflow();
37703      this.#reindexToolbarItems();
37704      this.#compactMenu();
37705      const isOverflowing = this.#overflowMenuDropdown.children.length > 0;
37706      this.toggleAttribute("overflowing", isOverflowing);
37707      this.#setOverflowMenuNonce();
37708      this.#showOverflowMenuButton(isOverflowing);
37709    }
37710    #resetToolbarOverflow() {
37711      const items = Array.from(this.#overflowMenuDropdown.children);
37712      items.sort((a2, b3) => this.#itemPosition(b3) - this.#itemPosition(a2));
37713      for (const item of items) {
37714        const nextItem = this.querySelector(`[data-position="${this.#itemPosition(item) + 1}"]`) ?? this.#overflowMenuButton;
37715        item.removeAttribute("role");
37716        this.insertBefore(item, nextItem);
37717      }
37718    }
37719    #showOverflowMenuButton(show = true) {
37720      this.#overflowMenuDropdown.toggleAttribute("disabled", !show);
37721      this.#overflowMenuButton.style.display = show ? "block" : "none";
37722    }
37723    #hideOverflowMenuButton() {
37724      this.#showOverflowMenuButton(false);
37725    }
37726    #itemPosition(item) {
37727      return parseInt(item.dataset.position ?? "999");
37728    }
37729    #reindexToolbarItems() {
37730      this.#toolbarItems.forEach((item, index) => {
37731        item.dataset.position = index;
37732      });
37733    }
37734    #compactMenu() {
37735      const overflowWidth = this.#getOverflowWidth();
37736      if (overflowWidth > 0) {
37737        this.#showOverflowMenuButton();
37738        const gap = this.#getToolbarGap();
37739        const spaceForOverflow = gap + this.#overflowMenuButton.offsetWidth;
37740        this.#reclaimWidth(overflowWidth + spaceForOverflow, { gap });
37741      }
37742    }
37743    #getOverflowWidth() {
37744      return this.scrollWidth - this.clientWidth;
37745    }
37746    #reclaimWidth(overflowWidth, { gap }) {
37747      const buttons = this.#overflowableButtons;
37748      const overflowButtons = [];
37749      let recoveredWidth = 0;
37750      while (recoveredWidth < overflowWidth && buttons.length) {
37751        const button = buttons.pop();
37752        overflowButtons.push(button);
37753        button.role = "menuitem";
37754        recoveredWidth += button.offsetWidth + gap;
37755      }
37756      this.#overflowMenuDropdown.append(...overflowButtons.reverse());
37757    }
37758    #setOverflowMenuNonce() {
37759      this.#overflowMenuButton.setAttribute("nonce", getNonce());
37760    }
37761    #getToolbarGap() {
37762      return parseFloat(window.getComputedStyle(this).columnGap) || 0;
37763    }
37764    get #dropdowns() {
37765      return this.querySelectorAll(":scope .lexxy-editor__toolbar-dropdown");
37766    }
37767    get #overflowMenuButton() {
37768      return this.querySelector(".lexxy-editor__toolbar-overflow");
37769    }
37770    get #overflowMenuDropdown() {
37771      return this.#overflowMenuButton?.querySelector(":scope > [data-dropdown-panel]");
37772    }
37773    get #overflowableButtons() {
37774      return Array.from(this.querySelectorAll(":scope > button:not([data-prevent-overflow])"));
37775    }
37776    get #buttons() {
37777      return Array.from(this.querySelectorAll(":scope button"));
37778    }
37779    get #toolbarItems() {
37780      return Array.from(this.querySelectorAll(":scope > *:not(.lexxy-editor__toolbar-overflow)"));
37781    }
37782    static get defaultTemplate() {
37783      const linkInputId = generateDomId("lexxy-link-url");
37784      return `
37785      <button class="lexxy-editor__toolbar-button" type="button" name="image" data-command="uploadImage" data-prevent-overflow="true" title="Add images and video">
37786        ${ToolbarIcons.image}
37787      </button>
37788
37789      <button class="lexxy-editor__toolbar-button lexxy-editor__toolbar-group-end" type="button" name="file" data-command="uploadFile" title="Upload files">
37790        ${ToolbarIcons.attachment}
37791      </button>
37792
37793      <button class="lexxy-editor__toolbar-button" type="button" name="bold" data-command="bold" title="Bold">
37794        ${ToolbarIcons.bold}
37795      </button>
37796
37797      <button class="lexxy-editor__toolbar-button" type="button" name="italic" data-command="italic" title="Italic">
37798      ${ToolbarIcons.italic}
37799      </button>
37800
37801      <button class="lexxy-editor__toolbar-button" type="button" name="strikethrough" data-command="strikethrough" title="Strikethrough">
37802        ${ToolbarIcons.strikethrough}
37803      </button>
37804
37805      <button class="lexxy-editor__toolbar-button lexxy-editor__toolbar-group-end" type="button" name="underline" data-command="underline" title="Underline">
37806        ${ToolbarIcons.underline}
37807      </button>
37808
37809      <lexxy-toolbar-dropdown class="lexxy-editor__toolbar-dropdown">
37810        <button data-dropdown-trigger class="lexxy-editor__toolbar-button lexxy-editor__toolbar-button--chevron" type="button" name="format" title="Text formatting" aria-haspopup="menu" aria-expanded="false">
37811          ${ToolbarIcons.heading}
37812        </button>
37813        <div data-dropdown-panel role="menu" class="lexxy-editor__toolbar-dropdown-list" hidden>
37814          <button type="button" name="paragraph" data-command="setFormatParagraph" title="Paragraph" role="menuitem">
37815            ${ToolbarIcons.paragraph} <span>Normal</span>
37816          </button>
37817          <lexxy-heading-dropdown>
37818            <div class="lexxy-heading-options"></div>
37819          </lexxy-heading-dropdown>
37820          <div class="lexxy-editor__toolbar-separator" role="separator"></div>
37821          <button type="button" name="clear-formatting" data-command="clearFormatting" title="Clear formatting" role="menuitem">
37822            ${ToolbarIcons.clearFormatting} <span>Clear formatting</span>
37823          </button>
37824        </div>
37825      </lexxy-toolbar-dropdown>
37826
37827      <lexxy-highlight-dropdown class="lexxy-editor__toolbar-dropdown lexxy-editor__toolbar-dropdown--highlight">
37828        <button data-dropdown-trigger class="lexxy-editor__toolbar-button lexxy-editor__toolbar-button--chevron" type="button" name="highlight" title="Color highlight" aria-haspopup="menu" aria-expanded="false">
37829          ${ToolbarIcons.highlight}
37830        </button>
37831        <div data-dropdown-panel role="menu" hidden>
37832          <div class="lexxy-highlight-colors"></div>
37833          <button data-command="removeHighlight" type="button" class="lexxy-editor__toolbar-button lexxy-editor__toolbar-dropdown-reset" role="menuitem">Remove all coloring</button>
37834        </div>
37835      </lexxy-highlight-dropdown>
37836
37837      <lexxy-link-dropdown class="lexxy-editor__toolbar-dropdown lexxy-editor__toolbar-dropdown--link">
37838        <button data-dropdown-trigger class="lexxy-editor__toolbar-button lexxy-editor__toolbar-group-end" type="button" name="link" title="Link" data-hotkey="cmd+k ctrl+k" aria-haspopup="dialog" aria-expanded="false">
37839          ${ToolbarIcons.link}
37840        </button>
37841        <div data-dropdown-panel role="dialog" aria-label="Link" hidden>
37842          <input type="url" placeholder="Enter a URL\u2026" class="input" id="${linkInputId}">
37843          <div class="lexxy-editor__toolbar-dropdown-actions">
37844            <button type="button" class="lexxy-editor__toolbar-button" value="link">Link</button>
37845            <button type="button" class="lexxy-editor__toolbar-button" value="unlink">Unlink</button>
37846          </div>
37847        </div>
37848      </lexxy-link-dropdown>
37849
37850      <button class="lexxy-editor__toolbar-button" type="button" name="quote" data-command="insertQuoteBlock" title="Quote">
37851        ${ToolbarIcons.quote}
37852      </button>
37853
37854      <button class="lexxy-editor__toolbar-button" type="button" name="code" data-command="insertCodeBlock" title="Code">
37855        ${ToolbarIcons.code}
37856      </button>
37857
37858      <button class="lexxy-editor__toolbar-button" type="button" name="unordered-list" data-command="insertUnorderedList" title="Bullet list">
37859        ${ToolbarIcons.ul}
37860      </button>
37861      <button class="lexxy-editor__toolbar-button lexxy-editor__toolbar-group-end" type="button" name="ordered-list" data-command="insertOrderedList" title="Numbered list">
37862        ${ToolbarIcons.ol}
37863      </button>
37864
37865      <button class="lexxy-editor__toolbar-button" type="button" name="table" data-command="insertTable" title="Insert a table">
37866        ${ToolbarIcons.table}
37867      </button>
37868
37869      <button class="lexxy-editor__toolbar-button" type="button" name="divider" data-command="insertHorizontalDivider" title="Insert a divider">
37870        ${ToolbarIcons.hr}
37871      </button>
37872
37873      <button class="lexxy-editor__toolbar-button lexxy-editor__toolbar-button--push-right" type="button" name="undo" data-command="undo" title="Undo" disabled aria-disabled="true">
37874        ${ToolbarIcons.undo}
37875      </button>
37876
37877      <button class="lexxy-editor__toolbar-button" type="button" name="redo" data-command="redo" title="Redo" disabled aria-disabled="true">
37878        ${ToolbarIcons.redo}
37879      </button>
37880
37881      <lexxy-toolbar-dropdown class="lexxy-editor__toolbar-dropdown lexxy-editor__toolbar-button--push-right lexxy-editor__toolbar-overflow">
37882        <button data-dropdown-trigger class="lexxy-editor__toolbar-button" type="button" aria-haspopup="menu" aria-expanded="false" aria-label="Show more toolbar buttons">
37883          ${ToolbarIcons.overflow}
37884        </button>
37885        <div data-dropdown-panel role="menu" class="lexxy-editor__toolbar-overflow-menu" aria-label="More toolbar buttons" hidden></div>
37886      </lexxy-toolbar-dropdown>
37887    `;
37888    }
37889  };
37890  function debounce(fn, wait) {
37891    let timeout;
37892    return (...args) => {
37893      clearTimeout(timeout);
37894      timeout = setTimeout(() => fn(...args), wait);
37895    };
37896  }
37897  function debounceAsync(fn, wait) {
37898    let timeout;
37899    return (...args) => {
37900      clearTimeout(timeout);
37901      return new Promise((resolve, reject) => {
37902        timeout = setTimeout(async () => {
37903          try {
37904            const result = await fn(...args);
37905            resolve(result);
37906          } catch (err) {
37907            reject(err);
37908          }
37909        }, wait);
37910      });
37911    };
37912  }
37913  function delay(ms) {
37914    return new Promise((resolve) => setTimeout(resolve, ms));
37915  }
37916  function nextFrame() {
37917    return new Promise(requestAnimationFrame);
37918  }
37919  var ToolbarDropdown = class extends HTMLElement {
37920    #listeners = new ListenerBin();
37921    connectedCallback() {
37922      this.#onToolbarEditor(() => {
37923        this.#registerListeners();
37924        this.editorReady();
37925      });
37926    }
37927    disconnectedCallback() {
37928      this.#listeners.dispose();
37929    }
37930    editorReady() {
37931    }
37932    onOpen() {
37933    }
37934    onClose() {
37935    }
37936    get trigger() {
37937      return this.querySelector(":scope > [data-dropdown-trigger]");
37938    }
37939    get panel() {
37940      return this.querySelector(":scope > [data-dropdown-panel]");
37941    }
37942    get toolbar() {
37943      return this.closest("lexxy-toolbar");
37944    }
37945    get editorElement() {
37946      return this.toolbar?.editorElement;
37947    }
37948    get editor() {
37949      return this.toolbar?.editor;
37950    }
37951    get isOpen() {
37952      return this.panel.hidden === false;
37953    }
37954    get isClosed() {
37955      return !this.isOpen;
37956    }
37957    track(...listeners) {
37958      this.#listeners.track(...listeners);
37959    }
37960    open() {
37961      if (this.isOpen) return;
37962      this.trigger.setAttribute("aria-expanded", "true");
37963      this.panel.hidden = false;
37964      this.onOpen();
37965      this.#focusFirstInteractive();
37966    }
37967    close({ focusEditor = true } = {}) {
37968      if (focusEditor) this.editor?.focus();
37969      if (this.isClosed) return;
37970      this.trigger.setAttribute("aria-expanded", "false");
37971      this.panel.hidden = true;
37972      this.onClose();
37973    }
37974    #registerListeners() {
37975      this.#listeners.track(
37976        registerEventListener(this, "keydown", this.#handleKeyDown),
37977        registerEventListener(this.trigger, "click", this.#handleTriggerClick)
37978      );
37979    }
37980    #handleTriggerClick = () => {
37981      if (this.isOpen) {
37982        this.close({ focusEditor: false });
37983      } else {
37984        this.toolbar?.closeDropdowns({ except: this });
37985        this.open();
37986      }
37987    };
37988    async #onToolbarEditor(callback) {
37989      if (!this.toolbar) return;
37990      await this.toolbar.getEditorElement();
37991      if (this.isConnected && this.toolbar) callback();
37992    }
37993    #handleKeyDown = (event) => {
37994      if (event.key === "Escape") {
37995        event.stopPropagation();
37996        this.close();
37997      }
37998    };
37999    async #focusFirstInteractive() {
38000      this.#interactiveElements[0]?.focus();
38001      await this.#resetTabIndexValues();
38002    }
38003    async #resetTabIndexValues() {
38004      await nextFrame();
38005      this.#buttons.forEach((element, index) => {
38006        element.setAttribute("tabindex", index === 0 ? 0 : "-1");
38007      });
38008    }
38009    get #interactiveElements() {
38010      return Array.from(this.panel.querySelectorAll("button, input"));
38011    }
38012    get #buttons() {
38013      return Array.from(this.panel.querySelectorAll("button"));
38014    }
38015  };
38016  var HEADING_BUTTON_SELECTOR = "button.lexxy-heading-button";
38017  var HEADING_PRESETS = [
38018    { label: "Large Heading", name: "heading-large", command: "setFormatHeadingLarge" },
38019    { label: "Medium Heading", name: "heading-medium", command: "setFormatHeadingMedium" },
38020    { label: "Small Heading", name: "heading-small", command: "setFormatHeadingSmall" }
38021  ];
38022  var HeadingDropdown = class _HeadingDropdown extends HTMLElement {
38023    static labelFor(tag, index) {
38024      if (index < HEADING_PRESETS.length) {
38025        return HEADING_PRESETS[index].label;
38026      } else {
38027        const level = tag.match(/^h(\d+)$/)?.[1];
38028        if (level) {
38029          return `Heading ${level}`;
38030        } else {
38031          return tag.toUpperCase();
38032        }
38033      }
38034    }
38035    static nameFor(tag, index) {
38036      if (index < HEADING_PRESETS.length) {
38037        return HEADING_PRESETS[index].name;
38038      } else {
38039        const level = tag.match(/^h(\d+)$/)?.[1];
38040        if (level) {
38041          return `heading-${level}`;
38042        } else {
38043          return `heading-${tag}`;
38044        }
38045      }
38046    }
38047    static commandFor(index) {
38048      if (index < HEADING_PRESETS.length) {
38049        return HEADING_PRESETS[index].command;
38050      } else {
38051        return "applyHeadingFormat";
38052      }
38053    }
38054    #listeners = new ListenerBin();
38055    connectedCallback() {
38056      this.style.display = "contents";
38057      this.#onToolbarEditor(() => {
38058        this.#buttonContainer.style.display = "contents";
38059        this.#setUpButtons();
38060        this.#registerButtonHandlers();
38061        this.#syncActiveHeading();
38062      });
38063    }
38064    disconnectedCallback() {
38065      this.#listeners.dispose();
38066    }
38067    updateActiveHeading(tag) {
38068      this.#headingButtons.forEach((button) => {
38069        const next = (button.dataset.heading === tag).toString();
38070        if (button.getAttribute("aria-pressed") !== next) {
38071          button.setAttribute("aria-pressed", next);
38072        }
38073      });
38074    }
38075    get #toolbar() {
38076      return this.closest("lexxy-toolbar");
38077    }
38078    get #editorElement() {
38079      return this.#toolbar?.editorElement;
38080    }
38081    get #editor() {
38082      return this.#toolbar?.editor;
38083    }
38084    async #onToolbarEditor(callback) {
38085      const toolbar = this.#toolbar;
38086      if (!toolbar) return;
38087      await toolbar.getEditorElement();
38088      if (this.isConnected && this.#toolbar) callback();
38089    }
38090    #setUpButtons() {
38091      this.#buttonContainer.innerHTML = "";
38092      this.#configuredHeadings.forEach((tag, index) => {
38093        this.#buttonContainer.appendChild(this.#createButton(tag, index));
38094      });
38095    }
38096    #createButton(tag, index) {
38097      const label = _HeadingDropdown.labelFor(tag, index);
38098      const name = _HeadingDropdown.nameFor(tag, index);
38099      const icon = ToolbarIcons[tag] || "";
38100      const button = document.createElement("button");
38101      button.type = "button";
38102      button.dataset.heading = tag;
38103      button.dataset.command = _HeadingDropdown.commandFor(index);
38104      button.classList.add("lexxy-heading-button");
38105      button.name = name;
38106      button.title = label;
38107      button.setAttribute("role", "menuitem");
38108      button.innerHTML = `${icon} <span>${label}</span>`;
38109      return button;
38110    }
38111    #registerButtonHandlers() {
38112      this.#headingButtons.forEach((button) => {
38113        this.#listeners.track(registerEventListener(button, "click", (event) => {
38114          if (!this.#editor) return;
38115          event.preventDefault();
38116          this.#editor.dispatchCommand(button.dataset.command, button.dataset.heading);
38117          this.#editor.focus();
38118        }));
38119      });
38120    }
38121    #syncActiveHeading() {
38122      const { headingTag } = this.#editor.read(() => this.#editorElement.selection.getFormat());
38123      this.updateActiveHeading(headingTag ?? null);
38124    }
38125    get #configuredHeadings() {
38126      return this.#editorElement.config.get("headings");
38127    }
38128    get #buttonContainer() {
38129      return this.querySelector(".lexxy-heading-options");
38130    }
38131    get #headingButtons() {
38132      return Array.from(this.querySelectorAll(HEADING_BUTTON_SELECTOR));
38133    }
38134  };
38135  var APPLY_HIGHLIGHT_SELECTOR = "button.lexxy-highlight-button";
38136  var REMOVE_HIGHLIGHT_SELECTOR = "[data-command='removeHighlight']";
38137  var NO_STYLE = Symbol("no_style");
38138  var HighlightDropdown = class extends ToolbarDropdown {
38139    editorReady() {
38140      this.#setUpButtons();
38141      this.#registerButtonHandlers();
38142    }
38143    onOpen() {
38144      this.editor.getEditorState().read(() => {
38145        this.#updateColorButtonStates($getSelection2());
38146      });
38147    }
38148    #registerButtonHandlers() {
38149      this.#colorButtons.forEach((button) => {
38150        this.track(registerEventListener(button, "click", this.#handleColorButtonClick));
38151      });
38152    }
38153    #setUpButtons() {
38154      this.#buttonContainer.innerHTML = "";
38155      const colorGroups = this.editorElement.config.get("highlight.buttons");
38156      this.#populateButtonGroup("color", colorGroups.color);
38157      this.#populateButtonGroup("background-color", colorGroups["background-color"]);
38158      const maxNumberOfColors = Math.max(colorGroups.color.length, colorGroups["background-color"].length);
38159      this.panel.style.setProperty("--max-colors", maxNumberOfColors);
38160    }
38161    #populateButtonGroup(attribute, values) {
38162      values.forEach((value, index) => {
38163        this.#buttonContainer.appendChild(this.#createButton(attribute, value, index));
38164      });
38165    }
38166    #createButton(attribute, value, index) {
38167      return createElement("button", {
38168        type: "button",
38169        dataset: { value, style: attribute },
38170        style: `${attribute}: ${value}`,
38171        class: "lexxy-editor__toolbar-button lexxy-highlight-button",
38172        name: `${attribute}-${index}`,
38173        role: "menuitem"
38174      });
38175    }
38176    #handleColorButtonClick = (event) => {
38177      event.preventDefault();
38178      const button = event.target.closest(APPLY_HIGHLIGHT_SELECTOR);
38179      if (!button) return;
38180      const { style, value } = button.dataset;
38181      this.editor.dispatchCommand("toggleHighlight", { [style]: value });
38182      this.close();
38183    };
38184    #updateColorButtonStates(selection) {
38185      if (!$isRangeSelection2(selection)) {
38186        return;
38187      }
38188      const textColor = $getSelectionStyleValueForProperty2(selection, "color", NO_STYLE);
38189      const backgroundColor = $getSelectionStyleValueForProperty2(selection, "background-color", NO_STYLE);
38190      this.#colorButtons.forEach((button) => {
38191        const matchesSelection = button.dataset.value === textColor || button.dataset.value === backgroundColor;
38192        const next = matchesSelection.toString();
38193        if (button.getAttribute("aria-pressed") !== next) {
38194          button.setAttribute("aria-pressed", next);
38195        }
38196      });
38197      const hasHighlight = textColor !== NO_STYLE || backgroundColor !== NO_STYLE;
38198      this.panel.querySelector(REMOVE_HIGHLIGHT_SELECTOR).disabled = !hasHighlight;
38199    }
38200    get #buttonContainer() {
38201      return this.panel.querySelector(".lexxy-highlight-colors");
38202    }
38203    get #colorButtons() {
38204      return Array.from(this.panel.querySelectorAll(APPLY_HIGHLIGHT_SELECTOR));
38205    }
38206  };
38207  var LinkDropdown = class extends ToolbarDropdown {
38208    editorReady() {
38209      this.input = this.panel.querySelector("input");
38210      this.track(
38211        registerEventListener(this.input, "keydown", this.#handleEnter),
38212        registerEventListener(this.linkButton, "click", this.#handleLink),
38213        registerEventListener(this.unlinkButton, "click", this.#handleUnlink)
38214      );
38215    }
38216    onOpen() {
38217      this.input.value = this.#selectedLinkUrl;
38218      this.input.required = true;
38219    }
38220    onClose() {
38221      this.input.required = false;
38222    }
38223    get linkButton() {
38224      return this.panel.querySelector("[value='link']");
38225    }
38226    get unlinkButton() {
38227      return this.panel.querySelector("[value='unlink']");
38228    }
38229    #handleEnter = (event) => {
38230      if (event.key === "Enter") {
38231        event.preventDefault();
38232        event.stopPropagation();
38233        this.#handleLink(event);
38234      }
38235    };
38236    #handleLink = () => {
38237      if (!this.input.checkValidity()) {
38238        this.input.reportValidity();
38239        return;
38240      }
38241      this.editor.dispatchCommand("link", this.input.value);
38242      this.close();
38243    };
38244    #handleUnlink = () => {
38245      this.editor.dispatchCommand("unlink");
38246      this.close();
38247    };
38248    get #selectedLinkUrl() {
38249      return this.editor.getEditorState().read(() => {
38250        const linkNode = this.editorElement.selection.nearestNodeOfType(LinkNode2);
38251        return linkNode?.getURL() ?? "";
38252      });
38253    }
38254  };
38255  function deepMerge(target, source) {
38256    const result = { ...target, ...source };
38257    for (const [key, value] of Object.entries(source)) {
38258      if (arePlainHashes(target[key], value)) {
38259        result[key] = deepMerge(target[key], value);
38260      }
38261    }
38262    return result;
38263  }
38264  function arePlainHashes(...values) {
38265    return values.every((value) => value && value.constructor == Object);
38266  }
38267  var Configuration = class {
38268    #tree = {};
38269    constructor(...configs) {
38270      this.merge(...configs);
38271    }
38272    merge(...configs) {
38273      return this.#tree = configs.reduce(deepMerge, this.#tree);
38274    }
38275    get(path) {
38276      const keys = path.split(".");
38277      return keys.reduce((node, key) => node[key], this.#tree);
38278    }
38279  };
38280  function range(from, to) {
38281    return [...Array(1 + to - from).keys()].map((i2) => i2 + from);
38282  }
38283  var global2 = new Configuration({
38284    attachmentTagName: "action-text-attachment",
38285    attachmentContentTypeNamespace: "actiontext",
38286    authenticatedUploads: false,
38287    extensions: []
38288  });
38289  var presets = new Configuration({
38290    default: {
38291      attachments: true,
38292      markdown: true,
38293      multiLine: true,
38294      permittedAttachmentTypes: null,
38295      richText: true,
38296      toolbar: {
38297        upload: "both"
38298      },
38299      headings: ["h2", "h3", "h4"],
38300      highlight: {
38301        buttons: {
38302          color: range(1, 9).map((n2) => `var(--highlight-${n2})`),
38303          "background-color": range(1, 9).map((n2) => `var(--highlight-bg-${n2})`)
38304        },
38305        permit: {
38306          color: [],
38307          "background-color": []
38308        }
38309      }
38310    }
38311  });
38312  var Lexxy = {
38313    global: global2,
38314    presets,
38315    configure({ global: newGlobal, ...newPresets }) {
38316      if (newGlobal) {
38317        global2.merge(newGlobal);
38318      }
38319      presets.merge(newPresets);
38320    }
38321  };
38322  function setSanitizerConfig(allowedTags) {
38323    purify.clearConfig();
38324    purify.setConfig(buildConfig(allowedTags));
38325  }
38326  function sanitize(html2) {
38327    return purify.sanitize(html2);
38328  }
38329  function bytesToHumanSize(bytes) {
38330    if (bytes === 0) return "0 B";
38331    const sizes = ["B", "KB", "MB", "GB", "TB", "PB"];
38332    const i2 = Math.floor(Math.log(bytes) / Math.log(1024));
38333    const value = bytes / Math.pow(1024, i2);
38334    return `${value.toFixed(2)} ${sizes[i2]}`;
38335  }
38336  function extractFileName(string) {
38337    return string.split("/").pop();
38338  }
38339  function parseAttachmentContent(content) {
38340    try {
38341      return JSON.parse(content);
38342    } catch {
38343      return content;
38344    }
38345  }
38346  function mimeTypeToExtension(mimeType) {
38347    if (!mimeType) return null;
38348    const extension = mimeType.split("/")[1];
38349    return extension;
38350  }
38351  var CustomActionTextAttachmentNode = class _CustomActionTextAttachmentNode extends DecoratorNode2 {
38352    static getType() {
38353      return "custom_action_text_attachment";
38354    }
38355    static clone(node) {
38356      return new _CustomActionTextAttachmentNode({ ...node }, node.__key);
38357    }
38358    static importJSON(serializedNode) {
38359      return new _CustomActionTextAttachmentNode({ ...serializedNode });
38360    }
38361    static importDOM() {
38362      return {
38363        [this.TAG_NAME]: (element) => {
38364          const content = element.getAttribute("content");
38365          if (!content) {
38366            return null;
38367          }
38368          if (isLexxyImageLayoutString(content)) {
38369            return null;
38370          }
38371          return {
38372            conversion: (attachment) => {
38373              const nodes = [];
38374              const previousSibling = attachment.previousSibling;
38375              if (previousSibling && previousSibling.nodeType === Node.TEXT_NODE && /\s$/.test(previousSibling.textContent)) {
38376                nodes.push($createTextNode2(" "));
38377              }
38378              const innerHtml = parseAttachmentContent(attachment.getAttribute("content"));
38379              nodes.push(new _CustomActionTextAttachmentNode({
38380                sgid: attachment.getAttribute("sgid"),
38381                innerHtml,
38382                plainText: attachment.textContent.trim() || extractPlainTextFromHtml(innerHtml),
38383                contentType: attachment.getAttribute("content-type")
38384              }));
38385              const nextSibling = attachment.nextSibling;
38386              if (nextSibling && nextSibling.nodeType === Node.TEXT_NODE && /^\s/.test(nextSibling.textContent)) {
38387                nodes.push($createTextNode2(" "));
38388              }
38389              return { node: nodes };
38390            },
38391            priority: 2
38392          };
38393        }
38394      };
38395    }
38396    static get TAG_NAME() {
38397      return Lexxy.global.get("attachmentTagName");
38398    }
38399    constructor({ tagName, sgid, contentType, innerHtml, plainText }, key) {
38400      super(key);
38401      const contentTypeNamespace = Lexxy.global.get("attachmentContentTypeNamespace");
38402      this.tagName = tagName || _CustomActionTextAttachmentNode.TAG_NAME;
38403      this.sgid = sgid;
38404      this.contentType = contentType || `application/vnd.${contentTypeNamespace}.unknown`;
38405      this.innerHtml = innerHtml;
38406      this.plainText = plainText ?? extractPlainTextFromHtml(innerHtml);
38407    }
38408    createDOM() {
38409      const figure = createElement(this.tagName, { "content-type": this.contentType, "data-lexxy-decorator": true, draggable: true });
38410      figure.dataset.lexicalNodeKey = this.__key;
38411      figure.insertAdjacentHTML("beforeend", sanitize(this.innerHtml));
38412      const deleteButton = createElement("lexxy-node-delete-button");
38413      figure.appendChild(deleteButton);
38414      return figure;
38415    }
38416    updateDOM() {
38417      return false;
38418    }
38419    getTextContent() {
38420      return "\uFEFF";
38421    }
38422    getReadableTextContent() {
38423      return this.plainText || `[${this.contentType}]`;
38424    }
38425    isInline() {
38426      return true;
38427    }
38428    exportDOM() {
38429      const attachment = createElement(this.tagName, {
38430        sgid: this.sgid,
38431        content: this.innerHtml,
38432        "content-type": this.contentType
38433      });
38434      return { element: attachment };
38435    }
38436    exportJSON() {
38437      return {
38438        type: "custom_action_text_attachment",
38439        version: 1,
38440        tagName: this.tagName,
38441        sgid: this.sgid,
38442        contentType: this.contentType,
38443        innerHtml: this.innerHtml,
38444        plainText: this.plainText
38445      };
38446    }
38447    decorate() {
38448      return null;
38449    }
38450  };
38451  function $isCustomActionTextAttachmentNode(node) {
38452    return node instanceof CustomActionTextAttachmentNode;
38453  }
38454  function dasherize(value) {
38455    return value.replace(/([A-Z])/g, (_3, char) => `-${char.toLowerCase()}`);
38456  }
38457  function isAutolinkableURL(string) {
38458    return /^(?:[a-z0-9]+:\/\/|www\.)[^\s]+$/i.test(string.trim());
38459  }
38460  function normalizeFilteredText(string) {
38461    return string.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "");
38462  }
38463  function filterMatchPosition(text2, potentialMatch) {
38464    const normalizedText = normalizeFilteredText(text2);
38465    const normalizedMatch = normalizeFilteredText(potentialMatch);
38466    if (!normalizedMatch) return 0;
38467    const match = normalizedText.match(new RegExp(`(?<![\\p{L}\\p{N}])${escapeForRegExp(normalizedMatch)}`, "u"));
38468    return match ? match.index : -1;
38469  }
38470  function upcaseFirst(string) {
38471    return string.charAt(0).toUpperCase() + string.slice(1);
38472  }
38473  function escapeForRegExp(string) {
38474    return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
38475  }
38476  function parseBoolean(value) {
38477    if (typeof value === "string") return value === "true";
38478    return Boolean(value);
38479  }
38480  var LexxyExtension = class {
38481    #editorElement;
38482    constructor(editorElement) {
38483      this.#editorElement = editorElement;
38484    }
38485    get editorElement() {
38486      return this.#editorElement;
38487    }
38488    get editorConfig() {
38489      return this.#editorElement.config;
38490    }
38491    // optional: defaults to true
38492    get enabled() {
38493      return true;
38494    }
38495    get lexicalExtension() {
38496      return null;
38497    }
38498    get allowedElements() {
38499      return [];
38500    }
38501    defineExtension(...args) {
38502      return defineExtension2(...args);
38503    }
38504    initializeToolbar(_lexxyToolbar) {
38505    }
38506    setEditorValidity(flags, message) {
38507      this.editorElement.setElementValidity(this, flags, message);
38508    }
38509    dispose() {
38510    }
38511  };
38512  function $containsRangeSelection(node, selection = $getSelection2()) {
38513    if ($isRangeSelection2(selection)) {
38514      const { commonAncestor } = $getCommonAncestor2(selection.focus.getNode(), selection.anchor.getNode());
38515      return $findMatchingParent2(commonAncestor, (parent) => parent.is(node));
38516    } else {
38517      return false;
38518    }
38519  }
38520  function $createNodeSelectionWith(...nodes) {
38521    const selection = $createNodeSelection2();
38522    nodes.forEach((node) => selection.add(node.getKey()));
38523    return selection;
38524  }
38525  function $isShadowRoot(node) {
38526    return $isElementNode2(node) && $isRootOrShadowRoot2(node) && !$isRootNode2(node);
38527  }
38528  function $isSafeForRoot(node) {
38529    return ($isElementNode2(node) || $isDecoratorNode2(node)) && !node.isParentRequired();
38530  }
38531  function $makeSafeForRoot(node) {
38532    if ($isSafeForRoot(node)) {
38533      return node;
38534    } else if (node.getParent()) {
38535      return $wrapNodeInElement2(node, () => node.createParentElementNode());
38536    } else {
38537      return node.createParentElementNode().append(node);
38538    }
38539  }
38540  function getListType(node) {
38541    const list = $getNearestNodeOfType2(node, ListNode2);
38542    return list?.getListType() ?? null;
38543  }
38544  function isEditorFocused(editor) {
38545    const rootElement = editor.getRootElement();
38546    return rootElement !== null && rootElement.contains(document.activeElement);
38547  }
38548  function $isAtNodeEdge(point, atStart = null) {
38549    if (atStart === null) {
38550      return $isAtNodeEdge(point, true) || $isAtNodeEdge(point, false);
38551    } else {
38552      return atStart ? $isAtNodeStart(point) : $isAtNodeEnd2(point);
38553    }
38554  }
38555  function $isAtNodeStart(point) {
38556    return point.offset === 0;
38557  }
38558  function extendTextNodeConversion(conversionName, ...callbacks) {
38559    return extendConversion(TextNode2, conversionName, (conversionOutput, element) => ({
38560      ...conversionOutput,
38561      forChild: (lexicalNode, parentNode) => {
38562        const originalForChild = conversionOutput?.forChild ?? ((x3) => x3);
38563        let childNode = originalForChild(lexicalNode, parentNode);
38564        if ($isTextNode2(childNode)) {
38565          childNode = callbacks.reduce(
38566            (childNode2, callback) => callback(childNode2, element) ?? childNode2,
38567            childNode
38568          );
38569          return childNode;
38570        }
38571      }
38572    }));
38573  }
38574  function extendConversion(nodeKlass, conversionName, callback = (output) => output) {
38575    return (element) => {
38576      const converter = nodeKlass.importDOM()?.[conversionName]?.(element);
38577      if (!converter) return null;
38578      const conversionOutput = converter.conversion(element);
38579      if (!conversionOutput) return conversionOutput;
38580      return callback(conversionOutput, element) ?? conversionOutput;
38581    };
38582  }
38583  function $isCursorOnLastLine(selection) {
38584    const anchorNode = selection.anchor.getNode();
38585    const elementNode = $isElementNode2(anchorNode) ? anchorNode : anchorNode.getParentOrThrow();
38586    const children = elementNode.getChildren();
38587    if (children.length === 0) return true;
38588    const lastChild = children[children.length - 1];
38589    if (anchorNode === elementNode.getLatest() && selection.anchor.offset === children.length) return true;
38590    if (anchorNode === lastChild) return true;
38591    const lastLineBreakIndex = children.findLastIndex((child) => $isLineBreakNode2(child));
38592    if (lastLineBreakIndex === -1) return true;
38593    const anchorIndex = children.indexOf(anchorNode);
38594    return anchorIndex > lastLineBreakIndex;
38595  }
38596  function $isBlankNode(node) {
38597    if (node.getTextContent().trim() !== "") return false;
38598    const children = node.getChildren?.();
38599    if (!children || children.length === 0) return true;
38600    return children.every((child) => {
38601      if ($isLineBreakNode2(child)) return true;
38602      return $isBlankNode(child);
38603    });
38604  }
38605  function $trimTrailingBlankNodes(parent) {
38606    for (const child of $lastToFirstIterator2(parent)) {
38607      if ($isBlankNode(child)) {
38608        child.remove();
38609      } else {
38610        break;
38611      }
38612    }
38613  }
38614  function $isListItemStructurallyEmpty(listItem) {
38615    const children = listItem.getChildren();
38616    for (const child of children) {
38617      if ($isDecoratorNode2(child)) return false;
38618      if ($isLineBreakNode2(child)) continue;
38619      if ($isTextNode2(child)) {
38620        if (child.getTextContent().trim() !== "") return false;
38621      } else if ($isElementNode2(child)) {
38622        if (child.getTextContent().trim() !== "") return false;
38623      }
38624    }
38625    return true;
38626  }
38627  function $textBeforeOffset(targetNode, offset3) {
38628    const parts = [];
38629    let done = false;
38630    function visit(node) {
38631      if (done) return;
38632      if (node === targetNode) {
38633        parts.push(node.getTextContent().slice(0, offset3));
38634        done = true;
38635        return;
38636      }
38637      if ($isElementNode2(node)) {
38638        const children = node.getChildren();
38639        for (let i2 = 0; i2 < children.length; i2++) {
38640          visit(children[i2]);
38641          if (done) return;
38642          const child = children[i2];
38643          if ($isElementNode2(child) && !child.isInline() && i2 < children.length - 1) {
38644            parts.push("\n\n");
38645          }
38646        }
38647      } else {
38648        parts.push(node.getTextContent());
38649      }
38650    }
38651    visit($getRoot2());
38652    return parts.join("");
38653  }
38654  function isAttachmentSpacerTextNode(node, previousNode, index, childCount) {
38655    return $isTextNode2(node) && node.getTextContent() === " " && index === childCount - 1 && previousNode instanceof CustomActionTextAttachmentNode;
38656  }
38657  function $splitSelectedParagraphsAtInnerLineBreaks(selection) {
38658    const topLevelElements = /* @__PURE__ */ new Set();
38659    for (const node of selection.getNodes()) {
38660      const topLevel = node.getTopLevelElement();
38661      if (topLevel) topLevelElements.add(topLevel);
38662    }
38663    for (const element of topLevelElements) {
38664      if (!$isParagraphNode2(element)) continue;
38665      const children = element.getChildren();
38666      if (!children.some($isLineBreakNode2)) continue;
38667      const groups = [[]];
38668      for (const child of children) {
38669        if ($isLineBreakNode2(child)) {
38670          groups.push([]);
38671          child.remove();
38672        } else {
38673          groups[groups.length - 1].push(child);
38674        }
38675      }
38676      for (const group of groups) {
38677        if (group.length === 0) continue;
38678        const paragraph = $createParagraphNode2();
38679        group.forEach((child) => paragraph.append(child));
38680        element.insertBefore(paragraph);
38681      }
38682      if (groups.some((group) => group.length > 0)) element.remove();
38683    }
38684  }
38685  function $expandSelectionToLineBreaksAndSplitAtEdges(selection, fallbackAncestor = (node) => node.getTopLevelElement()) {
38686    $ensureForwardRangeSelection2(selection);
38687    $shrinkSelectionPastBlockEdges(selection);
38688    const focusCaret = $caretFromPoint2(selection.focus, "next");
38689    const anchorCaret = $caretFromPoint2(selection.anchor, "previous");
38690    const skipInwardEdge = selection.isCollapsed();
38691    const focusBrCaret = $getCaretAtLineBreakBoundary(focusCaret, skipInwardEdge);
38692    let anchorBrCaret = $getCaretAtLineBreakBoundary(anchorCaret, skipInwardEdge);
38693    if (focusBrCaret?.origin.is(anchorBrCaret?.origin)) {
38694      anchorBrCaret = null;
38695    }
38696    const focusOuter = focusBrCaret && $splitAroundLineBreak(focusBrCaret);
38697    const anchorOuter = anchorBrCaret && $splitAroundLineBreak(anchorBrCaret);
38698    const innerStart = anchorOuter?.getNextSibling() ?? fallbackAncestor(selection.anchor.getNode());
38699    const innerEnd = focusOuter?.getPreviousSibling() ?? fallbackAncestor(selection.focus.getNode());
38700    if (!innerStart || !innerEnd) return;
38701    $setSelectionFromCaretRange2($getCaretRange2(
38702      $normalizeCaret2($getChildCaret2(innerStart, "next")),
38703      $getCaretInDirection2(
38704        $normalizeCaret2($getChildCaret2(innerEnd, "previous")),
38705        "next"
38706      )
38707    ));
38708  }
38709  function $shrinkSelectionPastBlockEdges(selection) {
38710    if (selection.isCollapsed()) return;
38711    const anchorBlock = selection.anchor.getNode().getTopLevelElement();
38712    const focusBlock = selection.focus.getNode().getTopLevelElement();
38713    if (!anchorBlock || !focusBlock || anchorBlock.is(focusBlock)) return;
38714    if ($isAtBlockEnd(selection.anchor, anchorBlock)) {
38715      const nextBlock = $nearestElementSibling(anchorBlock, "next");
38716      if (nextBlock) selection.anchor.set(nextBlock.getKey(), 0, "element");
38717    }
38718    if ($isAtBlockStart(selection.focus, focusBlock)) {
38719      const previousBlock = $nearestElementSibling(focusBlock, "previous");
38720      if (previousBlock) selection.focus.set(previousBlock.getKey(), previousBlock.getChildrenSize(), "element");
38721    }
38722    $ensureForwardRangeSelection2(selection);
38723  }
38724  function $nearestElementSibling(block, direction) {
38725    let sibling = block;
38726    do {
38727      sibling = direction === "next" ? sibling.getNextSibling() : sibling.getPreviousSibling();
38728    } while (sibling && !$isElementNode2(sibling));
38729    return sibling;
38730  }
38731  function $isAtBlockEnd(point, block) {
38732    return $isAtBlockBoundary($caretFromPoint2(point, "next"), block);
38733  }
38734  function $isAtBlockStart(point, block) {
38735    return $isAtBlockBoundary($caretFromPoint2(point, "previous"), block);
38736  }
38737  function $isAtBlockBoundary(caret, block) {
38738    if ($isTextPointCaret2(caret) && $isExtendableTextPointCaret2(caret)) return false;
38739    let cursor = $normalizeCaret2(caret);
38740    while (cursor && block.isParentOf(cursor.origin)) {
38741      if (cursor.getNodeAtCaret()) return false;
38742      cursor = cursor.getParentCaret();
38743    }
38744    return true;
38745  }
38746  function $getCaretAtLineBreakBoundary(caret, skipInwardEdge = false) {
38747    const paragraph = caret.origin.getTopLevelElement();
38748    if (!paragraph || !$isParagraphNode2(paragraph)) return null;
38749    const lineBreak = (skipInwardEdge ? null : $inwardEdgeLineBreak(caret, paragraph)) ?? $outwardLineBreak(caret, paragraph);
38750    return lineBreak ? $getSiblingCaret2(lineBreak, caret.direction) : null;
38751  }
38752  function $inwardEdgeLineBreak(caret, paragraph) {
38753    let candidateCaret;
38754    if ($isChildCaret2(caret) && caret.origin.is(paragraph) || $isTextPointCaret2(caret) && $isExtendableTextPointCaret2(caret.getFlipped())) {
38755      candidateCaret = null;
38756    } else if ($isSiblingCaret2(caret) && caret.getParentAtCaret().is(paragraph)) {
38757      candidateCaret = caret;
38758    } else {
38759      const childCaret = $paragraphChildCaretAtInwardEdge(caret, paragraph);
38760      candidateCaret = childCaret ? $rewindSiblingCaret2(childCaret) : null;
38761    }
38762    if (candidateCaret && $isLineBreakNode2(candidateCaret.origin)) {
38763      return $candidateUnlessShadowed(candidateCaret);
38764    } else {
38765      return null;
38766    }
38767  }
38768  function $candidateUnlessShadowed(candidateCaret) {
38769    const outward = candidateCaret.getNodeAtCaret();
38770    return $isLineBreakNode2(outward) ? null : candidateCaret.origin;
38771  }
38772  function $outwardLineBreak(caret, paragraph) {
38773    const startCaret = $outwardWalkStartCaret(caret, paragraph);
38774    if (!startCaret) return null;
38775    for (const { origin } of startCaret) {
38776      if (!origin.getParent().is(paragraph)) break;
38777      if ($isLineBreakNode2(origin)) return origin;
38778    }
38779    return null;
38780  }
38781  function $outwardWalkStartCaret(caret, paragraph) {
38782    if (caret.getParentAtCaret().is(paragraph)) {
38783      return caret;
38784    } else {
38785      return $paragraphChildCaretContaining(caret, paragraph);
38786    }
38787  }
38788  function $paragraphChildCaretContaining(caret, paragraph) {
38789    let cursor = caret.getSiblingCaret();
38790    while (cursor && !cursor.origin.getParent()?.is(paragraph)) {
38791      cursor = cursor.getParentCaret();
38792    }
38793    return cursor?.origin.getParent()?.is(paragraph) ? cursor : null;
38794  }
38795  function $paragraphChildCaretAtInwardEdge(caret, paragraph) {
38796    let cursor = caret.getSiblingCaret();
38797    while (cursor && !cursor.origin.getParent()?.is(paragraph)) {
38798      if (cursor.getNodeAtCaret()) return null;
38799      cursor = cursor.getParentCaret();
38800    }
38801    return cursor?.origin.getParent()?.is(paragraph) ? cursor : null;
38802  }
38803  function $splitAroundLineBreak(lineBreakCaret) {
38804    let outer = null;
38805    if (lineBreakCaret.getNodeAtCaret() === null) {
38806      lineBreakCaret.origin.remove();
38807    } else {
38808      const lineBreak = lineBreakCaret.origin;
38809      const splitCaret = $getCaretInDirection2($rewindSiblingCaret2(lineBreakCaret), "next");
38810      $splitAtPointCaretNext2(splitCaret);
38811      outer = lineBreak.getTopLevelElement();
38812      lineBreak.remove();
38813    }
38814    return outer;
38815  }
38816  function $isPointOnBlockContainer(point) {
38817    if (point.type !== "element") return false;
38818    const firstChild = point.getNode().getFirstChild();
38819    return ($isElementNode2(firstChild) || $isDecoratorNode2(firstChild)) && !firstChild.isInline();
38820  }
38821  function $hasPointOnBlockContainer(selection) {
38822    return $isRangeSelection2(selection) && [selection.anchor, selection.focus].some($isPointOnBlockContainer);
38823  }
38824  function $normalizeBlockContainerSelection(selection = $getSelection2()) {
38825    if (!$hasPointOnBlockContainer(selection)) return false;
38826    $normalizeSelection__EXPERIMENTAL(selection);
38827    return true;
38828  }
38829  function $consecutiveSiblingGroups(blocks) {
38830    const ordered = [...blocks].sort((a2, b3) => a2.getIndexWithinParent() - b3.getIndexWithinParent());
38831    const groups = [];
38832    for (const block of ordered) {
38833      const lastGroup = groups.at(-1);
38834      const previous = lastGroup?.at(-1);
38835      if (previous && previous.getParent().is(block.getParent()) && previous.getNextSibling()?.is(block)) {
38836        lastGroup.push(block);
38837      } else {
38838        groups.push([block]);
38839      }
38840    }
38841    return groups;
38842  }
38843  var REWRITE_HISTORY_COMMAND = createCommand2("REWRITE_HISTORY_COMMAND");
38844  var RewritableHistoryExtension = class extends LexxyExtension {
38845    #historyState = null;
38846    get lexicalExtension() {
38847      return defineExtension2({
38848        name: "lexxy/rewritable-history",
38849        dependencies: [HistoryExtension2],
38850        register: (editor, _config, state) => {
38851          const historyOutput = state.getDependency(HistoryExtension2).output;
38852          this.#historyState = historyOutput.historyState.value;
38853          return editor.registerCommand(
38854            REWRITE_HISTORY_COMMAND,
38855            (rewrites) => this.#rewriteHistory(rewrites),
38856            COMMAND_PRIORITY_EDITOR2
38857          );
38858        }
38859      });
38860    }
38861    get historyState() {
38862      return this.#historyState;
38863    }
38864    get #allHistoryEntries() {
38865      const entries2 = Array.from(this.#historyState.undoStack);
38866      if (this.#historyState.current) entries2.push(this.#historyState.current);
38867      return entries2.concat(this.#historyState.redoStack);
38868    }
38869    #rewriteHistory(rewrites) {
38870      this.#applyRewritesImmediatelyToCurrentState(rewrites);
38871      this.#applyRewritesToHistory(rewrites);
38872      return true;
38873    }
38874    #applyRewritesImmediatelyToCurrentState(rewrites) {
38875      $getEditor2().update(() => {
38876        for (const [nodeKey, { patch: patch2, replace }] of Object.entries(rewrites)) {
38877          const node = $getNodeByKey2(nodeKey);
38878          if (!node) continue;
38879          if (patch2) Object.assign(node.getWritable(), patch2);
38880          if (replace) node.replace(replace);
38881        }
38882      }, { discrete: true, tag: this.#getBackgroundUpdateTags() });
38883    }
38884    #applyRewritesToHistory(rewrites) {
38885      const nodeKeys = Object.keys(rewrites);
38886      for (const entry of this.#allHistoryEntries) {
38887        if (!this.#entryHasSomeKeys(entry, nodeKeys)) continue;
38888        const editorState = entry.editorState = safeCloneEditorState(entry.editorState);
38889        for (const [nodeKey, { patch: patch2, replace }] of Object.entries(rewrites)) {
38890          const node = editorState._nodeMap.get(nodeKey);
38891          if (!node) continue;
38892          if (patch2) {
38893            this.#patchNodeInEditorState(editorState, node, patch2);
38894          } else if (replace) {
38895            this.#replaceNodeInEditorState(editorState, node, replace);
38896          }
38897        }
38898      }
38899    }
38900    #entryHasSomeKeys(entry, nodeKeys) {
38901      return nodeKeys.some((key) => entry.editorState._nodeMap.has(key));
38902    }
38903    #getBackgroundUpdateTags() {
38904      const tags = [HISTORY_MERGE_TAG2, SKIP_SCROLL_INTO_VIEW_TAG2];
38905      if (!isEditorFocused(this.editorElement.editor)) {
38906        tags.push(SKIP_DOM_SELECTION_TAG2);
38907      }
38908      return tags;
38909    }
38910    #patchNodeInEditorState(editorState, node, patch2) {
38911      editorState._nodeMap.set(node.__key, $cloneNodeWithPatch(node, patch2));
38912    }
38913    #replaceNodeInEditorState(editorState, node, replaceWith) {
38914      editorState._nodeMap.set(node.__key, $cloneNodeAdoptingKeys(replaceWith, node));
38915    }
38916  };
38917  function $cloneNodeWithPatch(node, patch2) {
38918    const clone2 = $cloneWithProperties2(node);
38919    Object.assign(clone2, patch2);
38920    return clone2;
38921  }
38922  function $cloneNodeAdoptingKeys(node, previousNode) {
38923    const clone2 = $cloneWithProperties2(node);
38924    clone2.__key = previousNode.__key;
38925    clone2.__parent = previousNode.__parent;
38926    clone2.__prev = previousNode.__prev;
38927    clone2.__next = previousNode.__next;
38928    return clone2;
38929  }
38930  function safeCloneEditorState(editorState) {
38931    const clone2 = editorState.clone();
38932    clone2._nodeMap = new Map(editorState._nodeMap);
38933    return clone2;
38934  }
38935  var INITIAL_PREVIEW_POLL_DELAY_MS = 3e3;
38936  var MAX_PREVIEW_POLL_DELAY_MS = 12e4;
38937  var MAX_PREVIEW_POLL_ATTEMPTS = 20;
38938  var ActionTextAttachmentNode = class _ActionTextAttachmentNode extends DecoratorNode2 {
38939    static getType() {
38940      return "action_text_attachment";
38941    }
38942    static clone(node) {
38943      return new _ActionTextAttachmentNode({ ...node }, node.__key);
38944    }
38945    static importJSON(serializedNode) {
38946      return new _ActionTextAttachmentNode({ ...serializedNode });
38947    }
38948    static importDOM() {
38949      return {
38950        [this.TAG_NAME]: () => {
38951          return {
38952            conversion: (attachment) => ({
38953              node: new _ActionTextAttachmentNode({
38954                sgid: attachment.getAttribute("sgid"),
38955                src: attachment.getAttribute("url"),
38956                previewable: attachment.getAttribute("previewable"),
38957                altText: attachment.getAttribute("alt"),
38958                caption: attachment.getAttribute("caption"),
38959                contentType: attachment.getAttribute("content-type"),
38960                fileName: attachment.getAttribute("filename"),
38961                fileSize: attachment.getAttribute("filesize"),
38962                width: attachment.getAttribute("width"),
38963                height: attachment.getAttribute("height"),
38964                content: attachment.getAttribute("content") || attachment.getAttribute("data-lexxy-image"),
38965                blobSrc: attachment.getAttribute("data-blob-url")
38966              })
38967            }),
38968            priority: 1
38969          };
38970        },
38971        "img": () => {
38972          return {
38973            conversion: (img) => {
38974              const fileName = extractFileName(img.getAttribute("src") ?? "");
38975              return {
38976                node: new _ActionTextAttachmentNode({
38977                  src: img.getAttribute("src"),
38978                  fileName,
38979                  caption: img.getAttribute("alt") || "",
38980                  contentType: "image/*",
38981                  width: img.getAttribute("width"),
38982                  height: img.getAttribute("height")
38983                })
38984              };
38985            },
38986            priority: 1
38987          };
38988        },
38989        "video": () => {
38990          return {
38991            conversion: (video) => {
38992              const videoSource = video.getAttribute("src") || video.querySelector("source")?.src;
38993              const fileName = videoSource?.split("/")?.pop();
38994              const contentType = video.querySelector("source")?.getAttribute("content-type") || "video/*";
38995              return {
38996                node: new _ActionTextAttachmentNode({
38997                  src: videoSource,
38998                  fileName,
38999                  contentType
39000                })
39001              };
39002            },
39003            priority: 1
39004          };
39005        },
39006        "audio": () => {
39007          return {
39008            conversion: (audio) => {
39009              const audioSource = audio.getAttribute("src") || audio.querySelector("source")?.src;
39010              const fileName = audioSource?.split("/")?.pop();
39011              const contentType = audio.querySelector("source")?.getAttribute("content-type") || "audio/*";
39012              return {
39013                node: new _ActionTextAttachmentNode({
39014                  src: audioSource,
39015                  fileName,
39016                  contentType
39017                })
39018              };
39019            },
39020            priority: 1
39021          };
39022        }
39023      };
39024    }
39025    static get TAG_NAME() {
39026      return Lexxy.global.get("attachmentTagName");
39027    }
39028    constructor({ tagName, sgid, src, previewSrc, previewable, previewStatusUrl, pendingPreview, altText, caption, contentType, fileName, fileSize, width, height, content, blobSrc, uploadError }, key) {
39029      super(key);
39030      this.tagName = tagName || _ActionTextAttachmentNode.TAG_NAME;
39031      this.sgid = sgid;
39032      this.src = src;
39033      this.previewSrc = previewSrc;
39034      this.previewable = parseBoolean(previewable);
39035      this.previewStatusUrl = previewStatusUrl;
39036      this.pendingPreview = pendingPreview;
39037      this.altText = altText || "";
39038      this.caption = sanitizeCaptionHtml(caption || "");
39039      this.contentType = contentType || "";
39040      this.fileName = fileName || "";
39041      this.fileSize = fileSize;
39042      this.width = width;
39043      this.height = height;
39044      this.content = content;
39045      this.blobSrc = blobSrc;
39046      this.uploadError = uploadError;
39047      this.editor = $getEditor2();
39048    }
39049    createDOM() {
39050      if (this.uploadError) return this.createDOMForError();
39051      if (this.pendingPreview && !this.isPdf) return this.#createDOMForPendingPreview();
39052      const figure = this.createAttachmentFigure(this.isAudio || this.isPdf || this.isPreviewableAttachment);
39053      if (this.isPdf) {
39054        figure.appendChild(this.#createDOMForPdf());
39055        figure.appendChild(this.#createEditableCaption());
39056      } else if (this.isPreviewableAttachment) {
39057        figure.appendChild(this.#createDOMForImage());
39058        figure.appendChild(this.#createEditableCaption());
39059      } else if (this.isAudio) {
39060        figure.appendChild(this.#createDOMForAudio());
39061        figure.appendChild(this.#createEditableCaption());
39062      } else if (this.isVideo) {
39063        figure.appendChild(this.#createDOMForFile());
39064        figure.appendChild(this.#createEditableCaption());
39065      } else {
39066        figure.appendChild(this.#createDOMForFile());
39067        figure.appendChild(this.#createDOMForNotImage());
39068      }
39069      return figure;
39070    }
39071    updateDOM(prevNode, dom) {
39072      if (this.uploadError !== prevNode.uploadError) return true;
39073      if (this.isPreviewableImage) syncLexxyImageLayoutClasses(dom, this.content);
39074      const image = dom.querySelector("img");
39075      if (image && image.alt !== this.altText) image.alt = this.altText;
39076      const caption = dom.querySelector("figcaption [data-lexxy-caption-editor]");
39077      if (caption && !caption.contains(document.activeElement) && sanitizeCaptionHtml(caption.innerHTML) !== this.caption) {
39078        caption.innerHTML = this.caption;
39079      }
39080      return false;
39081    }
39082    getTextContent() {
39083      return `[${captionTextContent(this.caption) || this.fileName}]
39084
39085`;
39086    }
39087    isInline() {
39088      return this.isAttached() && !this.getParent().is($getNearestRootOrShadowRoot2(this));
39089    }
39090    exportDOM() {
39091      const attachment = createElement(this.tagName, {
39092        sgid: this.sgid,
39093        previewable: this.previewable || null,
39094        url: this.src,
39095        alt: this.altText,
39096        caption: this.caption,
39097        "content-type": this.contentType,
39098        filename: this.fileName,
39099        filesize: this.fileSize,
39100        width: this.width,
39101        height: this.height,
39102        presentation: "gallery"
39103      });
39104      if (this.content) {
39105        if (isLexxyImageLayoutString(this.content)) {
39106          attachment.setAttribute("data-lexxy-image", this.content);
39107        } else {
39108          attachment.setAttribute("content", this.content);
39109        }
39110      }
39111      if (this.isPdf && this.blobSrc) {
39112        attachment.setAttribute("data-blob-url", this.blobSrc);
39113      }
39114      return { element: attachment };
39115    }
39116    exportJSON() {
39117      return {
39118        type: "action_text_attachment",
39119        version: 1,
39120        tagName: this.tagName,
39121        sgid: this.sgid,
39122        src: this.src,
39123        previewable: this.previewable,
39124        previewStatusUrl: this.previewStatusUrl,
39125        pendingPreview: this.pendingPreview,
39126        altText: this.altText,
39127        caption: this.caption,
39128        contentType: this.contentType,
39129        fileName: this.fileName,
39130        fileSize: this.fileSize,
39131        width: this.width,
39132        height: this.height,
39133        content: this.content,
39134        blobSrc: this.blobSrc
39135      };
39136    }
39137    decorate() {
39138      return null;
39139    }
39140    createDOMForError() {
39141      const figure = this.createAttachmentFigure();
39142      figure.classList.add("attachment--error");
39143      figure.appendChild(createElement("div", { innerText: `Error uploading ${this.fileName || "file"}` }));
39144      return figure;
39145    }
39146    createAttachmentFigure(previewable = this.isPreviewableAttachment) {
39147      const figure = createAttachmentFigure(this.contentType, previewable, this.fileName);
39148      figure.draggable = true;
39149      figure.dataset.lexicalNodeKey = this.__key;
39150      if (this.isPreviewableImage) applyLexxyImageLayout(figure, this.content);
39151      if (this.isPreviewableImage) {
39152        figure.appendChild(this.#createImageAltButton());
39153      }
39154      const deleteButton = createElement("lexxy-node-delete-button");
39155      figure.appendChild(deleteButton);
39156      return figure;
39157    }
39158    get isPreviewableAttachment() {
39159      return this.isPreviewableImage || this.previewable;
39160    }
39161    get isPreviewableImage() {
39162      return isPreviewableImage(this.contentType, this.fileName);
39163    }
39164    get isVideo() {
39165      return this.contentType.startsWith("video/");
39166    }
39167    get isAudio() {
39168      return this.contentType.startsWith("audio/");
39169    }
39170    get isPdf() {
39171      return this.contentType === "application/pdf" || this.fileName.toLowerCase().endsWith(".pdf");
39172    }
39173    get #pdfSrc() {
39174      return this.blobSrc || this.src;
39175    }
39176    #createDOMForPdf(src = this.#pdfSrc) {
39177      const iframe = createElement("iframe", {
39178        src,
39179        title: this.fileName || "PDF",
39180        loading: "lazy"
39181      });
39182      const container = createElement("div", { className: "attachment__container attachment__pdf-frame" });
39183      container.appendChild(iframe);
39184      return container;
39185    }
39186    #createDOMForAudio(src = this.src) {
39187      const audio = createElement("audio", { src, controls: true, preload: "metadata" });
39188      const container = createElement("div", { className: "attachment__container" });
39189      container.appendChild(audio);
39190      return container;
39191    }
39192    #createDOMForPendingPreview() {
39193      const figure = this.createAttachmentFigure(false);
39194      figure.appendChild(this.#createDOMForFile());
39195      figure.appendChild(this.#createDOMForNotImage());
39196      this.#pollForPreview(figure);
39197      return figure;
39198    }
39199    patchAndRewriteHistory(patch2) {
39200      this.editor.dispatchCommand(REWRITE_HISTORY_COMMAND, {
39201        [this.getKey()]: { patch: patch2 }
39202      });
39203    }
39204    replaceAndRewriteHistory(node) {
39205      this.editor.dispatchCommand(REWRITE_HISTORY_COMMAND, {
39206        [this.getKey()]: { replace: node }
39207      });
39208    }
39209    #createDOMForImage(options = {}) {
39210      const initialSrc = this.previewSrc || this.src;
39211      const img = createElement("img", { src: initialSrc, draggable: false, alt: this.altText, ...this.#imageDimensions, ...options });
39212      if (this.previewable && !this.isPreviewableImage) {
39213        img.onerror = () => this.#swapPreviewToFileDOM(img);
39214      }
39215      if (this.previewSrc) {
39216        this.#preloadAndSwapSrc(img);
39217      }
39218      const container = createElement("div", { className: "attachment__container" });
39219      container.appendChild(img);
39220      return container;
39221    }
39222    #createImageAltButton() {
39223      const control = createElement("lexxy-image-alt-button", { className: "lexxy-floating-controls" });
39224      const group = createElement("div", { className: "lexxy-floating-controls__group" });
39225      const button = createElement("button", {
39226        className: "lexxy-image-alt",
39227        type: "button",
39228        ariaLabel: "Edit alt text",
39229        title: "Edit alt text",
39230        tabIndex: -1
39231      });
39232      button.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" aria-hidden="true" focusable="false"><g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" stroke="currentColor"><path d="M9 16.25C13.004 16.25 16.25 13.004 16.25 9C16.25 4.996 13.004 1.75 9 1.75C4.996 1.75 1.75 4.996 1.75 9C1.75 13.004 4.996 16.25 9 16.25Z"></path><path d="M9 12.75V9.25C9 8.9739 8.7761 8.75 8.5 8.75H7.75"></path><path d="M9 6.75C8.448 6.75 8 6.301 8 5.75C8 5.199 8.448 4.75 9 4.75C9.552 4.75 10 5.199 10 5.75C10 6.301 9.552 6.75 9 6.75Z" fill="currentColor" data-stroke="none" stroke="none"></path></g></svg>`;
39233      button.addEventListener("mousedown", (event) => event.preventDefault());
39234      button.addEventListener("click", (event) => this.#handleImageAltButtonClicked(event));
39235      group.appendChild(button);
39236      control.appendChild(group);
39237      return control;
39238    }
39239    #handleImageAltButtonClicked(event) {
39240      event.preventDefault();
39241      event.stopPropagation();
39242      const altText = window.prompt("Image alt text", this.altText);
39243      if (altText === null) return;
39244      this.editor.update(() => {
39245        this.getWritable().altText = altText.trim();
39246      });
39247    }
39248    #preloadAndSwapSrc(img) {
39249      const previewSrc = this.previewSrc;
39250      const serverImage = new Image();
39251      serverImage.onload = () => this.#handleImageLoaded(img, previewSrc);
39252      serverImage.onerror = () => this.#handleImageLoadError(previewSrc);
39253      serverImage.src = this.src;
39254    }
39255    #handleImageLoaded(img, previewSrc) {
39256      img.src = this.src;
39257      this.patchAndRewriteHistory({ previewSrc: null });
39258      this.#revokePreviewSrc(previewSrc);
39259    }
39260    #handleImageLoadError(previewSrc) {
39261      this.patchAndRewriteHistory({
39262        previewSrc: null,
39263        uploadError: true
39264      });
39265      this.#revokePreviewSrc(previewSrc);
39266    }
39267    #revokePreviewSrc(previewSrc) {
39268      if (previewSrc?.startsWith("blob:")) URL.revokeObjectURL(previewSrc);
39269    }
39270    #swapPreviewToFileDOM(img) {
39271      const figure = img.closest("figure.attachment");
39272      if (!figure) return;
39273      this.#swapFigureContent(figure, "attachment--preview", "attachment--file", () => {
39274        figure.appendChild(this.#createDOMForFile());
39275        figure.appendChild(this.#createDOMForNotImage());
39276      });
39277    }
39278    // While the file-icon is shown, watch for the preview to become ready.
39279    // With a status URL, poll it (2xx = processing, anything else = ready).
39280    // Without one, preload the preview URL once and swap on load.
39281    #pollForPreview(figure) {
39282      if (this.previewStatusUrl) {
39283        this.#waitForPreviewByPollingStatus(figure);
39284      } else {
39285        this.#waitForPreviewByPreloadingImage(figure);
39286      }
39287    }
39288    #waitForPreviewByPollingStatus(figure) {
39289      let attempt = 0;
39290      const tryStatus = async () => {
39291        if (!this.editor.read(() => this.isAttached())) return;
39292        try {
39293          const response = await fetch(this.previewStatusUrl, { credentials: "include", redirect: "manual" });
39294          if (!this.editor.read(() => this.isAttached())) return;
39295          if (response.ok) {
39296            retry();
39297          } else {
39298            this.#swapToPreviewDOM(figure, this.src);
39299          }
39300        } catch {
39301          retry();
39302        }
39303      };
39304      const retry = () => {
39305        attempt++;
39306        if (attempt < MAX_PREVIEW_POLL_ATTEMPTS && this.editor.read(() => this.isAttached())) {
39307          const delay2 = Math.min(2e3 * Math.pow(1.5, attempt), MAX_PREVIEW_POLL_DELAY_MS);
39308          setTimeout(tryStatus, delay2);
39309        }
39310      };
39311      setTimeout(tryStatus, INITIAL_PREVIEW_POLL_DELAY_MS);
39312    }
39313    #waitForPreviewByPreloadingImage(figure) {
39314      const img = new Image();
39315      img.onload = () => {
39316        if (!this.editor.read(() => this.isAttached())) return;
39317        this.#swapToPreviewDOM(figure, this.src);
39318      };
39319      img.onerror = () => {
39320        if (!this.editor.read(() => this.isAttached())) return;
39321        this.patchAndRewriteHistory({ pendingPreview: false });
39322      };
39323      img.src = this.src;
39324    }
39325    #swapToPreviewDOM(figure, previewSrc) {
39326      this.#swapFigureContent(figure, "attachment--file", "attachment--preview", () => {
39327        const img = createElement("img", { src: previewSrc, draggable: false, alt: this.altText });
39328        img.onerror = () => this.#swapPreviewToFileDOM(img);
39329        const container = createElement("div", { className: "attachment__container" });
39330        container.appendChild(img);
39331        figure.appendChild(container);
39332        figure.appendChild(this.#createEditableCaption());
39333      });
39334      this.patchAndRewriteHistory({ pendingPreview: false });
39335    }
39336    #swapFigureContent(figure, fromClass, toClass, renderContent) {
39337      figure.className = figure.className.replace(fromClass, toClass);
39338      for (const child of [...figure.querySelectorAll(".attachment__container, .attachment__icon, figcaption")]) {
39339        child.remove();
39340      }
39341      renderContent();
39342    }
39343    get #imageDimensions() {
39344      if (this.width && this.height) {
39345        return { width: this.width, height: this.height };
39346      } else {
39347        return {};
39348      }
39349    }
39350    #createDOMForFile() {
39351      const extension = this.fileName ? this.fileName.split(".").pop().toLowerCase() : "unknown";
39352      return createElement("span", { className: "attachment__icon", textContent: `${extension}` });
39353    }
39354    #createDOMForNotImage() {
39355      const figcaption = createElement("figcaption", { className: "attachment__caption" });
39356      const nameTag = createElement("strong", { className: "attachment__name" });
39357      if (this.caption) {
39358        nameTag.innerHTML = this.caption;
39359      } else {
39360        nameTag.textContent = this.fileName;
39361      }
39362      figcaption.appendChild(nameTag);
39363      if (this.fileSize) {
39364        const sizeSpan = createElement("span", { className: "attachment__size", textContent: bytesToHumanSize(this.fileSize) });
39365        figcaption.appendChild(sizeSpan);
39366      }
39367      return figcaption;
39368    }
39369    #createEditableCaption() {
39370      const caption = createElement("figcaption", { className: "attachment__caption" });
39371      const input = createElement("div", {
39372        className: "attachment__caption-editor",
39373        contentEditable: "true",
39374        role: "textbox",
39375        ariaLabel: "Caption",
39376        spellcheck: true,
39377        dataset: {
39378          lexxyCaptionEditor: "true",
39379          placeholder: this.fileName
39380        }
39381      });
39382      input.innerHTML = this.caption;
39383      syncCaptionEditorEmptyState(input);
39384      input.addEventListener("focusin", () => {
39385        input.dataset.placeholder = "Add caption...";
39386        this.#ensureCaptionToolbar(caption, input);
39387      });
39388      input.addEventListener("blur", (event) => this.#handleCaptionInputBlurred(event));
39389      input.addEventListener("input", (event) => this.#handleCaptionInputChanged(event));
39390      input.addEventListener("keydown", (event) => this.#handleCaptionInputKeydown(event));
39391      input.addEventListener("copy", (event) => event.stopPropagation());
39392      input.addEventListener("cut", (event) => event.stopPropagation());
39393      input.addEventListener("paste", (event) => this.#handleCaptionInputPaste(event));
39394      caption.appendChild(input);
39395      return caption;
39396    }
39397    #ensureCaptionToolbar(caption, input) {
39398      if (!caption.querySelector(".lexxy-caption-tools")) {
39399        caption.insertBefore(this.#createCaptionToolbar(input), input);
39400      }
39401    }
39402    #createCaptionToolbar(input) {
39403      const toolbar = createElement("div", {
39404        className: "lexxy-floating-controls lexxy-caption-tools",
39405        role: "toolbar",
39406        ariaLabel: "Caption formatting"
39407      });
39408      toolbar.innerHTML = `
39409      <div class="lexxy-floating-controls__group lexxy-caption-tools__bar">
39410        ${this.#captionToolbarButton("bold", "Bold", ToolbarIcons.bold)}
39411        ${this.#captionToolbarButton("italic", "Italic", ToolbarIcons.italic)}
39412        ${this.#captionToolbarButton("underline", "Underline", ToolbarIcons.underline)}
39413        ${this.#captionToolbarButton("link", "Link", ToolbarIcons.link)}
39414      </div>
39415    `;
39416      toolbar.addEventListener("mousedown", (event) => event.preventDefault());
39417      toolbar.addEventListener("click", (event) => this.#handleCaptionToolbarClick(event, input));
39418      return toolbar;
39419    }
39420    #captionToolbarButton(command, label, icon) {
39421      const toolbarIcon = CAPTION_TOOLBAR_ICONS[command] || icon;
39422      return `
39423      <button type="button" data-caption-command="${command}" data-lexxy-icon="${command}" title="${label}" aria-label="${label}">
39424        ${toolbarIcon}
39425        <span>${label}</span>
39426      </button>
39427    `;
39428    }
39429    #handleCaptionToolbarClick(event, input) {
39430      const button = event.target.closest("[data-caption-command]");
39431      if (!button) return;
39432      event.preventDefault();
39433      input.focus();
39434      if (button.dataset.captionCommand === "link") {
39435        this.#toggleCaptionLink(input);
39436      } else {
39437        document.execCommand(CAPTION_EXEC_COMMANDS[button.dataset.captionCommand], false);
39438      }
39439      this.#updateCaptionValueFromInput(input);
39440    }
39441    #toggleCaptionLink(input) {
39442      const selection = document.getSelection();
39443      if (!selection || !selection.rangeCount || !input.contains(selection.anchorNode)) return;
39444      const range2 = selection.getRangeAt(0).cloneRange();
39445      const existingLink = selection.anchorNode?.parentElement?.closest?.("a");
39446      const initialValue = existingLink?.getAttribute("href") || selection.toString();
39447      const url = window.prompt("Enter a URL", initialValue || "");
39448      if (url === null) return;
39449      selection.removeAllRanges();
39450      selection.addRange(range2);
39451      if (url.trim() === "") {
39452        document.execCommand("unlink", false);
39453        return;
39454      }
39455      const href = normalizedCaptionUrl(url);
39456      if (!href) return;
39457      if (selection.isCollapsed) {
39458        document.execCommand("insertHTML", false, `<a href="${escapeCaptionText(href)}">${escapeCaptionText(href)}</a>`);
39459      } else {
39460        document.execCommand("createLink", false, href);
39461        const link = selection.anchorNode?.parentElement?.closest?.("a");
39462        if (link) link.setAttribute("href", href);
39463      }
39464    }
39465    #handleCaptionInputBlurred(event) {
39466      this.#updateCaptionValueFromInput(event.target);
39467    }
39468    #handleCaptionInputChanged(event) {
39469      this.editor.update(() => {
39470        this.getWritable().caption = normalizeCaptionHtml(event.target.innerHTML);
39471      });
39472    }
39473    #updateCaptionValueFromInput(input) {
39474      input.dataset.placeholder = this.fileName;
39475      const caption = normalizeCaptionHtml(input.innerHTML);
39476      if (caption !== input.innerHTML) {
39477        input.innerHTML = caption;
39478      }
39479      this.editor.update(() => {
39480        this.getWritable().caption = caption;
39481      });
39482    }
39483    #handleCaptionInputPaste(event) {
39484      event.preventDefault();
39485      event.stopPropagation();
39486      const html2 = event.clipboardData?.getData("text/html");
39487      const text2 = event.clipboardData?.getData("text/plain") || "";
39488      const pastedHtml = sanitizeCaptionHtml(html2) || escapeCaptionText(text2);
39489      document.execCommand("insertHTML", false, pastedHtml);
39490      this.#updateCaptionValueFromInput(event.target);
39491    }
39492    #handleCaptionInputKeydown(event) {
39493      if (event.key === "Enter") {
39494        event.preventDefault();
39495        event.target.blur();
39496        this.editor.update(() => {
39497          this.selectNext(0, 0);
39498        }, {
39499          tag: HISTORY_MERGE_TAG2
39500        });
39501      }
39502      event.stopPropagation();
39503    }
39504  };
39505  function $isActionTextAttachmentNode(node) {
39506    return node instanceof ActionTextAttachmentNode;
39507  }
39508  function filterDisallowedAttachmentNodes(nodes, editorElement) {
39509    return nodes.filter((node) => !isDisallowedAttachment(node, editorElement)).map((node) => {
39510      $descendantsMatching2([node], (descendant) => isDisallowedAttachment(descendant, editorElement)).forEach((descendant) => descendant.remove());
39511      return node;
39512    });
39513  }
39514  function isDisallowedAttachment(node, editorElement) {
39515    const isAttachmentNode = node instanceof CustomActionTextAttachmentNode || node instanceof ActionTextAttachmentNode;
39516    return isAttachmentNode && !editorElement.permitsAttachmentContentType(node.contentType);
39517  }
39518  function $convertInlineImageDataURIs(nodes, editorElement) {
39519    const topLevel = nodes.map((node) => isInlineImageDataURIAttachment(node) ? $tryCreateUploadFromDataURI(node, editorElement) : node).filter((node) => node !== null);
39520    for (const node of topLevel) {
39521      for (const desc of $descendantsMatching2([node], isInlineImageDataURIAttachment)) {
39522        const upload = $tryCreateUploadFromDataURI(desc, editorElement);
39523        if (upload) {
39524          desc.replace(upload);
39525        } else {
39526          desc.remove();
39527        }
39528      }
39529    }
39530    return topLevel;
39531  }
39532  function isInlineImageDataURIAttachment(node) {
39533    return node instanceof ActionTextAttachmentNode && /^data:image\/[^,]*;base64,/i.test(node.src ?? "");
39534  }
39535  function $tryCreateUploadFromDataURI(node, editorElement) {
39536    const file = dataURIToFile(node.src);
39537    if (file && editorElement.acceptsFile(file)) {
39538      return editorElement.contents.$createUploadNode(file);
39539    }
39540    return null;
39541  }
39542  function dataURIToFile(dataURI) {
39543    try {
39544      const [header, data] = dataURI.split(",");
39545      const mimeType = header.match(/^data:(image\/[A-Za-z0-9][A-Za-z0-9!#$&\-^_.+]*)/)?.[1];
39546      if (mimeType) {
39547        const bytes = Uint8Array.from(atob(data), (c2) => c2.charCodeAt(0));
39548        const extension = mimeTypeToExtension(mimeType) ?? "png";
39549        return new File([bytes], `pasted-image-${Date.now()}.${extension}`, { type: mimeType });
39550      } else {
39551        return null;
39552      }
39553    } catch {
39554      return null;
39555    }
39556  }
39557  var HorizontalDividerNode = class _HorizontalDividerNode extends DecoratorNode2 {
39558    static getType() {
39559      return "horizontal_divider";
39560    }
39561    static clone(node) {
39562      return new _HorizontalDividerNode(node.__key);
39563    }
39564    static importJSON(serializedNode) {
39565      return new _HorizontalDividerNode();
39566    }
39567    static importDOM() {
39568      return {
39569        "hr": (hr) => {
39570          return {
39571            conversion: () => ({
39572              node: new _HorizontalDividerNode()
39573            }),
39574            priority: 1
39575          };
39576        }
39577      };
39578    }
39579    constructor(key) {
39580      super(key);
39581    }
39582    createDOM() {
39583      const figure = createElement("figure", { className: "horizontal-divider" });
39584      const hr = createElement("hr");
39585      figure.appendChild(hr);
39586      const deleteButton = createElement("lexxy-node-delete-button");
39587      figure.appendChild(deleteButton);
39588      return figure;
39589    }
39590    updateDOM() {
39591      return true;
39592    }
39593    getTextContent() {
39594      return "\u2504\n\n";
39595    }
39596    isInline() {
39597      return false;
39598    }
39599    exportDOM() {
39600      const hr = createElement("hr");
39601      return { element: hr };
39602    }
39603    exportJSON() {
39604      return {
39605        type: "horizontal_divider",
39606        version: 1
39607      };
39608    }
39609    decorate() {
39610      return null;
39611    }
39612  };
39613  var HORIZONTAL_DIVIDER = {
39614    dependencies: [HorizontalDividerNode],
39615    export: (node) => {
39616      return node instanceof HorizontalDividerNode ? "---" : null;
39617    },
39618    regExpStart: /^-{3,}\s?$/,
39619    replace: (parentNode, children, match, endMatch, linesInBetween, isImport) => {
39620      const hrNode = new HorizontalDividerNode();
39621      parentNode.replace(hrNode);
39622      if (!isImport) {
39623        const paragraph = $createParagraphNode2();
39624        hrNode.insertAfter(paragraph);
39625        paragraph.select();
39626      }
39627    },
39628    type: "multiline-element"
39629  };
39630  var DOUBLE_QUOTE = {
39631    ...QUOTE2,
39632    regExp: /^"\s/
39633  };
39634  var PUNCTUATION_OR_SPACE3 = /[^\w]/;
39635  function registerMarkdownLeadingTagHandler(editor, transformers) {
39636    const textFormatTransformers = transformers.filter((t2) => t2.type === "text-format").sort((a2, b3) => b3.tag.length - a2.tag.length);
39637    return editor.registerUpdateListener(({ tags, dirtyLeaves, editorState, prevEditorState }) => {
39638      if (tags.has("historic") || tags.has("collaboration")) return;
39639      if (editor.isComposing()) return;
39640      const selection = editorState.read($getSelection2);
39641      const prevSelection = prevEditorState.read($getSelection2);
39642      if (!$isRangeSelection2(prevSelection) || !$isRangeSelection2(selection) || !selection.isCollapsed()) return;
39643      const anchorKey = selection.anchor.key;
39644      const anchorOffset = selection.anchor.offset;
39645      if (!dirtyLeaves.has(anchorKey)) return;
39646      const anchorNode = editorState.read(() => $getNodeByKey2(anchorKey));
39647      if (!$isTextNode2(anchorNode)) return;
39648      const prevOffset = prevSelection.anchor.key === anchorKey ? prevSelection.anchor.offset : 0;
39649      if (anchorOffset <= prevOffset) return;
39650      const textContent = editorState.read(() => anchorNode.getTextContent());
39651      for (const transformer of textFormatTransformers) {
39652        const tag = transformer.tag;
39653        const tagLen = tag.length;
39654        const openTagStart = anchorOffset - tagLen;
39655        if (openTagStart < 0) continue;
39656        const candidateOpenTag = textContent.slice(openTagStart, anchorOffset);
39657        if (candidateOpenTag !== tag) continue;
39658        const tagChar = tag[0];
39659        if (openTagStart > 0 && textContent[openTagStart - 1] === tagChar) continue;
39660        if (transformer.intraword === false && openTagStart > 0) {
39661          const beforeChar = textContent[openTagStart - 1];
39662          if (beforeChar && !PUNCTUATION_OR_SPACE3.test(beforeChar)) continue;
39663        }
39664        const searchStart = anchorOffset;
39665        const closeTagIndex = textContent.indexOf(tag, searchStart);
39666        if (closeTagIndex < 0) continue;
39667        if (textContent[closeTagIndex + tagLen] === tagChar) continue;
39668        if (closeTagIndex > 0 && textContent[closeTagIndex - 1] === tagChar) continue;
39669        const innerStart = anchorOffset;
39670        const innerEnd = closeTagIndex;
39671        if (innerEnd <= innerStart) continue;
39672        if (textContent[innerStart] === " ") continue;
39673        if (textContent[innerEnd - 1] === " ") continue;
39674        if (transformer.intraword === false) {
39675          const afterCloseChar = textContent[closeTagIndex + tagLen];
39676          if (afterCloseChar && !PUNCTUATION_OR_SPACE3.test(afterCloseChar)) continue;
39677        }
39678        editor.update(() => {
39679          const node = $getNodeByKey2(anchorKey);
39680          if (!node || !$isTextNode2(node)) return;
39681          const parent = node.getParent();
39682          if (parent === null || $isCodeNode3(parent)) return;
39683          $applyFormatFromLeadingTag(node, openTagStart, transformer);
39684        });
39685        break;
39686      }
39687    });
39688  }
39689  function $applyFormatFromLeadingTag(anchorNode, openTagStart, transformer) {
39690    const tag = transformer.tag;
39691    const tagLen = tag.length;
39692    const textContent = anchorNode.getTextContent();
39693    const innerStart = openTagStart + tagLen;
39694    const closeTagIndex = textContent.indexOf(tag, innerStart);
39695    if (closeTagIndex < 0) return;
39696    const inner = textContent.slice(innerStart, closeTagIndex);
39697    if (inner.length === 0) return;
39698    const before = textContent.slice(0, openTagStart);
39699    const after = textContent.slice(closeTagIndex + tagLen);
39700    anchorNode.setTextContent(before + inner + after);
39701    const nextSelection = $createRangeSelection2();
39702    $setSelection2(nextSelection);
39703    nextSelection.anchor.set(anchorNode.getKey(), openTagStart, "text");
39704    nextSelection.focus.set(anchorNode.getKey(), openTagStart + inner.length, "text");
39705    for (const format of transformer.format) {
39706      if (!nextSelection.hasFormat(format)) {
39707        nextSelection.formatText(format);
39708      }
39709    }
39710    nextSelection.anchor.set(nextSelection.focus.key, nextSelection.focus.offset, nextSelection.focus.type);
39711    for (const format of transformer.format) {
39712      if (nextSelection.hasFormat(format)) {
39713        nextSelection.toggleFormat(format);
39714      }
39715    }
39716  }
39717  var theme = {
39718    text: {
39719      bold: "lexxy-content__bold",
39720      italic: "lexxy-content__italic",
39721      strikethrough: "lexxy-content__strikethrough",
39722      underline: "lexxy-content__underline",
39723      highlight: "lexxy-content__highlight"
39724    },
39725    tableCellHeader: "lexxy-content__table-cell--header",
39726    tableCellSelected: "lexxy-content__table-cell--selected",
39727    tableSelection: "lexxy-content__table--selection",
39728    tableScrollableWrapper: "lexxy-content__table-wrapper",
39729    tableCellHighlight: "lexxy-content__table-cell--highlight",
39730    tableCellFocus: "lexxy-content__table-cell--focus",
39731    list: {
39732      nested: {
39733        listitem: "lexxy-nested-listitem"
39734      }
39735    },
39736    codeHighlight: {
39737      addition: "code-token__selector",
39738      atrule: "code-token__attr",
39739      attr: "code-token__attr",
39740      "attr-name": "code-token__attr",
39741      "attr-value": "code-token__selector",
39742      boolean: "code-token__property",
39743      bold: "code-token__variable",
39744      builtin: "code-token__selector",
39745      cdata: "code-token__comment",
39746      char: "code-token__selector",
39747      class: "code-token__function",
39748      "class-name": "code-token__function",
39749      color: "code-token__property",
39750      comment: "code-token__comment",
39751      constant: "code-token__property",
39752      coord: "code-token__comment",
39753      decorator: "code-token__function",
39754      deleted: "code-token__operator",
39755      deletion: "code-token__operator",
39756      directive: "code-token__attr",
39757      "directive-hash": "code-token__property",
39758      doctype: "code-token__comment",
39759      entity: "code-token__operator",
39760      function: "code-token__function",
39761      hexcode: "code-token__property",
39762      important: "code-token__function",
39763      inserted: "code-token__selector",
39764      italic: "code-token__comment",
39765      keyword: "code-token__attr",
39766      line: "code-token__selector",
39767      namespace: "code-token__variable",
39768      number: "code-token__property",
39769      macro: "code-token__function",
39770      operator: "code-token__operator",
39771      parameter: "code-token__variable",
39772      prolog: "code-token__comment",
39773      property: "code-token__property",
39774      punctuation: "code-token__punctuation",
39775      "raw-string": "code-token__operator",
39776      regex: "code-token__variable",
39777      script: "code-token__function",
39778      selector: "code-token__selector",
39779      string: "code-token__selector",
39780      style: "code-token__function",
39781      symbol: "code-token__property",
39782      tag: "code-token__property",
39783      title: "code-token__function",
39784      "type-definition": "code-token__function",
39785      url: "code-token__operator",
39786      variable: "code-token__variable"
39787    }
39788  };
39789  var UploadRequests = class {
39790    #requestsByKey = /* @__PURE__ */ new Map();
39791    track(key, request) {
39792      this.#requestsByKey.set(key, request);
39793    }
39794    forget(key) {
39795      this.#requestsByKey.delete(key);
39796    }
39797    abort(key) {
39798      const request = this.#requestsByKey.get(key);
39799      if (request) {
39800        this.#requestsByKey.delete(key);
39801        request.abort();
39802      }
39803    }
39804    clear() {
39805      this.#requestsByKey.clear();
39806    }
39807  };
39808  var resolverRoot = null;
39809  function styleResolverRoot() {
39810    if (resolverRoot && resolverRoot.isConnected) return resolverRoot;
39811    resolverRoot = document.createElement("div");
39812    resolverRoot.setAttribute("aria-hidden", "true");
39813    resolverRoot.setAttribute("data-lexxy-style-resolver", "");
39814    resolverRoot.style.cssText = "contain: strict; position: fixed; top: 0; left: 0; visibility: hidden; pointer-events: none; width: 0; height: 0;";
39815    document.body.appendChild(resolverRoot);
39816    return resolverRoot;
39817  }
39818  function isSelectionHighlighted(selection) {
39819    if (!$isRangeSelection2(selection)) return false;
39820    if (selection.isCollapsed()) {
39821      return hasHighlightStyles(selection.style);
39822    } else {
39823      return selection.hasFormat("highlight");
39824    }
39825  }
39826  function getHighlightStyles(selection) {
39827    if (!$isRangeSelection2(selection)) return null;
39828    let styles = getStyleObjectFromCSS4(selection.style);
39829    if (!styles.color && !styles["background-color"]) {
39830      const anchorNode = selection.anchor.getNode();
39831      if ($isTextNode2(anchorNode)) {
39832        styles = getStyleObjectFromCSS4(anchorNode.getStyle());
39833      }
39834    }
39835    const color = styles.color || null;
39836    const backgroundColor = styles["background-color"] || null;
39837    if (!color && !backgroundColor) return null;
39838    return { color, backgroundColor };
39839  }
39840  function hasHighlightStyles(cssOrStyles) {
39841    const styles = typeof cssOrStyles === "string" ? getStyleObjectFromCSS4(cssOrStyles) : cssOrStyles;
39842    return !!(styles.color || styles["background-color"]);
39843  }
39844  function applyCanonicalizers(styles, canonicalizers = []) {
39845    return canonicalizers.reduce((css, canonicalizer) => {
39846      return canonicalizer.applyCanonicalization(css);
39847    }, styles);
39848  }
39849  var StyleCanonicalizer = class {
39850    constructor(property, allowedValues = []) {
39851      this._property = property;
39852      this._allowedValues = allowedValues;
39853      this._canonicalValues = this.#allowedValuesIdentityObject;
39854    }
39855    applyCanonicalization(css) {
39856      const styles = { ...getStyleObjectFromCSS4(css) };
39857      styles[this._property] = this.getCanonicalAllowedValue(styles[this._property]);
39858      if (!styles[this._property]) {
39859        delete styles[this._property];
39860      }
39861      return getCSSFromStyleObject2(styles);
39862    }
39863    getCanonicalAllowedValue(value) {
39864      return this._canonicalValues[value] ||= this.#resolveCannonicalValue(value);
39865    }
39866    // Private
39867    get #allowedValuesIdentityObject() {
39868      return this._allowedValues.reduce((object, value) => ({ ...object, [value]: value }), {});
39869    }
39870    #resolveCannonicalValue(value) {
39871      let index = this.#computedAllowedValues.indexOf(value);
39872      if (index === -1) {
39873        index = this.#computedAllowedValues.indexOf(computeStyleValues(this._property, [value])[0]);
39874      }
39875      return index === -1 ? null : this._allowedValues[index];
39876    }
39877    get #computedAllowedValues() {
39878      return this._computedAllowedValues ||= computeStyleValues(this._property, this._allowedValues);
39879    }
39880  };
39881  function computeStyleValues(property, values) {
39882    const fragment = document.createDocumentFragment();
39883    const elements = values.map((value) => {
39884      const element = createElement("span", { style: `display: none; ${property}: ${value};` });
39885      fragment.appendChild(element);
39886      return element;
39887    });
39888    styleResolverRoot().appendChild(fragment);
39889    const computed2 = elements.map(
39890      (element) => window.getComputedStyle(element).getPropertyValue(property)
39891    );
39892    elements.forEach((element) => element.remove());
39893    return computed2;
39894  }
39895  var TOGGLE_HIGHLIGHT_COMMAND = createCommand2();
39896  var REMOVE_HIGHLIGHT_COMMAND = createCommand2();
39897  var BLANK_STYLES = { "color": null, "background-color": null };
39898  var hasPastedStylesState = createState2("hasPastedStyles", {
39899    parse: (value) => value || false
39900  });
39901  var pendingCodeHighlights = /* @__PURE__ */ new WeakMap();
39902  var HighlightExtension = class extends LexxyExtension {
39903    get enabled() {
39904      return this.editorElement.supportsRichText;
39905    }
39906    get lexicalExtension() {
39907      const extension = defineExtension2({
39908        dependencies: [RichTextExtension2],
39909        name: "lexxy/highlight",
39910        config: {
39911          color: { buttons: [], permit: [] },
39912          "background-color": { buttons: [], permit: [] }
39913        },
39914        html: {
39915          import: {
39916            mark: $markConversion
39917          }
39918        },
39919        register(editor, config) {
39920          const canonicalizers = buildCanonicalizers(config);
39921          $registerPreConversion(editor);
39922          return mergeRegister3(
39923            editor.registerCommand(TOGGLE_HIGHLIGHT_COMMAND, (styles) => $toggleSelectionStyles(editor, styles), COMMAND_PRIORITY_NORMAL2),
39924            editor.registerCommand(REMOVE_HIGHLIGHT_COMMAND, () => $toggleSelectionStyles(editor, BLANK_STYLES), COMMAND_PRIORITY_NORMAL2),
39925            editor.registerNodeTransform(TextNode2, $syncHighlightWithStyle),
39926            editor.registerNodeTransform(CodeHighlightNode3, $syncHighlightWithCodeHighlightNode),
39927            editor.registerNodeTransform(TextNode2, (textNode) => $canonicalizePastedStyles(textNode, canonicalizers))
39928          );
39929        }
39930      });
39931      return [extension, this.editorConfig.get("highlight")];
39932    }
39933  };
39934  function $applyHighlightStyle(textNode, element) {
39935    const elementStyles = {
39936      color: element.style?.color,
39937      "background-color": element.style?.backgroundColor
39938    };
39939    if ($hasUpdateTag2(PASTE_TAG2)) {
39940      $setPastedStyles(textNode);
39941    }
39942    const highlightStyle = getCSSFromStyleObject2(elementStyles);
39943    if (highlightStyle.length) {
39944      return textNode.setStyle(textNode.getStyle() + highlightStyle);
39945    }
39946  }
39947  function $markConversion() {
39948    return {
39949      conversion: extendTextNodeConversion("mark", $applyHighlightStyle),
39950      priority: 1
39951    };
39952  }
39953  function $registerPreConversion(editor) {
39954    if (!editor._htmlConversions) return;
39955    let preEntries = editor._htmlConversions.get("pre");
39956    if (!preEntries) {
39957      preEntries = [];
39958      editor._htmlConversions.set("pre", preEntries);
39959    }
39960    preEntries.push($preConversionWithHighlightsFactory(editor));
39961  }
39962  function $preConversionWithHighlightsFactory(editor) {
39963    return function $preConversionWithHighlights(domNode) {
39964      const highlights = extractHighlightRanges(domNode);
39965      if (highlights.length === 0) return null;
39966      return {
39967        conversion: (domNode2) => {
39968          const language = domNode2.getAttribute("data-language");
39969          const codeNode = $createCodeNode3(language);
39970          $getPendingHighlights(editor).set(codeNode.getKey(), highlights);
39971          return { node: codeNode };
39972        },
39973        priority: 2
39974      };
39975    };
39976  }
39977  function extractHighlightRanges(preElement) {
39978    const ranges = [];
39979    const codeElement = preElement.querySelector("code") || preElement;
39980    let offset3 = 0;
39981    function walk(node) {
39982      if (node.nodeType === Node.TEXT_NODE) {
39983        offset3 += node.textContent.length;
39984      } else if (node.nodeType === Node.ELEMENT_NODE) {
39985        if (node.tagName === "BR") {
39986          offset3 += 1;
39987          return;
39988        }
39989        const isMark = node.tagName === "MARK";
39990        const start3 = offset3;
39991        for (const child of node.childNodes) {
39992          walk(child);
39993        }
39994        if (isMark) {
39995          const style = extractHighlightStyleFromElement(node);
39996          if (style) {
39997            ranges.push({ start: start3, end: offset3, style });
39998          }
39999        }
40000      }
40001    }
40002    for (const child of codeElement.childNodes) {
40003      walk(child);
40004    }
40005    return ranges;
40006  }
40007  function $getPendingHighlights(editor) {
40008    let map = pendingCodeHighlights.get(editor);
40009    if (!map) {
40010      map = /* @__PURE__ */ new Map();
40011      pendingCodeHighlights.set(editor, map);
40012    }
40013    return map;
40014  }
40015  function extractHighlightStyleFromElement(element) {
40016    const styles = {};
40017    if (element.style?.color) styles.color = element.style.color;
40018    if (element.style?.backgroundColor) styles["background-color"] = element.style.backgroundColor;
40019    const css = getCSSFromStyleObject2(styles);
40020    return css.length > 0 ? css : null;
40021  }
40022  function buildHighlightPreservingTokenizer(editor) {
40023    return {
40024      defaultLanguage: PrismTokenizer4.defaultLanguage,
40025      tokenize(code, language) {
40026        return PrismTokenizer4.tokenize(code, language);
40027      },
40028      $tokenize(codeNode, language) {
40029        const tokens = PrismTokenizer4.$tokenize(codeNode, language);
40030        const highlights = $takeHighlightRanges(editor, codeNode);
40031        return $applyHighlightRangesToTokens(tokens, highlights);
40032      }
40033    };
40034  }
40035  function $takeHighlightRanges(editor, codeNode) {
40036    const pending = $getPendingHighlights(editor);
40037    const key = codeNode.getKey();
40038    if (pending.has(key)) {
40039      const highlights = pending.get(key);
40040      pending.delete(key);
40041      return highlights;
40042    } else if (codeNode.getChildren().some($isCodeHighlightNode3)) {
40043      return $extractHighlightRangesFromCodeNode(codeNode);
40044    } else {
40045      return [];
40046    }
40047  }
40048  function $applyHighlightRangesToTokens(tokens, highlights) {
40049    if (highlights.length === 0) return tokens;
40050    const styledTokens = [];
40051    let offset3 = 0;
40052    for (const token of tokens) {
40053      if ($isCodeHighlightNode3(token)) {
40054        styledTokens.push(...$splitTokenAtHighlightBoundaries(token, offset3, highlights));
40055      } else {
40056        styledTokens.push(token);
40057      }
40058      offset3 += token.getTextContentSize();
40059    }
40060    return styledTokens;
40061  }
40062  function $splitTokenAtHighlightBoundaries(token, tokenStart, highlights) {
40063    const text2 = token.getTextContent();
40064    const segments = segmentTextByHighlights(text2, tokenStart, highlights);
40065    if (segments.length === 1) {
40066      const [segment] = segments;
40067      if (segment.style) {
40068        $applyHighlightStyleToToken(token, segment.style);
40069      }
40070      return [token];
40071    } else {
40072      return segments.map((segment) => {
40073        const segmentToken = $createCodeHighlightNode3(text2.slice(segment.start, segment.end), token.getHighlightType());
40074        if (segment.style) {
40075          $applyHighlightStyleToToken(segmentToken, segment.style);
40076        }
40077        return segmentToken;
40078      });
40079    }
40080  }
40081  function segmentTextByHighlights(text2, tokenStart, highlights) {
40082    const segments = [];
40083    let cursor = 0;
40084    for (const { start: start3, end, style } of highlights) {
40085      const from = Math.max(start3 - tokenStart, cursor);
40086      const to = Math.min(end - tokenStart, text2.length);
40087      if (from < to) {
40088        if (from > cursor) {
40089          segments.push({ start: cursor, end: from, style: null });
40090        }
40091        segments.push({ start: from, end: to, style });
40092        cursor = to;
40093      }
40094    }
40095    if (cursor < text2.length) {
40096      segments.push({ start: cursor, end: text2.length, style: null });
40097    }
40098    return segments;
40099  }
40100  function $applyHighlightStyleToToken(token, style) {
40101    token.setStyle(style);
40102    $setCodeHighlightFormat(token, true);
40103  }
40104  function $buildChildRanges(codeNode) {
40105    const childRanges = [];
40106    let charOffset = 0;
40107    for (const child of codeNode.getChildren()) {
40108      if ($isCodeHighlightNode3(child) || $isTextNode2(child)) {
40109        const text2 = child.getTextContent();
40110        childRanges.push({ node: child, start: charOffset, end: charOffset + text2.length });
40111        charOffset += text2.length;
40112      } else {
40113        charOffset += 1;
40114      }
40115    }
40116    return childRanges;
40117  }
40118  function $extractHighlightRangesFromCodeNode(codeNode) {
40119    const ranges = [];
40120    const childRanges = $buildChildRanges(codeNode);
40121    for (const { node, start: start3, end } of childRanges) {
40122      const style = node.getStyle();
40123      if (style && hasHighlightStyles(style)) {
40124        ranges.push({ start: start3, end, style });
40125      }
40126    }
40127    return ranges;
40128  }
40129  function buildCanonicalizers(config) {
40130    return [
40131      new StyleCanonicalizer("color", [...config.buttons.color, ...config.permit.color]),
40132      new StyleCanonicalizer("background-color", [...config.buttons["background-color"], ...config.permit["background-color"]])
40133    ];
40134  }
40135  function $toggleSelectionStyles(editor, styles) {
40136    const selection = $getSelection2();
40137    if (!$isRangeSelection2(selection)) return;
40138    const patch2 = {};
40139    for (const property in styles) {
40140      const oldValue = $getSelectionStyleValueForProperty2(selection, property);
40141      patch2[property] = toggleOrReplace(oldValue, styles[property]);
40142    }
40143    if ($selectionIsInCodeBlock(selection)) {
40144      $patchCodeHighlightStyles(editor, selection, patch2);
40145    } else {
40146      $patchStyleText2(selection, patch2);
40147    }
40148  }
40149  function $selectionIsInCodeBlock(selection) {
40150    const nodes = selection.getNodes();
40151    return nodes.some((node) => {
40152      if ($isCodeHighlightNode3(node) || $isTextNode2(node)) {
40153        return $isCodeNode3(node.getParent());
40154      }
40155      return $isCodeNode3(node);
40156    });
40157  }
40158  function $patchCodeHighlightStyles(editor, selection, patch2) {
40159    const nodeKeys = selection.getNodes().filter((node) => ($isCodeHighlightNode3(node) || $isTextNode2(node)) && $isCodeNode3(node.getParent())).map((node) => ({
40160      key: node.getKey(),
40161      startOffset: $getNodeSelectionOffsets(node, selection)[0],
40162      endOffset: $getNodeSelectionOffsets(node, selection)[1],
40163      textSize: node.getTextContentSize()
40164    }));
40165    editor.update(() => {
40166      for (const { key, startOffset, endOffset, textSize } of nodeKeys) {
40167        const node = $getNodeByKey2(key);
40168        if (!node) continue;
40169        const parent = node.getParent();
40170        if (!$isCodeNode3(parent)) continue;
40171        if (startOffset === endOffset) continue;
40172        if (startOffset === 0 && endOffset === textSize) {
40173          $applyStylePatchToNode(node, patch2);
40174        } else {
40175          const splitNodes = node.splitText(startOffset, endOffset);
40176          const targetNode = splitNodes[startOffset === 0 ? 0 : 1];
40177          $applyStylePatchToNode(targetNode, patch2);
40178        }
40179      }
40180    }, { skipTransforms: true, discrete: true });
40181  }
40182  function $getNodeSelectionOffsets(node, selection) {
40183    const nodeKey = node.getKey();
40184    const anchorKey = selection.anchor.key;
40185    const focusKey = selection.focus.key;
40186    const textSize = node.getTextContentSize();
40187    const isAnchor = nodeKey === anchorKey;
40188    const isFocus = nodeKey === focusKey;
40189    const isForward = selection.isBackward() === false;
40190    let start3 = 0;
40191    let end = textSize;
40192    if (isForward) {
40193      if (isAnchor) start3 = selection.anchor.offset;
40194      if (isFocus) end = selection.focus.offset;
40195    } else {
40196      if (isFocus) start3 = selection.focus.offset;
40197      if (isAnchor) end = selection.anchor.offset;
40198    }
40199    return [start3, end];
40200  }
40201  function $applyStylePatchToNode(node, patch2) {
40202    const prevStyles = getStyleObjectFromCSS4(node.getStyle());
40203    const newStyles = { ...prevStyles };
40204    for (const [key, value] of Object.entries(patch2)) {
40205      if (value === null) {
40206        delete newStyles[key];
40207      } else {
40208        newStyles[key] = value;
40209      }
40210    }
40211    const newCSSText = getCSSFromStyleObject2(newStyles);
40212    node.setStyle(newCSSText);
40213    const shouldHaveHighlight = hasHighlightStyles(newCSSText);
40214    const hasHighlight = node.hasFormat("highlight");
40215    if (shouldHaveHighlight !== hasHighlight) {
40216      $setCodeHighlightFormat(node, shouldHaveHighlight);
40217    }
40218  }
40219  function $setCodeHighlightFormat(node, shouldHaveHighlight) {
40220    const writable = node.getWritable();
40221    const IS_HIGHLIGHT3 = 1 << 7;
40222    if (shouldHaveHighlight) {
40223      writable.__format |= IS_HIGHLIGHT3;
40224    } else {
40225      writable.__format &= ~IS_HIGHLIGHT3;
40226    }
40227  }
40228  function toggleOrReplace(oldValue, newValue) {
40229    return oldValue === newValue ? null : newValue;
40230  }
40231  function $syncHighlightWithStyle(textNode) {
40232    if (hasHighlightStyles(textNode.getStyle()) !== textNode.hasFormat("highlight")) {
40233      textNode.toggleFormat("highlight");
40234    }
40235  }
40236  function $syncHighlightWithCodeHighlightNode(node) {
40237    const parent = node.getParent();
40238    if (!$isCodeNode3(parent)) return;
40239    const shouldHaveHighlight = hasHighlightStyles(node.getStyle());
40240    const hasHighlight = node.hasFormat("highlight");
40241    if (shouldHaveHighlight !== hasHighlight) {
40242      $setCodeHighlightFormat(node, shouldHaveHighlight);
40243    }
40244  }
40245  function $canonicalizePastedStyles(textNode, canonicalizers = []) {
40246    if ($hasPastedStyles(textNode)) {
40247      $setPastedStyles(textNode, false);
40248      const canonicalizedCSS = applyCanonicalizers(textNode.getStyle(), canonicalizers);
40249      textNode.setStyle(canonicalizedCSS);
40250      const selection = $getSelection2();
40251      if (textNode.isSelected(selection)) {
40252        selection.setStyle(textNode.getStyle());
40253        selection.setFormat(textNode.getFormat());
40254      }
40255    }
40256  }
40257  function $setPastedStyles(textNode, value = true) {
40258    $setState2(textNode, hasPastedStylesState, value);
40259  }
40260  function $hasPastedStyles(textNode) {
40261    return $getState2(textNode, hasPastedStylesState);
40262  }
40263  var COMMANDS = [
40264    "bold",
40265    "italic",
40266    "strikethrough",
40267    "underline",
40268    "link",
40269    "unlink",
40270    "toggleHighlight",
40271    "removeHighlight",
40272    "setFormatHeadingLarge",
40273    "setFormatHeadingMedium",
40274    "setFormatHeadingSmall",
40275    "setFormatParagraph",
40276    "applyHeadingFormat",
40277    "clearFormatting",
40278    "insertUnorderedList",
40279    "insertOrderedList",
40280    "insertQuoteBlock",
40281    "insertCodeBlock",
40282    "setCodeLanguage",
40283    "insertHorizontalDivider",
40284    "uploadImage",
40285    "uploadFile",
40286    "insertTable",
40287    "undo",
40288    "redo"
40289  ];
40290  var CommandDispatcher = class _CommandDispatcher {
40291    #selectionBeforeDrag = null;
40292    #listeners = new ListenerBin();
40293    static configureFor(editorElement) {
40294      return new _CommandDispatcher(editorElement);
40295    }
40296    constructor(editorElement) {
40297      this.editorElement = editorElement;
40298      this.editor = editorElement.editor;
40299      this.selection = editorElement.selection;
40300      this.contents = editorElement.contents;
40301      this.#registerCommands();
40302      this.#registerKeyboardCommands();
40303      this.#registerDragAndDropHandlers();
40304    }
40305    dispatchBold() {
40306      this.editor.dispatchCommand(FORMAT_TEXT_COMMAND2, "bold");
40307    }
40308    dispatchItalic() {
40309      this.editor.dispatchCommand(FORMAT_TEXT_COMMAND2, "italic");
40310    }
40311    dispatchStrikethrough() {
40312      this.editor.dispatchCommand(FORMAT_TEXT_COMMAND2, "strikethrough");
40313    }
40314    dispatchUnderline() {
40315      this.editor.dispatchCommand(FORMAT_TEXT_COMMAND2, "underline");
40316    }
40317    dispatchToggleHighlight(styles) {
40318      this.editor.dispatchCommand(TOGGLE_HIGHLIGHT_COMMAND, styles);
40319    }
40320    dispatchRemoveHighlight() {
40321      this.editor.dispatchCommand(REMOVE_HIGHLIGHT_COMMAND);
40322    }
40323    dispatchLink(url) {
40324      this.editor.update(() => {
40325        const selection = $getSelection2();
40326        if (!$isRangeSelection2(selection)) return;
40327        const anchorNode = selection.anchor.getNode();
40328        if (selection.isCollapsed() && !$getNearestNodeOfType2(anchorNode, LinkNode2)) {
40329          const autoLinkNode = $createAutoLinkNode2(url);
40330          const textNode = $createTextNode2(url);
40331          autoLinkNode.append(textNode);
40332          selection.insertNodes([autoLinkNode]);
40333        } else {
40334          $toggleLink2(url);
40335        }
40336      });
40337    }
40338    dispatchUnlink() {
40339      this.editor.update(() => {
40340        if (this.editorElement.adapter.unlinkFrozenNode?.()) {
40341          return;
40342        }
40343        $toggleLink2(null);
40344      });
40345    }
40346    dispatchInsertUnorderedList() {
40347      const selection = $getSelection2();
40348      if (!$isRangeSelection2(selection)) return;
40349      const anchorNode = selection.anchor.getNode();
40350      if (this.selection.isInsideList && anchorNode && getListType(anchorNode) === "bullet") {
40351        this.contents.applyParagraphFormat();
40352      } else {
40353        this.contents.applyUnorderedListFormat();
40354      }
40355    }
40356    dispatchInsertOrderedList() {
40357      const selection = $getSelection2();
40358      if (!$isRangeSelection2(selection)) return;
40359      const anchorNode = selection.anchor.getNode();
40360      if (this.selection.isInsideList && anchorNode && getListType(anchorNode) === "number") {
40361        this.contents.applyParagraphFormat();
40362      } else {
40363        this.contents.applyOrderedListFormat();
40364      }
40365    }
40366    dispatchInsertQuoteBlock() {
40367      this.contents.toggleBlockquote();
40368    }
40369    dispatchInsertCodeBlock() {
40370      if (this.selection.hasSelectedWordsInSingleLine) {
40371        this.#toggleInlineCode();
40372      } else {
40373        this.contents.toggleCodeBlock();
40374      }
40375    }
40376    #toggleInlineCode() {
40377      const selection = $getSelection2();
40378      if (!$isRangeSelection2(selection)) return;
40379      if (!selection.isCollapsed()) {
40380        const textNodes = selection.getNodes().filter($isTextNode2);
40381        const applyingCode = !textNodes.every((node) => node.hasFormat("code"));
40382        if (applyingCode) {
40383          this.#stripInlineFormattingFromSelection(selection, textNodes);
40384        }
40385      }
40386      this.editor.dispatchCommand(FORMAT_TEXT_COMMAND2, "code");
40387    }
40388    // Strip all inline formatting (bold, italic, etc.) from the selected text
40389    // nodes so that applying code produces a single merged <code> element instead
40390    // of one per differently-formatted span.
40391    #stripInlineFormattingFromSelection(selection, textNodes) {
40392      const isBackward = selection.isBackward();
40393      const startPoint = isBackward ? selection.focus : selection.anchor;
40394      const endPoint = isBackward ? selection.anchor : selection.focus;
40395      for (let i2 = 0; i2 < textNodes.length; i2++) {
40396        const node = textNodes[i2];
40397        if (node.getFormat() === 0) continue;
40398        const isFirst = i2 === 0;
40399        const isLast = i2 === textNodes.length - 1;
40400        const startOffset = isFirst && startPoint.type === "text" ? startPoint.offset : 0;
40401        const endOffset = isLast && endPoint.type === "text" ? endPoint.offset : node.getTextContentSize();
40402        if (startOffset === 0 && endOffset === node.getTextContentSize()) {
40403          node.setFormat(0);
40404        } else {
40405          const splits = node.splitText(startOffset, endOffset);
40406          const target = startOffset === 0 ? splits[0] : splits[1];
40407          target.setFormat(0);
40408          if (isFirst && startPoint.type === "text") {
40409            startPoint.set(target.getKey(), 0, "text");
40410          }
40411          if (isLast && endPoint.type === "text") {
40412            endPoint.set(target.getKey(), endOffset - startOffset, "text");
40413          }
40414        }
40415      }
40416    }
40417    dispatchSetCodeLanguage(language) {
40418      this.editor.update(() => {
40419        if (!this.selection.isInsideCodeBlock) return;
40420        const codeNode = this.selection.nearestNodeOfType(CodeNode3);
40421        if (!codeNode) return;
40422        codeNode.setLanguage(language);
40423      });
40424    }
40425    dispatchInsertHorizontalDivider() {
40426      $insertNodeToNearestRoot2(new HorizontalDividerNode());
40427    }
40428    dispatchSetFormatHeadingLarge() {
40429      this.#applyConfiguredHeadingFormat(0);
40430    }
40431    dispatchSetFormatHeadingMedium() {
40432      this.#applyConfiguredHeadingFormat(1);
40433    }
40434    dispatchSetFormatHeadingSmall() {
40435      this.#applyConfiguredHeadingFormat(2);
40436    }
40437    dispatchSetFormatParagraph() {
40438      this.contents.applyParagraphFormat();
40439    }
40440    dispatchApplyHeadingFormat(tag) {
40441      this.contents.applyHeadingFormat(tag);
40442    }
40443    dispatchClearFormatting() {
40444      this.contents.clearFormatting();
40445    }
40446    dispatchUploadImage() {
40447      this.#dispatchUploadAttachment("image/*,video/*,audio/*");
40448    }
40449    dispatchUploadFile() {
40450      this.#dispatchUploadAttachment();
40451    }
40452    #dispatchUploadAttachment(accept = null) {
40453      const attributes = {
40454        type: "file",
40455        multiple: true,
40456        style: "display: none;",
40457        onchange: ({ target: { files } }) => {
40458          this.contents.uploadFiles(files, { selectLast: true });
40459        }
40460      };
40461      if (accept) attributes.accept = accept;
40462      const input = createElement("input", attributes);
40463      this.editorElement.appendChild(input);
40464      input.click();
40465      setTimeout(() => input.remove(), 1e3);
40466    }
40467    dispatchInsertTable() {
40468      this.editor.dispatchCommand(INSERT_TABLE_COMMAND2, { "rows": 3, "columns": 3, "includeHeaders": true });
40469    }
40470    dispatchUndo() {
40471      this.editor.dispatchCommand(UNDO_COMMAND2, void 0);
40472    }
40473    dispatchRedo() {
40474      this.editor.dispatchCommand(REDO_COMMAND2, void 0);
40475    }
40476    dispose() {
40477      this.#listeners.dispose();
40478    }
40479    #applyConfiguredHeadingFormat(index) {
40480      const tag = this.editorElement.config.get("headings")[index];
40481      if (tag) this.contents.applyHeadingFormat(tag);
40482    }
40483    #registerCommands() {
40484      for (const command of COMMANDS) {
40485        const methodName = `dispatch${capitalize(command)}`;
40486        this.#registerCommandHandler(command, 0, this[methodName].bind(this));
40487      }
40488    }
40489    #registerCommandHandler(command, priority, handler) {
40490      this.#listeners.track(this.editor.registerCommand(command, handler, priority));
40491    }
40492    #registerKeyboardCommands() {
40493      this.#registerCommandHandler(KEY_ARROW_RIGHT_COMMAND2, COMMAND_PRIORITY_NORMAL2, this.#handleArrowRightKey.bind(this));
40494      this.#registerCommandHandler(KEY_TAB_COMMAND2, COMMAND_PRIORITY_NORMAL2, this.#handleTabKey.bind(this));
40495      this.#registerCommandHandler(INSERT_LINE_BREAK_COMMAND2, COMMAND_PRIORITY_HIGH2, this.#normalizeBlockContainerSelection.bind(this));
40496      this.#registerCommandHandler(INSERT_PARAGRAPH_COMMAND2, COMMAND_PRIORITY_HIGH2, this.#normalizeBlockContainerSelection.bind(this));
40497    }
40498    #normalizeBlockContainerSelection() {
40499      $normalizeBlockContainerSelection();
40500      return false;
40501    }
40502    #handleArrowRightKey(event) {
40503      const selection = $getSelection2();
40504      if (!$isRangeSelection2(selection) || !selection.isCollapsed()) return false;
40505      if (this.selection.isInsideCodeBlock || !selection.hasFormat("code")) return false;
40506      const anchorNode = selection.anchor.getNode();
40507      if (!$isTextNode2(anchorNode) || selection.anchor.offset !== anchorNode.getTextContentSize()) return false;
40508      if (anchorNode.getNextSibling() !== null) return false;
40509      event.preventDefault();
40510      selection.toggleFormat("code");
40511      return true;
40512    }
40513    #registerDragAndDropHandlers() {
40514      if (this.editorElement.supportsAttachments) {
40515        this.dragCounter = 0;
40516        this.#listeners.track(
40517          this.editor.registerRootListener((rootElement) => {
40518            if (rootElement) {
40519              const teardowns = [
40520                registerEventListener(rootElement, "dragover", this.#handleDragOver.bind(this)),
40521                registerEventListener(rootElement, "drop", this.#handleDrop.bind(this)),
40522                registerEventListener(rootElement, "dragenter", this.#handleDragEnter.bind(this)),
40523                registerEventListener(rootElement, "dragleave", this.#handleDragLeave.bind(this))
40524              ];
40525              return () => teardowns.forEach((teardown) => teardown());
40526            }
40527          })
40528        );
40529      }
40530    }
40531    #handleDragEnter(event) {
40532      if (this.#isInternalDrag(event)) return;
40533      this.dragCounter++;
40534      if (this.dragCounter === 1) {
40535        this.#saveSelectionBeforeDrag();
40536        this.editor.getRootElement().classList.add("lexxy-editor--drag-over");
40537      }
40538    }
40539    #handleDragLeave(event) {
40540      if (this.#isInternalDrag(event)) return;
40541      this.dragCounter--;
40542      if (this.dragCounter === 0) {
40543        this.#selectionBeforeDrag = null;
40544        this.editor.getRootElement().classList.remove("lexxy-editor--drag-over");
40545      }
40546    }
40547    #handleDragOver(event) {
40548      if (this.#isInternalDrag(event)) return;
40549      event.preventDefault();
40550    }
40551    #handleDrop(event) {
40552      if (this.#isInternalDrag(event)) return;
40553      event.preventDefault();
40554      this.dragCounter = 0;
40555      this.editor.getRootElement().classList.remove("lexxy-editor--drag-over");
40556      const dataTransfer = event.dataTransfer;
40557      if (!dataTransfer) return;
40558      const files = Array.from(dataTransfer.files);
40559      if (!files.length) return;
40560      this.#restoreSelectionBeforeDrag();
40561      this.contents.uploadFiles(files, { selectLast: true });
40562      this.editor.focus();
40563    }
40564    #saveSelectionBeforeDrag() {
40565      this.editor.getEditorState().read(() => {
40566        this.#selectionBeforeDrag = $getSelection2()?.clone();
40567      });
40568    }
40569    #restoreSelectionBeforeDrag() {
40570      if (!this.#selectionBeforeDrag) return;
40571      this.editor.update(() => {
40572        $setSelection2(this.#selectionBeforeDrag);
40573      });
40574      this.#selectionBeforeDrag = null;
40575    }
40576    #isInternalDrag(event) {
40577      return event.dataTransfer?.types.some((type) => type.startsWith("application/x-lexxy-"));
40578    }
40579    #handleTabKey(event) {
40580      if (this.selection.isInsideList) {
40581        return this.#handleTabForList(event);
40582      } else if (this.selection.isInsideCodeBlock) {
40583        return this.#handleTabForCode();
40584      }
40585      return false;
40586    }
40587    #handleTabForList(event) {
40588      if (event.shiftKey && !this.selection.isIndentedList) return false;
40589      event.preventDefault();
40590      const command = event.shiftKey ? OUTDENT_CONTENT_COMMAND2 : INDENT_CONTENT_COMMAND2;
40591      return this.editor.dispatchCommand(command);
40592    }
40593    #handleTabForCode() {
40594      const selection = $getSelection2();
40595      return $isRangeSelection2(selection) && selection.isCollapsed();
40596    }
40597  };
40598  function capitalize(str) {
40599    return str.charAt(0).toUpperCase() + str.slice(1);
40600  }
40601  var Selection = class {
40602    #listeners = new ListenerBin();
40603    constructor(editorElement) {
40604      this.editorElement = editorElement;
40605      this.editorContentElement = editorElement.editorContentElement;
40606      this.editor = this.editorElement.editor;
40607      this.previouslySelectedKeys = /* @__PURE__ */ new Set();
40608      this.#listenForNodeSelections();
40609      this.#processSelectionChangeCommands();
40610      this.#containEditorFocus();
40611      this.#clearStaleInlineCodeFormat();
40612    }
40613    get hasNodeSelection() {
40614      return this.editor.getEditorState().read(() => {
40615        const selection = $getSelection2();
40616        return selection !== null && $isNodeSelection2(selection);
40617      });
40618    }
40619    get cursorPosition() {
40620      let position = null;
40621      this.editor.getEditorState().read(() => {
40622        const range2 = this.#getValidSelectionRange();
40623        if (!range2) return;
40624        const rect = this.#getReliableRectFromRange(range2);
40625        if (this.#isRectUnreliable(rect)) return;
40626        position = this.#calculateCursorPosition(rect, range2);
40627      });
40628      return position;
40629    }
40630    placeCursorAtTheEnd() {
40631      this.editor.update(() => {
40632        const root = $getRoot2();
40633        const lastDescendant = root.getLastDescendant();
40634        if (lastDescendant && $isTextNode2(lastDescendant)) {
40635          lastDescendant.selectEnd();
40636        } else {
40637          root.selectEnd();
40638        }
40639      });
40640    }
40641    selectedNodeWithOffset() {
40642      const selection = $getSelection2();
40643      if (!selection) return { node: null, offset: 0 };
40644      if ($isRangeSelection2(selection)) {
40645        return {
40646          node: selection.anchor.getNode(),
40647          offset: selection.anchor.offset
40648        };
40649      } else if ($isNodeSelection2(selection)) {
40650        const [node] = selection.getNodes();
40651        return {
40652          node,
40653          offset: 0
40654        };
40655      }
40656      return { node: null, offset: 0 };
40657    }
40658    getFormat() {
40659      const selection = $getSelection2();
40660      if (!$isRangeSelection2(selection)) return {};
40661      const anchorNode = selection.anchor.getNode();
40662      if (!anchorNode.getParent()) return {};
40663      const topLevelElement = anchorNode.getTopLevelElementOrThrow();
40664      const listType = getListType(anchorNode);
40665      const headingNode = this.#getNearestHeadingNode(anchorNode);
40666      return {
40667        isBold: selection.hasFormat("bold"),
40668        isItalic: selection.hasFormat("italic"),
40669        isStrikethrough: selection.hasFormat("strikethrough"),
40670        isUnderline: selection.hasFormat("underline"),
40671        isHighlight: isSelectionHighlighted(selection),
40672        isInLink: $getNearestNodeOfType2(anchorNode, LinkNode2) !== null,
40673        isInQuote: $isQuoteNode2(topLevelElement),
40674        isInHeading: headingNode !== null,
40675        isInCode: this.#isInCode(selection, anchorNode),
40676        headingTag: headingNode?.getTag() ?? null,
40677        isInList: listType !== null,
40678        listType,
40679        isInTable: $getTableCellNodeFromLexicalNode2(anchorNode) !== null
40680      };
40681    }
40682    nearestNodeOfType(nodeType) {
40683      const anchorNode = $getSelection2()?.anchor?.getNode();
40684      return $getNearestNodeOfType2(anchorNode, nodeType);
40685    }
40686    get hasSelectedWordsInSingleLine() {
40687      const selection = $getSelection2();
40688      if (!$isRangeSelection2(selection)) return false;
40689      if (selection.isCollapsed()) return false;
40690      const anchorNode = selection.anchor.getNode();
40691      const focusNode = selection.focus.getNode();
40692      if (anchorNode.getTopLevelElement() !== focusNode.getTopLevelElement()) {
40693        return false;
40694      }
40695      const anchorElement = anchorNode.getTopLevelElement();
40696      if (!anchorElement) return false;
40697      const anchorBlock = $isElementNode2(anchorNode) ? anchorNode : anchorNode.getParent();
40698      const focusBlock = $isElementNode2(focusNode) ? focusNode : focusNode.getParent();
40699      if (anchorBlock !== focusBlock && anchorBlock !== anchorElement) {
40700        return false;
40701      }
40702      const nodes = selection.getNodes();
40703      for (const node of nodes) {
40704        if ($isLineBreakNode2(node)) {
40705          return false;
40706        }
40707      }
40708      return true;
40709    }
40710    get isInsideList() {
40711      return this.nearestNodeOfType(ListItemNode2);
40712    }
40713    get isInsideBlockQuote() {
40714      return this.nearestNodeOfType(QuoteNode2);
40715    }
40716    get isIndentedList() {
40717      const closestListNode = this.nearestNodeOfType(ListNode2);
40718      return closestListNode && $getListDepth2(closestListNode) > 1;
40719    }
40720    get isInsideCodeBlock() {
40721      return this.nearestNodeOfType(CodeNode3) !== null;
40722    }
40723    get isTableCellSelected() {
40724      const selection = $getSelection2();
40725      const { anchor, focus } = selection;
40726      if (!$isRangeSelection2(selection) || anchor.key !== focus.key) return false;
40727      return this.nearestNodeOfType(TableCellNode2) !== null;
40728    }
40729    get isOnPreviewableImage() {
40730      return this.previewableImageNode != null;
40731    }
40732    get previewableImageNode() {
40733      const firstNode = $getSelection2()?.getNodes().at(0);
40734      return $isActionTextAttachmentNode(firstNode) && firstNode.isPreviewableImage ? firstNode : null;
40735    }
40736    get isAtNodeStart() {
40737      const { anchorNode, offset: offset3 } = this.#getCollapsedSelectionData();
40738      return anchorNode && offset3 === 0;
40739    }
40740    get nodeAfterCursor() {
40741      const { anchorNode, offset: offset3 } = this.#getCollapsedSelectionData();
40742      if (!anchorNode) return null;
40743      if ($isTextNode2(anchorNode)) {
40744        return this.#getNodeAfterTextNode(anchorNode, offset3);
40745      }
40746      if ($isElementNode2(anchorNode)) {
40747        return this.#getNodeAfterElementNode(anchorNode, offset3);
40748      }
40749      return this.#findNextSiblingUp(anchorNode);
40750    }
40751    get topLevelNodeAfterCursor() {
40752      const { anchorNode, offset: offset3 } = this.#getCollapsedSelectionData();
40753      if (!anchorNode) return null;
40754      if ($isTextNode2(anchorNode)) {
40755        if (offset3 === anchorNode.getTextContentSize()) return this.#getNextNodeFromTextEnd(anchorNode);
40756        if (this.#isCursorOnLastVisualLineOfBlock(anchorNode)) {
40757          const topLevelElement = anchorNode.getTopLevelElement();
40758          return topLevelElement ? topLevelElement.getNextSibling() : null;
40759        }
40760        return null;
40761      }
40762      if ($isElementNode2(anchorNode)) {
40763        return this.#getNodeAfterElementNode(anchorNode, offset3);
40764      }
40765      return this.#findNextSiblingUp(anchorNode);
40766    }
40767    get nodeBeforeCursor() {
40768      const { anchorNode, offset: offset3 } = this.#getCollapsedSelectionData();
40769      if (!anchorNode) return null;
40770      if ($isTextNode2(anchorNode)) {
40771        return this.#getNodeBeforeTextNode(anchorNode, offset3);
40772      }
40773      if ($isElementNode2(anchorNode)) {
40774        return this.#getNodeBeforeElementNode(anchorNode, offset3);
40775      }
40776      return this.#findPreviousSiblingUp(anchorNode);
40777    }
40778    get topLevelNodeBeforeCursor() {
40779      const { anchorNode, offset: offset3 } = this.#getCollapsedSelectionData();
40780      if (!anchorNode) return null;
40781      if ($isTextNode2(anchorNode)) {
40782        if (offset3 === 0) return this.#getPreviousNodeFromTextStart(anchorNode);
40783        if (this.#isCursorOnFirstVisualLineOfBlock(anchorNode)) {
40784          const topLevelElement = anchorNode.getTopLevelElement();
40785          return topLevelElement ? topLevelElement.getPreviousSibling() : null;
40786        }
40787        return null;
40788      }
40789      if ($isElementNode2(anchorNode)) {
40790        return this.#getNodeBeforeElementNode(anchorNode, offset3);
40791      }
40792      return this.#findPreviousSiblingUp(anchorNode);
40793    }
40794    dispose() {
40795      this.editorElement = null;
40796      this.editorContentElement = null;
40797      this.editor = null;
40798      this.previouslySelectedKeys = null;
40799      this.#listeners.dispose();
40800    }
40801    // When all inline code text is deleted, Lexical's selection retains the stale
40802    // code format flag. Verify the flag is backed by actual code-formatted content:
40803    // a code block ancestor or a text node that carries the code format.
40804    #isInCode(selection, anchorNode) {
40805      if ($getNearestNodeOfType2(anchorNode, CodeNode3) !== null) return true;
40806      if (!selection.hasFormat("code")) return false;
40807      return $isTextNode2(anchorNode) && anchorNode.hasFormat("code");
40808    }
40809    // After deleting all inline code text, Lexical preserves the code format on
40810    // the selection even though no code-formatted content remains. This listener
40811    // detects that stale state and clears it so newly typed text won't be
40812    // code-formatted.
40813    #clearStaleInlineCodeFormat() {
40814      this.#listeners.track(this.editor.registerUpdateListener(({ editorState, tags }) => {
40815        if (tags.has("history-merge") || tags.has("skip-dom-selection")) return;
40816        let isStale = false;
40817        editorState.read(() => {
40818          const selection = $getSelection2();
40819          if (!$isRangeSelection2(selection) || !selection.isCollapsed()) return;
40820          if (!selection.hasFormat("code")) return;
40821          const anchorNode = selection.anchor.getNode();
40822          if (this.#isInCode(selection, anchorNode)) return;
40823          isStale = true;
40824        });
40825        if (isStale) {
40826          setTimeout(() => {
40827            this.editor.update(() => {
40828              const selection = $getSelection2();
40829              if (!$isRangeSelection2(selection) || !selection.hasFormat("code")) return;
40830              const anchorNode = selection.anchor.getNode();
40831              if (this.#isInCode(selection, anchorNode)) return;
40832              selection.toggleFormat("code");
40833            });
40834          }, 0);
40835        }
40836      }));
40837    }
40838    get #currentlySelectedKeys() {
40839      if (this.currentlySelectedKeys) {
40840        return this.currentlySelectedKeys;
40841      }
40842      this.currentlySelectedKeys = /* @__PURE__ */ new Set();
40843      const selection = $getSelection2();
40844      if (selection && $isNodeSelection2(selection)) {
40845        for (const node of selection.getNodes()) {
40846          this.currentlySelectedKeys.add(node.getKey());
40847        }
40848      }
40849      return this.currentlySelectedKeys;
40850    }
40851    #processSelectionChangeCommands() {
40852      this.#listeners.track(
40853        this.editor.registerCommand(KEY_ARROW_LEFT_COMMAND2, handlingDefault(this.#selectPreviousNode.bind(this)), COMMAND_PRIORITY_LOW2),
40854        this.editor.registerCommand(KEY_ARROW_RIGHT_COMMAND2, handlingDefault(this.#selectNextNode.bind(this)), COMMAND_PRIORITY_LOW2),
40855        this.editor.registerCommand(KEY_ARROW_UP_COMMAND2, handlingDefault(this.#selectPreviousTopLevelNode.bind(this)), COMMAND_PRIORITY_LOW2),
40856        this.editor.registerCommand(KEY_ARROW_DOWN_COMMAND2, handlingDefault(this.#selectNextTopLevelNode.bind(this)), COMMAND_PRIORITY_LOW2),
40857        this.editor.registerCommand(DELETE_CHARACTER_COMMAND2, this.#selectDecoratorNodeBeforeDeletion.bind(this), COMMAND_PRIORITY_LOW2),
40858        this.editor.registerCommand(SELECTION_CHANGE_COMMAND2, () => {
40859          this.#syncSelectedClasses();
40860        }, COMMAND_PRIORITY_LOW2)
40861      );
40862    }
40863    #listenForNodeSelections() {
40864      this.#listeners.track(this.editor.registerCommand(CLICK_COMMAND2, ({ target }) => {
40865        if (!isDOMNode2(target)) return false;
40866        const targetNode = $getNearestNodeFromDOMNode2(target);
40867        return $isDecoratorNode2(targetNode) && this.#selectInLexical(targetNode);
40868      }, COMMAND_PRIORITY_LOW2));
40869      this.#listeners.track(
40870        this.editor.registerRootListener((rootElement) => {
40871          if (rootElement) {
40872            return registerEventListener(rootElement, "lexxy:internal:move-to-next-line", () => this.#selectOrAppendNextLine());
40873          }
40874        })
40875      );
40876    }
40877    #containEditorFocus() {
40878      this.#listeners.track(
40879        this.editor.registerRootListener((rootElement) => {
40880          if (rootElement) {
40881            const handler = (event) => this.#handleArrowKeyOnLexicalCursor(event);
40882            rootElement.addEventListener("keydown", handler, true);
40883            return () => rootElement.removeEventListener("keydown", handler, true);
40884          }
40885        })
40886      );
40887    }
40888    #handleArrowKeyOnLexicalCursor(event) {
40889      if (event.key === "ArrowUp") {
40890        const lexicalCursor = this.editor.getRootElement().querySelector("[data-lexical-cursor]");
40891        if (lexicalCursor) {
40892          let currentElement = lexicalCursor.previousElementSibling;
40893          while (currentElement && currentElement.hasAttribute("data-lexical-cursor")) {
40894            currentElement = currentElement.previousElementSibling;
40895          }
40896          if (!currentElement) {
40897            event.preventDefault();
40898          }
40899        }
40900      }
40901      if (event.key === "ArrowDown") {
40902        const lexicalCursor = this.editor.getRootElement().querySelector("[data-lexical-cursor]");
40903        if (lexicalCursor) {
40904          let currentElement = lexicalCursor.nextElementSibling;
40905          while (currentElement && currentElement.hasAttribute("data-lexical-cursor")) {
40906            currentElement = currentElement.nextElementSibling;
40907          }
40908          if (!currentElement) {
40909            event.preventDefault();
40910          }
40911        }
40912      }
40913    }
40914    #syncSelectedClasses() {
40915      this.#clearPreviouslyHighlightedItems();
40916      this.#highlightNewItems();
40917      this.previouslySelectedKeys = this.#currentlySelectedKeys;
40918      this.currentlySelectedKeys = null;
40919    }
40920    #clearPreviouslyHighlightedItems() {
40921      for (const key of this.previouslySelectedKeys) {
40922        if (!this.#currentlySelectedKeys.has(key)) {
40923          const dom = this.editor.getElementByKey(key);
40924          if (dom) dom.classList.remove("node--selected");
40925        }
40926      }
40927    }
40928    #highlightNewItems() {
40929      for (const key of this.#currentlySelectedKeys) {
40930        if (!this.previouslySelectedKeys.has(key)) {
40931          const nodeElement = this.editor.getElementByKey(key);
40932          if (nodeElement) nodeElement.classList.add("node--selected");
40933        }
40934      }
40935    }
40936    #selectPreviousNode(event) {
40937      if (event.shiftKey) {
40938        return this.#withCurrentNodeSelectionNode((currentNode) => {
40939          const selection = this.#rangeSelectDecorator(currentNode, "forward");
40940          selection.modify("extend", true, "character");
40941          return true;
40942        });
40943      } else {
40944        return this.#withCurrentNodeSelectionNode((currentNode) => currentNode.selectPrevious()) || this.#selectInLexical(this.nodeBeforeCursor);
40945      }
40946    }
40947    #selectNextNode(event) {
40948      if (event.shiftKey) {
40949        return this.#withCurrentNodeSelectionNode((currentNode) => {
40950          const selection = this.#rangeSelectDecorator(currentNode, "forward");
40951          selection.modify("extend", false, "character");
40952          return true;
40953        });
40954      } else {
40955        return this.#withCurrentNodeSelectionNode((currentNode) => currentNode.selectNext(0, 0)) || this.#selectInLexical(this.nodeAfterCursor);
40956      }
40957    }
40958    #selectPreviousTopLevelNode() {
40959      return this.#withCurrentNodeSelectionNode((currentNode) => currentNode.getTopLevelElement().selectPrevious()) || this.#selectInLexical(this.topLevelNodeBeforeCursor);
40960    }
40961    #selectNextTopLevelNode() {
40962      return this.#withCurrentNodeSelectionNode((currentNode) => currentNode.getTopLevelElement().selectNext(0, 0)) || this.#selectInLexical(this.topLevelNodeAfterCursor);
40963    }
40964    #withCurrentNodeSelectionNode(fn) {
40965      if (this.hasNodeSelection) {
40966        return fn($getSelection2().getNodes()[0]);
40967      }
40968    }
40969    #rangeSelectDecorator(node, direction = "forward") {
40970      if ($isDecoratorNode2(node)) {
40971        const [anchorOffset, focusOffset] = direction === "forward" ? [0, 1] : [1, 0];
40972        const indexAtNode = node.getIndexWithinParent();
40973        return node.getParent().select(indexAtNode + anchorOffset, indexAtNode + focusOffset);
40974      }
40975    }
40976    async #selectOrAppendNextLine() {
40977      this.editor.update(() => {
40978        const topLevelElement = this.#getTopLevelElementFromSelection();
40979        if (!topLevelElement) return;
40980        this.#moveToOrCreateNextLine(topLevelElement);
40981      });
40982    }
40983    #getTopLevelElementFromSelection() {
40984      const selection = $getSelection2();
40985      if (!selection) return null;
40986      if ($isNodeSelection2(selection)) {
40987        return this.#getTopLevelFromNodeSelection(selection);
40988      }
40989      if ($isRangeSelection2(selection)) {
40990        return this.#getTopLevelFromRangeSelection(selection);
40991      }
40992      return null;
40993    }
40994    #getTopLevelFromNodeSelection(selection) {
40995      const nodes = selection.getNodes();
40996      return nodes.length > 0 ? nodes[0].getTopLevelElement() : null;
40997    }
40998    #getTopLevelFromRangeSelection(selection) {
40999      const anchorNode = selection.anchor.getNode();
41000      return anchorNode.getTopLevelElement();
41001    }
41002    #getNearestHeadingNode(anchorNode) {
41003      const topLevelElement = anchorNode.getTopLevelElementOrThrow();
41004      let headingNode = $isHeadingNode2(topLevelElement) ? topLevelElement : null;
41005      if (!headingNode) {
41006        let current = anchorNode.getParent();
41007        while (current) {
41008          if ($isHeadingNode2(current)) {
41009            headingNode = current;
41010            break;
41011          }
41012          current = current.getParent();
41013        }
41014      }
41015      return headingNode;
41016    }
41017    #moveToOrCreateNextLine(topLevelElement) {
41018      const nextSibling = topLevelElement.getNextSibling();
41019      if (nextSibling) {
41020        nextSibling.selectStart();
41021      } else {
41022        this.#createAndSelectNewParagraph();
41023      }
41024    }
41025    #createAndSelectNewParagraph() {
41026      const root = $getRoot2();
41027      const newParagraph = $createParagraphNode2();
41028      root.append(newParagraph);
41029      newParagraph.selectStart();
41030    }
41031    #selectInLexical(node) {
41032      if ($isDecoratorNode2(node)) {
41033        $addUpdateTag2(HISTORY_MERGE_TAG2);
41034        const selection = $createNodeSelectionWith(node);
41035        $setSelection2(selection);
41036        return selection;
41037      } else {
41038        return false;
41039      }
41040    }
41041    #selectDecoratorNodeBeforeDeletion(backwards) {
41042      if (backwards && this.#removeEmptyListItem()) return true;
41043      const node = backwards ? this.nodeBeforeCursor : this.nodeAfterCursor;
41044      if (!$isDecoratorNode2(node)) return false;
41045      if (this.#collapseListItemToParagraph(node)) return true;
41046      this.#removeEmptyElementAnchorNode();
41047      const selection = this.#selectInLexical(node);
41048      return Boolean(selection);
41049    }
41050    // When backspace is pressed on an empty list item that has siblings,
41051    // handle the deletion appropriately:
41052    //
41053    // - Middle/end items (has previous sibling): remove the empty item and
41054    //   place the cursor at the end of the previous sibling. Without this,
41055    //   Lexical's default collapseAtStart converts the empty item into a
41056    //   paragraph above the list, causing the cursor to jump away.
41057    //
41058    // - First item (no previous sibling): convert to a paragraph above the
41059    //   list, matching the standard "unwrap list formatting" behavior that
41060    //   users expect from pressing backspace at the start of a list item.
41061    //   Inside a blockquote we instead just remove the empty item and move
41062    //   the cursor into the next one — stranding a paragraph there would
41063    //   leave the blank line the user is trying to close.
41064    //
41065    // When the empty item is the last/only one in the list, we return false
41066    // and let Lexical's default (convert to paragraph) provide the standard
41067    // "exit list" behavior.
41068    #removeEmptyListItem() {
41069      const selection = $getSelection2();
41070      if (!$isRangeSelection2(selection) || !selection.isCollapsed()) return false;
41071      const anchorNode = selection.anchor.getNode();
41072      const listItem = $getNearestNodeOfType2(anchorNode, ListItemNode2);
41073      if (!listItem) return false;
41074      if (!$isListItemStructurallyEmpty(listItem)) return false;
41075      const nextSibling = listItem.getNextSibling();
41076      if (!nextSibling) return false;
41077      const previousSibling = listItem.getPreviousSibling();
41078      const listNode = $getNearestNodeOfType2(listItem, ListNode2);
41079      if (!listNode) return false;
41080      if (previousSibling) {
41081        previousSibling.selectEnd();
41082        listItem.remove();
41083      } else if ($isQuoteNode2(listNode.getParent())) {
41084        nextSibling.selectStart();
41085        listItem.remove();
41086      } else {
41087        const paragraph = $createParagraphNode2();
41088        listNode.insertBefore(paragraph);
41089        listItem.remove();
41090        paragraph.selectStart();
41091      }
41092      return true;
41093    }
41094    // When the cursor is inside a list item, collapse the list item into a
41095    // paragraph instead of selecting the decorator. This lets the user
41096    // delete a list that immediately follows an attachment without the
41097    // attachment becoming selected. Only applies when the decorator is
41098    // outside the list item (e.g. a block attachment before the list),
41099    // not when it's an inline mention inside the list item.
41100    #collapseListItemToParagraph(decoratorNode) {
41101      const anchorNode = $getSelection2()?.anchor?.getNode();
41102      const listItem = anchorNode && $getNearestNodeOfType2(anchorNode, ListItemNode2);
41103      if (!listItem) return false;
41104      if (listItem.isParentOf(decoratorNode)) return false;
41105      const listNode = $getNearestNodeOfType2(listItem, ListNode2);
41106      if (!listNode) return false;
41107      const paragraph = $createParagraphNode2();
41108      const children = listItem.getChildren();
41109      children.forEach((child) => paragraph.append(child));
41110      if (listNode.getChildrenSize() === 1) {
41111        listNode.insertBefore(paragraph);
41112        listNode.remove();
41113      } else {
41114        listNode.insertBefore(paragraph);
41115        listItem.remove();
41116      }
41117      paragraph.selectStart();
41118      return true;
41119    }
41120    #removeEmptyElementAnchorNode(anchor = $getSelection2()?.anchor) {
41121      const anchorNode = anchor?.getNode();
41122      if ($isElementNode2(anchorNode) && anchorNode?.isEmpty()) anchorNode.remove();
41123    }
41124    #getValidSelectionRange() {
41125      const lexicalSelection = $getSelection2();
41126      if (!lexicalSelection || !lexicalSelection.isCollapsed()) return null;
41127      const nativeSelection = window.getSelection();
41128      if (!nativeSelection || nativeSelection.rangeCount === 0) return null;
41129      return nativeSelection.getRangeAt(0);
41130    }
41131    #getReliableRectFromRange(range2) {
41132      let rect = range2.getBoundingClientRect();
41133      if (this.#isRectUnreliable(rect)) {
41134        const marker = this.#createAndInsertMarker(range2);
41135        rect = marker.getBoundingClientRect();
41136        this.#restoreSelectionAfterMarker(marker);
41137        marker.remove();
41138      }
41139      return rect;
41140    }
41141    #isRectUnreliable(rect) {
41142      return rect.width === 0 && rect.height === 0 || rect.top === 0 && rect.left === 0;
41143    }
41144    #createAndInsertMarker(range2) {
41145      const marker = this.#createMarker();
41146      range2.insertNode(marker);
41147      return marker;
41148    }
41149    #createMarker() {
41150      const marker = document.createElement("span");
41151      marker.textContent = "\u200B";
41152      marker.style.display = "inline-block";
41153      marker.style.width = "1px";
41154      marker.style.height = "1em";
41155      marker.style.lineHeight = "normal";
41156      marker.setAttribute("nonce", getNonce());
41157      return marker;
41158    }
41159    #restoreSelectionAfterMarker(marker) {
41160      const nativeSelection = window.getSelection();
41161      nativeSelection.removeAllRanges();
41162      const newRange = document.createRange();
41163      newRange.setStartAfter(marker);
41164      newRange.collapse(true);
41165      nativeSelection.addRange(newRange);
41166    }
41167    #calculateCursorPosition(rect, range2) {
41168      const rootRect = this.editor.getRootElement().getBoundingClientRect();
41169      const x3 = rect.left - rootRect.left;
41170      let y3 = rect.top - rootRect.top;
41171      const fontSize = this.#getFontSizeForCursor(range2);
41172      if (!isNaN(fontSize)) {
41173        y3 += fontSize;
41174      }
41175      return { x: x3, y: y3, fontSize };
41176    }
41177    #getFontSizeForCursor(range2) {
41178      const nativeSelection = window.getSelection();
41179      const anchorNode = nativeSelection.anchorNode;
41180      const parentElement = this.#getElementFromNode(anchorNode);
41181      if (parentElement instanceof HTMLElement) {
41182        const computed2 = window.getComputedStyle(parentElement);
41183        return parseFloat(computed2.fontSize);
41184      }
41185      return 0;
41186    }
41187    #getElementFromNode(node) {
41188      return node?.nodeType === Node.TEXT_NODE ? node.parentElement : node;
41189    }
41190    #getCollapsedSelectionData() {
41191      const selection = $getSelection2();
41192      if (!$isRangeSelection2(selection) || !selection.isCollapsed()) {
41193        return { anchorNode: null, offset: 0 };
41194      }
41195      const { anchor } = selection;
41196      return { anchorNode: anchor.getNode(), offset: anchor.offset };
41197    }
41198    #getNodeAfterTextNode(anchorNode, offset3) {
41199      if (offset3 === anchorNode.getTextContentSize()) {
41200        return this.#getNextNodeFromTextEnd(anchorNode);
41201      }
41202      return null;
41203    }
41204    #getNextNodeFromTextEnd(anchorNode) {
41205      const nextSibling = anchorNode.getNextSibling();
41206      if ($isDecoratorNode2(nextSibling)) {
41207        return nextSibling;
41208      }
41209      if (nextSibling != null) {
41210        return null;
41211      }
41212      const parent = anchorNode.getParent();
41213      return parent ? parent.getNextSibling() : null;
41214    }
41215    #getNodeAfterElementNode(anchorNode, offset3) {
41216      if (offset3 < anchorNode.getChildrenSize()) {
41217        return anchorNode.getChildAtIndex(offset3);
41218      }
41219      return this.#findNextSiblingUp(anchorNode);
41220    }
41221    #getNodeBeforeTextNode(anchorNode, offset3) {
41222      if (offset3 === 0) {
41223        return this.#getPreviousNodeFromTextStart(anchorNode);
41224      }
41225      return null;
41226    }
41227    #getPreviousNodeFromTextStart(anchorNode) {
41228      const previousSibling = anchorNode.getPreviousSibling();
41229      if ($isDecoratorNode2(previousSibling)) {
41230        return previousSibling;
41231      }
41232      if (previousSibling != null) {
41233        return null;
41234      }
41235      const parent = anchorNode.getParent();
41236      return parent ? parent.getPreviousSibling() : null;
41237    }
41238    #getNodeBeforeElementNode(anchorNode, offset3) {
41239      if (offset3 > 0) {
41240        return anchorNode.getChildAtIndex(offset3 - 1);
41241      }
41242      return this.#findPreviousSiblingUp(anchorNode);
41243    }
41244    #findNextSiblingUp(node) {
41245      let current = node;
41246      while (current && current.getNextSibling() == null) {
41247        current = current.getParent();
41248      }
41249      return current ? current.getNextSibling() : null;
41250    }
41251    #findPreviousSiblingUp(node) {
41252      let current = node;
41253      while (current && current.getPreviousSibling() == null) {
41254        current = current.getParent();
41255      }
41256      return current ? current.getPreviousSibling() : null;
41257    }
41258    #isCursorOnFirstVisualLineOfBlock(anchorNode) {
41259      return this.#isCursorOnEdgeLineOfBlock(anchorNode, "first");
41260    }
41261    #isCursorOnLastVisualLineOfBlock(anchorNode) {
41262      return this.#isCursorOnEdgeLineOfBlock(anchorNode, "last");
41263    }
41264    // Check whether the cursor sits on the first or last visual line of its
41265    // top-level block by comparing the Y position of the cursor with the Y
41266    // position of the block's start (first line) or end (last line).
41267    #isCursorOnEdgeLineOfBlock(anchorNode, edge) {
41268      const topLevelElement = anchorNode.getTopLevelElement();
41269      if (!topLevelElement) return false;
41270      const domElement = this.editor.getElementByKey(topLevelElement.getKey());
41271      if (!domElement) return false;
41272      const nativeSelection = window.getSelection();
41273      if (!nativeSelection?.rangeCount) return false;
41274      const cursorRect = this.#getReliableRectFromRange(nativeSelection.getRangeAt(0));
41275      if (!cursorRect || this.#isRectUnreliable(cursorRect)) return false;
41276      const edgeRect = this.#getEdgeCharRect(domElement, edge);
41277      if (!edgeRect || this.#isRectUnreliable(edgeRect)) return false;
41278      const tolerance = edgeRect.height > 0 ? edgeRect.height * 0.5 : 5;
41279      return Math.abs(cursorRect.top - edgeRect.top) < tolerance;
41280    }
41281    // Get a reliable bounding rect for the first or last character in a DOM
41282    // element by creating a non-collapsed range around it.
41283    #getEdgeCharRect(element, edge) {
41284      const walker = document.createTreeWalker(
41285        element,
41286        4
41287        /* NodeFilter.SHOW_TEXT */
41288      );
41289      let textNode;
41290      if (edge === "first") {
41291        textNode = walker.nextNode();
41292      } else {
41293        while (walker.nextNode()) textNode = walker.currentNode;
41294      }
41295      if (!textNode || textNode.length === 0) return null;
41296      const range2 = document.createRange();
41297      if (edge === "first") {
41298        range2.setStart(textNode, 0);
41299        range2.setEnd(textNode, 1);
41300      } else {
41301        range2.setStart(textNode, textNode.length - 1);
41302        range2.setEnd(textNode, textNode.length);
41303      }
41304      return range2.getBoundingClientRect();
41305    }
41306  };
41307  var EditorConfiguration = class {
41308    #editorElement;
41309    #config;
41310    constructor(editorElement) {
41311      this.#editorElement = editorElement;
41312      this.#config = new Configuration(
41313        Lexxy.presets.get("default"),
41314        Lexxy.presets.get(editorElement.preset),
41315        this.#overrides
41316      );
41317    }
41318    get(path) {
41319      return this.#config.get(path);
41320    }
41321    get #overrides() {
41322      const overrides = {};
41323      for (const option of this.#defaultOptions) {
41324        const attribute = dasherize(option);
41325        if (this.#editorElement.hasAttribute(attribute)) {
41326          overrides[option] = this.#parseAttribute(attribute);
41327        }
41328      }
41329      return overrides;
41330    }
41331    get #defaultOptions() {
41332      return Object.keys(Lexxy.presets.get("default"));
41333    }
41334    #parseAttribute(attribute) {
41335      const value = this.#editorElement.getAttribute(attribute);
41336      try {
41337        return JSON.parse(value);
41338      } catch {
41339        return value;
41340      }
41341    }
41342  };
41343  var ImageGalleryNode = class _ImageGalleryNode extends ElementNode2 {
41344    $config() {
41345      return this.config("image_gallery", {
41346        extends: ElementNode2
41347      });
41348    }
41349    static transform() {
41350      return (gallery) => {
41351        gallery.unwrapEmptyNode() || gallery.replaceWithSingularChild() || gallery.splitAroundInvalidChild();
41352      };
41353    }
41354    static importDOM() {
41355      return {
41356        div: (element) => {
41357          if (!this.#isGalleryElement(element)) return null;
41358          return {
41359            conversion: () => {
41360              return {
41361                node: $createImageGalleryNode()
41362              };
41363            },
41364            priority: 2
41365          };
41366        }
41367      };
41368    }
41369    static canCollapseWith(node) {
41370      return $isImageGalleryNode(node) || this.isValidChild(node);
41371    }
41372    static isValidChild(node) {
41373      return $isActionTextAttachmentNode(node) && node.isPreviewableImage;
41374    }
41375    static #isGalleryElement(element) {
41376      const attachmentChildren = element.querySelectorAll(`:scope > :is(${this.#attachmentTags.join()})`);
41377      return element.textContent.trim() === "" && attachmentChildren.length > 0 && element.children.length === attachmentChildren.length;
41378    }
41379    static get #attachmentTags() {
41380      return Object.keys(ActionTextAttachmentNode.importDOM());
41381    }
41382    createDOM() {
41383      const div = document.createElement("div");
41384      div.className = this.#galleryClassNames;
41385      return div;
41386    }
41387    updateDOM(_prevNode, dom) {
41388      dom.className = this.#galleryClassNames;
41389      return false;
41390    }
41391    canBeEmpty() {
41392      return true;
41393    }
41394    collapseAtStart(_selection) {
41395      return true;
41396    }
41397    insertNewAfter(selection, restoreSelection) {
41398      const selectionBeforeLastChild = selection.anchor.getNode().is(this) && selection.anchor.offset == this.getChildrenSize() - 1;
41399      if (selectionBeforeLastChild) {
41400        const paragraph = $createParagraphNode2();
41401        this.insertAfter(paragraph, false);
41402        paragraph.insertAfter(this.getLastChild(), false);
41403        paragraph.selectEnd();
41404        return null;
41405      }
41406      const newNode = $createImageGalleryNode();
41407      this.insertAfter(newNode, restoreSelection);
41408      return newNode;
41409    }
41410    getImageAttachments() {
41411      const children = this.getChildren();
41412      return children.filter($isActionTextAttachmentNode);
41413    }
41414    exportDOM() {
41415      const div = document.createElement("div");
41416      div.className = this.#galleryClassNames;
41417      return { element: div };
41418    }
41419    collapseWith(node, backwards) {
41420      if (!_ImageGalleryNode.canCollapseWith(node)) return false;
41421      if (backwards) {
41422        $insertFirst2(this, node);
41423      } else {
41424        this.append(node);
41425      }
41426      $unwrapAndFilterDescendants2(this, _ImageGalleryNode.isValidChild);
41427      return true;
41428    }
41429    unwrapEmptyNode() {
41430      if (this.isEmpty()) {
41431        const paragraph = $createParagraphNode2();
41432        return this.replace(paragraph);
41433      }
41434    }
41435    replaceWithSingularChild() {
41436      if (this.#hasSingularChild) {
41437        const child = this.getFirstChild();
41438        return this.replace($makeSafeForRoot(child));
41439      }
41440    }
41441    splitAroundInvalidChild() {
41442      for (const child of $firstToLastIterator2(this)) {
41443        if (_ImageGalleryNode.isValidChild(child)) continue;
41444        const poppedNode = $makeSafeForRoot(child);
41445        const [topGallery, secondGallery] = this.splitAtIndex(poppedNode.getIndexWithinParent());
41446        topGallery.insertAfter(poppedNode);
41447        poppedNode.selectEnd();
41448        if (secondGallery.isEmpty()) secondGallery.remove();
41449        break;
41450      }
41451    }
41452    splitAtIndex(index) {
41453      return $splitNode2(this, index);
41454    }
41455    get #hasSingularChild() {
41456      return this.getChildrenSize() === 1;
41457    }
41458    get #galleryClassNames() {
41459      return `attachment-gallery attachment-gallery--${this.getChildrenSize()}`;
41460    }
41461  };
41462  function $createImageGalleryNode() {
41463    return new ImageGalleryNode();
41464  }
41465  function $isImageGalleryNode(node) {
41466    return node instanceof ImageGalleryNode;
41467  }
41468  function $findOrCreateGalleryForImage(node) {
41469    if (!ImageGalleryNode.canCollapseWith(node)) return null;
41470    const existingGallery = $getNearestNodeOfType2(node, ImageGalleryNode);
41471    return existingGallery ?? $wrapNodeInElement2(node, $createImageGalleryNode);
41472  }
41473  var Uploader = class _Uploader {
41474    #files;
41475    static for(editorElement, files, options = {}) {
41476      const UploaderKlass = GalleryUploader.handle(editorElement, files) ? GalleryUploader : _Uploader;
41477      return new UploaderKlass(editorElement, files, options);
41478    }
41479    constructor(editorElement, files, options = {}) {
41480      this.#files = files;
41481      this.options = options;
41482      this.editorElement = editorElement;
41483      this.contents = editorElement.contents;
41484      this.selection = editorElement.selection;
41485    }
41486    get files() {
41487      return Array.from(this.#files);
41488    }
41489    $uploadFiles() {
41490      this.$createUploadNodes();
41491      this.$insertUploadNodes();
41492    }
41493    $createUploadNodes() {
41494      this.nodes = this.files.map((file) => this.#createUploadNode(file));
41495    }
41496    #createUploadNode(file) {
41497      return this.options.pending ? this.contents.$createPendingUploadNode(file) : this.contents.$createUploadNode(file);
41498    }
41499    $insertUploadNodes() {
41500      this.contents.insertAtCursor(...this.nodes);
41501    }
41502  };
41503  var GalleryUploader = class extends Uploader {
41504    #gallery;
41505    static handle(editorElement, files) {
41506      return this.isMultipleImageUpload(files) || this.gallerySelection(editorElement.selection);
41507    }
41508    static isMultipleImageUpload(files) {
41509      let imageFileCount = 0;
41510      for (const file of files) {
41511        if (isPreviewableImage(file.type)) imageFileCount++;
41512        if (imageFileCount > 1) return true;
41513      }
41514      return false;
41515    }
41516    static gallerySelection(selection) {
41517      return selection.isOnPreviewableImage || this.selectionIsAfterGalleryEdge(selection);
41518    }
41519    static selectionIsAfterGalleryEdge(selection) {
41520      return selection.isAtNodeStart && ImageGalleryNode.canCollapseWith(selection.nodeBeforeCursor);
41521    }
41522    $insertUploadNodes() {
41523      this.#findOrCreateGallery();
41524      this.#insertImagesInGallery();
41525      this.#insertNonImagesAfterGallery();
41526    }
41527    #findOrCreateGallery() {
41528      if (this.selection.isOnPreviewableImage) {
41529        this.#gallery = $findOrCreateGalleryForImage(this.selection.previewableImageNode);
41530      } else if (this.#selectionIsAfterGalleryEdge) {
41531        this.#gallery = $findOrCreateGalleryForImage(this.selection.nodeBeforeCursor);
41532      } else {
41533        this.#gallery = $createImageGalleryNode();
41534        this.contents.insertAtCursor(this.#gallery);
41535      }
41536    }
41537    get #selectionIsAfterGalleryEdge() {
41538      return this.constructor.selectionIsAfterGalleryEdge(this.selection);
41539    }
41540    get #selectedNode() {
41541      const { node } = this.selection.selectedNodeWithOffset();
41542      return node;
41543    }
41544    get #galleryInsertPosition() {
41545      if (this.#selectionIsAfterGalleryEdge) return this.#gallery.getChildrenSize();
41546      const anchor = $getSelection2()?.anchor;
41547      const galleryHasElementSelection = anchor?.getNode().is(this.#gallery);
41548      if (galleryHasElementSelection) return anchor.offset;
41549      const selectedNode = this.#selectedNode;
41550      const childIndex = this.#gallery.isParentOf(selectedNode) && selectedNode.getIndexWithinParent();
41551      return childIndex !== false ? childIndex + 1 : 0;
41552    }
41553    get #imageNodes() {
41554      return this.nodes.filter((node) => ImageGalleryNode.isValidChild(node));
41555    }
41556    get #nonImageNodes() {
41557      return this.nodes.filter((node) => !ImageGalleryNode.isValidChild(node));
41558    }
41559    #insertImagesInGallery() {
41560      this.#gallery.splice(this.#galleryInsertPosition, 0, this.#imageNodes);
41561    }
41562    #insertNonImagesAfterGallery() {
41563      let beforeNode = this.#gallery;
41564      for (const node of this.#nonImageNodes) {
41565        beforeNode.insertAfter(node);
41566        beforeNode = node;
41567      }
41568    }
41569  };
41570  async function loadFileIntoImage(file, image) {
41571    return new Promise((resolve) => {
41572      const reader = new FileReader();
41573      image.addEventListener("load", () => {
41574        resolve(image);
41575      });
41576      reader.onload = (event) => {
41577        image.src = event.target.result || null;
41578      };
41579      reader.readAsDataURL(file);
41580    });
41581  }
41582  var ActionTextAttachmentUploadNode = class _ActionTextAttachmentUploadNode extends ActionTextAttachmentNode {
41583    static getType() {
41584      return "action_text_attachment_upload";
41585    }
41586    static clone(node) {
41587      return new _ActionTextAttachmentUploadNode({ ...node }, node.__key);
41588    }
41589    static importJSON(serializedNode) {
41590      return new _ActionTextAttachmentUploadNode({ ...serializedNode });
41591    }
41592    // Should never run since this is a transient node. Defined to remove console warning.
41593    static importDOM() {
41594      return null;
41595    }
41596    constructor(node, key) {
41597      const { file, uploadUrl, blobUrlTemplate, progress, width, height, uploadError, fileName, contentType } = node;
41598      super({ ...node, contentType: file?.type ?? contentType }, key);
41599      this.file = file ?? null;
41600      this.fileName = file?.name ?? fileName;
41601      this.uploadUrl = uploadUrl;
41602      this.blobUrlTemplate = blobUrlTemplate;
41603      this.progress = progress ?? null;
41604      this.width = width;
41605      this.height = height;
41606      this.uploadError = uploadError;
41607    }
41608    createDOM() {
41609      if (this.uploadError) return this.createDOMForError();
41610      this.#startUploadIfNeeded();
41611      const canPreviewFile = this.isPreviewableAttachment && !this.isPdf && this.uploadUrl != null;
41612      const canPreviewAudio = this.isAudio && this.file && this.uploadUrl != null;
41613      const canPreviewPdf = this.isPdf && this.file && this.uploadUrl != null;
41614      const figure = this.createAttachmentFigure(canPreviewFile || canPreviewAudio || canPreviewPdf);
41615      if (canPreviewFile) {
41616        const img = figure.appendChild(this.#createDOMForImage());
41617        loadFileIntoImage(this.file, img).then((img2) => this.#setDimensionsFromImage(img2));
41618      } else if (canPreviewAudio) {
41619        figure.appendChild(this.#createDOMForAudio(URL.createObjectURL(this.file)));
41620      } else if (canPreviewPdf) {
41621        figure.appendChild(this.#createDOMForPdf(URL.createObjectURL(this.file)));
41622      } else {
41623        figure.appendChild(this.#createDOMForFile());
41624      }
41625      figure.appendChild(this.#createCaption());
41626      figure.appendChild(this.#createProgressBar());
41627      return figure;
41628    }
41629    updateDOM(prevNode, dom) {
41630      if (this.uploadError !== prevNode.uploadError) return true;
41631      if (prevNode.progress !== this.progress) {
41632        const progress = dom.querySelector("progress");
41633        progress.value = this.progress ?? 0;
41634      }
41635      return false;
41636    }
41637    exportDOM() {
41638      return { element: null };
41639    }
41640    exportJSON() {
41641      return {
41642        ...super.exportJSON(),
41643        type: "action_text_attachment_upload",
41644        version: 1,
41645        fileName: this.fileName,
41646        contentType: this.contentType,
41647        uploadUrl: this.uploadUrl,
41648        blobUrlTemplate: this.blobUrlTemplate,
41649        progress: this.progress,
41650        width: this.width,
41651        height: this.height,
41652        uploadError: this.uploadError
41653      };
41654    }
41655    get #uploadStarted() {
41656      return this.progress !== null;
41657    }
41658    #createDOMForImage() {
41659      return createElement("img");
41660    }
41661    #createDOMForFile() {
41662      const extension = this.#getFileExtension();
41663      const span = createElement("span", { className: "attachment__icon", textContent: extension });
41664      return span;
41665    }
41666    #createDOMForAudio(src = this.src) {
41667      const audio = createElement("audio", { src, controls: true, preload: "metadata" });
41668      const container = createElement("div", { className: "attachment__container" });
41669      container.appendChild(audio);
41670      return container;
41671    }
41672    #createDOMForPdf(src) {
41673      const iframe = createElement("iframe", {
41674        src,
41675        title: this.fileName || "PDF",
41676        loading: "lazy"
41677      });
41678      const container = createElement("div", { className: "attachment__container attachment__pdf-frame" });
41679      container.appendChild(iframe);
41680      return container;
41681    }
41682    #getFileExtension() {
41683      return (this.fileName || "").split(".").pop().toLowerCase();
41684    }
41685    #createCaption() {
41686      const figcaption = createElement("figcaption", { className: "attachment__caption" });
41687      const nameSpan = createElement("span", { className: "attachment__name", textContent: this.caption || this.fileName || "" });
41688      const sizeSpan = createElement("span", { className: "attachment__size", textContent: bytesToHumanSize(this.file?.size) });
41689      figcaption.appendChild(nameSpan);
41690      figcaption.appendChild(sizeSpan);
41691      return figcaption;
41692    }
41693    #createProgressBar() {
41694      return createElement("progress", { value: this.progress ?? 0, max: 100 });
41695    }
41696    #setDimensionsFromImage({ width, height }) {
41697      if (this.#hasDimensions) return;
41698      this.patchAndRewriteHistory({ width, height });
41699    }
41700    get #hasDimensions() {
41701      return Boolean(this.width && this.height);
41702    }
41703    async #startUploadIfNeeded() {
41704      if (this.#uploadStarted) return;
41705      if (!this.uploadUrl) return;
41706      this.#setUploadStarted();
41707      const { DirectUpload: DirectUpload3 } = await Promise.resolve().then(() => (init_activestorage_esm(), activestorage_esm_exports));
41708      const upload = new DirectUpload3(this.file, this.uploadUrl, this);
41709      upload.delegate = this.#createUploadDelegate();
41710      this.#dispatchEvent("lexxy:upload-start", { file: this.file });
41711      upload.create((error, blob) => {
41712        this.#forgetUploadRequest();
41713        if (error) {
41714          this.#dispatchEvent("lexxy:upload-end", { file: this.file, error });
41715          this.#handleUploadError(error);
41716        } else {
41717          this.#dispatchEvent("lexxy:upload-end", { file: this.file, error: null });
41718          this.editor.update(() => {
41719            this.$showUploadedAttachment(blob);
41720          });
41721        }
41722      });
41723    }
41724    #createUploadDelegate() {
41725      const shouldAuthenticateUploads = Lexxy.global.get("authenticatedUploads");
41726      return {
41727        directUploadWillCreateBlobWithXHR: (request) => {
41728          if (shouldAuthenticateUploads) request.withCredentials = true;
41729        },
41730        directUploadWillStoreFileWithXHR: (request) => {
41731          if (shouldAuthenticateUploads) request.withCredentials = true;
41732          this.#rememberUploadRequest(request);
41733          const uploadProgressHandler = (event) => this.#handleUploadProgress(event, request);
41734          request.upload.addEventListener("progress", uploadProgressHandler);
41735        }
41736      };
41737    }
41738    #forgetUploadRequest() {
41739      this.#editorElement?.uploadRequests.forget(this.getKey());
41740    }
41741    #rememberUploadRequest(request) {
41742      this.#editorElement?.uploadRequests.track(this.getKey(), request);
41743    }
41744    get #editorElement() {
41745      return this.editor.getRootElement()?.closest("lexxy-editor");
41746    }
41747    #setUploadStarted() {
41748      this.#setProgress(1);
41749    }
41750    #handleUploadProgress(event, request) {
41751      const progress = Math.round(event.loaded / event.total * 100);
41752      try {
41753        this.#setProgress(progress);
41754        this.#dispatchEvent("lexxy:upload-progress", { file: this.file, progress });
41755      } catch {
41756        request.abort();
41757      }
41758    }
41759    #setProgress(progress) {
41760      this.patchAndRewriteHistory({ progress });
41761    }
41762    #handleUploadError(error) {
41763      console.warn(`Upload error for ${this.file?.name ?? "file"}: ${error}`);
41764      this.patchAndRewriteHistory({ uploadError: true });
41765    }
41766    $showUploadedAttachment(blob) {
41767      const previewSrc = this.isPreviewableImage && this.file ? URL.createObjectURL(this.file) : null;
41768      const replacementNode = this.#toActionTextAttachmentNodeWith(blob, previewSrc);
41769      this.replaceAndRewriteHistory(replacementNode);
41770      return replacementNode.getKey();
41771    }
41772    #toActionTextAttachmentNodeWith(blob, previewSrc) {
41773      const conversion = new AttachmentNodeConversion(this, blob, previewSrc);
41774      return conversion.toAttachmentNode();
41775    }
41776    #dispatchEvent(name, detail) {
41777      const figure = this.editor.getElementByKey(this.getKey());
41778      if (figure) dispatch(figure, name, detail);
41779    }
41780  };
41781  var AttachmentNodeConversion = class {
41782    constructor(uploadNode, blob, previewSrc) {
41783      this.uploadNode = uploadNode;
41784      this.blob = blob;
41785      this.previewSrc = previewSrc;
41786    }
41787    toAttachmentNode() {
41788      return new ActionTextAttachmentNode({
41789        ...this.uploadNode,
41790        ...this.#propertiesFromBlob,
41791        src: this.#src,
41792        blobSrc: this.#pdfBlob ? this.#blobSrc : null,
41793        previewSrc: this.previewSrc,
41794        pendingPreview: this.blob.previewable && !this.uploadNode.isPreviewableImage && !this.#pdfBlob
41795      });
41796    }
41797    get #propertiesFromBlob() {
41798      const { blob } = this;
41799      return {
41800        sgid: blob.attachable_sgid,
41801        altText: blob.filename,
41802        contentType: blob.content_type,
41803        fileName: blob.filename,
41804        fileSize: blob.byte_size,
41805        previewable: blob.previewable,
41806        previewStatusUrl: blob.preview_status_url
41807      };
41808    }
41809    get #src() {
41810      return this.blob.previewable ? this.blob.url : this.#blobSrc;
41811    }
41812    get #blobSrc() {
41813      return this.uploadNode.blobUrlTemplate.replace(":signed_id", this.blob.signed_id).replace(":filename", encodeURIComponent(this.blob.filename));
41814    }
41815    get #pdfBlob() {
41816      const contentType = this.blob.content_type || this.uploadNode.contentType || "";
41817      const fileName = this.blob.filename || this.uploadNode.fileName || "";
41818      return contentType === "application/pdf" || fileName.toLowerCase().endsWith(".pdf");
41819    }
41820  };
41821  function $createActionTextAttachmentUploadNode(...args) {
41822    return new ActionTextAttachmentUploadNode(...args);
41823  }
41824  var BaseNodeInserter = class {
41825    constructor(selection) {
41826      this.selection = selection;
41827    }
41828  };
41829  var CodeNodeInserter = class extends BaseNodeInserter {
41830    static handles(selection) {
41831      return $getNearestNodeOfType2(selection.anchor?.getNode(), CodeNode3);
41832    }
41833    insertNodes(nodes) {
41834      if (!this.selection.isCollapsed()) {
41835        this.selection.removeText();
41836      }
41837      $ensureForwardRangeSelection2(this.selection);
41838      const focusNode = this.selection.focus.getNode();
41839      const codeNode = $getNearestNodeOfType2(focusNode, CodeNode3);
41840      const insertionIndex = focusNode.is(codeNode) ? 0 : focusNode.getIndexWithinParent();
41841      const caret = $getChildCaretAtIndex2(codeNode, insertionIndex + 1, "previous");
41842      const existingNodes = new Set(nodes.filter((node) => node.isAttached()));
41843      const trailingNodes = [];
41844      for (const node of nodes) {
41845        if (existingNodes.has(node)) {
41846          if (!node.isAttached()) continue;
41847        } else if (!this.#canJoinCodeBlock(node)) {
41848          trailingNodes.push(node);
41849          continue;
41850        }
41851        if (caret.getNodeAtCaret() && $isElementNode2(node)) {
41852          caret.insert($createLineBreakNode2());
41853        }
41854        caret.insert(this.#convertNodeToCodeChild(node));
41855      }
41856      const lastTrailingNode = this.#insertAfterCodeBlock(codeNode, trailingNodes);
41857      const nodeToSelect = lastTrailingNode ?? caret.getNodeAtCaret();
41858      nodeToSelect?.selectEnd();
41859    }
41860    #canJoinCodeBlock(node) {
41861      return $isTextNode2(node) || $isLineBreakNode2(node);
41862    }
41863    #insertAfterCodeBlock(codeNode, nodes) {
41864      let previousNode = codeNode;
41865      for (const node of nodes) {
41866        previousNode.insertAfter(node);
41867        previousNode = node;
41868      }
41869      return nodes.at(-1);
41870    }
41871    #convertNodeToCodeChild(node) {
41872      if ($isLineBreakNode2(node)) {
41873        return node;
41874      } else {
41875        node.remove();
41876        return $createTextNode2(node.getTextContent());
41877      }
41878    }
41879  };
41880  var ShadowRootNodeInserter = class extends BaseNodeInserter {
41881    static handles(selection) {
41882      return $isShadowRoot(selection?.anchor?.getNode());
41883    }
41884    insertNodes(nodes) {
41885      const anchorNode = this.selection.anchor.getNode();
41886      const paragraph = $createParagraphNode2();
41887      anchorNode.append(paragraph);
41888      paragraph.selectStart().insertNodes(nodes);
41889    }
41890  };
41891  var NodeSelectionNodeInserter = class extends BaseNodeInserter {
41892    static handles(selection) {
41893      return $isNodeSelection2(selection) && selection.getNodes().length > 0;
41894    }
41895    insertNodes(nodes) {
41896      let lastNode = this.selection.getNodes().at(-1);
41897      for (const node of nodes) {
41898        const nodeToInsert = this.#insertsIntoRoot(lastNode) ? $makeSafeForRoot(node) : node;
41899        lastNode = lastNode.insertAfter(nodeToInsert);
41900      }
41901    }
41902    #insertsIntoRoot(node) {
41903      return node.is(node.getTopLevelElement());
41904    }
41905  };
41906  var ListItemNodeInserter = class extends BaseNodeInserter {
41907    static handles(selection) {
41908      return $isRangeSelection2(selection) && $getNearestNodeOfType2(selection.anchor.getNode(), ListItemNode2);
41909    }
41910    insertNodes(nodes) {
41911      if (nodes.some((node) => this.#isBlockDecorator(node))) {
41912        this.#insertAroundList(nodes);
41913      } else {
41914        this.selection.insertNodes(nodes);
41915      }
41916    }
41917    #insertAroundList(nodes) {
41918      if (!this.selection.isCollapsed()) {
41919        this.selection.removeText();
41920      }
41921      const anchorNode = this.selection.anchor.getNode();
41922      const outerList = this.#outermostList(anchorNode);
41923      const topItem = this.#topLevelItemFor(anchorNode, outerList);
41924      const splitAfterItem = $isBlankNode(topItem) ? topItem.getPreviousSibling() : topItem;
41925      const splitIndex = splitAfterItem ? splitAfterItem.getIndexWithinParent() + 1 : 0;
41926      const [listBefore, listAfter] = $splitNode2(outerList, splitIndex);
41927      if ($isBlankNode(topItem)) {
41928        topItem.remove();
41929      }
41930      let anchor = listBefore ?? listAfter;
41931      for (const node of nodes) {
41932        anchor.insertAfter(node);
41933        anchor = node;
41934      }
41935      this.#removeEmptyList(listBefore);
41936      this.#removeEmptyList(listAfter);
41937      nodes.at(-1).selectNext();
41938    }
41939    #outermostList(node) {
41940      return [node, ...node.getParents()].reverse().find($isListNode2);
41941    }
41942    #topLevelItemFor(node, outerList) {
41943      return [node, ...node.getParents()].find(
41944        (ancestor) => $isListItemNode2(ancestor) && ancestor.getParent()?.is(outerList)
41945      );
41946    }
41947    #removeEmptyList(list) {
41948      if ($isListNode2(list) && list.isEmpty()) list.remove();
41949    }
41950    // Only block decorator nodes (image/file attachments) are intercepted. A list
41951    // item cannot hold them, so they must break out. Pasted element blocks
41952    // (paragraphs, quotes) keep Lexical's own list-escape semantics.
41953    #isBlockDecorator(node) {
41954      return $isDecoratorNode2(node) && !node.isInline();
41955    }
41956  };
41957  var BlockContainerNodeInserter = class extends BaseNodeInserter {
41958    static handles(selection) {
41959      return $hasPointOnBlockContainer(selection);
41960    }
41961    insertNodes(nodes) {
41962      $normalizeSelection__EXPERIMENTAL(this.selection);
41963      this.selection.insertNodes(nodes);
41964    }
41965  };
41966  var INSERTERS = [
41967    CodeNodeInserter,
41968    ShadowRootNodeInserter,
41969    NodeSelectionNodeInserter,
41970    ListItemNodeInserter,
41971    BlockContainerNodeInserter
41972  ];
41973  BaseNodeInserter.for = (selection) => {
41974    const inserterClass = INSERTERS.find((inserter) => inserter.handles(selection));
41975    return inserterClass ? new inserterClass(selection) : selection;
41976  };
41977  var PastedContentFormatter = class {
41978    constructor(doc) {
41979      this.doc = doc;
41980    }
41981    format() {
41982      this.#stripStyleElements();
41983      this.#unwrapPlaceholderAnchors();
41984      this.#stripTableCellColorStyles();
41985      this.#nestStrayListChildren();
41986      this.#stripStrayListChildren();
41987      return this.doc;
41988    }
41989    // Spreadsheets (e.g. Excel) copy a <style> block whose rules (td { color:
41990    // black }, .xlNN { ... }) cascade onto the imported text. That color rides
41991    // in through the cascade rather than an inline style, so it slips past both
41992    // the cell-level stripping below and the paste style canonicalizer, leaving
41993    // pasted tables with foreign text colors that don't adapt to the theme. Drop
41994    // foreign style sheets so nothing cascades into imported content.
41995    #stripStyleElements() {
41996      for (const style of this.doc.querySelectorAll("style")) {
41997        style.remove();
41998      }
41999    }
42000    // Anchors with non-meaningful hrefs (e.g. "#", "") appear in content copied
42001    // from rendered views where mentions and interactive elements are wrapped in
42002    // <a href="#"> tags. Unwrap them so their text content pastes as plain text
42003    // and real links are preserved.
42004    #unwrapPlaceholderAnchors() {
42005      for (const anchor of this.doc.querySelectorAll("a")) {
42006        const href = anchor.getAttribute("href") || "";
42007        if (href === "" || href === "#") {
42008          anchor.replaceWith(...anchor.childNodes);
42009        }
42010      }
42011    }
42012    // Table cells copied from a page inherit the source theme's inline color
42013    // styles (e.g. dark-mode backgrounds). Strip them so pasted tables adopt
42014    // the current theme instead of carrying stale colors.
42015    #stripTableCellColorStyles() {
42016      for (const cell of this.doc.querySelectorAll("td, th")) {
42017        cell.style.removeProperty("background-color");
42018        cell.style.removeProperty("background");
42019        cell.style.removeProperty("color");
42020      }
42021    }
42022    // Some sources (e.g. Gmail) nest a sublist as a direct child of the parent
42023    // <ol>/<ul> instead of inside a <li>. Move each nested list into its
42024    // preceding <li> so the import preserves the nesting instead of dropping it.
42025    #nestStrayListChildren() {
42026      for (const list of this.doc.querySelectorAll("ol, ul")) {
42027        for (const child of Array.from(list.children)) {
42028          if (child.tagName !== "OL" && child.tagName !== "UL") continue;
42029          const previousItem = child.previousElementSibling;
42030          if (previousItem && previousItem.tagName === "LI") {
42031            previousItem.appendChild(child);
42032          }
42033        }
42034      }
42035    }
42036    // Only <li> is a valid child of a list; drop stray <br>/whitespace so the
42037    // import doesn't wrap them into an empty leading item.
42038    #stripStrayListChildren() {
42039      for (const list of this.doc.querySelectorAll("ol, ul")) {
42040        for (const child of Array.from(list.childNodes)) {
42041          if (child.nodeType === Node.ELEMENT_NODE && child.tagName === "LI") continue;
42042          list.removeChild(child);
42043        }
42044      }
42045    }
42046  };
42047  var Contents = class {
42048    constructor(editorElement) {
42049      this.editorElement = editorElement;
42050      this.editor = editorElement.editor;
42051    }
42052    dispose() {
42053      this.editorElement = null;
42054      this.editor = null;
42055    }
42056    get selection() {
42057      return this.editorElement.selection;
42058    }
42059    insertHtml(html2, { tag } = {}) {
42060      this.insertDOM(parseHtml(html2), { tag });
42061    }
42062    insertDOM(doc, { tag } = {}) {
42063      this.editor.update(() => {
42064        if ($hasUpdateTag2(PASTE_TAG2)) this.#formatPastedDOM(doc);
42065        const nodes = this.editorElement.$generateNodesFromDOM(doc);
42066        if (!$hasUpdateTag2(PASTE_TAG2) || !this.#dispatchPastedNodesCommand(nodes)) {
42067          this.#insertUploadNodes(nodes) || this.insertAtCursor(...nodes);
42068        }
42069      }, { tag });
42070    }
42071    insertText(text2, { tag } = {}) {
42072      this.editor.update(() => {
42073        const paragraph = $createParagraphNode2();
42074        text2.split("\n").forEach((line, index) => {
42075          if (index > 0) paragraph.append($createLineBreakNode2());
42076          paragraph.append($createTextNode2(line));
42077        });
42078        this.insertAtCursor(paragraph);
42079      }, { tag });
42080    }
42081    insertAtCursor(...nodes) {
42082      const selection = this.#insertableSelection();
42083      const inserter = BaseNodeInserter.for(selection);
42084      inserter.insertNodes(nodes);
42085    }
42086    applyParagraphFormat() {
42087      const selection = $getSelection2();
42088      if (!$isRangeSelection2(selection)) return;
42089      $expandSelectionToLineBreaksAndSplitAtEdges(selection, (node) => $getNearestBlockElementAncestorOrThrow2(node));
42090      $setBlocksType2(selection, () => $createParagraphNode2());
42091    }
42092    applyHeadingFormat(tag) {
42093      const selection = $getSelection2();
42094      if (!$isRangeSelection2(selection)) return;
42095      $expandSelectionToLineBreaksAndSplitAtEdges(selection, (node) => $getNearestBlockElementAncestorOrThrow2(node));
42096      $setBlocksType2(selection, () => $createHeadingNode2(tag));
42097    }
42098    applyUnorderedListFormat() {
42099      this.#applyListFormat("bullet", INSERT_UNORDERED_LIST_COMMAND2);
42100    }
42101    applyOrderedListFormat() {
42102      this.#applyListFormat("number", INSERT_ORDERED_LIST_COMMAND2);
42103    }
42104    clearFormatting() {
42105      const selection = $getSelection2();
42106      if (!$isRangeSelection2(selection)) return;
42107      $forEachSelectedTextNode2((node) => {
42108        node.setFormat(0);
42109        node.setStyle("");
42110      });
42111      $toggleLink2(null);
42112      this.#topLevelElementsInSelection(selection).filter($isQuoteNode2).forEach((node) => this.#unwrap(node));
42113      $setBlocksType2(selection, () => $createParagraphNode2());
42114    }
42115    toggleCodeBlock() {
42116      const selection = $getSelection2();
42117      if (!$isRangeSelection2(selection)) return;
42118      if (this.#insertNodeIfRoot($createCodeNode3("plain"))) return;
42119      const blockElements = this.#blockLevelElementsInSelection(selection);
42120      const allCode = blockElements.every($isCodeNode3);
42121      if (allCode) {
42122        blockElements.forEach((node) => this.#unwrapCodeBlock(node));
42123      } else {
42124        $expandSelectionToLineBreaksAndSplitAtEdges(selection);
42125        const elements = this.#outermostElements(this.#blockLevelElementsInSelection(selection));
42126        if (elements.length === 0) return;
42127        const codeNode = $createCodeNode3("plain");
42128        elements.at(-1).insertAfter(codeNode);
42129        codeNode.selectEnd();
42130        this.insertAtCursor(...elements);
42131      }
42132    }
42133    toggleBlockquote() {
42134      const selection = $getSelection2();
42135      if (!$isRangeSelection2(selection)) return;
42136      if (this.#insertNodeIfRoot($createQuoteNode2())) return;
42137      const topLevelElements = this.#topLevelElementsInSelection(selection);
42138      const allQuoted = topLevelElements.length > 0 && topLevelElements.every($isQuoteNode2);
42139      if (allQuoted) {
42140        topLevelElements.forEach((node) => this.#unwrap(node));
42141      } else {
42142        topLevelElements.filter($isQuoteNode2).forEach((node) => this.#unwrap(node));
42143        $expandSelectionToLineBreaksAndSplitAtEdges(selection);
42144        const elements = this.#topLevelElementsInSelection(selection);
42145        if (elements.length === 0) return;
42146        const blockquote = $createQuoteNode2();
42147        elements[0].insertBefore(blockquote);
42148        elements.forEach((element) => blockquote.append(element));
42149      }
42150    }
42151    hasSelectedText() {
42152      let result = false;
42153      this.editor.read(() => {
42154        const selection = $getSelection2();
42155        result = $isRangeSelection2(selection) && !selection.isCollapsed();
42156      });
42157      return result;
42158    }
42159    createLink(url) {
42160      let linkNodeKey = null;
42161      this.editor.update(() => {
42162        const textNode = $createTextNode2(url);
42163        const linkNode = $createLinkNode2(url);
42164        linkNode.append(textNode);
42165        const selection = $getSelection2();
42166        if ($isRangeSelection2(selection)) {
42167          BaseNodeInserter.for(selection).insertNodes([linkNode]);
42168          linkNodeKey = linkNode.getKey();
42169        }
42170      });
42171      return linkNodeKey;
42172    }
42173    createLinkWithSelectedText(url) {
42174      if (!this.hasSelectedText()) return;
42175      this.editor.update(() => {
42176        $toggleLink2(null);
42177        $toggleLink2(url);
42178      });
42179    }
42180    textBackUntil(string) {
42181      let result = "";
42182      this.editor.getEditorState().read(() => {
42183        const selection = $getSelection2();
42184        if (!selection || !selection.isCollapsed()) return;
42185        const anchor = selection.anchor;
42186        const anchorNode = anchor.getNode();
42187        if (!$isTextNode2(anchorNode)) return;
42188        const fullText = anchorNode.getTextContent();
42189        const offset3 = anchor.offset;
42190        const lastIndex = fullText.slice(0, offset3).lastIndexOf(string);
42191        if (lastIndex !== -1) {
42192          result = fullText.slice(lastIndex + string.length, this.#endOffsetAt(fullText, offset3));
42193        }
42194      });
42195      return result;
42196    }
42197    // The query runs from the trigger up to the next boundary, even when the
42198    // cursor sits inside an existing word — inserting "@" before "Jack" must
42199    // filter by "Jack" rather than treating the prompt as empty.
42200    #endOffsetAt(fullText, cursorOffset) {
42201      for (let offset3 = cursorOffset; offset3 < fullText.length; offset3++) {
42202        if (this.#isQueryBoundary(fullText, offset3)) {
42203          return offset3;
42204        }
42205      }
42206      return fullText.length;
42207    }
42208    // Whitespace always ends the query. Punctuation ends it too: with "@" typed
42209    // right before a period, extending across it would glue "." onto everything
42210    // typed ("B" would query "B."), matching the wrong names or nothing at all.
42211    // But punctuation joining two word characters is part of a name — "@" before
42212    // "Anne-Marie" or "O'Connor" must keep the whole name as the query.
42213    #isQueryBoundary(fullText, offset3) {
42214      const character = fullText[offset3];
42215      if (/\s/.test(character)) return true;
42216      if (!/\p{P}/u.test(character)) return false;
42217      return !(this.#isWordCharacter(fullText[offset3 - 1]) && this.#isWordCharacter(fullText[offset3 + 1]));
42218    }
42219    #isWordCharacter(character) {
42220      return character != null && /[\p{L}\p{N}]/u.test(character);
42221    }
42222    containsTextBackUntil(string) {
42223      let result = false;
42224      this.editor.getEditorState().read(() => {
42225        const selection = $getSelection2();
42226        if (!selection || !selection.isCollapsed()) return;
42227        const anchor = selection.anchor;
42228        const anchorNode = anchor.getNode();
42229        if (!$isTextNode2(anchorNode)) return;
42230        const fullText = anchorNode.getTextContent();
42231        const offset3 = anchor.offset;
42232        const textBeforeCursor = fullText.slice(0, offset3);
42233        result = textBeforeCursor.includes(string);
42234      });
42235      return result;
42236    }
42237    replaceTextBackUntil(stringToReplace, replacementNodes) {
42238      replacementNodes = Array.isArray(replacementNodes) ? replacementNodes : [replacementNodes];
42239      const { anchorNode, offset: offset3 } = this.#getTextAnchorData();
42240      if (!anchorNode) return;
42241      const lastIndex = this.#findReplacementStart(anchorNode, offset3, stringToReplace);
42242      if (lastIndex === -1) return;
42243      this.#performTextReplacement(anchorNode, lastIndex, stringToReplace, replacementNodes);
42244    }
42245    uploadFiles(files, { selectLast } = {}) {
42246      if (!this.editorElement) return;
42247      if (!this.editorElement.supportsAttachments) {
42248        console.warn("This editor does not supports attachments (it's configured with [attachments=false])");
42249        return;
42250      }
42251      const validFiles = Array.from(files).filter((file) => this.editorElement.acceptsFile(file));
42252      this.editor.update(() => {
42253        const uploader = Uploader.for(this.editorElement, validFiles);
42254        uploader.$uploadFiles();
42255        if (selectLast && uploader.nodes?.length) {
42256          const lastNode = uploader.nodes.at(-1);
42257          lastNode.selectEnd();
42258          this.#normalizeSelectionInShadowRoot();
42259        }
42260      });
42261    }
42262    $createUploadNode(file) {
42263      return $createActionTextAttachmentUploadNode({
42264        file,
42265        uploadUrl: this.editorElement.directUploadUrl,
42266        blobUrlTemplate: this.editorElement.blobUrlTemplate,
42267        contentType: file.type
42268      });
42269    }
42270    $createPendingUploadNode(file) {
42271      return $createActionTextAttachmentUploadNode({
42272        file,
42273        uploadUrl: null,
42274        blobUrlTemplate: this.editorElement.blobUrlTemplate,
42275        contentType: file.type
42276      });
42277    }
42278    insertPendingAttachment(file) {
42279      if (!this.editorElement.supportsAttachments) return null;
42280      let nodeKey = null;
42281      this.editor.update(() => {
42282        const uploadNode = this.$createPendingUploadNode(file);
42283        this.insertAtCursor(uploadNode);
42284        nodeKey = uploadNode.getKey();
42285      });
42286      return nodeKey ? this.#pendingAttachmentHandle(nodeKey) : null;
42287    }
42288    insertPendingAttachments(files) {
42289      const fileList = Array.from(files);
42290      if (!this.editorElement.supportsAttachments || fileList.length === 0) return [];
42291      let nodeKeys = [];
42292      this.editor.update(() => {
42293        const uploader = Uploader.for(this.editorElement, fileList, { pending: true });
42294        uploader.$uploadFiles();
42295        nodeKeys = (uploader.nodes ?? []).map((node) => node.getKey());
42296      });
42297      return nodeKeys.map((nodeKey) => this.#pendingAttachmentHandle(nodeKey));
42298    }
42299    #pendingAttachmentHandle(initialNodeKey) {
42300      const editor = this.editor;
42301      let nodeKey = initialNodeKey;
42302      return {
42303        setAttributes(blob) {
42304          editor.update(() => {
42305            const node = $getNodeByKey2(nodeKey);
42306            if (!(node instanceof ActionTextAttachmentUploadNode)) return;
42307            const replacementNodeKey = node.$showUploadedAttachment(blob);
42308            if (replacementNodeKey) {
42309              nodeKey = replacementNodeKey;
42310            }
42311          }, { tag: HISTORY_MERGE_TAG2 });
42312        },
42313        setUploadProgress(progress) {
42314          editor.update(() => {
42315            const node = $getNodeByKey2(nodeKey);
42316            if (!(node instanceof ActionTextAttachmentUploadNode)) return;
42317            node.getWritable().progress = progress;
42318          }, { tag: HISTORY_MERGE_TAG2 });
42319        },
42320        remove() {
42321          editor.update(() => {
42322            const node = $getNodeByKey2(nodeKey);
42323            if (node) node.remove();
42324          });
42325        }
42326      };
42327    }
42328    replaceNodeWithHTML(nodeKey, html2, options = {}) {
42329      this.editor.update(() => {
42330        const node = $getNodeByKey2(nodeKey);
42331        if (!node) return;
42332        const selection = $getSelection2();
42333        let wasSelected = false;
42334        if ($isRangeSelection2(selection)) {
42335          const selectedNodes = selection.getNodes();
42336          wasSelected = selectedNodes.includes(node) || selectedNodes.some((n2) => n2.getParent() === node);
42337          if (wasSelected) {
42338            $setSelection2(null);
42339          }
42340        }
42341        const replacementNode = options.attachment ? this.#createCustomAttachmentNodeWithHtml(html2, options.attachment) : this.#createHtmlNodeWith(html2);
42342        node.replace(replacementNode);
42343        if (wasSelected) {
42344          replacementNode.selectEnd();
42345        }
42346      });
42347    }
42348    insertHTMLBelowNode(nodeKey, html2, options = {}) {
42349      this.editor.update(() => {
42350        const node = $getNodeByKey2(nodeKey);
42351        if (!node) return;
42352        const previousNode = node.getTopLevelElement() || node;
42353        const newNode = options.attachment ? this.#createCustomAttachmentNodeWithHtml(html2, options.attachment) : this.#createHtmlNodeWith(html2);
42354        previousNode.insertAfter(newNode);
42355      });
42356    }
42357    #insertableSelection() {
42358      const selection = $getSelection2();
42359      if ($isNodeSelection2(selection) && selection.getNodes().length === 0) {
42360        return $getRoot2().selectEnd();
42361      }
42362      return selection ?? $getRoot2().selectEnd();
42363    }
42364    #formatPastedDOM(doc) {
42365      new PastedContentFormatter(doc).format();
42366    }
42367    #dispatchPastedNodesCommand(nodes) {
42368      return this.editor.dispatchCommand(SELECTION_INSERT_CLIPBOARD_NODES_COMMAND2, {
42369        nodes,
42370        selection: $getSelection2()
42371      });
42372    }
42373    #insertNodeIfRoot(node) {
42374      const selection = $getSelection2();
42375      if (!$isRangeSelection2(selection)) return false;
42376      const anchorNode = selection.anchor.getNode();
42377      if ($isRootOrShadowRoot2(anchorNode)) {
42378        anchorNode.append(node);
42379        node.selectEnd();
42380        return true;
42381      }
42382      return false;
42383    }
42384    #unwrapCodeBlock(codeNode) {
42385      const children = codeNode.getChildren();
42386      const groups = [[]];
42387      for (const child of children) {
42388        if ($isLineBreakNode2(child)) {
42389          groups.push([]);
42390        } else {
42391          groups[groups.length - 1].push(child.getTextContent());
42392        }
42393      }
42394      for (const group of groups) {
42395        const paragraph = $createParagraphNode2();
42396        const text2 = group.join("");
42397        if (text2) {
42398          paragraph.append($createTextNode2(text2));
42399        }
42400        codeNode.insertBefore(paragraph);
42401      }
42402      codeNode.remove();
42403    }
42404    #applyListFormat(listType, command) {
42405      if (this.selection.isInsideBlockQuote) {
42406        this.#insertListInsideQuote(listType);
42407      } else {
42408        this.#splitParagraphsAtLineBreaksUnlessInsideList();
42409        this.editor.dispatchCommand(command);
42410      }
42411    }
42412    #insertListInsideQuote(listType) {
42413      for (const group of $consecutiveSiblingGroups(this.#quotedBlocksInSelection())) {
42414        this.#wrapBlocksInList(group, listType);
42415      }
42416    }
42417    #quotedBlocksInSelection() {
42418      const selection = $getSelection2();
42419      if (!$isRangeSelection2(selection)) return [];
42420      const blocks = this.#outermostElements(this.#blockLevelElementsInSelection(selection));
42421      return blocks.filter((block) => $isQuoteNode2(block.getParent()));
42422    }
42423    #wrapBlocksInList(blocks, listType) {
42424      const list = $createListNode2(listType);
42425      blocks[0].insertBefore(list);
42426      for (const block of blocks) {
42427        const listItem = $createListItemNode2();
42428        if ($isListNode2(block)) {
42429          listItem.append(...block.getChildren().flatMap((item) => item.getChildren()));
42430        } else {
42431          listItem.append(...block.getChildren());
42432        }
42433        list.append(listItem);
42434        block.remove();
42435      }
42436    }
42437    #splitParagraphsAtLineBreaksUnlessInsideList() {
42438      if (this.selection.isInsideList) return;
42439      const selection = $getSelection2();
42440      if (!$isRangeSelection2(selection)) return;
42441      $expandSelectionToLineBreaksAndSplitAtEdges(selection);
42442      $splitSelectedParagraphsAtInnerLineBreaks(selection);
42443    }
42444    #blockLevelElementsInSelection(selection) {
42445      const blocks = /* @__PURE__ */ new Set();
42446      for (const node of selection.getNodes()) {
42447        blocks.add($getNearestBlockElementAncestorOrThrow2(node));
42448      }
42449      return Array.from(blocks);
42450    }
42451    #topLevelElementsInSelection(selection) {
42452      const elements = /* @__PURE__ */ new Set();
42453      for (const node of selection.getNodes()) {
42454        const topLevel = node.getTopLevelElement();
42455        if (topLevel) elements.add(topLevel);
42456      }
42457      return Array.from(elements);
42458    }
42459    // Selections spanning nested structures (a quote and its inner paragraphs,
42460    // nested list items) yield both an element and its ancestor. Converting the
42461    // ancestor detaches its whole subtree — including a node freshly inserted
42462    // inside it — which can leave the selection on removed nodes (Lexical
42463    // invariant #19). The outermost elements already cover their descendants'
42464    // text content, so keep only those.
42465    #outermostElements(elements) {
42466      return elements.filter((element) => {
42467        return elements.every((other) => other === element || !element.getParents().includes(other));
42468      });
42469    }
42470    #insertUploadNodes(nodes) {
42471      if (nodes.every($isActionTextAttachmentNode)) {
42472        const uploader = Uploader.for(this.editorElement, []);
42473        uploader.nodes = nodes;
42474        uploader.$insertUploadNodes();
42475        return true;
42476      }
42477    }
42478    #unwrap(node) {
42479      const children = node.getChildren();
42480      if (children.length == 0) {
42481        node.insertBefore($createParagraphNode2());
42482      } else {
42483        children.forEach((child) => {
42484          if ($isTextNode2(child) && child.getTextContent().trim() !== "") {
42485            const newParagraph = $createParagraphNode2();
42486            newParagraph.append(child);
42487            node.insertBefore(newParagraph);
42488          } else if (!$isLineBreakNode2(child)) {
42489            node.insertBefore(child);
42490          }
42491        });
42492      }
42493      node.remove();
42494    }
42495    #getTextAnchorData() {
42496      const selection = $getSelection2();
42497      if (!selection || !selection.isCollapsed()) return { anchorNode: null, offset: 0 };
42498      const anchor = selection.anchor;
42499      const anchorNode = anchor.getNode();
42500      if (!$isTextNode2(anchorNode)) return { anchorNode: null, offset: 0 };
42501      return { anchorNode, offset: anchor.offset };
42502    }
42503    // The replaced span must start before the cursor but can extend past it
42504    // (e.g. "@Jack" when "@" was just inserted before "Jack"), so we bound the
42505    // match's start with lastIndexOf's fromIndex rather than slicing the text.
42506    #findReplacementStart(anchorNode, offset3, stringToReplace) {
42507      if (offset3 === 0) {
42508        return -1;
42509      } else {
42510        return anchorNode.getTextContent().lastIndexOf(stringToReplace, offset3 - 1);
42511      }
42512    }
42513    #performTextReplacement(anchorNode, startIndex, stringToReplace, replacementNodes) {
42514      const fullText = anchorNode.getTextContent();
42515      const textBeforeString = fullText.slice(0, startIndex);
42516      const textAfterString = fullText.slice(startIndex + stringToReplace.length);
42517      const textNodeBefore = this.#cloneTextNodeFormatting(anchorNode, textBeforeString);
42518      const textNodeAfter = this.#cloneTextNodeFormatting(anchorNode, textAfterString || " ");
42519      anchorNode.replace(textNodeBefore);
42520      const lastInsertedNode = this.#insertReplacementNodes(textNodeBefore, replacementNodes);
42521      lastInsertedNode.insertAfter(textNodeAfter);
42522      this.#appendLineBreakIfNeeded(textNodeAfter.getParentOrThrow());
42523      const cursorOffset = textAfterString ? 0 : 1;
42524      textNodeAfter.select(cursorOffset, cursorOffset);
42525    }
42526    #cloneTextNodeFormatting(anchorNode, text2) {
42527      return $createTextNode2(text2).setFormat(anchorNode.getFormat()).setDetail(anchorNode.getDetail()).setMode(anchorNode.getMode()).setStyle(anchorNode.getStyle());
42528    }
42529    #insertReplacementNodes(startNode, replacementNodes) {
42530      let previousNode = startNode;
42531      for (const node of replacementNodes) {
42532        previousNode.insertAfter(node);
42533        previousNode = node;
42534      }
42535      return previousNode;
42536    }
42537    #appendLineBreakIfNeeded(paragraph) {
42538      if ($isParagraphNode2(paragraph) && this.editorElement.supportsMultiLine) {
42539        const children = paragraph.getChildren();
42540        const last = children[children.length - 1];
42541        const beforeLast = children[children.length - 2];
42542        if ($isTextNode2(last) && last.getTextContent() === "" && (beforeLast && !$isTextNode2(beforeLast))) {
42543          paragraph.append($createLineBreakNode2());
42544        }
42545      }
42546    }
42547    #createCustomAttachmentNodeWithHtml(html2, options = {}) {
42548      const attachmentConfig = typeof options === "object" ? options : {};
42549      const contentType = attachmentConfig.contentType || "text/html";
42550      if (!this.editorElement.permitsAttachmentContentType(contentType)) {
42551        return this.#createHtmlNodeWith(html2);
42552      }
42553      return new CustomActionTextAttachmentNode({
42554        sgid: attachmentConfig.sgid || null,
42555        contentType,
42556        innerHtml: html2
42557      });
42558    }
42559    #createHtmlNodeWith(html2) {
42560      const htmlNodes = this.editorElement.$generateNodesFromDOM(parseHtml(html2));
42561      return htmlNodes[0] || $createParagraphNode2();
42562    }
42563    // When the selection anchor is on a shadow root (e.g. a table cell), Lexical's
42564    // insertNodes can't find a block parent and fails silently. Normalize the
42565    // selection to point inside the shadow root's content instead.
42566    #normalizeSelectionInShadowRoot() {
42567      const selection = $getSelection2();
42568      if (!$isRangeSelection2(selection)) return;
42569      const anchorNode = selection.anchor.getNode();
42570      if (!$isShadowRoot(anchorNode)) return;
42571      const paragraph = $createParagraphNode2();
42572      anchorNode.append(paragraph);
42573      paragraph.selectStart();
42574    }
42575  };
42576  var Clipboard = class {
42577    #listeners = new ListenerBin();
42578    constructor(editorElement) {
42579      this.editorElement = editorElement;
42580      this.editor = editorElement.editor;
42581      this.contents = editorElement.contents;
42582      this.#registerPasteCommands();
42583    }
42584    dispose() {
42585      this.editorElement = null;
42586      this.editor = null;
42587      this.contents = null;
42588      this.#listeners.dispose();
42589    }
42590    paste(event) {
42591      const clipboardData = event.clipboardData;
42592      if (!clipboardData) return false;
42593      if (this.#isPastingIntoCodeBlock()) {
42594        this.#pastePlainTextIntoCodeBlock(clipboardData);
42595        event.preventDefault();
42596        return true;
42597      }
42598      if (this.#isPlainTextOrURLPasted(clipboardData)) {
42599        this.#pastePlainTextOrURL(clipboardData);
42600        event.preventDefault();
42601        return true;
42602      }
42603      const handled = this.#handlePastedFiles(clipboardData);
42604      if (handled) event.preventDefault();
42605      return handled;
42606    }
42607    #registerPasteCommands() {
42608      this.#listeners.track(
42609        this.editor.registerCommand(PASTE_COMMAND2, this.paste.bind(this), COMMAND_PRIORITY_NORMAL2),
42610        this.editor.registerCommand(
42611          SELECTION_INSERT_CLIPBOARD_NODES_COMMAND2,
42612          (payload) => this.#handleParsedClipboardNodes(payload),
42613          COMMAND_PRIORITY_NORMAL2
42614        )
42615      );
42616    }
42617    #handleParsedClipboardNodes({ nodes, selection }) {
42618      const url = $bareUrlFromSingleLink(nodes);
42619      if (url && $isRangeSelection2(selection)) {
42620        this.#insertSingleLinkAt(selection, url);
42621        return true;
42622      }
42623    }
42624    #isPlainTextOrURLPasted(clipboardData) {
42625      return this.#isOnlyPlainTextPasted(clipboardData) || this.#isOnlyURLPasted(clipboardData) || this.#isSoloUrlWithHtml(clipboardData);
42626    }
42627    #isSoloUrlWithHtml(clipboardData) {
42628      if (!Array.from(clipboardData.types).includes("text/html")) return false;
42629      const text2 = clipboardData.getData("text/plain").trim();
42630      return isAutolinkableURL(text2);
42631    }
42632    #isOnlyPlainTextPasted(clipboardData) {
42633      const types = Array.from(clipboardData.types);
42634      return types.length === 1 && types[0] === "text/plain";
42635    }
42636    // Browsers expose a copied URL in several shapes:
42637    //   Safari          [ text/plain, text/uri-list ]
42638    //   App ShareSheet  [ text/uri-list ]
42639    //   Chromium macOS  [ text/plain, text/html, (?:text/link-preview) ]
42640    #isOnlyURLPasted(clipboardData) {
42641      if (this.#isLexicalClipboardData(clipboardData)) return false;
42642      const types = Array.from(clipboardData.types);
42643      if (types.includes("text/uri-list")) {
42644        return types.every((type) => type === "text/plain" || type === "text/uri-list");
42645      }
42646      if (clipboardData.files.length) return false;
42647      const text2 = clipboardData.getData("text/plain").trim();
42648      if (!isAutolinkableURL(text2)) return false;
42649      const html2 = clipboardData.getData("text/html");
42650      return !html2 || this.#htmlIsBareLinkToURL(html2, text2);
42651    }
42652    #htmlIsBareLinkToURL(html2, url) {
42653      const doc = parseHtml(html2);
42654      if (doc.body.textContent.trim() !== url) return false;
42655      const links = doc.body.querySelectorAll("a");
42656      if (links.length === 0) return true;
42657      return links.length === 1 && links[0].getAttribute("href") === url;
42658    }
42659    #isPastingIntoCodeBlock() {
42660      let result = false;
42661      this.editor.getEditorState().read(() => {
42662        const selection = $getSelection2();
42663        if (!$isRangeSelection2(selection)) return;
42664        let currentNode = selection.anchor.getNode();
42665        while (currentNode) {
42666          if ($isCodeNode3(currentNode)) {
42667            result = true;
42668            return;
42669          }
42670          currentNode = currentNode.getParent();
42671        }
42672      });
42673      return result;
42674    }
42675    #pastePlainTextIntoCodeBlock(clipboardData) {
42676      const text2 = clipboardData.getData("text/plain");
42677      if (!text2) return;
42678      this.editor.update(() => {
42679        const selection = $getSelection2();
42680        if ($isRangeSelection2(selection)) selection.insertRawText(text2);
42681      }, { tag: PASTE_TAG2 });
42682    }
42683    #pastePlainTextOrURL(clipboardData) {
42684      const item = this.#plainTextOrURLItem(clipboardData);
42685      item.getAsString((text2) => {
42686        const url = text2.trim();
42687        if (isAutolinkableURL(url)) {
42688          this.#pasteURL(url);
42689        } else if (this.editorElement.supportsMarkdown) {
42690          this.#pasteMarkdown(text2);
42691        } else {
42692          this.#pasteRichText(clipboardData);
42693        }
42694      });
42695    }
42696    #plainTextOrURLItem(clipboardData) {
42697      const items = Array.from(clipboardData.items);
42698      return items.find((item) => item.type === "text/plain") || items.find((item) => item.type === "text/uri-list");
42699    }
42700    #pasteURL(url) {
42701      if (this.contents.hasSelectedText()) {
42702        this.contents.createLinkWithSelectedText(url);
42703      } else {
42704        const nodeKey = this.contents.createLink(url);
42705        this.#dispatchLinkInsertEvent(nodeKey, { url });
42706      }
42707    }
42708    #insertSingleLinkAt(selection, url) {
42709      if (!$isRangeSelection2(selection)) return;
42710      if (!selection.isCollapsed()) {
42711        $toggleLink2(null);
42712        $toggleLink2(url);
42713        return;
42714      }
42715      const linkNode = $createLinkNode2(url).append($createTextNode2(url));
42716      BaseNodeInserter.for(selection).insertNodes([linkNode]);
42717      $onUpdate2(() => this.#dispatchLinkInsertEvent(linkNode.getKey(), { url }));
42718    }
42719    #dispatchLinkInsertEvent(nodeKey, payload) {
42720      const linkManipulationMethods = {
42721        replaceLinkWith: (html2, options) => this.contents.replaceNodeWithHTML(nodeKey, html2, options),
42722        insertBelowLink: (html2, options) => this.contents.insertHTMLBelowNode(nodeKey, html2, options)
42723      };
42724      dispatch(this.editorElement, "lexxy:insert-link", {
42725        ...payload,
42726        ...linkManipulationMethods
42727      });
42728    }
42729    #pasteMarkdown(text2) {
42730      const html2 = k(text2, { breaks: true });
42731      const doc = parseHtml(html2);
42732      if (this.#isPlainTextWithoutMarkdown(doc)) {
42733        this.contents.insertText(text2, { tag: PASTE_TAG2 });
42734      } else {
42735        const detail = Object.freeze({
42736          markdown: text2,
42737          document: doc,
42738          addBlockSpacing: () => addBlockSpacing(doc)
42739        });
42740        dispatch(this.editorElement, "lexxy:insert-markdown", detail);
42741        this.contents.insertDOM(doc, { tag: PASTE_TAG2 });
42742      }
42743    }
42744    // Markdown conversion collapses runs of whitespace and unescapes backslashes,
42745    // silently corrupting plain text such as Windows/UNC file paths. When the text
42746    // carries no Markdown structure, paste it verbatim instead. A path that wrapped
42747    // across lines renders as a single paragraph with <br> line breaks (marked runs
42748    // with breaks: true), which is still plain text we should preserve untouched.
42749    #isPlainTextWithoutMarkdown(doc) {
42750      const elements = Array.from(doc.body.children);
42751      if (elements.length !== 1) return false;
42752      const paragraph = elements[0];
42753      return paragraph.nodeName === "P" && Array.from(paragraph.childNodes).every((node) => node.nodeType === Node.TEXT_NODE || node.nodeName === "BR");
42754    }
42755    #pasteRichText(clipboardData) {
42756      this.editor.update(() => {
42757        const selection = $getSelection2();
42758        $insertDataTransferForRichText2(clipboardData, selection, this.editor);
42759      }, { tag: PASTE_TAG2 });
42760    }
42761    #handlePastedFiles(clipboardData) {
42762      if (!this.editorElement.supportsAttachments) return false;
42763      const html2 = clipboardData.getData("text/html");
42764      const files = clipboardData.files;
42765      if (files.length && this.#isCopiedImageHTML(html2)) {
42766        this.#uploadFilesPreservingScroll(files);
42767        return true;
42768      }
42769      if (html2 && !this.#isLexicalClipboardData(clipboardData)) {
42770        this.contents.insertHtml(html2, { tag: PASTE_TAG2 });
42771        return true;
42772      }
42773      if (files.length) {
42774        this.#uploadFilesPreservingScroll(files);
42775        return true;
42776      }
42777      return false;
42778    }
42779    #isLexicalClipboardData(clipboardData) {
42780      return Array.from(clipboardData.types).includes("application/x-lexical-editor");
42781    }
42782    #isCopiedImageHTML(html2) {
42783      if (!html2) return false;
42784      const doc = parseHtml(html2);
42785      const elementChildren = Array.from(doc.body.children);
42786      return elementChildren.length === 1 && elementChildren[0].tagName === "IMG";
42787    }
42788    #uploadFilesPreservingScroll(files) {
42789      this.#preservingScrollPosition(() => {
42790        if (files.length) {
42791          this.contents.uploadFiles(files, { selectLast: true });
42792        }
42793      });
42794    }
42795    // Deals with an issue in Safari where it scrolls to the tops after pasting attachments
42796    async #preservingScrollPosition(callback) {
42797      const scrollY = window.scrollY;
42798      const scrollX = window.scrollX;
42799      callback();
42800      await nextFrame();
42801      window.scrollTo(scrollX, scrollY);
42802      this.editor.focus();
42803    }
42804  };
42805  function $bareUrlFromSingleLink(nodes) {
42806    if (nodes.length !== 1) return null;
42807    const node = nodes[0];
42808    if ($isLinkNode2(node)) return $bareUrlFromLink(node);
42809    if ($isParagraphNode2(node)) {
42810      const children = node.getChildren();
42811      if (children.length === 1 && $isLinkNode2(children[0])) {
42812        return $bareUrlFromLink(children[0]);
42813      }
42814    }
42815    return null;
42816  }
42817  function $bareUrlFromLink(linkNode) {
42818    const url = linkNode.getURL();
42819    if (!url) return null;
42820    return linkNode.getTextContent() === url ? url : null;
42821  }
42822  var Extensions = class {
42823    constructor(lexxyElement) {
42824      this.lexxyElement = lexxyElement;
42825      this.enabledExtensions = this.#initializeExtensions();
42826    }
42827    get lexicalExtensions() {
42828      return this.enabledExtensions.map((ext) => ext.lexicalExtension).filter(Boolean);
42829    }
42830    initializeToolbars() {
42831      const toolbar = this.#lexxyToolbar;
42832      if (!toolbar) return;
42833      this.#clearPreviousExtensionToolbarButtons(toolbar);
42834      this.#addExtensionToolbarButtons(toolbar);
42835      toolbar.requestOverflowRefresh();
42836    }
42837    dispose() {
42838      while (this.enabledExtensions.length) {
42839        this.enabledExtensions.pop().dispose();
42840      }
42841    }
42842    #clearPreviousExtensionToolbarButtons(toolbar) {
42843      toolbar.querySelectorAll("[data-lexxy-extension]").forEach((el) => el.remove());
42844    }
42845    #addExtensionToolbarButtons(toolbar) {
42846      this.enabledExtensions.forEach((ext) => {
42847        const childrenBefore = new Set(toolbar.children);
42848        ext.initializeToolbar(toolbar);
42849        for (const child of toolbar.children) {
42850          if (!childrenBefore.has(child)) {
42851            child.setAttribute("data-lexxy-extension", "");
42852          }
42853        }
42854      });
42855    }
42856    get allowedElements() {
42857      return this.enabledExtensions.flatMap((ext) => ext.allowedElements);
42858    }
42859    get #lexxyToolbar() {
42860      return this.lexxyElement.toolbar;
42861    }
42862    get #baseExtensions() {
42863      return this.lexxyElement.baseExtensions;
42864    }
42865    get #configuredExtensions() {
42866      return Lexxy.global.get("extensions");
42867    }
42868    #initializeExtensions() {
42869      const extensionDefinitions = this.#baseExtensions.concat(this.#configuredExtensions);
42870      return extensionDefinitions.map(
42871        (extension) => new extension(this.lexxyElement)
42872      ).filter((extension) => extension.enabled);
42873    }
42874  };
42875  var BrowserAdapter = class {
42876    frozenLinkKey = null;
42877    dispatchAttributesChange(attributes, linkHref, highlight, headingTag) {
42878    }
42879    dispatchEditorInitialized(detail) {
42880    }
42881    freeze() {
42882    }
42883    thaw() {
42884    }
42885    unlinkFrozenNode() {
42886      return false;
42887    }
42888  };
42889  function exportTextNodeDOM(editor, textNode) {
42890    const element = textNode.createDOM(editor._config, editor);
42891    element.style.whiteSpace = "pre-wrap";
42892    if (textNode.hasFormat("lowercase")) {
42893      element.style.textTransform = "lowercase";
42894    } else if (textNode.hasFormat("uppercase")) {
42895      element.style.textTransform = "uppercase";
42896    } else if (textNode.hasFormat("capitalize")) {
42897      element.style.textTransform = "capitalize";
42898    }
42899    let result = element;
42900    if (textNode.hasFormat("bold") && !containsTag(element, "strong")) {
42901      result = wrapWith(result, "b");
42902    }
42903    if (textNode.hasFormat("italic") && !containsTag(element, "em")) {
42904      result = wrapWith(result, "i");
42905    }
42906    if (textNode.hasFormat("strikethrough")) {
42907      result = wrapWith(result, "s");
42908    }
42909    if (textNode.hasFormat("underline")) {
42910      result = wrapWith(result, "u");
42911    }
42912    return { element: unwrapSpans(result) };
42913  }
42914  function containsTag(element, tagName) {
42915    const upperTag = tagName.toUpperCase();
42916    if (element.tagName === upperTag) return true;
42917    return element.querySelector(tagName) !== null;
42918  }
42919  function wrapWith(element, tag) {
42920    const wrapper = document.createElement(tag);
42921    wrapper.appendChild(element);
42922    return wrapper;
42923  }
42924  function unwrapSpans(element) {
42925    if (element.tagName === "SPAN") return element.firstChild;
42926    for (const span of element.querySelectorAll("span")) {
42927      span.replaceWith(...span.childNodes);
42928    }
42929    return element;
42930  }
42931  var ProvisionalParagraphNode = class _ProvisionalParagraphNode extends ParagraphNode2 {
42932    $config() {
42933      return this.config("provisonal_paragraph", {
42934        extends: ParagraphNode2,
42935        importDOM: () => null,
42936        $transform: (node) => {
42937          node.concretizeIfEdited(node);
42938          node.removeUnlessRequired(node);
42939        }
42940      });
42941    }
42942    static neededBetween(nodeBefore, nodeAfter) {
42943      return !$isSelectableElement(nodeBefore, "next") && !$isSelectableElement(nodeAfter, "previous");
42944    }
42945    createDOM(editor) {
42946      const p2 = super.createDOM(editor);
42947      const selected = this.isSelected($getSelection2());
42948      p2.classList.add("provisional-paragraph");
42949      p2.classList.toggle("hidden", !selected);
42950      return p2;
42951    }
42952    updateDOM(_prevNode, dom) {
42953      const selected = this.isSelected($getSelection2());
42954      dom.classList.toggle("hidden", !selected);
42955      return false;
42956    }
42957    getTextContent() {
42958      return "";
42959    }
42960    exportDOM() {
42961      return {
42962        element: null
42963      };
42964    }
42965    // override as Lexical has an interesting view of collapsed selection in ElementNodes
42966    // https://github.com/facebook/lexical/blob/f1e4f66014377b1f2595aec2b0ee17f5b7ef4dfc/packages/lexical/src/LexicalNode.ts#L646
42967    isSelected(selection = null) {
42968      const targetSelection = selection || $getSelection2();
42969      if (!targetSelection) return false;
42970      if (targetSelection.getNodes().some((node) => node.is(this) || this.isParentOf(node))) return true;
42971      if ($isRangeSelection2(targetSelection) && targetSelection.isCollapsed()) {
42972        const { anchor } = targetSelection;
42973        const parent = this.getParent();
42974        if (parent && anchor.getNode().is(parent) && anchor.type === "element") {
42975          const index = this.getIndexWithinParent();
42976          return anchor.offset === index || anchor.offset === index + 1;
42977        }
42978      }
42979      return false;
42980    }
42981    removeUnlessRequired(self2 = this.getLatest()) {
42982      if (!self2.required) self2.remove();
42983    }
42984    concretizeIfEdited(self2 = this.getLatest()) {
42985      if (self2.getTextContentSize() > 0) {
42986        self2.replace($createParagraphNode2(), true);
42987      }
42988    }
42989    get required() {
42990      return this.isDirectRootChild && _ProvisionalParagraphNode.neededBetween(...this.immediateSiblings);
42991    }
42992    get isDirectRootChild() {
42993      const parent = this.getParent();
42994      return $isRootOrShadowRoot2(parent);
42995    }
42996    get immediateSiblings() {
42997      return [this.getPreviousSibling(), this.getNextSibling()];
42998    }
42999  };
43000  function $isProvisionalParagraphNode(node) {
43001    return node instanceof ProvisionalParagraphNode;
43002  }
43003  function $isSelectableElement(node, direction) {
43004    return $isElementNode2(node) && (direction === "next" ? node.canInsertTextBefore() : node.canInsertTextAfter());
43005  }
43006  var ProvisionalParagraphExtension = class extends LexxyExtension {
43007    get lexicalExtension() {
43008      return defineExtension2({
43009        name: "lexxy/provisional-paragraph",
43010        nodes: [
43011          ProvisionalParagraphNode
43012        ],
43013        register(editor) {
43014          return mergeRegister3(
43015            // Process Provisional Paragraph Nodes on RootNode changes as sibling status influences whether
43016            // they are required and their visible/hidden status
43017            editor.registerNodeTransform(RootNode2, $insertRequiredProvisionalParagraphs),
43018            editor.registerNodeTransform(RootNode2, $removeUnneededProvisionalParagraphs),
43019            editor.registerCommand(SELECTION_CHANGE_COMMAND2, $markAllProvisionalParagraphsDirty, COMMAND_PRIORITY_HIGH2)
43020          );
43021        }
43022      });
43023    }
43024  };
43025  function $insertRequiredProvisionalParagraphs(rootNode) {
43026    const nodeBeforeRootSelection = $nodeBeforeRootSelection(rootNode);
43027    const firstNode = rootNode.getFirstChild();
43028    if (ProvisionalParagraphNode.neededBetween(null, firstNode)) {
43029      $insertFirst2(rootNode, new ProvisionalParagraphNode());
43030    }
43031    for (const node of $firstToLastIterator2(rootNode)) {
43032      const nextNode = node.getNextSibling();
43033      if (ProvisionalParagraphNode.neededBetween(node, nextNode)) {
43034        node.insertAfter(new ProvisionalParagraphNode());
43035        if (node.is(nodeBeforeRootSelection)) node.selectNext();
43036      }
43037    }
43038  }
43039  function $nodeBeforeRootSelection(rootNode) {
43040    const selection = $getSelection2();
43041    if (!$isRootOrShadowRoot2(selection?.anchor?.getNode())) return null;
43042    return rootNode.getChildAtIndex(selection.anchor.offset - 1);
43043  }
43044  function $removeUnneededProvisionalParagraphs(rootNode) {
43045    for (const provisionalParagraph of $getAllProvisionalParagraphs(rootNode)) {
43046      provisionalParagraph.removeUnlessRequired();
43047    }
43048  }
43049  function $markAllProvisionalParagraphsDirty() {
43050    $addUpdateTag2(HISTORY_MERGE_TAG2);
43051    for (const provisionalParagraph of $getAllProvisionalParagraphs()) {
43052      provisionalParagraph.markDirty();
43053    }
43054  }
43055  function $getAllProvisionalParagraphs(rootNode = $getRoot2()) {
43056    return $descendantsMatching2(rootNode.getChildren(), $isProvisionalParagraphNode);
43057  }
43058  var CodeHighlightingExtension = class extends LexxyExtension {
43059    get enabled() {
43060      return this.editorElement.supportsRichText;
43061    }
43062    get lexicalExtension() {
43063      return defineExtension2({
43064        name: "lexxy/code-highlighting",
43065        register(editor) {
43066          return registerCodeHighlighting4(editor, buildHighlightPreservingTokenizer(editor));
43067        }
43068      });
43069    }
43070  };
43071  var TRIX_LANGUAGE_ATTR = "language";
43072  var TrixContentExtension = class extends LexxyExtension {
43073    get enabled() {
43074      return this.editorElement.supportsRichText;
43075    }
43076    get lexicalExtension() {
43077      return defineExtension2({
43078        name: "lexxy/trix-content",
43079        html: {
43080          import: {
43081            em: (element) => onlyStyledElements(element, {
43082              conversion: extendTextNodeConversion("i", $applyHighlightStyle),
43083              priority: 1
43084            }),
43085            span: (element) => onlyStyledElements(element, {
43086              conversion: extendTextNodeConversion("mark", $applyHighlightStyle),
43087              priority: 1
43088            }),
43089            strong: (element) => onlyStyledElements(element, {
43090              conversion: extendTextNodeConversion("b", $applyHighlightStyle),
43091              priority: 1
43092            }),
43093            del: () => ({
43094              conversion: extendTextNodeConversion("s", $applyStrikethrough, $applyHighlightStyle),
43095              priority: 1
43096            }),
43097            pre: (element) => onlyPreLanguageElements(element, {
43098              conversion: extendConversion(CodeNode3, "pre", $applyLanguage),
43099              priority: 1
43100            })
43101          }
43102        }
43103      });
43104    }
43105  };
43106  function onlyStyledElements(element, conversion) {
43107    const elementHighlighted = element.style.color !== "" || element.style.backgroundColor !== "";
43108    return elementHighlighted ? conversion : null;
43109  }
43110  function $applyStrikethrough(textNode) {
43111    if (!textNode.hasFormat("strikethrough")) textNode.toggleFormat("strikethrough");
43112    return textNode;
43113  }
43114  function onlyPreLanguageElements(element, conversion) {
43115    return element.hasAttribute(TRIX_LANGUAGE_ATTR) ? conversion : null;
43116  }
43117  function $applyLanguage(conversionOutput, element) {
43118    const language = normalizeCodeLang2(element.getAttribute(TRIX_LANGUAGE_ATTR));
43119    conversionOutput.node.setLanguage(language);
43120  }
43121  var WrappedTableNode = class extends TableNode2 {
43122    $config() {
43123      return this.config("wrapped_table_node", { extends: TableNode2 });
43124    }
43125    static importDOM() {
43126      return super.importDOM();
43127    }
43128    canInsertTextBefore() {
43129      return false;
43130    }
43131    canInsertTextAfter() {
43132      return false;
43133    }
43134    exportDOM(editor) {
43135      const superExport = super.exportDOM(editor);
43136      return {
43137        ...superExport,
43138        after: (tableElement) => {
43139          if (superExport.after) {
43140            tableElement = superExport.after(tableElement);
43141            const clonedTable = tableElement.cloneNode(true);
43142            const wrappedTable = createElement("figure", { className: "lexxy-content__table-wrapper" }, clonedTable.outerHTML);
43143            return wrappedTable;
43144          }
43145          return tableElement;
43146        }
43147      };
43148    }
43149  };
43150  var TablesExtension = class extends LexxyExtension {
43151    get enabled() {
43152      return this.editorElement.supportsRichText;
43153    }
43154    get allowedElements() {
43155      return ["figure", "tbody"];
43156    }
43157    get lexicalExtension() {
43158      return defineExtension2({
43159        name: "lexxy/tables",
43160        nodes: [
43161          WrappedTableNode,
43162          {
43163            replace: TableNode2,
43164            with: () => new WrappedTableNode(),
43165            withKlass: WrappedTableNode
43166          },
43167          TableCellNode2,
43168          TableRowNode2
43169        ],
43170        register(editor) {
43171          setScrollableTablesActive2(editor, true);
43172          return mergeRegister3(
43173            registerTablePlugin2(editor),
43174            // Lexxy registers extensions before setRootElement(), but table
43175            // drag-selection needs a root before wiring its pointer handlers.
43176            editor.registerRootListener((rootElement) => {
43177              if (rootElement) {
43178                return registerTableSelectionObserver2(editor, true);
43179              }
43180            }),
43181            // A table in Lexxy is a Lexxy table: cell shading can't be set in the
43182            // editor, so any cell background only ever comes from foreign content
43183            // (pasted spreadsheets, loaded documents). Normalize every cell to no
43184            // background so it adopts the current theme. This also clears
43185            // Lexical's hardcoded default header background (Lexical #8089).
43186            editor.registerNodeTransform(TableCellNode2, (node) => {
43187              if (node.getBackgroundColor() !== "") {
43188                node.setBackgroundColor("");
43189              }
43190            }),
43191            // Bug fix: Fix column header states (Lexical #8090)
43192            editor.registerNodeTransform(TableCellNode2, (node) => {
43193              const headerState = node.getHeaderStyles();
43194              if (headerState !== TableCellHeaderStates2.ROW) return;
43195              const rowParent = node.getParent();
43196              const tableNode = rowParent?.getParent();
43197              if (!tableNode) return;
43198              const rows = tableNode.getChildren();
43199              const cellIndex = rowParent.getChildren().indexOf(node);
43200              const cellsInRow = rowParent.getChildren();
43201              const isHeaderRow = cellsInRow.every(
43202                (cell) => cell.getHeaderStyles() !== TableCellHeaderStates2.NO_STATUS
43203              );
43204              const isHeaderColumn = rows.every((row) => {
43205                const cell = row.getChildren()[cellIndex];
43206                return cell && cell.getHeaderStyles() !== TableCellHeaderStates2.NO_STATUS;
43207              });
43208              let newHeaderState = TableCellHeaderStates2.NO_STATUS;
43209              if (isHeaderRow) newHeaderState |= TableCellHeaderStates2.ROW;
43210              if (isHeaderColumn) newHeaderState |= TableCellHeaderStates2.COLUMN;
43211              if (newHeaderState !== headerState) {
43212                node.setHeaderStyles(newHeaderState, TableCellHeaderStates2.BOTH);
43213              }
43214            }),
43215            editor.registerCommand("insertTableRowAfter", () => {
43216              $insertTableRowAtSelection2(true);
43217            }, COMMAND_PRIORITY_NORMAL2),
43218            editor.registerCommand("insertTableRowBefore", () => {
43219              $insertTableRowAtSelection2(false);
43220            }, COMMAND_PRIORITY_NORMAL2),
43221            editor.registerCommand("insertTableColumnAfter", () => {
43222              $insertTableColumnAtSelection2(true);
43223            }, COMMAND_PRIORITY_NORMAL2),
43224            editor.registerCommand("insertTableColumnBefore", () => {
43225              $insertTableColumnAtSelection2(false);
43226            }, COMMAND_PRIORITY_NORMAL2),
43227            editor.registerCommand("deleteTableRow", () => {
43228              $deleteTableRowAtSelection2();
43229            }, COMMAND_PRIORITY_NORMAL2),
43230            editor.registerCommand("deleteTableColumn", () => {
43231              $deleteTableColumnAtSelection2();
43232            }, COMMAND_PRIORITY_NORMAL2),
43233            editor.registerCommand("deleteTable", () => {
43234              const selection = $getSelection2();
43235              if (!$isRangeSelection2(selection)) return false;
43236              $findTableNode2(selection.anchor.getNode())?.remove();
43237            }, COMMAND_PRIORITY_NORMAL2)
43238          );
43239        }
43240      });
43241    }
43242  };
43243  var MIME_TYPE$1 = "application/x-lexxy-node-key";
43244  var AttachmentDragAndDrop = class _AttachmentDragAndDrop {
43245    #editor;
43246    #draggedNodeKey = null;
43247    #rafId = null;
43248    #draggingRafId = null;
43249    #listeners = new ListenerBin();
43250    constructor(editor) {
43251      this.#editor = editor;
43252      this.#listeners.track(
43253        editor.registerCommand(DRAGSTART_COMMAND2, (event) => this.#handleDragStart(event), COMMAND_PRIORITY_HIGH2),
43254        editor.registerCommand(DROP_COMMAND2, (event) => this.#handleDrop(event), COMMAND_PRIORITY_HIGH2)
43255      );
43256      this.#listeners.track(editor.registerRootListener((root, prevRoot) => {
43257        if (prevRoot) {
43258          prevRoot.removeEventListener("dragover", this.#onDragOver);
43259          prevRoot.removeEventListener("dragend", this.#onDragEnd);
43260        }
43261        if (root) {
43262          root.addEventListener("dragover", this.#onDragOver);
43263          root.addEventListener("dragend", this.#onDragEnd);
43264        }
43265      }));
43266    }
43267    destroy() {
43268      this.#cleanup();
43269      this.#listeners.dispose();
43270    }
43271    // -- Event handlers --------------------------------------------------------
43272    #handleDragStart(event) {
43273      if (event.target.closest?.("textarea, [data-lexxy-caption-editor]")) return false;
43274      const figure = event.target.closest?.("figure.attachment[data-lexical-node-key]");
43275      if (!figure) return false;
43276      this.#draggedNodeKey = figure.dataset.lexicalNodeKey;
43277      event.dataTransfer.setData(MIME_TYPE$1, this.#draggedNodeKey);
43278      event.dataTransfer.effectAllowed = "move";
43279      this.#draggingRafId = requestAnimationFrame(() => {
43280        this.#draggingRafId = null;
43281        figure.classList.add("lexxy-dragging");
43282      });
43283      return true;
43284    }
43285    #onDragOver = (event) => {
43286      if (!this.#draggedNodeKey) return;
43287      event.preventDefault();
43288      event.dataTransfer.dropEffect = "move";
43289      if (!this.#rafId) {
43290        this.#rafId = requestAnimationFrame(() => {
43291          this.#rafId = null;
43292          this.#updateDropTarget(event);
43293        });
43294      }
43295    };
43296    #handleDrop(event) {
43297      if (!this.#draggedNodeKey) return false;
43298      event.preventDefault();
43299      const target = this.#resolveDropTarget(event);
43300      const draggedKey = this.#draggedNodeKey;
43301      this.#cleanup();
43302      if (target) {
43303        this.#performDrop(draggedKey, target);
43304      }
43305      return true;
43306    }
43307    #onDragEnd = () => {
43308      this.#cleanup();
43309    };
43310    // -- Drop target resolution -----------------------------------------------
43311    #updateDropTarget(event) {
43312      this.#clearDropIndicators();
43313      const target = this.#resolveDropTarget(event);
43314      if (!target) return;
43315      if (target.type === "gallery" || target.type === "gallery-reorder") {
43316        target.element.classList.add(`lexxy-drop-target--gallery-${target.position}`);
43317      } else if (target.type === "list-item") {
43318        target.element.classList.add(`lexxy-drop-target--list-${target.position}`);
43319      } else {
43320        target.element.classList.add(`lexxy-drop-target--block-${target.position}`);
43321      }
43322    }
43323    #resolveDropTarget(event) {
43324      const element = document.elementFromPoint(event.clientX, event.clientY);
43325      if (!element) return null;
43326      const rootElement = this.#editor.getRootElement();
43327      if (!rootElement || !rootElement.contains(element)) return null;
43328      const draggedNode = this.#draggedNodeKey ? $getNodeByKey2(this.#draggedNodeKey) : null;
43329      const targetFigure = element.closest("figure.attachment[data-lexical-node-key]");
43330      if (targetFigure && targetFigure.dataset.lexicalNodeKey !== this.#draggedNodeKey) {
43331        const targetNode = this.#attachmentNodeForFigure(targetFigure);
43332        if (targetNode && draggedNode && this.#isGalleryImage(targetNode) && this.#isGalleryImage(draggedNode)) {
43333          const targetGallery2 = targetFigure.closest(".attachment-gallery");
43334          if (targetGallery2) {
43335            const draggedFigure = rootElement.querySelector(`[data-lexical-node-key="${this.#draggedNodeKey}"]`);
43336            if (draggedFigure && targetGallery2.contains(draggedFigure)) {
43337              const position3 = this.#computeHorizontalPosition(targetFigure, event.clientX);
43338              return { type: "gallery-reorder", element: targetFigure, nodeKey: targetFigure.dataset.lexicalNodeKey, position: position3 };
43339            }
43340          }
43341          const position2 = this.#computeHorizontalPosition(targetFigure, event.clientX);
43342          return { type: "gallery", element: targetFigure, nodeKey: targetFigure.dataset.lexicalNodeKey, position: position2 };
43343        }
43344        if (targetNode && draggedNode && $isActionTextAttachmentNode(targetNode) && $isActionTextAttachmentNode(draggedNode) && !this.#isGalleryImage(targetNode) && !this.#isGalleryImage(draggedNode) && !this.#isVerticalEdgeIntent(targetFigure, event.clientY)) {
43345          return null;
43346        }
43347      }
43348      if (targetFigure?.dataset.lexicalNodeKey === this.#draggedNodeKey && targetFigure.closest(".attachment-gallery")) return null;
43349      const targetGallery = element.closest(".attachment-gallery");
43350      if (targetGallery) {
43351        let galleryFigure = element.closest("figure.attachment[data-lexical-node-key]");
43352        if (!galleryFigure) {
43353          galleryFigure = this.#findNearestFigureInGallery(targetGallery, event.clientX);
43354        }
43355        if (galleryFigure && galleryFigure.dataset.lexicalNodeKey !== this.#draggedNodeKey) {
43356          const position2 = this.#computeHorizontalPosition(galleryFigure, event.clientX);
43357          return { type: "gallery-reorder", element: galleryFigure, nodeKey: galleryFigure.dataset.lexicalNodeKey, position: position2 };
43358        }
43359        if (galleryFigure) return null;
43360      }
43361      const listItem = element.closest("li");
43362      if (listItem && rootElement.contains(listItem)) {
43363        const position2 = this.#computeVerticalPosition(listItem, event.clientY);
43364        return { type: "list-item", element: listItem, position: position2 };
43365      }
43366      const block = this.#findNearestBlock(element, rootElement, event.clientY);
43367      if (!block) return null;
43368      const position = this.#computeVerticalPosition(block, event.clientY);
43369      if (position === "before" && block.previousElementSibling) {
43370        return { type: "block", element: block.previousElementSibling, position: "after" };
43371      }
43372      return { type: "block", element: block, position };
43373    }
43374    #findNearestBlock(element, rootElement, clientY) {
43375      let current = element;
43376      while (current && current !== rootElement) {
43377        if (current.parentElement === rootElement) return current;
43378        current = current.parentElement;
43379      }
43380      let nearest = null;
43381      let minDistance = Infinity;
43382      for (const child of rootElement.children) {
43383        const rect = child.getBoundingClientRect();
43384        const distance = Math.min(Math.abs(clientY - rect.top), Math.abs(clientY - rect.bottom));
43385        if (distance < minDistance) {
43386          minDistance = distance;
43387          nearest = child;
43388        }
43389      }
43390      return nearest;
43391    }
43392    #computeVerticalPosition(element, clientY) {
43393      const rect = element.getBoundingClientRect();
43394      return clientY < rect.top + rect.height / 2 ? "before" : "after";
43395    }
43396    #computeHorizontalPosition(element, clientX) {
43397      const rect = element.getBoundingClientRect();
43398      return clientX < rect.left + rect.width / 2 ? "before" : "after";
43399    }
43400    #isGalleryImage(node) {
43401      return $isActionTextAttachmentNode(node) && node.isPreviewableImage;
43402    }
43403    #attachmentNodeForFigure(figure) {
43404      if (!figure?.dataset?.lexicalNodeKey) return null;
43405      const node = $getNodeByKey2(figure.dataset.lexicalNodeKey);
43406      return $isActionTextAttachmentNode(node) ? node : null;
43407    }
43408    #isVerticalEdgeIntent(figure, clientY) {
43409      const rect = figure.getBoundingClientRect();
43410      const edgeZone = Math.min(24, rect.height * 0.15);
43411      return clientY < rect.top + edgeZone || clientY > rect.bottom - edgeZone;
43412    }
43413    #findNearestFigureInGallery(gallery, clientX) {
43414      const figures = gallery.querySelectorAll("figure.attachment[data-lexical-node-key]");
43415      let nearest = null;
43416      let minDistance = Infinity;
43417      for (const figure of figures) {
43418        const rect = figure.getBoundingClientRect();
43419        const center = rect.left + rect.width / 2;
43420        const distance = Math.abs(clientX - center);
43421        if (distance < minDistance) {
43422          minDistance = distance;
43423          nearest = figure;
43424        }
43425      }
43426      return nearest;
43427    }
43428    // -- Drop indicator --------------------------------------------------------
43429    static #DROP_CLASSES = [
43430      "lexxy-drop-target--gallery-before",
43431      "lexxy-drop-target--gallery-after",
43432      "lexxy-drop-target--list-before",
43433      "lexxy-drop-target--list-after",
43434      "lexxy-drop-target--block-before",
43435      "lexxy-drop-target--block-after"
43436    ];
43437    #clearDropIndicators() {
43438      const rootElement = this.#editor.getRootElement();
43439      if (!rootElement) return;
43440      for (const el of rootElement.querySelectorAll("[class*='lexxy-drop-target--']")) {
43441        el.classList.remove(..._AttachmentDragAndDrop.#DROP_CLASSES);
43442      }
43443    }
43444    // -- Node operations -------------------------------------------------------
43445    #performDrop(draggedKey, target) {
43446      const draggedNode = $getNodeByKey2(draggedKey);
43447      if (!draggedNode || !$isActionTextAttachmentNode(draggedNode)) return;
43448      if (target.type === "gallery") {
43449        this.#dropOntoImage(draggedNode, target.nodeKey, target.position);
43450      } else if (target.type === "gallery-reorder") {
43451        this.#reorderInGallery(draggedNode, target.nodeKey, target.position);
43452      } else if (target.type === "list-item") {
43453        this.#dropIntoList(draggedNode, target);
43454      } else {
43455        this.#dropBetweenBlocks(draggedNode, target);
43456      }
43457      $setSelection2(null);
43458    }
43459    #dropOntoImage(draggedNode, targetKey, position) {
43460      const targetNode = $getNodeByKey2(targetKey);
43461      if (!targetNode || !$isActionTextAttachmentNode(targetNode)) return;
43462      if (draggedNode.is(targetNode)) return;
43463      if (!draggedNode.isPreviewableImage || !targetNode.isPreviewableImage) return;
43464      const gallery = $findOrCreateGalleryForImage(targetNode);
43465      if (!gallery) return;
43466      draggedNode.remove();
43467      if (position === "before") {
43468        targetNode.insertBefore(draggedNode);
43469      } else {
43470        targetNode.insertAfter(draggedNode);
43471      }
43472    }
43473    #reorderInGallery(draggedNode, targetKey, position) {
43474      const targetNode = $getNodeByKey2(targetKey);
43475      if (!targetNode || draggedNode.is(targetNode)) return;
43476      if (!draggedNode.isPreviewableImage || !targetNode.isPreviewableImage) return;
43477      draggedNode.remove();
43478      if (position === "before") {
43479        targetNode.insertBefore(draggedNode);
43480      } else {
43481        targetNode.insertAfter(draggedNode);
43482      }
43483    }
43484    #dropIntoList(draggedNode, target) {
43485      const listItemNode = $getNearestNodeFromDOMNode2(target.element);
43486      if (!listItemNode || !$isListItemNode2(listItemNode)) return;
43487      const listNode = listItemNode.getParent();
43488      if (!listNode || !$isListNode2(listNode)) return;
43489      const children = listNode.getChildren();
43490      const index = children.indexOf(listItemNode);
43491      if (index === -1) return;
43492      const splitIndex = target.position === "before" ? index : index + 1;
43493      draggedNode.remove();
43494      if (splitIndex === 0) {
43495        listNode.insertBefore(draggedNode);
43496      } else if (splitIndex >= children.length) {
43497        listNode.insertAfter(draggedNode);
43498      } else {
43499        const [, listAfter] = $splitNode2(listNode, splitIndex);
43500        listAfter.insertBefore(draggedNode);
43501      }
43502    }
43503    #dropBetweenBlocks(draggedNode, target) {
43504      const targetNode = $getNearestNodeFromDOMNode2(target.element);
43505      if (!targetNode) return;
43506      const topLevelTarget = targetNode.getTopLevelElement?.() || targetNode;
43507      if (draggedNode.is(topLevelTarget)) return;
43508      draggedNode.remove();
43509      if (target.position === "before") {
43510        topLevelTarget.insertBefore(draggedNode);
43511      } else {
43512        topLevelTarget.insertAfter(draggedNode);
43513      }
43514    }
43515    // -- Lifecycle helpers -----------------------------------------------------
43516    #cleanup() {
43517      this.#clearDropIndicators();
43518      if (this.#draggedNodeKey) {
43519        const rootElement = this.#editor.getRootElement();
43520        if (rootElement) {
43521          const figure = rootElement.querySelector(`[data-lexical-node-key="${this.#draggedNodeKey}"]`);
43522          figure?.classList.remove("lexxy-dragging");
43523        }
43524      }
43525      this.#draggedNodeKey = null;
43526      if (this.#rafId) {
43527        cancelAnimationFrame(this.#rafId);
43528        this.#rafId = null;
43529      }
43530      if (this.#draggingRafId) {
43531        cancelAnimationFrame(this.#draggingRafId);
43532        this.#draggingRafId = null;
43533      }
43534    }
43535  };
43536  var ATTACHMENT_ATTRIBUTES = [
43537    "alt",
43538    "caption",
43539    "content",
43540    "content-type",
43541    "data-blob-url",
43542    "data-direct-upload-id",
43543    "data-lexxy-image",
43544    "data-sgid",
43545    "filename",
43546    "filesize",
43547    "height",
43548    "presentation",
43549    "previewable",
43550    "sgid",
43551    "url",
43552    "width"
43553  ];
43554  var UPLOADS_BUSY_MESSAGE = "Please wait for all files to upload";
43555  var AttachmentsExtension = class extends LexxyExtension {
43556    #uploadsCount = 0;
43557    get enabled() {
43558      return this.editorElement.supportsAttachments;
43559    }
43560    get allowedElements() {
43561      return [{ tag: ActionTextAttachmentNode.TAG_NAME, attributes: ATTACHMENT_ATTRIBUTES }];
43562    }
43563    get lexicalExtension() {
43564      return defineExtension2({
43565        name: "lexxy/action-text-attachments",
43566        nodes: [
43567          ActionTextAttachmentNode,
43568          ActionTextAttachmentUploadNode,
43569          ImageGalleryNode
43570        ],
43571        register: (editor) => {
43572          const dragAndDrop = new AttachmentDragAndDrop(editor);
43573          return mergeRegister3(
43574            editor.registerNodeTransform(ActionTextAttachmentNode, $extractAttachmentFromParagraph),
43575            editor.registerCommand(DELETE_CHARACTER_COMMAND2, $collapseIntoGallery, COMMAND_PRIORITY_NORMAL2),
43576            editor.registerMutationListener(ActionTextAttachmentUploadNode, this.#handleUploadMutations.bind(this)),
43577            () => dragAndDrop.destroy()
43578          );
43579        }
43580      });
43581    }
43582    #handleUploadMutations(mutations) {
43583      const previousUploadsCount = this.#uploadsCount;
43584      for (const [key, mutation] of mutations) {
43585        if (mutation === "created") {
43586          this.#uploadsCount++;
43587        } else if (mutation === "destroyed") {
43588          this.#uploadsCount--;
43589          this.editorElement.uploadRequests.abort(key);
43590        }
43591      }
43592      if (this.#uploadsCount !== previousUploadsCount) {
43593        this.#setUploadsValidity();
43594      }
43595    }
43596    #setUploadsValidity() {
43597      if (this.#uploadsCount) {
43598        this.setEditorValidity({ customError: true }, UPLOADS_BUSY_MESSAGE);
43599      } else {
43600        this.setEditorValidity({});
43601      }
43602    }
43603  };
43604  function $extractAttachmentFromParagraph(attachmentNode) {
43605    const parentNode = attachmentNode.getParent();
43606    if (!$isParagraphNode2(parentNode)) return;
43607    if (parentNode.getChildrenSize() === 1) {
43608      parentNode.replace(attachmentNode);
43609    } else {
43610      const index = attachmentNode.getIndexWithinParent();
43611      const [topParagraph, bottomParagraph] = $splitNode2(parentNode, index);
43612      topParagraph.insertAfter(attachmentNode);
43613      for (const p2 of [topParagraph, bottomParagraph]) {
43614        if (p2.isEmpty()) p2.remove();
43615      }
43616    }
43617  }
43618  function $collapseIntoGallery(backwards) {
43619    const anchor = $getSelection2()?.anchor;
43620    if (!anchor) return false;
43621    if ($collapseAtGalleryEdge(anchor, backwards)) {
43622      return true;
43623    } else if (backwards) {
43624      return $collapseAroundEmptyParagraph(anchor) || $moveSelectionBeforeGallery(anchor);
43625    }
43626    return false;
43627  }
43628  function $collapseAroundEmptyParagraph(anchor) {
43629    const anchorNode = anchor.getNode();
43630    if (!anchorNode) return false;
43631    const isWithinEmptyParagraph = $isParagraphNode2(anchorNode) && anchorNode.isEmpty();
43632    const previousSibling = anchorNode.getPreviousSibling();
43633    const topGallery = $findOrCreateGalleryForImage(previousSibling);
43634    const selectionIndex = topGallery?.getChildrenSize();
43635    if (isWithinEmptyParagraph && topGallery?.collapseWith(anchorNode.getNextSibling())) {
43636      topGallery.select(selectionIndex, selectionIndex);
43637      anchorNode.remove();
43638      return true;
43639    } else {
43640      return false;
43641    }
43642  }
43643  function $collapseAtGalleryEdge(anchor, backwards) {
43644    const anchorNode = anchor.getNode();
43645    if (!$isImageGalleryNode(anchorNode)) return false;
43646    const isAtGalleryEdge = $isAtNodeEdge(anchor, backwards);
43647    const sibling = backwards ? anchorNode.getPreviousSibling() : anchorNode.getNextSibling();
43648    if (isAtGalleryEdge && anchorNode.collapseWith(sibling, backwards)) {
43649      const selectionOffset = backwards ? 1 : anchorNode.getChildrenSize() - 1;
43650      anchorNode.select(selectionOffset, selectionOffset);
43651      return true;
43652    } else {
43653      return false;
43654    }
43655  }
43656  function $moveSelectionBeforeGallery(anchor) {
43657    const previousNode = anchor.getNode().getPreviousSibling();
43658    if (!$isImageGalleryNode(anchor.getNode()) || !$isAtNodeEdge(anchor, true) || !previousNode) return false;
43659    if ($isDecoratorNode2(previousNode)) {
43660      return false;
43661    } else if (previousNode.isEmpty()) {
43662      previousNode.remove();
43663    } else {
43664      previousNode.selectEnd();
43665    }
43666    return true;
43667  }
43668  var EarlyEscapeCodeNode = class _EarlyEscapeCodeNode extends CodeNode3 {
43669    $config() {
43670      return this.config("early_escape_code", { extends: CodeNode3 });
43671    }
43672    static $fromSelection(selection) {
43673      const anchorNode = selection.anchor.getNode();
43674      return $getNearestNodeOfType2(anchorNode, _EarlyEscapeCodeNode) || (anchorNode instanceof _EarlyEscapeCodeNode ? anchorNode : null);
43675    }
43676    insertNewAfter(selection, restoreSelection) {
43677      if ($hasUpdateTag2(PASTE_TAG2) || !selection.isCollapsed()) {
43678        return super.insertNewAfter(selection, restoreSelection);
43679      } else if (this.#isCursorAtStart(selection)) {
43680        return this.#insertParagraphBefore();
43681      } else if (this.#isCursorOnWhitespaceOnlyLastLine(selection)) {
43682        return this.#insertBlankLineBelow(selection, restoreSelection);
43683      } else if (this.#isCursorOnEmptyLastLine(selection)) {
43684        return this.#escapeToNewParagraphAfter();
43685      } else {
43686        return super.insertNewAfter(selection, restoreSelection);
43687      }
43688    }
43689    #isCursorAtStart(selection) {
43690      const { anchor } = selection;
43691      if (!$isAtNodeStart(anchor)) return false;
43692      const anchorNode = anchor.getNode();
43693      return this.is(anchorNode) || this.getFirstChild()?.is(anchorNode);
43694    }
43695    #isCursorOnEmptyLastLine(selection) {
43696      if (!$isCursorOnLastLine(selection)) return false;
43697      const textContent = this.getTextContent();
43698      return textContent === "" || textContent.endsWith("\n");
43699    }
43700    #isCursorOnWhitespaceOnlyLastLine(selection) {
43701      if (!$isCursorOnLastLine(selection)) return false;
43702      const textContent = this.getTextContent();
43703      const lastNewlineIndex = textContent.lastIndexOf("\n");
43704      const lastLine = lastNewlineIndex === -1 ? textContent : textContent.slice(lastNewlineIndex + 1);
43705      return lastLine.length > 0 && lastLine.trim() === "";
43706    }
43707    #insertParagraphBefore() {
43708      this.insertBefore($createParagraphNode2());
43709      return null;
43710    }
43711    #insertBlankLineBelow(selection, restoreSelection) {
43712      super.insertNewAfter(selection, restoreSelection);
43713      this.getLastChild().remove();
43714      return null;
43715    }
43716    #escapeToNewParagraphAfter() {
43717      $trimTrailingBlankNodes(this);
43718      const paragraph = $createParagraphNode2();
43719      this.insertAfter(paragraph);
43720      return paragraph;
43721    }
43722  };
43723  var EarlyEscapeListItemNode = class extends ListItemNode2 {
43724    $config() {
43725      return this.config("early_escape_listitem", { extends: ListItemNode2 });
43726    }
43727    insertNewAfter(selection, restoreSelection) {
43728      if (this.#shouldEscape(selection)) {
43729        return this.#escapeFromList();
43730      }
43731      return super.insertNewAfter(selection, restoreSelection);
43732    }
43733    get #isInBlockquote() {
43734      return Boolean($getNearestNodeOfType2(this, QuoteNode2));
43735    }
43736    #shouldEscape(selection) {
43737      if (this.#isInPasteOperation() || !this.#isInBlockquote) {
43738        return false;
43739      } else if ($isBlankNode(this)) {
43740        return true;
43741      } else {
43742        const paragraph = $getNearestNodeOfType2(selection.anchor.getNode(), ParagraphNode2);
43743        return paragraph && $isBlankNode(paragraph) && $isListItemNode2(paragraph.getParent());
43744      }
43745    }
43746    #isInPasteOperation() {
43747      return $hasUpdateTag2(PASTE_TAG2);
43748    }
43749    #escapeFromList() {
43750      const parentList = this.getParent();
43751      if (!parentList || !$isListNode2(parentList)) return;
43752      const blockquote = parentList.getParent();
43753      const isInBlockquote = blockquote && $isQuoteNode2(blockquote);
43754      if (isInBlockquote) {
43755        const hasNonEmptyListItems = this.getNextSiblings().some(
43756          (sibling) => $isListItemNode2(sibling) && !$isBlankNode(sibling)
43757        );
43758        if (hasNonEmptyListItems) {
43759          return this.#splitBlockquoteWithList();
43760        }
43761      }
43762      const paragraph = $createParagraphNode2();
43763      parentList.insertAfter(paragraph);
43764      this.remove();
43765      return paragraph;
43766    }
43767    #splitBlockquoteWithList() {
43768      const splitQuotes = $splitNode2(this.getParent(), this.getIndexWithinParent());
43769      this.remove();
43770      const middleParagraph = $createParagraphNode2();
43771      splitQuotes[0].insertAfter(middleParagraph);
43772      splitQuotes.forEach($trimTrailingBlankNodes);
43773      return middleParagraph;
43774    }
43775  };
43776  var FormatEscapeExtension = class extends LexxyExtension {
43777    get enabled() {
43778      return this.editorElement.supportsRichText;
43779    }
43780    get allowedElements() {
43781      return [{ tag: "ol", attributes: ["start"] }, { tag: "li", attributes: ["value"] }];
43782    }
43783    get lexicalExtension() {
43784      return defineExtension2({
43785        name: "lexxy/format-escape",
43786        nodes: [
43787          EarlyEscapeCodeNode,
43788          { replace: CodeNode3, with: (node) => new EarlyEscapeCodeNode(node.getLanguage()), withKlass: EarlyEscapeCodeNode },
43789          EarlyEscapeListItemNode,
43790          { replace: ListItemNode2, with: () => new EarlyEscapeListItemNode(), withKlass: EarlyEscapeListItemNode }
43791        ],
43792        register(editor) {
43793          return mergeRegister3(
43794            editor.registerCommand(
43795              INSERT_PARAGRAPH_COMMAND2,
43796              () => $escapeFromBlockquote(),
43797              COMMAND_PRIORITY_HIGH2
43798            ),
43799            editor.registerCommand(
43800              KEY_ARROW_DOWN_COMMAND2,
43801              (event) => $handleArrowDownInCodeBlock(event),
43802              COMMAND_PRIORITY_NORMAL2
43803            ),
43804            editor.registerNodeTransform(QuoteNode2, $ensureQuoteHasParagraphChild)
43805          );
43806        }
43807      });
43808    }
43809  };
43810  function $escapeFromBlockquote() {
43811    return $escapeBeforeBlockquoteStart() || $escapeFromBlankBlockquoteParagraph();
43812  }
43813  function $escapeBeforeBlockquoteStart() {
43814    const selection = $getSelection2();
43815    if (!$isRangeSelection2(selection) || !selection.isCollapsed() || selection.anchor.offset !== 0) return false;
43816    const paragraph = $getNearestNodeOfType2(selection.anchor.getNode(), ParagraphNode2);
43817    if (paragraph && !$isBlankNode(paragraph) && !paragraph.getPreviousSibling()) {
43818      const blockquote = paragraph.getParent();
43819      if ($isQuoteNode2(blockquote)) {
43820        blockquote.insertBefore($createParagraphNode2());
43821        return true;
43822      }
43823    }
43824    return false;
43825  }
43826  function $escapeFromBlankBlockquoteParagraph() {
43827    const anchorNode = $getSelection2().anchor.getNode();
43828    const paragraph = $getNearestNodeOfType2(anchorNode, ParagraphNode2);
43829    if (!paragraph || !$isBlankNode(paragraph)) return false;
43830    const blockquote = paragraph.getParent();
43831    if ($isQuoteNode2(blockquote)) {
43832      const nonEmptySiblings = paragraph.getNextSiblings().filter((sibling) => !$isBlankNode(sibling));
43833      if (nonEmptySiblings.length > 0) {
43834        $splitQuoteNode(blockquote, paragraph);
43835      } else {
43836        blockquote.insertAfter(paragraph);
43837        paragraph.selectStart();
43838      }
43839      return true;
43840    }
43841    return false;
43842  }
43843  function $splitQuoteNode(node, paragraph) {
43844    const splitQuotes = $splitNode2(node, paragraph.getIndexWithinParent());
43845    splitQuotes[0].insertAfter(paragraph);
43846    splitQuotes.forEach($trimTrailingBlankNodes);
43847    paragraph.selectEnd();
43848  }
43849  function $handleArrowDownInCodeBlock(event) {
43850    const selection = $getSelection2();
43851    if (!$isRangeSelection2(selection) || !selection.isCollapsed()) return false;
43852    const codeNode = EarlyEscapeCodeNode.$fromSelection(selection);
43853    if (!codeNode) return false;
43854    if ($isCursorOnLastLine(selection) && !codeNode.getNextSibling()) {
43855      event?.preventDefault();
43856      const paragraph = $createParagraphNode2();
43857      codeNode.insertAfter(paragraph);
43858      paragraph.selectEnd();
43859      return true;
43860    }
43861    return false;
43862  }
43863  function $ensureQuoteHasParagraphChild(quoteNode) {
43864    if (!quoteNode.isEmpty()) return;
43865    quoteNode.append($createParagraphNode2());
43866    if ($containsRangeSelection(quoteNode)) quoteNode.getFirstChild().select();
43867  }
43868  var LinkOpenerExtension = class extends LexxyExtension {
43869    get enabled() {
43870      return this.editorElement.supportsRichText;
43871    }
43872    get lexicalExtension() {
43873      return defineExtension2({
43874        name: "lexxy/link-opener",
43875        register: (editor) => mergeRegister2(
43876          editor.registerCommand(CLICK_COMMAND2, this.#handleClick.bind(this), COMMAND_PRIORITY_NORMAL2),
43877          registerEventListener(this.editorElement.editorContentElement, "auxclick", this.#handleAuxClick.bind(this)),
43878          registerEventListener(window, "keydown", this.#handleKey.bind(this)),
43879          registerEventListener(window, "keyup", this.#handleKey.bind(this)),
43880          registerEventListener(window, "focus", this.#handleFocus.bind(this))
43881        )
43882      });
43883    }
43884    #handleClick(event) {
43885      if (this.#isModified(event)) {
43886        return $openLink(event.target);
43887      } else {
43888        return false;
43889      }
43890    }
43891    #handleAuxClick(event) {
43892      if (event.button === 1) {
43893        this.editorElement.editor.read(() => $openLink(event.target));
43894      }
43895    }
43896    #handleKey(event) {
43897      this.#updateOpenableAttribute(event);
43898    }
43899    // Chrome dispatches events without modifier keys *for a while* after changing tabs
43900    async #handleFocus() {
43901      await delay(200);
43902      this.editorElement.addEventListener("mousemove", this.#updateOpenableAttribute.bind(this), { once: true });
43903    }
43904    #updateOpenableAttribute(event) {
43905      this.editorElement.toggleAttribute("data-links-openable", this.#isModified(event));
43906    }
43907    #isModified(event) {
43908      return IS_APPLE3 ? event.metaKey : event.ctrlKey;
43909    }
43910  };
43911  function $openLink(target) {
43912    const node = $getNearestNodeFromDOMNode2(target);
43913    const linkNode = $findMatchingParent2(node, $isLinkNode2);
43914    if (linkNode) {
43915      const url = linkNode.sanitizeUrl(linkNode.getURL());
43916      window.open(url, "_blank", "noopener,noreferrer");
43917      return true;
43918    } else {
43919      return false;
43920    }
43921  }
43922  var PreventLexicalTripleClickExtension = class extends LexxyExtension {
43923    get lexicalExtension() {
43924      return defineExtension2({
43925        name: "lexxy/prevent-lexical-triple-click",
43926        register: (editor) => editor.registerRootListener((rootElement) => {
43927          if (rootElement) {
43928            return registerEventListener(
43929              rootElement,
43930              "click",
43931              this.#handleTripleClick.bind(this),
43932              { capture: true }
43933            );
43934          }
43935        })
43936      });
43937    }
43938    // Stop propagation of the triple-click to prevent Lexical's handler from running.
43939    //
43940    // Lexical's onClick handler implements a triple-click handler that is trivial/anemic/naïve. The
43941    // intention of the change, made in facebook/lexical#4512, seems to be to deal with browsers'
43942    // "overselection" behavior, where a triple-click selection might end at offset 0 of the following
43943    // block, which can cause issues when transforming the selection. But the implementation breaks
43944    // many common real-world use cases and Lexxy does not demonstrate the behavior it's intended to
43945    // work around (in headers or tables).
43946    #handleTripleClick(event) {
43947      if (event.detail === 3) {
43948        event.stopPropagation();
43949      }
43950    }
43951  };
43952  function caretRect(node, offset3) {
43953    const range2 = document.createRange();
43954    range2.setStart(node, offset3);
43955    range2.collapse(true);
43956    const rect = range2.getBoundingClientRect();
43957    if (rect.height > 0) {
43958      return rect;
43959    } else {
43960      return null;
43961    }
43962  }
43963  function caretFromPoint3(clientX, clientY) {
43964    if (document.caretPositionFromPoint) {
43965      const position = document.caretPositionFromPoint(clientX, clientY);
43966      if (position) return { node: position.offsetNode, offset: position.offset };
43967    } else if (document.caretRangeFromPoint) {
43968      const range2 = document.caretRangeFromPoint(clientX, clientY);
43969      if (range2) return { node: range2.startContainer, offset: range2.startOffset };
43970    }
43971    return null;
43972  }
43973  var MIME_TYPE = "application/x-lexxy-custom-attachment-key";
43974  var CustomAttachmentDragAndDrop = class {
43975    #editor;
43976    #draggedNodeKey = null;
43977    #draggingRafId = null;
43978    #dragOverRafId = null;
43979    #dropIndicator = null;
43980    #listeners = new ListenerBin();
43981    constructor(editor) {
43982      this.#editor = editor;
43983      this.#listeners.track(
43984        editor.registerCommand(DRAGSTART_COMMAND2, (event) => this.#handleDragStart(event), COMMAND_PRIORITY_HIGH2),
43985        editor.registerCommand(DROP_COMMAND2, (event) => this.#handleDrop(event), COMMAND_PRIORITY_HIGH2)
43986      );
43987      this.#listeners.track(editor.registerRootListener((root, prevRoot) => {
43988        if (prevRoot) {
43989          prevRoot.removeEventListener("dragover", this.#onDragOver);
43990          prevRoot.removeEventListener("dragend", this.#onDragEnd);
43991        }
43992        if (root) {
43993          root.addEventListener("dragover", this.#onDragOver);
43994          root.addEventListener("dragend", this.#onDragEnd);
43995        }
43996      }));
43997    }
43998    destroy() {
43999      this.#cleanup();
44000      this.#dropIndicator?.remove();
44001      this.#dropIndicator = null;
44002      this.#listeners.dispose();
44003    }
44004    #handleDragStart(event) {
44005      const attachment = this.#customAttachmentElementFrom(event.target);
44006      if (!attachment) return false;
44007      this.#draggedNodeKey = attachment.dataset.lexicalNodeKey;
44008      event.dataTransfer.setData(MIME_TYPE, this.#draggedNodeKey);
44009      event.dataTransfer.effectAllowed = "move";
44010      this.#draggingRafId = requestAnimationFrame(() => {
44011        this.#draggingRafId = null;
44012        attachment.classList.add("lexxy-dragging");
44013      });
44014      return true;
44015    }
44016    #onDragOver = (event) => {
44017      if (!this.#draggedNodeKey) return;
44018      event.preventDefault();
44019      event.dataTransfer.dropEffect = "move";
44020      if (!this.#dragOverRafId) {
44021        this.#dragOverRafId = requestAnimationFrame(() => {
44022          this.#dragOverRafId = null;
44023          this.#updateDropIndicator(event);
44024        });
44025      }
44026    };
44027    #onDragEnd = () => {
44028      this.#cleanup();
44029    };
44030    #handleDrop(event) {
44031      if (!this.#draggedNodeKey) return false;
44032      event.preventDefault();
44033      const dropPoint = this.#resolveDropPoint(event);
44034      const draggedKey = this.#draggedNodeKey;
44035      this.#cleanup();
44036      if (dropPoint) {
44037        this.#moveAttachment(draggedKey, dropPoint);
44038      }
44039      return true;
44040    }
44041    #resolveDropPoint(event) {
44042      const rootElement = this.#editor.getRootElement();
44043      if (!rootElement) return null;
44044      const caret = caretFromPoint3(event.clientX, event.clientY);
44045      if (!caret || !rootElement.contains(caret.node)) return null;
44046      if (caret.node === rootElement) {
44047        return this.#nearestLineCaret(rootElement, event.clientY);
44048      }
44049      const decorator = this.#decoratorElementContaining(caret.node);
44050      if (decorator) {
44051        return this.#dropPointBesideDecorator(decorator, event.clientX);
44052      } else {
44053        return caret;
44054      }
44055    }
44056    #nearestLineCaret(rootElement, clientY) {
44057      let nearestLine = null;
44058      let nearestDistance = Infinity;
44059      for (const line of rootElement.children) {
44060        const rect2 = line.getBoundingClientRect();
44061        const distance = Math.min(Math.abs(clientY - rect2.top), Math.abs(clientY - rect2.bottom));
44062        if (distance < nearestDistance) {
44063          nearestDistance = distance;
44064          nearestLine = line;
44065        }
44066      }
44067      if (!nearestLine) return null;
44068      const rect = nearestLine.getBoundingClientRect();
44069      if (clientY < rect.top) {
44070        return { node: nearestLine, offset: 0 };
44071      } else {
44072        return { node: nearestLine, offset: nearestLine.childNodes.length };
44073      }
44074    }
44075    #decoratorElementContaining(node) {
44076      const element = node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;
44077      return element?.closest("[data-lexxy-decorator][data-lexical-node-key]");
44078    }
44079    #dropPointBesideDecorator(decorator, clientX) {
44080      const rect = decorator.getBoundingClientRect();
44081      const placement = clientX > rect.left + rect.width / 2 ? "after" : "before";
44082      return { decoratorKey: decorator.dataset.lexicalNodeKey, placement };
44083    }
44084    #moveAttachment(draggedKey, dropPoint) {
44085      this.#editor.update(() => {
44086        const draggedNode = $getNodeByKey2(draggedKey);
44087        if (!$isCustomActionTextAttachmentNode(draggedNode)) return;
44088        if (dropPoint.decoratorKey) {
44089          this.#moveBesideNode(draggedNode, dropPoint);
44090        } else {
44091          this.#moveToCaret(draggedNode, dropPoint);
44092        }
44093      });
44094    }
44095    #moveBesideNode(draggedNode, { decoratorKey, placement }) {
44096      const targetNode = $getNodeByKey2(decoratorKey);
44097      if (!targetNode || targetNode === draggedNode) return;
44098      draggedNode.remove();
44099      if (placement === "after") {
44100        targetNode.insertAfter(draggedNode);
44101      } else {
44102        targetNode.insertBefore(draggedNode);
44103      }
44104    }
44105    #moveToCaret(draggedNode, dropPoint) {
44106      const selection = $createRangeSelectionFromDom2({
44107        anchorNode: dropPoint.node,
44108        anchorOffset: dropPoint.offset,
44109        focusNode: dropPoint.node,
44110        focusOffset: dropPoint.offset
44111      }, this.#editor);
44112      if (!selection) return;
44113      $setSelection2(selection);
44114      draggedNode.remove();
44115      selection.insertNodes([draggedNode]);
44116    }
44117    #updateDropIndicator(event) {
44118      this.#hideCaret();
44119      const dropPoint = this.#resolveDropPoint(event);
44120      if (dropPoint) this.#showCaret(this.#caretRectFor(dropPoint));
44121    }
44122    #caretRectFor(dropPoint) {
44123      if (dropPoint.decoratorKey) {
44124        return this.#decoratorEdgeRect(dropPoint);
44125      }
44126      const { node, offset: offset3 } = dropPoint;
44127      const rect = caretRect(node, offset3);
44128      if (rect) return rect;
44129      const line = node.nodeType === Node.TEXT_NODE ? node.parentElement : node;
44130      if (!line) return null;
44131      const lineRect = line.getBoundingClientRect();
44132      return { left: lineRect.left, top: lineRect.top, height: lineRect.height };
44133    }
44134    #decoratorEdgeRect({ decoratorKey, placement }) {
44135      const decorator = this.#editor.getRootElement()?.querySelector(`[data-lexical-node-key="${decoratorKey}"]`);
44136      if (!decorator) return null;
44137      const rect = decorator.getBoundingClientRect();
44138      const left = placement === "after" ? rect.right : rect.left;
44139      return { left, top: rect.top, height: rect.height };
44140    }
44141    #showCaret(rect) {
44142      if (!rect) return;
44143      const caret = this.#ensureCaretIndicator();
44144      caret.style.blockSize = `${rect.height}px`;
44145      caret.style.insetInlineStart = `${rect.left}px`;
44146      caret.style.insetBlockStart = `${rect.top}px`;
44147    }
44148    #ensureCaretIndicator() {
44149      this.#dropIndicator ||= createElement("div", { className: "lexxy-drop-caret" });
44150      this.#editorElement().appendChild(this.#dropIndicator);
44151      this.#dropIndicator.style.display = "block";
44152      return this.#dropIndicator;
44153    }
44154    #editorElement() {
44155      return this.#editor.getRootElement().closest("lexxy-editor");
44156    }
44157    #hideCaret() {
44158      if (this.#dropIndicator) this.#dropIndicator.style.display = "none";
44159    }
44160    #customAttachmentElementFrom(target) {
44161      return target?.closest?.("[data-lexxy-decorator][data-lexical-node-key]");
44162    }
44163    #cleanup() {
44164      if (this.#draggedNodeKey) {
44165        const rootElement = this.#editor.getRootElement();
44166        const attachment = rootElement?.querySelector(`[data-lexical-node-key="${this.#draggedNodeKey}"]`);
44167        attachment?.classList.remove("lexxy-dragging");
44168      }
44169      this.#hideCaret();
44170      this.#draggedNodeKey = null;
44171      if (this.#draggingRafId) {
44172        cancelAnimationFrame(this.#draggingRafId);
44173        this.#draggingRafId = null;
44174      }
44175      if (this.#dragOverRafId) {
44176        cancelAnimationFrame(this.#dragOverRafId);
44177        this.#dragOverRafId = null;
44178      }
44179    }
44180  };
44181  var CustomAttachmentDragAndDropExtension = class extends LexxyExtension {
44182    get enabled() {
44183      return this.editorElement.supportsRichText;
44184    }
44185    get lexicalExtension() {
44186      return defineExtension2({
44187        name: "lexxy/custom-attachment-drag-and-drop",
44188        register: (editor) => {
44189          const dragAndDrop = new CustomAttachmentDragAndDrop(editor);
44190          return () => dragAndDrop.destroy();
44191        }
44192      });
44193    }
44194  };
44195  var LexicalEditorElement = class extends HTMLElement {
44196    static formAssociated = true;
44197    static debug = false;
44198    static commands = ["bold", "italic", "strikethrough"];
44199    static observedAttributes = ["autocapitalize", "connected", "required"];
44200    #initialValue = "";
44201    #previousInternalFormValue = null;
44202    #initializeEventDispatched = false;
44203    #editorInitializedDispatched = false;
44204    #listeners = new ListenerBin();
44205    #disposables = [];
44206    #historyState = { undo: false, redo: false };
44207    #validity = /* @__PURE__ */ new Map();
44208    #validationTextArea = document.createElement("textarea");
44209    #uploadRequests;
44210    constructor() {
44211      super();
44212      this.internals = this.attachInternals();
44213      this.internals.role = "presentation";
44214    }
44215    get uploadRequests() {
44216      return this.#uploadRequests;
44217    }
44218    connectedCallback() {
44219      this.id ||= generateDomId("lexxy-editor");
44220      this.config = new EditorConfiguration(this);
44221      this.extensions = new Extensions(this);
44222      this.#disposables.push(this.extensions);
44223      this.editor = this.#createEditor();
44224      this.#disposables.push(this.editor);
44225      this.#disposables.push(this.#listeners);
44226      this.contents = new Contents(this);
44227      this.#disposables.push(this.contents);
44228      this.selection = new Selection(this);
44229      this.#disposables.push(this.selection);
44230      this.clipboard = new Clipboard(this);
44231      this.#disposables.push(this.clipboard);
44232      this.adapter = new BrowserAdapter();
44233      this.#uploadRequests = new UploadRequests();
44234      const commandDispatcher = CommandDispatcher.configureFor(this);
44235      this.#disposables.push(commandDispatcher);
44236      this.#initialize();
44237      this.toggleAttribute("connected", true);
44238      requestAnimationFrame(() => {
44239        this.#mountRoot();
44240        this.#handleAutofocus();
44241        this.#dispatchInitialize();
44242      });
44243    }
44244    disconnectedCallback() {
44245      this.#initializeEventDispatched = false;
44246      this.#editorInitializedDispatched = false;
44247      this.#previousInternalFormValue = null;
44248      this.valueBeforeDisconnect = this.value;
44249      this.#clearCachedValues();
44250      this.#reset();
44251    }
44252    attributeChangedCallback(name, oldValue, newValue) {
44253      if (typeof this[`${name}ChangedCallback`] === "function") {
44254        this[`${name}ChangedCallback`](oldValue, newValue);
44255      }
44256    }
44257    autocapitalizeChangedCallback() {
44258      if (this.editorContentElement) {
44259        this.#transferAttributeToContentEditable(this.editorContentElement, "autocapitalize");
44260      }
44261    }
44262    connectedChangedCallback(oldValue, newValue) {
44263      if (this.isConnected && oldValue != null && oldValue !== newValue) {
44264        requestAnimationFrame(() => this.#reconnect());
44265      }
44266    }
44267    requiredChangedCallback() {
44268      if (this.isConnected) this.#requestValidityRefresh();
44269    }
44270    formResetCallback() {
44271      this.value = this.#initialValue;
44272      this.editor.dispatchCommand(CLEAR_HISTORY_COMMAND2, void 0);
44273    }
44274    toString() {
44275      return this.cachedStringValue ??= this.editor?.read(() => {
44276        return $getReadableTextContent($getRoot2());
44277      });
44278    }
44279    get form() {
44280      return this.internals.form;
44281    }
44282    get name() {
44283      return this.getAttribute("name");
44284    }
44285    get required() {
44286      return this.hasAttribute("required");
44287    }
44288    get validity() {
44289      return this.internals.validity;
44290    }
44291    checkValidity() {
44292      return this.internals.checkValidity();
44293    }
44294    reportValidity() {
44295      return this.internals.reportValidity();
44296    }
44297    setElementValidity(key, flags, message) {
44298      this.#validity.set(key, { flags, message });
44299      this.#requestValidityRefresh();
44300    }
44301    get toolbarElement() {
44302      if (!this.#hasToolbar) return null;
44303      this.toolbar ??= this.#findOrCreateDefaultToolbar();
44304      return this.toolbar;
44305    }
44306    get baseExtensions() {
44307      return [
44308        ProvisionalParagraphExtension,
44309        CodeHighlightingExtension,
44310        HighlightExtension,
44311        TrixContentExtension,
44312        TablesExtension,
44313        RewritableHistoryExtension,
44314        AttachmentsExtension,
44315        FormatEscapeExtension,
44316        LinkOpenerExtension,
44317        PreventLexicalTripleClickExtension,
44318        CustomAttachmentDragAndDropExtension
44319      ];
44320    }
44321    get directUploadUrl() {
44322      return this.dataset.directUploadUrl;
44323    }
44324    get blobUrlTemplate() {
44325      return this.dataset.blobUrlTemplate;
44326    }
44327    get permittedAttachmentTypes() {
44328      const raw = this.config.get("permittedAttachmentTypes");
44329      if (raw == null) {
44330        return null;
44331      } else {
44332        const tokens = Array.isArray(raw) ? raw : String(raw).split(/\s+/);
44333        return Object.freeze(tokens.filter((t2) => t2 && t2 !== "false"));
44334      }
44335    }
44336    permitsAttachmentContentType(contentType) {
44337      if (!this.supportsAttachments) {
44338        return false;
44339      } else {
44340        const list = this.permittedAttachmentTypes;
44341        return list === null || list.includes(contentType);
44342      }
44343    }
44344    acceptsFile(file) {
44345      return dispatch(this, "lexxy:file-accept", { file }, true);
44346    }
44347    $generateNodesFromDOM(doc, { editor = this.editor } = {}) {
44348      let nodes = $generateNodesFromDOM2(editor, doc);
44349      if ($hasUpdateTag2(PASTE_TAG2)) nodes = $convertInlineImageDataURIs(nodes, this);
44350      return filterDisallowedAttachmentNodes(nodes, this);
44351    }
44352    get isEmpty() {
44353      return ["<p><br></p>", "<p></p>", ""].includes(this.value.trim());
44354    }
44355    get isBlank() {
44356      return this.isEmpty || this.toString().match(/^\s*$/g) !== null;
44357    }
44358    get hasOpenPrompt() {
44359      return this.querySelector(".lexxy-prompt-menu.lexxy-prompt-menu--visible") !== null;
44360    }
44361    get preset() {
44362      return this.getAttribute("preset") || "default";
44363    }
44364    get supportsAttachments() {
44365      return this.config.get("attachments");
44366    }
44367    get supportsMarkdown() {
44368      return this.supportsRichText && this.config.get("markdown");
44369    }
44370    get supportsMultiLine() {
44371      return this.config.get("multiLine") && !this.isSingleLineMode;
44372    }
44373    get supportsRichText() {
44374      return this.config.get("richText");
44375    }
44376    registerAdapter(adapter) {
44377      this.adapter = adapter;
44378      if (!this.editor) return;
44379      this.#dispatchEditorInitialized();
44380      this.#dispatchAttributesChange();
44381    }
44382    freezeSelection() {
44383      this.adapter.freeze();
44384    }
44385    thawSelection() {
44386      this.adapter.thaw();
44387    }
44388    dispatchAttributesChange() {
44389      this.#dispatchAttributesChange();
44390    }
44391    dispatchEditorInitialized() {
44392      this.#dispatchEditorInitialized();
44393    }
44394    // TODO: Deprecate `single-line` attribute
44395    get isSingleLineMode() {
44396      return this.hasAttribute("single-line");
44397    }
44398    get contentTabIndex() {
44399      return parseInt(this.editorContentElement?.getAttribute("tabindex") ?? "0");
44400    }
44401    focus() {
44402      if (this.#isContentFocused) return;
44403      this.editor.focus(() => this.#onFocus());
44404    }
44405    get #isContentFocused() {
44406      return !!this.editor && isEditorFocused(this.editor);
44407    }
44408    get value() {
44409      return this.cachedValue ??= this.#readSanitizedEditorValue();
44410    }
44411    set value(html2) {
44412      const editorHasFocus = this.#isContentFocused;
44413      this.editor.update(() => {
44414        if (editorHasFocus) {
44415          $onUpdate2(() => this.editor.focus());
44416        } else {
44417          $addUpdateTag2(SKIP_DOM_SELECTION_TAG2);
44418        }
44419        this.#setEditorHtml(html2);
44420        this.#toggleEmptyStatus();
44421      }, { discrete: true });
44422    }
44423    get canUndo() {
44424      return this.#historyState.undo;
44425    }
44426    get canRedo() {
44427      return this.#historyState.redo;
44428    }
44429    #readSanitizedEditorValue() {
44430      return this.editor?.read(() => {
44431        return sanitize($generateHtmlFromNodes2(this.editor, null));
44432      }) ?? null;
44433    }
44434    #parseHtmlIntoLexicalNodes(html2, { editor = this.editor } = {}) {
44435      if (!html2) html2 = "<p></p>";
44436      const nodes = this.$generateNodesFromDOM(parseHtml(`${html2}`), { editor });
44437      return nodes.filter(this.#isNotWhitespaceOnlyNode).map(this.#wrapTextNode);
44438    }
44439    // Whitespace-only text nodes (e.g. "\n" between block elements like <div>) and stray line break
44440    // nodes are formatting artifacts from the HTML source. They can't be appended to the root node
44441    // and have no semantic meaning, so we strip them during import.
44442    #isNotWhitespaceOnlyNode(node) {
44443      if ($isLineBreakNode2(node)) return false;
44444      if ($isTextNode2(node) && node.getTextContent().trim() === "") return false;
44445      return true;
44446    }
44447    // Raw string values produce TextNodes which cannot be appended directly to the RootNode.
44448    // We wrap those in <p>
44449    #wrapTextNode(node) {
44450      if (!$isTextNode2(node)) return node;
44451      const paragraph = $createParagraphNode2();
44452      paragraph.append(node);
44453      return paragraph;
44454    }
44455    #initialize() {
44456      this.#registerComponents();
44457      this.#handleEnter();
44458      this.#registerFocusEvents();
44459      this.#registerHistoryEvents();
44460      this.#registerFileAcceptFilter();
44461      this.#attachDebugHooks();
44462      this.#attachToolbar();
44463      this.#resetBeforeTurboCaches();
44464      this.#setInternalFormValue(this.value, { suppressEvent: true });
44465      this.#synchronizeWithChanges();
44466    }
44467    #registerFileAcceptFilter() {
44468      this.#listeners.track(
44469        registerEventListener(this, "lexxy:file-accept", (event) => {
44470          if (!this.permitsAttachmentContentType(event.detail.file.type)) {
44471            event.preventDefault();
44472          }
44473        })
44474      );
44475    }
44476    #createEditor() {
44477      this.editorContentElement ||= this.#createEditorContentElement();
44478      this.appendChild(this.editorContentElement);
44479      const editor = buildEditorFromExtensions2(
44480        {
44481          name: "lexxy/core",
44482          namespace: "Lexxy",
44483          theme,
44484          nodes: this.#lexicalNodes,
44485          html: {
44486            export: /* @__PURE__ */ new Map([[TextNode2, exportTextNodeDOM], [CodeHighlightNode3, exportTextNodeDOM]])
44487          },
44488          $initialEditorState: (editor2) => {
44489            this.#configureSanitizer(editor2);
44490            this.#loadInitialValue(editor2);
44491          }
44492        },
44493        ...this.extensions.lexicalExtensions
44494      );
44495      return editor;
44496    }
44497    // Toggling editable around setRootElement skips Lexical's DOM-selection sync,
44498    // which would otherwise steal focus from elsewhere on the page.
44499    #mountRoot() {
44500      this.editor.setEditable(false);
44501      this.editor.setRootElement(this.editorContentElement);
44502      this.editor.setEditable(true);
44503    }
44504    get #lexicalNodes() {
44505      const nodes = [CustomActionTextAttachmentNode];
44506      if (this.supportsRichText) {
44507        nodes.push(
44508          QuoteNode2,
44509          HeadingNode2,
44510          ListNode2,
44511          ListItemNode2,
44512          CodeNode3,
44513          CodeHighlightNode3,
44514          LinkNode2,
44515          AutoLinkNode2,
44516          HorizontalDividerNode
44517        );
44518      }
44519      return nodes;
44520    }
44521    #createEditorContentElement() {
44522      const editorContentElement = createElement("div", {
44523        id: `${this.id}-content`,
44524        classList: "lexxy-editor__content",
44525        contenteditable: true,
44526        role: "textbox",
44527        "aria-multiline": true,
44528        "aria-label": this.#labelText,
44529        placeholder: this.getAttribute("placeholder")
44530      });
44531      this.#ariaAttributes.forEach((attribute) => editorContentElement.setAttribute(attribute.name, attribute.value));
44532      this.#transferAttributeToContentEditable(editorContentElement, "autocapitalize");
44533      this.#transferAttributeToContentEditable(editorContentElement, "tabindex", { defaultValue: 0, removeSource: true });
44534      return editorContentElement;
44535    }
44536    #transferAttributeToContentEditable(element, qualifiedName, { defaultValue = null, removeSource = false } = {}) {
44537      if (this.hasAttribute(qualifiedName)) {
44538        element.setAttribute(qualifiedName, this.getAttribute(qualifiedName));
44539      } else if (defaultValue !== null) {
44540        element.setAttribute(qualifiedName, defaultValue);
44541      } else {
44542        element.removeAttribute(qualifiedName);
44543      }
44544      if (removeSource) this.removeAttribute(qualifiedName);
44545    }
44546    get #labelText() {
44547      return Array.from(this.internals.labels).map((label) => label.textContent).join(" ");
44548    }
44549    get #ariaAttributes() {
44550      return Array.from(this.attributes).filter((attribute) => attribute.name.startsWith("aria-"));
44551    }
44552    #setInternalFormValue(html2, { suppressEvent = false } = {}) {
44553      const changed = html2 !== this.#previousInternalFormValue;
44554      this.internals.setFormValue(html2);
44555      this.#previousInternalFormValue = html2;
44556      if (changed && !suppressEvent) {
44557        dispatch(this, "lexxy:change");
44558      }
44559    }
44560    #loadInitialValue(editor) {
44561      const initialHtml = this.valueBeforeDisconnect || this.getAttribute("value") || "<p><br></p>";
44562      this.#initialValue = initialHtml;
44563      this.#setEditorHtml(initialHtml, { editor });
44564    }
44565    #setEditorHtml(html2, { editor = this.editor } = {}) {
44566      $getRoot2().clear().selectEnd().insertNodes(this.#parseHtmlIntoLexicalNodes(html2, { editor }));
44567    }
44568    #resetBeforeTurboCaches() {
44569      this.#listeners.track(
44570        registerEventListener(document, "turbo:before-cache", this.#handleTurboBeforeCache)
44571      );
44572    }
44573    #handleTurboBeforeCache = (event) => {
44574      if (!this.closest("[data-turbo-permanent]")) {
44575        this.#reset();
44576      }
44577    };
44578    #synchronizeWithChanges() {
44579      this.#listeners.track(this.editor.registerUpdateListener(({ editorState }) => {
44580        this.#clearCachedValues();
44581        this.#setInternalFormValue(this.value);
44582        this.#toggleEmptyStatus();
44583        this.#requestValidityRefresh();
44584        this.#dispatchAttributesChange();
44585      }));
44586    }
44587    async #requestValidityRefresh() {
44588      await nextFrame();
44589      if (this.isConnected) this.#refreshValidity();
44590    }
44591    #refreshValidity() {
44592      this.#refreshInternalValidity();
44593      const { validity, message } = this.#calculateValidity();
44594      this.internals.setValidity(validity, message, this.editorContentElement);
44595    }
44596    #refreshInternalValidity() {
44597      this.#validationTextArea.required = this.required && this.isBlank;
44598      const flags = this.#validationTextArea.validity;
44599      const message = this.#validationTextArea.validationMessage;
44600      this.#validity.set(this, { flags, message });
44601    }
44602    #calculateValidity() {
44603      const validity = {};
44604      const messages = [];
44605      for (const { flags, message } of this.#validity.values()) {
44606        if (flags.valid === true) continue;
44607        for (const flag in flags) {
44608          if (flags[flag]) {
44609            validity[flag] = true;
44610            messages.push(message);
44611          }
44612        }
44613      }
44614      return { validity, message: messages.join("\n") };
44615    }
44616    #clearCachedValues() {
44617      this.cachedValue = null;
44618      this.cachedStringValue = null;
44619    }
44620    #registerComponents() {
44621      const registered = [];
44622      if (this.supportsRichText) {
44623        registered.push(
44624          registerRichText2(this.editor),
44625          registerList2(this.editor)
44626        );
44627        this.#registerTableComponents();
44628        this.#registerCodeLanguagePicker();
44629        if (this.supportsMarkdown) {
44630          const transformers = [...TRANSFORMERS2.filter((transformer) => transformer !== QUOTE2), DOUBLE_QUOTE, HORIZONTAL_DIVIDER];
44631          registered.push(
44632            registerMarkdownShortcuts2(this.editor, transformers),
44633            registerMarkdownLeadingTagHandler(this.editor, transformers)
44634          );
44635        }
44636      } else {
44637        registered.push(registerPlainText2(this.editor));
44638      }
44639      this.#listeners.track(...registered);
44640    }
44641    #registerTableComponents() {
44642      let tableTools = this.querySelector("lexxy-table-tools");
44643      tableTools ??= createElement("lexxy-table-tools");
44644      this.append(tableTools);
44645      this.#disposables.push(tableTools);
44646    }
44647    #registerCodeLanguagePicker() {
44648      let codeLanguagePicker = this.querySelector("lexxy-code-language-picker");
44649      codeLanguagePicker ??= createElement("lexxy-code-language-picker");
44650      this.append(codeLanguagePicker);
44651      this.#disposables.push(codeLanguagePicker);
44652    }
44653    #handleEnter() {
44654      this.#listeners.track(this.editor.registerCommand(
44655        KEY_ENTER_COMMAND2,
44656        (event) => {
44657          if (event.ctrlKey || event.metaKey) {
44658            event.preventDefault();
44659            return true;
44660          }
44661          if (!this.supportsMultiLine) {
44662            event.preventDefault();
44663            return true;
44664          }
44665          return false;
44666        },
44667        COMMAND_PRIORITY_NORMAL2
44668      ));
44669    }
44670    #registerFocusEvents() {
44671      this.#listeners.track(
44672        registerEventListener(this, "focusin", this.#handleFocusIn),
44673        registerEventListener(this, "focusout", this.#handleFocusOut)
44674      );
44675    }
44676    #handleFocusIn(event) {
44677      if (this.#elementInEditorOrToolbar(event.target) && !this.currentlyFocused) {
44678        this.#dispatchAttributesChange();
44679        dispatch(this, "lexxy:focus");
44680        this.currentlyFocused = true;
44681      }
44682    }
44683    #handleFocusOut(event) {
44684      if (!this.#elementInEditorOrToolbar(event.relatedTarget)) {
44685        dispatch(this, "lexxy:blur");
44686        this.currentlyFocused = false;
44687      }
44688    }
44689    #elementInEditorOrToolbar(element) {
44690      return this.contains(element) || this.toolbarElement?.contains(element);
44691    }
44692    #onFocus() {
44693      if (this.isEmpty) {
44694        this.selection.placeCursorAtTheEnd();
44695      }
44696    }
44697    #handleAutofocus() {
44698      if (!document.querySelector(":focus")) {
44699        if (this.hasAttribute("autofocus") && document.querySelector("[autofocus]") === this) {
44700          this.focus();
44701        }
44702      }
44703    }
44704    #registerHistoryEvents() {
44705      this.#listeners.track(
44706        this.editor.registerCommand(CAN_UNDO_COMMAND2, (enabled) => {
44707          this.#historyState.undo = enabled;
44708        }, COMMAND_PRIORITY_NORMAL2),
44709        this.editor.registerCommand(CAN_REDO_COMMAND2, (enabled) => {
44710          this.#historyState.redo = enabled;
44711        }, COMMAND_PRIORITY_NORMAL2)
44712      );
44713    }
44714    #attachDebugHooks() {
44715      return;
44716    }
44717    #attachToolbar() {
44718      if (this.#hasToolbar) {
44719        this.toolbarElement.setEditor(this);
44720        if (typeof this.toolbarElement.dispose === "function") {
44721          this.#disposables.push(this.toolbarElement);
44722        }
44723        this.extensions.initializeToolbars();
44724      }
44725    }
44726    #findOrCreateDefaultToolbar() {
44727      const toolbarConfig = this.config.get("toolbar");
44728      if (typeof toolbarConfig === "string") {
44729        return document.getElementById(toolbarConfig);
44730      } else {
44731        return this.querySelector("lexxy-toolbar") ?? this.#createDefaultToolbar();
44732      }
44733    }
44734    get #hasToolbar() {
44735      return this.supportsRichText && !!this.config.get("toolbar");
44736    }
44737    #createDefaultToolbar() {
44738      const toolbar = createElement("lexxy-toolbar");
44739      toolbar.innerHTML = LexicalToolbarElement.defaultTemplate;
44740      toolbar.setAttribute("data-attachments", this.supportsAttachments);
44741      toolbar.configure(this.config.get("toolbar"));
44742      this.prepend(toolbar);
44743      return toolbar;
44744    }
44745    #toggleEmptyStatus() {
44746      this.classList.toggle("lexxy-editor--empty", this.isEmpty);
44747    }
44748    #configureSanitizer(editor) {
44749      setSanitizerConfig(this.#getAllowedElements(editor));
44750    }
44751    #getAllowedElements(editor) {
44752      return this.#getImportableTags(editor).concat(this.extensions.allowedElements);
44753    }
44754    #getImportableTags(editor) {
44755      const tags = Array.from(editor._htmlConversions.keys());
44756      return tags.filter((tag) => !tag.startsWith("#"));
44757    }
44758    #dispatchAttributesChange() {
44759      let attributes = null;
44760      let linkHref = null;
44761      let highlight = null;
44762      let headingTag = null;
44763      this.editor.getEditorState().read(() => {
44764        const selection = $getSelection2();
44765        if (!$isRangeSelection2(selection)) return;
44766        const format = this.selection.getFormat();
44767        if (Object.keys(format).length === 0) return;
44768        const anchorNode = selection.anchor.getNode();
44769        const linkNode = $getNearestNodeOfType2(anchorNode, LinkNode2);
44770        attributes = {
44771          bold: { active: format.isBold, enabled: true },
44772          italic: { active: format.isItalic, enabled: true },
44773          strikethrough: { active: format.isStrikethrough, enabled: true },
44774          code: { active: format.isInCode, enabled: true },
44775          highlight: { active: format.isHighlight, enabled: true },
44776          link: { active: format.isInLink, enabled: true },
44777          quote: { active: format.isInQuote, enabled: true },
44778          heading: { active: format.isInHeading, enabled: true },
44779          "unordered-list": { active: format.isInList && format.listType === "bullet", enabled: true },
44780          "ordered-list": { active: format.isInList && format.listType === "number", enabled: true },
44781          undo: { active: false, enabled: this.canUndo },
44782          redo: { active: false, enabled: this.canRedo }
44783        };
44784        linkHref = linkNode ? linkNode.getURL() : null;
44785        highlight = format.isHighlight ? getHighlightStyles(selection) : null;
44786        headingTag = format.headingTag ?? null;
44787      });
44788      if (attributes) {
44789        this.adapter.dispatchAttributesChange(attributes, linkHref, highlight, headingTag);
44790      }
44791    }
44792    #dispatchEditorInitialized() {
44793      if (!this.adapter) return;
44794      this.#editorInitializedDispatched = true;
44795      this.adapter.dispatchEditorInitialized({
44796        highlightColors: this.#resolvedHighlightColors,
44797        headingFormats: this.#supportedHeadingFormats
44798      });
44799    }
44800    #dispatchInitialize() {
44801      if (this.isConnected && this.adapter) {
44802        if (!this.#initializeEventDispatched) {
44803          this.#initializeEventDispatched = true;
44804          dispatch(this, "lexxy:initialize");
44805        }
44806        if (!this.#editorInitializedDispatched) {
44807          this.#dispatchEditorInitialized();
44808        }
44809      }
44810    }
44811    get #resolvedHighlightColors() {
44812      const buttons = this.config.get("highlight.buttons");
44813      if (!buttons) return null;
44814      const colors = this.#resolveColors("color", buttons.color || []);
44815      const backgroundColors = this.#resolveColors("background-color", buttons["background-color"] || []);
44816      return { colors, backgroundColors };
44817    }
44818    get #supportedHeadingFormats() {
44819      if (!this.supportsRichText) return [];
44820      const headings = this.config.get("headings");
44821      return [
44822        { label: "Normal", command: "setFormatParagraph", tag: null },
44823        ...headings.map((tag, index) => ({
44824          label: HeadingDropdown.labelFor(tag, index),
44825          command: HeadingDropdown.commandFor(index),
44826          tag
44827        }))
44828      ];
44829    }
44830    // Builds one resolver element per CSS value inside a hidden container, attaches
44831    // the container in a single DOM write, then reads all computed values in one pass
44832    // — triggering at most one forced reflow. The previous implementation interleaved
44833    // setProperty/getComputedStyle/removeProperty on the same element, forcing a style
44834    // recalc on every iteration during editor initialization.
44835    #resolveColors(property, cssValues) {
44836      const container = document.createElement("span");
44837      container.style.display = "none";
44838      const resolvers = cssValues.map((cssValue) => {
44839        const element = document.createElement("span");
44840        element.style.setProperty(property, cssValue);
44841        container.appendChild(element);
44842        return { element, name: cssValue };
44843      });
44844      styleResolverRoot().appendChild(container);
44845      const resolved = resolvers.map(({ element, name }) => ({
44846        name,
44847        value: window.getComputedStyle(element).getPropertyValue(property)
44848      }));
44849      container.remove();
44850      return resolved;
44851    }
44852    #reset() {
44853      this.#dispose();
44854      this.#resetValidity();
44855      this.#uploadRequests?.clear();
44856      this.editorContentElement?.remove();
44857      this.editorContentElement = null;
44858      this.toolbar = null;
44859    }
44860    #dispose() {
44861      while (this.#disposables.length) {
44862        this.#disposables.pop().dispose();
44863      }
44864    }
44865    #reconnect() {
44866      this.disconnectedCallback();
44867      this.valueBeforeDisconnect = null;
44868      this.connectedCallback();
44869    }
44870    #resetValidity() {
44871      this.#validity = /* @__PURE__ */ new Map();
44872    }
44873  };
44874  function $getReadableTextContent(node) {
44875    if (node instanceof CustomActionTextAttachmentNode) {
44876      return node.getReadableTextContent();
44877    }
44878    if ($isElementNode2(node)) {
44879      let text2 = "";
44880      const children = node.getChildren();
44881      for (let i2 = 0; i2 < children.length; i2++) {
44882        const child = children[i2];
44883        const previousChild = children[i2 - 1];
44884        if (isAttachmentSpacerTextNode(child, previousChild, i2, children.length)) continue;
44885        text2 += $getReadableTextContent(child);
44886        if ($isElementNode2(child) && i2 !== children.length - 1 && !child.isInline()) {
44887          text2 += "\n\n";
44888        }
44889      }
44890      return text2;
44891    }
44892    return node.getTextContent();
44893  }
44894  var BaseSource = class {
44895    // Template method to override
44896    async buildListItems(filter = "") {
44897      return Promise.resolve([]);
44898    }
44899    // Template method to override
44900    promptItemFor(listItem) {
44901      return null;
44902    }
44903    // Protected
44904    buildListItemElementFor(promptItemElement) {
44905      const template = promptItemElement.querySelector("template[type='menu']");
44906      const fragment = template.content.cloneNode(true);
44907      const listItemElement = createElement("li", { role: "option", id: generateDomId("prompt-item"), tabindex: "0" });
44908      listItemElement.classList.add("lexxy-prompt-menu__item");
44909      listItemElement.appendChild(fragment);
44910      return listItemElement;
44911    }
44912    async loadPromptItemsFromUrl(url) {
44913      try {
44914        const response = await fetch(url);
44915        const html2 = await response.text();
44916        const promptItems = parseHtml(html2).querySelectorAll("lexxy-prompt-item");
44917        return Promise.resolve(Array.from(promptItems));
44918      } catch (error) {
44919        return Promise.reject(error);
44920      }
44921    }
44922  };
44923  var MAX_RENDERED_SUGGESTIONS$1 = 100;
44924  var LocalFilterSource = class extends BaseSource {
44925    async buildListItems(filter = "") {
44926      const promptItems = await this.fetchPromptItems();
44927      return this.#buildListItemsFromPromptItems(promptItems, filter);
44928    }
44929    // Template method to override
44930    async fetchPromptItems(filter) {
44931      return Promise.resolve([]);
44932    }
44933    promptItemFor(listItem) {
44934      return this.promptItemByListItem.get(listItem);
44935    }
44936    #buildListItemsFromPromptItems(promptItems, filter) {
44937      this.promptItemByListItem = /* @__PURE__ */ new WeakMap();
44938      if (!filter) {
44939        return this.#buildAllListItems(promptItems);
44940      }
44941      const matches = [];
44942      for (const promptItem of promptItems) {
44943        const searchableText = promptItem.getAttribute("search");
44944        const position = filterMatchPosition(searchableText, filter);
44945        if (position >= 0) {
44946          matches.push({ promptItem, position });
44947        }
44948      }
44949      matches.sort((a2, b3) => a2.position - b3.position);
44950      const listItems = [];
44951      for (const { promptItem } of matches) {
44952        if (listItems.length >= MAX_RENDERED_SUGGESTIONS$1) break;
44953        const listItem = this.buildListItemElementFor(promptItem);
44954        this.promptItemByListItem.set(listItem, promptItem);
44955        listItems.push(listItem);
44956      }
44957      return listItems;
44958    }
44959    #buildAllListItems(promptItems) {
44960      const listItems = [];
44961      for (const promptItem of promptItems) {
44962        if (listItems.length >= MAX_RENDERED_SUGGESTIONS$1) break;
44963        const listItem = this.buildListItemElementFor(promptItem);
44964        this.promptItemByListItem.set(listItem, promptItem);
44965        listItems.push(listItem);
44966      }
44967      return listItems;
44968    }
44969  };
44970  var InlinePromptSource = class extends LocalFilterSource {
44971    constructor(inlinePromptItems) {
44972      super();
44973      this.inlinePromptItemElements = Array.from(inlinePromptItems);
44974    }
44975    async fetchPromptItems() {
44976      return Promise.resolve(this.inlinePromptItemElements);
44977    }
44978  };
44979  var DeferredPromptSource = class extends LocalFilterSource {
44980    constructor(url) {
44981      super();
44982      this.url = url;
44983      this.fetchPromptItems();
44984    }
44985    async fetchPromptItems() {
44986      this.promptItems ??= await this.loadPromptItemsFromUrl(this.url);
44987      return Promise.resolve(this.promptItems);
44988    }
44989  };
44990  var DEBOUNCE_INTERVAL = 200;
44991  var MAX_RENDERED_SUGGESTIONS = 100;
44992  var RemoteFilterSource = class extends BaseSource {
44993    constructor(url) {
44994      super();
44995      this.baseURL = url;
44996      this.loadAndFilterListItems = debounceAsync(this.fetchFilteredListItems.bind(this), DEBOUNCE_INTERVAL);
44997    }
44998    async buildListItems(filter = "") {
44999      return await this.loadAndFilterListItems(filter);
45000    }
45001    promptItemFor(listItem) {
45002      return this.promptItemByListItem.get(listItem);
45003    }
45004    async fetchFilteredListItems(filter) {
45005      const promptItems = await this.loadPromptItemsFromUrl(this.#urlFor(filter));
45006      return this.#buildListItemsFromPromptItems(promptItems);
45007    }
45008    #urlFor(filter) {
45009      const url = new URL(this.baseURL, window.location.origin);
45010      url.searchParams.append("filter", filter);
45011      return url.toString();
45012    }
45013    #buildListItemsFromPromptItems(promptItems) {
45014      const listItems = [];
45015      this.promptItemByListItem = /* @__PURE__ */ new WeakMap();
45016      for (const promptItem of promptItems) {
45017        if (listItems.length >= MAX_RENDERED_SUGGESTIONS) break;
45018        const listItem = this.buildListItemElementFor(promptItem);
45019        this.promptItemByListItem.set(listItem, promptItem);
45020        listItems.push(listItem);
45021      }
45022      return listItems;
45023    }
45024  };
45025  var NOTHING_FOUND_DEFAULT_MESSAGE = "Nothing found";
45026  var FILTER_DEBOUNCE_INTERVAL = 50;
45027  var DEFAULT_ONLY_AT_PATTERN = "^|[ \\n]";
45028  var LexicalPromptElement = class extends HTMLElement {
45029    #globalListeners = new ListenerBin();
45030    #popoverListeners = new ListenerBin();
45031    #debouncedFilterOptions = debounce(() => this.#filterOptions(), FILTER_DEBOUNCE_INTERVAL);
45032    constructor() {
45033      super();
45034      this.showPopoverId = 0;
45035    }
45036    static observedAttributes = ["connected"];
45037    connectedCallback() {
45038      this.source = this.#createSource();
45039      this.#addTriggerListener();
45040      this.#removePopoverBeforeTurboCaches();
45041      this.toggleAttribute("connected", true);
45042    }
45043    disconnectedCallback() {
45044      this.#popoverListeners.dispose();
45045      this.#globalListeners.dispose();
45046      this.source = null;
45047      this.#removePopover();
45048    }
45049    attributeChangedCallback(name, oldValue, newValue) {
45050      if (name === "connected" && this.isConnected && oldValue != null && oldValue !== newValue) {
45051        requestAnimationFrame(() => this.#reconnect());
45052      }
45053    }
45054    get name() {
45055      return this.getAttribute("name");
45056    }
45057    get trigger() {
45058      return this.getAttribute("trigger");
45059    }
45060    get supportsSpaceInSearches() {
45061      return this.hasAttribute("supports-space-in-searches");
45062    }
45063    get onlyAt() {
45064      return this.getAttribute("only-at");
45065    }
45066    get verticalDirection() {
45067      return this.getAttribute("vertical-direction");
45068    }
45069    get open() {
45070      return this.popoverElement?.classList?.contains("lexxy-prompt-menu--visible");
45071    }
45072    get closed() {
45073      return !this.open;
45074    }
45075    get #doesSpaceSelect() {
45076      return !this.supportsSpaceInSearches;
45077    }
45078    #createSource() {
45079      const src = this.getAttribute("src");
45080      if (src) {
45081        if (this.hasAttribute("remote-filtering")) {
45082          return new RemoteFilterSource(src);
45083        } else {
45084          return new DeferredPromptSource(src);
45085        }
45086      } else {
45087        return new InlinePromptSource(this.querySelectorAll("lexxy-prompt-item"));
45088      }
45089    }
45090    #addTriggerListener() {
45091      if (!this.#promptContentTypePermitted) return;
45092      this.#popoverListeners.track(this.#editor.registerUpdateListener(({ editorState }) => {
45093        editorState.read(() => {
45094          if (this.#selection.isInsideCodeBlock) return;
45095          const { node, offset: offset3 } = this.#selection.selectedNodeWithOffset();
45096          if (!node) return;
45097          if ($isTextNode2(node)) {
45098            const fullText = node.getTextContent();
45099            const triggerLength = this.trigger.length;
45100            if (offset3 >= triggerLength) {
45101              const textBeforeCursor = fullText.slice(offset3 - triggerLength, offset3);
45102              if (textBeforeCursor === this.trigger) {
45103                const textBeforeTrigger = $textBeforeOffset(node, offset3 - triggerLength);
45104                if (this.#onlyAtRegExp.test(textBeforeTrigger)) {
45105                  this.#popoverListeners.dispose();
45106                  this.#showPopover();
45107                }
45108              }
45109            }
45110          }
45111        });
45112      }));
45113    }
45114    get #onlyAtRegExp() {
45115      return new RegExp(`(?:${this.onlyAt ?? DEFAULT_ONLY_AT_PATTERN})$`);
45116    }
45117    get #promptContentTypePermitted() {
45118      if (this.hasAttribute("insert-editable-text")) return true;
45119      const el = this.#editorElement;
45120      if (!el.supportsAttachments) {
45121        return false;
45122      } else {
45123        const templates = Array.from(this.querySelectorAll("template[type='editor']"));
45124        const types = templates.length ? templates.map((t2) => t2.getAttribute("content-type") || this.#defaultPromptContentType) : [this.#defaultPromptContentType];
45125        return types.some((t2) => el.permitsAttachmentContentType(t2));
45126      }
45127    }
45128    #addCursorPositionListener() {
45129      this.#popoverListeners.track(this.#editor.registerUpdateListener(({ editorState }) => {
45130        if (this.closed) return;
45131        editorState.read(() => {
45132          if (this.#selection.isInsideCodeBlock) {
45133            this.#hidePopover();
45134            return;
45135          }
45136          const { node, offset: offset3 } = this.#selection.selectedNodeWithOffset();
45137          if (!node) return;
45138          if (this.#cursorIsTypingSearchTerm(node, offset3)) {
45139            if (!this.popoverElement.hasAttribute("data-anchored")) {
45140              this.#positionPopover();
45141            }
45142          } else {
45143            this.#hidePopover();
45144          }
45145        });
45146      }));
45147    }
45148    // The popover should stay open only while the cursor sits at the end of the
45149    // trigger and its search term. When the cursor moves away — before the
45150    // trigger, or past the token into later text — the text between the trigger
45151    // and the cursor breaks that run and we dismiss. A newline always breaks the
45152    // run; a space breaks it only for triggers that don't support spaces in
45153    // searches, since those that do (e.g. `person:`) expect multi-word terms.
45154    #cursorIsTypingSearchTerm(node, offset3) {
45155      if (!$isTextNode2(node) || offset3 === 0) return false;
45156      const textBeforeCursor = node.getTextContent().slice(0, offset3);
45157      const lastTriggerIndex = textBeforeCursor.lastIndexOf(this.trigger);
45158      if (lastTriggerIndex === -1) return false;
45159      const searchTerm = textBeforeCursor.slice(lastTriggerIndex + this.trigger.length);
45160      const breakPattern = this.supportsSpaceInSearches ? /\n/ : /[ \n]/;
45161      return !breakPattern.test(searchTerm);
45162    }
45163    get #editor() {
45164      return this.#editorElement.editor;
45165    }
45166    get #editorElement() {
45167      return this.closest("lexxy-editor");
45168    }
45169    get #selection() {
45170      return this.#editorElement.selection;
45171    }
45172    async #showPopover() {
45173      const showId = ++this.showPopoverId;
45174      this.popoverElement ??= await this.#buildPopover();
45175      if (this.showPopoverId !== showId) return;
45176      this.#resetPopoverPosition();
45177      await this.#filterOptions();
45178      if (this.showPopoverId !== showId) return;
45179      this.popoverElement.classList.toggle("lexxy-prompt-menu--visible", true);
45180      this.#selectFirstOption();
45181      this.#popoverListeners.track(
45182        registerEventListener(this.#editorElement, "keydown", this.#handleKeydownOnPopover),
45183        registerEventListener(this.#editorElement, "lexxy:change", this.#debouncedFilterOptions)
45184      );
45185      this.#registerKeyListeners();
45186      this.#addCursorPositionListener();
45187    }
45188    #registerKeyListeners() {
45189      this.#popoverListeners.track(
45190        this.#editor.registerCommand(KEY_ENTER_COMMAND2, this.#handleSelectedOption.bind(this), COMMAND_PRIORITY_CRITICAL2),
45191        this.#editor.registerCommand(KEY_TAB_COMMAND2, this.#handleSelectedOption.bind(this), COMMAND_PRIORITY_CRITICAL2)
45192      );
45193      if (this.#doesSpaceSelect) {
45194        this.#popoverListeners.track(this.#editor.registerCommand(KEY_SPACE_COMMAND2, this.#handleSelectedOption.bind(this), COMMAND_PRIORITY_CRITICAL2));
45195        this.#popoverListeners.track(this.#editor.registerCommand(INPUT_COMMAND2, this.#handleInputCommand.bind(this), COMMAND_PRIORITY_CRITICAL2));
45196      }
45197      this.#popoverListeners.track(
45198        this.#editor.registerCommand(KEY_ARROW_UP_COMMAND2, this.#handleArrowUp.bind(this), COMMAND_PRIORITY_CRITICAL2),
45199        this.#editor.registerCommand(KEY_ARROW_DOWN_COMMAND2, this.#handleArrowDown.bind(this), COMMAND_PRIORITY_CRITICAL2)
45200      );
45201    }
45202    #handleArrowUp(event) {
45203      this.#moveSelectionUp();
45204      event.preventDefault();
45205      return true;
45206    }
45207    #handleArrowDown(event) {
45208      this.#moveSelectionDown();
45209      event.preventDefault();
45210      return true;
45211    }
45212    #selectFirstOption() {
45213      const firstOption = this.#listItemElements[0];
45214      if (firstOption) {
45215        this.#selectOption(firstOption);
45216      }
45217    }
45218    get #listItemElements() {
45219      return Array.from(this.popoverElement.querySelectorAll(".lexxy-prompt-menu__item"));
45220    }
45221    #selectOption(listItem, { scrollIntoView = false } = {}) {
45222      this.#clearListItemSelection();
45223      listItem.toggleAttribute("aria-selected", true);
45224      if (scrollIntoView) {
45225        listItem.scrollIntoView({ block: "nearest", container: "nearest", behavior: "smooth" });
45226      }
45227      this.#setEditorAssociationAttribute("aria-controls", this.popoverElement.id);
45228      this.#setEditorAssociationAttribute("aria-activedescendant", listItem.id);
45229      this.#setEditorAssociationAttribute("aria-haspopup", "listbox");
45230    }
45231    #clearListItemSelection() {
45232      this.#listItemElements.forEach((item) => {
45233        item.toggleAttribute("aria-selected", false);
45234      });
45235    }
45236    #clearSelection() {
45237      this.#clearListItemSelection();
45238      this.#editorContentElement.removeAttribute("aria-controls");
45239      this.#editorContentElement.removeAttribute("aria-activedescendant");
45240      this.#editorContentElement.removeAttribute("aria-haspopup");
45241    }
45242    #setEditorAssociationAttribute(name, value) {
45243      if (this.#editorContentElement.getAttribute(name) !== value) {
45244        this.#editorContentElement.setAttribute(name, value);
45245      }
45246    }
45247    // Right after a Turbo history restore the editor reconnects before the DOM selection
45248    // is re-established, so the cursor geometry is momentarily unavailable. Anchoring then
45249    // would pin the menu to the editor's left edge for the rest of the open cycle, so we
45250    // skip it and let a later reposition anchor it once the selection is ready. The menu
45251    // stays hidden until anchored (see the `[data-anchored]` rule in the stylesheet).
45252    #positionPopover() {
45253      const cursorPosition = this.#selection.cursorPosition;
45254      if (!cursorPosition) return;
45255      const { x: x3, y: y3, fontSize } = cursorPosition;
45256      const editorRect = this.#editorElement.getBoundingClientRect();
45257      const contentRect = this.#editorContentElement.getBoundingClientRect();
45258      const verticalOffset = contentRect.top - editorRect.top;
45259      if (!this.popoverElement.hasAttribute("data-anchored")) {
45260        this.#setPopoverOffsetX(x3);
45261        this.#setPopoverOffsetY(y3 + verticalOffset);
45262        this.popoverElement.toggleAttribute("data-anchored", true);
45263      }
45264      const popoverRect = this.popoverElement.getBoundingClientRect();
45265      if (popoverRect.right > editorRect.right) {
45266        this.popoverElement.toggleAttribute("data-clipped-at-right", true);
45267      }
45268      const forceTop = this.verticalDirection === "top";
45269      const forceBottom = this.verticalDirection === "bottom";
45270      const overflowsWindow = popoverRect.bottom > window.innerHeight;
45271      if (!forceBottom && (forceTop || overflowsWindow)) {
45272        this.#setPopoverOffsetY(contentRect.height - y3 + fontSize);
45273        this.popoverElement.toggleAttribute("data-clipped-at-bottom", true);
45274      }
45275    }
45276    #setPopoverOffsetX(value) {
45277      this.popoverElement.style.setProperty("--lexxy-prompt-offset-x", `${value}px`);
45278    }
45279    #setPopoverOffsetY(value) {
45280      this.popoverElement.style.setProperty("--lexxy-prompt-offset-y", `${value}px`);
45281    }
45282    #resetPopoverPosition() {
45283      this.popoverElement.removeAttribute("data-clipped-at-bottom");
45284      this.popoverElement.removeAttribute("data-clipped-at-right");
45285      this.popoverElement.removeAttribute("data-anchored");
45286    }
45287    async #hidePopover() {
45288      this.showPopoverId++;
45289      this.#clearSelection();
45290      this.popoverElement.classList.toggle("lexxy-prompt-menu--visible", false);
45291      this.#popoverListeners.dispose();
45292      await nextFrame();
45293      this.#addTriggerListener();
45294    }
45295    // The popover is appended to the <lexxy-editor> subtree, so Turbo serializes it
45296    // into the page cache. Removing it before caching prevents an orphaned, unmanaged
45297    // popover from being restored on history back/forward.
45298    #removePopoverBeforeTurboCaches() {
45299      this.#globalListeners.track(
45300        registerEventListener(document, "turbo:before-cache", () => this.#removePopover())
45301      );
45302    }
45303    #removePopover() {
45304      this.#popoverListeners.dispose();
45305      this.popoverElement?.remove();
45306      this.popoverElement = null;
45307    }
45308    #filterOptions = async () => {
45309      if (this.initialPrompt) {
45310        this.initialPrompt = false;
45311        return;
45312      }
45313      if (this.#editorContents.containsTextBackUntil(this.trigger)) {
45314        await this.#showFilteredOptions();
45315        if (!this.#editorContents.containsTextBackUntil(this.trigger)) {
45316          this.#hidePopover();
45317          return;
45318        }
45319        await nextFrame();
45320        this.#positionPopover();
45321      } else {
45322        this.#hidePopover();
45323      }
45324    };
45325    async #showFilteredOptions() {
45326      const showId = this.showPopoverId;
45327      const filter = this.#editorContents.textBackUntil(this.trigger);
45328      const filteredListItems = await this.source.buildListItems(filter);
45329      if (this.showPopoverId !== showId) return;
45330      if (!this.#editorContents.containsTextBackUntil(this.trigger)) return;
45331      this.popoverElement.innerHTML = "";
45332      if (filteredListItems.length > 0) {
45333        this.#showResults(filteredListItems);
45334      } else {
45335        this.#showEmptyResults();
45336      }
45337      this.#selectFirstOption();
45338    }
45339    #showResults(filteredListItems) {
45340      this.popoverElement.classList.remove("lexxy-prompt-menu--empty");
45341      this.popoverElement.append(...filteredListItems);
45342    }
45343    #showEmptyResults() {
45344      this.popoverElement.classList.add("lexxy-prompt-menu--empty");
45345      const el = createElement("li", { textContent: this.#emptyResultsMessage });
45346      el.classList.add("lexxy-prompt-menu__item--empty");
45347      this.popoverElement.append(el);
45348    }
45349    get #emptyResultsMessage() {
45350      return this.getAttribute("empty-results") || NOTHING_FOUND_DEFAULT_MESSAGE;
45351    }
45352    #handleKeydownOnPopover = (event) => {
45353      if (event.key === "Escape") {
45354        this.#hidePopover();
45355        this.#editorElement.focus();
45356        event.stopPropagation();
45357      } else if (event.key === ",") {
45358        event.preventDefault();
45359        event.stopPropagation();
45360        this.#optionWasSelected();
45361        this.#editor.update(() => {
45362          const selection = $getSelection2();
45363          if ($isRangeSelection2(selection)) {
45364            selection.insertText(",");
45365          }
45366        });
45367      }
45368    };
45369    // Android Mobile keyboard doesn't trigger KEY_SPACE_COMMAND
45370    #handleInputCommand(event) {
45371      if (event.inputType === "insertText" && event.data === " ") return this.#handleSelectedOption(event);
45372    }
45373    #moveSelectionDown() {
45374      const nextIndex = this.#selectedIndex + 1;
45375      if (nextIndex < this.#listItemElements.length) this.#selectOption(this.#listItemElements[nextIndex], { scrollIntoView: true });
45376    }
45377    #moveSelectionUp() {
45378      const previousIndex = this.#selectedIndex - 1;
45379      if (previousIndex >= 0) this.#selectOption(this.#listItemElements[previousIndex], { scrollIntoView: true });
45380    }
45381    get #selectedIndex() {
45382      return this.#listItemElements.findIndex((item) => item.hasAttribute("aria-selected"));
45383    }
45384    get #selectedListItem() {
45385      return this.#listItemElements[this.#selectedIndex];
45386    }
45387    #handleSelectedOption(event) {
45388      event.preventDefault();
45389      event.stopPropagation();
45390      this.#optionWasSelected();
45391      return true;
45392    }
45393    #optionWasSelected() {
45394      this.#replaceTriggerWithSelectedItem();
45395      this.#hidePopover();
45396      this.#editorElement.focus();
45397    }
45398    #replaceTriggerWithSelectedItem() {
45399      const promptItem = this.source.promptItemFor(this.#selectedListItem);
45400      if (!promptItem) {
45401        return;
45402      }
45403      const templates = Array.from(promptItem.querySelectorAll("template[type='editor']"));
45404      const stringToReplace = `${this.trigger}${this.#editorContents.textBackUntil(this.trigger)}`;
45405      if (this.hasAttribute("insert-editable-text")) {
45406        this.#insertTemplatesAsEditableText(templates, stringToReplace);
45407      } else {
45408        this.#insertTemplatesAsAttachments(templates, stringToReplace, promptItem.getAttribute("sgid"));
45409      }
45410    }
45411    #insertTemplatesAsEditableText(templates, stringToReplace) {
45412      this.#editor.update(() => {
45413        const nodes = templates.flatMap((template) => this.#buildEditableTextNodes(template));
45414        this.#editorContents.replaceTextBackUntil(stringToReplace, nodes);
45415      });
45416    }
45417    #buildEditableTextNodes(template) {
45418      return this.#editorElement.$generateNodesFromDOM(parseHtml(`${template.innerHTML}`));
45419    }
45420    #insertTemplatesAsAttachments(templates, stringToReplace, fallbackSgid = null) {
45421      this.#editor.update(() => {
45422        const attachmentNodes = this.#buildAttachmentNodes(templates, fallbackSgid);
45423        const spacedAttachmentNodes = attachmentNodes.flatMap((node) => [node, this.#getSpacerTextNode()]).slice(0, -1);
45424        this.#editorContents.replaceTextBackUntil(stringToReplace, spacedAttachmentNodes);
45425      });
45426    }
45427    #buildAttachmentNodes(templates, fallbackSgid = null) {
45428      return templates.filter((template) => this.#editorElement.permitsAttachmentContentType(
45429        template.getAttribute("content-type") || this.#defaultPromptContentType
45430      )).map((template) => this.#buildAttachmentNode(
45431        template.innerHTML,
45432        template.getAttribute("content-type") || this.#defaultPromptContentType,
45433        template.getAttribute("sgid") || fallbackSgid
45434      ));
45435    }
45436    #getSpacerTextNode() {
45437      return $createTextNode2(" ");
45438    }
45439    get #defaultPromptContentType() {
45440      const attachmentContentTypeNamespace = Lexxy.global.get("attachmentContentTypeNamespace");
45441      return `application/vnd.${attachmentContentTypeNamespace}.${this.name}`;
45442    }
45443    #buildAttachmentNode(innerHtml, contentType, sgid) {
45444      return new CustomActionTextAttachmentNode({ sgid, contentType, innerHtml });
45445    }
45446    get #editorContents() {
45447      return this.#editorElement.contents;
45448    }
45449    get #editorContentElement() {
45450      return this.#editorElement.editorContentElement;
45451    }
45452    async #buildPopover() {
45453      const popoverContainer = createElement("ul", { role: "listbox", id: generateDomId("prompt-popover") });
45454      popoverContainer.classList.add("lexxy-prompt-menu");
45455      popoverContainer.style.position = "absolute";
45456      popoverContainer.setAttribute("nonce", getNonce());
45457      popoverContainer.append(...await this.source.buildListItems());
45458      this.#globalListeners.track(registerEventListener(popoverContainer, "click", this.#handlePopoverClick));
45459      this.#editorElement.appendChild(popoverContainer);
45460      return popoverContainer;
45461    }
45462    #handlePopoverClick = (event) => {
45463      const listItem = event.target.closest(".lexxy-prompt-menu__item");
45464      if (listItem) {
45465        this.#selectOption(listItem);
45466        this.#optionWasSelected();
45467      }
45468    };
45469    #reconnect() {
45470      this.disconnectedCallback();
45471      this.connectedCallback();
45472    }
45473  };
45474  var CodeLanguagePicker = class extends HTMLElement {
45475    #abortController = null;
45476    #listeners = new ListenerBin();
45477    connectedCallback() {
45478      this.editorElement = this.closest("lexxy-editor");
45479      this.editor = this.editorElement.editor;
45480      this.classList.add("lexxy-floating-controls");
45481      this.#abortController = new AbortController();
45482      this.#listeners.track(() => this.#abortController?.abort());
45483      this.#attachLanguagePicker();
45484      this.#hide();
45485      this.#monitorForCodeBlockSelection();
45486    }
45487    disconnectedCallback() {
45488      this.dispose();
45489    }
45490    dispose() {
45491      this.#listeners.dispose();
45492    }
45493    #attachLanguagePicker() {
45494      this.languagePickerElement = this.#findLanguagePicker() ?? this.#createLanguagePicker();
45495      const signal2 = this.#abortController.signal;
45496      this.#listeners.track(registerEventListener(this.languagePickerElement, "change", () => {
45497        this.#updateCodeBlockLanguage(this.languagePickerElement.value);
45498      }, { signal: signal2 }));
45499      this.#listeners.track(registerEventListener(this.languagePickerElement, "mousedown", (event) => {
45500        this.#dispatchOpenEvent(event);
45501      }, { signal: signal2 }));
45502      this.languagePickerElement.setAttribute("nonce", getNonce());
45503      this.appendChild(this.languagePickerElement);
45504    }
45505    #findLanguagePicker() {
45506      return this.querySelector("select");
45507    }
45508    #createLanguagePicker() {
45509      const selectElement = createElement("select", { className: "lexxy-code-language-picker", "aria-label": "Pick a language\u2026", name: "lexxy-code-language" });
45510      for (const [value, label] of Object.entries(this.#languages)) {
45511        const option = document.createElement("option");
45512        option.value = value;
45513        option.textContent = label;
45514        selectElement.appendChild(option);
45515      }
45516      return selectElement;
45517    }
45518    get #languages() {
45519      const languages = { ...CODE_LANGUAGE_FRIENDLY_NAME_MAP4 };
45520      languages.ruby ||= "Ruby";
45521      languages.php ||= "PHP";
45522      languages.go ||= "Go";
45523      languages.bash ||= "Bash";
45524      languages.json ||= "JSON";
45525      languages.diff ||= "Diff";
45526      languages.kotlin ||= "Kotlin";
45527      delete languages.plain;
45528      const sortedEntries = Object.entries(languages).sort((a2, b3) => a2[1].localeCompare(b3[1]));
45529      return { plain: "Plain text", ...Object.fromEntries(sortedEntries) };
45530    }
45531    #dispatchOpenEvent(event) {
45532      const handled = !dispatch(this.editorElement, "lexxy:code-language-picker-open", {
45533        languages: this.#bridgeLanguages,
45534        currentLanguage: this.languagePickerElement.value
45535      }, true);
45536      if (handled) {
45537        event.preventDefault();
45538      }
45539    }
45540    get #bridgeLanguages() {
45541      return Object.entries(this.#languages).map(([key, name]) => ({ key, name }));
45542    }
45543    #updateCodeBlockLanguage(language) {
45544      this.editor.update(() => {
45545        const codeNode = this.#getCurrentCodeNode();
45546        if (codeNode) {
45547          codeNode.setLanguage(language);
45548        }
45549      });
45550    }
45551    #monitorForCodeBlockSelection() {
45552      this.#listeners.track(this.editor.registerUpdateListener(({ editorState }) => {
45553        editorState.read(() => {
45554          const codeNode = this.#getCurrentCodeNode();
45555          if (codeNode) {
45556            this.#codeNodeWasSelected(codeNode);
45557          } else {
45558            this.#hide();
45559          }
45560        });
45561      }));
45562    }
45563    #getCurrentCodeNode() {
45564      return this.editorElement.selection.nearestNodeOfType(CodeNode3);
45565    }
45566    #codeNodeWasSelected(codeNode) {
45567      const language = codeNode.getLanguage();
45568      this.#updateLanguagePickerWith(language);
45569      this.#show();
45570      this.#positionLanguagePicker(codeNode);
45571    }
45572    #updateLanguagePickerWith(language) {
45573      if (this.languagePickerElement && language) {
45574        const normalizedLanguage = normalizeCodeLang2(language);
45575        this.languagePickerElement.value = normalizedLanguage;
45576      }
45577    }
45578    #positionLanguagePicker(codeNode) {
45579      const codeElement = this.editor.getElementByKey(codeNode.getKey());
45580      if (!codeElement) return;
45581      const codeRect = codeElement.getBoundingClientRect();
45582      const editorRect = this.editorElement.getBoundingClientRect();
45583      const relativeTop = codeRect.top - editorRect.top;
45584      const relativeRight = editorRect.right - codeRect.right;
45585      this.style.top = `${relativeTop}px`;
45586      this.style.right = `${relativeRight}px`;
45587    }
45588    #show() {
45589      this.hidden = false;
45590    }
45591    #hide() {
45592      this.hidden = true;
45593    }
45594  };
45595  var DELETE_ICON = `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
45596  <path d="M11.2041 1.01074C12.2128 1.113 13 1.96435 13 3V4H15L15.1025 4.00488C15.6067 4.05621 16 4.48232 16 5C16 5.55228 15.5523 6 15 6H14.8457L14.1416 15.1533C14.0614 16.1953 13.1925 17 12.1475 17H5.85254L5.6582 16.9902C4.76514 16.9041 4.03607 16.2296 3.88184 15.3457L3.8584 15.1533L3.1543 6H3C2.44772 6 2 5.55228 2 5C2 4.44772 2.44772 4 3 4H5V3C5 1.89543 5.89543 1 7 1H11L11.2041 1.01074ZM5.85254 15H12.1475L12.8398 6H5.16016L5.85254 15ZM7 4H11V3H7V4Z"/>
45597</svg>`;
45598  var NodeDeleteButton = class extends HTMLElement {
45599    connectedCallback() {
45600      this.editorElement = this.closest("lexxy-editor");
45601      this.editor = this.editorElement.editor;
45602      this.classList.add("lexxy-floating-controls");
45603      if (!this.querySelector(".lexxy-node-delete")) {
45604        this.#attachDeleteButton();
45605      }
45606    }
45607    disconnectedCallback() {
45608      this.editor = null;
45609      this.editorElement = null;
45610    }
45611    #attachDeleteButton() {
45612      const container = createElement("div", { className: "lexxy-floating-controls__group" });
45613      this.deleteButton = createElement("button", {
45614        className: "lexxy-node-delete",
45615        type: "button",
45616        "aria-label": "Remove"
45617      });
45618      this.deleteButton.tabIndex = -1;
45619      this.deleteButton.innerHTML = DELETE_ICON;
45620      this.handleDeleteClick = () => this.#deleteNode();
45621      this.deleteButton.addEventListener("click", this.handleDeleteClick);
45622      container.appendChild(this.deleteButton);
45623      this.appendChild(container);
45624    }
45625    #deleteNode() {
45626      this.editor.update(() => {
45627        const node = $getNearestNodeFromDOMNode2(this);
45628        node?.remove();
45629      });
45630    }
45631  };
45632  var TableController = class {
45633    #listeners = new ListenerBin();
45634    constructor(editorElement) {
45635      this.editor = editorElement.editor;
45636      this.contents = editorElement.contents;
45637      this.selection = editorElement.selection;
45638      this.currentTableNodeKey = null;
45639      this.currentCellKey = null;
45640      this.#registerKeyHandlers();
45641    }
45642    destroy() {
45643      this.currentTableNodeKey = null;
45644      this.currentCellKey = null;
45645      this.#listeners.dispose();
45646    }
45647    get currentCell() {
45648      if (!this.currentCellKey) return null;
45649      return this.editor.getEditorState().read(() => {
45650        const cell = $getNodeByKey2(this.currentCellKey);
45651        return cell instanceof TableCellNode2 ? cell : null;
45652      });
45653    }
45654    get currentTableNode() {
45655      if (!this.currentTableNodeKey) return null;
45656      return this.editor.getEditorState().read(() => {
45657        const tableNode = $getNodeByKey2(this.currentTableNodeKey);
45658        return tableNode instanceof TableNode2 ? tableNode : null;
45659      });
45660    }
45661    get currentRowCells() {
45662      const currentRowIndex = this.currentRowIndex;
45663      const rows = this.tableRows;
45664      if (!rows) return null;
45665      return this.editor.getEditorState().read(() => {
45666        return rows[currentRowIndex]?.getChildren() ?? null;
45667      }) ?? null;
45668    }
45669    get currentRowIndex() {
45670      const currentCell = this.currentCell;
45671      if (!currentCell) return 0;
45672      return this.editor.getEditorState().read(() => {
45673        return $getTableRowIndexFromTableCellNode2(currentCell);
45674      }) ?? 0;
45675    }
45676    get currentColumnCells() {
45677      const columnIndex = this.currentColumnIndex;
45678      const rows = this.tableRows;
45679      if (!rows) return null;
45680      return this.editor.getEditorState().read(() => {
45681        return rows.map((row) => row.getChildAtIndex(columnIndex));
45682      }) ?? null;
45683    }
45684    get currentColumnIndex() {
45685      const currentCell = this.currentCell;
45686      if (!currentCell) return 0;
45687      return this.editor.getEditorState().read(() => {
45688        return $getTableColumnIndexFromTableCellNode2(currentCell);
45689      }) ?? 0;
45690    }
45691    get tableRows() {
45692      return this.editor.getEditorState().read(() => {
45693        return this.currentTableNode?.getChildren();
45694      }) ?? null;
45695    }
45696    updateSelectedTable() {
45697      let cellNode = null;
45698      let tableNode = null;
45699      this.editor.getEditorState().read(() => {
45700        const selection = $getSelection2();
45701        if (!selection || !this.selection.isTableCellSelected) return;
45702        const node = selection.getNodes()[0];
45703        cellNode = $findCellNode2(node);
45704        tableNode = $findTableNode2(node);
45705      });
45706      this.currentCellKey = cellNode?.getKey() ?? null;
45707      this.currentTableNodeKey = tableNode?.getKey() ?? null;
45708      return tableNode;
45709    }
45710    executeTableCommand(command, customIndex = null) {
45711      if (command.action === "delete" && command.childType === "table") {
45712        this.#deleteTable();
45713        return;
45714      }
45715      if (command.action === "toggle") {
45716        this.#executeToggleStyle(command);
45717        return;
45718      }
45719      this.#executeCommand(command, customIndex);
45720    }
45721    #executeCommand(command, customIndex = null) {
45722      this.#selectCellAtSelection();
45723      this.editor.dispatchCommand(this.#commandName(command));
45724      this.#selectNextBestCell(command, customIndex);
45725    }
45726    #executeToggleStyle(command) {
45727      const childType = command.childType;
45728      let cells = null;
45729      let headerState = null;
45730      if (childType === "row") {
45731        cells = this.currentRowCells;
45732        headerState = TableCellHeaderStates2.ROW;
45733      } else if (childType === "column") {
45734        cells = this.currentColumnCells;
45735        headerState = TableCellHeaderStates2.COLUMN;
45736      }
45737      if (!cells || cells.length === 0) return;
45738      this.editor.update(() => {
45739        const firstCell = $getTableCellNodeFromLexicalNode2(cells[0]);
45740        if (!firstCell) return;
45741        const currentStyle = firstCell.getHeaderStyles();
45742        const newStyle = currentStyle ^ headerState;
45743        cells.forEach((cell) => {
45744          this.#setHeaderStyle(cell, newStyle, headerState);
45745        });
45746      });
45747    }
45748    #deleteTable() {
45749      this.#selectCellAtSelection();
45750      this.editor.dispatchCommand("deleteTable");
45751    }
45752    #selectCellAtSelection() {
45753      this.editor.update(() => {
45754        const selection = $getSelection2();
45755        if (!selection) return;
45756        const node = selection.getNodes()[0];
45757        $findCellNode2(node)?.selectEnd();
45758      });
45759    }
45760    #commandName(command) {
45761      const { action, childType, direction } = command;
45762      const childTypeSuffix = upcaseFirst(childType);
45763      const directionSuffix = action == "insert" ? upcaseFirst(direction) : "";
45764      return `${action}Table${childTypeSuffix}${directionSuffix}`;
45765    }
45766    #setHeaderStyle(cell, newStyle, headerState) {
45767      const tableCellNode = $getTableCellNodeFromLexicalNode2(cell);
45768      tableCellNode?.setHeaderStyles(newStyle, headerState);
45769    }
45770    async #selectCellAtIndex(rowIndex, columnIndex) {
45771      await nextFrame();
45772      if (!this.currentTableNode) return;
45773      const rows = this.tableRows;
45774      if (!rows) return;
45775      const row = rows[rowIndex];
45776      if (!row) return;
45777      this.editor.update(() => {
45778        const cell = $getTableCellNodeFromLexicalNode2(row.getChildAtIndex(columnIndex));
45779        cell?.selectEnd();
45780      });
45781    }
45782    #selectNextBestCell(command, customIndex = null) {
45783      const { childType, direction } = command;
45784      let rowIndex = this.currentRowIndex;
45785      let columnIndex = customIndex !== null ? customIndex : this.currentColumnIndex;
45786      const deleteOffset = command.action === "delete" ? -1 : 0;
45787      const offset3 = direction === "after" ? 1 : deleteOffset;
45788      if (childType === "row") {
45789        rowIndex += offset3;
45790      } else if (childType === "column") {
45791        columnIndex += offset3;
45792      }
45793      this.#selectCellAtIndex(rowIndex, columnIndex);
45794    }
45795    #selectNextRow() {
45796      const rows = this.tableRows;
45797      if (!rows) return;
45798      const nextRow = rows.at(this.currentRowIndex + 1);
45799      if (!nextRow) return;
45800      this.editor.update(() => {
45801        nextRow.getChildAtIndex(this.currentColumnIndex)?.selectEnd();
45802      });
45803    }
45804    #selectPreviousCell() {
45805      const cell = this.currentCell;
45806      if (!cell) return;
45807      this.editor.update(() => {
45808        cell.selectPrevious();
45809      });
45810    }
45811    #insertRowAndSelectFirstCell() {
45812      this.executeTableCommand({ action: "insert", childType: "row", direction: "after" }, 0);
45813    }
45814    #deleteRowAndSelectLastCell() {
45815      this.executeTableCommand({ action: "delete", childType: "row" }, -1);
45816    }
45817    #deleteRowAndSelectNextNode() {
45818      const tableNode = this.currentTableNode;
45819      this.executeTableCommand({ action: "delete", childType: "row" });
45820      this.editor.update(() => {
45821        const next = tableNode?.getNextSibling();
45822        if ($isParagraphNode2(next)) {
45823          next.selectStart();
45824        } else {
45825          const newParagraph = $createParagraphNode2();
45826          this.currentTableNode.insertAfter(newParagraph);
45827          newParagraph.selectStart();
45828        }
45829      });
45830    }
45831    #isCurrentCellEmpty() {
45832      if (!this.currentTableNode) return false;
45833      const cell = this.currentCell;
45834      if (!cell) return false;
45835      return cell.getTextContent().trim() === "";
45836    }
45837    #isCurrentRowLast() {
45838      if (!this.currentTableNode) return false;
45839      const rows = this.tableRows;
45840      if (!rows) return false;
45841      return rows.length === this.currentRowIndex + 1;
45842    }
45843    #isCurrentRowEmpty() {
45844      if (!this.currentTableNode) return false;
45845      const cells = this.currentRowCells;
45846      if (!cells) return false;
45847      return cells.every((cell) => cell.getTextContent().trim() === "");
45848    }
45849    #isFirstCellInRow() {
45850      if (!this.currentTableNode) return false;
45851      const cells = this.currentRowCells;
45852      if (!cells) return false;
45853      return cells.indexOf(this.currentCell) === 0;
45854    }
45855    #registerKeyHandlers() {
45856      this.#listeners.track(
45857        this.editor.registerCommand(KEY_BACKSPACE_COMMAND2, (event) => this.#handleBackspaceKey(event), COMMAND_PRIORITY_HIGH2),
45858        this.editor.registerCommand(KEY_ENTER_COMMAND2, (event) => this.#handleEnterKey(event), COMMAND_PRIORITY_HIGH2)
45859      );
45860    }
45861    #handleBackspaceKey(event) {
45862      if (!this.currentTableNode) return false;
45863      if (this.#isCurrentRowEmpty() && this.#isFirstCellInRow()) {
45864        event.preventDefault();
45865        this.#deleteRowAndSelectLastCell();
45866        return true;
45867      }
45868      if (this.#isCurrentCellEmpty() && !this.#isFirstCellInRow()) {
45869        event.preventDefault();
45870        this.#selectPreviousCell();
45871        return true;
45872      }
45873      return false;
45874    }
45875    #handleEnterKey(event) {
45876      if (event.ctrlKey || event.metaKey || event.shiftKey || !this.currentTableNode) return false;
45877      if (this.selection.isInsideList || this.selection.isInsideCodeBlock) return false;
45878      event.preventDefault();
45879      if (this.#isCurrentRowLast() && this.#isCurrentRowEmpty()) {
45880        this.#deleteRowAndSelectNextNode();
45881      } else if (this.#isCurrentRowLast()) {
45882        this.#insertRowAndSelectFirstCell();
45883      } else {
45884        this.#selectNextRow();
45885      }
45886      return true;
45887    }
45888  };
45889  var TableIcons = {
45890    "insert-row-before": `<svg  viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
45891    <path fill-rule="evenodd" clip-rule="evenodd" d="M7.86804e-07 15C8.29055e-07 15.8284 0.671574 16.5 1.5 16.5H15L15.1533 16.4922C15.8593 16.4205 16.4205 15.8593 16.4922 15.1533L16.5 15V4.5L16.4922 4.34668C16.4154 3.59028 15.7767 3 15 3H13.5L13.5 4.5H15V9H1.5L1.5 4.5L3 4.5V3H1.5C0.671574 3 1.20956e-06 3.67157 1.24577e-06 4.5L7.86804e-07 15ZM15 10.5V15H1.5L1.5 10.5H15Z"/>
45892    <path d="M4.5 4.5H7.5V7.5H9V4.5H12L12 3L9 3V6.55671e-08L7.5 0V3L4.5 3V4.5Z"/>
45893    </svg>`,
45894    "insert-row-after": `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
45895    <path fill-rule="evenodd" clip-rule="evenodd" d="M7.86804e-07 13.5C7.50592e-07 14.3284 0.671574 15 1.5 15H3V13.5H1.5L1.5 9L15 9V13.5H13.5V15H15C15.7767 15 16.4154 14.4097 16.4922 13.6533L16.5 13.5V3L16.4922 2.84668C16.4205 2.14069 15.8593 1.57949 15.1533 1.50781L15 1.5L1.5 1.5C0.671574 1.5 1.28803e-06 2.17157 1.24577e-06 3L7.86804e-07 13.5ZM15 3V7.5L1.5 7.5L1.5 3L15 3Z"/>
45896    <path d="M7.5 15V18H9V15H12V13.5H9V10.5H7.5V13.5H4.5V15H7.5Z"/>
45897    </svg>`,
45898    "delete-row": `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
45899    <path d="M16.4922 12.1533C16.4154 12.9097 15.7767 13.5 15 13.5L12 13.5V12H15V6L1.5 6L1.5 12H4.5V13.5H1.5C0.723337 13.5 0.0846104 12.9097 0.00781328 12.1533L7.86804e-07 12L1.04907e-06 6C1.17362e-06 5.22334 0.590278 4.58461 1.34668 4.50781L1.5 4.5L15 4.5C15.8284 4.5 16.5 5.17157 16.5 6V12L16.4922 12.1533Z"/>
45900    <path d="M10.3711 15.9316L8.25 13.8096L6.12793 15.9316L5.06738 14.8711L7.18945 12.75L5.06738 10.6289L6.12793 9.56836L8.25 11.6895L10.3711 9.56836L11.4316 10.6289L9.31055 12.75L11.4316 14.8711L10.3711 15.9316Z"/>
45901    </svg>`,
45902    "toggle-row": `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
45903    <path fill-rule="evenodd" clip-rule="evenodd" d="M0.00781328 13.6533C0.0846108 14.4097 0.723337 15 1.5 15L15 15L15.1533 14.9922C15.8593 14.9205 16.4205 14.3593 16.4922 13.6533L16.5 13.5V4.5L16.4922 4.34668C16.4205 3.64069 15.8593 3.07949 15.1533 3.00781L15 3L1.5 3C0.671574 3 1.24863e-06 3.67157 1.18021e-06 4.5L7.86804e-07 13.5L0.00781328 13.6533ZM15 9V13.5L1.5 13.5L1.5 9L15 9Z"/>
45904    </svg>`,
45905    "insert-column-before": `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
45906    <path fill-rule="evenodd" clip-rule="evenodd" d="M4.5 0C3.67157 0 3 0.671573 3 1.5V3H4.5V1.5H9V15H4.5V13.5H3V15C3 15.7767 3.59028 16.4154 4.34668 16.4922L4.5 16.5H15L15.1533 16.4922C15.8593 16.4205 16.4205 15.8593 16.4922 15.1533L16.5 15V1.5C16.5 0.671573 15.8284 6.03989e-09 15 0H4.5ZM15 15H10.5V1.5H15V15Z"/>
45907    <path d="M3 7.5H0V9H3V12H4.5V9H7.5V7.5H4.5V4.5H3V7.5Z"/>
45908    </svg>`,
45909    "insert-column-after": `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
45910    <path fill-rule="evenodd" clip-rule="evenodd" d="M13.5 0C14.3284 0 15 0.671573 15 1.5V3H13.5V1.5H9V15H13.5V13.5H15V15C15 15.7767 14.4097 16.4154 13.6533 16.4922L13.5 16.5H3L2.84668 16.4922C2.14069 16.4205 1.57949 15.8593 1.50781 15.1533L1.5 15V1.5C1.5 0.671573 2.17157 6.03989e-09 3 0H13.5ZM3 15H7.5V1.5H3V15Z"/>
45911    <path d="M15 7.5H18V9H15V12H13.5V9H10.5V7.5H13.5V4.5H15V7.5Z"/>
45912    </svg>`,
45913    "delete-column": `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
45914    <path d="M12.1533 0.0078125C12.9097 0.0846097 13.5 0.723336 13.5 1.5V4.5H12V1.5H6V15H12V12H13.5V15C13.5 15.7767 12.9097 16.4154 12.1533 16.4922L12 16.5H6C5.22334 16.5 4.58461 15.9097 4.50781 15.1533L4.5 15V1.5C4.5 0.671573 5.17157 2.41596e-08 6 0H12L12.1533 0.0078125Z"/>
45915    <path d="M15.9316 6.12891L13.8105 8.24902L15.9326 10.3711L14.8711 11.4316L12.75 9.31055L10.6289 11.4316L9.56738 10.3711L11.6885 8.24902L9.56836 6.12891L10.6289 5.06836L12.75 7.18848L14.8711 5.06836L15.9316 6.12891Z"/>
45916    </svg>`,
45917    "toggle-column": `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
45918    <path fill-rule="evenodd" clip-rule="evenodd" d="M13.6533 17.9922C14.4097 17.9154 15 17.2767 15 16.5L15 3L14.9922 2.84668C14.9205 2.14069 14.3593 1.57949 13.6533 1.50781L13.5 1.5L4.5 1.5L4.34668 1.50781C3.59028 1.58461 3 2.22334 3 3L3 16.5C3 17.2767 3.59028 17.9154 4.34668 17.9922L4.5 18L13.5 18L13.6533 17.9922ZM9 3L13.5 3L13.5 16.5L9 16.5L9 3Z"/>
45919    </svg>`,
45920    "delete-table": `<svg viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
45921      <path d="M11.2041 1.01074C12.2128 1.113 13 1.96435 13 3V4H15L15.1025 4.00488C15.6067 4.05621 16 4.48232 16 5C16 5.55228 15.5523 6 15 6H14.8457L14.1416 15.1533C14.0614 16.1953 13.1925 17 12.1475 17H5.85254L5.6582 16.9902C4.76514 16.9041 4.03607 16.2296 3.88184 15.3457L3.8584 15.1533L3.1543 6H3C2.44772 6 2 5.55228 2 5C2 4.44772 2.44772 4 3 4H5V3C5 1.89543 5.89543 1 7 1H11L11.2041 1.01074ZM5.85254 15H12.1475L12.8398 6H5.16016L5.85254 15ZM7 4H11V3H7V4Z"/>
45922    </svg>`
45923  };
45924  var TableTools = class extends HTMLElement {
45925    #listeners = new ListenerBin();
45926    connectedCallback() {
45927      this.tableController = new TableController(this.#editorElement);
45928      this.classList.add("lexxy-floating-controls");
45929      this.role = "toolbar";
45930      this.#setUpButtons();
45931      this.#hide();
45932      this.#monitorForTableSelection();
45933      this.#registerKeyboardShortcuts();
45934    }
45935    disconnectedCallback() {
45936      this.dispose();
45937    }
45938    dispose() {
45939      this.#listeners.dispose();
45940      this.tableController?.destroy();
45941      this.tableController = null;
45942    }
45943    get #editor() {
45944      return this.#editorElement.editor;
45945    }
45946    get #editorElement() {
45947      return this.closest("lexxy-editor");
45948    }
45949    get #tableToolsButtons() {
45950      return Array.from(this.querySelectorAll("button, details > summary"));
45951    }
45952    #setUpButtons() {
45953      this.innerHTML = "";
45954      this.appendChild(this.#createRowButtonsContainer());
45955      this.appendChild(this.#createColumnButtonsContainer());
45956      this.appendChild(this.#createDeleteTableButton());
45957      this.#listeners.track(registerEventListener(this, "keydown", this.#handleToolsKeydown));
45958    }
45959    #createButtonsContainer(childType, setCountProperty, moreMenu) {
45960      const container = createElement("div", { className: `lexxy-floating-controls__group lexxy-table-control lexxy-table-control--${childType}` });
45961      const plusButton = this.#createButton(`Add ${childType}`, { action: "insert", childType, direction: "after" }, "+");
45962      const minusButton = this.#createButton(`Remove ${childType}`, { action: "delete", childType }, "\u2212");
45963      const dropdown = createElement("details", { className: "lexxy-table-control__more-menu" });
45964      dropdown.setAttribute("name", "lexxy-dropdown");
45965      dropdown.tabIndex = -1;
45966      const count = createElement("summary", {}, `_ ${childType}s`);
45967      setCountProperty(count);
45968      dropdown.appendChild(count);
45969      dropdown.appendChild(moreMenu);
45970      container.appendChild(minusButton);
45971      container.appendChild(dropdown);
45972      container.appendChild(plusButton);
45973      return container;
45974    }
45975    #createRowButtonsContainer() {
45976      return this.#createButtonsContainer(
45977        "row",
45978        (count) => {
45979          this.rowCount = count;
45980        },
45981        this.#createMoreMenuSection("row")
45982      );
45983    }
45984    #createColumnButtonsContainer() {
45985      return this.#createButtonsContainer(
45986        "column",
45987        (count) => {
45988          this.columnCount = count;
45989        },
45990        this.#createMoreMenuSection("column")
45991      );
45992    }
45993    #createMoreMenuSection(childType) {
45994      const section = createElement("div", { className: "lexxy-floating-controls__group lexxy-table-control__more-menu-details" });
45995      const addBeforeButton = this.#createButton(`Add ${childType} before`, { action: "insert", childType, direction: "before" });
45996      const addAfterButton = this.#createButton(`Add ${childType} after`, { action: "insert", childType, direction: "after" });
45997      const toggleStyleButton = this.#createButton(`Toggle ${childType} style`, { action: "toggle", childType });
45998      const deleteButton = this.#createButton(`Remove ${childType}`, { action: "delete", childType });
45999      section.appendChild(addBeforeButton);
46000      section.appendChild(addAfterButton);
46001      section.appendChild(toggleStyleButton);
46002      section.appendChild(deleteButton);
46003      return section;
46004    }
46005    #createDeleteTableButton() {
46006      const container = createElement("div", { className: "lexxy-table-control lexxy-floating-controls__group" });
46007      const deleteTableButton = this.#createButton("Delete this table?", { action: "delete", childType: "table" });
46008      deleteTableButton.classList.add("lexxy-table-control__button--delete-table");
46009      container.appendChild(deleteTableButton);
46010      this.deleteContainer = container;
46011      return container;
46012    }
46013    #createButton(label, command = {}, icon = this.#icon(command)) {
46014      const button = createElement("button", {
46015        className: "lexxy-table-control__button",
46016        "aria-label": label,
46017        type: "button"
46018      });
46019      button.tabIndex = -1;
46020      button.innerHTML = `${icon} <span>${label}</span>`;
46021      button.dataset.action = command.action;
46022      button.dataset.childType = command.childType;
46023      button.dataset.direction = command.direction;
46024      button.addEventListener("click", () => this.#executeTableCommand(command));
46025      button.addEventListener("mouseover", () => this.#handleCommandButtonHover());
46026      button.addEventListener("focus", () => this.#handleCommandButtonHover());
46027      button.addEventListener("mouseout", () => this.#handleCommandButtonHover());
46028      return button;
46029    }
46030    #registerKeyboardShortcuts() {
46031      this.#listeners.track(this.#editor.registerCommand(KEY_DOWN_COMMAND2, this.#focusToolbarOnAltF10, COMMAND_PRIORITY_HIGH2));
46032    }
46033    #focusToolbarOnAltF10 = (event) => {
46034      if (this.#hasSelectedTable && event.altKey && event.key === "F10") {
46035        event.preventDefault();
46036        this.#tableToolsButtons[0]?.focus({ focusVisible: true });
46037        return true;
46038      } else {
46039        return false;
46040      }
46041    };
46042    get #hasSelectedTable() {
46043      return this.tableController?.currentTableNodeKey != null;
46044    }
46045    #handleToolsKeydown = (event) => {
46046      if (event.key === "Escape") {
46047        this.#handleEscapeKey();
46048      } else {
46049        handleRollingTabIndex(this.#tableToolsButtons, event);
46050      }
46051    };
46052    #handleEscapeKey() {
46053      const cell = this.tableController.currentCell;
46054      if (!cell) return;
46055      this.#editor.update(() => {
46056        cell.select();
46057        this.#editor.focus();
46058      });
46059      this.#update();
46060    }
46061    async #handleCommandButtonHover() {
46062      await nextFrame();
46063      this.#clearCellStyles();
46064      const activeElement = this.querySelector("button:hover, button:focus");
46065      if (!activeElement) return;
46066      const command = {
46067        action: activeElement.dataset.action,
46068        childType: activeElement.dataset.childType,
46069        direction: activeElement.dataset.direction
46070      };
46071      let cellsToHighlight = null;
46072      switch (command.childType) {
46073        case "row":
46074          cellsToHighlight = this.tableController.currentRowCells;
46075          break;
46076        case "column":
46077          cellsToHighlight = this.tableController.currentColumnCells;
46078          break;
46079        case "table":
46080          cellsToHighlight = this.tableController.tableRows;
46081          break;
46082      }
46083      if (!cellsToHighlight) return;
46084      cellsToHighlight.forEach((cell) => {
46085        const cellElement = this.#editor.getElementByKey(cell.getKey());
46086        if (!cellElement) return;
46087        cellElement.classList.toggle(theme.tableCellHighlight, true);
46088        Object.assign(cellElement.dataset, command);
46089      });
46090    }
46091    #monitorForTableSelection() {
46092      this.#listeners.track(this.#editor.registerUpdateListener(() => {
46093        const tableNode = this.#editor.getRootElement() && this.tableController.updateSelectedTable();
46094        if (tableNode) {
46095          this.#show();
46096        } else {
46097          this.#hide();
46098        }
46099      }));
46100    }
46101    #executeTableCommand(command) {
46102      this.tableController.executeTableCommand(command);
46103      this.#update();
46104    }
46105    #show() {
46106      this.#updateButtonsPosition();
46107      this.style.display = "flex";
46108      this.#updateRowColumnCount();
46109      this.#closeMoreMenu();
46110      this.#handleCommandButtonHover();
46111    }
46112    #hide() {
46113      this.style.display = "none";
46114      this.#clearCellStyles();
46115    }
46116    #update() {
46117      this.#updateButtonsPosition();
46118      this.#updateRowColumnCount();
46119      this.#closeMoreMenu();
46120      this.#handleCommandButtonHover();
46121    }
46122    #closeMoreMenu() {
46123      this.querySelector("details[open]")?.removeAttribute("open");
46124    }
46125    #updateButtonsPosition() {
46126      const tableNode = this.tableController.currentTableNode;
46127      if (!tableNode) return;
46128      const tableElement = this.#editor.getElementByKey(tableNode.getKey());
46129      if (!tableElement) return;
46130      const tableRect = tableElement.getBoundingClientRect();
46131      const editorRect = this.#editorElement.getBoundingClientRect();
46132      const relativeTop = tableRect.top - editorRect.top;
46133      const relativeCenter = (tableRect.left + tableRect.right) / 2 - editorRect.left;
46134      this.style.top = `${relativeTop}px`;
46135      this.style.left = `${relativeCenter}px`;
46136    }
46137    #updateRowColumnCount() {
46138      const tableNode = this.tableController.currentTableNode;
46139      if (!tableNode) return;
46140      const tableElement = $getElementForTableNode2(this.#editor, tableNode);
46141      if (!tableElement) return;
46142      const rowCount = tableElement.rows;
46143      const columnCount = tableElement.columns;
46144      this.rowCount.textContent = `${rowCount} row${rowCount === 1 ? "" : "s"}`;
46145      this.columnCount.textContent = `${columnCount} column${columnCount === 1 ? "" : "s"}`;
46146    }
46147    #setTableCellFocus() {
46148      const cell = this.tableController.currentCell;
46149      if (!cell) return;
46150      const cellElement = this.#editor.getElementByKey(cell.getKey());
46151      if (!cellElement) return;
46152      cellElement.classList.add(theme.tableCellFocus);
46153    }
46154    #clearCellStyles() {
46155      this.#editorElement.querySelectorAll(`.${theme.tableCellFocus}`)?.forEach((cell) => {
46156        cell.classList.remove(theme.tableCellFocus);
46157      });
46158      this.#editorElement.querySelectorAll(`.${theme.tableCellHighlight}`)?.forEach((cell) => {
46159        cell.classList.remove(theme.tableCellHighlight);
46160        cell.removeAttribute("data-action");
46161        cell.removeAttribute("data-child-type");
46162        cell.removeAttribute("data-direction");
46163      });
46164      this.#setTableCellFocus();
46165    }
46166    #icon(command) {
46167      const { action, childType } = command;
46168      const direction = action == "insert" ? command.direction : null;
46169      const iconId = [action, childType, direction].filter(Boolean).join("-");
46170      return TableIcons[iconId];
46171    }
46172  };
46173  function defineElements() {
46174    const elements = {
46175      // Toolbar must be registered BEFORE Editor
46176      "lexxy-toolbar": LexicalToolbarElement,
46177      "lexxy-toolbar-dropdown": ToolbarDropdown,
46178      "lexxy-heading-dropdown": HeadingDropdown,
46179      "lexxy-highlight-dropdown": HighlightDropdown,
46180      "lexxy-link-dropdown": LinkDropdown,
46181      "lexxy-editor": LexicalEditorElement,
46182      // Prompt must be registered AFTER Editor
46183      "lexxy-prompt": LexicalPromptElement,
46184      "lexxy-code-language-picker": CodeLanguagePicker,
46185      "lexxy-node-delete-button": NodeDeleteButton,
46186      "lexxy-table-tools": TableTools
46187    };
46188    Object.entries(elements).forEach(([name, element]) => {
46189      customElements.define(name, element);
46190    });
46191  }
46192  var configure = Lexxy.configure;
46193  setTimeout(defineElements, 0);
46194
46195  
46195// app/javascript/src/lexxy/callout_icons.js
46196  var CALLOUT_ICONS = [
46197    {
46198      id: "lightbulb",
46199      label: "Light bulb",
46200      svg: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 18h6"/><path d="M10 22h4"/><path d="M12 2a7 7 0 0 0-4 12.74V17a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1v-2.26A7 7 0 0 0 12 2z"/></svg>`
46201    },
46202    {
46203      id: "info",
46204      label: "Info",
46205      svg: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg>`
46206    },
46207    {
46208      id: "warning",
46209      label: "Warning",
46210      svg: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"/><path d="M12 9v4"/><path d="M12 17h.01"/></svg>`
46211    },
46212    {
46213      id: "check",
46214      label: "Check",
46215      svg: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20 6 9 17l-5-5"/></svg>`
46216    },
46217    {
46218      id: "x",
46219      label: "\u{1D54F} / Twitter",
46220      svg: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg>`
46221    },
46222    {
46223      id: "star",
46224      label: "Star",
46225      svg: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z"/></svg>`
46226    },
46227    {
46228      id: "heart",
46229      label: "Heart",
46230      svg: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z"/></svg>`
46231    },
46232    {
46233      id: "flag",
46234      label: "Flag",
46235      svg: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 15s1-1 4-1 5 2 8 2 4-1 4-1V3s-1 1-4 1-5-2-8-2-4 1-4 1z"/><line x1="4" x2="4" y1="22" y2="15"/></svg>`
46236    },
46237    {
46238      id: "bookmark",
46239      label: "Bookmark",
46240      svg: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="m19 21-7-4-7 4V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z"/></svg>`
46241    },
46242    {
46243      id: "pin",
46244      label: "Pin",
46245      svg: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 17v5"/><path d="M9 10.76a2 2 0 0 1-1.11 1.79l-1.78.9A2 2 0 0 0 5 15.24V16a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-.76a2 2 0 0 0-1.11-1.79l-1.78-.9A2 2 0 0 1 15 10.76V7a1 1 0 0 1 1-1h2a1 1 0 0 0 0-4H8a1 1 0 0 0 0 4h2a1 1 0 0 1 1 1z"/></svg>`
46246    },
46247    {
46248      id: "rocket",
46249      label: "Rocket",
46250      svg: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09z"/><path d="m12 15-3-3a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.35 22.35 0 0 1-4 2z"/><path d="M9 12H4s.55-3.03 2-4c1.62-1.08 5 0 5 0"/><path d="M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5"/></svg>`
46251    },
46252    {
46253      id: "message",
46254      label: "Message",
46255      svg: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M7.9 20A9 9 0 1 0 4 16.1L2 22Z"/></svg>`
46256    }
46257  ];
46258  function calloutIconById(id3) {
46259    return CALLOUT_ICONS.find((icon) => icon.id === id3);
46260  }
46261  function isSvgMarkup(value) {
46262    return typeof value === "string" && value.trim().startsWith("<svg");
46263  }
46264  function iconMaskUrl(svg2) {
46265    const encoded = encodeURIComponent(svg2.replace(/currentColor/g, "#000"));
46266    return `url("data:image/svg+xml,${encoded}")`;
46267  }
46268  function sanitizedSvgElement(markup) {
46269    if (!isSvgMarkup(markup)) return null;
46270    const template = document.createElement("template");
46271    template.innerHTML = markup.trim();
46272    const svg2 = template.content.firstElementChild;
46273    if (!svg2 || svg2.tagName.toLowerCase() !== "svg") return null;
46274    svg2.querySelectorAll("script, foreignObject").forEach((element) => element.remove());
46275    svg2.querySelectorAll("*").forEach((element) => {
46276      Array.from(element.attributes).forEach((attribute) => {
46277        if (/^on/i.test(attribute.name) || /javascript:/i.test(attribute.value)) {
46278          element.removeAttribute(attribute.name);
46279        }
46280      });
46281    });
46282    svg2.setAttribute("aria-hidden", "true");
46283    svg2.setAttribute("focusable", "false");
46284    svg2.classList.add("lexxy-callout__icon-svg");
46285    if (svg2.dataset.lucide) {
46286      svg2.classList.add("lucide", `lucide-${svg2.dataset.lucide}`);
46287    }
46288    return svg2;
46289  }
46290
46291  
46291// app/javascript/src/lexxy/callout_assets.js
46292  var LUCIDE_ICONS_GLOBAL = "LexxyLucideCalloutIcons";
46293  var LUCIDE_ICONS_META_SELECTOR = 'meta[name="lucide-callout-icons-src"]';
46294  var lucideIconsPromise = null;
46295  function lucideIconsScriptSrc() {
46296    return document.querySelector(LUCIDE_ICONS_META_SELECTOR)?.content || "/assets/lucide_callout_icons.js";
46297  }
46298  function loadLucideCalloutIcons() {
46299    if (window[LUCIDE_ICONS_GLOBAL]) return Promise.resolve(window[LUCIDE_ICONS_GLOBAL]);
46300    if (lucideIconsPromise) return lucideIconsPromise;
46301    lucideIconsPromise = new Promise((resolve, reject) => {
46302      const script = document.createElement("script");
46303      script.async = true;
46304      script.src = lucideIconsScriptSrc();
46305      script.addEventListener(
46306        "load",
46307        () => {
46308          if (window[LUCIDE_ICONS_GLOBAL]) {
46309            resolve(window[LUCIDE_ICONS_GLOBAL]);
46310          } else {
46311            reject(new Error("Lucide icons loaded without exposing the callout icon registry"));
46312          }
46313        },
46314        { once: true }
46315      );
46316      script.addEventListener(
46317        "error",
46318        () => {
46319          lucideIconsPromise = null;
46320          reject(new Error("Could not load callout icons"));
46321        },
46322        { once: true }
46323      );
46324      document.head.appendChild(script);
46325    });
46326    return lucideIconsPromise;
46327  }
46328  function safeImageUrl(value) {
46329    if (!value) return null;
46330    try {
46331      const url = new URL(value, window.location.href);
46332      if (url.protocol === "data:" && !value.startsWith("data:image/")) return null;
46333      if (!["http:", "https:", "data:", "blob:"].includes(url.protocol)) return null;
46334      return url.href;
46335    } catch (_error) {
46336      return null;
46337    }
46338  }
46339
46340  
46340// app/javascript/src/lexxy/callout_content.js
46341  var CALLOUT_SELECTOR = ":where(.trix-content, .lexxy-content) .lexxy-callout[data-icon-type]:not([data-icon-type='none']):not([data-icon-type='emoji'])";
46342  var CALLOUT_ICON_SELECTOR = ":scope > .lexxy-callout__icon";
46343  function queryCallouts(root) {
46344    if (root === document) {
46345      return document.querySelectorAll(CALLOUT_SELECTOR);
46346    }
46347    return root.querySelectorAll(".lexxy-callout[data-icon-type]:not([data-icon-type='none']):not([data-icon-type='emoji'])");
46348  }
46349  function hasLegacyIconStyle(callout) {
46350    return callout.style.getPropertyValue("--callout-icon-mask") || callout.style.getPropertyValue("--callout-icon-image");
46351  }
46352  function needsHydration(callout) {
46353    if (callout.closest("lexxy-editor")) return false;
46354    if (callout.querySelector(CALLOUT_ICON_SELECTOR)) return false;
46355    if (callout.dataset.calloutHydrated === "true" && !hasLegacyIconStyle(callout)) return false;
46356    const iconType = callout.dataset.iconType;
46357    if (iconType === "symbol") {
46358      return true;
46359    }
46360    if (iconType === "image") {
46361      return true;
46362    }
46363    return false;
46364  }
46365  function resolveSymbolSvg(callout) {
46366    const iconSrc = callout.dataset.iconSrc;
46367    if (isSvgMarkup(iconSrc)) return iconSrc;
46368    const builtIn = calloutIconById(callout.dataset.iconId);
46369    return builtIn?.svg || null;
46370  }
46371  function insertCalloutIcon(callout, icon) {
46372    const wrapper = document.createElement("span");
46373    wrapper.className = "lexxy-callout__icon";
46374    wrapper.setAttribute("aria-hidden", "true");
46375    wrapper.append(icon);
46376    callout.querySelector(CALLOUT_ICON_SELECTOR)?.remove();
46377    callout.insertBefore(wrapper, callout.firstChild);
46378  }
46379  function hydrateSymbolCallout(callout, svg2) {
46380    const icon = sanitizedSvgElement(svg2);
46381    if (icon) insertCalloutIcon(callout, icon);
46382    callout.style.removeProperty("--callout-icon-mask");
46383    callout.dataset.calloutHydrated = "true";
46384  }
46385  function hydrateImageCallout(callout) {
46386    const imageUrl = safeImageUrl(callout.dataset.iconSrc);
46387    if (!imageUrl) return;
46388    if (!callout.isConnected || callout.querySelector(CALLOUT_ICON_SELECTOR)) {
46389      return;
46390    }
46391    const image = document.createElement("img");
46392    image.className = "lexxy-callout__icon-image";
46393    image.decoding = "async";
46394    image.loading = "lazy";
46395    image.alt = "";
46396    image.src = imageUrl;
46397    insertCalloutIcon(callout, image);
46398    callout.style.removeProperty("--callout-icon-image");
46399    callout.dataset.calloutHydrated = "true";
46400  }
46401  function scheduleDecorativeHydration(callback) {
46402    if ("requestIdleCallback" in window) {
46403      window.requestIdleCallback(callback, { timeout: 1200 });
46404    } else {
46405      setTimeout(callback, 0);
46406    }
46407  }
46408  function hydrateCallouts(root = document) {
46409    const callouts = [...queryCallouts(root)].filter(needsHydration);
46410    if (callouts.length === 0) return Promise.resolve();
46411    const pendingLucide = [];
46412    callouts.forEach((callout) => {
46413      if (callout.dataset.iconType === "image") {
46414        hydrateImageCallout(callout);
46415        return;
46416      }
46417      if (callout.dataset.iconType !== "symbol") return;
46418      const svg2 = resolveSymbolSvg(callout);
46419      if (svg2) {
46420        hydrateSymbolCallout(callout, svg2);
46421        return;
46422      }
46423      if (callout.dataset.iconId) {
46424        pendingLucide.push(callout);
46425      }
46426    });
46427    if (pendingLucide.length > 0) {
46428      scheduleDecorativeHydration(() => {
46429        loadLucideCalloutIcons().then((lucide) => {
46430          pendingLucide.forEach((callout) => {
46431            if (!callout.isConnected || !needsHydration(callout)) return;
46432            const svg2 = lucide.svgFor(callout.dataset.iconId);
46433            if (svg2) hydrateSymbolCallout(callout, svg2);
46434          });
46435        }).catch(() => {
46436        });
46437      });
46438    }
46439    return Promise.resolve();
46440  }
46441  function scheduleCalloutHydration(root = document) {
46442    requestAnimationFrame(() => {
46443      requestAnimationFrame(() => hydrateCallouts(root));
46444    });
46445  }
46446
46447  
46447// app/javascript/src/lexxy/code_block_copy.js
46448  var CODE_BLOCK_SELECTOR = ":where(.trix-content, .lexxy-content) pre[data-language]";
46449  var WRAPPER_CLASS = "lexxy-code-block";
46450  var COPY_ICON = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M7 7m0 2.667a2.667 2.667 0 0 1 2.667 -2.667h8.666a2.667 2.667 0 0 1 2.667 2.667v8.666a2.667 2.667 0 0 1 -2.667 2.667h-8.666a2.667 2.667 0 0 1 -2.667 -2.667z"></path><path d="M4.012 16.737a2.005 2.005 0 0 1 -1.012 -1.737v-10c0 -1.1 .9 -2 2 -2h10c.75 0 1.158 .385 1.5 1"></path></svg>`;
46451  var COPIED_ICON = `<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12l5 5l10 -10"></path></svg>`;
46452  function queryCodeBlocks(root) {
46453    if (root === document) {
46454      return document.querySelectorAll(CODE_BLOCK_SELECTOR);
46455    }
46456    return root.querySelectorAll("pre[data-language]");
46457  }
46458  function isReadableCodeBlock(pre) {
46459    return pre?.isConnected && !pre.closest("lexxy-editor") && !pre.closest(`.${WRAPPER_CLASS}`);
46460  }
46461  function createCopyButton(codeText) {
46462    const button = document.createElement("button");
46463    button.type = "button";
46464    button.className = "lexxy-code-block__copy";
46465    button.setAttribute("aria-label", "Copy code");
46466    button.dataset.controller = "clipboard";
46467    button.dataset.clipboardText = codeText;
46468    button.dataset.clipboardShowTooltipValue = "false";
46469    button.dataset.clipboardTooltipDurationValue = "1500";
46470    const copyContent = document.createElement("span");
46471    copyContent.dataset.clipboardTarget = "copyContent";
46472    copyContent.innerHTML = COPY_ICON;
46473    const copiedContent = document.createElement("span");
46474    copiedContent.dataset.clipboardTarget = "copiedContent";
46475    copiedContent.className = "hidden";
46476    copiedContent.innerHTML = COPIED_ICON;
46477    button.append(copyContent, copiedContent);
46478    return button;
46479  }
46480  function wrapCodeBlock(pre) {
46481    const wrapper = document.createElement("div");
46482    wrapper.className = WRAPPER_CLASS;
46483    const parent = pre.parentNode;
46484    parent.insertBefore(wrapper, pre);
46485    wrapper.append(pre, createCopyButton(pre.textContent || ""));
46486  }
46487  function enhanceCodeBlockCopyButtons(root = document) {
46488    [...queryCodeBlocks(root)].filter(isReadableCodeBlock).forEach(wrapCodeBlock);
46489  }
46490  function scheduleCodeBlockCopyButtons(root = document) {
46491    requestAnimationFrame(() => {
46492      enhanceCodeBlockCopyButtons(root);
46493    });
46494  }
46495
46496  
46496// app/javascript/src/lexxy/hex_color_node.js
46497  var { $applyNodeReplacement: $applyNodeReplacement3, TextNode: TextNode3 } = Lexical_exports;
46498  var HEX_COLOR_CLASS = "lexxy-hex-color";
46499  var HEX_COLOR_SWATCH_VAR = "--lexxy-hex-swatch";
46500  var HEX_COLOR_PATTERN = /#(?:[0-9a-fA-F]{6}(?![0-9a-fA-F])|[0-9a-fA-F]{3}(?=[^0-9a-fA-F]))/;
46501  function getHexColorMatch(text2) {
46502    const match = HEX_COLOR_PATTERN.exec(text2);
46503    if (!match) return null;
46504    return {
46505      start: match.index,
46506      end: match.index + match[0].length
46507    };
46508  }
46509  function isHexColorValue(text2) {
46510    return typeof text2 === "string" && /^#(?:[0-9a-fA-F]{6}|[0-9a-fA-F]{3})$/.test(text2);
46511  }
46512  function colorFromStyle(style) {
46513    if (!style) return null;
46514    const swatchMatch = /(?:^|;)\s*--lexxy-hex-swatch\s*:\s*([^;]+)/i.exec(style);
46515    const backgroundMatch = /(?:^|;)\s*background-color\s*:\s*([^;]+)/i.exec(style);
46516    const colorMatch = /(?:^|;)\s*color\s*:\s*([^;]+)/i.exec(style);
46517    const value = (swatchMatch?.[1] || backgroundMatch?.[1] || colorMatch?.[1])?.trim();
46518    return isHexColorValue(value) ? value : null;
46519  }
46520  function applyHexColorSwatch(element, color) {
46521    if (!(element instanceof HTMLElement) || !isHexColorValue(color)) return;
46522    element.classList.add(HEX_COLOR_CLASS);
46523    element.style.setProperty(HEX_COLOR_SWATCH_VAR, color);
46524    element.style.removeProperty("background-color");
46525    element.style.removeProperty("color");
46526  }
46527  var HexColorNode = class _HexColorNode extends TextNode3 {
46528    static getType() {
46529      return "lexxy-hex-color";
46530    }
46531    static clone(node) {
46532      return new _HexColorNode(node.__text, node.__key);
46533    }
46534    createDOM(config, editor) {
46535      const element = super.createDOM(config, editor);
46536      applyHexColorSwatch(element, this.getTextContent());
46537      return element;
46538    }
46539    updateDOM(prevNode, dom, config) {
46540      const updated = super.updateDOM(prevNode, dom, config);
46541      applyHexColorSwatch(dom, this.getTextContent());
46542      return updated;
46543    }
46544    static importDOM() {
46545      return {
46546        span: (domNode) => {
46547          if (!domNode.classList.contains(HEX_COLOR_CLASS)) return null;
46548          const text2 = domNode.textContent?.trim() || "";
46549          const color = isHexColorValue(text2) ? text2 : colorFromStyle(domNode.getAttribute("style"));
46550          if (!color) return null;
46551          return {
46552            conversion: () => ({
46553              node: $createHexColorNode(color),
46554              forChild: () => null
46555            }),
46556            priority: 2
46557          };
46558        }
46559      };
46560    }
46561    exportDOM(editor) {
46562      const element = document.createElement("span");
46563      element.textContent = this.getTextContent();
46564      applyHexColorSwatch(element, this.getTextContent());
46565      return { element };
46566    }
46567    static importJSON(serializedNode) {
46568      return $createHexColorNode(serializedNode.text).updateFromJSON(serializedNode);
46569    }
46570    exportJSON() {
46571      return {
46572        ...super.exportJSON(),
46573        type: "lexxy-hex-color",
46574        version: 1
46575      };
46576    }
46577    isTextEntity() {
46578      return true;
46579    }
46580    canInsertTextBefore() {
46581      return false;
46582    }
46583    canInsertTextAfter() {
46584      return false;
46585    }
46586  };
46587  function $createHexColorNode(text2) {
46588    return $applyNodeReplacement3(new HexColorNode(text2));
46589  }
46590  function $isHexColorNode(node) {
46591    return node instanceof HexColorNode;
46592  }
46593
46594  
46594// app/javascript/src/lexxy/hex_color_content.js
46595  var HEX_COLOR_SELECTOR = `:where(.trix-content, .lexxy-content) .${HEX_COLOR_CLASS}`;
46596  var COPIED_CLASS = "lexxy-hex-color--copied";
46597  var COPIED_ICON_CLASS = "lexxy-hex-color__copied-icon";
46598  var COPIED_ICON2 = `<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" aria-hidden="true"><g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" stroke="currentColor"><path d="M6.25,2.75h-1c-1.105,0-2,.895-2,2V14.25c0,1.105,.895,2,2,2h7.5c1.105,0,2-.895,2-2V4.75c0-1.105-.895-2-2-2h-1"></path><rect x="6.25" y="1.25" width="5.5" height="3" rx="1" ry="1"></rect><polyline points="6.25 10.25 8 12.25 11.75 7.25"></polyline></g></svg>`;
46599  var COPIED_RESET_MS = 1e3;
46600  var hydrationFrame = null;
46601  var dynamicContentObserver = null;
46602  var clickListenerAttached = false;
46603  var copiedResetTimers = /* @__PURE__ */ new WeakMap();
46604  function queryHexColors(root) {
46605    if (root === document) {
46606      return document.querySelectorAll(HEX_COLOR_SELECTOR);
46607    }
46608    const matches = [];
46609    if (root instanceof Element && root.classList?.contains(HEX_COLOR_CLASS)) {
46610      matches.push(root);
46611    }
46612    if (root?.querySelectorAll) {
46613      matches.push(...root.querySelectorAll(`.${HEX_COLOR_CLASS}`));
46614    }
46615    return matches;
46616  }
46617  function colorFromElement(element) {
46618    const text2 = element.textContent?.trim().replace(/\s+/g, "") || "";
46619    const hexMatch = text2.match(/#(?:[0-9a-fA-F]{6}|[0-9a-fA-F]{3})\b/);
46620    if (hexMatch && isHexColorValue(hexMatch[0])) return hexMatch[0];
46621    const swatch = element.style.getPropertyValue("--lexxy-hex-swatch")?.trim();
46622    if (isHexColorValue(swatch)) return swatch;
46623    const background = element.style.backgroundColor?.trim();
46624    return isHexColorValue(background) ? background : null;
46625  }
46626  function isReadableHexColor(element) {
46627    return element?.isConnected && !element.closest("lexxy-editor");
46628  }
46629  function ensureCopiedIcon(element) {
46630    let icon = element.querySelector(`:scope > .${COPIED_ICON_CLASS}`);
46631    if (icon) return icon;
46632    icon = document.createElement("span");
46633    icon.className = COPIED_ICON_CLASS;
46634    icon.setAttribute("aria-hidden", "true");
46635    icon.innerHTML = COPIED_ICON2;
46636    element.insertBefore(icon, element.firstChild);
46637    return icon;
46638  }
46639  function clearCopiedState(element) {
46640    const timer = copiedResetTimers.get(element);
46641    if (timer) {
46642      clearTimeout(timer);
46643      copiedResetTimers.delete(element);
46644    }
46645    element.classList.remove(COPIED_CLASS);
46646    element.querySelector(`:scope > .${COPIED_ICON_CLASS}`)?.remove();
46647  }
46648  function showCopiedState(element) {
46649    clearCopiedState(element);
46650    ensureCopiedIcon(element);
46651    element.classList.add(COPIED_CLASS);
46652    const timer = setTimeout(() => {
46653      clearCopiedState(element);
46654    }, COPIED_RESET_MS);
46655    copiedResetTimers.set(element, timer);
46656  }
46657  function copyTextToClipboard(text2) {
46658    if (navigator.clipboard?.writeText) {
46659      return navigator.clipboard.writeText(text2).catch(() => copyTextWithTextarea(text2));
46660    }
46661    return copyTextWithTextarea(text2);
46662  }
46663  function copyTextWithTextarea(text2) {
46664    return new Promise((resolve, reject) => {
46665      const textArea = document.createElement("textarea");
46666      textArea.value = text2;
46667      textArea.setAttribute("readonly", "");
46668      textArea.style.position = "fixed";
46669      textArea.style.top = "0";
46670      textArea.style.left = "0";
46671      textArea.style.opacity = "0";
46672      document.body.appendChild(textArea);
46673      textArea.focus();
46674      textArea.select();
46675      try {
46676        const successful = document.execCommand("copy");
46677        document.body.removeChild(textArea);
46678        if (successful) resolve();
46679        else reject(new Error("Copy command failed"));
46680      } catch (error) {
46681        document.body.removeChild(textArea);
46682        reject(error);
46683      }
46684    });
46685  }
46686  function enhanceHexColor(element) {
46687    if (!isReadableHexColor(element)) return;
46688    const color = colorFromElement(element);
46689    if (!color) return;
46690    applyHexColorSwatch(element, color);
46691    element.dataset.lexxyHex = color;
46692    element.setAttribute("role", "button");
46693    element.setAttribute("tabindex", "0");
46694    element.setAttribute("aria-label", `Copy ${color}`);
46695    element.title = `Copy ${color}`;
46696  }
46697  async function handleHexColorActivation(element) {
46698    if (!isReadableHexColor(element)) return;
46699    const color = element.dataset.lexxyHex || colorFromElement(element);
46700    if (!color) return;
46701    try {
46702      await copyTextToClipboard(color);
46703      showCopiedState(element);
46704    } catch (_error) {
46705    }
46706  }
46707  function handleHexColorClick(event) {
46708    const element = event.target.closest?.(`.${HEX_COLOR_CLASS}`);
46709    if (!element || !isReadableHexColor(element)) return;
46710    event.preventDefault();
46711    handleHexColorActivation(element);
46712  }
46713  function handleHexColorKeydown(event) {
46714    if (event.key !== "Enter" && event.key !== " ") return;
46715    const element = event.target.closest?.(`.${HEX_COLOR_CLASS}`);
46716    if (!element || event.target !== element || !isReadableHexColor(element)) return;
46717    event.preventDefault();
46718    handleHexColorActivation(element);
46719  }
46720  function attachHexColorListeners() {
46721    if (clickListenerAttached || typeof document === "undefined") return;
46722    document.addEventListener("click", handleHexColorClick);
46723    document.addEventListener("keydown", handleHexColorKeydown);
46724    clickListenerAttached = true;
46725  }
46726  function hydrateHexColors(root = document) {
46727    queryHexColors(root).forEach(enhanceHexColor);
46728  }
46729  function scheduleHexColorHydration(root = document) {
46730    if (hydrationFrame) cancelAnimationFrame(hydrationFrame);
46731    hydrationFrame = requestAnimationFrame(() => {
46732      hydrationFrame = null;
46733      hydrateHexColors(root);
46734    });
46735  }
46736  function nodeContainsHexColor(node) {
46737    if (!(node instanceof Element) && !(node instanceof DocumentFragment)) return false;
46738    return node instanceof Element && node.classList?.contains(HEX_COLOR_CLASS) || Boolean(node.querySelector?.(`.${HEX_COLOR_CLASS}`));
46739  }
46740  function observeDynamicHexColors() {
46741    if (dynamicContentObserver || !document.documentElement) return;
46742    dynamicContentObserver = new MutationObserver((mutations) => {
46743      const needsHydration2 = mutations.some(
46744        (mutation) => Array.from(mutation.addedNodes).some(nodeContainsHexColor)
46745      );
46746      if (needsHydration2) scheduleHexColorHydration();
46747    });
46748    dynamicContentObserver.observe(document.documentElement, {
46749      childList: true,
46750      subtree: true
46751    });
46752  }
46753  attachHexColorListeners();
46754  observeDynamicHexColors();
46755
46756  
46756// app/javascript/src/twitter_embeds.js
46757  var TWITTER_WIDGETS_SRC = "https://platform.twitter.com/widgets.js";
46758  var twitterWidgetsPromise;
46759  function twitterBlockquotes(root = document) {
46760    const selectors = [
46761      ".trix-content blockquote.twitter-tweet",
46762      ".lexxy-content blockquote.twitter-tweet",
46763      "lexxy-editor blockquote.twitter-tweet",
46764      "action-text-attachment blockquote.twitter-tweet"
46765    ];
46766    if (root === document) {
46767      return document.querySelectorAll(selectors.join(", "));
46768    }
46769    return root.querySelectorAll("blockquote.twitter-tweet");
46770  }
46771  function loadTwitterWidgetsScript() {
46772    if (window.twttr?.widgets) return Promise.resolve(window.twttr);
46773    if (twitterWidgetsPromise) return twitterWidgetsPromise;
46774    twitterWidgetsPromise = new Promise((resolve, reject) => {
46775      const existing = document.getElementById("twitter-wjs");
46776      if (existing) {
46777        if (window.twttr?.widgets) {
46778          resolve(window.twttr);
46779          return;
46780        }
46781        existing.addEventListener("load", () => resolve(window.twttr), { once: true });
46782        return;
46783      }
46784      window.twttr = window.twttr || { _e: [], ready(callback) {
46785        window.twttr._e.push(callback);
46786      } };
46787      const script = document.createElement("script");
46788      script.id = "twitter-wjs";
46789      script.async = true;
46790      script.src = TWITTER_WIDGETS_SRC;
46791      script.charset = "utf-8";
46792      script.onload = () => resolve(window.twttr);
46793      script.onerror = () => {
46794        twitterWidgetsPromise = null;
46795        reject(new Error("Failed to load Twitter widgets"));
46796      };
46797      document.body.appendChild(script);
46798    });
46799    return twitterWidgetsPromise;
46800  }
46801  function renderTwitterEmbeds(root = document) {
46802    const blockquotes = twitterBlockquotes(root);
46803    if (blockquotes.length === 0) return;
46804    loadTwitterWidgetsScript().then((twttr) => {
46805      if (!twttr?.widgets) return;
46806      blockquotes.forEach((blockquote) => {
46807        if (blockquote.closest(".twitter-tweet-rendered")) return;
46808        twttr.widgets.load(blockquote);
46809      });
46810    }).catch(() => {
46811    });
46812  }
46813  function scheduleTwitterEmbeds(root = document) {
46814    requestAnimationFrame(() => {
46815      requestAnimationFrame(() => renderTwitterEmbeds(root));
46816    });
46817  }
46818
46819  
46819// app/javascript/src/instagram_embeds.js
46820  var INSTAGRAM_EMBED_SRC = "https://www.instagram.com/embed.js";
46821  var instagramEmbedPromise;
46822  function instagramBlockquotes(root = document) {
46823    const selectors = [
46824      ".trix-content blockquote.instagram-media",
46825      ".lexxy-content blockquote.instagram-media",
46826      "lexxy-editor blockquote.instagram-media",
46827      "action-text-attachment blockquote.instagram-media"
46828    ];
46829    if (root === document) {
46830      return document.querySelectorAll(selectors.join(", "));
46831    }
46832    return root.querySelectorAll("blockquote.instagram-media");
46833  }
46834  function instagramIframes(root = document) {
46835    const selectors = [
46836      ".trix-content .embed--instagram iframe.instagram-media",
46837      ".trix-content .embed--instagram iframe.instagram-media-rendered",
46838      ".lexxy-content .embed--instagram iframe.instagram-media",
46839      ".lexxy-content .embed--instagram iframe.instagram-media-rendered",
46840      "lexxy-editor .embed--instagram iframe.instagram-media",
46841      "lexxy-editor .embed--instagram iframe.instagram-media-rendered",
46842      "action-text-attachment .embed--instagram iframe.instagram-media",
46843      "action-text-attachment .embed--instagram iframe.instagram-media-rendered"
46844    ];
46845    if (root === document) {
46846      return document.querySelectorAll(selectors.join(", "));
46847    }
46848    return root.querySelectorAll(
46849      ".embed--instagram iframe.instagram-media, .embed--instagram iframe.instagram-media-rendered"
46850    );
46851  }
46852  function loadInstagramEmbedScript() {
46853    if (window.instgrm?.Embeds) return Promise.resolve(window.instgrm);
46854    if (instagramEmbedPromise) return instagramEmbedPromise;
46855    instagramEmbedPromise = new Promise((resolve, reject) => {
46856      const existing = document.getElementById("instagram-embed-js");
46857      if (existing) {
46858        if (window.instgrm?.Embeds) {
46859          resolve(window.instgrm);
46860          return;
46861        }
46862        existing.addEventListener("load", () => resolve(window.instgrm), { once: true });
46863        return;
46864      }
46865      const script = document.createElement("script");
46866      script.id = "instagram-embed-js";
46867      script.async = true;
46868      script.src = INSTAGRAM_EMBED_SRC;
46869      script.onload = () => resolve(window.instgrm);
46870      script.onerror = () => {
46871        instagramEmbedPromise = null;
46872        reject(new Error("Failed to load Instagram embed script"));
46873      };
46874      document.body.appendChild(script);
46875    });
46876    return instagramEmbedPromise;
46877  }
46878  function syncInstagramIframeHeight(iframe) {
46879    const height = Number.parseInt(iframe.getAttribute("height"), 10);
46880    if (!Number.isFinite(height) || height <= 0) return;
46881    iframe.style.height = `${height}px`;
46882  }
46883  function watchInstagramIframeHeight(iframe) {
46884    if (iframe.dataset.instagramHeightWatched === "true") {
46885      syncInstagramIframeHeight(iframe);
46886      return;
46887    }
46888    iframe.dataset.instagramHeightWatched = "true";
46889    syncInstagramIframeHeight(iframe);
46890    new MutationObserver(() => syncInstagramIframeHeight(iframe)).observe(iframe, {
46891      attributes: true,
46892      attributeFilter: ["height"]
46893    });
46894  }
46895  function syncInstagramIframeHeights(root = document) {
46896    instagramIframes(root).forEach(watchInstagramIframeHeight);
46897  }
46898  function renderInstagramEmbeds(root = document) {
46899    const blockquotes = instagramBlockquotes(root);
46900    const afterProcess = () => {
46901      requestAnimationFrame(() => {
46902        syncInstagramIframeHeights(root);
46903      });
46904    };
46905    if (blockquotes.length > 0) {
46906      loadInstagramEmbedScript().then((instgrm) => {
46907        if (!instgrm?.Embeds) return;
46908        instgrm.Embeds.process(root === document ? void 0 : root);
46909        afterProcess();
46910      }).catch(() => {
46911      });
46912      return;
46913    }
46914    syncInstagramIframeHeights(root);
46915  }
46916  function scheduleInstagramEmbeds(root = document) {
46917    requestAnimationFrame(() => {
46918      requestAnimationFrame(() => renderInstagramEmbeds(root));
46919    });
46920  }
46921
46922  
46922// app/javascript/src/tiktok_embeds.js
46923  var TIKTOK_EMBED_SRC = "https://www.tiktok.com/embed.js";
46924  var tiktokEmbedPromise;
46925  function tiktokBlockquotes(root = document) {
46926    const selectors = [
46927      ".trix-content blockquote.tiktok-embed",
46928      ".lexxy-content blockquote.tiktok-embed",
46929      "lexxy-editor blockquote.tiktok-embed",
46930      "action-text-attachment blockquote.tiktok-embed"
46931    ];
46932    if (root === document) {
46933      return document.querySelectorAll(selectors.join(", "));
46934    }
46935    return root.querySelectorAll("blockquote.tiktok-embed");
46936  }
46937  function loadTikTokEmbedScript() {
46938    if (window.tiktokEmbed?.lib) return Promise.resolve(window.tiktokEmbed);
46939    if (tiktokEmbedPromise) return tiktokEmbedPromise;
46940    tiktokEmbedPromise = new Promise((resolve, reject) => {
46941      const existing = document.getElementById("tiktok-embed-js");
46942      if (existing) {
46943        if (window.tiktokEmbed?.lib) {
46944          resolve(window.tiktokEmbed);
46945          return;
46946        }
46947        existing.addEventListener("load", () => resolve(window.tiktokEmbed), { once: true });
46948        return;
46949      }
46950      const script = document.createElement("script");
46951      script.id = "tiktok-embed-js";
46952      script.async = true;
46953      script.src = TIKTOK_EMBED_SRC;
46954      script.onload = () => resolve(window.tiktokEmbed);
46955      script.onerror = () => {
46956        tiktokEmbedPromise = null;
46957        reject(new Error("Failed to load TikTok embed script"));
46958      };
46959      document.body.appendChild(script);
46960    });
46961    return tiktokEmbedPromise;
46962  }
46963  function syncTikTokIframeHeight(iframe) {
46964    const inlineHeight = iframe.style.height?.replace("px", "");
46965    const attributeHeight = iframe.getAttribute("height");
46966    const height = Number.parseInt(inlineHeight || attributeHeight, 10);
46967    if (Number.isFinite(height) && height > 0) {
46968      iframe.style.height = `${height}px`;
46969    }
46970  }
46971  function renderTikTokBlockquote(blockquote, tiktokEmbed) {
46972    if (blockquote.querySelector("iframe")) {
46973      syncTikTokIframeHeight(blockquote.querySelector("iframe"));
46974      return;
46975    }
46976    if (tiktokEmbed?.lib?.render) {
46977      tiktokEmbed.lib.render(blockquote);
46978      requestAnimationFrame(() => {
46979        const iframe = blockquote.querySelector("iframe");
46980        if (iframe) syncTikTokIframeHeight(iframe);
46981      });
46982    }
46983  }
46984  function renderTikTokEmbeds(root = document) {
46985    const blockquotes = tiktokBlockquotes(root);
46986    if (blockquotes.length === 0) return;
46987    loadTikTokEmbedScript().then((tiktokEmbed) => {
46988      blockquotes.forEach((blockquote) => renderTikTokBlockquote(blockquote, tiktokEmbed));
46989    }).catch(() => {
46990    });
46991  }
46992  function scheduleTikTokEmbeds(root = document) {
46993    requestAnimationFrame(() => {
46994      requestAnimationFrame(() => renderTikTokEmbeds(root));
46995    });
46996  }
46997
46998  
46998// app/javascript/src/facebook_embeds.js
46999  var FACEBOOK_SDK_SRC = "https://connect.facebook.net/en_US/sdk.js";
47000  var facebookSdkPromise;
47001  function facebookEmbeds(root = document) {
47002    const selectors = [
47003      ".trix-content .fb-video",
47004      ".trix-content .fb-post",
47005      ".lexxy-content .fb-video",
47006      ".lexxy-content .fb-post",
47007      "lexxy-editor .fb-video",
47008      "lexxy-editor .fb-post",
47009      "action-text-attachment .fb-video",
47010      "action-text-attachment .fb-post"
47011    ];
47012    if (root === document) {
47013      return document.querySelectorAll(selectors.join(", "));
47014    }
47015    return root.querySelectorAll(".fb-video, .fb-post");
47016  }
47017  function ensureFbRoot() {
47018    if (document.getElementById("fb-root")) return;
47019    const root = document.createElement("div");
47020    root.id = "fb-root";
47021    document.body.appendChild(root);
47022  }
47023  function loadFacebookSdk() {
47024    if (window.FB?.XFBML) return Promise.resolve(window.FB);
47025    if (facebookSdkPromise) return facebookSdkPromise;
47026    facebookSdkPromise = new Promise((resolve, reject) => {
47027      const existing = document.getElementById("facebook-jssdk");
47028      if (existing) {
47029        if (window.FB?.XFBML) {
47030          resolve(window.FB);
47031          return;
47032        }
47033        existing.addEventListener("load", () => resolve(window.FB), { once: true });
47034        return;
47035      }
47036      window.fbAsyncInit = () => {
47037        window.FB.init({ xfbml: true, version: "v25.0" });
47038        resolve(window.FB);
47039      };
47040      const script = document.createElement("script");
47041      script.id = "facebook-jssdk";
47042      script.async = true;
47043      script.defer = true;
47044      script.crossOrigin = "anonymous";
47045      script.src = `${FACEBOOK_SDK_SRC}#xfbml=1&version=v25.0`;
47046      script.onerror = () => {
47047        facebookSdkPromise = null;
47048        reject(new Error("Failed to load Facebook SDK"));
47049      };
47050      document.body.appendChild(script);
47051    });
47052    return facebookSdkPromise;
47053  }
47054  function renderFacebookEmbeds(root = document) {
47055    const embeds = facebookEmbeds(root);
47056    if (embeds.length === 0) return;
47057    ensureFbRoot();
47058    loadFacebookSdk().then((FB) => {
47059      if (!FB?.XFBML) return;
47060      FB.XFBML.parse(root === document ? void 0 : root);
47061    }).catch(() => {
47062    });
47063  }
47064  function scheduleFacebookEmbeds(root = document) {
47065    requestAnimationFrame(() => {
47066      requestAnimationFrame(() => renderFacebookEmbeds(root));
47067    });
47068  }
47069
47070  
47070// app/javascript/src/airtable_embeds.js
47071  var AIRTABLE_EMBED_HEIGHT = "533px";
47072  function airtableContainers(root = document) {
47073    const selectors = [
47074      ".trix-content [data-airtable-embed-url]",
47075      ".lexxy-content [data-airtable-embed-url]",
47076      "lexxy-editor [data-airtable-embed-url]",
47077      "action-text-attachment [data-airtable-embed-url]"
47078    ];
47079    if (root === document) {
47080      return document.querySelectorAll(selectors.join(", "));
47081    }
47082    return root.querySelectorAll("[data-airtable-embed-url]");
47083  }
47084  function hydrateAirtableEmbed(container) {
47085    if (container.querySelector("iframe")) return;
47086    const url = container.dataset.airtableEmbedUrl?.trim();
47087    if (!url) return;
47088    container.style.left = "0";
47089    container.style.width = "100%";
47090    container.style.height = AIRTABLE_EMBED_HEIGHT;
47091    container.style.position = "relative";
47092    const iframe = document.createElement("iframe");
47093    iframe.src = url;
47094    iframe.style.top = "0";
47095    iframe.style.left = "0";
47096    iframe.style.width = "100%";
47097    iframe.style.height = "100%";
47098    iframe.style.position = "absolute";
47099    iframe.style.border = "0";
47100    iframe.setAttribute("allowfullscreen", "");
47101    container.appendChild(iframe);
47102  }
47103  function renderAirtableEmbeds(root = document) {
47104    airtableContainers(root).forEach(hydrateAirtableEmbed);
47105  }
47106  function scheduleAirtableEmbeds(root = document) {
47107    requestAnimationFrame(() => {
47108      requestAnimationFrame(() => renderAirtableEmbeds(root));
47109    });
47110  }
47111
47112  
47112// app/javascript/src/responsive_embeds.js
47113  function responsiveEmbedContainers(root = document) {
47114    const selectors = [
47115      ".trix-content [data-responsive-embed-url]",
47116      ".lexxy-content [data-responsive-embed-url]",
47117      "lexxy-editor [data-responsive-embed-url]",
47118      "action-text-attachment [data-responsive-embed-url]"
47119    ];
47120    if (root === document) {
47121      return document.querySelectorAll(selectors.join(", "));
47122    }
47123    return root.querySelectorAll("[data-responsive-embed-url]");
47124  }
47125  function hydrateResponsiveEmbed(container) {
47126    if (container.querySelector("iframe")) return;
47127    const url = container.dataset.responsiveEmbedUrl?.trim();
47128    if (!url) return;
47129    container.style.left = "0";
47130    container.style.width = "100%";
47131    container.style.position = "relative";
47132    const height = parseInt(container.dataset.responsiveEmbedHeight, 10);
47133    if (height > 0) {
47134      container.style.height = `${height}px`;
47135      container.style.paddingBottom = "0";
47136    } else {
47137      container.style.height = "0";
47138      container.style.paddingBottom = "56.25%";
47139    }
47140    const iframe = document.createElement("iframe");
47141    iframe.src = url;
47142    iframe.style.top = "0";
47143    iframe.style.left = "0";
47144    iframe.style.width = "100%";
47145    iframe.style.height = "100%";
47146    iframe.style.position = "absolute";
47147    iframe.style.border = "0";
47148    iframe.setAttribute("scrolling", "no");
47149    const allow = container.dataset.responsiveEmbedAllow?.trim();
47150    if (allow) {
47151      iframe.setAttribute("allow", allow);
47152    } else {
47153      iframe.setAttribute("allowfullscreen", "");
47154    }
47155    container.appendChild(iframe);
47156  }
47157  function renderResponsiveEmbeds(root = document) {
47158    responsiveEmbedContainers(root).forEach(hydrateResponsiveEmbed);
47159  }
47160  function scheduleResponsiveEmbeds(root = document) {
47161    requestAnimationFrame(() => {
47162      requestAnimationFrame(() => renderResponsiveEmbeds(root));
47163    });
47164  }
47165
47166  
47166// app/javascript/src/embed_provider_icons.data.json
47167  var embed_provider_icons_data_default = {
47168    icons: {
47169      youtube: {
47170        label: "YouTube",
47171        viewBox: "0 0 32 32",
47172        markup: '<path fill="red" d="M31.33 8.498a4.007 4.007 0 0 0-2.828-2.829C26.007 5 16 5 16 5S5.993 5 3.498 5.67A4.007 4.007 0 0 0 .67 8.497C0 10.993 0 16.201 0 16.201s0 5.207.67 7.702a4.007 4.007 0 0 0 2.828 2.829C5.993 27.4 16 27.4 16 27.4s10.007 0 12.502-.67a4.007 4.007 0 0 0 2.829-2.828C32 21.408 32 16.2 32 16.2s-.003-5.208-.67-7.703Z"/><path fill="#fff" d="m12.797 21 8.313-4.799-8.313-4.8v9.6Z"/>'
47173      },
47174      vimeo: {
47175        label: "Vimeo",
47176        viewBox: "0 0 32 32",
47177        markup: '<path fill="#1AB7EA" d="M28.8 0H3.2A3.2 3.2 0 0 0 0 3.2v25.6A3.2 3.2 0 0 0 3.2 32h25.6a3.2 3.2 0 0 0 3.2-3.2V3.2A3.2 3.2 0 0 0 28.8 0Z"/><path fill="#fff" d="M26.925 10.627c-.104 2.25-1.674 5.333-4.717 9.245C19.064 23.957 16.403 26 14.229 26c-1.349 0-2.488-1.243-3.421-3.733-.621-2.28-1.243-4.563-1.867-6.843-.693-2.488-1.434-3.733-2.229-3.733-.173 0-.779.365-1.816 1.088l-1.088-1.4A295.481 295.481 0 0 0 7.181 8.37c1.523-1.315 2.667-2.006 3.427-2.078 1.8-.173 2.907 1.056 3.323 3.691.45 2.84.76 4.608.936 5.299.52 2.357 1.09 3.533 1.714 3.533.483 0 1.211-.765 2.182-2.293.968-1.528 1.485-2.691 1.557-3.491.139-1.32-.381-1.981-1.557-1.981-.555 0-1.126.128-1.712.378 1.136-3.722 3.309-5.53 6.512-5.426 2.376.069 3.496 1.61 3.36 4.621l.002.003Z"/>'
47178      },
47179      spotify: {
47180        label: "Spotify",
47181        viewBox: "0 0 32 32",
47182        markup: '<path fill="#1ED760" d="M16 0C7.164 0 0 7.164 0 16c0 8.837 7.164 16 16 16 8.838 0 16-7.163 16-16 0-8.836-7.162-16-16-16Zm7.338 23.077a.997.997 0 0 1-1.372.33c-3.757-2.294-8.486-2.814-14.055-1.542a.998.998 0 0 1-.444-1.945c6.095-1.392 11.323-.793 15.54 1.785.47.288.62.902.33 1.372Zm1.958-4.357a1.248 1.248 0 0 1-1.715.411c-4.301-2.643-10.857-3.409-15.944-1.865a1.25 1.25 0 0 1-1.557-.83 1.25 1.25 0 0 1 .832-1.557c5.81-1.763 13.035-.909 17.974 2.126.586.361.771 1.13.41 1.715Zm.169-4.536c-5.157-3.063-13.665-3.345-18.589-1.85a1.496 1.496 0 1 1-.869-2.865c5.652-1.716 15.048-1.384 20.985 2.14a1.496 1.496 0 1 1-1.527 2.574Z"/>'
47183      },
47184      soundcloud: {
47185        label: "SoundCloud",
47186        viewBox: "0 0 32 32",
47187        markup: '<path fill="#F50" fill-rule="evenodd" d="M31.997 18.07a4.48 4.48 0 0 1-4.535 4.23H16.558a.915.915 0 0 1-.905-.909V9.651a1 1 0 0 1 .603-.956S17.258 8 19.37 8a7.145 7.145 0 0 1 3.666 1.007 7.254 7.254 0 0 1 3.413 4.728 4.212 4.212 0 0 1 1.157-.158 4.365 4.365 0 0 1 4.391 4.494Zm-17.705-7.676c.33 3.982.568 7.613 0 11.582a.354.354 0 0 1-.704 0c-.529-3.935-.298-7.635 0-11.582a.353.353 0 0 1 .54-.339.354.354 0 0 1 .164.339ZM12.086 21.98a.37.37 0 0 1-.734 0 44.265 44.265 0 0 1 0-10.22.372.372 0 0 1 .739 0 39.77 39.77 0 0 1-.005 10.22Zm-2.21-10.566c.358 3.649.52 6.917-.004 10.557a.355.355 0 0 1-.709 0c-.508-3.593-.337-6.955 0-10.557a.357.357 0 0 1 .356-.319c.183 0 .337.137.356.32ZM7.66 21.984a.364.364 0 0 1-.721 0 37.382 37.382 0 0 1 0-9.542.366.366 0 1 1 .734 0 34.87 34.87 0 0 1-.013 9.543Zm-2.21-7.156c.558 2.475.306 4.66-.022 7.182a.346.346 0 0 1-.683 0c-.299-2.488-.546-4.724-.021-7.183a.363.363 0 0 1 .725.001Zm-2.207-.376c.512 2.535.346 4.682-.013 7.225-.042.376-.686.38-.72 0-.325-2.505-.479-4.716-.014-7.225a.376.376 0 0 1 .747 0Zm-2.227 1.23c.537 1.68.354 3.047-.022 4.77a.35.35 0 0 1-.696 0c-.324-1.69-.455-3.085-.029-4.77a.375.375 0 0 1 .747 0Z" clip-rule="evenodd"/>'
47188      },
47189      x: {
47190        label: "\u{1D54F} (Twitter)",
47191        viewBox: "0 0 32 32",
47192        themeAdaptive: true,
47193        markup: '<path fill="currentColor" d="M25.2 2h4.91L19.39 14.25 32 30.92h-9.87L14.4 20.81 5.55 30.92H.63L12.1 17.81 0 2h10.13l6.99 9.24L25.2 2Zm-1.72 25.99h2.72L8.65 4.78H5.73l17.75 23.21Z"/>'
47194      },
47195      instagram: {
47196        label: "Instagram",
47197        viewBox: "0 0 32 32",
47198        markup: '<path fill="url(#instagram-a-{id})" d="M16.008.242C9.428.242 7.504.25 7.13.28c-1.35.112-2.19.325-3.106.78a6.292 6.292 0 0 0-1.81 1.326C1.213 3.424.606 4.702.387 6.22.28 6.957.25 7.107.244 10.87c-.003 1.255 0 2.906 0 5.121 0 6.575.007 8.497.038 8.87.11 1.315.316 2.141.752 3.046a6.64 6.64 0 0 0 4.303 3.515c.65.167 1.367.26 2.288.303.39.017 4.369.029 8.35.029 3.98 0 7.96-.005 8.341-.024 1.067-.05 1.686-.134 2.371-.31a6.599 6.599 0 0 0 4.303-3.523c.428-.883.645-1.74.743-2.986.022-.271.03-4.6.03-8.924 0-4.323-.01-8.644-.03-8.916-.1-1.265-.317-2.116-.759-3.016a6.247 6.247 0 0 0-1.349-1.848C28.583 1.212 27.308.606 25.788.387c-.736-.107-.883-.138-4.65-.145h-5.13Z"/><path fill="url(#instagram-b-{id})" d="M16.008.242C9.428.242 7.504.25 7.13.28c-1.35.112-2.19.325-3.106.78a6.292 6.292 0 0 0-1.81 1.326C1.213 3.424.606 4.702.387 6.22.28 6.957.25 7.107.244 10.87c-.003 1.255 0 2.906 0 5.121 0 6.575.007 8.497.038 8.87.11 1.315.316 2.141.752 3.046a6.64 6.64 0 0 0 4.303 3.515c.65.167 1.367.26 2.288.303.39.017 4.369.029 8.35.029 3.98 0 7.96-.005 8.341-.024 1.067-.05 1.686-.134 2.371-.31a6.599 6.599 0 0 0 4.303-3.523c.428-.883.645-1.74.743-2.986.022-.271.03-4.6.03-8.924 0-4.323-.01-8.644-.03-8.916-.1-1.265-.317-2.116-.759-3.016a6.247 6.247 0 0 0-1.349-1.848C28.583 1.212 27.308.606 25.788.387c-.736-.107-.883-.138-4.65-.145h-5.13Z"/><path fill="#fff" d="M16.001 4.364c-3.16 0-3.557.013-4.798.07-1.239.057-2.084.253-2.824.54a5.698 5.698 0 0 0-2.062 1.342 5.712 5.712 0 0 0-1.343 2.061c-.288.74-.485 1.586-.54 2.825-.056 1.24-.07 1.638-.07 4.798s.014 3.556.07 4.797c.057 1.239.253 2.084.54 2.824a5.702 5.702 0 0 0 1.343 2.061 5.697 5.697 0 0 0 2.06 1.344c.74.287 1.586.483 2.825.54 1.241.057 1.637.07 4.797.07 3.161 0 3.556-.013 4.798-.07 1.238-.057 2.085-.253 2.825-.54a5.693 5.693 0 0 0 2.06-1.344 5.712 5.712 0 0 0 1.343-2.06c.286-.74.483-1.587.54-2.825.057-1.241.071-1.637.071-4.797 0-3.16-.014-3.557-.07-4.798-.058-1.239-.255-2.084-.54-2.824a5.71 5.71 0 0 0-1.344-2.062 5.688 5.688 0 0 0-2.06-1.341c-.742-.288-1.588-.484-2.827-.541-1.241-.057-1.637-.07-4.798-.07h.004ZM14.957 6.46h1.044c3.107 0 3.475.01 4.702.067 1.135.051 1.75.241 2.16.4.544.211.93.463 1.338.87.407.408.66.796.87 1.339.16.41.35 1.025.401 2.16.056 1.226.068 1.595.068 4.7 0 3.106-.012 3.474-.068 4.701-.052 1.134-.241 1.75-.4 2.16-.211.543-.464.93-.871 1.337-.407.407-.794.66-1.338.87-.41.16-1.025.35-2.16.401-1.227.056-1.595.068-4.702.068s-3.475-.012-4.702-.068c-1.135-.052-1.75-.242-2.16-.401a3.604 3.604 0 0 1-1.339-.87 3.606 3.606 0 0 1-.87-1.338c-.16-.41-.35-1.026-.402-2.16-.055-1.227-.066-1.595-.066-4.703 0-3.107.01-3.473.066-4.7.052-1.135.242-1.75.401-2.16.211-.544.464-.932.871-1.339.407-.407.795-.66 1.338-.87.41-.16 1.026-.35 2.16-.402 1.074-.048 1.49-.063 3.66-.065v.003Zm7.255 1.932a1.396 1.396 0 1 0 0 2.793 1.396 1.396 0 0 0 0-2.794Zm-6.211 1.631a5.976 5.976 0 1 0 0 11.952 5.976 5.976 0 0 0 0-11.952Zm0 2.097a3.879 3.879 0 1 1 0 7.758 3.879 3.879 0 0 1 0-7.758Z"/><defs><radialGradient id="instagram-a-{id}" cx="0" cy="0" r="1" gradientTransform="matrix(0 -31.2312 29.0554 0 8.615 34.182)" gradientUnits="userSpaceOnUse"><stop stop-color="#FD5"/><stop offset=".1" stop-color="#FD5"/><stop offset=".5" stop-color="#FF543E"/><stop offset="1" stop-color="#C837AB"/></radialGradient><radialGradient id="instagram-b-{id}" cx="0" cy="0" r="1" gradientTransform="rotate(78.678 -4.051 -1.817) scale(13.9606 57.5608)" gradientUnits="userSpaceOnUse"><stop stop-color="#3771C8"/><stop offset=".128" stop-color="#3771C8"/><stop offset="1" stop-color="#60F" stop-opacity="0"/></radialGradient></defs>'
47199      },
47200      gumlet: {
47201        label: "Gumlet",
47202        viewBox: "0 0 32 32",
47203        markup: '<path fill="#104A70" d="m12.21 21.434-5.468 7.691c2.43 1.668 5.206 2.732 8.352 2.875v-9.535c-1.095-.121-1.998-.47-2.883-1.031Z"/><path fill="#ED7324" d="M15.094 9.468 15.031 0c-3.108.15-5.87 1.154-8.289 2.82l5.457 7.645a6.613 6.613 0 0 1 2.895-.997Z"/><path fill="#FBBC05" d="M24.553 2.647C22.104.972 19.227.094 16.06 0L16 9.456c1.088.078 2.119.365 2.998.909l5.555-7.718Z"/><path fill="#0F1E2A" d="M9.726 18.415.806 21.362c1.042 2.909 2.821 5.358 5.207 7.217l5.56-7.63a6.648 6.648 0 0 1-1.845-2.534Z"/><path fill="#DF5216" d="m11.572 10.91-5.49-7.59c-1.603 1.256-2.91 2.783-3.944 4.553a15.686 15.686 0 0 0-1.232 2.701l8.867 2.91c.402-.992 1.002-1.89 1.8-2.574Z"/><path fill="#D53C0D" d="M9.34 15.972a6.59 6.59 0 0 1 .166-1.631L.64 11.47A15.759 15.759 0 0 0 0 15.9c0 1.565.178 2.998.593 4.428L9.56 17.5a6.913 6.913 0 0 1-.22-1.528Z"/><path fill="#378A9B" d="m19.824 21.061 5.559 7.618c2.381-1.863 4.273-4.341 5.309-7.253l-8.937-2.91a6.768 6.768 0 0 1-1.931 2.545Z"/><path fill="#1D77B2" d="M16 22.493V32c3.155-.098 6.113-1.03 8.553-2.695l-5.58-7.67c-.886.535-1.889.791-2.973.858Z"/><path fill="#539E82" d="m30.924 11.371-10.698 3.293c.12.52.168.776.166 1.235-.001.459-.057.702-.166 1.224l10.736 3.305c.42-1.431.636-2.965.636-4.529 0-1.571-.235-3.066-.674-4.528Z"/>'
47204      },
47205      tiktok: {
47206        label: "TikTok",
47207        viewBox: "0 0 32 32",
47208        themeAdaptive: true,
47209        markup: '<path fill="#FF004F" d="M22.987 11.551a12.568 12.568 0 0 0 7.331 2.345V8.638a7.426 7.426 0 0 1-1.54-.16v4.138a12.57 12.57 0 0 1-7.33-2.345v10.73c0 5.368-4.354 9.719-9.724 9.719a9.68 9.68 0 0 1-5.413-1.644A9.697 9.697 0 0 0 13.263 32c5.37 0 9.725-4.351 9.725-9.719v-10.73Zm1.9-5.304a7.328 7.328 0 0 1-1.9-4.29V1.28h-1.459a7.36 7.36 0 0 0 3.359 4.967Zm-15.18 18.71a4.447 4.447 0 0 1 4.89-6.929v-5.375c-.51-.07-1.024-.1-1.539-.089v4.184a4.447 4.447 0 0 0-3.351 8.209Z"/><path fill="currentColor" d="M21.448 10.271a12.57 12.57 0 0 0 7.33 2.345V8.477a7.36 7.36 0 0 1-3.891-2.23 7.361 7.361 0 0 1-3.359-4.967h-3.832v21a4.447 4.447 0 0 1-7.989 2.677 4.445 4.445 0 0 1 2.001-8.417c.471 0 .925.074 1.35.209v-4.184c-5.276.109-9.519 4.417-9.519 9.716a9.683 9.683 0 0 0 2.772 6.795 9.682 9.682 0 0 0 5.413 1.644c5.37 0 9.724-4.351 9.724-9.719v-10.73Z"/><path fill="#00F2EA" d="M28.779 8.477V7.358a7.333 7.333 0 0 1-3.892-1.111 7.353 7.353 0 0 0 3.892 2.23Zm-7.25-7.197a7.483 7.483 0 0 1-.081-.604V0h-5.292v21.001a4.447 4.447 0 0 1-6.449 3.956 4.447 4.447 0 0 0 7.989-2.676V1.28h3.832Zm-8.47 11.285v-1.192a9.824 9.824 0 0 0-1.335-.09C6.354 11.283 2 15.633 2 21a9.708 9.708 0 0 0 4.311 8.075 9.683 9.683 0 0 1-2.771-6.795c0-5.299 4.242-9.607 9.518-9.716Z"/>'
47210      },
47211      facebook: {
47212        label: "Facebook",
47213        viewBox: "0 0 32 32",
47214        markup: '<path fill="#0766FF" d="M17.939 31.884C25.86 30.925 32 24.18 32 16c0-8.836-7.164-16-16-16S0 7.164 0 16c0 7.504 5.165 13.8 12.135 15.53l.31-1.308h4.888l.606 1.662Z"/><path fill="#fff" d="M12.134 31.53V20.89H8.832V16h3.302v-2.107c0-5.446 2.464-7.968 7.808-7.968 1.012 0 2.758.199 3.476.397v4.43c-.378-.04-1.038-.059-1.85-.059-2.624 0-3.636.992-3.636 3.578V16h5.23l-.896 4.889H17.94v10.995c-1.94.234-3.907.114-5.805-.354Z"/>'
47215      },
47216      loom: {
47217        label: "Loom",
47218        viewBox: "0 0 32 32",
47219        markup: '<path fill="#625DF5" d="M32 14.325h-9.748l8.442-4.874-1.674-2.902-8.443 4.875 4.873-8.443-2.9-1.674-4.875 8.44V0h-3.35v9.748L9.45 1.307 6.549 2.98l4.873 8.44-8.44-4.872-1.676 2.902 8.442 4.874H0v3.35h9.747l-8.44 4.875 1.673 2.902 8.443-4.875L6.55 29.02l2.9 1.674 4.876-8.441V32h3.35v-9.956l4.964 8.597 2.72-1.57-4.965-8.6 8.623 4.98 1.676-2.902-8.441-4.874h9.747l.001-3.35Zm-16 6.23a4.554 4.554 0 0 1-3.221-7.777 4.552 4.552 0 0 1 7.775 3.22A4.557 4.557 0 0 1 16 20.555Z"/>'
47220      },
47221      airtable: {
47222        label: "Airtable",
47223        viewBox: "0 0 32 32",
47224        markup: '<path fill="#FCB400" d="M14.29 3.338 2.358 8.275c-.664.274-.657 1.217.01 1.481l11.981 4.751a4.445 4.445 0 0 0 3.277 0l11.98-4.75a.8.8 0 0 0 .012-1.482l-11.93-4.937a4.446 4.446 0 0 0-3.4 0"/><path fill="#18BFFF" d="M17.052 17.101V28.97a.8.8 0 0 0 1.094.743l13.35-5.182a.799.799 0 0 0 .504-.743V11.92a.8.8 0 0 0-1.094-.743l-13.35 5.181a.8.8 0 0 0-.504.743Z"/><path fill="#F82B60" d="m13.934 17.714-3.962 1.913-.402.194-8.363 4.007c-.53.256-1.207-.13-1.207-.72V11.97c0-.213.11-.396.256-.535a.909.909 0 0 1 .202-.152c.2-.12.485-.152.727-.056l12.683 5.025c.644.256.695 1.16.066 1.463Z"/><path fill="#000" fill-opacity=".25" d="m13.934 17.714-3.962 1.913-9.716-8.193c.06-.06.128-.11.202-.152.2-.12.485-.152.727-.056l12.683 5.025c.644.256.695 1.16.066 1.463Z"/>'
47225      },
47226      wistia: {
47227        label: "Wistia",
47228        viewBox: "0 0 32 32",
47229        markup: '<path fill="#1E64F0" d="M19.275 28.147c-4.328 1.196-14.082.62-15.644.62H0l5.968-6.72c1.616-1.827 2.446-2.204 4.251-2.204 1.805 0 5.979.177 8.248-.044 4.207-.41 7.485-1.461 9.057-2.458 3.698-2.336 4.44-3.809 4.44-3.809s1.372 10.75-12.689 14.615ZM31.587 9.259C32.262 5.129 29.937 4 29.937 4s.1 3.355-6.078 4.074C18.379 8.705 0 8.23 0 8.23l5.912 6.776c1.606 1.838 2.447 2.048 4.252 2.181 1.793.122 5.768.078 8.458-.122 2.945-.221 7.13-1.184 9.965-3.377 1.45-1.129 2.723-2.69 3-4.406V9.26Z"/>'
47230      },
47231      genially: {
47232        label: "Genially",
47233        viewBox: "0 0 32 33",
47234        markup: '<path fill="url(#genially-a-{id})" d="M30.017 8.234C27.164 3.131 21.841.003 16.024.003v16.023l13.993-7.792Z"/><path fill="url(#genially-b-{id})" d="M29.743 24.258a16.079 16.079 0 0 0 .11-16.243l-13.829 8.011 13.719 8.232Z"/><path fill="url(#genially-c-{id})" d="M15.75 32.05a16.007 16.007 0 0 0 14.157-8.012l-13.883-8.012-.274 16.024Z"/><path fill="url(#genially-d-{id})" d="M2.031 23.764c2.799 5.103 8.176 8.23 13.993 8.286V16.026L2.031 23.764Z"/><path fill="url(#genially-e-{id})" d="M2.305 7.795a15.951 15.951 0 0 0-.164 16.243l13.883-8.012-13.719-8.23Z"/><path fill="url(#genially-f-{id})" d="M16.299.003A16.006 16.006 0 0 0 2.14 8.015l13.883 8.011.274-16.023Z"/><path fill="#000F33" d="M16.024 28.702c7.001 0 12.676-5.675 12.676-12.676 0-7-5.675-12.676-12.676-12.676-7 0-12.676 5.675-12.676 12.676s5.675 12.676 12.676 12.676Z"/><path fill="#fff" d="M24.09 15.807c-.767 0-1.371.548-1.536 1.262-.713 3.457-4.06 5.707-7.518 4.994-3.457-.714-5.707-4.061-4.993-7.518.713-3.457 4.06-5.707 7.518-4.994.274.055.548.11.823.22.658.274 1.481 0 1.81-.659l.056-.11c.439-.713.164-1.646-.55-2.085-.109-.055-.164-.11-.274-.11C14.488 5.051 9 7.63 7.244 12.624c-1.756 4.939.823 10.426 5.817 12.182 4.939 1.756 10.426-.823 12.182-5.817.165-.439.274-.878.384-1.371.165-.823-.439-1.647-1.262-1.811-.055.055-.164 0-.274 0Z"/><path fill="#fff" d="M18.603 14.874c-1.152 0-2.03.933-2.03 2.03 0 1.153.933 2.03 2.03 2.03 1.153 0 2.03-.932 2.03-2.03.056-1.097-.877-2.03-2.03-2.03Z"/><defs><linearGradient id="genially-a-{id}" x1="15.45" x2="24.164" y1="6.452" y2="11.479" gradientUnits="userSpaceOnUse"><stop stop-color="#F3B444"/><stop offset="1" stop-color="#F15480"/></linearGradient><linearGradient id="genially-b-{id}" x1="24.026" x2="24.026" y1="21.053" y2="11.428" gradientUnits="userSpaceOnUse"><stop stop-color="#B157CE"/><stop offset="1" stop-color="#F15480"/></linearGradient><linearGradient id="genially-c-{id}" x1="15.658" x2="24.246" y1="25.479" y2="20.518" gradientUnits="userSpaceOnUse"><stop stop-color="#5DA5FB"/><stop offset="1" stop-color="#B157CE"/></linearGradient><linearGradient id="genially-d-{id}" x1="7.646" x2="16.03" y1="20.437" y2="25.282" gradientUnits="userSpaceOnUse"><stop stop-color="#74E6A7"/><stop offset="1" stop-color="#5DA5FB"/></linearGradient><linearGradient id="genially-e-{id}" x1="8.003" x2="8.003" y1="11.055" y2="20.685" gradientUnits="userSpaceOnUse"><stop stop-color="#C8ED5C"/><stop offset="1" stop-color="#74E6A7"/></linearGradient><linearGradient id="genially-f-{id}" x1="8.099" x2="16.144" y1="11.343" y2="6.695" gradientUnits="userSpaceOnUse"><stop stop-color="#C8ED5C"/><stop offset="1" stop-color="#F3B444"/></linearGradient></defs>'
47235      },
47236      excalidraw: {
47237        label: "Excalidraw",
47238        viewBox: "0 0 32 32",
47239        markup: '<path fill="#6965DB" d="M31.924 26.365a.262.262 0 0 0-.224-.045c-1.68-2.473-3.83-4.814-5.892-7.087l-.336-.378a.17.17 0 0 0-.045-.112.469.469 0 0 0-.134-.089l-.067-.067-.045-.044c-.067-.134-.225-.223-.381-.134-.628.313-1.21.78-1.77 1.226-.738.579-1.478 1.159-2.173 1.805a6.747 6.747 0 0 0-.784.825c-.112.155-.022.29.113.356-.494.49-.987.981-1.479 1.493a.253.253 0 0 0-.067.179c0 .066.045.133.089.155l.874.669v.022c1.232 1.226 3.405 2.898 5.713 4.703.335.268.694.535 1.03.802.156.179.313.38.448.558.067.088.224.111.313.044.045.045.113.089.158.134a.32.32 0 0 0 .134.045.205.205 0 0 0 .18-.09.317.317 0 0 0 .043-.133c.024 0 .023.022.045.022a.255.255 0 0 0 .18-.067l4.077-4.436a.248.248 0 0 0 0-.356Zm-11.738-1.538a.39.39 0 0 0 .089.112c.47.402.963.803 1.479 1.248l-2.062-1.56-.201-.134c-.045-.022-.09-.067-.135-.089l-.156-.134.045-.045.044-.044.09-.089c.694-.69 1.882-1.85 2.487-2.43-.65.647-1.95 2.542-1.681 3.165Zm7.034 5.528-1.703-1.293a35.927 35.927 0 0 0-2.106-2.006c.919.69 1.703 1.293 1.815 1.404.896.78.85.647 1.456 1.16l.74.534a.854.854 0 0 1-.202.201Zm.447.334-.045-.023c.068-.044.135-.089.203-.155l-.158.178ZM.785 4.59c.044.29.112.58.156.847.269 1.47.538 2.808 1.03 3.811l.203.758c.067.29.178.646.29.735a89.02 89.02 0 0 0 4.772 3.923.236.236 0 0 0 .291 0s0 .022.023.022a.205.205 0 0 0 .157.067.256.256 0 0 0 .18-.067c2.396-2.652 4.188-4.836 5.465-6.664.09-.089.113-.223.113-.334.089-.09.156-.2.246-.267.089-.09.089-.246 0-.313l-.023-.022c0-.044-.022-.112-.067-.134-.56-.534-.963-.913-1.389-1.314-.74-.692-1.5-1.404-3.114-3.009l-.022-.022c-.023-.023-.045-.045-.09-.045-.448-.156-1.366-.312-2.509-.513C4.795 1.76 2.487 1.36.404.735c0 0-.135 0-.158.022L.18.825C.157.846.135.869 0 .913c.022.134.022.223.067.38 0 .044.09.4.09.445L.785 4.59Zm12.432 2.63-.268-.268c.067.09.157.156.268.268Zm-2.845 3.744-.044.044c0-.022.022-.044.045-.044ZM8.738 2.94c.135.134.695.67.83.781-.583-.268-2.039-.936-2.712-1.16.672.135 1.591.269 1.882.38ZM1.053 1.828c.337.579.605 2.585.874 4.546-.157-.625-.269-1.248-.403-1.828-.202-1.025-.404-1.938-.673-2.74.045 0 .113 0 .202.022ZM.92 1.359c-.09 0-.18-.022-.247-.022 0-.022 0-.044-.022-.044.112 0 .179.022.269.066Zm-.874.178c0-.021 0-.021 0 0Zm31.52-.49c.023-.088-.448-.49-.291-.513.337-.021.337-.534 0-.534-.448.022-.918.133-1.344.2-.784.156-1.59.313-2.375.49-1.77.38-3.517.78-5.264 1.25-.538.155-1.143.266-1.658.534-.18.089-.157.267-.067.378-.045.023-.067.023-.112.045-.157.023-.292.045-.448.067-.135.022-.202.134-.18.268 0 .021.023.066.023.088a138.343 138.343 0 0 1-3.137 3.968c-1.12 1.292-2.307 2.652-3.495 4.056-3.786 4.413-8.064 9.427-12.791 13.84a.215.215 0 0 0 0 .312c.023.022.045.044.067.044-.067.068-.134.113-.202.178-.045.046-.067.09-.067.134a.485.485 0 0 0-.09.112c-.09.09-.09.245.023.312.09.088.247.088.313-.022.023-.023.023-.045.045-.045a.353.353 0 0 1 .494 0c.268.29.537.58.783.825l-.56-.468c-.09-.09-.246-.067-.313.022-.09.088-.068.245.022.312L6.9 31.87c.045.045.09.045.157.045a.201.201 0 0 0 .157-.067l.134-.134c.023.022.067.022.09.022a.203.203 0 0 0 .157-.067c8.065-8.067 14.562-14.152 22-19.59.066-.044.089-.133.089-.2.09 0 .157-.067.201-.156 1.367-4.168 1.636-7.868 1.725-9.695v-.022c0-.023.023-.045.023-.067.022-.045.022-.067.022-.067.06-.277.029-.567-.09-.825ZM17.138 7.6c.358-.402.717-.825 1.076-1.204-2.308 3.031-6.138 7.689-11.56 13.239 3.696-4.079 7.415-8.29 10.485-12.035ZM6.856 31.246c-.022-.023-.022-.023 0-.023v.023Zm3.338-2.875c.18-.2.36-.379.56-.58 0 0 0 .022.023.022-.202.18-.381.357-.582.558h-.001Zm.92-.891c.112-.113.223-.268.357-.402l.022-.022c1.323-1.36 2.69-2.72 4.078-4.1l.022-.023c.337-.267.74-.557 1.098-.825a304.242 304.242 0 0 0-5.578 5.372Zm8.69-22.31c-.738.959-1.567 2.229-2.262 3.232C15.346 11.566 8.29 19.3 8.132 19.434a1590.966 1590.966 0 0 1-6.452 6.129l-.134.134c-.112-.134-.112-.335.023-.446 9.968-9.339 16.017-17.116 18.46-20.526-.068.156-.113.289-.225.445Zm3.876 4.57c-.895-.514-1.32-1.316-1.075-2.095l.067-.268c.023-.067.068-.156.113-.223a2.533 2.533 0 0 1 1.008-.936c.022 0 .044 0 .067-.022-.023-.045-.023-.112-.023-.179.023-.134.113-.223.27-.223.268 0 1.097.246 1.411.513.09.067.18.156.269.245.112.134.291.357.38.535.045.022.09.245.157.357.045.178.09.379.068.557-.023.022 0 .155-.023.155a2.14 2.14 0 0 1-.29.825c-.023.023-.023.045-.046.068l-.022.021a1.628 1.628 0 0 1-.425.446c-.516.357-1.099.468-1.681.312 0 0-.157-.067-.225-.089Zm6.542-.67a31.38 31.38 0 0 1-.716 2.541c0 .023-.023.067 0 .09-.045 0-.068.022-.113.044-1.77 1.292-3.494 2.652-5.22 4.034 1.48-1.316 2.958-2.652 4.504-3.967.448-.401.761-.914.85-1.493l.225-1.338v-.044c.112-.268.538-.156.47.133Z"/>'
47240      },
47241      tldraw: {
47242        label: "tldraw",
47243        viewBox: "0 0 24 24",
47244        themeAdaptive: true,
47245        markup: '<path fill="currentColor" d="M21.474 0H2.526C1.131 0 0 1.18 0 2.637v18.726C0 22.819 1.131 24 2.526 24h18.948C22.869 24 24 22.82 24 21.363V2.637C24 1.181 22.869 0 21.474 0zm-11.01 5.388c.397-.405.888-.607 1.474-.607.57 0 1.052.202 1.448.607.397.404.595.896.595 1.476s-.198 1.072-.595 1.476c-.396.405-.879.607-1.448.607-.586 0-1.077-.202-1.474-.607-.396-.404-.594-.896-.594-1.476s.198-1.072.594-1.476zm3.13 11.49a4.887 4.887 0 0 1-2.018 2.136c-.483.281-.879.273-1.19-.026-.292-.281-.206-.615.26-1.002.258-.193.473-.44.646-.738.172-.299.284-.607.336-.923.017-.14-.043-.21-.181-.21-.345-.018-.698-.212-1.06-.581-.362-.37-.543-.826-.543-1.37 0-.58.198-1.073.594-1.477a2.024 2.024 0 0 1 1.5-.633c.552 0 1.034.21 1.448.633.414.404.655.86.724 1.37.138.95-.034 1.89-.517 2.822z"/>'
47246      },
47247      google_maps: {
47248        label: "Google Maps",
47249        viewBox: "0 0 32 32",
47250        markup: '<path fill="#4285F4" d="M16.166 6.888a4.27 4.27 0 0 1 4.278 4.278c0 1.04-.387 2.006-1.015 2.755 0 0 4.571-3.421 6.647-7.903A11.134 11.134 0 0 0 19.55.532L15.5 3.5l-2.62 4.91c.797-.918 1.957-1.522 3.286-1.522Z"/><path fill="#FBBC04" d="M16.166 15.42a4.27 4.27 0 0 1-4.278-4.278c0-1.04.363-2.006.991-2.731L8.5 12l-2.388 4.46c1.16 2.561 3.093 4.64 5.075 7.226L16.5 19.5l2.929-5.603a4.243 4.243 0 0 1-3.263 1.523Z"/><path fill="#34A853" d="M19.284 26.393c3.722-5.825 8.048-8.46 8.048-15.227 0-1.86-.459-3.601-1.256-5.148L11.187 23.686a44.567 44.567 0 0 1 1.91 2.73C15.369 29.923 14.74 32 16.19 32s.822-2.103 3.094-5.607Z"/><path fill="#EA4335" d="M7.61 3.988A11.154 11.154 0 0 0 5 11.142c0 2.103.41 3.795 1.112 5.317l6.767-8.048L11 5.5 7.61 3.988Z"/><path fill="#1A73E8" d="M19.55.532A11.3 11.3 0 0 0 16.142 0C12.734 0 9.665 1.547 7.61 3.988l5.27 4.423L19.55.53Z"/>'
47251      },
47252      tella: {
47253        label: "Tella",
47254        viewBox: "0 0 32 32",
47255        markup: '<path fill="#8278FA" d="M29.702 0h-27.5C.985 0 0 .99 0 2.207v27.587C0 31.01.985 32 2.2 32h27.502c1.214 0 2.2-.99 2.2-2.206V2.207A2.2 2.2 0 0 0 29.701 0Z"/><path fill="#fff" d="M25.853 17.104c-.605-.03-7.097-.03-7.702 0a1.143 1.143 0 0 0-1.1 1.102c-.027.608-.027 7.117 0 7.724.03.608.495 1.076 1.1 1.105.607.027 7.097.027 7.702 0a1.143 1.143 0 0 0 1.1-1.105c.027-.607.027-7.117 0-7.724a1.143 1.143 0 0 0-1.1-1.102ZM4.95 17.635c0-.407.5-.663.902-.46l8.698 4.435c.401.204.401.713 0 .916l-8.698 4.437c-.4.203-.902-.051-.902-.46v-8.868ZM9.901 14.896a4.958 4.958 0 0 0 4.95-4.964A4.958 4.958 0 0 0 9.9 4.966 4.959 4.959 0 0 0 4.95 9.932 4.959 4.959 0 0 0 9.9 14.896ZM17.602 4.966c.302-.03 8.498-.03 8.8 0a.592.592 0 0 1 .55.552c.028.303.028 1.075 0 1.378a.592.592 0 0 1-.55.553c-.302.027-3.135.021-3.135.021s0 6.598-.028 6.875a.615.615 0 0 1-.55.552 11.42 11.42 0 0 1-1.374 0 .592.592 0 0 1-.55-.552c-.029-.277-.029-6.875-.029-6.875s-2.804.006-3.134-.021a.592.592 0 0 1-.55-.553c-.028-.46-.028-.92 0-1.38a.592.592 0 0 1 .55-.55Z"/>'
47256      }
47257    },
47258    providers: [
47259      {
47260        id: "youtube",
47261        name: "YouTube",
47262        url: "https://www.youtube.com/"
47263      },
47264      {
47265        id: "vimeo",
47266        name: "Vimeo",
47267        url: "https://vimeo.com/"
47268      },
47269      {
47270        id: "spotify",
47271        name: "Spotify",
47272        url: "https://open.spotify.com/"
47273      },
47274      {
47275        id: "soundcloud",
47276        name: "SoundCloud",
47277        url: "https://soundcloud.com/"
47278      },
47279      {
47280        id: "x",
47281        name: "\u{1D54F} / Twitter",
47282        url: "https://x.com/"
47283      },
47284      {
47285        id: "instagram",
47286        name: "Instagram",
47287        url: "https://www.instagram.com/"
47288      },
47289      {
47290        id: "tiktok",
47291        name: "TikTok",
47292        url: "https://www.tiktok.com/"
47293      },
47294      {
47295        id: "facebook",
47296        name: "Facebook",
47297        url: "https://www.facebook.com/"
47298      },
47299      {
47300        id: "loom",
47301        name: "Loom",
47302        url: "https://www.loom.com/"
47303      },
47304      {
47305        id: "airtable",
47306        name: "Airtable",
47307        url: "https://airtable.com/"
47308      },
47309      {
47310        id: "wistia",
47311        name: "Wistia",
47312        url: "https://wistia.com/"
47313      },
47314      {
47315        id: "gumlet",
47316        name: "Gumlet",
47317        url: "https://www.gumlet.com/"
47318      },
47319      {
47320        id: "genially",
47321        name: "Genially",
47322        url: "https://genially.com/"
47323      },
47324      {
47325        id: "excalidraw",
47326        name: "Excalidraw",
47327        url: "https://excalidraw.com/"
47328      },
47329      {
47330        id: "tldraw",
47331        name: "tldraw",
47332        url: "https://www.tldraw.com/"
47333      },
47334      {
47335        id: "google_maps",
47336        name: "Google Maps",
47337        url: "https://www.google.com/maps"
47338      },
47339      {
47340        id: "tella",
47341        name: "Tella",
47342        url: "https://www.tella.tv/"
47343      }
47344    ],
47345    providerNameToId: {
47346      YouTube: "youtube",
47347      Vimeo: "vimeo",
47348      Spotify: "spotify",
47349      SoundCloud: "soundcloud",
47350      "\u{1D54F} / Twitter": "x",
47351      X: "x",
47352      Twitter: "x",
47353      Instagram: "instagram",
47354      Gumlet: "gumlet",
47355      TikTok: "tiktok",
47356      Facebook: "facebook",
47357      Loom: "loom",
47358      Airtable: "airtable",
47359      "Wistia, Inc.": "wistia",
47360      Wistia: "wistia",
47361      Genially: "genially",
47362      Excalidraw: "excalidraw",
47363      tldraw: "tldraw",
47364      Tldraw: "tldraw",
47365      TLDraw: "tldraw",
47366      "Google Maps": "google_maps",
47367      GoogleMaps: "google_maps",
47368      Google: "google_maps",
47369      Tella: "tella"
47370    }
47371  };
47372
47373  
47373// app/javascript/src/embed_provider_icons.js
47374  var ICONS = embed_provider_icons_data_default.icons;
47375  var EMBED_PROVIDERS = embed_provider_icons_data_default.providers;
47376  var PROVIDER_NAME_TO_ID = embed_provider_icons_data_default.providerNameToId;
47377  var PROVIDER_DISPLAY_NAMES = {
47378    X: "\u{1D54F} / Twitter",
47379    Twitter: "\u{1D54F} / Twitter"
47380  };
47381  function embedProviderDisplayName(providerName) {
47382    return PROVIDER_DISPLAY_NAMES[providerName] || providerName;
47383  }
47384  function embedProviderIcon(id3, { className = "link_to_embed__provider-icon" } = {}) {
47385    const icon = ICONS[id3];
47386    if (!icon) return "";
47387    const viewBox = icon.viewBox || "0 0 24 24";
47388    const instanceId = `${id3}-${Math.random().toString(36).slice(2, 9)}`;
47389    if (icon.markup) {
47390      const markup = icon.markup.replace(/\{id\}/g, instanceId);
47391      const themeClass = icon.themeAdaptive ? " embed-provider-icon--theme-adaptive" : "";
47392      return `<svg class="${className} embed-provider-icon--${id3}${themeClass}" viewBox="${viewBox}" aria-hidden="true" fill="none">${markup}</svg>`;
47393    }
47394    const color = icon.color === "currentColor" ? "currentColor" : icon.color;
47395    return `<svg class="${className}" viewBox="${viewBox}" aria-hidden="true" fill="${color}"><path d="${icon.path}"></path></svg>`;
47396  }
47397  function embedProviderIconForName(providerName, options = {}) {
47398    const displayName = embedProviderDisplayName(providerName);
47399    const id3 = PROVIDER_NAME_TO_ID[displayName] || PROVIDER_NAME_TO_ID[providerName];
47400    return id3 ? embedProviderIcon(id3, options) : "";
47401  }
47402  function embedProviderPill(provider) {
47403    return `<div><a class="link_to_embed__provider-pill" href="${provider.url}" target="_blank" rel="noopener noreferrer" aria-label="Open ${provider.name} in a new tab">${embedProviderIcon(provider.id)}<span>${provider.name}</span></a></div>`;
47404  }
47405  function decorateEmbedBadges(root = document) {
47406    root.querySelectorAll(".embed__badge[data-provider-name]").forEach((badge) => {
47407      if (badge.querySelector(".embed__badge-icon, .link_to_embed__provider-icon")) return;
47408      const iconMarkup = embedProviderIconForName(badge.dataset.providerName, {
47409        className: "embed__badge-icon"
47410      });
47411      if (!iconMarkup) return;
47412      badge.insertAdjacentHTML("afterbegin", iconMarkup);
47413    });
47414  }
47415
47416  
47416// app/javascript/src/lexxy/container_content_blocks.js
47417  var {
47418    $createParagraphNode: $createParagraphNode3,
47419    $isDecoratorNode: $isDecoratorNode3,
47420    $isElementNode: $isElementNode3,
47421    $isRootOrShadowRoot: $isRootOrShadowRoot3
47422  } = Lexical_exports;
47423  function $isContainerContentBlock(node) {
47424    return $isElementNode3(node) && !node.isInline() && !$isRootOrShadowRoot3(node);
47425  }
47426  function $isBlockDecoratorNode(node) {
47427    return $isDecoratorNode3(node) && !node.isInline();
47428  }
47429  function $isValidContainerContentNode(node) {
47430    return $isContainerContentBlock(node) || $isBlockDecoratorNode(node);
47431  }
47432  function $normalizeContainerContent(container) {
47433    const children = [...container.getLatest().getChildren()];
47434    const needsWrap = children.some((child) => !$isValidContainerContentNode(child));
47435    const needsParagraph = children.length === 0;
47436    if (!needsWrap && !needsParagraph) return;
47437    let inlineRun = [];
47438    const flushInlineRun = () => {
47439      if (inlineRun.length === 0) return;
47440      const paragraph = $createParagraphNode3();
47441      inlineRun[0].insertBefore(paragraph);
47442      inlineRun.forEach((node) => paragraph.append(node));
47443      inlineRun = [];
47444    };
47445    for (const child of children) {
47446      if ($isValidContainerContentNode(child)) {
47447        flushInlineRun();
47448      } else {
47449        inlineRun.push(child);
47450      }
47451    }
47452    flushInlineRun();
47453    if (container.getLatest().getChildrenSize() === 0) {
47454      container.append($createParagraphNode3());
47455    }
47456  }
47457
47458  
47458// app/javascript/src/lexxy/highlight_palette.js
47459  var HIGHLIGHT_VARIANTS = [
47460    { id: 1, label: "Taupe" },
47461    { id: 2, label: "Orange" },
47462    { id: 3, label: "Red" },
47463    { id: 4, label: "Fuchsia" },
47464    { id: 5, label: "Purple" },
47465    { id: 6, label: "Blue" },
47466    { id: 7, label: "Green" },
47467    { id: 8, label: "Amber" },
47468    { id: 9, label: "Gray" }
47469  ];
47470  var CALLOUT_VARIANT_NONE = 0;
47471  var DEFAULT_CALLOUT_BORDER_VARIANT = 6;
47472  var DEFAULT_CALLOUT_BG_VARIANT = 6;
47473  function parseCalloutVariant(value, fallback) {
47474    if (value === void 0 || value === null || value === "") return fallback;
47475    const parsed = Number(value);
47476    return Number.isNaN(parsed) ? fallback : parsed;
47477  }
47478
47479  
47479// app/javascript/src/lexxy/callout_node.js
47480  var {
47481    $applyNodeReplacement: $applyNodeReplacement4,
47482    $createParagraphNode: $createParagraphNode4,
47483    $findMatchingParent: $findMatchingParent4,
47484    $getSelection: $getSelection3,
47485    $isElementNode: $isElementNode4,
47486    $isParagraphNode: $isParagraphNode3,
47487    $isRangeSelection: $isRangeSelection3,
47488    ElementNode: ElementNode3,
47489    INTERNAL_$isBlock: INTERNAL_$isBlock3
47490  } = Lexical_exports;
47491  var CALLOUT_CLASS = "lexxy-callout";
47492  var CALLOUT_ICON_TRIGGER_SELECTOR = "[data-callout-inline-icon-toggle]";
47493  var MAX_CALLOUT_NESTING_DEPTH = 4;
47494  var CalloutNode = class _CalloutNode extends ElementNode3 {
47495    __borderVariant = DEFAULT_CALLOUT_BORDER_VARIANT;
47496    __bgVariant = DEFAULT_CALLOUT_BG_VARIANT;
47497    __icon = "\u{1F4A1}";
47498    __iconType = "emoji";
47499    __iconSrc = null;
47500    static getType() {
47501      return "lexxy-callout";
47502    }
47503    static clone(node) {
47504      return new _CalloutNode(
47505        node.__borderVariant,
47506        node.__bgVariant,
47507        node.__icon,
47508        node.__iconType,
47509        node.__iconSrc,
47510        node.__key
47511      );
47512    }
47513    constructor(borderVariant = DEFAULT_CALLOUT_BORDER_VARIANT, bgVariant = DEFAULT_CALLOUT_BG_VARIANT, icon = "\u{1F4A1}", iconType = "emoji", iconSrc = null, key) {
47514      super(key);
47515      this.__borderVariant = borderVariant;
47516      this.__bgVariant = bgVariant;
47517      this.__icon = icon;
47518      this.__iconType = iconType;
47519      this.__iconSrc = iconSrc;
47520    }
47521    createDOM() {
47522      const element = document.createElement("aside");
47523      element.className = CALLOUT_CLASS;
47524      this.#syncDom(element);
47525      return element;
47526    }
47527    updateDOM(prevNode, dom) {
47528      if (prevNode.__borderVariant !== this.__borderVariant || prevNode.__bgVariant !== this.__bgVariant || prevNode.__icon !== this.__icon || prevNode.__iconType !== this.__iconType || prevNode.__iconSrc !== this.__iconSrc) {
47529        this.#syncDom(dom);
47530      }
47531      return false;
47532    }
47533    #syncDom(element) {
47534      element.dataset.borderVariant = String(this.__borderVariant);
47535      element.dataset.bgVariant = String(this.__bgVariant);
47536      element.dataset.iconType = this.__iconType;
47537      delete element.dataset.icon;
47538      delete element.dataset.iconId;
47539      delete element.dataset.iconSrc;
47540      element.style.removeProperty("--callout-icon-image");
47541      element.style.removeProperty("--callout-icon-mask");
47542      if (this.__iconType === "none") {
47543        this.#syncIconTrigger(element);
47544        return;
47545      }
47546      if (this.__iconType === "symbol") {
47547        element.dataset.iconId = this.__icon;
47548        const svg2 = isSvgMarkup(this.__iconSrc) ? this.__iconSrc : calloutIconById(this.__icon)?.svg;
47549        if (this.__iconSrc) {
47550          element.dataset.iconSrc = this.__iconSrc;
47551        }
47552        if (svg2) {
47553          element.style.setProperty("--callout-icon-mask", iconMaskUrl(svg2));
47554        }
47555        this.#syncIconTrigger(element);
47556        return;
47557      }
47558      element.dataset.icon = this.__icon;
47559      if (this.__iconSrc) {
47560        element.dataset.iconSrc = this.__iconSrc;
47561        element.style.setProperty("--callout-icon-image", `url("${this.__iconSrc.replace(/"/g, '\\"')}")`);
47562      }
47563      this.#syncIconTrigger(element);
47564    }
47565    #syncIconTrigger(element) {
47566      const existingTrigger = element.querySelector(CALLOUT_ICON_TRIGGER_SELECTOR);
47567      if (this.__iconType === "none") {
47568        existingTrigger?.remove();
47569        return;
47570      }
47571      const trigger = existingTrigger || (() => {
47572        const button = document.createElement("button");
47573        button.type = "button";
47574        button.className = "lexxy-callout__icon-trigger";
47575        button.dataset.calloutInlineIconToggle = "";
47576        button.setAttribute("aria-label", "Change callout icon");
47577        element.insertBefore(button, element.firstChild);
47578        return button;
47579      })();
47580      trigger.contentEditable = "false";
47581      trigger.tabIndex = -1;
47582      this.#syncIconTriggerPreview(trigger);
47583    }
47584    #syncIconTriggerPreview(trigger) {
47585      trigger.replaceChildren();
47586      if (this.__iconType === "emoji") {
47587        const emoji = document.createElement("span");
47588        emoji.className = "lexxy-callout__icon-emoji";
47589        emoji.setAttribute("aria-hidden", "true");
47590        emoji.textContent = this.__icon || "\u{1F4A1}";
47591        trigger.append(emoji);
47592        return;
47593      }
47594      if (this.__iconType === "image" && this.__iconSrc) {
47595        const image = document.createElement("img");
47596        image.className = "lexxy-callout__icon-image";
47597        image.alt = "";
47598        image.decoding = "async";
47599        image.loading = "lazy";
47600        image.src = this.__iconSrc;
47601        trigger.append(image);
47602        return;
47603      }
47604      if (this.__iconType === "symbol") {
47605        const svgMarkup = isSvgMarkup(this.__iconSrc) ? this.__iconSrc : calloutIconById(this.__icon)?.svg;
47606        const svg2 = sanitizedSvgElement(svgMarkup);
47607        if (svg2) trigger.append(svg2);
47608      }
47609    }
47610    static importDOM() {
47611      const convert = (domNode) => {
47612        if (!domNode.classList.contains(CALLOUT_CLASS)) return null;
47613        const legacyVariant = domNode.dataset.variant;
47614        const borderVariant = parseCalloutVariant(
47615          domNode.dataset.borderVariant ?? legacyVariant,
47616          DEFAULT_CALLOUT_BORDER_VARIANT
47617        );
47618        const bgVariant = parseCalloutVariant(domNode.dataset.bgVariant ?? legacyVariant, DEFAULT_CALLOUT_BG_VARIANT);
47619        const iconType = domNode.dataset.iconType || "emoji";
47620        const icon = iconType === "symbol" ? domNode.dataset.iconId || "lightbulb" : domNode.dataset.icon || "\u{1F4A1}";
47621        return {
47622          conversion: () => ({
47623            node: $createCalloutNode(borderVariant, bgVariant, icon, iconType, domNode.dataset.iconSrc || null)
47624          }),
47625          priority: 2
47626        };
47627      };
47628      return { aside: convert, div: convert };
47629    }
47630    exportDOM(editor) {
47631      const { element } = super.exportDOM(editor);
47632      if (element) {
47633        element.className = CALLOUT_CLASS;
47634        this.#syncDom(element);
47635        element.querySelector(CALLOUT_ICON_TRIGGER_SELECTOR)?.remove();
47636      }
47637      return { element };
47638    }
47639    static importJSON(serializedNode) {
47640      return $createCalloutNode(
47641        serializedNode.borderVariant ?? serializedNode.variant,
47642        serializedNode.bgVariant ?? serializedNode.variant,
47643        serializedNode.icon,
47644        serializedNode.iconType,
47645        serializedNode.iconSrc
47646      );
47647    }
47648    exportJSON() {
47649      return {
47650        ...super.exportJSON(),
47651        type: "lexxy-callout",
47652        borderVariant: this.__borderVariant,
47653        bgVariant: this.__bgVariant,
47654        icon: this.__icon,
47655        iconType: this.__iconType,
47656        iconSrc: this.__iconSrc,
47657        version: 2
47658      };
47659    }
47660    insertNewAfter(_selection, restoreSelection) {
47661      const paragraph = $createParagraphNode4();
47662      this.insertAfter(paragraph, restoreSelection);
47663      return paragraph;
47664    }
47665    collapseAtStart() {
47666      const children = [...this.getChildren()];
47667      const firstChild = children[0];
47668      if (!firstChild) {
47669        const paragraph = $createParagraphNode4();
47670        this.replace(paragraph);
47671        paragraph.selectStart();
47672        return true;
47673      }
47674      children.forEach((child) => this.insertBefore(child));
47675      this.remove();
47676      firstChild.selectStart?.();
47677      return true;
47678    }
47679    isShadowRoot() {
47680      return true;
47681    }
47682    canBeEmpty() {
47683      return false;
47684    }
47685    canIndent() {
47686      return false;
47687    }
47688    canMergeWhenEmpty() {
47689      return true;
47690    }
47691    setBorderVariant(variant) {
47692      const self2 = this.getWritable();
47693      self2.__borderVariant = variant;
47694      return self2;
47695    }
47696    getBorderVariant() {
47697      return this.getLatest().__borderVariant;
47698    }
47699    setBgVariant(variant) {
47700      const self2 = this.getWritable();
47701      self2.__bgVariant = variant;
47702      return self2;
47703    }
47704    getBgVariant() {
47705      return this.getLatest().__bgVariant;
47706    }
47707    setIcon(icon) {
47708      const self2 = this.getWritable();
47709      self2.__icon = icon || "\u{1F4A1}";
47710      return self2;
47711    }
47712    getIcon() {
47713      return this.getLatest().__icon;
47714    }
47715    setIconType(iconType) {
47716      const self2 = this.getWritable();
47717      self2.__iconType = iconType || "emoji";
47718      return self2;
47719    }
47720    getIconType() {
47721      return this.getLatest().__iconType;
47722    }
47723    setIconSrc(iconSrc) {
47724      const self2 = this.getWritable();
47725      self2.__iconSrc = iconSrc || null;
47726      return self2;
47727    }
47728    getIconSrc() {
47729      return this.getLatest().__iconSrc;
47730    }
47731  };
47732  function $createCalloutNode(borderVariant = DEFAULT_CALLOUT_BORDER_VARIANT, bgVariant = DEFAULT_CALLOUT_BG_VARIANT, icon = "\u{1F4A1}", iconType = "emoji", iconSrc = null) {
47733    return $applyNodeReplacement4(new CalloutNode(borderVariant, bgVariant, icon, iconType, iconSrc));
47734  }
47735  function $isCalloutNode(node) {
47736    return node instanceof CalloutNode;
47737  }
47738  function $countCalloutAncestors(node) {
47739    let count = 0;
47740    let ancestor = $findMatchingParent4(node, $isCalloutNode);
47741    while ($isCalloutNode(ancestor)) {
47742      count += 1;
47743      ancestor = $findMatchingParent4(ancestor.getParent(), $isCalloutNode);
47744    }
47745    return count;
47746  }
47747  function $canNestCalloutAt(node) {
47748    return $countCalloutAncestors(node) < MAX_CALLOUT_NESTING_DEPTH;
47749  }
47750  function $getSelectedBlocks(selection) {
47751    const blockMap = /* @__PURE__ */ new Map();
47752    const anchorAndFocus = selection.getStartEndPoints();
47753    if (anchorAndFocus) {
47754      const [anchor, focus] = anchorAndFocus;
47755      const anchorBlock = $findMatchingParent4(anchor.getNode(), INTERNAL_$isBlock3);
47756      const focusBlock = $findMatchingParent4(focus.getNode(), INTERNAL_$isBlock3);
47757      if ($isElementNode4(anchorBlock)) blockMap.set(anchorBlock.getKey(), anchorBlock);
47758      if ($isElementNode4(focusBlock)) blockMap.set(focusBlock.getKey(), focusBlock);
47759    }
47760    for (const node of selection.getNodes()) {
47761      if ($isElementNode4(node) && INTERNAL_$isBlock3(node)) {
47762        blockMap.set(node.getKey(), node);
47763      } else if (anchorAndFocus === null) {
47764        const ancestorBlock = $findMatchingParent4(node, INTERNAL_$isBlock3);
47765        if ($isElementNode4(ancestorBlock)) blockMap.set(ancestorBlock.getKey(), ancestorBlock);
47766      }
47767    }
47768    return [...blockMap.values()];
47769  }
47770  function $normalizeCalloutContent(callout) {
47771    $normalizeContainerContent(callout);
47772  }
47773  function $insertCallout() {
47774    const selection = $getSelection3();
47775    if (!$isRangeSelection3(selection)) return;
47776    const blocks = $getSelectedBlocks(selection).filter((block) => !$isCalloutNode(block));
47777    if (blocks.length === 0) return;
47778    if (!$canNestCalloutAt(blocks[0])) return;
47779    const wrapInCallout = blocks.some((block) => !$isParagraphNode3(block));
47780    if (wrapInCallout) {
47781      const callout = $createCalloutNode();
47782      blocks[0].insertBefore(callout);
47783      blocks.forEach((block) => callout.append(block));
47784      return;
47785    }
47786    blocks.forEach((block) => {
47787      const callout = $createCalloutNode();
47788      block.insertBefore(callout);
47789      callout.append(block);
47790    });
47791  }
47792
47793  
vendor: 3,782 bytes, lines 47793-47921
47793// node_modules/@floating-ui/utils/dist/floating-ui.utils.mjs
47794  var min = Math.min;
47795  var max = Math.max;
47796  var round = Math.round;
47797  var floor = Math.floor;
47798  var createCoords = (v3) => ({
47799    x: v3,
47800    y: v3
47801  });
47802  var oppositeSideMap = {
47803    left: "right",
47804    right: "left",
47805    bottom: "top",
47806    top: "bottom"
47807  };
47808  function clamp(start3, value, end) {
47809    return max(start3, min(value, end));
47810  }
47811  function evaluate(value, param) {
47812    return typeof value === "function" ? value(param) : value;
47813  }
47814  function getSide(placement) {
47815    return placement.split("-")[0];
47816  }
47817  function getAlignment(placement) {
47818    return placement.split("-")[1];
47819  }
47820  function getOppositeAxis(axis) {
47821    return axis === "x" ? "y" : "x";
47822  }
47823  function getAxisLength(axis) {
47824    return axis === "y" ? "height" : "width";
47825  }
47826  function getSideAxis(placement) {
47827    const firstChar = placement[0];
47828    return firstChar === "t" || firstChar === "b" ? "y" : "x";
47829  }
47830  function getAlignmentAxis(placement) {
47831    return getOppositeAxis(getSideAxis(placement));
47832  }
47833  function getAlignmentSides(placement, rects, rtl) {
47834    if (rtl === void 0) {
47835      rtl = false;
47836    }
47837    const alignment = getAlignment(placement);
47838    const alignmentAxis = getAlignmentAxis(placement);
47839    const length = getAxisLength(alignmentAxis);
47840    let mainAlignmentSide = alignmentAxis === "x" ? alignment === (rtl ? "end" : "start") ? "right" : "left" : alignment === "start" ? "bottom" : "top";
47841    if (rects.reference[length] > rects.floating[length]) {
47842      mainAlignmentSide = getOppositePlacement(mainAlignmentSide);
47843    }
47844    return [mainAlignmentSide, getOppositePlacement(mainAlignmentSide)];
47845  }
47846  function getExpandedPlacements(placement) {
47847    const oppositePlacement = getOppositePlacement(placement);
47848    return [getOppositeAlignmentPlacement(placement), oppositePlacement, getOppositeAlignmentPlacement(oppositePlacement)];
47849  }
47850  function getOppositeAlignmentPlacement(placement) {
47851    return placement.includes("start") ? placement.replace("start", "end") : placement.replace("end", "start");
47852  }
47853  var lrPlacement = ["left", "right"];
47854  var rlPlacement = ["right", "left"];
47855  var tbPlacement = ["top", "bottom"];
47856  var btPlacement = ["bottom", "top"];
47857  function getSideList(side, isStart, rtl) {
47858    switch (side) {
47859      case "top":
47860      case "bottom":
47861        if (rtl) return isStart ? rlPlacement : lrPlacement;
47862        return isStart ? lrPlacement : rlPlacement;
47863      case "left":
47864      case "right":
47865        return isStart ? tbPlacement : btPlacement;
47866      default:
47867        return [];
47868    }
47869  }
47870  function getOppositeAxisPlacements(placement, flipAlignment, direction, rtl) {
47871    const alignment = getAlignment(placement);
47872    let list = getSideList(getSide(placement), direction === "start", rtl);
47873    if (alignment) {
47874      list = list.map((side) => side + "-" + alignment);
47875      if (flipAlignment) {
47876        list = list.concat(list.map(getOppositeAlignmentPlacement));
47877      }
47878    }
47879    return list;
47880  }
47881  function getOppositePlacement(placement) {
47882    const side = getSide(placement);
47883    return oppositeSideMap[side] + placement.slice(side.length);
47884  }
47885  function expandPaddingObject(padding) {
47886    return {
47887      top: 0,
47888      right: 0,
47889      bottom: 0,
47890      left: 0,
47891      ...padding
47892    };
47893  }
47894  function getPaddingObject(padding) {
47895    return typeof padding !== "number" ? expandPaddingObject(padding) : {
47896      top: padding,
47897      right: padding,
47898      bottom: padding,
47899      left: padding
47900    };
47901  }
47902  function rectToClientRect(rect) {
47903    const {
47904      x: x3,
47905      y: y3,
47906      width,
47907      height
47908    } = rect;
47909    return {
47910      width,
47911      height,
47912      top: y3,
47913      left: x3,
47914      right: x3 + width,
47915      bottom: y3 + height,
47916      x: x3,
47917      y: y3
47918    };
47919  }
47920
47921  
vendor: 15,448 bytes, lines 47921-48372
47921// node_modules/@floating-ui/core/dist/floating-ui.core.mjs
47922  function computeCoordsFromPlacement(_ref2, placement, rtl) {
47923    let {
47924      reference,
47925      floating
47926    } = _ref2;
47927    const sideAxis = getSideAxis(placement);
47928    const alignmentAxis = getAlignmentAxis(placement);
47929    const alignLength = getAxisLength(alignmentAxis);
47930    const side = getSide(placement);
47931    const isVertical = sideAxis === "y";
47932    const commonX = reference.x + reference.width / 2 - floating.width / 2;
47933    const commonY = reference.y + reference.height / 2 - floating.height / 2;
47934    const commonAlign = reference[alignLength] / 2 - floating[alignLength] / 2;
47935    let coords;
47936    switch (side) {
47937      case "top":
47938        coords = {
47939          x: commonX,
47940          y: reference.y - floating.height
47941        };
47942        break;
47943      case "bottom":
47944        coords = {
47945          x: commonX,
47946          y: reference.y + reference.height
47947        };
47948        break;
47949      case "right":
47950        coords = {
47951          x: reference.x + reference.width,
47952          y: commonY
47953        };
47954        break;
47955      case "left":
47956        coords = {
47957          x: reference.x - floating.width,
47958          y: commonY
47959        };
47960        break;
47961      default:
47962        coords = {
47963          x: reference.x,
47964          y: reference.y
47965        };
47966    }
47967    switch (getAlignment(placement)) {
47968      case "start":
47969        coords[alignmentAxis] -= commonAlign * (rtl && isVertical ? -1 : 1);
47970        break;
47971      case "end":
47972        coords[alignmentAxis] += commonAlign * (rtl && isVertical ? -1 : 1);
47973        break;
47974    }
47975    return coords;
47976  }
47977  async function detectOverflow(state, options) {
47978    var _await$platform$isEle;
47979    if (options === void 0) {
47980      options = {};
47981    }
47982    const {
47983      x: x3,
47984      y: y3,
47985      platform: platform2,
47986      rects,
47987      elements,
47988      strategy
47989    } = state;
47990    const {
47991      boundary = "clippingAncestors",
47992      rootBoundary = "viewport",
47993      elementContext = "floating",
47994      altBoundary = false,
47995      padding = 0
47996    } = evaluate(options, state);
47997    const paddingObject = getPaddingObject(padding);
47998    const altContext = elementContext === "floating" ? "reference" : "floating";
47999    const element = elements[altBoundary ? altContext : elementContext];
48000    const clippingClientRect = rectToClientRect(await platform2.getClippingRect({
48001      element: ((_await$platform$isEle = await (platform2.isElement == null ? void 0 : platform2.isElement(element))) != null ? _await$platform$isEle : true) ? element : element.contextElement || await (platform2.getDocumentElement == null ? void 0 : platform2.getDocumentElement(elements.floating)),
48002      boundary,
48003      rootBoundary,
48004      strategy
48005    }));
48006    const rect = elementContext === "floating" ? {
48007      x: x3,
48008      y: y3,
48009      width: rects.floating.width,
48010      height: rects.floating.height
48011    } : rects.reference;
48012    const offsetParent = await (platform2.getOffsetParent == null ? void 0 : platform2.getOffsetParent(elements.floating));
48013    const offsetScale = await (platform2.isElement == null ? void 0 : platform2.isElement(offsetParent)) ? await (platform2.getScale == null ? void 0 : platform2.getScale(offsetParent)) || {
48014      x: 1,
48015      y: 1
48016    } : {
48017      x: 1,
48018      y: 1
48019    };
48020    const elementClientRect = rectToClientRect(platform2.convertOffsetParentRelativeRectToViewportRelativeRect ? await platform2.convertOffsetParentRelativeRectToViewportRelativeRect({
48021      elements,
48022      rect,
48023      offsetParent,
48024      strategy
48025    }) : rect);
48026    return {
48027      top: (clippingClientRect.top - elementClientRect.top + paddingObject.top) / offsetScale.y,
48028      bottom: (elementClientRect.bottom - clippingClientRect.bottom + paddingObject.bottom) / offsetScale.y,
48029      left: (clippingClientRect.left - elementClientRect.left + paddingObject.left) / offsetScale.x,
48030      right: (elementClientRect.right - clippingClientRect.right + paddingObject.right) / offsetScale.x
48031    };
48032  }
48033  var MAX_RESET_COUNT = 50;
48034  var computePosition = async (reference, floating, config) => {
48035    const {
48036      placement = "bottom",
48037      strategy = "absolute",
48038      middleware = [],
48039      platform: platform2
48040    } = config;
48041    const platformWithDetectOverflow = platform2.detectOverflow ? platform2 : {
48042      ...platform2,
48043      detectOverflow
48044    };
48045    const rtl = await (platform2.isRTL == null ? void 0 : platform2.isRTL(floating));
48046    let rects = await platform2.getElementRects({
48047      reference,
48048      floating,
48049      strategy
48050    });
48051    let {
48052      x: x3,
48053      y: y3
48054    } = computeCoordsFromPlacement(rects, placement, rtl);
48055    let statefulPlacement = placement;
48056    let resetCount = 0;
48057    const middlewareData = {};
48058    for (let i2 = 0; i2 < middleware.length; i2++) {
48059      const currentMiddleware = middleware[i2];
48060      if (!currentMiddleware) {
48061        continue;
48062      }
48063      const {
48064        name,
48065        fn
48066      } = currentMiddleware;
48067      const {
48068        x: nextX,
48069        y: nextY,
48070        data,
48071        reset
48072      } = await fn({
48073        x: x3,
48074        y: y3,
48075        initialPlacement: placement,
48076        placement: statefulPlacement,
48077        strategy,
48078        middlewareData,
48079        rects,
48080        platform: platformWithDetectOverflow,
48081        elements: {
48082          reference,
48083          floating
48084        }
48085      });
48086      x3 = nextX != null ? nextX : x3;
48087      y3 = nextY != null ? nextY : y3;
48088      middlewareData[name] = {
48089        ...middlewareData[name],
48090        ...data
48091      };
48092      if (reset && resetCount < MAX_RESET_COUNT) {
48093        resetCount++;
48094        if (typeof reset === "object") {
48095          if (reset.placement) {
48096            statefulPlacement = reset.placement;
48097          }
48098          if (reset.rects) {
48099            rects = reset.rects === true ? await platform2.getElementRects({
48100              reference,
48101              floating,
48102              strategy
48103            }) : reset.rects;
48104          }
48105          ({
48106            x: x3,
48107            y: y3
48108          } = computeCoordsFromPlacement(rects, statefulPlacement, rtl));
48109        }
48110        i2 = -1;
48111      }
48112    }
48113    return {
48114      x: x3,
48115      y: y3,
48116      placement: statefulPlacement,
48117      strategy,
48118      middlewareData
48119    };
48120  };
48121  var flip = function(options) {
48122    if (options === void 0) {
48123      options = {};
48124    }
48125    return {
48126      name: "flip",
48127      options,
48128      async fn(state) {
48129        var _middlewareData$arrow, _middlewareData$flip;
48130        const {
48131          placement,
48132          middlewareData,
48133          rects,
48134          initialPlacement,
48135          platform: platform2,
48136          elements
48137        } = state;
48138        const {
48139          mainAxis: checkMainAxis = true,
48140          crossAxis: checkCrossAxis = true,
48141          fallbackPlacements: specifiedFallbackPlacements,
48142          fallbackStrategy = "bestFit",
48143          fallbackAxisSideDirection = "none",
48144          flipAlignment = true,
48145          ...detectOverflowOptions
48146        } = evaluate(options, state);
48147        if ((_middlewareData$arrow = middlewareData.arrow) != null && _middlewareData$arrow.alignmentOffset) {
48148          return {};
48149        }
48150        const side = getSide(placement);
48151        const initialSideAxis = getSideAxis(initialPlacement);
48152        const isBasePlacement = getSide(initialPlacement) === initialPlacement;
48153        const rtl = await (platform2.isRTL == null ? void 0 : platform2.isRTL(elements.floating));
48154        const fallbackPlacements = specifiedFallbackPlacements || (isBasePlacement || !flipAlignment ? [getOppositePlacement(initialPlacement)] : getExpandedPlacements(initialPlacement));
48155        const hasFallbackAxisSideDirection = fallbackAxisSideDirection !== "none";
48156        if (!specifiedFallbackPlacements && hasFallbackAxisSideDirection) {
48157          fallbackPlacements.push(...getOppositeAxisPlacements(initialPlacement, flipAlignment, fallbackAxisSideDirection, rtl));
48158        }
48159        const placements2 = [initialPlacement, ...fallbackPlacements];
48160        const overflow = await platform2.detectOverflow(state, detectOverflowOptions);
48161        const overflows = [];
48162        let overflowsData = ((_middlewareData$flip = middlewareData.flip) == null ? void 0 : _middlewareData$flip.overflows) || [];
48163        if (checkMainAxis) {
48164          overflows.push(overflow[side]);
48165        }
48166        if (checkCrossAxis) {
48167          const sides2 = getAlignmentSides(placement, rects, rtl);
48168          overflows.push(overflow[sides2[0]], overflow[sides2[1]]);
48169        }
48170        overflowsData = [...overflowsData, {
48171          placement,
48172          overflows
48173        }];
48174        if (!overflows.every((side2) => side2 <= 0)) {
48175          var _middlewareData$flip2, _overflowsData$filter;
48176          const nextIndex = (((_middlewareData$flip2 = middlewareData.flip) == null ? void 0 : _middlewareData$flip2.index) || 0) + 1;
48177          const nextPlacement = placements2[nextIndex];
48178          if (nextPlacement) {
48179            const ignoreCrossAxisOverflow = checkCrossAxis === "alignment" ? initialSideAxis !== getSideAxis(nextPlacement) : false;
48180            if (!ignoreCrossAxisOverflow || // We leave the current main axis only if every placement on that axis
48181            // overflows the main axis.
48182            overflowsData.every((d3) => getSideAxis(d3.placement) === initialSideAxis ? d3.overflows[0] > 0 : true)) {
48183              return {
48184                data: {
48185                  index: nextIndex,
48186                  overflows: overflowsData
48187                },
48188                reset: {
48189                  placement: nextPlacement
48190                }
48191              };
48192            }
48193          }
48194          let resetPlacement = (_overflowsData$filter = overflowsData.filter((d3) => d3.overflows[0] <= 0).sort((a2, b3) => a2.overflows[1] - b3.overflows[1])[0]) == null ? void 0 : _overflowsData$filter.placement;
48195          if (!resetPlacement) {
48196            switch (fallbackStrategy) {
48197              case "bestFit": {
48198                var _overflowsData$filter2;
48199                const placement2 = (_overflowsData$filter2 = overflowsData.filter((d3) => {
48200                  if (hasFallbackAxisSideDirection) {
48201                    const currentSideAxis = getSideAxis(d3.placement);
48202                    return currentSideAxis === initialSideAxis || // Create a bias to the `y` side axis due to horizontal
48203                    // reading directions favoring greater width.
48204                    currentSideAxis === "y";
48205                  }
48206                  return true;
48207                }).map((d3) => [d3.placement, d3.overflows.filter((overflow2) => overflow2 > 0).reduce((acc, overflow2) => acc + overflow2, 0)]).sort((a2, b3) => a2[1] - b3[1])[0]) == null ? void 0 : _overflowsData$filter2[0];
48208                if (placement2) {
48209                  resetPlacement = placement2;
48210                }
48211                break;
48212              }
48213              case "initialPlacement":
48214                resetPlacement = initialPlacement;
48215                break;
48216            }
48217          }
48218          if (placement !== resetPlacement) {
48219            return {
48220              reset: {
48221                placement: resetPlacement
48222              }
48223            };
48224          }
48225        }
48226        return {};
48227      }
48228    };
48229  };
48230  var originSides = /* @__PURE__ */ new Set(["left", "top"]);
48231  async function convertValueToCoords(state, options) {
48232    const {
48233      placement,
48234      platform: platform2,
48235      elements
48236    } = state;
48237    const rtl = await (platform2.isRTL == null ? void 0 : platform2.isRTL(elements.floating));
48238    const side = getSide(placement);
48239    const alignment = getAlignment(placement);
48240    const isVertical = getSideAxis(placement) === "y";
48241    const mainAxisMulti = originSides.has(side) ? -1 : 1;
48242    const crossAxisMulti = rtl && isVertical ? -1 : 1;
48243    const rawValue = evaluate(options, state);
48244    let {
48245      mainAxis,
48246      crossAxis,
48247      alignmentAxis
48248    } = typeof rawValue === "number" ? {
48249      mainAxis: rawValue,
48250      crossAxis: 0,
48251      alignmentAxis: null
48252    } : {
48253      mainAxis: rawValue.mainAxis || 0,
48254      crossAxis: rawValue.crossAxis || 0,
48255      alignmentAxis: rawValue.alignmentAxis
48256    };
48257    if (alignment && typeof alignmentAxis === "number") {
48258      crossAxis = alignment === "end" ? alignmentAxis * -1 : alignmentAxis;
48259    }
48260    return isVertical ? {
48261      x: crossAxis * crossAxisMulti,
48262      y: mainAxis * mainAxisMulti
48263    } : {
48264      x: mainAxis * mainAxisMulti,
48265      y: crossAxis * crossAxisMulti
48266    };
48267  }
48268  var offset = function(options) {
48269    if (options === void 0) {
48270      options = 0;
48271    }
48272    return {
48273      name: "offset",
48274      options,
48275      async fn(state) {
48276        var _middlewareData$offse, _middlewareData$arrow;
48277        const {
48278          x: x3,
48279          y: y3,
48280          placement,
48281          middlewareData
48282        } = state;
48283        const diffCoords = await convertValueToCoords(state, options);
48284        if (placement === ((_middlewareData$offse = middlewareData.offset) == null ? void 0 : _middlewareData$offse.placement) && (_middlewareData$arrow = middlewareData.arrow) != null && _middlewareData$arrow.alignmentOffset) {
48285          return {};
48286        }
48287        return {
48288          x: x3 + diffCoords.x,
48289          y: y3 + diffCoords.y,
48290          data: {
48291            ...diffCoords,
48292            placement
48293          }
48294        };
48295      }
48296    };
48297  };
48298  var shift = function(options) {
48299    if (options === void 0) {
48300      options = {};
48301    }
48302    return {
48303      name: "shift",
48304      options,
48305      async fn(state) {
48306        const {
48307          x: x3,
48308          y: y3,
48309          placement,
48310          platform: platform2
48311        } = state;
48312        const {
48313          mainAxis: checkMainAxis = true,
48314          crossAxis: checkCrossAxis = false,
48315          limiter = {
48316            fn: (_ref2) => {
48317              let {
48318                x: x4,
48319                y: y4
48320              } = _ref2;
48321              return {
48322                x: x4,
48323                y: y4
48324              };
48325            }
48326          },
48327          ...detectOverflowOptions
48328        } = evaluate(options, state);
48329        const coords = {
48330          x: x3,
48331          y: y3
48332        };
48333        const overflow = await platform2.detectOverflow(state, detectOverflowOptions);
48334        const crossAxis = getSideAxis(getSide(placement));
48335        const mainAxis = getOppositeAxis(crossAxis);
48336        let mainAxisCoord = coords[mainAxis];
48337        let crossAxisCoord = coords[crossAxis];
48338        if (checkMainAxis) {
48339          const minSide = mainAxis === "y" ? "top" : "left";
48340          const maxSide = mainAxis === "y" ? "bottom" : "right";
48341          const min2 = mainAxisCoord + overflow[minSide];
48342          const max2 = mainAxisCoord - overflow[maxSide];
48343          mainAxisCoord = clamp(min2, mainAxisCoord, max2);
48344        }
48345        if (checkCrossAxis) {
48346          const minSide = crossAxis === "y" ? "top" : "left";
48347          const maxSide = crossAxis === "y" ? "bottom" : "right";
48348          const min2 = crossAxisCoord + overflow[minSide];
48349          const max2 = crossAxisCoord - overflow[maxSide];
48350          crossAxisCoord = clamp(min2, crossAxisCoord, max2);
48351        }
48352        const limitedCoords = limiter.fn({
48353          ...state,
48354          [mainAxis]: mainAxisCoord,
48355          [crossAxis]: crossAxisCoord
48356        });
48357        return {
48358          ...limitedCoords,
48359          data: {
48360            x: limitedCoords.x - x3,
48361            y: limitedCoords.y - y3,
48362            enabled: {
48363              [mainAxis]: checkMainAxis,
48364              [crossAxis]: checkCrossAxis
48365            }
48366          }
48367        };
48368      }
48369    };
48370  };
48371
48372  
vendor: 5,524 bytes, lines 48372-48528
48372// node_modules/@floating-ui/utils/dist/floating-ui.utils.dom.mjs
48373  function hasWindow() {
48374    return typeof window !== "undefined";
48375  }
48376  function getNodeName(node) {
48377    if (isNode(node)) {
48378      return (node.nodeName || "").toLowerCase();
48379    }
48380    return "#document";
48381  }
48382  function getWindow2(node) {
48383    var _node$ownerDocument;
48384    return (node == null || (_node$ownerDocument = node.ownerDocument) == null ? void 0 : _node$ownerDocument.defaultView) || window;
48385  }
48386  function getDocumentElement(node) {
48387    var _ref2;
48388    return (_ref2 = (isNode(node) ? node.ownerDocument : node.document) || window.document) == null ? void 0 : _ref2.documentElement;
48389  }
48390  function isNode(value) {
48391    if (!hasWindow()) {
48392      return false;
48393    }
48394    return value instanceof Node || value instanceof getWindow2(value).Node;
48395  }
48396  function isElement(value) {
48397    if (!hasWindow()) {
48398      return false;
48399    }
48400    return value instanceof Element || value instanceof getWindow2(value).Element;
48401  }
48402  function isHTMLElement4(value) {
48403    if (!hasWindow()) {
48404      return false;
48405    }
48406    return value instanceof HTMLElement || value instanceof getWindow2(value).HTMLElement;
48407  }
48408  function isShadowRoot(value) {
48409    if (!hasWindow() || typeof ShadowRoot === "undefined") {
48410      return false;
48411    }
48412    return value instanceof ShadowRoot || value instanceof getWindow2(value).ShadowRoot;
48413  }
48414  function isOverflowElement(element) {
48415    const {
48416      overflow,
48417      overflowX,
48418      overflowY,
48419      display
48420    } = getComputedStyle2(element);
48421    return /auto|scroll|overlay|hidden|clip/.test(overflow + overflowY + overflowX) && display !== "inline" && display !== "contents";
48422  }
48423  function isTableElement(element) {
48424    return /^(table|td|th)$/.test(getNodeName(element));
48425  }
48426  function isTopLayer(element) {
48427    try {
48428      if (element.matches(":popover-open")) {
48429        return true;
48430      }
48431    } catch (_e2) {
48432    }
48433    try {
48434      return element.matches(":modal");
48435    } catch (_e2) {
48436      return false;
48437    }
48438  }
48439  var willChangeRe = /transform|translate|scale|rotate|perspective|filter/;
48440  var containRe = /paint|layout|strict|content/;
48441  var isNotNone = (value) => !!value && value !== "none";
48442  var isWebKitValue;
48443  function isContainingBlock(elementOrCss) {
48444    const css = isElement(elementOrCss) ? getComputedStyle2(elementOrCss) : elementOrCss;
48445    return isNotNone(css.transform) || isNotNone(css.translate) || isNotNone(css.scale) || isNotNone(css.rotate) || isNotNone(css.perspective) || !isWebKit() && (isNotNone(css.backdropFilter) || isNotNone(css.filter)) || willChangeRe.test(css.willChange || "") || containRe.test(css.contain || "");
48446  }
48447  function getContainingBlock(element) {
48448    let currentNode = getParentNode(element);
48449    while (isHTMLElement4(currentNode) && !isLastTraversableNode(currentNode)) {
48450      if (isContainingBlock(currentNode)) {
48451        return currentNode;
48452      } else if (isTopLayer(currentNode)) {
48453        return null;
48454      }
48455      currentNode = getParentNode(currentNode);
48456    }
48457    return null;
48458  }
48459  function isWebKit() {
48460    if (isWebKitValue == null) {
48461      isWebKitValue = typeof CSS !== "undefined" && CSS.supports && CSS.supports("-webkit-backdrop-filter", "none");
48462    }
48463    return isWebKitValue;
48464  }
48465  function isLastTraversableNode(node) {
48466    return /^(html|body|#document)$/.test(getNodeName(node));
48467  }
48468  function getComputedStyle2(element) {
48469    return getWindow2(element).getComputedStyle(element);
48470  }
48471  function getNodeScroll(element) {
48472    if (isElement(element)) {
48473      return {
48474        scrollLeft: element.scrollLeft,
48475        scrollTop: element.scrollTop
48476      };
48477    }
48478    return {
48479      scrollLeft: element.scrollX,
48480      scrollTop: element.scrollY
48481    };
48482  }
48483  function getParentNode(node) {
48484    if (getNodeName(node) === "html") {
48485      return node;
48486    }
48487    const result = (
48488      // Step into the shadow DOM of the parent of a slotted node.
48489      node.assignedSlot || // DOM Element detected.
48490      node.parentNode || // ShadowRoot detected.
48491      isShadowRoot(node) && node.host || // Fallback.
48492      getDocumentElement(node)
48493    );
48494    return isShadowRoot(result) ? result.host : result;
48495  }
48496  function getNearestOverflowAncestor(node) {
48497    const parentNode = getParentNode(node);
48498    if (isLastTraversableNode(parentNode)) {
48499      return node.ownerDocument ? node.ownerDocument.body : node.body;
48500    }
48501    if (isHTMLElement4(parentNode) && isOverflowElement(parentNode)) {
48502      return parentNode;
48503    }
48504    return getNearestOverflowAncestor(parentNode);
48505  }
48506  function getOverflowAncestors(node, list, traverseIframes) {
48507    var _node$ownerDocument2;
48508    if (list === void 0) {
48509      list = [];
48510    }
48511    if (traverseIframes === void 0) {
48512      traverseIframes = true;
48513    }
48514    const scrollableAncestor = getNearestOverflowAncestor(node);
48515    const isBody = scrollableAncestor === ((_node$ownerDocument2 = node.ownerDocument) == null ? void 0 : _node$ownerDocument2.body);
48516    const win = getWindow2(scrollableAncestor);
48517    if (isBody) {
48518      const frameElement = getFrameElement(win);
48519      return list.concat(win, win.visualViewport || [], isOverflowElement(scrollableAncestor) ? scrollableAncestor : [], frameElement && traverseIframes ? getOverflowAncestors(frameElement) : []);
48520    } else {
48521      return list.concat(scrollableAncestor, getOverflowAncestors(scrollableAncestor, [], traverseIframes));
48522    }
48523  }
48524  function getFrameElement(win) {
48525    return win.parent && Object.getPrototypeOf(win.parent) ? win.frameElement : null;
48526  }
48527
48528  
vendor: 21,760 bytes, lines 48528-49139
48528// node_modules/@floating-ui/dom/dist/floating-ui.dom.mjs
48529  function getCssDimensions(element) {
48530    const css = getComputedStyle2(element);
48531    let width = parseFloat(css.width) || 0;
48532    let height = parseFloat(css.height) || 0;
48533    const hasOffset = isHTMLElement4(element);
48534    const offsetWidth = hasOffset ? element.offsetWidth : width;
48535    const offsetHeight = hasOffset ? element.offsetHeight : height;
48536    const shouldFallback = round(width) !== offsetWidth || round(height) !== offsetHeight;
48537    if (shouldFallback) {
48538      width = offsetWidth;
48539      height = offsetHeight;
48540    }
48541    return {
48542      width,
48543      height,
48544      $: shouldFallback
48545    };
48546  }
48547  function unwrapElement(element) {
48548    return !isElement(element) ? element.contextElement : element;
48549  }
48550  function getScale(element) {
48551    const domElement = unwrapElement(element);
48552    if (!isHTMLElement4(domElement)) {
48553      return createCoords(1);
48554    }
48555    const rect = domElement.getBoundingClientRect();
48556    const {
48557      width,
48558      height,
48559      $: $2
48560    } = getCssDimensions(domElement);
48561    let x3 = ($2 ? round(rect.width) : rect.width) / width;
48562    let y3 = ($2 ? round(rect.height) : rect.height) / height;
48563    if (!x3 || !Number.isFinite(x3)) {
48564      x3 = 1;
48565    }
48566    if (!y3 || !Number.isFinite(y3)) {
48567      y3 = 1;
48568    }
48569    return {
48570      x: x3,
48571      y: y3
48572    };
48573  }
48574  var noOffsets = /* @__PURE__ */ createCoords(0);
48575  function getVisualOffsets(element) {
48576    const win = getWindow2(element);
48577    if (!isWebKit() || !win.visualViewport) {
48578      return noOffsets;
48579    }
48580    return {
48581      x: win.visualViewport.offsetLeft,
48582      y: win.visualViewport.offsetTop
48583    };
48584  }
48585  function shouldAddVisualOffsets(element, isFixed, floatingOffsetParent) {
48586    if (isFixed === void 0) {
48587      isFixed = false;
48588    }
48589    if (!floatingOffsetParent || isFixed && floatingOffsetParent !== getWindow2(element)) {
48590      return false;
48591    }
48592    return isFixed;
48593  }
48594  function getBoundingClientRect(element, includeScale, isFixedStrategy, offsetParent) {
48595    if (includeScale === void 0) {
48596      includeScale = false;
48597    }
48598    if (isFixedStrategy === void 0) {
48599      isFixedStrategy = false;
48600    }
48601    const clientRect = element.getBoundingClientRect();
48602    const domElement = unwrapElement(element);
48603    let scale = createCoords(1);
48604    if (includeScale) {
48605      if (offsetParent) {
48606        if (isElement(offsetParent)) {
48607          scale = getScale(offsetParent);
48608        }
48609      } else {
48610        scale = getScale(element);
48611      }
48612    }
48613    const visualOffsets = shouldAddVisualOffsets(domElement, isFixedStrategy, offsetParent) ? getVisualOffsets(domElement) : createCoords(0);
48614    let x3 = (clientRect.left + visualOffsets.x) / scale.x;
48615    let y3 = (clientRect.top + visualOffsets.y) / scale.y;
48616    let width = clientRect.width / scale.x;
48617    let height = clientRect.height / scale.y;
48618    if (domElement) {
48619      const win = getWindow2(domElement);
48620      const offsetWin = offsetParent && isElement(offsetParent) ? getWindow2(offsetParent) : offsetParent;
48621      let currentWin = win;
48622      let currentIFrame = getFrameElement(currentWin);
48623      while (currentIFrame && offsetParent && offsetWin !== currentWin) {
48624        const iframeScale = getScale(currentIFrame);
48625        const iframeRect = currentIFrame.getBoundingClientRect();
48626        const css = getComputedStyle2(currentIFrame);
48627        const left = iframeRect.left + (currentIFrame.clientLeft + parseFloat(css.paddingLeft)) * iframeScale.x;
48628        const top = iframeRect.top + (currentIFrame.clientTop + parseFloat(css.paddingTop)) * iframeScale.y;
48629        x3 *= iframeScale.x;
48630        y3 *= iframeScale.y;
48631        width *= iframeScale.x;
48632        height *= iframeScale.y;
48633        x3 += left;
48634        y3 += top;
48635        currentWin = getWindow2(currentIFrame);
48636        currentIFrame = getFrameElement(currentWin);
48637      }
48638    }
48639    return rectToClientRect({
48640      width,
48641      height,
48642      x: x3,
48643      y: y3
48644    });
48645  }
48646  function getWindowScrollBarX(element, rect) {
48647    const leftScroll = getNodeScroll(element).scrollLeft;
48648    if (!rect) {
48649      return getBoundingClientRect(getDocumentElement(element)).left + leftScroll;
48650    }
48651    return rect.left + leftScroll;
48652  }
48653  function getHTMLOffset(documentElement, scroll) {
48654    const htmlRect = documentElement.getBoundingClientRect();
48655    const x3 = htmlRect.left + scroll.scrollLeft - getWindowScrollBarX(documentElement, htmlRect);
48656    const y3 = htmlRect.top + scroll.scrollTop;
48657    return {
48658      x: x3,
48659      y: y3
48660    };
48661  }
48662  function convertOffsetParentRelativeRectToViewportRelativeRect(_ref2) {
48663    let {
48664      elements,
48665      rect,
48666      offsetParent,
48667      strategy
48668    } = _ref2;
48669    const isFixed = strategy === "fixed";
48670    const documentElement = getDocumentElement(offsetParent);
48671    const topLayer = elements ? isTopLayer(elements.floating) : false;
48672    if (offsetParent === documentElement || topLayer && isFixed) {
48673      return rect;
48674    }
48675    let scroll = {
48676      scrollLeft: 0,
48677      scrollTop: 0
48678    };
48679    let scale = createCoords(1);
48680    const offsets = createCoords(0);
48681    const isOffsetParentAnElement = isHTMLElement4(offsetParent);
48682    if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) {
48683      if (getNodeName(offsetParent) !== "body" || isOverflowElement(documentElement)) {
48684        scroll = getNodeScroll(offsetParent);
48685      }
48686      if (isOffsetParentAnElement) {
48687        const offsetRect = getBoundingClientRect(offsetParent);
48688        scale = getScale(offsetParent);
48689        offsets.x = offsetRect.x + offsetParent.clientLeft;
48690        offsets.y = offsetRect.y + offsetParent.clientTop;
48691      }
48692    }
48693    const htmlOffset = documentElement && !isOffsetParentAnElement && !isFixed ? getHTMLOffset(documentElement, scroll) : createCoords(0);
48694    return {
48695      width: rect.width * scale.x,
48696      height: rect.height * scale.y,
48697      x: rect.x * scale.x - scroll.scrollLeft * scale.x + offsets.x + htmlOffset.x,
48698      y: rect.y * scale.y - scroll.scrollTop * scale.y + offsets.y + htmlOffset.y
48699    };
48700  }
48701  function getClientRects(element) {
48702    return Array.from(element.getClientRects());
48703  }
48704  function getDocumentRect(element) {
48705    const html2 = getDocumentElement(element);
48706    const scroll = getNodeScroll(element);
48707    const body = element.ownerDocument.body;
48708    const width = max(html2.scrollWidth, html2.clientWidth, body.scrollWidth, body.clientWidth);
48709    const height = max(html2.scrollHeight, html2.clientHeight, body.scrollHeight, body.clientHeight);
48710    let x3 = -scroll.scrollLeft + getWindowScrollBarX(element);
48711    const y3 = -scroll.scrollTop;
48712    if (getComputedStyle2(body).direction === "rtl") {
48713      x3 += max(html2.clientWidth, body.clientWidth) - width;
48714    }
48715    return {
48716      width,
48717      height,
48718      x: x3,
48719      y: y3
48720    };
48721  }
48722  var SCROLLBAR_MAX = 25;
48723  function getViewportRect(element, strategy) {
48724    const win = getWindow2(element);
48725    const html2 = getDocumentElement(element);
48726    const visualViewport = win.visualViewport;
48727    let width = html2.clientWidth;
48728    let height = html2.clientHeight;
48729    let x3 = 0;
48730    let y3 = 0;
48731    if (visualViewport) {
48732      width = visualViewport.width;
48733      height = visualViewport.height;
48734      const visualViewportBased = isWebKit();
48735      if (!visualViewportBased || visualViewportBased && strategy === "fixed") {
48736        x3 = visualViewport.offsetLeft;
48737        y3 = visualViewport.offsetTop;
48738      }
48739    }
48740    const windowScrollbarX = getWindowScrollBarX(html2);
48741    if (windowScrollbarX <= 0) {
48742      const doc = html2.ownerDocument;
48743      const body = doc.body;
48744      const bodyStyles = getComputedStyle(body);
48745      const bodyMarginInline = doc.compatMode === "CSS1Compat" ? parseFloat(bodyStyles.marginLeft) + parseFloat(bodyStyles.marginRight) || 0 : 0;
48746      const clippingStableScrollbarWidth = Math.abs(html2.clientWidth - body.clientWidth - bodyMarginInline);
48747      if (clippingStableScrollbarWidth <= SCROLLBAR_MAX) {
48748        width -= clippingStableScrollbarWidth;
48749      }
48750    } else if (windowScrollbarX <= SCROLLBAR_MAX) {
48751      width += windowScrollbarX;
48752    }
48753    return {
48754      width,
48755      height,
48756      x: x3,
48757      y: y3
48758    };
48759  }
48760  function getInnerBoundingClientRect(element, strategy) {
48761    const clientRect = getBoundingClientRect(element, true, strategy === "fixed");
48762    const top = clientRect.top + element.clientTop;
48763    const left = clientRect.left + element.clientLeft;
48764    const scale = isHTMLElement4(element) ? getScale(element) : createCoords(1);
48765    const width = element.clientWidth * scale.x;
48766    const height = element.clientHeight * scale.y;
48767    const x3 = left * scale.x;
48768    const y3 = top * scale.y;
48769    return {
48770      width,
48771      height,
48772      x: x3,
48773      y: y3
48774    };
48775  }
48776  function getClientRectFromClippingAncestor(element, clippingAncestor, strategy) {
48777    let rect;
48778    if (clippingAncestor === "viewport") {
48779      rect = getViewportRect(element, strategy);
48780    } else if (clippingAncestor === "document") {
48781      rect = getDocumentRect(getDocumentElement(element));
48782    } else if (isElement(clippingAncestor)) {
48783      rect = getInnerBoundingClientRect(clippingAncestor, strategy);
48784    } else {
48785      const visualOffsets = getVisualOffsets(element);
48786      rect = {
48787        x: clippingAncestor.x - visualOffsets.x,
48788        y: clippingAncestor.y - visualOffsets.y,
48789        width: clippingAncestor.width,
48790        height: clippingAncestor.height
48791      };
48792    }
48793    return rectToClientRect(rect);
48794  }
48795  function hasFixedPositionAncestor(element, stopNode) {
48796    const parentNode = getParentNode(element);
48797    if (parentNode === stopNode || !isElement(parentNode) || isLastTraversableNode(parentNode)) {
48798      return false;
48799    }
48800    return getComputedStyle2(parentNode).position === "fixed" || hasFixedPositionAncestor(parentNode, stopNode);
48801  }
48802  function getClippingElementAncestors(element, cache) {
48803    const cachedResult = cache.get(element);
48804    if (cachedResult) {
48805      return cachedResult;
48806    }
48807    let result = getOverflowAncestors(element, [], false).filter((el) => isElement(el) && getNodeName(el) !== "body");
48808    let currentContainingBlockComputedStyle = null;
48809    const elementIsFixed = getComputedStyle2(element).position === "fixed";
48810    let currentNode = elementIsFixed ? getParentNode(element) : element;
48811    while (isElement(currentNode) && !isLastTraversableNode(currentNode)) {
48812      const computedStyle = getComputedStyle2(currentNode);
48813      const currentNodeIsContaining = isContainingBlock(currentNode);
48814      if (!currentNodeIsContaining && computedStyle.position === "fixed") {
48815        currentContainingBlockComputedStyle = null;
48816      }
48817      const shouldDropCurrentNode = elementIsFixed ? !currentNodeIsContaining && !currentContainingBlockComputedStyle : !currentNodeIsContaining && computedStyle.position === "static" && !!currentContainingBlockComputedStyle && (currentContainingBlockComputedStyle.position === "absolute" || currentContainingBlockComputedStyle.position === "fixed") || isOverflowElement(currentNode) && !currentNodeIsContaining && hasFixedPositionAncestor(element, currentNode);
48818      if (shouldDropCurrentNode) {
48819        result = result.filter((ancestor) => ancestor !== currentNode);
48820      } else {
48821        currentContainingBlockComputedStyle = computedStyle;
48822      }
48823      currentNode = getParentNode(currentNode);
48824    }
48825    cache.set(element, result);
48826    return result;
48827  }
48828  function getClippingRect(_ref2) {
48829    let {
48830      element,
48831      boundary,
48832      rootBoundary,
48833      strategy
48834    } = _ref2;
48835    const elementClippingAncestors = boundary === "clippingAncestors" ? isTopLayer(element) ? [] : getClippingElementAncestors(element, this._c) : [].concat(boundary);
48836    const clippingAncestors = [...elementClippingAncestors, rootBoundary];
48837    const firstRect = getClientRectFromClippingAncestor(element, clippingAncestors[0], strategy);
48838    let top = firstRect.top;
48839    let right = firstRect.right;
48840    let bottom = firstRect.bottom;
48841    let left = firstRect.left;
48842    for (let i2 = 1; i2 < clippingAncestors.length; i2++) {
48843      const rect = getClientRectFromClippingAncestor(element, clippingAncestors[i2], strategy);
48844      top = max(rect.top, top);
48845      right = min(rect.right, right);
48846      bottom = min(rect.bottom, bottom);
48847      left = max(rect.left, left);
48848    }
48849    return {
48850      width: right - left,
48851      height: bottom - top,
48852      x: left,
48853      y: top
48854    };
48855  }
48856  function getDimensions(element) {
48857    const {
48858      width,
48859      height
48860    } = getCssDimensions(element);
48861    return {
48862      width,
48863      height
48864    };
48865  }
48866  function getRectRelativeToOffsetParent(element, offsetParent, strategy) {
48867    const isOffsetParentAnElement = isHTMLElement4(offsetParent);
48868    const documentElement = getDocumentElement(offsetParent);
48869    const isFixed = strategy === "fixed";
48870    const rect = getBoundingClientRect(element, true, isFixed, offsetParent);
48871    let scroll = {
48872      scrollLeft: 0,
48873      scrollTop: 0
48874    };
48875    const offsets = createCoords(0);
48876    function setLeftRTLScrollbarOffset() {
48877      offsets.x = getWindowScrollBarX(documentElement);
48878    }
48879    if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) {
48880      if (getNodeName(offsetParent) !== "body" || isOverflowElement(documentElement)) {
48881        scroll = getNodeScroll(offsetParent);
48882      }
48883      if (isOffsetParentAnElement) {
48884        const offsetRect = getBoundingClientRect(offsetParent, true, isFixed, offsetParent);
48885        offsets.x = offsetRect.x + offsetParent.clientLeft;
48886        offsets.y = offsetRect.y + offsetParent.clientTop;
48887      } else if (documentElement) {
48888        setLeftRTLScrollbarOffset();
48889      }
48890    }
48891    if (isFixed && !isOffsetParentAnElement && documentElement) {
48892      setLeftRTLScrollbarOffset();
48893    }
48894    const htmlOffset = documentElement && !isOffsetParentAnElement && !isFixed ? getHTMLOffset(documentElement, scroll) : createCoords(0);
48895    const x3 = rect.left + scroll.scrollLeft - offsets.x - htmlOffset.x;
48896    const y3 = rect.top + scroll.scrollTop - offsets.y - htmlOffset.y;
48897    return {
48898      x: x3,
48899      y: y3,
48900      width: rect.width,
48901      height: rect.height
48902    };
48903  }
48904  function isStaticPositioned(element) {
48905    return getComputedStyle2(element).position === "static";
48906  }
48907  function getTrueOffsetParent(element, polyfill) {
48908    if (!isHTMLElement4(element) || getComputedStyle2(element).position === "fixed") {
48909      return null;
48910    }
48911    if (polyfill) {
48912      return polyfill(element);
48913    }
48914    let rawOffsetParent = element.offsetParent;
48915    if (getDocumentElement(element) === rawOffsetParent) {
48916      rawOffsetParent = rawOffsetParent.ownerDocument.body;
48917    }
48918    return rawOffsetParent;
48919  }
48920  function getOffsetParent(element, polyfill) {
48921    const win = getWindow2(element);
48922    if (isTopLayer(element)) {
48923      return win;
48924    }
48925    if (!isHTMLElement4(element)) {
48926      let svgOffsetParent = getParentNode(element);
48927      while (svgOffsetParent && !isLastTraversableNode(svgOffsetParent)) {
48928        if (isElement(svgOffsetParent) && !isStaticPositioned(svgOffsetParent)) {
48929          return svgOffsetParent;
48930        }
48931        svgOffsetParent = getParentNode(svgOffsetParent);
48932      }
48933      return win;
48934    }
48935    let offsetParent = getTrueOffsetParent(element, polyfill);
48936    while (offsetParent && isTableElement(offsetParent) && isStaticPositioned(offsetParent)) {
48937      offsetParent = getTrueOffsetParent(offsetParent, polyfill);
48938    }
48939    if (offsetParent && isLastTraversableNode(offsetParent) && isStaticPositioned(offsetParent) && !isContainingBlock(offsetParent)) {
48940      return win;
48941    }
48942    return offsetParent || getContainingBlock(element) || win;
48943  }
48944  var getElementRects = async function(data) {
48945    const getOffsetParentFn = this.getOffsetParent || getOffsetParent;
48946    const getDimensionsFn = this.getDimensions;
48947    const floatingDimensions = await getDimensionsFn(data.floating);
48948    return {
48949      reference: getRectRelativeToOffsetParent(data.reference, await getOffsetParentFn(data.floating), data.strategy),
48950      floating: {
48951        x: 0,
48952        y: 0,
48953        width: floatingDimensions.width,
48954        height: floatingDimensions.height
48955      }
48956    };
48957  };
48958  function isRTL(element) {
48959    return getComputedStyle2(element).direction === "rtl";
48960  }
48961  var platform = {
48962    convertOffsetParentRelativeRectToViewportRelativeRect,
48963    getDocumentElement,
48964    getClippingRect,
48965    getOffsetParent,
48966    getElementRects,
48967    getClientRects,
48968    getDimensions,
48969    getScale,
48970    isElement,
48971    isRTL
48972  };
48973  function rectsAreEqual(a2, b3) {
48974    return a2.x === b3.x && a2.y === b3.y && a2.width === b3.width && a2.height === b3.height;
48975  }
48976  function observeMove(element, onMove) {
48977    let io = null;
48978    let timeoutId;
48979    const root = getDocumentElement(element);
48980    function cleanup() {
48981      var _io;
48982      clearTimeout(timeoutId);
48983      (_io = io) == null || _io.disconnect();
48984      io = null;
48985    }
48986    function refresh(skip, threshold) {
48987      if (skip === void 0) {
48988        skip = false;
48989      }
48990      if (threshold === void 0) {
48991        threshold = 1;
48992      }
48993      cleanup();
48994      const elementRectForRootMargin = element.getBoundingClientRect();
48995      const {
48996        left,
48997        top,
48998        width,
48999        height
49000      } = elementRectForRootMargin;
49001      if (!skip) {
49002        onMove();
49003      }
49004      if (!width || !height) {
49005        return;
49006      }
49007      const insetTop = floor(top);
49008      const insetRight = floor(root.clientWidth - (left + width));
49009      const insetBottom = floor(root.clientHeight - (top + height));
49010      const insetLeft = floor(left);
49011      const rootMargin = -insetTop + "px " + -insetRight + "px " + -insetBottom + "px " + -insetLeft + "px";
49012      const options = {
49013        rootMargin,
49014        threshold: max(0, min(1, threshold)) || 1
49015      };
49016      let isFirstUpdate = true;
49017      function handleObserve(entries2) {
49018        const ratio = entries2[0].intersectionRatio;
49019        if (ratio !== threshold) {
49020          if (!isFirstUpdate) {
49021            return refresh();
49022          }
49023          if (!ratio) {
49024            timeoutId = setTimeout(() => {
49025              refresh(false, 1e-7);
49026            }, 1e3);
49027          } else {
49028            refresh(false, ratio);
49029          }
49030        }
49031        if (ratio === 1 && !rectsAreEqual(elementRectForRootMargin, element.getBoundingClientRect())) {
49032          refresh();
49033        }
49034        isFirstUpdate = false;
49035      }
49036      try {
49037        io = new IntersectionObserver(handleObserve, {
49038          ...options,
49039          // Handle <iframe>s
49040          root: root.ownerDocument
49041        });
49042      } catch (_e2) {
49043        io = new IntersectionObserver(handleObserve, options);
49044      }
49045      io.observe(element);
49046    }
49047    refresh(true);
49048    return cleanup;
49049  }
49050  function autoUpdate(reference, floating, update, options) {
49051    if (options === void 0) {
49052      options = {};
49053    }
49054    const {
49055      ancestorScroll = true,
49056      ancestorResize = true,
49057      elementResize = typeof ResizeObserver === "function",
49058      layoutShift = typeof IntersectionObserver === "function",
49059      animationFrame = false
49060    } = options;
49061    const referenceEl = unwrapElement(reference);
49062    const ancestors = ancestorScroll || ancestorResize ? [...referenceEl ? getOverflowAncestors(referenceEl) : [], ...floating ? getOverflowAncestors(floating) : []] : [];
49063    ancestors.forEach((ancestor) => {
49064      ancestorScroll && ancestor.addEventListener("scroll", update, {
49065        passive: true
49066      });
49067      ancestorResize && ancestor.addEventListener("resize", update);
49068    });
49069    const cleanupIo = referenceEl && layoutShift ? observeMove(referenceEl, update) : null;
49070    let reobserveFrame = -1;
49071    let resizeObserver = null;
49072    if (elementResize) {
49073      resizeObserver = new ResizeObserver((_ref2) => {
49074        let [firstEntry] = _ref2;
49075        if (firstEntry && firstEntry.target === referenceEl && resizeObserver && floating) {
49076          resizeObserver.unobserve(floating);
49077          cancelAnimationFrame(reobserveFrame);
49078          reobserveFrame = requestAnimationFrame(() => {
49079            var _resizeObserver;
49080            (_resizeObserver = resizeObserver) == null || _resizeObserver.observe(floating);
49081          });
49082        }
49083        update();
49084      });
49085      if (referenceEl && !animationFrame) {
49086        resizeObserver.observe(referenceEl);
49087      }
49088      if (floating) {
49089        resizeObserver.observe(floating);
49090      }
49091    }
49092    let frameId;
49093    let prevRefRect = animationFrame ? getBoundingClientRect(reference) : null;
49094    if (animationFrame) {
49095      frameLoop();
49096    }
49097    function frameLoop() {
49098      const nextRefRect = getBoundingClientRect(reference);
49099      if (prevRefRect && !rectsAreEqual(prevRefRect, nextRefRect)) {
49100        update();
49101      }
49102      prevRefRect = nextRefRect;
49103      frameId = requestAnimationFrame(frameLoop);
49104    }
49105    update();
49106    return () => {
49107      var _resizeObserver2;
49108      ancestors.forEach((ancestor) => {
49109        ancestorScroll && ancestor.removeEventListener("scroll", update);
49110        ancestorResize && ancestor.removeEventListener("resize", update);
49111      });
49112      cleanupIo == null || cleanupIo();
49113      (_resizeObserver2 = resizeObserver) == null || _resizeObserver2.disconnect();
49114      resizeObserver = null;
49115      if (animationFrame) {
49116        cancelAnimationFrame(frameId);
49117      }
49118    };
49119  }
49120  var offset2 = offset;
49121  var shift2 = shift;
49122  var flip2 = flip;
49123  var computePosition2 = (reference, floating, options) => {
49124    const cache = /* @__PURE__ */ new Map();
49125    const mergedOptions = {
49126      platform,
49127      ...options
49128    };
49129    const platformWithCache = {
49130      ...mergedOptions.platform,
49131      _c: cache
49132    };
49133    return computePosition(reference, floating, {
49134      ...mergedOptions,
49135      platform: platformWithCache
49136    });
49137  };
49138
49139  
49139// app/javascript/src/lexxy/callout_image_uploader.js
49140  var CALLOUT_ICON_TYPES = ["image/jpeg", "image/png", "image/webp", "image/gif"];
49141  var MAX_CALLOUT_ICON_BYTES = 1024 * 1024;
49142  function isCalloutIconFile(file) {
49143    return file && CALLOUT_ICON_TYPES.includes(file.type) && file.size <= MAX_CALLOUT_ICON_BYTES;
49144  }
49145  function uploadCalloutIcon(editorElement, file) {
49146    const uploadUrl = editorElement.directUploadUrl;
49147    const blobUrlTemplate = editorElement.blobUrlTemplate;
49148    if (!uploadUrl || !blobUrlTemplate) {
49149      return Promise.reject(new Error("Direct upload is not configured for this editor"));
49150    }
49151    if (!isCalloutIconFile(file)) {
49152      return Promise.reject(new Error("Please choose a PNG, JPG, WEBP, or GIF under 1MB"));
49153    }
49154    return Promise.resolve().then(() => (init_activestorage_esm(), activestorage_esm_exports)).then(({ DirectUpload: DirectUpload3 }) => {
49155      return new Promise((resolve, reject) => {
49156        const upload = new DirectUpload3(file, uploadUrl, {
49157          directUploadWillCreateBlobWithXHR(request) {
49158            request.withCredentials = true;
49159          },
49160          directUploadWillStoreFileWithXHR(request) {
49161            request.withCredentials = true;
49162          }
49163        });
49164        upload.create((error, blob) => {
49165          if (error) {
49166            reject(error);
49167            return;
49168          }
49169          const url = blob.previewable ? blob.url : blobUrlTemplate.replace(":signed_id", blob.signed_id).replace(":filename", encodeURIComponent(blob.filename));
49170          resolve(url);
49171        });
49172      });
49173    });
49174  }
49175
49176  
vendor: 139,589 bytes, lines 49176-51762
49176// node_modules/emoji-mart/dist/module.js
49177  function $parcel$interopDefault(a2) {
49178    return a2 && a2.__esModule ? a2.default : a2;
49179  }
49180  function $c770c458706daa72$export$2e2bcd8739ae039(obj, key, value) {
49181    if (key in obj) Object.defineProperty(obj, key, {
49182      value,
49183      enumerable: true,
49184      configurable: true,
49185      writable: true
49186    });
49187    else obj[key] = value;
49188    return obj;
49189  }
49190  var $fb96b826c0c5f37a$var$n;
49191  var $fb96b826c0c5f37a$export$41c562ebe57d11e2;
49192  var $fb96b826c0c5f37a$var$u;
49193  var $fb96b826c0c5f37a$export$a8257692ac88316c;
49194  var $fb96b826c0c5f37a$var$t;
49195  var $fb96b826c0c5f37a$var$r;
49196  var $fb96b826c0c5f37a$var$o;
49197  var $fb96b826c0c5f37a$var$f;
49198  var $fb96b826c0c5f37a$var$e = {};
49199  var $fb96b826c0c5f37a$var$c = [];
49200  var $fb96b826c0c5f37a$var$s = /acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i;
49201  function $fb96b826c0c5f37a$var$a(n1, l1) {
49202    for (var u1 in l1) n1[u1] = l1[u1];
49203    return n1;
49204  }
49205  function $fb96b826c0c5f37a$var$h(n2) {
49206    var l22 = n2.parentNode;
49207    l22 && l22.removeChild(n2);
49208  }
49209  function $fb96b826c0c5f37a$export$c8a8987d4410bf2d(l32, u2, i1) {
49210    var t1, r1, o1, f1 = {};
49211    for (o1 in u2) "key" == o1 ? t1 = u2[o1] : "ref" == o1 ? r1 = u2[o1] : f1[o1] = u2[o1];
49212    if (arguments.length > 2 && (f1.children = arguments.length > 3 ? $fb96b826c0c5f37a$var$n.call(arguments, 2) : i1), "function" == typeof l32 && null != l32.defaultProps) for (o1 in l32.defaultProps) void 0 === f1[o1] && (f1[o1] = l32.defaultProps[o1]);
49213    return $fb96b826c0c5f37a$var$y(l32, f1, t1, r1, null);
49214  }
49215  function $fb96b826c0c5f37a$var$y(n3, i2, t2, r2, o2) {
49216    var f2 = {
49217      type: n3,
49218      props: i2,
49219      key: t2,
49220      ref: r2,
49221      __k: null,
49222      __: null,
49223      __b: 0,
49224      __e: null,
49225      __d: void 0,
49226      __c: null,
49227      __h: null,
49228      constructor: void 0,
49229      __v: null == o2 ? ++$fb96b826c0c5f37a$var$u : o2
49230    };
49231    return null == o2 && null != $fb96b826c0c5f37a$export$41c562ebe57d11e2.vnode && $fb96b826c0c5f37a$export$41c562ebe57d11e2.vnode(f2), f2;
49232  }
49233  function $fb96b826c0c5f37a$export$7d1e3a5e95ceca43() {
49234    return {
49235      current: null
49236    };
49237  }
49238  function $fb96b826c0c5f37a$export$ffb0004e005737fa(n4) {
49239    return n4.children;
49240  }
49241  function $fb96b826c0c5f37a$export$16fa2f45be04daa8(n5, l4) {
49242    this.props = n5, this.context = l4;
49243  }
49244  function $fb96b826c0c5f37a$var$k(n6, l5) {
49245    if (null == l5) return n6.__ ? $fb96b826c0c5f37a$var$k(n6.__, n6.__.__k.indexOf(n6) + 1) : null;
49246    for (var u3; l5 < n6.__k.length; l5++) if (null != (u3 = n6.__k[l5]) && null != u3.__e) return u3.__e;
49247    return "function" == typeof n6.type ? $fb96b826c0c5f37a$var$k(n6) : null;
49248  }
49249  function $fb96b826c0c5f37a$var$b(n7) {
49250    var l6, u4;
49251    if (null != (n7 = n7.__) && null != n7.__c) {
49252      for (n7.__e = n7.__c.base = null, l6 = 0; l6 < n7.__k.length; l6++) if (null != (u4 = n7.__k[l6]) && null != u4.__e) {
49253        n7.__e = n7.__c.base = u4.__e;
49254        break;
49255      }
49256      return $fb96b826c0c5f37a$var$b(n7);
49257    }
49258  }
49259  function $fb96b826c0c5f37a$var$m(n8) {
49260    (!n8.__d && (n8.__d = true) && $fb96b826c0c5f37a$var$t.push(n8) && !$fb96b826c0c5f37a$var$g.__r++ || $fb96b826c0c5f37a$var$o !== $fb96b826c0c5f37a$export$41c562ebe57d11e2.debounceRendering) && (($fb96b826c0c5f37a$var$o = $fb96b826c0c5f37a$export$41c562ebe57d11e2.debounceRendering) || $fb96b826c0c5f37a$var$r)($fb96b826c0c5f37a$var$g);
49261  }
49262  function $fb96b826c0c5f37a$var$g() {
49263    for (var n9; $fb96b826c0c5f37a$var$g.__r = $fb96b826c0c5f37a$var$t.length; ) n9 = $fb96b826c0c5f37a$var$t.sort(function(n10, l7) {
49264      return n10.__v.__b - l7.__v.__b;
49265    }), $fb96b826c0c5f37a$var$t = [], n9.some(function(n11) {
49266      var l8, u5, i3, t3, r3, o3;
49267      n11.__d && (r3 = (t3 = (l8 = n11).__v).__e, (o3 = l8.__P) && (u5 = [], (i3 = $fb96b826c0c5f37a$var$a({}, t3)).__v = t3.__v + 1, $fb96b826c0c5f37a$var$j(o3, t3, i3, l8.__n, void 0 !== o3.ownerSVGElement, null != t3.__h ? [
49268        r3
49269      ] : null, u5, null == r3 ? $fb96b826c0c5f37a$var$k(t3) : r3, t3.__h), $fb96b826c0c5f37a$var$z(u5, t3), t3.__e != r3 && $fb96b826c0c5f37a$var$b(t3)));
49270    });
49271  }
49272  function $fb96b826c0c5f37a$var$w(n12, l9, u6, i4, t4, r4, o4, f3, s1, a1) {
49273    var h1, v1, p1, _1, b1, m1, g1, w1 = i4 && i4.__k || $fb96b826c0c5f37a$var$c, A1 = w1.length;
49274    for (u6.__k = [], h1 = 0; h1 < l9.length; h1++) if (null != (_1 = u6.__k[h1] = null == (_1 = l9[h1]) || "boolean" == typeof _1 ? null : "string" == typeof _1 || "number" == typeof _1 || "bigint" == typeof _1 ? $fb96b826c0c5f37a$var$y(null, _1, null, null, _1) : Array.isArray(_1) ? $fb96b826c0c5f37a$var$y($fb96b826c0c5f37a$export$ffb0004e005737fa, {
49275      children: _1
49276    }, null, null, null) : _1.__b > 0 ? $fb96b826c0c5f37a$var$y(_1.type, _1.props, _1.key, null, _1.__v) : _1)) {
49277      if (_1.__ = u6, _1.__b = u6.__b + 1, null === (p1 = w1[h1]) || p1 && _1.key == p1.key && _1.type === p1.type) w1[h1] = void 0;
49278      else for (v1 = 0; v1 < A1; v1++) {
49279        if ((p1 = w1[v1]) && _1.key == p1.key && _1.type === p1.type) {
49280          w1[v1] = void 0;
49281          break;
49282        }
49283        p1 = null;
49284      }
49285      $fb96b826c0c5f37a$var$j(n12, _1, p1 = p1 || $fb96b826c0c5f37a$var$e, t4, r4, o4, f3, s1, a1), b1 = _1.__e, (v1 = _1.ref) && p1.ref != v1 && (g1 || (g1 = []), p1.ref && g1.push(p1.ref, null, _1), g1.push(v1, _1.__c || b1, _1)), null != b1 ? (null == m1 && (m1 = b1), "function" == typeof _1.type && _1.__k === p1.__k ? _1.__d = s1 = $fb96b826c0c5f37a$var$x(_1, s1, n12) : s1 = $fb96b826c0c5f37a$var$P(n12, _1, p1, w1, b1, s1), "function" == typeof u6.type && (u6.__d = s1)) : s1 && p1.__e == s1 && s1.parentNode != n12 && (s1 = $fb96b826c0c5f37a$var$k(p1));
49286    }
49287    for (u6.__e = m1, h1 = A1; h1--; ) null != w1[h1] && ("function" == typeof u6.type && null != w1[h1].__e && w1[h1].__e == u6.__d && (u6.__d = $fb96b826c0c5f37a$var$k(i4, h1 + 1)), $fb96b826c0c5f37a$var$N(w1[h1], w1[h1]));
49288    if (g1) for (h1 = 0; h1 < g1.length; h1++) $fb96b826c0c5f37a$var$M(g1[h1], g1[++h1], g1[++h1]);
49289  }
49290  function $fb96b826c0c5f37a$var$x(n13, l10, u7) {
49291    for (var i5, t5 = n13.__k, r5 = 0; t5 && r5 < t5.length; r5++) (i5 = t5[r5]) && (i5.__ = n13, l10 = "function" == typeof i5.type ? $fb96b826c0c5f37a$var$x(i5, l10, u7) : $fb96b826c0c5f37a$var$P(u7, i5, i5, t5, i5.__e, l10));
49292    return l10;
49293  }
49294  function $fb96b826c0c5f37a$export$47e4c5b300681277(n14, l11) {
49295    return l11 = l11 || [], null == n14 || "boolean" == typeof n14 || (Array.isArray(n14) ? n14.some(function(n15) {
49296      $fb96b826c0c5f37a$export$47e4c5b300681277(n15, l11);
49297    }) : l11.push(n14)), l11;
49298  }
49299  function $fb96b826c0c5f37a$var$P(n16, l12, u8, i6, t6, r6) {
49300    var o5, f4, e1;
49301    if (void 0 !== l12.__d) o5 = l12.__d, l12.__d = void 0;
49302    else if (null == u8 || t6 != r6 || null == t6.parentNode) n: if (null == r6 || r6.parentNode !== n16) n16.appendChild(t6), o5 = null;
49303    else {
49304      for (f4 = r6, e1 = 0; (f4 = f4.nextSibling) && e1 < i6.length; e1 += 2) if (f4 == t6) break n;
49305      n16.insertBefore(t6, r6), o5 = r6;
49306    }
49307    return void 0 !== o5 ? o5 : t6.nextSibling;
49308  }
49309  function $fb96b826c0c5f37a$var$C(n17, l13, u9, i7, t7) {
49310    var r7;
49311    for (r7 in u9) "children" === r7 || "key" === r7 || r7 in l13 || $fb96b826c0c5f37a$var$H(n17, r7, null, u9[r7], i7);
49312    for (r7 in l13) t7 && "function" != typeof l13[r7] || "children" === r7 || "key" === r7 || "value" === r7 || "checked" === r7 || u9[r7] === l13[r7] || $fb96b826c0c5f37a$var$H(n17, r7, l13[r7], u9[r7], i7);
49313  }
49314  function $fb96b826c0c5f37a$var$$(n18, l14, u10) {
49315    "-" === l14[0] ? n18.setProperty(l14, u10) : n18[l14] = null == u10 ? "" : "number" != typeof u10 || $fb96b826c0c5f37a$var$s.test(l14) ? u10 : u10 + "px";
49316  }
49317  function $fb96b826c0c5f37a$var$H(n19, l15, u11, i8, t8) {
49318    var r8;
49319    n: if ("style" === l15) {
49320      if ("string" == typeof u11) n19.style.cssText = u11;
49321      else {
49322        if ("string" == typeof i8 && (n19.style.cssText = i8 = ""), i8) for (l15 in i8) u11 && l15 in u11 || $fb96b826c0c5f37a$var$$(n19.style, l15, "");
49323        if (u11) for (l15 in u11) i8 && u11[l15] === i8[l15] || $fb96b826c0c5f37a$var$$(n19.style, l15, u11[l15]);
49324      }
49325    } else if ("o" === l15[0] && "n" === l15[1]) r8 = l15 !== (l15 = l15.replace(/Capture$/, "")), l15 = l15.toLowerCase() in n19 ? l15.toLowerCase().slice(2) : l15.slice(2), n19.l || (n19.l = {}), n19.l[l15 + r8] = u11, u11 ? i8 || n19.addEventListener(l15, r8 ? $fb96b826c0c5f37a$var$T : $fb96b826c0c5f37a$var$I, r8) : n19.removeEventListener(l15, r8 ? $fb96b826c0c5f37a$var$T : $fb96b826c0c5f37a$var$I, r8);
49326    else if ("dangerouslySetInnerHTML" !== l15) {
49327      if (t8) l15 = l15.replace(/xlink[H:h]/, "h").replace(/sName$/, "s");
49328      else if ("href" !== l15 && "list" !== l15 && "form" !== l15 && "tabIndex" !== l15 && "download" !== l15 && l15 in n19) try {
49329        n19[l15] = null == u11 ? "" : u11;
49330        break n;
49331      } catch (n2) {
49332      }
49333      "function" == typeof u11 || (null != u11 && (false !== u11 || "a" === l15[0] && "r" === l15[1]) ? n19.setAttribute(l15, u11) : n19.removeAttribute(l15));
49334    }
49335  }
49336  function $fb96b826c0c5f37a$var$I(n20) {
49337    this.l[n20.type + false]($fb96b826c0c5f37a$export$41c562ebe57d11e2.event ? $fb96b826c0c5f37a$export$41c562ebe57d11e2.event(n20) : n20);
49338  }
49339  function $fb96b826c0c5f37a$var$T(n21) {
49340    this.l[n21.type + true]($fb96b826c0c5f37a$export$41c562ebe57d11e2.event ? $fb96b826c0c5f37a$export$41c562ebe57d11e2.event(n21) : n21);
49341  }
49342  function $fb96b826c0c5f37a$var$j(n22, u12, i9, t9, r9, o6, f5, e2, c1) {
49343    var s2, h2, v22, y1, p2, k1, b22, m22, g2, x1, A2, P1 = u12.type;
49344    if (void 0 !== u12.constructor) return null;
49345    null != i9.__h && (c1 = i9.__h, e2 = u12.__e = i9.__e, u12.__h = null, o6 = [
49346      e2
49347    ]), (s2 = $fb96b826c0c5f37a$export$41c562ebe57d11e2.__b) && s2(u12);
49348    try {
49349      n: if ("function" == typeof P1) {
49350        if (m22 = u12.props, g2 = (s2 = P1.contextType) && t9[s2.__c], x1 = s2 ? g2 ? g2.props.value : s2.__ : t9, i9.__c ? b22 = (h2 = u12.__c = i9.__c).__ = h2.__E : ("prototype" in P1 && P1.prototype.render ? u12.__c = h2 = new P1(m22, x1) : (u12.__c = h2 = new $fb96b826c0c5f37a$export$16fa2f45be04daa8(m22, x1), h2.constructor = P1, h2.render = $fb96b826c0c5f37a$var$O), g2 && g2.sub(h2), h2.props = m22, h2.state || (h2.state = {}), h2.context = x1, h2.__n = t9, v22 = h2.__d = true, h2.__h = []), null == h2.__s && (h2.__s = h2.state), null != P1.getDerivedStateFromProps && (h2.__s == h2.state && (h2.__s = $fb96b826c0c5f37a$var$a({}, h2.__s)), $fb96b826c0c5f37a$var$a(h2.__s, P1.getDerivedStateFromProps(m22, h2.__s))), y1 = h2.props, p2 = h2.state, v22) null == P1.getDerivedStateFromProps && null != h2.componentWillMount && h2.componentWillMount(), null != h2.componentDidMount && h2.__h.push(h2.componentDidMount);
49351        else {
49352          if (null == P1.getDerivedStateFromProps && m22 !== y1 && null != h2.componentWillReceiveProps && h2.componentWillReceiveProps(m22, x1), !h2.__e && null != h2.shouldComponentUpdate && false === h2.shouldComponentUpdate(m22, h2.__s, x1) || u12.__v === i9.__v) {
49353            h2.props = m22, h2.state = h2.__s, u12.__v !== i9.__v && (h2.__d = false), h2.__v = u12, u12.__e = i9.__e, u12.__k = i9.__k, u12.__k.forEach(function(n23) {
49354              n23 && (n23.__ = u12);
49355            }), h2.__h.length && f5.push(h2);
49356            break n;
49357          }
49358          null != h2.componentWillUpdate && h2.componentWillUpdate(m22, h2.__s, x1), null != h2.componentDidUpdate && h2.__h.push(function() {
49359            h2.componentDidUpdate(y1, p2, k1);
49360          });
49361        }
49362        h2.context = x1, h2.props = m22, h2.state = h2.__s, (s2 = $fb96b826c0c5f37a$export$41c562ebe57d11e2.__r) && s2(u12), h2.__d = false, h2.__v = u12, h2.__P = n22, s2 = h2.render(h2.props, h2.state, h2.context), h2.state = h2.__s, null != h2.getChildContext && (t9 = $fb96b826c0c5f37a$var$a($fb96b826c0c5f37a$var$a({}, t9), h2.getChildContext())), v22 || null == h2.getSnapshotBeforeUpdate || (k1 = h2.getSnapshotBeforeUpdate(y1, p2)), A2 = null != s2 && s2.type === $fb96b826c0c5f37a$export$ffb0004e005737fa && null == s2.key ? s2.props.children : s2, $fb96b826c0c5f37a$var$w(n22, Array.isArray(A2) ? A2 : [
49363          A2
49364        ], u12, i9, t9, r9, o6, f5, e2, c1), h2.base = u12.__e, u12.__h = null, h2.__h.length && f5.push(h2), b22 && (h2.__E = h2.__ = null), h2.__e = false;
49365      } else null == o6 && u12.__v === i9.__v ? (u12.__k = i9.__k, u12.__e = i9.__e) : u12.__e = $fb96b826c0c5f37a$var$L(i9.__e, u12, i9, t9, r9, o6, f5, c1);
49366      (s2 = $fb96b826c0c5f37a$export$41c562ebe57d11e2.diffed) && s2(u12);
49367    } catch (n24) {
49368      u12.__v = null, (c1 || null != o6) && (u12.__e = e2, u12.__h = !!c1, o6[o6.indexOf(e2)] = null), $fb96b826c0c5f37a$export$41c562ebe57d11e2.__e(n24, u12, i9);
49369    }
49370  }
49371  function $fb96b826c0c5f37a$var$z(n25, u13) {
49372    $fb96b826c0c5f37a$export$41c562ebe57d11e2.__c && $fb96b826c0c5f37a$export$41c562ebe57d11e2.__c(u13, n25), n25.some(function(u14) {
49373      try {
49374        n25 = u14.__h, u14.__h = [], n25.some(function(n26) {
49375          n26.call(u14);
49376        });
49377      } catch (n27) {
49378        $fb96b826c0c5f37a$export$41c562ebe57d11e2.__e(n27, u14.__v);
49379      }
49380    });
49381  }
49382  function $fb96b826c0c5f37a$var$L(l16, u15, i10, t10, r10, o7, f6, c2) {
49383    var s3, a2, v3, y22 = i10.props, p3 = u15.props, d1 = u15.type, _22 = 0;
49384    if ("svg" === d1 && (r10 = true), null != o7) {
49385      for (; _22 < o7.length; _22++) if ((s3 = o7[_22]) && "setAttribute" in s3 == !!d1 && (d1 ? s3.localName === d1 : 3 === s3.nodeType)) {
49386        l16 = s3, o7[_22] = null;
49387        break;
49388      }
49389    }
49390    if (null == l16) {
49391      if (null === d1) return document.createTextNode(p3);
49392      l16 = r10 ? document.createElementNS("http://www.w3.org/2000/svg", d1) : document.createElement(d1, p3.is && p3), o7 = null, c2 = false;
49393    }
49394    if (null === d1) y22 === p3 || c2 && l16.data === p3 || (l16.data = p3);
49395    else {
49396      if (o7 = o7 && $fb96b826c0c5f37a$var$n.call(l16.childNodes), a2 = (y22 = i10.props || $fb96b826c0c5f37a$var$e).dangerouslySetInnerHTML, v3 = p3.dangerouslySetInnerHTML, !c2) {
49397        if (null != o7) for (y22 = {}, _22 = 0; _22 < l16.attributes.length; _22++) y22[l16.attributes[_22].name] = l16.attributes[_22].value;
49398        (v3 || a2) && (v3 && (a2 && v3.__html == a2.__html || v3.__html === l16.innerHTML) || (l16.innerHTML = v3 && v3.__html || ""));
49399      }
49400      if ($fb96b826c0c5f37a$var$C(l16, p3, y22, r10, c2), v3) u15.__k = [];
49401      else if (_22 = u15.props.children, $fb96b826c0c5f37a$var$w(l16, Array.isArray(_22) ? _22 : [
49402        _22
49403      ], u15, i10, t10, r10 && "foreignObject" !== d1, o7, f6, o7 ? o7[0] : i10.__k && $fb96b826c0c5f37a$var$k(i10, 0), c2), null != o7) for (_22 = o7.length; _22--; ) null != o7[_22] && $fb96b826c0c5f37a$var$h(o7[_22]);
49404      c2 || ("value" in p3 && void 0 !== (_22 = p3.value) && (_22 !== y22.value || _22 !== l16.value || "progress" === d1 && !_22) && $fb96b826c0c5f37a$var$H(l16, "value", _22, y22.value, false), "checked" in p3 && void 0 !== (_22 = p3.checked) && _22 !== l16.checked && $fb96b826c0c5f37a$var$H(l16, "checked", _22, y22.checked, false));
49405    }
49406    return l16;
49407  }
49408  function $fb96b826c0c5f37a$var$M(n28, u16, i11) {
49409    try {
49410      "function" == typeof n28 ? n28(u16) : n28.current = u16;
49411    } catch (n29) {
49412      $fb96b826c0c5f37a$export$41c562ebe57d11e2.__e(n29, i11);
49413    }
49414  }
49415  function $fb96b826c0c5f37a$var$N(n30, u17, i12) {
49416    var t11, r11;
49417    if ($fb96b826c0c5f37a$export$41c562ebe57d11e2.unmount && $fb96b826c0c5f37a$export$41c562ebe57d11e2.unmount(n30), (t11 = n30.ref) && (t11.current && t11.current !== n30.__e || $fb96b826c0c5f37a$var$M(t11, null, u17)), null != (t11 = n30.__c)) {
49418      if (t11.componentWillUnmount) try {
49419        t11.componentWillUnmount();
49420      } catch (n31) {
49421        $fb96b826c0c5f37a$export$41c562ebe57d11e2.__e(n31, u17);
49422      }
49423      t11.base = t11.__P = null;
49424    }
49425    if (t11 = n30.__k) for (r11 = 0; r11 < t11.length; r11++) t11[r11] && $fb96b826c0c5f37a$var$N(t11[r11], u17, "function" != typeof n30.type);
49426    i12 || null == n30.__e || $fb96b826c0c5f37a$var$h(n30.__e), n30.__e = n30.__d = void 0;
49427  }
49428  function $fb96b826c0c5f37a$var$O(n32, l4, u18) {
49429    return this.constructor(n32, u18);
49430  }
49431  function $fb96b826c0c5f37a$export$b3890eb0ae9dca99(u19, i13, t12) {
49432    var r12, o8, f7;
49433    $fb96b826c0c5f37a$export$41c562ebe57d11e2.__ && $fb96b826c0c5f37a$export$41c562ebe57d11e2.__(u19, i13), o8 = (r12 = "function" == typeof t12) ? null : t12 && t12.__k || i13.__k, f7 = [], $fb96b826c0c5f37a$var$j(i13, u19 = (!r12 && t12 || i13).__k = $fb96b826c0c5f37a$export$c8a8987d4410bf2d($fb96b826c0c5f37a$export$ffb0004e005737fa, null, [
49434      u19
49435    ]), o8 || $fb96b826c0c5f37a$var$e, $fb96b826c0c5f37a$var$e, void 0 !== i13.ownerSVGElement, !r12 && t12 ? [
49436      t12
49437    ] : o8 ? null : i13.firstChild ? $fb96b826c0c5f37a$var$n.call(i13.childNodes) : null, f7, !r12 && t12 ? t12 : o8 ? o8.__e : i13.firstChild, r12), $fb96b826c0c5f37a$var$z(f7, u19);
49438  }
49439  $fb96b826c0c5f37a$var$n = $fb96b826c0c5f37a$var$c.slice, $fb96b826c0c5f37a$export$41c562ebe57d11e2 = {
49440    __e: function(n39, l22) {
49441      for (var u23, i16, t14; l22 = l22.__; ) if ((u23 = l22.__c) && !u23.__) try {
49442        if ((i16 = u23.constructor) && null != i16.getDerivedStateFromError && (u23.setState(i16.getDerivedStateFromError(n39)), t14 = u23.__d), null != u23.componentDidCatch && (u23.componentDidCatch(n39), t14 = u23.__d), t14) return u23.__E = u23;
49443      } catch (l23) {
49444        n39 = l23;
49445      }
49446      throw n39;
49447    }
49448  }, $fb96b826c0c5f37a$var$u = 0, $fb96b826c0c5f37a$export$a8257692ac88316c = function(n40) {
49449    return null != n40 && void 0 === n40.constructor;
49450  }, $fb96b826c0c5f37a$export$16fa2f45be04daa8.prototype.setState = function(n41, l24) {
49451    var u24;
49452    u24 = null != this.__s && this.__s !== this.state ? this.__s : this.__s = $fb96b826c0c5f37a$var$a({}, this.state), "function" == typeof n41 && (n41 = n41($fb96b826c0c5f37a$var$a({}, u24), this.props)), n41 && $fb96b826c0c5f37a$var$a(u24, n41), null != n41 && this.__v && (l24 && this.__h.push(l24), $fb96b826c0c5f37a$var$m(this));
49453  }, $fb96b826c0c5f37a$export$16fa2f45be04daa8.prototype.forceUpdate = function(n42) {
49454    this.__v && (this.__e = true, n42 && this.__h.push(n42), $fb96b826c0c5f37a$var$m(this));
49455  }, $fb96b826c0c5f37a$export$16fa2f45be04daa8.prototype.render = $fb96b826c0c5f37a$export$ffb0004e005737fa, $fb96b826c0c5f37a$var$t = [], $fb96b826c0c5f37a$var$r = "function" == typeof Promise ? Promise.prototype.then.bind(Promise.resolve()) : setTimeout, $fb96b826c0c5f37a$var$g.__r = 0, $fb96b826c0c5f37a$var$f = 0;
49456  var $bd9dd35321b03dd4$var$o = 0;
49457  function $bd9dd35321b03dd4$export$34b9dba7ce09269b(_1, e1, n2, t2, f) {
49458    var l4, s2, u2 = {};
49459    for (s2 in e1) "ref" == s2 ? l4 = e1[s2] : u2[s2] = e1[s2];
49460    var a2 = {
49461      type: _1,
49462      props: u2,
49463      key: n2,
49464      ref: l4,
49465      __k: null,
49466      __: null,
49467      __b: 0,
49468      __e: null,
49469      __d: void 0,
49470      __c: null,
49471      __h: null,
49472      constructor: void 0,
49473      __v: --$bd9dd35321b03dd4$var$o,
49474      __source: t2,
49475      __self: f
49476    };
49477    if ("function" == typeof _1 && (l4 = _1.defaultProps)) for (s2 in l4) void 0 === u2[s2] && (u2[s2] = l4[s2]);
49478    return (0, $fb96b826c0c5f37a$export$41c562ebe57d11e2).vnode && (0, $fb96b826c0c5f37a$export$41c562ebe57d11e2).vnode(a2), a2;
49479  }
49480  function $f72b75cf796873c7$var$set(key, value) {
49481    try {
49482      window.localStorage[`emoji-mart.${key}`] = JSON.stringify(value);
49483    } catch (error) {
49484    }
49485  }
49486  function $f72b75cf796873c7$var$get(key) {
49487    try {
49488      const value = window.localStorage[`emoji-mart.${key}`];
49489      if (value) return JSON.parse(value);
49490    } catch (error) {
49491    }
49492  }
49493  var $f72b75cf796873c7$export$2e2bcd8739ae039 = {
49494    set: $f72b75cf796873c7$var$set,
49495    get: $f72b75cf796873c7$var$get
49496  };
49497  var $c84d045dcc34faf5$var$CACHE = /* @__PURE__ */ new Map();
49498  var $c84d045dcc34faf5$var$VERSIONS = [
49499    {
49500      v: 15,
49501      emoji: "\u{1FAE8}"
49502    },
49503    {
49504      v: 14,
49505      emoji: "\u{1FAE0}"
49506    },
49507    {
49508      v: 13.1,
49509      emoji: "\u{1F636}\u200D\u{1F32B}\uFE0F"
49510    },
49511    {
49512      v: 13,
49513      emoji: "\u{1F978}"
49514    },
49515    {
49516      v: 12.1,
49517      emoji: "\u{1F9D1}\u200D\u{1F9B0}"
49518    },
49519    {
49520      v: 12,
49521      emoji: "\u{1F971}"
49522    },
49523    {
49524      v: 11,
49525      emoji: "\u{1F970}"
49526    },
49527    {
49528      v: 5,
49529      emoji: "\u{1F929}"
49530    },
49531    {
49532      v: 4,
49533      emoji: "\u{1F471}\u200D\u2640\uFE0F"
49534    },
49535    {
49536      v: 3,
49537      emoji: "\u{1F923}"
49538    },
49539    {
49540      v: 2,
49541      emoji: "\u{1F44B}\u{1F3FB}"
49542    },
49543    {
49544      v: 1,
49545      emoji: "\u{1F643}"
49546    }
49547  ];
49548  function $c84d045dcc34faf5$var$latestVersion() {
49549    for (const { v: v3, emoji } of $c84d045dcc34faf5$var$VERSIONS) {
49550      if ($c84d045dcc34faf5$var$isSupported(emoji)) return v3;
49551    }
49552  }
49553  function $c84d045dcc34faf5$var$noCountryFlags() {
49554    if ($c84d045dcc34faf5$var$isSupported("\u{1F1E8}\u{1F1E6}")) return false;
49555    return true;
49556  }
49557  function $c84d045dcc34faf5$var$isSupported(emoji) {
49558    if ($c84d045dcc34faf5$var$CACHE.has(emoji)) return $c84d045dcc34faf5$var$CACHE.get(emoji);
49559    const supported = $c84d045dcc34faf5$var$isEmojiSupported(emoji);
49560    $c84d045dcc34faf5$var$CACHE.set(emoji, supported);
49561    return supported;
49562  }
49563  var $c84d045dcc34faf5$var$isEmojiSupported = (() => {
49564    let ctx = null;
49565    try {
49566      if (!navigator.userAgent.includes("jsdom")) ctx = document.createElement("canvas").getContext("2d", {
49567        willReadFrequently: true
49568      });
49569    } catch {
49570    }
49571    if (!ctx) return () => false;
49572    const CANVAS_HEIGHT = 25;
49573    const CANVAS_WIDTH = 20;
49574    const textSize = Math.floor(CANVAS_HEIGHT / 2);
49575    ctx.font = textSize + "px Arial, Sans-Serif";
49576    ctx.textBaseline = "top";
49577    ctx.canvas.width = CANVAS_WIDTH * 2;
49578    ctx.canvas.height = CANVAS_HEIGHT;
49579    return (unicode) => {
49580      ctx.clearRect(0, 0, CANVAS_WIDTH * 2, CANVAS_HEIGHT);
49581      ctx.fillStyle = "#FF0000";
49582      ctx.fillText(unicode, 0, 22);
49583      ctx.fillStyle = "#0000FF";
49584      ctx.fillText(unicode, CANVAS_WIDTH, 22);
49585      const a2 = ctx.getImageData(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT).data;
49586      const count = a2.length;
49587      let i2 = 0;
49588      for (; i2 < count && !a2[i2 + 3]; i2 += 4) ;
49589      if (i2 >= count) return false;
49590      const x3 = CANVAS_WIDTH + i2 / 4 % CANVAS_WIDTH;
49591      const y3 = Math.floor(i2 / 4 / CANVAS_WIDTH);
49592      const b3 = ctx.getImageData(x3, y3, 1, 1).data;
49593      if (a2[i2] !== b3[0] || a2[i2 + 2] !== b3[2]) return false;
49594      if (ctx.measureText(unicode).width >= CANVAS_WIDTH) return false;
49595      return true;
49596    };
49597  })();
49598  var $c84d045dcc34faf5$export$2e2bcd8739ae039 = {
49599    latestVersion: $c84d045dcc34faf5$var$latestVersion,
49600    noCountryFlags: $c84d045dcc34faf5$var$noCountryFlags
49601  };
49602  var $b22cfd0a55410b4f$var$DEFAULTS = [
49603    "+1",
49604    "grinning",
49605    "kissing_heart",
49606    "heart_eyes",
49607    "laughing",
49608    "stuck_out_tongue_winking_eye",
49609    "sweat_smile",
49610    "joy",
49611    "scream",
49612    "disappointed",
49613    "unamused",
49614    "weary",
49615    "sob",
49616    "sunglasses",
49617    "heart"
49618  ];
49619  var $b22cfd0a55410b4f$var$Index = null;
49620  function $b22cfd0a55410b4f$var$add(emoji) {
49621    $b22cfd0a55410b4f$var$Index || ($b22cfd0a55410b4f$var$Index = (0, $f72b75cf796873c7$export$2e2bcd8739ae039).get("frequently") || {});
49622    const emojiId = emoji.id || emoji;
49623    if (!emojiId) return;
49624    $b22cfd0a55410b4f$var$Index[emojiId] || ($b22cfd0a55410b4f$var$Index[emojiId] = 0);
49625    $b22cfd0a55410b4f$var$Index[emojiId] += 1;
49626    (0, $f72b75cf796873c7$export$2e2bcd8739ae039).set("last", emojiId);
49627    (0, $f72b75cf796873c7$export$2e2bcd8739ae039).set("frequently", $b22cfd0a55410b4f$var$Index);
49628  }
49629  function $b22cfd0a55410b4f$var$get({ maxFrequentRows, perLine }) {
49630    if (!maxFrequentRows) return [];
49631    $b22cfd0a55410b4f$var$Index || ($b22cfd0a55410b4f$var$Index = (0, $f72b75cf796873c7$export$2e2bcd8739ae039).get("frequently"));
49632    let emojiIds = [];
49633    if (!$b22cfd0a55410b4f$var$Index) {
49634      $b22cfd0a55410b4f$var$Index = {};
49635      for (let i2 in $b22cfd0a55410b4f$var$DEFAULTS.slice(0, perLine)) {
49636        const emojiId = $b22cfd0a55410b4f$var$DEFAULTS[i2];
49637        $b22cfd0a55410b4f$var$Index[emojiId] = perLine - i2;
49638        emojiIds.push(emojiId);
49639      }
49640      return emojiIds;
49641    }
49642    const max2 = maxFrequentRows * perLine;
49643    const last = (0, $f72b75cf796873c7$export$2e2bcd8739ae039).get("last");
49644    for (let emojiId in $b22cfd0a55410b4f$var$Index) emojiIds.push(emojiId);
49645    emojiIds.sort((a2, b3) => {
49646      const aScore = $b22cfd0a55410b4f$var$Index[b3];
49647      const bScore = $b22cfd0a55410b4f$var$Index[a2];
49648      if (aScore == bScore) return a2.localeCompare(b3);
49649      return aScore - bScore;
49650    });
49651    if (emojiIds.length > max2) {
49652      const removedIds = emojiIds.slice(max2);
49653      emojiIds = emojiIds.slice(0, max2);
49654      for (let removedId of removedIds) {
49655        if (removedId == last) continue;
49656        delete $b22cfd0a55410b4f$var$Index[removedId];
49657      }
49658      if (last && emojiIds.indexOf(last) == -1) {
49659        delete $b22cfd0a55410b4f$var$Index[emojiIds[emojiIds.length - 1]];
49660        emojiIds.splice(-1, 1, last);
49661      }
49662      (0, $f72b75cf796873c7$export$2e2bcd8739ae039).set("frequently", $b22cfd0a55410b4f$var$Index);
49663    }
49664    return emojiIds;
49665  }
49666  var $b22cfd0a55410b4f$export$2e2bcd8739ae039 = {
49667    add: $b22cfd0a55410b4f$var$add,
49668    get: $b22cfd0a55410b4f$var$get,
49669    DEFAULTS: $b22cfd0a55410b4f$var$DEFAULTS
49670  };
49671  var $8d50d93417ef682a$exports = {};
49672  $8d50d93417ef682a$exports = JSON.parse('{"search":"Search","search_no_results_1":"Oh no!","search_no_results_2":"That emoji couldn\u2019t be found","pick":"Pick an emoji\u2026","add_custom":"Add custom emoji","categories":{"activity":"Activity","custom":"Custom","flags":"Flags","foods":"Food & Drink","frequent":"Frequently used","nature":"Animals & Nature","objects":"Objects","people":"Smileys & People","places":"Travel & Places","search":"Search Results","symbols":"Symbols"},"skins":{"1":"Default","2":"Light","3":"Medium-Light","4":"Medium","5":"Medium-Dark","6":"Dark","choose":"Choose default skin tone"}}');
49673  var $b247ea80b67298d5$export$2e2bcd8739ae039 = {
49674    autoFocus: {
49675      value: false
49676    },
49677    dynamicWidth: {
49678      value: false
49679    },
49680    emojiButtonColors: {
49681      value: null
49682    },
49683    emojiButtonRadius: {
49684      value: "100%"
49685    },
49686    emojiButtonSize: {
49687      value: 36
49688    },
49689    emojiSize: {
49690      value: 24
49691    },
49692    emojiVersion: {
49693      value: 17,
49694      choices: [
49695        1,
49696        2,
49697        3,
49698        4,
49699        5,
49700        11,
49701        12,
49702        12.1,
49703        13,
49704        13.1,
49705        14,
49706        15,
49707        16,
49708        17
49709      ]
49710    },
49711    exceptEmojis: {
49712      value: []
49713    },
49714    icons: {
49715      value: "auto",
49716      choices: [
49717        "auto",
49718        "outline",
49719        "solid"
49720      ]
49721    },
49722    locale: {
49723      value: "en",
49724      choices: [
49725        "en",
49726        "ar",
49727        "be",
49728        "cs",
49729        "de",
49730        "es",
49731        "fa",
49732        "fi",
49733        "fr",
49734        "hi",
49735        "it",
49736        "ja",
49737        "ko",
49738        "nl",
49739        "pl",
49740        "pt",
49741        "ru",
49742        "sa",
49743        "tr",
49744        "uk",
49745        "vi",
49746        "zh"
49747      ]
49748    },
49749    maxFrequentRows: {
49750      value: 4
49751    },
49752    navPosition: {
49753      value: "top",
49754      choices: [
49755        "top",
49756        "bottom",
49757        "none"
49758      ]
49759    },
49760    noCountryFlags: {
49761      value: false
49762    },
49763    noResultsEmoji: {
49764      value: null
49765    },
49766    perLine: {
49767      value: 9
49768    },
49769    previewEmoji: {
49770      value: null
49771    },
49772    previewPosition: {
49773      value: "bottom",
49774      choices: [
49775        "top",
49776        "bottom",
49777        "none"
49778      ]
49779    },
49780    searchPosition: {
49781      value: "sticky",
49782      choices: [
49783        "sticky",
49784        "static",
49785        "none"
49786      ]
49787    },
49788    set: {
49789      value: "native",
49790      choices: [
49791        "native",
49792        "apple",
49793        "facebook",
49794        "google",
49795        "twitter"
49796      ]
49797    },
49798    skin: {
49799      value: 1,
49800      choices: [
49801        1,
49802        2,
49803        3,
49804        4,
49805        5,
49806        6
49807      ]
49808    },
49809    skinTonePosition: {
49810      value: "preview",
49811      choices: [
49812        "preview",
49813        "search",
49814        "none"
49815      ]
49816    },
49817    theme: {
49818      value: "auto",
49819      choices: [
49820        "auto",
49821        "light",
49822        "dark"
49823      ]
49824    },
49825    // Data
49826    categories: null,
49827    categoryIcons: null,
49828    custom: null,
49829    data: null,
49830    i18n: null,
49831    // Callbacks
49832    getImageURL: null,
49833    getSpritesheetURL: null,
49834    onAddCustomEmoji: null,
49835    onClickOutside: null,
49836    onEmojiSelect: null,
49837    // Deprecated
49838    stickySearch: {
49839      deprecated: true,
49840      value: true
49841    }
49842  };
49843  var $7adb23b0109cc36a$export$dbe3113d60765c1a = null;
49844  var $7adb23b0109cc36a$export$2d0294657ab35f1b = null;
49845  var $7adb23b0109cc36a$var$fetchCache = {};
49846  async function $7adb23b0109cc36a$var$fetchJSON(src) {
49847    if ($7adb23b0109cc36a$var$fetchCache[src]) return $7adb23b0109cc36a$var$fetchCache[src];
49848    const response = await fetch(src);
49849    const json = await response.json();
49850    $7adb23b0109cc36a$var$fetchCache[src] = json;
49851    return json;
49852  }
49853  var $7adb23b0109cc36a$var$promise = null;
49854  var $7adb23b0109cc36a$var$initCallback = null;
49855  var $7adb23b0109cc36a$var$initialized = false;
49856  function $7adb23b0109cc36a$export$2cd8252107eb640b(options, { caller } = {}) {
49857    $7adb23b0109cc36a$var$promise || ($7adb23b0109cc36a$var$promise = new Promise((resolve) => {
49858      $7adb23b0109cc36a$var$initCallback = resolve;
49859    }));
49860    if (options) $7adb23b0109cc36a$var$_init(options);
49861    else if (caller && !$7adb23b0109cc36a$var$initialized) console.warn(`\`${caller}\` requires data to be initialized first. Promise will be pending until \`init\` is called.`);
49862    return $7adb23b0109cc36a$var$promise;
49863  }
49864  async function $7adb23b0109cc36a$var$_init(props) {
49865    $7adb23b0109cc36a$var$initialized = true;
49866    let { emojiVersion, set, locale } = props;
49867    emojiVersion || (emojiVersion = (0, $b247ea80b67298d5$export$2e2bcd8739ae039).emojiVersion.value);
49868    set || (set = (0, $b247ea80b67298d5$export$2e2bcd8739ae039).set.value);
49869    locale || (locale = (0, $b247ea80b67298d5$export$2e2bcd8739ae039).locale.value);
49870    if (!$7adb23b0109cc36a$export$2d0294657ab35f1b) {
49871      $7adb23b0109cc36a$export$2d0294657ab35f1b = (typeof props.data === "function" ? await props.data() : props.data) || await $7adb23b0109cc36a$var$fetchJSON(`https://cdn.jsdelivr.net/npm/@emoji-mart/data@latest/sets/${emojiVersion}/${set}.json`);
49872      $7adb23b0109cc36a$export$2d0294657ab35f1b.emoticons = {};
49873      $7adb23b0109cc36a$export$2d0294657ab35f1b.natives = {};
49874      $7adb23b0109cc36a$export$2d0294657ab35f1b.categories.unshift({
49875        id: "frequent",
49876        emojis: []
49877      });
49878      for (const alias in $7adb23b0109cc36a$export$2d0294657ab35f1b.aliases) {
49879        const emojiId = $7adb23b0109cc36a$export$2d0294657ab35f1b.aliases[alias];
49880        const emoji = $7adb23b0109cc36a$export$2d0294657ab35f1b.emojis[emojiId];
49881        if (!emoji) continue;
49882        emoji.aliases || (emoji.aliases = []);
49883        emoji.aliases.push(alias);
49884      }
49885      $7adb23b0109cc36a$export$2d0294657ab35f1b.originalCategories = $7adb23b0109cc36a$export$2d0294657ab35f1b.categories;
49886    } else $7adb23b0109cc36a$export$2d0294657ab35f1b.categories = $7adb23b0109cc36a$export$2d0294657ab35f1b.categories.filter((c2) => {
49887      const isCustom = !!c2.name;
49888      if (!isCustom) return true;
49889      return false;
49890    });
49891    $7adb23b0109cc36a$export$dbe3113d60765c1a = (typeof props.i18n === "function" ? await props.i18n() : props.i18n) || (locale == "en" ? (0, /* @__PURE__ */ $parcel$interopDefault($8d50d93417ef682a$exports)) : await $7adb23b0109cc36a$var$fetchJSON(`https://cdn.jsdelivr.net/npm/@emoji-mart/data@latest/i18n/${locale}.json`));
49892    if (props.custom) for (let i2 in props.custom) {
49893      i2 = parseInt(i2);
49894      const category = props.custom[i2];
49895      const prevCategory = props.custom[i2 - 1];
49896      if (!category.emojis || !category.emojis.length) continue;
49897      category.id || (category.id = `custom_${i2 + 1}`);
49898      category.name || (category.name = $7adb23b0109cc36a$export$dbe3113d60765c1a.categories.custom);
49899      if (prevCategory && !category.icon) category.target = prevCategory.target || prevCategory;
49900      $7adb23b0109cc36a$export$2d0294657ab35f1b.categories.push(category);
49901      for (const emoji of category.emojis) $7adb23b0109cc36a$export$2d0294657ab35f1b.emojis[emoji.id] = emoji;
49902    }
49903    if (props.categories) $7adb23b0109cc36a$export$2d0294657ab35f1b.categories = $7adb23b0109cc36a$export$2d0294657ab35f1b.originalCategories.filter((c2) => {
49904      return props.categories.indexOf(c2.id) != -1;
49905    }).sort((c1, c2) => {
49906      const i1 = props.categories.indexOf(c1.id);
49907      const i2 = props.categories.indexOf(c2.id);
49908      return i1 - i2;
49909    });
49910    let latestVersionSupport = null;
49911    let noCountryFlags = null;
49912    if (set == "native") {
49913      latestVersionSupport = emojiVersion;
49914      noCountryFlags = props.noCountryFlags || (0, $c84d045dcc34faf5$export$2e2bcd8739ae039).noCountryFlags();
49915    }
49916    let categoryIndex = $7adb23b0109cc36a$export$2d0294657ab35f1b.categories.length;
49917    let resetSearchIndex = false;
49918    while (categoryIndex--) {
49919      const category = $7adb23b0109cc36a$export$2d0294657ab35f1b.categories[categoryIndex];
49920      if (category.id == "frequent") {
49921        let { maxFrequentRows, perLine } = props;
49922        maxFrequentRows = maxFrequentRows >= 0 ? maxFrequentRows : (0, $b247ea80b67298d5$export$2e2bcd8739ae039).maxFrequentRows.value;
49923        perLine || (perLine = (0, $b247ea80b67298d5$export$2e2bcd8739ae039).perLine.value);
49924        category.emojis = (0, $b22cfd0a55410b4f$export$2e2bcd8739ae039).get({
49925          maxFrequentRows,
49926          perLine
49927        });
49928      }
49929      if (!category.emojis || !category.emojis.length) {
49930        $7adb23b0109cc36a$export$2d0294657ab35f1b.categories.splice(categoryIndex, 1);
49931        continue;
49932      }
49933      const { categoryIcons } = props;
49934      if (categoryIcons) {
49935        const icon = categoryIcons[category.id];
49936        if (icon && !category.icon) category.icon = icon;
49937      }
49938      let emojiIndex = category.emojis.length;
49939      while (emojiIndex--) {
49940        const emojiId = category.emojis[emojiIndex];
49941        const emoji = emojiId.id ? emojiId : $7adb23b0109cc36a$export$2d0294657ab35f1b.emojis[emojiId];
49942        const ignore = () => {
49943          category.emojis.splice(emojiIndex, 1);
49944        };
49945        if (!emoji || props.exceptEmojis && props.exceptEmojis.includes(emoji.id)) {
49946          ignore();
49947          continue;
49948        }
49949        if (latestVersionSupport && emoji.version > latestVersionSupport) {
49950          ignore();
49951          continue;
49952        }
49953        if (noCountryFlags && category.id == "flags") {
49954          if (!(0, $e6eae5155b87f591$export$bcb25aa587e9cb13).includes(emoji.id)) {
49955            ignore();
49956            continue;
49957          }
49958        }
49959        if (!emoji.search) {
49960          resetSearchIndex = true;
49961          emoji.search = "," + [
49962            [
49963              emoji.id,
49964              false
49965            ],
49966            [
49967              emoji.name,
49968              true
49969            ],
49970            [
49971              emoji.keywords,
49972              false
49973            ],
49974            [
49975              emoji.emoticons,
49976              false
49977            ]
49978          ].map(([strings, split]) => {
49979            if (!strings) return;
49980            return (Array.isArray(strings) ? strings : [
49981              strings
49982            ]).map((string) => {
49983              return (split ? string.split(/[-|_|\s]+/) : [
49984                string
49985              ]).map((s2) => s2.toLowerCase());
49986            }).flat();
49987          }).flat().filter((a2) => a2 && a2.trim()).join(",");
49988          if (emoji.emoticons) for (const emoticon of emoji.emoticons) {
49989            if ($7adb23b0109cc36a$export$2d0294657ab35f1b.emoticons[emoticon]) continue;
49990            $7adb23b0109cc36a$export$2d0294657ab35f1b.emoticons[emoticon] = emoji.id;
49991          }
49992          let skinIndex = 0;
49993          for (const skin of emoji.skins) {
49994            if (!skin) continue;
49995            skinIndex++;
49996            const { native } = skin;
49997            if (native) {
49998              $7adb23b0109cc36a$export$2d0294657ab35f1b.natives[native] = emoji.id;
49999              emoji.search += `,${native}`;
50000            }
50001            const skinShortcodes = skinIndex == 1 ? "" : `:skin-tone-${skinIndex}:`;
50002            skin.shortcodes = `:${emoji.id}:${skinShortcodes}`;
50003          }
50004        }
50005      }
50006    }
50007    if (resetSearchIndex) (0, $c4d155af13ad4d4b$export$2e2bcd8739ae039).reset();
50008    $7adb23b0109cc36a$var$initCallback();
50009  }
50010  function $7adb23b0109cc36a$export$75fe5f91d452f94b(props, defaultProps2, element) {
50011    props || (props = {});
50012    const _props = {};
50013    for (let k2 in defaultProps2) _props[k2] = $7adb23b0109cc36a$export$88c9ddb45cea7241(k2, props, defaultProps2, element);
50014    return _props;
50015  }
50016  function $7adb23b0109cc36a$export$88c9ddb45cea7241(propName, props, defaultProps2, element) {
50017    const defaults = defaultProps2[propName];
50018    let value = element && element.getAttribute(propName) || (props[propName] != null && props[propName] != void 0 ? props[propName] : null);
50019    if (!defaults) return value;
50020    if (value != null && defaults.value && typeof defaults.value != typeof value) {
50021      if (typeof defaults.value == "boolean") value = value == "false" ? false : true;
50022      else value = defaults.value.constructor(value);
50023    }
50024    if (defaults.transform && value) value = defaults.transform(value);
50025    if (value == null || defaults.choices && defaults.choices.indexOf(value) == -1) value = defaults.value;
50026    return value;
50027  }
50028  var $c4d155af13ad4d4b$var$SHORTCODES_REGEX = /^(?:\:([^\:]+)\:)(?:\:skin-tone-(\d)\:)?$/;
50029  var $c4d155af13ad4d4b$var$Pool = null;
50030  function $c4d155af13ad4d4b$var$get(emojiId) {
50031    if (emojiId.id) return emojiId;
50032    return (0, $7adb23b0109cc36a$export$2d0294657ab35f1b).emojis[emojiId] || (0, $7adb23b0109cc36a$export$2d0294657ab35f1b).emojis[(0, $7adb23b0109cc36a$export$2d0294657ab35f1b).aliases[emojiId]] || (0, $7adb23b0109cc36a$export$2d0294657ab35f1b).emojis[(0, $7adb23b0109cc36a$export$2d0294657ab35f1b).natives[emojiId]];
50033  }
50034  function $c4d155af13ad4d4b$var$reset() {
50035    $c4d155af13ad4d4b$var$Pool = null;
50036  }
50037  async function $c4d155af13ad4d4b$var$search(value, { maxResults, caller } = {}) {
50038    if (!value || !value.trim().length) return null;
50039    maxResults || (maxResults = 90);
50040    await (0, $7adb23b0109cc36a$export$2cd8252107eb640b)(null, {
50041      caller: caller || "SearchIndex.search"
50042    });
50043    const values = value.toLowerCase().replace(/(\w)-/, "$1 ").split(/[\s|,]+/).filter((word, i2, words) => {
50044      return word.trim() && words.indexOf(word) == i2;
50045    });
50046    if (!values.length) return;
50047    let pool = $c4d155af13ad4d4b$var$Pool || ($c4d155af13ad4d4b$var$Pool = Object.values((0, $7adb23b0109cc36a$export$2d0294657ab35f1b).emojis));
50048    let results, scores;
50049    for (const value1 of values) {
50050      if (!pool.length) break;
50051      results = [];
50052      scores = {};
50053      for (const emoji of pool) {
50054        if (!emoji.search) continue;
50055        const score = emoji.search.indexOf(`,${value1}`);
50056        if (score == -1) continue;
50057        results.push(emoji);
50058        scores[emoji.id] || (scores[emoji.id] = 0);
50059        scores[emoji.id] += emoji.id == value1 ? 0 : score + 1;
50060      }
50061      pool = results;
50062    }
50063    if (results.length < 2) return results;
50064    results.sort((a2, b3) => {
50065      const aScore = scores[a2.id];
50066      const bScore = scores[b3.id];
50067      if (aScore == bScore) return a2.id.localeCompare(b3.id);
50068      return aScore - bScore;
50069    });
50070    if (results.length > maxResults) results = results.slice(0, maxResults);
50071    return results;
50072  }
50073  var $c4d155af13ad4d4b$export$2e2bcd8739ae039 = {
50074    search: $c4d155af13ad4d4b$var$search,
50075    get: $c4d155af13ad4d4b$var$get,
50076    reset: $c4d155af13ad4d4b$var$reset,
50077    SHORTCODES_REGEX: $c4d155af13ad4d4b$var$SHORTCODES_REGEX
50078  };
50079  var $e6eae5155b87f591$export$bcb25aa587e9cb13 = [
50080    "checkered_flag",
50081    "crossed_flags",
50082    "pirate_flag",
50083    "rainbow-flag",
50084    "transgender_flag",
50085    "triangular_flag_on_post",
50086    "waving_black_flag",
50087    "waving_white_flag"
50088  ];
50089  function $693b183b0a78708f$export$9cb4719e2e525b7a(a2, b3) {
50090    return Array.isArray(a2) && Array.isArray(b3) && a2.length === b3.length && a2.every((val, index) => val == b3[index]);
50091  }
50092  async function $693b183b0a78708f$export$e772c8ff12451969(frames = 1) {
50093    for (let _3 in [
50094      ...Array(frames).keys()
50095    ]) await new Promise(requestAnimationFrame);
50096  }
50097  function $693b183b0a78708f$export$d10ac59fbe52a745(emoji, { skinIndex = 0 } = {}) {
50098    const skin = emoji.skins[skinIndex] || (() => {
50099      skinIndex = 0;
50100      return emoji.skins[skinIndex];
50101    })();
50102    const emojiData = {
50103      id: emoji.id,
50104      name: emoji.name,
50105      native: skin.native,
50106      unified: skin.unified,
50107      keywords: emoji.keywords,
50108      shortcodes: skin.shortcodes || emoji.shortcodes
50109    };
50110    if (emoji.skins.length > 1) emojiData.skin = skinIndex + 1;
50111    if (skin.src) emojiData.src = skin.src;
50112    if (emoji.aliases && emoji.aliases.length) emojiData.aliases = emoji.aliases;
50113    if (emoji.emoticons && emoji.emoticons.length) emojiData.emoticons = emoji.emoticons;
50114    return emojiData;
50115  }
50116  var $fcccfb36ed0cde68$var$categories = {
50117    activity: {
50118      outline: /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("svg", {
50119        xmlns: "http://www.w3.org/2000/svg",
50120        viewBox: "0 0 24 24",
50121        children: /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("path", {
50122          d: "M12 0C5.373 0 0 5.372 0 12c0 6.627 5.373 12 12 12 6.628 0 12-5.373 12-12 0-6.628-5.372-12-12-12m9.949 11H17.05c.224-2.527 1.232-4.773 1.968-6.113A9.966 9.966 0 0 1 21.949 11M13 11V2.051a9.945 9.945 0 0 1 4.432 1.564c-.858 1.491-2.156 4.22-2.392 7.385H13zm-2 0H8.961c-.238-3.165-1.536-5.894-2.393-7.385A9.95 9.95 0 0 1 11 2.051V11zm0 2v8.949a9.937 9.937 0 0 1-4.432-1.564c.857-1.492 2.155-4.221 2.393-7.385H11zm4.04 0c.236 3.164 1.534 5.893 2.392 7.385A9.92 9.92 0 0 1 13 21.949V13h2.04zM4.982 4.887C5.718 6.227 6.726 8.473 6.951 11h-4.9a9.977 9.977 0 0 1 2.931-6.113M2.051 13h4.9c-.226 2.527-1.233 4.771-1.969 6.113A9.972 9.972 0 0 1 2.051 13m16.967 6.113c-.735-1.342-1.744-3.586-1.968-6.113h4.899a9.961 9.961 0 0 1-2.931 6.113"
50123        })
50124      }),
50125      solid: /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("svg", {
50126        xmlns: "http://www.w3.org/2000/svg",
50127        viewBox: "0 0 512 512",
50128        children: /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("path", {
50129          d: "M16.17 337.5c0 44.98 7.565 83.54 13.98 107.9C35.22 464.3 50.46 496 174.9 496c9.566 0 19.59-.4707 29.84-1.271L17.33 307.3C16.53 317.6 16.17 327.7 16.17 337.5zM495.8 174.5c0-44.98-7.565-83.53-13.98-107.9c-4.688-17.54-18.34-31.23-36.04-35.95C435.5 27.91 392.9 16 337 16c-9.564 0-19.59 .4707-29.84 1.271l187.5 187.5C495.5 194.4 495.8 184.3 495.8 174.5zM26.77 248.8l236.3 236.3c142-36.1 203.9-150.4 222.2-221.1L248.9 26.87C106.9 62.96 45.07 177.2 26.77 248.8zM256 335.1c0 9.141-7.474 16-16 16c-4.094 0-8.188-1.564-11.31-4.689L164.7 283.3C161.6 280.2 160 276.1 160 271.1c0-8.529 6.865-16 16-16c4.095 0 8.189 1.562 11.31 4.688l64.01 64C254.4 327.8 256 331.9 256 335.1zM304 287.1c0 9.141-7.474 16-16 16c-4.094 0-8.188-1.564-11.31-4.689L212.7 235.3C209.6 232.2 208 228.1 208 223.1c0-9.141 7.473-16 16-16c4.094 0 8.188 1.562 11.31 4.688l64.01 64.01C302.5 279.8 304 283.9 304 287.1zM256 175.1c0-9.141 7.473-16 16-16c4.094 0 8.188 1.562 11.31 4.688l64.01 64.01c3.125 3.125 4.688 7.219 4.688 11.31c0 9.133-7.468 16-16 16c-4.094 0-8.189-1.562-11.31-4.688l-64.01-64.01C257.6 184.2 256 180.1 256 175.1z"
50130        })
50131      })
50132    },
50133    custom: /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("svg", {
50134      xmlns: "http://www.w3.org/2000/svg",
50135      viewBox: "0 0 448 512",
50136      children: /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("path", {
50137        d: "M417.1 368c-5.937 10.27-16.69 16-27.75 16c-5.422 0-10.92-1.375-15.97-4.281L256 311.4V448c0 17.67-14.33 32-31.1 32S192 465.7 192 448V311.4l-118.3 68.29C68.67 382.6 63.17 384 57.75 384c-11.06 0-21.81-5.734-27.75-16c-8.828-15.31-3.594-34.88 11.72-43.72L159.1 256L41.72 187.7C26.41 178.9 21.17 159.3 29.1 144C36.63 132.5 49.26 126.7 61.65 128.2C65.78 128.7 69.88 130.1 73.72 132.3L192 200.6V64c0-17.67 14.33-32 32-32S256 46.33 256 64v136.6l118.3-68.29c3.838-2.213 7.939-3.539 12.07-4.051C398.7 126.7 411.4 132.5 417.1 144c8.828 15.31 3.594 34.88-11.72 43.72L288 256l118.3 68.28C421.6 333.1 426.8 352.7 417.1 368z"
50138      })
50139    }),
50140    flags: {
50141      outline: /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("svg", {
50142        xmlns: "http://www.w3.org/2000/svg",
50143        viewBox: "0 0 24 24",
50144        children: /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("path", {
50145          d: "M0 0l6.084 24H8L1.916 0zM21 5h-4l-1-4H4l3 12h3l1 4h13L21 5zM6.563 3h7.875l2 8H8.563l-2-8zm8.832 10l-2.856 1.904L12.063 13h3.332zM19 13l-1.5-6h1.938l2 8H16l3-2z"
50146        })
50147      }),
50148      solid: /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("svg", {
50149        xmlns: "http://www.w3.org/2000/svg",
50150        viewBox: "0 0 512 512",
50151        children: /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("path", {
50152          d: "M64 496C64 504.8 56.75 512 48 512h-32C7.25 512 0 504.8 0 496V32c0-17.75 14.25-32 32-32s32 14.25 32 32V496zM476.3 0c-6.365 0-13.01 1.35-19.34 4.233c-45.69 20.86-79.56 27.94-107.8 27.94c-59.96 0-94.81-31.86-163.9-31.87C160.9 .3055 131.6 4.867 96 15.75v350.5c32-9.984 59.87-14.1 84.85-14.1c73.63 0 124.9 31.78 198.6 31.78c31.91 0 68.02-5.971 111.1-23.09C504.1 355.9 512 344.4 512 332.1V30.73C512 11.1 495.3 0 476.3 0z"
50153        })
50154      })
50155    },
50156    foods: {
50157      outline: /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("svg", {
50158        xmlns: "http://www.w3.org/2000/svg",
50159        viewBox: "0 0 24 24",
50160        children: /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("path", {
50161          d: "M17 4.978c-1.838 0-2.876.396-3.68.934.513-1.172 1.768-2.934 4.68-2.934a1 1 0 0 0 0-2c-2.921 0-4.629 1.365-5.547 2.512-.064.078-.119.162-.18.244C11.73 1.838 10.798.023 9.207.023 8.579.022 7.85.306 7 .978 5.027 2.54 5.329 3.902 6.492 4.999 3.609 5.222 0 7.352 0 12.969c0 4.582 4.961 11.009 9 11.009 1.975 0 2.371-.486 3-1 .629.514 1.025 1 3 1 4.039 0 9-6.418 9-11 0-5.953-4.055-8-7-8M8.242 2.546c.641-.508.943-.523.965-.523.426.169.975 1.405 1.357 3.055-1.527-.629-2.741-1.352-2.98-1.846.059-.112.241-.356.658-.686M15 21.978c-1.08 0-1.21-.109-1.559-.402l-.176-.146c-.367-.302-.816-.452-1.266-.452s-.898.15-1.266.452l-.176.146c-.347.292-.477.402-1.557.402-2.813 0-7-5.389-7-9.009 0-5.823 4.488-5.991 5-5.991 1.939 0 2.484.471 3.387 1.251l.323.276a1.995 1.995 0 0 0 2.58 0l.323-.276c.902-.78 1.447-1.251 3.387-1.251.512 0 5 .168 5 6 0 3.617-4.187 9-7 9"
50162        })
50163      }),
50164      solid: /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("svg", {
50165        xmlns: "http://www.w3.org/2000/svg",
50166        viewBox: "0 0 512 512",
50167        children: /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("path", {
50168          d: "M481.9 270.1C490.9 279.1 496 291.3 496 304C496 316.7 490.9 328.9 481.9 337.9C472.9 346.9 460.7 352 448 352H64C51.27 352 39.06 346.9 30.06 337.9C21.06 328.9 16 316.7 16 304C16 291.3 21.06 279.1 30.06 270.1C39.06 261.1 51.27 256 64 256H448C460.7 256 472.9 261.1 481.9 270.1zM475.3 388.7C478.3 391.7 480 395.8 480 400V416C480 432.1 473.3 449.3 461.3 461.3C449.3 473.3 432.1 480 416 480H96C79.03 480 62.75 473.3 50.75 461.3C38.74 449.3 32 432.1 32 416V400C32 395.8 33.69 391.7 36.69 388.7C39.69 385.7 43.76 384 48 384H464C468.2 384 472.3 385.7 475.3 388.7zM50.39 220.8C45.93 218.6 42.03 215.5 38.97 211.6C35.91 207.7 33.79 203.2 32.75 198.4C31.71 193.5 31.8 188.5 32.99 183.7C54.98 97.02 146.5 32 256 32C365.5 32 457 97.02 479 183.7C480.2 188.5 480.3 193.5 479.2 198.4C478.2 203.2 476.1 207.7 473 211.6C469.1 215.5 466.1 218.6 461.6 220.8C457.2 222.9 452.3 224 447.3 224H64.67C59.73 224 54.84 222.9 50.39 220.8zM372.7 116.7C369.7 119.7 368 123.8 368 128C368 131.2 368.9 134.3 370.7 136.9C372.5 139.5 374.1 141.6 377.9 142.8C380.8 143.1 384 144.3 387.1 143.7C390.2 143.1 393.1 141.6 395.3 139.3C397.6 137.1 399.1 134.2 399.7 131.1C400.3 128 399.1 124.8 398.8 121.9C397.6 118.1 395.5 116.5 392.9 114.7C390.3 112.9 387.2 111.1 384 111.1C379.8 111.1 375.7 113.7 372.7 116.7V116.7zM244.7 84.69C241.7 87.69 240 91.76 240 96C240 99.16 240.9 102.3 242.7 104.9C244.5 107.5 246.1 109.6 249.9 110.8C252.8 111.1 256 112.3 259.1 111.7C262.2 111.1 265.1 109.6 267.3 107.3C269.6 105.1 271.1 102.2 271.7 99.12C272.3 96.02 271.1 92.8 270.8 89.88C269.6 86.95 267.5 84.45 264.9 82.7C262.3 80.94 259.2 79.1 256 79.1C251.8 79.1 247.7 81.69 244.7 84.69V84.69zM116.7 116.7C113.7 119.7 112 123.8 112 128C112 131.2 112.9 134.3 114.7 136.9C116.5 139.5 118.1 141.6 121.9 142.8C124.8 143.1 128 144.3 131.1 143.7C134.2 143.1 137.1 141.6 139.3 139.3C141.6 137.1 143.1 134.2 143.7 131.1C144.3 128 143.1 124.8 142.8 121.9C141.6 118.1 139.5 116.5 136.9 114.7C134.3 112.9 131.2 111.1 128 111.1C123.8 111.1 119.7 113.7 116.7 116.7L116.7 116.7z"
50169        })
50170      })
50171    },
50172    frequent: {
50173      outline: /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("svg", {
50174        xmlns: "http://www.w3.org/2000/svg",
50175        viewBox: "0 0 24 24",
50176        children: [
50177          /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("path", {
50178            d: "M13 4h-2l-.001 7H9v2h2v2h2v-2h4v-2h-4z"
50179          }),
50180          /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("path", {
50181            d: "M12 0C5.373 0 0 5.373 0 12s5.373 12 12 12 12-5.373 12-12S18.627 0 12 0m0 22C6.486 22 2 17.514 2 12S6.486 2 12 2s10 4.486 10 10-4.486 10-10 10"
50182          })
50183        ]
50184      }),
50185      solid: /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("svg", {
50186        xmlns: "http://www.w3.org/2000/svg",
50187        viewBox: "0 0 512 512",
50188        children: /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("path", {
50189          d: "M256 512C114.6 512 0 397.4 0 256C0 114.6 114.6 0 256 0C397.4 0 512 114.6 512 256C512 397.4 397.4 512 256 512zM232 256C232 264 236 271.5 242.7 275.1L338.7 339.1C349.7 347.3 364.6 344.3 371.1 333.3C379.3 322.3 376.3 307.4 365.3 300L280 243.2V120C280 106.7 269.3 96 255.1 96C242.7 96 231.1 106.7 231.1 120L232 256z"
50190        })
50191      })
50192    },
50193    nature: {
50194      outline: /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("svg", {
50195        xmlns: "http://www.w3.org/2000/svg",
50196        viewBox: "0 0 24 24",
50197        children: [
50198          /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("path", {
50199            d: "M15.5 8a1.5 1.5 0 1 0 .001 3.001A1.5 1.5 0 0 0 15.5 8M8.5 8a1.5 1.5 0 1 0 .001 3.001A1.5 1.5 0 0 0 8.5 8"
50200          }),
50201          /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("path", {
50202            d: "M18.933 0h-.027c-.97 0-2.138.787-3.018 1.497-1.274-.374-2.612-.51-3.887-.51-1.285 0-2.616.133-3.874.517C7.245.79 6.069 0 5.093 0h-.027C3.352 0 .07 2.67.002 7.026c-.039 2.479.276 4.238 1.04 5.013.254.258.882.677 1.295.882.191 3.177.922 5.238 2.536 6.38.897.637 2.187.949 3.2 1.102C8.04 20.6 8 20.795 8 21c0 1.773 2.35 3 4 3 1.648 0 4-1.227 4-3 0-.201-.038-.393-.072-.586 2.573-.385 5.435-1.877 5.925-7.587.396-.22.887-.568 1.104-.788.763-.774 1.079-2.534 1.04-5.013C23.929 2.67 20.646 0 18.933 0M3.223 9.135c-.237.281-.837 1.155-.884 1.238-.15-.41-.368-1.349-.337-3.291.051-3.281 2.478-4.972 3.091-5.031.256.015.731.27 1.265.646-1.11 1.171-2.275 2.915-2.352 5.125-.133.546-.398.858-.783 1.313M12 22c-.901 0-1.954-.693-2-1 0-.654.475-1.236 1-1.602V20a1 1 0 1 0 2 0v-.602c.524.365 1 .947 1 1.602-.046.307-1.099 1-2 1m3-3.48v.02a4.752 4.752 0 0 0-1.262-1.02c1.092-.516 2.239-1.334 2.239-2.217 0-1.842-1.781-2.195-3.977-2.195-2.196 0-3.978.354-3.978 2.195 0 .883 1.148 1.701 2.238 2.217A4.8 4.8 0 0 0 9 18.539v-.025c-1-.076-2.182-.281-2.973-.842-1.301-.92-1.838-3.045-1.853-6.478l.023-.041c.496-.826 1.49-1.45 1.804-3.102 0-2.047 1.357-3.631 2.362-4.522C9.37 3.178 10.555 3 11.948 3c1.447 0 2.685.192 3.733.57 1 .9 2.316 2.465 2.316 4.48.313 1.651 1.307 2.275 1.803 3.102.035.058.068.117.102.178-.059 5.967-1.949 7.01-4.902 7.19m6.628-8.202c-.037-.065-.074-.13-.113-.195a7.587 7.587 0 0 0-.739-.987c-.385-.455-.648-.768-.782-1.313-.076-2.209-1.241-3.954-2.353-5.124.531-.376 1.004-.63 1.261-.647.636.071 3.044 1.764 3.096 5.031.027 1.81-.347 3.218-.37 3.235"
50203          })
50204        ]
50205      }),
50206      solid: /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("svg", {
50207        xmlns: "http://www.w3.org/2000/svg",
50208        viewBox: "0 0 576 512",
50209        children: /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("path", {
50210          d: "M332.7 19.85C334.6 8.395 344.5 0 356.1 0C363.6 0 370.6 3.52 375.1 9.502L392 32H444.1C456.8 32 469.1 37.06 478.1 46.06L496 64H552C565.3 64 576 74.75 576 88V112C576 156.2 540.2 192 496 192H426.7L421.6 222.5L309.6 158.5L332.7 19.85zM448 64C439.2 64 432 71.16 432 80C432 88.84 439.2 96 448 96C456.8 96 464 88.84 464 80C464 71.16 456.8 64 448 64zM416 256.1V480C416 497.7 401.7 512 384 512H352C334.3 512 320 497.7 320 480V364.8C295.1 377.1 268.8 384 240 384C211.2 384 184 377.1 160 364.8V480C160 497.7 145.7 512 128 512H96C78.33 512 64 497.7 64 480V249.8C35.23 238.9 12.64 214.5 4.836 183.3L.9558 167.8C-3.331 150.6 7.094 133.2 24.24 128.1C41.38 124.7 58.76 135.1 63.05 152.2L66.93 167.8C70.49 182 83.29 191.1 97.97 191.1H303.8L416 256.1z"
50211        })
50212      })
50213    },
50214    objects: {
50215      outline: /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("svg", {
50216        xmlns: "http://www.w3.org/2000/svg",
50217        viewBox: "0 0 24 24",
50218        children: [
50219          /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("path", {
50220            d: "M12 0a9 9 0 0 0-5 16.482V21s2.035 3 5 3 5-3 5-3v-4.518A9 9 0 0 0 12 0zm0 2c3.86 0 7 3.141 7 7s-3.14 7-7 7-7-3.141-7-7 3.14-7 7-7zM9 17.477c.94.332 1.946.523 3 .523s2.06-.19 3-.523v.834c-.91.436-1.925.689-3 .689a6.924 6.924 0 0 1-3-.69v-.833zm.236 3.07A8.854 8.854 0 0 0 12 21c.965 0 1.888-.167 2.758-.451C14.155 21.173 13.153 22 12 22c-1.102 0-2.117-.789-2.764-1.453z"
50221          }),
50222          /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("path", {
50223            d: "M14.745 12.449h-.004c-.852-.024-1.188-.858-1.577-1.824-.421-1.061-.703-1.561-1.182-1.566h-.009c-.481 0-.783.497-1.235 1.537-.436.982-.801 1.811-1.636 1.791l-.276-.043c-.565-.171-.853-.691-1.284-1.794-.125-.313-.202-.632-.27-.913-.051-.213-.127-.53-.195-.634C7.067 9.004 7.039 9 6.99 9A1 1 0 0 1 7 7h.01c1.662.017 2.015 1.373 2.198 2.134.486-.981 1.304-2.058 2.797-2.075 1.531.018 2.28 1.153 2.731 2.141l.002-.008C14.944 8.424 15.327 7 16.979 7h.032A1 1 0 1 1 17 9h-.011c-.149.076-.256.474-.319.709a6.484 6.484 0 0 1-.311.951c-.429.973-.79 1.789-1.614 1.789"
50224          })
50225        ]
50226      }),
50227      solid: /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("svg", {
50228        xmlns: "http://www.w3.org/2000/svg",
50229        viewBox: "0 0 384 512",
50230        children: /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("path", {
50231          d: "M112.1 454.3c0 6.297 1.816 12.44 5.284 17.69l17.14 25.69c5.25 7.875 17.17 14.28 26.64 14.28h61.67c9.438 0 21.36-6.401 26.61-14.28l17.08-25.68c2.938-4.438 5.348-12.37 5.348-17.7L272 415.1h-160L112.1 454.3zM191.4 .0132C89.44 .3257 16 82.97 16 175.1c0 44.38 16.44 84.84 43.56 115.8c16.53 18.84 42.34 58.23 52.22 91.45c.0313 .25 .0938 .5166 .125 .7823h160.2c.0313-.2656 .0938-.5166 .125-.7823c9.875-33.22 35.69-72.61 52.22-91.45C351.6 260.8 368 220.4 368 175.1C368 78.61 288.9-.2837 191.4 .0132zM192 96.01c-44.13 0-80 35.89-80 79.1C112 184.8 104.8 192 96 192S80 184.8 80 176c0-61.76 50.25-111.1 112-111.1c8.844 0 16 7.159 16 16S200.8 96.01 192 96.01z"
50232        })
50233      })
50234    },
50235    people: {
50236      outline: /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("svg", {
50237        xmlns: "http://www.w3.org/2000/svg",
50238        viewBox: "0 0 24 24",
50239        children: [
50240          /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("path", {
50241            d: "M12 0C5.373 0 0 5.373 0 12s5.373 12 12 12 12-5.373 12-12S18.627 0 12 0m0 22C6.486 22 2 17.514 2 12S6.486 2 12 2s10 4.486 10 10-4.486 10-10 10"
50242          }),
50243          /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("path", {
50244            d: "M8 7a2 2 0 1 0-.001 3.999A2 2 0 0 0 8 7M16 7a2 2 0 1 0-.001 3.999A2 2 0 0 0 16 7M15.232 15c-.693 1.195-1.87 2-3.349 2-1.477 0-2.655-.805-3.347-2H15m3-2H6a6 6 0 1 0 12 0"
50245          })
50246        ]
50247      }),
50248      solid: /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("svg", {
50249        xmlns: "http://www.w3.org/2000/svg",
50250        viewBox: "0 0 512 512",
50251        children: /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("path", {
50252          d: "M0 256C0 114.6 114.6 0 256 0C397.4 0 512 114.6 512 256C512 397.4 397.4 512 256 512C114.6 512 0 397.4 0 256zM256 432C332.1 432 396.2 382 415.2 314.1C419.1 300.4 407.8 288 393.6 288H118.4C104.2 288 92.92 300.4 96.76 314.1C115.8 382 179.9 432 256 432V432zM176.4 160C158.7 160 144.4 174.3 144.4 192C144.4 209.7 158.7 224 176.4 224C194 224 208.4 209.7 208.4 192C208.4 174.3 194 160 176.4 160zM336.4 224C354 224 368.4 209.7 368.4 192C368.4 174.3 354 160 336.4 160C318.7 160 304.4 174.3 304.4 192C304.4 209.7 318.7 224 336.4 224z"
50253        })
50254      })
50255    },
50256    places: {
50257      outline: /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("svg", {
50258        xmlns: "http://www.w3.org/2000/svg",
50259        viewBox: "0 0 24 24",
50260        children: [
50261          /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("path", {
50262            d: "M6.5 12C5.122 12 4 13.121 4 14.5S5.122 17 6.5 17 9 15.879 9 14.5 7.878 12 6.5 12m0 3c-.275 0-.5-.225-.5-.5s.225-.5.5-.5.5.225.5.5-.225.5-.5.5M17.5 12c-1.378 0-2.5 1.121-2.5 2.5s1.122 2.5 2.5 2.5 2.5-1.121 2.5-2.5-1.122-2.5-2.5-2.5m0 3c-.275 0-.5-.225-.5-.5s.225-.5.5-.5.5.225.5.5-.225.5-.5.5"
50263          }),
50264          /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("path", {
50265            d: "M22.482 9.494l-1.039-.346L21.4 9h.6c.552 0 1-.439 1-.992 0-.006-.003-.008-.003-.008H23c0-1-.889-2-1.984-2h-.642l-.731-1.717C19.262 3.012 18.091 2 16.764 2H7.236C5.909 2 4.738 3.012 4.357 4.283L3.626 6h-.642C1.889 6 1 7 1 8h.003S1 8.002 1 8.008C1 8.561 1.448 9 2 9h.6l-.043.148-1.039.346a2.001 2.001 0 0 0-1.359 2.097l.751 7.508a1 1 0 0 0 .994.901H3v1c0 1.103.896 2 2 2h2c1.104 0 2-.897 2-2v-1h6v1c0 1.103.896 2 2 2h2c1.104 0 2-.897 2-2v-1h1.096a.999.999 0 0 0 .994-.901l.751-7.508a2.001 2.001 0 0 0-1.359-2.097M6.273 4.857C6.402 4.43 6.788 4 7.236 4h9.527c.448 0 .834.43.963.857L19.313 9H4.688l1.585-4.143zM7 21H5v-1h2v1zm12 0h-2v-1h2v1zm2.189-3H2.811l-.662-6.607L3 11h18l.852.393L21.189 18z"
50266          })
50267        ]
50268      }),
50269      solid: /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("svg", {
50270        xmlns: "http://www.w3.org/2000/svg",
50271        viewBox: "0 0 512 512",
50272        children: /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("path", {
50273          d: "M39.61 196.8L74.8 96.29C88.27 57.78 124.6 32 165.4 32H346.6C387.4 32 423.7 57.78 437.2 96.29L472.4 196.8C495.6 206.4 512 229.3 512 256V448C512 465.7 497.7 480 480 480H448C430.3 480 416 465.7 416 448V400H96V448C96 465.7 81.67 480 64 480H32C14.33 480 0 465.7 0 448V256C0 229.3 16.36 206.4 39.61 196.8V196.8zM109.1 192H402.9L376.8 117.4C372.3 104.6 360.2 96 346.6 96H165.4C151.8 96 139.7 104.6 135.2 117.4L109.1 192zM96 256C78.33 256 64 270.3 64 288C64 305.7 78.33 320 96 320C113.7 320 128 305.7 128 288C128 270.3 113.7 256 96 256zM416 320C433.7 320 448 305.7 448 288C448 270.3 433.7 256 416 256C398.3 256 384 270.3 384 288C384 305.7 398.3 320 416 320z"
50274        })
50275      })
50276    },
50277    symbols: {
50278      outline: /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("svg", {
50279        xmlns: "http://www.w3.org/2000/svg",
50280        viewBox: "0 0 24 24",
50281        children: /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("path", {
50282          d: "M0 0h11v2H0zM4 11h3V6h4V4H0v2h4zM15.5 17c1.381 0 2.5-1.116 2.5-2.493s-1.119-2.493-2.5-2.493S13 13.13 13 14.507 14.119 17 15.5 17m0-2.986c.276 0 .5.222.5.493 0 .272-.224.493-.5.493s-.5-.221-.5-.493.224-.493.5-.493M21.5 19.014c-1.381 0-2.5 1.116-2.5 2.493S20.119 24 21.5 24s2.5-1.116 2.5-2.493-1.119-2.493-2.5-2.493m0 2.986a.497.497 0 0 1-.5-.493c0-.271.224-.493.5-.493s.5.222.5.493a.497.497 0 0 1-.5.493M22 13l-9 9 1.513 1.5 8.99-9.009zM17 11c2.209 0 4-1.119 4-2.5V2s.985-.161 1.498.949C23.01 4.055 23 6 23 6s1-1.119 1-3.135C24-.02 21 0 21 0h-2v6.347A5.853 5.853 0 0 0 17 6c-2.209 0-4 1.119-4 2.5s1.791 2.5 4 2.5M10.297 20.482l-1.475-1.585a47.54 47.54 0 0 1-1.442 1.129c-.307-.288-.989-1.016-2.045-2.183.902-.836 1.479-1.466 1.729-1.892s.376-.871.376-1.336c0-.592-.273-1.178-.818-1.759-.546-.581-1.329-.871-2.349-.871-1.008 0-1.79.293-2.344.879-.556.587-.832 1.181-.832 1.784 0 .813.419 1.748 1.256 2.805-.847.614-1.444 1.208-1.794 1.784a3.465 3.465 0 0 0-.523 1.833c0 .857.308 1.56.924 2.107.616.549 1.423.823 2.42.823 1.173 0 2.444-.379 3.813-1.137L8.235 24h2.819l-2.09-2.383 1.333-1.135zm-6.736-6.389a1.02 1.02 0 0 1 .73-.286c.31 0 .559.085.747.254a.849.849 0 0 1 .283.659c0 .518-.419 1.112-1.257 1.784-.536-.651-.805-1.231-.805-1.742a.901.901 0 0 1 .302-.669M3.74 22c-.427 0-.778-.116-1.057-.349-.279-.232-.418-.487-.418-.766 0-.594.509-1.288 1.527-2.083.968 1.134 1.717 1.946 2.248 2.438-.921.507-1.686.76-2.3.76"
50283        })
50284      }),
50285      solid: /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("svg", {
50286        xmlns: "http://www.w3.org/2000/svg",
50287        viewBox: "0 0 512 512",
50288        children: /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("path", {
50289          d: "M500.3 7.251C507.7 13.33 512 22.41 512 31.1V175.1C512 202.5 483.3 223.1 447.1 223.1C412.7 223.1 383.1 202.5 383.1 175.1C383.1 149.5 412.7 127.1 447.1 127.1V71.03L351.1 90.23V207.1C351.1 234.5 323.3 255.1 287.1 255.1C252.7 255.1 223.1 234.5 223.1 207.1C223.1 181.5 252.7 159.1 287.1 159.1V63.1C287.1 48.74 298.8 35.61 313.7 32.62L473.7 .6198C483.1-1.261 492.9 1.173 500.3 7.251H500.3zM74.66 303.1L86.5 286.2C92.43 277.3 102.4 271.1 113.1 271.1H174.9C185.6 271.1 195.6 277.3 201.5 286.2L213.3 303.1H239.1C266.5 303.1 287.1 325.5 287.1 351.1V463.1C287.1 490.5 266.5 511.1 239.1 511.1H47.1C21.49 511.1-.0019 490.5-.0019 463.1V351.1C-.0019 325.5 21.49 303.1 47.1 303.1H74.66zM143.1 359.1C117.5 359.1 95.1 381.5 95.1 407.1C95.1 434.5 117.5 455.1 143.1 455.1C170.5 455.1 191.1 434.5 191.1 407.1C191.1 381.5 170.5 359.1 143.1 359.1zM440.3 367.1H496C502.7 367.1 508.6 372.1 510.1 378.4C513.3 384.6 511.6 391.7 506.5 396L378.5 508C372.9 512.1 364.6 513.3 358.6 508.9C352.6 504.6 350.3 496.6 353.3 489.7L391.7 399.1H336C329.3 399.1 323.4 395.9 321 389.6C318.7 383.4 320.4 376.3 325.5 371.1L453.5 259.1C459.1 255 467.4 254.7 473.4 259.1C479.4 263.4 481.6 271.4 478.7 278.3L440.3 367.1zM116.7 219.1L19.85 119.2C-8.112 90.26-6.614 42.31 24.85 15.34C51.82-8.137 93.26-3.642 118.2 21.83L128.2 32.32L137.7 21.83C162.7-3.642 203.6-8.137 231.6 15.34C262.6 42.31 264.1 90.26 236.1 119.2L139.7 219.1C133.2 225.6 122.7 225.6 116.7 219.1H116.7z"
50290        })
50291      })
50292    }
50293  };
50294  var $fcccfb36ed0cde68$var$search = {
50295    loupe: /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("svg", {
50296      xmlns: "http://www.w3.org/2000/svg",
50297      viewBox: "0 0 20 20",
50298      children: /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("path", {
50299        d: "M12.9 14.32a8 8 0 1 1 1.41-1.41l5.35 5.33-1.42 1.42-5.33-5.34zM8 14A6 6 0 1 0 8 2a6 6 0 0 0 0 12z"
50300      })
50301    }),
50302    delete: /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("svg", {
50303      xmlns: "http://www.w3.org/2000/svg",
50304      viewBox: "0 0 20 20",
50305      children: /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("path", {
50306        d: "M10 8.586L2.929 1.515 1.515 2.929 8.586 10l-7.071 7.071 1.414 1.414L10 11.414l7.071 7.071 1.414-1.414L11.414 10l7.071-7.071-1.414-1.414L10 8.586z"
50307      })
50308    })
50309  };
50310  var $fcccfb36ed0cde68$export$2e2bcd8739ae039 = {
50311    categories: $fcccfb36ed0cde68$var$categories,
50312    search: $fcccfb36ed0cde68$var$search
50313  };
50314  function $254755d3f438722f$export$2e2bcd8739ae039(props) {
50315    let { id: id3, skin, emoji } = props;
50316    if (props.shortcodes) {
50317      const matches = props.shortcodes.match((0, $c4d155af13ad4d4b$export$2e2bcd8739ae039).SHORTCODES_REGEX);
50318      if (matches) {
50319        id3 = matches[1];
50320        if (matches[2]) skin = matches[2];
50321      }
50322    }
50323    emoji || (emoji = (0, $c4d155af13ad4d4b$export$2e2bcd8739ae039).get(id3 || props.native));
50324    if (!emoji) return props.fallback;
50325    const emojiSkin = emoji.skins[skin - 1] || emoji.skins[0];
50326    const imageSrc = emojiSkin.src || (props.set != "native" && !props.spritesheet ? typeof props.getImageURL === "function" ? props.getImageURL(props.set, emojiSkin.unified) : `https://cdn.jsdelivr.net/npm/emoji-datasource-${props.set}@15.0.1/img/${props.set}/64/${emojiSkin.unified}.png` : void 0);
50327    const spritesheetSrc = typeof props.getSpritesheetURL === "function" ? props.getSpritesheetURL(props.set) : `https://cdn.jsdelivr.net/npm/emoji-datasource-${props.set}@15.0.1/img/${props.set}/sheets-256/64.png`;
50328    return /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("span", {
50329      class: "emoji-mart-emoji",
50330      "data-emoji-set": props.set,
50331      children: imageSrc ? /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("img", {
50332        style: {
50333          maxWidth: props.size || "1em",
50334          maxHeight: props.size || "1em",
50335          display: "inline-block"
50336        },
50337        alt: emojiSkin.native || emojiSkin.shortcodes,
50338        src: imageSrc
50339      }) : props.set == "native" ? /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("span", {
50340        style: {
50341          fontSize: props.size,
50342          fontFamily: '"EmojiMart", "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "Apple Color Emoji", "Twemoji Mozilla", "Noto Color Emoji", "Android Emoji"'
50343        },
50344        children: emojiSkin.native
50345      }) : /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("span", {
50346        style: {
50347          display: "block",
50348          width: props.size,
50349          height: props.size,
50350          backgroundImage: `url(${spritesheetSrc})`,
50351          backgroundSize: `${100 * (0, $7adb23b0109cc36a$export$2d0294657ab35f1b).sheet.cols}% ${100 * (0, $7adb23b0109cc36a$export$2d0294657ab35f1b).sheet.rows}%`,
50352          backgroundPosition: `${100 / ((0, $7adb23b0109cc36a$export$2d0294657ab35f1b).sheet.cols - 1) * emojiSkin.x}% ${100 / ((0, $7adb23b0109cc36a$export$2d0294657ab35f1b).sheet.rows - 1) * emojiSkin.y}%`
50353        }
50354      })
50355    });
50356  }
50357  var $6f57cc9cd54c5aaa$var$WindowHTMLElement = typeof window !== "undefined" && window.HTMLElement ? window.HTMLElement : Object;
50358  var $6f57cc9cd54c5aaa$export$2e2bcd8739ae039 = class extends $6f57cc9cd54c5aaa$var$WindowHTMLElement {
50359    static get observedAttributes() {
50360      return Object.keys(this.Props);
50361    }
50362    update(props = {}) {
50363      for (let k2 in props) this.attributeChangedCallback(k2, null, props[k2]);
50364    }
50365    attributeChangedCallback(attr, _3, newValue) {
50366      if (!this.component) return;
50367      const value = (0, $7adb23b0109cc36a$export$88c9ddb45cea7241)(attr, {
50368        [attr]: newValue
50369      }, this.constructor.Props, this);
50370      if (this.component.componentWillReceiveProps) this.component.componentWillReceiveProps({
50371        [attr]: value
50372      });
50373      else {
50374        this.component.props[attr] = value;
50375        this.component.forceUpdate();
50376      }
50377    }
50378    disconnectedCallback() {
50379      this.disconnected = true;
50380      if (this.component && this.component.unregister) this.component.unregister();
50381    }
50382    constructor(props = {}) {
50383      super();
50384      this.props = props;
50385      if (props.parent || props.ref) {
50386        let ref = null;
50387        const parent = props.parent || (ref = props.ref && props.ref.current);
50388        if (ref) ref.innerHTML = "";
50389        if (parent) parent.appendChild(this);
50390      }
50391    }
50392  };
50393  var $26f27c338a96b1a6$export$2e2bcd8739ae039 = class extends (0, $6f57cc9cd54c5aaa$export$2e2bcd8739ae039) {
50394    setShadow() {
50395      this.attachShadow({
50396        mode: "open"
50397      });
50398    }
50399    injectStyles(styles) {
50400      if (!styles) return;
50401      const style = document.createElement("style");
50402      style.textContent = styles;
50403      this.shadowRoot.insertBefore(style, this.shadowRoot.firstChild);
50404    }
50405    constructor(props, { styles } = {}) {
50406      super(props);
50407      this.setShadow();
50408      this.injectStyles(styles);
50409    }
50410  };
50411  var $3d90f6e46fb2dd47$export$2e2bcd8739ae039 = {
50412    fallback: "",
50413    id: "",
50414    native: "",
50415    shortcodes: "",
50416    size: {
50417      value: "",
50418      transform: (value) => {
50419        if (!/\D/.test(value)) return `${value}px`;
50420        return value;
50421      }
50422    },
50423    // Shared
50424    set: (0, $b247ea80b67298d5$export$2e2bcd8739ae039).set,
50425    skin: (0, $b247ea80b67298d5$export$2e2bcd8739ae039).skin
50426  };
50427  var $331b4160623139bf$export$2e2bcd8739ae039 = class extends (0, $6f57cc9cd54c5aaa$export$2e2bcd8739ae039) {
50428    async connectedCallback() {
50429      const props = (0, $7adb23b0109cc36a$export$75fe5f91d452f94b)(this.props, (0, $3d90f6e46fb2dd47$export$2e2bcd8739ae039), this);
50430      props.element = this;
50431      props.ref = (component) => {
50432        this.component = component;
50433      };
50434      await (0, $7adb23b0109cc36a$export$2cd8252107eb640b)();
50435      if (this.disconnected) return;
50436      (0, $fb96b826c0c5f37a$export$b3890eb0ae9dca99)(/* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)((0, $254755d3f438722f$export$2e2bcd8739ae039), {
50437        ...props
50438      }), this);
50439    }
50440    constructor(props) {
50441      super(props);
50442    }
50443  };
50444  (0, $c770c458706daa72$export$2e2bcd8739ae039)($331b4160623139bf$export$2e2bcd8739ae039, "Props", (0, $3d90f6e46fb2dd47$export$2e2bcd8739ae039));
50445  if (typeof customElements !== "undefined" && !customElements.get("em-emoji")) customElements.define("em-emoji", $331b4160623139bf$export$2e2bcd8739ae039);
50446  var $1a9a8ef576b7773d$var$t;
50447  var $1a9a8ef576b7773d$var$u;
50448  var $1a9a8ef576b7773d$var$r;
50449  var $1a9a8ef576b7773d$var$i = [];
50450  var $1a9a8ef576b7773d$var$c = (0, $fb96b826c0c5f37a$export$41c562ebe57d11e2).__b;
50451  var $1a9a8ef576b7773d$var$f = (0, $fb96b826c0c5f37a$export$41c562ebe57d11e2).__r;
50452  var $1a9a8ef576b7773d$var$e = (0, $fb96b826c0c5f37a$export$41c562ebe57d11e2).diffed;
50453  var $1a9a8ef576b7773d$var$a = (0, $fb96b826c0c5f37a$export$41c562ebe57d11e2).__c;
50454  var $1a9a8ef576b7773d$var$v = (0, $fb96b826c0c5f37a$export$41c562ebe57d11e2).unmount;
50455  function $1a9a8ef576b7773d$var$x() {
50456    var t6;
50457    for ($1a9a8ef576b7773d$var$i.sort(function(n11, t7) {
50458      return n11.__v.__b - t7.__v.__b;
50459    }); t6 = $1a9a8ef576b7773d$var$i.pop(); ) if (t6.__P) try {
50460      t6.__H.__h.forEach($1a9a8ef576b7773d$var$g), t6.__H.__h.forEach($1a9a8ef576b7773d$var$j), t6.__H.__h = [];
50461    } catch (u4) {
50462      t6.__H.__h = [], (0, $fb96b826c0c5f37a$export$41c562ebe57d11e2).__e(u4, t6.__v);
50463    }
50464  }
50465  (0, $fb96b826c0c5f37a$export$41c562ebe57d11e2).__b = function(n12) {
50466    $1a9a8ef576b7773d$var$u = null, $1a9a8ef576b7773d$var$c && $1a9a8ef576b7773d$var$c(n12);
50467  }, (0, $fb96b826c0c5f37a$export$41c562ebe57d11e2).__r = function(n13) {
50468    $1a9a8ef576b7773d$var$f && $1a9a8ef576b7773d$var$f(n13), $1a9a8ef576b7773d$var$t = 0;
50469    var r8 = ($1a9a8ef576b7773d$var$u = n13.__c).__H;
50470    r8 && (r8.__h.forEach($1a9a8ef576b7773d$var$g), r8.__h.forEach($1a9a8ef576b7773d$var$j), r8.__h = []);
50471  }, (0, $fb96b826c0c5f37a$export$41c562ebe57d11e2).diffed = function(t8) {
50472    $1a9a8ef576b7773d$var$e && $1a9a8ef576b7773d$var$e(t8);
50473    var o6 = t8.__c;
50474    o6 && o6.__H && o6.__H.__h.length && (1 !== $1a9a8ef576b7773d$var$i.push(o6) && $1a9a8ef576b7773d$var$r === (0, $fb96b826c0c5f37a$export$41c562ebe57d11e2).requestAnimationFrame || (($1a9a8ef576b7773d$var$r = (0, $fb96b826c0c5f37a$export$41c562ebe57d11e2).requestAnimationFrame) || function(n14) {
50475      var t9, u5 = function() {
50476        clearTimeout(r9), $1a9a8ef576b7773d$var$b && cancelAnimationFrame(t9), setTimeout(n14);
50477      }, r9 = setTimeout(u5, 100);
50478      $1a9a8ef576b7773d$var$b && (t9 = requestAnimationFrame(u5));
50479    })($1a9a8ef576b7773d$var$x)), $1a9a8ef576b7773d$var$u = null;
50480  }, (0, $fb96b826c0c5f37a$export$41c562ebe57d11e2).__c = function(t10, u6) {
50481    u6.some(function(t11) {
50482      try {
50483        t11.__h.forEach($1a9a8ef576b7773d$var$g), t11.__h = t11.__h.filter(function(n15) {
50484          return !n15.__ || $1a9a8ef576b7773d$var$j(n15);
50485        });
50486      } catch (r10) {
50487        u6.some(function(n16) {
50488          n16.__h && (n16.__h = []);
50489        }), u6 = [], (0, $fb96b826c0c5f37a$export$41c562ebe57d11e2).__e(r10, t11.__v);
50490      }
50491    }), $1a9a8ef576b7773d$var$a && $1a9a8ef576b7773d$var$a(t10, u6);
50492  }, (0, $fb96b826c0c5f37a$export$41c562ebe57d11e2).unmount = function(t12) {
50493    $1a9a8ef576b7773d$var$v && $1a9a8ef576b7773d$var$v(t12);
50494    var u7, r11 = t12.__c;
50495    r11 && r11.__H && (r11.__H.__.forEach(function(n17) {
50496      try {
50497        $1a9a8ef576b7773d$var$g(n17);
50498      } catch (n18) {
50499        u7 = n18;
50500      }
50501    }), u7 && (0, $fb96b826c0c5f37a$export$41c562ebe57d11e2).__e(u7, r11.__v));
50502  };
50503  var $1a9a8ef576b7773d$var$b = "function" == typeof requestAnimationFrame;
50504  function $1a9a8ef576b7773d$var$g(n19) {
50505    var t13 = $1a9a8ef576b7773d$var$u, r12 = n19.__c;
50506    "function" == typeof r12 && (n19.__c = void 0, r12()), $1a9a8ef576b7773d$var$u = t13;
50507  }
50508  function $1a9a8ef576b7773d$var$j(n20) {
50509    var t14 = $1a9a8ef576b7773d$var$u;
50510    n20.__c = n20.__(), $1a9a8ef576b7773d$var$u = t14;
50511  }
50512  function $dc040a17866866fa$var$S(n1, t1) {
50513    for (var e1 in t1) n1[e1] = t1[e1];
50514    return n1;
50515  }
50516  function $dc040a17866866fa$var$C(n2, t2) {
50517    for (var e2 in n2) if ("__source" !== e2 && !(e2 in t2)) return true;
50518    for (var r1 in t2) if ("__source" !== r1 && n2[r1] !== t2[r1]) return true;
50519    return false;
50520  }
50521  function $dc040a17866866fa$export$221d75b3f55bb0bd(n3) {
50522    this.props = n3;
50523  }
50524  ($dc040a17866866fa$export$221d75b3f55bb0bd.prototype = new (0, $fb96b826c0c5f37a$export$16fa2f45be04daa8)()).isPureReactComponent = true, $dc040a17866866fa$export$221d75b3f55bb0bd.prototype.shouldComponentUpdate = function(n6, t5) {
50525    return $dc040a17866866fa$var$C(this.props, n6) || $dc040a17866866fa$var$C(this.state, t5);
50526  };
50527  var $dc040a17866866fa$var$w = (0, $fb96b826c0c5f37a$export$41c562ebe57d11e2).__b;
50528  (0, $fb96b826c0c5f37a$export$41c562ebe57d11e2).__b = function(n7) {
50529    n7.type && n7.type.__f && n7.ref && (n7.props.ref = n7.ref, n7.ref = null), $dc040a17866866fa$var$w && $dc040a17866866fa$var$w(n7);
50530  };
50531  var $dc040a17866866fa$var$R = "undefined" != typeof Symbol && Symbol.for && Symbol.for("react.forward_ref") || 3911;
50532  var $dc040a17866866fa$var$A = (0, $fb96b826c0c5f37a$export$41c562ebe57d11e2).__e;
50533  (0, $fb96b826c0c5f37a$export$41c562ebe57d11e2).__e = function(n12, t10, e6) {
50534    if (n12.then) {
50535      for (var r5, u1 = t10; u1 = u1.__; ) if ((r5 = u1.__c) && r5.__c) return null == t10.__e && (t10.__e = e6.__e, t10.__k = e6.__k), r5.__c(n12, t10);
50536    }
50537    $dc040a17866866fa$var$A(n12, t10, e6);
50538  };
50539  var $dc040a17866866fa$var$O = (0, $fb96b826c0c5f37a$export$41c562ebe57d11e2).unmount;
50540  function $dc040a17866866fa$export$74bf444e3cd11ea5() {
50541    this.__u = 0, this.t = null, this.__b = null;
50542  }
50543  function $dc040a17866866fa$var$U(n13) {
50544    var t11 = n13.__.__c;
50545    return t11 && t11.__e && t11.__e(n13);
50546  }
50547  function $dc040a17866866fa$export$998bcd577473dd93() {
50548    this.u = null, this.o = null;
50549  }
50550  (0, $fb96b826c0c5f37a$export$41c562ebe57d11e2).unmount = function(n17) {
50551    var t13 = n17.__c;
50552    t13 && t13.__R && t13.__R(), t13 && true === n17.__h && (n17.type = null), $dc040a17866866fa$var$O && $dc040a17866866fa$var$O(n17);
50553  }, ($dc040a17866866fa$export$74bf444e3cd11ea5.prototype = new (0, $fb96b826c0c5f37a$export$16fa2f45be04daa8)()).__c = function(n18, t14) {
50554    var e8 = t14.__c, r7 = this;
50555    null == r7.t && (r7.t = []), r7.t.push(e8);
50556    var u4 = $dc040a17866866fa$var$U(r7.__v), o1 = false, i1 = function() {
50557      o1 || (o1 = true, e8.__R = null, u4 ? u4(l1) : l1());
50558    };
50559    e8.__R = i1;
50560    var l1 = function() {
50561      if (!--r7.__u) {
50562        if (r7.state.__e) {
50563          var n19 = r7.state.__e;
50564          r7.__v.__k[0] = function n22(t17, e9, r8) {
50565            return t17 && (t17.__v = null, t17.__k = t17.__k && t17.__k.map(function(t18) {
50566              return n22(t18, e9, r8);
50567            }), t17.__c && t17.__c.__P === e9 && (t17.__e && r8.insertBefore(t17.__e, t17.__d), t17.__c.__e = true, t17.__c.__P = r8)), t17;
50568          }(n19, n19.__c.__P, n19.__c.__O);
50569        }
50570        var t15;
50571        for (r7.setState({
50572          __e: r7.__b = null
50573        }); t15 = r7.t.pop(); ) t15.forceUpdate();
50574      }
50575    }, c1 = true === t14.__h;
50576    r7.__u++ || c1 || r7.setState({
50577      __e: r7.__b = r7.__v.__k[0]
50578    }), n18.then(i1, i1);
50579  }, $dc040a17866866fa$export$74bf444e3cd11ea5.prototype.componentWillUnmount = function() {
50580    this.t = [];
50581  }, $dc040a17866866fa$export$74bf444e3cd11ea5.prototype.render = function(n23, t19) {
50582    if (this.__b) {
50583      if (this.__v.__k) {
50584        var e10 = document.createElement("div"), r9 = this.__v.__k[0].__c;
50585        this.__v.__k[0] = function n24(t20, e13, r12) {
50586          return t20 && (t20.__c && t20.__c.__H && (t20.__c.__H.__.forEach(function(n25) {
50587            "function" == typeof n25.__c && n25.__c();
50588          }), t20.__c.__H = null), null != (t20 = $dc040a17866866fa$var$S({}, t20)).__c && (t20.__c.__P === r12 && (t20.__c.__P = e13), t20.__c = null), t20.__k = t20.__k && t20.__k.map(function(t21) {
50589            return n24(t21, e13, r12);
50590          })), t20;
50591        }(this.__b, e10, r9.__O = r9.__P);
50592      }
50593      this.__b = null;
50594    }
50595    var u5 = t19.__e && (0, $fb96b826c0c5f37a$export$c8a8987d4410bf2d)((0, $fb96b826c0c5f37a$export$ffb0004e005737fa), null, n23.fallback);
50596    return u5 && (u5.__h = null), [
50597      (0, $fb96b826c0c5f37a$export$c8a8987d4410bf2d)((0, $fb96b826c0c5f37a$export$ffb0004e005737fa), null, t19.__e ? null : n23.children),
50598      u5
50599    ];
50600  };
50601  var $dc040a17866866fa$var$T = function(n26, t22, e14) {
50602    if (++e14[1] === e14[0] && n26.o.delete(t22), n26.props.revealOrder && ("t" !== n26.props.revealOrder[0] || !n26.o.size)) for (e14 = n26.u; e14; ) {
50603      for (; e14.length > 3; ) e14.pop()();
50604      if (e14[1] < e14[0]) break;
50605      n26.u = e14 = e14[2];
50606    }
50607  };
50608  ($dc040a17866866fa$export$998bcd577473dd93.prototype = new (0, $fb96b826c0c5f37a$export$16fa2f45be04daa8)()).__e = function(n33) {
50609    var t25 = this, e16 = $dc040a17866866fa$var$U(t25.__v), r13 = t25.o.get(n33);
50610    return r13[0]++, function(u6) {
50611      var o2 = function() {
50612        t25.props.revealOrder ? (r13.push(u6), $dc040a17866866fa$var$T(t25, n33, r13)) : u6();
50613      };
50614      e16 ? e16(o2) : o2();
50615    };
50616  }, $dc040a17866866fa$export$998bcd577473dd93.prototype.render = function(n34) {
50617    this.u = null, this.o = /* @__PURE__ */ new Map();
50618    var t26 = (0, $fb96b826c0c5f37a$export$47e4c5b300681277)(n34.children);
50619    n34.revealOrder && "b" === n34.revealOrder[0] && t26.reverse();
50620    for (var e17 = t26.length; e17--; ) this.o.set(t26[e17], this.u = [
50621      1,
50622      0,
50623      this.u
50624    ]);
50625    return n34.children;
50626  }, $dc040a17866866fa$export$998bcd577473dd93.prototype.componentDidUpdate = $dc040a17866866fa$export$998bcd577473dd93.prototype.componentDidMount = function() {
50627    var n35 = this;
50628    this.o.forEach(function(t27, e18) {
50629      $dc040a17866866fa$var$T(n35, e18, t27);
50630    });
50631  };
50632  var $dc040a17866866fa$var$j = "undefined" != typeof Symbol && Symbol.for && Symbol.for("react.element") || 60103;
50633  var $dc040a17866866fa$var$P = /^(?:accent|alignment|arabic|baseline|cap|clip(?!PathU)|color|dominant|fill|flood|font|glyph(?!R)|horiz|marker(?!H|W|U)|overline|paint|stop|strikethrough|stroke|text(?!L)|underline|unicode|units|v|vector|vert|word|writing|x(?!C))[A-Z]/;
50634  var $dc040a17866866fa$var$V = "undefined" != typeof document;
50635  var $dc040a17866866fa$var$z = function(n36) {
50636    return ("undefined" != typeof Symbol && "symbol" == typeof Symbol() ? /fil|che|rad/i : /fil|che|ra/i).test(n36);
50637  };
50638  (0, $fb96b826c0c5f37a$export$16fa2f45be04daa8).prototype.isReactComponent = {}, [
50639    "componentWillMount",
50640    "componentWillReceiveProps",
50641    "componentWillUpdate"
50642  ].forEach(function(n39) {
50643    Object.defineProperty((0, $fb96b826c0c5f37a$export$16fa2f45be04daa8).prototype, n39, {
50644      configurable: true,
50645      get: function() {
50646        return this["UNSAFE_" + n39];
50647      },
50648      set: function(t30) {
50649        Object.defineProperty(this, n39, {
50650          configurable: true,
50651          writable: true,
50652          value: t30
50653        });
50654      }
50655    });
50656  });
50657  var $dc040a17866866fa$var$H = (0, $fb96b826c0c5f37a$export$41c562ebe57d11e2).event;
50658  function $dc040a17866866fa$var$Z() {
50659  }
50660  function $dc040a17866866fa$var$Y() {
50661    return this.cancelBubble;
50662  }
50663  function $dc040a17866866fa$var$q() {
50664    return this.defaultPrevented;
50665  }
50666  (0, $fb96b826c0c5f37a$export$41c562ebe57d11e2).event = function(n40) {
50667    return $dc040a17866866fa$var$H && (n40 = $dc040a17866866fa$var$H(n40)), n40.persist = $dc040a17866866fa$var$Z, n40.isPropagationStopped = $dc040a17866866fa$var$Y, n40.isDefaultPrevented = $dc040a17866866fa$var$q, n40.nativeEvent = n40;
50668  };
50669  var $dc040a17866866fa$var$G;
50670  var $dc040a17866866fa$var$J = {
50671    configurable: true,
50672    get: function() {
50673      return this.class;
50674    }
50675  };
50676  var $dc040a17866866fa$var$K = (0, $fb96b826c0c5f37a$export$41c562ebe57d11e2).vnode;
50677  (0, $fb96b826c0c5f37a$export$41c562ebe57d11e2).vnode = function(n41) {
50678    var t31 = n41.type, e21 = n41.props, r14 = e21;
50679    if ("string" == typeof t31) {
50680      var u7 = -1 === t31.indexOf("-");
50681      for (var o3 in r14 = {}, e21) {
50682        var i2 = e21[o3];
50683        $dc040a17866866fa$var$V && "children" === o3 && "noscript" === t31 || "value" === o3 && "defaultValue" in e21 && null == i2 || ("defaultValue" === o3 && "value" in e21 && null == e21.value ? o3 = "value" : "download" === o3 && true === i2 ? i2 = "" : /ondoubleclick/i.test(o3) ? o3 = "ondblclick" : /^onchange(textarea|input)/i.test(o3 + t31) && !$dc040a17866866fa$var$z(e21.type) ? o3 = "oninput" : /^onfocus$/i.test(o3) ? o3 = "onfocusin" : /^onblur$/i.test(o3) ? o3 = "onfocusout" : /^on(Ani|Tra|Tou|BeforeInp)/.test(o3) ? o3 = o3.toLowerCase() : u7 && $dc040a17866866fa$var$P.test(o3) ? o3 = o3.replace(/[A-Z0-9]/, "-$&").toLowerCase() : null === i2 && (i2 = void 0), r14[o3] = i2);
50684      }
50685      "select" == t31 && r14.multiple && Array.isArray(r14.value) && (r14.value = (0, $fb96b826c0c5f37a$export$47e4c5b300681277)(e21.children).forEach(function(n42) {
50686        n42.props.selected = -1 != r14.value.indexOf(n42.props.value);
50687      })), "select" == t31 && null != r14.defaultValue && (r14.value = (0, $fb96b826c0c5f37a$export$47e4c5b300681277)(e21.children).forEach(function(n43) {
50688        n43.props.selected = r14.multiple ? -1 != r14.defaultValue.indexOf(n43.props.value) : r14.defaultValue == n43.props.value;
50689      })), n41.props = r14, e21.class != e21.className && ($dc040a17866866fa$var$J.enumerable = "className" in e21, null != e21.className && (r14.class = e21.className), Object.defineProperty(r14, "className", $dc040a17866866fa$var$J));
50690    }
50691    n41.$$typeof = $dc040a17866866fa$var$j, $dc040a17866866fa$var$K && $dc040a17866866fa$var$K(n41);
50692  };
50693  var $dc040a17866866fa$var$Q = (0, $fb96b826c0c5f37a$export$41c562ebe57d11e2).__r;
50694  (0, $fb96b826c0c5f37a$export$41c562ebe57d11e2).__r = function(n44) {
50695    $dc040a17866866fa$var$Q && $dc040a17866866fa$var$Q(n44), $dc040a17866866fa$var$G = n44.__c;
50696  };
50697  var $ec8c39fdad15601a$var$THEME_ICONS = {
50698    light: "outline",
50699    dark: "solid"
50700  };
50701  var $ec8c39fdad15601a$export$2e2bcd8739ae039 = class extends (0, $dc040a17866866fa$export$221d75b3f55bb0bd) {
50702    renderIcon(category) {
50703      const { icon } = category;
50704      if (icon) {
50705        if (icon.svg) return /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("span", {
50706          class: "flex",
50707          dangerouslySetInnerHTML: {
50708            __html: icon.svg
50709          }
50710        });
50711        if (icon.src) return /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("img", {
50712          src: icon.src
50713        });
50714      }
50715      const categoryIcons = (0, $fcccfb36ed0cde68$export$2e2bcd8739ae039).categories[category.id] || (0, $fcccfb36ed0cde68$export$2e2bcd8739ae039).categories.custom;
50716      const style = this.props.icons == "auto" ? $ec8c39fdad15601a$var$THEME_ICONS[this.props.theme] : this.props.icons;
50717      return categoryIcons[style] || categoryIcons;
50718    }
50719    render() {
50720      let selectedCategoryIndex = null;
50721      return /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("nav", {
50722        id: "nav",
50723        class: "padding",
50724        "data-position": this.props.position,
50725        dir: this.props.dir,
50726        children: /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("div", {
50727          class: "flex relative",
50728          children: [
50729            this.categories.map((category, i2) => {
50730              const title = category.name || (0, $7adb23b0109cc36a$export$dbe3113d60765c1a).categories[category.id];
50731              const selected = !this.props.unfocused && category.id == this.state.categoryId;
50732              if (selected) selectedCategoryIndex = i2;
50733              return /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("button", {
50734                "aria-label": title,
50735                "aria-selected": selected || void 0,
50736                title,
50737                type: "button",
50738                class: "flex flex-grow flex-center",
50739                onMouseDown: (e2) => e2.preventDefault(),
50740                onClick: () => {
50741                  this.props.onClick({
50742                    category,
50743                    i: i2
50744                  });
50745                },
50746                children: this.renderIcon(category)
50747              });
50748            }),
50749            /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("div", {
50750              class: "bar",
50751              style: {
50752                width: `${100 / this.categories.length}%`,
50753                opacity: selectedCategoryIndex == null ? 0 : 1,
50754                transform: this.props.dir === "rtl" ? `scaleX(-1) translateX(${selectedCategoryIndex * 100}%)` : `translateX(${selectedCategoryIndex * 100}%)`
50755              }
50756            })
50757          ]
50758        })
50759      });
50760    }
50761    constructor() {
50762      super();
50763      this.categories = (0, $7adb23b0109cc36a$export$2d0294657ab35f1b).categories.filter((category) => {
50764        return !category.target;
50765      });
50766      this.state = {
50767        categoryId: this.categories[0].id
50768      };
50769    }
50770  };
50771  var $e0d4dda61265ff1e$export$2e2bcd8739ae039 = class extends (0, $dc040a17866866fa$export$221d75b3f55bb0bd) {
50772    shouldComponentUpdate(nextProps) {
50773      for (let k2 in nextProps) {
50774        if (k2 == "children") continue;
50775        if (nextProps[k2] != this.props[k2]) return true;
50776      }
50777      return false;
50778    }
50779    render() {
50780      return this.props.children;
50781    }
50782  };
50783  var $89bd6bb200cc8fef$var$Performance = {
50784    rowsPerRender: 10
50785  };
50786  var $89bd6bb200cc8fef$export$2e2bcd8739ae039 = class extends (0, $fb96b826c0c5f37a$export$16fa2f45be04daa8) {
50787    getInitialState(props = this.props) {
50788      return {
50789        skin: (0, $f72b75cf796873c7$export$2e2bcd8739ae039).get("skin") || props.skin,
50790        theme: this.initTheme(props.theme)
50791      };
50792    }
50793    componentWillMount() {
50794      this.dir = (0, $7adb23b0109cc36a$export$dbe3113d60765c1a).rtl ? "rtl" : "ltr";
50795      this.refs = {
50796        menu: (0, $fb96b826c0c5f37a$export$7d1e3a5e95ceca43)(),
50797        navigation: (0, $fb96b826c0c5f37a$export$7d1e3a5e95ceca43)(),
50798        scroll: (0, $fb96b826c0c5f37a$export$7d1e3a5e95ceca43)(),
50799        search: (0, $fb96b826c0c5f37a$export$7d1e3a5e95ceca43)(),
50800        searchInput: (0, $fb96b826c0c5f37a$export$7d1e3a5e95ceca43)(),
50801        skinToneButton: (0, $fb96b826c0c5f37a$export$7d1e3a5e95ceca43)(),
50802        skinToneRadio: (0, $fb96b826c0c5f37a$export$7d1e3a5e95ceca43)()
50803      };
50804      this.initGrid();
50805      if (this.props.stickySearch == false && this.props.searchPosition == "sticky") {
50806        console.warn("[EmojiMart] Deprecation warning: `stickySearch` has been renamed `searchPosition`.");
50807        this.props.searchPosition = "static";
50808      }
50809    }
50810    componentDidMount() {
50811      this.register();
50812      this.shadowRoot = this.base.parentNode;
50813      if (this.props.autoFocus) {
50814        const { searchInput } = this.refs;
50815        if (searchInput.current) searchInput.current.focus();
50816      }
50817    }
50818    componentWillReceiveProps(nextProps) {
50819      this.nextState || (this.nextState = {});
50820      for (const k1 in nextProps) this.nextState[k1] = nextProps[k1];
50821      clearTimeout(this.nextStateTimer);
50822      this.nextStateTimer = setTimeout(() => {
50823        let requiresGridReset = false;
50824        for (const k2 in this.nextState) {
50825          this.props[k2] = this.nextState[k2];
50826          if (k2 === "custom" || k2 === "categories") requiresGridReset = true;
50827        }
50828        delete this.nextState;
50829        const nextState = this.getInitialState();
50830        if (requiresGridReset) return this.reset(nextState);
50831        this.setState(nextState);
50832      });
50833    }
50834    componentWillUnmount() {
50835      this.unregister();
50836    }
50837    async reset(nextState = {}) {
50838      await (0, $7adb23b0109cc36a$export$2cd8252107eb640b)(this.props);
50839      this.initGrid();
50840      this.unobserve();
50841      this.setState(nextState, () => {
50842        this.observeCategories();
50843        this.observeRows();
50844      });
50845    }
50846    register() {
50847      document.addEventListener("click", this.handleClickOutside);
50848      this.observe();
50849    }
50850    unregister() {
50851      document.removeEventListener("click", this.handleClickOutside);
50852      this.darkMedia?.removeEventListener("change", this.darkMediaCallback);
50853      this.unobserve();
50854    }
50855    observe() {
50856      this.observeCategories();
50857      this.observeRows();
50858    }
50859    unobserve({ except = [] } = {}) {
50860      if (!Array.isArray(except)) except = [
50861        except
50862      ];
50863      for (const observer of this.observers) {
50864        if (except.includes(observer)) continue;
50865        observer.disconnect();
50866      }
50867      this.observers = [].concat(except);
50868    }
50869    initGrid() {
50870      const { categories } = (0, $7adb23b0109cc36a$export$2d0294657ab35f1b);
50871      this.refs.categories = /* @__PURE__ */ new Map();
50872      const navKey = (0, $7adb23b0109cc36a$export$2d0294657ab35f1b).categories.map((category) => category.id).join(",");
50873      if (this.navKey && this.navKey != navKey) this.refs.scroll.current && (this.refs.scroll.current.scrollTop = 0);
50874      this.navKey = navKey;
50875      this.grid = [];
50876      this.grid.setsize = 0;
50877      const addRow = (rows, category) => {
50878        const row = [];
50879        row.__categoryId = category.id;
50880        row.__index = rows.length;
50881        this.grid.push(row);
50882        const rowIndex = this.grid.length - 1;
50883        const rowRef = rowIndex % $89bd6bb200cc8fef$var$Performance.rowsPerRender ? {} : (0, $fb96b826c0c5f37a$export$7d1e3a5e95ceca43)();
50884        rowRef.index = rowIndex;
50885        rowRef.posinset = this.grid.setsize + 1;
50886        rows.push(rowRef);
50887        return row;
50888      };
50889      for (let category1 of categories) {
50890        const rows = [];
50891        let row = addRow(rows, category1);
50892        for (let emoji of category1.emojis) {
50893          if (row.length == this.getPerLine()) row = addRow(rows, category1);
50894          this.grid.setsize += 1;
50895          row.push(emoji);
50896        }
50897        this.refs.categories.set(category1.id, {
50898          root: (0, $fb96b826c0c5f37a$export$7d1e3a5e95ceca43)(),
50899          rows
50900        });
50901      }
50902    }
50903    initTheme(theme2) {
50904      if (theme2 != "auto") return theme2;
50905      if (!this.darkMedia) {
50906        this.darkMedia = matchMedia("(prefers-color-scheme: dark)");
50907        if (this.darkMedia.media.match(/^not/)) return "light";
50908        this.darkMedia.addEventListener("change", this.darkMediaCallback);
50909      }
50910      return this.darkMedia.matches ? "dark" : "light";
50911    }
50912    initDynamicPerLine(props = this.props) {
50913      if (!props.dynamicWidth) return;
50914      const { element, emojiButtonSize } = props;
50915      const calculatePerLine = () => {
50916        const { width } = element.getBoundingClientRect();
50917        return Math.floor(width / emojiButtonSize);
50918      };
50919      const observer = new ResizeObserver(() => {
50920        this.unobserve({
50921          except: observer
50922        });
50923        this.setState({
50924          perLine: calculatePerLine()
50925        }, () => {
50926          this.initGrid();
50927          this.forceUpdate(() => {
50928            this.observeCategories();
50929            this.observeRows();
50930          });
50931        });
50932      });
50933      observer.observe(element);
50934      this.observers.push(observer);
50935      return calculatePerLine();
50936    }
50937    getPerLine() {
50938      return this.state.perLine || this.props.perLine;
50939    }
50940    getEmojiByPos([p1, p2]) {
50941      const grid = this.state.searchResults || this.grid;
50942      const emoji = grid[p1] && grid[p1][p2];
50943      if (!emoji) return;
50944      return (0, $c4d155af13ad4d4b$export$2e2bcd8739ae039).get(emoji);
50945    }
50946    observeCategories() {
50947      const navigation = this.refs.navigation.current;
50948      if (!navigation) return;
50949      const visibleCategories = /* @__PURE__ */ new Map();
50950      const setFocusedCategory = (categoryId) => {
50951        if (categoryId != navigation.state.categoryId) navigation.setState({
50952          categoryId
50953        });
50954      };
50955      const observerOptions2 = {
50956        root: this.refs.scroll.current,
50957        threshold: [
50958          0,
50959          1
50960        ]
50961      };
50962      const observer = new IntersectionObserver((entries2) => {
50963        for (const entry of entries2) {
50964          const id3 = entry.target.dataset.id;
50965          visibleCategories.set(id3, entry.intersectionRatio);
50966        }
50967        const ratios = [
50968          ...visibleCategories
50969        ];
50970        for (const [id3, ratio] of ratios) if (ratio) {
50971          setFocusedCategory(id3);
50972          break;
50973        }
50974      }, observerOptions2);
50975      for (const { root } of this.refs.categories.values()) observer.observe(root.current);
50976      this.observers.push(observer);
50977    }
50978    observeRows() {
50979      const visibleRows = {
50980        ...this.state.visibleRows
50981      };
50982      const observer = new IntersectionObserver((entries2) => {
50983        for (const entry of entries2) {
50984          const index = parseInt(entry.target.dataset.index);
50985          if (entry.isIntersecting) visibleRows[index] = true;
50986          else delete visibleRows[index];
50987        }
50988        this.setState({
50989          visibleRows
50990        });
50991      }, {
50992        root: this.refs.scroll.current,
50993        rootMargin: `${this.props.emojiButtonSize * ($89bd6bb200cc8fef$var$Performance.rowsPerRender + 5)}px 0px ${this.props.emojiButtonSize * $89bd6bb200cc8fef$var$Performance.rowsPerRender}px`
50994      });
50995      for (const { rows } of this.refs.categories.values()) {
50996        for (const row of rows) if (row.current) observer.observe(row.current);
50997      }
50998      this.observers.push(observer);
50999    }
51000    preventDefault(e2) {
51001      e2.preventDefault();
51002    }
51003    unfocusSearch() {
51004      const input = this.refs.searchInput.current;
51005      if (!input) return;
51006      input.blur();
51007    }
51008    navigate({ e: e2, input, left, right, up, down }) {
51009      const grid = this.state.searchResults || this.grid;
51010      if (!grid.length) return;
51011      let [p1, p2] = this.state.pos;
51012      const pos = (() => {
51013        if (p1 == 0) {
51014          if (p2 == 0 && !e2.repeat && (left || up)) return null;
51015        }
51016        if (p1 == -1) {
51017          if (!e2.repeat && (right || down) && input.selectionStart == input.value.length) return [
51018            0,
51019            0
51020          ];
51021          return null;
51022        }
51023        if (left || right) {
51024          let row = grid[p1];
51025          const increment = left ? -1 : 1;
51026          p2 += increment;
51027          if (!row[p2]) {
51028            p1 += increment;
51029            row = grid[p1];
51030            if (!row) {
51031              p1 = left ? 0 : grid.length - 1;
51032              p2 = left ? 0 : grid[p1].length - 1;
51033              return [
51034                p1,
51035                p2
51036              ];
51037            }
51038            p2 = left ? row.length - 1 : 0;
51039          }
51040          return [
51041            p1,
51042            p2
51043          ];
51044        }
51045        if (up || down) {
51046          p1 += up ? -1 : 1;
51047          const row = grid[p1];
51048          if (!row) {
51049            p1 = up ? 0 : grid.length - 1;
51050            p2 = up ? 0 : grid[p1].length - 1;
51051            return [
51052              p1,
51053              p2
51054            ];
51055          }
51056          if (!row[p2]) p2 = row.length - 1;
51057          return [
51058            p1,
51059            p2
51060          ];
51061        }
51062      })();
51063      if (pos) e2.preventDefault();
51064      else {
51065        if (this.state.pos[0] > -1) this.setState({
51066          pos: [
51067            -1,
51068            -1
51069          ]
51070        });
51071        return;
51072      }
51073      this.setState({
51074        pos,
51075        keyboard: true
51076      }, () => {
51077        this.scrollTo({
51078          row: pos[0]
51079        });
51080      });
51081    }
51082    scrollTo({ categoryId, row }) {
51083      const grid = this.state.searchResults || this.grid;
51084      if (!grid.length) return;
51085      const scroll = this.refs.scroll.current;
51086      const scrollRect = scroll.getBoundingClientRect();
51087      let scrollTop = 0;
51088      if (row >= 0) categoryId = grid[row].__categoryId;
51089      if (categoryId) {
51090        const ref = this.refs[categoryId] || this.refs.categories.get(categoryId).root;
51091        const categoryRect = ref.current.getBoundingClientRect();
51092        scrollTop = categoryRect.top - (scrollRect.top - scroll.scrollTop) + 1;
51093      }
51094      if (row >= 0) {
51095        if (!row) scrollTop = 0;
51096        else {
51097          const rowIndex = grid[row].__index;
51098          const rowTop = scrollTop + rowIndex * this.props.emojiButtonSize;
51099          const rowBot = rowTop + this.props.emojiButtonSize + this.props.emojiButtonSize * 0.88;
51100          if (rowTop < scroll.scrollTop) scrollTop = rowTop;
51101          else if (rowBot > scroll.scrollTop + scrollRect.height) scrollTop = rowBot - scrollRect.height;
51102          else return;
51103        }
51104      }
51105      this.ignoreMouse();
51106      scroll.scrollTop = scrollTop;
51107    }
51108    ignoreMouse() {
51109      this.mouseIsIgnored = true;
51110      clearTimeout(this.ignoreMouseTimer);
51111      this.ignoreMouseTimer = setTimeout(() => {
51112        delete this.mouseIsIgnored;
51113      }, 100);
51114    }
51115    handleEmojiOver(pos) {
51116      if (this.mouseIsIgnored || this.state.showSkins) return;
51117      this.setState({
51118        pos: pos || [
51119          -1,
51120          -1
51121        ],
51122        keyboard: false
51123      });
51124    }
51125    handleEmojiClick({ e: e2, emoji, pos }) {
51126      if (!this.props.onEmojiSelect) return;
51127      if (!emoji && pos) emoji = this.getEmojiByPos(pos);
51128      if (emoji) {
51129        const emojiData = (0, $693b183b0a78708f$export$d10ac59fbe52a745)(emoji, {
51130          skinIndex: this.state.skin - 1
51131        });
51132        if (this.props.maxFrequentRows) (0, $b22cfd0a55410b4f$export$2e2bcd8739ae039).add(emojiData, this.props);
51133        this.props.onEmojiSelect(emojiData, e2);
51134      }
51135    }
51136    closeSkins() {
51137      if (!this.state.showSkins) return;
51138      this.setState({
51139        showSkins: null,
51140        tempSkin: null
51141      });
51142      this.base.removeEventListener("click", this.handleBaseClick);
51143      this.base.removeEventListener("keydown", this.handleBaseKeydown);
51144    }
51145    handleSkinMouseOver(tempSkin) {
51146      this.setState({
51147        tempSkin
51148      });
51149    }
51150    handleSkinClick(skin) {
51151      this.ignoreMouse();
51152      this.closeSkins();
51153      this.setState({
51154        skin,
51155        tempSkin: null
51156      });
51157      (0, $f72b75cf796873c7$export$2e2bcd8739ae039).set("skin", skin);
51158    }
51159    renderNav() {
51160      return /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)((0, $ec8c39fdad15601a$export$2e2bcd8739ae039), {
51161        ref: this.refs.navigation,
51162        icons: this.props.icons,
51163        theme: this.state.theme,
51164        dir: this.dir,
51165        unfocused: !!this.state.searchResults,
51166        position: this.props.navPosition,
51167        onClick: this.handleCategoryClick
51168      }, this.navKey);
51169    }
51170    renderPreview() {
51171      const emoji = this.getEmojiByPos(this.state.pos);
51172      const noSearchResults = this.state.searchResults && !this.state.searchResults.length;
51173      return /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("div", {
51174        id: "preview",
51175        class: "flex flex-middle",
51176        dir: this.dir,
51177        "data-position": this.props.previewPosition,
51178        children: [
51179          /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("div", {
51180            class: "flex flex-middle flex-grow",
51181            children: [
51182              /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("div", {
51183                class: "flex flex-auto flex-middle flex-center",
51184                style: {
51185                  height: this.props.emojiButtonSize,
51186                  fontSize: this.props.emojiButtonSize
51187                },
51188                children: /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)((0, $254755d3f438722f$export$2e2bcd8739ae039), {
51189                  emoji,
51190                  id: noSearchResults ? this.props.noResultsEmoji || "cry" : this.props.previewEmoji || (this.props.previewPosition == "top" ? "point_down" : "point_up"),
51191                  set: this.props.set,
51192                  size: this.props.emojiButtonSize,
51193                  skin: this.state.tempSkin || this.state.skin,
51194                  spritesheet: true,
51195                  getSpritesheetURL: this.props.getSpritesheetURL
51196                })
51197              }),
51198              /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("div", {
51199                class: `margin-${this.dir[0]}`,
51200                children: emoji || noSearchResults ? /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("div", {
51201                  class: `padding-${this.dir[2]} align-${this.dir[0]}`,
51202                  children: [
51203                    /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("div", {
51204                      class: "preview-title ellipsis",
51205                      children: emoji ? emoji.name : (0, $7adb23b0109cc36a$export$dbe3113d60765c1a).search_no_results_1
51206                    }),
51207                    /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("div", {
51208                      class: "preview-subtitle ellipsis color-c",
51209                      children: emoji ? emoji.skins[0].shortcodes : (0, $7adb23b0109cc36a$export$dbe3113d60765c1a).search_no_results_2
51210                    })
51211                  ]
51212                }) : /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("div", {
51213                  class: "preview-placeholder color-c",
51214                  children: (0, $7adb23b0109cc36a$export$dbe3113d60765c1a).pick
51215                })
51216              })
51217            ]
51218          }),
51219          !emoji && this.props.skinTonePosition == "preview" && this.renderSkinToneButton()
51220        ]
51221      });
51222    }
51223    renderEmojiButton(emoji, { pos, posinset, grid }) {
51224      const size2 = this.props.emojiButtonSize;
51225      const skin = this.state.tempSkin || this.state.skin;
51226      const emojiSkin = emoji.skins[skin - 1] || emoji.skins[0];
51227      const native = emojiSkin.native;
51228      const selected = (0, $693b183b0a78708f$export$9cb4719e2e525b7a)(this.state.pos, pos);
51229      const key = pos.concat(emoji.id).join("");
51230      return /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)((0, $e0d4dda61265ff1e$export$2e2bcd8739ae039), {
51231        selected,
51232        skin,
51233        size: size2,
51234        children: /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("button", {
51235          "aria-label": native,
51236          "aria-selected": selected || void 0,
51237          "aria-posinset": posinset,
51238          "aria-setsize": grid.setsize,
51239          "data-keyboard": this.state.keyboard,
51240          title: this.props.previewPosition == "none" ? emoji.name : void 0,
51241          type: "button",
51242          class: "flex flex-center flex-middle",
51243          tabindex: "-1",
51244          onClick: (e2) => this.handleEmojiClick({
51245            e: e2,
51246            emoji
51247          }),
51248          onMouseEnter: () => this.handleEmojiOver(pos),
51249          onMouseLeave: () => this.handleEmojiOver(),
51250          style: {
51251            width: this.props.emojiButtonSize,
51252            height: this.props.emojiButtonSize,
51253            fontSize: this.props.emojiSize,
51254            lineHeight: 0
51255          },
51256          children: [
51257            /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("div", {
51258              "aria-hidden": "true",
51259              class: "background",
51260              style: {
51261                borderRadius: this.props.emojiButtonRadius,
51262                backgroundColor: this.props.emojiButtonColors ? this.props.emojiButtonColors[(posinset - 1) % this.props.emojiButtonColors.length] : void 0
51263              }
51264            }),
51265            /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)((0, $254755d3f438722f$export$2e2bcd8739ae039), {
51266              emoji,
51267              set: this.props.set,
51268              size: this.props.emojiSize,
51269              skin,
51270              spritesheet: true,
51271              getSpritesheetURL: this.props.getSpritesheetURL
51272            })
51273          ]
51274        })
51275      }, key);
51276    }
51277    renderSearch() {
51278      const renderSkinTone = this.props.previewPosition == "none" || this.props.skinTonePosition == "search";
51279      return /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("div", {
51280        children: [
51281          /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("div", {
51282            class: "spacer"
51283          }),
51284          /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("div", {
51285            class: "flex flex-middle",
51286            children: [
51287              /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("div", {
51288                class: "search relative flex-grow",
51289                children: [
51290                  /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("input", {
51291                    type: "search",
51292                    ref: this.refs.searchInput,
51293                    placeholder: (0, $7adb23b0109cc36a$export$dbe3113d60765c1a).search,
51294                    onClick: this.handleSearchClick,
51295                    onInput: this.handleSearchInput,
51296                    onKeyDown: this.handleSearchKeyDown,
51297                    autoComplete: "off"
51298                  }),
51299                  /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("span", {
51300                    class: "icon loupe flex",
51301                    children: (0, $fcccfb36ed0cde68$export$2e2bcd8739ae039).search.loupe
51302                  }),
51303                  this.state.searchResults && /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("button", {
51304                    title: "Clear",
51305                    "aria-label": "Clear",
51306                    type: "button",
51307                    class: "icon delete flex",
51308                    onClick: this.clearSearch,
51309                    onMouseDown: this.preventDefault,
51310                    children: (0, $fcccfb36ed0cde68$export$2e2bcd8739ae039).search.delete
51311                  })
51312                ]
51313              }),
51314              renderSkinTone && this.renderSkinToneButton()
51315            ]
51316          })
51317        ]
51318      });
51319    }
51320    renderSearchResults() {
51321      const { searchResults } = this.state;
51322      if (!searchResults) return null;
51323      return /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("div", {
51324        class: "category",
51325        ref: this.refs.search,
51326        children: [
51327          /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("div", {
51328            class: `sticky padding-small align-${this.dir[0]}`,
51329            children: (0, $7adb23b0109cc36a$export$dbe3113d60765c1a).categories.search
51330          }),
51331          /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("div", {
51332            children: !searchResults.length ? /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("div", {
51333              class: `padding-small align-${this.dir[0]}`,
51334              children: this.props.onAddCustomEmoji && /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("a", {
51335                onClick: this.props.onAddCustomEmoji,
51336                children: (0, $7adb23b0109cc36a$export$dbe3113d60765c1a).add_custom
51337              })
51338            }) : searchResults.map((row, i2) => {
51339              return /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("div", {
51340                class: "flex",
51341                children: row.map((emoji, ii) => {
51342                  return this.renderEmojiButton(emoji, {
51343                    pos: [
51344                      i2,
51345                      ii
51346                    ],
51347                    posinset: i2 * this.props.perLine + ii + 1,
51348                    grid: searchResults
51349                  });
51350                })
51351              });
51352            })
51353          })
51354        ]
51355      });
51356    }
51357    renderCategories() {
51358      const { categories } = (0, $7adb23b0109cc36a$export$2d0294657ab35f1b);
51359      const hidden = !!this.state.searchResults;
51360      const perLine = this.getPerLine();
51361      return /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("div", {
51362        style: {
51363          visibility: hidden ? "hidden" : void 0,
51364          display: hidden ? "none" : void 0,
51365          height: "100%"
51366        },
51367        children: categories.map((category) => {
51368          const { root, rows } = this.refs.categories.get(category.id);
51369          return /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("div", {
51370            "data-id": category.target ? category.target.id : category.id,
51371            class: "category",
51372            ref: root,
51373            children: [
51374              /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("div", {
51375                class: `sticky padding-small align-${this.dir[0]}`,
51376                children: category.name || (0, $7adb23b0109cc36a$export$dbe3113d60765c1a).categories[category.id]
51377              }),
51378              /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("div", {
51379                class: "relative",
51380                style: {
51381                  height: rows.length * this.props.emojiButtonSize
51382                },
51383                children: rows.map((row, i2) => {
51384                  const targetRow = row.index - row.index % $89bd6bb200cc8fef$var$Performance.rowsPerRender;
51385                  const visible = this.state.visibleRows[targetRow];
51386                  const ref = "current" in row ? row : void 0;
51387                  if (!visible && !ref) return null;
51388                  const start3 = i2 * perLine;
51389                  const end = start3 + perLine;
51390                  const emojiIds = category.emojis.slice(start3, end);
51391                  if (emojiIds.length < perLine) emojiIds.push(...new Array(perLine - emojiIds.length));
51392                  return /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("div", {
51393                    "data-index": row.index,
51394                    ref,
51395                    class: "flex row",
51396                    style: {
51397                      top: i2 * this.props.emojiButtonSize
51398                    },
51399                    children: visible && emojiIds.map((emojiId, ii) => {
51400                      if (!emojiId) return /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("div", {
51401                        style: {
51402                          width: this.props.emojiButtonSize,
51403                          height: this.props.emojiButtonSize
51404                        }
51405                      });
51406                      const emoji = (0, $c4d155af13ad4d4b$export$2e2bcd8739ae039).get(emojiId);
51407                      return this.renderEmojiButton(emoji, {
51408                        pos: [
51409                          row.index,
51410                          ii
51411                        ],
51412                        posinset: row.posinset + ii,
51413                        grid: this.grid
51414                      });
51415                    })
51416                  }, row.index);
51417                })
51418              })
51419            ]
51420          });
51421        })
51422      });
51423    }
51424    renderSkinToneButton() {
51425      if (this.props.skinTonePosition == "none") return null;
51426      return /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("div", {
51427        class: "flex flex-auto flex-center flex-middle",
51428        style: {
51429          position: "relative",
51430          width: this.props.emojiButtonSize,
51431          height: this.props.emojiButtonSize
51432        },
51433        children: /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("button", {
51434          type: "button",
51435          ref: this.refs.skinToneButton,
51436          class: "skin-tone-button flex flex-auto flex-center flex-middle",
51437          "aria-selected": this.state.showSkins ? "" : void 0,
51438          "aria-label": (0, $7adb23b0109cc36a$export$dbe3113d60765c1a).skins.choose,
51439          title: (0, $7adb23b0109cc36a$export$dbe3113d60765c1a).skins.choose,
51440          onClick: this.openSkins,
51441          style: {
51442            width: this.props.emojiSize,
51443            height: this.props.emojiSize
51444          },
51445          children: /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("span", {
51446            class: `skin-tone skin-tone-${this.state.skin}`
51447          })
51448        })
51449      });
51450    }
51451    renderLiveRegion() {
51452      const emoji = this.getEmojiByPos(this.state.pos);
51453      const contents = emoji ? emoji.name : "";
51454      return /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("div", {
51455        "aria-live": "polite",
51456        class: "sr-only",
51457        children: contents
51458      });
51459    }
51460    renderSkins() {
51461      const skinToneButton = this.refs.skinToneButton.current;
51462      const skinToneButtonRect = skinToneButton.getBoundingClientRect();
51463      const baseRect = this.base.getBoundingClientRect();
51464      const position = {};
51465      if (this.dir == "ltr") position.right = baseRect.right - skinToneButtonRect.right - 3;
51466      else position.left = skinToneButtonRect.left - baseRect.left - 3;
51467      if (this.props.previewPosition == "bottom" && this.props.skinTonePosition == "preview") position.bottom = baseRect.bottom - skinToneButtonRect.top + 6;
51468      else {
51469        position.top = skinToneButtonRect.bottom - baseRect.top + 3;
51470        position.bottom = "auto";
51471      }
51472      return /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("div", {
51473        ref: this.refs.menu,
51474        role: "radiogroup",
51475        dir: this.dir,
51476        "aria-label": (0, $7adb23b0109cc36a$export$dbe3113d60765c1a).skins.choose,
51477        class: "menu hidden",
51478        "data-position": position.top ? "top" : "bottom",
51479        style: position,
51480        children: [
51481          ...Array(6).keys()
51482        ].map((i2) => {
51483          const skin = i2 + 1;
51484          const checked = this.state.skin == skin;
51485          return /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("div", {
51486            children: [
51487              /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("input", {
51488                type: "radio",
51489                name: "skin-tone",
51490                value: skin,
51491                "aria-label": (0, $7adb23b0109cc36a$export$dbe3113d60765c1a).skins[skin],
51492                ref: checked ? this.refs.skinToneRadio : null,
51493                defaultChecked: checked,
51494                onChange: () => this.handleSkinMouseOver(skin),
51495                onKeyDown: (e2) => {
51496                  if (e2.code == "Enter" || e2.code == "Space" || e2.code == "Tab") {
51497                    e2.preventDefault();
51498                    this.handleSkinClick(skin);
51499                  }
51500                }
51501              }),
51502              /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("button", {
51503                "aria-hidden": "true",
51504                tabindex: "-1",
51505                onClick: () => this.handleSkinClick(skin),
51506                onMouseEnter: () => this.handleSkinMouseOver(skin),
51507                onMouseLeave: () => this.handleSkinMouseOver(),
51508                class: "option flex flex-grow flex-middle",
51509                children: [
51510                  /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("span", {
51511                    class: `skin-tone skin-tone-${skin}`
51512                  }),
51513                  /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("span", {
51514                    class: "margin-small-lr",
51515                    children: (0, $7adb23b0109cc36a$export$dbe3113d60765c1a).skins[skin]
51516                  })
51517                ]
51518              })
51519            ]
51520          });
51521        })
51522      });
51523    }
51524    render() {
51525      const lineWidth = this.props.perLine * this.props.emojiButtonSize;
51526      return /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("section", {
51527        id: "root",
51528        class: "flex flex-column",
51529        dir: this.dir,
51530        style: {
51531          width: this.props.dynamicWidth ? "100%" : `calc(${lineWidth}px + (var(--padding) + var(--sidebar-width)))`
51532        },
51533        "data-emoji-set": this.props.set,
51534        "data-theme": this.state.theme,
51535        "data-menu": this.state.showSkins ? "" : void 0,
51536        children: [
51537          this.props.previewPosition == "top" && this.renderPreview(),
51538          this.props.navPosition == "top" && this.renderNav(),
51539          this.props.searchPosition == "sticky" && /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("div", {
51540            class: "padding-lr",
51541            children: this.renderSearch()
51542          }),
51543          /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("div", {
51544            ref: this.refs.scroll,
51545            class: "scroll flex-grow padding-lr",
51546            children: /* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)("div", {
51547              style: {
51548                width: this.props.dynamicWidth ? "100%" : lineWidth,
51549                height: "100%"
51550              },
51551              children: [
51552                this.props.searchPosition == "static" && this.renderSearch(),
51553                this.renderSearchResults(),
51554                this.renderCategories()
51555              ]
51556            })
51557          }),
51558          this.props.navPosition == "bottom" && this.renderNav(),
51559          this.props.previewPosition == "bottom" && this.renderPreview(),
51560          this.state.showSkins && this.renderSkins(),
51561          this.renderLiveRegion()
51562        ]
51563      });
51564    }
51565    constructor(props) {
51566      super();
51567      (0, $c770c458706daa72$export$2e2bcd8739ae039)(this, "darkMediaCallback", () => {
51568        if (this.props.theme != "auto") return;
51569        this.setState({
51570          theme: this.darkMedia.matches ? "dark" : "light"
51571        });
51572      });
51573      (0, $c770c458706daa72$export$2e2bcd8739ae039)(this, "handleClickOutside", (e2) => {
51574        const { element } = this.props;
51575        if (e2.target != element) {
51576          if (this.state.showSkins) this.closeSkins();
51577          if (this.props.onClickOutside) this.props.onClickOutside(e2);
51578        }
51579      });
51580      (0, $c770c458706daa72$export$2e2bcd8739ae039)(this, "handleBaseClick", (e2) => {
51581        if (!this.state.showSkins) return;
51582        if (!e2.target.closest(".menu")) {
51583          e2.preventDefault();
51584          e2.stopImmediatePropagation();
51585          this.closeSkins();
51586        }
51587      });
51588      (0, $c770c458706daa72$export$2e2bcd8739ae039)(this, "handleBaseKeydown", (e2) => {
51589        if (!this.state.showSkins) return;
51590        if (e2.key == "Escape") {
51591          e2.preventDefault();
51592          e2.stopImmediatePropagation();
51593          this.closeSkins();
51594        }
51595      });
51596      (0, $c770c458706daa72$export$2e2bcd8739ae039)(this, "handleSearchClick", () => {
51597        const emoji = this.getEmojiByPos(this.state.pos);
51598        if (!emoji) return;
51599        this.setState({
51600          pos: [
51601            -1,
51602            -1
51603          ]
51604        });
51605      });
51606      (0, $c770c458706daa72$export$2e2bcd8739ae039)(this, "handleSearchInput", async () => {
51607        const input = this.refs.searchInput.current;
51608        if (!input) return;
51609        const { value } = input;
51610        const searchResults = await (0, $c4d155af13ad4d4b$export$2e2bcd8739ae039).search(value);
51611        const afterRender = () => {
51612          if (!this.refs.scroll.current) return;
51613          this.refs.scroll.current.scrollTop = 0;
51614        };
51615        if (!searchResults) return this.setState({
51616          searchResults,
51617          pos: [
51618            -1,
51619            -1
51620          ]
51621        }, afterRender);
51622        const pos = input.selectionStart == input.value.length ? [
51623          0,
51624          0
51625        ] : [
51626          -1,
51627          -1
51628        ];
51629        const grid = [];
51630        grid.setsize = searchResults.length;
51631        let row = null;
51632        for (let emoji of searchResults) {
51633          if (!grid.length || row.length == this.getPerLine()) {
51634            row = [];
51635            row.__categoryId = "search";
51636            row.__index = grid.length;
51637            grid.push(row);
51638          }
51639          row.push(emoji);
51640        }
51641        this.ignoreMouse();
51642        this.setState({
51643          searchResults: grid,
51644          pos
51645        }, afterRender);
51646      });
51647      (0, $c770c458706daa72$export$2e2bcd8739ae039)(this, "handleSearchKeyDown", (e2) => {
51648        const input = e2.currentTarget;
51649        e2.stopImmediatePropagation();
51650        switch (e2.key) {
51651          case "ArrowLeft":
51652            this.navigate({
51653              e: e2,
51654              input,
51655              left: true
51656            });
51657            break;
51658          case "ArrowRight":
51659            this.navigate({
51660              e: e2,
51661              input,
51662              right: true
51663            });
51664            break;
51665          case "ArrowUp":
51666            this.navigate({
51667              e: e2,
51668              input,
51669              up: true
51670            });
51671            break;
51672          case "ArrowDown":
51673            this.navigate({
51674              e: e2,
51675              input,
51676              down: true
51677            });
51678            break;
51679          case "Enter":
51680            e2.preventDefault();
51681            this.handleEmojiClick({
51682              e: e2,
51683              pos: this.state.pos
51684            });
51685            break;
51686          case "Escape":
51687            e2.preventDefault();
51688            if (this.state.searchResults) this.clearSearch();
51689            else this.unfocusSearch();
51690            break;
51691          default:
51692            break;
51693        }
51694      });
51695      (0, $c770c458706daa72$export$2e2bcd8739ae039)(this, "clearSearch", () => {
51696        const input = this.refs.searchInput.current;
51697        if (!input) return;
51698        input.value = "";
51699        input.focus();
51700        this.handleSearchInput();
51701      });
51702      (0, $c770c458706daa72$export$2e2bcd8739ae039)(this, "handleCategoryClick", ({ category, i: i2 }) => {
51703        this.scrollTo(i2 == 0 ? {
51704          row: -1
51705        } : {
51706          categoryId: category.id
51707        });
51708      });
51709      (0, $c770c458706daa72$export$2e2bcd8739ae039)(this, "openSkins", (e2) => {
51710        const { currentTarget } = e2;
51711        const rect = currentTarget.getBoundingClientRect();
51712        this.setState({
51713          showSkins: rect
51714        }, async () => {
51715          await (0, $693b183b0a78708f$export$e772c8ff12451969)(2);
51716          const menu = this.refs.menu.current;
51717          if (!menu) return;
51718          menu.classList.remove("hidden");
51719          this.refs.skinToneRadio.current.focus();
51720          this.base.addEventListener("click", this.handleBaseClick, true);
51721          this.base.addEventListener("keydown", this.handleBaseKeydown, true);
51722        });
51723      });
51724      this.observers = [];
51725      this.state = {
51726        pos: [
51727          -1,
51728          -1
51729        ],
51730        perLine: this.initDynamicPerLine(props),
51731        visibleRows: {
51732          0: true
51733        },
51734        ...this.getInitialState(props)
51735      };
51736    }
51737  };
51738  var $efa000751917694d$export$2e2bcd8739ae039 = class extends (0, $26f27c338a96b1a6$export$2e2bcd8739ae039) {
51739    async connectedCallback() {
51740      const props = (0, $7adb23b0109cc36a$export$75fe5f91d452f94b)(this.props, (0, $b247ea80b67298d5$export$2e2bcd8739ae039), this);
51741      props.element = this;
51742      props.ref = (component) => {
51743        this.component = component;
51744      };
51745      await (0, $7adb23b0109cc36a$export$2cd8252107eb640b)(props);
51746      if (this.disconnected) return;
51747      (0, $fb96b826c0c5f37a$export$b3890eb0ae9dca99)(/* @__PURE__ */ (0, $bd9dd35321b03dd4$export$34b9dba7ce09269b)((0, $89bd6bb200cc8fef$export$2e2bcd8739ae039), {
51748        ...props
51749      }), this.shadowRoot);
51750    }
51751    constructor(props) {
51752      super(props, {
51753        styles: (0, /* @__PURE__ */ $parcel$interopDefault($329d53ba9fd7125f$exports))
51754      });
51755    }
51756  };
51757  (0, $c770c458706daa72$export$2e2bcd8739ae039)($efa000751917694d$export$2e2bcd8739ae039, "Props", (0, $b247ea80b67298d5$export$2e2bcd8739ae039));
51758  if (typeof customElements !== "undefined" && !customElements.get("em-emoji-picker")) customElements.define("em-emoji-picker", $efa000751917694d$export$2e2bcd8739ae039);
51759  var $329d53ba9fd7125f$exports = {};
51760  $329d53ba9fd7125f$exports = ':host {\n  width: min-content;\n  height: 435px;\n  min-height: 230px;\n  border-radius: var(--border-radius);\n  box-shadow: var(--shadow);\n  --border-radius: 10px;\n  --category-icon-size: 18px;\n  --font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", sans-serif;\n  --font-size: 15px;\n  --preview-placeholder-size: 21px;\n  --preview-title-size: 1.1em;\n  --preview-subtitle-size: .9em;\n  --shadow-color: 0deg 0% 0%;\n  --shadow: .3px .5px 2.7px hsl(var(--shadow-color) / .14), .4px .8px 1px -3.2px hsl(var(--shadow-color) / .14), 1px 2px 2.5px -4.5px hsl(var(--shadow-color) / .14);\n  display: flex;\n}\n\n[data-theme="light"] {\n  --em-rgb-color: var(--rgb-color, 34, 36, 39);\n  --em-rgb-accent: var(--rgb-accent, 34, 102, 237);\n  --em-rgb-background: var(--rgb-background, 255, 255, 255);\n  --em-rgb-input: var(--rgb-input, 255, 255, 255);\n  --em-color-border: var(--color-border, rgba(0, 0, 0, .05));\n  --em-color-border-over: var(--color-border-over, rgba(0, 0, 0, .1));\n}\n\n[data-theme="dark"] {\n  --em-rgb-color: var(--rgb-color, 222, 222, 221);\n  --em-rgb-accent: var(--rgb-accent, 58, 130, 247);\n  --em-rgb-background: var(--rgb-background, 21, 22, 23);\n  --em-rgb-input: var(--rgb-input, 0, 0, 0);\n  --em-color-border: var(--color-border, rgba(255, 255, 255, .1));\n  --em-color-border-over: var(--color-border-over, rgba(255, 255, 255, .2));\n}\n\n#root {\n  --color-a: rgb(var(--em-rgb-color));\n  --color-b: rgba(var(--em-rgb-color), .65);\n  --color-c: rgba(var(--em-rgb-color), .45);\n  --padding: 12px;\n  --padding-small: calc(var(--padding) / 2);\n  --sidebar-width: 16px;\n  --duration: 225ms;\n  --duration-fast: 125ms;\n  --duration-instant: 50ms;\n  --easing: cubic-bezier(.4, 0, .2, 1);\n  width: 100%;\n  text-align: left;\n  border-radius: var(--border-radius);\n  background-color: rgb(var(--em-rgb-background));\n  position: relative;\n}\n\n@media (prefers-reduced-motion) {\n  #root {\n    --duration: 0;\n    --duration-fast: 0;\n    --duration-instant: 0;\n  }\n}\n\n#root[data-menu] button {\n  cursor: auto;\n}\n\n#root[data-menu] .menu button {\n  cursor: pointer;\n}\n\n:host, #root, input, button {\n  color: rgb(var(--em-rgb-color));\n  font-family: var(--font-family);\n  font-size: var(--font-size);\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  line-height: normal;\n}\n\n*, :before, :after {\n  box-sizing: border-box;\n  min-width: 0;\n  margin: 0;\n  padding: 0;\n}\n\n.relative {\n  position: relative;\n}\n\n.flex {\n  display: flex;\n}\n\n.flex-auto {\n  flex: none;\n}\n\n.flex-center {\n  justify-content: center;\n}\n\n.flex-column {\n  flex-direction: column;\n}\n\n.flex-grow {\n  flex: auto;\n}\n\n.flex-middle {\n  align-items: center;\n}\n\n.flex-wrap {\n  flex-wrap: wrap;\n}\n\n.padding {\n  padding: var(--padding);\n}\n\n.padding-t {\n  padding-top: var(--padding);\n}\n\n.padding-lr {\n  padding-left: var(--padding);\n  padding-right: var(--padding);\n}\n\n.padding-r {\n  padding-right: var(--padding);\n}\n\n.padding-small {\n  padding: var(--padding-small);\n}\n\n.padding-small-b {\n  padding-bottom: var(--padding-small);\n}\n\n.padding-small-lr {\n  padding-left: var(--padding-small);\n  padding-right: var(--padding-small);\n}\n\n.margin {\n  margin: var(--padding);\n}\n\n.margin-r {\n  margin-right: var(--padding);\n}\n\n.margin-l {\n  margin-left: var(--padding);\n}\n\n.margin-small-l {\n  margin-left: var(--padding-small);\n}\n\n.margin-small-lr {\n  margin-left: var(--padding-small);\n  margin-right: var(--padding-small);\n}\n\n.align-l {\n  text-align: left;\n}\n\n.align-r {\n  text-align: right;\n}\n\n.color-a {\n  color: var(--color-a);\n}\n\n.color-b {\n  color: var(--color-b);\n}\n\n.color-c {\n  color: var(--color-c);\n}\n\n.ellipsis {\n  white-space: nowrap;\n  max-width: 100%;\n  width: auto;\n  text-overflow: ellipsis;\n  overflow: hidden;\n}\n\n.sr-only {\n  width: 1px;\n  height: 1px;\n  position: absolute;\n  top: auto;\n  left: -10000px;\n  overflow: hidden;\n}\n\na {\n  cursor: pointer;\n  color: rgb(var(--em-rgb-accent));\n}\n\na:hover {\n  text-decoration: underline;\n}\n\n.spacer {\n  height: 10px;\n}\n\n[dir="rtl"] .scroll {\n  padding-left: 0;\n  padding-right: var(--padding);\n}\n\n.scroll {\n  padding-right: 0;\n  overflow-x: hidden;\n  overflow-y: auto;\n}\n\n.scroll::-webkit-scrollbar {\n  width: var(--sidebar-width);\n  height: var(--sidebar-width);\n}\n\n.scroll::-webkit-scrollbar-track {\n  border: 0;\n}\n\n.scroll::-webkit-scrollbar-button {\n  width: 0;\n  height: 0;\n  display: none;\n}\n\n.scroll::-webkit-scrollbar-corner {\n  background-color: rgba(0, 0, 0, 0);\n}\n\n.scroll::-webkit-scrollbar-thumb {\n  min-height: 20%;\n  min-height: 65px;\n  border: 4px solid rgb(var(--em-rgb-background));\n  border-radius: 8px;\n}\n\n.scroll::-webkit-scrollbar-thumb:hover {\n  background-color: var(--em-color-border-over) !important;\n}\n\n.scroll:hover::-webkit-scrollbar-thumb {\n  background-color: var(--em-color-border);\n}\n\n.sticky {\n  z-index: 1;\n  background-color: rgba(var(--em-rgb-background), .9);\n  -webkit-backdrop-filter: blur(4px);\n  backdrop-filter: blur(4px);\n  font-weight: 500;\n  position: sticky;\n  top: -1px;\n}\n\n[dir="rtl"] .search input[type="search"] {\n  padding: 10px 2.2em 10px 2em;\n}\n\n[dir="rtl"] .search .loupe {\n  left: auto;\n  right: .7em;\n}\n\n[dir="rtl"] .search .delete {\n  left: .7em;\n  right: auto;\n}\n\n.search {\n  z-index: 2;\n  position: relative;\n}\n\n.search input, .search button {\n  font-size: calc(var(--font-size)  - 1px);\n}\n\n.search input[type="search"] {\n  width: 100%;\n  background-color: var(--em-color-border);\n  transition-duration: var(--duration);\n  transition-property: background-color, box-shadow;\n  transition-timing-function: var(--easing);\n  border: 0;\n  border-radius: 10px;\n  outline: 0;\n  padding: 10px 2em 10px 2.2em;\n  display: block;\n}\n\n.search input[type="search"]::-ms-input-placeholder {\n  color: inherit;\n  opacity: .6;\n}\n\n.search input[type="search"]::placeholder {\n  color: inherit;\n  opacity: .6;\n}\n\n.search input[type="search"], .search input[type="search"]::-webkit-search-decoration, .search input[type="search"]::-webkit-search-cancel-button, .search input[type="search"]::-webkit-search-results-button, .search input[type="search"]::-webkit-search-results-decoration {\n  -webkit-appearance: none;\n  -ms-appearance: none;\n  appearance: none;\n}\n\n.search input[type="search"]:focus {\n  background-color: rgb(var(--em-rgb-input));\n  box-shadow: inset 0 0 0 1px rgb(var(--em-rgb-accent)), 0 1px 3px rgba(65, 69, 73, .2);\n}\n\n.search .icon {\n  z-index: 1;\n  color: rgba(var(--em-rgb-color), .7);\n  position: absolute;\n  top: 50%;\n  transform: translateY(-50%);\n}\n\n.search .loupe {\n  pointer-events: none;\n  left: .7em;\n}\n\n.search .delete {\n  right: .7em;\n}\n\nsvg {\n  fill: currentColor;\n  width: 1em;\n  height: 1em;\n}\n\nbutton {\n  -webkit-appearance: none;\n  -ms-appearance: none;\n  appearance: none;\n  cursor: pointer;\n  color: currentColor;\n  background-color: rgba(0, 0, 0, 0);\n  border: 0;\n}\n\n#nav {\n  z-index: 2;\n  padding-top: 12px;\n  padding-bottom: 12px;\n  padding-right: var(--sidebar-width);\n  position: relative;\n}\n\n#nav button {\n  color: var(--color-b);\n  transition: color var(--duration) var(--easing);\n}\n\n#nav button:hover {\n  color: var(--color-a);\n}\n\n#nav svg, #nav img {\n  width: var(--category-icon-size);\n  height: var(--category-icon-size);\n}\n\n#nav[dir="rtl"] .bar {\n  left: auto;\n  right: 0;\n}\n\n#nav .bar {\n  width: 100%;\n  height: 3px;\n  background-color: rgb(var(--em-rgb-accent));\n  transition: transform var(--duration) var(--easing);\n  border-radius: 3px 3px 0 0;\n  position: absolute;\n  bottom: -12px;\n  left: 0;\n}\n\n#nav button[aria-selected] {\n  color: rgb(var(--em-rgb-accent));\n}\n\n#preview {\n  z-index: 2;\n  padding: calc(var(--padding)  + 4px) var(--padding);\n  padding-right: var(--sidebar-width);\n  position: relative;\n}\n\n#preview .preview-placeholder {\n  font-size: var(--preview-placeholder-size);\n}\n\n#preview .preview-title {\n  font-size: var(--preview-title-size);\n}\n\n#preview .preview-subtitle {\n  font-size: var(--preview-subtitle-size);\n}\n\n#nav:before, #preview:before {\n  content: "";\n  height: 2px;\n  position: absolute;\n  left: 0;\n  right: 0;\n}\n\n#nav[data-position="top"]:before, #preview[data-position="top"]:before {\n  background: linear-gradient(to bottom, var(--em-color-border), transparent);\n  top: 100%;\n}\n\n#nav[data-position="bottom"]:before, #preview[data-position="bottom"]:before {\n  background: linear-gradient(to top, var(--em-color-border), transparent);\n  bottom: 100%;\n}\n\n.category:last-child {\n  min-height: calc(100% + 1px);\n}\n\n.category button {\n  font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, sans-serif;\n  position: relative;\n}\n\n.category button > * {\n  position: relative;\n}\n\n.category button .background {\n  opacity: 0;\n  background-color: var(--em-color-border);\n  transition: opacity var(--duration-fast) var(--easing) var(--duration-instant);\n  position: absolute;\n  top: 0;\n  bottom: 0;\n  left: 0;\n  right: 0;\n}\n\n.category button:hover .background {\n  transition-duration: var(--duration-instant);\n  transition-delay: 0s;\n}\n\n.category button[aria-selected] .background {\n  opacity: 1;\n}\n\n.category button[data-keyboard] .background {\n  transition: none;\n}\n\n.row {\n  width: 100%;\n  position: absolute;\n  top: 0;\n  left: 0;\n}\n\n.skin-tone-button {\n  border: 1px solid rgba(0, 0, 0, 0);\n  border-radius: 100%;\n}\n\n.skin-tone-button:hover {\n  border-color: var(--em-color-border);\n}\n\n.skin-tone-button:active .skin-tone {\n  transform: scale(.85) !important;\n}\n\n.skin-tone-button .skin-tone {\n  transition: transform var(--duration) var(--easing);\n}\n\n.skin-tone-button[aria-selected] {\n  background-color: var(--em-color-border);\n  border-top-color: rgba(0, 0, 0, .05);\n  border-bottom-color: rgba(0, 0, 0, 0);\n  border-left-width: 0;\n  border-right-width: 0;\n}\n\n.skin-tone-button[aria-selected] .skin-tone {\n  transform: scale(.9);\n}\n\n.menu {\n  z-index: 2;\n  white-space: nowrap;\n  border: 1px solid var(--em-color-border);\n  background-color: rgba(var(--em-rgb-background), .9);\n  -webkit-backdrop-filter: blur(4px);\n  backdrop-filter: blur(4px);\n  transition-property: opacity, transform;\n  transition-duration: var(--duration);\n  transition-timing-function: var(--easing);\n  border-radius: 10px;\n  padding: 4px;\n  position: absolute;\n  box-shadow: 1px 1px 5px rgba(0, 0, 0, .05);\n}\n\n.menu.hidden {\n  opacity: 0;\n}\n\n.menu[data-position="bottom"] {\n  transform-origin: 100% 100%;\n}\n\n.menu[data-position="bottom"].hidden {\n  transform: scale(.9)rotate(-3deg)translateY(5%);\n}\n\n.menu[data-position="top"] {\n  transform-origin: 100% 0;\n}\n\n.menu[data-position="top"].hidden {\n  transform: scale(.9)rotate(3deg)translateY(-5%);\n}\n\n.menu input[type="radio"] {\n  clip: rect(0 0 0 0);\n  width: 1px;\n  height: 1px;\n  border: 0;\n  margin: 0;\n  padding: 0;\n  position: absolute;\n  overflow: hidden;\n}\n\n.menu input[type="radio"]:checked + .option {\n  box-shadow: 0 0 0 2px rgb(var(--em-rgb-accent));\n}\n\n.option {\n  width: 100%;\n  border-radius: 6px;\n  padding: 4px 6px;\n}\n\n.option:hover {\n  color: #fff;\n  background-color: rgb(var(--em-rgb-accent));\n}\n\n.skin-tone {\n  width: 16px;\n  height: 16px;\n  border-radius: 100%;\n  display: inline-block;\n  position: relative;\n  overflow: hidden;\n}\n\n.skin-tone:after {\n  content: "";\n  mix-blend-mode: overlay;\n  background: linear-gradient(rgba(255, 255, 255, .2), rgba(0, 0, 0, 0));\n  border: 1px solid rgba(0, 0, 0, .8);\n  border-radius: 100%;\n  position: absolute;\n  top: 0;\n  bottom: 0;\n  left: 0;\n  right: 0;\n  box-shadow: inset 0 -2px 3px #000, inset 0 1px 2px #fff;\n}\n\n.skin-tone-1 {\n  background-color: #ffc93a;\n}\n\n.skin-tone-2 {\n  background-color: #ffdab7;\n}\n\n.skin-tone-3 {\n  background-color: #e7b98f;\n}\n\n.skin-tone-4 {\n  background-color: #c88c61;\n}\n\n.skin-tone-5 {\n  background-color: #a46134;\n}\n\n.skin-tone-6 {\n  background-color: #5d4437;\n}\n\n[data-index] {\n  justify-content: space-between;\n}\n\n[data-emoji-set="twitter"] .skin-tone:after {\n  box-shadow: none;\n  border-color: rgba(0, 0, 0, .5);\n}\n\n[data-emoji-set="twitter"] .skin-tone-1 {\n  background-color: #fade72;\n}\n\n[data-emoji-set="twitter"] .skin-tone-2 {\n  background-color: #f3dfd0;\n}\n\n[data-emoji-set="twitter"] .skin-tone-3 {\n  background-color: #eed3a8;\n}\n\n[data-emoji-set="twitter"] .skin-tone-4 {\n  background-color: #cfad8d;\n}\n\n[data-emoji-set="twitter"] .skin-tone-5 {\n  background-color: #a8805d;\n}\n\n[data-emoji-set="twitter"] .skin-tone-6 {\n  background-color: #765542;\n}\n\n[data-emoji-set="google"] .skin-tone:after {\n  box-shadow: inset 0 0 2px 2px rgba(0, 0, 0, .4);\n}\n\n[data-emoji-set="google"] .skin-tone-1 {\n  background-color: #f5c748;\n}\n\n[data-emoji-set="google"] .skin-tone-2 {\n  background-color: #f1d5aa;\n}\n\n[data-emoji-set="google"] .skin-tone-3 {\n  background-color: #d4b48d;\n}\n\n[data-emoji-set="google"] .skin-tone-4 {\n  background-color: #aa876b;\n}\n\n[data-emoji-set="google"] .skin-tone-5 {\n  background-color: #916544;\n}\n\n[data-emoji-set="google"] .skin-tone-6 {\n  background-color: #61493f;\n}\n\n[data-emoji-set="facebook"] .skin-tone:after {\n  border-color: rgba(0, 0, 0, .4);\n  box-shadow: inset 0 -2px 3px #000, inset 0 1px 4px #fff;\n}\n\n[data-emoji-set="facebook"] .skin-tone-1 {\n  background-color: #f5c748;\n}\n\n[data-emoji-set="facebook"] .skin-tone-2 {\n  background-color: #f1d5aa;\n}\n\n[data-emoji-set="facebook"] .skin-tone-3 {\n  background-color: #d4b48d;\n}\n\n[data-emoji-set="facebook"] .skin-tone-4 {\n  background-color: #aa876b;\n}\n\n[data-emoji-set="facebook"] .skin-tone-5 {\n  background-color: #916544;\n}\n\n[data-emoji-set="facebook"] .skin-tone-6 {\n  background-color: #61493f;\n}\n\n';
51761
51762  
51762// app/javascript/src/emoji_mart/native.json
51763  var native_default = { categories: [{ id: "people", emojis: ["grinning", "smiley", "smile", "grin", "laughing", "sweat_smile", "rolling_on_the_floor_laughing", "joy", "slightly_smiling_face", "upside_down_face", "melting_face", "wink", "blush", "innocent", "smiling_face_with_3_hearts", "heart_eyes", "star-struck", "kissing_heart", "kissing", "relaxed", "kissing_closed_eyes", "kissing_smiling_eyes", "smiling_face_with_tear", "yum", "stuck_out_tongue", "stuck_out_tongue_winking_eye", "zany_face", "stuck_out_tongue_closed_eyes", "money_mouth_face", "hugging_face", "face_with_hand_over_mouth", "face_with_open_eyes_and_hand_over_mouth", "face_with_peeking_eye", "shushing_face", "thinking_face", "saluting_face", "zipper_mouth_face", "face_with_raised_eyebrow", "neutral_face", "expressionless", "no_mouth", "dotted_line_face", "face_in_clouds", "smirk", "unamused", "face_with_rolling_eyes", "grimacing", "face_exhaling", "lying_face", "shaking_face", "head_shaking_horizontally", "head_shaking_vertically", "relieved", "pensive", "sleepy", "drooling_face", "sleeping", "face_with_bags_under_eyes", "mask", "face_with_thermometer", "face_with_head_bandage", "nauseated_face", "face_vomiting", "sneezing_face", "hot_face", "cold_face", "woozy_face", "dizzy_face", "face_with_spiral_eyes", "exploding_head", "face_with_cowboy_hat", "partying_face", "disguised_face", "sunglasses", "nerd_face", "face_with_monocle", "confused", "face_with_diagonal_mouth", "worried", "slightly_frowning_face", "white_frowning_face", "open_mouth", "hushed", "astonished", "flushed", "pleading_face", "face_holding_back_tears", "frowning", "anguished", "fearful", "cold_sweat", "disappointed_relieved", "cry", "sob", "scream", "confounded", "persevere", "disappointed", "sweat", "weary", "tired_face", "yawning_face", "triumph", "rage", "angry", "face_with_symbols_on_mouth", "smiling_imp", "imp", "skull", "skull_and_crossbones", "hankey", "clown_face", "japanese_ogre", "japanese_goblin", "wave", "raised_back_of_hand", "raised_hand_with_fingers_splayed", "hand", "spock-hand", "rightwards_hand", "leftwards_hand", "palm_down_hand", "palm_up_hand", "leftwards_pushing_hand", "rightwards_pushing_hand", "ok_hand", "pinched_fingers", "pinching_hand", "v", "crossed_fingers", "hand_with_index_finger_and_thumb_crossed", "i_love_you_hand_sign", "the_horns", "call_me_hand", "point_left", "point_right", "point_up_2", "middle_finger", "point_down", "point_up", "index_pointing_at_the_viewer", "+1", "-1", "fist", "facepunch", "left-facing_fist", "right-facing_fist", "clap", "raised_hands", "heart_hands", "open_hands", "palms_up_together", "handshake", "pray", "writing_hand", "nail_care", "selfie", "muscle", "mechanical_arm", "mechanical_leg", "leg", "foot", "ear", "ear_with_hearing_aid", "nose", "brain", "anatomical_heart", "lungs", "tooth", "bone", "eyes", "eye", "tongue", "lips", "biting_lip", "baby", "child", "boy", "girl", "adult", "person_with_blond_hair", "man", "bearded_person", "man_with_beard", "woman_with_beard", "red_haired_man", "curly_haired_man", "white_haired_man", "bald_man", "woman", "red_haired_woman", "red_haired_person", "curly_haired_woman", "curly_haired_person", "white_haired_woman", "white_haired_person", "bald_woman", "bald_person", "blond-haired-woman", "blond-haired-man", "older_adult", "older_man", "older_woman", "person_frowning", "man-frowning", "woman-frowning", "person_with_pouting_face", "man-pouting", "woman-pouting", "no_good", "man-gesturing-no", "woman-gesturing-no", "ok_woman", "man-gesturing-ok", "woman-gesturing-ok", "information_desk_person", "man-tipping-hand", "woman-tipping-hand", "raising_hand", "man-raising-hand", "woman-raising-hand", "deaf_person", "deaf_man", "deaf_woman", "bow", "man-bowing", "woman-bowing", "face_palm", "man-facepalming", "woman-facepalming", "shrug", "man-shrugging", "woman-shrugging", "health_worker", "male-doctor", "female-doctor", "student", "male-student", "female-student", "teacher", "male-teacher", "female-teacher", "judge", "male-judge", "female-judge", "farmer", "male-farmer", "female-farmer", "co
vendor: 5,074 bytes, line 51763
51763ok", "male-cook", "female-cook", "mechanic", "male-mechanic", "female-mechanic", "factory_worker", "male-factory-worker", "female-factory-worker", "office_worker", "male-office-worker", "female-office-worker", "scientist", "male-scientist", "female-scientist", "technologist", "male-technologist", "female-technologist", "singer", "male-singer", "female-singer", "artist", "male-artist", "female-artist", "pilot", "male-pilot", "female-pilot", "astronaut", "male-astronaut", "female-astronaut", "firefighter", "male-firefighter", "female-firefighter", "cop", "male-police-officer", "female-police-officer", "sleuth_or_spy", "male-detective", "female-detective", "guardsman", "male-guard", "female-guard", "ninja", "construction_worker", "male-construction-worker", "female-construction-worker", "person_with_crown", "prince", "princess", "man_with_turban", "man-wearing-turban", "woman-wearing-turban", "man_with_gua_pi_mao", "person_with_headscarf", "person_in_tuxedo", "man_in_tuxedo", "woman_in_tuxedo", "bride_with_veil", "man_with_veil", "woman_with_veil", "pregnant_woman", "pregnant_man", "pregnant_person", "breast-feeding", "woman_feeding_baby", "man_feeding_baby", "person_feeding_baby", "angel", "santa", "mrs_claus", "mx_claus", "superhero", "male_superhero", "female_superhero", "supervillain", "male_supervillain", "female_supervillain", "mage", "male_mage", "female_mage", "fairy", "male_fairy", "female_fairy", "vampire", "male_vampire", "female_vampire", "merperson", "merman", "mermaid", "elf", "male_elf", "female_elf", "genie", "male_genie", "female_genie", "zombie", "male_zombie", "female_zombie", "troll", "massage", "man-getting-massage", "woman-getting-massage", "haircut", "man-getting-haircut", "woman-getting-haircut", "walking", "man-walking", "woman-walking", "person_walking_facing_right", "woman_walking_facing_right", "man_walking_facing_right", "standing_person", "man_standing", "woman_standing", "kneeling_person", "man_kneeling", "woman_kneeling", "person_kneeling_facing_right", "woman_kneeling_facing_right", "man_kneeling_facing_right", "person_with_probing_cane", "person_with_white_cane_facing_right", "man_with_probing_cane", "man_with_white_cane_facing_right", "woman_with_probing_cane", "woman_with_white_cane_facing_right", "person_in_motorized_wheelchair", "person_in_motorized_wheelchair_facing_right", "man_in_motorized_wheelchair", "man_in_motorized_wheelchair_facing_right", "woman_in_motorized_wheelchair", "woman_in_motorized_wheelchair_facing_right", "person_in_manual_wheelchair", "person_in_manual_wheelchair_facing_right", "man_in_manual_wheelchair", "man_in_manual_wheelchair_facing_right", "woman_in_manual_wheelchair", "woman_in_manual_wheelchair_facing_right", "runner", "man-running", "woman-running", "person_running_facing_right", "woman_running_facing_right", "man_running_facing_right", "dancer", "man_dancing", "man_in_business_suit_levitating", "dancers", "men-with-bunny-ears-partying", "women-with-bunny-ears-partying", "person_in_steamy_room", "man_in_steamy_room", "woman_in_steamy_room", "person_climbing", "man_climbing", "woman_climbing", "fencer", "horse_racing", "skier", "snowboarder", "golfer", "man-golfing", "woman-golfing", "surfer", "man-surfing", "woman-surfing", "rowboat", "man-rowing-boat", "woman-rowing-boat", "swimmer", "man-swimming", "woman-swimming", "person_with_ball", "man-bouncing-ball", "woman-bouncing-ball", "weight_lifter", "man-lifting-weights", "woman-lifting-weights", "bicyclist", "man-biking", "woman-biking", "mountain_bicyclist", "man-mountain-biking", "woman-mountain-biking", "person_doing_cartwheel", "man-cartwheeling", "woman-cartwheeling", "wrestlers", "man-wrestling", "woman-wrestling", "water_polo", "man-playing-water-polo", "woman-playing-water-polo", "handball", "man-playing-handball", "woman-playing-handball", "juggling", "man-juggling", "woman-juggling", "person_in_lotus_position", "man_in_lotus_position", "woman_in_lotus_position", "bath", "sleeping_accommodation", "people_holding_hands", "two_women_holding_hands", "man_and_woman_holding_hands", "two_men_holding_hands", "couplekiss", "woman-kiss-man", "man-kiss-man", "woman-kiss-woman", "couple_with_heart", "woman-heart-man", "man-heart-man", "woman-heart-woman", "man-woman-boy", "man-woman-girl", "man-woman-girl-boy", "man-woman-boy-boy", "man-woman-girl-girl", "man-man-boy", "man-man-girl", "man-man-girl-boy", "man-man-boy-boy", "man-man-girl-girl", "woman-woman-boy", "woman-woman-girl", "woman-woman-girl-boy", "woman-woman-boy-boy", "woman-woman-girl-girl", "man-boy", "man-boy-boy", "man-girl", "man-girl-boy", "man-girl-girl", "woman-boy", "woman-boy-boy", "woman-girl", "woman-girl-boy", "woman-girl-girl", "speaking_head_in_silhouette", "bust_in_silhouette", "busts_in_silhouette", "people_hugging", "family", "family_adult_adult_child", "family_adult_adult_child_child", "family_adult_child", "family_adult_child_child", "footprints", "fingerprint", "ghost", "alien", "space_invader", "robot_face", "smiley_cat", "smile_cat", "joy_cat", "heart_eyes_cat", "smirk_cat", "kissing_c
51763at", "scream_cat", "crying_cat_face", "pouting_cat", "see_no_evil", "hear_no_evil", "speak_no_evil", "love_letter", "cupid", "gift_heart", "sparkling_heart", "heartpulse", "heartbeat", "revolving_hearts", "two_hearts", "heart_decoration", "heavy_heart_exclamation_mark_ornament", "broken_heart", "heart_on_fire", "mending_heart", "heart", "pink_heart", "orange_heart", "yellow_heart", "green_heart", "blue_heart", "light_blue_heart", "purple_heart", "brown_heart", "black_heart", "grey_heart", "white_heart", "kiss", "100", "anger", "boom", "dizzy", "sweat_drops", "dash", "hole", "speech_balloon", "eye-in-speech-bubble", "left_speech_bubble", "right_anger_bubble", "thought_balloon", "zzz", "distorted_face", "fight_cloud", "hairy_creature", "ballet_dancer"] }, { id: "nature", emojis: ["monkey_face", "monkey", "gorilla", "orangutan", "dog", "dog2", "guide_dog", "service_dog", "poodle", "wolf", "fox_face", "raccoon", "cat", "cat2", "black_cat", "lion_face", "tiger", "tiger2", "leopard", "horse", "moose", "donkey", "racehorse", "unicorn_face", "zebra_face", "deer", "bison", "cow", "ox", "water_buffalo", "cow2", "pig", "pig2", "boar", "pig_nose", "ram", "sheep", "goat", "dromedary_camel", "camel", "llama", "giraffe_face", "elephant", "mammoth", "rhinoceros", "hippopotamus", "mouse", "mouse2", "rat", "hamster", "rabbit", "rabbit2", "chipmunk", "beaver", "hedgehog", "bat", "bear", "polar_bear", "koala", "panda_face", "sloth", "otter", "skunk", "kangaroo", "badger", "feet", "turkey", "chicken", "rooster", "hatching_chick", "baby_chick", "hatched_chick", "bird", "penguin", "dove_of_peace", "eagle", "duck", "swan", "owl", "dodo", "feather", "flamingo", "peacock", "parrot", "wing", "black_bird", "goose", "phoenix", "frog", "crocodile", "turtle", "lizard", "snake", "dragon_face", "dragon", "sauropod", "t-rex", "whale", "whale2", "dolphin", "seal", "fish", "tropical_fish", "blowfish", "shark", "octopus", "shell", "coral", "jellyfish", "crab", "lobster", "shrimp", "squid", "oyster", "snail", "butterfly", "bug", "ant", "bee", "beetle", "ladybug", "cricket", "cockroach", "spider", "spider_web", "scorpion", "mosquito", "fly", "worm", "microbe", "bouquet", "cherry_blossom", "white_flower", "lotus", "rosette", "rose", "wilted_flower", "hibiscus", "sunflower", "blossom", "tulip", "hyacinth", "seedling", "potted_plant", "evergreen_tree", "deciduous_tree", "palm_tree", "cactus", "ear_of_rice", "herb", "shamrock", "four_leaf_clover", "maple_leaf", "fallen_leaf", "leaves", "empty_nest", "nest_with_eggs", "mushroom", "leafless_tree", "orca"] }, { id: "foods", emojis: ["grapes", "melon", "watermelon", "tangerine", "lemon", "lime", "banana", "pineapple", "mango", "apple", "green_apple", "pear", "peach", "cherries", "strawberry", "blueberries", "kiwifruit", "tomato", "olive", "coconut", "avocado", "eggplant", "potato", "carrot", "corn", "hot_pepper", "bell_pepper", "cucumber", "leafy_green", "broccoli", "garlic", "onion", "peanuts", "beans", "chestnut", "ginger_root", "pea_pod", "brown_mushroom", "root_vegetable", "bread", "croissant", "baguette_bread", "flatbread", "pretzel", "bagel", "pancakes", "waffle", "cheese_wedge", "meat_on_bone", "poultry_leg", "cut_of_meat", "bacon", "hamburger", "fries", "pizza", "hotdog", "sandwich", "taco", "burrito", "tamale", "stuffed_flatbread", "falafel", "egg", "fried_egg", "shallow_pan_of_food", "stew", "fondue", "bowl_with_spoon", "green_salad", "popcorn", "butter", "salt", "canned_food", "bento", "rice_cracker", "rice_ball", "rice", "curry", "ramen", "spaghetti", "sweet_potato", "oden", "sushi", "fried_shrimp", "fish_cake", "moon_cake", "dango", "dumpling", "fortune_cookie", "takeout_box", "icecream", "shaved_ice", "ice_cream", "doughnut", "cookie", "birthday", "cake", "cupcake", "pie", "chocolate_bar", "candy", "lollipop", "custard", "honey_pot", "baby_bottle", "glass_of_milk", "coffee", "teapot", "tea", "sake", "champagne", "wine_glass", "cocktail", "tropical_drink", "beer", "beers", "clinking_glasses", "tumbler_glass", "pouring_liquid", "cup_with_straw", "bubble_tea", "beverage_box", "mate_drink", "ice_cube", "chopsticks", "knife_fork_plate", "fork_and_knife", "spoon", "hocho", "jar", "amphora"] }, { id: "activity", emojis: ["jack_o_lantern", "christmas_tree", "fireworks", "sparkler", "firecracker", "sparkles", "balloon", "tada", "confetti_ball", "tanabata_tree", "bamboo", "dolls", "flags", "wind_chime", "rice_scene", "red_envelope", "ribbon", "gift", "reminder_ribbon", "admission_tickets", "ticket", "medal", "trophy", "sports_medal", "first_place_medal", "second_place_medal", "third_place_medal", "soccer", "baseball", "softball", "basketball", "volleyball", "football", "rugby_football", "tennis", "flying_disc", "bowling", "cricket_bat_and_ball", "field_hockey_stick_and_ball", "ice_hockey_stick_and_puck", "lacrosse", "table_tennis_paddle_and_ball", "badminton_racquet_and_shuttlecock", "boxing_glove", "martial_arts_uniform", "goal_net", "golf", "ice_skate", "fishing_pole_and_fish", "diving_mask", "running_shirt_with_sash", "ski", "sled", "curling_stone", "dart", "yo-yo", "kite", "gun", "8ball", "crystal_ball", "magic_wand", "video_game", "joystick", "slot_machine", "game_die", "jigsaw", "teddy_bear", "pinata", "mirror_ball", "nesting_dolls", "spades", "hearts", "diamonds", "clubs", "chess_pawn", "black_joker", "mahjong", "flower_playing_cards", "performing_arts", "frame_with_picture", "art", "thread", "sewing_needle", "yarn", "knot"] }, { id: "places", emojis: ["earth_africa", "earth_americas", "earth_asia", "globe_with_meri
51763dians", "world_map", "japan", "compass", "snow_capped_mountain", "mountain", "volcano", "mount_fuji", "camping", "beach_with_umbrella", "desert", "desert_island", "national_park", "stadium", "classical_building", "building_construction", "bricks", "rock", "wood", "hut", "house_buildings", "derelict_house_building", "house", "house_with_garden", "office", "post_office", "european_post_office", "hospital", "bank", "hotel", "love_hotel", "convenience_store", "school", "department_store", "factory", "japanese_castle", "european_castle", "wedding", "tokyo_tower", "statue_of_liberty", "church", "mosque", "hindu_temple", "synagogue", "shinto_shrine", "kaaba", "fountain", "tent", "foggy", "night_with_stars", "cityscape", "sunrise_over_mountains", "sunrise", "city_sunset", "city_sunrise", "bridge_at_night", "hotsprings", "carousel_horse", "playground_slide", "ferris_wheel", "roller_coaster", "barber", "circus_tent", "steam_locomotive", "railway_car", "bullettrain_side", "bullettrain_front", "train2", "metro", "light_rail", "station", "tram", "monorail", "mountain_railway", "train", "bus", "oncoming_bus", "trolleybus", "minibus", "ambulance", "fire_engine", "police_car", "oncoming_police_car", "taxi", "oncoming_taxi", "car", "oncoming_automobile", "blue_car", "pickup_truck", "truck", "articulated_lorry", "tractor", "racing_car", "racing_motorcycle", "motor_scooter", "manual_wheelchair", "motorized_wheelchair", "auto_rickshaw", "bike", "scooter", "skateboard", "roller_skate", "busstop", "motorway", "railway_track", "oil_drum", "fuelpump", "wheel", "rotating_light", "traffic_light", "vertical_traffic_light", "octagonal_sign", "construction", "anchor", "ring_buoy", "boat", "canoe", "speedboat", "passenger_ship", "ferry", "motor_boat", "ship", "airplane", "small_airplane", "airplane_departure", "airplane_arriving", "parachute", "seat", "helicopter", "suspension_railway", "mountain_cableway", "aerial_tramway", "satellite", "rocket", "flying_saucer", "bellhop_bell", "luggage", "hourglass", "hourglass_flowing_sand", "watch", "alarm_clock", "stopwatch", "timer_clock", "mantelpiece_clock", "clock12", "clock1230", "clock1", "clock130", "clock2", "clock230", "clock3", "clock330", "clock4", "clock430", "clock5", "clock530", "clock6", "clock630", "clock7", "clock730", "clock8", "clock830", "clock9", "clock930", "clock10", "clock1030", "clock11", "clock1130", "new_moon", "waxing_crescent_moon", "first_quarter_moon", "moon", "full_moon", "waning_gibbous_moon", "last_quarter_moon", "waning_crescent_moon", "crescent_moon", "new_moon_with_face", "first_quarter_moon_with_face", "last_quarter_moon_with_face", "thermometer", "sunny", "full_moon_with_face", "sun_with_face", "ringed_planet", "star", "star2", "stars", "milky_way", "cloud", "partly_sunny", "thunder_cloud_and_rain", "mostly_sunny", "barely_sunny", "partly_sunny_rain", "rain_cloud", "snow_cloud", "lightning", "tornado", "fog", "wind_blowing_face", "cyclone", "rainbow", "closed_umbrella", "umbrella", "umbrella_with_rain_drops", "umbrella_on_ground", "zap", "snowflake", "snowman", "snowman_without_snow", "comet", "fire", "droplet", "ocean", "landslide"] }, { id: "objects", emojis: ["eyeglasses", "dark_sunglasses", "goggles", "lab_coat", "safety_vest", "necktie", "shirt", "jeans", "scarf", "gloves", "coat", "socks", "dress", "kimono", "sari", "one-piece_swimsuit", "briefs", "shorts", "bikini", "womans_clothes", "folding_hand_fan", "purse", "handbag", "pouch", "shopping_bags", "school_satchel", "thong_sandal", "mans_shoe", "athletic_shoe", "hiking_boot", "womans_flat_shoe", "high_heel", "sandal", "ballet_shoes", "boot", "hair_pick", "crown", "womans_hat", "tophat", "mortar_board", "billed_cap", "military_helmet", "helmet_with_white_cross", "prayer_beads", "lipstick", "ring", "gem", "mute", "speaker", "sound", "loud_sound", "loudspeaker", "mega", "postal_horn", "bell", "no_bell", "musical_score", "musical_note", "notes", "studio_microphone", "level_slider", "control_knobs", "microphone", "headphones", "radio", "saxophone", "accordion", "guitar", "musical_keyboard", "trumpet", "violin", "banjo", "drum_with_drumsticks", "long_drum", "maracas", "flute", "harp", "iphone", "calling", "phone", "telephone_receiver", "pager", "fax", "battery", "low_battery", "electric_plug", "computer", "desktop_computer", "printer", "keyboard", "three_button_mouse", "trackball", "minidisc", "floppy_disk", "cd", "dvd", "abacus", "movie_camera", "film_frames", "film_projector", "clapper", "tv", "camera", "camera_with_flash", "video_camera", "vhs", "mag", "mag_right", "candle", "bulb", "flashlight", "izakaya_lantern", "diya_lamp", "notebook_with_decorative_cover", "closed_book", "book", "green_book", "blue_book", "orange_book", "books", "notebook", "ledger", "page_with_curl", "scroll", "page_facing_up", "newspaper", "rolled_up_newspaper", "bookmark_tabs", "bookmark", "label", "moneybag", "coin", "yen", "dollar", "euro", "pound", "money_with_wings", "credit_card", "receipt", "chart", "email", "e-mail", "incoming_envelope", "envelope_with_arrow", "outbox_tray", "inbox_tray", "package", "mailbox", "mailbox_closed", "mailbox_with_mail", "mailbox_with_no_mail", "postbox", "ballot_box_with_ballot", "pencil2", "black_nib", "lower_left_fountain_pen", "lower_left_ballpoint_pen", "lower_left_paintbrush", "lower_left_crayon", "memo", "briefcase", "file_folder", "open_file_folder", "card_index_dividers", "date", "calendar", "spiral_note_pad", "spiral_calendar_pad", "card_index", "chart_with_upwards_trend", "chart_with_downwards_trend", "bar_chart", "clipboard", "pushpin", "round_pushpin", "paperclip", "linked_paperclips", "straight_ruler", "triangular_ruler", "scissors", "card_file_box", "file_cabinet", "wastebasket", "lock", "unlock", "lock_with_ink_pen", "closed_lock_with_key", "key", "old_key", "hammer", "axe", "pick", "hammer_and_pick", "hammer_and_wrench", "dagger_knife", "crossed_swords", "bomb", "boomerang", "bow_and_arrow", "shield", "carpentry_saw", "wrench", "screwdriver", "nut_and_bolt", "gear", "compression", "scales", "probing_cane", "link", "broken_chain", "chains", "hook", "toolbox", "magnet", "ladder", "shovel", "alembic", "test_tube", "petri_dish", "dna", "microscope", "telescope", "satellite_antenna", "syringe", "drop_of_blood", "pill", "adhesive_bandage", "crutch", "stethoscope", "x-ray", "door", "elevator", "mirror", "window", "bed", "couch_and_lamp", "chair", "toilet", "plunger", "shower", "bathtub", "mouse_trap", "razor", "lotion_bottle", "safety_pin", "broom", "basket", "roll_of_paper", "bucket", "soap", "bubbles", "toothbrush", "sponge", "fire_extinguisher", "shopping_trolley", "smoking", "coffin", "headstone", "funeral_urn", "nazar_amulet", "hamsa", "moyai", "placard", "identification_card", "trombone", "treasure_chest"] }, { id: "symbols", emojis: ["atm", "put_litter_in_its_place", "potable_water", "wheelchair", "mens", "womens", "restroom", "baby_symbol", "wc", "passport_control", "customs", "baggage_claim", "left_luggage", "warning", "children_crossing", "no_entry", "no_entry_sign", "no_bicycles", "no_smoking", "do_not_litter", "non-potable_water", "no_pedestrians", "no_mobile_phones", "underage", "radioactive_sign", "biohazard_sign", "arrow_up", "arrow_upper_right", "arrow_right", "arrow_lower_right", "arrow_down", "arrow_lower_left", "arrow_left", "arrow_upper_left", "arrow_up_down", "left_right_arrow", "leftwards_arrow_with_hook", "arrow_right_hook", "arrow_heading_up", "arrow_heading_down", "arrows_clockwise", "arrows_counterclockwise", "back", "end", "on", "soon", "top", "place_of_worship", "atom_symbol", "om_symbol", "star_of_david", "wheel_of_dharma", "yin_yang", "latin_cross", "orthodox_cross", "star_and_crescent", "peace_symbol", "menorah_with_nine_branches", "six_pointed_star", "khanda", "aries", "taurus", "gemini", "cancer", "leo", "virgo", "libra", "scorpius", "sagittarius", "capricorn", "aquarius", "pisces", "ophiuchus", "twisted_rightwards_arrows", "repeat", "repeat_one", "arrow_forward", "fast_forward", "black_right_pointing_double_triangle_with_vertical_bar", "black_right_pointing_triangle_with_double_vertical_bar", "arrow_backward", "rewind", "black_left_pointing_double_triangle_with_vertical_bar", "arrow_up_small", "arrow_double_up", "arrow_down_small", "arrow_double_down", "double_vertical_bar", "black_square_for_stop", "black_circle_for_record", "eject", "cinema", "low_brightness", "high_brightness", "signal_strength", "wireless", "vibration_mode", "mobile_phone_off", "female_sign", "male_sign", "transgender_symbol", "heavy_multiplication_x", "heavy_plus_sign", "heavy_minus_sign", "heavy_division_sign", "heavy_equals_sign", "infinity", "bangbang", "interrobang", "question", "grey_question", "grey_exclamation", "exclamation", "wavy_dash", "currency_exchange", "heavy_dollar_sign", "medical_symbol", "recycle", "fleur_de_lis", "trident", "name_badge", "beginner", "o", "white_check_mark", "ballot_box_with_check", "heavy_check_mark", "x", "negative_squared_cross_mark", "curly_loop", "loop", "part_alternation_mark", "eight_spoked_asterisk", "eight_pointed_black_star", "sparkle", "copyright", "registered", "tm", "splatter", "hash", "keycap_star", "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "keycap_ten", "capital_abcd", "abcd", "1234", "symbols", "abc", "a", "ab", "b", "cl", "cool", "free", "information_source", "id", "m", "new", "ng", "o2", "ok", "parking", "sos", "up", "vs", "koko", "sa", "u6708", "u6709", "u
517636307", "ideograph_advantage", "u5272", "u7121", "u7981", "accept", "u7533", "u5408", "u7a7a", "congratulations", "secret", "u55b6", "u6e80", "red_circle", "large_orange_circle", "large_yellow_circle", "large_green_circle", "large_blue_circle", "large_purple_circle", "large_brown_circle", "black_circle", "white_circle", "large_red_square", "large_orange_square", "large_yellow_square", "large_green_square", "large_blue_square", "large_purple_square", "large_brown_square", "black_large_square", "white_large_square", "black_medium_square", "white_medium_square", "black_medium_small_square", "white_medium_small_square", "black_small_square", "white_small_square", "large_orange_diamond", "large_blue_diamond", "small_orange_diamond", "small_blue_diamond", "small_red_triangle", "small_red_triangle_down", "diamond_shape_with_a_dot_inside", "radio_button", "white_square_button", "black_square_button"] }, { id: "flags", emojis: ["checkered_flag", "cn", "crossed_flags", "de", "es", "flag-ac", "flag-ad", "flag-ae", "flag-af", "flag-ag", "flag-ai", "flag-al", "flag-am", "flag-ao", "flag-aq", "flag-ar", "flag-as", "flag-at", "flag-au", "flag-aw", "flag-ax", "flag-az", "flag-ba", "flag-bb", "flag-bd", "flag-be", "flag-bf", "flag-bg", "flag-bh", "flag-bi", "flag-bj", "flag-bl", "flag-bm", "flag-bn", "flag-bo", "flag-bq", "flag-br", "flag-bs", "flag-bt", "flag-bv", "flag-bw", "flag-by", "flag-bz", "flag-ca", "flag-cc", "flag-cd", "flag-cf", "flag-cg", "flag-ch", "flag-ci", "flag-ck", "flag-cl", "flag-cm", "flag-co", "flag-cp", "flag-cr", "flag-cu", "flag-cv", "flag-cw", "flag-cx", "flag-cy", "flag-cz", "flag-dg", "flag-dj", "flag-dk", "flag-dm", "flag-do", "flag-dz", "flag-ea", "flag-ec", "flag-ee", "flag-eg", "flag-eh", "flag-england", "flag-er", "flag-et", "flag-eu", "flag-fi", "flag-fj", "flag-fk", "flag-fm", "flag-fo", "flag-ga", "flag-gd", "flag-ge", "flag-gf", "flag-gg", "flag-gh", "flag-gi", "flag-gl", "flag-gm", "flag-gn", "flag-gp", "flag-gq", "flag-gr", "flag-gs", "flag-gt", "flag-gu", "flag-gw", "flag-gy", "flag-hk", "flag-hm", "flag-hn", "flag-hr", "flag-ht", "flag-hu", "flag-ic", "flag-id", "flag-ie", "flag-il", "flag-im", "flag-in", "flag-io", "flag-iq", "flag-ir", "flag-is", "flag-je", "flag-jm", "flag-jo", "flag-ke", "flag-kg", "flag-kh", "flag-ki", "flag-km", "flag-kn", "flag-kp", "flag-kw", "flag-ky", "flag-kz", "flag-la", "flag-lb", "flag-lc", "flag-li", "flag-lk", "flag-lr", "flag-ls", "flag-lt", "flag-lu", "flag-lv", "flag-ly", "flag-ma", "flag-mc", "flag-md", "flag-me", "flag-mf", "flag-mg", "flag-mh", "flag-mk", "flag-ml", "flag-mm", "flag-mn", "flag-mo", "flag-mp", "flag-mq", "flag-mr", "flag-ms", "flag-mt", "flag-mu", "flag-mv", "flag-mw", "flag-mx", "flag-my", "flag-mz", "flag-na", "flag-nc", "flag-ne", "flag-nf", "flag-ng", "flag-ni", "flag-nl", "flag-no", "flag-np", "flag-nr", "flag-nu", "flag-nz", "flag-om", "flag-pa", "flag-pe", "flag-pf", "flag-pg", "flag-ph", "flag-pk", "flag-pl", "flag-pm", "flag-pn", "flag-pr", "flag-ps", "flag-pt", "flag-pw", "flag-py", "flag-qa", "flag-re", "flag-ro", "flag-rs", "flag-rw", "flag-sa", "flag-sark", "flag-sb", "flag-sc", "flag-scotland", "flag-sd", "flag-se", "flag-sg", "flag-sh", "flag-si", "flag-sj", "flag-sk", "flag-sl", "flag-sm", "flag-sn", "flag-so", "flag-sr", "flag-ss", "flag-st", "flag-sv", "flag-sx", "flag-sy", "flag-sz", "flag-ta", "flag-tc", "flag-td", "flag-tf", "flag-tg", "flag-th", "flag-tj", "flag-tk", "flag-tl", "flag-tm", "flag-tn", "flag-to", "flag-tr", "flag-tt", "flag-tv", "flag-tw", "flag-tz", "flag-ua", "flag-ug", "flag-um", "flag-un", "flag-uy", "flag-uz", "flag-va", "flag-vc", "flag-ve", "flag-vg", "flag-vi", "flag-vn", "flag-vu", "flag-wales", "flag-wf", "flag-ws", "flag-xk", "flag-ye", "flag-yt", "flag-za", "flag-zm", "flag-zw", "fr", "gb", "it", "jp", "kr", "pirate_flag", "rainbow-flag", "ru", "transgender_flag", "triangular_flag_on_post", "us", "waving_black_flag", "waving_white_flag"] }], emojis: { "100": { id: "100", name: "Hundred Points", keywords: ["100", "score", "perfect", "numbers", "century", "exam", "quiz", "test", "pass"], skins: [{ unified: "1f4af", native: "\u{1F4AF}" }], version: 1 }, "1234": { id: "1234", name: "Input Numbers", keywords: ["1234", "blue", "square", "1", "2", "3", "4"], skins: [{ unified: "1f522", native: "\u{1F522}" }], version: 1 }, grinning: { id: "grinning", name: "Grinning Face", emoticons: [":D"], keywords: ["smile", "happy", "joy", ":D", "grin"], skins: [{ unified: "1f600", native: "\u{1F600}" }], version: 1 }, smiley: { id: "smiley", name: "Grinning Face with Big Eyes", emoticons: [":)", "=)", "=-)"], keywords: ["smiley", "happy", "joy", "haha", ":D", ":)", "smile", "funny"], skins: [{ unified: "1f603", native: "\u{1F603}" }], version: 1 }, smile: { id: "smile", name: "Grinning Face with Smiling Eyes", emoticons: [":)", "C:", "c:", ":D", ":-D"], keywords: ["smile", "happy", "joy", "funny", "haha", "laugh", "like", ":D", ":)"], skins: [{ unified: "1f604", native: "\u{1F604}" }], version: 1 }, grin: { id: "grin", name: "Beaming Face with Smiling Eyes", keywords: ["grin", "happy", "smile", "joy", "kawaii"], skins: [{ unified: "1f601", native: "\u{1F601}" }], version: 1 }, laughing: { id: "laughing", name: "Grinning Squinting Face", emoticons: [":>", ":->"], keywords: ["laughing", "satisfied", "happy", "joy", "lol", "haha", "glad", "XD", "laugh"], skins: [{ unified: "1f606", native: "\u{1F606}" }], version: 1 }, sweat_smile: { id: "sweat_smile", name: "Grinning Face with Sweat", keywords: ["smile", "hot", "happy", "laugh", "relief"], skins: [{ unified: "1f605", native: "\u{1F605}" }], version: 1 }, rolling_on_the_floor_laughing: { id: "rolling_on_the_floor_laughing", name: "Rolling on the Floor Laughing", keywords: ["face", "lol", "haha", "rofl"], skins: [{ unified: "1f923", native: "\u{1F923}" }], version: 3 }, joy: { id: "joy", name: "Face with Tears of Joy", keywords: ["cry", "weep", "happy", "happytears", "haha"], skins: [{ unified: "1f602", native: "\u{1F602}" }], version: 1 }, slightly_smiling_face: { id: "slightly_smiling_face", name: "Slightly Smiling Face", emoticons: [":)", "(:", ":-)"], keywords: ["smile"], skins: [{ unified: "1f642", native: "\u{1F642}" }], version: 1 }, upside_down_face: { id: "upside_down_face", name: "Upside-Down Face", keywords: ["upside", "down", "flipped", "silly", "smile"], skins: [{ unified: "1f643", native: "\u{1F643}" }], version: 1 }, melting_face: { id: "melting_face", name: "Melting Face", keywords: ["hot", "heat"], skins: [{ unified: "1fae0", native: "\u{1FAE0}" }], version: 14 }, wink: { id: "wink", name: "Winking Face", emoticons: [";)", ";-)"], keywords: ["wink", "happy", "mischievous", "secret", ";)", "smile", "eye"], skins: [{ unified: "1f609", native: "\u{1F609}" }], version: 1 }, blush: { id: "blush", name: "Smiling Face with Smiling Eyes", emoticons: [":)"], keywords: ["blush", "smile", "happy", "flushed", "crush", "embarrassed", "shy", "joy"], skins: [{ unified: "1f60a", native: "\u{1F60A}" }], version: 1 }, innocent: { id: "innocent", name: "Smiling Face with Halo", keywords: ["innocent", "angel", "heaven"], skins: [{ unified: "1f607", native: "\u{1F607}" }], version: 1 }, smiling_face_with_3_hearts: { id: "smiling_face_with_3_hearts", name: "Smiling Face with Hearts", keywords: ["3", "love", "like", "affection", "valentines", "infatuation", "crush", "adore"], skins: [{ unified: "1f970", native: "\u{1F970}" }], version: 11 }, heart_eyes: { id: "heart_eyes", name: "Smiling Face with Heart-Eyes", keywords: ["heart", "eyes", "love", "like", "affection", "valentines", "infatuation", "crush"], skins: [{ unified: "1f60d", native: "\u{1F60D}" }], version: 1 }, "star-struck": { id: "star-struck", name: "Star-Struck", keywords: ["star", "struck", "grinning", "face", "with", "eyes", "smile", "starry"], skins: [{ unified: "1f929", native: "\u{1F929}" }], version: 5 }, kissing_heart: { id: "kissing_heart", name: "Face Blowing a Kiss", emoticons: [":*", ":-*"], keywords: ["kissing", "heart", "love", "like", "affection", "valentines", "infatuation"], skins: [{ unified: "1f618", native: "\u{1F618}" }], version: 1 }, kissing: { id: "kissing", name: "Kissing Face", keywords: ["love", "like", "3", "valentines", "infatuation", "kiss"], skins: [{ unified: "1f617", native: "\u{1F617}" }], version: 1 }, relaxed: { id: "relaxed", name: "Smiling Face", keywords: ["relaxed", "blush", "massage", "happiness"], skins: [{ unified: "263a-fe0f", native: "\u263A\uFE0F" }], version: 1 }, kissing_closed_eyes: { id: "kissing_closed_eyes", name: "Kissing Face with Closed Eyes", keywords: ["love", "like", "affection", "valentines", "infatuation", "kiss"], skins: [{ unified: "1f61a", native: "\u{1F61A}" }], version: 1 }, kissing_smiling_eyes: { id: "kissing_smiling_eyes", name: "Kissing Face with Smiling Eyes", keywords: ["affection", "valentines", "infatuation", "kiss"], skins: [{ unified: "1f619", native: "\u{1F619}" }], version: 1 }, smiling_face_with_tear: { id: "smiling_face_with_tear", name: "Smiling Face with Tear", keywords: ["sad", "cry", "pretend"], skins: [{ unified: "1f972", native: "\u{1F972}" }
51763], version: 13 }, yum: { id: "yum", name: "Face Savoring Food", keywords: ["yum", "happy", "joy", "tongue", "smile", "silly", "yummy", "nom", "delicious", "savouring"], skins: [{ unified: "1f60b", native: "\u{1F60B}" }], version: 1 }, stuck_out_tongue: { id: "stuck_out_tongue", name: "Face with Tongue", emoticons: [":p", ":-p", ":P", ":-P", ":b", ":-b"], keywords: ["stuck", "out", "prank", "childish", "playful", "mischievous", "smile"], skins: [{ unified: "1f61b", native: "\u{1F61B}" }], version: 1 }, stuck_out_tongue_winking_eye: { id: "stuck_out_tongue_winking_eye", name: "Winking Face with Tongue", emoticons: [";p", ";-p", ";b", ";-b", ";P", ";-P"], keywords: ["stuck", "out", "eye", "prank", "childish", "playful", "mischievous", "smile", "wink"], skins: [{ unified: "1f61c", native: "\u{1F61C}" }], version: 1 }, zany_face: { id: "zany_face", name: "Zany Face", keywords: ["grinning", "with", "one", "large", "and", "small", "eye", "goofy", "crazy"], skins: [{ unified: "1f92a", native: "\u{1F92A}" }], version: 5 }, stuck_out_tongue_closed_eyes: { id: "stuck_out_tongue_closed_eyes", name: "Squinting Face with Tongue", keywords: ["stuck", "out", "closed", "eyes", "prank", "playful", "mischievous", "smile"], skins: [{ unified: "1f61d", native: "\u{1F61D}" }], version: 1 }, money_mouth_face: { id: "money_mouth_face", name: "Money-Mouth Face", keywords: ["money", "mouth", "rich", "dollar"], skins: [{ unified: "1f911", native: "\u{1F911}" }], version: 1 }, hugging_face: { id: "hugging_face", name: "Hugging Face", keywords: ["smile", "hug"], skins: [{ unified: "1f917", native: "\u{1F917}" }], version: 1 }, face_with_hand_over_mouth: { id: "face_with_hand_over_mouth", name: "Face with Hand over Mouth", keywords: ["smiling", "eyes", "and", "covering", "whoops", "shock", "surprise"], skins: [{ unified: "1f92d", native: "\u{1F92D}" }], version: 5 }, face_with_open_eyes_and_hand_over_mouth: { id: "face_with_open_eyes_and_hand_over_mouth", name: "Face with Open Eyes and Hand over Mouth", keywords: ["silence", "secret", "shock", "surprise"], skins: [{ unified: "1fae2", native: "\u{1FAE2}" }], version: 14 }, face_with_peeking_eye: { id: "face_with_peeking_eye", name: "Face with Peeking Eye", keywords: ["scared", "frightening", "embarrassing", "shy"], skins: [{ unified: "1fae3", native: "\u{1FAE3}" }], version: 14 }, shushing_face: { id: "shushing_face", name: "Shushing Face", keywords: ["with", "finger", "covering", "closed", "lips", "quiet", "shhh"], skins: [{ unified: "1f92b", native: "\u{1F92B}" }], version: 5 }, thinking_face: { id: "thinking_face", name: "Thinking Face", keywords: ["hmmm", "think", "consider"], skins: [{ unified: "1f914", native: "\u{1F914}" }], version: 1 }, saluting_face: { id: "saluting_face", name: "Saluting Face", keywords: ["respect", "salute"], skins: [{ unified: "1fae1", native: "\u{1FAE1}" }], version: 14 }, zipper_mouth_face: { id: "zipper_mouth_face", name: "Zipper-Mouth Face", keywords: ["zipper", "mouth", "sealed", "secret"], skins: [{ unified: "1f910", native: "\u{1F910}" }], version: 1 }, face_with_raised_eyebrow: { id: "face_with_raised_eyebrow", name: "Face with Raised Eyebrow", keywords: ["one", "distrust", "scepticism", "disapproval", "disbelief", "surprise", "suspicious"], skins: [{ unified: "1f928", native: "\u{1F928}" }], version: 5 }, neutral_face: { id: "neutral_face", name: "Neutral Face", emoticons: [":|", ":-|"], keywords: ["indifference", "meh", ":", ""], skins: [{ unified: "1f610", native: "\u{1F610}" }], version: 1 }, expressionless: { id: "expressionless", name: "Expressionless Face", emoticons: ["-_-"], keywords: ["indifferent", "-", "", "meh", "deadpan"], skins: [{ unified: "1f611", native: "\u{1F611}" }], version: 1 }, no_mouth: { id: "no_mouth", name: "Face Without Mouth", keywords: ["no"], skins: [{ unified: "1f636", native: "\u{1F636}" }], version: 1 }, dotted_line_face: { id: "dotted_line_face", name: "Dotted Line Face", keywords: ["invisible", "lonely", "isolation", "depression"], skins: [{ unified: "1fae5", native: "\u{1FAE5}" }], version: 14 }, face_in_clouds: { id: "face_in_clouds", name: "Face in Clouds", keywords: ["shower", "steam", "dream"], skins: [{ unified: "1f636-200d-1f32b-fe0f", native: "\u{1F636}\u200D\u{1F32B}\uFE0F" }], version: 13.1 }, smirk: { id: "smirk", name: "Smirking Face", keywords: ["smirk", "smile", "mean", "prank", "smug", "sarcasm"], skins: [{ unified: "1f60f", native: "\u{1F60F}" }], version: 1 }, unamused: { id: "unamused", name: "Unamused Face", emoticons: [":("], keywords: ["indifference", "bored", "straight", "serious", "sarcasm", "unimpressed", "skeptical", "dubious", "ugh", "side", "eye"], skins: [{ unified: "1f612", native: "\u{1F612}" }], version: 1 }, face_with_rolling_eyes: { id: "face_with_rolling_eyes", name: "Face with Rolling Eyes", keywords: ["eyeroll", "frustrated"], skins: [{ unified: "1f644", native: "\u{1F644}" }], version: 1 }, grimacing: { id: "grimacing", name: "Grimacing Face", keywords: ["grimace", "teeth"], skins: [{ unified: "1f62c", native: "\u{1F62C}" }], version: 1 }, face_exhaling: { id: "face_exhaling", name: "Face Exhaling", keywords: ["relieve", "relief", "tired", "sigh"], skins: [{ unified: "1f62e-200d-1f4a8", native: "\u{1F62E}\u200D\u{1F4A8}" }], version: 13.1 }, lying_face: { id: "lying_face", name: "Lying Face", keywords: ["lie", "pinocchio"], skins: [{ unified: "1f925", native: "\u{1F925}" }], version: 3 }, shaking_face: { id: "shaking_face", name: "Shaking Face", keywords: ["dizzy", "shock", "blurry", "earthquake"], skins: [{ unified: "1fae8", native: "\u{1FAE8}" }], version: 15 }, head_shaking_horizontally: { id: "head_shaking_horizontally", name: "Head Shaking Horizontally", keywords: ["disapprove", "indiffernt", "left"], skins: [{ unified: "1f642-200d-2194-fe0f", native: "\u{1F642}\u200D\u2194\uFE0F" }], version: 15.1 }, head_shaking_vertically: { id: "head_shaking_vertically", name: "Head Shaking Vertically", keywords: ["down", "nod"], skins: [{ unified: "1f642-200d-2195-fe0f", native: "\u{1F642}\u200D\u2195\uFE0F" }], version: 15.1 }, relieved: { id: "relieved", name: "Relieved Face", keywords: ["relaxed", "phew", "massage", "happiness"], skins: [{ unified: "1f60c", native: "\u{1F60C}" }], version: 1 }, pensive: { id: "pensive", name: "Pensive Face", keywords: ["sad", "depressed", "upset"], skins: [{ unified: "1f614", native: "\u{1F614}" }], version: 1 }, sleepy: { id: "sleepy", name: "Sleepy Face", keywords: ["tired", "rest", "nap"], skins: [{ unified: "1f62a", native: "\u{1F62A}" }], version: 1 }, drooling_face: { id: "drooling_face", name: "Drooling Face", keywords: [], skins: [{ unified: "1f924", native: "\u{1F924}" }], version: 3 }, sleeping: { id: "sleeping", name: "Sleeping Face", keywords: ["tired", "sleepy", "night", "zzz"], skins: [{ unified: "1f634", native: "\u{1F634}" }], version: 1 }, face_with_bags_under_eyes: { id: "face_with_bags_under_eyes", name: "Face with Bags Under Eyes", keywords: [], skins: [{ unified: "1fae9", native: "\u{1FAE9}" }], version: 16 }, mask: { id: "mask", name: "Face with Medical Mask", keywords: ["sick", "ill", "disease", "covid"], skins: [{ unified: "1f637", native: "\u{1F637}" }], version: 1 }, face_with_thermometer: { id: "face_with_thermometer", name: "Face with Thermometer", keywords: ["sick", "temperature", "cold", "fever", "covid"], skins: [{ unified: "1f912", native: "\u{1F912}" }], version: 1 }, face_with_head_bandage: { id: "face_with_head_bandage", name: "Face with Head-Bandage", keywords: ["head", "bandage", "injured", "clumsy", "hurt"], skins: [{ unified: "1f915", native: "\u{1F915}" }], version: 1 }, nauseated_face: { id: "nauseated_face", name: "Nauseated Face", keywords: ["vomit", "gross", "green", "sick", "throw", "up", "ill"], skins: [{ unified: "1f922", native: "\u{1F922}" }], version: 3 }, face_vomiting: { id: "face_vomiting", name: "Face Vomiting", keywords: ["with", "open", "mouth", "sick"], skins: [{ unified: "1f92e", native: "\u{1F92E}" }], version: 5 }, sneezing_face: { id: "sneezing_face", name: "Sneezing Face", keywords: ["gesundheit", "sneeze", "sick", "allergy"], skins: [{ unified: "1f927", native: "\u{1F927}" }], version: 3 }, hot_face: { id: "hot_face", name: "Hot Face", keywords: ["feverish", "heat", "red", "sweating"], skins: [{ unified: "1f975", native: "\u{1F975}" }], version: 11 }, cold_face: { id: "cold_face", name: "Cold Face", keywords: ["blue", "freezing", "frozen", "frostbite", "icicles"], skins: [{ unified: "1f976", native: "\u{1F976}" }], version: 11 }, woozy_face: { id: "woozy_face", name: "Woozy Face", keywords: ["dizzy", "intoxicated", "tipsy", "wavy"], skins: [{ unified: "1f974", native: "\u{1F974}" }], version: 11 }, dizzy_face: { id: "dizzy_face", name: "Dizzy Face", keywords: ["spent", "unconscious", "xox"], skins: [{ unified: "1f635", native: "\u{1F635}" }], version: 1 }, face_with_spiral_eyes: { id: "face_with_spiral_eyes", name: "Face with Spiral Eyes", keywords: ["sick", "ill", "confused", "nauseous", "nausea"], skins: [{ unified: "1f635-200d-1f4ab", native: "\u{1F635}\u200D\u{1F4AB}" }], version: 13.1 }, exploding_head: { id: "exploding_head", name: "Exploding Head", keywords: ["shocked", "face", "with", "mind", "blown"], skins: [{ unified: "1f92f", native: "\u{1F92F}" }], version: 5 }, face_with_cowboy_hat: { id: "face_with_cowboy_hat", name: "Cowboy Hat Face", keywords: ["with", "cowgirl"], skins: [{ unified: "1f920", native: "\u{1F920}" }], version: 3 }, partying_face: { id: "partying_face", name: "Partying Face", keywords: ["celebration", "woohoo"], skins: [{ unified: "1f973", native: "\u{1F973}" }], version: 11 }, disguised_face: { id: "disguised_face", name: "Disguised Face", keywords: ["pretent", "brows", "glasses", "moustache"], skins: [{ unified: "1f978", native: "\u{1F978}" }], version: 13 }, sunglasses: { id: "sunglasses", name: "Smiling Face with Sunglasses", emoticons: ["8)"], keywords: ["cool", "smile", "summer", "beach", "sunglass"], skins: [{ unified: "1f60e", native: "\u{1F60E}" }], version: 1 }, nerd_face: { id: "nerd_face", name: "Nerd Face", keywords: ["nerdy", "geek", "dork"], skins: [{ unified: "1f913", native: "\u{1F913}" }], version: 1 }, face_with_monocle: { id: "face_with_monocle", name: "Face with Monocle", keywords: ["stuffy", "wealthy"], skins: [{ unified: "1f9d0", native: "\u{1F9D0}" }], version: 5 }, confused: { id: "confused", name: "Confused Face", emoticons: [":\\", ":-\\", ":/", ":-/"], keywords: ["indifference", "huh", "weird", "hmmm", ":/"], skins: [{ unified: "1f615", native: "\u{1F615}" }], version: 1 }, face_with_diagonal_mouth: { id: "face_with_diagonal_mouth", name: "Face with Diagonal Mouth", keywords: ["skeptic", "confuse", "frustrated", "indifferent"], skins: [{ unified: "1fae4", native: "\u{1FAE4}" }
51763], version: 14 }, worried: { id: "worried", name: "Worried Face", keywords: ["concern", "nervous", ":("], skins: [{ unified: "1f61f", native: "\u{1F61F}" }], version: 1 }, slightly_frowning_face: { id: "slightly_frowning_face", name: "Slightly Frowning Face", keywords: ["disappointed", "sad", "upset"], skins: [{ unified: "1f641", native: "\u{1F641}" }], version: 1 }, white_frowning_face: { id: "white_frowning_face", name: "Frowning Face", keywords: ["white", "sad", "upset", "frown"], skins: [{ unified: "2639-fe0f", native: "\u2639\uFE0F" }], version: 1 }, open_mouth: { id: "open_mouth", name: "Face with Open Mouth", emoticons: [":o", ":-o", ":O", ":-O"], keywords: ["surprise", "impressed", "wow", "whoa", ":O"], skins: [{ unified: "1f62e", native: "\u{1F62E}" }], version: 1 }, hushed: { id: "hushed", name: "Hushed Face", keywords: ["woo", "shh"], skins: [{ unified: "1f62f", native: "\u{1F62F}" }], version: 1 }, astonished: { id: "astonished", name: "Astonished Face", keywords: ["xox", "surprised", "poisoned"], skins: [{ unified: "1f632", native: "\u{1F632}" }], version: 1 }, flushed: { id: "flushed", name: "Flushed Face", keywords: ["blush", "shy", "flattered"], skins: [{ unified: "1f633", native: "\u{1F633}" }], version: 1 }, pleading_face: { id: "pleading_face", name: "Pleading Face", keywords: ["begging", "mercy", "cry", "tears", "sad", "grievance"], skins: [{ unified: "1f97a", native: "\u{1F97A}" }], version: 11 }, face_holding_back_tears: { id: "face_holding_back_tears", name: "Face Holding Back Tears", keywords: ["touched", "gratitude", "cry"], skins: [{ unified: "1f979", native: "\u{1F979}" }], version: 14 }, frowning: { id: "frowning", name: "Frowning Face with Open Mouth", keywords: ["aw", "what"], skins: [{ unified: "1f626", native: "\u{1F626}" }], version: 1 }, anguished: { id: "anguished", name: "Anguished Face", emoticons: ["D:"], keywords: ["stunned", "nervous"], skins: [{ unified: "1f627", native: "\u{1F627}" }], version: 1 }, fearful: { id: "fearful", name: "Fearful Face", keywords: ["scared", "terrified", "nervous"], skins: [{ unified: "1f628", native: "\u{1F628}" }], version: 1 }, cold_sweat: { id: "cold_sweat", name: "Anxious Face with Sweat", keywords: ["cold", "nervous"], skins: [{ unified: "1f630", native: "\u{1F630}" }], version: 1 }, disappointed_relieved: { id: "disappointed_relieved", name: "Sad but Relieved Face", keywords: ["disappointed", "phew", "sweat", "nervous"], skins: [{ unified: "1f625", native: "\u{1F625}" }], version: 1 }, cry: { id: "cry", name: "Crying Face", emoticons: [":'("], keywords: ["cry", "tears", "sad", "depressed", "upset", ":'("], skins: [{ unified: "1f622", native: "\u{1F622}" }], version: 1 }, sob: { id: "sob", name: "Loudly Crying Face", emoticons: [":'("], keywords: ["sob", "sobbing", "cry", "tears", "sad", "upset", "depressed"], skins: [{ unified: "1f62d", native: "\u{1F62D}" }], version: 1 }, scream: { id: "scream", name: "Face Screaming in Fear", keywords: ["scream", "munch", "scared", "omg"], skins: [{ unified: "1f631", native: "\u{1F631}" }], version: 1 }, confounded: { id: "confounded", name: "Confounded Face", keywords: ["confused", "sick", "unwell", "oops", ":S"], skins: [{ unified: "1f616", native: "\u{1F616}" }], version: 1 }, persevere: { id: "persevere", name: "Persevering Face", keywords: ["persevere", "sick", "no", "upset", "oops"], skins: [{ unified: "1f623", native: "\u{1F623}" }], version: 1 }, disappointed: { id: "disappointed", name: "Disappointed Face", emoticons: ["):", ":(", ":-("], keywords: ["sad", "upset", "depressed", ":("], skins: [{ unified: "1f61e", native: "\u{1F61E}" }], version: 1 }, sweat: { id: "sweat", name: "Face with Cold Sweat", keywords: ["downcast", "hot", "sad", "tired", "exercise"], skins: [{ unified: "1f613", native: "\u{1F613}" }], version: 1 }, weary: { id: "weary", name: "Weary Face", keywords: ["tired", "sleepy", "sad", "frustrated", "upset"], skins: [{ unified: "1f629", native: "\u{1F629}" }], version: 1 }, tired_face: { id: "tired_face", name: "Tired Face", keywords: ["sick", "whine", "upset", "frustrated"], skins: [{ unified: "1f62b", native: "\u{1F62B}" }], version: 1 }, yawning_face: { id: "yawning_face", name: "Yawning Face", keywords: ["tired", "sleepy"], skins: [{ unified: "1f971", native: "\u{1F971}" }], version: 12 }, triumph: { id: "triumph", name: "Face with Look of Triumph", keywords: ["steam", "from", "nose", "gas", "phew", "proud", "pride"], skins: [{ unified: "1f624", native: "\u{1F624}" }], version: 1 }, rage: { id: "rage", name: "Pouting Face", keywords: ["rage", "angry", "mad", "hate", "despise"], skins: [{ unified: "1f621", native: "\u{1F621}" }], version: 1 }, angry: { id: "angry", name: "Angry Face", emoticons: [">:(", ">:-("], keywords: ["mad", "annoyed", "frustrated"], skins: [{ unified: "1f620", native: "\u{1F620}" }], version: 1 }, face_with_symbols_on_mouth: { id: "face_with_symbols_on_mouth", name: "Face with Symbols on Mouth", keywords: ["serious", "covering", "swearing", "cursing", "cussing", "profanity", "expletive"], skins: [{ unified: "1f92c", native: "\u{1F92C}" }], version: 5 }, smiling_imp: { id: "smiling_imp", name: "Smiling Face with Horns", keywords: ["imp", "devil"], skins: [{ unified: "1f608", native: "\u{1F608}" }], version: 1 }, imp: { id: "imp", name: "Imp", keywords: ["angry", "face", "with", "horns", "devil"], skins: [{ unified: "1f47f", native: "\u{1F47F}" }], version: 1 }, skull: { id: "skull", name: "Skull", keywords: ["dead", "skeleton", "creepy", "death"], skins: [{ unified: "1f480", native: "\u{1F480}" }], version: 1 }, skull_and_crossbones: { id: "skull_and_crossbones", name: "Skull and Crossbones", keywords: ["poison", "danger", "deadly", "scary", "death", "pirate", "evil"], skins: [{ unified: "2620-fe0f", native: "\u2620\uFE0F" }], version: 1 }, hankey: { id: "hankey", name: "Pile of Poo", keywords: ["hankey", "poop", "shit", "shitface", "fail", "turd"], skins: [{ unified: "1f4a9", native: "\u{1F4A9}" }], version: 1 }, clown_face: { id: "clown_face", name: "Clown Face", keywords: [], skins: [{ unified: "1f921", native: "\u{1F921}" }], version: 3 }, japanese_ogre: { id: "japanese_ogre", name: "Ogre", keywords: ["japanese", "monster", "red", "mask", "halloween", "scary", "creepy", "devil", "demon"], skins: [{ unified: "1f479", native: "\u{1F479}" }], version: 1 }, japanese_goblin: { id: "japanese_goblin", name: "Goblin", keywords: ["japanese", "red", "evil", "mask", "monster", "scary", "creepy"], skins: [{ unified: "1f47a", native: "\u{1F47A}" }], version: 1 }, ghost: { id: "ghost", name: "Ghost", keywords: ["halloween", "spooky", "scary"], skins: [{ unified: "1f47b", native: "\u{1F47B}" }], version: 1 }, alien: { id: "alien", name: "Alien", keywords: ["UFO", "paul", "weird", "outer", "space"], skins: [{ unified: "1f47d", native: "\u{1F47D}" }], version: 1 }, space_invader: { id: "space_invader", name: "Alien Monster", keywords: ["space", "invader", "game", "arcade", "play"], skins: [{ unified: "1f47e", native: "\u{1F47E}" }], version: 1 }, robot_face: { id: "robot_face", name: "Robot", keywords: ["face", "computer", "machine", "bot"], skins: [{ unified: "1f916", native: "\u{1F916}" }], version: 1 }, smiley_cat: { id: "smiley_cat", name: "Grinning Cat", keywords: ["smiley", "animal", "cats", "happy", "smile"], skins: [{ unified: "1f63a", native: "\u{1F63A}" }], version: 1 }, smile_cat: { id: "smile_cat", name: "Grinning Cat with Smiling Eyes", keywords: ["smile", "animal", "cats"], skins: [{ unified: "1f638", native: "\u{1F638}" }], version: 1 }, joy_cat: { id: "joy_cat", name: "Cat with Tears of Joy", keywords: ["animal", "cats", "haha", "happy"], skins: [{ unified: "1f639", native: "\u{1F639}" }], version: 1 }, heart_eyes_cat: { id: "heart_eyes_cat", name: "Smiling Cat with Heart-Eyes", keywords: ["heart", "eyes", "animal", "love", "like", "affection", "cats", "valentines"], skins: [{ unified: "1f63b", native: "\u{1F63B}" }], version: 1 }, smirk_cat: { id: "smirk_cat", name: "Cat with Wry Smile", keywords: ["smirk", "animal", "cats"], skins: [{ unified: "1f63c", native: "\u{1F63C}" }], version: 1 }
51763, kissing_cat: { id: "kissing_cat", name: "Kissing Cat", keywords: ["animal", "cats", "kiss"], skins: [{ unified: "1f63d", native: "\u{1F63D}" }], version: 1 }, scream_cat: { id: "scream_cat", name: "Weary Cat", keywords: ["scream", "animal", "cats", "munch", "scared"], skins: [{ unified: "1f640", native: "\u{1F640}" }], version: 1 }, crying_cat_face: { id: "crying_cat_face", name: "Crying Cat", keywords: ["face", "animal", "tears", "weep", "sad", "cats", "upset", "cry"], skins: [{ unified: "1f63f", native: "\u{1F63F}" }], version: 1 }, pouting_cat: { id: "pouting_cat", name: "Pouting Cat", keywords: ["animal", "cats"], skins: [{ unified: "1f63e", native: "\u{1F63E}" }], version: 1 }, see_no_evil: { id: "see_no_evil", name: "See-No-Evil Monkey", keywords: ["see", "no", "evil", "animal", "nature", "haha"], skins: [{ unified: "1f648", native: "\u{1F648}" }], version: 1 }, hear_no_evil: { id: "hear_no_evil", name: "Hear-No-Evil Monkey", keywords: ["hear", "no", "evil", "animal", "nature"], skins: [{ unified: "1f649", native: "\u{1F649}" }], version: 1 }, speak_no_evil: { id: "speak_no_evil", name: "Speak-No-Evil Monkey", keywords: ["speak", "no", "evil", "animal", "nature", "omg"], skins: [{ unified: "1f64a", native: "\u{1F64A}" }], version: 1 }, love_letter: { id: "love_letter", name: "Love Letter", keywords: ["email", "like", "affection", "envelope", "valentines"], skins: [{ unified: "1f48c", native: "\u{1F48C}" }], version: 1 }, cupid: { id: "cupid", name: "Heart with Arrow", keywords: ["cupid", "love", "like", "affection", "valentines"], skins: [{ unified: "1f498", native: "\u{1F498}" }], version: 1 }, gift_heart: { id: "gift_heart", name: "Heart with Ribbon", keywords: ["gift", "love", "valentines"], skins: [{ unified: "1f49d", native: "\u{1F49D}" }], version: 1 }, sparkling_heart: { id: "sparkling_heart", name: "Sparkling Heart", keywords: ["love", "like", "affection", "valentines"], skins: [{ unified: "1f496", native: "\u{1F496}" }], version: 1 }, heartpulse: { id: "heartpulse", name: "Growing Heart", keywords: ["heartpulse", "like", "love", "affection", "valentines", "pink"], skins: [{ unified: "1f497", native: "\u{1F497}" }], version: 1 }, heartbeat: { id: "heartbeat", name: "Beating Heart", keywords: ["heartbeat", "love", "like", "affection", "valentines", "pink"], skins: [{ unified: "1f493", native: "\u{1F493}" }], version: 1 }, revolving_hearts: { id: "revolving_hearts", name: "Revolving Hearts", keywords: ["love", "like", "affection", "valentines"], skins: [{ unified: "1f49e", native: "\u{1F49E}" }], version: 1 }, two_hearts: { id: "two_hearts", name: "Two Hearts", keywords: ["love", "like", "affection", "valentines", "heart"], skins: [{ unified: "1f495", native: "\u{1F495}" }], version: 1 }, heart_decoration: { id: "heart_decoration", name: "Heart Decoration", keywords: ["purple", "square", "love", "like"], skins: [{ unified: "1f49f", native: "\u{1F49F}" }], version: 1 }, heavy_heart_exclamation_mark_ornament: { id: "heavy_heart_exclamation_mark_ornament", name: "Heart Exclamation", keywords: ["heavy", "mark", "ornament", "decoration", "love"], skins: [{ unified: "2763-fe0f", native: "\u2763\uFE0F" }], version: 1 }, broken_heart: { id: "broken_heart", name: "Broken Heart", emoticons: ["</3"], keywords: ["sad", "sorry", "break", "heartbreak"], skins: [{ unified: "1f494", native: "\u{1F494}" }], version: 1 }, heart_on_fire: { id: "heart_on_fire", name: "Heart on Fire", keywords: ["passionate", "enthusiastic"], skins: [{ unified: "2764-fe0f-200d-1f525", native: "\u2764\uFE0F\u200D\u{1F525}" }], version: 13.1 }, mending_heart: { id: "mending_heart", name: "Mending Heart", keywords: ["broken", "bandage", "wounded"], skins: [{ unified: "2764-fe0f-200d-1fa79", native: "\u2764\uFE0F\u200D\u{1FA79}" }], version: 13.1 }, heart: { id: "heart", name: "Red Heart", emoticons: ["<3"], keywords: ["love", "like", "valentines"], skins: [{ unified: "2764-fe0f", native: "\u2764\uFE0F" }], version: 1 }, pink_heart: { id: "pink_heart", name: "Pink Heart", keywords: ["valentines"], skins: [{ unified: "1fa77", native: "\u{1FA77}" }], version: 15 }, orange_heart: { id: "orange_heart", name: "Orange Heart", keywords: ["love", "like", "affection", "valentines"], skins: [{ unified: "1f9e1", native: "\u{1F9E1}" }], version: 5 }, yellow_heart: { id: "yellow_heart", name: "Yellow Heart", emoticons: ["<3"], keywords: ["love", "like", "affection", "valentines"], skins: [{ unified: "1f49b", native: "\u{1F49B}" }], version: 1 }, green_heart: { id: "green_heart", name: "Green Heart", emoticons: ["<3"], keywords: ["love", "like", "affection", "valentines"], skins: [{ unified: "1f49a", native: "\u{1F49A}" }], version: 1 }, blue_heart: { id: "blue_heart", name: "Blue Heart", emoticons: ["<3"], keywords: ["love", "like", "affection", "valentines"], skins: [{ unified: "1f499", native: "\u{1F499}" }], version: 1 }, light_blue_heart: { id: "light_blue_heart", name: "Light Blue Heart", keywords: ["ice", "baby"], skins: [{ unified: "1fa75", native: "\u{1FA75}" }], version: 15 }, purple_heart: { id: "purple_heart", name: "Purple Heart", emoticons: ["<3"], keywords: ["love", "like", "affection", "valentines"], skins: [{ unified: "1f49c", native: "\u{1F49C}" }], version: 1 }, brown_heart: { id: "brown_heart", name: "Brown Heart", keywords: ["coffee"], skins: [{ unified: "1f90e", native: "\u{1F90E}" }], version: 12 }, black_heart: { id: "black_heart", name: "Black Heart", keywords: ["evil"], skins: [{ unified: "1f5a4", native: "\u{1F5A4}" }], version: 3 }, grey_heart: { id: "grey_heart", name: "Grey Heart", keywords: ["silver", "monochrome"], skins: [{ unified: "1fa76", native: "\u{1FA76}" }], version: 15 }, white_heart: { id: "white_heart", name: "White Heart", keywords: ["pure"], skins: [{ unified: "1f90d", native: "\u{1F90D}" }], version: 12 }, kiss: { id: "kiss", name: "Kiss Mark", keywords: ["face", "lips", "love", "like", "affection", "valentines"], skins: [{ unified: "1f48b", native: "\u{1F48B}" }], version: 1 }, anger: { id: "anger", name: "Anger Symbol", keywords: ["angry", "mad"], skins: [{ unified: "1f4a2", native: "\u{1F4A2}" }], version: 1 }, boom: { id: "boom", name: "Collision", keywords: ["boom", "bomb", "explode", "explosion", "blown"], skins: [{ unified: "1f4a5", native: "\u{1F4A5}" }], version: 1 }, dizzy: { id: "dizzy", name: "Dizzy", keywords: ["star", "sparkle", "shoot", "magic"], skins: [{ unified: "1f4ab", native: "\u{1F4AB}" }], version: 1 }, sweat_drops: { id: "sweat_drops", name: "Sweat Droplets", keywords: ["drops", "water", "drip", "oops"], skins: [{ unified: "1f4a6", native: "\u{1F4A6}" }], version: 1 }, dash: { id: "dash", name: "Dash Symbol", keywords: ["dashing", "away", "wind", "air", "fast", "shoo", "fart", "smoke", "puff"], skins: [{ unified: "1f4a8", native: "\u{1F4A8}" }], version: 1 }, hole: { id: "hole", name: "Hole", keywords: ["embarrassing"], skins: [{ unified: "1f573-fe0f", native: "\u{1F573}\uFE0F" }], version: 1 }, speech_balloon: { id: "speech_balloon", name: "Speech Balloon", keywords: ["bubble", "words", "message", "talk", "chatting"], skins: [{ unified: "1f4ac", native: "\u{1F4AC}" }], version: 1 }, "eye-in-speech-bubble": { id: "eye-in-speech-bubble", name: "Eye in Speech Bubble", keywords: ["in-speech-bubble", "info"], skins: [{ unified: "1f441-fe0f-200d-1f5e8-fe0f", native: "\u{1F441}\uFE0F\u200D\u{1F5E8}\uFE0F" }], version: 2 }, left_speech_bubble: { id: "left_speech_bubble", name: "Left Speech Bubble", keywords: ["words", "message", "talk", "chatting"], skins: [{ unified: "1f5e8-fe0f", native: "\u{1F5E8}\uFE0F" }], version: 2 }, right_anger_bubble: { id: "right_anger_bubble", name: "Right Anger Bubble", keywords: ["caption", "speech", "thinking", "mad"], skins: [{ unified: "1f5ef-fe0f", native: "\u{1F5EF}\uFE0F" }], version: 1 }, thought_balloon: { id: "thought_balloon", name: "Thought Balloon", keywords: ["bubble", "cloud", "speech", "thinking", "dream"], skins: [{ unified: "1f4ad", native: "\u{1F4AD}" }], version: 1 }, zzz: { id: "zzz", name: "Zzz", keywords: ["sleepy", "tired", "dream"], skins: [{ unified: "1f4a4", native: "\u{1F4A4}" }], version: 1 }, wave: { id: "wave", name: "Waving Hand", keywords: ["wave", "hands", "gesture", "goodbye", "solong", "farewell", "hello", "hi", "palm"], skins: [{ unified: "1f44b", native: "\u{1F44B}" }, { unified: "1f44b-1f3fb", native: "\u{1F44B}\u{1F3FB}" }, { unified: "1f44b-1f3fc", native: "\u{1F44B}\u{1F3FC}" }, { unified: "1f44b-1f3fd", native: "\u{1F44B}\u{1F3FD}" }, { unified: "1f44b-1f3fe", native: "\u{1F44B}\u{1F3FE}" }, { unified: "1f44b-1f3ff", native: "\u{1F44B}\u{1F3FF}" }], version: 1 }, raised_back_of_hand: { id: "raised_back_of_hand", name: "Raised Back of Hand", keywords: ["fingers", "backhand"], skins: [{ unified: "1f91a", native: "\u{1F91A}" }, { unified: "1f91a-1f3fb", native: "\u{1F91A}\u{1F3FB}" }, { unified: "1f91a-1f3fc", native: "\u{1F91A}\u{1F3FC}" }, { unified: "1f91a-1f3fd", native: "\u{1F91A}\u{1F3FD}" }, { unified: "1f91a-1f3fe", native: "\u{1F91A}\u{1F3FE}" }, { unified: "1f91a-1f3ff", native: "\u{1F91A}\u{1F3FF}" }], version: 3 }, raised_hand_with_fingers_splayed: { id: "raised_hand_with_fingers_splayed", name: "Hand with Fingers Splayed", keywords: ["raised", "palm"], skins: [{ unified: "1f590-fe0f", native: "\u{1F590}\uFE0F" }, { unified: "1f590-1f3fb", native: "\u{1F590}\u{1F3FB}" }, { unified: "1f590-1f3fc", native: "\u{1F590}\u{1F3FC}" }, { unified: "1f590-1f3fd", native: "\u{1F590}\u{1F3FD}" }, { unified: "1f590-1f3fe", native: "\u{1F590}\u{1F3FE}" }, { unified: "1f590-1f3ff", native: "\u{1F590}\u{1F3FF}" }], version: 1 }, hand: { id: "hand", name: "Raised Hand", keywords: ["fingers", "stop", "highfive", "high", "five", "palm", "ban"], skins: [{ unified: "270b", native: "\u270B" }, { unified: "270b-1f3fb", native: "\u270B\u{1F3FB}" }, { unified: "270b-1f3fc", native: "\u270B\u{1F3FC}" }, { unified: "270b-1f3fd", native: "\u270B\u{1F3FD}" }, { unified: "270b-1f3fe", native: "\u270B\u{1F3FE}" }, { unified: "270b-1f3ff", native: "\u270B\u{1F3FF}" }], version: 1 }, "spock-hand": { id: "spock-hand", name: "Vulcan Salute", keywords: ["spock", "hand", "fingers", "star", "trek"], skins: [{ unified: "1f596", native: "\u{1F596}" }, { unified: "1f596-1f3fb", native: "\u{1F596}\u{1F3FB}" }, { unified: "1f596-1f3fc", native: "\u{1F596}\u{1F3FC}" }, { unified: "1f596-1f3fd", native: "\u{1F596}\u{1F3FD}" }, { unified: "1f596-1f3fe", native: "\u{1F596}\u{1F3FE}" }, { unified: "1f596-1f3ff", native: "\u{1F596}\u{1F3FF}" }], version: 1 }, rightwards_hand: { id: "rightwards_hand", name: "Rightwards Hand", keywords: ["palm", "offer"], skins: [{ unified: "1faf1", native: "\u{1FAF1}" }, { unified: "1faf1-1f3fb", native: "\u{1FAF1}\u{1F3FB}" }, { unified: "1faf1-1f3fc", native: "\u{1FAF1}\u{1F3FC}" }, { unified: "1faf1-1f3fd", native: "\u{1FAF1}\u{1F3FD}" }, { unified: "1faf1-1f3fe", native: "\u{1FAF1}\u{1F3FE}" }, { unified: "1faf1-1f3ff", native: "\u{1FAF1}\u{1F3FF}" }], version: 14 }, leftwards_hand: { id: "leftwards_hand", name: "Leftwards Hand", keywords: ["palm", "offer"], skins: [{ unified: "1faf2", native: "\u{1FAF2}" }, { unified: "1faf2-1f3fb", native: "\u{1FAF2}\u{1F3FB}" }, { unified: "1faf2-1f3fc", native: "\u{1FAF2}\u{1F3FC}" }, { unified: "1faf2-1f3fd", native: "\u{1FAF2}\u{1F3FD}" }, { unified: "1faf2-1f3fe", native: "\u{1FAF2}\u{1F3FE}" }, { unified: "1faf2-1f3ff", native: "\u{1FAF2}\u{1F3FF}" }], version: 14 }, palm_down_hand: { id: "palm_down_hand", name: "Palm Down Hand", keywords: ["drop"], skins: [{ unified: "1faf3", native: "\u{1FAF3}" }, { unified: "1faf3-1f3fb", native: "\u{1FAF3}\u{1F3FB}" }, { unified: "1faf3-1f3fc", native: "\u{1FAF3}\u{1F3FC}" }, { unified: "1faf3-1f3fd", native: "\u{1FAF3}\u{1F3FD}" }, { unified: "1faf3-1f3fe", native: "\u{1FAF3}\u{1F3FE}" }, { unified: "1faf3-1f3ff", native: "\u{1FAF3}\u{1F3FF}" }], version: 14 }, palm_up_hand: { id: "palm_up_hand", name: "Palm Up Hand", keywords: ["lift", "offer", "demand"], skins: [{ unified: "1faf4", native: "\u{1FAF4}" }, { unified: "1faf4-1f3fb", native: "\u{1FAF4}\u{1F3FB}" }, { unified: "1faf4-1f3fc", native: "\u{1FAF4}\u{1F3FC}" }, { unified: "1faf4-1f3fd", native: "\u{1FAF4}\u{1F3FD}" }, { unified: "1faf4-1f3fe", native: "\u{1FAF4}\u{1F3FE}" }, { unified: "1faf4-1f3ff", native: "\u{1FAF4}\u{1F3FF}" }], version: 14 }, leftwards_pushing_hand: { id: "leftwards_pushing_hand", name: "Leftwards Pushing Hand", keywords: ["highfive", "high", "five", "pressing", "stop"], skins: [{ unified: "1faf7", native: "\u{1FAF7}" }, { unified: "1faf7-1f3fb", native: "\u{1FAF7}\u{1F3FB}" }, { unified: "1faf7-1f3fc", native: "\u{1FAF7}\u{1F3FC}" }, { unified: "1faf7-1f3fd", native: "\u{1FAF7}\u{1F3FD}" }, { unified: "1faf7-1f3fe", native: "\u{1FAF7}\u{1F3FE}" }, { unified: "1faf7-1f3ff", native: "\u{1FAF7}\u{1F3FF}" }], version: 15 }, rightwards_pushing_hand: { id: "rightwards_pushing_hand", name: "Rightwards Pushing Hand", keywords: ["highfive", "high", "five", "pressing", "stop"], skins: [{ unified: "1faf8", native: "\u{1FAF8}" }, { unified: "1faf8-1f3fb", native: "\u{1FAF8}\u{1F3FB}" }, { unified: "1faf8-1f3fc", native: "\u{1FAF8}\u{1F3FC}" }, { unified: "1faf8-1f3fd", native: "\u{1FAF8}\u{1F3FD}" }, { unified: "1faf8-1f3fe", native: "\u{1FAF8}\u{1F3FE}" }, { unified: "1faf8-1f3ff", native: "\u{1FAF8}\u{1F3FF}" }], version: 15 }, ok_hand: { id: "ok_hand", name: "Ok Hand", keywords: ["fingers", "limbs", "perfect", "okay"], skins: [{ unified: "1f44c", native: "\u{1F44C}" }, { unified: "1f44c-1f3fb", native: "\u{1F44C}\u{1F3FB}" }, { unified: "1f44c-1f3fc", native: "\u{1F44C}\u{1F3FC}" }, { unified: "1f44c-1f3fd", native: "\u{1F44C}\u{1F3FD}" }, { unified: "1f44c-1f3fe", native: "\u{1F44C}\u{1F3FE}" }, { unified: "1f44c-1f3ff", native: "\u{1F44C}\u{1F3FF}" }], version: 1 }, pinched_fingers: { id: "pinched_fingers", name: "Pinched Fingers", keywords: ["size", "tiny", "small"], skins: [{ unified: "1f90c", native: "\u{1F90C}" }, { unified: "1f90c-1f3fb", native: "\u{1F90C}\u{1F3FB}" }, { unified: "1f90c-1f3fc", native: "\u{1F90C}\u{1F3FC}" }, { unified: "1f90c-1f3fd", native: "\u{1F90C}\u{1F3FD}" }, { unified: "1f90c-1f3fe", native: "\u{1F90C}\u{1F3FE}" }, { unified: "1f90c-1f3ff", native: "\u{1F90C}\u{1F3FF}" }], version: 13 }, pinching_hand: { id: "pinching_hand", name: "Pinching Hand", keywords: ["tiny", "small", "size"], skins: [{ unified: "1f90f", native: "\u{1F90F}" }, { unified: "1f90f-1f3fb", native: "\u{1F90F}\u{1F3FB}" }, { unified: "1f90f-1f3fc", native: "\u{1F90F}\u{1F3FC}" }, { unified: "1f90f-1f3fd", native: "\u{1F90F}\u{1F3FD}" }, { unified: "1f90f-1f3fe", native: "\u{1F90F}\u{1F3FE}" }, { unified: "1f90f-1f3ff", native: "\u{1F90F}\u{1F3FF}" }], version: 12 }, v: { id: "v", name: "Victory Hand", keywords: ["v", "fingers", "ohyeah", "peace", "two"], skins: [{ unified: "270c-fe0f", native: "\u270C\uFE0F" }, { unified: "270c-1f3fb", native: "\u270C\u{1F3FB}" }, { unified: "270c-1f3fc", native: "\u270C\u{1F3FC}" }, { unified: "270c-1f3fd", native: "\u270C\u{1F3FD}" }, { unified: "270c-1f3fe", native: "\u270C\u{1F3FE}" }, { unified: "270c-1f3ff", native: "\u270C\u{1F3FF}" }], version: 1 }, crossed_fingers: { id: "crossed_fingers", name: "Crossed Fingers", keywords: ["hand", "with", "index", "and", "middle", "good", "lucky"], skins: [{ unified: "1f91e", native: "\u{1F91E}" }, { unified: "1f91e-1f3fb", native: "\u{1F91E}\u{1F3FB}" }, { unified: "1f91e-1f3fc", native: "\u{1F91E}\u{1F3FC}" }, { unified: "1f91e-1f3fd", native: "\u{1F91E}\u{1F3FD}" }, { unified: "1f91e-1f3fe", native: "\u{1F91E}\u{1F3FE}" }, { unified: "1f91e-1f3ff", native: "\u{1F91E}\u{1F3FF}" }], version: 3 }, hand_with_index_finger_and_thumb_crossed: { id: "hand_with_index_finger_and_thumb_crossed", name: "Hand with Index Finger and Thumb Crossed", keywords: ["heart", "love", "money", "expensive"], skins: [{ unified: "1faf0", native: "\u{1FAF0}" }, { unified: "1faf0-1f3fb", native: "\u{1FAF0}\u{1F3FB}" }, { unified: "1faf0-1f3fc", native: "\u{1FAF0}\u{1F3FC}" }, { unified: "1faf0-1f3fd", native: "\u{1FAF0}\u{1F3FD}" }, { unified: "1faf0-1f3fe", native: "\u{1FAF0}\u{1F3FE}" }, { unified: "1faf0-1f3ff", native: "\u{1FAF0}\u{1F3FF}" }], version: 14 }, i_love_you_hand_sign: { id: "i_love_you_hand_sign", name: "Love-You Gesture", keywords: ["i", "love", "you", "hand", "sign", "fingers"], skins: [{ unified: "1f91f", native: "\u{1F91F}" }, { unified: "1f91f-1f3fb", na
51763tive: "\u{1F91F}\u{1F3FB}" }, { unified: "1f91f-1f3fc", native: "\u{1F91F}\u{1F3FC}" }, { unified: "1f91f-1f3fd", native: "\u{1F91F}\u{1F3FD}" }, { unified: "1f91f-1f3fe", native: "\u{1F91F}\u{1F3FE}" }, { unified: "1f91f-1f3ff", native: "\u{1F91F}\u{1F3FF}" }], version: 5 }, the_horns: { id: "the_horns", name: "Sign of the Horns", keywords: ["hand", "fingers", "evil", "eye", "rock", "on"], skins: [{ unified: "1f918", native: "\u{1F918}" }, { unified: "1f918-1f3fb", native: "\u{1F918}\u{1F3FB}" }, { unified: "1f918-1f3fc", native: "\u{1F918}\u{1F3FC}" }, { unified: "1f918-1f3fd", native: "\u{1F918}\u{1F3FD}" }, { unified: "1f918-1f3fe", native: "\u{1F918}\u{1F3FE}" }, { unified: "1f918-1f3ff", native: "\u{1F918}\u{1F3FF}" }], version: 1 }, call_me_hand: { id: "call_me_hand", name: "Call Me Hand", keywords: ["hands", "gesture", "shaka"], skins: [{ unified: "1f919", native: "\u{1F919}" }, { unified: "1f919-1f3fb", native: "\u{1F919}\u{1F3FB}" }, { unified: "1f919-1f3fc", native: "\u{1F919}\u{1F3FC}" }, { unified: "1f919-1f3fd", native: "\u{1F919}\u{1F3FD}" }, { unified: "1f919-1f3fe", native: "\u{1F919}\u{1F3FE}" }, { unified: "1f919-1f3ff", native: "\u{1F919}\u{1F3FF}" }], version: 3 }, point_left: { id: "point_left", name: "Backhand Index Pointing Left", keywords: ["point", "direction", "fingers", "hand"], skins: [{ unified: "1f448", native: "\u{1F448}" }, { unified: "1f448-1f3fb", native: "\u{1F448}\u{1F3FB}" }, { unified: "1f448-1f3fc", native: "\u{1F448}\u{1F3FC}" }, { unified: "1f448-1f3fd", native: "\u{1F448}\u{1F3FD}" }, { unified: "1f448-1f3fe", native: "\u{1F448}\u{1F3FE}" }, { unified: "1f448-1f3ff", native: "\u{1F448}\u{1F3FF}" }], version: 1 }, point_right: { id: "point_right", name: "Backhand Index Pointing Right", keywords: ["point", "fingers", "hand", "direction"], skins: [{ unified: "1f449", native: "\u{1F449}" }, { unified: "1f449-1f3fb", native: "\u{1F449}\u{1F3FB}" }, { unified: "1f449-1f3fc", native: "\u{1F449}\u{1F3FC}" }, { unified: "1f449-1f3fd", native: "\u{1F449}\u{1F3FD}" }, { unified: "1f449-1f3fe", native: "\u{1F449}\u{1F3FE}" }, { unified: "1f449-1f3ff", native: "\u{1F449}\u{1F3FF}" }], version: 1 }, point_up_2: { id: "point_up_2", name: "Backhand Index Pointing Up", keywords: ["point", "2", "fingers", "hand", "direction"], skins: [{ unified: "1f446", native: "\u{1F446}" }, { unified: "1f446-1f3fb", native: "\u{1F446}\u{1F3FB}" }, { unified: "1f446-1f3fc", native: "\u{1F446}\u{1F3FC}" }, { unified: "1f446-1f3fd", native: "\u{1F446}\u{1F3FD}" }, { unified: "1f446-1f3fe", native: "\u{1F446}\u{1F3FE}" }, { unified: "1f446-1f3ff", native: "\u{1F446}\u{1F3FF}" }], version: 1 }, middle_finger: { id: "middle_finger", name: "Middle Finger", keywords: ["reversed", "hand", "with", "extended", "fingers", "rude", "flipping"], skins: [{ unified: "1f595", native: "\u{1F595}" }, { unified: "1f595-1f3fb", native: "\u{1F595}\u{1F3FB}" }, { unified: "1f595-1f3fc", native: "\u{1F595}\u{1F3FC}" }, { unified: "1f595-1f3fd", native: "\u{1F595}\u{1F3FD}" }, { unified: "1f595-1f3fe", native: "\u{1F595}\u{1F3FE}" }, { unified: "1f595-1f3ff", native: "\u{1F595}\u{1F3FF}" }], version: 1 }, point_down: { id: "point_down", name: "Backhand Index Pointing Down", keywords: ["point", "fingers", "hand", "direction"], skins: [{ unified: "1f447", native: "\u{1F447}" }, { unified: "1f447-1f3fb", native: "\u{1F447}\u{1F3FB}" }, { unified: "1f447-1f3fc", native: "\u{1F447}\u{1F3FC}" }, { unified: "1f447-1f3fd", native: "\u{1F447}\u{1F3FD}" }, { unified: "1f447-1f3fe", native: "\u{1F447}\u{1F3FE}" }, { unified: "1f447-1f3ff", native: "\u{1F447}\u{1F3FF}" }], version: 1 }, point_up: { id: "point_up", name: "Index Pointing Up", keywords: ["point", "hand", "fingers", "direction"], skins: [{ unified: "261d-fe0f", native: "\u261D\uFE0F" }, { unified: "261d-1f3fb", native: "\u261D\u{1F3FB}" }, { unified: "261d-1f3fc", native: "\u261D\u{1F3FC}" }, { unified: "261d-1f3fd", native: "\u261D\u{1F3FD}" }, { unified: "261d-1f3fe", native: "\u261D\u{1F3FE}" }, { unified: "261d-1f3ff", native: "\u261D\u{1F3FF}" }], version: 1 }, index_pointing_at_the_viewer: { id: "index_pointing_at_the_viewer", name: "Index Pointing at the Viewer", keywords: ["you", "recruit"], skins: [{ unified: "1faf5", native: "\u{1FAF5}" }, { unified: "1faf5-1f3fb", native: "\u{1FAF5}\u{1F3FB}" }, { unified: "1faf5-1f3fc", native: "\u{1FAF5}\u{1F3FC}" }, { unified: "1faf5-1f3fd", native: "\u{1FAF5}\u{1F3FD}" }, { unified: "1faf5-1f3fe", native: "\u{1FAF5}\u{1F3FE}" }, { unified: "1faf5-1f3ff", native: "\u{1FAF5}\u{1F3FF}" }], version: 14 }, "+1": { id: "+1", name: "Thumbs Up", keywords: ["+1", "thumbsup", "yes", "awesome", "good", "agree", "accept", "cool", "hand", "like"], skins: [{ unified: "1f44d", native: "\u{1F44D}" }, { unified: "1f44d-1f3fb", native: "\u{1F44D}\u{1F3FB}" }, { unified: "1f44d-1f3fc", native: "\u{1F44D}\u{1F3FC}" }, { unified: "1f44d-1f3fd", native: "\u{1F44D}\u{1F3FD}" }, { unified: "1f44d-1f3fe", native: "\u{1F44D}\u{1F3FE}" }, { unified: "1f44d-1f3ff", native: "\u{1F44D}\u{1F3FF}" }], version: 1 }, "-1": { id: "-1", name: "Thumbs Down", keywords: ["-1", "thumbsdown", "no", "dislike", "hand"], skins: [{ unified: "1f44e", native: "\u{1F44E}" }, { unified: "1f44e-1f3fb", native: "\u{1F44E}\u{1F3FB}" }, { unified: "1f44e-1f3fc", native: "\u{1F44E}\u{1F3FC}" }, { unified: "1f44e-1f3fd", native: "\u{1F44E}\u{1F3FD}" }, { unified: "1f44e-1f3fe", native: "\u{1F44E}\u{1F3FE}" }, { unified: "1f44e-1f3ff", native: "\u{1F44E}\u{1F3FF}" }], version: 1 }, fist: { id: "fist", name: "Raised Fist", keywords: ["fingers", "hand", "grasp"], skins: [{ unified: "270a", native: "\u270A" }, { unified: "270a-1f3fb", native: "\u270A\u{1F3FB}" }, { unified: "270a-1f3fc", native: "\u270A\u{1F3FC}" }, { unified: "270a-1f3fd", native: "\u270A\u{1F3FD}" }, { unified: "270a-1f3fe", native: "\u270A\u{1F3FE}" }, { unified: "270a-1f3ff", native: "\u270A\u{1F3FF}" }], version: 1 }, facepunch: { id: "facepunch", name: "Oncoming Fist", keywords: ["facepunch", "punch", "angry", "violence", "hit", "attack", "hand"], skins: [{ unified: "1f44a", native: "\u{1F44A}" }, { unified: "1f44a-1f3fb", native: "\u{1F44A}\u{1F3FB}" }, { unified: "1f44a-1f3fc", native: "\u{1F44A}\u{1F3FC}" }, { unified: "1f44a-1f3fd", native: "\u{1F44A}\u{1F3FD}" }, { unified: "1f44a-1f3fe", native: "\u{1F44A}\u{1F3FE}" }, { unified: "1f44a-1f3ff", native: "\u{1F44A}\u{1F3FF}" }], version: 1 }, "left-facing_fist": { id: "left-facing_fist", name: "Left-Facing Fist", keywords: ["left", "facing", "hand", "fistbump"], skins: [{ unified: "1f91b", native: "\u{1F91B}" }, { unified: "1f91b-1f3fb", native: "\u{1F91B}\u{1F3FB}" }, { unified: "1f91b-1f3fc", native: "\u{1F91B}\u{1F3FC}" }, { unified: "1f91b-1f3fd", native: "\u{1F91B}\u{1F3FD}" }, { unified: "1f91b-1f3fe", native: "\u{1F91B}\u{1F3FE}" }, { unified: "1f91b-1f3ff", native: "\u{1F91B}\u{1F3FF}" }], version: 3 }, "right-facing_fist": { id: "right-facing_fist", name: "Right-Facing Fist", keywords: ["right", "facing", "hand", "fistbump"], skins: [{ unified: "1f91c", native: "\u{1F91C}" }, { unified: "1f91c-1f3fb", native: "\u{1F91C}\u{1F3FB}" }, { unified: "1f91c-1f3fc", native: "\u{1F91C}\u{1F3FC}" }, { unified: "1f91c-1f3fd", native: "\u{1F91C}\u{1F3FD}" }, { unified: "1f91c-1f3fe", native: "\u{1F91C}\u{1F3FE}" }, { unified: "1f91c-1f3ff", native: "\u{1F91C}\u{1F3FF}" }], version: 3 }, clap: { id: "clap", name: "Clapping Hands", keywords: ["clap", "praise", "applause", "congrats", "yay"], skins: [{ unified: "1f44f", native: "\u{1F44F}" }, { unified: "1f44f-1f3fb", native: "\u{1F44F}\u{1F3FB}" }, { unified: "1f44f-1f3fc", native: "\u{1F44F}\u{1F3FC}" }, { unified: "1f44f-1f3fd", native: "\u{1F44F}\u{1F3FD}" }, { unified: "1f44f-1f3fe", native: "\u{1F44F}\u{1F3FE}" }, { unified: "1f44f-1f3ff", native: "\u{1F44F}\u{1F3FF}" }], version: 1 }, raised_hands: { id: "raised_hands", name: "Raising Hands", keywords: ["raised", "gesture", "hooray", "yea", "celebration"], skins: [{ unified: "1f64c", native: "\u{1F64C}" }, { unified: "1f64c-1f3fb", native: "\u{1F64C}\u{1F3FB}" }, { unified: "1f64c-1f3fc", native: "\u{1F64C}\u{1F3FC}" }, { unified: "1f64c-1f3fd", native: "\u{1F64C}\u{1F3FD}" }, { unified: "1f64c-1f3fe", native: "\u{1F64C}\u{1F3FE}" }, { unified: "1f64c-1f3ff", native: "\u{1F64C}\u{1F3FF}" }], version: 1 }, heart_hands: { id: "heart_hands", name: "Heart Hands", keywords: ["love", "appreciation", "support"], skins: [{ unified: "1faf6", native: "\u{1FAF6}" }, { unified: "1faf6-1f3fb", native: "\u{1FAF6}
51763\u{1F3FB}" }, { unified: "1faf6-1f3fc", native: "\u{1FAF6}\u{1F3FC}" }, { unified: "1faf6-1f3fd", native: "\u{1FAF6}\u{1F3FD}" }, { unified: "1faf6-1f3fe", native: "\u{1FAF6}\u{1F3FE}" }, { unified: "1faf6-1f3ff", native: "\u{1FAF6}\u{1F3FF}" }], version: 14 }, open_hands: { id: "open_hands", name: "Open Hands", keywords: ["fingers", "butterfly"], skins: [{ unified: "1f450", native: "\u{1F450}" }, { unified: "1f450-1f3fb", native: "\u{1F450}\u{1F3FB}" }, { unified: "1f450-1f3fc", native: "\u{1F450}\u{1F3FC}" }, { unified: "1f450-1f3fd", native: "\u{1F450}\u{1F3FD}" }, { unified: "1f450-1f3fe", native: "\u{1F450}\u{1F3FE}" }, { unified: "1f450-1f3ff", native: "\u{1F450}\u{1F3FF}" }], version: 1 }, palms_up_together: { id: "palms_up_together", name: "Palms Up Together", keywords: ["hands", "gesture", "cupped", "prayer"], skins: [{ unified: "1f932", native: "\u{1F932}" }, { unified: "1f932-1f3fb", native: "\u{1F932}\u{1F3FB}" }, { unified: "1f932-1f3fc", native: "\u{1F932}\u{1F3FC}" }, { unified: "1f932-1f3fd", native: "\u{1F932}\u{1F3FD}" }, { unified: "1f932-1f3fe", native: "\u{1F932}\u{1F3FE}" }, { unified: "1f932-1f3ff", native: "\u{1F932}\u{1F3FF}" }], version: 5 }, handshake: { id: "handshake", name: "Handshake", keywords: ["agreement", "shake"], skins: [{ unified: "1f91d", native: "\u{1F91D}" }, { unified: "1f91d-1f3fb", native: "\u{1F91D}\u{1F3FB}" }, { unified: "1f91d-1f3fc", native: "\u{1F91D}\u{1F3FC}" }, { unified: "1f91d-1f3fd", native: "\u{1F91D}\u{1F3FD}" }, { unified: "1f91d-1f3fe", native: "\u{1F91D}\u{1F3FE}" }, { unified: "1f91d-1f3ff", native: "\u{1F91D}\u{1F3FF}" }], version: 3 }, pray: { id: "pray", name: "Folded Hands", keywords: ["pray", "please", "hope", "wish", "namaste", "highfive", "high", "five", "thank", "you", "thanks", "appreciate"], skins: [{ unified: "1f64f", native: "\u{1F64F}" }, { unified: "1f64f-1f3fb", native: "\u{1F64F}\u{1F3FB}" }, { unified: "1f64f-1f3fc", native: "\u{1F64F}\u{1F3FC}" }, { unified: "1f64f-1f3fd", native: "\u{1F64F}\u{1F3FD}" }, { unified: "1f64f-1f3fe", native: "\u{1F64F}\u{1F3FE}" }, { unified: "1f64f-1f3ff", native: "\u{1F64F}\u{1F3FF}" }], version: 1 }, writing_hand: { id: "writing_hand", name: "Writing Hand", keywords: ["lower", "left", "ballpoint", "pen", "stationery", "write", "compose"], skins: [{ unified: "270d-fe0f", native: "\u270D\uFE0F" }, { unified: "270d-1f3fb", native: "\u270D\u{1F3FB}" }, { unified: "270d-1f3fc", native: "\u270D\u{1F3FC}" }, { unified: "270d-1f3fd", native: "\u270D\u{1F3FD}" }, { unified: "270d-1f3fe", native: "\u270D\u{1F3FE}" }, { unified: "270d-1f3ff", native: "\u270D\u{1F3FF}" }], version: 1 }, nail_care: { id: "nail_care", name: "Nail Polish", keywords: ["care", "beauty", "manicure", "finger", "fashion", "slay"], skins: [{ unified: "1f485", native: "\u{1F485}" }, { unified: "1f485-1f3fb", native: "\u{1F485}\u{1F3FB}" }, { unified: "1f485-1f3fc", native: "\u{1F485}\u{1F3FC}" }, { unified: "1f485-1f3fd", native: "\u{1F485}\u{1F3FD}" }, { unified: "1f485-1f3fe", native: "\u{1F485}\u{1F3FE}" }, { unified: "1f485-1f3ff", native: "\u{1F485}\u{1F3FF}" }], version: 1 }, selfie: { id: "selfie", name: "Selfie", keywords: ["camera", "phone"], skins: [{ unified: "1f933", native: "\u{1F933}" }, { unified: "1f933-1f3fb", native: "\u{1F933}\u{1F3FB}" }, { unified: "1f933-1f3fc", native: "\u{1F933}\u{1F3FC}" }, { unified: "1f933-1f3fd", native: "\u{1F933}\u{1F3FD}" }, { unified: "1f933-1f3fe", native: "\u{1F933}\u{1F3FE}" }, { unified: "1f933-1f3ff", native: "\u{1F933}\u{1F3FF}" }], version: 3 }, muscle: { id: "muscle", name: "Flexed Biceps", keywords: ["muscle", "arm", "flex", "hand", "summer", "strong"], skins: [{ unified: "1f4aa", native: "\u{1F4AA}" }, { unified: "1f4aa-1f3fb", native: "\u{1F4AA}\u{1F3FB}" }, { unified: "1f4aa-1f3fc", native: "\u{1F4AA}\u{1F3FC}" }, { unified: "1f4aa-1f3fd", native: "\u{1F4AA}\u{1F3FD}" }, { unified: "1f4aa-1f3fe", native: "\u{1F4AA}\u{1F3FE}" }, { unified: "1f4aa-1f3ff", native: "\u{1F4AA}\u{1F3FF}" }], version: 1 }, mechanical_arm: { id: "mechanical_arm", name: "Mechanical Arm", keywords: ["accessibility"], skins: [{ unified: "1f9be", native: "\u{1F9BE}" }], version: 12 }, mechanical_leg: { id: "mechanical_leg", name: "Mechanical Leg", keywords: ["accessibility"], skins: [{ unified: "1f9bf", native: "\u{1F9BF}" }], version: 12 }, leg: { id: "leg", name: "Leg", keywords: ["kick", "limb"], skins: [{ unified: "1f9b5", native: "\u{1F9B5}" }, { unified: "1f9b5-1f3fb", native: "\u{1F9B5}\u{1F3FB}" }, { unified: "1f9b5-1f3fc", native: "\u{1F9B5}\u{1F3FC}" }, { unified: "1f9b5-1f3fd", native: "\u{1F9B5}\u{1F3FD}" }, { unified: "1f9b5-1f3fe", native: "\u{1F9B5}\u{1F3FE}" }, { unified: "1f9b5-1f3ff", native: "\u{1F9B5}\u{1F3FF}" }], version: 11 }, foot: { id: "foot", name: "Foot", keywords: ["kick", "stomp"], skins: [{ unified: "1f9b6", native: "\u{1F9B6}" }, { unified: "1f9b6-1f3fb", native: "\u{1F9B6}\u{1F3FB}" }, { unified: "1f9b6-1f3fc", native: "\u{1F9B6}\u{1F3FC}" }, { unified: "1f9b6-1f3fd", native: "\u{1F9B6}\u{1F3FD}" }, { unified: "1f9b6-1f3fe", native: "\u{1F9B6}\u{1F3FE}" }, { unified: "1f9b6-1f3ff", native: "\u{1F9B6}\u{1F3FF}" }], version: 11 }, ear: { id: "ear", name: "Ear", keywords: ["face", "hear", "sound", "listen"], skins: [{ unified: "1f442", native: "\u{1F442}" }, { unified: "1f442-1f3fb", native: "\u{1F442}\u{1F3FB}" }, { unified: "1f442-1f3fc", native: "\u{1F442}\u{1F3FC}" }, { unified: "1f442-1f3fd", native: "\u{1F442}\u{1F3FD}" }, { unified: "1f442-1f3fe", native: "\u{1F442}\u{1F3FE}" }, { unified: "1f442-1f3ff", native: "\u{1F442}\u{1F3FF}" }], version: 1 }, ear_with_hearing_aid: { id: "ear_with_hearing_aid", name: "Ear with Hearing Aid", keywords: ["accessibility"], skins: [{ unified: "1f9bb", native: "\u{1F9BB}" }, { unified: "1f9bb-1f3fb", native: "\u{1F9BB}\u{1F3FB}" }, { unified: "1f9bb-1f3fc", native: "\u{1F9BB}\u{1F3FC}" }, { unified: "1f9bb-1f3fd", native: "\u{1F9BB}\u{1F3FD}" }, { unified: "1f9bb-1f3fe", native: "\u{1F9BB}\u{1F3FE}" }, { unified: "1f9bb-1f3ff", native: "\u{1F9BB}\u{1F3FF}" }], version: 12 }, nose: { id: "nose", name: "Nose", keywords: ["smell", "sniff"], skins: [{ unified: "1f443", native: "\u{1F443}" }, { unified: "1f443-1f3fb", native: "\u{1F443}\u{1F3FB}" }, { unified: "1f443-1f3fc", native: "\u{1F443}\u{1F3FC}" }, { unified: "1f443-1f3fd", native: "\u{1F443}\u{1F3FD}" }, { unified: "1f443-1f3fe", native: "\u{1F443}\u{1F3FE}" }, { unified: "1f443-1f3ff", native: "\u{1F443}\u{1F3FF}" }], version: 1 }, brain: { id: "brain", name: "Brain", keywords: ["smart", "intelligent"], skins: [{ unified: "1f9e0", native: "\u{1F9E0}" }], version: 5 }, anatomical_heart: { id: "anatomical_heart", name: "Anatomical Heart", keywords: ["health", "heartbeat"], skins: [{ unified: "1fac0", native: "\u{1FAC0}" }], version: 13 }, lungs: { id: "lungs", name: "Lungs", keywords: ["breathe"], skins: [{ unified: "1fac1", native: "\u{1FAC1}" }], version: 13 }, tooth: { id: "tooth", name: "Tooth", keywords: ["teeth", "dentist"], skins: [{ unified: "1f9b7", native: "\u{1F9B7}" }], version: 11 }, bone: { id: "bone", name: "Bone", keywords: ["skeleton"], skins: [{ unified: "1f9b4", native: "\u{1F9B4}" }], version: 11 }, eyes: { id: "eyes", name: "Eyes", keywords: ["look", "watch", "stalk", "peek", "see"], skins: [{ unified: "1f440", native: "\u{1F440}" }], version: 1 }, eye: { id: "eye", name: "Eye", keywords: ["face", "look", "see", "watch", "stare"], skins: [{ unified: "1f441-fe0f", native: "\u{1F441}\uFE0F" }], version: 1 }, tongue: { id: "tongue", name: "Tongue", keywords: ["mouth", "playful"], skins: [{ unified: "1f445", native: "\u{1F445}" }], version: 1 }, lips: { id: "lips", name: "Mouth", keywords: ["lips", "kiss"], skins: [{ unified: "1f444", native: "\u{1F444}" }], version: 1 }, biting_lip: { id: "biting_lip", name: "Biting Lip", keywords: ["flirt", "sexy", "pain", "worry"], skins: [{ unified: "1fae6", native: "\u{1FAE6}" }], version: 14 }, baby: { id: "baby", name: "Baby", keywords: ["child", "boy", "girl", "toddler"], skins: [{ unified: "1f476", native: "\u{1F476}" }, { unified: "1f476-1f3fb", native: "\u{1F476}\u{1F3FB}" }, { unified: "1f476-1f3fc", native: "\u{1F476}\u{1F3FC}" }, { unified: "1f476-1f3fd", native: "\u{1F476}\u{1F3FD}" }, { unified: "1f476-1f3fe", native: "\u{1F476}\u{1F3FE}" }, { unified: "1f476-1f3ff", native: "\u{1F476}\u{1F3FF}" }], version: 1 }, child: { id: "child", name: "Child", keywords: ["gender", "neutral", "young"], skins: [{ unified: "1f9d2", native: "\u{1F9D2}" }, { unified: "1f9d2-1f3fb", native: "\u{1F9D2}\u{1F3FB}" }, { unified: "1f9d2-1f3fc", native: "\u{1F9D2}\u{1F3FC}" }, { unified: "1f9d2-1f3fd", native: "\u{1F9D2}\u{1F3FD}" }, { unified: "1f9d2-1f3fe", native: "\u{1F9D2}\u{1F3FE}" }, { unified: "1f9d2-1f3ff", native: "\u{1F9D2}\u{1F3FF}" }], version: 5 }, boy: { id: "boy", name: "Boy", keywords: ["man", "male", "guy", "teenager"], skins: [{ unified: "1f466", native: "\u{1F466}" }, { unified: "1f466-1f3fb", native: "\u{1F466}\u{1F3FB}" }, { unified: "1f466-1f3fc", native: "\u{1F466}\u{1F3FC}" }, { unified: "1f466-1f3fd", native: "\u{1F466}\u{1F3FD}" }, { unified: "1f466-1f3fe", native: "\u{1F466}\u{1F3FE}" }, { unified: "1f466-1f3ff", native: "\u{1F466}\u{1F3FF}" }], version: 1 }, girl: { id: "girl", name: "Girl", keywords: ["female", "woman", "teenager"], skins: [{ unified: "1f467", native: "\u{1F467}" }, { unified: "1f467-1f3fb", native: "\u{1F467}\u{1F3FB}" }, { unified: "1f467-1f3fc", native: "\u{1F467}\u{1F3FC}" }, { unified: "1f467-1f3fd", native: "\u{1F467}\u{1F3FD}" }, { unified: "1f467-1f3fe", native: "\u{1F467}\u{1F3FE}" }, { unified: "1f467-1f3ff", native: "\u{1F467}\u{1F3FF}" }], version: 1 }, adult: { id: "adult", name: "Adult", keywords: ["person", "gender", "neutral"], skins: [{ unified: "1f9d1", native: "\u{1F9D1}" }, { unified: "1f9d1-1f3fb", native: "\u{1F9D1}\u{1F3FB}" }, { unified: "1f9d1-1f3fc", native: "\u{1F9D1}\u{1F3FC}" }, { unified: "1f9d1-1f3fd", native: "\u{1F9D1}\u{1F3FD}" }, { unified: "1f9d1-1f3fe", native: "\u{1F9D1}\u{1F3FE}" }, { unified: "1f9d1-1f3ff", native: "\u{1F9D1}\u{1F3FF}" }], version: 5 }, person_with_blond_hair: { id: "person_with_blond_hair", name: "Person Blond Hair", keywords: ["with", "hairstyle"], skins: [{ unified: "1f471", native: "\u{1F471}" }, { unified: "1f471-1f3fb", native: "\u{1F471}\u{1F3FB}" }, { unified: "1f471-1f3fc", native: "\u{1F471}\u{1F3FC}" }, { unified: "1f471-1f3fd", native: "\u{1F471}\u{1F3FD}" }, { unified: "1f471-1f3fe", native: "\u{1F471}\u{1F3FE}" }, { unified: "1f471-1f3ff", native: "\u{1F471}\u{1F3FF}" }], version: 1 }, man: { id: "man", name: "Man", keywords: ["mustache", "father", "dad", "guy", "classy", "sir", "moustache"], skins: [{ unified: "1f468", native: "\u{1F468}" }, { unified: "1f468-1f3fb", native: "\u{1F468}\u{1F3FB}" }, { unified: "1f468-1f3fc", native: "\u{1F468}\u{1F3FC}" }, { unified: "1f468-1f3fd", native: "\u{1F468}\u{1F3FD}" }, { unified: "1f468-1f3fe", native: "\u{1F468}\u{1F3FE}" }, { unified: "1f468-1f3ff", native: "\u{1F468}\u{1F3FF}" }], version: 1 }, bearded_person: { id: "bearded_person", name: "Person Beard", keywords: ["bearded", "man", "bewhiskered"], skins: [{ unified: "1f9d4", native: "\u{1F9D4}" }, { unified: "1f9d4-1f3fb", native: "\u{1F9D4}\u{1F3FB}" }, { unified: "1f9d4-1f3fc", native: "\u{1F9D4}\u{1F3FC}" }, { unified: "1f9d4-1f3fd", native: "\u{1F9D4}\u{1F3FD}" }, { unified: "1f9d4-1f3fe", native: "\u{1F9D4}\u{1F3FE}" }, { unified: "1f9d4-1f3ff", native: "\u{1F9D4}\u{1F3FF}" }], version: 5 }, man_with_beard: { id: "man_with_beard", name: "Man: Beard", keywords: ["man", "with", "facial", "hair"], skins: [{ unified: "1f9d4-200d-2642-fe0f", native: "\u{1F9D4}\u200D\u2642\uFE0F" }, { unified: "1f9d4-1f3fb-200d-2642-fe0f", native: "\u{1F9D4}\u{1F3FB}\u200D\u2642\uFE0F" }, { unified: "1f9d4-1f3fc-200d-2642-fe0f", native: "\u{1F9D4}\u{1F3FC}\u200D\u2642\uFE0F" }, { unified: "1f9d4-1f3fd-200d-2642-fe0f", native: "\u{1F9D4}\u{1F3FD}\u200D\u2642\uFE0F" }, { unified: "1f9d4-1f3fe-200d-2642-fe0f", native: "\u{1F9D4}\u{1F3FE}\u200D\u2642\uFE0F" }, { unified: "1f9d4-1f3ff-200d-2642-fe0f", native: "\u{1F9D4}\u{1F3FF}\u200D\u2642\uFE0F" }], version: 13.1 }, woman_with_beard: { id: "woman_with_beard", name: "Woman: Beard", keywords: ["woman", "with", "facial", "hair"], skins: [{ unified: "1f9d4-200d-2640-fe0f", native: "\u{1F9D4}\u200D\u2640\uFE0F" }, { unified: "1f9d4-1f3fb-200d-2640-fe0f", native: "\u{1F9D4}\u{1F3FB}\u200D\u2640\uFE0F" }, { unified: "1f9d4-1f3fc-200d-2640-fe0f", native: "\u{1F9D4}\u{1F3FC}\u200D\u2640\uFE0F" }, { unified: "1f9d4-1f3fd-200d-2640-fe0f", native: "\u{1F9D4}\u{1F3FD}\u200D\u2640\uFE0F" }, { unified: "1f9d4-1f3fe-200d-2640-fe0f", native: "\u{1F9D4}\u{1F3FE}\u200D\u2640\uFE0F" }, { unified: "1f9d4-1f3ff-200d-2640-fe0f", native: "\u{1F9D4}\u{1F3FF}\u200D\u2640\uFE0F" }], version: 13.1 }, red_haired_man: { id: "red_haired_man", name: "Man: Red Hair", keywords: ["haired", "man", "hairstyle"], skins: [{ unified: "1f468-200d-1f9b0", native: "\u{1F468}\u200D\u{1F9B0}" }, { unified: "1f468-1f3fb-200d-1f9b0", native: "\u{1F468}\u{1F3FB}\u200D\u{1F9B0}" }, { unified: "1f468-1f3fc-200d-1f9b0", native: "\u{1F468}\u{1F3FC}\u200D\u{1F9B0}" }, { unified: "1f468-1f3fd-200d-1f9b0", native: "\u{1F468}\u{1F3FD}\u200D\u{1F9B0}" }, { unified: "1f468-1f3fe-200d-1f9b0", native: "\u{1F468}\u{1F3FE}\u200D\u{1F9B0}" }, { unified: "1f468-1f3ff-200d-1f9b0", native: "\u{1F468}\u{1F3FF}\u200D\u{1F9B0}" }], version: 11 }, curly_haired_man: { id: "curly_haired_man", name: "Man: Curly Hair", keywords: ["haired", "man", "hairstyle"], skins: [{ unified: "1f468-200d-1f9b1", native: "\u{1F468}\u200D\u{1F9B1}" }, { unified: "1f468-1f3fb-200d-1f9b1", native: "\u{1F468}\u{1F3FB}\u200D\u{1F9B1}" }, { unified: "1f468-1f3fc-200d-1f9b1", native: "\u{1F468}\u{1F3FC}\u200D\u{1F9B1}" }, { unified: "1f468-1f3fd-200d-1f9b1", native: "\u{1F468}\u{1F3FD}\u200D\u{1F9B1}" }, { unified: "1f468-1f3fe-200d-1f9b1", native: "\u{1F468}\u{1F3FE}\u200D\u{1F9B1}" }, { unified: "1f468-1f3ff-200d-1f9b1", native: "\u{1F468}\u{1F3FF}\u200D\u{1F9B1}" }], version: 11 }, white_haired_man: { id: "white_haired_man", name: "Man: White Hair", keywords: ["haired", "man", "old", "elder"], skins: [{ unified: "1f468-200d-1f9b3", native: "\u{1F468}\u200D\u{1F9B3}" }, { unified: "1f468-1f3fb-200d-1f9b3", native: "\u{1F468}\u{1F3FB}\u200D\u{1F9B3}" }, { unified: "1f468-1f3fc-200d-1f9b3", native: "\u{1F468}\u{1F3FC}\u200D\u{1F9B3}" }, { unified: "1f468-1f3fd-200d-1f9b3", native: "\u{1F468}\u{1F3FD}\u200D\u{1F9B3}" }, { unified: "1f468-1f3fe-200d-1f9b3", native: "\u{1F468}\u{1F3FE}\u200D\u{1F9B3}" }, { unified: "1f468-1f3ff-200d-1f9b3", native: "\u{1F468}\u{1F3FF}\u200D\u{1F9B3}" }], version: 11 }, bald_man: { id: "bald_man", name: "Man: Bald", keywords: ["man", "hairless"], skins: [{ unified: "1f468-200d-1f9b2", native: "\u{1F468}\u200D\u{1F9B2}" }, { unified: "1f468-1f3fb-200d-1f9b2", native: "\u{1F468}\u{1F3FB}\u200D\u{1F9B2}" }, { unified: "1f468-1f3fc-200d-1f9b2", native: "\u{1F468}\u{1F3FC}\u200D\u{1F9B2}" }, { unified: "1f468-1f3fd-200d-1f9b2", native: "\u{1F468}\u{1F3FD}\u200D\u{1F9B2}" }, { unified: "1f468-1f3fe-200d-1f9b2", native: "\u{1F468}\u{1F3FE}\u200D\u{1F9B2}" }, { unified: "1f468-1f3ff-200d-1f9b2", native: "\u{1F468}\u{1F3FF}\u200D\u{1F9B2}" }], version: 11 }, woman: { id: "woman", name: "Woman", keywords: ["female", "girls", "lady"], skins: [{ unified: "1f469", native: "\u{1F469}" }, { unified: "1f469-1f3fb", native: "\u{1F469}\u{1F3FB}" }, { unified: "1f469-1f3fc", native: "\u{1F469}\u{1F3FC}" }, { unified: "1f469-1f3fd", native: "\u{1F469}\u{1F3FD}" }, { unified: "1f469-1f3fe", native: "\u{1F469}\u{1F3FE}" }, { unified: "1f469-1f3ff", native: "\u{1F469}\u{1F3FF}" }], version: 1 }, red_haired_woman: { id: "red_haired_woman", name: "Woman: Red Hair", keywords: ["haired", "woman", "hairstyle"], skins: [{ unified: "1f469-200d-1f9b0", native: "\u{1F469}\u200D\u{1F9B0}" }, { unified: "1f469-1f3fb-200d-1f9b0", native: "\u{1F469}\u{1F3FB}\u200D\u{1F9B0}" }, { unified: "1f469-1f3fc-200d-1f9b0", native: "\u{1F469}\u{1F3FC}\u200D\u{1F9B0}" }, { unified: "1f469-1f3fd-200d-1f9b0", native: "\u{1F469}\u{1F3FD}\u200D\u{1F9B0}" }, { unified: "1f469-1f3fe-200d-1f9b0", native: "\u{1F469}\u{1F3FE}\u200D\u{1F9B0}" }, { unified: "1f469-1f3ff-200d-1f9b0", native: "\u{1F469}\u{1F3FF}\u200D\u{1F9B0}" }], version: 11 }, red_haired_person: { id: "red_h
51763aired_person", name: "Person: Red Hair", keywords: ["haired", "person", "hairstyle"], skins: [{ unified: "1f9d1-200d-1f9b0", native: "\u{1F9D1}\u200D\u{1F9B0}" }, { unified: "1f9d1-1f3fb-200d-1f9b0", native: "\u{1F9D1}\u{1F3FB}\u200D\u{1F9B0}" }, { unified: "1f9d1-1f3fc-200d-1f9b0", native: "\u{1F9D1}\u{1F3FC}\u200D\u{1F9B0}" }, { unified: "1f9d1-1f3fd-200d-1f9b0", native: "\u{1F9D1}\u{1F3FD}\u200D\u{1F9B0}" }, { unified: "1f9d1-1f3fe-200d-1f9b0", native: "\u{1F9D1}\u{1F3FE}\u200D\u{1F9B0}" }, { unified: "1f9d1-1f3ff-200d-1f9b0", native: "\u{1F9D1}\u{1F3FF}\u200D\u{1F9B0}" }], version: 12.1 }, curly_haired_woman: { id: "curly_haired_woman", name: "Woman: Curly Hair", keywords: ["haired", "woman", "hairstyle"], skins: [{ unified: "1f469-200d-1f9b1", native: "\u{1F469}\u200D\u{1F9B1}" }, { unified: "1f469-1f3fb-200d-1f9b1", native: "\u{1F469}\u{1F3FB}\u200D\u{1F9B1}" }, { unified: "1f469-1f3fc-200d-1f9b1", native: "\u{1F469}\u{1F3FC}\u200D\u{1F9B1}" }, { unified: "1f469-1f3fd-200d-1f9b1", native: "\u{1F469}\u{1F3FD}\u200D\u{1F9B1}" }, { unified: "1f469-1f3fe-200d-1f9b1", native: "\u{1F469}\u{1F3FE}\u200D\u{1F9B1}" }, { unified: "1f469-1f3ff-200d-1f9b1", native: "\u{1F469}\u{1F3FF}\u200D\u{1F9B1}" }], version: 11 }, curly_haired_person: { id: "curly_haired_person", name: "Person: Curly Hair", keywords: ["haired", "person", "hairstyle"], skins: [{ unified: "1f9d1-200d-1f9b1", native: "\u{1F9D1}\u200D\u{1F9B1}" }, { unified: "1f9d1-1f3fb-200d-1f9b1", native: "\u{1F9D1}\u{1F3FB}\u200D\u{1F9B1}" }, { unified: "1f9d1-1f3fc-200d-1f9b1", native: "\u{1F9D1}\u{1F3FC}\u200D\u{1F9B1}" }, { unified: "1f9d1-1f3fd-200d-1f9b1", native: "\u{1F9D1}\u{1F3FD}\u200D\u{1F9B1}" }, { unified: "1f9d1-1f3fe-200d-1f9b1", native: "\u{1F9D1}\u{1F3FE}\u200D\u{1F9B1}" }, { unified: "1f9d1-1f3ff-200d-1f9b1", native: "\u{1F9D1}\u{1F3FF}\u200D\u{1F9B1}" }], version: 12.1 }, white_haired_woman: { id: "white_haired_woman", name: "Woman: White Hair", keywords: ["haired", "woman", "old", "elder"], skins: [{ unified: "1f469-200d-1f9b3", native: "\u{1F469}\u200D\u{1F9B3}" }, { unified: "1f469-1f3fb-200d-1f9b3", native: "\u{1F469}\u{1F3FB}\u200D\u{1F9B3}" }, { unified: "1f469-1f3fc-200d-1f9b3", native: "\u{1F469}\u{1F3FC}\u200D\u{1F9B3}" }, { unified: "1f469-1f3fd-200d-1f9b3", native: "\u{1F469}\u{1F3FD}\u200D\u{1F9B3}" }, { unified: "1f469-1f3fe-200d-1f9b3", native: "\u{1F469}\u{1F3FE}\u200D\u{1F9B3}" }, { unified: "1f469-1f3ff-200d-1f9b3", native: "\u{1F469}\u{1F3FF}\u200D\u{1F9B3}" }], version: 11 }, white_haired_person: { id: "white_haired_person", name: "Person: White Hair", keywords: ["haired", "person", "elder", "old"], skins: [{ unified: "1f9d1-200d-1f9b3", native: "\u{1F9D1}\u200D\u{1F9B3}" }, { unified: "1f9d1-1f3fb-200d-1f9b3", native: "\u{1F9D1}\u{1F3FB}\u200D\u{1F9B3}" }, { unified: "1f9d1-1f3fc-200d-1f9b3", native: "\u{1F9D1}\u{1F3FC}\u200D\u{1F9B3}" }, { unified: "1f9d1-1f3fd-200d-1f9b3", native: "\u{1F9D1}\u{1F3FD}\u200D\u{1F9B3}" }, { unified: "1f9d1-1f3fe-200d-1f9b3", native: "\u{1F9D1}\u{1F3FE}\u200D\u{1F9B3}" }, { unified: "1f9d1-1f3ff-200d-1f9b3", native: "\u{1F9D1}\u{1F3FF}\u200D\u{1F9B3}" }], version: 12.1 }, bald_woman: { id: "bald_woman", name: "Woman: Bald", keywords: ["woman", "hairless"], skins: [{ unified: "1f469-200d-1f9b2", native: "\u{1F469}\u200D\u{1F9B2}" }, { unified: "1f469-1f3fb-200d-1f9b2", native: "\u{1F469}\u{1F3FB}\u200D\u{1F9B2}" }, { unified: "1f469-1f3fc-200d-1f9b2", native: "\u{1F469}\u{1F3FC}\u200D\u{1F9B2}" }, { unified: "1f469-1f3fd-200d-1f9b2", native: "\u{1F469}\u{1F3FD}\u200D\u{1F9B2}" }, { unified: "1f469-1f3fe-200d-1f9b2", native: "\u{1F469}\u{1F3FE}\u200D\u{1F9B2}" }, { unified: "1f469-1f3ff-200d-1f9b2", native: "\u{1F469}\u{1F3FF}\u200D\u{1F9B2}" }], version: 11 }, bald_person: { id: "bald_person", name: "Person: Bald", keywords: ["person", "hairless"], skins: [{ unified: "1f9d1-200d-1f9b2", native: "\u{1F9D1}\u200D\u{1F9B2}" }, { unified: "1f9d1-1f3fb-200d-1f9b2", native: "\u{1F9D1}\u{1F3FB}\u200D\u{1F9B2}" }, { unified: "1f9d1-1f3fc-200d-1f9b2", native: "\u{1F9D1}\u{1F3FC}\u200D\u{1F9B2}" }, { unified: "1f9d1-1f3fd-200d-1f9b2", native: "\u{1F9D1}\u{1F3FD}\u200D\u{1F9B2}" }, { unified: "1f9d1-1f3fe-200d-1f9b2", native: "\u{1F9D1}\u{1F3FE}\u200D\u{1F9B2}" }, { unified: "1f9d1-1f3ff-200d-1f9b2", native: "\u{1F9D1}\u{1F3FF}\u200D\u{1F9B2}" }], version: 12.1 }, "blond-haired-woman": { id: "blond-haired-woman", name: "Woman: Blond Hair", keywords: ["haired-woman", "woman", "female", "girl", "blonde", "person"], skins: [{ unified: "1f471-200d-2640-fe0f", native: "\u{1F471}\u200D\u2640\uFE0F" }, { unified: "1f471-1f3fb-200d-2640-fe0f", native: "\u{1F471}\u{1F3FB}\u200D\u2640\uFE0F" }, { unified: "1f471-1f3fc-200d-2640-fe0f", native: "\u{1F471}\u{1F3FC}\u200D\u2640\uFE0F" }, { unified: "1f471-1f3fd-200d-2640-fe0f", native: "\u{1F471}\u{1F3FD}\u200D\u2640\uFE0F" }, { unified: "1f471-1f3fe-200d-2640-fe0f", native: "\u{1F471}\u{1F3FE}\u200D\u2640\uFE0F" }, { unified: "1f471-1f3ff-200d-2640-fe0f", native: "\u{1F471}\u{1F3FF}\u200D\u2640\uFE0F" }], version: 4 }, "blond-haired-man": { id: "blond-haired-man", name: "Man: Blond Hair", keywords: ["haired-man", "man", "male", "boy", "blonde", "guy", "person"], skins: [{ unified: "1f471-200d-2642-fe0f", native: "\u{1F471}\u200D\u2642\uFE0F" }, { unified: "1f471-1f3fb-200d-2642-fe0f", native: "\u{1F471}\u{1F3FB}\u200D\u2642\uFE0F" }, { unified: "1f471-1f3fc-200d-2642-fe0f", native: "\u{1F471}\u{1F3FC}\u200D\u2642\uFE0F" }, { unified: "1f471-1f3fd-200d-2642-fe0f", native: "\u{1F471}\u{1F3FD}\u200D\u2642\uFE0F" }, { unified: "1f471-1f3fe-200d-2642-fe0f", native: "\u{1F471}\u{1F3FE}\u200D\u2642\uFE0F" }, { unified: "1f471-1f3ff-200d-2642-fe0f", native: "\u{1F471}\u{1F3FF}\u200D\u2642\uFE0F" }], version: 4 }, older_adult: { id: "older_adult", name: "Older Adult", keywords: ["person", "human", "elder", "senior", "gender", "neutral"], skins: [{ unified: "1f9d3", native: "\u{1F9D3}" }, { unified: "1f9d3-1f3fb", native: "\u{1F9D3}\u{1F3FB}" }, { unified: "1f9d3-1f3fc", native: "\u{1F9D3}\u{1F3FC}" }, { unified: "1f9d3-1f3fd", native: "\u{1F9D3}\u{1F3FD}" }, { unified: "1f9d3-1f3fe", native: "\u{1F9D3}\u{1F3FE}" }, { unified: "1f9d3-1f3ff", native: "\u{1F9D3}\u{1F3FF}" }], version: 5 }, older_man: { id: "older_man", name: "Old Man", keywords: ["older", "human", "male", "men", "elder", "senior"], skins: [{ unified: "1f474", native: "\u{1F474}" }, { unified: "1f474-1f3fb", native: "\u{1F474}\u{1F3FB}" }, { unified: "1f474-1f3fc", native: "\u{1F474}\u{1F3FC}" }, { unified: "1f474-1f3fd", native: "\u{1F474}\u{1F3FD}" }, { unified: "1f474-1f3fe", native: "\u{1F474}\u{1F3FE}" }, { unified: "1f474-1f3ff", native: "\u{1F474}\u{1F3FF}" }], version: 1 }, older_woman: { id: "older_woman", name: "Old Woman", keywords: ["older", "human", "female", "women", "lady", "elder", "senior"], skins: [{ unified: "1f475", native: "\u{1F475}" }, { unified: "1f475-1f3fb", native: "\u{1F475}\u{1F3FB}" }, { unified: "1f475-1f3fc", native: "\u{1F475}\u{1F3FC}" }, { unified: "1f475-1f3fd", native: "\u{1F475}\u{1F3FD}" }, { unified: "1f475-1f3fe", native: "\u{1F475}\u{1F3FE}" }, { unified: "1f475-1f3ff", native: "\u{1F475}\u{1F3FF}" }], version: 1 }, person_frowning: { id: "person_frowning", name: "Person Frowning", keywords: ["worried"], skins: [{ unified: "1f64d", native: "\u{1F64D}" }, { unified: "1f64d-1f3fb", native: "\u{1F64D}\u{1F3FB}" }, { unified: "1f64d-1f3fc", native: "\u{1F64D}\u{1F3FC}" }, { unified: "1f64d-1f3fd", native: "\u{1F64D}\u{1F3FD}" }, { unified: "1f64d-1f3fe", native: "\u{1F64D}\u{1F3FE}" }, { unified: "1f64d-1f3ff", native: "\u{1F64D}\u{1F3FF}" }], version: 1 }, "man-frowning": { id: "man-frowning", name: "Man Frowning", keywords: ["male", "boy", "sad", "depressed", "discouraged", "unhappy"], skins: [{ unified: "1f64d-200d-2642-fe0f", native: "\u{1F64D}\u200D\u2642\uFE0F" }, { unified: "1f64d-1f3fb-200d-2642-fe0f", native: "\u{1F64D}\u{1F3FB}\u200D\u2642\uFE0F" }, { unified: "1f64d-1f3fc-200d-2642-fe0f", native: "\u{1F64D}\u{1F3FC}\u200D\u2642\uFE0F" }, { unified: "1f64d-1f3fd-200d-2642-fe0f", native: "\u{1F64D}\u{1F3FD}\u200D\u2642\uFE0F" }, { unified: "1f64d-1f3fe-200d-2642-fe0f", native: "\u{1F64D}\u{1F3FE}\u200D\u2642\uFE0F" }, { unified: "1f64d-1f3ff-200d-2642-fe0f", native: "\u{1F64D}\u{1F3FF}\u200D\u2642\uFE0F" }], version: 4 }, "woman-frowning": { id: "woman-frowning", name: "Woman Frowning", keywords: ["female", "girl", "sad", "depressed", "discouraged", "unhappy"], skins: [{ unified: "1f64d-200d-2640-fe0f", native: "\u{1F64D}\u200D\u2640\uFE0F" }, { unified: "1f64d-1f3fb-200d-2640-fe0f", native: "\u{1F64D}\u{1F3FB}\u200D\u2640\uFE0F" }, { unified: "1f64d-1f3fc-200d-2640-fe0f", native: "\u{1F64D}\u{1F3FC}\u200D\u2640\uFE0F" }, { unified: "1f64d-1f3fd-200d-2640-fe0f", native: "\u{1F64D}\u{1F3FD}\u200D\u2640\uFE0F" }, { unified: "1f64d-1f3fe-200d-2640-fe0f", native: "\u{1F64D}\u{1F3FE}\u200D\u2640\uFE0F" }, { unified: "1f64d-1f3ff-200d-2640-fe0f", native: "\u{1F64D}\u{1F3FF}\u200D\u2640\uFE0F" }], version: 4 }, person_with_pouting_face: { id: "person_with_pouting_face", name: "Person Pouting", keywords: ["with", "face", "upset"], skins: [{ unified: "1f64e", native: "\u{1F64E}" }, { unified: "1f64e-1f3fb", native: "\u{1F64E}\u{1F3FB}" }, { unified: "1f64e-1f3fc", native: "\u{1F64E}\u{1F3FC}" }, { unified: "1f64e-1f3fd", native: "\u{1F64E}\u{1F3FD}" }, { unified: "1f64e-1f3fe", native: "\u{1F64E}\u{1F3FE}" }, { unified: "1f64e-1f3ff", native: "\u{1F64E}\u{1F3FF}" }], version: 1 }, "man-pouting": { id: "man-pouting", name: "Man Pouting", keywords: ["male", "boy"], skins: [{ unified: "1f64e-200d-2642-fe0f", native: "\u{1F64E}\u200D\u2642\uFE0F" }, { unified: "1f64e-1f3fb-200d-2642-fe0f", native: "\u{1F64E}\u{1F3FB}\u200D\u2642\uFE0F" }, { unified: "1f64e-1f3fc-200d-2642-fe0f", native: "\u{1F64E}\u{1F3FC}\u200D\u2642\uFE0F" }, { unified: "1f64e-1f3fd-200d-2642-fe0f", native: "\u{1F64E}\u{1F3FD}\u200D\u2642\uFE0F" }, { unified: "1f64e-1f3fe-200d-2642-fe0f", native: "\u{1F64E}\u{1F3FE}\u200D\u2642\uFE0F" }, { unified: "1f64e-1f3ff-200d-2642-fe0f", native: "\u{1F64E}\u{1F3FF}\u200D\u2642\uFE0F" }], version: 4 }, "woman-pouting": { id: "woman-pouting", name: "Woman Pouting", keywords: ["female", "girl"], skins: [{ unified: "1f64e-200d-2640-fe0f", native: "\u{1F64E}\u200D\u2640\uFE0F" }, { unified: "1f64e-1f3fb-200d-2640-fe0f", native: "\u{1F64E}\u{1F3FB}\u200D\u2640\uFE0F" }, { unified: "1f64e-1f3fc-200d-2640-fe0f", native: "\u{1F64E}\u{1F3FC}\u200D\u2640\uFE0F" }, { unified: "1f64e-1f3fd-200d-2640-fe0f", native: "\u{1F64E}\u{1F3FD}\u200D\u2640\uFE0F" }, { unified: "1f64e-1f3fe-200d-2640-fe0f", native: "\u{1F64E}\u{1F3FE}\u200D\u2640\uFE0F" }, { unified: "1f64e-1f3ff-200d-2640-fe0f", native: "\u{1F64E}\u{1F3FF}\u200D\u2640\uFE0F" }], version: 4 }, no_good: { id: "no_good", name: "Person Gesturing No", keywords: ["good", "decline"], skins: [{ unified: "1f645", native: "\u{1F645}" }, { unified: "1f645-1f3fb", native: "\u{1F645}\u{1F3FB}" }, { unified: "1f645-1f3fc", native: "\u{1F645}\u{1F3FC}" }, { unified: "1f645-1f3fd", native: "\u{1F645}\u{1F3FD}" }, { unified: "1f645-1f3fe", native: "\u{1F645}\u{1F3FE}" }, { unified: "1f645-1f3ff", native: "\u{1F645}\u{1F3FF}" }], version: 1 }, "man-gesturing-no": { id: "man-gesturing-no", name: "Man Gesturing No", keywords: ["gesturing-no", "male", "boy", "nope"], skins: [{ unified: "1f645-200d-2642-fe0f", native: "\u{1F645}\u200D\u2642\uFE0F" }, { unified: "1f645-1f3fb-200d-2642-fe0f", native: "\u{1F645}\u{1F3FB}\u200D\u2642\uFE0F" }, { unified: "1f645-1f3fc-200d-2642-fe0f", native: "\u{1F645}\u{1F3FC}\u200D\u2642\uFE0F" }, { unified: "1f645-1f3fd-200d-2642-fe0f", native: "\u{1F645}\u{1F3FD}\u200D\u2642\uFE0F" }, { unified: "1f645-1f3fe-200d-2642-fe0f", native: "\u{1F645}\u{1F3FE}\u200D\u2642\uFE0F" }, { unified: "1f645-1f3ff-200d-2642-fe0f", native: "\u{1F645}\u{1F3FF}\u200D\u2642\uFE0F" }], version: 4 }, "woman-gesturing-no": { id: "woman-gesturing-no", name: "Woman Gesturing No", keywords: ["gesturing-no", "female", "girl", "nope"], skins: [{ unified: "1f645-200d-2640-fe0f", native: "\u{1F645}\u200D\u2640\uFE0F" }, { unified: "1f645-1f3fb-200d-2640-fe0f", native: "\u{1F645}\u{1F3FB}\u200D\u2640\uFE0F" }, { unified: "1f645-1f3fc-200d-2640-fe0f", native: "\u{1F645}\u{1F3FC}\u200D\u2640\uFE0F" }, { unified: "1f645-1f3fd-200d-2640-fe0f", native: "\u{1F645}\u{1F3FD}\u200D\u2640\uFE0F" }, { unified: "1f645-1f3fe-200d-2640-fe0f", native: "\u{1F645}\u{1F3FE}\u200D\u2640\uFE0F" }, { unified: "1f645-1f3ff-200d-2640-fe0f", native: "\u{1F645}\u{1F3FF}\u200D\u2640\uFE0F" }], version: 4 }, ok_woman: { id: "ok_woman", name: "Person Gesturing Ok", keywords: ["woman", "agree"], skins: [{ unified: "1f646", native: "\u{1F646}" }, { unified: "1f646-1f3fb", native: "\u{1F646}\u{1F3FB}" }, { unified: "1f646-1f3fc", native: "\u{1F646}\u{1F3FC}" }, { unified: "1f646-1f3fd", native: "\u{1F646}\u{1F3FD}" }, { unified: "1f646-1f3fe", native: "\u{1F646}\u{1F3FE}" }, { unified: "1f646-1f3ff", native: "\u{1F646}\u{1F3FF}" }], version: 1 }, "man-gesturing-ok": { id: "man-gesturing-ok", name: "Man Gesturing Ok", keywords: ["gesturing-ok", "men", "boy", "male", "blue", "human"], skins: [{ unified: "1f646-200d-2642-fe0f", native: "\u{1F646}\u200D\u2642\uFE0F" }, { unified: "1f646-1f3fb-200d-2642-fe0f", native: "\u{1F646}\u{1F3FB}\u200D\u2642\uFE0F" }, { unified: "1f646-1f3fc-200d-2642-fe0f", native: "\u{1F646}\u{1F3FC}\u200D\u2642\uFE0F" }, { unified: "1f646-1f3fd-200d-2642-fe0f", native: "\u{1F646}\u{1F3FD}\u200D\u2642\uFE0F" }, { unified: "1f646-1f3fe-200d-2642-fe0f", native: "\u{1F646}\u{1F3FE}\u200D\u2642\uFE0F" }, { unified: "1f646-1f3ff-200d-2642-fe0f", native: "\u{1F646}\u{1F3FF}\u200D\u2642\uFE0F" }], version: 4 }, "woman-gesturing-ok": { id: "woman-gesturing-ok", name: "Woman Gesturing Ok", keywords: ["gesturing-ok", "women", "girl", "female", "pink", "human"], skins: [{ unified: "1f646-200d-2640-fe0f", native: "\u{1F646}\u200D\u2640\uFE0F" }, { unified: "1f646-1f3fb-200d-2640-fe0f", native: "\u{1F646}\u{1F3FB}\u200D\u2640\uFE0F" }, { unified: "1f646-1f3fc-200d-2640-fe0f", native: "\u{1F646}\u{1F3FC}\u200D\u2640\uFE0F" }, { unified: "1f646-1f3fd-200d-2640-fe0f", native: "\u{1F646}\u{1F3FD}\u200D\u2640\uFE0F" }, { unified: "1f646-1f3fe-200d-2640-fe0f", native: "\u{1F646}\u{1F3FE}\u200D\u2640\uFE0F" }, { unified: "1f646-1f3ff-200d-2640-fe0f", native: "\u{1F646}\u{1F3FF}\u200D\u2640\uFE0F" }], version: 4 }, information_desk_person: { id: "information_desk_person", name: "Person Tipping Hand", keywords: ["information", "desk"], skins: [{ unified: "1f481", native: "\u{1F481}" }, { unified: "1f481-1f3fb", native: "\u{1F481}\u{1F3FB}" }, { unified: "1f481-1f3fc", native: "\u{1F481}\u{1F3FC}" }, { unified: "1f481-1f3fd", native: "\u{1F481}\u{1F3FD}" }, { unified: "1f481-1f3fe", native: "\u{1F481}\u{1F3FE}" }, { unified: "1f481-1f3ff", native: "\u{1F481}\u{1F3FF}" }], version: 1 }, "man-tipping-hand": { id: "man-tipping-hand", name: "Man Tipping Hand", keywords: ["tipping-hand", "male", "boy", "human", "information"], skins: [{ unified: "1f481-200d-2642-fe0f", native: "\u{1F481}\u200D\u2642\uFE0F" }, { unified: "1f481-1f3fb-200d-2642-fe0f", native: "\u{1F481}\u{1F3FB}\u200D\u2642\uFE0F" }, { unified: "1f481-1f3fc-200d-2642-fe0f", native: "\u{1F481}\u{1F3FC}\u200D\u2642\uFE0F" }, { unified: "1f481-1f3fd-200d-2642-fe0f", native: "\u{1F481}\u{1F3FD}\u200D\u2642\uFE0F" }, { unified: "1f481-1f3fe-200d-2642-fe0f", native: "\u{1F481}\u{1F3FE}\u200D\u2642\uFE0F" }, { unified: "1f481-1f3ff-200d-2642-fe0f", native: "\u{1F481}\u{1F3FF}\u200D\u2642\uFE0F" }], version: 4 }, "woman-tipping-hand": { id: "woman-tipping-hand", name: "Woman Tipping Hand", keywords: ["tipping-hand", "female", "girl", "human", "information"], skins: [{ unified: "1f481-200d-2640-fe0f", native: "\u{1F481}\u200D\u2640\uFE0F" }, { unified: "1f481-1f3fb-200d-2640-fe0f", native: "\u{1F481}\u{1F3FB}\u200D\u2640\uFE0F" }, { unified: "1f481-1f3fc-200d-2640-fe0f", native: "\u{1F481}\u{1F3FC}\u200D\u2640\uFE0F" }, { unified: "1f481-1f3fd-200d-2640-fe0f", native: "\u{1F481}\u{1F3FD}\u200D\u2640\uFE0F" }, { unified: "1f481-1f3fe-200d-2640-fe0f", native: "\u{1F481}\u{1F3FE}\u200D\u2640\uFE0F" }, { unified: "1f481-1f3ff-200d-2640-fe0f", native: "\u{1F481}\u{1F3FF}\u200D\u2640\uFE0F" }], version: 4 }, raising_hand: { id: "raising_hand", name: "Person Raising Hand", keywords: ["questio
51763n"], skins: [{ unified: "1f64b", native: "\u{1F64B}" }, { unified: "1f64b-1f3fb", native: "\u{1F64B}\u{1F3FB}" }, { unified: "1f64b-1f3fc", native: "\u{1F64B}\u{1F3FC}" }, { unified: "1f64b-1f3fd", native: "\u{1F64B}\u{1F3FD}" }, { unified: "1f64b-1f3fe", native: "\u{1F64B}\u{1F3FE}" }, { unified: "1f64b-1f3ff", native: "\u{1F64B}\u{1F3FF}" }], version: 1 }, "man-raising-hand": { id: "man-raising-hand", name: "Man Raising Hand", keywords: ["raising-hand", "male", "boy"], skins: [{ unified: "1f64b-200d-2642-fe0f", native: "\u{1F64B}\u200D\u2642\uFE0F" }, { unified: "1f64b-1f3fb-200d-2642-fe0f", native: "\u{1F64B}\u{1F3FB}\u200D\u2642\uFE0F" }, { unified: "1f64b-1f3fc-200d-2642-fe0f", native: "\u{1F64B}\u{1F3FC}\u200D\u2642\uFE0F" }, { unified: "1f64b-1f3fd-200d-2642-fe0f", native: "\u{1F64B}\u{1F3FD}\u200D\u2642\uFE0F" }, { unified: "1f64b-1f3fe-200d-2642-fe0f", native: "\u{1F64B}\u{1F3FE}\u200D\u2642\uFE0F" }, { unified: "1f64b-1f3ff-200d-2642-fe0f", native: "\u{1F64B}\u{1F3FF}\u200D\u2642\uFE0F" }], version: 4 }, "woman-raising-hand": { id: "woman-raising-hand", name: "Woman Raising Hand", keywords: ["raising-hand", "female", "girl"], skins: [{ unified: "1f64b-200d-2640-fe0f", native: "\u{1F64B}\u200D\u2640\uFE0F" }, { unified: "1f64b-1f3fb-200d-2640-fe0f", native: "\u{1F64B}\u{1F3FB}\u200D\u2640\uFE0F" }, { unified: "1f64b-1f3fc-200d-2640-fe0f", native: "\u{1F64B}\u{1F3FC}\u200D\u2640\uFE0F" }, { unified: "1f64b-1f3fd-200d-2640-fe0f", native: "\u{1F64B}\u{1F3FD}\u200D\u2640\uFE0F" }, { unified: "1f64b-1f3fe-200d-2640-fe0f", native: "\u{1F64B}\u{1F3FE}\u200D\u2640\uFE0F" }, { unified: "1f64b-1f3ff-200d-2640-fe0f", native: "\u{1F64B}\u{1F3FF}\u200D\u2640\uFE0F" }], version: 4 }, deaf_person: { id: "deaf_person", name: "Deaf Person", keywords: ["accessibility"], skins: [{ unified: "1f9cf", native: "\u{1F9CF}" }, { unified: "1f9cf-1f3fb", native: "\u{1F9CF}\u{1F3FB}" }, { unified: "1f9cf-1f3fc", native: "\u{1F9CF}\u{1F3FC}" }, { unified: "1f9cf-1f3fd", native: "\u{1F9CF}\u{1F3FD}" }, { unified: "1f9cf-1f3fe", native: "\u{1F9CF}\u{1F3FE}" }, { unified: "1f9cf-1f3ff", native: "\u{1F9CF}\u{1F3FF}" }], version: 12 }, deaf_man: { id: "deaf_man", name: "Deaf Man", keywords: ["accessibility"], skins: [{ unified: "1f9cf-200d-2642-fe0f", native: "\u{1F9CF}\u200D\u2642\uFE0F" }, { unified: "1f9cf-1f3fb-200d-2642-fe0f", native: "\u{1F9CF}\u{1F3FB}\u200D\u2642\uFE0F" }, { unified: "1f9cf-1f3fc-200d-2642-fe0f", native: "\u{1F9CF}\u{1F3FC}\u200D\u2642\uFE0F" }, { unified: "1f9cf-1f3fd-200d-2642-fe0f", native: "\u{1F9CF}\u{1F3FD}\u200D\u2642\uFE0F" }, { unified: "1f9cf-1f3fe-200d-2642-fe0f", native: "\u{1F9CF}\u{1F3FE}\u200D\u2642\uFE0F" }, { unified: "1f9cf-1f3ff-200d-2642-fe0f", native: "\u{1F9CF}\u{1F3FF}\u200D\u2642\uFE0F" }], version: 12 }, deaf_woman: { id: "deaf_woman", name: "Deaf Woman", keywords: ["accessibility"], skins: [{ unified: "1f9cf-200d-2640-fe0f", native: "\u{1F9CF}\u200D\u2640\uFE0F" }, { unified: "1f9cf-1f3fb-200d-2640-fe0f", native: "\u{1F9CF}\u{1F3FB}\u200D\u2640\uFE0F" }, { unified: "1f9cf-1f3fc-200d-2640-fe0f", native: "\u{1F9CF}\u{1F3FC}\u200D\u2640\uFE0F" }, { unified: "1f9cf-1f3fd-200d-2640-fe0f", native: "\u{1F9CF}\u{1F3FD}\u200D\u2640\uFE0F" }, { unified: "1f9cf-1f3fe-200d-2640-fe0f", native: "\u{1F9CF}\u{1F3FE}\u200D\u2640\uFE0F" }, { unified: "1f9cf-1f3ff-200d-2640-fe0f", native: "\u{1F9CF}\u{1F3FF}\u200D\u2640\uFE0F" }], version: 12 }, bow: { id: "bow", name: "Person Bowing", keywords: ["bow", "respectiful"], skins: [{ unified: "1f647", native: "\u{1F647}" }, { unified: "1f647-1f3fb", native: "\u{1F647}\u{1F3FB}" }, { unified: "1f647-1f3fc", native: "\u{1F647}\u{1F3FC}" }, { unified: "1f647-1f3fd", native: "\u{1F647}\u{1F3FD}" }, { unified: "1f647-1f3fe", native: "\u{1F647}\u{1F3FE}" }, { unified: "1f647-1f3ff", native: "\u{1F647}\u{1F3FF}" }], version: 1 }, "man-bowing": { id: "man-bowing", name: "Man Bowing", keywords: ["male", "boy"], skins: [{ unified: "1f647-200d-2642-fe0f", native: "\u{1F647}\u200D\u2642\uFE0F" }, { unified: "1f647-1f3fb-200d-2642-fe0f", native: "\u{1F647}\u{1F3FB}\u200D\u2642\uFE0F" }, { unified: "1f647-1f3fc-200d-2642-fe0f", native: "\u{1F647}\u{1F3FC}\u200D\u2642\uFE0F" }, { unified: "1f647-1f3fd-200d-2642-fe0f", native: "\u{1F647}\u{1F3FD}\u200D\u2642\uFE0F" }, { unified: "1f647-1f3fe-200d-2642-fe0f", native: "\u{1F647}\u{1F3FE}\u200D\u2642\uFE0F" }, { unified: "1f647-1f3ff-200d-2642-fe0f", native: "\u{1F647}\u{1F3FF}\u200D\u2642\uFE0F" }], version: 4 }, "woman-bowing": { id: "woman-bowing", name: "Woman Bowing", keywords: ["female", "girl"], skins: [{ unified: "1f647-200d-2640-fe0f", native: "\u{1F647}\u200D\u2640\uFE0F" }, { unified: "1f647-1f3fb-200d-2640-fe0f", native: "\u{1F647}\u{1F3FB}\u200D\u2640\uFE0F" }, { unified: "1f647-1f3fc-200d-2640-fe0f", native: "\u{1F647}\u{1F3FC}\u200D\u2640\uFE0F" }, { unified: "1f647-1f3fd-200d-2640-fe0f", native: "\u{1F647}\u{1F3FD}\u200D\u2640\uFE0F" }, { unified: "1f647-1f3fe-200d-2640-fe0f", native: "\u{1F647}\u{1F3FE}\u200D\u2640\uFE0F" }, { unified: "1f647-1f3ff-200d-2640-fe0f", native: "\u{1F647}\u{1F3FF}\u200D\u2640\uFE0F" }], version: 4 }, face_palm: { id: "face_palm", name: "Face Palm", keywords: ["person", "facepalming", "disappointed"], skins: [{ unified: "1f926", native: "\u{1F926}" }, { unified: "1f926-1f3fb", native: "\u{1F926}\u{1F3FB}" }, { unified: "1f926-1f3fc", native: "\u{1F926}\u{1F3FC}" }, { unified: "1f926-1f3fd", native: "\u{1F926}\u{1F3FD}" }, { unified: "1f926-1f3fe", native: "\u{1F926}\u{1F3FE}" }, { unified: "1f926-1f3ff", native: "\u{1F926}\u{1F3FF}" }], version: 3 }, "man-facepalming": { id: "man-facepalming", name: "Man Facepalming", keywords: ["male", "boy", "disbelief"], skins: [{ unified: "1f926-200d-2642-fe0f", native: "\u{1F926}\u200D\u2642\uFE0F" }, { unified: "1f926-1f3fb-200d-2642-fe0f", native: "\u{1F926}\u{1F3FB}\u200D\u2642\uFE0F" }, { unified: "1f926-1f3fc-200d-2642-fe0f", native: "\u{1F926}\u{1F3FC}\u200D\u2642\uFE0F" }, { unified: "1f926-1f3fd-200d-2642-fe0f", native: "\u{1F926}\u{1F3FD}\u200D\u2642\uFE0F" }, { unified: "1f926-1f3fe-200d-2642-fe0f", native: "\u{1F926}\u{1F3FE}\u200D\u2642\uFE0F" }, { unified: "1f926-1f3ff-200d-2642-fe0f", native: "\u{1F926}\u{1F3FF}\u200D\u2642\uFE0F" }], version: 4 }, "woman-facepalming": { id: "woman-facepalming", name: "Woman Facepalming", keywords: ["female", "girl", "disbelief"], skins: [{ unified: "1f926-200d-2640-fe0f", native: "\u{1F926}\u200D\u2640\uFE0F" }, { unified: "1f926-1f3fb-200d-2640-fe0f", native: "\u{1F926}\u{1F3FB}\u200D\u2640\uFE0F" }, { unified: "1f926-1f3fc-200d-2640-fe0f", native: "\u{1F926}\u{1F3FC}\u200D\u2640\uFE0F" }, { unified: "1f926-1f3fd-200d-2640-fe0f", native: "\u{1F926}\u{1F3FD}\u200D\u2640\uFE0F" }, { unified: "1f926-1f3fe-200d-2640-fe0f", native: "\u{1F926}\u{1F3FE}\u200D\u2640\uFE0F" }, { unified: "1f926-1f3ff-200d-2640-fe0f", native: "\u{1F926}\u{1F3FF}\u200D\u2640\uFE0F" }], version: 4 }, shrug: { id: "shrug", name: "Shrug", keywords: ["person", "shrugging", "regardless"], skins: [{ unified: "1f937", native: "\u{1F937}" }, { unified: "1f937-1f3fb", native: "\u{1F937}\u{1F3FB}" }, { unified: "1f937-1f3fc", native: "\u{1F937}\u{1F3FC}" }, { unified: "1f937-1f3fd", native: "\u{1F937}\u{1F3FD}" }, { unified: "1f937-1f3fe", native: "\u{1F937}\u{1F3FE}" }, { unified: "1f937-1f3ff", native: "\u{1F937}\u{1F3FF}" }], version: 3 }, "man-shrugging": { id: "man-shrugging", name: "Man Shrugging", keywords: ["male", "boy", "confused", "indifferent", "doubt"], skins: [{ unified: "1f937-200d-2642-fe0f", native: "\u{1F937}\u200D\u2642\uFE0F" }, { unified: "1f937-1f3fb-200d-2642-fe0f", native: "\u{1F937}\u{1F3FB}\u200D\u2642\uFE0F" }, { unified: "1f937-1f3fc-200d-2642-fe0f", native: "\u{1F937}\u{1F3FC}\u200D\u2642\uFE0F" }, { unified: "1f937-1f3fd-200d-2642-fe0f", native: "\u{1F937}\u{1F3FD}\u200D\u2642\uFE0F" }, { unified: "1f937-1f3fe-200d-2642-fe0f", native: "\u{1F937}\u{1F3FE}\u200D\u2642\uFE0F" }, { unified: "1f937-1f3ff-200d-2642-fe0f", native: "\u{1F937}\u{1F3FF}\u200D\u2642\uFE0F" }], version: 4 }, "woman-shrugging": { id: "woman-shrugging", name: "Woman Shrugging", keywords: ["female", "girl", "confused", "indifferent", "doubt"], skins: [{ unified: "1f937-200d-2640-fe0f", native: "\u{1F937}\u200D\u2640\uFE0F" }, { unified: "1f937-1f3fb-200d-2640-fe0f", native: "\u{1F937}\u{1F3FB}\u200D\u2640\uFE0F" }, { unified: "1f937-1f3fc-200d-2640-fe0f", native: "\u{1F937}\u{1F3FC}\u200D\u2640\uFE0F" }, { unified: "1f937-1f3fd-200d-2640-fe0f", native: "\u{1F937}\u{1F3FD}\u200D\u2640\uFE0F" }, { unified: "1f937-1f3fe-200d-2640-fe0f", native: "\u{1F937}\u{1F3FE}\u200D\u2640\uFE0F" }, { unified: "1f937-1f3ff-200d-2640-fe0f", native: "\u{1F937}\u{1F3FF}\u200D\u2640\uFE0F" }], version: 4 }, health_worker: { id: "health_worker", name: "Health Worker", keywords: ["hospital"], skins: [{ unified: "1f9d1-200d-2695-fe0f", native: "\u{1F9D1}\u200D\u2695\uFE0F" }, { unified: "1f9d1-1f3fb-200d-2695-fe0f", native: "\u{1F9D1}\u{1F3FB}\u200D\u2695\uFE0F" }, { unified: "1f9d1-1f3fc-200d-2695-fe0f", native: "\u{1F9D1}\u{1F3FC}\u200D\u2695\uFE0F" }, { unified: "1f9d1-1f3fd-200d-2695-fe0f", native: "\u{1F9D1}\u{1F3FD}\u200D\u2695\uFE0F" }, { unified: "1f9d1-1f3fe-200d-2695-fe0f", native: "\u{1F9D1}\u{1F3FE}\u200D\u2695\uFE0F" }, { unified: "1f9d1-1f3ff-200d-2695-fe0f", native: "\u{1F9D1}\u{1F3FF}\u200D\u2695\uFE0F" }], version: 12.1 }, "male-doctor": { id: "male-doctor", name: "Man Health Worker", keywords: ["male", "doctor", "nurse", "therapist", "healthcare", "human"], skins: [{ unified: "1f468-200d-2695-fe0f", native: "\u{1F468}\u200D\u2695\uFE0F" }, { unified: "1f468-1f3fb-200d-2695-fe0f", native: "\u{1F468}\u{1F3FB}\u200D\u2695\uFE0F" }, { unified: "1f468-1f3fc-200d-2695-fe0f", native: "\u{1F468}\u{1F3FC}\u200D\u2695\uFE0F" }, { unified: "1f468-1f3fd-200d-2695-fe0f", native: "\u{1F468}\u{1F3FD}\u200D\u2695\uFE0F" }, { unified: "1f468-1f3fe-200d-2695-fe0f", native: "\u{1F468}\u{1F3FE}\u200D\u2695\uFE0F" }, { unified: "1f468-1f3ff-200d-2695-fe0f", native: "\u{1F468}\u{1F3FF}\u200D\u2695\uFE0F" }], version: 4 }, "female-doctor": { id: "female-doctor", name: "Woman Health Worker", keywords: ["female", "doctor", "nurse", "therapist", "healthcare", "human"], skins: [{ unified: "1f469-200d-2695-fe0f", native: "\u{1F469}\u200D\u2695\uFE0F" }, { unified: "1f469-1f3fb-200d-2695-fe0f", native: "\u{1F469}\u{1F3FB}\u200D\u2695\uFE0F" }, { unified: "1f469-1f3fc-200d-2695-fe0f", native: "\u{1F469}\u{1F3FC}\u200D\u2695\uFE0F" }, { unified: "1f469-1f3fd-200d-2695-fe0f", native: "\u{1F469}\u{1F3FD}\u200D\u2695\uFE0F" }, { unified: "1f469-1f3fe-200d-2695-fe0f", native: "\u{1F469}\u{1F3FE}\u200D\u2695\uFE0F" }, { unified: "1f469-1f3ff-200d-2695-fe0f", native: "\u{1F469}\u{1F3FF}\u200D\u2695\uFE0F" }], version: 4 }, student: { id: "student", name: "Student", keywords: ["learn"], skins: [{ unified: "1f9d1-200d-1f393", native: "\u{1F9D1}\u200D\u{1F393}" }, { unified: "1f9d1-1f3fb-200d-1f393", native: "\u{1F9D1}\u{1F3FB}\u200D\u{1F393}" }, { unified: "1f9d1-1f3fc-200d-1f393", native: "\u{1F9D1}\u{1F3FC}\u200D\u{1F393}" }, { unified: "1f9d1-1f3fd-200d-1f393", native: "\u{1F9D1}\u{1F3FD}\u200D\u{1F393}" }, { unified: "1f9d1-1f3fe-200d-1f393", native: "\u{1F9D1}\u{1F3FE}\u200D\u{1F393}" }, { unified: "1f9d1-1f3ff-200d-1f393", native: "\u{1F9D1}\u{1F3FF}\u200D\u{1F393}" }
51763], version: 12.1 }, "male-student": { id: "male-student", name: "Man Student", keywords: ["male", "graduate", "human"], skins: [{ unified: "1f468-200d-1f393", native: "\u{1F468}\u200D\u{1F393}" }, { unified: "1f468-1f3fb-200d-1f393", native: "\u{1F468}\u{1F3FB}\u200D\u{1F393}" }, { unified: "1f468-1f3fc-200d-1f393", native: "\u{1F468}\u{1F3FC}\u200D\u{1F393}" }, { unified: "1f468-1f3fd-200d-1f393", native: "\u{1F468}\u{1F3FD}\u200D\u{1F393}" }, { unified: "1f468-1f3fe-200d-1f393", native: "\u{1F468}\u{1F3FE}\u200D\u{1F393}" }, { unified: "1f468-1f3ff-200d-1f393", native: "\u{1F468}\u{1F3FF}\u200D\u{1F393}" }], version: 4 }, "female-student": { id: "female-student", name: "Woman Student", keywords: ["female", "graduate", "human"], skins: [{ unified: "1f469-200d-1f393", native: "\u{1F469}\u200D\u{1F393}" }, { unified: "1f469-1f3fb-200d-1f393", native: "\u{1F469}\u{1F3FB}\u200D\u{1F393}" }, { unified: "1f469-1f3fc-200d-1f393", native: "\u{1F469}\u{1F3FC}\u200D\u{1F393}" }, { unified: "1f469-1f3fd-200d-1f393", native: "\u{1F469}\u{1F3FD}\u200D\u{1F393}" }, { unified: "1f469-1f3fe-200d-1f393", native: "\u{1F469}\u{1F3FE}\u200D\u{1F393}" }, { unified: "1f469-1f3ff-200d-1f393", native: "\u{1F469}\u{1F3FF}\u200D\u{1F393}" }], version: 4 }, teacher: { id: "teacher", name: "Teacher", keywords: ["professor"], skins: [{ unified: "1f9d1-200d-1f3eb", native: "\u{1F9D1}\u200D\u{1F3EB}" }, { unified: "1f9d1-1f3fb-200d-1f3eb", native: "\u{1F9D1}\u{1F3FB}\u200D\u{1F3EB}" }, { unified: "1f9d1-1f3fc-200d-1f3eb", native: "\u{1F9D1}\u{1F3FC}\u200D\u{1F3EB}" }, { unified: "1f9d1-1f3fd-200d-1f3eb", native: "\u{1F9D1}\u{1F3FD}\u200D\u{1F3EB}" }, { unified: "1f9d1-1f3fe-200d-1f3eb", native: "\u{1F9D1}\u{1F3FE}\u200D\u{1F3EB}" }, { unified: "1f9d1-1f3ff-200d-1f3eb", native: "\u{1F9D1}\u{1F3FF}\u200D\u{1F3EB}" }], version: 12.1 }, "male-teacher": { id: "male-teacher", name: "Man Teacher", keywords: ["male", "instructor", "professor", "human"], skins: [{ unified: "1f468-200d-1f3eb", native: "\u{1F468}\u200D\u{1F3EB}" }, { unified: "1f468-1f3fb-200d-1f3eb", native: "\u{1F468}\u{1F3FB}\u200D\u{1F3EB}" }, { unified: "1f468-1f3fc-200d-1f3eb", native: "\u{1F468}\u{1F3FC}\u200D\u{1F3EB}" }, { unified: "1f468-1f3fd-200d-1f3eb", native: "\u{1F468}\u{1F3FD}\u200D\u{1F3EB}" }, { unified: "1f468-1f3fe-200d-1f3eb", native: "\u{1F468}\u{1F3FE}\u200D\u{1F3EB}" }, { unified: "1f468-1f3ff-200d-1f3eb", native: "\u{1F468}\u{1F3FF}\u200D\u{1F3EB}" }], version: 4 }, "female-teacher": { id: "female-teacher", name: "Woman Teacher", keywords: ["female", "instructor", "professor", "human"], skins: [{ unified: "1f469-200d-1f3eb", native: "\u{1F469}\u200D\u{1F3EB}" }, { unified: "1f469-1f3fb-200d-1f3eb", native: "\u{1F469}\u{1F3FB}\u200D\u{1F3EB}" }, { unified: "1f469-1f3fc-200d-1f3eb", native: "\u{1F469}\u{1F3FC}\u200D\u{1F3EB}" }, { unified: "1f469-1f3fd-200d-1f3eb", native: "\u{1F469}\u{1F3FD}\u200D\u{1F3EB}" }, { unified: "1f469-1f3fe-200d-1f3eb", native: "\u{1F469}\u{1F3FE}\u200D\u{1F3EB}" }, { unified: "1f469-1f3ff-200d-1f3eb", native: "\u{1F469}\u{1F3FF}\u200D\u{1F3EB}" }], version: 4 }, judge: { id: "judge", name: "Judge", keywords: ["law"], skins: [{ unified: "1f9d1-200d-2696-fe0f", native: "\u{1F9D1}\u200D\u2696\uFE0F" }, { unified: "1f9d1-1f3fb-200d-2696-fe0f", native: "\u{1F9D1}\u{1F3FB}\u200D\u2696\uFE0F" }, { unified: "1f9d1-1f3fc-200d-2696-fe0f", native: "\u{1F9D1}\u{1F3FC}\u200D\u2696\uFE0F" }, { unified: "1f9d1-1f3fd-200d-2696-fe0f", native: "\u{1F9D1}\u{1F3FD}\u200D\u2696\uFE0F" }, { unified: "1f9d1-1f3fe-200d-2696-fe0f", native: "\u{1F9D1}\u{1F3FE}\u200D\u2696\uFE0F" }, { unified: "1f9d1-1f3ff-200d-2696-fe0f", native: "\u{1F9D1}\u{1F3FF}\u200D\u2696\uFE0F" }], version: 12.1 }, "male-judge": { id: "male-judge", name: "Man Judge", keywords: ["male", "justice", "court", "human"], skins: [{ unified: "1f468-200d-2696-fe0f", native: "\u{1F468}\u200D\u2696\uFE0F" }, { unified: "1f468-1f3fb-200d-2696-fe0f", native: "\u{1F468}\u{1F3FB}\u200D\u2696\uFE0F" }, { unified: "1f468-1f3fc-200d-2696-fe0f", native: "\u{1F468}\u{1F3FC}\u200D\u2696\uFE0F" }, { unified: "1f468-1f3fd-200d-2696-fe0f", native: "\u{1F468}\u{1F3FD}\u200D\u2696\uFE0F" }, { unified: "1f468-1f3fe-200d-2696-fe0f", native: "\u{1F468}\u{1F3FE}\u200D\u2696\uFE0F" }, { unified: "1f468-1f3ff-200d-2696-fe0f", native: "\u{1F468}\u{1F3FF}\u200D\u2696\uFE0F" }], version: 4 }, "female-judge": { id: "female-judge", name: "Woman Judge", keywords: ["female", "justice", "court", "human"], skins: [{ unified: "1f469-200d-2696-fe0f", native: "\u{1F469}\u200D\u2696\uFE0F" }, { unified: "1f469-1f3fb-200d-2696-fe0f", native: "\u{1F469}\u{1F3FB}\u200D\u2696\uFE0F" }, { unified: "1f469-1f3fc-200d-2696-fe0f", native: "\u{1F469}\u{1F3FC}\u200D\u2696\uFE0F" }, { unified: "1f469-1f3fd-200d-2696-fe0f", native: "\u{1F469}\u{1F3FD}\u200D\u2696\uFE0F" }, { unified: "1f469-1f3fe-200d-2696-fe0f", native: "\u{1F469}\u{1F3FE}\u200D\u2696\uFE0F" }, { unified: "1f469-1f3ff-200d-2696-fe0f", native: "\u{1F469}\u{1F3FF}\u200D\u2696\uFE0F" }], version: 4 }, farmer: { id: "farmer", name: "Farmer", keywords: ["crops"], skins: [{ unified: "1f9d1-200d-1f33e", native: "\u{1F9D1}\u200D\u{1F33E}" }, { unified: "1f9d1-1f3fb-200d-1f33e", native: "\u{1F9D1}\u{1F3FB}\u200D\u{1F33E}" }, { unified: "1f9d1-1f3fc-200d-1f33e", native: "\u{1F9D1}\u{1F3FC}\u200D\u{1F33E}" }, { unified: "1f9d1-1f3fd-200d-1f33e", native: "\u{1F9D1}\u{1F3FD}\u200D\u{1F33E}" }, { unified: "1f9d1-1f3fe-200d-1f33e", native: "\u{1F9D1}\u{1F3FE}\u200D\u{1F33E}" }, { unified: "1f9d1-1f3ff-200d-1f33e", native: "\u{1F9D1}\u{1F3FF}\u200D\u{1F33E}" }], version: 12.1 }, "male-farmer": { id: "male-farmer", name: "Man Farmer", keywords: ["male", "rancher", "gardener", "human"], skins: [{ unified: "1f468-200d-1f33e", native: "\u{1F468}\u200D\u{1F33E}" }, { unified: "1f468-1f3fb-200d-1f33e", native: "\u{1F468}\u{1F3FB}\u200D\u{1F33E}" }, { unified: "1f468-1f3fc-200d-1f33e", native: "\u{1F468}\u{1F3FC}\u200D\u{1F33E}" }, { unified: "1f468-1f3fd-200d-1f33e", native: "\u{1F468}\u{1F3FD}\u200D\u{1F33E}" }, { unified: "1f468-1f3fe-200d-1f33e", native: "\u{1F468}\u{1F3FE}\u200D\u{1F33E}" }, { unified: "1f468-1f3ff-200d-1f33e", native: "\u{1F468}\u{1F3FF}\u200D\u{1F33E}" }], version: 4 }, "female-farmer": { id: "female-farmer", name: "Woman Farmer", keywords: ["female", "rancher", "gardener", "human"], skins: [{ unified: "1f469-200d-1f33e", native: "\u{1F469}\u200D\u{1F33E}" }, { unified: "1f469-1f3fb-200d-1f33e", native: "\u{1F469}\u{1F3FB}\u200D\u{1F33E}" }, { unified: "1f469-1f3fc-200d-1f33e", native: "\u{1F469}\u{1F3FC}\u200D\u{1F33E}" }, { unified: "1f469-1f3fd-200d-1f33e", native: "\u{1F469}\u{1F3FD}\u200D\u{1F33E}" }, { unified: "1f469-1f3fe-200d-1f33e", native: "\u{1F469}\u{1F3FE}\u200D\u{1F33E}" }, { unified: "1f469-1f3ff-200d-1f33e", native: "\u{1F469}\u{1F3FF}\u200D\u{1F33E}" }], version: 4 }
51763, cook: { id: "cook", name: "Cook", keywords: ["food", "kitchen", "culinary"], skins: [{ unified: "1f9d1-200d-1f373", native: "\u{1F9D1}\u200D\u{1F373}" }, { unified: "1f9d1-1f3fb-200d-1f373", native: "\u{1F9D1}\u{1F3FB}\u200D\u{1F373}" }, { unified: "1f9d1-1f3fc-200d-1f373", native: "\u{1F9D1}\u{1F3FC}\u200D\u{1F373}" }, { unified: "1f9d1-1f3fd-200d-1f373", native: "\u{1F9D1}\u{1F3FD}\u200D\u{1F373}" }, { unified: "1f9d1-1f3fe-200d-1f373", native: "\u{1F9D1}\u{1F3FE}\u200D\u{1F373}" }, { unified: "1f9d1-1f3ff-200d-1f373", native: "\u{1F9D1}\u{1F3FF}\u200D\u{1F373}" }], version: 12.1 }, "male-cook": { id: "male-cook", name: "Man Cook", keywords: ["male", "chef", "human"], skins: [{ unified: "1f468-200d-1f373", native: "\u{1F468}\u200D\u{1F373}" }, { unified: "1f468-1f3fb-200d-1f373", native: "\u{1F468}\u{1F3FB}\u200D\u{1F373}" }, { unified: "1f468-1f3fc-200d-1f373", native: "\u{1F468}\u{1F3FC}\u200D\u{1F373}" }, { unified: "1f468-1f3fd-200d-1f373", native: "\u{1F468}\u{1F3FD}\u200D\u{1F373}" }, { unified: "1f468-1f3fe-200d-1f373", native: "\u{1F468}\u{1F3FE}\u200D\u{1F373}" }, { unified: "1f468-1f3ff-200d-1f373", native: "\u{1F468}\u{1F3FF}\u200D\u{1F373}" }], version: 4 }, "female-cook": { id: "female-cook", name: "Woman Cook", keywords: ["female", "chef", "human"], skins: [{ unified: "1f469-200d-1f373", native: "\u{1F469}\u200D\u{1F373}" }, { unified: "1f469-1f3fb-200d-1f373", native: "\u{1F469}\u{1F3FB}\u200D\u{1F373}" }, { unified: "1f469-1f3fc-200d-1f373", native: "\u{1F469}\u{1F3FC}\u200D\u{1F373}" }, { unified: "1f469-1f3fd-200d-1f373", native: "\u{1F469}\u{1F3FD}\u200D\u{1F373}" }, { unified: "1f469-1f3fe-200d-1f373", native: "\u{1F469}\u{1F3FE}\u200D\u{1F373}" }, { unified: "1f469-1f3ff-200d-1f373", native: "\u{1F469}\u{1F3FF}\u200D\u{1F373}" }], version: 4 }, mechanic: { id: "mechanic", name: "Mechanic", keywords: ["worker", "technician"], skins: [{ unified: "1f9d1-200d-1f527", native: "\u{1F9D1}\u200D\u{1F527}" }, { unified: "1f9d1-1f3fb-200d-1f527", native: "\u{1F9D1}\u{1F3FB}\u200D\u{1F527}" }, { unified: "1f9d1-1f3fc-200d-1f527", native: "\u{1F9D1}\u{1F3FC}\u200D\u{1F527}" }, { unified: "1f9d1-1f3fd-200d-1f527", native: "\u{1F9D1}\u{1F3FD}\u200D\u{1F527}" }, { unified: "1f9d1-1f3fe-200d-1f527", native: "\u{1F9D1}\u{1F3FE}\u200D\u{1F527}" }, { unified: "1f9d1-1f3ff-200d-1f527", native: "\u{1F9D1}\u{1F3FF}\u200D\u{1F527}" }], version: 12.1 }, "male-mechanic": { id: "male-mechanic", name: "Man Mechanic", keywords: ["male", "plumber", "human", "wrench"], skins: [{ unified: "1f468-200d-1f527", native: "\u{1F468}\u200D\u{1F527}" }, { unified: "1f468-1f3fb-200d-1f527", native: "\u{1F468}\u{1F3FB}\u200D\u{1F527}" }, { unified: "1f468-1f3fc-200d-1f527", native: "\u{1F468}\u{1F3FC}\u200D\u{1F527}" }, { unified: "1f468-1f3fd-200d-1f527", native: "\u{1F468}\u{1F3FD}\u200D\u{1F527}" }, { unified: "1f468-1f3fe-200d-1f527", native: "\u{1F468}\u{1F3FE}\u200D\u{1F527}" }, { unified: "1f468-1f3ff-200d-1f527", native: "\u{1F468}\u{1F3FF}\u200D\u{1F527}" }], version: 4 }, "female-mechanic": { id: "female-mechanic", name: "Woman Mechanic", keywords: ["female", "plumber", "human", "wrench"], skins: [{ unified: "1f469-200d-1f527", native: "\u{1F469}\u200D\u{1F527}" }, { unified: "1f469-1f3fb-200d-1f527", native: "\u{1F469}\u{1F3FB}\u200D\u{1F527}" }, { unified: "1f469-1f3fc-200d-1f527", native: "\u{1F469}\u{1F3FC}\u200D\u{1F527}" }, { unified: "1f469-1f3fd-200d-1f527", native: "\u{1F469}\u{1F3FD}\u200D\u{1F527}" }, { unified: "1f469-1f3fe-200d-1f527", native: "\u{1F469}\u{1F3FE}\u200D\u{1F527}" }, { unified: "1f469-1f3ff-200d-1f527", native: "\u{1F469}\u{1F3FF}\u200D\u{1F527}" }], version: 4 }, factory_worker: { id: "factory_worker", name: "Factory Worker", keywords: ["labor"], skins: [{ unified: "1f9d1-200d-1f3ed", native: "\u{1F9D1}\u200D\u{1F3ED}" }, { unified: "1f9d1-1f3fb-200d-1f3ed", native: "\u{1F9D1}\u{1F3FB}\u200D\u{1F3ED}" }, { unified: "1f9d1-1f3fc-200d-1f3ed", native: "\u{1F9D1}\u{1F3FC}\u200D\u{1F3ED}" }, { unified: "1f9d1-1f3fd-200d-1f3ed", native: "\u{1F9D1}\u{1F3FD}\u200D\u{1F3ED}" }, { unified: "1f9d1-1f3fe-200d-1f3ed", native: "\u{1F9D1}\u{1F3FE}\u200D\u{1F3ED}" }, { unified: "1f9d1-1f3ff-200d-1f3ed", native: "\u{1F9D1}\u{1F3FF}\u200D\u{1F3ED}" }], version: 12.1 }, "male-factory-worker": { id: "male-factory-worker", name: "Man Factory Worker", keywords: ["male", "factory-worker", "assembly", "industrial", "human"], skins: [{ unified: "1f468-200d-1f3ed", native: "\u{1F468}\u200D\u{1F3ED}" }, { unified: "1f468-1f3fb-200d-1f3ed", native: "\u{1F468}\u{1F3FB}\u200D\u{1F3ED}" }, { unified: "1f468-1f3fc-200d-1f3ed", native: "\u{1F468}\u{1F3FC}\u200D\u{1F3ED}" }, { unified: "1f468-1f3fd-200d-1f3ed", native: "\u{1F468}\u{1F3FD}\u200D\u{1F3ED}" }, { unified: "1f468-1f3fe-200d-1f3ed", native: "\u{1F468}\u{1F3FE}\u200D\u{1F3ED}" }, { unified: "1f468-1f3ff-200d-1f3ed", native: "\u{1F468}\u{1F3FF}\u200D\u{1F3ED}" }], version: 4 }, "female-factory-worker": { id: "female-factory-worker", name: "Woman Factory Worker", keywords: ["female", "factory-worker", "assembly", "industrial", "human"], skins: [{ unified: "1f469-200d-1f3ed", native: "\u{1F469}\u200D\u{1F3ED}" }, { unified: "1f469-1f3fb-200d-1f3ed", native: "\u{1F469}\u{1F3FB}\u200D\u{1F3ED}" }, { unified: "1f469-1f3fc-200d-1f3ed", native: "\u{1F469}\u{1F3FC}\u200D\u{1F3ED}" }, { unified: "1f469-1f3fd-200d-1f3ed", native: "\u{1F469}\u{1F3FD}\u200D\u{1F3ED}" }, { unified: "1f469-1f3fe-200d-1f3ed", native: "\u{1F469}\u{1F3FE}\u200D\u{1F3ED}" }, { unified: "1f469-1f3ff-200d-1f3ed", native: "\u{1F469}\u{1F3FF}\u200D\u{1F3ED}" }], version: 4 }, office_worker: { id: "office_worker", name: "Office Worker", keywords: ["business"], skins: [{ unified: "1f9d1-200d-1f4bc", native: "\u{1F9D1}\u200D\u{1F4BC}" }, { unified: "1f9d1-1f3fb-200d-1f4bc", native: "\u{1F9D1}\u{1F3FB}\u200D\u{1F4BC}" }, { unified: "1f9d1-1f3fc-200d-1f4bc", native: "\u{1F9D1}\u{1F3FC}\u200D\u{1F4BC}" }, { unified: "1f9d1-1f3fd-200d-1f4bc", native: "\u{1F9D1}\u{1F3FD}\u200D\u{1F4BC}" }, { unified: "1f9d1-1f3fe-200d-1f4bc", native: "\u{1F9D1}\u{1F3FE}\u200D\u{1F4BC}" }, { unified: "1f9d1-1f3ff-200d-1f4bc", native: "\u{1F9D1}\u{1F3FF}\u200D\u{1F4BC}" }], version: 12.1 }, "male-office-worker": { id: "male-office-worker", name: "Man Office Worker", keywords: ["male", "office-worker", "business", "manager", "human"], skins: [{ unified: "1f468-200d-1f4bc", native: "\u{1F468}\u200D\u{1F4BC}" }, { unified: "1f468-1f3fb-200d-1f4bc", native: "\u{1F468}\u{1F3FB}\u200D\u{1F4BC}" }, { unified: "1f468-1f3fc-200d-1f4bc", native: "\u{1F468}\u{1F3FC}\u200D\u{1F4BC}" }, { unified: "1f468-1f3fd-200d-1f4bc", native: "\u{1F468}\u{1F3FD}\u200D\u{1F4BC}" }, { unified: "1f468-1f3fe-200d-1f4bc", native: "\u{1F468}\u{1F3FE}\u200D\u{1F4BC}" }, { unified: "1f468-1f3ff-200d-1f4bc", native: "\u{1F468}\u{1F3FF}\u200D\u{1F4BC}" }], version: 4 }, "female-office-worker": { id: "female-office-worker", name: "Woman Office Worker", keywords: ["female", "office-worker", "business", "manager", "human"], skins: [{ unified: "1f469-200d-1f4bc", native: "\u{1F469}\u200D\u{1F4BC}" }, { unified: "1f469-1f3fb-200d-1f4bc", native: "\u{1F469}\u{1F3FB}\u200D\u{1F4BC}" }, { unified: "1f469-1f3fc-200d-1f4bc", native: "\u{1F469}\u{1F3FC}\u200D\u{1F4BC}" }, { unified: "1f469-1f3fd-200d-1f4bc", native: "\u{1F469}\u{1F3FD}\u200D\u{1F4BC}" }, { unified: "1f469-1f3fe-200d-1f4bc", native: "\u{1F469}\u{1F3FE}\u200D\u{1F4BC}" }, { unified: "1f469-1f3ff-200d-1f4bc", native: "\u{1F469}\u{1F3FF}\u200D\u{1F4BC}" }], version: 4 }
51763, scientist: { id: "scientist", name: "Scientist", keywords: ["chemistry"], skins: [{ unified: "1f9d1-200d-1f52c", native: "\u{1F9D1}\u200D\u{1F52C}" }, { unified: "1f9d1-1f3fb-200d-1f52c", native: "\u{1F9D1}\u{1F3FB}\u200D\u{1F52C}" }, { unified: "1f9d1-1f3fc-200d-1f52c", native: "\u{1F9D1}\u{1F3FC}\u200D\u{1F52C}" }, { unified: "1f9d1-1f3fd-200d-1f52c", native: "\u{1F9D1}\u{1F3FD}\u200D\u{1F52C}" }, { unified: "1f9d1-1f3fe-200d-1f52c", native: "\u{1F9D1}\u{1F3FE}\u200D\u{1F52C}" }, { unified: "1f9d1-1f3ff-200d-1f52c", native: "\u{1F9D1}\u{1F3FF}\u200D\u{1F52C}" }], version: 12.1 }, "male-scientist": { id: "male-scientist", name: "Man Scientist", keywords: ["male", "biologist", "chemist", "engineer", "physicist", "human"], skins: [{ unified: "1f468-200d-1f52c", native: "\u{1F468}\u200D\u{1F52C}" }, { unified: "1f468-1f3fb-200d-1f52c", native: "\u{1F468}\u{1F3FB}\u200D\u{1F52C}" }, { unified: "1f468-1f3fc-200d-1f52c", native: "\u{1F468}\u{1F3FC}\u200D\u{1F52C}" }, { unified: "1f468-1f3fd-200d-1f52c", native: "\u{1F468}\u{1F3FD}\u200D\u{1F52C}" }, { unified: "1f468-1f3fe-200d-1f52c", native: "\u{1F468}\u{1F3FE}\u200D\u{1F52C}" }, { unified: "1f468-1f3ff-200d-1f52c", native: "\u{1F468}\u{1F3FF}\u200D\u{1F52C}" }], version: 4 }, "female-scientist": { id: "female-scientist", name: "Woman Scientist", keywords: ["female", "biologist", "chemist", "engineer", "physicist", "human"], skins: [{ unified: "1f469-200d-1f52c", native: "\u{1F469}\u200D\u{1F52C}" }, { unified: "1f469-1f3fb-200d-1f52c", native: "\u{1F469}\u{1F3FB}\u200D\u{1F52C}" }, { unified: "1f469-1f3fc-200d-1f52c", native: "\u{1F469}\u{1F3FC}\u200D\u{1F52C}" }, { unified: "1f469-1f3fd-200d-1f52c", native: "\u{1F469}\u{1F3FD}\u200D\u{1F52C}" }, { unified: "1f469-1f3fe-200d-1f52c", native: "\u{1F469}\u{1F3FE}\u200D\u{1F52C}" }, { unified: "1f469-1f3ff-200d-1f52c", native: "\u{1F469}\u{1F3FF}\u200D\u{1F52C}" }], version: 4 }, technologist: { id: "technologist", name: "Technologist", keywords: ["computer"], skins: [{ unified: "1f9d1-200d-1f4bb", native: "\u{1F9D1}\u200D\u{1F4BB}" }, { unified: "1f9d1-1f3fb-200d-1f4bb", native: "\u{1F9D1}\u{1F3FB}\u200D\u{1F4BB}" }, { unified: "1f9d1-1f3fc-200d-1f4bb", native: "\u{1F9D1}\u{1F3FC}\u200D\u{1F4BB}" }, { unified: "1f9d1-1f3fd-200d-1f4bb", native: "\u{1F9D1}\u{1F3FD}\u200D\u{1F4BB}" }, { unified: "1f9d1-1f3fe-200d-1f4bb", native: "\u{1F9D1}\u{1F3FE}\u200D\u{1F4BB}" }, { unified: "1f9d1-1f3ff-200d-1f4bb", native: "\u{1F9D1}\u{1F3FF}\u200D\u{1F4BB}" }], version: 12.1 }, "male-technologist": { id: "male-technologist", name: "Man Technologist", keywords: ["male", "coder", "developer", "engineer", "programmer", "software", "human", "laptop", "computer"], skins: [{ unified: "1f468-200d-1f4bb", native: "\u{1F468}\u200D\u{1F4BB}" }, { unified: "1f468-1f3fb-200d-1f4bb", native: "\u{1F468}\u{1F3FB}\u200D\u{1F4BB}" }, { unified: "1f468-1f3fc-200d-1f4bb", native: "\u{1F468}\u{1F3FC}\u200D\u{1F4BB}" }, { unified: "1f468-1f3fd-200d-1f4bb", native: "\u{1F468}\u{1F3FD}\u200D\u{1F4BB}" }, { unified: "1f468-1f3fe-200d-1f4bb", native: "\u{1F468}\u{1F3FE}\u200D\u{1F4BB}" }, { unified: "1f468-1f3ff-200d-1f4bb", native: "\u{1F468}\u{1F3FF}\u200D\u{1F4BB}" }], version: 4 }, "female-technologist": { id: "female-technologist", name: "Woman Technologist", keywords: ["female", "coder", "developer", "engineer", "programmer", "software", "human", "laptop", "computer"], skins: [{ unified: "1f469-200d-1f4bb", native: "\u{1F469}\u200D\u{1F4BB}" }, { unified: "1f469-1f3fb-200d-1f4bb", native: "\u{1F469}\u{1F3FB}\u200D\u{1F4BB}" }, { unified: "1f469-1f3fc-200d-1f4bb", native: "\u{1F469}\u{1F3FC}\u200D\u{1F4BB}" }, { unified: "1f469-1f3fd-200d-1f4bb", native: "\u{1F469}\u{1F3FD}\u200D\u{1F4BB}" }, { unified: "1f469-1f3fe-200d-1f4bb", native: "\u{1F469}\u{1F3FE}\u200D\u{1F4BB}" }, { unified: "1f469-1f3ff-200d-1f4bb", native: "\u{1F469}\u{1F3FF}\u200D\u{1F4BB}" }], version: 4 }, singer: { id: "singer", name: "Singer", keywords: ["song", "artist", "performer"], skins: [{ unified: "1f9d1-200d-1f3a4", native: "\u{1F9D1}\u200D\u{1F3A4}" }, { unified: "1f9d1-1f3fb-200d-1f3a4", native: "\u{1F9D1}\u{1F3FB}\u200D\u{1F3A4}" }, { unified: "1f9d1-1f3fc-200d-1f3a4", native: "\u{1F9D1}\u{1F3FC}\u200D\u{1F3A4}" }, { unified: "1f9d1-1f3fd-200d-1f3a4", native: "\u{1F9D1}\u{1F3FD}\u200D\u{1F3A4}" }, { unified: "1f9d1-1f3fe-200d-1f3a4", native: "\u{1F9D1}\u{1F3FE}\u200D\u{1F3A4}" }, { unified: "1f9d1-1f3ff-200d-1f3a4", native: "\u{1F9D1}\u{1F3FF}\u200D\u{1F3A4}" }], version: 12.1 }, "male-singer": { id: "male-singer", name: "Man Singer", keywords: ["male", "rockstar", "entertainer", "human"], skins: [{ unified: "1f468-200d-1f3a4", native: "\u{1F468}\u200D\u{1F3A4}" }, { unified: "1f468-1f3fb-200d-1f3a4", native: "\u{1F468}\u{1F3FB}\u200D\u{1F3A4}" }, { unified: "1f468-1f3fc-200d-1f3a4", native: "\u{1F468}\u{1F3FC}\u200D\u{1F3A4}" }, { unified: "1f468-1f3fd-200d-1f3a4", native: "\u{1F468}\u{1F3FD}\u200D\u{1F3A4}" }, { unified: "1f468-1f3fe-200d-1f3a4", native: "\u{1F468}\u{1F3FE}\u200D\u{1F3A4}" }, { unified: "1f468-1f3ff-200d-1f3a4", native: "\u{1F468}\u{1F3FF}\u200D\u{1F3A4}" }], version: 4 }, "female-singer": { id: "female-singer", name: "Woman Singer", keywords: ["female", "rockstar", "entertainer", "human"], skins: [{ unified: "1f469-200d-1f3a4", native: "\u{1F469}\u200D\u{1F3A4}" }, { unified: "1f469-1f3fb-200d-1f3a4", native: "\u{1F469}\u{1F3FB}\u200D\u{1F3A4}" }, { unified: "1f469-1f3fc-200d-1f3a4", native: "\u{1F469}\u{1F3FC}\u200D\u{1F3A4}" }, { unified: "1f469-1f3fd-200d-1f3a4", native: "\u{1F469}\u{1F3FD}\u200D\u{1F3A4}" }, { unified: "1f469-1f3fe-200d-1f3a4", native: "\u{1F469}\u{1F3FE}\u200D\u{1F3A4}" }, { unified: "1f469-1f3ff-200d-1f3a4", native: "\u{1F469}\u{1F3FF}\u200D\u{1F3A4}" }], version: 4 }, artist: { id: "artist", name: "Artist", keywords: ["painting", "draw", "creativity"], skins: [{ unified: "1f9d1-200d-1f3a8", native: "\u{1F9D1}\u200D\u{1F3A8}" }, { unified: "1f9d1-1f3fb-200d-1f3a8", native: "\u{1F9D1}\u{1F3FB}\u200D\u{1F3A8}" }, { unified: "1f9d1-1f3fc-200d-1f3a8", native: "\u{1F9D1}\u{1F3FC}\u200D\u{1F3A8}" }, { unified: "1f9d1-1f3fd-200d-1f3a8", native: "\u{1F9D1}\u{1F3FD}\u200D\u{1F3A8}" }, { unified: "1f9d1-1f3fe-200d-1f3a8", native: "\u{1F9D1}\u{1F3FE}\u200D\u{1F3A8}" }, { unified: "1f9d1-1f3ff-200d-1f3a8", native: "\u{1F9D1}\u{1F3FF}\u200D\u{1F3A8}" }
51763], version: 12.1 }, "male-artist": { id: "male-artist", name: "Man Artist", keywords: ["male", "painter", "human"], skins: [{ unified: "1f468-200d-1f3a8", native: "\u{1F468}\u200D\u{1F3A8}" }, { unified: "1f468-1f3fb-200d-1f3a8", native: "\u{1F468}\u{1F3FB}\u200D\u{1F3A8}" }, { unified: "1f468-1f3fc-200d-1f3a8", native: "\u{1F468}\u{1F3FC}\u200D\u{1F3A8}" }, { unified: "1f468-1f3fd-200d-1f3a8", native: "\u{1F468}\u{1F3FD}\u200D\u{1F3A8}" }, { unified: "1f468-1f3fe-200d-1f3a8", native: "\u{1F468}\u{1F3FE}\u200D\u{1F3A8}" }, { unified: "1f468-1f3ff-200d-1f3a8", native: "\u{1F468}\u{1F3FF}\u200D\u{1F3A8}" }], version: 4 }, "female-artist": { id: "female-artist", name: "Woman Artist", keywords: ["female", "painter", "human"], skins: [{ unified: "1f469-200d-1f3a8", native: "\u{1F469}\u200D\u{1F3A8}" }, { unified: "1f469-1f3fb-200d-1f3a8", native: "\u{1F469}\u{1F3FB}\u200D\u{1F3A8}" }, { unified: "1f469-1f3fc-200d-1f3a8", native: "\u{1F469}\u{1F3FC}\u200D\u{1F3A8}" }, { unified: "1f469-1f3fd-200d-1f3a8", native: "\u{1F469}\u{1F3FD}\u200D\u{1F3A8}" }, { unified: "1f469-1f3fe-200d-1f3a8", native: "\u{1F469}\u{1F3FE}\u200D\u{1F3A8}" }, { unified: "1f469-1f3ff-200d-1f3a8", native: "\u{1F469}\u{1F3FF}\u200D\u{1F3A8}" }], version: 4 }, pilot: { id: "pilot", name: "Pilot", keywords: ["fly", "plane", "airplane"], skins: [{ unified: "1f9d1-200d-2708-fe0f", native: "\u{1F9D1}\u200D\u2708\uFE0F" }, { unified: "1f9d1-1f3fb-200d-2708-fe0f", native: "\u{1F9D1}\u{1F3FB}\u200D\u2708\uFE0F" }, { unified: "1f9d1-1f3fc-200d-2708-fe0f", native: "\u{1F9D1}\u{1F3FC}\u200D\u2708\uFE0F" }, { unified: "1f9d1-1f3fd-200d-2708-fe0f", native: "\u{1F9D1}\u{1F3FD}\u200D\u2708\uFE0F" }, { unified: "1f9d1-1f3fe-200d-2708-fe0f", native: "\u{1F9D1}\u{1F3FE}\u200D\u2708\uFE0F" }, { unified: "1f9d1-1f3ff-200d-2708-fe0f", native: "\u{1F9D1}\u{1F3FF}\u200D\u2708\uFE0F" }], version: 12.1 }, "male-pilot": { id: "male-pilot", name: "Man Pilot", keywords: ["male", "aviator", "plane", "human"], skins: [{ unified: "1f468-200d-2708-fe0f", native: "\u{1F468}\u200D\u2708\uFE0F" }, { unified: "1f468-1f3fb-200d-2708-fe0f", native: "\u{1F468}\u{1F3FB}\u200D\u2708\uFE0F" }, { unified: "1f468-1f3fc-200d-2708-fe0f", native: "\u{1F468}\u{1F3FC}\u200D\u2708\uFE0F" }, { unified: "1f468-1f3fd-200d-2708-fe0f", native: "\u{1F468}\u{1F3FD}\u200D\u2708\uFE0F" }, { unified: "1f468-1f3fe-200d-2708-fe0f", native: "\u{1F468}\u{1F3FE}\u200D\u2708\uFE0F" }, { unified: "1f468-1f3ff-200d-2708-fe0f", native: "\u{1F468}\u{1F3FF}\u200D\u2708\uFE0F" }], version: 4 }, "female-pilot": { id: "female-pilot", name: "Woman Pilot", keywords: ["female", "aviator", "plane", "human"], skins: [{ unified: "1f469-200d-2708-fe0f", native: "\u{1F469}\u200D\u2708\uFE0F" }, { unified: "1f469-1f3fb-200d-2708-fe0f", native: "\u{1F469}\u{1F3FB}\u200D\u2708\uFE0F" }, { unified: "1f469-1f3fc-200d-2708-fe0f", native: "\u{1F469}\u{1F3FC}\u200D\u2708\uFE0F" }, { unified: "1f469-1f3fd-200d-2708-fe0f", native: "\u{1F469}\u{1F3FD}\u200D\u2708\uFE0F" }, { unified: "1f469-1f3fe-200d-2708-fe0f", native: "\u{1F469}\u{1F3FE}\u200D\u2708\uFE0F" }, { unified: "1f469-1f3ff-200d-2708-fe0f", native: "\u{1F469}\u{1F3FF}\u200D\u2708\uFE0F" }], version: 4 }, astronaut: { id: "astronaut", name: "Astronaut", keywords: ["outerspace"], skins: [{ unified: "1f9d1-200d-1f680", native: "\u{1F9D1}\u200D\u{1F680}" }, { unified: "1f9d1-1f3fb-200d-1f680", native: "\u{1F9D1}\u{1F3FB}\u200D\u{1F680}" }, { unified: "1f9d1-1f3fc-200d-1f680", native: "\u{1F9D1}\u{1F3FC}\u200D\u{1F680}" }, { unified: "1f9d1-1f3fd-200d-1f680", native: "\u{1F9D1}\u{1F3FD}\u200D\u{1F680}" }, { unified: "1f9d1-1f3fe-200d-1f680", native: "\u{1F9D1}\u{1F3FE}\u200D\u{1F680}" }, { unified: "1f9d1-1f3ff-200d-1f680", native: "\u{1F9D1}\u{1F3FF}\u200D\u{1F680}" }], version: 12.1 }, "male-astronaut": { id: "male-astronaut", name: "Man Astronaut", keywords: ["male", "space", "rocket", "human"], skins: [{ unified: "1f468-200d-1f680", native: "\u{1F468}\u200D\u{1F680}" }, { unified: "1f468-1f3fb-200d-1f680", native: "\u{1F468}\u{1F3FB}\u200D\u{1F680}" }, { unified: "1f468-1f3fc-200d-1f680", native: "\u{1F468}\u{1F3FC}\u200D\u{1F680}" }, { unified: "1f468-1f3fd-200d-1f680", native: "\u{1F468}\u{1F3FD}\u200D\u{1F680}" }, { unified: "1f468-1f3fe-200d-1f680", native: "\u{1F468}\u{1F3FE}\u200D\u{1F680}" }, { unified: "1f468-1f3ff-200d-1f680", native: "\u{1F468}\u{1F3FF}\u200D\u{1F680}" }], version: 4 }, "female-astronaut": { id: "female-astronaut", name: "Woman Astronaut", keywords: ["female", "space", "rocket", "human"], skins: [{ unified: "1f469-200d-1f680", native: "\u{1F469}\u200D\u{1F680}" }, { unified: "1f469-1f3fb-200d-1f680", native: "\u{1F469}\u{1F3FB}\u200D\u{1F680}" }, { unified: "1f469-1f3fc-200d-1f680", native: "\u{1F469}\u{1F3FC}\u200D\u{1F680}" }, { unified: "1f469-1f3fd-200d-1f680", native: "\u{1F469}\u{1F3FD}\u200D\u{1F680}" }, { unified: "1f469-1f3fe-200d-1f680", native: "\u{1F469}\u{1F3FE}\u200D\u{1F680}" }, { unified: "1f469-1f3ff-200d-1f680", native: "\u{1F469}\u{1F3FF}\u200D\u{1F680}" }], version: 4 }, firefighter: { id: "firefighter", name: "Firefighter", keywords: ["fire"], skins: [{ unified: "1f9d1-200d-1f692", native: "\u{1F9D1}\u200D\u{1F692}" }, { unified: "1f9d1-1f3fb-200d-1f692", native: "\u{1F9D1}\u{1F3FB}\u200D\u{1F692}" }, { unified: "1f9d1-1f3fc-200d-1f692", native: "\u{1F9D1}\u{1F3FC}\u200D\u{1F692}" }, { unified: "1f9d1-1f3fd-200d-1f692", native: "\u{1F9D1}\u{1F3FD}\u200D\u{1F692}" }, { unified: "1f9d1-1f3fe-200d-1f692", native: "\u{1F9D1}\u{1F3FE}\u200D\u{1F692}" }, { unified: "1f9d1-1f3ff-200d-1f692", native: "\u{1F9D1}\u{1F3FF}\u200D\u{1F692}" }], version: 12.1 }, "male-firefighter": { id: "male-firefighter", name: "Man Firefighter", keywords: ["male", "fireman", "human"], skins: [{ unified: "1f468-200d-1f692", native: "\u{1F468}\u200D\u{1F692}" }, { unified: "1f468-1f3fb-200d-1f692", native: "\u{1F468}\u{1F3FB}\u200D\u{1F692}" }, { unified: "1f468-1f3fc-200d-1f692", native: "\u{1F468}\u{1F3FC}\u200D\u{1F692}" }, { unified: "1f468-1f3fd-200d-1f692", native: "\u{1F468}\u{1F3FD}\u200D\u{1F692}" }, { unified: "1f468-1f3fe-200d-1f692", native: "\u{1F468}\u{1F3FE}\u200D\u{1F692}" }, { unified: "1f468-1f3ff-200d-1f692", native: "\u{1F468}\u{1F3FF}\u200D\u{1F692}" }], version: 4 }, "female-firefighter": { id: "female-firefighter", name: "Woman Firefighter", keywords: ["female", "fireman", "human"], skins: [{ unified: "1f469-200d-1f692", native: "\u{1F469}\u200D\u{1F692}" }, { unified: "1f469-1f3fb-200d-1f692", native: "\u{1F469}\u{1F3FB}\u200D\u{1F692}" }, { unified: "1f469-1f3fc-200d-1f692", native: "\u{1F469}\u{1F3FC}\u200D\u{1F692}" }, { unified: "1f469-1f3fd-200d-1f692", native: "\u{1F469}\u{1F3FD}\u200D\u{1F692}" }, { unified: "1f469-1f3fe-200d-1f692", native: "\u{1F469}\u{1F3FE}\u200D\u{1F692}" }, { unified: "1f469-1f3ff-200d-1f692", native: "\u{1F469}\u{1F3FF}\u200D\u{1F692}" }], version: 4 }
51763, cop: { id: "cop", name: "Police Officer", keywords: ["cop"], skins: [{ unified: "1f46e", native: "\u{1F46E}" }, { unified: "1f46e-1f3fb", native: "\u{1F46E}\u{1F3FB}" }, { unified: "1f46e-1f3fc", native: "\u{1F46E}\u{1F3FC}" }, { unified: "1f46e-1f3fd", native: "\u{1F46E}\u{1F3FD}" }, { unified: "1f46e-1f3fe", native: "\u{1F46E}\u{1F3FE}" }, { unified: "1f46e-1f3ff", native: "\u{1F46E}\u{1F3FF}" }], version: 1 }, "male-police-officer": { id: "male-police-officer", name: "Man Police Officer", keywords: ["male", "police-officer", "law", "legal", "enforcement", "arrest", "911"], skins: [{ unified: "1f46e-200d-2642-fe0f", native: "\u{1F46E}\u200D\u2642\uFE0F" }, { unified: "1f46e-1f3fb-200d-2642-fe0f", native: "\u{1F46E}\u{1F3FB}\u200D\u2642\uFE0F" }, { unified: "1f46e-1f3fc-200d-2642-fe0f", native: "\u{1F46E}\u{1F3FC}\u200D\u2642\uFE0F" }, { unified: "1f46e-1f3fd-200d-2642-fe0f", native: "\u{1F46E}\u{1F3FD}\u200D\u2642\uFE0F" }, { unified: "1f46e-1f3fe-200d-2642-fe0f", native: "\u{1F46E}\u{1F3FE}\u200D\u2642\uFE0F" }, { unified: "1f46e-1f3ff-200d-2642-fe0f", native: "\u{1F46E}\u{1F3FF}\u200D\u2642\uFE0F" }], version: 4 }, "female-police-officer": { id: "female-police-officer", name: "Woman Police Officer", keywords: ["female", "police-officer", "law", "legal", "enforcement", "arrest", "911"], skins: [{ unified: "1f46e-200d-2640-fe0f", native: "\u{1F46E}\u200D\u2640\uFE0F" }, { unified: "1f46e-1f3fb-200d-2640-fe0f", native: "\u{1F46E}\u{1F3FB}\u200D\u2640\uFE0F" }, { unified: "1f46e-1f3fc-200d-2640-fe0f", native: "\u{1F46E}\u{1F3FC}\u200D\u2640\uFE0F" }, { unified: "1f46e-1f3fd-200d-2640-fe0f", native: "\u{1F46E}\u{1F3FD}\u200D\u2640\uFE0F" }, { unified: "1f46e-1f3fe-200d-2640-fe0f", native: "\u{1F46E}\u{1F3FE}\u200D\u2640\uFE0F" }, { unified: "1f46e-1f3ff-200d-2640-fe0f", native: "\u{1F46E}\u{1F3FF}\u200D\u2640\uFE0F" }], version: 4 }, sleuth_or_spy: { id: "sleuth_or_spy", name: "Detective", keywords: ["sleuth", "or", "spy", "human"], skins: [{ unified: "1f575-fe0f", native: "\u{1F575}\uFE0F" }, { unified: "1f575-1f3fb", native: "\u{1F575}\u{1F3FB}" }, { unified: "1f575-1f3fc", native: "\u{1F575}\u{1F3FC}" }, { unified: "1f575-1f3fd", native: "\u{1F575}\u{1F3FD}" }, { unified: "1f575-1f3fe", native: "\u{1F575}\u{1F3FE}" }, { unified: "1f575-1f3ff", native: "\u{1F575}\u{1F3FF}" }], version: 1 }, "male-detective": { id: "male-detective", name: "Man Detective", keywords: ["male", "crime"], skins: [{ unified: "1f575-fe0f-200d-2642-fe0f", native: "\u{1F575}\uFE0F\u200D\u2642\uFE0F" }, { unified: "1f575-1f3fb-200d-2642-fe0f", native: "\u{1F575}\u{1F3FB}\u200D\u2642\uFE0F" }, { unified: "1f575-1f3fc-200d-2642-fe0f", native: "\u{1F575}\u{1F3FC}\u200D\u2642\uFE0F" }, { unified: "1f575-1f3fd-200d-2642-fe0f", native: "\u{1F575}\u{1F3FD}\u200D\u2642\uFE0F" }, { unified: "1f575-1f3fe-200d-2642-fe0f", native: "\u{1F575}\u{1F3FE}\u200D\u2642\uFE0F" }, { unified: "1f575-1f3ff-200d-2642-fe0f", native: "\u{1F575}\u{1F3FF}\u200D\u2642\uFE0F" }], version: 4 }, "female-detective": { id: "female-detective", name: "Woman Detective", keywords: ["female", "human", "spy"], skins: [{ unified: "1f575-fe0f-200d-2640-fe0f", native: "\u{1F575}\uFE0F\u200D\u2640\uFE0F" }, { unified: "1f575-1f3fb-200d-2640-fe0f", native: "\u{1F575}\u{1F3FB}\u200D\u2640\uFE0F" }, { unified: "1f575-1f3fc-200d-2640-fe0f", native: "\u{1F575}\u{1F3FC}\u200D\u2640\uFE0F" }, { unified: "1f575-1f3fd-200d-2640-fe0f", native: "\u{1F575}\u{1F3FD}\u200D\u2640\uFE0F" }, { unified: "1f575-1f3fe-200d-2640-fe0f", native: "\u{1F575}\u{1F3FE}\u200D\u2640\uFE0F" }, { unified: "1f575-1f3ff-200d-2640-fe0f", native: "\u{1F575}\u{1F3FF}\u200D\u2640\uFE0F" }], version: 4 }, guardsman: { id: "guardsman", name: "Guard", keywords: ["guardsman", "protect"], skins: [{ unified: "1f482", native: "\u{1F482}" }, { unified: "1f482-1f3fb", native: "\u{1F482}\u{1F3FB}" }, { unified: "1f482-1f3fc", native: "\u{1F482}\u{1F3FC}" }, { unified: "1f482-1f3fd", native: "\u{1F482}\u{1F3FD}" }, { unified: "1f482-1f3fe", native: "\u{1F482}\u{1F3FE}" }, { unified: "1f482-1f3ff", native: "\u{1F482}\u{1F3FF}" }], version: 1 }, "male-guard": { id: "male-guard", name: "Man Guard", keywords: ["male", "uk", "gb", "british", "guy", "royal"], skins: [{ unified: "1f482-200d-2642-fe0f", native: "\u{1F482}\u200D\u2642\uFE0F" }, { unified: "1f482-1f3fb-200d-2642-fe0f", native: "\u{1F482}\u{1F3FB}\u200D\u2642\uFE0F" }, { unified: "1f482-1f3fc-200d-2642-fe0f", native: "\u{1F482}\u{1F3FC}\u200D\u2642\uFE0F" }, { unified: "1f482-1f3fd-200d-2642-fe0f", native: "\u{1F482}\u{1F3FD}\u200D\u2642\uFE0F" }, { unified: "1f482-1f3fe-200d-2642-fe0f", native: "\u{1F482}\u{1F3FE}\u200D\u2642\uFE0F" }, { unified: "1f482-1f3ff-200d-2642-fe0f", native: "\u{1F482}\u{1F3FF}\u200D\u2642\uFE0F" }], version: 4 }, "female-guard": { id: "female-guard", name: "Woman Guard", keywords: ["female", "uk", "gb", "british", "royal"], skins: [{ unified: "1f482-200d-2640-fe0f", native: "\u{1F482}\u200D\u2640\uFE0F" }, { unified: "1f482-1f3fb-200d-2640-fe0f", native: "\u{1F482}\u{1F3FB}\u200D\u2640\uFE0F" }, { unified: "1f482-1f3fc-200d-2640-fe0f", native: "\u{1F482}\u{1F3FC}\u200D\u2640\uFE0F" }, { unified: "1f482-1f3fd-200d-2640-fe0f", native: "\u{1F482}\u{1F3FD}\u200D\u2640\uFE0F" }, { unified: "1f482-1f3fe-200d-2640-fe0f", native: "\u{1F482}\u{1F3FE}\u200D\u2640\uFE0F" }, { unified: "1f482-1f3ff-200d-2640-fe0f", native: "\u{1F482}\u{1F3FF}\u200D\u2640\uFE0F" }], version: 4 }, ninja: { id: "ninja", name: "Ninja", keywords: ["ninjutsu", "skills", "japanese"], skins: [{ unified: "1f977", native: "\u{1F977}" }, { unified: "1f977-1f3fb", native: "\u{1F977}\u{1F3FB}" }, { unified: "1f977-1f3fc", native: "\u{1F977}\u{1F3FC}" }, { unified: "1f977-1f3fd", native: "\u{1F977}\u{1F3FD}" }, { unified: "1f977-1f3fe", native: "\u{1F977}\u{1F3FE}" }, { unified: "1f977-1f3ff", native: "\u{1F977}\u{1F3FF}" }], version: 13 }
51763, construction_worker: { id: "construction_worker", name: "Construction Worker", keywords: ["labor", "build"], skins: [{ unified: "1f477", native: "\u{1F477}" }, { unified: "1f477-1f3fb", native: "\u{1F477}\u{1F3FB}" }, { unified: "1f477-1f3fc", native: "\u{1F477}\u{1F3FC}" }, { unified: "1f477-1f3fd", native: "\u{1F477}\u{1F3FD}" }, { unified: "1f477-1f3fe", native: "\u{1F477}\u{1F3FE}" }, { unified: "1f477-1f3ff", native: "\u{1F477}\u{1F3FF}" }], version: 1 }, "male-construction-worker": { id: "male-construction-worker", name: "Man Construction Worker", keywords: ["male", "construction-worker", "human", "wip", "guy", "build", "labor"], skins: [{ unified: "1f477-200d-2642-fe0f", native: "\u{1F477}\u200D\u2642\uFE0F" }, { unified: "1f477-1f3fb-200d-2642-fe0f", native: "\u{1F477}\u{1F3FB}\u200D\u2642\uFE0F" }, { unified: "1f477-1f3fc-200d-2642-fe0f", native: "\u{1F477}\u{1F3FC}\u200D\u2642\uFE0F" }, { unified: "1f477-1f3fd-200d-2642-fe0f", native: "\u{1F477}\u{1F3FD}\u200D\u2642\uFE0F" }, { unified: "1f477-1f3fe-200d-2642-fe0f", native: "\u{1F477}\u{1F3FE}\u200D\u2642\uFE0F" }, { unified: "1f477-1f3ff-200d-2642-fe0f", native: "\u{1F477}\u{1F3FF}\u200D\u2642\uFE0F" }], version: 4 }, "female-construction-worker": { id: "female-construction-worker", name: "Woman Construction Worker", keywords: ["female", "construction-worker", "human", "wip", "build", "labor"], skins: [{ unified: "1f477-200d-2640-fe0f", native: "\u{1F477}\u200D\u2640\uFE0F" }, { unified: "1f477-1f3fb-200d-2640-fe0f", native: "\u{1F477}\u{1F3FB}\u200D\u2640\uFE0F" }, { unified: "1f477-1f3fc-200d-2640-fe0f", native: "\u{1F477}\u{1F3FC}\u200D\u2640\uFE0F" }, { unified: "1f477-1f3fd-200d-2640-fe0f", native: "\u{1F477}\u{1F3FD}\u200D\u2640\uFE0F" }, { unified: "1f477-1f3fe-200d-2640-fe0f", native: "\u{1F477}\u{1F3FE}\u200D\u2640\uFE0F" }, { unified: "1f477-1f3ff-200d-2640-fe0f", native: "\u{1F477}\u{1F3FF}\u200D\u2640\uFE0F" }], version: 4 }, person_with_crown: { id: "person_with_crown", name: "Person with Crown", keywords: ["royalty", "power"], skins: [{ unified: "1fac5", native: "\u{1FAC5}" }, { unified: "1fac5-1f3fb", native: "\u{1FAC5}\u{1F3FB}" }, { unified: "1fac5-1f3fc", native: "\u{1FAC5}\u{1F3FC}" }, { unified: "1fac5-1f3fd", native: "\u{1FAC5}\u{1F3FD}" }, { unified: "1fac5-1f3fe", native: "\u{1FAC5}\u{1F3FE}" }, { unified: "1fac5-1f3ff", native: "\u{1FAC5}\u{1F3FF}" }], version: 14 }, prince: { id: "prince", name: "Prince", keywords: ["boy", "man", "male", "crown", "royal", "king"], skins: [{ unified: "1f934", native: "\u{1F934}" }, { unified: "1f934-1f3fb", native: "\u{1F934}\u{1F3FB}" }, { unified: "1f934-1f3fc", native: "\u{1F934}\u{1F3FC}" }, { unified: "1f934-1f3fd", native: "\u{1F934}\u{1F3FD}" }, { unified: "1f934-1f3fe", native: "\u{1F934}\u{1F3FE}" }, { unified: "1f934-1f3ff", native: "\u{1F934}\u{1F3FF}" }], version: 3 }, princess: { id: "princess", name: "Princess", keywords: ["girl", "woman", "female", "blond", "crown", "royal", "queen"], skins: [{ unified: "1f478", native: "\u{1F478}" }, { unified: "1f478-1f3fb", native: "\u{1F478}\u{1F3FB}" }, { unified: "1f478-1f3fc", native: "\u{1F478}\u{1F3FC}" }, { unified: "1f478-1f3fd", native: "\u{1F478}\u{1F3FD}" }, { unified: "1f478-1f3fe", native: "\u{1F478}\u{1F3FE}" }, { unified: "1f478-1f3ff", native: "\u{1F478}\u{1F3FF}" }], version: 1 }, man_with_turban: { id: "man_with_turban", name: "Man with Turban", keywords: ["person", "wearing", "headdress"], skins: [{ unified: "1f473", native: "\u{1F473}" }, { unified: "1f473-1f3fb", native: "\u{1F473}\u{1F3FB}" }, { unified: "1f473-1f3fc", native: "\u{1F473}\u{1F3FC}" }, { unified: "1f473-1f3fd", native: "\u{1F473}\u{1F3FD}" }, { unified: "1f473-1f3fe", native: "\u{1F473}\u{1F3FE}" }, { unified: "1f473-1f3ff", native: "\u{1F473}\u{1F3FF}" }], version: 1 }, "man-wearing-turban": { id: "man-wearing-turban", name: "Man Wearing Turban", keywords: ["wearing-turban", "male", "indian", "hinduism", "arabs"], skins: [{ unified: "1f473-200d-2642-fe0f", native: "\u{1F473}\u200D\u2642\uFE0F" }, { unified: "1f473-1f3fb-200d-2642-fe0f", native: "\u{1F473}\u{1F3FB}\u200D\u2642\uFE0F" }, { unified: "1f473-1f3fc-200d-2642-fe0f", native: "\u{1F473}\u{1F3FC}\u200D\u2642\uFE0F" }, { unified: "1f473-1f3fd-200d-2642-fe0f", native: "\u{1F473}\u{1F3FD}\u200D\u2642\uFE0F" }, { unified: "1f473-1f3fe-200d-2642-fe0f", native: "\u{1F473}\u{1F3FE}\u200D\u2642\uFE0F" }, { unified: "1f473-1f3ff-200d-2642-fe0f", native: "\u{1F473}\u{1F3FF}\u200D\u2642\uFE0F" }], version: 4 }, "woman-wearing-turban": { id: "woman-wearing-turban", name: "Woman Wearing Turban", keywords: ["wearing-turban", "female", "indian", "hinduism", "arabs"], skins: [{ unified: "1f473-200d-2640-fe0f", native: "\u{1F473}\u200D\u2640\uFE0F" }, { unified: "1f473-1f3fb-200d-2640-fe0f", native: "\u{1F473}\u{1F3FB}\u200D\u2640\uFE0F" }, { unified: "1f473-1f3fc-200d-2640-fe0f", native: "\u{1F473}\u{1F3FC}\u200D\u2640\uFE0F" }, { unified: "1f473-1f3fd-200d-2640-fe0f", native: "\u{1F473}\u{1F3FD}\u200D\u2640\uFE0F" }, { unified: "1f473-1f3fe-200d-2640-fe0f", native: "\u{1F473}\u{1F3FE}\u200D\u2640\uFE0F" }, { unified: "1f473-1f3ff-200d-2640-fe0f", native: "\u{1F473}\u{1F3FF}\u200D\u2640\uFE0F" }], version: 4 }, man_with_gua_pi_mao: { id: "man_with_gua_pi_mao", name: "Man with Gua Pi Mao", keywords: ["skullcap", "male", "boy", "chinese"], skins: [{ unified: "1f472", native: "\u{1F472}" }, { unified: "1f472-1f3fb", native: "\u{1F472}\u{1F3FB}" }, { unified: "1f472-1f3fc", native: "\u{1F472}\u{1F3FC}" }, { unified: "1f472-1f3fd", native: "\u{1F472}\u{1F3FD}" }, { unified: "1f472-1f3fe", native: "\u{1F472}\u{1F3FE}" }, { unified: "1f472-1f3ff", native: "\u{1F472}\u{1F3FF}" }], version: 1 }, person_with_headscarf: { id: "person_with_headscarf", name: "Woman with Headscarf", keywords: ["person", "female", "hijab", "mantilla", "tichel"], skins: [{ unified: "1f9d5", native: "\u{1F9D5}" }, { unified: "1f9d5-1f3fb", native: "\u{1F9D5}\u{1F3FB}" }, { unified: "1f9d5-1f3fc", native: "\u{1F9D5}\u{1F3FC}" }, { unified: "1f9d5-1f3fd", native: "\u{1F9D5}\u{1F3FD}" }, { unified: "1f9d5-1f3fe", native: "\u{1F9D5}\u{1F3FE}" }, { unified: "1f9d5-1f3ff", native: "\u{1F9D5}\u{1F3FF}" }], version: 5 }, person_in_tuxedo: { id: "person_in_tuxedo", name: "Man in Tuxedo", keywords: ["person", "couple", "marriage", "wedding", "groom"], skins: [{ unified: "1f935", native: "\u{1F935}" }, { unified: "1f935-1f3fb", native: "\u{1F935}\u{1F3FB}" }, { unified: "1f935-1f3fc", native: "\u{1F935}\u{1F3FC}" }, { unified: "1f935-1f3fd", native: "\u{1F935}\u{1F3FD}" }, { unified: "1f935-1f3fe", native: "\u{1F935}\u{1F3FE}" }, { unified: "1f935-1f3ff", native: "\u{1F935}\u{1F3FF}" }], version: 3 }, man_in_tuxedo: { id: "man_in_tuxedo", name: "Man in Tuxedo", keywords: ["formal", "fashion"], skins: [{ unified: "1f935-200d-2642-fe0f", native: "\u{1F935}\u200D\u2642\uFE0F" }, { unified: "1f935-1f3fb-200d-2642-fe0f", native: "\u{1F935}\u{1F3FB}\u200D\u2642\uFE0F" }, { unified: "1f935-1f3fc-200d-2642-fe0f", native: "\u{1F935}\u{1F3FC}\u200D\u2642\uFE0F" }, { unified: "1f935-1f3fd-200d-2642-fe0f", native: "\u{1F935}\u{1F3FD}\u200D\u2642\uFE0F" }, { unified: "1f935-1f3fe-200d-2642-fe0f", native: "\u{1F935}\u{1F3FE}\u200D\u2642\uFE0F" }, { unified: "1f935-1f3ff-200d-2642-fe0f", native: "\u{1F935}\u{1F3FF}\u200D\u2642\uFE0F" }], version: 13 }, woman_in_tuxedo: { id: "woman_in_tuxedo", name: "Woman in Tuxedo", keywords: ["formal", "fashion"], skins: [{ unified: "1f935-200d-2640-fe0f", native: "\u{1F935}\u200D\u2640\uFE0F" }, { unified: "1f935-1f3fb-200d-2640-fe0f", native: "\u{1F935}\u{1F3FB}\u200D\u2640\uFE0F" }, { unified: "1f935-1f3fc-200d-2640-fe0f", native: "\u{1F935}\u{1F3FC}\u200D\u2640\uFE0F" }, { unified: "1f935-1f3fd-200d-2640-fe0f", native: "\u{1F935}\u{1F3FD}\u200D\u2640\uFE0F" }, { unified: "1f935-1f3fe-200d-2640-fe0f", native: "\u{1F935}\u{1F3FE}\u200D\u2640\uFE0F" }, { unified: "1f935-1f3ff-200d-2640-fe0f", native: "\u{1F935}\u{1F3FF}\u200D\u2640\uFE0F" }], version: 13 }, bride_with_veil: { id: "bride_with_veil", name: "Bride with Veil", keywords: ["couple", "marriage", "wedding", "woman"], skins: [{ unified: "1f470", native: "\u{1F470}" }, { unified: "1f470-1f3fb", native: "\u{1F470}\u{1F3FB}" }, { unified: "1f470-1f3fc", native: "\u{1F470}\u{1F3FC}" }, { unified: "1f470-1f3fd", native: "\u{1F470}\u{1F3FD}" }, { unified: "1f470-1f3fe", native: "\u{1F470}\u{1F3FE}" }, { unified: "1f470-1f3ff", native: "\u{1F470}\u{1F3FF}" }], version: 1 }, man_with_veil: { id: "man_with_veil", name: "Man with Veil", keywords: ["wedding", "marriage"], skins: [{ unified: "1f470-200d-2642-fe0f", native: "\u{1F470}\u200D\u2642\uFE0F" }, { unified: "1f470-1f3fb-200d-2642-fe0f", native: "\u{1F470}\u{1F3FB}\u200D\u2642\uFE0F" }, { unified: "1f470-1f3fc-200d-2642-fe0f", native: "\u{1F470}\u{1F3FC}\u200D\u2642\uFE0F" }, { unified: "1f470-1f3fd-200d-2642-fe0f", native: "\u{1F470}\u{1F3FD}\u200D\u2642\uFE0F" }, { unified: "1f470-1f3fe-200d-2642-fe0f", native: "\u{1F470}\u{1F3FE}\u200D\u2642\uFE0F" }, { unified: "1f470-1f3ff-200d-2642-fe0f", native: "\u{1F470}\u{1F3FF}\u200D\u2642\uFE0F" }], version: 13 }, woman_with_veil: { id: "woman_with_veil", name: "Woman with Veil", keywords: ["wedding", "marriage"], skins: [{ unified: "1f470-200d-2640-fe0f", native: "\u{1F470}\u200D\u2640\uFE0F" }, { unified: "1f470-1f3fb-200d-2640-fe0f", native: "\u{1F470}\u{1F3FB}\u200D\u2640\uFE0F" }, { unified: "1f470-1f3fc-200d-2640-fe0f", native: "\u{1F470}\u{1F3FC}\u200D\u2640\uFE0F" }, { unified: "1f470-1f3fd-200d-2640-fe0f", native: "\u{1F470}\u{1F3FD}\u200D\u2640\uFE0F" }, { unified: "1f470-1f3fe-200d-2640-fe0f", native: "\u{1F470}\u{1F3FE}\u200D\u2640\uFE0F" }, { unified: "1f470-1f3ff-200d-2640-fe0f", native: "\u{1F470}\u{1F3FF}\u200D\u2640\uFE0F" }], version: 13 }, pregnant_woman: { id: "pregnant_woman", name: "Pregnant Woman", keywords: ["baby"], skins: [{ unified: "1f930", native: "\u{1F930}" }, { unified: "1f930-1f3fb", native: "\u{1F930}\u{1F3FB}" }, { unified: "1f930-1f3fc", native: "\u{1F930}\u{1F3FC}" }, { unified: "1f930-1f3fd", native: "\u{1F930}\u{1F3FD}" }, { unified: "1f930-1f3fe", native: "\u{1F930}\u{1F3FE}" }, { unified: "1f930-1f3ff", native: "\u{1F930}\u{1F3FF}" }], version: 3 }, pregnant_man: { id: "pregnant_man", name: "Pregnant Man", keywords: ["baby", "belly"], skins: [{ unified: "1fac3", native: "\u{1FAC3}" }, { unified: "1fac3-1f3fb", native: "\u{1FAC3}\u{1F3FB}" }, { unified: "1fac3-1f3fc", native: "\u{1FAC3}\u{1F3FC}" }, { unified: "1fac3-1f3fd", native: "\u{1FAC3}\u{1F3FD}" }, { unified: "1fac3-1f3fe", native: "\u{1FAC3}\u{1F3FE}" }, { unified: "1fac3-1f3ff", native: "\u{1FAC3}\u{1F3FF}" }], version: 14 }, pregnant_person: { id: "pregnant_person", name: "Pregnant Person", keywords: ["baby", "belly"], skins: [{ unified: "1fac4", native: "\u{1FAC4}" }, { unified: "1fac4-1f3fb", native: "\u{1FAC4}\u{1F3FB}" }, { unified: "1fac4-1f3fc", native: "\u{1FAC4}\u{1F3FC}" }, { unified: "1fac4-1f3fd", native: "\u{1FAC4}\u{1F3FD}" }, { unified: "1fac4-1f3fe", native: "\u{1FAC4}\u{1F3FE}" }, { unified: "1fac4-1f3ff", native: "\u{1FAC4}\u{1F3FF}" }], version: 14 }, "breast-feeding": { id: "breast-feeding", name: "Breast-Feeding", keywords: ["breast", "feeding", "nursing", "baby"], skins: [{ unified: "1f931", native: "\u{1F931}" }, { unified: "1f931-1f3fb", native: "\u{1F931}\u{1F3FB}" }, { unified: "1f931-1f3fc", native: "\u{1F931}\u{1F3FC}" }, { unified: "1f931-1f3fd", native: "\u{1F931}\u{1F3FD}" }, { unified: "1f931-1f3fe", native: "\u{1F931}\u{1F3FE}" }, { unified: "1f931-1f3ff", native: "\u{1F931}\u{1F3FF}" }], version: 5 }, woman_feeding_baby: { id: "woman_feeding_baby", name: "Woman Feeding Baby", keywords: ["birth", "food"], skins: [{ unified: "1f469-200d-1f37c", native: "\u{1F469}\u200D\u{1F37C}" }, { unified: "1f469-1f3fb-200d-1f37c", native: "\u{1F469}\u{1F3FB}\u200D\u{1F37C}" }, { unified: "1f469-1f3fc-200d-1f37c", native: "\u{1F469}\u{1F3FC}\u200D\u{1F37C}" }, { unified: "1f469-1f3fd-200d-1f37c", native: "\u{1F469}\u{1F3FD}\u200D\u{1F37C}" }, { unified: "1f469-1f3fe-200d-1f37c", native: "\u{1F469}\u{1F3FE}\u200D\u{1F37C}" }, { unified: "1f469-1f3ff-200d-1f37c", native: "\u{1F469}\u{1F3FF}\u200D\u{1F37C}" }], version: 13 }, man_feeding_baby: { id: "man_feeding_baby", name: "Man Feeding Baby", keywords: ["birth", "food"], skins: [{ unified: "1f468-200d-1f37c", native: "\u{1F468}\u200D\u{1F37C}" }, { unified: "1f468-1f3fb-200d-1f37c", native: "\u{1F468}\u{1F3FB}\u200D\u{1F37C}" }, { unified: "1f468-1f3fc-200d-1f37c", native: "\u{1F468}\u{1F3FC}\u200D\u{1F37C}" }, { unified: "1f468-1f3fd-200d-1f37c", native: "\u{1F468}\u{1F3FD}\u200D\u{1F37C}" }, { unified: "1f468-1f3fe-200d-1f37c", native: "\u{1F468}\u{1F3FE}\u200D\u{1F37C}" }, { unified: "1f468-1f3ff-200d-1f37c", native: "\u{1F468}\u{1F3FF}\u200D\u{1F37C}" }], version: 13 }, person_feeding_baby: { id: "person_feeding_baby", name: "Person Feeding Baby", keywords: ["birth", "food"], skins: [{ unified: "1f9d1-200d-1f37c", native: "\u{1F9D1}\u200D\u{1F37C}" }, { unified: "1f9d1-1f3fb-200d-1f37c", native: "\u{1F9D1}\u{1F3FB}\u200D\u{1F37C}" }, { unified: "1f9d1-1f3fc-200d-1f37c", native: "\u{1F9D1}\u{1F3FC}\u200D\u{1F37C}" }, { unified: "1f9d1-1f3fd-200d-1f37c", native: "\u{1F9D1}\u{1F3FD}\u200D\u{1F37C}" }, { unified: "1f9d1-1f3fe-200d-1f37c", native: "\u{1F9D1}\u{1F3FE}\u200D\u{1F37C}" }, { unified: "1f9d1-1f3ff-200d-1f37c", native: "\u{1F9D1}\u{1F3FF}\u200D\u{1F37C}" }], version: 13 }, angel: { id: "angel", name: "Baby Angel", keywords: ["heaven", "wings", "halo"], skins: [{ unified: "1f47c", native: "\u{1F47C}" }, { unified: "1f47c-1f3fb", native: "\u{1F47C}\u{1F3FB}" }, { unified: "1f47c-1f3fc", native: "\u{1F47C}\u{1F3FC}" }, { unified: "1f47c-1f3fd", native: "\u{1F47C}\u{1F3FD}" }, { unified: "1f47c-1f3fe", native: "\u{1F47C}\u{1F3FE}" }, { unified: "1f47c-1f3ff", native: "\u{1F47C}\u{1F3FF}" }], version: 1 }, santa: { id: "santa", name: "Santa Claus", keywords: ["festival", "man", "male", "xmas", "father", "christmas"], skins: [{ unified: "1f385", native: "\u{1F385}" }, { unified: "1f385-1f3fb", native: "\u{1F385}\u{1F3FB}" }, { unified: "1f385-1f3fc", native: "\u{1F385}\u{1F3FC}" }, { unified: "1f385-1f3fd", native: "\u{1F385}\u{1F3FD}" }, { unified: "1f385-1f3fe", native: "\u{1F385}\u{1F3FE}" }, { unified: "1f385-1f3ff", native: "\u{1F385}\u{1F3FF}" }], version: 1 }, mrs_claus: { id: "mrs_claus", name: "Mrs. Claus", keywords: ["mrs", "mother", "christmas", "woman", "female", "xmas"], skins: [{ unified: "1f936", native: "\u{1F936}" }, { unified: "1f936-1f3fb", native: "\u{1F936}\u{1F3FB}" }, { unified: "1f936-1f3fc", native: "\u{1F936}\u{1F3FC}" }, { unified: "1f936-1f3fd", native: "\u{1F936}\u{1F3FD}" }, { unified: "1f936-1f3fe", native: "\u{1F936}\u{1F3FE}" }, { unified: "1f936-1f3ff", native: "\u{1F936}\u{1F3FF}" }], version: 3 }, mx_claus: { id: "mx_claus", name: "Mx Claus", keywords: ["christmas"], skins: [{ unified: "1f9d1-200d-1f384", native: "\u{1F9D1}\u200D\u{1F384}" }, { unified: "1f9d1-1f3fb-200d-1f384", native: "\u{1F9D1}\u{1F3FB}\u200D\u{1F384}" }, { unified: "1f9d1-1f3fc-200d-1f384", native: "\u{1F9D1}\u{1F3FC}\u200D\u{1F384}" }, { unified: "1f9d1-1f3fd-200d-1f384", native: "\u{1F9D1}\u{1F3FD}\u200D\u{1F384}" }, { unified: "1f9d1-1f3fe-200d-1f384", native: "\u{1F9D1}\u{1F3FE}\u200D\u{1F384}" }, { unified: "1f9d1-1f3ff-200d-1f384", native: "\u{1F9D1}\u{1F3FF}\u200D\u{1F384}" }], version: 13 }, superhero: { id: "superhero", name: "Superhero", keywords: ["marvel"], skins: [{ unified: "1f9b8", native: "\u{1F9B8}" }, { unified: "1f9b8-1f3fb", native: "\u{1F9B8}\u{1F3FB}" }, { unified: "1f9b8-1f3fc", native: "\u{1F9B8}\u{1F3FC}" }, { unified: "1f9b8-1f3fd", native: "\u{1F9B8}\u{1F3FD}" }, { unified: "1f9b8-1f3fe", native: "\u{1F9B8}\u{1F3FE}" }, { unified: "1f9b8-1f3ff", native: "\u{1F9B8}\u{1F3FF}" }], version: 11 }, male_superhero: { id: "male_superhero", name: "Man Superhero", keywords: ["male", "good", "hero", "superpowers"], skins: [{ unified: "1f9b8-200d-2642-fe0f", native: "\u{1F9B8}\u200D\u2642\uFE0F" }, { unified: "1f9b8-1f3fb-200d-2642-fe0f", native: "\u{1F9B8}\u{1F3FB}\u200D\u2642\uFE0F" }, { unified: "1f9b8-1f3fc-200d-2642-fe0f", native: "\u{1F9B8}\u{1F3FC}\u200D\u2642\uFE0F" }, { unified: "1f9b8-1f3fd-200d-2642-fe0f", native: "\u{1F9B8}\u{1F3FD}\u200D\u2642\uFE0F" }, { unified: "1f9b8-1f3fe-200d-2642-fe0f", native: "\u{1F9B8}\u{1F3FE}\u200D\u2642\uFE0F
51763" }, { unified: "1f9b8-1f3ff-200d-2642-fe0f", native: "\u{1F9B8}\u{1F3FF}\u200D\u2642\uFE0F" }], version: 11 }, female_superhero: { id: "female_superhero", name: "Woman Superhero", keywords: ["female", "good", "heroine", "superpowers"], skins: [{ unified: "1f9b8-200d-2640-fe0f", native: "\u{1F9B8}\u200D\u2640\uFE0F" }, { unified: "1f9b8-1f3fb-200d-2640-fe0f", native: "\u{1F9B8}\u{1F3FB}\u200D\u2640\uFE0F" }, { unified: "1f9b8-1f3fc-200d-2640-fe0f", native: "\u{1F9B8}\u{1F3FC}\u200D\u2640\uFE0F" }, { unified: "1f9b8-1f3fd-200d-2640-fe0f", native: "\u{1F9B8}\u{1F3FD}\u200D\u2640\uFE0F" }, { unified: "1f9b8-1f3fe-200d-2640-fe0f", native: "\u{1F9B8}\u{1F3FE}\u200D\u2640\uFE0F" }, { unified: "1f9b8-1f3ff-200d-2640-fe0f", native: "\u{1F9B8}\u{1F3FF}\u200D\u2640\uFE0F" }], version: 11 }, supervillain: { id: "supervillain", name: "Supervillain", keywords: ["marvel"], skins: [{ unified: "1f9b9", native: "\u{1F9B9}" }, { unified: "1f9b9-1f3fb", native: "\u{1F9B9}\u{1F3FB}" }, { unified: "1f9b9-1f3fc", native: "\u{1F9B9}\u{1F3FC}" }, { unified: "1f9b9-1f3fd", native: "\u{1F9B9}\u{1F3FD}" }, { unified: "1f9b9-1f3fe", native: "\u{1F9B9}\u{1F3FE}" }, { unified: "1f9b9-1f3ff", native: "\u{1F9B9}\u{1F3FF}" }], version: 11 }, male_supervillain: { id: "male_supervillain", name: "Man Supervillain", keywords: ["male", "evil", "bad", "criminal", "hero", "superpowers"], skins: [{ unified: "1f9b9-200d-2642-fe0f", native: "\u{1F9B9}\u200D\u2642\uFE0F" }, { unified: "1f9b9-1f3fb-200d-2642-fe0f", native: "\u{1F9B9}\u{1F3FB}\u200D\u2642\uFE0F" }, { unified: "1f9b9-1f3fc-200d-2642-fe0f", native: "\u{1F9B9}\u{1F3FC}\u200D\u2642\uFE0F" }, { unified: "1f9b9-1f3fd-200d-2642-fe0f", native: "\u{1F9B9}\u{1F3FD}\u200D\u2642\uFE0F" }, { unified: "1f9b9-1f3fe-200d-2642-fe0f", native: "\u{1F9B9}\u{1F3FE}\u200D\u2642\uFE0F" }, { unified: "1f9b9-1f3ff-200d-2642-fe0f", native: "\u{1F9B9}\u{1F3FF}\u200D\u2642\uFE0F" }], version: 11 }, female_supervillain: { id: "female_supervillain", name: "Woman Supervillain", keywords: ["female", "evil", "bad", "criminal", "heroine", "superpowers"], skins: [{ unified: "1f9b9-200d-2640-fe0f", native: "\u{1F9B9}\u200D\u2640\uFE0F" }, { unified: "1f9b9-1f3fb-200d-2640-fe0f", native: "\u{1F9B9}\u{1F3FB}\u200D\u2640\uFE0F" }, { unified: "1f9b9-1f3fc-200d-2640-fe0f", native: "\u{1F9B9}\u{1F3FC}\u200D\u2640\uFE0F" }, { unified: "1f9b9-1f3fd-200d-2640-fe0f", native: "\u{1F9B9}\u{1F3FD}\u200D\u2640\uFE0F" }, { unified: "1f9b9-1f3fe-200d-2640-fe0f", native: "\u{1F9B9}\u{1F3FE}\u200D\u2640\uFE0F" }, { unified: "1f9b9-1f3ff-200d-2640-fe0f", native: "\u{1F9B9}\u{1F3FF}\u200D\u2640\uFE0F" }], version: 11 }, mage: { id: "mage", name: "Mage", keywords: ["magic"], skins: [{ unified: "1f9d9", native: "\u{1F9D9}" }, { unified: "1f9d9-1f3fb", native: "\u{1F9D9}\u{1F3FB}" }, { unified: "1f9d9-1f3fc", native: "\u{1F9D9}\u{1F3FC}" }, { unified: "1f9d9-1f3fd", native: "\u{1F9D9}\u{1F3FD}" }, { unified: "1f9d9-1f3fe", native: "\u{1F9D9}\u{1F3FE}" }, { unified: "1f9d9-1f3ff", native: "\u{1F9D9}\u{1F3FF}" }], version: 5 }, male_mage: { id: "male_mage", name: "Man Mage", keywords: ["male", "sorcerer"], skins: [{ unified: "1f9d9-200d-2642-fe0f", native: "\u{1F9D9}\u200D\u2642\uFE0F" }, { unified: "1f9d9-1f3fb-200d-2642-fe0f", native: "\u{1F9D9}\u{1F3FB}\u200D\u2642\uFE0F" }, { unified: "1f9d9-1f3fc-200d-2642-fe0f", native: "\u{1F9D9}\u{1F3FC}\u200D\u2642\uFE0F" }, { unified: "1f9d9-1f3fd-200d-2642-fe0f", native: "\u{1F9D9}\u{1F3FD}\u200D\u2642\uFE0F" }, { unified: "1f9d9-1f3fe-200d-2642-fe0f", native: "\u{1F9D9}\u{1F3FE}\u200D\u2642\uFE0F" }, { unified: "1f9d9-1f3ff-200d-2642-fe0f", native: "\u{1F9D9}\u{1F3FF}\u200D\u2642\uFE0F" }], version: 5 }, female_mage: { id: "female_mage", name: "Woman Mage", keywords: ["female", "witch"], skins: [{ unified: "1f9d9-200d-2640-fe0f", native: "\u{1F9D9}\u200D\u2640\uFE0F" }, { unified: "1f9d9-1f3fb-200d-2640-fe0f", native: "\u{1F9D9}\u{1F3FB}\u200D\u2640\uFE0F" }, { unified: "1f9d9-1f3fc-200d-2640-fe0f", native: "\u{1F9D9}\u{1F3FC}\u200D\u2640\uFE0F" }, { unified: "1f9d9-1f3fd-200d-2640-fe0f", native: "\u{1F9D9}\u{1F3FD}\u200D\u2640\uFE0F" }, { unified: "1f9d9-1f3fe-200d-2640-fe0f", native: "\u{1F9D9}\u{1F3FE}\u200D\u2640\uFE0F" }, { unified: "1f9d9-1f3ff-200d-2640-fe0f", native: "\u{1F9D9}\u{1F3FF}\u200D\u2640\uFE0F" }], version: 5 }, fairy: { id: "fairy", name: "Fairy", keywords: ["wings", "magical"], skins: [{ unified: "1f9da", native: "\u{1F9DA}" }, { unified: "1f9da-1f3fb", native: "\u{1F9DA}\u{1F3FB}" }, { unified: "1f9da-1f3fc", native: "\u{1F9DA}\u{1F3FC}" }, { unified: "1f9da-1f3fd", native: "\u{1F9DA}\u{1F3FD}" }, { unified: "1f9da-1f3fe", native: "\u{1F9DA}\u{1F3FE}" }, { unified: "1f9da-1f3ff", native: "\u{1F9DA}\u{1F3FF}" }], version: 5 }, male_fairy: { id: "male_fairy", name: "Man Fairy", keywords: ["male"], skins: [{ unified: "1f9da-200d-2642-fe0f", native: "\u{1F9DA}\u200D\u2642\uFE0F" }, { unified: "1f9da-1f3fb-200d-2642-fe0f", native: "\u{1F9DA}\u{1F3FB}\u200D\u2642\uFE0F" }, { unified: "1f9da-1f3fc-200d-2642-fe0f", native: "\u{1F9DA}\u{1F3FC}\u200D\u2642\uFE0F" }, { unified: "1f9da-1f3fd-200d-2642-fe0f", native: "\u{1F9DA}\u{1F3FD}\u200D\u2642\uFE0F" }, { unified: "1f9da-1f3fe-200d-2642-fe0f", native: "\u{1F9DA}\u{1F3FE}\u200D\u2642\uFE0F" }, { unified: "1f9da-1f3ff-200d-2642-fe0f", native: "\u{1F9DA}\u{1F3FF}\u200D\u2642\uFE0F" }], version: 5 }, female_fairy: { id: "female_fairy", name: "Woman Fairy", keywords: ["female"], skins: [{ unified: "1f9da-200d-2640-fe0f", native: "\u{1F9DA}\u200D\u2640\uFE0F" }, { unified: "1f9da-1f3fb-200d-2640-fe0f", native: "\u{1F9DA}\u{1F3FB}\u200D\u2640\uFE0F" }, { unified: "1f9da-1f3fc-200d-2640-fe0f", native: "\u{1F9DA}\u{1F3FC}\u200D\u2640\uFE0F" }, { unified: "1f9da-1f3fd-200d-2640-fe0f", native: "\u{1F9DA}\u{1F3FD}\u200D\u2640\uFE0F" }, { unified: "1f9da-1f3fe-200d-2640-fe0f", native: "\u{1F9DA}\u{1F3FE}\u200D\u2640\uFE0F" }, { unified: "1f9da-1f3ff-200d-2640-fe0f", native: "\u{1F9DA}\u{1F3FF}\u200D\u2640\uFE0F" }], version: 5 }, vampire: { id: "vampire", name: "Vampire", keywords: ["blood", "twilight"], skins: [{ unified: "1f9db", native: "\u{1F9DB}" }, { unified: "1f9db-1f3fb", native: "\u{1F9DB}\u{1F3FB}" }, { unified: "1f9db-1f3fc", native: "\u{1F9DB}\u{1F3FC}" }, { unified: "1f9db-1f3fd", native: "\u{1F9DB}\u{1F3FD}" }, { unified: "1f9db-1f3fe", native: "\u{1F9DB}\u{1F3FE}" }, { unified: "1f9db-1f3ff", native: "\u{1F9DB}\u{1F3FF}" }], version: 5 }, male_vampire: { id: "male_vampire", name: "Man Vampire", keywords: ["male", "dracula"], skins: [{ unified: "1f9db-200d-2642-fe0f", native: "\u{1F9DB}\u200D\u2642\uFE0F" }, { unified: "1f9db-1f3fb-200d-2642-fe0f", native: "\u{1F9DB}\u{1F3FB}\u200D\u2642\uFE0F" }, { unified: "1f9db-1f3fc-200d-2642-fe0f", native: "\u{1F9DB}\u{1F3FC}\u200D\u2642\uFE0F" }, { unified: "1f9db-1f3fd-200d-2642-fe0f", native: "\u{1F9DB}\u{1F3FD}\u200D\u2642\uFE0F" }, { unified: "1f9db-1f3fe-200d-2642-fe0f", native: "\u{1F9DB}\u{1F3FE}\u200D\u2642\uFE0F" }, { unified: "1f9db-1f3ff-200d-2642-fe0f", native: "\u{1F9DB}\u{1F3FF}\u200D\u2642\uFE0F" }], version: 5 }, female_vampire: { id: "female_vampire", name: "Woman Vampire", keywords: ["female"], skins: [{ unified: "1f9db-200d-2640-fe0f", native: "\u{1F9DB}\u200D\u2640\uFE0F" }, { unified: "1f9db-1f3fb-200d-2640-fe0f", native: "\u{1F9DB}\u{1F3FB}\u200D\u2640\uFE0F" }, { unified: "1f9db-1f3fc-200d-2640-fe0f", native: "\u{1F9DB}\u{1F3FC}\u200D\u2640\uFE0F" }, { unified: "1f9db-1f3fd-200d-2640-fe0f", native: "\u{1F9DB}\u{1F3FD}\u200D\u2640\uFE0F" }, { unified: "1f9db-1f3fe-200d-2640-fe0f", native: "\u{1F9DB}\u{1F3FE}\u200D\u2640\uFE0F" }, { unified: "1f9db-1f3ff-200d-2640-fe0f", native: "\u{1F9DB}\u{1F3FF}\u200D\u2640\uFE0F" }], version: 5 }, merperson: { id: "merperson", name: "Merperson", keywords: ["sea"], skins: [{ unified: "1f9dc", native: "\u{1F9DC}" }, { unified: "1f9dc-1f3fb", native: "\u{1F9DC}
51763\u{1F3FB}" }, { unified: "1f9dc-1f3fc", native: "\u{1F9DC}\u{1F3FC}" }, { unified: "1f9dc-1f3fd", native: "\u{1F9DC}\u{1F3FD}" }, { unified: "1f9dc-1f3fe", native: "\u{1F9DC}\u{1F3FE}" }, { unified: "1f9dc-1f3ff", native: "\u{1F9DC}\u{1F3FF}" }], version: 5 }, merman: { id: "merman", name: "Merman", keywords: ["man", "male", "triton"], skins: [{ unified: "1f9dc-200d-2642-fe0f", native: "\u{1F9DC}\u200D\u2642\uFE0F" }, { unified: "1f9dc-1f3fb-200d-2642-fe0f", native: "\u{1F9DC}\u{1F3FB}\u200D\u2642\uFE0F" }, { unified: "1f9dc-1f3fc-200d-2642-fe0f", native: "\u{1F9DC}\u{1F3FC}\u200D\u2642\uFE0F" }, { unified: "1f9dc-1f3fd-200d-2642-fe0f", native: "\u{1F9DC}\u{1F3FD}\u200D\u2642\uFE0F" }, { unified: "1f9dc-1f3fe-200d-2642-fe0f", native: "\u{1F9DC}\u{1F3FE}\u200D\u2642\uFE0F" }, { unified: "1f9dc-1f3ff-200d-2642-fe0f", native: "\u{1F9DC}\u{1F3FF}\u200D\u2642\uFE0F" }], version: 5 }, mermaid: { id: "mermaid", name: "Mermaid", keywords: ["woman", "female", "merwoman", "ariel"], skins: [{ unified: "1f9dc-200d-2640-fe0f", native: "\u{1F9DC}\u200D\u2640\uFE0F" }, { unified: "1f9dc-1f3fb-200d-2640-fe0f", native: "\u{1F9DC}\u{1F3FB}\u200D\u2640\uFE0F" }, { unified: "1f9dc-1f3fc-200d-2640-fe0f", native: "\u{1F9DC}\u{1F3FC}\u200D\u2640\uFE0F" }, { unified: "1f9dc-1f3fd-200d-2640-fe0f", native: "\u{1F9DC}\u{1F3FD}\u200D\u2640\uFE0F" }, { unified: "1f9dc-1f3fe-200d-2640-fe0f", native: "\u{1F9DC}\u{1F3FE}\u200D\u2640\uFE0F" }, { unified: "1f9dc-1f3ff-200d-2640-fe0f", native: "\u{1F9DC}\u{1F3FF}\u200D\u2640\uFE0F" }], version: 5 }, elf: { id: "elf", name: "Elf", keywords: ["magical"], skins: [{ unified: "1f9dd", native: "\u{1F9DD}" }, { unified: "1f9dd-1f3fb", native: "\u{1F9DD}\u{1F3FB}" }, { unified: "1f9dd-1f3fc", native: "\u{1F9DD}\u{1F3FC}" }, { unified: "1f9dd-1f3fd", native: "\u{1F9DD}\u{1F3FD}" }, { unified: "1f9dd-1f3fe", native: "\u{1F9DD}\u{1F3FE}" }, { unified: "1f9dd-1f3ff", native: "\u{1F9DD}\u{1F3FF}" }], version: 5 }, male_elf: { id: "male_elf", name: "Man Elf", keywords: ["male"], skins: [{ unified: "1f9dd-200d-2642-fe0f", native: "\u{1F9DD}\u200D\u2642\uFE0F" }, { unified: "1f9dd-1f3fb-200d-2642-fe0f", native: "\u{1F9DD}\u{1F3FB}\u200D\u2642\uFE0F" }, { unified: "1f9dd-1f3fc-200d-2642-fe0f", native: "\u{1F9DD}\u{1F3FC}\u200D\u2642\uFE0F" }, { unified: "1f9dd-1f3fd-200d-2642-fe0f", native: "\u{1F9DD}\u{1F3FD}\u200D\u2642\uFE0F" }, { unified: "1f9dd-1f3fe-200d-2642-fe0f", native: "\u{1F9DD}\u{1F3FE}\u200D\u2642\uFE0F" }, { unified: "1f9dd-1f3ff-200d-2642-fe0f", native: "\u{1F9DD}\u{1F3FF}\u200D\u2642\uFE0F" }], version: 5 }, female_elf: { id: "female_elf", name: "Woman Elf", keywords: ["female"], skins: [{ unified: "1f9dd-200d-2640-fe0f", native: "\u{1F9DD}\u200D\u2640\uFE0F" }, { unified: "1f9dd-1f3fb-200d-2640-fe0f", native: "\u{1F9DD}\u{1F3FB}\u200D\u2640\uFE0F" }, { unified: "1f9dd-1f3fc-200d-2640-fe0f", native: "\u{1F9DD}\u{1F3FC}\u200D\u2640\uFE0F" }, { unified: "1f9dd-1f3fd-200d-2640-fe0f", native: "\u{1F9DD}\u{1F3FD}\u200D\u2640\uFE0F" }, { unified: "1f9dd-1f3fe-200d-2640-fe0f", native: "\u{1F9DD}\u{1F3FE}\u200D\u2640\uFE0F" }, { unified: "1f9dd-1f3ff-200d-2640-fe0f", native: "\u{1F9DD}\u{1F3FF}\u200D\u2640\uFE0F" }], version: 5 }, genie: { id: "genie", name: "Genie", keywords: ["magical", "wishes"], skins: [{ unified: "1f9de", native: "\u{1F9DE}" }], version: 5 }, male_genie: { id: "male_genie", name: "Man Genie", keywords: ["male"], skins: [{ unified: "1f9de-200d-2642-fe0f", native: "\u{1F9DE}\u200D\u2642\uFE0F" }], version: 5 }, female_genie: { id: "female_genie", name: "Woman Genie", keywords: ["female"], skins: [{ unified: "1f9de-200d-2640-fe0f", native: "\u{1F9DE}\u200D\u2640\uFE0F" }], version: 5 }, zombie: { id: "zombie", name: "Zombie", keywords: ["dead"], skins: [{ unified: "1f9df", native: "\u{1F9DF}" }], version: 5 }, male_zombie: { id: "male_zombie", name: "Man Zombie", keywords: ["male", "dracula", "undead", "walking", "dead"], skins: [{ unified: "1f9df-200d-2642-fe0f", native: "\u{1F9DF}\u200D\u2642\uFE0F" }], version: 5 }, female_zombie: { id: "female_zombie", name: "Woman Zombie", keywords: ["female", "undead", "walking", "dead"], skins: [{ unified: "1f9df-200d-2640-fe0f", native: "\u{1F9DF}\u200D\u2640\uFE0F" }], version: 5 }, troll: { id: "troll", name: "Troll", keywords: ["mystical", "monster"], skins: [{ unified: "1f9cc", native: "\u{1F9CC}" }], version: 14 }, massage: { id: "massage", name: "Face Massage", keywords: ["person", "getting", "relax"], skins: [{ unified: "1f486", native: "\u{1F486}" }, { unified: "1f486-1f3fb", native: "\u{1F486}\u{1F3FB}" }, { unified: "1f486-1f3fc", native: "\u{1F486}\u{1F3FC}" }, { unified: "1f486-1f3fd", native: "\u{1F486}\u{1F3FD}" }, { unified: "1f486-1f3fe", native: "\u{1F486}\u{1F3FE}" }, { unified: "1f486-1f3ff", native: "\u{1F486}\u{1F3FF}" }], version: 1 }, "man-getting-massage": { id: "man-getting-massage", name: "Man Getting Massage", keywords: ["getting-massage", "male", "boy", "head"], skins: [{ unified: "1f486-200d-2642-fe0f", native: "\u{1F486}\u200D\u2642\uFE0F" }, { unified: "1f486-1f3fb-200d-2642-fe0f", native: "\u{1F486}\u{1F3FB}\u200D\u2642\uFE0F" }, { unified: "1f486-1f3fc-200d-2642-fe0f", native: "\u{1F486}\u{1F3FC}\u200D\u2642\uFE0F" }, { unified: "1f486-1f3fd-200d-2642-fe0f", native: "\u{1F486}\u{1F3FD}\u200D\u2642\uFE0F" }, { unified: "1f486-1f3fe-200d-2642-fe0f", native: "\u{1F486}\u{1F3FE}\u200D\u2642\uFE0F" }, { unified: "1f486-1f3ff-200d-2642-fe0f", native: "\u{1F486}\u{1F3FF}\u200D\u2642\uFE0F" }], version: 4 }, "woman-getting-massage": { id: "woman-getting-massage", name: "Woman Getting Massage", keywords: ["getting-massage", "female", "girl", "head"], skins: [{ unified: "1f486-200d-2640-fe0f", native: "\u{1F486}\u200D\u2640\uFE0F" }, { unified: "1f486-1f3fb-200d-2640-fe0f", native: "\u{1F486}\u{1F3FB}\u200D\u2640\uFE0F" }, { unified: "1f486-1f3fc-200d-2640-fe0f", native: "\u{1F486}\u{1F3FC}\u200D\u2640\uFE0F" }, { unified: "1f486-1f3fd-200d-2640-fe0f", native: "\u{1F486}\u{1F3FD}\u200D\u2640\uFE0F" }, { unified: "1f486-1f3fe-200d-2640-fe0f", native: "\u{1F486}\u{1F3FE}\u200D\u2640\uFE0F" }, { unified: "1f486-1f3ff-200d-2640-fe0f", native: "\u{1F486}\u{1F3FF}\u200D\u2640\uFE0F" }], version: 4 }, haircut: { id: "haircut", name: "Haircut", keywords: ["person", "getting", "hairstyle"], skins: [{ unified: "1f487", native: "\u{1F487}" }, { unified: "1f487-1f3fb", native: "\u{1F487}\u{1F3FB}" }, { unified: "1f487-1f3fc", native: "\u{1F487}\u{1F3FC}" }, { unified: "1f487-1f3fd", native: "\u{1F487}\u{1F3FD}" }, { unified: "1f487-1f3fe", native: "\u{1F487}\u{1F3FE}" }, { unified: "1f487-1f3ff", native: "\u{1F487}\u{1F3FF}" }], version: 1 }, "man-getting-haircut": { id: "man-getting-haircut", name: "Man Getting Haircut", keywords: ["getting-haircut", "male", "boy"], skins: [{ unified: "1f487-200d-2642-fe0f", native: "\u{1F487}\u200D\u2642\uFE0F" }, { unified: "1f487-1f3fb-200d-2642-fe0f", native: "\u{1F487}\u{1F3FB}\u200D\u2642\uFE0F" }, { unified: "1f487-1f3fc-200d-2642-fe0f", native: "\u{1F487}\u{1F3FC}\u200D\u2642\uFE0F" }, { unified: "1f487-1f3fd-200d-2642-fe0f", native: "\u{1F487}\u{1F3FD}\u200D\u2642\uFE0F" }, { unified: "1f487-1f3fe-200d-2642-fe0f", native: "\u{1F487}\u{1F3FE}\u200D\u2642\uFE0F" }, { unified: "1f487-1f3ff-200d-2642-fe0f", native: "\u{1F487}\u{1F3FF}\u200D\u2642\uFE0F" }], version: 4 }, "woman-getting-haircut": { id: "woman-getting-haircut", name: "Woman Getting Haircut", keywords: ["getting-haircut", "female", "girl"], skins: [{ unified: "1f487-200d-2640-fe0f", native: "\u{1F487}\u200D\u2640\uFE0F" }, { unified: "1f487-1f3fb-200d-2640-fe0f", native: "\u{1F487}\u{1F3FB}\u200D\u2640\uFE0F" }, { unified: "1f487-1f3fc-200d-2640-fe0f", native: "\u{1F487}\u{1F3FC}\u200D\u2640\uFE0F" }, { unified: "1f487-1f3fd-200d-2640-fe0f", native: "\u{1F487}\u{1F3FD}\u200D\u2640\uFE0F" }, { unified: "1f487-1f3fe-200d-2640-fe0f", native: "\u{1F487}\u{1F3FE}\u200D\u2640\uFE0F" }, { unified: "1f487-1f3ff-200d-2640-fe0f", native: "\u{1F487}\u{1F3FF}\u200D\u2640\uFE0F" }], version: 4 }, walking: { id: "walking", name: "Pedestrian", keywords: ["walking", "person", "move"], skins: [{ unified: "1f6b6", native: "\u{1F6B6}" }, { unified: "1f6b6-1f3fb", native: "\u{1F6B6}\u{1F3FB}" }, { unified: "1f6b6-1f3fc", native: "\u{1F6B6}\u{1F3FC}" }, { unified: "1f6b6-1f3fd", native: "\u{1F6B6}\u{1F3FD}" }, { unified: "1f6b6-1f3fe", native: "\u{1F6B6}\u{1F3FE}" }, { unified: "1f6b6-1f3ff", native: "\u{1F6B6}\u{1F3FF}" }], version: 1 }, "man-walking": { id: "man-walking", name: "Man Walking", keywords: ["human", "feet", "steps"], skins: [{ unified: "1f6b6-200d-2642-fe0f", native: "\u{1F6B6}\u200D\u2642\uFE0F" }, { unified: "1f6b6-1f3fb-200d-2642-fe0f", native: "\u{1F6B6}\u{1F3FB}\u200D\u2642\uFE0F" }, { unified: "1f6b6-1f3fc-200d-2642-fe0f", native: "\u{1F6B6}\u{1F3FC}\u200D\u2642\uFE0F" }, { unified: "1f6b6-1f3fd-200d-2642-fe0f", native: "\u{1F6B6}\u{1F3FD}\u200D\u2642\uFE0F" }, { unified: "1f6b6-1f3fe-200d-2642-fe0f", native: "\u{1F6B6}\u{1F3FE}\u200D\u2642\uFE0F" }, { unified: "1f6b6-1f3ff-200d-2642-fe0f", native: "\u{1F6B6}\u{1F3FF}\u200D\u2642\uFE0F" }], version: 4 }, "woman-walking": { id: "woman-walking", name: "Woman Walking", keywords: ["human", "feet", "steps", "female"], skins: [{ unified: "1f6b6-200d-2640-fe0f", native: "\u{1F6B6}\u200D\u2640\uFE0F" }, { unified: "1f6b6-1f3fb-200d-2640-fe0f", native: "\u{1F6B6}\u{1F3FB}\u200D\u2640\uFE0F" }, { unified: "1f6b6-1f3fc-200d-2640-fe0f", native: "\u{1F6B6}\u{1F3FC}\u200D\u2640\uFE0F" }, { unified: "1f6b6-1f3fd-200d-2640-fe0f", native: "\u{1F6B6}\u{1F3FD}\u200D\u2640\uFE0F" }, { unified: "1f6b6-1f3fe-200d-2640-fe0f", native: "\u{1F6B6}\u{1F3FE}\u200D\u2640\uFE0F" }, { unified: "1f6b6-1f3ff-200d-2640-fe0f", native: "\u{1F6B6}\u{1F3FF}\u200D\u2640\uFE0F" }], version: 4 }, person_walking_facing_right: { id: "person_walking_facing_right", name: "Person Walking Facing Right", keywords: ["peerson", "exercise"], skins: [{ unified: "1f6b6-200d-27a1-fe0f", native: "\u{1F6B6}\u200D\u27A1\uFE0F" }, { unified: "1f6b6-1f3fb-200d-27a1-fe0f", native: "\u{1F6B6}\u{1F3FB}\u200D\u27A1\uFE0F" }, { unified: "1f6b6-1f3fc-200d-27a1-fe0f", native: "\u{1F6B6}\u{1F3FC}\u200D\u27A1\uFE0F" }, { unified: "1f6b6-1f3fd-200d-27a1-fe0f", native: "\u{1F6B6}\u{1F3FD}\u200D\u27A1\uFE0F" }, { unified: "1f6b6-1f3fe-200d-27a1-fe0f", native: "\u{1F6B6}\u{1F3FE}\u200D\u27A1\uFE0F" }, { unified: "1f6b6-1f3ff-200d-27a1-fe0f", native: "\u{1F6B6}\u{1F3FF}\u200D\u27A1\uFE0F" }], version: 15.1 }, woman_walking_facing_right: { id: "woman_walking_facing_right", name: "Woman Walking Facing Right", keywords: ["person", "exercise"], skins: [{ unified: "1f6b6-200d-2640-fe0f-200d-27a1-fe0f", native: "\u{1F6B6}\u200D\u2640\uFE0F\u200D\u27A1\uFE0F" }, { unified: "1f6b6-1f3fb-200d-2640-fe0f-200d-27a1-fe0f", native: "\u{1F6B6}\u{1F3FB}\u200D\u2640\uFE0F\u200D\u27A1\uFE0F" }, { unified: "1f6b6-1f3fc-200d-2640-fe0f-200d-27a1-fe0f", native: "\u{1F6B6}\u{1F3FC}\u200D\u2640\uFE0F\u200D\u27A1\uFE0F" }, { unified: "1f6b6-1f3fd-200d-2640-fe0f-200d-27a1-fe0f", native: "\u{1F6B6}\u{1F3FD}\u200D\u2640\uFE0F\u200D\u27A1\uFE0F" }, { unified: "1f6b6-1f3fe-200d-2640-fe0f-200d-27a1-fe0f", native: "\u{1F6B6}\u{1F3FE}\u200D\u2640\uFE0F\u200D\u27A1\uFE0F" }, { unified: "1f6b6-1f3ff-200d-2640-fe0f-200d-27a1-fe0f", native: "\u{1F6B6}\u{1F3FF}\u200D\u2640\uFE0F\u200D\u27A1\uFE0F" }], version: 15.1 }, man_walking_facing_right: { id: "man_walking_facing_right", name: "Man Walking Facing Right", keywords: ["person", "exercise"], skins: [{ unified: "1f6b6-200d-2642-fe0f-200d-27a1-fe0f", native: "\u{1F6B6}\u200D\u2642\uFE0F\u200D\u27A1\uFE0F" }, { unified: "1f6b6-1f3fb-200d-2642-fe0f-200d-27a1-fe0f", native: "\u{1F6B6}\u{1F3FB}\u200D\u2642\uFE0F\u200D\u27A1\uFE0F" }, { unified: "1f6b6-1f3fc-200d-2642-fe0f-200d-27a1-fe0f", native: "\u{1F6B6}\u{1F3FC}\u200D\u2642\uFE0F\u200D\u27A1\uFE0F" }, { unified: "1f6b6-1f3fd-200d-2642-fe0f-200d-27a1-fe0f", native: "\u{1F6B6}\u{1F3FD}\u200D\u2642\uFE0F\u200D\u27A1\uFE0F" }, { unified: "1f6b6-1f3fe-200d-2642-fe0f-200d-27a1-fe0f", native: "\u{1F6B6}\u{1F3FE}\u200D\u2642\uFE0F\u200D\u27A1\uFE0F" }, { unified: "1f6b6-1f3ff-200d-2642-fe0f-200d-27a1-fe0f", native: "\u{1F6B6}\u{1F3FF}\u200D\u2642\uFE0F\u200D\u27A1\uFE0F" }], version: 15.1 }, standing_person: { id: "standing_person", name: "Standing Person", keywords: ["still"], skins: [{ unified: "1f9cd", native: "\u{1F9C
51763D}" }, { unified: "1f9cd-1f3fb", native: "\u{1F9CD}\u{1F3FB}" }, { unified: "1f9cd-1f3fc", native: "\u{1F9CD}\u{1F3FC}" }, { unified: "1f9cd-1f3fd", native: "\u{1F9CD}\u{1F3FD}" }, { unified: "1f9cd-1f3fe", native: "\u{1F9CD}\u{1F3FE}" }, { unified: "1f9cd-1f3ff", native: "\u{1F9CD}\u{1F3FF}" }], version: 12 }, man_standing: { id: "man_standing", name: "Man Standing", keywords: ["still"], skins: [{ unified: "1f9cd-200d-2642-fe0f", native: "\u{1F9CD}\u200D\u2642\uFE0F" }, { unified: "1f9cd-1f3fb-200d-2642-fe0f", native: "\u{1F9CD}\u{1F3FB}\u200D\u2642\uFE0F" }, { unified: "1f9cd-1f3fc-200d-2642-fe0f", native: "\u{1F9CD}\u{1F3FC}\u200D\u2642\uFE0F" }, { unified: "1f9cd-1f3fd-200d-2642-fe0f", native: "\u{1F9CD}\u{1F3FD}\u200D\u2642\uFE0F" }, { unified: "1f9cd-1f3fe-200d-2642-fe0f", native: "\u{1F9CD}\u{1F3FE}\u200D\u2642\uFE0F" }, { unified: "1f9cd-1f3ff-200d-2642-fe0f", native: "\u{1F9CD}\u{1F3FF}\u200D\u2642\uFE0F" }], version: 12 }, woman_standing: { id: "woman_standing", name: "Woman Standing", keywords: ["still"], skins: [{ unified: "1f9cd-200d-2640-fe0f", native: "\u{1F9CD}\u200D\u2640\uFE0F" }, { unified: "1f9cd-1f3fb-200d-2640-fe0f", native: "\u{1F9CD}\u{1F3FB}\u200D\u2640\uFE0F" }, { unified: "1f9cd-1f3fc-200d-2640-fe0f", native: "\u{1F9CD}\u{1F3FC}\u200D\u2640\uFE0F" }, { unified: "1f9cd-1f3fd-200d-2640-fe0f", native: "\u{1F9CD}\u{1F3FD}\u200D\u2640\uFE0F" }, { unified: "1f9cd-1f3fe-200d-2640-fe0f", native: "\u{1F9CD}\u{1F3FE}\u200D\u2640\uFE0F" }, { unified: "1f9cd-1f3ff-200d-2640-fe0f", native: "\u{1F9CD}\u{1F3FF}\u200D\u2640\uFE0F" }], version: 12 }, kneeling_person: { id: "kneeling_person", name: "Kneeling Person", keywords: ["pray", "respectful"], skins: [{ unified: "1f9ce", native: "\u{1F9CE}" }, { unified: "1f9ce-1f3fb", native: "\u{1F9CE}\u{1F3FB}" }, { unified: "1f9ce-1f3fc", native: "\u{1F9CE}\u{1F3FC}" }, { unified: "1f9ce-1f3fd", native: "\u{1F9CE}\u{1F3FD}" }, { unified: "1f9ce-1f3fe", native: "\u{1F9CE}\u{1F3FE}" }, { unified: "1f9ce-1f3ff", native: "\u{1F9CE}\u{1F3FF}" }], version: 12 }, man_kneeling: { id: "man_kneeling", name: "Man Kneeling", keywords: ["pray", "respectful"], skins: [{ unified: "1f9ce-200d-2642-fe0f", native: "\u{1F9CE}\u200D\u2642\uFE0F" }, { unified: "1f9ce-1f3fb-200d-2642-fe0f", native: "\u{1F9CE}\u{1F3FB}\u200D\u2642\uFE0F" }, { unified: "1f9ce-1f3fc-200d-2642-fe0f", native: "\u{1F9CE}\u{1F3FC}\u200D\u2642\uFE0F" }, { unified: "1f9ce-1f3fd-200d-2642-fe0f", native: "\u{1F9CE}\u{1F3FD}\u200D\u2642\uFE0F" }, { unified: "1f9ce-1f3fe-200d-2642-fe0f", native: "\u{1F9CE}\u{1F3FE}\u200D\u2642\uFE0F" }, { unified: "1f9ce-1f3ff-200d-2642-fe0f", native: "\u{1F9CE}\u{1F3FF}\u200D\u2642\uFE0F" }], version: 12 }, woman_kneeling: { id: "woman_kneeling", name: "Woman Kneeling", keywords: ["respectful", "pray"], skins: [{ unified: "1f9ce-200d-2640-fe0f", native: "\u{1F9CE}\u200D\u2640\uFE0F" }, { unified: "1f9ce-1f3fb-200d-2640-fe0f", native: "\u{1F9CE}\u{1F3FB}\u200D\u2640\uFE0F" }, { unified: "1f9ce-1f3fc-200d-2640-fe0f", native: "\u{1F9CE}\u{1F3FC}\u200D\u2640\uFE0F" }, { unified: "1f9ce-1f3fd-200d-2640-fe0f", native: "\u{1F9CE}\u{1F3FD}\u200D\u2640\uFE0F" }, { unified: "1f9ce-1f3fe-200d-2640-fe0f", native: "\u{1F9CE}\u{1F3FE}\u200D\u2640\uFE0F" }, { unified: "1f9ce-1f3ff-200d-2640-fe0f", native: "\u{1F9CE}\u{1F3FF}\u200D\u2640\uFE0F" }], version: 12 }, person_kneeling_facing_right: { id: "person_kneeling_facing_right", name: "Person Kneeling Facing Right", keywords: ["pray"], skins: [{ unified: "1f9ce-200d-27a1-fe0f", native: "\u{1F9CE}\u200D\u27A1\uFE0F" }, { unified: "1f9ce-1f3fb-200d-27a1-fe0f", native: "\u{1F9CE}\u{1F3FB}\u200D\u27A1\uFE0F" }, { unified: "1f9ce-1f3fc-200d-27a1-fe0f", native: "\u{1F9CE}\u{1F3FC}\u200D\u27A1\uFE0F" }, { unified: "1f9ce-1f3fd-200d-27a1-fe0f", native: "\u{1F9CE}\u{1F3FD}\u200D\u27A1\uFE0F" }, { unified: "1f9ce-1f3fe-200d-27a1-fe0f", native: "\u{1F9CE}\u{1F3FE}\u200D\u27A1\uFE0F" }, { unified: "1f9ce-1f3ff-200d-27a1-fe0f", native: "\u{1F9CE}\u{1F3FF}\u200D\u27A1\uFE0F" }], version: 15.1 }, woman_kneeling_facing_right: { id: "woman_kneeling_facing_right", name: "Woman Kneeling Facing Right", keywords: ["pray", "worship"], skins: [{ unified: "1f9ce-200d-2640-fe0f-200d-27a1-fe0f", native: "\u{1F9CE}\u200D\u2640\uFE0F\u200D\u27A1\uFE0F" }, { unified: "1f9ce-1f3fb-200d-2640-fe0f-200d-27a1-fe0f", native: "\u{1F9CE}\u{1F3FB}\u200D\u2640\uFE0F\u200D\u27A1\uFE0F" }, { unified: "1f9ce-1f3fc-200d-2640-fe0f-200d-27a1-fe0f", native: "\u{1F9CE}\u{1F3FC}\u200D\u2640\uFE0F\u200D\u27A1\uFE0F" }, { unified: "1f9ce-1f3fd-200d-2640-fe0f-200d-27a1-fe0f", native: "\u{1F9CE}\u{1F3FD}\u200D\u2640\uFE0F\u200D\u27A1\uFE0F" }, { unified: "1f9ce-1f3fe-200d-2640-fe0f-200d-27a1-fe0f", native: "\u{1F9CE}\u{1F3FE}\u200D\u2640\uFE0F\u200D\u27A1\uFE0F" }, { unified: "1f9ce-1f3ff-200d-2640-fe0f-200d-27a1-fe0f", native: "\u{1F9CE}\u{1F3FF}\u200D\u2640\uFE0F\u200D\u27A1\uFE0F" }], version: 15.1 }, man_kneeling_facing_right: { id: "man_kneeling_facing_right", name: "Man Kneeling Facing Right", keywords: ["pray", "worship"], skins: [{ unified: "1f9ce-200d-2642-fe0f-200d-27a1-fe0f", native: "\u{1F9CE}\u200D\u2642\uFE0F\u200D\u27A1\uFE0F" }, { unified: "1f9ce-1f3fb-200d-2642-fe0f-200d-27a1-fe0f", native: "\u{1F9CE}\u{1F3FB}\u200D\u2642\uFE0F\u200D\u27A1\uFE0F" }, { unified: "1f9ce-1f3fc-200d-2642-fe0f-200d-27a1-fe0f", native: "\u{1F9CE}\u{1F3FC}\u200D\u2642\uFE0F\u200D\u27A1\uFE0F" }, { unified: "1f9ce-1f3fd-200d-2642-fe0f-200d-27a1-fe0f", native: "\u{1F9CE}\u{1F3FD}\u200D\u2642\uFE0F\u200D\u27A1\uFE0F" }, { unified: "1f9ce-1f3fe-200d-2642-fe0f-200d-27a1-fe0f", native: "\u{1F9CE}\u{1F3FE}\u200D\u2642\uFE0F\u200D\u27A1\uFE0F" }, { unified: "1f9ce-1f3ff-200d-2642-fe0f-200d-27a1-fe0f", native: "\u{1F9CE}\u{1F3FF}\u200D\u2642\uFE0F\u200D\u27A1\uFE0F" }], version: 15.1 }, person_with_probing_cane: { id: "person_with_probing_cane", name: "Person with White Cane", keywords: ["probing", "blind"], skins: [{ unified: "1f9d1-200d-1f9af", native: "\u{1F9D1}\u200D\u{1F9AF}" }, { unified: "1f9d1-1f3fb-200d-1f9af", native: "\u{1F9D1}\u{1F3FB}\u200D\u{1F9AF}" }, { unified: "1f9d1-1f3fc-200d-1f9af", native: "\u{1F9D1}\u{1F3FC}\u200D\u{1F9AF}" }, { unified: "1f9d1-1f3fd-200d-1f9af", native: "\u{1F9D1}\u{1F3FD}\u200D\u{1F9AF}" }, { unified: "1f9d1-1f3fe-200d-1f9af", native: "\u{1F9D1}\u{1F3FE}\u200D\u{1F9AF}" }, { unified: "1f9d1-1f3ff-200d-1f9af", native: "\u{1F9D1}\u{1F3FF}\u200D\u{1F9AF}" }], version: 12.1 }
51763, person_with_white_cane_facing_right: { id: "person_with_white_cane_facing_right", name: "Person with White Cane Facing Right", keywords: ["walk", "visually", "impaired", "blind"], skins: [{ unified: "1f9d1-200d-1f9af-200d-27a1-fe0f", native: "\u{1F9D1}\u200D\u{1F9AF}\u200D\u27A1\uFE0F" }, { unified: "1f9d1-1f3fb-200d-1f9af-200d-27a1-fe0f", native: "\u{1F9D1}\u{1F3FB}\u200D\u{1F9AF}\u200D\u27A1\uFE0F" }, { unified: "1f9d1-1f3fc-200d-1f9af-200d-27a1-fe0f", native: "\u{1F9D1}\u{1F3FC}\u200D\u{1F9AF}\u200D\u27A1\uFE0F" }, { unified: "1f9d1-1f3fd-200d-1f9af-200d-27a1-fe0f", native: "\u{1F9D1}\u{1F3FD}\u200D\u{1F9AF}\u200D\u27A1\uFE0F" }, { unified: "1f9d1-1f3fe-200d-1f9af-200d-27a1-fe0f", native: "\u{1F9D1}\u{1F3FE}\u200D\u{1F9AF}\u200D\u27A1\uFE0F" }, { unified: "1f9d1-1f3ff-200d-1f9af-200d-27a1-fe0f", native: "\u{1F9D1}\u{1F3FF}\u200D\u{1F9AF}\u200D\u27A1\uFE0F" }], version: 15.1 }, man_with_probing_cane: { id: "man_with_probing_cane", name: "Man with White Cane", keywords: ["probing", "blind"], skins: [{ unified: "1f468-200d-1f9af", native: "\u{1F468}\u200D\u{1F9AF}" }, { unified: "1f468-1f3fb-200d-1f9af", native: "\u{1F468}\u{1F3FB}\u200D\u{1F9AF}" }, { unified: "1f468-1f3fc-200d-1f9af", native: "\u{1F468}\u{1F3FC}\u200D\u{1F9AF}" }, { unified: "1f468-1f3fd-200d-1f9af", native: "\u{1F468}\u{1F3FD}\u200D\u{1F9AF}" }, { unified: "1f468-1f3fe-200d-1f9af", native: "\u{1F468}\u{1F3FE}\u200D\u{1F9AF}" }, { unified: "1f468-1f3ff-200d-1f9af", native: "\u{1F468}\u{1F3FF}\u200D\u{1F9AF}" }], version: 12 }, man_with_white_cane_facing_right: { id: "man_with_white_cane_facing_right", name: "Man with White Cane Facing Right", keywords: ["visually", "impaired", "blind", "walk", "stick"], skins: [{ unified: "1f468-200d-1f9af-200d-27a1-fe0f", native: "\u{1F468}\u200D\u{1F9AF}\u200D\u27A1\uFE0F" }, { unified: "1f468-1f3fb-200d-1f9af-200d-27a1-fe0f", native: "\u{1F468}\u{1F3FB}\u200D\u{1F9AF}\u200D\u27A1\uFE0F" }, { unified: "1f468-1f3fc-200d-1f9af-200d-27a1-fe0f", native: "\u{1F468}\u{1F3FC}\u200D\u{1F9AF}\u200D\u27A1\uFE0F" }, { unified: "1f468-1f3fd-200d-1f9af-200d-27a1-fe0f", native: "\u{1F468}\u{1F3FD}\u200D\u{1F9AF}\u200D\u27A1\uFE0F" }, { unified: "1f468-1f3fe-200d-1f9af-200d-27a1-fe0f", native: "\u{1F468}\u{1F3FE}\u200D\u{1F9AF}\u200D\u27A1\uFE0F" }, { unified: "1f468-1f3ff-200d-1f9af-200d-27a1-fe0f", native: "\u{1F468}\u{1F3FF}\u200D\u{1F9AF}\u200D\u27A1\uFE0F" }], version: 15.1 }, woman_with_probing_cane: { id: "woman_with_probing_cane", name: "Woman with White Cane", keywords: ["probing", "blind"], skins: [{ unified: "1f469-200d-1f9af", native: "\u{1F469}\u200D\u{1F9AF}" }, { unified: "1f469-1f3fb-200d-1f9af", native: "\u{1F469}\u{1F3FB}\u200D\u{1F9AF}" }, { unified: "1f469-1f3fc-200d-1f9af", native: "\u{1F469}\u{1F3FC}\u200D\u{1F9AF}" }, { unified: "1f469-1f3fd-200d-1f9af", native: "\u{1F469}\u{1F3FD}\u200D\u{1F9AF}" }, { unified: "1f469-1f3fe-200d-1f9af", native: "\u{1F469}\u{1F3FE}\u200D\u{1F9AF}" }, { unified: "1f469-1f3ff-200d-1f9af", native: "\u{1F469}\u{1F3FF}\u200D\u{1F9AF}" }], version: 12 }, woman_with_white_cane_facing_right: { id: "woman_with_white_cane_facing_right", name: "Woman with White Cane Facing Right", keywords: ["stick", "visually", "impaired", "blind"], skins: [{ unified: "1f469-200d-1f9af-200d-27a1-fe0f", native: "\u{1F469}\u200D\u{1F9AF}\u200D\u27A1\uFE0F" }, { unified: "1f469-1f3fb-200d-1f9af-200d-27a1-fe0f", native: "\u{1F469}\u{1F3FB}\u200D\u{1F9AF}\u200D\u27A1\uFE0F" }, { unified: "1f469-1f3fc-200d-1f9af-200d-27a1-fe0f", native: "\u{1F469}\u{1F3FC}\u200D\u{1F9AF}\u200D\u27A1\uFE0F" }, { unified: "1f469-1f3fd-200d-1f9af-200d-27a1-fe0f", native: "\u{1F469}\u{1F3FD}\u200D\u{1F9AF}\u200D\u27A1\uFE0F" }, { unified: "1f469-1f3fe-200d-1f9af-200d-27a1-fe0f", native: "\u{1F469}\u{1F3FE}\u200D\u{1F9AF}\u200D\u27A1\uFE0F" }, { unified: "1f469-1f3ff-200d-1f9af-200d-27a1-fe0f", native: "\u{1F469}\u{1F3FF}\u200D\u{1F9AF}\u200D\u27A1\uFE0F" }], version: 15.1 }, person_in_motorized_wheelchair: { id: "person_in_motorized_wheelchair", name: "Person in Motorized Wheelchair", keywords: ["disability", "accessibility"], skins: [{ unified: "1f9d1-200d-1f9bc", native: "\u{1F9D1}\u200D\u{1F9BC}" }, { unified: "1f9d1-1f3fb-200d-1f9bc", native: "\u{1F9D1}\u{1F3FB}\u200D\u{1F9BC}" }, { unified: "1f9d1-1f3fc-200d-1f9bc", native: "\u{1F9D1}\u{1F3FC}\u200D\u{1F9BC}" }, { unified: "1f9d1-1f3fd-200d-1f9bc", native: "\u{1F9D1}\u{1F3FD}\u200D\u{1F9BC}" }, { unified: "1f9d1-1f3fe-200d-1f9bc", native: "\u{1F9D1}\u{1F3FE}\u200D\u{1F9BC}" }, { unified: "1f9d1-1f3ff-200d-1f9bc", native: "\u{1F9D1}\u{1F3FF}\u200D\u{1F9BC}" }], version: 12.1 }, person_in_motorized_wheelchair_facing_right: { id: "person_in_motorized_wheelchair_facing_right", name: "Person in Motorized Wheelchair Facing Right", keywords: ["accessibility", "disability"], skins: [{ unified: "1f9d1-200d-1f9bc-200d-27a1-fe0f", native: "\u{1F9D1}\u200D\u{1F9BC}\u200D\u27A1\uFE0F" }, { unified: "1f9d1-1f3fb-200d-1f9bc-200d-27a1-fe0f", native: "\u{1F9D1}\u{1F3FB}\u200D\u{1F9BC}\u200D\u27A1\uFE0F" }, { unified: "1f9d1-1f3fc-200d-1f9bc-200d-27a1-fe0f", native: "\u{1F9D1}\u{1F3FC}\u200D\u{1F9BC}\u200D\u27A1\uFE0F" }, { unified: "1f9d1-1f3fd-200d-1f9bc-200d-27a1-fe0f", native: "\u{1F9D1}\u{1F3FD}\u200D\u{1F9BC}\u200D\u27A1\uFE0F" }, { unified: "1f9d1-1f3fe-200d-1f9bc-200d-27a1-fe0f", native: "\u{1F9D1}\u{1F3FE}\u200D\u{1F9BC}\u200D\u27A1\uFE0F" }, { unified: "1f9d1-1f3ff-200d-1f9bc-200d-27a1-fe0f", native: "\u{1F9D1}\u{1F3FF}\u200D\u{1F9BC}\u200D\u27A1\uFE0F" }], version: 15.1 }, man_in_motorized_wheelchair: { id: "man_in_motorized_wheelchair", name: "Man in Motorized Wheelchair", keywords: ["disability", "accessibility"], skins: [{ unified: "1f468-200d-1f9bc", native: "\u{1F468}\u200D\u{1F9BC}" }, { unified: "1f468-1f3fb-200d-1f9bc", native: "\u{1F468}\u{1F3FB}\u200D\u{1F9BC}" }, { unified: "1f468-1f3fc-200d-1f9bc", native: "\u{1F468}\u{1F3FC}\u200D\u{1F9BC}" }, { unified: "1f468-1f3fd-200d-1f9bc", native: "\u{1F468}\u{1F3FD}\u200D\u{1F9BC}" }, { unified: "1f468-1f3fe-200d-1f9bc", native: "\u{1F468}\u{1F3FE}\u200D\u{1F9BC}" }, { unified: "1f468-1f3ff-200d-1f9bc", native: "\u{1F468}\u{1F3FF}\u200D\u{1F9BC}" }], version: 12 }, man_in_motorized_wheelchair_facing_right: { id: "man_in_motorized_wheelchair_facing_right", name: "Man in Motorized Wheelchair Facing Right", keywords: ["disability", "accessibility", "mobility"], skins: [{ unified: "1f468-200d-1f9bc-200d-27a1-fe0f", native: "\u{1F468}\u200D\u{1F9BC}\u200D\u27A1\uFE0F" }, { unified: "1f468-1f3fb-200d-1f9bc-200d-27a1-fe0f", native: "\u{1F468}\u{1F3FB}\u200D\u{1F9BC}\u200D\u27A1\uFE0F" }, { unified: "1f468-1f3fc-200d-1f9bc-200d-27a1-fe0f", native: "\u{1F468}\u{1F3FC}\u200D\u{1F9BC}\u200D\u27A1\uFE0F" }, { unified: "1f468-1f3fd-200d-1f9bc-200d-27a1-fe0f", native: "\u{1F468}\u{1F3FD}\u200D\u{1F9BC}\u200D\u27A1\uFE0F" }, { unified: "1f468-1f3fe-200d-1f9bc-200d-27a1-fe0f", native: "\u{1F468}\u{1F3FE}\u200D\u{1F9BC}\u200D\u27A1\uFE0F" }, { unified: "1f468-1f3ff-200d-1f9bc-200d-27a1-fe0f", native: "\u{1F468}\u{1F3FF}\u200D\u{1F9BC}\u200D\u27A1\uFE0F" }], version: 15.1 }, woman_in_motorized_wheelchair: { id: "woman_in_motorized_wheelchair", name: "Woman in Motorized Wheelchair", keywords: ["disability", "accessibility"], skins: [{ unified: "1f469-200d-1f9bc", native: "\u{1F469}\u200D\u{1F9BC}" }, { unified: "1f469-1f3fb-200d-1f9bc", native: "\u{1F469}\u{1F3FB}\u200D\u{1F9BC}" }, { unified: "1f469-1f3fc-200d-1f9bc", native: "\u{1F469}\u{1F3FC}\u200D\u{1F9BC}" }, { unified: "1f469-1f3fd-200d-1f9bc", native: "\u{1F469}\u{1F3FD}\u200D\u{1F9BC}" }, { unified: "1f469-1f3fe-200d-1f9bc", native: "\u{1F469}\u{1F3FE}\u200D\u{1F9BC}" }, { unified: "1f469-1f3ff-200d-1f9bc", native: "\u{1F469}\u{1F3FF}\u200D\u{1F9BC}" }], version: 12 }, woman_in_motorized_wheelchair_facing_right: { id: "woman_in_motorized_wheelchair_facing_right", name: "Woman in Motorized Wheelchair Facing Right", keywords: ["mobility", "accessibility", "disability"], skins: [{ unified: "1f469-200d-1f9bc-200d-27a1-fe0f", native: "\u{1F469}\u200D\u{1F9BC}\u200D\u27A1\uFE0F" }, { unified: "1f469-1f3fb-200d-1f9bc-200d-27a1-fe0f", native: "\u{1F469}\u{1F3FB}\u200D\u{1F9BC}\u200D\u27A1\uFE0F" }, { unified: "1f469-1f3fc-200d-1f9bc-200d-27a1-fe0f", native: "\u{1F469}\u{1F3FC}\u200D\u{1F9BC}\u200D\u27A1\uFE0F" }, { unified: "1f469-1f3fd-200d-1f9bc-200d-27a1-fe0f", native: "\u{1F469}\u{1F3FD}\u200D\u{1F9BC}\u200D\u27A1\uFE0F" }, { unified: "1f469-1f3fe-200d-1f9bc-200d-27a1-fe0f", native: "\u{1F469}\u{1F3FE}\u200D\u{1F9BC}\u200D\u27A1\uFE0F" }, { unified: "1f469-1f3ff-200d-1f9bc-200d-27a1-fe0f", native: "\u{1F469}\u{1F3FF}\u200D\u{1F9BC}\u200D\u27A1\uFE0F" }], version: 15.1 }, person_in_manual_wheelchair: { id: "person_in_manual_wheelchair", name: "Person in Manual Wheelchair", keywords: ["disability", "accessibility"], skins: [{ unified: "1f9d1-200d-1f9bd", native: "\u{1F9D1}\u200D\u{1F9BD}" }, { unified: "1f9d1-1f3fb-200d-1f9bd", native: "\u{1F9D1}\u{1F3FB}\u200D\u{1F9BD}" }, { unified: "1f9d1-1f3fc-200d-1f9bd", native: "\u{1F9D1}\u{1F3FC}\u200D\u{1F9BD}" }, { unified: "1f9d1-1f3fd-200d-1f9bd", native: "\u{1F9D1}\u{1F3FD}\u200D\u{1F9BD}" }, { unified: "1f9d1-1f3fe-200d-1f9bd", native: "\u{1F9D1}\u{1F3FE}\u200D\u{1F9BD}" }, { unified: "1f9d1-1f3ff-200d-1f9bd", native: "\u{1F9D1}\u{1F3FF}\u200D\u{1F9BD}" }], version: 12.1 }, person_in_manual_wheelchair_facing_right: { id: "person_in_manual_wheelchair_facing_right", name: "Person in Manual Wheelchair Facing Right", keywords: ["mobility", "accessibility", "disability"], skins: [{ unified: "1f9d1-200d-1f9bd-200d-27a1-fe0f", native: "\u{1F9D1}\u200D\u{1F9BD}\u200D\u27A1\uFE0F" }, { unified: "1f9d1-1f3fb-200d-1f9bd-200d-27a1-fe0f", native: "\u{1F9D1}\u{1F3FB}\u200D\u{1F9BD}\u200D\u27A1\uFE0F" }, { unified: "1f9d1-1f3fc-200d-1f9bd-200d-27a1-fe0f", native: "\u{1F9D1}\u{1F3FC}\u200D\u{1F9BD}\u200D\u27A1\uFE0F" }, { unified: "1f9d1-1f3fd-200d-1f9bd-200d-27a1-fe0f", native: "\u{1F9D1}\u{1F3FD}\u200D\u{1F9BD}\u200D\u27A1\uFE0F" }, { unified: "1f9d1-1f3fe-200d-1f9bd-200d-27a1-fe0f", native: "\u{1F9D1}\u{1F3FE}\u200D\u{1F9BD}\u200D\u27A1\uFE0F" }, { unified: "1f9d1-1f3ff-200d-1f9bd-200d-27a1-fe0f", native: "\u{1F9D1}\u{1F3FF}\u200D\u{1F9BD}\u200D\u27A1\uFE0F" }], version: 15.1 }, man_in_manual_wheelchair: { id: "man_in_manual_wheelchair", name: "Man in Manual Wheelchair", keywords: ["disability", "accessibility"], skins: [{ unified: "1f468-200d-1f9bd", native: "\u{1F468}\u200D\u{1F9BD}" }, { unified: "1f468-1f3fb-200d-1f9bd", native: "\u{1F468}\u{1F3FB}\u200D\u{1F9BD}" }, { unified: "1f468-1f3fc-200d-1f9bd", native: "\u{1F468}\u{1F3FC}\u200D\u{1F9BD}" }, { unified: "1f468-1f3fd-200d-1f9bd", native: "\u{1F468}\u{1F3FD}\u200D\u{1F9BD}" }, { unified: "1f468-1f3fe-200d-1f9bd", native: "\u{1F468}\u{1F3FE}\u200D\u{1F9BD}" }, { unified: "1f468-1f3ff-200d-1f9bd", native: "\u{1F468}\u{1F3FF}\u200D\u{1F9BD}" }], version: 12 }, man_in_manual_wheelchair_facing_right: { id: "man_in_manual_wheelchair_facing_right", name: "Man in Manual Wheelchair Facing Right", keywords: ["mobility", "accessibility", "disability"], skins: [{ unified: "1f468-200d-1f9bd-200d-27a1-fe0f", native: "\u{1F468}\u200D\u{1F9BD}\u200D\u27A1\uFE0F" }, { unified: "1f468-1f3fb-200d-1f9bd-200d-27a1-fe0f", native: "\u{1F468}\u{1F3FB}\u200D\u{1F9BD}\u200D\u27A1\uFE0F" }, { unified: "1f468-1f3fc-200d-1f9bd-200d-27a1-fe0f", native: "\u{1F468}\u{1F3FC}\u200D\u{1F9BD}\u200D\u27A1\uFE0F" }, { unified: "1f468-1f3fd-200d-1f9bd-200d-27a1-fe0f", native: "\u{1F468}\u{1F3FD}\u200D\u{1F9BD}\u200D\u27A1\uFE0F" }, { unified: "1f468-1f3fe-200d-1f9bd-200d-27a1-fe0f", native: "\u{1F468}\u{1F3FE}\u200D\u{1F9BD}\u200D\u27A1\uFE0F" }, { unified: "1f468-1f3ff-200d-1f9bd-200d-27a1-fe0f", native: "\u{1F468}\u{1F3FF}\u200D\u{1F9BD}\u200D\u27A1\uFE0F" }], version: 15.1 }, woman_in_manual_wheelchair: { id: "woman_in_manual_wheelchair", name: "Woman in Manual Wheelchair", keywords: ["disability", "accessibility"], skins: [{ unified: "1f469-200d-1f9bd", native: "\u{1F469}\u200D\u{1F9BD}" }, { unified: "1f469-1f3fb-200d-1f9bd", native: "\u{1F469}\u{1F3FB}\u200D\u{1F9BD}" }, { unified: "1f469-1f3fc-200d-1f9bd", native: "\u{1F469}\u{1F3FC}\u200D\u{1F9BD}" }, { unified: "1f469-1f3fd-200d-1f9bd", native: "\u{1F469}\u{1F3FD}\u200D\u{1F9BD}" }, { unified: "1f469-1f3fe-200d-1f9bd", native: "\u{1F469}\u{1F3FE}\u200D\u{1F9BD}" }, { unified: "1f469-1f3ff-200d-1f9bd", native: "\u{1F469}\u{1F3FF}\u200D\u{1F9BD}" }], version: 12 }, woman_in_manual_wheelchair_facing_right: { id: "woman_in_manual_wheelchair_facing_right", name: "Woman in Manual Wheelchair Facing Right", keywords: ["disability", "mobility", "accessibility"], skins: [{ unified: "1f469-200d-1f9bd-200d-27a1-fe0f", native: "\u{1F469}\u200D\u{1F9BD}\u200D\u27A1\uFE0F" }, { unified: "1f469-1f3fb-200d-1f9bd-200d-27a1-fe0f", native: "\u{1F469}\u{1F3FB}\u200D\u{1F9BD}\u200D\u27A1\uFE0F" }, { unified: "1f469-1f3fc-200d-1f9bd-200d-27a1-fe0f", native: "\u{1F469}\u{1F3FC}\u200D\u{1F9BD}\u200D\u27A1\uFE0F" }, { unified: "1f469-1f3fd-200d-1f9bd-200d-27a1-fe0f", native: "\u{1F469}\u{1F3FD}\u200D\u{1F9BD}\u200D\u27A1\uFE0F" }, { unified: "1f469-1f3fe-200d-1f9bd-200d-27a1-fe0f", native: "\u{1F469}\u{1F3FE}\u200D\u{1F9BD}\u200D\u27A1\uFE0F" }, { unified: "1f469-1f3ff-200d-1f9bd-200d-27a1-fe0f", native: "\u{1F469}\u{1F3FF}\u200D\u{1F9BD}\u200D\u27A1\uFE0F" }], version: 15.1 }, runner: { id: "runner", name: "Runner", keywords: ["running", "person", "move"], skins: [{ unified: "1f3c3", native: "\u{1F3C3}" }, { unified: "1f3c3-1f3fb", native: "\u{1F3C3}\u{1F3FB}" }, { unified: "1f3c3-1f3fc", native: "\u{1F3C3}\u{1F3FC}" }, { unified: "1f3c3-1f3fd", native: "\u{1F3C3}\u{1F3FD}" }, { unified: "1f3c3-1f3fe", native: "\u{1F3C3}\u{1F3FE}" }, { unified: "1f3c3-1f3ff", native: "\u{1F3C3}\u{1F3FF}" }], version: 1 }, "man-running": { id: "man-running", name: "Man Running", keywords: ["walking", "exercise", "race"], skins: [{ unified: "1f3c3-200d-2642-fe0f", native: "\u{1F3C3}\u200D\u2642\uFE0F" }, { unified: "1f3c3-1f3fb-200d-2642-fe0f", native: "\u{1F3C3}\u{1F3FB}\u200D\u2642\uFE0F" }, { unified: "1f3c3-1f3fc-200d-2642-fe0f", native: "\u{1F3C3}\u{1F3FC}\u200D\u2642\uFE0F" }, { unified: "1f3c3-1f3fd-200d-2642-fe0f", native: "\u{1F3C3}\u{1F3FD}\u200D\u2642\uFE0F" }, { unified: "1f3c3-1f3fe-200d-2642-fe0f", native: "\u{1F3C3}\u{1F3FE}\u200D\u2642\uFE0F" }, { unified: "1f3c3-1f3ff-200d-2642-fe0f", native: "\u{1F3C3}\u{1F3FF}\u200D\u2642\uFE0F" }], version: 4 }, "woman-running": { id: "woman-running", name: "Woman Running", keywords: ["walking", "exercise", "race", "female"], skins: [{ unified: "1f3c3-200d-2640-fe0f", native: "\u{1F3C3}\u200D\u2640\uFE0F" }, { unified: "1f3c3-1f3fb-200d-2640-fe0f", native: "\u{1F3C3}\u{1F3FB}\u200D\u2640\uFE0F" }, { unified: "1f3c3-1f3fc-200d-2640-fe0f", native: "\u{1F3C3}\u{1F3FC}\u200D\u2640\uFE0F" }, { unified: "1f3c3-1f3fd-200d-2640-fe0f", native: "\u{1F3C3}\u{1F3FD}\u200D\u2640\uFE0F" }, { unified: "1f3c3-1f3fe-200d-2640-fe0f", native: "\u{1F3C3}\u{1F3FE}\u200D\u2640\uFE0F" }, { unified: "1f3c3-1f3ff-200d-2640-fe0f", native: "\u{1F3C3}\u{1F3FF}\u200D\u2640\uFE0F" }], version: 4 }, person_running_facing_right: { id: "person_running_facing_right", name: "Person Running Facing Right", keywords: ["exercise", "jog"], skins: [{ unified: "1f3c3-200d-27a1-fe0f", native: "\u{1F3C3}\u200D\u27A1\uFE0F" }, { unified: "1f3c3-1f3fb-200d-27a1-fe0f", native: "\u{1F3C3}\u{1F3FB}\u200D\u27A1\uFE0F" }, { unified: "1f3c3-1f3fc-200d-27a1-fe0f", native: "\u{1F3C3}\u{1F3FC}\u200D\u27A1\uFE0F" }, { unified: "1f3c3-1f3fd-200d-27a1-fe0f", native: "\u{1F3C3}\u{1F3FD}\u200D\u27A1\uFE0F" }, { unified: "1f3c3-1f3fe-200d-27a1-fe0f", native: "\u{1F3C3}\u{1F3FE}\u200D\u27A1\uFE0F" }, { unified: "1f3c3-1f3ff-200d-27a1-fe0f", native: "\u{1F3C3}\u{1F3FF}\u200D\u27A1\uFE0F" }], version: 15.1 }, woman_running_facing_right: { id: "woman_running_facing_right", name: "Woman Running Facing Right", keywords: ["exercise", "jog"], skins: [{ unified: "1f3c3-200d-2640-fe0f-200d-27a1-fe0f", native: "\u{1F3C3}\u200D\u2640\uFE0F\u200D\u27A1\uFE0F" }, { unified: "1f3c3-1f3fb-200d-2640-fe0f-200d-27a1-fe0f", native: "\u{1F3C3}\u{1F3FB}\u200D\u2640\uFE0F\u200D\u27A1\uFE0F" }, { unified: "1f3c3-1f3fc-200d-2640-fe0f-200d-27a1-fe0f", native: "\u{1F3C3}\u{1F3FC}\u200D\u2640\uFE0F\u200D\u27A1\uFE0F" }, { unified: "1f3c3-1f3fd-200d-2640-fe0f-200d-27a1-fe0f", native: "\u{1F3C3}\u{1F3FD}
51763\u200D\u2640\uFE0F\u200D\u27A1\uFE0F" }, { unified: "1f3c3-1f3fe-200d-2640-fe0f-200d-27a1-fe0f", native: "\u{1F3C3}\u{1F3FE}\u200D\u2640\uFE0F\u200D\u27A1\uFE0F" }, { unified: "1f3c3-1f3ff-200d-2640-fe0f-200d-27a1-fe0f", native: "\u{1F3C3}\u{1F3FF}\u200D\u2640\uFE0F\u200D\u27A1\uFE0F" }], version: 15.1 }, man_running_facing_right: { id: "man_running_facing_right", name: "Man Running Facing Right", keywords: ["jog", "exercise"], skins: [{ unified: "1f3c3-200d-2642-fe0f-200d-27a1-fe0f", native: "\u{1F3C3}\u200D\u2642\uFE0F\u200D\u27A1\uFE0F" }, { unified: "1f3c3-1f3fb-200d-2642-fe0f-200d-27a1-fe0f", native: "\u{1F3C3}\u{1F3FB}\u200D\u2642\uFE0F\u200D\u27A1\uFE0F" }, { unified: "1f3c3-1f3fc-200d-2642-fe0f-200d-27a1-fe0f", native: "\u{1F3C3}\u{1F3FC}\u200D\u2642\uFE0F\u200D\u27A1\uFE0F" }, { unified: "1f3c3-1f3fd-200d-2642-fe0f-200d-27a1-fe0f", native: "\u{1F3C3}\u{1F3FD}\u200D\u2642\uFE0F\u200D\u27A1\uFE0F" }, { unified: "1f3c3-1f3fe-200d-2642-fe0f-200d-27a1-fe0f", native: "\u{1F3C3}\u{1F3FE}\u200D\u2642\uFE0F\u200D\u27A1\uFE0F" }, { unified: "1f3c3-1f3ff-200d-2642-fe0f-200d-27a1-fe0f", native: "\u{1F3C3}\u{1F3FF}\u200D\u2642\uFE0F\u200D\u27A1\uFE0F" }], version: 15.1 }, dancer: { id: "dancer", name: "Dancer", keywords: ["woman", "dancing", "female", "girl", "fun"], skins: [{ unified: "1f483", native: "\u{1F483}" }, { unified: "1f483-1f3fb", native: "\u{1F483}\u{1F3FB}" }, { unified: "1f483-1f3fc", native: "\u{1F483}\u{1F3FC}" }, { unified: "1f483-1f3fd", native: "\u{1F483}\u{1F3FD}" }, { unified: "1f483-1f3fe", native: "\u{1F483}\u{1F3FE}" }, { unified: "1f483-1f3ff", native: "\u{1F483}\u{1F3FF}" }], version: 1 }, man_dancing: { id: "man_dancing", name: "Man Dancing", keywords: ["male", "boy", "fun", "dancer"], skins: [{ unified: "1f57a", native: "\u{1F57A}" }, { unified: "1f57a-1f3fb", native: "\u{1F57A}\u{1F3FB}" }, { unified: "1f57a-1f3fc", native: "\u{1F57A}\u{1F3FC}" }, { unified: "1f57a-1f3fd", native: "\u{1F57A}\u{1F3FD}" }, { unified: "1f57a-1f3fe", native: "\u{1F57A}\u{1F3FE}" }, { unified: "1f57a-1f3ff", native: "\u{1F57A}\u{1F3FF}" }], version: 3 }, man_in_business_suit_levitating: { id: "man_in_business_suit_levitating", name: "Person in Suit Levitating", keywords: ["man", "business", "levitate", "hover", "jump"], skins: [{ unified: "1f574-fe0f", native: "\u{1F574}\uFE0F" }, { unified: "1f574-1f3fb", native: "\u{1F574}\u{1F3FB}" }, { unified: "1f574-1f3fc", native: "\u{1F574}\u{1F3FC}" }, { unified: "1f574-1f3fd", native: "\u{1F574}\u{1F3FD}" }, { unified: "1f574-1f3fe", native: "\u{1F574}\u{1F3FE}" }, { unified: "1f574-1f3ff", native: "\u{1F574}\u{1F3FF}" }], version: 1 }, dancers: { id: "dancers", name: "Woman with Bunny Ears", keywords: ["dancers", "people", "perform", "costume"], skins: [{ unified: "1f46f", native: "\u{1F46F}" }], version: 1 }, "men-with-bunny-ears-partying": { id: "men-with-bunny-ears-partying", name: "Men with Bunny Ears", keywords: ["with-bunny-ears-partying", "man", "male", "boys"], skins: [{ unified: "1f46f-200d-2642-fe0f", native: "\u{1F46F}\u200D\u2642\uFE0F" }], version: 4 }, "women-with-bunny-ears-partying": { id: "women-with-bunny-ears-partying", name: "Women with Bunny Ears", keywords: ["with-bunny-ears-partying", "woman", "female", "girls"], skins: [{ unified: "1f46f-200d-2640-fe0f", native: "\u{1F46F}\u200D\u2640\uFE0F" }], version: 4 }, person_in_steamy_room: { id: "person_in_steamy_room", name: "Person in Steamy Room", keywords: ["relax", "spa"], skins: [{ unified: "1f9d6", native: "\u{1F9D6}" }, { unified: "1f9d6-1f3fb", native: "\u{1F9D6}\u{1F3FB}" }, { unified: "1f9d6-1f3fc", native: "\u{1F9D6}\u{1F3FC}" }, { unified: "1f9d6-1f3fd", native: "\u{1F9D6}\u{1F3FD}" }, { unified: "1f9d6-1f3fe", native: "\u{1F9D6}\u{1F3FE}" }, { unified: "1f9d6-1f3ff", native: "\u{1F9D6}\u{1F3FF}" }], version: 5 }, man_in_steamy_room: { id: "man_in_steamy_room", name: "Man in Steamy Room", keywords: ["male", "spa", "steamroom", "sauna"], skins: [{ unified: "1f9d6-200d-2642-fe0f", native: "\u{1F9D6}\u200D\u2642\uFE0F" }, { unified: "1f9d6-1f3fb-200d-2642-fe0f", native: "\u{1F9D6}\u{1F3FB}\u200D\u2642\uFE0F" }, { unified: "1f9d6-1f3fc-200d-2642-fe0f", native: "\u{1F9D6}\u{1F3FC}\u200D\u2642\uFE0F" }, { unified: "1f9d6-1f3fd-200d-2642-fe0f", native: "\u{1F9D6}\u{1F3FD}\u200D\u2642\uFE0F" }, { unified: "1f9d6-1f3fe-200d-2642-fe0f", native: "\u{1F9D6}\u{1F3FE}\u200D\u2642\uFE0F" }, { unified: "1f9d6-1f3ff-200d-2642-fe0f", native: "\u{1F9D6}\u{1F3FF}\u200D\u2642\uFE0F" }], version: 5 }, woman_in_steamy_room: { id: "woman_in_steamy_room", name: "Woman in Steamy Room", keywords: ["female", "spa", "steamroom", "sauna"], skins: [{ unified: "1f9d6-200d-2640-fe0f", native: "\u{1F9D6}\u200D\u2640\uFE0F" }, { unified: "1f9d6-1f3fb-200d-2640-fe0f", native: "\u{1F9D6}\u{1F3FB}\u200D\u2640\uFE0F" }, { unified: "1f9d6-1f3fc-200d-2640-fe0f", native: "\u{1F9D6}\u{1F3FC}\u200D\u2640\uFE0F" }, { unified: "1f9d6-1f3fd-200d-2640-fe0f", native: "\u{1F9D6}\u{1F3FD}\u200D\u2640\uFE0F" }, { unified: "1f9d6-1f3fe-200d-2640-fe0f", native: "\u{1F9D6}\u{1F3FE}\u200D\u2640\uFE0F" }, { unified: "1f9d6-1f3ff-200d-2640-fe0f", native: "\u{1F9D6}\u{1F3FF}\u200D\u2640\uFE0F" }], version: 5 }, person_climbing: { id: "person_climbing", name: "Person Climbing", keywords: ["sport"], skins: [{ unified: "1f9d7", native: "\u{1F9D7}" }, { unified: "1f9d7-1f3fb", native: "\u{1F9D7}\u{1F3FB}" }, { unified: "1f9d7-1f3fc", native: "\u{1F9D7}\u{1F3FC}" }, { unified: "1f9d7-1f3fd", native: "\u{1F9D7}\u{1F3FD}" }, { unified: "1f9d7-1f3fe", native: "\u{1F9D7}\u{1F3FE}" }, { unified: "1f9d7-1f3ff", native: "\u{1F9D7}\u{1F3FF}" }], version: 5 }, man_climbing: { id: "man_climbing", name: "Man Climbing", keywords: ["sports", "hobby", "male", "rock"], skins: [{ unified: "1f9d7-200d-2642-fe0f", native: "\u{1F9D7}\u200D\u2642\uFE0F" }, { unified: "1f9d7-1f3fb-200d-2642-fe0f", native: "\u{1F9D7}\u{1F3FB}\u200D\u2642\uFE0F" }, { unified: "1f9d7-1f3fc-200d-2642-fe0f", native: "\u{1F9D7}\u{1F3FC}\u200D\u2642\uFE0F" }, { unified: "1f9d7-1f3fd-200d-2642-fe0f", native: "\u{1F9D7}\u{1F3FD}\u200D\u2642\uFE0F" }, { unified: "1f9d7-1f3fe-200d-2642-fe0f", native: "\u{1F9D7}\u{1F3FE}\u200D\u2642\uFE0F" }, { unified: "1f9d7-1f3ff-200d-2642-fe0f", native: "\u{1F9D7}\u{1F3FF}\u200D\u2642\uFE0F" }], version: 5 }, woman_climbing: { id: "woman_climbing", name: "Woman Climbing", keywords: ["sports", "hobby", "female", "rock"], skins: [{ unified: "1f9d7-200d-2640-fe0f", native: "\u{1F9D7}\u200D\u2640\uFE0F" }, { unified: "1f9d7-1f3fb-200d-2640-fe0f", native: "\u{1F9D7}\u{1F3FB}\u200D\u2640\uFE0F" }, { unified: "1f9d7-1f3fc-200d-2640-fe0f", native: "\u{1F9D7}\u{1F3FC}\u200D\u2640\uFE0F" }, { unified: "1f9d7-1f3fd-200d-2640-fe0f", native: "\u{1F9D7}\u{1F3FD}\u200D\u2640\uFE0F" }, { unified: "1f9d7-1f3fe-200d-2640-fe0f", native: "\u{1F9D7}\u{1F3FE}\u200D\u2640\uFE0F" }, { unified: "1f9d7-1f3ff-200d-2640-fe0f", native: "\u{1F9D7}\u{1F3FF}\u200D\u2640\uFE0F" }], version: 5 }, fencer: { id: "fencer", name: "Fencer", keywords: ["person", "fencing", "sports", "sword"], skins: [{ unified: "1f93a", native: "\u{1F93A}" }], version: 3 }, horse_racing: { id: "horse_racing", name: "Horse Racing", keywords: ["animal", "betting", "competition", "gambling", "luck"], skins: [{ unified: "1f3c7", native: "\u{1F3C7}" }, { unified: "1f3c7-1f3fb", native: "\u{1F3C7}\u{1F3FB}" }, { unified: "1f3c7-1f3fc", native: "\u{1F3C7}\u{1F3FC}" }, { unified: "1f3c7-1f3fd", native: "\u{1F3C7}\u{1F3FD}" }, { unified: "1f3c7-1f3fe", native: "\u{1F3C7}\u{1F3FE}" }, { unified: "1f3c7-1f3ff", native: "\u{1F3C7}\u{1F3FF}" }], version: 1 }, skier: { id: "skier", name: "Skier", keywords: ["sports", "winter", "snow"], skins: [{ unified: "26f7-fe0f", native: "\u26F7\uFE0F" }], version: 1 }, snowboarder: { id: "snowboarder", name: "Snowboarder", keywords: ["sports", "winter"], skins: [{ unified: "1f3c2", native: "\u{1F3C2}" }, { unified: "1f3c2-1f3fb", native: "\u{1F3C2}\u{1F3FB}" }, { unified: "1f3c2-1f3fc", native: "\u{1F3C2}\u{1F3FC}" }, { unified: "1f3c2-1f3fd", native: "\u{1F3C2}\u{1F3FD}" }, { unified: "1f3c2-1f3fe", native: "\u{1F3C2}\u{1F3FE}" }, { unified: "1f3c2-1f3ff", native: "\u{1F3C2}\u{1F3FF}" }], version: 1 }, golfer: { id: "golfer", name: "Person Golfing", keywords: ["golfer", "sports", "business"], skins: [{ unified: "1f3cc-fe0f", native: "\u{1F3CC}\uFE0F" }, { unified: "1f3cc-1f3fb", native: "\u{1F3CC}\u{1F3FB}" }, { unified: "1f3cc-1f3fc", native: "\u{1F3CC}\u{1F3FC}" }, { unified: "1f3cc-1f3fd", native: "\u{1F3CC}\u{1F3FD}" }, { unified: "1f3cc-1f3fe", native: "\u{1F3CC}\u{1F3FE}" }, { unified: "1f3cc-1f3ff", native: "\u{1F3CC}\u{1F3FF}" }], version: 1 }, "man-golfing": { id: "man-golfing", name: "Man Golfing", keywords: ["sport"], skins: [{ unified: "1f3cc-fe0f-200d-2642-fe0f", native: "\u{1F3CC}\uFE0F\u200D\u2642\uFE0F" }, { unified: "1f3cc-1f3fb-200d-2642-fe0f", native: "\u{1F3CC}\u{1F3FB}\u200D\u2642\uFE0F" }, { unified: "1f3cc-1f3fc-200d-2642-fe0f", native: "\u{1F3CC}\u{1F3FC}\u200D\u2642\uFE0F" }, { unified: "1f3cc-1f3fd-200d-2642-fe0f", native: "\u{1F3CC}\u{1F3FD}\u200D\u2642\uFE0F" }, { unified: "1f3cc-1f3fe-200d-2642-fe0f", native: "\u{1F3CC}\u{1F3FE}\u200D\u2642\uFE0F" }, { unified: "1f3cc-1f3ff-200d-2642-fe0f", native: "\u{1F3CC}\u{1F3FF}\u200D\u2642\uFE0F" }], version: 4 }, "woman-golfing": { id: "woman-golfing", name: "Woman Golfing", keywords: ["sports", "business", "female"], skins: [{ unified: "1f3cc-fe0f-200d-2640-fe0f", native: "\u{1F3CC}\uFE0F\u200D\u2640\uFE0F" }, { unified: "1f3cc-1f3fb-200d-2640-fe0f", native: "\u{1F3CC}\u{1F3FB}\u200D\u2640\uFE0F" }, { unified: "1f3cc-1f3fc-200d-2640-fe0f", native: "\u{1F3CC}\u{1F3FC}\u200D\u2640\uFE0F" }, { unified: "1f3cc-1f3fd-200d-2640-fe0f", native: "\u{1F3CC}\u{1F3FD}\u200D\u2640\uFE0F" }, { unified: "1f3cc-1f3fe-200d-2640-fe0f", native: "\u{1F3CC}\u{1F3FE}\u200D\u2640\uFE0F" }, { unified: "1f3cc-1f3ff-200d-2640-fe0f", native: "\u{1F3CC}\u{1F3FF}\u200D\u2640\uFE0F" }], version: 4 }, surfer: { id: "surfer", name: "Surfer", keywords: ["person", "surfing", "sport", "sea"], skins: [{ unified: "1f3c4", native: "\u{1F3C4}" }, { unified: "1f3c4-1f3fb", native: "\u{1F3C4}\u{1F3FB}" }, { unified: "1f3c4-1f3fc", native: "\u{1F3C4}\u{1F3FC}" }, { unified: "1f3c4-1f3fd", native: "\u{1F3C4}\u{1F3FD}" }, { unified: "1f3c4-1f3fe", native: "\u{1F3C4}\u{1F3FE}" }, { unified: "1f3c4-1f3ff", native: "\u{1F3C4}\u{1F3FF}" }], version: 1 }
51763, "man-surfing": { id: "man-surfing", name: "Man Surfing", keywords: ["sports", "ocean", "sea", "summer", "beach"], skins: [{ unified: "1f3c4-200d-2642-fe0f", native: "\u{1F3C4}\u200D\u2642\uFE0F" }, { unified: "1f3c4-1f3fb-200d-2642-fe0f", native: "\u{1F3C4}\u{1F3FB}\u200D\u2642\uFE0F" }, { unified: "1f3c4-1f3fc-200d-2642-fe0f", native: "\u{1F3C4}\u{1F3FC}\u200D\u2642\uFE0F" }, { unified: "1f3c4-1f3fd-200d-2642-fe0f", native: "\u{1F3C4}\u{1F3FD}\u200D\u2642\uFE0F" }, { unified: "1f3c4-1f3fe-200d-2642-fe0f", native: "\u{1F3C4}\u{1F3FE}\u200D\u2642\uFE0F" }, { unified: "1f3c4-1f3ff-200d-2642-fe0f", native: "\u{1F3C4}\u{1F3FF}\u200D\u2642\uFE0F" }], version: 4 }, "woman-surfing": { id: "woman-surfing", name: "Woman Surfing", keywords: ["sports", "ocean", "sea", "summer", "beach", "female"], skins: [{ unified: "1f3c4-200d-2640-fe0f", native: "\u{1F3C4}\u200D\u2640\uFE0F" }, { unified: "1f3c4-1f3fb-200d-2640-fe0f", native: "\u{1F3C4}\u{1F3FB}\u200D\u2640\uFE0F" }, { unified: "1f3c4-1f3fc-200d-2640-fe0f", native: "\u{1F3C4}\u{1F3FC}\u200D\u2640\uFE0F" }, { unified: "1f3c4-1f3fd-200d-2640-fe0f", native: "\u{1F3C4}\u{1F3FD}\u200D\u2640\uFE0F" }, { unified: "1f3c4-1f3fe-200d-2640-fe0f", native: "\u{1F3C4}\u{1F3FE}\u200D\u2640\uFE0F" }, { unified: "1f3c4-1f3ff-200d-2640-fe0f", native: "\u{1F3C4}\u{1F3FF}\u200D\u2640\uFE0F" }], version: 4 }, rowboat: { id: "rowboat", name: "Rowboat", keywords: ["person", "rowing", "boat", "sport", "move"], skins: [{ unified: "1f6a3", native: "\u{1F6A3}" }, { unified: "1f6a3-1f3fb", native: "\u{1F6A3}\u{1F3FB}" }, { unified: "1f6a3-1f3fc", native: "\u{1F6A3}\u{1F3FC}" }, { unified: "1f6a3-1f3fd", native: "\u{1F6A3}\u{1F3FD}" }, { unified: "1f6a3-1f3fe", native: "\u{1F6A3}\u{1F3FE}" }, { unified: "1f6a3-1f3ff", native: "\u{1F6A3}\u{1F3FF}" }], version: 1 }, "man-rowing-boat": { id: "man-rowing-boat", name: "Man Rowing Boat", keywords: ["rowing-boat", "sports", "hobby", "water", "ship"], skins: [{ unified: "1f6a3-200d-2642-fe0f", native: "\u{1F6A3}\u200D\u2642\uFE0F" }, { unified: "1f6a3-1f3fb-200d-2642-fe0f", native: "\u{1F6A3}\u{1F3FB}\u200D\u2642\uFE0F" }, { unified: "1f6a3-1f3fc-200d-2642-fe0f", native: "\u{1F6A3}\u{1F3FC}\u200D\u2642\uFE0F" }, { unified: "1f6a3-1f3fd-200d-2642-fe0f", native: "\u{1F6A3}\u{1F3FD}\u200D\u2642\uFE0F" }, { unified: "1f6a3-1f3fe-200d-2642-fe0f", native: "\u{1F6A3}\u{1F3FE}\u200D\u2642\uFE0F" }, { unified: "1f6a3-1f3ff-200d-2642-fe0f", native: "\u{1F6A3}\u{1F3FF}\u200D\u2642\uFE0F" }], version: 4 }, "woman-rowing-boat": { id: "woman-rowing-boat", name: "Woman Rowing Boat", keywords: ["rowing-boat", "sports", "hobby", "water", "ship", "female"], skins: [{ unified: "1f6a3-200d-2640-fe0f", native: "\u{1F6A3}\u200D\u2640\uFE0F" }, { unified: "1f6a3-1f3fb-200d-2640-fe0f", native: "\u{1F6A3}\u{1F3FB}\u200D\u2640\uFE0F" }, { unified: "1f6a3-1f3fc-200d-2640-fe0f", native: "\u{1F6A3}\u{1F3FC}\u200D\u2640\uFE0F" }, { unified: "1f6a3-1f3fd-200d-2640-fe0f", native: "\u{1F6A3}\u{1F3FD}\u200D\u2640\uFE0F" }, { unified: "1f6a3-1f3fe-200d-2640-fe0f", native: "\u{1F6A3}\u{1F3FE}\u200D\u2640\uFE0F" }, { unified: "1f6a3-1f3ff-200d-2640-fe0f", native: "\u{1F6A3}\u{1F3FF}\u200D\u2640\uFE0F" }], version: 4 }, swimmer: { id: "swimmer", name: "Swimmer", keywords: ["person", "swimming", "sport", "pool"], skins: [{ unified: "1f3ca", native: "\u{1F3CA}" }, { unified: "1f3ca-1f3fb", native: "\u{1F3CA}\u{1F3FB}" }, { unified: "1f3ca-1f3fc", native: "\u{1F3CA}\u{1F3FC}" }, { unified: "1f3ca-1f3fd", native: "\u{1F3CA}\u{1F3FD}" }, { unified: "1f3ca-1f3fe", native: "\u{1F3CA}\u{1F3FE}" }, { unified: "1f3ca-1f3ff", native: "\u{1F3CA}\u{1F3FF}" }], version: 1 }, "man-swimming": { id: "man-swimming", name: "Man Swimming", keywords: ["sports", "exercise", "human", "athlete", "water", "summer"], skins: [{ unified: "1f3ca-200d-2642-fe0f", native: "\u{1F3CA}\u200D\u2642\uFE0F" }, { unified: "1f3ca-1f3fb-200d-2642-fe0f", native: "\u{1F3CA}\u{1F3FB}\u200D\u2642\uFE0F" }, { unified: "1f3ca-1f3fc-200d-2642-fe0f", native: "\u{1F3CA}\u{1F3FC}\u200D\u2642\uFE0F" }, { unified: "1f3ca-1f3fd-200d-2642-fe0f", native: "\u{1F3CA}\u{1F3FD}\u200D\u2642\uFE0F" }, { unified: "1f3ca-1f3fe-200d-2642-fe0f", native: "\u{1F3CA}\u{1F3FE}\u200D\u2642\uFE0F" }, { unified: "1f3ca-1f3ff-200d-2642-fe0f", native: "\u{1F3CA}\u{1F3FF}\u200D\u2642\uFE0F" }], version: 4 }, "woman-swimming": { id: "woman-swimming", name: "Woman Swimming", keywords: ["sports", "exercise", "human", "athlete", "water", "summer", "female"], skins: [{ unified: "1f3ca-200d-2640-fe0f", native: "\u{1F3CA}\u200D\u2640\uFE0F" }, { unified: "1f3ca-1f3fb-200d-2640-fe0f", native: "\u{1F3CA}\u{1F3FB}\u200D\u2640\uFE0F" }, { unified: "1f3ca-1f3fc-200d-2640-fe0f", native: "\u{1F3CA}\u{1F3FC}\u200D\u2640\uFE0F" }, { unified: "1f3ca-1f3fd-200d-2640-fe0f", native: "\u{1F3CA}\u{1F3FD}\u200D\u2640\uFE0F" }, { unified: "1f3ca-1f3fe-200d-2640-fe0f", native: "\u{1F3CA}\u{1F3FE}\u200D\u2640\uFE0F" }, { unified: "1f3ca-1f3ff-200d-2640-fe0f", native: "\u{1F3CA}\u{1F3FF}\u200D\u2640\uFE0F" }], version: 4 }, person_with_ball: { id: "person_with_ball", name: "Person Bouncing Ball", keywords: ["with", "sports", "human"], skins: [{ unified: "26f9-fe0f", native: "\u26F9\uFE0F" }, { unified: "26f9-1f3fb", native: "\u26F9\u{1F3FB}" }, { unified: "26f9-1f3fc", native: "\u26F9\u{1F3FC}" }, { unified: "26f9-1f3fd", native: "\u26F9\u{1F3FD}" }, { unified: "26f9-1f3fe", native: "\u26F9\u{1F3FE}" }, { unified: "26f9-1f3ff", native: "\u26F9\u{1F3FF}" }], version: 1 }, "man-bouncing-ball": { id: "man-bouncing-ball", name: "Man Bouncing Ball", keywords: ["bouncing-ball", "sport"], skins: [{ unified: "26f9-fe0f-200d-2642-fe0f", native: "\u26F9\uFE0F\u200D\u2642\uFE0F" }, { unified: "26f9-1f3fb-200d-2642-fe0f", native: "\u26F9\u{1F3FB}\u200D\u2642\uFE0F" }, { unified: "26f9-1f3fc-200d-2642-fe0f", native: "\u26F9\u{1F3FC}\u200D\u2642\uFE0F" }, { unified: "26f9-1f3fd-200d-2642-fe0f", native: "\u26F9\u{1F3FD}\u200D\u2642\uFE0F" }, { unified: "26f9-1f3fe-200d-2642-fe0f", native: "\u26F9\u{1F3FE}\u200D\u2642\uFE0F" }, { unified: "26f9-1f3ff-200d-2642-fe0f", native: "\u26F9\u{1F3FF}\u200D\u2642\uFE0F" }], version: 4 }, "woman-bouncing-ball": { id: "woman-bouncing-ball", name: "Woman Bouncing Ball", keywords: ["bouncing-ball", "sports", "human", "female"], skins: [{ unified: "26f9-fe0f-200d-2640-fe0f", native: "\u26F9\uFE0F\u200D\u2640\uFE0F" }, { unified: "26f9-1f3fb-200d-2640-fe0f", native: "\u26F9\u{1F3FB}\u200D\u2640\uFE0F" }, { unified: "26f9-1f3fc-200d-2640-fe0f", native: "\u26F9\u{1F3FC}\u200D\u2640\uFE0F" }, { unified: "26f9-1f3fd-200d-2640-fe0f", native: "\u26F9\u{1F3FD}\u200D\u2640\uFE0F" }, { unified: "26f9-1f3fe-200d-2640-fe0f", native: "\u26F9\u{1F3FE}\u200D\u2640\uFE0F" }, { unified: "26f9-1f3ff-200d-2640-fe0f", native: "\u26F9\u{1F3FF}\u200D\u2640\uFE0F" }], version: 4 }, weight_lifter: { id: "weight_lifter", name: "Person Lifting Weights", keywords: ["weight", "lifter", "sports", "training", "exercise"], skins: [{ unified: "1f3cb-fe0f", native: "\u{1F3CB}\uFE0F" }, { unified: "1f3cb-1f3fb", native: "\u{1F3CB}\u{1F3FB}" }, { unified: "1f3cb-1f3fc", native: "\u{1F3CB}\u{1F3FC}" }, { unified: "1f3cb-1f3fd", native: "\u{1F3CB}\u{1F3FD}" }, { unified: "1f3cb-1f3fe", native: "\u{1F3CB}\u{1F3FE}" }, { unified: "1f3cb-1f3ff", native: "\u{1F3CB}\u{1F3FF}" }], version: 1 }, "man-lifting-weights": { id: "man-lifting-weights", name: "Man Lifting Weights", keywords: ["lifting-weights", "sport"], skins: [{ unified: "1f3cb-fe0f-200d-2642-fe0f", native: "\u{1F3CB}\uFE0F\u200D\u2642\uFE0F" }, { unified: "1f3cb-1f3fb-200d-2642-fe0f", native: "\u{1F3CB}\u{1F3FB}\u200D\u2642\uFE0F" }, { unified: "1f3cb-1f3fc-200d-2642-fe0f", native: "\u{1F3CB}\u{1F3FC}\u200D\u2642\uFE0F" }, { unified: "1f3cb-1f3fd-200d-2642-fe0f", native: "\u{1F3CB}\u{1F3FD}\u200D\u2642\uFE0F" }, { unified: "1f3cb-1f3fe-200d-2642-fe0f", native: "\u{1F3CB}\u{1F3FE}\u200D\u2642\uFE0F" }, { unified: "1f3cb-1f3ff-200d-2642-fe0f", native: "\u{1F3CB}\u{1F3FF}\u200D\u2642\uFE0F" }], version: 4 }, "woman-lifting-weights": { id: "woman-lifting-weights", name: "Woman Lifting Weights", keywords: ["lifting-weights", "sports", "training", "exercise", "female"], skins: [{ unified: "1f3cb-fe0f-200d-2640-fe0f", native: "\u{1F3CB}\uFE0F\u200D\u2640\uFE0F" }, { unified: "1f3cb-1f3fb-200d-2640-fe0f", native: "\u{1F3CB}\u{1F3FB}\u200D\u2640\uFE0F" }, { unified: "1f3cb-1f3fc-200d-2640-fe0f", native: "\u{1F3CB}\u{1F3FC}\u200D\u2640\uFE0F" }, { unified: "1f3cb-1f3fd-200d-2640-fe0f", native: "\u{1F3CB}\u{1F3FD}\u200D\u2640\uFE0F" }, { unified: "1f3cb-1f3fe-200d-2640-fe0f", native: "\u{1F3CB}\u{1F3FE}\u200D\u2640\uFE0F" }, { unified: "1f3cb-1f3ff-200d-2640-fe0f", native: "\u{1F3CB}\u{1F3FF}\u200D\u2640\uFE0F" }], version: 4 }, bicyclist: { id: "bicyclist", name: "Bicyclist", keywords: ["person", "biking", "bicycle", "bike", "cyclist", "sport", "move"], skins: [{ unified: "1f6b4", native: "\u{1F6B4}" }, { unified: "1f6b4-1f3fb", native: "\u{1F6B4}\u{1F3FB}" }, { unified: "1f6b4-1f3fc", native: "\u{1F6B4}\u{1F3FC}" }, { unified: "1f6b4-1f3fd", native: "\u{1F6B4}\u{1F3FD}" }, { unified: "1f6b4-1f3fe", native: "\u{1F6B4}\u{1F3FE}" }, { unified: "1f6b4-1f3ff", native: "\u{1F6B4}\u{1F3FF}" }], version: 1 }, "man-biking": { id: "man-biking", name: "Man Biking", keywords: ["bicycle", "bike", "cyclist", "sports", "exercise", "hipster"], skins: [{ unified: "1f6b4-200d-2642-fe0f", native: "\u{1F6B4}\u200D\u2642\uFE0F" }, { unified: "1f6b4-1f3fb-200d-2642-fe0f", native: "\u{1F6B4}\u{1F3FB}\u200D\u2642\uFE0F" }, { unified: "1f6b4-1f3fc-200d-2642-fe0f", native: "\u{1F6B4}\u{1F3FC}\u200D\u2642\uFE0F" }, { unified: "1f6b4-1f3fd-200d-2642-fe0f", native: "\u{1F6B4}\u{1F3FD}\u200D\u2642\uFE0F" }, { unified: "1f6b4-1f3fe-200d-2642-fe0f", native: "\u{1F6B4}\u{1F3FE}\u200D\u2642\uFE0F" }, { unified: "1f6b4-1f3ff-200d-2642-fe0f", native: "\u{1F6B4}\u{1F3FF}\u200D\u2642\uFE0F" }], version: 4 }, "woman-biking": { id: "woman-biking", name: "Woman Biking", keywords: ["bicycle", "bike", "cyclist", "sports", "exercise", "hipster", "female"], skins: [{ unified: "1f6b4-200d-2640-fe0f", native: "\u{1F6B4}\u200D\u2640\uFE0F" }, { unified: "1f6b4-1f3fb-200d-2640-fe0f", native: "\u{1F6B4}\u{1F3FB}\u200D\u2640\uFE0F" }, { unified: "1f6b4-1f3fc-200d-2640-fe0f", native: "\u{1F6B4}\u{1F3FC}\u200D\u2640\uFE0F" }, { unified: "1f6b4-1f3fd-200d-2640-fe0f", native: "\u{1F6B4}\u{1F3FD}\u200D\u2640\uFE0F" }, { unified: "1f6b4-1f3fe-200d-2640-fe0f", native: "\u{1F6B4}\u{1F3FE}\u200D\u2640\uFE0F" }, { unified: "1f6b4-1f3ff-200d-2640-fe0f", native: "\u{1F6B4}\u{1F3FF}\u200D\u2640\uFE0F" }], version: 4 }, mountain_bicyclist: { id: "mountain_bicyclist", name: "Mountain Bicyclist", keywords: ["person", "biking", "bicycle", "bike", "cyclist", "sport", "move"], skins: [{ unified: "1f6b5", native: "\u{1F6B5}" }, { unified: "1f6b5-1f3fb", native: "\u{1F6B5}\u{1F3FB}" }, { unified: "1f6b5-1f3fc", native: "\u{1F6B5}\u{1F3FC}" }, { unified: "1f6b5-1f3fd", native: "\u{1F6B5}\u{1F3FD}" }, { unified: "1f6b5-1f3fe", native: "\u{1F6B5}\u{1F3FE}" }, { unified: "1f6b5-1f3ff", native: "\u{1F6B5}\u{1F3FF}" }], version: 1 }, "man-mountain-biking": { id: "man-mountain-biking", name: "Man Mountain Biking", keywords: ["mountain-biking", "bicycle", "bike", "cyclist", "transportation", "sports", "human", "race"], skins: [{ unified: "1f6b5-200d-2642-fe0f", native: "\u{1F6B5}\u200D\u2642\uFE0F" }, { unified: "1f6b5-1f3fb-200d-2642-fe0f", native: "\u{1F6B5}\u{1F3FB}\u200D\u2642\uFE0F" }, { unified: "1f6b5-1f3fc-200d-2642-fe0f", native: "\u{1F6B5}\u{1F3FC}\u200D\u2642\uFE0F" }, { unified: "1f6b5-1f3fd-200d-2642-fe0f", native: "\u{1F6B5}\u{1F3FD}\u200D\u2642\uFE0F" }, { unified: "1f6b5-1f3fe-200d-2642-fe0f", native: "\u{1F6B5}\u{1F3FE}\u200D\u2642\uFE0F" }, { unified: "1f6b5-1f3ff-200d-2642-fe0f", native: "\u{1F6B5}\u{1F3FF}\u200D\u2642\uFE0F" }], version: 4 }, "woman-mountain-biking": { id: "woman-mountain-biking", name: "Woman Mountain Biking", keywords: ["mountain-biking", "bicycle", "bike", "cyclist", "transportation", "sports", "human", "race", "female"], skins: [{ unified: "1f6b5-200d-2640-fe0f", native: "\u{1F6B5}\u200D\u2640\uFE0F" }, { unified: "1f6b5-1f3fb-200d-2640-fe0f", native: "\u{1F6B5}\u{1F3FB}\u200D\u2640\uFE0F" }, { unified: "1f6b5-1f3fc-200d-2640-fe0f", native: "\u{1F6B5}\u{1F3FC}\u200D\u2640\uFE0F" }, { unified: "1f6b5-1f3fd-200d-2640-fe0f", native: "\u{1F6B5}\u{1F3FD}\u200D\u2640\uFE0F" }, { unified: "1f6b5-1f3fe-200d-2640-fe0f", native: "\u{1F6B5}\u{1F3FE}\u200D\u2640\uFE0F" }, { unified: "1f6b5-1f3ff-200d-2640-fe0f", native: "\u{1F6B5}\u{1F3FF}\u200D\u2640\uFE0F" }], version: 4 }, person_doing_cartwheel: { id: "person_doing_cartwheel", name: "Person Cartwheeling", keywords: ["doing", "cartwheel", "sport", "gymnastic"], skins: [{ unified: "1f938", native: "\u{1F938}" }, { unified: "1f938-1f3fb", native: "\u{1F938}\u{1F3FB}" }, { unified: "1f938-1f3fc", native: "\u{1F938}\u{1F3FC}" }, { unified: "1f938-1f3fd", native: "\u{1F938}\u{1F3FD}" }, { unified: "1f938-1f3fe", native: "\u{1F938}\u{1F3FE}" }, { unified: "1f938-1f3ff", native: "\u{1F938}\u{1F3FF}" }], version: 3 }, "man-cartwheeling": { id: "man-cartwheeling", name: "Man Cartwheeling", keywords: ["gymnastics"], skins: [{ unified: "1f938-200d-2642-fe0f", native: "\u{1F938}\u200D\u2642\uFE0F" }, { unified: "1f938-1f3fb-200d-2642-fe0f", native: "\u{1F938}\u{1F3FB}\u200D\u2642\uFE0F" }, { unified: "1f938-1f3fc-200d-2642-fe0f", native: "\u{1F938}\u{1F3FC}\u200D\u2642\uFE0F" }, { unified: "1f938-1f3fd-200d-2642-fe0f", native: "\u{1F938}\u{1F3FD}\u200D\u2642\uFE0F" }, { unified: "1f938-1f3fe-200d-2642-fe0f", native: "\u{1F938}\u{1F3FE}\u200D\u2642\uFE0F" }, { unified: "1f938-1f3ff-200d-2642-fe0f", native: "\u{1F938}\u{1F3FF}\u200D\u2642\uFE0F" }], version: 4 }, "woman-cartwheeling": { id: "woman-cartwheeling", name: "Woman Cartwheeling", keywords: ["gymnastics"], skins: [{ unified: "1f938-200d-2640-fe0f", native: "\u{1F938}\u200D\u2640\uFE0F" }, { unified: "1f938-1f3fb-200d-2640-fe0f", native: "\u{1F938}\u{1F3FB}\u200D\u2640\uFE0F" }, { unified: "1f938-1f3fc-200d-2640-fe0f", native: "\u{1F938}\u{1F3FC}\u200D\u2640\uFE0F" }, { unified: "1f938-1f3fd-200d-2640-fe0f", native: "\u{1F938}\u{1F3FD}\u200D\u2640\uFE0F" }, { unified: "1f938-1f3fe-200d-2640-fe0f", native: "\u{1F938}\u{1F3FE}\u200D\u2640\uFE0F" }, { unified: "1f938-1f3ff-200d-2640-fe0f", native: "\u{1F938}\u{1F3FF}\u200D\u2640\uFE0F" }], version: 4 }, wrestlers: { id: "wrestlers", name: "Wrestlers", keywords: ["people", "wrestling", "sport"], skins: [{ unified: "1f93c", native: "\u{1F93C}" }], version: 3 }, "man-wrestling": { id: "man-wrestling", name: "Men Wrestling", keywords: ["man", "sports", "wrestlers"], skins: [{ unified: "1f93c-200d-2642-fe0f", native: "\u{1F93C}\u200D\u2642\uFE0F" }], version: 4 }, "woman-wrestling": { id: "woman-wrestling", name: "Women Wrestling", keywords: ["woman", "sports", "wrestlers"], skins: [{ unified: "1f93c-200d-2640-fe0f", native: "\u{1F93C}\u200D\u2640\uFE0F" }], version: 4 }, water_polo: { id: "water_polo", name: "Water Polo", keywords: ["person", "playing", "sport"], skins: [{ unified: "1f93d", native: "\u{1F93D}" }, { unified: "1f93d-1f3fb", native: "\u{1F93D}\u{1F3FB}" }, { unified: "1f93d-1f3fc", native: "\u{1F93D}\u{1F3FC}" }, { unified: "1f93d-1f3fd", native: "\u{1F93D}\u{1F3FD}" }, { unified: "1f93d-1f3fe", native: "\u{1F93D}\u{1F3FE}" }, { unified: "1f93d-1f3ff", native: "\u{1F93D}\u{1F3FF}" }], version: 3 }, "man-playing-water-polo": { id: "man-playing-water-polo", name: "Man Playing Water Polo", keywords: ["playing-water-polo", "sports", "pool"], skins: [{ unified: "1f93d-200d-2642-fe0f", native: "\u{1F93D}\u200D\u2642\uFE0F" }, { unified: "1f93d-1f3fb-200d-2642-fe0f", native: "\u{1F93D}\u{1F3FB}\u200D\u2642\uFE0F" }, { unified: "1f93d-1f3fc-200d-2642-fe0f", native: "\u{1F93D}\u{1F3FC}\u200D\u2642\uFE0F" }, { unified: "1f93d-1f3fd-200d-2642-fe0f", native: "\u{1F93D}\u{1F3FD}\u200D\u2642\uFE0F" }, { unified: "1f93d-1f3fe-200d-2642-fe0f", native: "\u{1F93D}\u{1F3FE}\u200D\u2642\uFE0F" }, { unified: "1f93d-1f3ff-200d-2642-fe0f", native: "\u{1F93D}\u{1F3FF}\u200D\u2642\uFE0F" }], version: 4 }, "woman-playing-water-polo": { id: "woman-playing-water-polo", name: "Woman Playing Water Polo", keywords: ["playing-water-polo", "sports", "pool"], skins: [{ unified: "1f93d-200d-2640-fe0f", native: "\u{1F93D}\u200D\u2640\uFE0F" }, { uni
51763fied: "1f93d-1f3fb-200d-2640-fe0f", native: "\u{1F93D}\u{1F3FB}\u200D\u2640\uFE0F" }, { unified: "1f93d-1f3fc-200d-2640-fe0f", native: "\u{1F93D}\u{1F3FC}\u200D\u2640\uFE0F" }, { unified: "1f93d-1f3fd-200d-2640-fe0f", native: "\u{1F93D}\u{1F3FD}\u200D\u2640\uFE0F" }, { unified: "1f93d-1f3fe-200d-2640-fe0f", native: "\u{1F93D}\u{1F3FE}\u200D\u2640\uFE0F" }, { unified: "1f93d-1f3ff-200d-2640-fe0f", native: "\u{1F93D}\u{1F3FF}\u200D\u2640\uFE0F" }], version: 4 }, handball: { id: "handball", name: "Handball", keywords: ["person", "playing", "sport"], skins: [{ unified: "1f93e", native: "\u{1F93E}" }, { unified: "1f93e-1f3fb", native: "\u{1F93E}\u{1F3FB}" }, { unified: "1f93e-1f3fc", native: "\u{1F93E}\u{1F3FC}" }, { unified: "1f93e-1f3fd", native: "\u{1F93E}\u{1F3FD}" }, { unified: "1f93e-1f3fe", native: "\u{1F93E}\u{1F3FE}" }, { unified: "1f93e-1f3ff", native: "\u{1F93E}\u{1F3FF}" }], version: 3 }, "man-playing-handball": { id: "man-playing-handball", name: "Man Playing Handball", keywords: ["playing-handball", "sports"], skins: [{ unified: "1f93e-200d-2642-fe0f", native: "\u{1F93E}\u200D\u2642\uFE0F" }, { unified: "1f93e-1f3fb-200d-2642-fe0f", native: "\u{1F93E}\u{1F3FB}\u200D\u2642\uFE0F" }, { unified: "1f93e-1f3fc-200d-2642-fe0f", native: "\u{1F93E}\u{1F3FC}\u200D\u2642\uFE0F" }, { unified: "1f93e-1f3fd-200d-2642-fe0f", native: "\u{1F93E}\u{1F3FD}\u200D\u2642\uFE0F" }, { unified: "1f93e-1f3fe-200d-2642-fe0f", native: "\u{1F93E}\u{1F3FE}\u200D\u2642\uFE0F" }, { unified: "1f93e-1f3ff-200d-2642-fe0f", native: "\u{1F93E}\u{1F3FF}\u200D\u2642\uFE0F" }], version: 4 }, "woman-playing-handball": { id: "woman-playing-handball", name: "Woman Playing Handball", keywords: ["playing-handball", "sports"], skins: [{ unified: "1f93e-200d-2640-fe0f", native: "\u{1F93E}\u200D\u2640\uFE0F" }, { unified: "1f93e-1f3fb-200d-2640-fe0f", native: "\u{1F93E}\u{1F3FB}\u200D\u2640\uFE0F" }, { unified: "1f93e-1f3fc-200d-2640-fe0f", native: "\u{1F93E}\u{1F3FC}\u200D\u2640\uFE0F" }, { unified: "1f93e-1f3fd-200d-2640-fe0f", native: "\u{1F93E}\u{1F3FD}\u200D\u2640\uFE0F" }, { unified: "1f93e-1f3fe-200d-2640-fe0f", native: "\u{1F93E}\u{1F3FE}\u200D\u2640\uFE0F" }, { unified: "1f93e-1f3ff-200d-2640-fe0f", native: "\u{1F93E}\u{1F3FF}\u200D\u2640\uFE0F" }], version: 4 }, juggling: { id: "juggling", name: "Juggling", keywords: ["person", "performance", "balance"], skins: [{ unified: "1f939", native: "\u{1F939}" }, { unified: "1f939-1f3fb", native: "\u{1F939}\u{1F3FB}" }, { unified: "1f939-1f3fc", native: "\u{1F939}\u{1F3FC}" }, { unified: "1f939-1f3fd", native: "\u{1F939}\u{1F3FD}" }, { unified: "1f939-1f3fe", native: "\u{1F939}\u{1F3FE}" }, { unified: "1f939-1f3ff", native: "\u{1F939}\u{1F3FF}" }], version: 3 }, "man-juggling": { id: "man-juggling", name: "Man Juggling", keywords: ["juggle", "balance", "skill", "multitask"], skins: [{ unified: "1f939-200d-2642-fe0f", native: "\u{1F939}\u200D\u2642\uFE0F" }, { unified: "1f939-1f3fb-200d-2642-fe0f", native: "\u{1F939}\u{1F3FB}\u200D\u2642\uFE0F" }, { unified: "1f939-1f3fc-200d-2642-fe0f", native: "\u{1F939}\u{1F3FC}\u200D\u2642\uFE0F" }, { unified: "1f939-1f3fd-200d-2642-fe0f", native: "\u{1F939}\u{1F3FD}\u200D\u2642\uFE0F" }, { unified: "1f939-1f3fe-200d-2642-fe0f", native: "\u{1F939}\u{1F3FE}\u200D\u2642\uFE0F" }, { unified: "1f939-1f3ff-200d-2642-fe0f", native: "\u{1F939}\u{1F3FF}\u200D\u2642\uFE0F" }], version: 4 }, "woman-juggling": { id: "woman-juggling", name: "Woman Juggling", keywords: ["juggle", "balance", "skill", "multitask"], skins: [{ unified: "1f939-200d-2640-fe0f", native: "\u{1F939}\u200D\u2640\uFE0F" }, { unified: "1f939-1f3fb-200d-2640-fe0f", native: "\u{1F939}\u{1F3FB}\u200D\u2640\uFE0F" }, { unified: "1f939-1f3fc-200d-2640-fe0f", native: "\u{1F939}\u{1F3FC}\u200D\u2640\uFE0F" }, { unified: "1f939-1f3fd-200d-2640-fe0f", native: "\u{1F939}\u{1F3FD}\u200D\u2640\uFE0F" }, { unified: "1f939-1f3fe-200d-2640-fe0f", native: "\u{1F939}\u{1F3FE}\u200D\u2640\uFE0F" }, { unified: "1f939-1f3ff-200d-2640-fe0f", native: "\u{1F939}\u{1F3FF}\u200D\u2640\uFE0F" }], version: 4 }, person_in_lotus_position: { id: "person_in_lotus_position", name: "Person in Lotus Position", keywords: ["meditate"], skins: [{ unified: "1f9d8", native: "\u{1F9D8}" }, { unified: "1f9d8-1f3fb", native: "\u{1F9D8}\u{1F3FB}" }, { unified: "1f9d8-1f3fc", native: "\u{1F9D8}\u{1F3FC}" }, { unified: "1f9d8-1f3fd", native: "\u{1F9D8}\u{1F3FD}" }, { unified: "1f9d8-1f3fe", native: "\u{1F9D8}\u{1F3FE}" }, { unified: "1f9d8-1f3ff", native: "\u{1F9D8}\u{1F3FF}" }], version: 5 }, man_in_lotus_position: { id: "man_in_lotus_position", name: "Man in Lotus Position", keywords: ["male", "meditation", "yoga", "serenity", "zen", "mindfulness"], skins: [{ unified: "1f9d8-200d-2642-fe0f", native: "\u{1F9D8}\u200D\u2642\uFE0F" }, { unified: "1f9d8-1f3fb-200d-2642-fe0f", native: "\u{1F9D8}\u{1F3FB}\u200D\u2642\uFE0F" }, { unified: "1f9d8-1f3fc-200d-2642-fe0f", native: "\u{1F9D8}\u{1F3FC}\u200D\u2642\uFE0F" }, { unified: "1f9d8-1f3fd-200d-2642-fe0f", native: "\u{1F9D8}\u{1F3FD}\u200D\u2642\uFE0F" }, { unified: "1f9d8-1f3fe-200d-2642-fe0f", native: "\u{1F9D8}\u{1F3FE}\u200D\u2642\uFE0F" }, { unified: "1f9d8-1f3ff-200d-2642-fe0f", native: "\u{1F9D8}\u{1F3FF}\u200D\u2642\uFE0F" }], version: 5 }, woman_in_lotus_position: { id: "woman_in_lotus_position", name: "Woman in Lotus Position", keywords: ["female", "meditation", "yoga", "serenity", "zen", "mindfulness"], skins: [{ unified: "1f9d8-200d-2640-fe0f", native: "\u{1F9D8}\u200D\u2640\uFE0F" }, { unified: "1f9d8-1f3fb-200d-2640-fe0f", native: "\u{1F9D8}\u{1F3FB}\u200D\u2640\uFE0F" }, { unified: "1f9d8-1f3fc-200d-2640-fe0f", native: "\u{1F9D8}\u{1F3FC}\u200D\u2640\uFE0F" }, { unified: "1f9d8-1f3fd-200d-2640-fe0f", native: "\u{1F9D8}\u{1F3FD}\u200D\u2640\uFE0F" }, { unified: "1f9d8-1f3fe-200d-2640-fe0f", native: "\u{1F9D8}\u{1F3FE}\u200D\u2640\uFE0F" }, { unified: "1f9d8-1f3ff-200d-2640-fe0f", native: "\u{1F9D8}\u{1F3FF}\u200D\u2640\uFE0F" }], version: 5 }, bath: { id: "bath", name: "Bath", keywords: ["person", "taking", "clean", "shower", "bathroom"], skins: [{ unified: "1f6c0", native: "\u{1F6C0}" }, { unified: "1f6c0-1f3fb", native: "\u{1F6C0}\u{1F3FB}" }, { unified: "1f6c0-1f3fc", native: "\u{1F6C0}\u{1F3FC}" }, { unified: "1f6c0-1f3fd", native: "\u{1F6C0}\u{1F3FD}" }, { unified: "1f6c0-1f3fe", native: "\u{1F6C0}\u{1F3FE}" }, { unified: "1f6c0-1f3ff", native: "\u{1F6C0}\u{1F3FF}" }], version: 1 }, sleeping_accommodation: { id: "sleeping_accommodation", name: "Person in Bed", keywords: ["sleeping", "accommodation", "rest"], skins: [{ unified: "1f6cc", native: "\u{1F6CC}" }, { unified: "1f6cc-1f3fb", native: "\u{1F6CC}\u{1F3FB}" }, { unified: "1f6cc-1f3fc", native: "\u{1F6CC}\u{1F3FC}" }, { unified: "1f6cc-1f3fd", native: "\u{1F6CC}\u{1F3FD}" }, { unified: "1f6cc-1f3fe", native: "\u{1F6CC}\u{1F3FE}" }, { unified: "1f6cc-1f3ff", native: "\u{1F6CC}\u{1F3FF}" }], version: 1 }, people_holding_hands: { id: "people_holding_hands", name: "People Holding Hands", keywords: ["friendship"], skins: [{ unified: "1f9d1-200d-1f91d-200d-1f9d1", native: "\u{1F9D1}\u200D\u{1F91D}\u200D\u{1F9D1}" }, { unified: "1f9d1-1f3fb-200d-1f91d-200d-1f9d1-1f3fb", native: "\u{1F9D1}\u{1F3FB}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FB}" }, { unified: "1f9d1-1f3fc-200d-1f91d-200d-1f9d1-1f3fc", native: "\u{1F9D1}\u{1F3FC}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FC}" }, { unified: "1f9d1-1f3fd-200d-1f91d-200d-1f9d1-1f3fd", native: "\u{1F9D1}\u{1F3FD}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FD}" }, { unified: "1f9d1-1f3fe-200d-1f91d-200d-1f9d1-1f3fe", native: "\u{1F9D1}\u{1F3FE}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FE}" }, { unified: "1f9d1-1f3ff-200d-1f91d-200d-1f9d1-1f3ff", native: "\u{1F9D1}\u{1F3FF}\u200D\u{1F91D}\u200D\u{1F9D1}\u{1F3FF}" }], version: 12 }, two_women_holding_hands: { id: "two_women_holding_hands", name: "Women Holding Hands", keywords: ["two", "pair", "friendship", "couple", "love", "like", "female", "people", "human"], skins: [{ unified: "1f46d", native: "\u{1F46D}" }, { unified: "1f46d-1f3fb", native: "\u{1F46D}\u{1F3FB}" }, { unified: "1f46d-1f3fc", native: "\u{1F46D}\u{1F3FC}" }, { unified: "1f46d-1f3fd", native: "\u{1F46D}\u{1F3FD}" }, { unified: "1f46d-1f3fe", native: "\u{1F46D}\u{1F3FE}" }, { unified: "1f46d-1f3ff", native: "\u{1F46D}\u{1F3FF}" }], version: 1 }, man_and_woman_holding_hands: { id: "man_and_woman_holding_hands", name: "Man and Woman Holding Hands", keywords: ["couple", "pair", "people", "human", "love", "date", "dating", "like", "affection", "valentines", "marriage"], skins: [{ unified: "1f46b", native: "\u{1F46B}" }, { unified: "1f46b-1f3fb", native: "\u{1F46B}\u{1F3FB}" }, { unified: "1f46b-1f3fc", native: "\u{1F46B}\u{1F3FC}" }, { unified: "1f46b-1f3fd", native: "\u{1F46B}\u{1F3FD}" }, { unified: "1f46b-1f3fe", native: "\u{1F46B}\u{1F3FE}" }, { unified: "1f46b-1f3ff", native: "\u{1F46B}\u{1F3FF}" }], version: 1 }
51763, two_men_holding_hands: { id: "two_men_holding_hands", name: "Men Holding Hands", keywords: ["two", "pair", "couple", "love", "like", "bromance", "friendship", "people", "human"], skins: [{ unified: "1f46c", native: "\u{1F46C}" }, { unified: "1f46c-1f3fb", native: "\u{1F46C}\u{1F3FB}" }, { unified: "1f46c-1f3fc", native: "\u{1F46C}\u{1F3FC}" }, { unified: "1f46c-1f3fd", native: "\u{1F46C}\u{1F3FD}" }, { unified: "1f46c-1f3fe", native: "\u{1F46C}\u{1F3FE}" }, { unified: "1f46c-1f3ff", native: "\u{1F46C}\u{1F3FF}" }], version: 1 }, couplekiss: { id: "couplekiss", name: "Kiss", keywords: ["couplekiss", "pair", "valentines", "love", "like", "dating", "marriage"], skins: [{ unified: "1f48f", native: "\u{1F48F}" }, { unified: "1f48f-1f3fb", native: "\u{1F48F}\u{1F3FB}" }, { unified: "1f48f-1f3fc", native: "\u{1F48F}\u{1F3FC}" }, { unified: "1f48f-1f3fd", native: "\u{1F48F}\u{1F3FD}" }, { unified: "1f48f-1f3fe", native: "\u{1F48F}\u{1F3FE}" }, { unified: "1f48f-1f3ff", native: "\u{1F48F}\u{1F3FF}" }], version: 1 }, "woman-kiss-man": { id: "woman-kiss-man", name: "Kiss: Woman, Man", keywords: ["woman", "kiss-man", "kiss", "love"], skins: [{ unified: "1f469-200d-2764-fe0f-200d-1f48b-200d-1f468", native: "\u{1F469}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}" }, { unified: "1f469-1f3fb-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fb", native: "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FB}" }, { unified: "1f469-1f3fc-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fc", native: "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FC}" }, { unified: "1f469-1f3fd-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fd", native: "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FD}" }, { unified: "1f469-1f3fe-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fe", native: "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FE}" }, { unified: "1f469-1f3ff-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3ff", native: "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FF}" }], version: 2 }, "man-kiss-man": { id: "man-kiss-man", name: "Kiss: Man, Man", keywords: ["kiss-man", "kiss", "pair", "valentines", "love", "like", "dating", "marriage"], skins: [{ unified: "1f468-200d-2764-fe0f-200d-1f48b-200d-1f468", native: "\u{1F468}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}" }, { unified: "1f468-1f3fb-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fb", native: "\u{1F468}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FB}" }, { unified: "1f468-1f3fc-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fc", native: "\u{1F468}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FC}" }, { unified: "1f468-1f3fd-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fd", native: "\u{1F468}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FD}" }, { unified: "1f468-1f3fe-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3fe", native: "\u{1F468}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FE}" }, { unified: "1f468-1f3ff-200d-2764-fe0f-200d-1f48b-200d-1f468-1f3ff", native: "\u{1F468}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F468}\u{1F3FF}" }], version: 2 }, "woman-kiss-woman": { id: "woman-kiss-woman", name: "Kiss: Woman, Woman", keywords: ["kiss-woman", "kiss", "pair", "valentines", "love", "like", "dating", "marriage"], skins: [{ unified: "1f469-200d-2764-fe0f-200d-1f48b-200d-1f469", native: "\u{1F469}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}" }, { unified: "1f469-1f3fb-200d-2764-fe0f-200d-1f48b-200d-1f469-1f3fb", native: "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FB}" }, { unified: "1f469-1f3fc-200d-2764-fe0f-200d-1f48b-200d-1f469-1f3fc", native: "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FC}" }, { unified: "1f469-1f3fd-200d-2764-fe0f-200d-1f48b-200d-1f469-1f3fd", native: "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FD}" }, { unified: "1f469-1f3fe-200d-2764-fe0f-200d-1f48b-200d-1f469-1f3fe", native: "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FE}" }, { unified: "1f469-1f3ff-200d-2764-fe0f-200d-1f48b-200d-1f469-1f3ff", native: "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F48B}\u200D\u{1F469}\u{1F3FF}" }], version: 2 }, couple_with_heart: { id: "couple_with_heart", name: "Couple with Heart", keywords: ["pair", "love", "like", "affection", "human", "dating", "valentines", "marriage"], skins: [{ unified: "1f491", native: "\u{1F491}" }, { unified: "1f491-1f3fb", native: "\u{1F491}\u{1F3FB}" }, { unified: "1f491-1f3fc", native: "\u{1F491}\u{1F3FC}" }, { unified: "1f491-1f3fd", native: "\u{1F491}\u{1F3FD}" }, { unified: "1f491-1f3fe", native: "\u{1F491}\u{1F3FE}" }, { unified: "1f491-1f3ff", native: "\u{1F491}\u{1F3FF}" }], version: 1 }, "woman-heart-man": { id: "woman-heart-man", name: "Couple with Heart: Woman, Man", keywords: ["woman", "heart-man", "heart", "love"], skins: [{ unified: "1f469-200d-2764-fe0f-200d-1f468", native: "\u{1F469}\u200D\u2764\uFE0F\u200D\u{1F468}" }, { unified: "1f469-1f3fb-200d-2764-fe0f-200d-1f468-1f3fb", native: "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FB}" }, { unified: "1f469-1f3fc-200d-2764-fe0f-200d-1f468-1f3fc", native: "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FC}" }, { unified: "1f469-1f3fd-200d-2764-fe0f-200d-1f468-1f3fd", native: "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FD}" }, { unified: "1f469-1f3fe-200d-2764-fe0f-200d-1f468-1f3fe", native: "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FE}" }, { unified: "1f469-1f3ff-200d-2764-fe0f-200d-1f468-1f3ff", native: "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FF}" }], version: 2 }, "man-heart-man": { id: "man-heart-man", name: "Couple with Heart: Man, Man", keywords: ["heart-man", "heart", "pair", "love", "like", "affection", "human", "dating", "valentines", "marriage"], skins: [{ unified: "1f468-200d-2764-fe0f-200d-1f468", native: "\u{1F468}\u200D\u2764\uFE0F\u200D\u{1F468}" }, { unified: "1f468-1f3fb-200d-2764-fe0f-200d-1f468-1f3fb", native: "\u{1F468}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FB}" }, { unified: "1f468-1f3fc-200d-2764-fe0f-200d-1f468-1f3fc", native: "\u{1F468}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FC}" }, { unified: "1f468-1f3fd-200d-2764-fe0f-200d-1f468-1f3fd", native: "\u{1F468}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FD}" }, { unified: "1f468-1f3fe-200d-2764-fe0f-200d-1f468-1f3fe", native: "\u{1F468}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FE}" }, { unified: "1f468-1f3ff-200d-2764-fe0f-200d-1f468-1f3ff", native: "\u{1F468}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F468}\u{1F3FF}" }], version: 2 }, "woman-heart-woman": { id: "woman-heart-woman", name: "Couple with Heart: Woman, Woman", keywords: ["heart-woman", "heart", "pair", "love", "like", "affection", "human", "dating", "valentines", "marriage"], skins: [{ unified: "1f469-200d-2764-fe0f-200d-1f469", native: "\u{1F469}\u200D\u2764\uFE0F\u200D\u{1F469}" }, { unified: "1f469-1f3fb-200d-2764-fe0f-200d-1f469-1f3fb", native: "\u{1F469}\u{1F3FB}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FB}" }, { unified: "1f469-1f3fc-200d-2764-fe0f-200d-1f469-1f3fc", native: "\u{1F469}\u{1F3FC}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FC}" }, { unified: "1f469-1f3fd-200d-2764-fe0f-200d-1f469-1f3fd", native: "\u{1F469}\u{1F3FD}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FD}" }, { unified: "1f469-1f3fe-200d-2764-fe0f-200d-1f469-1f3fe", native: "\u{1F469}\u{1F3FE}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FE}" }, { unified: "1f469-1f3ff-200d-2764-fe0f-200d-1f469-1f3ff", native: "\u{1F469}\u{1F3FF}\u200D\u2764\uFE0F\u200D\u{1F469}\u{1F3FF}" }], version: 2 }, "man-woman-boy": { id: "man-woman-boy", name: "Family: Man, Woman, Boy", keywords: ["man", "woman-boy", "family", "woman", "love"], skins: [{ unified: "1f468-200d-1f469-200d-1f466", native: "\u{1F468}\u200D\u{1F469}\u200D\u{1F466}" }], version: 2 }, "man-woman-girl": { id: "man-woman-girl", name: "Family: Man, Woman, Girl", keywords: ["man", "woman-girl", "family", "woman", "home", "parents", "peo
51763ple", "human", "child"], skins: [{ unified: "1f468-200d-1f469-200d-1f467", native: "\u{1F468}\u200D\u{1F469}\u200D\u{1F467}" }], version: 2 }, "man-woman-girl-boy": { id: "man-woman-girl-boy", name: "Family: Man, Woman, Girl, Boy", keywords: ["man", "woman-girl-boy", "family", "woman", "girl", "home", "parents", "people", "human", "children"], skins: [{ unified: "1f468-200d-1f469-200d-1f467-200d-1f466", native: "\u{1F468}\u200D\u{1F469}\u200D\u{1F467}\u200D\u{1F466}" }], version: 2 }, "man-woman-boy-boy": { id: "man-woman-boy-boy", name: "Family: Man, Woman, Boy, Boy", keywords: ["man", "woman-boy-boy", "family", "woman", "home", "parents", "people", "human", "children"], skins: [{ unified: "1f468-200d-1f469-200d-1f466-200d-1f466", native: "\u{1F468}\u200D\u{1F469}\u200D\u{1F466}\u200D\u{1F466}" }], version: 2 }, "man-woman-girl-girl": { id: "man-woman-girl-girl", name: "Family: Man, Woman, Girl, Girl", keywords: ["man", "woman-girl-girl", "family", "woman", "home", "parents", "people", "human", "children"], skins: [{ unified: "1f468-200d-1f469-200d-1f467-200d-1f467", native: "\u{1F468}\u200D\u{1F469}\u200D\u{1F467}\u200D\u{1F467}" }], version: 2 }, "man-man-boy": { id: "man-man-boy", name: "Family: Man, Man, Boy", keywords: ["man", "man-boy", "family", "home", "parents", "people", "human", "children"], skins: [{ unified: "1f468-200d-1f468-200d-1f466", native: "\u{1F468}\u200D\u{1F468}\u200D\u{1F466}" }], version: 2 }, "man-man-girl": { id: "man-man-girl", name: "Family: Man, Man, Girl", keywords: ["man", "man-girl", "family", "home", "parents", "people", "human", "children"], skins: [{ unified: "1f468-200d-1f468-200d-1f467", native: "\u{1F468}\u200D\u{1F468}\u200D\u{1F467}" }], version: 2 }, "man-man-girl-boy": { id: "man-man-girl-boy", name: "Family: Man, Man, Girl, Boy", keywords: ["man", "man-girl-boy", "family", "girl", "home", "parents", "people", "human", "children"], skins: [{ unified: "1f468-200d-1f468-200d-1f467-200d-1f466", native: "\u{1F468}\u200D\u{1F468}\u200D\u{1F467}\u200D\u{1F466}" }], version: 2 }, "man-man-boy-boy": { id: "man-man-boy-boy", name: "Family: Man, Man, Boy, Boy", keywords: ["man", "man-boy-boy", "family", "home", "parents", "people", "human", "children"], skins: [{ unified: "1f468-200d-1f468-200d-1f466-200d-1f466", native: "\u{1F468}\u200D\u{1F468}\u200D\u{1F466}\u200D\u{1F466}" }], version: 2 }, "man-man-girl-girl": { id: "man-man-girl-girl", name: "Family: Man, Man, Girl, Girl", keywords: ["man", "man-girl-girl", "family", "home", "parents", "people", "human", "children"], skins: [{ unified: "1f468-200d-1f468-200d-1f467-200d-1f467", native: "\u{1F468}\u200D\u{1F468}\u200D\u{1F467}\u200D\u{1F467}" }], version: 2 }, "woman-woman-boy": { id: "woman-woman-boy", name: "Family: Woman, Woman, Boy", keywords: ["woman", "woman-boy", "family", "home", "parents", "people", "human", "children"], skins: [{ unified: "1f469-200d-1f469-200d-1f466", native: "\u{1F469}\u200D\u{1F469}\u200D\u{1F466}" }], version: 2 }, "woman-woman-girl": { id: "woman-woman-girl", name: "Family: Woman, Woman, Girl", keywords: ["woman", "woman-girl", "family", "home", "parents", "people", "human", "children"], skins: [{ unified: "1f469-200d-1f469-200d-1f467", native: "\u{1F469}\u200D\u{1F469}\u200D\u{1F467}" }], version: 2 }, "woman-woman-girl-boy": { id: "woman-woman-girl-boy", name: "Family: Woman, Woman, Girl, Boy", keywords: ["woman", "woman-girl-boy", "family", "girl", "home", "parents", "people", "human", "children"], skins: [{ unified: "1f469-200d-1f469-200d-1f467-200d-1f466", native: "\u{1F469}\u200D\u{1F469}\u200D\u{1F467}\u200D\u{1F466}" }], version: 2 }, "woman-woman-boy-boy": { id: "woman-woman-boy-boy", name: "Family: Woman, Woman, Boy, Boy", keywords: ["woman", "woman-boy-boy", "family", "home", "parents", "people", "human", "children"], skins: [{ unified: "1f469-200d-1f469-200d-1f466-200d-1f466", native: "\u{1F469}\u200D\u{1F469}\u200D\u{1F466}\u200D\u{1F466}" }], version: 2 }, "woman-woman-girl-girl": { id: "woman-woman-girl-girl", name: "Family: Woman, Woman, Girl, Girl", keywords: ["woman", "woman-girl-girl", "family", "home", "parents", "peo
51763ple", "human", "children"], skins: [{ unified: "1f469-200d-1f469-200d-1f467-200d-1f467", native: "\u{1F469}\u200D\u{1F469}\u200D\u{1F467}\u200D\u{1F467}" }], version: 2 }, "man-boy": { id: "man-boy", name: "Family: Man, Boy", keywords: ["man", "family", "home", "parent", "people", "human", "child"], skins: [{ unified: "1f468-200d-1f466", native: "\u{1F468}\u200D\u{1F466}" }], version: 4 }, "man-boy-boy": { id: "man-boy-boy", name: "Family: Man, Boy, Boy", keywords: ["man", "boy-boy", "family", "home", "parent", "people", "human", "children"], skins: [{ unified: "1f468-200d-1f466-200d-1f466", native: "\u{1F468}\u200D\u{1F466}\u200D\u{1F466}" }], version: 4 }, "man-girl": { id: "man-girl", name: "Family: Man, Girl", keywords: ["man", "family", "home", "parent", "people", "human", "child"], skins: [{ unified: "1f468-200d-1f467", native: "\u{1F468}\u200D\u{1F467}" }], version: 4 }, "man-girl-boy": { id: "man-girl-boy", name: "Family: Man, Girl, Boy", keywords: ["man", "girl-boy", "family", "girl", "home", "parent", "people", "human", "children"], skins: [{ unified: "1f468-200d-1f467-200d-1f466", native: "\u{1F468}\u200D\u{1F467}\u200D\u{1F466}" }], version: 4 }, "man-girl-girl": { id: "man-girl-girl", name: "Family: Man, Girl, Girl", keywords: ["man", "girl-girl", "family", "home", "parent", "people", "human", "children"], skins: [{ unified: "1f468-200d-1f467-200d-1f467", native: "\u{1F468}\u200D\u{1F467}\u200D\u{1F467}" }], version: 4 }, "woman-boy": { id: "woman-boy", name: "Family: Woman, Boy", keywords: ["woman", "family", "home", "parent", "people", "human", "child"], skins: [{ unified: "1f469-200d-1f466", native: "\u{1F469}\u200D\u{1F466}" }], version: 4 }, "woman-boy-boy": { id: "woman-boy-boy", name: "Family: Woman, Boy, Boy", keywords: ["woman", "boy-boy", "family", "home", "parent", "people", "human", "children"], skins: [{ unified: "1f469-200d-1f466-200d-1f466", native: "\u{1F469}\u200D\u{1F466}\u200D\u{1F466}" }], version: 4 }, "woman-girl": { id: "woman-girl", name: "Family: Woman, Girl", keywords: ["woman", "family", "home", "parent", "people", "human", "child"], skins: [{ unified: "1f469-200d-1f467", native: "\u{1F469}\u200D\u{1F467}" }], version: 4 }, "woman-girl-boy": { id: "woman-girl-boy", name: "Family: Woman, Girl, Boy", keywords: ["woman", "girl-boy", "family", "girl", "home", "parent", "people", "human", "children"], skins: [{ unified: "1f469-200d-1f467-200d-1f466", native: "\u{1F469}\u200D\u{1F467}\u200D\u{1F466}" }], version: 4 }, "woman-girl-girl": { id: "woman-girl-girl", name: "Family: Woman, Girl, Girl", keywords: ["woman", "girl-girl", "family", "home", "parent", "people", "human", "children"], skins: [{ unified: "1f469-200d-1f467-200d-1f467", native: "\u{1F469}\u200D\u{1F467}\u200D\u{1F467}" }], version: 4 }, speaking_head_in_silhouette: { id: "speaking_head_in_silhouette", name: "Speaking Head", keywords: ["in", "silhouette", "user", "person", "human", "sing", "say", "talk"], skins: [{ unified: "1f5e3-fe0f", native: "\u{1F5E3}\uFE0F" }], version: 1 }, bust_in_silhouette: { id: "bust_in_silhouette", name: "Bust in Silhouette", keywords: ["user", "person", "human"], skins: [{ unified: "1f464", native: "\u{1F464}" }], version: 1 }, busts_in_silhouette: { id: "busts_in_silhouette", name: "Busts in Silhouette", keywords: ["user", "person", "human", "group", "team"], skins: [{ unified: "1f465", native: "\u{1F465}" }], version: 1 }, people_hugging: { id: "people_hugging", name: "People Hugging", keywords: ["care"], skins: [{ unified: "1fac2", native: "\u{1FAC2}" }], version: 13 }, family: { id: "family", name: "Family", keywords: ["home", "parents", "child", "mom", "dad", "father", "mother", "people", "human"], skins: [{ unified: "1f46a", native: "\u{1F46A}" }], version: 1 }, family_adult_adult_child: { id: "family_adult_adult_child", name: "Family: Adult, Adult, Child", keywords: ["family", "adult", "kid", "parents"], skins: [{ unified: "1f9d1-200d-1f9d1-200d-1f9d2", native: "\u{1F9D1}\u200D\u{1F9D1}\u200D\u{1F9D2}" }], version: 15.1 }, family_adult_adult_child_child: { id: "family_adult_adult_child_child", name: "Family: Adult, Adult, Child, Child", keywords: ["family", "adult", "children", "parents"], skins: [{ unified: "1f9d1-200d-1f9d1-200d-1f9d2-200d-1f9d2", native: "\u{1F9D1}\u200D\u{1F9D1}\u200D\u{1F9D2}\u200D\u{1F9D2}" }], version: 15.1 }, family_adult_child: { id: "family_adult_child", name: "Family: Adult, Child", keywords: ["family", "adult", "parent", "kid"], skins: [{ unified: "1f9d1-200d-1f9d2", native: "\u{1F9D1}\u200D\u{1F9D2}" }], version: 15.1 }, family_adult_child_child: { id: "family_adult_child_child", name: "Family: Adult, Child, Child", keywords: ["family", "adult", "parent", "children"], skins: [{ unified: "1f9d1-200d-1f9d2-200d-1f9d2", native: "\u{1F9D1}\u200D\u{1F9D2}\u200D\u{1F9D2}" }], version: 15.1 }, footprints: { id: "footprints", name: "Footprints", keywords: ["feet", "tracking", "walking", "beach"], skins: [{ unified: "1f463", native: "\u{1F463}" }], version: 1 }, fingerprint: { id: "fingerprint", name: "Fingerprint", keywords: [], skins: [{ unified: "1fac6", native: "\u{1FAC6}" }], version: 16 }, monkey_face: { id: "monkey_face", name: "Monkey Face", emoticons: [":o)"], keywords: ["animal", "nature", "circus"], skins: [{ unified: "1f435", native: "\u{1F435}" }], version: 1 }, monkey: { id: "monkey", name: "Monkey", keywords: ["animal", "nature", "banana", "circus"], skins: [{ unified: "1f412", native: "\u{1F412}" }], version: 1 }, gorilla: { id: "gorilla", name: "Gorilla", keywords: ["animal", "nature", "circus"], skins: [{ unified: "1f98d", native: "\u{1F98D}" }], version: 3 }, orangutan: { id: "orangutan", name: "Orangutan", keywords: ["animal"], skins: [{ unified: "1f9a7", native: "\u{1F9A7}" }], version: 12 }, dog: { id: "dog", name: "Dog Face", keywords: ["animal", "friend", "nature", "woof", "puppy", "pet", "faithful"], skins: [{ unified: "1f436", native: "\u{1F436}" }], version: 1 }, dog2: { id: "dog2", name: "Dog", keywords: ["dog2", "animal", "nature", "friend", "doge", "pet", "faithful"], skins: [{ unified: "1f415", native: "\u{1F415}" }], version: 1 }, guide_dog: { id: "guide_dog", name: "Guide Dog", keywords: ["animal", "blind"], skins: [{ unified: "1f9ae", native: "\u{1F9AE}" }], version: 12 }, service_dog: { id: "service_dog", name: "Service Dog", keywords: ["blind", "animal"], skins: [{ unified: "1f415-200d-1f9ba", native: "\u{1F415}\u200D\u{1F9BA}" }], version: 12 }, poodle: { id: "poodle", name: "Poodle", keywords: ["dog", "animal", "101", "nature", "pet"], skins: [{ unified: "1f429", native: "\u{1F429}" }], version: 1 }, wolf: { id: "wolf", name: "Wolf", keywords: ["animal", "nature", "wild"], skins: [{ unified: "1f43a", native: "\u{1F43A}" }], version: 1 }, fox_face: { id: "fox_face", name: "Fox", keywords: ["face", "animal", "nature"], skins: [{ unified: "1f98a", native: "\u{1F98A}" }
51763], version: 3 }, raccoon: { id: "raccoon", name: "Raccoon", keywords: ["animal", "nature"], skins: [{ unified: "1f99d", native: "\u{1F99D}" }], version: 11 }, cat: { id: "cat", name: "Cat Face", keywords: ["animal", "meow", "nature", "pet", "kitten"], skins: [{ unified: "1f431", native: "\u{1F431}" }], version: 1 }, cat2: { id: "cat2", name: "Cat", keywords: ["cat2", "animal", "meow", "pet", "cats"], skins: [{ unified: "1f408", native: "\u{1F408}" }], version: 1 }, black_cat: { id: "black_cat", name: "Black Cat", keywords: ["superstition", "luck"], skins: [{ unified: "1f408-200d-2b1b", native: "\u{1F408}\u200D\u2B1B" }], version: 13 }, lion_face: { id: "lion_face", name: "Lion", keywords: ["face", "animal", "nature"], skins: [{ unified: "1f981", native: "\u{1F981}" }], version: 1 }, tiger: { id: "tiger", name: "Tiger Face", keywords: ["animal", "cat", "danger", "wild", "nature", "roar"], skins: [{ unified: "1f42f", native: "\u{1F42F}" }], version: 1 }, tiger2: { id: "tiger2", name: "Tiger", keywords: ["tiger2", "animal", "nature", "roar"], skins: [{ unified: "1f405", native: "\u{1F405}" }], version: 1 }, leopard: { id: "leopard", name: "Leopard", keywords: ["animal", "nature"], skins: [{ unified: "1f406", native: "\u{1F406}" }], version: 1 }, horse: { id: "horse", name: "Horse Face", keywords: ["animal", "brown", "nature"], skins: [{ unified: "1f434", native: "\u{1F434}" }], version: 1 }, moose: { id: "moose", name: "Moose", keywords: ["shrek", "canada", "sweden", "sven", "cool"], skins: [{ unified: "1face", native: "\u{1FACE}" }], version: 15 }, donkey: { id: "donkey", name: "Donkey", keywords: ["eeyore", "mule"], skins: [{ unified: "1facf", native: "\u{1FACF}" }], version: 15 }, racehorse: { id: "racehorse", name: "Horse", keywords: ["racehorse", "animal", "gamble", "luck"], skins: [{ unified: "1f40e", native: "\u{1F40E}" }], version: 1 }, unicorn_face: { id: "unicorn_face", name: "Unicorn", keywords: ["face", "animal", "nature", "mystical"], skins: [{ unified: "1f984", native: "\u{1F984}" }], version: 1 }, zebra_face: { id: "zebra_face", name: "Zebra", keywords: ["face", "animal", "nature", "stripes", "safari"], skins: [{ unified: "1f993", native: "\u{1F993}" }], version: 5 }, deer: { id: "deer", name: "Deer", keywords: ["animal", "nature", "horns", "venison"], skins: [{ unified: "1f98c", native: "\u{1F98C}" }], version: 3 }, bison: { id: "bison", name: "Bison", keywords: ["ox"], skins: [{ unified: "1f9ac", native: "\u{1F9AC}" }], version: 13 }, cow: { id: "cow", name: "Cow Face", keywords: ["beef", "ox", "animal", "nature", "moo", "milk"], skins: [{ unified: "1f42e", native: "\u{1F42E}" }], version: 1 }, ox: { id: "ox", name: "Ox", keywords: ["animal", "cow", "beef"], skins: [{ unified: "1f402", native: "\u{1F402}" }], version: 1 }, water_buffalo: { id: "water_buffalo", name: "Water Buffalo", keywords: ["animal", "nature", "ox", "cow"], skins: [{ unified: "1f403", native: "\u{1F403}" }], version: 1 }, cow2: { id: "cow2", name: "Cow", keywords: ["cow2", "beef", "ox", "animal", "nature", "moo", "milk"], skins: [{ unified: "1f404", native: "\u{1F404}" }], version: 1 }, pig: { id: "pig", name: "Pig Face", keywords: ["animal", "oink", "nature"], skins: [{ unified: "1f437", native: "\u{1F437}" }], version: 1 }, pig2: { id: "pig2", name: "Pig", keywords: ["pig2", "animal", "nature"], skins: [{ unified: "1f416", native: "\u{1F416}" }], version: 1 }, boar: { id: "boar", name: "Boar", keywords: ["animal", "nature"], skins: [{ unified: "1f417", native: "\u{1F417}" }], version: 1 }, pig_nose: { id: "pig_nose", name: "Pig Nose", keywords: ["animal", "oink"], skins: [{ unified: "1f43d", native: "\u{1F43D}" }], version: 1 }, ram: { id: "ram", name: "Ram", keywords: ["animal", "sheep", "nature"], skins: [{ unified: "1f40f", native: "\u{1F40F}" }], version: 1 }, sheep: { id: "sheep", name: "Ewe", keywords: ["sheep", "animal", "nature", "wool", "shipit"], skins: [{ unified: "1f411", native: "\u{1F411}" }], version: 1 }, goat: { id: "goat", name: "Goat", keywords: ["animal", "nature"], skins: [{ unified: "1f410", native: "\u{1F410}" }], version: 1 }, dromedary_camel: { id: "dromedary_camel", name: "Camel", keywords: ["dromedary", "animal", "hot", "desert", "hump"], skins: [{ unified: "1f42a", native: "\u{1F42A}" }], version: 1 }, camel: { id: "camel", name: "Bactrian Camel", keywords: ["two", "hump", "animal", "nature", "hot", "desert"], skins: [{ unified: "1f42b", native: "\u{1F42B}" }], version: 1 }, llama: { id: "llama", name: "Llama", keywords: ["animal", "nature", "alpaca"], skins: [{ unified: "1f999", native: "\u{1F999}" }], version: 11 }, giraffe_face: { id: "giraffe_face", name: "Giraffe", keywords: ["face", "animal", "nature", "spots", "safari"], skins: [{ unified: "1f992", native: "\u{1F992}" }], version: 5 }, elephant: { id: "elephant", name: "Elephant", keywords: ["animal", "nature", "nose", "th", "cir
51763cus"], skins: [{ unified: "1f418", native: "\u{1F418}" }], version: 1 }, mammoth: { id: "mammoth", name: "Mammoth", keywords: ["elephant", "tusks"], skins: [{ unified: "1f9a3", native: "\u{1F9A3}" }], version: 13 }, rhinoceros: { id: "rhinoceros", name: "Rhinoceros", keywords: ["animal", "nature", "horn"], skins: [{ unified: "1f98f", native: "\u{1F98F}" }], version: 3 }, hippopotamus: { id: "hippopotamus", name: "Hippopotamus", keywords: ["animal", "nature"], skins: [{ unified: "1f99b", native: "\u{1F99B}" }], version: 11 }, mouse: { id: "mouse", name: "Mouse Face", keywords: ["animal", "nature", "cheese", "wedge", "rodent"], skins: [{ unified: "1f42d", native: "\u{1F42D}" }], version: 1 }, mouse2: { id: "mouse2", name: "Mouse", keywords: ["mouse2", "animal", "nature", "rodent"], skins: [{ unified: "1f401", native: "\u{1F401}" }], version: 1 }, rat: { id: "rat", name: "Rat", keywords: ["animal", "mouse", "rodent"], skins: [{ unified: "1f400", native: "\u{1F400}" }], version: 1 }, hamster: { id: "hamster", name: "Hamster", keywords: ["animal", "nature"], skins: [{ unified: "1f439", native: "\u{1F439}" }], version: 1 }, rabbit: { id: "rabbit", name: "Rabbit Face", keywords: ["animal", "nature", "pet", "spring", "magic", "bunny"], skins: [{ unified: "1f430", native: "\u{1F430}" }], version: 1 }, rabbit2: { id: "rabbit2", name: "Rabbit", keywords: ["rabbit2", "animal", "nature", "pet", "magic", "spring"], skins: [{ unified: "1f407", native: "\u{1F407}" }], version: 1 }, chipmunk: { id: "chipmunk", name: "Chipmunk", keywords: ["animal", "nature", "rodent", "squirrel"], skins: [{ unified: "1f43f-fe0f", native: "\u{1F43F}\uFE0F" }], version: 1 }, beaver: { id: "beaver", name: "Beaver", keywords: ["animal", "rodent"], skins: [{ unified: "1f9ab", native: "\u{1F9AB}" }], version: 13 }, hedgehog: { id: "hedgehog", name: "Hedgehog", keywords: ["animal", "nature", "spiny"], skins: [{ unified: "1f994", native: "\u{1F994}" }], version: 5 }, bat: { id: "bat", name: "Bat", keywords: ["animal", "nature", "blind", "vampire"], skins: [{ unified: "1f987", native: "\u{1F987}" }], version: 3 }, bear: { id: "bear", name: "Bear", keywords: ["animal", "nature", "wild"], skins: [{ unified: "1f43b", native: "\u{1F43B}" }], version: 1 }, polar_bear: { id: "polar_bear", name: "Polar Bear", keywords: ["animal", "arctic"], skins: [{ unified: "1f43b-200d-2744-fe0f", native: "\u{1F43B}\u200D\u2744\uFE0F" }], version: 13 }, koala: { id: "koala", name: "Koala", keywords: ["animal", "nature"], skins: [{ unified: "1f428", native: "\u{1F428}" }], version: 1 }, panda_face: { id: "panda_face", name: "Panda", keywords: ["face", "animal", "nature"], skins: [{ unified: "1f43c", native: "\u{1F43C}" }], version: 1 }, sloth: { id: "sloth", name: "Sloth", keywords: ["animal"], skins: [{ unified: "1f9a5", native: "\u{1F9A5}" }], version: 12 }, otter: { id: "otter", name: "Otter", keywords: ["animal"], skins: [{ unified: "1f9a6", native: "\u{1F9A6}" }], version: 12 }, skunk: { id: "skunk", name: "Skunk", keywords: ["animal"], skins: [{ unified: "1f9a8", native: "\u{1F9A8}" }], version: 12 }, kangaroo: { id: "kangaroo", name: "Kangaroo", keywords: ["animal", "nature", "australia", "joey", "hop", "marsupial"], skins: [{ unified: "1f998", native: "\u{1F998}" }], version: 11 }, badger: { id: "badger", name: "Badger", keywords: ["animal", "nature", "honey"], skins: [{ unified: "1f9a1", native: "\u{1F9A1}" }], version: 11 }, feet: { id: "feet", name: "Paw Prints", keywords: ["feet", "animal", "tracking", "footprints", "dog", "cat", "pet"], skins: [{ unified: "1f43e", native: "\u{1F43E}" }], version: 1 }, turkey: { id: "turkey", name: "Turkey", keywords: ["animal", "bird"], skins: [{ unified: "1f983", native: "\u{1F983}" }], version: 1 }, chicken: { id: "chicken", name: "Chicken", keywords: ["animal", "cluck", "nature", "bird"], skins: [{ unified: "1f414", native: "\u{1F414}" }], version: 1 }, rooster: { id: "rooster", name: "Rooster", keywords: ["animal", "nature", "chicken"], skins: [{ unified: "1f413", native: "\u{1F413}" }], version: 1 }, hatching_chick: { id: "hatching_chick", name: "Hatching Chick", keywords: ["animal", "chicken", "egg", "born", "baby", "bird"], skins: [{ unified: "1f423", native: "\u{1F423}" }], version: 1 }, baby_chick: { id: "baby_chick", name: "Baby Chick", keywords: ["animal", "chicken", "bird"], skins: [{ unified: "1f424", native: "\u{1F424}" }], version: 1 }, hatched_chick: { id: "hatched_chick", name: "Front-Facing Baby Chick", keywords: ["hatched", "front", "facing", "animal", "chicken", "bird"], skins: [{ unified: "1f425", native: "\u{1F425}" }], version: 1 }, bird: { id: "bird", name: "Bird", keywords: ["animal", "nature", "fly", "tweet", "spring"], skins: [{ unified: "1f426", native: "\u{1F426}" }], version: 1 }, penguin: { id: "penguin", name: "Penguin", keywords: ["animal", "nature"], skins: [{ unified: "1f427", native: "\u{1F427}" }], version: 1 }, dove_of_peace: { id: "dove_of_peace", name: "Dove", keywords: ["of", "peace", "animal", "bird"], skins: [{ unified: "1f54a-fe0f", native: "\u{1F54A}\uFE0F" }], version: 1 }, eagle: { id: "eagle", name: "Eagle", keywords: ["animal", "nature", "bird"], skins: [{ unified: "1f985", native: "\u{1F985}" }], version: 3 }, duck: { id: "duck", name: "Duck", keywords: ["animal", "nature", "bird", "mallard"], skins: [{ unified: "1f986", native: "\u{1F986}" }], version: 3 }, swan: { id: "swan", name: "Swan", keywords: ["animal", "nature", "bird"], skins: [{ unified: "1f9a2", native: "\u{1F9A2}" }], version: 11 }, owl: { id: "owl", name: "Owl", keywords: ["animal", "nature", "bird", "hoot"], skins: [{ unified: "1f989", native: "\u{1F989}" }], version: 3 }, dodo: { id: "dodo", name: "Dodo", keywords: ["animal", "bird"], skins: [{ unified: "1f9a4", native: "\u{1F9A4}" }], version: 13 }, feather: { id: "feather", name: "Feather", keywords: ["bird", "fly"], skins: [{ unified: "1fab6", native: "\u{1FAB6}" }], version: 13 }, flamingo: { id: "flamingo", name: "Flamingo", keywords: ["animal"], skins: [{ unified: "1f9a9", native: "\u{1F9A9}" }], version: 12 }, peacock: { id: "peacock", name: "Peacock", keywords: ["animal", "nature", "peahen", "bird"], skins: [{ unified: "1f99a", native: "\u{1F99A}" }], version: 11 }, parrot: { id: "parrot", name: "Parrot", keywords: ["animal", "nature", "bird", "pirate", "talk"], skins: [{ unified: "1f99c", native: "\u{1F99C}" }], version: 11 }, wing: { id: "wing", name: "Wing", keywords: ["angel", "birds", "flying"], skins: [{ unified: "1fabd", native: "\u{1FABD}" }], version: 15 }, black_bird: { id: "black_bird", name: "Black Bird", keywords: ["crow"], skins: [{ unified: "1f426-200d-2b1b", native: "\u{1F426}\u200D\u2B1B" }], version: 15 }, goose: { id: "goose", name: "Goose", keywords: ["silly", "jemima", "goosebumps"], skins: [{ unified: "1fabf", native: "\u{1FABF}" }], version: 15 }, phoenix: { id: "phoenix", name: "Phoenix", keywords: ["immortal", "bird", "mythtical", "reborn"], skins: [{ unified: "1f426-200d-1f525", native: "\u{1F426}\u200D\u{1F525}" }], version: 15.1 }, frog: { id: "frog", name: "Frog", keywords: ["animal", "nature", "croak", "toad"], skins: [{ unified: "1f438", native: "\u{1F438}" }], version: 1 }, crocodile: { id: "crocodile", name: "Crocodile", keywords: ["animal", "nature", "reptile", "lizard", "alligator"], skins: [{ unified: "1f40a", native: "\u{1F40A}" }], version: 1 }, turtle: { id: "turtle", name: "Turtle", keywords: ["animal", "slow", "nature", "tortoise"], skins: [{ unified: "1f422", native: "\u{1F422}" }], version: 1 }, lizard: { id: "lizard", name: "Lizard", keywords: ["animal", "nature", "reptile"], skins: [{ unified: "1f98e", native: "\u{1F98E}" }], version: 3 }, snake: { id: "snake", name: "Snake", keywords: ["animal", "evil", "nature", "hiss", "python"], skins: [{ unified: "1f40d", native: "\u{1F40D}" }], version: 1 }, dragon_face: { id: "dragon_face", name: "Dragon Face", keywords: ["animal", "myth", "nature", "chinese", "green"], skins: [{ unified: "1f432", native: "\u{1F432}" }], version: 1 }, dragon: { id: "dragon", name: "Dragon", keywords: ["animal", "myth", "nature", "chinese", "green"], skins: [{ unified: "1f409", native: "\u{1F409}" }], version: 1 }, sauropod: { id: "sauropod", name: "Sauropod", keywords: ["animal", "nature", "dinosaur", "brachiosaurus", "brontosaurus", "diplodocus", "extinct"], skins: [{ unified: "1f995", native: "\u{1F995}" }], version: 5 }, "t-rex": { id: "t-rex", name: "T-Rex", keywords: ["t", "rex", "animal", "nature", "dinosaur", "tyrannosaurus", "extinct"], skins: [{ unified: "1f996", native: "\u{1F996}" }], version: 5 }, whale: { id: "whale", name: "Spouting Whale", keywords: ["animal", "nature", "sea", "ocean"], skins: [{ unified: "1f433", native: "\u{1F433}" }
51763], version: 1 }, whale2: { id: "whale2", name: "Whale", keywords: ["whale2", "animal", "nature", "sea", "ocean"], skins: [{ unified: "1f40b", native: "\u{1F40B}" }], version: 1 }, dolphin: { id: "dolphin", name: "Dolphin", keywords: ["flipper", "animal", "nature", "fish", "sea", "ocean", "fins", "beach"], skins: [{ unified: "1f42c", native: "\u{1F42C}" }], version: 1 }, seal: { id: "seal", name: "Seal", keywords: ["animal", "creature", "sea"], skins: [{ unified: "1f9ad", native: "\u{1F9AD}" }], version: 13 }, fish: { id: "fish", name: "Fish", keywords: ["animal", "food", "nature"], skins: [{ unified: "1f41f", native: "\u{1F41F}" }], version: 1 }, tropical_fish: { id: "tropical_fish", name: "Tropical Fish", keywords: ["animal", "swim", "ocean", "beach", "nemo"], skins: [{ unified: "1f420", native: "\u{1F420}" }], version: 1 }, blowfish: { id: "blowfish", name: "Blowfish", keywords: ["animal", "nature", "food", "sea", "ocean"], skins: [{ unified: "1f421", native: "\u{1F421}" }], version: 1 }, shark: { id: "shark", name: "Shark", keywords: ["animal", "nature", "fish", "sea", "ocean", "jaws", "fins", "beach"], skins: [{ unified: "1f988", native: "\u{1F988}" }], version: 3 }, octopus: { id: "octopus", name: "Octopus", keywords: ["animal", "creature", "ocean", "sea", "nature", "beach"], skins: [{ unified: "1f419", native: "\u{1F419}" }], version: 1 }, shell: { id: "shell", name: "Spiral Shell", keywords: ["nature", "sea", "beach"], skins: [{ unified: "1f41a", native: "\u{1F41A}" }], version: 1 }, coral: { id: "coral", name: "Coral", keywords: ["ocean", "sea", "reef"], skins: [{ unified: "1fab8", native: "\u{1FAB8}" }], version: 14 }, jellyfish: { id: "jellyfish", name: "Jellyfish", keywords: ["sting", "tentacles"], skins: [{ unified: "1fabc", native: "\u{1FABC}" }], version: 15 }, crab: { id: "crab", name: "Crab", keywords: ["animal", "crustacean"], skins: [{ unified: "1f980", native: "\u{1F980}" }], version: 1 }, lobster: { id: "lobster", name: "Lobster", keywords: ["animal", "nature", "bisque", "claws", "seafood"], skins: [{ unified: "1f99e", native: "\u{1F99E}" }], version: 11 }, shrimp: { id: "shrimp", name: "Shrimp", keywords: ["animal", "ocean", "nature", "seafood"], skins: [{ unified: "1f990", native: "\u{1F990}" }], version: 3 }, squid: { id: "squid", name: "Squid", keywords: ["animal", "nature", "ocean", "sea"], skins: [{ unified: "1f991", native: "\u{1F991}" }], version: 3 }, oyster: { id: "oyster", name: "Oyster", keywords: ["food"], skins: [{ unified: "1f9aa", native: "\u{1F9AA}" }], version: 12 }, snail: { id: "snail", name: "Snail", keywords: ["slow", "animal", "shell"], skins: [{ unified: "1f40c", native: "\u{1F40C}" }], version: 1 }, butterfly: { id: "butterfly", name: "Butterfly", keywords: ["animal", "insect", "nature", "caterpillar"], skins: [{ unified: "1f98b", native: "\u{1F98B}" }], version: 3 }, bug: { id: "bug", name: "Bug", keywords: ["animal", "insect", "nature", "worm"], skins: [{ unified: "1f41b", native: "\u{1F41B}" }], version: 1 }, ant: { id: "ant", name: "Ant", keywords: ["animal", "insect", "nature", "bug"], skins: [{ unified: "1f41c", native: "\u{1F41C}" }], version: 1 }, bee: { id: "bee", name: "Honeybee", keywords: ["bee", "animal", "insect", "nature", "bug", "spring", "honey"], skins: [{ unified: "1f41d", native: "\u{1F41D}" }], version: 1 }, beetle: { id: "beetle", name: "Beetle", keywords: ["insect"], skins: [{ unified: "1fab2", native: "\u{1FAB2}" }], version: 13 }, ladybug: { id: "ladybug", name: "Lady Beetle", keywords: ["ladybug", "animal", "insect", "nature"], skins: [{ unified: "1f41e", native: "\u{1F41E}" }], version: 1 }, cricket: { id: "cricket", name: "Cricket", keywords: ["animal", "chirp"], skins: [{ unified: "1f997", native: "\u{1F997}" }], version: 5 }, cockroach: { id: "cockroach", name: "Cockroach", keywords: ["insect", "pests"], skins: [{ unified: "1fab3", native: "\u{1FAB3}" }], version: 13 }, spider: { id: "spider", name: "Spider", keywords: ["animal", "arachnid"], skins: [{ unified: "1f577-fe0f", native: "\u{1F577}\uFE0F" }], version: 1 }, spider_web: { id: "spider_web", name: "Spider Web", keywords: ["animal", "insect", "arachnid", "silk"], skins: [{ unified: "1f578-fe0f", native: "\u{1F578}\uFE0F" }], version: 1 }, scorpion: { id: "scorpion", name: "Scorpion", keywords: ["animal", "arachnid"], skins: [{ unified: "1f982", native: "\u{1F982}" }], version: 1 }, mosquito: { id: "mosquito", name: "Mosquito", keywords: ["animal", "nature", "insect", "malaria"], skins: [{ unified: "1f99f", native: "\u{1F99F}" }], version: 11 }, fly: { id: "fly", name: "Fly", keywords: ["insect"], skins: [{ unified: "1fab0", native: "\u{1FAB0}" }], version: 13 }, worm: { id: "worm", name: "Worm", keywords: ["animal"], skins: [{ unified: "1fab1", native: "\u{1FAB1}" }], version: 13 }, microbe: { id: "microbe", name: "Microbe", keywords: ["amoeba", "bacteria", "germs", "virus", "covid"], skins: [{ unified: "1f9a0", native: "\u{1F9A0}" }], version: 11 }, bouquet: { id: "bouquet", name: "Bouquet", keywords: ["flowers", "nature", "spring"], skins: [{ unified: "1f490", native: "\u{1F490}" }], version: 1 }, cherry_blossom: { id: "cherry_blossom", name: "Cherry Blossom", keywords: ["nature", "plant", "spring", "flower"], skins: [{ unified: "1f338", native: "\u{1F338}" }], version: 1 }, white_flower: { id: "white_flower", name: "White Flower", keywords: ["japanese", "spring"], skins: [{ unified: "1f4ae", native: "\u{1F4AE}" }], version: 1 }, lotus: { id: "lotus", name: "Lotus", keywords: ["flower", "calm", "meditation"], skins: [{ unified: "1fab7", native: "\u{1FAB7}" }], version: 14 }, rosette: { id: "rosette", name: "Rosette", keywords: ["flower", "decoration", "military"], skins: [{ unified: "1f3f5-fe0f", native: "\u{1F3F5}\uFE0F" }], version: 1 }, rose: { id: "rose", name: "Rose", keywords: ["flowers", "valentines", "love", "spring"], skins: [{ unified: "1f339", native: "\u{1F339}" }], version: 1 }, wilted_flower: { id: "wilted_flower", name: "Wilted Flower", keywords: ["plant", "nature", "rose"], skins: [{ unified: "1f940", native: "\u{1F940}" }], version: 3 }, hibiscus: { id: "hibiscus", name: "Hibiscus", keywords: ["plant", "vegetable", "flowers", "beach"], skins: [{ unified: "1f33a", native: "\u{1F33A}" }
51763], version: 1 }, sunflower: { id: "sunflower", name: "Sunflower", keywords: ["nature", "plant", "fall"], skins: [{ unified: "1f33b", native: "\u{1F33B}" }], version: 1 }, blossom: { id: "blossom", name: "Blossom", keywords: ["nature", "flowers", "yellow"], skins: [{ unified: "1f33c", native: "\u{1F33C}" }], version: 1 }, tulip: { id: "tulip", name: "Tulip", keywords: ["flowers", "plant", "nature", "summer", "spring"], skins: [{ unified: "1f337", native: "\u{1F337}" }], version: 1 }, hyacinth: { id: "hyacinth", name: "Hyacinth", keywords: ["flower", "lavender"], skins: [{ unified: "1fabb", native: "\u{1FABB}" }], version: 15 }, seedling: { id: "seedling", name: "Seedling", keywords: ["plant", "nature", "grass", "lawn", "spring"], skins: [{ unified: "1f331", native: "\u{1F331}" }], version: 1 }, potted_plant: { id: "potted_plant", name: "Potted Plant", keywords: ["greenery", "house"], skins: [{ unified: "1fab4", native: "\u{1FAB4}" }], version: 13 }, evergreen_tree: { id: "evergreen_tree", name: "Evergreen Tree", keywords: ["plant", "nature"], skins: [{ unified: "1f332", native: "\u{1F332}" }], version: 1 }, deciduous_tree: { id: "deciduous_tree", name: "Deciduous Tree", keywords: ["plant", "nature"], skins: [{ unified: "1f333", native: "\u{1F333}" }], version: 1 }, palm_tree: { id: "palm_tree", name: "Palm Tree", keywords: ["plant", "vegetable", "nature", "summer", "beach", "mojito", "tropical"], skins: [{ unified: "1f334", native: "\u{1F334}" }], version: 1 }, cactus: { id: "cactus", name: "Cactus", keywords: ["vegetable", "plant", "nature"], skins: [{ unified: "1f335", native: "\u{1F335}" }], version: 1 }, ear_of_rice: { id: "ear_of_rice", name: "Ear of Rice", keywords: ["sheaf", "nature", "plant"], skins: [{ unified: "1f33e", native: "\u{1F33E}" }], version: 1 }, herb: { id: "herb", name: "Herb", keywords: ["vegetable", "plant", "medicine", "weed", "grass", "lawn"], skins: [{ unified: "1f33f", native: "\u{1F33F}" }], version: 1 }, shamrock: { id: "shamrock", name: "Shamrock", keywords: ["vegetable", "plant", "nature", "irish", "clover"], skins: [{ unified: "2618-fe0f", native: "\u2618\uFE0F" }], version: 1 }, four_leaf_clover: { id: "four_leaf_clover", name: "Four Leaf Clover", keywords: ["vegetable", "plant", "nature", "lucky", "irish"], skins: [{ unified: "1f340", native: "\u{1F340}" }], version: 1 }, maple_leaf: { id: "maple_leaf", name: "Maple Leaf", keywords: ["nature", "plant", "vegetable", "ca", "fall"], skins: [{ unified: "1f341", native: "\u{1F341}" }], version: 1 }, fallen_leaf: { id: "fallen_leaf", name: "Fallen Leaf", keywords: ["nature", "plant", "vegetable", "leaves"], skins: [{ unified: "1f342", native: "\u{1F342}" }], version: 1 }, leaves: { id: "leaves", name: "Leaf Fluttering in Wind", keywords: ["leaves", "nature", "plant", "tree", "vegetable", "grass", "lawn", "spring"], skins: [{ unified: "1f343", native: "\u{1F343}" }], version: 1 }, empty_nest: { id: "empty_nest", name: "Empty Nest", keywords: ["bird"], skins: [{ unified: "1fab9", native: "\u{1FAB9}" }], version: 14 }, nest_with_eggs: { id: "nest_with_eggs", name: "Nest with Eggs", keywords: ["bird"], skins: [{ unified: "1faba", native: "\u{1FABA}" }], version: 14 }, mushroom: { id: "mushroom", name: "Mushroom", keywords: ["plant", "vegetable"], skins: [{ unified: "1f344", native: "\u{1F344}" }], version: 1 }, leafless_tree: { id: "leafless_tree", name: "Leafless Tree", keywords: [], skins: [{ unified: "1fabe", native: "\u{1FABE}" }], version: 16 }, grapes: { id: "grapes", name: "Grapes", keywords: ["fruit", "food", "wine"], skins: [{ unified: "1f347", native: "\u{1F347}" }], version: 1 }, melon: { id: "melon", name: "Melon", keywords: ["fruit", "nature", "food"], skins: [{ unified: "1f348", native: "\u{1F348}" }], version: 1 }, watermelon: { id: "watermelon", name: "Watermelon", keywords: ["fruit", "food", "picnic", "summer"], skins: [{ unified: "1f349", native: "\u{1F349}" }], version: 1 }, tangerine: { id: "tangerine", name: "Tangerine", keywords: ["food", "fruit", "nature", "orange"], skins: [{ unified: "1f34a", native: "\u{1F34A}" }], version: 1 }, lemon: { id: "lemon", name: "Lemon", keywords: ["fruit", "nature"], skins: [{ unified: "1f34b", native: "\u{1F34B}" }], version: 1 }, lime: { id: "lime", name: "Lime", keywords: ["fruit", "acidic", "citric"], skins: [{ unified: "1f34b-200d-1f7e9", native: "\u{1F34B}\u200D\u{1F7E9}" }], version: 15.1 }, banana: { id: "banana", name: "Banana", keywords: ["fruit", "food", "monkey"], skins: [{ unified: "1f34c", native: "\u{1F34C}" }], version: 1 }, pineapple: { id: "pineapple", name: "Pineapple", keywords: ["fruit", "nature", "food"], skins: [{ unified: "1f34d", native: "\u{1F34D}" }], version: 1 }, mango: { id: "mango", name: "Mango", keywords: ["fruit", "food", "tropical"], skins: [{ unified: "1f96d", native: "\u{1F96D}" }], version: 11 }, apple: { id: "apple", name: "Red Apple", keywords: ["fruit", "mac", "school"], skins: [{ unified: "1f34e", native: "\u{1F34E}" }], version: 1 }, green_apple: { id: "green_apple", name: "Green Apple", keywords: ["fruit", "nature"], skins: [{ unified: "1f34f", native: "\u{1F34F}" }], version: 1 }, pear: { id: "pear", name: "Pear", keywords: ["fruit", "nature", "food"], skins: [{ unified: "1f350", native: "\u{1F350}" }], version: 1 }, peach: { id: "peach", name: "Peach", keywords: ["fruit", "nature", "food"], skins: [{ unified: "1f351", native: "\u{1F351}" }], version: 1 }, cherries: { id: "cherries", name: "Cherries", keywords: ["food", "fruit"], skins: [{ unified: "1f352", native: "\u{1F352}" }
51763], version: 1 }, strawberry: { id: "strawberry", name: "Strawberry", keywords: ["fruit", "food", "nature"], skins: [{ unified: "1f353", native: "\u{1F353}" }], version: 1 }, blueberries: { id: "blueberries", name: "Blueberries", keywords: ["fruit"], skins: [{ unified: "1fad0", native: "\u{1FAD0}" }], version: 13 }, kiwifruit: { id: "kiwifruit", name: "Kiwifruit", keywords: ["kiwi", "fruit", "food"], skins: [{ unified: "1f95d", native: "\u{1F95D}" }], version: 3 }, tomato: { id: "tomato", name: "Tomato", keywords: ["fruit", "vegetable", "nature", "food"], skins: [{ unified: "1f345", native: "\u{1F345}" }], version: 1 }, olive: { id: "olive", name: "Olive", keywords: ["fruit"], skins: [{ unified: "1fad2", native: "\u{1FAD2}" }], version: 13 }, coconut: { id: "coconut", name: "Coconut", keywords: ["fruit", "nature", "food", "palm"], skins: [{ unified: "1f965", native: "\u{1F965}" }], version: 5 }, avocado: { id: "avocado", name: "Avocado", keywords: ["fruit", "food"], skins: [{ unified: "1f951", native: "\u{1F951}" }], version: 3 }, eggplant: { id: "eggplant", name: "Eggplant", keywords: ["vegetable", "nature", "food", "aubergine"], skins: [{ unified: "1f346", native: "\u{1F346}" }], version: 1 }, potato: { id: "potato", name: "Potato", keywords: ["food", "tuber", "vegatable", "starch"], skins: [{ unified: "1f954", native: "\u{1F954}" }], version: 3 }, carrot: { id: "carrot", name: "Carrot", keywords: ["vegetable", "food", "orange"], skins: [{ unified: "1f955", native: "\u{1F955}" }], version: 3 }, corn: { id: "corn", name: "Ear of Corn", keywords: ["food", "vegetable", "plant"], skins: [{ unified: "1f33d", native: "\u{1F33D}" }], version: 1 }, hot_pepper: { id: "hot_pepper", name: "Hot Pepper", keywords: ["food", "spicy", "chilli", "chili"], skins: [{ unified: "1f336-fe0f", native: "\u{1F336}\uFE0F" }], version: 1 }, bell_pepper: { id: "bell_pepper", name: "Bell Pepper", keywords: ["fruit", "plant"], skins: [{ unified: "1fad1", native: "\u{1FAD1}" }], version: 13 }, cucumber: { id: "cucumber", name: "Cucumber", keywords: ["fruit", "food", "pickle"], skins: [{ unified: "1f952", native: "\u{1F952}" }], version: 3 }, leafy_green: { id: "leafy_green", name: "Leafy Green", keywords: ["food", "vegetable", "plant", "bok", "choy", "cabbage", "kale", "lettuce"], skins: [{ unified: "1f96c", native: "\u{1F96C}" }], version: 11 }, broccoli: { id: "broccoli", name: "Broccoli", keywords: ["fruit", "food", "vegetable"], skins: [{ unified: "1f966", native: "\u{1F966}" }], version: 5 }, garlic: { id: "garlic", name: "Garlic", keywords: ["food", "spice", "co
51763ok"], skins: [{ unified: "1f9c4", native: "\u{1F9C4}" }], version: 12 }, onion: { id: "onion", name: "Onion", keywords: ["cook", "food", "spice"], skins: [{ unified: "1f9c5", native: "\u{1F9C5}" }], version: 12 }, peanuts: { id: "peanuts", name: "Peanuts", keywords: ["food", "nut"], skins: [{ unified: "1f95c", native: "\u{1F95C}" }], version: 3 }, beans: { id: "beans", name: "Beans", keywords: ["food"], skins: [{ unified: "1fad8", native: "\u{1FAD8}" }], version: 14 }, chestnut: { id: "chestnut", name: "Chestnut", keywords: ["food", "squirrel"], skins: [{ unified: "1f330", native: "\u{1F330}" }], version: 1 }, ginger_root: { id: "ginger_root", name: "Ginger Root", keywords: ["spice", "yellow", "cooking", "gingerbread"], skins: [{ unified: "1fada", native: "\u{1FADA}" }], version: 15 }, pea_pod: { id: "pea_pod", name: "Pea Pod", keywords: ["cozy", "green"], skins: [{ unified: "1fadb", native: "\u{1FADB}" }], version: 15 }, brown_mushroom: { id: "brown_mushroom", name: "Brown Mushroom", keywords: ["toadstool", "fungus"], skins: [{ unified: "1f344-200d-1f7eb", native: "\u{1F344}\u200D\u{1F7EB}" }], version: 15.1 }, root_vegetable: { id: "root_vegetable", name: "Root Vegetable", keywords: [], skins: [{ unified: "1fadc", native: "\u{1FADC}" }], version: 16 }, bread: { id: "bread", name: "Bread", keywords: ["food", "wheat", "breakfast", "toast"], skins: [{ unified: "1f35e", native: "\u{1F35E}" }], version: 1 }, croissant: { id: "croissant", name: "Croissant", keywords: ["food", "bread", "french"], skins: [{ unified: "1f950", native: "\u{1F950}" }], version: 3 }, baguette_bread: { id: "baguette_bread", name: "Baguette Bread", keywords: ["food", "french", "france", "bakery"], skins: [{ unified: "1f956", native: "\u{1F956}" }], version: 3 }, flatbread: { id: "flatbread", name: "Flatbread", keywords: ["flour", "food", "bakery"], skins: [{ unified: "1fad3", native: "\u{1FAD3}" }], version: 13 }, pretzel: { id: "pretzel", name: "Pretzel", keywords: ["food", "bread", "twisted", "germany", "bakery"], skins: [{ unified: "1f968", native: "\u{1F968}" }], version: 5 }, bagel: { id: "bagel", name: "Bagel", keywords: ["food", "bread", "bakery", "schmear", "jewish"], skins: [{ unified: "1f96f", native: "\u{1F96F}" }], version: 11 }, pancakes: { id: "pancakes", name: "Pancakes", keywords: ["food", "breakfast", "flapjacks", "hotcakes", "brunch"], skins: [{ unified: "1f95e", native: "\u{1F95E}" }], version: 3 }, waffle: { id: "waffle", name: "Waffle", keywords: ["food", "breakfast", "brunch"], skins: [{ unified: "1f9c7", native: "\u{1F9C7}" }], version: 12 }, cheese_wedge: { id: "cheese_wedge", name: "Cheese Wedge", keywords: ["food", "chadder", "swiss"], skins: [{ unified: "1f9c0", native: "\u{1F9C0}" }], version: 1 }, meat_on_bone: { id: "meat_on_bone", name: "Meat on Bone", keywords: ["good", "food", "drumstick"], skins: [{ unified: "1f356", native: "\u{1F356}" }], version: 1 }, poultry_leg: { id: "poultry_leg", name: "Poultry Leg", keywords: ["food", "meat", "drumstick", "bird", "chicken", "turkey"], skins: [{ unified: "1f357", native: "\u{1F357}" }], version: 1 }, cut_of_meat: { id: "cut_of_meat", name: "Cut of Meat", keywords: ["food", "cow", "chop", "lambchop", "porkchop"], skins: [{ unified: "1f969", native: "\u{1F969}" }], version: 5 }, bacon: { id: "bacon", name: "Bacon", keywords: ["food", "breakfast", "pork", "pig", "meat", "brunch"], skins: [{ unified: "1f953", native: "\u{1F953}" }], version: 3 }, hamburger: { id: "hamburger", name: "Hamburger", keywords: ["meat", "fast", "food", "beef", "cheeseburger", "mcdonalds", "burger", "king"], skins: [{ unified: "1f354", native: "\u{1F354}" }], version: 1 }, fries: { id: "fries", name: "French Fries", keywords: ["chips", "snack", "fast", "food", "potato"], skins: [{ unified: "1f35f", native: "\u{1F35F}" }], version: 1 }, pizza: { id: "pizza", name: "Pizza", keywords: ["food", "party", "italy"], skins: [{ unified: "1f355", native: "\u{1F355}" }], version: 1 }, hotdog: { id: "hotdog", name: "Hot Dog", keywords: ["hotdog", "food", "frankfurter", "america"], skins: [{ unified: "1f32d", native: "\u{1F32D}" }], version: 1 }, sandwich: { id: "sandwich", name: "Sandwich", keywords: ["food", "lunch", "bread", "toast", "bakery"], skins: [{ unified: "1f96a", native: "\u{1F96A}" }], version: 5 }, taco: { id: "taco", name: "Taco", keywords: ["food", "mexican"], skins: [{ unified: "1f32e", native: "\u{1F32E}" }], version: 1 }, burrito: { id: "burrito", name: "Burrito", keywords: ["food", "mexican"], skins: [{ unified: "1f32f", native: "\u{1F32F}" }], version: 1 }, tamale: { id: "tamale", name: "Tamale", keywords: ["food", "masa"], skins: [{ unified: "1fad4", native: "\u{1FAD4}" }], version: 13 }, stuffed_flatbread: { id: "stuffed_flatbread", name: "Stuffed Flatbread", keywords: ["food", "gyro", "mediterranean"], skins: [{ unified: "1f959", native: "\u{1F959}" }], version: 3 }, falafel: { id: "falafel", name: "Falafel", keywords: ["food", "mediterranean"], skins: [{ unified: "1f9c6", native: "\u{1F9C6}" }], version: 12 }, egg: { id: "egg", name: "Egg", keywords: ["food", "chicken", "breakfast"], skins: [{ unified: "1f95a", native: "\u{1F95A}" }], version: 3 }, fried_egg: { id: "fried_egg", name: "Cooking", keywords: ["fried", "egg", "food", "breakfast", "kitchen", "skillet"], skins: [{ unified: "1f373", native: "\u{1F373}" }], version: 1 }, shallow_pan_of_food: { id: "shallow_pan_of_food", name: "Shallow Pan of Food", keywords: ["cooking", "casserole", "paella", "skillet"], skins: [{ unified: "1f958", native: "\u{1F958}" }], version: 3 }, stew: { id: "stew", name: "Pot of Food", keywords: ["stew", "meat", "soup", "hot"], skins: [{ unified: "1f372", native: "\u{1F372}" }], version: 1 }, fondue: { id: "fondue", name: "Fondue", keywords: ["cheese", "pot", "food"], skins: [{ unified: "1fad5", native: "\u{1FAD5}" }], version: 13 }, bowl_with_spoon: { id: "bowl_with_spoon", name: "Bowl with Spoon", keywords: ["food", "breakfast", "cereal", "oatmeal", "porridge"], skins: [{ unified: "1f963", native: "\u{1F963}" }], version: 5 }, green_salad: { id: "green_salad", name: "Green Salad", keywords: ["food", "healthy", "lettuce", "vegetable"], skins: [{ unified: "1f957", native: "\u{1F957}" }], version: 3 }, popcorn: { id: "popcorn", name: "Popcorn", keywords: ["food", "movie", "theater", "films", "snack", "drama"], skins: [{ unified: "1f37f", native: "\u{1F37F}" }], version: 1 }, butter: { id: "butter", name: "Butter", keywords: ["food", "cook"], skins: [{ unified: "1f9c8", native: "\u{1F9C8}" }], version: 12 }, salt: { id: "salt", name: "Salt", keywords: ["condiment", "shaker"], skins: [{ unified: "1f9c2", native: "\u{1F9C2}" }], version: 11 }, canned_food: { id: "canned_food", name: "Canned Food", keywords: ["soup", "tomatoes"], skins: [{ unified: "1f96b", native: "\u{1F96B}" }], version: 5 }, bento: { id: "bento", name: "Bento Box", keywords: ["food", "japanese", "lunch"], skins: [{ unified: "1f371", native: "\u{1F371}" }], version: 1 }, rice_cracker: { id: "rice_cracker", name: "Rice Cracker", keywords: ["food", "japanese", "snack", "senbei"], skins: [{ unified: "1f358", native: "\u{1F358}" }], version: 1 }, rice_ball: { id: "rice_ball", name: "Rice Ball", keywords: ["food", "japanese", "onigiri", "omusubi"], skins: [{ unified: "1f359", native: "\u{1F359}" }], version: 1 }, rice: { id: "rice", name: "Cooked Rice", keywords: ["food", "asian"], skins: [{ unified: "1f35a", native: "\u{1F35A}" }], version: 1 }, curry: { id: "curry", name: "Curry Rice", keywords: ["food", "spicy", "hot", "indian"], skins: [{ unified: "1f35b", native: "\u{1F35B}" }], version: 1 }, ramen: { id: "ramen", name: "Steaming Bowl", keywords: ["ramen", "food", "japanese", "noodle", "chopsticks"], skins: [{ unified: "1f35c", native: "\u{1F35C}" }], version: 1 }, spaghetti: { id: "spaghetti", name: "Spaghetti", keywords: ["food", "italian", "pasta", "noodle"], skins: [{ unified: "1f35d", native: "\u{1F35D}" }], version: 1 }, sweet_potato: { id: "sweet_potato", name: "Roasted Sweet Potato", keywords: ["food", "nature", "plant"], skins: [{ unified: "1f360", native: "\u{1F360}" }], version: 1 }, oden: { id: "oden", name: "Oden", keywords: ["skewer", "food", "japanese"], skins: [{ unified: "1f362", native: "\u{1F362}" }], version: 1 }, sushi: { id: "sushi", name: "Sushi", keywords: ["food", "fish", "japanese", "rice"], skins: [{ unified: "1f363", native: "\u{1F363}" }], version: 1 }, fried_shrimp: { id: "fried_shrimp", name: "Fried Shrimp", keywords: ["food", "animal", "appetizer", "summer"], skins: [{ unified: "1f364", native: "\u{1F364}" }], version: 1 }, fish_cake: { id: "fish_cake", name: "Fish Cake with Swirl", keywords: ["food", "japan", "sea", "beach", "narutomaki", "pink", "kamaboko", "surimi", "ramen"], skins: [{ unified: "1f365", native: "\u{1F365}" }], version: 1 }, moon_cake: { id: "moon_cake", name: "Moon Cake", keywords: ["food", "autumn", "dessert"], skins: [{ unified: "1f96e", native: "\u{1F96E}" }], version: 11 }, dango: { id: "dango", name: "Dango", keywords: ["food", "dessert", "sweet", "japanese", "barbecue", "meat"], skins: [{ unified: "1f361", native: "\u{1F361}" }], version: 1 }, dumpling: { id: "dumpling", name: "Dumpling", keywords: ["food", "empanad
51763a", "pierogi", "potsticker", "gyoza"], skins: [{ unified: "1f95f", native: "\u{1F95F}" }], version: 5 }, fortune_cookie: { id: "fortune_cookie", name: "Fortune Cookie", keywords: ["food", "prophecy", "dessert"], skins: [{ unified: "1f960", native: "\u{1F960}" }], version: 5 }, takeout_box: { id: "takeout_box", name: "Takeout Box", keywords: ["food", "leftovers"], skins: [{ unified: "1f961", native: "\u{1F961}" }], version: 5 }, icecream: { id: "icecream", name: "Soft Ice Cream", keywords: ["icecream", "food", "hot", "dessert", "summer"], skins: [{ unified: "1f366", native: "\u{1F366}" }], version: 1 }, shaved_ice: { id: "shaved_ice", name: "Shaved Ice", keywords: ["hot", "dessert", "summer"], skins: [{ unified: "1f367", native: "\u{1F367}" }], version: 1 }, ice_cream: { id: "ice_cream", name: "Ice Cream", keywords: ["food", "hot", "dessert"], skins: [{ unified: "1f368", native: "\u{1F368}" }], version: 1 }, doughnut: { id: "doughnut", name: "Doughnut", keywords: ["food", "dessert", "snack", "sweet", "donut"], skins: [{ unified: "1f369", native: "\u{1F369}" }], version: 1 }, cookie: { id: "cookie", name: "Cookie", keywords: ["food", "snack", "oreo", "chocolate", "sweet", "dessert"], skins: [{ unified: "1f36a", native: "\u{1F36A}" }], version: 1 }, birthday: { id: "birthday", name: "Birthday Cake", keywords: ["food", "dessert"], skins: [{ unified: "1f382", native: "\u{1F382}" }], version: 1 }, cake: { id: "cake", name: "Shortcake", keywords: ["cake", "food", "dessert"], skins: [{ unified: "1f370", native: "\u{1F370}" }], version: 1 }, cupcake: { id: "cupcake", name: "Cupcake", keywords: ["food", "dessert", "bakery", "sweet"], skins: [{ unified: "1f9c1", native: "\u{1F9C1}" }], version: 11 }, pie: { id: "pie", name: "Pie", keywords: ["food", "dessert", "pastry"], skins: [{ unified: "1f967", native: "\u{1F967}" }], version: 5 }, chocolate_bar: { id: "chocolate_bar", name: "Chocolate Bar", keywords: ["food", "snack", "dessert", "sweet"], skins: [{ unified: "1f36b", native: "\u{1F36B}" }], version: 1 }, candy: { id: "candy", name: "Candy", keywords: ["snack", "dessert", "sweet", "lolly"], skins: [{ unified: "1f36c", native: "\u{1F36C}" }], version: 1 }, lollipop: { id: "lollipop", name: "Lollipop", keywords: ["food", "snack", "candy", "sweet"], skins: [{ unified: "1f36d", native: "\u{1F36D}" }], version: 1 }, custard: { id: "custard", name: "Custard", keywords: ["dessert", "food", "pudding", "flan"], skins: [{ unified: "1f36e", native: "\u{1F36E}" }], version: 1 }, honey_pot: { id: "honey_pot", name: "Honey Pot", keywords: ["bees", "sweet", "kitchen"], skins: [{ unified: "1f36f", native: "\u{1F36F}" }], version: 1 }, baby_bottle: { id: "baby_bottle", name: "Baby Bottle", keywords: ["food", "container", "milk"], skins: [{ unified: "1f37c", native: "\u{1F37C}" }], version: 1 }, glass_of_milk: { id: "glass_of_milk", name: "Glass of Milk", keywords: ["beverage", "drink", "cow"], skins: [{ unified: "1f95b", native: "\u{1F95B}" }], version: 3 }, coffee: { id: "coffee", name: "Hot Beverage", keywords: ["coffee", "caffeine", "latte", "espresso", "mug"], skins: [{ unified: "2615", native: "\u2615" }], version: 1 }, teapot: { id: "teapot", name: "Teapot", keywords: ["drink", "hot"], skins: [{ unified: "1fad6", native: "\u{1FAD6}" }], version: 13 }, tea: { id: "tea", name: "Teacup Without Handle", keywords: ["tea", "drink", "bowl", "breakfast", "green", "british"], skins: [{ unified: "1f375", native: "\u{1F375}" }], version: 1 }, sake: { id: "sake", name: "Sake", keywords: ["wine", "drink", "drunk", "beverage", "japanese", "alcohol", "booze"], skins: [{ unified: "1f376", native: "\u{1F376}" }], version: 1 }, champagne: { id: "champagne", name: "Bottle with Popping Cork", keywords: ["champagne", "drink", "wine", "celebration"], skins: [{ unified: "1f37e", native: "\u{1F37E}" }], version: 1 }, wine_glass: { id: "wine_glass", name: "Wine Glass", keywords: ["drink", "beverage", "drunk", "alcohol", "booze"], skins: [{ unified: "1f377", native: "\u{1F377}" }], version: 1 }, cocktail: { id: "cocktail", name: "Cocktail Glass", keywords: ["drink", "drunk", "alcohol", "beverage", "booze", "mojito"], skins: [{ unified: "1f378", native: "\u{1F378}" }], version: 1 }, tropical_drink: { id: "tropical_drink", name: "Tropical Drink", keywords: ["beverage", "cocktail", "summer", "beach", "alcohol", "booze", "mojito"], skins: [{ unified: "1f379", native: "\u{1F379}" }], version: 1 }, beer: { id: "beer", name: "Beer Mug", keywords: ["relax", "beverage", "drink", "drunk", "party", "pub", "summer", "alcohol", "booze"], skins: [{ unified: "1f37a", native: "\u{1F37A}" }], version: 1 }, beers: { id: "beers", name: "Clinking Beer Mugs", keywords: ["beers", "relax", "beverage", "drink", "drunk", "party", "pub", "summer", "alcohol", "booze"], skins: [{ unified: "1f37b", native: "\u{1F37B}" }], version: 1 }, clinking_glasses: { id: "clinking_glasses", name: "Clinking Glasses", keywords: ["beverage", "drink", "party", "alcohol", "celebrate", "cheers", "wine", "champagne", "toast"], skins: [{ unified: "1f942", native: "\u{1F942}" }], version: 3 }, tumbler_glass: { id: "tumbler_glass", name: "Tumbler Glass", keywords: ["drink", "beverage", "drunk", "alcohol", "liquor", "booze", "bourbon", "scotch", "whisky", "shot"], skins: [{ unified: "1f943", native: "\u{1F943}" }], version: 3 }, pouring_liquid: { id: "pouring_liquid", name: "Pouring Liquid", keywords: ["cup", "water"], skins: [{ unified: "1fad7", native: "\u{1FAD7}" }], version: 14 }
51763, cup_with_straw: { id: "cup_with_straw", name: "Cup with Straw", keywords: ["drink", "soda"], skins: [{ unified: "1f964", native: "\u{1F964}" }], version: 5 }, bubble_tea: { id: "bubble_tea", name: "Bubble Tea", keywords: ["taiwan", "boba", "milk", "straw"], skins: [{ unified: "1f9cb", native: "\u{1F9CB}" }], version: 13 }, beverage_box: { id: "beverage_box", name: "Beverage Box", keywords: ["drink"], skins: [{ unified: "1f9c3", native: "\u{1F9C3}" }], version: 12 }, mate_drink: { id: "mate_drink", name: "Mate", keywords: ["drink", "tea", "beverage"], skins: [{ unified: "1f9c9", native: "\u{1F9C9}" }], version: 12 }, ice_cube: { id: "ice_cube", name: "Ice", keywords: ["cube", "water", "cold"], skins: [{ unified: "1f9ca", native: "\u{1F9CA}" }], version: 12 }, chopsticks: { id: "chopsticks", name: "Chopsticks", keywords: ["food"], skins: [{ unified: "1f962", native: "\u{1F962}" }], version: 5 }, knife_fork_plate: { id: "knife_fork_plate", name: "Fork and Knife with Plate", keywords: ["food", "eat", "meal", "lunch", "dinner", "restaurant"], skins: [{ unified: "1f37d-fe0f", native: "\u{1F37D}\uFE0F" }], version: 1 }, fork_and_knife: { id: "fork_and_knife", name: "Fork and Knife", keywords: ["cutlery", "kitchen"], skins: [{ unified: "1f374", native: "\u{1F374}" }], version: 1 }, spoon: { id: "spoon", name: "Spoon", keywords: ["cutlery", "kitchen", "tableware"], skins: [{ unified: "1f944", native: "\u{1F944}" }], version: 3 }, hocho: { id: "hocho", name: "Hocho", keywords: ["knife", "kitchen", "blade", "cutlery", "weapon"], skins: [{ unified: "1f52a", native: "\u{1F52A}" }], version: 1 }, jar: { id: "jar", name: "Jar", keywords: ["container", "sauce"], skins: [{ unified: "1fad9", native: "\u{1FAD9}" }], version: 14 }, amphora: { id: "amphora", name: "Amphora", keywords: ["vase", "jar"], skins: [{ unified: "1f3fa", native: "\u{1F3FA}" }], version: 1 }, earth_africa: { id: "earth_africa", name: "Earth Globe Europe-Africa", keywords: ["africa", "showing", "europe", "world", "international"], skins: [{ unified: "1f30d", native: "\u{1F30D}" }], version: 1 }, earth_americas: { id: "earth_americas", name: "Earth Globe Americas", keywords: ["showing", "world", "USA", "international"], skins: [{ unified: "1f30e", native: "\u{1F30E}" }], version: 1 }, earth_asia: { id: "earth_asia", name: "Earth Globe Asia-Australia", keywords: ["asia", "showing", "australia", "world", "east", "international"], skins: [{ unified: "1f30f", native: "\u{1F30F}" }], version: 1 }, globe_with_meridians: { id: "globe_with_meridians", name: "Globe with Meridians", keywords: ["earth", "international", "world", "internet", "interweb", "i18n"], skins: [{ unified: "1f310", native: "\u{1F310}" }], version: 1 }, world_map: { id: "world_map", name: "World Map", keywords: ["location", "direction"], skins: [{ unified: "1f5fa-fe0f", native: "\u{1F5FA}\uFE0F" }], version: 1 }, japan: { id: "japan", name: "Map of Japan", keywords: ["nation", "country", "japanese", "asia"], skins: [{ unified: "1f5fe", native: "\u{1F5FE}" }], version: 1 }, compass: { id: "compass", name: "Compass", keywords: ["magnetic", "navigation", "orienteering"], skins: [{ unified: "1f9ed", native: "\u{1F9ED}" }], version: 11 }, snow_capped_mountain: { id: "snow_capped_mountain", name: "Snow-Capped Mountain", keywords: ["snow", "capped", "photo", "nature", "environment", "winter", "cold"], skins: [{ unified: "1f3d4-fe0f", native: "\u{1F3D4}\uFE0F" }], version: 1 }, mountain: { id: "mountain", name: "Mountain", keywords: ["photo", "nature", "environment"], skins: [{ unified: "26f0-fe0f", native: "\u26F0\uFE0F" }], version: 1 }, volcano: { id: "volcano", name: "Volcano", keywords: ["photo", "nature", "disaster"], skins: [{ unified: "1f30b", native: "\u{1F30B}" }], version: 1 }, mount_fuji: { id: "mount_fuji", name: "Mount Fuji", keywords: ["photo", "mountain", "nature", "japanese"], skins: [{ unified: "1f5fb", native: "\u{1F5FB}" }], version: 1 }, camping: { id: "camping", name: "Camping", keywords: ["photo", "outdoors", "tent"], skins: [{ unified: "1f3d5-fe0f", native: "\u{1F3D5}\uFE0F" }], version: 1 }, beach_with_umbrella: { id: "beach_with_umbrella", name: "Beach with Umbrella", keywords: ["weather", "summer", "sunny", "sand", "mojito"], skins: [{ unified: "1f3d6-fe0f", native: "\u{1F3D6}\uFE0F" }], version: 1 }, desert: { id: "desert", name: "Desert", keywords: ["photo", "warm", "saharah"], skins: [{ unified: "1f3dc-fe0f", native: "\u{1F3DC}\uFE0F" }], version: 1 }, desert_island: { id: "desert_island", name: "Desert Island", keywords: ["photo", "tropical", "mojito"], skins: [{ unified: "1f3dd-fe0f", native: "\u{1F3DD}\uFE0F" }], version: 1 }, national_park: { id: "national_park", name: "National Park", keywords: ["photo", "environment", "nature"], skins: [{ unified: "1f3de-fe0f", native: "\u{1F3DE}\uFE0F" }], version: 1 }, stadium: { id: "stadium", name: "Stadium", keywords: ["photo", "place", "sports", "concert", "venue"], skins: [{ unified: "1f3df-fe0f", native: "\u{1F3DF}\uFE0F" }], version: 1 }, classical_building: { id: "classical_building", name: "Classical Building", keywords: ["art", "culture", "history"], skins: [{ unified: "1f3db-fe0f", native: "\u{1F3DB}\uFE0F" }], version: 1 }, building_construction: { id: "building_construction", name: "Building Construction", keywords: ["wip", "working", "progress"], skins: [{ unified: "1f3d7-fe0f", native: "\u{1F3D7}\uFE0F" }], version: 1 }, bricks: { id: "bricks", name: "Brick", keywords: ["bricks"], skins: [{ unified: "1f9f1", native: "\u{1F9F1}" }], version: 11 }, rock: { id: "rock", name: "Rock", keywords: ["stone"], skins: [{ unified: "1faa8", native: "\u{1FAA8}" }
51763], version: 13 }, wood: { id: "wood", name: "Wood", keywords: ["nature", "timber", "trunk"], skins: [{ unified: "1fab5", native: "\u{1FAB5}" }], version: 13 }, hut: { id: "hut", name: "Hut", keywords: ["house", "structure"], skins: [{ unified: "1f6d6", native: "\u{1F6D6}" }], version: 13 }, house_buildings: { id: "house_buildings", name: "Houses", keywords: ["house", "buildings", "photo"], skins: [{ unified: "1f3d8-fe0f", native: "\u{1F3D8}\uFE0F" }], version: 1 }, derelict_house_building: { id: "derelict_house_building", name: "Derelict House", keywords: ["building", "abandon", "evict", "broken"], skins: [{ unified: "1f3da-fe0f", native: "\u{1F3DA}\uFE0F" }], version: 1 }, house: { id: "house", name: "House", keywords: ["building", "home"], skins: [{ unified: "1f3e0", native: "\u{1F3E0}" }], version: 1 }, house_with_garden: { id: "house_with_garden", name: "House with Garden", keywords: ["home", "plant", "nature"], skins: [{ unified: "1f3e1", native: "\u{1F3E1}" }], version: 1 }, office: { id: "office", name: "Office Building", keywords: ["bureau", "work"], skins: [{ unified: "1f3e2", native: "\u{1F3E2}" }], version: 1 }, post_office: { id: "post_office", name: "Japanese Post Office", keywords: ["building", "envelope", "communication"], skins: [{ unified: "1f3e3", native: "\u{1F3E3}" }], version: 1 }, european_post_office: { id: "european_post_office", name: "Post Office", keywords: ["european", "building", "email"], skins: [{ unified: "1f3e4", native: "\u{1F3E4}" }], version: 1 }, hospital: { id: "hospital", name: "Hospital", keywords: ["building", "health", "surgery", "doctor"], skins: [{ unified: "1f3e5", native: "\u{1F3E5}" }], version: 1 }, bank: { id: "bank", name: "Bank", keywords: ["building", "money", "sales", "cash", "business", "enterprise"], skins: [{ unified: "1f3e6", native: "\u{1F3E6}" }], version: 1 }, hotel: { id: "hotel", name: "Hotel", keywords: ["building", "accomodation", "checkin"], skins: [{ unified: "1f3e8", native: "\u{1F3E8}" }], version: 1 }, love_hotel: { id: "love_hotel", name: "Love Hotel", keywords: ["like", "affection", "dating"], skins: [{ unified: "1f3e9", native: "\u{1F3E9}" }], version: 1 }, convenience_store: { id: "convenience_store", name: "Convenience Store", keywords: ["building", "shopping", "groceries"], skins: [{ unified: "1f3ea", native: "\u{1F3EA}" }], version: 1 }, school: { id: "school", name: "School", keywords: ["building", "student", "education", "learn", "teach"], skins: [{ unified: "1f3eb", native: "\u{1F3EB}" }], version: 1 }, department_store: { id: "department_store", name: "Department Store", keywords: ["building", "shopping", "mall"], skins: [{ unified: "1f3ec", native: "\u{1F3EC}" }], version: 1 }, factory: { id: "factory", name: "Factory", keywords: ["building", "industry", "pollution", "smoke"], skins: [{ unified: "1f3ed", native: "\u{1F3ED}" }], version: 1 }, japanese_castle: { id: "japanese_castle", name: "Japanese Castle", keywords: ["photo", "building"], skins: [{ unified: "1f3ef", native: "\u{1F3EF}" }], version: 1 }, european_castle: { id: "european_castle", name: "Castle", keywords: ["european", "building", "royalty", "history"], skins: [{ unified: "1f3f0", native: "\u{1F3F0}" }], version: 1 }, wedding: { id: "wedding", name: "Wedding", keywords: ["love", "like", "affection", "couple", "marriage", "bride", "groom"], skins: [{ unified: "1f492", native: "\u{1F492}" }], version: 1 }, tokyo_tower: { id: "tokyo_tower", name: "Tokyo Tower", keywords: ["photo", "japanese"], skins: [{ unified: "1f5fc", native: "\u{1F5FC}" }], version: 1 }, statue_of_liberty: { id: "statue_of_liberty", name: "Statue of Liberty", keywords: ["american", "newyork"], skins: [{ unified: "1f5fd", native: "\u{1F5FD}" }], version: 1 }, church: { id: "church", name: "Church", keywords: ["building", "religion", "christ"], skins: [{ unified: "26ea", native: "\u26EA" }], version: 1 }, mosque: { id: "mosque", name: "Mosque", keywords: ["islam", "worship", "minaret"], skins: [{ unified: "1f54c", native: "\u{1F54C}" }], version: 1 }, hindu_temple: { id: "hindu_temple", name: "Hindu Temple", keywords: ["religion"], skins: [{ unified: "1f6d5", native: "\u{1F6D5}" }], version: 12 }, synagogue: { id: "synagogue", name: "Synagogue", keywords: ["judaism", "worship", "temple", "jewish"], skins: [{ unified: "1f54d", native: "\u{1F54D}" }], version: 1 }, shinto_shrine: { id: "shinto_shrine", name: "Shinto Shrine", keywords: ["temple", "japan", "kyoto"], skins: [{ unified: "26e9-fe0f", native: "\u26E9\uFE0F" }], version: 1 }, kaaba: { id: "kaaba", name: "Kaaba", keywords: ["mecca", "mosque", "islam"], skins: [{ unified: "1f54b", native: "\u{1F54B}" }], version: 1 }, fountain: { id: "fountain", name: "Fountain", keywords: ["photo", "summer", "water", "fresh"], skins: [{ unified: "26f2", native: "\u26F2" }], version: 1 }, tent: { id: "tent", name: "Tent", keywords: ["photo", "camping", "outdoors"], skins: [{ unified: "26fa", native: "\u26FA" }], version: 1 }, foggy: { id: "foggy", name: "Foggy", keywords: ["photo", "mountain"], skins: [{ unified: "1f301", native: "\u{1F301}" }], version: 1 }, night_with_stars: { id: "night_with_stars", name: "Night with Stars", keywords: ["evening", "city", "downtown"], skins: [{ unified: "1f303", native: "\u{1F303}" }], version: 1 }, cityscape: { id: "cityscape", name: "Cityscape", keywords: ["photo", "night", "life", "urban"], skins: [{ unified: "1f3d9-fe0f", native: "\u{1F3D9}\uFE0F" }], version: 1 }, sunrise_over_mountains: { id: "sunrise_over_mountains", name: "Sunrise over Mountains", keywords: ["view", "vacation", "photo"], skins: [{ unified: "1f304", native: "\u{1F304}" }], version: 1 }, sunrise: { id: "sunrise", name: "Sunrise", keywords: ["morning", "view", "vacation", "photo"], skins: [{ unified: "1f305", native: "\u{1F305}" }], version: 1 }, city_sunset: { id: "city_sunset", name: "Cityscape at Dusk", keywords: ["city", "sunset", "photo", "evening", "sky", "buildings"], skins: [{ unified: "1f306", native: "\u{1F306}" }], version: 1 }, city_sunrise: { id: "city_sunrise", name: "Sunset", keywords: ["city", "sunrise", "photo", "good", "morning", "dawn"], skins: [{ unified: "1f307", native: "\u{1F307}" }], version: 1 }, bridge_at_night: { id: "bridge_at_night", name: "Bridge at Night", keywords: ["photo", "sanfrancisco"], skins: [{ unified: "1f309", native: "\u{1F309}" }], version: 1 }, hotsprings: { id: "hotsprings", name: "Hot Springs", keywords: ["hotsprings", "bath", "warm", "relax"], skins: [{ unified: "2668-fe0f", native: "\u2668\uFE0F" }], version: 1 }, carousel_horse: { id: "carousel_horse", name: "Carousel Horse", keywords: ["photo", "carnival"], skins: [{ unified: "1f3a0", native: "\u{1F3A0}" }], version: 1 }, playground_slide: { id: "playground_slide", name: "Playground Slide", keywords: ["fun", "park"], skins: [{ unified: "1f6dd", native: "\u{1F6DD}" }], version: 14 }, ferris_wheel: { id: "ferris_wheel", name: "Ferris Wheel", keywords: ["photo", "carnival", "londoneye"], skins: [{ unified: "1f3a1", native: "\u{1F3A1}" }], version: 1 }, roller_coaster: { id: "roller_coaster", name: "Roller Coaster", keywords: ["carnival", "playground", "photo", "fun"], skins: [{ unified: "1f3a2", native: "\u{1F3A2}" }], version: 1 }, barber: { id: "barber", name: "Barber Pole", keywords: ["hair", "salon", "style"], skins: [{ unified: "1f488", native: "\u{1F488}" }], version: 1 }, circus_tent: { id: "circus_tent", name: "Circus Tent", keywords: ["festival", "carnival", "party"], skins: [{ unified: "1f3aa", native: "\u{1F3AA}" }], version: 1 }, steam_locomotive: { id: "steam_locomotive", name: "Locomotive", keywords: ["steam", "transportation", "vehicle", "train"], skins: [{ unified: "1f682", native: "\u{1F682}" }], version: 1 }, railway_car: { id: "railway_car", name: "Railway Car", keywords: ["transportation", "vehicle"], skins: [{ unified: "1f683", native: "\u{1F683}" }], version: 1 }, bullettrain_side: { id: "bullettrain_side", name: "High-Speed Train", keywords: ["bullettrain", "side", "high", "speed", "transportation", "vehicle"], skins: [{ unified: "1f684", native: "\u{1F684}" }], version: 1 }, bullettrain_front: { id: "bullettrain_front", name: "Bullet Train", keywords: ["bullettrain", "front", "transportation", "vehicle", "speed", "fast", "public", "travel"], skins: [{ unified: "1f685", native: "\u{1F685}" }], version: 1 }, train2: { id: "train2", name: "Train", keywords: ["train2", "transportation", "vehicle"], skins: [{ unified: "1f686", native: "\u{1F686}" }], version: 1 }, metro: { id: "metro", name: "Metro", keywords: ["transportation", "blue", "square", "mrt", "underground", "tube"], skins: [{ unified: "1f687", native: "\u{1F687}" }], version: 1 }, light_rail: { id: "light_rail", name: "Light Rail", keywords: ["transportation", "vehicle"], skins: [{ unified: "1f688", native: "\u{1F688}" }], version: 1 }, station: { id: "station", name: "Station", keywords: ["transportation", "vehicle", "public"], skins: [{ unified: "1f689", native: "\u{1F689}" }], version: 1 }, tram: { id: "tram", name: "Tram", keywords: ["transportation", "vehicle"], skins: [{ unified: "1f68a", native: "\u{1F68A}" }], version: 1 }, monorail: { id: "monorail", name: "Monorail", keywords: ["transportation", "vehicle"], skins: [{ unified: "1f69d", native: "\u{1F69D}" }], version: 1 }, mountain_railway: { id: "mountain_railway", name: "Mountain Railway", keywords: ["transportation", "vehicle"], skins: [{ unified: "1f69e", native: "\u{1F69E}" }], version: 1 }, train: { id: "train", name: "Tram Car", keywords: ["train", "transportation", "vehicle", "carriage", "public", "travel"], skins: [{ unified: "1f68b", native: "\u{1F68B}" }], version: 1 }, bus: { id: "bus", name: "Bus", keywords: ["car", "vehicle", "transportation"], skins: [{ unified: "1f68c", native: "\u{1F68C}" }], version: 1 }, oncoming_bus: { id: "oncoming_bus", name: "Oncoming Bus", keywords: ["vehicle", "transportation"], skins: [{ unified: "1f68d", native: "\u{1F68D}" }], version: 1 }, trolleybus: { id: "trolleybus", name: "Trolleybus", keywords: ["bart", "transportation", "vehicle"], skins: [{ unified: "1f68e", native: "\u{1F68E}" }], version: 1 }, minibus: { id: "minibus", name: "Minibus", keywords: ["vehicle", "car", "transportation"], skins: [{ unified: "1f690", native: "\u{1F690}" }], version: 1 }, ambulance: { id: "ambulance", name: "Ambulance", keywords: ["health", "911", "hospital"], skins: [{ unified: "1f691", native: "\u{1F691}" }], version: 1 }, fire_engine: { id: "fire_engine", name: "Fire Engine", keywords: ["transportation", "cars", "vehicle"], skins: [{ unified: "1f692", native: "\u{1F692}" }], version: 1 }, police_car: { id: "police_car", name: "Police Car", keywords: ["vehicle", "cars", "transportation", "law", "legal", "enforcement"], skins: [{ unified: "1f693", native: "\u{1F693}" }], version: 1 }, oncoming_police_car: { id: "oncoming_police_car", name: "Oncoming Police Car", keywords: ["vehicle", "law", "legal", "enforcement", "911"], skins: [{ unified: "1f694", native: "\u{1F694}" }], version: 1 }, taxi: { id: "taxi", name: "Taxi", keywords: ["uber", "vehicle", "cars", "transportation"], skins: [{ unified: "1f695", native: "\u{1F695}" }], version: 1 }, oncoming_taxi: { id: "oncoming_taxi", name: "Oncoming Taxi", keywords: ["vehicle", "cars", "uber"], skins: [{ unified: "1f696", native: "\u{1F696}" }], version: 1 }, car: { id: "car", name: "Automobile", keywords: ["car", "red", "transportation", "vehicle"], skins: [{ unified: "1f697", native: "\u{1F697}" }], version: 1 }, oncoming_automobile: { id: "oncoming_automobile", name: "Oncoming Automobile", keywords: ["car", "vehicle", "transportation"], skins: [{ unified: "1f698", native: "\u{1F698}" }], version: 1 }, blue_car: { id: "blue_car", name: "Recreational Vehicle", keywords: ["blue", "car", "sport", "utility", "transportation"], skins: [{ unified: "1f699", native: "\u{1F699}" }], version: 1 }, pickup_truck: { id: "pickup_truck", name: "Pickup Truck", keywords: ["car", "transportation"], skins: [{ unified: "1f6fb", native: "\u{1F6FB}" }], version: 13 }, truck: { id: "truck", name: "Delivery Truck", keywords: ["cars", "transportation"], skins: [{ unified: "1f69a", native: "\u{1F69A}" }], version: 1 }, articulated_lorry: { id: "articulated_lorry", name: "Articulated Lorry", keywords: ["vehicle", "cars", "transportation", "express"], skins: [{ unified: "1f69b", native: "\u{1F69B}" }], version: 1 }, tractor: { id: "tractor", name: "Tractor", keywords: ["vehicle", "car", "farming", "agriculture"], skins: [{ unified: "1f69c", native: "\u{1F69C}" }], version: 1 }, racing_car: { id: "racing_car", name: "Racing Car", keywords: ["sports", "race", "fast", "formula", "f1"], skins: [{ unified: "1f3ce-fe0f", native: "\u{1F3CE}\uFE0F" }], version: 1 }, racing_motorcycle: { id: "racing_motorcycle", name: "Motorcycle", keywords: ["racing", "race", "sports", "fast"], skins: [{ unified: "1f3cd-fe0f", native: "\u{1F3CD}\uFE0F" }], version: 1 }, motor_scooter: { id: "motor_scooter", name: "Motor Scooter", keywords: ["vehicle", "vespa", "sasha"], skins: [{ unified: "1f6f5", native: "\u{1F6F5}" }], version: 3 }, manual_wheelchair: { id: "manual_wheelchair", name: "Manual Wheelchair", keywords: ["accessibility"], skins: [{ unified: "1f9bd", native: "\u{1F9BD}" }], version: 12 }, motorized_wheelchair: { id: "motorized_wheelchair", name: "Motorized Wheelchair", keywords: ["accessibility"], skins: [{ unified: "1f9bc", native: "\u{1F9BC}" }], version: 12 }, auto_rickshaw: { id: "auto_rickshaw", name: "Auto Rickshaw", keywords: ["move", "transportation"], skins: [{ unified: "1f6fa", native: "\u{1F6FA}" }], version: 12 }, bike: { id: "bike", name: "Bicycle", keywords: ["bike", "sports", "exercise", "hipster"], skins: [{ unified: "1f6b2", native: "\u{1F6B2}" }], version: 1 }, scooter: { id: "scooter", name: "Scooter", keywords: ["kick", "vehicle", "razor"], skins: [{ unified: "1f6f4", native: "\u{1F6F4}" }
51763], version: 3 }, skateboard: { id: "skateboard", name: "Skateboard", keywords: ["board"], skins: [{ unified: "1f6f9", native: "\u{1F6F9}" }], version: 11 }, roller_skate: { id: "roller_skate", name: "Roller Skate", keywords: ["footwear", "sports"], skins: [{ unified: "1f6fc", native: "\u{1F6FC}" }], version: 13 }, busstop: { id: "busstop", name: "Bus Stop", keywords: ["busstop", "transportation", "wait"], skins: [{ unified: "1f68f", native: "\u{1F68F}" }], version: 1 }, motorway: { id: "motorway", name: "Motorway", keywords: ["road", "cupertino", "interstate", "highway"], skins: [{ unified: "1f6e3-fe0f", native: "\u{1F6E3}\uFE0F" }], version: 1 }, railway_track: { id: "railway_track", name: "Railway Track", keywords: ["train", "transportation"], skins: [{ unified: "1f6e4-fe0f", native: "\u{1F6E4}\uFE0F" }], version: 1 }, oil_drum: { id: "oil_drum", name: "Oil Drum", keywords: ["barrell"], skins: [{ unified: "1f6e2-fe0f", native: "\u{1F6E2}\uFE0F" }], version: 1 }, fuelpump: { id: "fuelpump", name: "Fuel Pump", keywords: ["fuelpump", "gas", "station", "petroleum"], skins: [{ unified: "26fd", native: "\u26FD" }], version: 1 }, wheel: { id: "wheel", name: "Wheel", keywords: ["car", "transport"], skins: [{ unified: "1f6de", native: "\u{1F6DE}" }], version: 14 }, rotating_light: { id: "rotating_light", name: "Police Car Light", keywords: ["rotating", "ambulance", "911", "emergency", "alert", "error", "pinged", "law", "legal"], skins: [{ unified: "1f6a8", native: "\u{1F6A8}" }], version: 1 }, traffic_light: { id: "traffic_light", name: "Horizontal Traffic Light", keywords: ["transportation", "signal"], skins: [{ unified: "1f6a5", native: "\u{1F6A5}" }], version: 1 }, vertical_traffic_light: { id: "vertical_traffic_light", name: "Vertical Traffic Light", keywords: ["transportation", "driving"], skins: [{ unified: "1f6a6", native: "\u{1F6A6}" }], version: 1 }, octagonal_sign: { id: "octagonal_sign", name: "Stop Sign", keywords: ["octagonal"], skins: [{ unified: "1f6d1", native: "\u{1F6D1}" }], version: 3 }, construction: { id: "construction", name: "Construction", keywords: ["wip", "progress", "caution", "warning"], skins: [{ unified: "1f6a7", native: "\u{1F6A7}" }], version: 1 }, anchor: { id: "anchor", name: "Anchor", keywords: ["ship", "ferry", "sea", "boat"], skins: [{ unified: "2693", native: "\u2693" }], version: 1 }, ring_buoy: { id: "ring_buoy", name: "Ring Buoy", keywords: ["life", "saver", "preserver"], skins: [{ unified: "1f6df", native: "\u{1F6DF}" }], version: 14 }, boat: { id: "boat", name: "Sailboat", keywords: ["boat", "ship", "summer", "transportation", "water", "sailing"], skins: [{ unified: "26f5", native: "\u26F5" }], version: 1 }, canoe: { id: "canoe", name: "Canoe", keywords: ["boat", "paddle", "water", "ship"], skins: [{ unified: "1f6f6", native: "\u{1F6F6}" }], version: 3 }, speedboat: { id: "speedboat", name: "Speedboat", keywords: ["ship", "transportation", "vehicle", "summer"], skins: [{ unified: "1f6a4", native: "\u{1F6A4}" }], version: 1 }, passenger_ship: { id: "passenger_ship", name: "Passenger Ship", keywords: ["yacht", "cruise", "ferry"], skins: [{ unified: "1f6f3-fe0f", native: "\u{1F6F3}\uFE0F" }], version: 1 }, ferry: { id: "ferry", name: "Ferry", keywords: ["boat", "ship", "yacht"], skins: [{ unified: "26f4-fe0f", native: "\u26F4\uFE0F" }], version: 1 }, motor_boat: { id: "motor_boat", name: "Motor Boat", keywords: ["ship"], skins: [{ unified: "1f6e5-fe0f", native: "\u{1F6E5}\uFE0F" }], version: 1 }, ship: { id: "ship", name: "Ship", keywords: ["transportation", "titanic", "deploy"], skins: [{ unified: "1f6a2", native: "\u{1F6A2}" }], version: 1 }, airplane: { id: "airplane", name: "Airplane", keywords: ["vehicle", "transportation", "flight", "fly"], skins: [{ unified: "2708-fe0f", native: "\u2708\uFE0F" }], version: 1 }, small_airplane: { id: "small_airplane", name: "Small Airplane", keywords: ["flight", "transportation", "fly", "vehicle"], skins: [{ unified: "1f6e9-fe0f", native: "\u{1F6E9}\uFE0F" }], version: 1 }, airplane_departure: { id: "airplane_departure", name: "Airplane Departure", keywords: ["airport", "flight", "landing"], skins: [{ unified: "1f6eb", native: "\u{1F6EB}" }], version: 1 }, airplane_arriving: { id: "airplane_arriving", name: "Airplane Arrival", keywords: ["arriving", "airport", "flight", "boarding"], skins: [{ unified: "1f6ec", native: "\u{1F6EC}" }], version: 1 }, parachute: { id: "parachute", name: "Parachute", keywords: ["fly", "glide"], skins: [{ unified: "1fa82", native: "\u{1FA82}" }], version: 12 }, seat: { id: "seat", name: "Seat", keywords: ["sit", "airplane", "transport", "bus", "flight", "fly"], skins: [{ unified: "1f4ba", native: "\u{1F4BA}" }], version: 1 }, helicopter: { id: "helicopter", name: "Helicopter", keywords: ["transportation", "vehicle", "fly"], skins: [{ unified: "1f681", native: "\u{1F681}" }], version: 1 }, suspension_railway: { id: "suspension_railway", name: "Suspension Railway", keywords: ["vehicle", "transportation"], skins: [{ unified: "1f69f", native: "\u{1F69F}" }], version: 1 }, mountain_cableway: { id: "mountain_cableway", name: "Mountain Cableway", keywords: ["transportation", "vehicle", "ski"], skins: [{ unified: "1f6a0", native: "\u{1F6A0}" }], version: 1 }, aerial_tramway: { id: "aerial_tramway", name: "Aerial Tramway", keywords: ["transportation", "vehicle", "ski"], skins: [{ unified: "1f6a1", native: "\u{1F6A1}" }], version: 1 }, satellite: { id: "satellite", name: "Satellite", keywords: ["communication", "gps", "orbit", "spaceflight", "NASA", "ISS"], skins: [{ unified: "1f6f0-fe0f", native: "\u{1F6F0}\uFE0F" }], version: 1 }, rocket: { id: "rocket", name: "Rocket", keywords: ["launch", "ship", "staffmode", "NASA", "outer", "space", "fly"], skins: [{ unified: "1f680", native: "\u{1F680}" }], version: 1 }, flying_saucer: { id: "flying_saucer", name: "Flying Saucer", keywords: ["transportation", "vehicle", "ufo"], skins: [{ unified: "1f6f8", native: "\u{1F6F8}" }], version: 5 }, bellhop_bell: { id: "bellhop_bell", name: "Bellhop Bell", keywords: ["service"], skins: [{ unified: "1f6ce-fe0f", native: "\u{1F6CE}\uFE0F" }], version: 1 }, luggage: { id: "luggage", name: "Luggage", keywords: ["packing", "travel"], skins: [{ unified: "1f9f3", native: "\u{1F9F3}" }], version: 11 }, hourglass: { id: "hourglass", name: "Hourglass", keywords: ["done", "time", "clock", "oldschool", "limit", "exam", "quiz", "test"], skins: [{ unified: "231b", native: "\u231B" }], version: 1 }, hourglass_flowing_sand: { id: "hourglass_flowing_sand", name: "Hourglass Not Done", keywords: ["flowing", "sand", "oldschool", "time", "countdown"], skins: [{ unified: "23f3", native: "\u23F3" }], version: 1 }, watch: { id: "watch", name: "Watch", keywords: ["time", "accessories"], skins: [{ unified: "231a", native: "\u231A" }], version: 1 }, alarm_clock: { id: "alarm_clock", name: "Alarm Clock", keywords: ["time", "wake"], skins: [{ unified: "23f0", native: "\u23F0" }], version: 1 }, stopwatch: { id: "stopwatch", name: "Stopwatch", keywords: ["time", "deadline"], skins: [{ unified: "23f1-fe0f", native: "\u23F1\uFE0F" }], version: 1 }, timer_clock: { id: "timer_clock", name: "Timer Clock", keywords: ["alarm"], skins: [{ unified: "23f2-fe0f", native: "\u23F2\uFE0F" }], version: 1 }, mantelpiece_clock: { id: "mantelpiece_clock", name: "Mantelpiece Clock", keywords: ["time"], skins: [{ unified: "1f570-fe0f", native: "\u{1F570}\uFE0F" }], version: 1 }, clock12: { id: "clock12", name: "Twelve O\u2019clock", keywords: ["clock12", "o", "clock", "12", "00:00", "0000", "12:00", "1200", "time", "noon", "midnight", "midday", "late", "early", "schedule"], skins: [{ unified: "1f55b", native: "\u{1F55B}" }], version: 1 }, clock1230: { id: "clock1230", name: "Twelve-Thirty", keywords: ["clock1230", "twelve", "thirty", "00:30", "0030", "12:30", "1230", "time", "late", "early", "schedule"], skins: [{ unified: "1f567", native: "\u{1F567}" }], version: 1 }, clock1: { id: "clock1", name: "One O\u2019clock", keywords: ["clock1", "o", "clock", "1", "1:00", "100", "13:00", "1300", "time", "late", "early", "schedule"], skins: [{ unified: "1f550", native: "\u{1F550}" }], version: 1 }, clock130: { id: "clock130", name: "One-Thirty", keywords: ["clock130", "one", "thirty", "1:30", "130", "13:30", "1330", "time", "late", "early", "schedule"], skins: [{ unified: "1f55c", native: "\u{1F55C}" }], version: 1 }, clock2: { id: "clock2", name: "Two O\u2019clock", keywords: ["clock2", "o", "clock", "2", "2:00", "200", "14:00", "1400", "time", "late", "early", "schedule"], skins: [{ unified: "1f551", native: "\u{1F551}" }], version: 1 }, clock230: { id: "clock230", name: "Two-Thirty", keywords: ["clock230", "two", "thirty", "2:30", "230", "14:30", "1430", "time", "late", "early", "schedule"], skins: [{ unified: "1f55d", native: "\u{1F55D}" }], version: 1 }, clock3: { id: "clock3", name: "Three O\u2019clock", keywords: ["clock3", "o", "clock", "3", "3:00", "300", "15:00", "1500", "time", "late", "early", "schedule"], skins: [{ unified: "1f552", native: "\u{1F552}" }], version: 1 }, clock330: { id: "clock330", name: "Three-Thirty", keywords: ["clock330", "three", "thirty", "3:30", "330", "15:30", "1530", "time", "late", "early", "schedule"], skins: [{ unified: "1f55e", native: "\u{1F55E}" }], version: 1 }, clock4: { id: "clock4", name: "Four O\u2019clock", keywords: ["clock4", "o", "clock", "4", "4:00", "400", "16:00", "1600", "time", "late", "early", "schedule"], skins: [{ unified: "1f553", native: "\u{1F553}" }], version: 1 }, clock430: { id: "clock430", name: "Four-Thirty", keywords: ["clock430", "four", "thirty", "4:30", "430", "16:30", "1630", "time", "late", "early", "schedule"], skins: [{ unified: "1f55f", native: "\u{1F55F}" }], version: 1 }, clock5: { id: "clock5", name: "Five O\u2019clock", keywords: ["clock5", "o", "clock", "5", "5:00", "500", "17:00", "1700", "time", "late", "early", "schedule"], skins: [{ unified: "1f554", native: "\u{1F554}" }], version: 1 }, clock530: { id: "clock530", name: "Five-Thirty", keywords: ["clock530", "five", "thirty", "5:30", "530", "17:30", "1730", "time", "late", "early", "schedule"], skins: [{ unified: "1f560", native: "\u{1F560}" }], version: 1 }, clock6: { id: "clock6", name: "Six O\u2019clock", keywords: ["clock6", "o", "clock", "6", "6:00", "600", "18:00", "1800", "time", "late", "early", "schedule", "dawn", "dusk"], skins: [{ unified: "1f555", native: "\u{1F555}" }], version: 1 }, clock630: { id: "clock630", name: "Six-Thirty", keywords: ["clock630", "six", "thirty", "6:30", "630", "18:30", "1830", "time", "late", "early", "schedule"], skins: [{ unified: "1f561", native: "\u{1F561}" }], version: 1 }, clock7: { id: "clock7", name: "Seven O\u2019clock", keywords: ["clock7", "o", "clock", "7", "7:00", "700", "19:00", "1900", "time", "late", "early", "schedule"], skins: [{ unified: "1f556", native: "\u{1F556}" }], version: 1 }, clock730: { id: "clock730", name: "Seven-Thirty", keywords: ["clock730", "seven", "thirty", "7:30", "730", "19:30", "1930", "time", "late", "early", "schedule"], skins: [{ unified: "1f562", native: "\u{1F562}" }], version: 1 }, clock8: { id: "clock8", name: "Eight O\u2019clock", keywords: ["clock8", "o", "clock", "8", "8:00", "800", "20:00", "2000", "time", "late", "early", "schedule"], skins: [{ unified: "1f557", native: "\u{1F557}" }], version: 1 }, clock830: { id: "clock830", name: "Eight-Thirty", keywords: ["clock830", "eight", "thirty", "8:30", "830", "20:30", "2030", "time", "late", "early", "schedule"], skins: [{ unified: "1f563", native: "\u{1F563}" }], version: 1 }, clock9: { id: "clock9", name: "Nine O\u2019clock", keywords: ["clock9", "o", "clock", "9", "9:00", "900", "21:00", "2100", "time", "late", "early", "schedule"], skins: [{ unified: "1f558", native: "\u{1F558}" }], version: 1 }, clock930: { id: "clock930", name: "Nine-Thirty", keywords: ["clock930", "nine", "thirty", "9:30", "930", "21:30", "2130", "time", "late", "early", "schedule"], skins: [{ unified: "1f564", native: "\u{1F564}" }], version: 1 }, clock10: { id: "clock10", name: "Ten O\u2019clock", keywords: ["clock10", "o", "clock", "10", "10:00", "1000", "22:00", "2200", "time", "late", "early", "schedule"], skins: [{ unified: "1f559", native: "\u{1F559}" }], version: 1 }, clock1030: { id: "clock1030", name: "Ten-Thirty", keywords: ["clock1030", "ten", "thirty", "10:30", "1030", "22:30", "2230", "time", "late", "early", "schedule"], skins: [{ unified: "1f565", native: "\u{1F565}" }], version: 1 }, clock11: { id: "clock11", name: "Eleven O\u2019clock", keywords: ["clock11", "o", "clock", "11", "11:00", "1100", "23:00", "2300", "time", "late", "early", "schedule"], skins: [{ unified: "1f55a", native: "\u{1F55A}" }], version: 1 }, clock1130: { id: "clock1130", name: "Eleven-Thirty", keywords: ["clock1130", "eleven", "thirty", "11:30", "1130", "23:30", "2330", "time", "late", "early", "schedule"], skins: [{ unified: "1f566", native: "\u{1F566}" }], version: 1 }, new_moon: { id: "new_moon", name: "New Moon", keywords: ["nature", "twilight", "planet", "space", "night", "evening", "sleep"], skins: [{ unified: "1f311", native: "\u{1F311}" }], version: 1 }, waxing_crescent_moon: { id: "waxing_crescent_moon", name: "Waxing Crescent Moon", keywords: ["nature", "twilight", "planet", "space", "night", "evening", "sleep"], skins: [{ unified: "1f312", native: "\u{1F312}" }], version: 1 }, first_quarter_moon: { id: "first_quarter_moon", name: "First Quarter Moon", keywords: ["nature", "twilight", "planet", "space", "night", "evening", "sleep"], skins: [{ unified: "1f313", native: "\u{1F313}" }], version: 1 }, moon: { id: "moon", name: "Waxing Gibbous Moon", keywords: ["nature", "night", "sky", "gray", "twilight", "planet", "space", "evening", "sleep"], skins: [{ unified: "1f314", native: "\u{1F314}" }], version: 1 }, full_moon: { id: "full_moon", name: "Full Moon", keywords: ["nature", "yellow", "twilight", "planet", "space", "night", "evening", "sleep"], skins: [{ unified: "1f315", native: "\u{1F315}" }], version: 1 }, waning_gibbous_moon: { id: "waning_gibbous_moon", name: "Waning Gibbous Moon", keywords: ["nature", "twilight", "planet", "space", "night", "evening", "sleep", "waxing"], skins: [{ unified: "1f316", native: "\u{1F316}" }], version: 1 }, last_quarter_moon: { id: "last_quarter_moon", name: "Last Quarter Moon", keywords: ["nature", "twilight", "planet", "space", "night", "evening", "sleep"], skins: [{ unified: "1f317", native: "\u{1F317}" }], version: 1 }, waning_crescent_moon: { id: "waning_crescent_moon", name: "Waning Crescent Moon", keywords: ["nature", "twilight", "planet", "space", "night", "evening", "sleep"], skins: [{ unified: "1f318", native: "\u{1F318}" }], version: 1 }, crescent_moon: { id: "crescent_moon", name: "Crescent Moon", keywords: ["night", "sleep", "sky", "evening", "magic"], skins: [{ unified: "1f319", native: "\u{1F319}" }], version: 1 }
51763, new_moon_with_face: { id: "new_moon_with_face", name: "New Moon Face", keywords: ["with", "nature", "twilight", "planet", "space", "night", "evening", "sleep"], skins: [{ unified: "1f31a", native: "\u{1F31A}" }], version: 1 }, first_quarter_moon_with_face: { id: "first_quarter_moon_with_face", name: "First Quarter Moon Face", keywords: ["with", "nature", "twilight", "planet", "space", "night", "evening", "sleep"], skins: [{ unified: "1f31b", native: "\u{1F31B}" }], version: 1 }, last_quarter_moon_with_face: { id: "last_quarter_moon_with_face", name: "Last Quarter Moon Face", keywords: ["with", "nature", "twilight", "planet", "space", "night", "evening", "sleep"], skins: [{ unified: "1f31c", native: "\u{1F31C}" }], version: 1 }, thermometer: { id: "thermometer", name: "Thermometer", keywords: ["weather", "temperature", "hot", "cold"], skins: [{ unified: "1f321-fe0f", native: "\u{1F321}\uFE0F" }], version: 1 }, sunny: { id: "sunny", name: "Sun", keywords: ["sunny", "weather", "nature", "brightness", "summer", "beach", "spring"], skins: [{ unified: "2600-fe0f", native: "\u2600\uFE0F" }], version: 1 }, full_moon_with_face: { id: "full_moon_with_face", name: "Full Moon Face", keywords: ["with", "nature", "twilight", "planet", "space", "night", "evening", "sleep"], skins: [{ unified: "1f31d", native: "\u{1F31D}" }], version: 1 }, sun_with_face: { id: "sun_with_face", name: "Sun with Face", keywords: ["nature", "morning", "sky"], skins: [{ unified: "1f31e", native: "\u{1F31E}" }], version: 1 }, ringed_planet: { id: "ringed_planet", name: "Ringed Planet", keywords: ["outerspace"], skins: [{ unified: "1fa90", native: "\u{1FA90}" }], version: 12 }, star: { id: "star", name: "Star", keywords: ["night", "yellow"], skins: [{ unified: "2b50", native: "\u2B50" }], version: 1 }, star2: { id: "star2", name: "Glowing Star", keywords: ["star2", "night", "sparkle", "awesome", "good", "magic"], skins: [{ unified: "1f31f", native: "\u{1F31F}" }], version: 1 }, stars: { id: "stars", name: "Shooting Star", keywords: ["stars", "night", "photo"], skins: [{ unified: "1f320", native: "\u{1F320}" }], version: 1 }, milky_way: { id: "milky_way", name: "Milky Way", keywords: ["photo", "space", "stars"], skins: [{ unified: "1f30c", native: "\u{1F30C}" }], version: 1 }, cloud: { id: "cloud", name: "Cloud", keywords: ["weather", "sky"], skins: [{ unified: "2601-fe0f", native: "\u2601\uFE0F" }], version: 1 }, partly_sunny: { id: "partly_sunny", name: "Sun Behind Cloud", keywords: ["partly", "sunny", "weather", "nature", "cloudy", "morning", "fall", "spring"], skins: [{ unified: "26c5", native: "\u26C5" }], version: 1 }, thunder_cloud_and_rain: { id: "thunder_cloud_and_rain", name: "Cloud with Lightning and Rain", keywords: ["thunder", "weather"], skins: [{ unified: "26c8-fe0f", native: "\u26C8\uFE0F" }], version: 1 }, mostly_sunny: { id: "mostly_sunny", name: "Sun Behind Small Cloud", keywords: ["mostly", "sunny", "weather"], skins: [{ unified: "1f324-fe0f", native: "\u{1F324}\uFE0F" }], version: 1 }, barely_sunny: { id: "barely_sunny", name: "Sun Behind Large Cloud", keywords: ["barely", "sunny", "weather"], skins: [{ unified: "1f325-fe0f", native: "\u{1F325}\uFE0F" }], version: 1 }, partly_sunny_rain: { id: "partly_sunny_rain", name: "Sun Behind Rain Cloud", keywords: ["partly", "sunny", "weather"], skins: [{ unified: "1f326-fe0f", native: "\u{1F326}\uFE0F" }], version: 1 }, rain_cloud: { id: "rain_cloud", name: "Cloud with Rain", keywords: ["weather"], skins: [{ unified: "1f327-fe0f", native: "\u{1F327}\uFE0F" }], version: 1 }, snow_cloud: { id: "snow_cloud", name: "Cloud with Snow", keywords: ["weather"], skins: [{ unified: "1f328-fe0f", native: "\u{1F328}\uFE0F" }], version: 1 }, lightning: { id: "lightning", name: "Cloud with Lightning", keywords: ["weather", "thunder"], skins: [{ unified: "1f329-fe0f", native: "\u{1F329}\uFE0F" }], version: 1 }, tornado: { id: "tornado", name: "Tornado", keywords: ["cloud", "weather", "cyclone", "twister"], skins: [{ unified: "1f32a-fe0f", native: "\u{1F32A}\uFE0F" }], version: 1 }, fog: { id: "fog", name: "Fog", keywords: ["weather"], skins: [{ unified: "1f32b-fe0f", native: "\u{1F32B}\uFE0F" }], version: 1 }, wind_blowing_face: { id: "wind_blowing_face", name: "Wind Face", keywords: ["blowing", "gust", "air"], skins: [{ unified: "1f32c-fe0f", native: "\u{1F32C}\uFE0F" }], version: 1 }, cyclone: { id: "cyclone", name: "Cyclone", keywords: ["weather", "swirl", "blue", "cloud", "vortex", "spiral", "whirlpool", "spin", "tornado", "hurricane", "typhoon"], skins: [{ unified: "1f300", native: "\u{1F300}" }], version: 1 }, rainbow: { id: "rainbow", name: "Rainbow", keywords: ["nature", "happy", "unicorn", "face", "photo", "sky", "spring"], skins: [{ unified: "1f308", native: "\u{1F308}" }], version: 1 }, closed_umbrella: { id: "closed_umbrella", name: "Closed Umbrella", keywords: ["weather", "rain", "drizzle"], skins: [{ unified: "1f302", native: "\u{1F302}" }], version: 1 }, umbrella: { id: "umbrella", name: "Umbrella", keywords: ["weather", "spring"], skins: [{ unified: "2602-fe0f", native: "\u2602\uFE0F" }], version: 1 }, umbrella_with_rain_drops: { id: "umbrella_with_rain_drops", name: "Umbrella with Rain Drops", keywords: ["rainy", "weather", "spring"], skins: [{ unified: "2614", native: "\u2614" }], version: 1 }, umbrella_on_ground: { id: "umbrella_on_ground", name: "Umbrella on Ground", keywords: ["weather", "summer"], skins: [{ unified: "26f1-fe0f", native: "\u26F1\uFE0F" }], version: 1 }, zap: { id: "zap", name: "High Voltage", keywords: ["zap", "thunder", "weather", "lightning", "bolt", "fast"], skins: [{ unified: "26a1", native: "\u26A1" }], version: 1 }, snowflake: { id: "snowflake", name: "Snowflake", keywords: ["winter", "season", "cold", "weather", "christmas", "xmas"], skins: [{ unified: "2744-fe0f", native: "\u2744\uFE0F" }], version: 1 }, snowman: { id: "snowman", name: "Snowman", keywords: ["winter", "season", "cold", "weather", "christmas", "xmas", "frozen"], skins: [{ unified: "2603-fe0f", native: "\u2603\uFE0F" }], version: 1 }, snowman_without_snow: { id: "snowman_without_snow", name: "Snowman Without Snow", keywords: ["winter", "season", "cold", "weather", "christmas", "xmas", "frozen"], skins: [{ unified: "26c4", native: "\u26C4" }], version: 1 }, comet: { id: "comet", name: "Comet", keywords: ["space"], skins: [{ unified: "2604-fe0f", native: "\u2604\uFE0F" }], version: 1 }, fire: { id: "fire", name: "Fire", keywords: ["hot", "cook", "flame"], skins: [{ unified: "1f525", native: "\u{1F525}" }], version: 1 }, droplet: { id: "droplet", name: "Droplet", keywords: ["water", "drip", "faucet", "spring"], skins: [{ unified: "1f4a7", native: "\u{1F4A7}" }], version: 1 }, ocean: { id: "ocean", name: "Water Wave", keywords: ["ocean", "sea", "nature", "tsunami", "disaster"], skins: [{ unified: "1f30a", native: "\u{1F30A}" }], version: 1 }, jack_o_lantern: { id: "jack_o_lantern", name: "Jack-O-Lantern", keywords: ["jack", "o", "lantern", "halloween", "light", "pumpkin", "creepy", "fall"], skins: [{ unified: "1f383", native: "\u{1F383}" }], version: 1 }, christmas_tree: { id: "christmas_tree", name: "Christmas Tree", keywords: ["festival", "vacation", "december", "xmas", "celebration"], skins: [{ unified: "1f384", native: "\u{1F384}" }], version: 1 }, fireworks: { id: "fireworks", name: "Fireworks", keywords: ["photo", "festival", "carnival", "congratulations"], skins: [{ unified: "1f386", native: "\u{1F386}" }], version: 1 }, sparkler: { id: "sparkler", name: "Sparkler", keywords: ["stars", "night", "shine"], skins: [{ unified: "1f387", native: "\u{1F387}" }], version: 1 }, firecracker: { id: "firecracker", name: "Firecracker", keywords: ["dynamite", "boom", "explode", "explosion", "explosive"], skins: [{ unified: "1f9e8", native: "\u{1F9E8}" }], version: 11 }, sparkles: { id: "sparkles", name: "Sparkles", keywords: ["stars", "shine", "shiny", "cool", "awesome", "good", "magic"], skins: [{ unified: "2728", native: "\u2728" }], version: 1 }, balloon: { id: "balloon", name: "Balloon", keywords: ["party", "celebration", "birthday", "cir
51763cus"], skins: [{ unified: "1f388", native: "\u{1F388}" }], version: 1 }, tada: { id: "tada", name: "Party Popper", keywords: ["tada", "congratulations", "birthday", "magic", "circus", "celebration"], skins: [{ unified: "1f389", native: "\u{1F389}" }], version: 1 }, confetti_ball: { id: "confetti_ball", name: "Confetti Ball", keywords: ["festival", "party", "birthday", "circus"], skins: [{ unified: "1f38a", native: "\u{1F38A}" }], version: 1 }, tanabata_tree: { id: "tanabata_tree", name: "Tanabata Tree", keywords: ["plant", "nature", "branch", "summer", "bamboo", "wish", "star", "festival", "tanzaku"], skins: [{ unified: "1f38b", native: "\u{1F38B}" }], version: 1 }, bamboo: { id: "bamboo", name: "Pine Decoration", keywords: ["bamboo", "japanese", "plant", "nature", "vegetable", "panda", "new", "years"], skins: [{ unified: "1f38d", native: "\u{1F38D}" }], version: 1 }, dolls: { id: "dolls", name: "Japanese Dolls", keywords: ["toy", "kimono"], skins: [{ unified: "1f38e", native: "\u{1F38E}" }], version: 1 }, flags: { id: "flags", name: "Carp Streamer", keywords: ["flags", "fish", "japanese", "koinobori", "banner"], skins: [{ unified: "1f38f", native: "\u{1F38F}" }], version: 1 }, wind_chime: { id: "wind_chime", name: "Wind Chime", keywords: ["nature", "ding", "spring", "bell"], skins: [{ unified: "1f390", native: "\u{1F390}" }], version: 1 }, rice_scene: { id: "rice_scene", name: "Moon Viewing Ceremony", keywords: ["rice", "scene", "photo", "japan", "asia", "tsukimi"], skins: [{ unified: "1f391", native: "\u{1F391}" }], version: 1 }, red_envelope: { id: "red_envelope", name: "Red Envelope", keywords: ["gift"], skins: [{ unified: "1f9e7", native: "\u{1F9E7}" }], version: 11 }, ribbon: { id: "ribbon", name: "Ribbon", keywords: ["decoration", "pink", "girl", "bowtie"], skins: [{ unified: "1f380", native: "\u{1F380}" }], version: 1 }, gift: { id: "gift", name: "Wrapped Gift", keywords: ["present", "birthday", "christmas", "xmas"], skins: [{ unified: "1f381", native: "\u{1F381}" }], version: 1 }, reminder_ribbon: { id: "reminder_ribbon", name: "Reminder Ribbon", keywords: ["sports", "cause", "support", "awareness"], skins: [{ unified: "1f397-fe0f", native: "\u{1F397}\uFE0F" }], version: 1 }, admission_tickets: { id: "admission_tickets", name: "Admission Tickets", keywords: ["sports", "concert", "entrance"], skins: [{ unified: "1f39f-fe0f", native: "\u{1F39F}\uFE0F" }], version: 1 }, ticket: { id: "ticket", name: "Ticket", keywords: ["event", "concert", "pass"], skins: [{ unified: "1f3ab", native: "\u{1F3AB}" }], version: 1 }, medal: { id: "medal", name: "Military Medal", keywords: ["award", "winning", "army"], skins: [{ unified: "1f396-fe0f", native: "\u{1F396}\uFE0F" }], version: 1 }, trophy: { id: "trophy", name: "Trophy", keywords: ["win", "award", "contest", "place", "ftw", "ceremony"], skins: [{ unified: "1f3c6", native: "\u{1F3C6}" }], version: 1 }, sports_medal: { id: "sports_medal", name: "Sports Medal", keywords: ["award", "winning"], skins: [{ unified: "1f3c5", native: "\u{1F3C5}" }], version: 1 }, first_place_medal: { id: "first_place_medal", name: "1st Place Medal", keywords: ["first", "award", "winning"], skins: [{ unified: "1f947", native: "\u{1F947}" }], version: 3 }, second_place_medal: { id: "second_place_medal", name: "2nd Place Medal", keywords: ["second", "award"], skins: [{ unified: "1f948", native: "\u{1F948}" }], version: 3 }, third_place_medal: { id: "third_place_medal", name: "3rd Place Medal", keywords: ["third", "award"], skins: [{ unified: "1f949", native: "\u{1F949}" }], version: 3 }, soccer: { id: "soccer", name: "Soccer Ball", keywords: ["sports", "football"], skins: [{ unified: "26bd", native: "\u26BD" }], version: 1 }, baseball: { id: "baseball", name: "Baseball", keywords: ["sports", "balls"], skins: [{ unified: "26be", native: "\u26BE" }], version: 1 }, softball: { id: "softball", name: "Softball", keywords: ["sports", "balls"], skins: [{ unified: "1f94e", native: "\u{1F94E}" }], version: 11 }, basketball: { id: "basketball", name: "Basketball", keywords: ["sports", "balls", "NBA"], skins: [{ unified: "1f3c0", native: "\u{1F3C0}" }], version: 1 }, volleyball: { id: "volleyball", name: "Volleyball", keywords: ["sports", "balls"], skins: [{ unified: "1f3d0", native: "\u{1F3D0}" }], version: 1 }, football: { id: "football", name: "American Football", keywords: ["sports", "balls", "NFL"], skins: [{ unified: "1f3c8", native: "\u{1F3C8}" }], version: 1 }, rugby_football: { id: "rugby_football", name: "Rugby Football", keywords: ["sports", "team"], skins: [{ unified: "1f3c9", native: "\u{1F3C9}" }], version: 1 }, tennis: { id: "tennis", name: "Tennis", keywords: ["sports", "balls", "green"], skins: [{ unified: "1f3be", native: "\u{1F3BE}" }], version: 1 }, flying_disc: { id: "flying_disc", name: "Flying Disc", keywords: ["sports", "frisbee", "ultimate"], skins: [{ unified: "1f94f", native: "\u{1F94F}" }], version: 11 }, bowling: { id: "bowling", name: "Bowling", keywords: ["sports", "fun", "play"], skins: [{ unified: "1f3b3", native: "\u{1F3B3}" }], version: 1 }, cricket_bat_and_ball: { id: "cricket_bat_and_ball", name: "Cricket Game", keywords: ["bat", "and", "ball", "sports"], skins: [{ unified: "1f3cf", native: "\u{1F3CF}" }], version: 1 }, field_hockey_stick_and_ball: { id: "field_hockey_stick_and_ball", name: "Field Hockey", keywords: ["stick", "and", "ball", "sports"], skins: [{ unified: "1f3d1", native: "\u{1F3D1}" }], version: 1 }, ice_hockey_stick_and_puck: { id: "ice_hockey_stick_and_puck", name: "Ice Hockey", keywords: ["stick", "and", "puck", "sports"], skins: [{ unified: "1f3d2", native: "\u{1F3D2}" }], version: 1 }, lacrosse: { id: "lacrosse", name: "Lacrosse", keywords: ["sports", "ball", "stick"], skins: [{ unified: "1f94d", native: "\u{1F94D}" }], version: 11 }, table_tennis_paddle_and_ball: { id: "table_tennis_paddle_and_ball", name: "Ping Pong", keywords: ["table", "tennis", "paddle", "and", "ball", "sports", "pingpong"], skins: [{ unified: "1f3d3", native: "\u{1F3D3}" }], version: 1 }, badminton_racquet_and_shuttlecock: { id: "badminton_racquet_and_shuttlecock", name: "Badminton", keywords: ["racquet", "and", "shuttlecock", "sports"], skins: [{ unified: "1f3f8", native: "\u{1F3F8}" }], version: 1 }, boxing_glove: { id: "boxing_glove", name: "Boxing Glove", keywords: ["sports", "fighting"], skins: [{ unified: "1f94a", native: "\u{1F94A}" }], version: 3 }, martial_arts_uniform: { id: "martial_arts_uniform", name: "Martial Arts Uniform", keywords: ["judo", "karate", "taekwondo"], skins: [{ unified: "1f94b", native: "\u{1F94B}" }], version: 3 }, goal_net: { id: "goal_net", name: "Goal Net", keywords: ["sports"], skins: [{ unified: "1f945", native: "\u{1F945}" }], version: 3 }, golf: { id: "golf", name: "Flag in Hole", keywords: ["golf", "sports", "business", "summer"], skins: [{ unified: "26f3", native: "\u26F3" }], version: 1 }, ice_skate: { id: "ice_skate", name: "Ice Skate", keywords: ["sports"], skins: [{ unified: "26f8-fe0f", native: "\u26F8\uFE0F" }], version: 1 }, fishing_pole_and_fish: { id: "fishing_pole_and_fish", name: "Fishing Pole", keywords: ["and", "fish", "food", "hobby", "summer"], skins: [{ unified: "1f3a3", native: "\u{1F3A3}" }], version: 1 }, diving_mask: { id: "diving_mask", name: "Diving Mask", keywords: ["sport", "ocean"], skins: [{ unified: "1f93f", native: "\u{1F93F}" }], version: 12 }, running_shirt_with_sash: { id: "running_shirt_with_sash", name: "Running Shirt", keywords: ["with", "sash", "play", "pageant"], skins: [{ unified: "1f3bd", native: "\u{1F3BD}" }], version: 1 }, ski: { id: "ski", name: "Skis", keywords: ["ski", "sports", "winter", "cold", "snow"], skins: [{ unified: "1f3bf", native: "\u{1F3BF}" }], version: 1 }, sled: { id: "sled", name: "Sled", keywords: ["sleigh", "luge", "toboggan"], skins: [{ unified: "1f6f7", native: "\u{1F6F7}" }], version: 5 }, curling_stone: { id: "curling_stone", name: "Curling Stone", keywords: ["sports"], skins: [{ unified: "1f94c", native: "\u{1F94C}" }], version: 5 }, dart: { id: "dart", name: "Bullseye", keywords: ["dart", "direct", "hit", "game", "play", "bar", "target"], skins: [{ unified: "1f3af", native: "\u{1F3AF}" }], version: 1 }, "yo-yo": { id: "yo-yo", name: "Yo-Yo", keywords: ["yo", "toy"], skins: [{ unified: "1fa80", native: "\u{1FA80}" }], version: 12 }, kite: { id: "kite", name: "Kite", keywords: ["wind", "fly"], skins: [{ unified: "1fa81", native: "\u{1FA81}" }], version: 12 }, gun: { id: "gun", name: "Pistol", keywords: ["gun", "violence", "weapon", "revolver"], skins: [{ unified: "1f52b", native: "\u{1F52B}" }], version: 1 }, "8ball": { id: "8ball", name: "Billiards", keywords: ["8ball", "pool", "8", "ball", "hobby", "game", "luck", "magic"], skins: [{ unified: "1f3b1", native: "\u{1F3B1}" }], version: 1 }, crystal_ball: { id: "crystal_ball", name: "Crystal Ball", keywords: ["disco", "party", "magic", "cir
51763cus", "fortune", "teller"], skins: [{ unified: "1f52e", native: "\u{1F52E}" }], version: 1 }, magic_wand: { id: "magic_wand", name: "Magic Wand", keywords: ["supernature", "power"], skins: [{ unified: "1fa84", native: "\u{1FA84}" }], version: 13 }, video_game: { id: "video_game", name: "Video Game", keywords: ["play", "console", "PS4", "controller"], skins: [{ unified: "1f3ae", native: "\u{1F3AE}" }], version: 1 }, joystick: { id: "joystick", name: "Joystick", keywords: ["game", "play"], skins: [{ unified: "1f579-fe0f", native: "\u{1F579}\uFE0F" }], version: 1 }, slot_machine: { id: "slot_machine", name: "Slot Machine", keywords: ["bet", "gamble", "vegas", "fruit", "luck", "casino"], skins: [{ unified: "1f3b0", native: "\u{1F3B0}" }], version: 1 }, game_die: { id: "game_die", name: "Game Die", keywords: ["dice", "random", "tabletop", "play", "luck"], skins: [{ unified: "1f3b2", native: "\u{1F3B2}" }], version: 1 }, jigsaw: { id: "jigsaw", name: "Puzzle Piece", keywords: ["jigsaw", "interlocking"], skins: [{ unified: "1f9e9", native: "\u{1F9E9}" }], version: 11 }, teddy_bear: { id: "teddy_bear", name: "Teddy Bear", keywords: ["plush", "stuffed"], skins: [{ unified: "1f9f8", native: "\u{1F9F8}" }], version: 11 }, pinata: { id: "pinata", name: "Pinata", keywords: ["mexico", "candy", "celebration"], skins: [{ unified: "1fa85", native: "\u{1FA85}" }], version: 13 }, mirror_ball: { id: "mirror_ball", name: "Mirror Ball", keywords: ["disco", "dance", "party"], skins: [{ unified: "1faa9", native: "\u{1FAA9}" }], version: 14 }, nesting_dolls: { id: "nesting_dolls", name: "Nesting Dolls", keywords: ["matryoshka", "toy"], skins: [{ unified: "1fa86", native: "\u{1FA86}" }], version: 13 }, spades: { id: "spades", name: "Spade Suit", keywords: ["spades", "poker", "cards", "suits", "magic"], skins: [{ unified: "2660-fe0f", native: "\u2660\uFE0F" }], version: 1 }, hearts: { id: "hearts", name: "Heart Suit", keywords: ["hearts", "poker", "cards", "magic", "suits"], skins: [{ unified: "2665-fe0f", native: "\u2665\uFE0F" }], version: 1 }, diamonds: { id: "diamonds", name: "Diamond Suit", keywords: ["diamonds", "poker", "cards", "magic", "suits"], skins: [{ unified: "2666-fe0f", native: "\u2666\uFE0F" }], version: 1 }, clubs: { id: "clubs", name: "Club Suit", keywords: ["clubs", "poker", "cards", "magic", "suits"], skins: [{ unified: "2663-fe0f", native: "\u2663\uFE0F" }], version: 1 }, chess_pawn: { id: "chess_pawn", name: "Chess Pawn", keywords: ["expendable"], skins: [{ unified: "265f-fe0f", native: "\u265F\uFE0F" }], version: 11 }, black_joker: { id: "black_joker", name: "Joker", keywords: ["black", "poker", "cards", "game", "play", "magic"], skins: [{ unified: "1f0cf", native: "\u{1F0CF}" }], version: 1 }, mahjong: { id: "mahjong", name: "Mahjong Red Dragon", keywords: ["game", "play", "chinese", "kanji"], skins: [{ unified: "1f004", native: "\u{1F004}" }], version: 1 }, flower_playing_cards: { id: "flower_playing_cards", name: "Flower Playing Cards", keywords: ["game", "sunset", "red"], skins: [{ unified: "1f3b4", native: "\u{1F3B4}" }], version: 1 }, performing_arts: { id: "performing_arts", name: "Performing Arts", keywords: ["acting", "theater", "drama"], skins: [{ unified: "1f3ad", native: "\u{1F3AD}" }], version: 1 }, frame_with_picture: { id: "frame_with_picture", name: "Framed Picture", keywords: ["frame", "with", "photography"], skins: [{ unified: "1f5bc-fe0f", native: "\u{1F5BC}\uFE0F" }], version: 1 }, art: { id: "art", name: "Artist Palette", keywords: ["art", "design", "paint", "draw", "colors"], skins: [{ unified: "1f3a8", native: "\u{1F3A8}" }], version: 1 }, thread: { id: "thread", name: "Thread", keywords: ["needle", "sewing", "spool", "string"], skins: [{ unified: "1f9f5", native: "\u{1F9F5}" }], version: 11 }, sewing_needle: { id: "sewing_needle", name: "Sewing Needle", keywords: ["stitches"], skins: [{ unified: "1faa1", native: "\u{1FAA1}" }], version: 13 }, yarn: { id: "yarn", name: "Yarn", keywords: ["ball", "crochet", "knit"], skins: [{ unified: "1f9f6", native: "\u{1F9F6}" }], version: 11 }, knot: { id: "knot", name: "Knot", keywords: ["rope", "scout"], skins: [{ unified: "1faa2", native: "\u{1FAA2}" }], version: 13 }, eyeglasses: { id: "eyeglasses", name: "Glasses", keywords: ["eyeglasses", "fashion", "accessories", "eyesight", "nerdy", "dork", "geek"], skins: [{ unified: "1f453", native: "\u{1F453}" }], version: 1 }, dark_sunglasses: { id: "dark_sunglasses", name: "Sunglasses", keywords: ["dark", "face", "co
51763ol", "accessories"], skins: [{ unified: "1f576-fe0f", native: "\u{1F576}\uFE0F" }], version: 1 }, goggles: { id: "goggles", name: "Goggles", keywords: ["eyes", "protection", "safety"], skins: [{ unified: "1f97d", native: "\u{1F97D}" }], version: 11 }, lab_coat: { id: "lab_coat", name: "Lab Coat", keywords: ["doctor", "experiment", "scientist", "chemist"], skins: [{ unified: "1f97c", native: "\u{1F97C}" }], version: 11 }, safety_vest: { id: "safety_vest", name: "Safety Vest", keywords: ["protection"], skins: [{ unified: "1f9ba", native: "\u{1F9BA}" }], version: 12 }, necktie: { id: "necktie", name: "Necktie", keywords: ["shirt", "suitup", "formal", "fashion", "cloth", "business"], skins: [{ unified: "1f454", native: "\u{1F454}" }], version: 1 }, shirt: { id: "shirt", name: "T-Shirt", keywords: ["shirt", "tshirt", "t", "fashion", "cloth", "casual", "tee"], skins: [{ unified: "1f455", native: "\u{1F455}" }], version: 1 }, jeans: { id: "jeans", name: "Jeans", keywords: ["fashion", "shopping"], skins: [{ unified: "1f456", native: "\u{1F456}" }], version: 1 }, scarf: { id: "scarf", name: "Scarf", keywords: ["neck", "winter", "clothes"], skins: [{ unified: "1f9e3", native: "\u{1F9E3}" }], version: 5 }, gloves: { id: "gloves", name: "Gloves", keywords: ["hands", "winter", "clothes"], skins: [{ unified: "1f9e4", native: "\u{1F9E4}" }], version: 5 }, coat: { id: "coat", name: "Coat", keywords: ["jacket"], skins: [{ unified: "1f9e5", native: "\u{1F9E5}" }], version: 5 }, socks: { id: "socks", name: "Socks", keywords: ["stockings", "clothes"], skins: [{ unified: "1f9e6", native: "\u{1F9E6}" }], version: 5 }, dress: { id: "dress", name: "Dress", keywords: ["clothes", "fashion", "shopping"], skins: [{ unified: "1f457", native: "\u{1F457}" }], version: 1 }, kimono: { id: "kimono", name: "Kimono", keywords: ["dress", "fashion", "women", "female", "japanese"], skins: [{ unified: "1f458", native: "\u{1F458}" }], version: 1 }, sari: { id: "sari", name: "Sari", keywords: ["dress"], skins: [{ unified: "1f97b", native: "\u{1F97B}" }], version: 12 }, "one-piece_swimsuit": { id: "one-piece_swimsuit", name: "One-Piece Swimsuit", keywords: ["one", "piece", "fashion"], skins: [{ unified: "1fa71", native: "\u{1FA71}" }], version: 12 }, briefs: { id: "briefs", name: "Briefs", keywords: ["clothing"], skins: [{ unified: "1fa72", native: "\u{1FA72}" }], version: 12 }, shorts: { id: "shorts", name: "Shorts", keywords: ["clothing"], skins: [{ unified: "1fa73", native: "\u{1FA73}" }], version: 12 }, bikini: { id: "bikini", name: "Bikini", keywords: ["swimming", "female", "woman", "girl", "fashion", "beach", "summer"], skins: [{ unified: "1f459", native: "\u{1F459}" }], version: 1 }, womans_clothes: { id: "womans_clothes", name: "Womans Clothes", keywords: ["woman", "s", "fashion", "shopping", "bags", "female"], skins: [{ unified: "1f45a", native: "\u{1F45A}" }], version: 1 }, folding_hand_fan: { id: "folding_hand_fan", name: "Folding Hand Fan", keywords: ["flamenco", "hot"], skins: [{ unified: "1faad", native: "\u{1FAAD}" }], version: 15 }, purse: { id: "purse", name: "Purse", keywords: ["fashion", "accessories", "money", "sales", "shopping"], skins: [{ unified: "1f45b", native: "\u{1F45B}" }], version: 1 }, handbag: { id: "handbag", name: "Handbag", keywords: ["fashion", "accessory", "accessories", "shopping"], skins: [{ unified: "1f45c", native: "\u{1F45C}" }], version: 1 }, pouch: { id: "pouch", name: "Pouch", keywords: ["clutch", "bag", "accessories", "shopping"], skins: [{ unified: "1f45d", native: "\u{1F45D}" }], version: 1 }, shopping_bags: { id: "shopping_bags", name: "Shopping Bags", keywords: ["mall", "buy", "purchase"], skins: [{ unified: "1f6cd-fe0f", native: "\u{1F6CD}\uFE0F" }], version: 1 }, school_satchel: { id: "school_satchel", name: "Backpack", keywords: ["school", "satchel", "student", "education", "bag"], skins: [{ unified: "1f392", native: "\u{1F392}" }], version: 1 }, thong_sandal: { id: "thong_sandal", name: "Thong Sandal", keywords: ["footwear", "summer"], skins: [{ unified: "1fa74", native: "\u{1FA74}" }], version: 13 }, mans_shoe: { id: "mans_shoe", name: "Mans Shoe", keywords: ["man", "s", "fashion", "male"], skins: [{ unified: "1f45e", native: "\u{1F45E}" }], version: 1 }, athletic_shoe: { id: "athletic_shoe", name: "Running Shoe", keywords: ["athletic", "shoes", "sports", "sneakers"], skins: [{ unified: "1f45f", native: "\u{1F45F}" }], version: 1 }, hiking_boot: { id: "hiking_boot", name: "Hiking Boot", keywords: ["backpacking", "camping"], skins: [{ unified: "1f97e", native: "\u{1F97E}" }], version: 11 }, womans_flat_shoe: { id: "womans_flat_shoe", name: "Flat Shoe", keywords: ["womans", "ballet", "slip", "on", "slipper"], skins: [{ unified: "1f97f", native: "\u{1F97F}" }], version: 11 }, high_heel: { id: "high_heel", name: "High-Heeled Shoe", keywords: ["high", "heel", "heeled", "fashion", "shoes", "female", "pumps", "stiletto"], skins: [{ unified: "1f460", native: "\u{1F460}" }], version: 1 }, sandal: { id: "sandal", name: "Womans Sandal", keywords: ["woman", "s", "shoes", "fashion", "flip", "flops"], skins: [{ unified: "1f461", native: "\u{1F461}" }], version: 1 }, ballet_shoes: { id: "ballet_shoes", name: "Ballet Shoes", keywords: ["dance"], skins: [{ unified: "1fa70", native: "\u{1FA70}" }], version: 12 }, boot: { id: "boot", name: "Womans Boots", keywords: ["boot", "woman", "s", "shoes", "fashion"], skins: [{ unified: "1f462", native: "\u{1F462}" }], version: 1 }, hair_pick: { id: "hair_pick", name: "Hair Pick", keywords: ["afro", "comb"], skins: [{ unified: "1faae", native: "\u{1FAAE}" }], version: 15 }, crown: { id: "crown", name: "Crown", keywords: ["king", "kod", "leader", "royalty", "lord"], skins: [{ unified: "1f451", native: "\u{1F451}" }], version: 1 }, womans_hat: { id: "womans_hat", name: "Womans Hat", keywords: ["woman", "s", "fashion", "accessories", "female", "lady", "spring"], skins: [{ unified: "1f452", native: "\u{1F452}" }], version: 1 }, tophat: { id: "tophat", name: "Top Hat", keywords: ["tophat", "magic", "gentleman", "classy", "cir
51763cus"], skins: [{ unified: "1f3a9", native: "\u{1F3A9}" }], version: 1 }, mortar_board: { id: "mortar_board", name: "Graduation Cap", keywords: ["mortar", "board", "school", "college", "degree", "university", "hat", "legal", "learn", "education"], skins: [{ unified: "1f393", native: "\u{1F393}" }], version: 1 }, billed_cap: { id: "billed_cap", name: "Billed Cap", keywords: ["baseball"], skins: [{ unified: "1f9e2", native: "\u{1F9E2}" }], version: 5 }, military_helmet: { id: "military_helmet", name: "Military Helmet", keywords: ["army", "protection"], skins: [{ unified: "1fa96", native: "\u{1FA96}" }], version: 13 }, helmet_with_white_cross: { id: "helmet_with_white_cross", name: "Rescue Worker\u2019s Helmet", keywords: ["with", "white", "cross", "worker", "s", "construction", "build"], skins: [{ unified: "26d1-fe0f", native: "\u26D1\uFE0F" }], version: 1 }, prayer_beads: { id: "prayer_beads", name: "Prayer Beads", keywords: ["dhikr", "religious"], skins: [{ unified: "1f4ff", native: "\u{1F4FF}" }], version: 1 }, lipstick: { id: "lipstick", name: "Lipstick", keywords: ["female", "girl", "fashion", "woman"], skins: [{ unified: "1f484", native: "\u{1F484}" }], version: 1 }, ring: { id: "ring", name: "Ring", keywords: ["wedding", "propose", "marriage", "valentines", "diamond", "fashion", "jewelry", "gem", "engagement"], skins: [{ unified: "1f48d", native: "\u{1F48D}" }], version: 1 }, gem: { id: "gem", name: "Gem Stone", keywords: ["blue", "ruby", "diamond", "jewelry"], skins: [{ unified: "1f48e", native: "\u{1F48E}" }], version: 1 }, mute: { id: "mute", name: "Muted Speaker", keywords: ["mute", "sound", "volume", "silence", "quiet"], skins: [{ unified: "1f507", native: "\u{1F507}" }], version: 1 }, speaker: { id: "speaker", name: "Speaker", keywords: ["low", "volume", "sound", "silence", "broadcast"], skins: [{ unified: "1f508", native: "\u{1F508}" }], version: 1 }, sound: { id: "sound", name: "Speaker Medium Volume", keywords: ["sound", "broadcast"], skins: [{ unified: "1f509", native: "\u{1F509}" }], version: 1 }, loud_sound: { id: "loud_sound", name: "Speaker High Volume", keywords: ["loud", "sound", "noise", "noisy", "broadcast"], skins: [{ unified: "1f50a", native: "\u{1F50A}" }], version: 1 }, loudspeaker: { id: "loudspeaker", name: "Loudspeaker", keywords: ["volume", "sound"], skins: [{ unified: "1f4e2", native: "\u{1F4E2}" }], version: 1 }, mega: { id: "mega", name: "Megaphone", keywords: ["mega", "sound", "speaker", "volume"], skins: [{ unified: "1f4e3", native: "\u{1F4E3}" }], version: 1 }, postal_horn: { id: "postal_horn", name: "Postal Horn", keywords: ["instrument", "music"], skins: [{ unified: "1f4ef", native: "\u{1F4EF}" }], version: 1 }, bell: { id: "bell", name: "Bell", keywords: ["sound", "notification", "christmas", "xmas", "chime"], skins: [{ unified: "1f514", native: "\u{1F514}" }], version: 1 }, no_bell: { id: "no_bell", name: "Bell with Slash", keywords: ["no", "sound", "volume", "mute", "quiet", "silent"], skins: [{ unified: "1f515", native: "\u{1F515}" }], version: 1 }, musical_score: { id: "musical_score", name: "Musical Score", keywords: ["treble", "clef", "compose"], skins: [{ unified: "1f3bc", native: "\u{1F3BC}" }], version: 1 }, musical_note: { id: "musical_note", name: "Musical Note", keywords: ["score", "tone", "sound"], skins: [{ unified: "1f3b5", native: "\u{1F3B5}" }], version: 1 }, notes: { id: "notes", name: "Musical Notes", keywords: ["music", "score"], skins: [{ unified: "1f3b6", native: "\u{1F3B6}" }], version: 1 }, studio_microphone: { id: "studio_microphone", name: "Studio Microphone", keywords: ["sing", "recording", "artist", "talkshow"], skins: [{ unified: "1f399-fe0f", native: "\u{1F399}\uFE0F" }], version: 1 }, level_slider: { id: "level_slider", name: "Level Slider", keywords: ["scale"], skins: [{ unified: "1f39a-fe0f", native: "\u{1F39A}\uFE0F" }], version: 1 }, control_knobs: { id: "control_knobs", name: "Control Knobs", keywords: ["dial"], skins: [{ unified: "1f39b-fe0f", native: "\u{1F39B}\uFE0F" }], version: 1 }, microphone: { id: "microphone", name: "Microphone", keywords: ["sound", "music", "PA", "sing", "talkshow"], skins: [{ unified: "1f3a4", native: "\u{1F3A4}" }], version: 1 }, headphones: { id: "headphones", name: "Headphone", keywords: ["headphones", "music", "score", "gadgets"], skins: [{ unified: "1f3a7", native: "\u{1F3A7}" }], version: 1 }, radio: { id: "radio", name: "Radio", keywords: ["communication", "music", "podcast", "program"], skins: [{ unified: "1f4fb", native: "\u{1F4FB}" }], version: 1 }, saxophone: { id: "saxophone", name: "Saxophone", keywords: ["music", "instrument", "jazz", "blues"], skins: [{ unified: "1f3b7", native: "\u{1F3B7}" }], version: 1 }, accordion: { id: "accordion", name: "Accordion", keywords: ["music"], skins: [{ unified: "1fa97", native: "\u{1FA97}" }], version: 13 }, guitar: { id: "guitar", name: "Guitar", keywords: ["music", "instrument"], skins: [{ unified: "1f3b8", native: "\u{1F3B8}" }], version: 1 }, musical_keyboard: { id: "musical_keyboard", name: "Musical Keyboard", keywords: ["piano", "instrument", "compose"], skins: [{ unified: "1f3b9", native: "\u{1F3B9}" }], version: 1 }, trumpet: { id: "trumpet", name: "Trumpet", keywords: ["music", "brass"], skins: [{ unified: "1f3ba", native: "\u{1F3BA}" }], version: 1 }, violin: { id: "violin", name: "Violin", keywords: ["music", "instrument", "orchestra", "symphony"], skins: [{ unified: "1f3bb", native: "\u{1F3BB}" }], version: 1 }, banjo: { id: "banjo", name: "Banjo", keywords: ["music", "instructment"], skins: [{ unified: "1fa95", native: "\u{1FA95}" }], version: 12 }, drum_with_drumsticks: { id: "drum_with_drumsticks", name: "Drum", keywords: ["with", "drumsticks", "music", "instrument", "snare"], skins: [{ unified: "1f941", native: "\u{1F941}" }], version: 3 }, long_drum: { id: "long_drum", name: "Long Drum", keywords: ["music"], skins: [{ unified: "1fa98", native: "\u{1FA98}" }], version: 13 }, maracas: { id: "maracas", name: "Maracas", keywords: ["music", "instrument", "percussion"], skins: [{ unified: "1fa87", native: "\u{1FA87}" }], version: 15 }, flute: { id: "flute", name: "Flute", keywords: ["bamboo", "music", "instrument", "pied", "piper"], skins: [{ unified: "1fa88", native: "\u{1FA88}" }
51763], version: 15 }, harp: { id: "harp", name: "Harp", keywords: [], skins: [{ unified: "1fa89", native: "\u{1FA89}" }], version: 16 }, iphone: { id: "iphone", name: "Mobile Phone", keywords: ["iphone", "technology", "apple", "gadgets", "dial"], skins: [{ unified: "1f4f1", native: "\u{1F4F1}" }], version: 1 }, calling: { id: "calling", name: "Mobile Phone with Arrow", keywords: ["calling", "iphone", "incoming"], skins: [{ unified: "1f4f2", native: "\u{1F4F2}" }], version: 1 }, phone: { id: "phone", name: "Telephone", keywords: ["phone", "technology", "communication", "dial"], skins: [{ unified: "260e-fe0f", native: "\u260E\uFE0F" }], version: 1 }, telephone_receiver: { id: "telephone_receiver", name: "Telephone Receiver", keywords: ["technology", "communication", "dial"], skins: [{ unified: "1f4de", native: "\u{1F4DE}" }], version: 1 }, pager: { id: "pager", name: "Pager", keywords: ["bbcall", "oldschool", "90s"], skins: [{ unified: "1f4df", native: "\u{1F4DF}" }], version: 1 }, fax: { id: "fax", name: "Fax Machine", keywords: ["communication", "technology"], skins: [{ unified: "1f4e0", native: "\u{1F4E0}" }], version: 1 }, battery: { id: "battery", name: "Battery", keywords: ["power", "energy", "sustain"], skins: [{ unified: "1f50b", native: "\u{1F50B}" }], version: 1 }, low_battery: { id: "low_battery", name: "Low Battery", keywords: ["drained", "dead"], skins: [{ unified: "1faab", native: "\u{1FAAB}" }], version: 14 }, electric_plug: { id: "electric_plug", name: "Electric Plug", keywords: ["charger", "power"], skins: [{ unified: "1f50c", native: "\u{1F50C}" }], version: 1 }, computer: { id: "computer", name: "Laptop", keywords: ["computer", "technology", "screen", "display", "monitor"], skins: [{ unified: "1f4bb", native: "\u{1F4BB}" }], version: 1 }, desktop_computer: { id: "desktop_computer", name: "Desktop Computer", keywords: ["technology", "computing", "screen"], skins: [{ unified: "1f5a5-fe0f", native: "\u{1F5A5}\uFE0F" }], version: 1 }, printer: { id: "printer", name: "Printer", keywords: ["paper", "ink"], skins: [{ unified: "1f5a8-fe0f", native: "\u{1F5A8}\uFE0F" }], version: 1 }, keyboard: { id: "keyboard", name: "Keyboard", keywords: ["technology", "computer", "type", "input", "text"], skins: [{ unified: "2328-fe0f", native: "\u2328\uFE0F" }], version: 1 }, three_button_mouse: { id: "three_button_mouse", name: "Computer Mouse", keywords: ["three", "button", "click"], skins: [{ unified: "1f5b1-fe0f", native: "\u{1F5B1}\uFE0F" }], version: 1 }, trackball: { id: "trackball", name: "Trackball", keywords: ["technology", "trackpad"], skins: [{ unified: "1f5b2-fe0f", native: "\u{1F5B2}\uFE0F" }], version: 1 }, minidisc: { id: "minidisc", name: "Minidisc", keywords: ["computer", "disk", "technology", "record", "data", "90s"], skins: [{ unified: "1f4bd", native: "\u{1F4BD}" }], version: 1 }, floppy_disk: { id: "floppy_disk", name: "Floppy Disk", keywords: ["oldschool", "technology", "save", "90s", "80s"], skins: [{ unified: "1f4be", native: "\u{1F4BE}" }], version: 1 }, cd: { id: "cd", name: "Optical Disc", keywords: ["cd", "disk", "technology", "dvd", "90s"], skins: [{ unified: "1f4bf", native: "\u{1F4BF}" }], version: 1 }, dvd: { id: "dvd", name: "Dvd", keywords: ["cd", "disk", "disc"], skins: [{ unified: "1f4c0", native: "\u{1F4C0}" }], version: 1 }, abacus: { id: "abacus", name: "Abacus", keywords: ["calculation"], skins: [{ unified: "1f9ee", native: "\u{1F9EE}" }], version: 11 }, movie_camera: { id: "movie_camera", name: "Movie Camera", keywords: ["film", "record"], skins: [{ unified: "1f3a5", native: "\u{1F3A5}" }], version: 1 }, film_frames: { id: "film_frames", name: "Film Frames", keywords: ["movie"], skins: [{ unified: "1f39e-fe0f", native: "\u{1F39E}\uFE0F" }], version: 1 }, film_projector: { id: "film_projector", name: "Film Projector", keywords: ["video", "tape", "record", "movie"], skins: [{ unified: "1f4fd-fe0f", native: "\u{1F4FD}\uFE0F" }], version: 1 }, clapper: { id: "clapper", name: "Clapper Board", keywords: ["movie", "film", "record"], skins: [{ unified: "1f3ac", native: "\u{1F3AC}" }], version: 1 }, tv: { id: "tv", name: "Television", keywords: ["tv", "technology", "program", "oldschool", "show"], skins: [{ unified: "1f4fa", native: "\u{1F4FA}" }], version: 1 }, camera: { id: "camera", name: "Camera", keywords: ["gadgets", "photography"], skins: [{ unified: "1f4f7", native: "\u{1F4F7}" }], version: 1 }, camera_with_flash: { id: "camera_with_flash", name: "Camera with Flash", keywords: ["photography", "gadgets"], skins: [{ unified: "1f4f8", native: "\u{1F4F8}" }], version: 1 }, video_camera: { id: "video_camera", name: "Video Camera", keywords: ["film", "record"], skins: [{ unified: "1f4f9", native: "\u{1F4F9}" }], version: 1 }, vhs: { id: "vhs", name: "Videocassette", keywords: ["vhs", "record", "video", "oldschool", "90s", "80s"], skins: [{ unified: "1f4fc", native: "\u{1F4FC}" }], version: 1 }, mag: { id: "mag", name: "Magnifying Glass Tilted Left", keywords: ["mag", "search", "zoom", "find", "detective"], skins: [{ unified: "1f50d", native: "\u{1F50D}" }], version: 1 }, mag_right: { id: "mag_right", name: "Magnifying Glass Tilted Right", keywords: ["mag", "search", "zoom", "find", "detective"], skins: [{ unified: "1f50e", native: "\u{1F50E}" }], version: 1 }, candle: { id: "candle", name: "Candle", keywords: ["fire", "wax"], skins: [{ unified: "1f56f-fe0f", native: "\u{1F56F}\uFE0F" }], version: 1 }, bulb: { id: "bulb", name: "Light Bulb", keywords: ["electricity", "idea"], skins: [{ unified: "1f4a1", native: "\u{1F4A1}" }], version: 1 }, flashlight: { id: "flashlight", name: "Flashlight", keywords: ["dark", "camping", "sight", "night"], skins: [{ unified: "1f526", native: "\u{1F526}" }], version: 1 }, izakaya_lantern: { id: "izakaya_lantern", name: "Izakaya Lantern", keywords: ["red", "paper", "light", "halloween", "spooky"], skins: [{ unified: "1f3ee", native: "\u{1F3EE}" }], version: 1 }, diya_lamp: { id: "diya_lamp", name: "Diya Lamp", keywords: ["lighting"], skins: [{ unified: "1fa94", native: "\u{1FA94}" }], version: 12 }, notebook_with_decorative_cover: { id: "notebook_with_decorative_cover", name: "Notebook with Decorative 
51763Cover", keywords: ["classroom", "notes", "record", "paper", "study"], skins: [{ unified: "1f4d4", native: "\u{1F4D4}" }], version: 1 }, closed_book: { id: "closed_book", name: "Closed Book", keywords: ["read", "library", "knowledge", "textbook", "learn"], skins: [{ unified: "1f4d5", native: "\u{1F4D5}" }], version: 1 }, book: { id: "book", name: "Open Book", keywords: ["read", "library", "knowledge", "literature", "learn", "study"], skins: [{ unified: "1f4d6", native: "\u{1F4D6}" }], version: 1 }, green_book: { id: "green_book", name: "Green Book", keywords: ["read", "library", "knowledge", "study"], skins: [{ unified: "1f4d7", native: "\u{1F4D7}" }], version: 1 }, blue_book: { id: "blue_book", name: "Blue Book", keywords: ["read", "library", "knowledge", "learn", "study"], skins: [{ unified: "1f4d8", native: "\u{1F4D8}" }], version: 1 }, orange_book: { id: "orange_book", name: "Orange Book", keywords: ["read", "library", "knowledge", "textbook", "study"], skins: [{ unified: "1f4d9", native: "\u{1F4D9}" }], version: 1 }, books: { id: "books", name: "Books", keywords: ["literature", "library", "study"], skins: [{ unified: "1f4da", native: "\u{1F4DA}" }], version: 1 }, notebook: { id: "notebook", name: "Notebook", keywords: ["stationery", "record", "notes", "paper", "study"], skins: [{ unified: "1f4d3", native: "\u{1F4D3}" }], version: 1 }, ledger: { id: "ledger", name: "Ledger", keywords: ["notes", "paper"], skins: [{ unified: "1f4d2", native: "\u{1F4D2}" }], version: 1 }, page_with_curl: { id: "page_with_curl", name: "Page with Curl", keywords: ["documents", "office", "paper"], skins: [{ unified: "1f4c3", native: "\u{1F4C3}" }], version: 1 }, scroll: { id: "scroll", name: "Scroll", keywords: ["documents", "ancient", "history", "paper"], skins: [{ unified: "1f4dc", native: "\u{1F4DC}" }], version: 1 }, page_facing_up: { id: "page_facing_up", name: "Page Facing Up", keywords: ["documents", "office", "paper", "information"], skins: [{ unified: "1f4c4", native: "\u{1F4C4}" }], version: 1 }, newspaper: { id: "newspaper", name: "Newspaper", keywords: ["press", "headline"], skins: [{ unified: "1f4f0", native: "\u{1F4F0}" }], version: 1 }, rolled_up_newspaper: { id: "rolled_up_newspaper", name: "Rolled-Up Newspaper", keywords: ["rolled", "up", "press", "headline"], skins: [{ unified: "1f5de-fe0f", native: "\u{1F5DE}\uFE0F" }], version: 1 }, bookmark_tabs: { id: "bookmark_tabs", name: "Bookmark Tabs", keywords: ["favorite", "save", "order", "tidy"], skins: [{ unified: "1f4d1", native: "\u{1F4D1}" }], version: 1 }, bookmark: { id: "bookmark", name: "Bookmark", keywords: ["favorite", "label", "save"], skins: [{ unified: "1f516", native: "\u{1F516}" }], version: 1 }, label: { id: "label", name: "Label", keywords: ["sale", "tag"], skins: [{ unified: "1f3f7-fe0f", native: "\u{1F3F7}\uFE0F" }], version: 1 }, moneybag: { id: "moneybag", name: "Money Bag", keywords: ["moneybag", "dollar", "payment", "coins", "sale"], skins: [{ unified: "1f4b0", native: "\u{1F4B0}" }], version: 1 }, coin: { id: "coin", name: "Coin", keywords: ["money", "currency"], skins: [{ unified: "1fa99", native: "\u{1FA99}" }], version: 13 }, yen: { id: "yen", name: "Yen Banknote", keywords: ["money", "sales", "japanese", "dollar", "currency"], skins: [{ unified: "1f4b4", native: "\u{1F4B4}" }], version: 1 }, dollar: { id: "dollar", name: "Dollar Banknote", keywords: ["money", "sales", "bill", "currency"], skins: [{ unified: "1f4b5", native: "\u{1F4B5}" }], version: 1 }, euro: { id: "euro", name: "Euro Banknote", keywords: ["money", "sales", "dollar", "currency"], skins: [{ unified: "1f4b6", native: "\u{1F4B6}" }], version: 1 }, pound: { id: "pound", name: "Pound Banknote", keywords: ["british", "sterling", "money", "sales", "bills", "uk", "england", "currency"], skins: [{ unified: "1f4b7", native: "\u{1F4B7}" }], version: 1 }, money_with_wings: { id: "money_with_wings", name: "Money with Wings", keywords: ["dollar", "bills", "payment", "sale"], skins: [{ unified: "1f4b8", native: "\u{1F4B8}" }], version: 1 }, credit_card: { id: "credit_card", name: "Credit Card", keywords: ["money", "sales", "dollar", "bill", "payment", "shopping"], skins: [{ unified: "1f4b3", native: "\u{1F4B3}" }], version: 1 }, receipt: { id: "receipt", name: "Receipt", keywords: ["accounting", "expenses"], skins: [{ unified: "1f9fe", native: "\u{1F9FE}" }], version: 11 }, chart: { id: "chart", name: "Chart Increasing with Yen", keywords: ["green", "square", "graph", "presentation", "stats"], skins: [{ unified: "1f4b9", native: "\u{1F4B9}" }], version: 1 }, email: { id: "email", name: "Envelope", keywords: ["email", "letter", "postal", "inbox", "communication"], skins: [{ unified: "2709-fe0f", native: "\u2709\uFE0F" }], version: 1 }, "e-mail": { id: "e-mail", name: "E-Mail", keywords: ["e", "mail", "communication", "inbox"], skins: [{ unified: "1f4e7", native: "\u{1F4E7}" }], version: 1 }, incoming_envelope: { id: "incoming_envelope", name: "Incoming Envelope", keywords: ["email", "inbox"], skins: [{ unified: "1f4e8", native: "\u{1F4E8}" }], version: 1 }, envelope_with_arrow: { id: "envelope_with_arrow", name: "Envelope with Arrow", keywords: ["email", "communication"], skins: [{ unified: "1f4e9", native: "\u{1F4E9}" }], version: 1 }, outbox_tray: { id: "outbox_tray", name: "Outbox Tray", keywords: ["inbox", "email"], skins: [{ unified: "1f4e4", native: "\u{1F4E4}" }], version: 1 }, inbox_tray: { id: "inbox_tray", name: "Inbox Tray", keywords: ["email", "documents"], skins: [{ unified: "1f4e5", native: "\u{1F4E5}" }], version: 1 }, package: { id: "package", name: "Package", keywords: ["mail", "gift", "cardboard", "box", "moving"], skins: [{ unified: "1f4e6", native: "\u{1F4E6}" }], version: 1 }, mailbox: { id: "mailbox", name: "Closed Mailbox with Raised Flag", keywords: ["email", "inbox", "communication"], skins: [{ unified: "1f4eb", native: "\u{1F4EB}" }], version: 1 }, mailbox_closed: { id: "mailbox_closed", name: "Closed Mailbox with Lowered Flag", keywords: ["email", "communication", "inbox"], skins: [{ unified: "1f4ea", native: "\u{1F4EA}" }], version: 1 }, mailbox_with_mail: { id: "mailbox_with_mail", name: "Open Mailbox with Raised Flag", keywords: ["mail", "email", "inbox", "communication"], skins: [{ unified: "1f4ec", native: "\u{1F4EC}" }], version: 1 }, mailbox_with_no_mail: { id: "mailbox_with_no_mail", name: "Open Mailbox with Lowered Flag", keywords: ["no", "mail", "email", "inbox"], skins: [{ unified: "1f4ed", native: "\u{1F4ED}" }], version: 1 }, postbox: { id: "postbox", name: "Postbox", keywords: ["email", "letter", "envelope"], skins: [{ unified: "1f4ee", native: "\u{1F4EE}" }], version: 1 }, ballot_box_with_ballot: { id: "ballot_box_with_ballot", name: "Ballot Box with Ballot", keywords: ["election", "vote"], skins: [{ unified: "1f5f3-fe0f", native: "\u{1F5F3}\uFE0F" }], version: 1 }, pencil2: { id: "pencil2", name: "Pencil", keywords: ["pencil2", "stationery", "write", "paper", "writing", "school", "study"], skins: [{ unified: "270f-fe0f", native: "\u270F\uFE0F" }], version: 1 }, black_nib: { id: "black_nib", name: "Black Nib", keywords: ["pen", "stationery", "writing", "write"], skins: [{ unified: "2712-fe0f", native: "\u2712\uFE0F" }], version: 1 }, lower_left_fountain_pen: { id: "lower_left_fountain_pen", name: "Fountain Pen", keywords: ["lower", "left", "stationery", "writing", "write"], skins: [{ unified: "1f58b-fe0f", native: "\u{1F58B}\uFE0F" }], version: 1 }, lower_left_ballpoint_pen: { id: "lower_left_ballpoint_pen", name: "Pen", keywords: ["lower", "left", "ballpoint", "stationery", "writing", "write"], skins: [{ unified: "1f58a-fe0f", native: "\u{1F58A}\uFE0F" }], version: 1 }, lower_left_paintbrush: { id: "lower_left_paintbrush", name: "Paintbrush", keywords: ["lower", "left", "drawing", "creativity", "art"], skins: [{ unified: "1f58c-fe0f", native: "\u{1F58C}\uFE0F" }], version: 1 }, lower_left_crayon: { id: "lower_left_crayon", name: "Crayon", keywords: ["lower", "left", "drawing", "creativity"], skins: [{ unified: "1f58d-fe0f", native: "\u{1F58D}\uFE0F" }], version: 1 }, memo: { id: "memo", name: "Memo", keywords: ["pencil", "write", "documents", "stationery", "paper", "writing", "legal", "exam", "quiz", "test", "study", "compose"], skins: [{ unified: "1f4dd", native: "\u{1F4DD}" }], version: 1 }, briefcase: { id: "briefcase", name: "Briefcase", keywords: ["business", "documents", "work", "law", "legal", "job", "career"], skins: [{ unified: "1f4bc", native: "\u{1F4BC}" }], version: 1 }, file_folder: { id: "file_folder", name: "File Folder", keywords: ["documents", "business", "office"], skins: [{ unified: "1f4c1", native: "\u{1F4C1}" }], version: 1 }, open_file_folder: { id: "open_file_folder", name: "Open File Folder", keywords: ["documents", "load"], skins: [{ unified: "1f4c2", native: "\u{1F4C2}" }], version: 1 }, card_index_dividers: { id: "card_index_dividers", name: "Card Index Divi
51763ders", keywords: ["organizing", "business", "stationery"], skins: [{ unified: "1f5c2-fe0f", native: "\u{1F5C2}\uFE0F" }], version: 1 }, date: { id: "date", name: "Calendar", keywords: ["date", "schedule"], skins: [{ unified: "1f4c5", native: "\u{1F4C5}" }], version: 1 }, calendar: { id: "calendar", name: "Tear-off Calendar", keywords: ["tear", "off", "schedule", "date", "planning"], skins: [{ unified: "1f4c6", native: "\u{1F4C6}" }], version: 1 }, spiral_note_pad: { id: "spiral_note_pad", name: "Spiral Notepad", keywords: ["note", "pad", "memo", "stationery"], skins: [{ unified: "1f5d2-fe0f", native: "\u{1F5D2}\uFE0F" }], version: 1 }, spiral_calendar_pad: { id: "spiral_calendar_pad", name: "Spiral Calendar", keywords: ["pad", "date", "schedule", "planning"], skins: [{ unified: "1f5d3-fe0f", native: "\u{1F5D3}\uFE0F" }], version: 1 }, card_index: { id: "card_index", name: "Card Index", keywords: ["business", "stationery"], skins: [{ unified: "1f4c7", native: "\u{1F4C7}" }], version: 1 }, chart_with_upwards_trend: { id: "chart_with_upwards_trend", name: "Chart Increasing", keywords: ["with", "upwards", "trend", "graph", "presentation", "stats", "recovery", "business", "economics", "money", "sales", "good", "success"], skins: [{ unified: "1f4c8", native: "\u{1F4C8}" }], version: 1 }, chart_with_downwards_trend: { id: "chart_with_downwards_trend", name: "Chart Decreasing", keywords: ["with", "downwards", "trend", "graph", "presentation", "stats", "recession", "business", "economics", "money", "sales", "bad", "failure"], skins: [{ unified: "1f4c9", native: "\u{1F4C9}" }], version: 1 }, bar_chart: { id: "bar_chart", name: "Bar Chart", keywords: ["graph", "presentation", "stats"], skins: [{ unified: "1f4ca", native: "\u{1F4CA}" }], version: 1 }, clipboard: { id: "clipboard", name: "Clipboard", keywords: ["stationery", "documents"], skins: [{ unified: "1f4cb", native: "\u{1F4CB}" }], version: 1 }, pushpin: { id: "pushpin", name: "Pushpin", keywords: ["stationery", "mark", "here"], skins: [{ unified: "1f4cc", native: "\u{1F4CC}" }], version: 1 }, round_pushpin: { id: "round_pushpin", name: "Round Pushpin", keywords: ["stationery", "location", "map", "here"], skins: [{ unified: "1f4cd", native: "\u{1F4CD}" }], version: 1 }, paperclip: { id: "paperclip", name: "Paperclip", keywords: ["documents", "stationery"], skins: [{ unified: "1f4ce", native: "\u{1F4CE}" }], version: 1 }, linked_paperclips: { id: "linked_paperclips", name: "Linked Paperclips", keywords: ["documents", "stationery"], skins: [{ unified: "1f587-fe0f", native: "\u{1F587}\uFE0F" }], version: 1 }, straight_ruler: { id: "straight_ruler", name: "Straight Ruler", keywords: ["stationery", "calculate", "length", "math", "school", "drawing", "architect", "sketch"], skins: [{ unified: "1f4cf", native: "\u{1F4CF}" }], version: 1 }, triangular_ruler: { id: "triangular_ruler", name: "Triangular Ruler", keywords: ["stationery", "math", "architect", "sketch"], skins: [{ unified: "1f4d0", native: "\u{1F4D0}" }], version: 1 }, scissors: { id: "scissors", name: "Scissors", keywords: ["stationery", "cut"], skins: [{ unified: "2702-fe0f", native: "\u2702\uFE0F" }], version: 1 }, card_file_box: { id: "card_file_box", name: "Card File Box", keywords: ["business", "stationery"], skins: [{ unified: "1f5c3-fe0f", native: "\u{1F5C3}\uFE0F" }], version: 1 }, file_cabinet: { id: "file_cabinet", name: "File Cabinet", keywords: ["filing", "organizing"], skins: [{ unified: "1f5c4-fe0f", native: "\u{1F5C4}\uFE0F" }], version: 1 }, wastebasket: { id: "wastebasket", name: "Wastebasket", keywords: ["bin", "trash", "rubbish", "garbage", "toss"], skins: [{ unified: "1f5d1-fe0f", native: "\u{1F5D1}\uFE0F" }], version: 1 }, lock: { id: "lock", name: "Lock", keywords: ["locked", "security", "password", "padlock"], skins: [{ unified: "1f512", native: "\u{1F512}" }], version: 1 }, unlock: { id: "unlock", name: "Unlocked", keywords: ["unlock", "privacy", "security"], skins: [{ unified: "1f513", native: "\u{1F513}" }], version: 1 }, lock_with_ink_pen: { id: "lock_with_ink_pen", name: "Locked with Pen", keywords: ["lock", "ink", "security", "secret"], skins: [{ unified: "1f50f", native: "\u{1F50F}" }], version: 1 }, closed_lock_with_key: { id: "closed_lock_with_key", name: "Locked with Key", keywords: ["closed", "lock", "security", "privacy"], skins: [{ unified: "1f510", native: "\u{1F510}" }], version: 1 }, key: { id: "key", name: "Key", keywords: ["lock", "door", "password"], skins: [{ unified: "1f511", native: "\u{1F511}" }], version: 1 }, old_key: { id: "old_key", name: "Old Key", keywords: ["lock", "door", "password"], skins: [{ unified: "1f5dd-fe0f", native: "\u{1F5DD}\uFE0F" }], version: 1 }, hammer: { id: "hammer", name: "Hammer", keywords: ["tools", "build", "create"], skins: [{ unified: "1f528", native: "\u{1F528}" }
51763], version: 1 }, axe: { id: "axe", name: "Axe", keywords: ["tool", "chop", "cut"], skins: [{ unified: "1fa93", native: "\u{1FA93}" }], version: 12 }, pick: { id: "pick", name: "Pick", keywords: ["tools", "dig"], skins: [{ unified: "26cf-fe0f", native: "\u26CF\uFE0F" }], version: 1 }, hammer_and_pick: { id: "hammer_and_pick", name: "Hammer and Pick", keywords: ["tools", "build", "create"], skins: [{ unified: "2692-fe0f", native: "\u2692\uFE0F" }], version: 1 }, hammer_and_wrench: { id: "hammer_and_wrench", name: "Hammer and Wrench", keywords: ["tools", "build", "create"], skins: [{ unified: "1f6e0-fe0f", native: "\u{1F6E0}\uFE0F" }], version: 1 }, dagger_knife: { id: "dagger_knife", name: "Dagger", keywords: ["knife", "weapon"], skins: [{ unified: "1f5e1-fe0f", native: "\u{1F5E1}\uFE0F" }], version: 1 }, crossed_swords: { id: "crossed_swords", name: "Crossed Swords", keywords: ["weapon"], skins: [{ unified: "2694-fe0f", native: "\u2694\uFE0F" }], version: 1 }, bomb: { id: "bomb", name: "Bomb", keywords: ["boom", "explode", "explosion", "terrorism"], skins: [{ unified: "1f4a3", native: "\u{1F4A3}" }], version: 1 }, boomerang: { id: "boomerang", name: "Boomerang", keywords: ["weapon"], skins: [{ unified: "1fa83", native: "\u{1FA83}" }], version: 13 }, bow_and_arrow: { id: "bow_and_arrow", name: "Bow and Arrow", keywords: ["sports"], skins: [{ unified: "1f3f9", native: "\u{1F3F9}" }], version: 1 }, shield: { id: "shield", name: "Shield", keywords: ["protection", "security"], skins: [{ unified: "1f6e1-fe0f", native: "\u{1F6E1}\uFE0F" }], version: 1 }, carpentry_saw: { id: "carpentry_saw", name: "Carpentry Saw", keywords: ["cut", "chop"], skins: [{ unified: "1fa9a", native: "\u{1FA9A}" }], version: 13 }, wrench: { id: "wrench", name: "Wrench", keywords: ["tools", "diy", "ikea", "fix", "maintainer"], skins: [{ unified: "1f527", native: "\u{1F527}" }], version: 1 }, screwdriver: { id: "screwdriver", name: "Screwdriver", keywords: ["tools"], skins: [{ unified: "1fa9b", native: "\u{1FA9B}" }], version: 13 }, nut_and_bolt: { id: "nut_and_bolt", name: "Nut and Bolt", keywords: ["handy", "tools", "fix"], skins: [{ unified: "1f529", native: "\u{1F529}" }], version: 1 }, gear: { id: "gear", name: "Gear", keywords: ["cog"], skins: [{ unified: "2699-fe0f", native: "\u2699\uFE0F" }], version: 1 }, compression: { id: "compression", name: "Clamp", keywords: ["compression", "tool"], skins: [{ unified: "1f5dc-fe0f", native: "\u{1F5DC}\uFE0F" }], version: 1 }, scales: { id: "scales", name: "Balance Scale", keywords: ["scales", "law", "fairness", "weight"], skins: [{ unified: "2696-fe0f", native: "\u2696\uFE0F" }], version: 1 }, probing_cane: { id: "probing_cane", name: "White Cane", keywords: ["probing", "accessibility"], skins: [{ unified: "1f9af", native: "\u{1F9AF}" }], version: 12 }, link: { id: "link", name: "Link", keywords: ["rings", "url"], skins: [{ unified: "1f517", native: "\u{1F517}" }], version: 1 }, broken_chain: { id: "broken_chain", name: "Broken Chain", keywords: ["constraint", "break"], skins: [{ unified: "26d3-fe0f-200d-1f4a5", native: "\u26D3\uFE0F\u200D\u{1F4A5}" }], version: 15.1 }, chains: { id: "chains", name: "Chains", keywords: ["lock", "arrest"], skins: [{ unified: "26d3-fe0f", native: "\u26D3\uFE0F" }], version: 1 }, hook: { id: "hook", name: "Hook", keywords: ["tools"], skins: [{ unified: "1fa9d", native: "\u{1FA9D}" }], version: 13 }, toolbox: { id: "toolbox", name: "Toolbox", keywords: ["tools", "diy", "fix", "maintainer", "mechanic"], skins: [{ unified: "1f9f0", native: "\u{1F9F0}" }], version: 11 }, magnet: { id: "magnet", name: "Magnet", keywords: ["attraction", "magnetic"], skins: [{ unified: "1f9f2", native: "\u{1F9F2}" }], version: 11 }, ladder: { id: "ladder", name: "Ladder", keywords: ["tools"], skins: [{ unified: "1fa9c", native: "\u{1FA9C}" }], version: 13 }, shovel: { id: "shovel", name: "Shovel", keywords: [], skins: [{ unified: "1fa8f", native: "\u{1FA8F}" }], version: 16 }, alembic: { id: "alembic", name: "Alembic", keywords: ["distilling", "science", "experiment", "chemistry"], skins: [{ unified: "2697-fe0f", native: "\u2697\uFE0F" }], version: 1 }, test_tube: { id: "test_tube", name: "Test Tube", keywords: ["chemistry", "experiment", "lab", "science"], skins: [{ unified: "1f9ea", native: "\u{1F9EA}" }], version: 11 }, petri_dish: { id: "petri_dish", name: "Petri Dish", keywords: ["bacteria", "biology", "culture", "lab"], skins: [{ unified: "1f9eb", native: "\u{1F9EB}" }], version: 11 }, dna: { id: "dna", name: "Dna", keywords: ["biologist", "genetics", "life"], skins: [{ unified: "1f9ec", native: "\u{1F9EC}" }], version: 11 }, microscope: { id: "microscope", name: "Microscope", keywords: ["laboratory", "experiment", "zoomin", "science", "study"], skins: [{ unified: "1f52c", native: "\u{1F52C}" }], version: 1 }, telescope: { id: "telescope", name: "Telescope", keywords: ["stars", "space", "zoom", "science", "astronomy"], skins: [{ unified: "1f52d", native: "\u{1F52D}" }], version: 1 }, satellite_antenna: { id: "satellite_antenna", name: "Satellite Antenna", keywords: ["communication", "future", "radio", "space"], skins: [{ unified: "1f4e1", native: "\u{1F4E1}" }], version: 1 }, syringe: { id: "syringe", name: "Syringe", keywords: ["health", "hospital", "drugs", "blood", "medicine", "needle", "doctor", "nurse"], skins: [{ unified: "1f489", native: "\u{1F489}" }], version: 1 }, drop_of_blood: { id: "drop_of_blood", name: "Drop of Blood", keywords: ["period", "hurt", "harm", "wound"], skins: [{ unified: "1fa78", native: "\u{1FA78}" }], version: 12 }, pill: { id: "pill", name: "Pill", keywords: ["health", "medicine", "doctor", "pharmacy", "drug"], skins: [{ unified: "1f48a", native: "\u{1F48A}" }], version: 1 }, adhesive_bandage: { id: "adhesive_bandage", name: "Adhesive Bandage", keywords: ["heal"], skins: [{ unified: "1fa79", native: "\u{1FA79}" }], version: 12 }, crutch: { id: "crutch", name: "Crutch", keywords: ["accessibility", "assist"], skins: [{ unified: "1fa7c", native: "\u{1FA7C}" }], version: 14 }, stethoscope: { id: "stethoscope", name: "Stethoscope", keywords: ["health"], skins: [{ unified: "1fa7a", native: "\u{1FA7A}" }], version: 12 }, "x-ray": { id: "x-ray", name: "X-Ray", keywords: ["x", "ray", "skeleton", "medicine"], skins: [{ unified: "1fa7b", native: "\u{1FA7B}" }], version: 14 }, door: { id: "door", name: "Door", keywords: ["house", "entry", "exit"], skins: [{ unified: "1f6aa", native: "\u{1F6AA}" }], version: 1 }, elevator: { id: "elevator", name: "Elevator", keywords: ["lift"], skins: [{ unified: "1f6d7", native: "\u{1F6D7}" }], version: 13 }, mirror: { id: "mirror", name: "Mirror", keywords: ["reflection"], skins: [{ unified: "1fa9e", native: "\u{1FA9E}" }], version: 13 }
51763, window: { id: "window", name: "Window", keywords: ["scenery"], skins: [{ unified: "1fa9f", native: "\u{1FA9F}" }], version: 13 }, bed: { id: "bed", name: "Bed", keywords: ["sleep", "rest"], skins: [{ unified: "1f6cf-fe0f", native: "\u{1F6CF}\uFE0F" }], version: 1 }, couch_and_lamp: { id: "couch_and_lamp", name: "Couch and Lamp", keywords: ["read", "chill"], skins: [{ unified: "1f6cb-fe0f", native: "\u{1F6CB}\uFE0F" }], version: 1 }, chair: { id: "chair", name: "Chair", keywords: ["sit", "furniture"], skins: [{ unified: "1fa91", native: "\u{1FA91}" }], version: 12 }, toilet: { id: "toilet", name: "Toilet", keywords: ["restroom", "wc", "washroom", "bathroom", "potty"], skins: [{ unified: "1f6bd", native: "\u{1F6BD}" }], version: 1 }, plunger: { id: "plunger", name: "Plunger", keywords: ["toilet"], skins: [{ unified: "1faa0", native: "\u{1FAA0}" }], version: 13 }, shower: { id: "shower", name: "Shower", keywords: ["clean", "water", "bathroom"], skins: [{ unified: "1f6bf", native: "\u{1F6BF}" }], version: 1 }, bathtub: { id: "bathtub", name: "Bathtub", keywords: ["clean", "shower", "bathroom"], skins: [{ unified: "1f6c1", native: "\u{1F6C1}" }], version: 1 }, mouse_trap: { id: "mouse_trap", name: "Mouse Trap", keywords: ["cheese"], skins: [{ unified: "1faa4", native: "\u{1FAA4}" }], version: 13 }, razor: { id: "razor", name: "Razor", keywords: ["cut"], skins: [{ unified: "1fa92", native: "\u{1FA92}" }], version: 12 }, lotion_bottle: { id: "lotion_bottle", name: "Lotion Bottle", keywords: ["moisturizer", "sunscreen"], skins: [{ unified: "1f9f4", native: "\u{1F9F4}" }], version: 11 }, safety_pin: { id: "safety_pin", name: "Safety Pin", keywords: ["diaper"], skins: [{ unified: "1f9f7", native: "\u{1F9F7}" }], version: 11 }, broom: { id: "broom", name: "Broom", keywords: ["cleaning", "sweeping", "witch"], skins: [{ unified: "1f9f9", native: "\u{1F9F9}" }], version: 11 }, basket: { id: "basket", name: "Basket", keywords: ["laundry"], skins: [{ unified: "1f9fa", native: "\u{1F9FA}" }], version: 11 }, roll_of_paper: { id: "roll_of_paper", name: "Roll of Paper", keywords: [], skins: [{ unified: "1f9fb", native: "\u{1F9FB}" }], version: 11 }
51763, bucket: { id: "bucket", name: "Bucket", keywords: ["water", "container"], skins: [{ unified: "1faa3", native: "\u{1FAA3}" }], version: 13 }, soap: { id: "soap", name: "Soap", keywords: ["bar", "bathing", "cleaning", "lather"], skins: [{ unified: "1f9fc", native: "\u{1F9FC}" }], version: 11 }, bubbles: { id: "bubbles", name: "Bubbles", keywords: ["soap", "fun", "carbonation", "sparkling"], skins: [{ unified: "1fae7", native: "\u{1FAE7}" }], version: 14 }, toothbrush: { id: "toothbrush", name: "Toothbrush", keywords: ["hygiene", "dental"], skins: [{ unified: "1faa5", native: "\u{1FAA5}" }], version: 13 }, sponge: { id: "sponge", name: "Sponge", keywords: ["absorbing", "cleaning", "porous"], skins: [{ unified: "1f9fd", native: "\u{1F9FD}" }], version: 11 }, fire_extinguisher: { id: "fire_extinguisher", name: "Fire Extinguisher", keywords: ["quench"], skins: [{ unified: "1f9ef", native: "\u{1F9EF}" }], version: 11 }, shopping_trolley: { id: "shopping_trolley", name: "Shopping Cart", keywords: ["trolley"], skins: [{ unified: "1f6d2", native: "\u{1F6D2}" }], version: 3 }, smoking: { id: "smoking", name: "Cigarette", keywords: ["smoking", "kills", "tobacco", "joint", "smoke"], skins: [{ unified: "1f6ac", native: "\u{1F6AC}" }], version: 1 }, coffin: { id: "coffin", name: "Coffin", keywords: ["vampire", "dead", "die", "death", "rip", "graveyard", "cemetery", "casket", "funeral", "box"], skins: [{ unified: "26b0-fe0f", native: "\u26B0\uFE0F" }], version: 1 }, headstone: { id: "headstone", name: "Headstone", keywords: ["death", "rip", "grave"], skins: [{ unified: "1faa6", native: "\u{1FAA6}" }], version: 13 }, funeral_urn: { id: "funeral_urn", name: "Funeral Urn", keywords: ["dead", "die", "death", "rip", "ashes"], skins: [{ unified: "26b1-fe0f", native: "\u26B1\uFE0F" }], version: 1 }, nazar_amulet: { id: "nazar_amulet", name: "Nazar Amulet", keywords: ["bead", "charm"], skins: [{ unified: "1f9ff", native: "\u{1F9FF}" }], version: 11 }, hamsa: { id: "hamsa", name: "Hamsa", keywords: ["religion", "protection"], skins: [{ unified: "1faac", native: "\u{1FAAC}" }], version: 14 }, moyai: { id: "moyai", name: "Moai", keywords: ["moyai", "rock", "easter", "island"], skins: [{ unified: "1f5ff", native: "\u{1F5FF}" }], version: 1 }, placard: { id: "placard", name: "Placard", keywords: ["announcement"], skins: [{ unified: "1faa7", native: "\u{1FAA7}" }], version: 13 }, identification_card: { id: "identification_card", name: "Identification Card", keywords: ["document"], skins: [{ unified: "1faaa", native: "\u{1FAAA}" }], version: 14 }, atm: { id: "atm", name: "Atm Sign", keywords: ["money", "sales", "cash", "blue", "square", "payment", "bank"], skins: [{ unified: "1f3e7", native: "\u{1F3E7}" }], version: 1 }, put_litter_in_its_place: { id: "put_litter_in_its_place", name: "Litter in Bin Sign", keywords: ["put", "its", "place", "blue", "square", "human", "info"], skins: [{ unified: "1f6ae", native: "\u{1F6AE}" }], version: 1 }, potable_water: { id: "potable_water", name: "Potable Water", keywords: ["blue", "square", "liquid", "restroom", "cleaning", "faucet"], skins: [{ unified: "1f6b0", native: "\u{1F6B0}" }], version: 1 }, wheelchair: { id: "wheelchair", name: "Wheelchair Symbol", keywords: ["blue", "square", "disabled", "accessibility"], skins: [{ unified: "267f", native: "\u267F" }], version: 1 }, mens: { id: "mens", name: "Men\u2019s Room", keywords: ["mens", "men", "s", "toilet", "restroom", "wc", "blue", "square", "gender", "male"], skins: [{ unified: "1f6b9", native: "\u{1F6B9}" }], version: 1 }, womens: { id: "womens", name: "Women\u2019s Room", keywords: ["womens", "women", "s", "purple", "square", "woman", "female", "toilet", "loo", "restroom", "gender"], skins: [{ unified: "1f6ba", native: "\u{1F6BA}" }], version: 1 }, restroom: { id: "restroom", name: "Restroom", keywords: ["blue", "square", "toilet", "refresh", "wc", "gender"], skins: [{ unified: "1f6bb", native: "\u{1F6BB}" }], version: 1 }, baby_symbol: { id: "baby_symbol", name: "Baby Symbol", keywords: ["orange", "square", "child"], skins: [{ unified: "1f6bc", native: "\u{1F6BC}" }], version: 1 }, wc: { id: "wc", name: "Water Closet", keywords: ["wc", "toilet", "restroom", "blue", "square"], skins: [{ unified: "1f6be", native: "\u{1F6BE}" }], version: 1 }, passport_control: { id: "passport_control", name: "Passport Control", keywords: ["custom", "blue", "square"], skins: [{ unified: "1f6c2", native: "\u{1F6C2}" }
51763], version: 1 }, customs: { id: "customs", name: "Customs", keywords: ["passport", "border", "blue", "square"], skins: [{ unified: "1f6c3", native: "\u{1F6C3}" }], version: 1 }, baggage_claim: { id: "baggage_claim", name: "Baggage Claim", keywords: ["blue", "square", "airport", "transport"], skins: [{ unified: "1f6c4", native: "\u{1F6C4}" }], version: 1 }, left_luggage: { id: "left_luggage", name: "Left Luggage", keywords: ["blue", "square", "travel"], skins: [{ unified: "1f6c5", native: "\u{1F6C5}" }], version: 1 }, warning: { id: "warning", name: "Warning", keywords: ["exclamation", "wip", "alert", "error", "problem", "issue"], skins: [{ unified: "26a0-fe0f", native: "\u26A0\uFE0F" }], version: 1 }, children_crossing: { id: "children_crossing", name: "Children Crossing", keywords: ["school", "warning", "danger", "sign", "driving", "yellow", "diamond"], skins: [{ unified: "1f6b8", native: "\u{1F6B8}" }], version: 1 }, no_entry: { id: "no_entry", name: "No Entry", keywords: ["limit", "security", "privacy", "bad", "denied", "stop", "circle"], skins: [{ unified: "26d4", native: "\u26D4" }], version: 1 }, no_entry_sign: { id: "no_entry_sign", name: "Prohibited", keywords: ["no", "entry", "sign", "forbid", "stop", "limit", "denied", "disallow", "circle"], skins: [{ unified: "1f6ab", native: "\u{1F6AB}" }], version: 1 }, no_bicycles: { id: "no_bicycles", name: "No Bicycles", keywords: ["bikes", "bicycle", "bike", "cyclist", "prohibited", "circle"], skins: [{ unified: "1f6b3", native: "\u{1F6B3}" }], version: 1 }, no_smoking: { id: "no_smoking", name: "No Smoking", keywords: ["cigarette", "blue", "square", "smell", "smoke"], skins: [{ unified: "1f6ad", native: "\u{1F6AD}" }], version: 1 }, do_not_litter: { id: "do_not_litter", name: "No Littering", keywords: ["do", "not", "litter", "trash", "bin", "garbage", "circle"], skins: [{ unified: "1f6af", native: "\u{1F6AF}" }], version: 1 }, "non-potable_water": { id: "non-potable_water", name: "Non-Potable Water", keywords: ["non", "potable", "drink", "faucet", "tap", "circle"], skins: [{ unified: "1f6b1", native: "\u{1F6B1}" }], version: 1 }, no_pedestrians: { id: "no_pedestrians", name: "No Pedestrians", keywords: ["rules", "crossing", "walking", "circle"], skins: [{ unified: "1f6b7", native: "\u{1F6B7}" }], version: 1 }, no_mobile_phones: { id: "no_mobile_phones", name: "No Mobile Phones", keywords: ["iphone", "mute", "circle"], skins: [{ unified: "1f4f5", native: "\u{1F4F5}" }], version: 1 }, underage: { id: "underage", name: "No One Under Eighteen", keywords: ["underage", "18", "drink", "pub", "night", "minor", "circle"], skins: [{ unified: "1f51e", native: "\u{1F51E}" }], version: 1 }, radioactive_sign: { id: "radioactive_sign", name: "Radioactive", keywords: ["sign", "nuclear", "danger"], skins: [{ unified: "2622-fe0f", native: "\u2622\uFE0F" }], version: 1 }, biohazard_sign: { id: "biohazard_sign", name: "Biohazard", keywords: ["sign", "danger"], skins: [{ unified: "2623-fe0f", native: "\u2623\uFE0F" }], version: 1 }, arrow_up: { id: "arrow_up", name: "Up Arrow", keywords: ["blue", "square", "continue", "top", "direction"], skins: [{ unified: "2b06-fe0f", native: "\u2B06\uFE0F" }], version: 1 }, arrow_upper_right: { id: "arrow_upper_right", name: "Up-Right Arrow", keywords: ["upper", "right", "up", "blue", "square", "point", "direction", "diagonal", "northeast"], skins: [{ unified: "2197-fe0f", native: "\u2197\uFE0F" }], version: 1 }, arrow_right: { id: "arrow_right", name: "Right Arrow", keywords: ["blue", "square", "next"], skins: [{ unified: "27a1-fe0f", native: "\u27A1\uFE0F" }], version: 1 }, arrow_lower_right: { id: "arrow_lower_right", name: "South East Arrow", keywords: ["lower", "right", "down", "blue", "square", "direction", "diagonal", "southeast"], skins: [{ unified: "2198-fe0f", native: "\u2198\uFE0F" }], version: 1 }, arrow_down: { id: "arrow_down", name: "Down Arrow", keywords: ["blue", "square", "direction", "bottom"], skins: [{ unified: "2b07-fe0f", native: "\u2B07\uFE0F" }], version: 1 }, arrow_lower_left: { id: "arrow_lower_left", name: "Down-Left Arrow", keywords: ["lower", "left", "down", "blue", "square", "direction", "diagonal", "southwest"], skins: [{ unified: "2199-fe0f", native: "\u2199\uFE0F" }], version: 1 }, arrow_left: { id: "arrow_left", name: "Left Arrow", keywords: ["blue", "square", "previous", "back"], skins: [{ unified: "2b05-fe0f", native: "\u2B05\uFE0F" }], version: 1 }, arrow_upper_left: { id: "arrow_upper_left", name: "Up-Left Arrow", keywords: ["upper", "left", "up", "blue", "square", "point", "direction", "diagonal", "northwest"], skins: [{ unified: "2196-fe0f", native: "\u2196\uFE0F" }], version: 1 }, arrow_up_down: { id: "arrow_up_down", name: "Up Down Arrow", keywords: ["blue", "square", "direction", "way", "vertical"], skins: [{ unified: "2195-fe0f", native: "\u2195\uFE0F" }], version: 1 }
51763, left_right_arrow: { id: "left_right_arrow", name: "Left Right Arrow", keywords: ["shape", "direction", "horizontal", "sideways"], skins: [{ unified: "2194-fe0f", native: "\u2194\uFE0F" }], version: 1 }, leftwards_arrow_with_hook: { id: "leftwards_arrow_with_hook", name: "Right Arrow Curving Left", keywords: ["leftwards", "with", "hook", "back", "return", "blue", "square", "undo", "enter"], skins: [{ unified: "21a9-fe0f", native: "\u21A9\uFE0F" }], version: 1 }, arrow_right_hook: { id: "arrow_right_hook", name: "Left Arrow Curving Right", keywords: ["hook", "blue", "square", "return", "rotate", "direction"], skins: [{ unified: "21aa-fe0f", native: "\u21AA\uFE0F" }], version: 1 }, arrow_heading_up: { id: "arrow_heading_up", name: "Right Arrow Curving Up", keywords: ["heading", "blue", "square", "direction", "top"], skins: [{ unified: "2934-fe0f", native: "\u2934\uFE0F" }], version: 1 }, arrow_heading_down: { id: "arrow_heading_down", name: "Right Arrow Curving Down", keywords: ["heading", "blue", "square", "direction", "bottom"], skins: [{ unified: "2935-fe0f", native: "\u2935\uFE0F" }], version: 1 }, arrows_clockwise: { id: "arrows_clockwise", name: "Clockwise Vertical Arrows", keywords: ["sync", "cycle", "round", "repeat"], skins: [{ unified: "1f503", native: "\u{1F503}" }], version: 1 }, arrows_counterclockwise: { id: "arrows_counterclockwise", name: "Counterclockwise Arrows Button", keywords: ["blue", "square", "sync", "cycle"], skins: [{ unified: "1f504", native: "\u{1F504}" }], version: 1 }, back: { id: "back", name: "Back Arrow", keywords: ["words", "return"], skins: [{ unified: "1f519", native: "\u{1F519}" }], version: 1 }, end: { id: "end", name: "End Arrow", keywords: ["words"], skins: [{ unified: "1f51a", native: "\u{1F51A}" }], version: 1 }, on: { id: "on", name: "On! Arrow", keywords: ["on", "words"], skins: [{ unified: "1f51b", native: "\u{1F51B}" }], version: 1 }, soon: { id: "soon", name: "Soon Arrow", keywords: ["words"], skins: [{ unified: "1f51c", native: "\u{1F51C}" }], version: 1 }, top: { id: "top", name: "Top Arrow", keywords: ["words", "blue", "square"], skins: [{ unified: "1f51d", native: "\u{1F51D}" }], version: 1 }, place_of_worship: { id: "place_of_worship", name: "Place of Worship", keywords: ["religion", "church", "temple", "prayer"], skins: [{ unified: "1f6d0", native: "\u{1F6D0}" }], version: 1 }, atom_symbol: { id: "atom_symbol", name: "Atom Symbol", keywords: ["science", "physics", "chemistry"], skins: [{ unified: "269b-fe0f", native: "\u269B\uFE0F" }], version: 1 }, om_symbol: { id: "om_symbol", name: "Om", keywords: ["symbol", "hinduism", "buddhism", "sikhism", "jainism"], skins: [{ unified: "1f549-fe0f", native: "\u{1F549}\uFE0F" }], version: 1 }, star_of_david: { id: "star_of_david", name: "Star of David", keywords: ["judaism"], skins: [{ unified: "2721-fe0f", native: "\u2721\uFE0F" }], version: 1 }, wheel_of_dharma: { id: "wheel_of_dharma", name: "Wheel of Dharma", keywords: ["hinduism", "buddhism", "sikhism", "jainism"], skins: [{ unified: "2638-fe0f", native: "\u2638\uFE0F" }], version: 1 }, yin_yang: { id: "yin_yang", name: "Yin Yang", keywords: ["balance"], skins: [{ unified: "262f-fe0f", native: "\u262F\uFE0F" }], version: 1 }, latin_cross: { id: "latin_cross", name: "Latin Cross", keywords: ["christianity"], skins: [{ unified: "271d-fe0f", native: "\u271D\uFE0F" }], version: 1 }, orthodox_cross: { id: "orthodox_cross", name: "Orthodox Cross", keywords: ["suppedaneum", "religion"], skins: [{ unified: "2626-fe0f", native: "\u2626\uFE0F" }], version: 1 }, star_and_crescent: { id: "star_and_crescent", name: "Star and Crescent", keywords: ["islam"], skins: [{ unified: "262a-fe0f", native: "\u262A\uFE0F" }], version: 1 }, peace_symbol: { id: "peace_symbol", name: "Peace Symbol", keywords: ["hippie"], skins: [{ unified: "262e-fe0f", native: "\u262E\uFE0F" }], version: 1 }, menorah_with_nine_branches: { id: "menorah_with_nine_branches", name: "Menorah", keywords: ["with", "nine", "branches", "hanukkah", "candles", "jewish"], skins: [{ unified: "1f54e", native: "\u{1F54E}" }], version: 1 }, six_pointed_star: { id: "six_pointed_star", name: "Dotted Six-Pointed Star", keywords: ["six", "pointed", "purple", "square", "religion", "jewish", "hexagram"], skins: [{ unified: "1f52f", native: "\u{1F52F}" }], version: 1 }, khanda: { id: "khanda", name: "Khanda", keywords: ["Sikhism", "religion"], skins: [{ unified: "1faaf", native: "\u{1FAAF}" }], version: 15 }, aries: { id: "aries", name: "Aries", keywords: ["sign", "purple", "square", "zodiac", "astrology"], skins: [{ unified: "2648", native: "\u2648" }], version: 1 }, taurus: { id: "taurus", name: "Taurus", keywords: ["purple", "square", "sign", "zodiac", "astrology"], skins: [{ unified: "2649", native: "\u2649" }], version: 1 }, gemini: { id: "gemini", name: "Gemini", keywords: ["sign", "zodiac", "purple", "square", "astrology"], skins: [{ unified: "264a", native: "\u264A" }], version: 1 }, cancer: { id: "cancer", name: "Cancer", keywords: ["sign", "zodiac", "purple", "square", "astrology"], skins: [{ unified: "264b", native: "\u264B" }], version: 1 }, leo: { id: "leo", name: "Leo", keywords: ["sign", "purple", "square", "zodiac", "astrology"], skins: [{ unified: "264c", native: "\u264C" }], version: 1 }, virgo: { id: "virgo", name: "Virgo", keywords: ["sign", "zodiac", "purple", "square", "astrology"], skins: [{ unified: "264d", native: "\u264D" }], version: 1 }, libra: { id: "libra", name: "Libra", keywords: ["sign", "purple", "square", "zodiac", "astrology"], skins: [{ unified: "264e", native: "\u264E" }], version: 1 }, scorpius: { id: "scorpius", name: "Scorpio", keywords: ["scorpius", "sign", "zodiac", "purple", "square", "astrology"], skins: [{ unified: "264f", native: "\u264F" }], version: 1 }, sagittarius: { id: "sagittarius", name: "Sagittarius", keywords: ["sign", "zodiac", "purple", "square", "astrology"], skins: [{ unified: "2650", native: "\u2650" }
51763], version: 1 }, capricorn: { id: "capricorn", name: "Capricorn", keywords: ["sign", "zodiac", "purple", "square", "astrology"], skins: [{ unified: "2651", native: "\u2651" }], version: 1 }, aquarius: { id: "aquarius", name: "Aquarius", keywords: ["sign", "purple", "square", "zodiac", "astrology"], skins: [{ unified: "2652", native: "\u2652" }], version: 1 }, pisces: { id: "pisces", name: "Pisces", keywords: ["purple", "square", "sign", "zodiac", "astrology"], skins: [{ unified: "2653", native: "\u2653" }], version: 1 }, ophiuchus: { id: "ophiuchus", name: "Ophiuchus", keywords: ["sign", "purple", "square", "constellation", "astrology"], skins: [{ unified: "26ce", native: "\u26CE" }], version: 1 }, twisted_rightwards_arrows: { id: "twisted_rightwards_arrows", name: "Shuffle Tracks Button", keywords: ["twisted", "rightwards", "arrows", "blue", "square", "music", "random"], skins: [{ unified: "1f500", native: "\u{1F500}" }], version: 1 }, repeat: { id: "repeat", name: "Repeat Button", keywords: ["loop", "record"], skins: [{ unified: "1f501", native: "\u{1F501}" }], version: 1 }, repeat_one: { id: "repeat_one", name: "Repeat Single Button", keywords: ["one", "blue", "square", "loop"], skins: [{ unified: "1f502", native: "\u{1F502}" }], version: 1 }, arrow_forward: { id: "arrow_forward", name: "Play Button", keywords: ["arrow", "forward", "blue", "square", "right", "direction"], skins: [{ unified: "25b6-fe0f", native: "\u25B6\uFE0F" }], version: 1 }, fast_forward: { id: "fast_forward", name: "Fast-Forward Button", keywords: ["fast", "forward", "blue", "square", "play", "speed", "continue"], skins: [{ unified: "23e9", native: "\u23E9" }], version: 1 }, black_right_pointing_double_triangle_with_vertical_bar: { id: "black_right_pointing_double_triangle_with_vertical_bar", name: "Next Track Button", keywords: ["black", "right", "pointing", "double", "triangle", "with", "vertical", "bar", "forward", "blue", "square"], skins: [{ unified: "23ed-fe0f", native: "\u23ED\uFE0F" }], version: 1 }, black_right_pointing_triangle_with_double_vertical_bar: { id: "black_right_pointing_triangle_with_double_vertical_bar", name: "Play or Pause Button", keywords: ["black", "right", "pointing", "triangle", "with", "double", "vertical", "bar", "blue", "square"], skins: [{ unified: "23ef-fe0f", native: "\u23EF\uFE0F" }], version: 1 }, arrow_backward: { id: "arrow_backward", name: "Reverse Button", keywords: ["arrow", "backward", "blue", "square", "left", "direction"], skins: [{ unified: "25c0-fe0f", native: "\u25C0\uFE0F" }], version: 1 }, rewind: { id: "rewind", name: "Fast Reverse Button", keywords: ["rewind", "play", "blue", "square"], skins: [{ unified: "23ea", native: "\u23EA" }], version: 1 }, black_left_pointing_double_triangle_with_vertical_bar: { id: "black_left_pointing_double_triangle_with_vertical_bar", name: "Last Track Button", keywords: ["black", "left", "pointing", "double", "triangle", "with", "vertical", "bar", "backward"], skins: [{ unified: "23ee-fe0f", native: "\u23EE\uFE0F" }], version: 1 }, arrow_up_small: { id: "arrow_up_small", name: "Upwards Button", keywords: ["arrow", "up", "small", "blue", "square", "triangle", "direction", "point", "forward", "top"], skins: [{ unified: "1f53c", native: "\u{1F53C}" }], version: 1 }, arrow_double_up: { id: "arrow_double_up", name: "Fast Up Button", keywords: ["arrow", "double", "blue", "square", "direction", "top"], skins: [{ unified: "23eb", native: "\u23EB" }], version: 1 }, arrow_down_small: { id: "arrow_down_small", name: "Downwards Button", keywords: ["arrow", "down", "small", "blue", "square", "direction", "bottom"], skins: [{ unified: "1f53d", native: "\u{1F53D}" }], version: 1 }, arrow_double_down: { id: "arrow_double_down", name: "Fast Down Button", keywords: ["arrow", "double", "blue", "square", "direction", "bottom"], skins: [{ unified: "23ec", native: "\u23EC" }], version: 1 }, double_vertical_bar: { id: "double_vertical_bar", name: "Pause Button", keywords: ["double", "vertical", "bar", "blue", "square"], skins: [{ unified: "23f8-fe0f", native: "\u23F8\uFE0F" }], version: 1 }, black_square_for_stop: { id: "black_square_for_stop", name: "Stop Button", keywords: ["black", "square", "for", "blue"], skins: [{ unified: "23f9-fe0f", native: "\u23F9\uFE0F" }], version: 1 }, black_circle_for_record: { id: "black_circle_for_record", name: "Record Button", keywords: ["black", "cir
51763cle", "for", "blue", "square"], skins: [{ unified: "23fa-fe0f", native: "\u23FA\uFE0F" }], version: 1 }, eject: { id: "eject", name: "Eject Button", keywords: ["blue", "square"], skins: [{ unified: "23cf-fe0f", native: "\u23CF\uFE0F" }], version: 1 }, cinema: { id: "cinema", name: "Cinema", keywords: ["blue", "square", "record", "film", "movie", "curtain", "stage", "theater"], skins: [{ unified: "1f3a6", native: "\u{1F3A6}" }], version: 1 }, low_brightness: { id: "low_brightness", name: "Dim Button", keywords: ["low", "brightness", "sun", "afternoon", "warm", "summer"], skins: [{ unified: "1f505", native: "\u{1F505}" }], version: 1 }, high_brightness: { id: "high_brightness", name: "Bright Button", keywords: ["high", "brightness", "sun", "light"], skins: [{ unified: "1f506", native: "\u{1F506}" }], version: 1 }, signal_strength: { id: "signal_strength", name: "Antenna Bars", keywords: ["signal", "strength", "blue", "square", "reception", "phone", "internet", "connection", "wifi", "bluetooth"], skins: [{ unified: "1f4f6", native: "\u{1F4F6}" }], version: 1 }, wireless: { id: "wireless", name: "Wireless", keywords: ["wifi", "internet", "contactless", "signal"], skins: [{ unified: "1f6dc", native: "\u{1F6DC}" }], version: 15 }, vibration_mode: { id: "vibration_mode", name: "Vibration Mode", keywords: ["orange", "square", "phone"], skins: [{ unified: "1f4f3", native: "\u{1F4F3}" }], version: 1 }, mobile_phone_off: { id: "mobile_phone_off", name: "Mobile Phone off", keywords: ["mute", "orange", "square", "silence", "quiet"], skins: [{ unified: "1f4f4", native: "\u{1F4F4}" }], version: 1 }, female_sign: { id: "female_sign", name: "Female Sign", keywords: ["woman", "women", "lady", "girl"], skins: [{ unified: "2640-fe0f", native: "\u2640\uFE0F" }], version: 4 }, male_sign: { id: "male_sign", name: "Male Sign", keywords: ["man", "boy", "men"], skins: [{ unified: "2642-fe0f", native: "\u2642\uFE0F" }], version: 4 }, transgender_symbol: { id: "transgender_symbol", name: "Transgender Symbol", keywords: ["lgbtq"], skins: [{ unified: "26a7-fe0f", native: "\u26A7\uFE0F" }], version: 13 }, heavy_multiplication_x: { id: "heavy_multiplication_x", name: "Multiply", keywords: ["heavy", "multiplication", "x", "sign", "math", "calculation"], skins: [{ unified: "2716-fe0f", native: "\u2716\uFE0F" }], version: 1 }, heavy_plus_sign: { id: "heavy_plus_sign", name: "Plus", keywords: ["heavy", "sign", "math", "calculation", "addition", "more", "increase"], skins: [{ unified: "2795", native: "\u2795" }], version: 1 }, heavy_minus_sign: { id: "heavy_minus_sign", name: "Minus", keywords: ["heavy", "sign", "math", "calculation", "subtract", "less"], skins: [{ unified: "2796", native: "\u2796" }], version: 1 }, heavy_division_sign: { id: "heavy_division_sign", name: "Divide", keywords: ["heavy", "division", "sign", "math", "calculation"], skins: [{ unified: "2797", native: "\u2797" }], version: 1 }, heavy_equals_sign: { id: "heavy_equals_sign", name: "Heavy Equals Sign", keywords: ["math"], skins: [{ unified: "1f7f0", native: "\u{1F7F0}" }], version: 14 }, infinity: { id: "infinity", name: "Infinity", keywords: ["forever"], skins: [{ unified: "267e-fe0f", native: "\u267E\uFE0F" }], version: 11 }, bangbang: { id: "bangbang", name: "Double Exclamation Mark", keywords: ["bangbang", "surprise"], skins: [{ unified: "203c-fe0f", native: "\u203C\uFE0F" }], version: 1 }, interrobang: { id: "interrobang", name: "Exclamation Question Mark", keywords: ["interrobang", "wat", "punctuation", "surprise"], skins: [{ unified: "2049-fe0f", native: "\u2049\uFE0F" }], version: 1 }, question: { id: "question", name: "Red Question Mark", keywords: ["doubt", "confused"], skins: [{ unified: "2753", native: "\u2753" }], version: 1 }, grey_question: { id: "grey_question", name: "White Question Mark", keywords: ["grey", "doubts", "gray", "huh", "confused"], skins: [{ unified: "2754", native: "\u2754" }], version: 1 }, grey_exclamation: { id: "grey_exclamation", name: "White Exclamation Mark", keywords: ["grey", "surprise", "punctuation", "gray", "wow", "warning"], skins: [{ unified: "2755", native: "\u27
5176355" }], version: 1 }, exclamation: { id: "exclamation", name: "Red Exclamation Mark", keywords: ["heavy", "danger", "surprise", "punctuation", "wow", "warning"], skins: [{ unified: "2757", native: "\u2757" }], version: 1 }, wavy_dash: { id: "wavy_dash", name: "Wavy Dash", keywords: ["draw", "line", "moustache", "mustache", "squiggle", "scribble"], skins: [{ unified: "3030-fe0f", native: "\u3030\uFE0F" }], version: 1 }, currency_exchange: { id: "currency_exchange", name: "Currency Exchange", keywords: ["money", "sales", "dollar", "travel"], skins: [{ unified: "1f4b1", native: "\u{1F4B1}" }], version: 1 }, heavy_dollar_sign: { id: "heavy_dollar_sign", name: "Heavy Dollar Sign", keywords: ["money", "sales", "payment", "currency", "buck"], skins: [{ unified: "1f4b2", native: "\u{1F4B2}" }], version: 1 }, medical_symbol: { id: "medical_symbol", name: "Medical Symbol", keywords: ["staff", "of", "aesculapius", "health", "hospital"], skins: [{ unified: "2695-fe0f", native: "\u2695\uFE0F" }], version: 4 }, recycle: { id: "recycle", name: "Recycling Symbol", keywords: ["recycle", "arrow", "environment", "garbage", "trash"], skins: [{ unified: "267b-fe0f", native: "\u267B\uFE0F" }], version: 1 }, fleur_de_lis: { id: "fleur_de_lis", name: "Fleur-De-Lis", keywords: ["fleur", "de", "lis", "decorative", "scout"], skins: [{ unified: "269c-fe0f", native: "\u269C\uFE0F" }], version: 1 }, trident: { id: "trident", name: "Trident Emblem", keywords: ["weapon", "spear"], skins: [{ unified: "1f531", native: "\u{1F531}" }], version: 1 }, name_badge: { id: "name_badge", name: "Name Badge", keywords: ["fire", "forbid"], skins: [{ unified: "1f4db", native: "\u{1F4DB}" }], version: 1 }, beginner: { id: "beginner", name: "Japanese Symbol for Beginner", keywords: ["badge", "shield"], skins: [{ unified: "1f530", native: "\u{1F530}" }], version: 1 }, o: { id: "o", name: "Hollow Red Circle", keywords: ["o", "round"], skins: [{ unified: "2b55", native: "\u2B55" }], version: 1 }, white_check_mark: { id: "white_check_mark", name: "Check Mark Button", keywords: ["white", "green", "square", "ok", "agree", "vote", "election", "answer", "tick"], skins: [{ unified: "2705", native: "\u2705" }], version: 1 }, ballot_box_with_check: { id: "ballot_box_with_check", name: "Check Box with Check", keywords: ["ballot", "ok", "agree", "confirm", "black", "square", "vote", "election", "yes", "tick"], skins: [{ unified: "2611-fe0f", native: "\u2611\uFE0F" }], version: 1 }, heavy_check_mark: { id: "heavy_check_mark", name: "Check Mark", keywords: ["heavy", "ok", "nike", "answer", "yes", "tick"], skins: [{ unified: "2714-fe0f", native: "\u2714\uFE0F" }], version: 1 }, x: { id: "x", name: "Cross Mark", keywords: ["x", "no", "delete", "remove", "cancel", "red"], skins: [{ unified: "274c", native: "\u274C" }], version: 1 }, negative_squared_cross_mark: { id: "negative_squared_cross_mark", name: "Cross Mark Button", keywords: ["negative", "squared", "x", "green", "square", "no", "deny"], skins: [{ unified: "274e", native: "\u274E" }], version: 1 }, curly_loop: { id: "curly_loop", name: "Curly Loop", keywords: ["scribble", "draw", "shape", "squiggle"], skins: [{ unified: "27b0", native: "\u27B0" }], version: 1 }, loop: { id: "loop", name: "Double Curly Loop", keywords: ["tape", "cassette"], skins: [{ unified: "27bf", native: "\u27BF" }], version: 1 }, part_alternation_mark: { id: "part_alternation_mark", name: "Part Alternation Mark", keywords: ["graph", "presentation", "stats", "business", "economics", "bad"], skins: [{ unified: "303d-fe0f", native: "\u303D\uFE0F" }], version: 1 }, eight_spoked_asterisk: { id: "eight_spoked_asterisk", name: "Eight Spoked Asterisk", keywords: ["star", "sparkle", "green", "square"], skins: [{ unified: "2733-fe0f", native: "\u2733\uFE0F" }], version: 1 }, eight_pointed_black_star: { id: "eight_pointed_black_star", name: "Eight-Pointed Star", keywords: ["eight", "pointed", "black", "orange", "square", "shape", "polygon"], skins: [{ unified: "2734-fe0f", native: "\u2734\uFE0F" }], version: 1 }, sparkle: { id: "sparkle", name: "Sparkle", keywords: ["stars", "green", "square", "awe
51763some", "good", "fireworks"], skins: [{ unified: "2747-fe0f", native: "\u2747\uFE0F" }], version: 1 }, copyright: { id: "copyright", name: "Copyright", keywords: ["ip", "license", "circle", "law", "legal"], skins: [{ unified: "00a9-fe0f", native: "\xA9\uFE0F" }], version: 1 }, registered: { id: "registered", name: "Registered", keywords: ["alphabet", "circle"], skins: [{ unified: "00ae-fe0f", native: "\xAE\uFE0F" }], version: 1 }, tm: { id: "tm", name: "Trade Mark", keywords: ["tm", "trademark", "brand", "law", "legal"], skins: [{ unified: "2122-fe0f", native: "\u2122\uFE0F" }], version: 1 }, splatter: { id: "splatter", name: "Splatter", keywords: [], skins: [{ unified: "1fadf", native: "\u{1FADF}" }], version: 16 }, hash: { id: "hash", name: "Hash Key", keywords: ["keycap", "", "symbol", "blue", "square", "twitter"], skins: [{ unified: "0023-fe0f-20e3", native: "#\uFE0F\u20E3" }], version: 1 }, keycap_star: { id: "keycap_star", name: "Keycap: *", keywords: ["keycap", "star", ""], skins: [{ unified: "002a-fe0f-20e3", native: "*\uFE0F\u20E3" }], version: 2 }, zero: { id: "zero", name: "Keycap 0", keywords: ["zero", "numbers", "blue", "square", "null"], skins: [{ unified: "0030-fe0f-20e3", native: "0\uFE0F\u20E3" }], version: 1 }, one: { id: "one", name: "Keycap 1", keywords: ["one", "blue", "square", "numbers"], skins: [{ unified: "0031-fe0f-20e3", native: "1\uFE0F\u20E3" }], version: 1 }, two: { id: "two", name: "Keycap 2", keywords: ["two", "numbers", "prime", "blue", "square"], skins: [{ unified: "0032-fe0f-20e3", native: "2\uFE0F\u20E3" }], version: 1 }, three: { id: "three", name: "Keycap 3", keywords: ["three", "numbers", "prime", "blue", "square"], skins: [{ unified: "0033-fe0f-20e3", native: "3\uFE0F\u20E3" }], version: 1 }, four: { id: "four", name: "Keycap 4", keywords: ["four", "numbers", "blue", "square"], skins: [{ unified: "0034-fe0f-20e3", native: "4\uFE0F\u20E3" }], version: 1 }, five: { id: "five", name: "Keycap 5", keywords: ["five", "numbers", "blue", "square", "prime"], skins: [{ unified: "0035-fe0f-20e3", native: "5\uFE0F\u20E3" }], version: 1 }, six: { id: "six", name: "Keycap 6", keywords: ["six", "numbers", "blue", "square"], skins: [{ unified: "0036-fe0f-20e3", native: "6\uFE0F\u20E3" }], version: 1 }, seven: { id: "seven", name: "Keycap 7", keywords: ["seven", "numbers", "blue", "square", "prime"], skins: [{ unified: "0037-fe0f-20e3", native: "7\uFE0F\u20E3" }], version: 1 }, eight: { id: "eight", name: "Keycap 8", keywords: ["eight", "blue", "square", "numbers"], skins: [{ unified: "0038-fe0f-20e3", native: "8\uFE0F\u20E3" }], version: 1 }, nine: { id: "nine", name: "Keycap 9", keywords: ["nine", "blue", "square", "numbers"], skins: [{ unified: "0039-fe0f-20e3", native: "9\uFE0F\u20E3" }], version: 1 }, keycap_ten: { id: "keycap_ten", name: "Keycap 10", keywords: ["ten", "numbers", "blue", "square"], skins: [{ unified: "1f51f", native: "\u{1F51F}" }], version: 1 }, capital_abcd: { id: "capital_abcd", name: "Input Latin Uppercase", keywords: ["capital", "abcd", "alphabet", "words", "letters", "blue", "square"], skins: [{ unified: "1f520", native: "\u{1F520}" }], version: 1 }, abcd: { id: "abcd", name: "Input Latin Lowercase", keywords: ["abcd", "blue", "square", "letters", "alphabet"], skins: [{ unified: "1f521", native: "\u{1F521}" }], version: 1 }, symbols: { id: "symbols", name: "Input Symbols", keywords: ["blue", "square", "music", "note", "ampersand", "percent", "glyphs", "characters"], skins: [{ unified: "1f523", native: "\u{1F523}" }], version: 1 }, abc: { id: "abc", name: "Input Latin Letters", keywords: ["abc", "blue", "square", "alphabet"], skins: [{ unified: "1f524", native: "\u{1F524}" }], version: 1 }, a: { id: "a", name: "A Button (blood Type)", keywords: ["red", "square", "alphabet", "letter"], skins: [{ unified: "1f170-fe0f", native: "\u{1F170}\uFE0F" }], version: 1 }, ab: { id: "ab", name: "Negative Squared Ab", keywords: ["button", "red", "square", "alphabet"], skins: [{ unified: "1f18e", native: "\u{1F18E}" }], version: 1 }, b: { id: "b", name: "B Button (blood Type)", keywords: ["red", "square", "alphabet", "letter"], skins: [{ unified: "1f171-fe0f", native: "\u{1F171}\uFE0F" }], version: 1 }, cl: { id: "cl", name: "Cl Button", keywords: ["alphabet", "words", "red", "square"], skins: [{ unified: "1f191", native: "\u{1F191}" }], version: 1 }, cool: { id: "cool", name: "Cool Button", keywords: ["words", "blue", "square"], skins: [{ unified: "1f192", native: "\u{1F192}" }], version: 1 }, free: { id: "free", name: "Free Button", keywords: ["blue", "square", "words"], skins: [{ unified: "1f193", native: "\u{1F193}" }], version: 1 }, information_source: { id: "information_source", name: "Information", keywords: ["source", "blue", "square", "alphabet", "letter"], skins: [{ unified: "2139-fe0f", native: "\u2139\uFE0F" }], version: 1 }, id: { id: "id", name: "Id Button", keywords: ["purple", "square", "words"], skins: [{ unified: "1f194", native: "\u{1F194}" }], version: 1 }, m: { id: "m", name: "Circled M", keywords: ["alphabet", "blue", "circle", "letter"], skins: [{ unified: "24c2-fe0f", native: "\u24C2\uFE0F" }], version: 1 }, new: { id: "new", name: "New Button", keywords: ["blue", "square", "words", "start"], skins: [{ unified: "1f195", native: "\u{1F195}" }], version: 1 }, ng: { id: "ng", name: "Ng Button", keywords: ["blue", "square", "words", "shape", "icon"], skins: [{ unified: "1f196", native: "\u{1F196}" }], version: 1 }, o2: { id: "o2", name: "O Button (blood Type)", keywords: ["o2", "alphabet", "red", "square", "letter"], skins: [{ unified: "1f17e-fe0f", native: "\u{1F17E}\uFE0F" }], version: 1 }, ok: { id: "ok", name: "Ok Button", keywords: ["good", "agree", "yes", "blue", "square"], skins: [{ unified: "1f197", native: "\u{1F197}" }], version: 1 }
51763, parking: { id: "parking", name: "P Button", keywords: ["parking", "cars", "blue", "square", "alphabet", "letter"], skins: [{ unified: "1f17f-fe0f", native: "\u{1F17F}\uFE0F" }], version: 1 }, sos: { id: "sos", name: "Sos Button", keywords: ["help", "red", "square", "words", "emergency", "911"], skins: [{ unified: "1f198", native: "\u{1F198}" }], version: 1 }, up: { id: "up", name: "Up! Button", keywords: ["up", "blue", "square", "above", "high"], skins: [{ unified: "1f199", native: "\u{1F199}" }], version: 1 }, vs: { id: "vs", name: "Vs Button", keywords: ["words", "orange", "square"], skins: [{ unified: "1f19a", native: "\u{1F19A}" }], version: 1 }, koko: { id: "koko", name: "Squared Katakana Koko", keywords: ["japanese", "here", "button", "blue", "square", "destination"], skins: [{ unified: "1f201", native: "\u{1F201}" }], version: 1 }, sa: { id: "sa", name: "Squared Katakana Sa", keywords: ["japanese", "service", "charge", "button", "blue", "square"], skins: [{ unified: "1f202-fe0f", native: "\u{1F202}\uFE0F" }], version: 1 }, u6708: { id: "u6708", name: "Japanese \u201Cmonthly Amount\u201D Button", keywords: ["u6708", "monthly", "amount", "chinese", "month", "moon", "orange", "square", "kanji"], skins: [{ unified: "1f237-fe0f", native: "\u{1F237}\uFE0F" }], version: 1 }, u6709: { id: "u6709", name: "Squared Cjk Unified Ideograph-6709", keywords: ["u6709", "japanese", "not", "free", "of", "charge", "button", "orange", "square", "chinese", "have", "kanji"], skins: [{ unified: "1f236", native: "\u{1F236}" }], version: 1 }, u6307: { id: "u6307", name: "Japanese \u201Creserved\u201D Button", keywords: ["u6307", "reserved", "chinese", "point", "green", "square", "kanji"], skins: [{ unified: "1f22f", native: "\u{1F22F}" }], version: 1 }, ideograph_advantage: { id: "ideograph_advantage", name: "Japanese \u201Cbargain\u201D Button", keywords: ["ideograph", "advantage", "bargain", "chinese", "kanji", "obtain", "get", "circle"], skins: [{ unified: "1f250", native: "\u{1F250}" }], version: 1 }, u5272: { id: "u5272", name: "Japanese \u201Cdiscount\u201D Button", keywords: ["u5272", "discount", "cut", "divide", "chinese", "kanji", "pink", "square"], skins: [{ unified: "1f239", native: "\u{1F239}" }], version: 1 }, u7121: { id: "u7121", name: "Japanese \u201Cfree of Charge\u201D Button", keywords: ["u7121", "free", "charge", "nothing", "chinese", "kanji", "orange", "square"], skins: [{ unified: "1f21a", native: "\u{1F21A}" }], version: 1 }, u7981: { id: "u7981", name: "Japanese \u201Cprohibited\u201D Button", keywords: ["u7981", "prohibited", "kanji", "chinese", "forbidden", "limit", "restricted", "red", "square"], skins: [{ unified: "1f232", native: "\u{1F232}" }], version: 1 }, accept: { id: "accept", name: "Circled Ideograph Accept", keywords: ["japanese", "acceptable", "button", "ok", "good", "chinese", "kanji", "agree", "yes", "orange", "circle"], skins: [{ unified: "1f251", native: "\u{1F251}" }], version: 1 }, u7533: { id: "u7533", name: "Japanese \u201Capplication\u201D Button", keywords: ["u7533", "application", "chinese", "kanji", "orange", "square"], skins: [{ unified: "1f238", native: "\u{1F238}" }], version: 1 }, u5408: { id: "u5408", name: "Japanese \u201Cpassing Grade\u201D Button", keywords: ["u5408", "passing", "grade", "chinese", "join", "kanji", "red", "square"], skins: [{ unified: "1f234", native: "\u{1F234}" }], version: 1 }, u7a7a: { id: "u7a7a", name: "Japanese \u201Cvacancy\u201D Button", keywords: ["u7a7a", "vacancy", "kanji", "chinese", "empty", "sky", "blue", "square"], skins: [{ unified: "1f233", native: "\u{1F233}" }], version: 1 }, congratulations: { id: "congratulations", name: "Circled Ideograph Congratulation", keywords: ["congratulations", "japanese", "button", "chinese", "kanji", "red", "circle"], skins: [{ unified: "3297-fe0f", native: "\u3297\uFE0F" }], version: 1 }, secret: { id: "secret", name: "Circled Ideograph Secret", keywords: ["japanese", "button", "privacy", "chinese", "sshh", "kanji", "red", "circle"], skins: [{ unified: "3299-fe0f", native: "\u3299\uFE0F" }], version: 1 }, u55b6: { id: "u55b6", name: "Squared Cjk Unified Ideograph-55b6", keywords: ["u55b6", "japanese", "open", "for", "business", "button", "opening", "hours", "orange", "square"], skins: [{ unified: "1f23a", native: "\u{1F23A}" }], version: 1 }, u6e80: { id: "u6e80", name: "Japanese \u201Cno Vacancy\u201D Button", keywords: ["u6e80", "no", "vacancy", "full", "chinese", "red", "square", "kanji"], skins: [{ unified: "1f235", native: "\u{1F235}" }], version: 1 }, red_circle: { id: "red_circle", name: "Red Circle", keywords: ["shape", "error", "danger"], skins: [{ unified: "1f534", native: "\u{1F534}" }], version: 1 }, large_orange_circle: { id: "large_orange_circle", name: "Orange Circle", keywords: ["large", "round"], skins: [{ unified: "1f7e0", native: "\u{1F7E0}" }], version: 12 }, large_yellow_circle: { id: "large_yellow_circle", name: "Yellow Cir
51763cle", keywords: ["large", "round"], skins: [{ unified: "1f7e1", native: "\u{1F7E1}" }], version: 12 }, large_green_circle: { id: "large_green_circle", name: "Green Circle", keywords: ["large", "round"], skins: [{ unified: "1f7e2", native: "\u{1F7E2}" }], version: 12 }, large_blue_circle: { id: "large_blue_circle", name: "Blue Circle", keywords: ["large", "shape", "icon", "button"], skins: [{ unified: "1f535", native: "\u{1F535}" }], version: 1 }, large_purple_circle: { id: "large_purple_circle", name: "Purple Circle", keywords: ["large", "round"], skins: [{ unified: "1f7e3", native: "\u{1F7E3}" }], version: 12 }, large_brown_circle: { id: "large_brown_circle", name: "Brown Circle", keywords: ["large", "round"], skins: [{ unified: "1f7e4", native: "\u{1F7E4}" }], version: 12 }, black_circle: { id: "black_circle", name: "Black Circle", keywords: ["shape", "button", "round"], skins: [{ unified: "26ab", native: "\u26AB" }], version: 1 }, white_circle: { id: "white_circle", name: "White Circle", keywords: ["shape", "round"], skins: [{ unified: "26aa", native: "\u26AA" }], version: 1 }, large_red_square: { id: "large_red_square", name: "Red Square", keywords: ["large"], skins: [{ unified: "1f7e5", native: "\u{1F7E5}" }], version: 12 }, large_orange_square: { id: "large_orange_square", name: "Orange Square", keywords: ["large"], skins: [{ unified: "1f7e7", native: "\u{1F7E7}" }], version: 12 }, large_yellow_square: { id: "large_yellow_square", name: "Yellow Square", keywords: ["large"], skins: [{ unified: "1f7e8", native: "\u{1F7E8}" }], version: 12 }, large_green_square: { id: "large_green_square", name: "Green Square", keywords: ["large"], skins: [{ unified: "1f7e9", native: "\u{1F7E9}" }], version: 12 }, large_blue_square: { id: "large_blue_square", name: "Blue Square", keywords: ["large"], skins: [{ unified: "1f7e6", native: "\u{1F7E6}" }], version: 12 }, large_purple_square: { id: "large_purple_square", name: "Purple Square", keywords: ["large"], skins: [{ unified: "1f7ea", native: "\u{1F7EA}" }], version: 12 }, large_brown_square: { id: "large_brown_square", name: "Brown Square", keywords: ["large"], skins: [{ unified: "1f7eb", native: "\u{1F7EB}" }], version: 12 }, black_large_square: { id: "black_large_square", name: "Black Large Square", keywords: ["shape", "icon", "button"], skins: [{ unified: "2b1b", native: "\u2B1B" }], version: 1 }, white_large_square: { id: "white_large_square", name: "White Large Square", keywords: ["shape", "icon", "stone", "button"], skins: [{ unified: "2b1c", native: "\u2B1C" }], version: 1 }, black_medium_square: { id: "black_medium_square", name: "Black Medium Square", keywords: ["shape", "button", "icon"], skins: [{ unified: "25fc-fe0f", native: "\u25FC\uFE0F" }], version: 1 }, white_medium_square: { id: "white_medium_square", name: "White Medium Square", keywords: ["shape", "stone", "icon"], skins: [{ unified: "25fb-fe0f", native: "\u25FB\uFE0F" }], version: 1 }, black_medium_small_square: { id: "black_medium_small_square", name: "Black Medium Small Square", keywords: ["icon", "shape", "button"], skins: [{ unified: "25fe", native: "\u25FE" }], version: 1 }, white_medium_small_square: { id: "white_medium_small_square", name: "White Medium Small Square", keywords: ["shape", "stone", "icon", "button"], skins: [{ unified: "25fd", native: "\u25FD" }], version: 1 }, black_small_square: { id: "black_small_square", name: "Black Small Square", keywords: ["shape", "icon"], skins: [{ unified: "25aa-fe0f", native: "\u25AA\uFE0F" }], version: 1 }, white_small_square: { id: "white_small_square", name: "White Small Square", keywords: ["shape", "icon"], skins: [{ unified: "25ab-fe0f", native: "\u25AB\uFE0F" }], version: 1 }, large_orange_diamond: { id: "large_orange_diamond", name: "Large Orange Diamond", keywords: ["shape", "jewel", "gem"], skins: [{ unified: "1f536", native: "\u{1F536}" }], version: 1 }, large_blue_diamond: { id: "large_blue_diamond", name: "Large Blue Diamond", keywords: ["shape", "jewel", "gem"], skins: [{ unified: "1f537", native: "\u{1F537}" }], version: 1 }, small_orange_diamond: { id: "small_orange_diamond", name: "Small Orange Diamond", keywords: ["shape", "jewel", "gem"], skins: [{ unified: "1f538", native: "\u{1F538}" }], version: 1 }, small_blue_diamond: { id: "small_blue_diamond", name: "Small Blue Diamond", keywords: ["shape", "jewel", "gem"], skins: [{ unified: "1f539", native: "\u{1F539}" }
51763], version: 1 }, small_red_triangle: { id: "small_red_triangle", name: "Red Triangle Pointed Up", keywords: ["small", "shape", "direction", "top"], skins: [{ unified: "1f53a", native: "\u{1F53A}" }], version: 1 }, small_red_triangle_down: { id: "small_red_triangle_down", name: "Red Triangle Pointed Down", keywords: ["small", "shape", "direction", "bottom"], skins: [{ unified: "1f53b", native: "\u{1F53B}" }], version: 1 }, diamond_shape_with_a_dot_inside: { id: "diamond_shape_with_a_dot_inside", name: "Diamond with a Dot", keywords: ["shape", "inside", "jewel", "blue", "gem", "crystal", "fancy"], skins: [{ unified: "1f4a0", native: "\u{1F4A0}" }], version: 1 }, radio_button: { id: "radio_button", name: "Radio Button", keywords: ["input", "old", "music", "circle"], skins: [{ unified: "1f518", native: "\u{1F518}" }], version: 1 }, white_square_button: { id: "white_square_button", name: "White Square Button", keywords: ["shape", "input"], skins: [{ unified: "1f533", native: "\u{1F533}" }], version: 1 }, black_square_button: { id: "black_square_button", name: "Black Square Button", keywords: ["shape", "input", "frame"], skins: [{ unified: "1f532", native: "\u{1F532}" }], version: 1 }, checkered_flag: { id: "checkered_flag", name: "Chequered Flag", keywords: ["checkered", "contest", "finishline", "race", "gokart"], skins: [{ unified: "1f3c1", native: "\u{1F3C1}" }], version: 1 }, triangular_flag_on_post: { id: "triangular_flag_on_post", name: "Triangular Flag", keywords: ["on", "post", "mark", "milestone", "place"], skins: [{ unified: "1f6a9", native: "\u{1F6A9}" }], version: 1 }, crossed_flags: { id: "crossed_flags", name: "Crossed Flags", keywords: ["japanese", "nation", "country", "border"], skins: [{ unified: "1f38c", native: "\u{1F38C}" }], version: 1 }, waving_black_flag: { id: "waving_black_flag", name: "Black Flag", keywords: ["waving", "pirate"], skins: [{ unified: "1f3f4", native: "\u{1F3F4}" }], version: 1 }, waving_white_flag: { id: "waving_white_flag", name: "White Flag", keywords: ["waving", "losing", "loser", "lost", "surrender", "give", "up", "fail"], skins: [{ unified: "1f3f3-fe0f", native: "\u{1F3F3}\uFE0F" }], version: 1 }, "rainbow-flag": { id: "rainbow-flag", name: "Rainbow Flag", keywords: ["pride", "gay", "lgbt", "queer", "homosexual", "lesbian", "bisexual"], skins: [{ unified: "1f3f3-fe0f-200d-1f308", native: "\u{1F3F3}\uFE0F\u200D\u{1F308}" }], version: 4 }, transgender_flag: { id: "transgender_flag", name: "Transgender Flag", keywords: ["pride", "lgbtq"], skins: [{ unified: "1f3f3-fe0f-200d-26a7-fe0f", native: "\u{1F3F3}\uFE0F\u200D\u26A7\uFE0F" }], version: 13 }, pirate_flag: { id: "pirate_flag", name: "Pirate Flag", keywords: ["skull", "crossbones", "banner"], skins: [{ unified: "1f3f4-200d-2620-fe0f", native: "\u{1F3F4}\u200D\u2620\uFE0F" }], version: 11 }, "flag-ac": { id: "flag-ac", name: "Ascension Island Flag", keywords: ["ac"], skins: [{ unified: "1f1e6-1f1e8", native: "\u{1F1E6}\u{1F1E8}" }], version: 2 }, "flag-ad": { id: "flag-ad", name: "Andorra Flag", keywords: ["ad", "nation", "country", "banner"], skins: [{ unified: "1f1e6-1f1e9", native: "\u{1F1E6}\u{1F1E9}" }], version: 2 }, "flag-ae": { id: "flag-ae", name: "United Arab Emirates Flag", keywords: ["ae", "nation", "country", "banner"], skins: [{ unified: "1f1e6-1f1ea", native: "\u{1F1E6}\u{1F1EA}" }], version: 2 }, "flag-af": { id: "flag-af", name: "Afghanistan Flag", keywords: ["af", "nation", "country", "banner"], skins: [{ unified: "1f1e6-1f1eb", native: "\u{1F1E6}\u{1F1EB}" }], version: 2 }, "flag-ag": { id: "flag-ag", name: "Antigua & Barbuda Flag", keywords: ["ag", "nation", "country", "banner"], skins: [{ unified: "1f1e6-1f1ec", native: "\u{1F1E6}\u{1F1EC}" }], version: 2 }, "flag-ai": { id: "flag-ai", name: "Anguilla Flag", keywords: ["ai", "nation", "country", "banner"], skins: [{ unified: "1f1e6-1f1ee", native: "\u{1F1E6}\u{1F1EE}" }], version: 2 }, "flag-al": { id: "flag-al", name: "Albania Flag", keywords: ["al", "nation", "country", "banner"], skins: [{ unified: "1f1e6-1f1f1", native: "\u{1F1E6}\u{1F1F1}" }], version: 2 }, "flag-am": { id: "flag-am", name: "Armenia Flag", keywords: ["am", "nation", "country", "banner"], skins: [{ unified: "1f1e6-1f1f2", native: "\u{1F1E6}\u{1F1F2}" }], version: 2 }, "flag-ao": { id: "flag-ao", name: "Angola Flag", keywords: ["ao", "nation", "country", "banner"], skins: [{ unified: "1f1e6-1f1f4", native: "\u{1F1E6}\u{1F1F4}" }
51763], version: 2 }, "flag-aq": { id: "flag-aq", name: "Antarctica Flag", keywords: ["aq", "nation", "country", "banner"], skins: [{ unified: "1f1e6-1f1f6", native: "\u{1F1E6}\u{1F1F6}" }], version: 2 }, "flag-ar": { id: "flag-ar", name: "Argentina Flag", keywords: ["ar", "nation", "country", "banner"], skins: [{ unified: "1f1e6-1f1f7", native: "\u{1F1E6}\u{1F1F7}" }], version: 2 }, "flag-as": { id: "flag-as", name: "American Samoa Flag", keywords: ["as", "ws", "nation", "country", "banner"], skins: [{ unified: "1f1e6-1f1f8", native: "\u{1F1E6}\u{1F1F8}" }], version: 2 }, "flag-at": { id: "flag-at", name: "Austria Flag", keywords: ["at", "nation", "country", "banner"], skins: [{ unified: "1f1e6-1f1f9", native: "\u{1F1E6}\u{1F1F9}" }], version: 2 }, "flag-au": { id: "flag-au", name: "Australia Flag", keywords: ["au", "nation", "country", "banner"], skins: [{ unified: "1f1e6-1f1fa", native: "\u{1F1E6}\u{1F1FA}" }], version: 2 }, "flag-aw": { id: "flag-aw", name: "Aruba Flag", keywords: ["aw", "nation", "country", "banner"], skins: [{ unified: "1f1e6-1f1fc", native: "\u{1F1E6}\u{1F1FC}" }], version: 2 }, "flag-ax": { id: "flag-ax", name: "\xC5land Islands Flag", keywords: ["ax", "aland", "Aland", "nation", "country", "banner"], skins: [{ unified: "1f1e6-1f1fd", native: "\u{1F1E6}\u{1F1FD}" }], version: 2 }, "flag-az": { id: "flag-az", name: "Azerbaijan Flag", keywords: ["az", "nation", "country", "banner"], skins: [{ unified: "1f1e6-1f1ff", native: "\u{1F1E6}\u{1F1FF}" }], version: 2 }, "flag-ba": { id: "flag-ba", name: "Bosnia & Herzegovina Flag", keywords: ["ba", "nation", "country", "banner"], skins: [{ unified: "1f1e7-1f1e6", native: "\u{1F1E7}\u{1F1E6}" }], version: 2 }, "flag-bb": { id: "flag-bb", name: "Barbados Flag", keywords: ["bb", "nation", "country", "banner"], skins: [{ unified: "1f1e7-1f1e7", native: "\u{1F1E7}\u{1F1E7}" }], version: 2 }, "flag-bd": { id: "flag-bd", name: "Bangladesh Flag", keywords: ["bd", "nation", "country", "banner"], skins: [{ unified: "1f1e7-1f1e9", native: "\u{1F1E7}\u{1F1E9}" }], version: 2 }, "flag-be": { id: "flag-be", name: "Belgium Flag", keywords: ["be", "nation", "country", "banner"], skins: [{ unified: "1f1e7-1f1ea", native: "\u{1F1E7}\u{1F1EA}" }], version: 2 }, "flag-bf": { id: "flag-bf", name: "Burkina Faso Flag", keywords: ["bf", "nation", "country", "banner"], skins: [{ unified: "1f1e7-1f1eb", native: "\u{1F1E7}\u{1F1EB}" }], version: 2 }, "flag-bg": { id: "flag-bg", name: "Bulgaria Flag", keywords: ["bg", "nation", "country", "banner"], skins: [{ unified: "1f1e7-1f1ec", native: "\u{1F1E7}\u{1F1EC}" }], version: 2 }, "flag-bh": { id: "flag-bh", name: "Bahrain Flag", keywords: ["bh", "nation", "country", "banner"], skins: [{ unified: "1f1e7-1f1ed", native: "\u{1F1E7}\u{1F1ED}" }], version: 2 }, "flag-bi": { id: "flag-bi", name: "Burundi Flag", keywords: ["bi", "nation", "country", "banner"], skins: [{ unified: "1f1e7-1f1ee", native: "\u{1F1E7}\u{1F1EE}" }], version: 2 }, "flag-bj": { id: "flag-bj", name: "Benin Flag", keywords: ["bj", "nation", "country", "banner"], skins: [{ unified: "1f1e7-1f1ef", native: "\u{1F1E7}\u{1F1EF}" }], version: 2 }, "flag-bl": { id: "flag-bl", name: "St. Barth\xE9lemy Flag", keywords: ["bl", "st", "barthelemy", "saint", "nation", "country", "banner"], skins: [{ unified: "1f1e7-1f1f1", native: "\u{1F1E7}\u{1F1F1}" }], version: 2 }, "flag-bm": { id: "flag-bm", name: "Bermuda Flag", keywords: ["bm", "nation", "country", "banner"], skins: [{ unified: "1f1e7-1f1f2", native: "\u{1F1E7}\u{1F1F2}" }], version: 2 }, "flag-bn": { id: "flag-bn", name: "Brunei Flag", keywords: ["bn", "darussalam", "nation", "country", "banner"], skins: [{ unified: "1f1e7-1f1f3", native: "\u{1F1E7}\u{1F1F3}" }], version: 2 }, "flag-bo": { id: "flag-bo", name: "Bolivia Flag", keywords: ["bo", "nation", "country", "banner"], skins: [{ unified: "1f1e7-1f1f4", native: "\u{1F1E7}\u{1F1F4}" }
51763], version: 2 }, "flag-bq": { id: "flag-bq", name: "Caribbean Netherlands Flag", keywords: ["bq", "bonaire", "nation", "country", "banner"], skins: [{ unified: "1f1e7-1f1f6", native: "\u{1F1E7}\u{1F1F6}" }], version: 2 }, "flag-br": { id: "flag-br", name: "Brazil Flag", keywords: ["br", "nation", "country", "banner"], skins: [{ unified: "1f1e7-1f1f7", native: "\u{1F1E7}\u{1F1F7}" }], version: 2 }, "flag-bs": { id: "flag-bs", name: "Bahamas Flag", keywords: ["bs", "nation", "country", "banner"], skins: [{ unified: "1f1e7-1f1f8", native: "\u{1F1E7}\u{1F1F8}" }], version: 2 }, "flag-bt": { id: "flag-bt", name: "Bhutan Flag", keywords: ["bt", "nation", "country", "banner"], skins: [{ unified: "1f1e7-1f1f9", native: "\u{1F1E7}\u{1F1F9}" }], version: 2 }, "flag-bv": { id: "flag-bv", name: "Bouvet Island Flag", keywords: ["bv", "norway"], skins: [{ unified: "1f1e7-1f1fb", native: "\u{1F1E7}\u{1F1FB}" }], version: 2 }, "flag-bw": { id: "flag-bw", name: "Botswana Flag", keywords: ["bw", "nation", "country", "banner"], skins: [{ unified: "1f1e7-1f1fc", native: "\u{1F1E7}\u{1F1FC}" }], version: 2 }, "flag-by": { id: "flag-by", name: "Belarus Flag", keywords: ["by", "nation", "country", "banner"], skins: [{ unified: "1f1e7-1f1fe", native: "\u{1F1E7}\u{1F1FE}" }], version: 2 }, "flag-bz": { id: "flag-bz", name: "Belize Flag", keywords: ["bz", "nation", "country", "banner"], skins: [{ unified: "1f1e7-1f1ff", native: "\u{1F1E7}\u{1F1FF}" }], version: 2 }, "flag-ca": { id: "flag-ca", name: "Canada Flag", keywords: ["ca", "nation", "country", "banner"], skins: [{ unified: "1f1e8-1f1e6", native: "\u{1F1E8}\u{1F1E6}" }], version: 2 }, "flag-cc": { id: "flag-cc", name: "Cocos (keeling) Islands Flag", keywords: ["cc", "keeling", "nation", "country", "banner"], skins: [{ unified: "1f1e8-1f1e8", native: "\u{1F1E8}\u{1F1E8}" }], version: 2 }, "flag-cd": { id: "flag-cd", name: "Congo - Kinshasa Flag", keywords: ["cd", "democratic", "republic", "nation", "country", "banner"], skins: [{ unified: "1f1e8-1f1e9", native: "\u{1F1E8}\u{1F1E9}" }], version: 2 }, "flag-cf": { id: "flag-cf", name: "Central African Republic Flag", keywords: ["cf", "nation", "country", "banner"], skins: [{ unified: "1f1e8-1f1eb", native: "\u{1F1E8}\u{1F1EB}" }], version: 2 }, "flag-cg": { id: "flag-cg", name: "Congo - Brazzaville Flag", keywords: ["cg", "nation", "country", "banner"], skins: [{ unified: "1f1e8-1f1ec", native: "\u{1F1E8}\u{1F1EC}" }], version: 2 }, "flag-ch": { id: "flag-ch", name: "Switzerland Flag", keywords: ["ch", "nation", "country", "banner"], skins: [{ unified: "1f1e8-1f1ed", native: "\u{1F1E8}\u{1F1ED}" }], version: 2 }, "flag-ci": { id: "flag-ci", name: "C\xF4te D\u2019ivoire Flag", keywords: ["ci", "cote", "d", "ivoire", "ivory", "coast", "nation", "country", "banner"], skins: [{ unified: "1f1e8-1f1ee", native: "\u{1F1E8}\u{1F1EE}" }], version: 2 }, "flag-ck": { id: "flag-ck", name: "Cook Islands Flag", keywords: ["ck", "nation", "country", "banner"], skins: [{ unified: "1f1e8-1f1f0", native: "\u{1F1E8}\u{1F1F0}" }], version: 2 }, "flag-cl": { id: "flag-cl", name: "Chile Flag", keywords: ["cl", "nation", "country", "banner"], skins: [{ unified: "1f1e8-1f1f1", native: "\u{1F1E8}\u{1F1F1}" }], version: 2 }, "flag-cm": { id: "flag-cm", name: "Cameroon Flag", keywords: ["cm", "nation", "country", "banner"], skins: [{ unified: "1f1e8-1f1f2", native: "\u{1F1E8}\u{1F1F2}" }], version: 2 }, cn: { id: "cn", name: "China Flag", keywords: ["cn", "chinese", "prc", "country", "nation", "banner"], skins: [{ unified: "1f1e8-1f1f3", native: "\u{1F1E8}\u{1F1F3}" }], version: 1 }, "flag-co": { id: "flag-co", name: "Colombia Flag", keywords: ["co", "nation", "country", "banner"], skins: [{ unified: "1f1e8-1f1f4", native: "\u{1F1E8}\u{1F1F4}" }
51763], version: 2 }, "flag-cp": { id: "flag-cp", name: "Clipperton Island Flag", keywords: ["cp"], skins: [{ unified: "1f1e8-1f1f5", native: "\u{1F1E8}\u{1F1F5}" }], version: 2 }, "flag-sark": { id: "flag-sark", name: "Sark Flag", keywords: [], skins: [{ unified: "1f1e8-1f1f6", native: "\u{1F1E8}\u{1F1F6}" }], version: 16 }, "flag-cr": { id: "flag-cr", name: "Costa Rica Flag", keywords: ["cr", "nation", "country", "banner"], skins: [{ unified: "1f1e8-1f1f7", native: "\u{1F1E8}\u{1F1F7}" }], version: 2 }, "flag-cu": { id: "flag-cu", name: "Cuba Flag", keywords: ["cu", "nation", "country", "banner"], skins: [{ unified: "1f1e8-1f1fa", native: "\u{1F1E8}\u{1F1FA}" }], version: 2 }, "flag-cv": { id: "flag-cv", name: "Cape Verde Flag", keywords: ["cv", "cabo", "nation", "country", "banner"], skins: [{ unified: "1f1e8-1f1fb", native: "\u{1F1E8}\u{1F1FB}" }], version: 2 }, "flag-cw": { id: "flag-cw", name: "Cura\xE7ao Flag", keywords: ["cw", "curacao", "nation", "country", "banner"], skins: [{ unified: "1f1e8-1f1fc", native: "\u{1F1E8}\u{1F1FC}" }], version: 2 }, "flag-cx": { id: "flag-cx", name: "Christmas Island Flag", keywords: ["cx", "nation", "country", "banner"], skins: [{ unified: "1f1e8-1f1fd", native: "\u{1F1E8}\u{1F1FD}" }], version: 2 }, "flag-cy": { id: "flag-cy", name: "Cyprus Flag", keywords: ["cy", "nation", "country", "banner"], skins: [{ unified: "1f1e8-1f1fe", native: "\u{1F1E8}\u{1F1FE}" }], version: 2 }, "flag-cz": { id: "flag-cz", name: "Czechia Flag", keywords: ["cz", "nation", "country", "banner"], skins: [{ unified: "1f1e8-1f1ff", native: "\u{1F1E8}\u{1F1FF}" }], version: 2 }, de: { id: "de", name: "Germany Flag", keywords: ["de", "german", "nation", "country", "banner"], skins: [{ unified: "1f1e9-1f1ea", native: "\u{1F1E9}\u{1F1EA}" }], version: 1 }, "flag-dg": { id: "flag-dg", name: "Diego Garcia Flag", keywords: ["dg"], skins: [{ unified: "1f1e9-1f1ec", native: "\u{1F1E9}\u{1F1EC}" }], version: 2 }, "flag-dj": { id: "flag-dj", name: "Djibouti Flag", keywords: ["dj", "nation", "country", "banner"], skins: [{ unified: "1f1e9-1f1ef", native: "\u{1F1E9}\u{1F1EF}" }], version: 2 }, "flag-dk": { id: "flag-dk", name: "Denmark Flag", keywords: ["dk", "nation", "country", "banner"], skins: [{ unified: "1f1e9-1f1f0", native: "\u{1F1E9}\u{1F1F0}" }], version: 2 }, "flag-dm": { id: "flag-dm", name: "Dominica Flag", keywords: ["dm", "nation", "country", "banner"], skins: [{ unified: "1f1e9-1f1f2", native: "\u{1F1E9}\u{1F1F2}" }], version: 2 }, "flag-do": { id: "flag-do", name: "Dominican Republic Flag", keywords: ["do", "nation", "country", "banner"], skins: [{ unified: "1f1e9-1f1f4", native: "\u{1F1E9}\u{1F1F4}" }
51763], version: 2 }, "flag-dz": { id: "flag-dz", name: "Algeria Flag", keywords: ["dz", "nation", "country", "banner"], skins: [{ unified: "1f1e9-1f1ff", native: "\u{1F1E9}\u{1F1FF}" }], version: 2 }, "flag-ea": { id: "flag-ea", name: "Ceuta & Melilla Flag", keywords: ["ea"], skins: [{ unified: "1f1ea-1f1e6", native: "\u{1F1EA}\u{1F1E6}" }], version: 2 }, "flag-ec": { id: "flag-ec", name: "Ecuador Flag", keywords: ["ec", "nation", "country", "banner"], skins: [{ unified: "1f1ea-1f1e8", native: "\u{1F1EA}\u{1F1E8}" }], version: 2 }, "flag-ee": { id: "flag-ee", name: "Estonia Flag", keywords: ["ee", "nation", "country", "banner"], skins: [{ unified: "1f1ea-1f1ea", native: "\u{1F1EA}\u{1F1EA}" }], version: 2 }, "flag-eg": { id: "flag-eg", name: "Egypt Flag", keywords: ["eg", "nation", "country", "banner"], skins: [{ unified: "1f1ea-1f1ec", native: "\u{1F1EA}\u{1F1EC}" }], version: 2 }, "flag-eh": { id: "flag-eh", name: "Western Sahara Flag", keywords: ["eh", "nation", "country", "banner"], skins: [{ unified: "1f1ea-1f1ed", native: "\u{1F1EA}\u{1F1ED}" }], version: 2 }, "flag-er": { id: "flag-er", name: "Eritrea Flag", keywords: ["er", "nation", "country", "banner"], skins: [{ unified: "1f1ea-1f1f7", native: "\u{1F1EA}\u{1F1F7}" }], version: 2 }, es: { id: "es", name: "Spain Flag", keywords: ["es", "nation", "country", "banner"], skins: [{ unified: "1f1ea-1f1f8", native: "\u{1F1EA}\u{1F1F8}" }], version: 1 }, "flag-et": { id: "flag-et", name: "Ethiopia Flag", keywords: ["et", "nation", "country", "banner"], skins: [{ unified: "1f1ea-1f1f9", native: "\u{1F1EA}\u{1F1F9}" }], version: 2 }, "flag-eu": { id: "flag-eu", name: "European Union Flag", keywords: ["eu", "banner"], skins: [{ unified: "1f1ea-1f1fa", native: "\u{1F1EA}\u{1F1FA}" }], version: 2 }, "flag-fi": { id: "flag-fi", name: "Finland Flag", keywords: ["fi", "nation", "country", "banner"], skins: [{ unified: "1f1eb-1f1ee", native: "\u{1F1EB}\u{1F1EE}" }], version: 2 }, "flag-fj": { id: "flag-fj", name: "Fiji Flag", keywords: ["fj", "nation", "country", "banner"], skins: [{ unified: "1f1eb-1f1ef", native: "\u{1F1EB}\u{1F1EF}" }], version: 2 }, "flag-fk": { id: "flag-fk", name: "Falkland Islands Flag", keywords: ["fk", "malvinas", "nation", "country", "banner"], skins: [{ unified: "1f1eb-1f1f0", native: "\u{1F1EB}\u{1F1F0}" }], version: 2 }, "flag-fm": { id: "flag-fm", name: "Micronesia Flag", keywords: ["fm", "federated", "states", "nation", "country", "banner"], skins: [{ unified: "1f1eb-1f1f2", native: "\u{1F1EB}\u{1F1F2}" }], version: 2 }, "flag-fo": { id: "flag-fo", name: "Faroe Islands Flag", keywords: ["fo", "nation", "country", "banner"], skins: [{ unified: "1f1eb-1f1f4", native: "\u{1F1EB}\u{1F1F4}" }
51763], version: 2 }, fr: { id: "fr", name: "France Flag", keywords: ["fr", "banner", "nation", "french", "country"], skins: [{ unified: "1f1eb-1f1f7", native: "\u{1F1EB}\u{1F1F7}" }], version: 1 }, "flag-ga": { id: "flag-ga", name: "Gabon Flag", keywords: ["ga", "nation", "country", "banner"], skins: [{ unified: "1f1ec-1f1e6", native: "\u{1F1EC}\u{1F1E6}" }], version: 2 }, gb: { id: "gb", name: "United Kingdom Flag", keywords: ["gb", "uk", "great", "britain", "northern", "ireland", "nation", "country", "banner", "british", "UK", "english", "england", "union", "jack"], skins: [{ unified: "1f1ec-1f1e7", native: "\u{1F1EC}\u{1F1E7}" }], version: 1 }, "flag-gd": { id: "flag-gd", name: "Grenada Flag", keywords: ["gd", "nation", "country", "banner"], skins: [{ unified: "1f1ec-1f1e9", native: "\u{1F1EC}\u{1F1E9}" }], version: 2 }, "flag-ge": { id: "flag-ge", name: "Georgia Flag", keywords: ["ge", "nation", "country", "banner"], skins: [{ unified: "1f1ec-1f1ea", native: "\u{1F1EC}\u{1F1EA}" }], version: 2 }, "flag-gf": { id: "flag-gf", name: "French Guiana Flag", keywords: ["gf", "nation", "country", "banner"], skins: [{ unified: "1f1ec-1f1eb", native: "\u{1F1EC}\u{1F1EB}" }], version: 2 }, "flag-gg": { id: "flag-gg", name: "Guernsey Flag", keywords: ["gg", "nation", "country", "banner"], skins: [{ unified: "1f1ec-1f1ec", native: "\u{1F1EC}\u{1F1EC}" }], version: 2 }, "flag-gh": { id: "flag-gh", name: "Ghana Flag", keywords: ["gh", "nation", "country", "banner"], skins: [{ unified: "1f1ec-1f1ed", native: "\u{1F1EC}\u{1F1ED}" }], version: 2 }, "flag-gi": { id: "flag-gi", name: "Gibraltar Flag", keywords: ["gi", "nation", "country", "banner"], skins: [{ unified: "1f1ec-1f1ee", native: "\u{1F1EC}\u{1F1EE}" }], version: 2 }, "flag-gl": { id: "flag-gl", name: "Greenland Flag", keywords: ["gl", "nation", "country", "banner"], skins: [{ unified: "1f1ec-1f1f1", native: "\u{1F1EC}\u{1F1F1}" }], version: 2 }, "flag-gm": { id: "flag-gm", name: "Gambia Flag", keywords: ["gm", "nation", "country", "banner"], skins: [{ unified: "1f1ec-1f1f2", native: "\u{1F1EC}\u{1F1F2}" }], version: 2 }, "flag-gn": { id: "flag-gn", name: "Guinea Flag", keywords: ["gn", "nation", "country", "banner"], skins: [{ unified: "1f1ec-1f1f3", native: "\u{1F1EC}\u{1F1F3}" }], version: 2 }, "flag-gp": { id: "flag-gp", name: "Guadeloupe Flag", keywords: ["gp", "nation", "country", "banner"], skins: [{ unified: "1f1ec-1f1f5", native: "\u{1F1EC}\u{1F1F5}" }], version: 2 }, "flag-gq": { id: "flag-gq", name: "Equatorial Guinea Flag", keywords: ["gq", "gn", "nation", "country", "banner"], skins: [{ unified: "1f1ec-1f1f6", native: "\u{1F1EC}\u{1F1F6}" }], version: 2 }, "flag-gr": { id: "flag-gr", name: "Greece Flag", keywords: ["gr", "nation", "country", "banner"], skins: [{ unified: "1f1ec-1f1f7", native: "\u{1F1EC}\u{1F1F7}" }], version: 2 }, "flag-gs": { id: "flag-gs", name: "South Georgia & South Sandwich Islands Flag", keywords: ["gs", "nation", "country", "banner"], skins: [{ unified: "1f1ec-1f1f8", native: "\u{1F1EC}\u{1F1F8}" }], version: 2 }, "flag-gt": { id: "flag-gt", name: "Guatemala Flag", keywords: ["gt", "nation", "country", "banner"], skins: [{ unified: "1f1ec-1f1f9", native: "\u{1F1EC}\u{1F1F9}" }], version: 2 }, "flag-gu": { id: "flag-gu", name: "Guam Flag", keywords: ["gu", "nation", "country", "banner"], skins: [{ unified: "1f1ec-1f1fa", native: "\u{1F1EC}\u{1F1FA}" }], version: 2 }, "flag-gw": { id: "flag-gw", name: "Guinea-Bissau Flag", keywords: ["gw", "guinea", "bissau", "nation", "country", "banner"], skins: [{ unified: "1f1ec-1f1fc", native: "\u{1F1EC}\u{1F1FC}" }], version: 2 }, "flag-gy": { id: "flag-gy", name: "Guyana Flag", keywords: ["gy", "nation", "country", "banner"], skins: [{ unified: "1f1ec-1f1fe", native: "\u{1F1EC}\u{1F1FE}" }], version: 2 }, "flag-hk": { id: "flag-hk", name: "Hong Kong Sar China Flag", keywords: ["hk", "nation", "country", "banner"], skins: [{ unified: "1f1ed-1f1f0", native: "\u{1F1ED}\u{1F1F0}" }], version: 2 }, "flag-hm": { id: "flag-hm", name: "Heard & Mcdonald Islands Flag", keywords: ["hm"], skins: [{ unified: "1f1ed-1f1f2", native: "\u{1F1ED}\u{1F1F2}" }], version: 2 }, "flag-hn": { id: "flag-hn", name: "Honduras Flag", keywords: ["hn", "nation", "country", "banner"], skins: [{ unified: "1f1ed-1f1f3", native: "\u{1F1ED}\u{1F1F3}" }], version: 2 }, "flag-hr": { id: "flag-hr", name: "Croatia Flag", keywords: ["hr", "nation", "country", "banner"], skins: [{ unified: "1f1ed-1f1f7", native: "\u{1F1ED}\u{1F1F7}" }], version: 2 }, "flag-ht": { id: "flag-ht", name: "Haiti Flag", keywords: ["ht", "n
51763ation", "country", "banner"], skins: [{ unified: "1f1ed-1f1f9", native: "\u{1F1ED}\u{1F1F9}" }], version: 2 }, "flag-hu": { id: "flag-hu", name: "Hungary Flag", keywords: ["hu", "nation", "country", "banner"], skins: [{ unified: "1f1ed-1f1fa", native: "\u{1F1ED}\u{1F1FA}" }], version: 2 }, "flag-ic": { id: "flag-ic", name: "Canary Islands Flag", keywords: ["ic", "nation", "country", "banner"], skins: [{ unified: "1f1ee-1f1e8", native: "\u{1F1EE}\u{1F1E8}" }], version: 2 }, "flag-id": { id: "flag-id", name: "Indonesia Flag", keywords: ["id", "nation", "country", "banner"], skins: [{ unified: "1f1ee-1f1e9", native: "\u{1F1EE}\u{1F1E9}" }], version: 2 }, "flag-ie": { id: "flag-ie", name: "Ireland Flag", keywords: ["ie", "nation", "country", "banner"], skins: [{ unified: "1f1ee-1f1ea", native: "\u{1F1EE}\u{1F1EA}" }], version: 2 }, "flag-il": { id: "flag-il", name: "Israel Flag", keywords: ["il", "nation", "country", "banner"], skins: [{ unified: "1f1ee-1f1f1", native: "\u{1F1EE}\u{1F1F1}" }], version: 2 }, "flag-im": { id: "flag-im", name: "Isle of Man Flag", keywords: ["im", "nation", "country", "banner"], skins: [{ unified: "1f1ee-1f1f2", native: "\u{1F1EE}\u{1F1F2}" }], version: 2 }, "flag-in": { id: "flag-in", name: "India Flag", keywords: ["in", "nation", "country", "banner"], skins: [{ unified: "1f1ee-1f1f3", native: "\u{1F1EE}\u{1F1F3}" }], version: 2 }, "flag-io": { id: "flag-io", name: "British Indian Ocean Territory Flag", keywords: ["io", "nation", "country", "banner"], skins: [{ unified: "1f1ee-1f1f4", native: "\u{1F1EE}\u{1F1F4}" }
51763], version: 2 }, "flag-iq": { id: "flag-iq", name: "Iraq Flag", keywords: ["iq", "nation", "country", "banner"], skins: [{ unified: "1f1ee-1f1f6", native: "\u{1F1EE}\u{1F1F6}" }], version: 2 }, "flag-ir": { id: "flag-ir", name: "Iran Flag", keywords: ["ir", "islamic", "republic", "nation", "country", "banner"], skins: [{ unified: "1f1ee-1f1f7", native: "\u{1F1EE}\u{1F1F7}" }], version: 2 }, "flag-is": { id: "flag-is", name: "Iceland Flag", keywords: ["is", "nation", "country", "banner"], skins: [{ unified: "1f1ee-1f1f8", native: "\u{1F1EE}\u{1F1F8}" }], version: 2 }, it: { id: "it", name: "Italy Flag", keywords: ["it", "nation", "country", "banner"], skins: [{ unified: "1f1ee-1f1f9", native: "\u{1F1EE}\u{1F1F9}" }], version: 1 }, "flag-je": { id: "flag-je", name: "Jersey Flag", keywords: ["je", "nation", "country", "banner"], skins: [{ unified: "1f1ef-1f1ea", native: "\u{1F1EF}\u{1F1EA}" }], version: 2 }, "flag-jm": { id: "flag-jm", name: "Jamaica Flag", keywords: ["jm", "nation", "country", "banner"], skins: [{ unified: "1f1ef-1f1f2", native: "\u{1F1EF}\u{1F1F2}" }], version: 2 }, "flag-jo": { id: "flag-jo", name: "Jordan Flag", keywords: ["jo", "nation", "country", "banner"], skins: [{ unified: "1f1ef-1f1f4", native: "\u{1F1EF}\u{1F1F4}" }
51763], version: 2 }, jp: { id: "jp", name: "Japan Flag", keywords: ["jp", "japanese", "nation", "country", "banner", "ja"], skins: [{ unified: "1f1ef-1f1f5", native: "\u{1F1EF}\u{1F1F5}" }], version: 1 }, "flag-ke": { id: "flag-ke", name: "Kenya Flag", keywords: ["ke", "nation", "country", "banner"], skins: [{ unified: "1f1f0-1f1ea", native: "\u{1F1F0}\u{1F1EA}" }], version: 2 }, "flag-kg": { id: "flag-kg", name: "Kyrgyzstan Flag", keywords: ["kg", "nation", "country", "banner"], skins: [{ unified: "1f1f0-1f1ec", native: "\u{1F1F0}\u{1F1EC}" }], version: 2 }, "flag-kh": { id: "flag-kh", name: "Cambodia Flag", keywords: ["kh", "nation", "country", "banner"], skins: [{ unified: "1f1f0-1f1ed", native: "\u{1F1F0}\u{1F1ED}" }], version: 2 }, "flag-ki": { id: "flag-ki", name: "Kiribati Flag", keywords: ["ki", "nation", "country", "banner"], skins: [{ unified: "1f1f0-1f1ee", native: "\u{1F1F0}\u{1F1EE}" }], version: 2 }, "flag-km": { id: "flag-km", name: "Comoros Flag", keywords: ["km", "nation", "country", "banner"], skins: [{ unified: "1f1f0-1f1f2", native: "\u{1F1F0}\u{1F1F2}" }], version: 2 }, "flag-kn": { id: "flag-kn", name: "St. Kitts & Nevis Flag", keywords: ["kn", "st", "saint", "nation", "country", "banner"], skins: [{ unified: "1f1f0-1f1f3", native: "\u{1F1F0}\u{1F1F3}" }], version: 2 }, "flag-kp": { id: "flag-kp", name: "North Korea Flag", keywords: ["kp", "nation", "country", "banner"], skins: [{ unified: "1f1f0-1f1f5", native: "\u{1F1F0}\u{1F1F5}" }], version: 2 }, kr: { id: "kr", name: "South Korea Flag", keywords: ["kr", "nation", "country", "banner"], skins: [{ unified: "1f1f0-1f1f7", native: "\u{1F1F0}\u{1F1F7}" }], version: 1 }, "flag-kw": { id: "flag-kw", name: "Kuwait Flag", keywords: ["kw", "nation", "country", "banner"], skins: [{ unified: "1f1f0-1f1fc", native: "\u{1F1F0}\u{1F1FC}" }], version: 2 }, "flag-ky": { id: "flag-ky", name: "Cayman Islands Flag", keywords: ["ky", "nation", "country", "banner"], skins: [{ unified: "1f1f0-1f1fe", native: "\u{1F1F0}\u{1F1FE}" }], version: 2 }, "flag-kz": { id: "flag-kz", name: "Kazakhstan Flag", keywords: ["kz", "nation", "country", "banner"], skins: [{ unified: "1f1f0-1f1ff", native: "\u{1F1F0}\u{1F1FF}" }], version: 2 }, "flag-la": { id: "flag-la", name: "Laos Flag", keywords: ["la", "lao", "democratic", "republic", "nation", "country", "banner"], skins: [{ unified: "1f1f1-1f1e6", native: "\u{1F1F1}\u{1F1E6}" }], version: 2 }, "flag-lb": { id: "flag-lb", name: "Lebanon Flag", keywords: ["lb", "nation", "country", "banner"], skins: [{ unified: "1f1f1-1f1e7", native: "\u{1F1F1}\u{1F1E7}" }], version: 2 }, "flag-lc": { id: "flag-lc", name: "St. Lucia Flag", keywords: ["lc", "st", "saint", "nation", "country", "banner"], skins: [{ unified: "1f1f1-1f1e8", native: "\u{1F1F1}\u{1F1E8}" }], version: 2 }, "flag-li": { id: "flag-li", name: "Liechtenstein Flag", keywords: ["li", "nation", "country", "banner"], skins: [{ unified: "1f1f1-1f1ee", native: "\u{1F1F1}\u{1F1EE}" }], version: 2 }, "flag-lk": { id: "flag-lk", name: "Sri Lanka Flag", keywords: ["lk", "nation", "country", "banner"], skins: [{ unified: "1f1f1-1f1f0", native: "\u{1F1F1}\u{1F1F0}" }], version: 2 }, "flag-lr": { id: "flag-lr", name: "Liberia Flag", keywords: ["lr", "nation", "country", "banner"], skins: [{ unified: "1f1f1-1f1f7", native: "\u{1F1F1}\u{1F1F7}" }], version: 2 }, "flag-ls": { id: "flag-ls", name: "Lesotho Flag", keywords: ["ls", "nation", "country", "banner"], skins: [{ unified: "1f1f1-1f1f8", native: "\u{1F1F1}\u{1F1F8}" }], version: 2 }, "flag-lt": { id: "flag-lt", name: "Lithuania Flag", keywords: ["lt", "nation", "country", "banner"], skins: [{ unified: "1f1f1-1f1f9", native: "\u{1F1F1}\u{1F1F9}" }], version: 2 }, "flag-lu": { id: "flag-lu", name: "Luxembourg Flag", keywords: ["lu", "nation", "country", "banner"], skins: [{ unified: "1f1f1-1f1fa", native: "\u{1F1F1}\u{1F1FA}" }], version: 2 }, "flag-lv": { id: "flag-lv", name: "Latvia Flag", keywords: ["lv", "nation", "country", "banner"], skins: [{ unified: "1f1f1-1f1fb", native: "\u{1F1F1}\u{1F1FB}" }], version: 2 }, "flag-ly": { id: "flag-ly", name: "Libya Flag", keywords: ["ly", "nation", "country", "banner"], skins: [{ unified: "1f1f1-1f1fe", native: "\u{1F1F1}\u{1F1FE}" }], version: 2 }, "flag-ma": { id: "flag-ma", name: "Morocco Flag", keywords: ["ma", "nation", "country", "banner"], skins: [{ unified: "1f1f2-1f1e6", native: "\u{1F1F2}\u{1F1E6}" }], version: 2 }, "flag-mc": { id: "flag-mc", name: "Monaco Flag", keywords: ["mc", "nation", "country", "banner"], skins: [{ unified: "1f1f2-1f1e8", native: "\u{1F1F2}\u{1F1E8}" }], version: 2 }, "flag-md": { id: "flag-md", name: "Moldova Flag", keywords: ["md", "republic", "nation", "country", "banner"], skins: [{ unified: "1f1f2-1f1e9", native: "\u{1F1F2}\u{1F1E9}" }], version: 2 }, "flag-me": { id: "flag-me", name: "Montenegro Flag", keywords: ["me", "nation", "country", "banner"], skins: [{ unified: "1f1f2-1f1ea", native: "\u{1F1F2}\u{1F1EA}" }], version: 2 }, "flag-mf": { id: "flag-mf", name: "St. Martin Flag", keywords: ["mf", "st"], skins: [{ unified: "1f1f2-1f1eb", native: "\u{1F1F2}\u{1F1EB}" }], version: 2 }, "flag-mg": { id: "flag-mg", name: "Madagascar Flag", keywords: ["mg", "nation", "country", "banner"], skins: [{ unified: "1f1f2-1f1ec", native: "\u{1F1F2}\u{1F1EC}" }], version: 2 }, "flag-mh": { id: "flag-mh", name: "Marshall Islands Flag", keywords: ["mh", "nation", "country", "banner"], skins: [{ unified: "1f1f2-1f1ed", native: "\u{1F1F2}\u{1F1ED}" }], version: 2 }, "flag-mk": { id: "flag-mk", name: "North Macedonia Flag", keywords: ["mk", "nation", "country", "banner"], skins: [{ unified: "1f1f2-1f1f0", native: "\u{1F1F2}\u{1F1F0}" }], version: 2 }, "flag-ml": { id: "flag-ml", name: "Mali Flag", keywords: ["ml", "nation", "country", "banner"], skins: [{ unified: "1f1f2-1f1f1", native: "\u{1F1F2}\u{1F1F1}" }], version: 2 }, "flag-mm": { id: "flag-mm", name: "Myanmar (burma) Flag", keywords: ["mm", "n
51763ation", "country", "banner"], skins: [{ unified: "1f1f2-1f1f2", native: "\u{1F1F2}\u{1F1F2}" }], version: 2 }, "flag-mn": { id: "flag-mn", name: "Mongolia Flag", keywords: ["mn", "nation", "country", "banner"], skins: [{ unified: "1f1f2-1f1f3", native: "\u{1F1F2}\u{1F1F3}" }], version: 2 }, "flag-mo": { id: "flag-mo", name: "Macao Sar China Flag", keywords: ["mo", "nation", "country", "banner"], skins: [{ unified: "1f1f2-1f1f4", native: "\u{1F1F2}\u{1F1F4}" }], version: 2 }, "flag-mp": { id: "flag-mp", name: "Northern Mariana Islands Flag", keywords: ["mp", "nation", "country", "banner"], skins: [{ unified: "1f1f2-1f1f5", native: "\u{1F1F2}\u{1F1F5}" }], version: 2 }, "flag-mq": { id: "flag-mq", name: "Martinique Flag", keywords: ["mq", "nation", "country", "banner"], skins: [{ unified: "1f1f2-1f1f6", native: "\u{1F1F2}\u{1F1F6}" }], version: 2 }, "flag-mr": { id: "flag-mr", name: "Mauritania Flag", keywords: ["mr", "nation", "country", "banner"], skins: [{ unified: "1f1f2-1f1f7", native: "\u{1F1F2}\u{1F1F7}" }], version: 2 }, "flag-ms": { id: "flag-ms", name: "Montserrat Flag", keywords: ["ms", "nation", "country", "banner"], skins: [{ unified: "1f1f2-1f1f8", native: "\u{1F1F2}\u{1F1F8}" }], version: 2 }, "flag-mt": { id: "flag-mt", name: "Malta Flag", keywords: ["mt", "nation", "country", "banner"], skins: [{ unified: "1f1f2-1f1f9", native: "\u{1F1F2}\u{1F1F9}" }], version: 2 }, "flag-mu": { id: "flag-mu", name: "Mauritius Flag", keywords: ["mu", "nation", "country", "banner"], skins: [{ unified: "1f1f2-1f1fa", native: "\u{1F1F2}\u{1F1FA}" }], version: 2 }, "flag-mv": { id: "flag-mv", name: "Maldives Flag", keywords: ["mv", "nation", "country", "banner"], skins: [{ unified: "1f1f2-1f1fb", native: "\u{1F1F2}\u{1F1FB}" }], version: 2 }, "flag-mw": { id: "flag-mw", name: "Malawi Flag", keywords: ["mw", "nation", "country", "banner"], skins: [{ unified: "1f1f2-1f1fc", native: "\u{1F1F2}\u{1F1FC}" }], version: 2 }, "flag-mx": { id: "flag-mx", name: "Mexico Flag", keywords: ["mx", "nation", "country", "banner"], skins: [{ unified: "1f1f2-1f1fd", native: "\u{1F1F2}\u{1F1FD}" }], version: 2 }, "flag-my": { id: "flag-my", name: "Malaysia Flag", keywords: ["my", "nation", "country", "banner"], skins: [{ unified: "1f1f2-1f1fe", native: "\u{1F1F2}\u{1F1FE}" }], version: 2 }, "flag-mz": { id: "flag-mz", name: "Mozambique Flag", keywords: ["mz", "nation", "country", "banner"], skins: [{ unified: "1f1f2-1f1ff", native: "\u{1F1F2}\u{1F1FF}" }], version: 2 }, "flag-na": { id: "flag-na", name: "Namibia Flag", keywords: ["na", "nation", "country", "banner"], skins: [{ unified: "1f1f3-1f1e6", native: "\u{1F1F3}\u{1F1E6}" }], version: 2 }, "flag-nc": { id: "flag-nc", name: "New Caledonia Flag", keywords: ["nc", "nation", "country", "banner"], skins: [{ unified: "1f1f3-1f1e8", native: "\u{1F1F3}\u{1F1E8}" }], version: 2 }, "flag-ne": { id: "flag-ne", name: "Niger Flag", keywords: ["ne", "nation", "country", "banner"], skins: [{ unified: "1f1f3-1f1ea", native: "\u{1F1F3}\u{1F1EA}" }], version: 2 }, "flag-nf": { id: "flag-nf", name: "Norfolk Island Flag", keywords: ["nf", "nation", "country", "banner"], skins: [{ unified: "1f1f3-1f1eb", native: "\u{1F1F3}\u{1F1EB}" }], version: 2 }, "flag-ng": { id: "flag-ng", name: "Nigeria Flag", keywords: ["ng", "nation", "country", "banner"], skins: [{ unified: "1f1f3-1f1ec", native: "\u{1F1F3}\u{1F1EC}" }], version: 2 }, "flag-ni": { id: "flag-ni", name: "Nicaragua Flag", keywords: ["ni", "nation", "country", "banner"], skins: [{ unified: "1f1f3-1f1ee", native: "\u{1F1F3}\u{1F1EE}" }], version: 2 }, "flag-nl": { id: "flag-nl", name: "Netherlands Flag", keywords: ["nl", "nation", "country", "banner"], skins: [{ unified: "1f1f3-1f1f1", native: "\u{1F1F3}\u{1F1F1}" }], version: 2 }, "flag-no": { id: "flag-no", name: "Norway Flag", keywords: ["no", "nation", "country", "banner"], skins: [{ unified: "1f1f3-1f1f4", native: "\u{1F1F3}\u{1F1F4}" }
51763], version: 2 }, "flag-np": { id: "flag-np", name: "Nepal Flag", keywords: ["np", "nation", "country", "banner"], skins: [{ unified: "1f1f3-1f1f5", native: "\u{1F1F3}\u{1F1F5}" }], version: 2 }, "flag-nr": { id: "flag-nr", name: "Nauru Flag", keywords: ["nr", "nation", "country", "banner"], skins: [{ unified: "1f1f3-1f1f7", native: "\u{1F1F3}\u{1F1F7}" }], version: 2 }, "flag-nu": { id: "flag-nu", name: "Niue Flag", keywords: ["nu", "nation", "country", "banner"], skins: [{ unified: "1f1f3-1f1fa", native: "\u{1F1F3}\u{1F1FA}" }], version: 2 }, "flag-nz": { id: "flag-nz", name: "New Zealand Flag", keywords: ["nz", "nation", "country", "banner"], skins: [{ unified: "1f1f3-1f1ff", native: "\u{1F1F3}\u{1F1FF}" }], version: 2 }, "flag-om": { id: "flag-om", name: "Oman Flag", keywords: ["om", "symbol", "nation", "country", "banner"], skins: [{ unified: "1f1f4-1f1f2", native: "\u{1F1F4}\u{1F1F2}" }], version: 2 }, "flag-pa": { id: "flag-pa", name: "Panama Flag", keywords: ["pa", "nation", "country", "banner"], skins: [{ unified: "1f1f5-1f1e6", native: "\u{1F1F5}\u{1F1E6}" }], version: 2 }, "flag-pe": { id: "flag-pe", name: "Peru Flag", keywords: ["pe", "nation", "country", "banner"], skins: [{ unified: "1f1f5-1f1ea", native: "\u{1F1F5}\u{1F1EA}" }], version: 2 }, "flag-pf": { id: "flag-pf", name: "French Polynesia Flag", keywords: ["pf", "nation", "country", "banner"], skins: [{ unified: "1f1f5-1f1eb", native: "\u{1F1F5}\u{1F1EB}" }], version: 2 }, "flag-pg": { id: "flag-pg", name: "Papua New Guinea Flag", keywords: ["pg", "nation", "country", "banner"], skins: [{ unified: "1f1f5-1f1ec", native: "\u{1F1F5}\u{1F1EC}" }], version: 2 }, "flag-ph": { id: "flag-ph", name: "Philippines Flag", keywords: ["ph", "nation", "country", "banner"], skins: [{ unified: "1f1f5-1f1ed", native: "\u{1F1F5}\u{1F1ED}" }], version: 2 }, "flag-pk": { id: "flag-pk", name: "Pakistan Flag", keywords: ["pk", "nation", "country", "banner"], skins: [{ unified: "1f1f5-1f1f0", native: "\u{1F1F5}\u{1F1F0}" }], version: 2 }, "flag-pl": { id: "flag-pl", name: "Poland Flag", keywords: ["pl", "nation", "country", "banner"], skins: [{ unified: "1f1f5-1f1f1", native: "\u{1F1F5}\u{1F1F1}" }], version: 2 }, "flag-pm": { id: "flag-pm", name: "St. Pierre & Miquelon Flag", keywords: ["pm", "st", "saint", "nation", "country", "banner"], skins: [{ unified: "1f1f5-1f1f2", native: "\u{1F1F5}\u{1F1F2}" }], version: 2 }, "flag-pn": { id: "flag-pn", name: "Pitcairn Islands Flag", keywords: ["pn", "nation", "country", "banner"], skins: [{ unified: "1f1f5-1f1f3", native: "\u{1F1F5}\u{1F1F3}" }], version: 2 }, "flag-pr": { id: "flag-pr", name: "Puerto Rico Flag", keywords: ["pr", "nation", "country", "banner"], skins: [{ unified: "1f1f5-1f1f7", native: "\u{1F1F5}\u{1F1F7}" }], version: 2 }, "flag-ps": { id: "flag-ps", name: "Palestinian Territories Flag", keywords: ["ps", "palestine", "nation", "country", "banner"], skins: [{ unified: "1f1f5-1f1f8", native: "\u{1F1F5}\u{1F1F8}" }], version: 2 }, "flag-pt": { id: "flag-pt", name: "Portugal Flag", keywords: ["pt", "nation", "country", "banner"], skins: [{ unified: "1f1f5-1f1f9", native: "\u{1F1F5}\u{1F1F9}" }], version: 2 }, "flag-pw": { id: "flag-pw", name: "Palau Flag", keywords: ["pw", "nation", "country", "banner"], skins: [{ unified: "1f1f5-1f1fc", native: "\u{1F1F5}\u{1F1FC}" }], version: 2 }, "flag-py": { id: "flag-py", name: "Paraguay Flag", keywords: ["py", "nation", "country", "banner"], skins: [{ unified: "1f1f5-1f1fe", native: "\u{1F1F5}\u{1F1FE}" }], version: 2 }, "flag-qa": { id: "flag-qa", name: "Qatar Flag", keywords: ["qa", "nation", "country", "banner"], skins: [{ unified: "1f1f6-1f1e6", native: "\u{1F1F6}\u{1F1E6}" }], version: 2 }, "flag-re": { id: "flag-re", name: "R\xE9union Flag", keywords: ["re", "reunion", "nation", "country", "banner"], skins: [{ unified: "1f1f7-1f1ea", native: "\u{1F1F7}\u{1F1EA}" }], version: 2 }, "flag-ro": { id: "flag-ro", name: "Romania Flag", keywords: ["ro", "nation", "country", "banner"], skins: [{ unified: "1f1f7-1f1f4", native: "\u{1F1F7}\u{1F1F4}" }
51763], version: 2 }, "flag-rs": { id: "flag-rs", name: "Serbia Flag", keywords: ["rs", "nation", "country", "banner"], skins: [{ unified: "1f1f7-1f1f8", native: "\u{1F1F7}\u{1F1F8}" }], version: 2 }, ru: { id: "ru", name: "Russia Flag", keywords: ["ru", "russian", "federation", "nation", "country", "banner"], skins: [{ unified: "1f1f7-1f1fa", native: "\u{1F1F7}\u{1F1FA}" }], version: 1 }, "flag-rw": { id: "flag-rw", name: "Rwanda Flag", keywords: ["rw", "nation", "country", "banner"], skins: [{ unified: "1f1f7-1f1fc", native: "\u{1F1F7}\u{1F1FC}" }], version: 2 }, "flag-sa": { id: "flag-sa", name: "Saudi Arabia Flag", keywords: ["sa", "nation", "country", "banner"], skins: [{ unified: "1f1f8-1f1e6", native: "\u{1F1F8}\u{1F1E6}" }], version: 2 }, "flag-sb": { id: "flag-sb", name: "Solomon Islands Flag", keywords: ["sb", "nation", "country", "banner"], skins: [{ unified: "1f1f8-1f1e7", native: "\u{1F1F8}\u{1F1E7}" }], version: 2 }, "flag-sc": { id: "flag-sc", name: "Seychelles Flag", keywords: ["sc", "nation", "country", "banner"], skins: [{ unified: "1f1f8-1f1e8", native: "\u{1F1F8}\u{1F1E8}" }], version: 2 }, "flag-sd": { id: "flag-sd", name: "Sudan Flag", keywords: ["sd", "nation", "country", "banner"], skins: [{ unified: "1f1f8-1f1e9", native: "\u{1F1F8}\u{1F1E9}" }], version: 2 }, "flag-se": { id: "flag-se", name: "Sweden Flag", keywords: ["se", "nation", "country", "banner"], skins: [{ unified: "1f1f8-1f1ea", native: "\u{1F1F8}\u{1F1EA}" }], version: 2 }, "flag-sg": { id: "flag-sg", name: "Singapore Flag", keywords: ["sg", "nation", "country", "banner"], skins: [{ unified: "1f1f8-1f1ec", native: "\u{1F1F8}\u{1F1EC}" }], version: 2 }, "flag-sh": { id: "flag-sh", name: "St. Helena Flag", keywords: ["sh", "st", "saint", "ascension", "tristan", "cunha", "nation", "country", "banner"], skins: [{ unified: "1f1f8-1f1ed", native: "\u{1F1F8}\u{1F1ED}" }], version: 2 }, "flag-si": { id: "flag-si", name: "Slovenia Flag", keywords: ["si", "nation", "country", "banner"], skins: [{ unified: "1f1f8-1f1ee", native: "\u{1F1F8}\u{1F1EE}" }], version: 2 }, "flag-sj": { id: "flag-sj", name: "Svalbard & Jan Mayen Flag", keywords: ["sj"], skins: [{ unified: "1f1f8-1f1ef", native: "\u{1F1F8}\u{1F1EF}" }], version: 2 }, "flag-sk": { id: "flag-sk", name: "Slovakia Flag", keywords: ["sk", "nation", "country", "banner"], skins: [{ unified: "1f1f8-1f1f0", native: "\u{1F1F8}\u{1F1F0}" }], version: 2 }, "flag-sl": { id: "flag-sl", name: "Sierra Leone Flag", keywords: ["sl", "nation", "country", "banner"], skins: [{ unified: "1f1f8-1f1f1", native: "\u{1F1F8}\u{1F1F1}" }], version: 2 }, "flag-sm": { id: "flag-sm", name: "San Marino Flag", keywords: ["sm", "nation", "country", "banner"], skins: [{ unified: "1f1f8-1f1f2", native: "\u{1F1F8}\u{1F1F2}" }], version: 2 }, "flag-sn": { id: "flag-sn", name: "Senegal Flag", keywords: ["sn", "nation", "country", "banner"], skins: [{ unified: "1f1f8-1f1f3", native: "\u{1F1F8}\u{1F1F3}" }], version: 2 }, "flag-so": { id: "flag-so", name: "Somalia Flag", keywords: ["so", "nation", "country", "banner"], skins: [{ unified: "1f1f8-1f1f4", native: "\u{1F1F8}\u{1F1F4}" }
51763], version: 2 }, "flag-sr": { id: "flag-sr", name: "Suriname Flag", keywords: ["sr", "nation", "country", "banner"], skins: [{ unified: "1f1f8-1f1f7", native: "\u{1F1F8}\u{1F1F7}" }], version: 2 }, "flag-ss": { id: "flag-ss", name: "South Sudan Flag", keywords: ["ss", "sd", "nation", "country", "banner"], skins: [{ unified: "1f1f8-1f1f8", native: "\u{1F1F8}\u{1F1F8}" }], version: 2 }, "flag-st": { id: "flag-st", name: "S\xE3o Tom\xE9 & Pr\xEDncipe Flag", keywords: ["st", "sao", "tome", "principe", "nation", "country", "banner"], skins: [{ unified: "1f1f8-1f1f9", native: "\u{1F1F8}\u{1F1F9}" }], version: 2 }, "flag-sv": { id: "flag-sv", name: "El Salvador Flag", keywords: ["sv", "nation", "country", "banner"], skins: [{ unified: "1f1f8-1f1fb", native: "\u{1F1F8}\u{1F1FB}" }], version: 2 }, "flag-sx": { id: "flag-sx", name: "Sint Maarten Flag", keywords: ["sx", "dutch", "nation", "country", "banner"], skins: [{ unified: "1f1f8-1f1fd", native: "\u{1F1F8}\u{1F1FD}" }], version: 2 }, "flag-sy": { id: "flag-sy", name: "Syria Flag", keywords: ["sy", "syrian", "arab", "republic", "nation", "country", "banner"], skins: [{ unified: "1f1f8-1f1fe", native: "\u{1F1F8}\u{1F1FE}" }], version: 2 }, "flag-sz": { id: "flag-sz", name: "Eswatini Flag", keywords: ["sz", "nation", "country", "banner"], skins: [{ unified: "1f1f8-1f1ff", native: "\u{1F1F8}\u{1F1FF}" }], version: 2 }, "flag-ta": { id: "flag-ta", name: "Tristan Da Cunha Flag", keywords: ["ta"], skins: [{ unified: "1f1f9-1f1e6", native: "\u{1F1F9}\u{1F1E6}" }], version: 2 }, "flag-tc": { id: "flag-tc", name: "Turks & Caicos Islands Flag", keywords: ["tc", "nation", "country", "banner"], skins: [{ unified: "1f1f9-1f1e8", native: "\u{1F1F9}\u{1F1E8}" }], version: 2 }, "flag-td": { id: "flag-td", name: "Chad Flag", keywords: ["td", "nation", "country", "banner"], skins: [{ unified: "1f1f9-1f1e9", native: "\u{1F1F9}\u{1F1E9}" }], version: 2 }, "flag-tf": { id: "flag-tf", name: "French Southern Territories Flag", keywords: ["tf", "nation", "country", "banner"], skins: [{ unified: "1f1f9-1f1eb", native: "\u{1F1F9}\u{1F1EB}" }], version: 2 }, "flag-tg": { id: "flag-tg", name: "Togo Flag", keywords: ["tg", "nation", "country", "banner"], skins: [{ unified: "1f1f9-1f1ec", native: "\u{1F1F9}\u{1F1EC}" }], version: 2 }, "flag-th": { id: "flag-th", name: "Thailand Flag", keywords: ["th", "nation", "country", "banner"], skins: [{ unified: "1f1f9-1f1ed", native: "\u{1F1F9}\u{1F1ED}" }], version: 2 }, "flag-tj": { id: "flag-tj", name: "Tajikistan Flag", keywords: ["tj", "nation", "country", "banner"], skins: [{ unified: "1f1f9-1f1ef", native: "\u{1F1F9}\u{1F1EF}" }], version: 2 }, "flag-tk": { id: "flag-tk", name: "Tokelau Flag", keywords: ["tk", "nation", "country", "banner"], skins: [{ unified: "1f1f9-1f1f0", native: "\u{1F1F9}\u{1F1F0}" }], version: 2 }, "flag-tl": { id: "flag-tl", name: "Timor-Leste Flag", keywords: ["tl", "timor", "leste", "nation", "country", "banner"], skins: [{ unified: "1f1f9-1f1f1", native: "\u{1F1F9}\u{1F1F1}" }], version: 2 }, "flag-tm": { id: "flag-tm", name: "Turkmenistan Flag", keywords: ["tm", "nation", "country", "banner"], skins: [{ unified: "1f1f9-1f1f2", native: "\u{1F1F9}\u{1F1F2}" }], version: 2 }, "flag-tn": { id: "flag-tn", name: "Tunisia Flag", keywords: ["tn", "nation", "country", "banner"], skins: [{ unified: "1f1f9-1f1f3", native: "\u{1F1F9}\u{1F1F3}" }], version: 2 }, "flag-to": { id: "flag-to", name: "Tonga Flag", keywords: ["to", "nation", "country", "banner"], skins: [{ unified: "1f1f9-1f1f4", native: "\u{1F1F9}\u{1F1F4}" }
51763], version: 2 }, "flag-tr": { id: "flag-tr", name: "Flag Turkey", keywords: ["tr", "nation", "country", "banner"], skins: [{ unified: "1f1f9-1f1f7", native: "\u{1F1F9}\u{1F1F7}" }], version: 2 }, "flag-tt": { id: "flag-tt", name: "Trinidad & Tobago Flag", keywords: ["tt", "nation", "country", "banner"], skins: [{ unified: "1f1f9-1f1f9", native: "\u{1F1F9}\u{1F1F9}" }], version: 2 }, "flag-tv": { id: "flag-tv", name: "Tuvalu Flag", keywords: ["tv", "nation", "country", "banner"], skins: [{ unified: "1f1f9-1f1fb", native: "\u{1F1F9}\u{1F1FB}" }], version: 2 }, "flag-tw": { id: "flag-tw", name: "Taiwan Flag", keywords: ["tw", "nation", "country", "banner"], skins: [{ unified: "1f1f9-1f1fc", native: "\u{1F1F9}\u{1F1FC}" }], version: 2 }, "flag-tz": { id: "flag-tz", name: "Tanzania Flag", keywords: ["tz", "united", "republic", "nation", "country", "banner"], skins: [{ unified: "1f1f9-1f1ff", native: "\u{1F1F9}\u{1F1FF}" }], version: 2 }, "flag-ua": { id: "flag-ua", name: "Ukraine Flag", keywords: ["ua", "nation", "country", "banner"], skins: [{ unified: "1f1fa-1f1e6", native: "\u{1F1FA}\u{1F1E6}" }], version: 2 }, "flag-ug": { id: "flag-ug", name: "Uganda Flag", keywords: ["ug", "nation", "country", "banner"], skins: [{ unified: "1f1fa-1f1ec", native: "\u{1F1FA}\u{1F1EC}" }], version: 2 }, "flag-um": { id: "flag-um", name: "U.s. Outlying Islands Flag", keywords: ["um", "u", "s"], skins: [{ unified: "1f1fa-1f1f2", native: "\u{1F1FA}\u{1F1F2}" }], version: 2 }, "flag-un": { id: "flag-un", name: "United Nations Flag", keywords: ["un", "banner"], skins: [{ unified: "1f1fa-1f1f3", native: "\u{1F1FA}\u{1F1F3}" }], version: 4 }, us: { id: "us", name: "United States Flag", keywords: ["us", "america", "nation", "country", "banner"], skins: [{ unified: "1f1fa-1f1f8", native: "\u{1F1FA}\u{1F1F8}" }], version: 1 }, "flag-uy": { id: "flag-uy", name: "Uruguay Flag", keywords: ["uy", "nation", "country", "banner"], skins: [{ unified: "1f1fa-1f1fe", native: "\u{1F1FA}\u{1F1FE}" }], version: 2 }, "flag-uz": { id: "flag-uz", name: "Uzbekistan Flag", keywords: ["uz", "nation", "country", "banner"], skins: [{ unified: "1f1fa-1f1ff", native: "\u{1F1FA}\u{1F1FF}" }], version: 2 }, "flag-va": { id: "flag-va", name: "Vatican City Flag", keywords: ["va", "nation", "country", "banner"], skins: [{ unified: "1f1fb-1f1e6", native: "\u{1F1FB}\u{1F1E6}" }], version: 2 }, "flag-vc": { id: "flag-vc", name: "St. Vincent & Grenadines Flag", keywords: ["vc", "st", "saint", "nation", "country", "banner"], skins: [{ unified: "1f1fb-1f1e8", native: "\u{1F1FB}\u{1F1E8}" }], version: 2 }, "flag-ve": { id: "flag-ve", name: "Venezuela Flag", keywords: ["ve", "bolivarian", "republic", "nation", "country", "banner"], skins: [{ unified: "1f1fb-1f1ea", native: "\u{1F1FB}\u{1F1EA}" }], version: 2 }, "flag-vg": { id: "flag-vg", name: "British Virgin Islands Flag", keywords: ["vg", "bvi", "nation", "country", "banner"], skins: [{ unified: "1f1fb-1f1ec", native: "\u{1F1FB}\u{1F1EC}" }], version: 2 }, "flag-vi": { id: "flag-vi", name: "U.s. Virgin Islands Flag", keywords: ["vi", "u", "s", "us", "nation", "country", "banner"], skins: [{ unified: "1f1fb-1f1ee", native: "\u{1F1FB}\u{1F1EE}" }], version: 2 }, "flag-vn": { id: "flag-vn", name: "Vietnam Flag", keywords: ["vn", "viet", "nam", "nation", "country", "banner"], skins: [{ unified: "1f1fb-1f1f3", native: "\u{1F1FB}\u{1F1F3}" }], version: 2 }, "flag-vu": { id: "flag-vu", name: "Vanuatu Flag", keywords: ["vu", "nation", "country", "banner"], skins: [{ unified: "1f1fb-1f1fa", native: "\u{1F1FB}\u{1F1FA}" }], version: 2 }, "flag-wf": { id: "flag-wf", name: "Wallis & Futuna Flag", keywords: ["wf", "nation", "country", "banner"], skins: [{ unified: "1f1fc-1f1eb", native: "\u{1F1FC}\u{1F1EB}" }], version: 2 }, "flag-ws": { id: "flag-ws", name: "Samoa Flag", keywords: ["ws", "nation", "country", "banner"], skins: [{ unified: "1f1fc-1f1f8", native: "\u{1F1FC}\u{1F1F8}" }], version: 2 }, "flag-xk": { id: "flag-xk", name: "Kosovo Flag", keywords: ["xk", "nation", "country", "banner"], skins: [{ unified: "1f1fd-1f1f0", native: "\u{1F1FD}\u{1F1F0}" }], version: 2 }, "flag-ye": { id: "flag-ye", name: "Yemen Flag", keywords: ["ye", "nation", "country", "banner"], skins: [{ unified: "1f1fe-1f1ea", native: "\u{1F1FE}
51763\u{1F1EA}" }], version: 2 }, "flag-yt": { id: "flag-yt", name: "Mayotte Flag", keywords: ["yt", "nation", "country", "banner"], skins: [{ unified: "1f1fe-1f1f9", native: "\u{1F1FE}\u{1F1F9}" }], version: 2 }, "flag-za": { id: "flag-za", name: "South Africa Flag", keywords: ["za", "nation", "country", "banner"], skins: [{ unified: "1f1ff-1f1e6", native: "\u{1F1FF}\u{1F1E6}" }], version: 2 }, "flag-zm": { id: "flag-zm", name: "Zambia Flag", keywords: ["zm", "nation", "country", "banner"], skins: [{ unified: "1f1ff-1f1f2", native: "\u{1F1FF}\u{1F1F2}" }], version: 2 }, "flag-zw": { id: "flag-zw", name: "Zimbabwe Flag", keywords: ["zw", "nation", "country", "banner"], skins: [{ unified: "1f1ff-1f1fc", native: "\u{1F1FF}\u{1F1FC}" }], version: 2 }, "flag-england": { id: "flag-england", name: "England Flag", keywords: ["english"], skins: [{ unified: "1f3f4-e0067-e0062-e0065-e006e-e0067-e007f", native: "\u{1F3F4}\u{E0067}\u{E0062}\u{E0065}\u{E006E}\u{E0067}\u{E007F}" }], version: 5 }, "flag-scotland": { id: "flag-scotland", name: "Scotland Flag", keywords: ["scottish"], skins: [{ unified: "1f3f4-e0067-e0062-e0073-e0063-e0074-e007f", native: "\u{1F3F4}\u{E0067}\u{E0062}\u{E0073}\u{E0063}\u{E0074}\u{E007F}" }], version: 5 }, "flag-wales": { id: "flag-wales", name: "Wales Flag", keywords: ["welsh"], skins: [{ unified: "1f3f4-e0067-e0062-e0077-e006c-e0073-e007f", native: "\u{1F3F4}\u{E0067}\u{E0062}\u{E0077}\u{E006C}\u{E0073}\u{E007F}" }], version: 5 }, distorted_face: { id: "distorted_face", name: "Distorted Face", keywords: ["anxiety", "bloated", "panic", "shocked", "surprised", "vulnerable"], skins: [{ unified: "1faea", native: "\u{1FAEA}" }], version: 17 }, fight_cloud: { id: "fight_cloud", name: "Fight Cloud", keywords: ["argument", "brawl", "debate", "disagreement", "ruckus", "wrestle"], skins: [{ unified: "1faef", native: "\u{1FAEF}" }], version: 17 }, hairy_creature: { id: "hairy_creature", name: "Hairy Creature", keywords: ["bigfoot", "cryptid", "forest", "giant", "sasquatch", "woodwose", "yeti"], skins: [{ unified: "1fac8", native: "\u{1FAC8}" }], version: 17 }, ballet_dancer: { id: "ballet_dancer", name: "Ballet Dancer", keywords: [], skins: [{ unified: "1f9d1-200d-1fa70", native: "\u{1F9D1}\u200D\u{1FA70}" }, { unified: "1f9d1-1f3fb-200d-1fa70", native: "\u{1F9D1}\u{1F3FB}\u200D\u{1FA70}" }, { unified: "1f9d1-1f3fc-200d-1fa70", native: "\u{1F9D1}\u{1F3FC}\u200D\u{1FA70}" }, { unified: "1f9d1-1f3fd-200d-1fa70", native: "\u{1F9D1}\u{1F3FD}\u200D\u{1FA70}" }, { unified: "1f9d1-1f3fe-200d-1fa70", native: "\u{1F9D1}\u{1F3FE}\u200D\u{1FA70}" }, { unified: "1f9d1-1f3ff-200d-1fa70", native: "\u{1F9D1}\u{1F3FF}\u200D\u{1FA70}" }], version: 17 }, orca: { id: "orca", name: "Orca", keywords: ["marine", "ocean", "whale"], skins: [{ unified: "1facd", native: "\u{1FACD}" }], version: 17 }, landslide: { id: "landslide", name: "Landslide", keywords: ["avalanche", "danger", "disaster", "earthquake", "mountain", "mudslide", "rocks"], skins: [{ unified: "1f6d8", native: "\u{1F6D8}" }], version: 17 }, trombone: { id: "trombone", name: "Trombone", keywords: ["brass", "instrument", "jazz", "music", "sad", "slide"], skins: [{ unified: "1fa8a", native: "\u{1FA8A}" }], version: 17 }, treasure_chest: { id: "treasure_chest", name: "Treasure Chest", keywords: ["gem", "gold", "jewels", "loot", "money", "prize", "silver", "valuables", "wealth"], skins: [{ unified: "1fa8e", native: "\u{1FA8E}" }], version: 17 } }, aliases: { satisfied: "laughing", grinning_face_with_star_eyes: "star-struck", grinning_face_with_one_large_and_one_small_eye: "zany_face", smiling_face_with_smiling_eyes_and_hand_covering_mouth: "face_with_hand_over_mouth", face_with_finger_covering_closed_lips: "shushing_face", face_with_one_eyebrow_raised: "face_with_raised_eyebrow", face_with_open_mouth_vomiting: "face_vomiting", shocked_face_with_exploding_head: "exploding_head", serious_face_with_symbols_covering_mouth: "face_with_symbols_on_mouth", poop: "hankey", shit: "hankey", collision: "boom", raised_hand: "hand", hand_with_index_and_middle_fingers_crossed: "crossed_fingers", sign_of_the_horns: "the_horns", reversed_hand_with_middle_finger_extended: "middle_finger", thumbsup: "+1", thumbsdown: "-1", punch: "facepunch", mother_christmas: "mrs_claus", running: "runner", "man-with-bunny-ears-partying": "men-with-bunny-ears-partying", "woman-with-bunny-ears-partying": "women-with-bunny-ears-partying", women_holding_hands: "two_women_holding_hands", woman_and_man_holding_hands: "man_and_woman_holding_hands", couple: "man_and_woman_holding_hands", men_holding_hands: "two_men_holding_hands", paw_prints: "feet", flipper: "dolphin", honeybee: "bee", lady_beetle: "ladybug", cooking: "fried_egg", knife: "hocho", red_car: "car", sailboat: "boat", waxing_gibbous_moon: "moon", sun_small_cloud: "mostly_sunny", sun_behind_cloud: "barely_sunny", sun_behind_rain_cloud: "partly_sunny_rain", lightning_cloud: "lightning", tornado_cloud: "tornado", tshirt: "shirt", shoe: "mans_shoe", telephone: "phone", lantern: "izakaya_lantern", open_book: "book", envelope: "email", pencil: "memo", heavy_exclamation_mark: "exclamation", staff_of_aesculapius: "medical_symbol", "flag-cn": "cn", "flag-de": "de", "flag-es": "es", "flag-fr": "fr", uk: "gb", "flag-gb": "gb", "flag-it": "it", "flag-jp": "jp", "flag-kr": "kr", "flag-ru": "ru", "flag-us": "us" }, sheet: { cols: 61, rows: 61 } };
51764
51765  
51765// app/javascript/src/emoji_mart/data.js
51766  var EMOJI_MART_DATA = native_default;
51767  var EMOJI_MART_VERSION = 17;
51768
51769  
51769// app/javascript/src/emoji_mart/theme.js
51770  function emojiMartTheme() {
51771    return document.documentElement.classList.contains("dark") ? "dark" : "light";
51772  }
51773  function watchEmojiMartTheme(picker) {
51774    const syncTheme = () => {
51775      picker.update?.({ theme: emojiMartTheme() });
51776    };
51777    const observer = new MutationObserver(syncTheme);
51778    observer.observe(document.documentElement, { attributes: true, attributeFilter: ["class"] });
51779    return () => observer.disconnect();
51780  }
51781
51782  
51782// app/javascript/src/lexxy/callout_emoji_picker.js
51783  function createCalloutEmojiPicker(container, { onSelect, pickerOptions = {} }) {
51784    const picker = new $efa000751917694d$export$2e2bcd8739ae039({
51785      data: EMOJI_MART_DATA,
51786      onEmojiSelect: onSelect,
51787      dynamicWidth: true,
51788      emojiButtonColors: ["rgba(128, 128, 128, 0.22)"],
51789      emojiVersion: EMOJI_MART_VERSION,
51790      navPosition: "bottom",
51791      previewPosition: "none",
51792      theme: emojiMartTheme(),
51793      ...pickerOptions
51794    });
51795    picker._unwatchTheme = watchEmojiMartTheme(picker);
51796    container.replaceChildren(picker);
51797    return picker;
51798  }
51799  function applyCalloutEmojiPickerStyles(root) {
51800    if (root.querySelector("[data-callout-emoji-styles]")) return;
51801    const style = document.createElement("style");
51802    style.dataset.calloutEmojiStyles = "";
51803    style.textContent = `
51804    #root {
51805      border-radius: 0 !important;
51806    }
51807
51808    * {
51809      scrollbar-color: #d6d6d6 transparent !important;
51810      scrollbar-width: thin !important;
51811    }
51812
51813    *::-webkit-scrollbar {
51814      height: 6px !important;
51815      width: 6px !important;
51816    }
51817
51818    *::-webkit-scrollbar-track {
51819      background: transparent !important;
51820    }
51821
51822    *::-webkit-scrollbar-thumb {
51823      background-color: #d6d6d6 !important;
51824    }
51825
51826    [data-theme="dark"] * {
51827      scrollbar-color: #5c5c5c transparent !important;
51828    }
51829
51830    [data-theme="dark"] *::-webkit-scrollbar-thumb {
51831      background-color: #5c5c5c !important;
51832    }
51833
51834    .search {
51835      align-items: center !important;
51836      background-color: var(--callout-tools-control-bg, rgb(var(--em-rgb-background))) !important;
51837      border: 1px solid var(--callout-tools-control-border, var(--color-border)) !important;
51838      border-radius: 8px !important;
51839      block-size: 37.5px !important;
51840      box-sizing: border-box !important;
51841      box-shadow: none !important;
51842      color: var(--callout-tools-control-muted, rgba(var(--em-rgb-color), 0.52)) !important;
51843      min-block-size: 37.5px !important;
51844    }
51845
51846    .search:focus-within {
51847      border-color: var(--callout-tools-control-border-focus, rgba(var(--em-rgb-color), 0.78)) !important;
51848      box-shadow: none !important;
51849    }
51850
51851    .search input {
51852      background: transparent !important;
51853      border: 0 !important;
51854      box-shadow: none !important;
51855      color: var(--callout-tools-control-text, rgb(var(--em-rgb-color))) !important;
51856      appearance: none !important;
51857      -webkit-appearance: none !important;
51858      font: inherit !important;
51859      font-size: 0.95rem !important;
51860      block-size: 100% !important;
51861      min-inline-size: 0 !important;
51862      outline: none !important;
51863      padding-block: 0 !important;
51864      padding-inline: 2.2rem !important;
51865    }
51866
51867    .search input::placeholder {
51868      color: var(--callout-tools-control-muted, rgba(var(--em-rgb-color), 0.52)) !important;
51869      opacity: 1 !important;
51870    }
51871
51872    .search .icon {
51873      color: var(--callout-tools-control-muted, rgba(var(--em-rgb-color), 0.52)) !important;
51874      height: 1.05rem !important;
51875      width: 1.05rem !important;
51876    }
51877
51878    .search .loupe {
51879      left: 0.65rem !important;
51880      pointer-events: none !important;
51881      right: auto !important;
51882    }
51883
51884    .search .delete {
51885      align-items: center !important;
51886      background-color: #6c7280 !important;
51887      background-image: none !important;
51888      block-size: 1rem !important;
51889      inline-size: 1rem !important;
51890      justify-content: center !important;
51891      left: auto !important;
51892      mask-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24'%3E%3Cpath stroke='%23000' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M6 18 18 6M6 6l12 12'/%3E%3C/svg%3E") !important;
51893      mask-position: center !important;
51894      mask-repeat: no-repeat !important;
51895      mask-size: 1rem 1rem !important;
51896      -webkit-mask-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24'%3E%3Cpath stroke='%23000' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M6 18 18 6M6 6l12 12'/%3E%3C/svg%3E") !important;
51897      -webkit-mask-position: center !important;
51898      -webkit-mask-repeat: no-repeat !important;
51899      -webkit-mask-size: 1rem 1rem !important;
51900      right: 0.85rem !important;
51901    }
51902
51903    .search .delete:hover {
51904      background-color: #374151 !important;
51905    }
51906
51907    [data-theme="dark"] .search .delete {
51908      background-color: #d1d5dc !important;
51909    }
51910
51911    [data-theme="dark"] .search .delete:hover {
51912      background-color: #f3f4f6 !important;
51913    }
51914
51915    .search .delete svg {
51916      display: none !important;
51917    }
51918
51919    [dir="rtl"] .search .loupe {
51920      left: auto !important;
51921      right: 0.65rem !important;
51922    }
51923
51924    [dir="rtl"] .search .delete {
51925      left: 0.85rem !important;
51926      right: auto !important;
51927    }
51928
51929    .search .icon svg {
51930      fill: currentColor !important;
51931      height: 1.05rem !important;
51932      width: 1.05rem !important;
51933    }
51934
51935    .spacer {
51936      height: 8px !important;
51937    }
51938
51939    button:focus,
51940    button:focus-visible {
51941      box-shadow: none !important;
51942      outline: none !important;
51943    }
51944
51945    button:focus .background,
51946    button:focus-visible .background {
51947      border-radius: 30% !important;
51948    }
51949
51950    .background {
51951      border-radius: 30% !important;
51952    }
51953
51954    .skin-tone-button,
51955    .skin-tone-button:focus,
51956    .skin-tone-button:focus-visible {
51957      border-radius: 0 !important;
51958    }
51959
51960    button[data-callout-selected-emoji="true"] .background {
51961      opacity: 1 !important;
51962      border-radius: 30% !important;
51963    }
51964
51965    button[data-callout-selected-emoji="true"] {
51966      box-shadow: inset 0 0 0 1px rgba(var(--em-rgb-color), 0.78);
51967      border-radius: 30%;
51968    }
51969  `;
51970    root.append(style);
51971  }
51972
51973  
51973// app/javascript/src/lexxy/callout_tools.js
51974  var { $getNearestNodeFromDOMNode: $getNearestNodeFromDOMNode3, $getNodeByKey: $getNodeByKey3, $getSelection: $getSelection4, $isElementNode: $isElementNode5, $isRangeSelection: $isRangeSelection4 } = Lexical_exports;
51975  var ICON_GRID_BATCH_SIZE = 240;
51976  var ICON_GRID_COLUMNS = 10;
51977  var SEARCH_ICON_SVG = `
51978  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" aria-hidden="true" focusable="false">
51979    <path d="M12.9 14.32a8 8 0 1 1 1.41-1.41l5.35 5.33-1.42 1.42-5.33-5.34zM8 14A6 6 0 1 0 8 2a6 6 0 0 0 0 12z"></path>
51980  </svg>
51981`;
51982  var SHUFFLE_ICON_SVG = `
51983  <svg viewBox="0 0 24 24" aria-hidden="true" focusable="false">
51984    <path d="m18 14 4 4-4 4"></path>
51985    <path d="m18 2 4 4-4 4"></path>
51986    <path d="M2 18h1.4c1.3 0 2.5-.6 3.3-1.6L14 7.6C14.8 6.6 16 6 17.3 6H22"></path>
51987    <path d="M2 6h1.4c1.3 0 2.5.6 3.3 1.6l1.2 1.5"></path>
51988    <path d="m13.9 14.9.1.1c.8 1.2 2.1 3 3.3 3H22"></path>
51989  </svg>
51990`;
51991  var IMAGE_ICON_SVG = `
51992  <svg viewBox="0 0 24 24" aria-hidden="true" focusable="false">
51993    <rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
51994    <circle cx="9" cy="9" r="2"></circle>
51995    <path d="m21 15-3.1-3.1a2 2 0 0 0-2.8 0L6 21"></path>
51996  </svg>
51997`;
51998  var TRASH_ICON_SVG = `
51999  <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" aria-hidden="true" focusable="false">
52000    <g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" stroke="currentColor">
52001      <path d="M2.75 4.75H15.25"></path>
52002      <path d="M6.75 4.75V2.75C6.75 2.2 7.198 1.75 7.75 1.75H10.25C10.802 1.75 11.25 2.2 11.25 2.75V4.75"></path>
52003      <path d="M7.375 8.75L7.59219 13.25"></path>
52004      <path d="M10.625 8.75L10.4078 13.25"></path>
52005      <path d="M13.6977 7.75L13.35 14.35C13.294 15.4201 12.416 16.25 11.353 16.25H6.64804C5.58404 16.25 4.70703 15.42 4.65103 14.35L4.30334 7.75"></path>
52006    </g>
52007  </svg>
52008`;
52009  var SWATCH_CHECK_SVG = `
52010  <svg class="lexxy-callout-tools__swatch-check" viewBox="0 0 12 12" aria-hidden="true" focusable="false">
52011    <path d="M1.75391 6.41392L4.4001 9.24985L10.2467 2.98532" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path>
52012  </svg>
52013`;
52014  var SWATCH_NONE_ICON_SVG = `
52015  <svg class="lexxy-callout-tools__swatch-none-icon" viewBox="0 0 12 12" aria-hidden="true" focusable="false">
52016    <g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5">
52017      <path d="M9.35876 2.64124C8.49918 1.78166 7.31168 1.25 6 1.25C3.37665 1.25 1.25 3.37665 1.25 6C1.25 7.31168 1.78166 8.49918 2.64124 9.35876"></path>
52018      <path d="M10.6832 5.20337C10.7269 5.46236 10.7496 5.72846 10.7496 5.99989C10.7496 8.62324 8.623 10.7499 5.99965 10.7499C5.72822 10.7499 5.46211 10.7271 5.20312 10.6834"></path>
52019      <path d="M1.25 10.75L10.75 1.25"></path>
52020    </g>
52021  </svg>
52022`;
52023  function $getCalloutInSelection() {
52024    const selection = $getSelection4();
52025    if (!$isRangeSelection4(selection)) return null;
52026    return $findMatchingParent3(selection.anchor.getNode(), $isCalloutNode);
52027  }
52028  function $getCalloutByKey(activeCalloutKey) {
52029    if (!activeCalloutKey) return null;
52030    const callout = $getNodeByKey3(activeCalloutKey);
52031    return $isCalloutNode(callout) ? callout : null;
52032  }
52033  function $getToolbarCallout(activeCalloutKey) {
52034    return $getCalloutByKey(activeCalloutKey) || $getCalloutInSelection();
52035  }
52036  function escapeHtml(value) {
52037    return String(value).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
52038  }
52039  var CalloutToolsElement = class extends HTMLElement {
52040    #updateListener = null;
52041    #fileInput = null;
52042    #emojiPicker = null;
52043    #lucideIcons = null;
52044    #outsideClickHandler = null;
52045    #escapeHandler = null;
52046    #pasteHandler = null;
52047    #activeIconTab = "emoji";
52048    #uploadFile = null;
52049    #uploadUrl = null;
52050    #uploadPreviewObjectUrl = null;
52051    #uploadSaving = false;
52052    #uploadUrlValidationId = 0;
52053    #activeCalloutKey = null;
52054    #iconPopover = null;
52055    #popoverPositionCleanup = null;
52056    #selectedSymbol = null;
52057    #selectedEmoji = null;
52058    #emojiPickerObserver = null;
52059    #visibleIconCount = ICON_GRID_BATCH_SIZE;
52060    #iconSearchQuery = "";
52061    #iconKeyboardIndex = -1;
52062    #iconSearchNavigated = false;
52063    #inlineIconMouseDownHandler = null;
52064    #inlineIconClickHandler = null;
52065    #editorFocusOutHandler = null;
52066    #pendingCalloutSyncFrame = null;
52067    connectedCallback() {
52068      this.editorElement = this.closest("lexxy-editor");
52069      this.editor = this.editorElement.editor;
52070      this.classList.add("lexxy-floating-controls", "ph-no-autocapture");
52071      this.setAttribute("data-ph-no-autocapture", "");
52072      this.#buildUI();
52073      this.#hide();
52074      this.#monitorSelection();
52075      this.#bindInlineIconTriggerEvents();
52076      this.#bindEditorFocusEvents();
52077    }
52078    disconnectedCallback() {
52079      this.#updateListener?.();
52080      this.#unbindInlineIconTriggerEvents();
52081      this.#unbindEditorFocusEvents();
52082      this.#fileInput?.remove();
52083      this.#closeIconPopover();
52084      this.#teardownIconPopoverPortal();
52085      this.#removeGlobalListeners();
52086      if (this.#pendingCalloutSyncFrame) {
52087        cancelAnimationFrame(this.#pendingCalloutSyncFrame);
52088        this.#pendingCalloutSyncFrame = null;
52089      }
52090      this.#emojiPickerObserver?.disconnect();
52091      this.#emojiPickerObserver = null;
52092      this.#emojiPicker?._unwatchTheme?.();
52093      this.#revokeUploadPreview();
52094      this.#emojiPicker = null;
52095      this.#iconPopover = null;
52096    }
52097    #buildUI() {
52098      this.innerHTML = `
52099      <div class="lexxy-floating-controls__group lexxy-callout-tools__bar">
52100        <div class="lexxy-callout-tools__tool-row">
52101          <div class="lexxy-callout-tools__icon-section">
52102            <button
52103              type="button"
52104              class="lexxy-callout-tools__icon-trigger"
52105              data-callout-icon-toggle
52106              aria-label="Callout icon"
52107              aria-expanded="false"
52108              aria-haspopup="dialog"
52109            >
52110              <span data-callout-icon-preview>\u{1F4A1}</span>
52111            </button>
52112
52113            <div
52114              class="lexxy-callout-tools__icon-popover ph-no-autocapture hidden"
52115              data-icon-popover
52116              data-ph-no-autocapture
52117              hidden
52118              role="dialog"
52119              aria-label="Callout icon"
52120            >
52121              <div class="lexxy-callout-tools__tab-bar">
52122                <div class="lexxy-callout-tools__tabs" role="tablist" aria-label="Callout icon type">
52123                  <button type="button" role="tab" data-icon-tab="emoji" aria-selected="true">Emoji</button>
52124                  <button type="button" role="tab" data-icon-tab="icons" aria-selected="false">Icons</button>
52125                  <button type="button" role="tab" data-icon-tab="upload" aria-selected="false">Upload</button>
52126                </div>
52127                <button
52128                  type="button"
52129                  class="lexxy-callout-tools__remove-button"
52130                  data-callout-remove
52131                  aria-label="Remove"
52132                >
52133                  <span class="lexxy-callout-tools__remove-label">Remove</span>
52134                  <span class="lexxy-callout-tools__remove-icon">${TRASH_ICON_SVG}</span>
52135                </button>
52136              </div>
52137
52138              <div class="lexxy-callout-tools__tab-panel" data-icon-tab-panel="emoji">
52139                <div class="lexxy-callout-tools__emoji-picker" data-emoji-picker-container></div>
52140              </div>
52141
52142              <div class="lexxy-callout-tools__tab-panel hidden" data-icon-tab-panel="icons">
52143                <div class="lexxy-callout-tools__icons-panel">
52144                  <div class="lexxy-callout-tools__search-row">
52145                    <label class="lexxy-callout-tools__search">
52146                      ${SEARCH_ICON_SVG}
52147                      <input type="search" placeholder="Search" autocomplete="off" data-icon-search>
52148                    </label>
52149                    <button type="button" class="lexxy-callout-tools__icon-random" data-callout-random-icon title="Random icon" aria-label="Random icon">
52150                      ${SHUFFLE_ICON_SVG}
52151                    </button>
52152                  </div>
52153                  <div class="lexxy-callout-tools__icon-status" data-icon-status role="status" aria-live="polite" hidden></div>
52154                  <div class="lexxy-callout-tools__icon-grid small-scrollbar" data-icon-grid></div>
52155                </div>
52156              </div>
52157
52158              <div class="lexxy-callout-tools__tab-panel hidden" data-icon-tab-panel="upload">
52159                <div class="lexxy-callout-tools__upload-panel">
52160                  <button type="button" class="lexxy-callout-tools__upload-dropzone" data-callout-upload>
52161                    <span class="lexxy-callout-tools__upload-empty" data-upload-empty>
52162                      <span class="lexxy-callout-tools__upload-empty-icon">${IMAGE_ICON_SVG}</span>
52163                      <span>Upload an image</span>
52164                    </span>
52165                    <span class="lexxy-callout-tools__upload-preview hidden" data-upload-preview></span>
52166                  </button>
52167                  <label class="lexxy-callout-tools__upload-url">
52168                    <span>Image link</span>
52169                    <input type="url" placeholder="https://example.com/image.png" data-upload-url>
52170                  </label>
52171                  <p class="lexxy-callout-tools__upload-hint" data-upload-hint>
52172                    or
52173                    <button type="button" class="lexxy-callout-tools__upload-inline-action" data-upload-paste-clipboard>paste an image</button>
52174                    from your clipboard
52175                  </p>
52176                  <p class="lexxy-callout-tools__upload-status" data-upload-status role="status" aria-live="polite" hidden></p>
52177                  <div class="lexxy-callout-tools__upload-actions">
52178                    <button type="button" class="lexxy-callout-tools__upload-cancel" data-upload-cancel>Cancel</button>
52179                    <button type="button" class="lexxy-callout-tools__upload-save" data-upload-save disabled>Save</button>
52180                  </div>
52181                </div>
52182              </div>
52183            </div>
52184          </div>
52185
52186          <div class="lexxy-callout-tools__color-section lexxy-callout-tools__color-section--border">
52187            <div class="lexxy-callout-tools__swatch-row" data-color-target="border">
52188              ${this.#swatchButtons("border")}
52189            </div>
52190          </div>
52191        </div>
52192
52193        <div class="lexxy-callout-tools__tool-row lexxy-callout-tools__secondary-row">
52194          <div class="lexxy-callout-tools__delete-section">
52195            <button
52196              type="button"
52197              class="lexxy-callout-tools__delete-button"
52198              data-callout-delete
52199              aria-label="Delete callout"
52200              title="Delete callout"
52201            >
52202              ${TRASH_ICON_SVG}
52203            </button>
52204          </div>
52205
52206          <div class="lexxy-callout-tools__color-section lexxy-callout-tools__color-section--background">
52207            <div class="lexxy-callout-tools__swatch-row" data-color-target="background">
52208              ${this.#swatchButtons("background")}
52209            </div>
52210          </div>
52211        </div>
52212      </div>
52213    `;
52214      this.#fileInput = document.createElement("input");
52215      this.#fileInput.type = "file";
52216      this.#fileInput.accept = "image/png,image/jpeg,image/webp,image/gif";
52217      this.#fileInput.hidden = true;
52218      this.appendChild(this.#fileInput);
52219      this.addEventListener("mousedown", (event) => {
52220        if (event.target.closest("button, input, label, [data-callout-upload]")) event.preventDefault();
52221      });
52222      this.addEventListener("click", (event) => this.#handleClick(event));
52223      this.addEventListener("input", (event) => this.#handleInput(event));
52224      this.addEventListener("dragenter", (event) => this.#handleUploadDrag(event));
52225      this.addEventListener("dragover", (event) => this.#handleUploadDrag(event));
52226      this.addEventListener("dragleave", (event) => this.#handleUploadDragLeave(event));
52227      this.addEventListener("drop", (event) => this.#handleUploadDrop(event));
52228      this.#fileInput.addEventListener("change", (event) => this.#handleFileSelected(event));
52229      this.#iconPopover = this.querySelector("[data-icon-popover]");
52230      this.#setupIconPopoverPortal();
52231    }
52232    #setupIconPopoverPortal() {
52233      if (!this.#iconPopover) return;
52234      this.#iconPopover.classList.add("lexxy-callout-tools__icon-popover--portaled");
52235      this.#iconPopover.addEventListener("mousedown", (event) => {
52236        if (event.target.closest("button, input, label, [data-callout-upload]")) event.preventDefault();
52237      });
52238      this.#iconPopover.addEventListener("click", (event) => this.#handleClick(event));
52239      this.#iconPopover.addEventListener("input", (event) => this.#handleInput(event));
52240      this.#iconPopover.addEventListener("dragenter", (event) => this.#handleUploadDrag(event));
52241      this.#iconPopover.addEventListener("dragover", (event) => this.#handleUploadDrag(event));
52242      this.#iconPopover.addEventListener("dragleave", (event) => this.#handleUploadDragLeave(event));
52243      this.#iconPopover.addEventListener("drop", (event) => this.#handleUploadDrop(event));
52244      this.#iconPopover.addEventListener("scroll", (event) => this.#handleIconGridScroll(event), true);
52245      this.#iconPopover.addEventListener("keydown", (event) => this.#handleIconSearchKeydown(event));
52246      this.#iconPopover.addEventListener("pointerover", (event) => this.#handleIconGridPointerOver(event));
52247    }
52248    #teardownIconPopoverPortal() {
52249      this.#iconPopover?.remove();
52250    }
52251    #iconPopoverToggle() {
52252      return this.querySelector("[data-callout-icon-toggle]");
52253    }
52254    #popoverQuery(selector) {
52255      return this.#iconPopover?.querySelector(selector) ?? null;
52256    }
52257    #popoverQueryAll(selector) {
52258      return this.#iconPopover ? [...this.#iconPopover.querySelectorAll(selector)] : [];
52259    }
52260    #iconPopoverAnchor() {
52261      return this.querySelector(".lexxy-callout-tools__bar");
52262    }
52263    #clickedEditorCalloutElement(path) {
52264      for (const node of path) {
52265        const element = node instanceof Element ? node : node instanceof Node ? node.parentElement : null;
52266        const callout = element?.closest(".lexxy-callout");
52267        if (callout && this.editorElement.contains(callout)) return callout;
52268      }
52269      return null;
52270    }
52271    #syncToolbarForCalloutElement(calloutElement) {
52272      this.editor.getEditorState().read(() => {
52273        const node = $getNearestNodeFromDOMNode3(calloutElement);
52274        const callout = $isCalloutNode(node) ? node : $findMatchingParent3(node, $isCalloutNode);
52275        if (!callout) return;
52276        this.#syncUI(callout);
52277        this.#show(callout);
52278      });
52279    }
52280    #scheduleToolbarSyncForCalloutElement(calloutElement) {
52281      if (this.#pendingCalloutSyncFrame) {
52282        cancelAnimationFrame(this.#pendingCalloutSyncFrame);
52283      }
52284      this.#pendingCalloutSyncFrame = requestAnimationFrame(() => {
52285        this.#pendingCalloutSyncFrame = null;
52286        if (!calloutElement.isConnected) return;
52287        this.#syncToolbarForCalloutElement(calloutElement);
52288      });
52289    }
52290    #startPopoverPositioning() {
52291      const popover = this.#iconPopover;
52292      const anchor = this.#iconPopoverAnchor();
52293      if (!popover || !anchor) return;
52294      this.#stopPopoverPositioning();
52295      const updatePosition = () => {
52296        computePosition2(anchor, popover, {
52297          strategy: "fixed",
52298          placement: "bottom",
52299          middleware: [offset2(6), flip2(), shift2({ padding: 8 })]
52300        }).then(({ x: x3, y: y3 }) => {
52301          Object.assign(popover.style, {
52302            position: "fixed",
52303            left: `${x3}px`,
52304            top: `${y3}px`
52305          });
52306        });
52307      };
52308      this.#popoverPositionCleanup = autoUpdate(anchor, popover, updatePosition);
52309      updatePosition();
52310    }
52311    #stopPopoverPositioning() {
52312      this.#popoverPositionCleanup?.();
52313      this.#popoverPositionCleanup = null;
52314    }
52315    #showIconPopoverLayer() {
52316      if (this.#iconPopover && this.#iconPopover.parentElement !== document.body) {
52317        document.body.appendChild(this.#iconPopover);
52318      }
52319    }
52320    #swatchButtons(target) {
52321      const noneButton = `
52322      <button
52323        type="button"
52324        class="lexxy-callout-tools__swatch lexxy-callout-tools__swatch--none"
52325        data-color-target="${target}"
52326        data-variant="${CALLOUT_VARIANT_NONE}"
52327        title="None"
52328        aria-label="None"
52329      >${SWATCH_NONE_ICON_SVG}${SWATCH_CHECK_SVG}</button>
52330    `;
52331      const colorButtons = HIGHLIGHT_VARIANTS.map(
52332        ({ id: id3, label }) => `
52333      <button
52334        type="button"
52335        class="lexxy-callout-tools__swatch"
52336        data-color-target="${target}"
52337        data-variant="${id3}"
52338        style="--swatch-color: var(--callout-${target === "background" ? "bg" : "border"}-${id3}); --swatch-solid: var(--callout-border-${id3});"
52339        title="${label}"
52340        aria-label="${label}"
52341      >${SWATCH_CHECK_SVG}</button>
52342    `
52343      ).join("");
52344      return noneButton + colorButtons;
52345    }
52346    #handleClick(event) {
52347      const uploadCancel = event.target.closest("[data-upload-cancel]");
52348      if (uploadCancel) {
52349        event.preventDefault();
52350        this.#resetUploadPanel();
52351        this.#closeIconPopover();
52352        return;
52353      }
52354      const uploadSave = event.target.closest("[data-upload-save]");
52355      if (uploadSave) {
52356        event.preventDefault();
52357        this.#saveUploadSelection();
52358        return;
52359      }
52360      const uploadPasteClipboard = event.target.closest("[data-upload-paste-clipboard]");
52361      if (uploadPasteClipboard) {
52362        event.preventDefault();
52363        this.#pasteUploadFromClipboard();
52364        return;
52365      }
52366      const deleteButton = event.target.closest("[data-callout-delete]");
52367      if (deleteButton) {
52368        event.preventDefault();
52369        this.#deleteCallout();
52370        return;
52371      }
52372      const iconToggle = event.target.closest("[data-callout-icon-toggle]");
52373      if (iconToggle) {
52374        event.preventDefault();
52375        event.stopPropagation();
52376        this.#toggleIconPopover();
52377        return;
52378      }
52379      const tab = event.target.closest("[data-icon-tab]");
52380      if (tab) {
52381        event.preventDefault();
52382        this.#setIconTab(tab.dataset.iconTab);
52383        return;
52384      }
52385      const removeButton = event.target.closest("[data-callout-remove]");
52386      if (removeButton) {
52387        event.preventDefault();
52388        this.#setNoIcon();
52389        this.#closeIconPopover();
52390        return;
52391      }
52392      const randomIconButton = event.target.closest("[data-callout-random-icon]");
52393      if (randomIconButton) {
52394        event.preventDefault();
52395        this.#setRandomSymbolIcon();
52396        return;
52397      }
52398      const symbolButton = event.target.closest("[data-callout-symbol]");
52399      if (symbolButton) {
52400        event.preventDefault();
52401        this.#setSymbolIcon(symbolButton.dataset.calloutSymbol, symbolButton.dataset.calloutSymbolSvg);
52402        this.#closeIconPopover();
52403        return;
52404      }
52405      const swatch = event.target.closest("[data-variant][data-color-target]");
52406      if (swatch) {
52407        event.preventDefault();
52408        this.#setColor(swatch.dataset.colorTarget, Number(swatch.dataset.variant));
52409        return;
52410      }
52411      const uploadButton = event.target.closest("[data-callout-upload]");
52412      if (uploadButton) {
52413        event.preventDefault();
52414        this.#fileInput.click();
52415        return;
52416      }
52417    }
52418    #handleInput(event) {
52419      if (event.target.matches("[data-icon-search]")) {
52420        this.#visibleIconCount = ICON_GRID_BATCH_SIZE;
52421        this.#resetIconKeyboardNavigation();
52422        this.#renderIconGrid();
52423      } else if (event.target.matches("[data-upload-url]")) {
52424        this.#stageUploadInputUrl(event.target.value);
52425      }
52426    }
52427    #readActiveCalloutState() {
52428      let state = null;
52429      this.editor.getEditorState().read(() => {
52430        const callout = $getToolbarCallout(this.#activeCalloutKey);
52431        if (callout) {
52432          state = {
52433            iconType: callout.getIconType(),
52434            iconSrc: callout.getIconSrc()
52435          };
52436        }
52437      });
52438      return state;
52439    }
52440    #iconTabForIconType(iconType) {
52441      if (iconType === "symbol") return "icons";
52442      if (iconType === "image") return "upload";
52443      return "emoji";
52444    }
52445    #syncUploadPanelFromCalloutState(calloutState) {
52446      const imageUrl = calloutState?.iconType === "image" ? safeImageUrl(calloutState.iconSrc) : null;
52447      if (imageUrl) {
52448        const uploadUrlInput = this.#popoverQuery("[data-upload-url]");
52449        if (uploadUrlInput) uploadUrlInput.value = imageUrl;
52450        this.#stageUploadUrl(imageUrl);
52451        return;
52452      }
52453      this.#resetUploadPanel();
52454    }
52455    #bindInlineIconTriggerEvents() {
52456      if (!this.editorElement) return;
52457      this.#inlineIconMouseDownHandler = (event) => {
52458        if (!event.target.closest("[data-callout-inline-icon-toggle]")) return;
52459        event.preventDefault();
52460      };
52461      this.#inlineIconClickHandler = (event) => {
52462        const trigger = event.target.closest("[data-callout-inline-icon-toggle]");
52463        if (!trigger) return;
52464        event.preventDefault();
52465        event.stopPropagation();
52466        this.editor.update(
52467          () => {
52468            const node = $getNearestNodeFromDOMNode3(trigger);
52469            const callout = $findMatchingParent3(node, $isCalloutNode);
52470            callout?.selectStart();
52471          },
52472          { onUpdate: () => this.#openIconPopover() }
52473        );
52474      };
52475      this.editorElement.addEventListener("mousedown", this.#inlineIconMouseDownHandler);
52476      this.editorElement.addEventListener("click", this.#inlineIconClickHandler);
52477    }
52478    #unbindInlineIconTriggerEvents() {
52479      if (!this.editorElement) return;
52480      if (this.#inlineIconMouseDownHandler) {
52481        this.editorElement.removeEventListener("mousedown", this.#inlineIconMouseDownHandler);
52482        this.#inlineIconMouseDownHandler = null;
52483      }
52484      if (this.#inlineIconClickHandler) {
52485        this.editorElement.removeEventListener("click", this.#inlineIconClickHandler);
52486        this.#inlineIconClickHandler = null;
52487      }
52488    }
52489    #bindEditorFocusEvents() {
52490      if (!this.editorElement) return;
52491      this.#editorFocusOutHandler = (event) => {
52492        if (this.#iconPopoverOpen()) return;
52493        const relatedTarget = event.relatedTarget;
52494        if (relatedTarget instanceof Node) {
52495          const stayingInToolbar = this.contains(relatedTarget) || this.#iconPopover?.contains(relatedTarget);
52496          if (stayingInToolbar) return;
52497        }
52498        this.#activeCalloutKey = null;
52499        this.#hide();
52500      };
52501      this.editorElement.addEventListener("focusout", this.#editorFocusOutHandler);
52502    }
52503    #unbindEditorFocusEvents() {
52504      if (!this.editorElement || !this.#editorFocusOutHandler) return;
52505      this.editorElement.removeEventListener("focusout", this.#editorFocusOutHandler);
52506      this.#editorFocusOutHandler = null;
52507    }
52508    #openIconPopover() {
52509      if (this.#iconPopoverOpen()) return;
52510      this.#toggleIconPopover();
52511    }
52512    #toggleIconPopover() {
52513      const popover = this.#iconPopover;
52514      const toggle = this.#iconPopoverToggle();
52515      if (!popover || !toggle) return;
52516      const willOpen = popover.hidden || popover.classList.contains("hidden");
52517      if (willOpen) {
52518        const calloutState = this.#readActiveCalloutState();
52519        this.#setIconTab(this.#iconTabForIconType(calloutState?.iconType));
52520        popover.hidden = false;
52521        popover.classList.remove("hidden");
52522        toggle.setAttribute("aria-expanded", "true");
52523        this.#showIconPopoverLayer();
52524        this.#startPopoverPositioning();
52525        requestAnimationFrame(() => this.#addGlobalListeners());
52526        this.#afterPopoverPaint(() => {
52527          if (this.#activeIconTab === "emoji") this.#ensureEmojiPicker();
52528        });
52529      } else {
52530        this.#closeIconPopover();
52531      }
52532    }
52533    #setIconTab(tab) {
52534      this.#activeIconTab = tab;
52535      this.#popoverQueryAll("[data-icon-tab]").forEach((button) => {
52536        const isActive = button.dataset.iconTab === tab;
52537        button.setAttribute("aria-selected", String(isActive));
52538      });
52539      this.#popoverQueryAll("[data-icon-tab-panel]").forEach((panel) => {
52540        panel.classList.toggle("hidden", panel.dataset.iconTabPanel !== tab);
52541      });
52542      if (tab === "emoji") {
52543        this.#afterPopoverPaint(() => {
52544          this.#ensureEmojiPicker();
52545          this.#focusEmojiSearch();
52546        });
52547      } else if (tab === "icons") {
52548        this.#resetIconKeyboardNavigation();
52549        this.#ensureIconGrid();
52550        requestAnimationFrame(() => this.#popoverQuery("[data-icon-search]")?.focus());
52551      } else if (tab === "upload") {
52552        this.#syncUploadPanelFromCalloutState(this.#readActiveCalloutState());
52553      }
52554    }
52555    #afterPopoverPaint(callback) {
52556      requestAnimationFrame(() => requestAnimationFrame(callback));
52557    }
52558    #closeIconPopover() {
52559      const popover = this.#iconPopover;
52560      const toggle = this.#iconPopoverToggle();
52561      this.#stopPopoverPositioning();
52562      if (popover) popover.hidden = true;
52563      popover?.classList.add("hidden");
52564      toggle?.setAttribute("aria-expanded", "false");
52565      this.#resetIconKeyboardNavigation();
52566      this.#removeGlobalListeners();
52567    }
52568    #iconPopoverOpen() {
52569      const popover = this.#iconPopover;
52570      return Boolean(popover && !popover.hidden && !popover.classList.contains("hidden"));
52571    }
52572    #ensureEmojiPicker() {
52573      if (this.#emojiPicker) {
52574        this.#afterPopoverPaint(() => this.#highlightSelectedEmoji());
52575        return;
52576      }
52577      const container = this.#popoverQuery("[data-emoji-picker-container]");
52578      if (!container) return;
52579      this.#emojiPicker = createCalloutEmojiPicker(container, {
52580        onSelect: (emoji) => {
52581          this.#afterPopoverPaint(() => {
52582            this.#setEmojiIcon(emoji.native);
52583            this.#closeIconPopover();
52584          });
52585        }
52586      });
52587      this.#watchEmojiPicker();
52588      this.#afterPopoverPaint(() => {
52589        this.#highlightSelectedEmoji();
52590        this.#focusEmojiSearch();
52591      });
52592    }
52593    #focusEmojiSearch(attempts = 4) {
52594      if (this.#activeIconTab !== "emoji") return;
52595      const root = this.#popoverQuery("em-emoji-picker")?.shadowRoot;
52596      const searchInput = root?.querySelector(
52597        'input[type="search"], input[placeholder*="Search" i], input[aria-label*="Search" i], input'
52598      );
52599      if (searchInput instanceof HTMLElement) {
52600        searchInput.focus({ preventScroll: true });
52601        return;
52602      }
52603      if (attempts > 0) this.#afterPopoverPaint(() => this.#focusEmojiSearch(attempts - 1));
52604    }
52605    #watchEmojiPicker() {
52606      this.#emojiPickerObserver?.disconnect();
52607      this.#emojiPickerObserver = null;
52608      const picker = this.#popoverQuery("em-emoji-picker");
52609      const root = picker?.shadowRoot;
52610      if (!root) {
52611        this.#afterPopoverPaint(() => this.#watchEmojiPicker());
52612        return;
52613      }
52614      this.#ensureEmojiPickerStyles(root);
52615      this.#emojiPickerObserver = new MutationObserver(() => this.#highlightSelectedEmoji());
52616      this.#emojiPickerObserver.observe(root, { childList: true, subtree: true });
52617    }
52618    #ensureEmojiPickerStyles(root) {
52619      applyCalloutEmojiPickerStyles(root);
52620    }
52621    #highlightSelectedEmoji() {
52622      const root = this.#popoverQuery("em-emoji-picker")?.shadowRoot;
52623      if (!root) return;
52624      root.querySelectorAll("[data-callout-selected-emoji]").forEach((button) => {
52625        if (button.getAttribute("aria-label") === this.#selectedEmoji) return;
52626        button.removeAttribute("data-callout-selected-emoji");
52627        if (button.getAttribute("aria-current") === "true") button.removeAttribute("aria-current");
52628      });
52629      if (!this.#selectedEmoji) return;
52630      root.querySelectorAll("button[aria-label]").forEach((button) => {
52631        if (button.getAttribute("aria-label") !== this.#selectedEmoji) return;
52632        if (button.dataset.calloutSelectedEmoji === "true" && button.getAttribute("aria-current") === "true") return;
52633        button.dataset.calloutSelectedEmoji = "true";
52634        button.setAttribute("aria-current", "true");
52635      });
52636    }
52637    #ensureIconGrid() {
52638      if (this.#lucideIcons) {
52639        this.#visibleIconCount = ICON_GRID_BATCH_SIZE;
52640        this.#renderIconGrid();
52641        return;
52642      }
52643      this.#setIconStatus("Loading icons...");
52644      loadLucideCalloutIcons().then((icons) => {
52645        this.#lucideIcons = icons;
52646        this.#renderIconGrid();
52647      }).catch((error) => {
52648        console.error(error);
52649        this.#setIconStatus("Could not load icons.");
52650      });
52651    }
52652    #renderIconGrid() {
52653      const grid = this.#popoverQuery("[data-icon-grid]");
52654      const status = this.#popoverQuery("[data-icon-status]");
52655      const query = this.#popoverQuery("[data-icon-search]")?.value || "";
52656      if (!grid || !status || !this.#lucideIcons) return;
52657      if (query !== this.#iconSearchQuery) {
52658        this.#iconSearchQuery = query;
52659        this.#visibleIconCount = ICON_GRID_BATCH_SIZE;
52660      }
52661      const icons = this.#lucideIcons.search(query, this.#visibleIconCount + 1);
52662      const visibleIcons = icons.slice(0, this.#visibleIconCount);
52663      const hasMoreIcons = icons.length > visibleIcons.length;
52664      this.#setIconStatus(icons.length ? "" : "No icons found.");
52665      grid.dataset.hasMoreIcons = String(hasMoreIcons);
52666      grid.innerHTML = visibleIcons.map(
52667        ({ id: id3, label, svg: svg2 }) => `
52668      <button
52669        type="button"
52670        class="lexxy-callout-tools__icon-button"
52671        data-callout-symbol="${escapeHtml(id3)}"
52672        data-callout-symbol-svg="${escapeHtml(svg2)}"
52673        ${this.#selectedSymbol === id3 ? 'aria-selected="true"' : ""}
52674        title="${escapeHtml(label)}"
52675        aria-label="${escapeHtml(label)}"
52676      >${svg2}</button>
52677    `
52678      ).join("");
52679      this.#updateIconKeyboardHighlight();
52680    }
52681    #iconButtons() {
52682      return Array.from(this.#popoverQuery("[data-icon-grid]")?.querySelectorAll("[data-callout-symbol]") || []);
52683    }
52684    #iconGridColumns() {
52685      const grid = this.#popoverQuery("[data-icon-grid]");
52686      if (!grid) return ICON_GRID_COLUMNS;
52687      const template = getComputedStyle(grid).gridTemplateColumns;
52688      if (!template || template === "none") return ICON_GRID_COLUMNS;
52689      return template.split(" ").length || ICON_GRID_COLUMNS;
52690    }
52691    #resetIconKeyboardNavigation() {
52692      this.#iconKeyboardIndex = -1;
52693      this.#iconSearchNavigated = false;
52694      this.#setIconGridKeyboardNav(false);
52695      this.#updateIconKeyboardHighlight();
52696    }
52697    #setIconGridKeyboardNav(active) {
52698      const grid = this.#popoverQuery("[data-icon-grid]");
52699      if (!grid) return;
52700      grid.toggleAttribute("data-keyboard-nav", active);
52701      if (active) this.#clearStuckIconHover(grid);
52702    }
52703    #clearStuckIconHover(grid) {
52704      grid.style.pointerEvents = "none";
52705      requestAnimationFrame(() => {
52706        grid.style.pointerEvents = "";
52707      });
52708    }
52709    #highlightedIconButton() {
52710      if (!this.#iconSearchNavigated || this.#iconKeyboardIndex < 0) return null;
52711      return this.#iconButtons()[this.#iconKeyboardIndex] || null;
52712    }
52713    #updateIconKeyboardHighlight() {
52714      this.#iconButtons().forEach((button, index) => {
52715        const isHighlighted = this.#iconSearchNavigated && index === this.#iconKeyboardIndex;
52716        button.toggleAttribute("data-highlighted", isHighlighted);
52717      });
52718    }
52719    #moveIconKeyboardHighlight(direction) {
52720      const buttons = this.#iconButtons();
52721      if (!buttons.length) return;
52722      const columns = this.#iconGridColumns();
52723      let index = this.#iconKeyboardIndex;
52724      if (!this.#iconSearchNavigated || index < 0) {
52725        index = direction === "down" || direction === "right" ? 0 : buttons.length - 1;
52726        this.#iconSearchNavigated = true;
52727        this.#setIconGridKeyboardNav(true);
52728      } else {
52729        switch (direction) {
52730          case "down":
52731            index = Math.min(index + columns, buttons.length - 1);
52732            break;
52733          case "up":
52734            index = Math.max(index - columns, 0);
52735            break;
52736          case "right":
52737            index = Math.min(index + 1, buttons.length - 1);
52738            break;
52739          case "left":
52740            index = Math.max(index - 1, 0);
52741            break;
52742        }
52743      }
52744      const grid = this.#popoverQuery("[data-icon-grid]");
52745      if (index >= buttons.length - columns && grid?.dataset.hasMoreIcons === "true") {
52746        this.#visibleIconCount += ICON_GRID_BATCH_SIZE;
52747        this.#renderIconGrid();
52748        index = Math.min(index, this.#iconButtons().length - 1);
52749      }
52750      this.#iconKeyboardIndex = index;
52751      this.#updateIconKeyboardHighlight();
52752      this.#scrollToOption(this.#iconButtons()[index], grid);
52753    }
52754    #handleIconGridPointerOver(event) {
52755      if (this.#activeIconTab !== "icons" || !this.#iconSearchNavigated) return;
52756      const button = event.target.closest("[data-callout-symbol]");
52757      if (!button) return;
52758      const index = this.#iconButtons().indexOf(button);
52759      if (index < 0 || index === this.#iconKeyboardIndex) return;
52760      this.#iconKeyboardIndex = index;
52761      this.#updateIconKeyboardHighlight();
52762    }
52763    #shouldNavigateIconGrid(event, direction) {
52764      if (this.#iconSearchNavigated) return true;
52765      const input = event.target;
52766      const start3 = input.selectionStart;
52767      const end = input.selectionEnd;
52768      if (start3 === null || end === null) return true;
52769      if (direction === "down" || direction === "up") return true;
52770      if (direction === "left") return start3 === 0 && end === 0;
52771      if (direction === "right") return start3 === input.value.length && end === input.value.length;
52772      return false;
52773    }
52774    #handleIconSearchKeydown(event) {
52775      if (!event.target.matches("[data-icon-search]")) return;
52776      if (this.#activeIconTab !== "icons") return;
52777      const buttons = this.#iconButtons();
52778      if (!buttons.length) return;
52779      if (event.key === "Enter") {
52780        const highlighted = this.#highlightedIconButton();
52781        if (!highlighted) return;
52782        event.preventDefault();
52783        this.#setSymbolIcon(highlighted.dataset.calloutSymbol, highlighted.dataset.calloutSymbolSvg);
52784        this.#closeIconPopover();
52785        return;
52786      }
52787      const direction = {
52788        ArrowDown: "down",
52789        ArrowUp: "up",
52790        ArrowLeft: "left",
52791        ArrowRight: "right"
52792      }[event.key];
52793      if (!direction) return;
52794      if (!this.#shouldNavigateIconGrid(event, direction)) return;
52795      event.preventDefault();
52796      event.stopPropagation();
52797      const searchInput = event.target;
52798      const selectionStart = searchInput.selectionStart;
52799      const selectionEnd = searchInput.selectionEnd;
52800      this.#moveIconKeyboardHighlight(direction);
52801      requestAnimationFrame(() => {
52802        searchInput.focus({ preventScroll: true });
52803        if (selectionStart === null || selectionEnd === null) return;
52804        searchInput.setSelectionRange(selectionStart, selectionEnd);
52805      });
52806    }
52807    #handleIconGridScroll(event) {
52808      const grid = event.target;
52809      if (!grid?.matches?.("[data-icon-grid]") || grid.dataset.hasMoreIcons !== "true") return;
52810      const remainingScroll = grid.scrollHeight - grid.scrollTop - grid.clientHeight;
52811      if (remainingScroll > 80) return;
52812      this.#visibleIconCount += ICON_GRID_BATCH_SIZE;
52813      this.#renderIconGrid();
52814    }
52815    #scrollToOption(optionEl, content = this.#popoverQuery("[data-icon-grid]")) {
52816      if (!optionEl || !content) return;
52817      const contentRect = content.getBoundingClientRect();
52818      const optionRect = optionEl.getBoundingClientRect();
52819      const optionRelativeTop = optionRect.top - contentRect.top;
52820      const optionRelativeBottom = optionRelativeTop + optionRect.height;
52821      const contentScrollTop = content.scrollTop;
52822      const contentHeight = contentRect.height;
52823      const scrollPadding = optionRect.height + 6;
52824      if (optionRelativeBottom > contentHeight - scrollPadding) {
52825        content.scrollTop = contentScrollTop + (optionRelativeBottom - contentHeight + scrollPadding);
52826      } else if (optionRelativeTop < scrollPadding) {
52827        content.scrollTop = contentScrollTop + (optionRelativeTop - scrollPadding);
52828      }
52829    }
52830    #setIconStatus(message) {
52831      const status = this.#popoverQuery("[data-icon-status]");
52832      if (!status) return;
52833      status.textContent = message;
52834      status.hidden = !message;
52835    }
52836    #setRandomSymbolIcon() {
52837      if (!this.#lucideIcons) return;
52838      const query = this.#popoverQuery("[data-icon-search]")?.value || "";
52839      const icons = this.#lucideIcons.search(query, Number.MAX_SAFE_INTEGER);
52840      const icon = icons[Math.floor(Math.random() * icons.length)];
52841      if (!icon) return;
52842      this.#setSymbolIcon(icon.id, icon.svg);
52843      this.#closeIconPopover();
52844    }
52845    #addGlobalListeners() {
52846      if (this.#outsideClickHandler) return;
52847      this.#outsideClickHandler = (event) => {
52848        const popover = this.#iconPopover;
52849        const toggle = this.#iconPopoverToggle();
52850        if (!popover || popover.classList.contains("hidden")) return;
52851        const path = event.composedPath?.() || [event.target];
52852        const clickedInside = path.some((node) => {
52853          if (!(node instanceof Node)) return false;
52854          return popover.contains(node) || toggle?.contains(node) || this.contains(node);
52855        });
52856        if (clickedInside) return;
52857        const clickedCalloutElement = this.#clickedEditorCalloutElement(path);
52858        this.#closeIconPopover();
52859        if (clickedCalloutElement) {
52860          this.#scheduleToolbarSyncForCalloutElement(clickedCalloutElement);
52861        } else {
52862          this.#activeCalloutKey = null;
52863          this.#hide();
52864        }
52865      };
52866      this.#escapeHandler = (event) => {
52867        if (event.key === "Escape") this.#closeIconPopover();
52868      };
52869      this.#pasteHandler = (event) => this.#handleUploadPaste(event);
52870      document.addEventListener("mousedown", this.#outsideClickHandler, true);
52871      document.addEventListener("keydown", this.#escapeHandler);
52872      document.addEventListener("paste", this.#pasteHandler);
52873    }
52874    #removeGlobalListeners() {
52875      if (this.#outsideClickHandler) {
52876        document.removeEventListener("mousedown", this.#outsideClickHandler, true);
52877        this.#outsideClickHandler = null;
52878      }
52879      if (this.#escapeHandler) {
52880        document.removeEventListener("keydown", this.#escapeHandler);
52881        this.#escapeHandler = null;
52882      }
52883      if (this.#pasteHandler) {
52884        document.removeEventListener("paste", this.#pasteHandler);
52885        this.#pasteHandler = null;
52886      }
52887    }
52888    #handleFileSelected(event) {
52889      const file = event.target.files?.[0];
52890      event.target.value = "";
52891      if (file) this.#stageUploadFile(file);
52892    }
52893    #handleUploadPaste(event) {
52894      if (this.#activeIconTab !== "upload") return;
52895      const file = Array.from(event.clipboardData?.files || []).find((item) => item.type.startsWith("image/"));
52896      if (file) {
52897        event.preventDefault();
52898        this.#stageUploadFile(file);
52899        return;
52900      }
52901      const text2 = event.clipboardData?.getData("text/plain")?.trim();
52902      if (!text2 || event.target?.matches?.("[data-upload-url]")) return;
52903      const url = safeImageUrl(text2);
52904      event.preventDefault();
52905      if (url) {
52906        this.#validateAndStageUploadUrl(url);
52907      } else {
52908        this.#rejectUploadUrl();
52909      }
52910    }
52911    async #pasteUploadFromClipboard() {
52912      if (!navigator.clipboard) {
52913        this.#setUploadStatus("Clipboard access is not available in this browser.");
52914        return;
52915      }
52916      try {
52917        if (navigator.clipboard.read) {
52918          const items = await navigator.clipboard.read();
52919          for (const item of items) {
52920            const imageType = item.types.find((type) => type.startsWith("image/"));
52921            if (!imageType) continue;
52922            const blob = await item.getType(imageType);
52923            const extension = imageType.split("/")[1] || "png";
52924            this.#stageUploadFile(new File([blob], `clipboard-image.${extension}`, { type: imageType }));
52925            return;
52926          }
52927        }
52928        const text2 = await navigator.clipboard.readText();
52929        const url = safeImageUrl(text2.trim());
52930        if (url) {
52931          this.#validateAndStageUploadUrl(url);
52932        } else {
52933          this.#rejectUploadUrl("Clipboard does not contain an image or image URL.");
52934        }
52935      } catch (error) {
52936        console.error(error);
52937        this.#setUploadStatus("Allow clipboard access to paste an image.");
52938      }
52939    }
52940    #handleUploadDrag(event) {
52941      if (this.#activeIconTab !== "upload") return;
52942      if (!event.dataTransfer?.types?.includes("Files")) return;
52943      event.preventDefault();
52944      this.#popoverQuery("[data-callout-upload]")?.classList.add("is-dragging");
52945    }
52946    #handleUploadDragLeave(event) {
52947      if (!event.target.closest("[data-callout-upload]")) return;
52948      this.#popoverQuery("[data-callout-upload]")?.classList.remove("is-dragging");
52949    }
52950    #handleUploadDrop(event) {
52951      if (this.#activeIconTab !== "upload") return;
52952      const file = Array.from(event.dataTransfer?.files || []).find((item) => item.type.startsWith("image/"));
52953      if (!file) return;
52954      event.preventDefault();
52955      this.#popoverQuery("[data-callout-upload]")?.classList.remove("is-dragging");
52956      this.#stageUploadFile(file);
52957    }
52958    #stageUploadFile(file) {
52959      if (!isCalloutIconFile(file)) {
52960        this.#setUploadStatus("Choose a PNG, JPG, WEBP, or GIF under 1MB.");
52961        return;
52962      }
52963      this.#uploadUrlValidationId += 1;
52964      this.#revokeUploadPreview();
52965      this.#uploadFile = file;
52966      this.#uploadUrl = null;
52967      this.#uploadPreviewObjectUrl = URL.createObjectURL(file);
52968      this.#renderUploadPreview(this.#uploadPreviewObjectUrl, file.name);
52969      this.#setUploadStatus("");
52970    }
52971    #stageUploadUrl(url) {
52972      this.#revokeUploadPreview();
52973      this.#uploadFile = null;
52974      this.#uploadUrl = url;
52975      this.#renderUploadPreview(url, "Image preview");
52976      this.#setUploadStatus("");
52977    }
52978    #stageUploadInputUrl(value) {
52979      this.#uploadUrlValidationId += 1;
52980      const url = safeImageUrl(value.trim());
52981      if (url) {
52982        this.#validateAndStageUploadUrl(url);
52983      } else if (!value.trim() && this.#uploadUrl) {
52984        this.#resetUploadPanel();
52985      } else if (value.trim()) {
52986        this.#rejectUploadUrl();
52987      } else {
52988        this.#setUploadStatus("");
52989      }
52990    }
52991    #validateAndStageUploadUrl(url) {
52992      const validationId = ++this.#uploadUrlValidationId;
52993      this.#clearUploadSelection();
52994      this.#setUploadStatus("Checking image...");
52995      this.#loadUploadPreview(url).then((loaded) => {
52996        if (validationId !== this.#uploadUrlValidationId) return;
52997        if (loaded) {
52998          this.#stageUploadUrl(url);
52999        } else {
53000          this.#rejectUploadUrl("Use a direct image URL that can be previewed.");
53001        }
53002      });
53003    }
53004    #loadUploadPreview(url) {
53005      return new Promise((resolve) => {
53006        const image = new Image();
53007        let settled = false;
53008        const finish = (loaded) => {
53009          if (settled) return;
53010          settled = true;
53011          resolve(loaded);
53012        };
53013        image.onload = () => finish(image.naturalWidth > 0 && image.naturalHeight > 0);
53014        image.onerror = () => finish(false);
53015        image.src = url;
53016        setTimeout(() => finish(false), 5e3);
53017      });
53018    }
53019    #rejectUploadUrl(message = "Use a direct image URL or paste an image file.") {
53020      this.#uploadUrlValidationId += 1;
53021      this.#clearUploadSelection();
53022      this.#setUploadStatus(message);
53023    }
53024    #renderUploadPreview(src, label) {
53025      const empty = this.#popoverQuery("[data-upload-empty]");
53026      const preview = this.#popoverQuery("[data-upload-preview]");
53027      const saveButton = this.#popoverQuery("[data-upload-save]");
53028      if (!empty || !preview || !saveButton) return;
53029      empty.classList.add("hidden");
53030      preview.classList.remove("hidden");
53031      preview.innerHTML = `
53032      <img src="${escapeHtml(src)}" alt="">
53033      <span>${escapeHtml(label)}</span>
53034    `;
53035      saveButton.disabled = false;
53036    }
53037    #resetUploadPanel() {
53038      this.#uploadUrlValidationId += 1;
53039      this.#clearUploadSelection();
53040      const uploadUrlInput = this.#popoverQuery("[data-upload-url]");
53041      if (uploadUrlInput) uploadUrlInput.value = "";
53042      this.#setUploadStatus("");
53043    }
53044    #clearUploadSelection() {
53045      this.#uploadFile = null;
53046      this.#uploadUrl = null;
53047      this.#uploadSaving = false;
53048      this.#revokeUploadPreview();
53049      const empty = this.#popoverQuery("[data-upload-empty]");
53050      const preview = this.#popoverQuery("[data-upload-preview]");
53051      const saveButton = this.#popoverQuery("[data-upload-save]");
53052      const uploadButton = this.#popoverQuery("[data-callout-upload]");
53053      empty?.classList.remove("hidden");
53054      preview?.classList.add("hidden");
53055      preview?.replaceChildren();
53056      uploadButton?.classList.remove("is-dragging");
53057      if (saveButton) saveButton.disabled = true;
53058    }
53059    #revokeUploadPreview() {
53060      if (this.#uploadPreviewObjectUrl) {
53061        URL.revokeObjectURL(this.#uploadPreviewObjectUrl);
53062        this.#uploadPreviewObjectUrl = null;
53063      }
53064    }
53065    #setUploadStatus(message) {
53066      const status = this.#popoverQuery("[data-upload-status]");
53067      if (!status) return;
53068      status.textContent = message;
53069      status.hidden = !message;
53070    }
53071    async #saveUploadSelection() {
53072      if (this.#uploadSaving || !this.#uploadFile && !this.#uploadUrl) return;
53073      this.#uploadSaving = true;
53074      const saveButton = this.#popoverQuery("[data-upload-save]");
53075      if (saveButton) {
53076        saveButton.disabled = true;
53077        saveButton.textContent = "Saving...";
53078      }
53079      this.#setUploadStatus("");
53080      try {
53081        const imageUrl = this.#uploadFile ? await uploadCalloutIcon(this.editorElement, this.#uploadFile) : this.#uploadUrl;
53082        this.#setImageIcon(imageUrl);
53083        this.#resetUploadPanel();
53084        this.#closeIconPopover();
53085      } catch (error) {
53086        console.error(error);
53087        this.#setUploadStatus(error.message || "Could not save the image.");
53088        if (saveButton) saveButton.disabled = false;
53089      } finally {
53090        this.#uploadSaving = false;
53091        if (saveButton) saveButton.textContent = "Save";
53092      }
53093    }
53094    #setEmojiIcon(emoji) {
53095      this.editor.update(() => {
53096        const callout = $getToolbarCallout(this.#activeCalloutKey);
53097        callout?.setIconType("emoji").setIcon(emoji).setIconSrc(null);
53098      });
53099      this.editor.focus();
53100    }
53101    #setSymbolIcon(iconId, svg2 = null) {
53102      this.editor.update(() => {
53103        const callout = $getToolbarCallout(this.#activeCalloutKey);
53104        callout?.setIconType("symbol").setIcon(iconId).setIconSrc(svg2);
53105      });
53106      this.editor.focus();
53107    }
53108    #setImageIcon(url) {
53109      this.editor.update(() => {
53110        const callout = $getToolbarCallout(this.#activeCalloutKey);
53111        callout?.setIconType("image").setIconSrc(url);
53112      });
53113      this.editor.focus();
53114    }
53115    #setNoIcon() {
53116      this.editor.update(() => {
53117        const callout = $getToolbarCallout(this.#activeCalloutKey);
53118        callout?.setIconType("none").setIcon("").setIconSrc(null);
53119      });
53120      this.editor.focus();
53121    }
53122    #deleteCallout() {
53123      const targetKey = this.#activeCalloutKey;
53124      this.editor.update(() => {
53125        const callout = $getToolbarCallout(targetKey);
53126        if (!callout) return;
53127        const nextSibling = callout.getNextSibling();
53128        const previousSibling = callout.getPreviousSibling();
53129        callout.remove();
53130        if ($isElementNode5(nextSibling)) {
53131          nextSibling.selectStart();
53132        } else if ($isElementNode5(previousSibling)) {
53133          previousSibling.selectEnd();
53134        }
53135      });
53136      this.#activeCalloutKey = null;
53137      this.#hide();
53138      this.editor.focus();
53139    }
53140    #setColor(target, variant) {
53141      this.editor.update(() => {
53142        const callout = $getToolbarCallout(this.#activeCalloutKey);
53143        if (!callout) return;
53144        if (target === "border") {
53145          callout.setBorderVariant(variant);
53146        } else {
53147          callout.setBgVariant(variant);
53148        }
53149      });
53150      this.editor.focus();
53151    }
53152    #monitorSelection() {
53153      this.#updateListener = this.editor.registerUpdateListener(({ editorState }) => {
53154        editorState.read(() => {
53155          const callout = $getCalloutInSelection();
53156          if (callout) {
53157            this.#syncUI(callout);
53158            this.#show(callout);
53159          } else if (this.#iconPopoverOpen()) {
53160            return;
53161          } else {
53162            this.#activeCalloutKey = null;
53163            this.#hide();
53164          }
53165        });
53166      });
53167    }
53168    #syncUI(callout) {
53169      this.#activeCalloutKey = callout.getKey();
53170      const preview = this.querySelector("[data-callout-icon-preview]");
53171      if (preview) {
53172        this.#syncIconPreview(preview, callout);
53173      }
53174      this.querySelectorAll("[data-color-target='border'][data-variant]").forEach((button) => {
53175        const isSelected = Number(button.dataset.variant) === callout.getBorderVariant();
53176        if (isSelected) {
53177          button.setAttribute("aria-selected", "true");
53178        } else {
53179          button.removeAttribute("aria-selected");
53180        }
53181      });
53182      this.querySelectorAll("[data-color-target='background'][data-variant]").forEach((button) => {
53183        const isSelected = Number(button.dataset.variant) === callout.getBgVariant();
53184        if (isSelected) {
53185          button.setAttribute("aria-selected", "true");
53186        } else {
53187          button.removeAttribute("aria-selected");
53188        }
53189      });
53190      this.#popoverQueryAll("[data-callout-symbol]").forEach((button) => {
53191        button.toggleAttribute(
53192          "aria-selected",
53193          callout.getIconType() === "symbol" && button.dataset.calloutSymbol === callout.getIcon()
53194        );
53195      });
53196      this.#selectedSymbol = callout.getIconType() === "symbol" ? callout.getIcon() : null;
53197      this.#selectedEmoji = callout.getIconType() === "emoji" ? callout.getIcon() : null;
53198      this.#activeIconTab = this.#iconTabForIconType(callout.getIconType());
53199      this.#highlightSelectedEmoji();
53200    }
53201    #syncIconPreview(preview, callout) {
53202      preview.replaceChildren();
53203      if (callout.getIconType() === "none") {
53204        preview.innerHTML = `<span class="lexxy-callout-tools__icon-none lexxy-callout-tools__icon-empty" aria-hidden="true">-</span>`;
53205      } else if (callout.getIconType() === "image" && callout.getIconSrc()) {
53206        const image = document.createElement("img");
53207        image.src = callout.getIconSrc();
53208        image.alt = "";
53209        image.className = "lexxy-callout-tools__icon-image";
53210        preview.append(image);
53211      } else if (callout.getIconType() === "symbol") {
53212        const svg2 = sanitizedSvgElement(callout.getIconSrc()) || sanitizedSvgElement(calloutIconById(callout.getIcon())?.svg);
53213        if (svg2) {
53214          preview.append(svg2);
53215        } else {
53216          preview.innerHTML = `<span class="lexxy-callout-tools__icon-none lexxy-callout-tools__icon-empty">-</span>`;
53217        }
53218      } else {
53219        preview.textContent = callout.getIcon() || "\u{1F4A1}";
53220      }
53221    }
53222    #show(callout) {
53223      const dom = this.editor.getElementByKey(callout.getKey());
53224      if (!dom) return;
53225      const calloutRect = dom.getBoundingClientRect();
53226      const editorRect = this.editorElement.getBoundingClientRect();
53227      const relativeTop = calloutRect.top - editorRect.top;
53228      const relativeCenter = (calloutRect.left + calloutRect.right) / 2 - editorRect.left;
53229      this.style.display = "flex";
53230      this.style.top = `${relativeTop}px`;
53231      this.style.left = `${relativeCenter}px`;
53232    }
53233    #hide() {
53234      this.style.display = "none";
53235      this.#closeIconPopover();
53236    }
53237  };
53238  if (!customElements.get("lexxy-callout-tools")) {
53239    customElements.define("lexxy-callout-tools", CalloutToolsElement);
53240  }
53241
53242  
53242// app/javascript/src/lexxy/toolbar_icons.js
53243  var ICONS2 = {
53244    audio: `
53245    <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" aria-hidden="true" focusable="false">
53246      <g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" stroke="currentColor">
53247        <path d="M5,5.75H2.25c-.828,0-1.5,.672-1.5,1.5v3.5c0,.828,.672,1.5,1.5,1.5h2.75l5.48,3.508c.333,.213,.77-.026,.77-.421V2.664c0-.395-.437-.634-.77-.421l-5.48,3.508Z"></path>
53248        <path d="M13.914,7.586c.781,.781,.781,2.047,0,2.828"></path>
53249        <path d="M15.859,5.641c1.855,1.855,1.855,4.863,0,6.718"></path>
53250      </g>
53251    </svg>
53252  `,
53253    attachment: `
53254    <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" aria-hidden="true" focusable="false">
53255      <g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" stroke="currentColor">
53256        <path d="M10.985,5.422l-4.773,4.773c-.586,.586-.586,1.536,0,2.121h0c.586,.586,1.536,.586,2.121,0l4.95-4.95c1.172-1.172,1.172-3.071,0-4.243h0c-1.172-1.172-3.071-1.172-4.243,0l-4.95,4.95c-1.757,1.757-1.757,4.607,0,6.364h0c1.757,1.757,4.607,1.757,6.364,0l4.773-4.773"></path>
53257      </g>
53258    </svg>
53259  `,
53260    bold: `
53261    <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" aria-hidden="true" focusable="false">
53262      <g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" stroke="currentColor">
53263        <path d="M6.75 2.25H10C11.795 2.25 13.25 3.71 13.25 5.5C13.25 7.29 11.795 8.75 10 8.75H6.75"></path>
53264        <path d="M6.75 8.75H10.75C12.683 8.75 14.25 10.3199 14.25 12.25C14.25 14.1801 12.683 15.75 10.75 15.75H6.75"></path>
53265        <path d="M6.75 15.75H4.75C4.198 15.75 3.75 15.3 3.75 14.75V3.25C3.75 2.7 4.198 2.25 4.75 2.25H6.75V15.75Z"></path>
53266      </g>
53267    </svg>
53268  `,
53269    bulletList: `
53270    <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" aria-hidden="true" focusable="false">
53271      <g fill="currentColor">
53272        <path d="M15.75,9.75h-7.5c-.414,0-.75-.336-.75-.75s.336-.75,.75-.75h7.5c.414,0,.75,.336,.75,.75s-.336,.75-.75,.75Z"></path>
53273        <path d="M15.75,4.5h-7.5c-.414,0-.75-.336-.75-.75s.336-.75,.75-.75h7.5c.414,0,.75,.336,.75,.75s-.336,.75-.75,.75Z"></path>
53274        <circle cx="3.75" cy="9" r="1.75"></circle>
53275        <circle cx="3.75" cy="3.75" r="1.75"></circle>
53276        <circle cx="3.75" cy="14.25" r="1.75"></circle>
53277        <path d="M15.75,15h-7.5c-.414,0-.75-.336-.75-.75s.336-.75,.75-.75h7.5c.414,0,.75,.336,.75,.75s-.336,.75-.75,.75Z"></path>
53278      </g>
53279    </svg>
53280  `,
53281    callout: `
53282    <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" aria-hidden="true" focusable="false">
53283      <g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" stroke="currentColor">
53284        <line x1="6.75" y1="13.25" x2="11.25" y2="13.25"></line>
53285        <path d="M14,6.75c0-3.113-2.846-5.562-6.078-4.887-1.932,.403-3.475,1.993-3.834,3.933-.434,2.344,.771,4.459,2.662,5.415v3.039c0,1.105,.895,2,2,2h.5c1.105,0,2-.895,2-2v-3.039c1.63-.824,2.7
532855-2.51,2.75-4.461Z"></path>
53286      </g>
53287    </svg>
53288  `,
53289    checklist: `
53290    <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" aria-hidden="true" focusable="false">
53291      <g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" stroke="currentColor">
53292        <line x1="10.25" y1="5.25" x2="16.25" y2="5.25"></line>
53293        <line x1="10.25" y1="12.75" x2="16.25" y2="12.75"></line>
53294        <polyline points="2.244 5.641 3.603 7 7 2.583"></polyline>
53295        <rect x="2.25" y="10.75" width="4.5" height="4.5" rx="1" ry="1"></rect>
53296      </g>
53297    </svg>
53298  `,
53299    toggleList: `
53300    <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" aria-hidden="true" focusable="false">
53301      <g fill="currentColor">
53302        <path d="M4.8 2.75a.55.55 0 0 1 .825-.476l2.1 1.45a.55.55 0 0 1 0 .952l-2.1 1.45A.55.55 0 0 1 4.8 5.65v-2.9Z"></path>
53303        <path d="M4.8 7.55a.55.55 0 0 1 .825-.476l2.1 1.45a.55.55 0 0 1 0 .952l-2.1 1.45A.55.55 0 0 1 4.8 10.45v-2.9Z"></path>
53304        <path d="M4.8 12.35a.55.55 0 0 1 .825-.476l2.1 1.45a.55.55 0 0 1 0 .952l-2.1 1.45a.55.55 0 0 1-.825-.476v-2.9Z"></path>
53305        <path d="M15.75 4.95h-5.5a.75.75 0 0 1 0-1.5h5.5a.75.75 0 0 1 0 1.5Z"></path>
53306        <path d="M15.75 9.75h-5.5a.75.75 0 0 1 0-1.5h5.5a.75.75 0 0 1 0 1.5Z"></path>
53307        <path d="M15.75 14.55h-5.5a.75.75 0 0 1 0-1.5h5.5a.75.75 0 0 1 0 1.5Z"></path>
53308      </g>
53309    </svg>
53310  `,
53311    clearFormatting: `
53312    <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" aria-hidden="true" focusable="false">
53313      <g fill="currentColor">
53314        <path d="M16,16h-7.374c-.414,0-.75-.336-.75-.75s.336-.75,.75-.75h7.374c.414,0,.75,.336,.75,.75s-.336,.75-.75,.75Z"></path>
53315        <path d="M16.056,5.691l-3.712-3.713c-.851-.85-2.333-.848-3.182,0L1.944,9.197c-.425,.425-.659,.99-.659,1.591s.234,1.167,.659,1.591l3.401,3.402c.141,.141,.331,.22,.53,.22h2.743c.199,0,.39-.079,.53-.22l6.906-6.907c.425-.425,.659-.99,.659-1.591s-.234-1.167-.659-1.591Zm-7.747,8.809h-2.122l-3.182-3.183c-.142-.141-.22-.33-.22-.53s.078-.389,.22-.53l3.078-3.078,4.773,4.773-2.548,2.548Z"></path>
53316      </g>
53317    </svg>
53318  `,
53319    code: `
53320    <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" aria-hidden="true" focusable="false">
53321      <g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" stroke="currentColor">
53322        <path d="M14 6.25L16.25 4L14 1.75"></path>
53323        <path d="M6.0225 2.75H4.75C3.645 2.75 2.75 3.646 2.75 4.75V13.25C2.75 14.354 3.645 15.25 4.75 15.25H13.25C14.355 15.25 15.25 14.354 15.25 13.25V8.97748"></path>
53324        <path d="M11 6.25L8.75 4L11 1.75"></path>
53325      </g>
53326    </svg>
53327  `,
53328    format: `
53329    <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" aria-hidden="true" focusable="false">
53330      <g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" stroke="currentColor">
53331        <path d="M6.75 2.75V15.25"></path>
53332        <path d="M11.75 2.75H1.75"></path>
53333        <path d="M13.25 7.75V15.25"></path>
53334        <path d="M16.25 7.75H10.25"></path>
53335      </g>
53336    </svg>
53337  `,
53338    heading1: `
53339    <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" aria-hidden="true" focusable="false">
53340      <g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" stroke="currentColor">
53341        <line x1="2.75" y1="4.75" x2="2.75" y2="13.25"></line>
53342        <line x1="8.75" y1="4.75" x2="8.75" y2="13.25"></line>
53343        <line x1="2.75" y1="9" x2="8.75" y2="9"></line>
53344        <path d="M14.75,13.25V4.75s-.974,1.713-3.04,2.108"></path>
53345      </g>
53346    </svg>
53347  `,
53348    heading2: `
53349    <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" aria-hidden="true" focusable="false">
53350      <g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" stroke="currentColor">
53351        <line x1="1.25" y1="4.75" x2="1.25" y2="13.25"></line>
53352        <line x1="7.25" y1="4.75" x2="7.25" y2="13.25"></line>
53353        <line x1="1.25" y1="9" x2="7.25" y2="9"></line>
53354        <path d="M10.5,6.931c.384-1.424,1.707-2.203,3.137-2.181,1.43,.022,2.774,.69,2.86,2.181s-1.43,2.492-2.998,3.16c-1.569,.668-2.87,1.291-2.998,3.16h6"></path>
53355      </g>
53356    </svg>
53357  `,
53358    heading3: `
53359    <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" aria-hidden="true" focusable="false">
53360      <g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" stroke="currentColor">
53361        <line x1="1.75" y1="4.75" x2="1.75" y2="13.25"></line>
53362        <line x1="7.75" y1="4.75" x2="7.75" y2="13.25"></line>
53363        <line x1="1.75" y1="9" x2="7.75" y2="9"></line>
53364        <path d="M10.75,4.75h5.542l-4.005,3.462c1.322-.342,2.672-.141,3.505,.744,1.022,1.086,.868,2.597-.012,3.505s-3.515,1.436-5.029-.727"></path>
53365      </g>
53366    </svg>
53367  `,
53368    heading4: `
53369    <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" aria-hidden="true" focusable="false">
53370      <g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" stroke="currentColor">
53371        <line x1="1.75" y1="4.75" x2="1.75" y2="13.25"></line>
53372        <line x1="7.75" y1="4.75" x2="7.75" y2="13.25"></line>
53373        <line x1="1.75" y1="9" x2="7.75" y2="9"></line>
53374        <polyline points="16.691 10.75 10.25 10.75 10.25 10.641 15 4.75 15 13.25"></polyline>
53375      </g>
53376    </svg>
53377  `,
53378    highlight: `
53379    <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" aria-hidden="true" focusable="false">
53380      <g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" stroke="currentColor">
53381        <path d="m8.3034,16.217c-3.7776-.3601-6.7098-3.619-6.5469-7.5271.157-3.7659,3.3501-6.8755,7.1188-6.9388,4.0612-.0683,7.3747,3.2034,7.3747,7.2489h0c0,1.5188-1.2312,2.75-2.75,2.75h-2.963c-1.0336,0-1.6928,1.1036-1.2027,2.0137l.2374.4409c.2597.4823.2062,1.0732-.1361,1.501h0c-.2736.342-.6962.553-1.1322.5115Z"></path>
53382        <circle cx="9" cy="5" r="1" fill="currentColor" stroke-width="0"></circle>
53383        <circle cx="6.1716" cy="6.1716" r="1" fill="currentColor" stroke-width="0"></circle>
53384        <circle cx="11.8284" cy="6.1716" r="1" fill="currentColor" stroke-width="0"></circle>
53385        <circle cx="5" cy="9" r="1" fill="currentColor" stroke-width="0"></circle>
53386      </g>
53387    </svg>
53388  `,
53389    image: `
53390    <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" aria-hidden="true" focusable="false">
53391      <g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" stroke="currentColor">
53392        <path d="M3.762,14.989l6.074-6.075c.781-.781,2.047-.781,2.828,0l2.586,2.586"></path>
53393        <rect x="2.75" y="2.75" width="12.5" height="12.5" rx="2" ry="2"></rect>
53394        <circle cx="6.25" cy="7.25" r="1.25" fill="currentColor" data-stroke="none" stroke="none"></circle>
53395      </g>
53396    </svg>
53397  `,
53398    indentDecrease: `
53399    <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" aria-hidden="true" focusable="false">
53400      <g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" stroke="currentColor">
53401        <path d="M15.25 6.75L13 9L15.25 11.25"></path>
53402        <path d="M2.75 14.25H15.25"></path>
53403        <path d="M2.75 10.75H10.25"></path>
53404        <path d="M2.75 7.25H10.25"></path>
53405        <path d="M2.75 3.75H15.25"></path>
53406      </g>
53407    </svg>
53408  `,
53409    indentIncrease: `
53410    <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" aria-hidden="true" focusable="false">
53411      <g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" stroke="currentColor">
53412        <path d="M2.75 11.25L5 9L2.75 6.75"></path>
53413        <path d="M15.25 3.75H2.75"></path>
53414        <path d="M15.25 7.25H7.75"></path>
53415        <path d="M15.25 10.75H7.75"></path>
53416        <path d="M15.25 14.25H2.75"></path>
53417      </g>
53418    </svg>
53419  `,
53420    italic: `
53421    <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" aria-hidden="true" focusable="false">
53422      <g stroke-linejoin="round" stroke-linecap="round" stroke-width="1.75" fill="none" stroke="currentColor">
53423        <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
53424        <path d="M11 5l6 0"></path>
53425        <path d="M7 19l6 0"></path>
53426        <path d="M14 5l-4 14"></path>
53427      </g>
53428    </svg>
53429  `,
53430    link: `
53431    <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" aria-hidden="true" focusable="false">
53432      <g fill="currentColor">
53433        <path fill-rule="evenodd" clip-rule="evenodd" d="M9.03166 6.54197C9.22575 6.9079 9.08644 7.36188 8.72052 7.55597C8.47184 7.68787 8.24717 7.85851 8.04832 8.05733C6.96021 9.14544 6.96021 10.9086 8.04832 11.9967L10.2233 14.1717C11.3114 15.2598 13.0746 15.2598 14.1627 14.1717C15.2507 13.0836 15.2608 11.3104 14.1727 10.2223L13.4103 9.45993C13.1174 9.16703 13.1174 8.69216 13.4103 8.39927C13.7032 8.10638 14.178 8.10638 14.4709 8.39927L15.2333 9.16167C16.9072 10.8356 16.9
53433072 13.5484 15.2333 15.2223C13.5594 16.8962 10.8365 16.9062 9.16266 15.2323L6.98766 13.0573C5.31377 11.3834 5.31377 8.67056 6.98766 6.99667C7.29576 6.68747 7.64975 6.42597 8.01766 6.23083C8.38359 6.03674 8.83757 6.17604 9.03166 6.54197Z"></path>
53434        <path fill-rule="evenodd" clip-rule="evenodd" d="M2.77868 2.76766C4.45257 1.09376 7.16544 1.09376 8.83934 2.76766L11.0143 4.94266C12.6882 6.61655 12.6882 9.32942 11.0143 11.0033C10.7101 11.3075 10.3647 11.5674 9.98433 11.7692C9.6184 11.9633 9.16442 11.824 8.97033 11.458C8.77624 11.0921 8.91554 10.6381 9.28147 10.444C9.53006 10.3122 9.7549 10.1414 9.95368 9.94267C11.0418 8.85455 11.0418 7.09142 9.95368 6.00332L7.77868 3.82832C6.69057 2.74021 4.92744 2.74021 3.83934 3.82832C2.76193 4.90573 2.74775 6.69607 3.82934 7.77766L4.59174 8.54006C4.88463 8.83295 4.88463 9.30782 4.59174 9.60072C4.29884 9.89361 3.82397 9.89361 3.53108 9.60072L2.76868 8.83832C1.10903 7.17867 1.1232 4.42314 2.77868 2.76766Z"></path>
53435      </g>
53436    </svg>
53437  `,
53438    numberList: `
53439    <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" aria-hidden="true" focusable="false">
53440      <g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" stroke="currentColor">
53441        <line x1="9.25" y1="9" x2="15.75" y2="9"></line>
53442        <line x1="9.25" y1="3.75" x2="15.75" y2="3.75"></line>
53443        <line x1="9.25" y1="14.25" x2="15.75" y2="14.25"></line>
53444        <path d="M2.5,11.661c.259-.921,1.152-1.425,2.116-1.411,.965,.014,1.872,.446,1.929,1.411s-.965,1.612-2.023,2.044c-1.058,.432-1.936,.835-2.023,2.044H6.548"></path>
53445        <path d="M4.75,7.5V2s-.63,1.108-1.967,1.364"></path>
53446      </g>
53447    </svg>
53448  `,
53449    pdf: `
53450    <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" aria-hidden="true" focusable="false">
53451      <g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" stroke="currentColor">
53452        <line x1="10.25" y1="6.25" x2="12.25" y2="6.25"></line>
53453        <line x1="5.75" y1="9.25" x2="12.25" y2="9.25"></line>
53454        <line x1="5.75" y1="12.25" x2="12.25" y2="12.25"></line>
53455        <rect x="1.75" y="2.75" width="14.5" height="12.5" rx="2" ry="2" transform="translate(18 0) rotate(90)"></rect>
53456        <rect x="5.75" y="4.75" width="1.5" height="1.5" fill="currentColor"></rect>
53457      </g>
53458    </svg>
53459  `,
53460    paragraph: `
53461    <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" aria-hidden="true" focusable="false">
53462      <g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" stroke="currentColor">
53463        <line x1="6.75" y1="15.25" x2="11.25" y2="15.25"></line>
53464        <line x1="9" y1="2.75" x2="9" y2="15.25"></line>
53465        <polyline points="14.75 4.25 14 2.75 4 2.75 3.25 4.25"></polyline>
53466      </g>
53467    </svg>
53468  `,
53469    text: `
53470    <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" aria-hidden="true" focusable="false">
53471      <g fill="currentColor">
53472        <path d="M11.25,14.5h-1.5V2.75c0-.414-.336-.75-.75-.75s-.75,.336-.75,.75V14.5h-1.5c-.414,0-.75,.336-.75,.75s.336,.75,.75,.75h4.5c.414,0,.75-.336,.75-.75s-.336-.75-.75-.75Z"></path>
53473        <path d="M14.751,5c-.275,0-.54-.152-.672-.415l-.543-1.085H4.464l-.543,1.085c-.185,.37-.635,.521-1.006,.335s-.521-.636-.336-1.006l.75-1.5c.127-.254,.387-.415,.671-.415H14c.284,0,.544,.161,.671,.415l.75,1.5c.186,.371,.035,.821-.336,1.006-.107,.054-.222,.079-.334,.079Z"></path>
53474      </g>
53475    </svg>
53476  `,
53477    quote: `
53478    <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" aria-hidden="true" focusable="false">
53479      <g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" stroke="currentColor">
53480        <path d="M2.75 14.25H15.25"></path>
53481        <path d="M2.75 10.75H15.25"></path>
53482        <path d="M12.25 7.25H15.25"></path>
53483        <path d="M12.25 3.75H15.25"></path>
53484        <path d="M2.75 5.75H4.75V7.25H2.75V5.75ZM2.75 5.75C2.75 3.957 3.348 3.168 4.424 2.75"></path>
53485        <path d="M7.25 5.75H9.25V7.25H7.25V5.75ZM7.25 5.75C7.25 3.957 7.848 3.168 8.924 2.75"></path>
53486      </g>
53487    </svg>
53488  `,
53489    redo: `
53490    <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" aria-hidden="true" focusable="false">
53491      <g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" stroke="currentColor">
53492        <path d="M15.75 6.25H6C3.929 6.25 2.25 7.929 2.25 10C2.25 12.071 3.929 13.75 6 13.75H9.75"></path>
53493        <path d="M12.25 9.75L15.75 6.25L12.25 2.75"></path>
53494      </g>
53495    </svg>
53496  `,
53497    separator: `
53498    <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" aria-hidden="true" focusable="false">
53499      <g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" stroke="currentColor">
53500        <path d="m2.75,2.25v1.5c0,1.105.895,2,2,2h8.5c1.105,0,2-.895,2-2v-1.5"></path>
53501        <path d="m2.75,15.75v-1.5c0-1.105.895-2,2-2h8.5c1.105,0,2,.895,2,2v1.5"></path>
53502        <line x1="16" y1="9" x2="2" y2="9"></line>
53503      </g>
53504    </svg>
53505  `,
53506    strike: `
53507    <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" aria-hidden="true" focusable="false">
53508      <g fill="currentColor">
53509        <path d="M9.67402 9.75C9.61902 9.75 9.56302 9.744 9.50702 9.731C9.28001 9.679 9.05902 9.636 8.84902 9.599C5.44502 8.991 4.57202 7.218 4.43902 5.837C4.33202 4.728 4.63202 3.749 5.30802 3.006C6.63702 1.543 8.83402 1.5 9.08002 1.5C10.27 1.5 12.423 1.868 13.465 4.334C13.626 4.715 13.447 5.155 13.066 5.317C12.685 5.478 12.244 5.299 12.083 4.918C11.545 3.645 10.535 3 9.08002 3C8.47801 3 7.14601 3.212 6.41701 4.014C6.02302 4.448 5.86502 4.996 5.93202 5.693C5.97702 6.161 6.11502 7.587 9.11202 8.122C9.34302 8.163 9.58902 8.211 9.84101 8.268C10.245 8.36 10.497 8.763 10.405 9.166C10.325 9.514 10.016 9.749 9.67402 9.749V9.75Z"></path>
53510        <path d="M16 9.75H2C1.586 9.75 1.25 9.414 1.25 9C1.25 8.586 1.586 8.25 2 8.25H16C16.414 8.25 16.75 8.586 16.75 9C16.75 9.414 16.414 9.75 16 9.75Z"></path>
53511        <path fill-rule="evenodd" clip-rule="evenodd" d="M13.0672 11.2532C13.4796 11.214 13.8457 11.5165 13.8849 11.9288C13.8943 12.0276 13.9004 12.1288 13.9028 12.2325C13.9676 14.8775 11.598 16.5 9.079 16.5C7.90939 16.5 6.8445 16.2729 5.97294 15.7286C5.08701 15.1753 4.46415 14.3331 4.12756 13.2286C4.00681 12.8324 4.23014 12.4133 4.62636 12.2925C
535115.02258 12.1718 5.44167 12.3951 5.56241 12.7913C5.80482 13.5868 6.22047 14.1147 6.76754 14.4563C7.32899 14.807 8.0916 15 9.079 15C11.074 15 12.4404 13.7834 12.4032 12.2684C12.4016 12.2003 12.3977 12.1339 12.3917 12.0709C12.3524 11.6586 12.6549 11.2925 13.0672 11.2532Z"></path>
53512      </g>
53513    </svg>
53514  `,
53515    table: `
53516    <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" aria-hidden="true" focusable="false">
53517      <g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" stroke="currentColor">
53518        <line x1="15.25" y1="6.75" x2="2.75" y2="6.75"></line>
53519        <line x1="15.25" y1="11.25" x2="2.75" y2="11.25"></line>
53520        <line x1="7.25" y1="2.75" x2="7.25" y2="15.25"></line>
53521        <rect x="2.75" y="2.75" width="12.5" height="12.5" rx="2" ry="2"></rect>
53522      </g>
53523    </svg>
53524  `,
53525    trash: `
53526    <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" aria-hidden="true" focusable="false">
53527      <g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" stroke="currentColor">
53528        <path d="M2.75 4.75H15.25"></path>
53529        <path d="M6.75 4.75V2.75C6.75 2.2 7.198 1.75 7.75 1.75H10.25C10.802 1.75 11.25 2.2 11.25 2.75V4.75"></path>
53530        <path d="M7.375 8.75L7.59219 13.25"></path>
53531        <path d="M10.625 8.75L10.4078 13.25"></path>
53532        <path d="M13.6977 7.75L13.35 14.35C13.294 15.4201 12.416 16.25 11.353 16.25H6.64804C5.58404 16.25 4.70703 15.42 4.65103 14.35L4.30334 7.75"></path>
53533      </g>
53534    </svg>
53535  `,
53536    undo: `
53537    <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" aria-hidden="true" focusable="false">
53538      <g fill="currentColor">
53539        <path d="M12,14.5h-3.75c-.414,0-.75-.336-.75-.75s.336-.75,.75-.75h3.75c1.654,0,3-1.346,3-3s-1.346-3-3-3H2.5c-.414,0-.75-.336-.75-.75s.336-.75,.75-.75H12c2.481,0,4.5,2.019,4.5,4.5s-2.019,4.5-4.5,4.5Z"></path>
53540        <path d="M5.75,10.5c-.192,0-.384-.073-.53-.22L1.72,6.78c-.293-.293-.293-.768,0-1.061l3.5-3.5c.293-.293,.768-.293,1.061,0s.293,.768,0,1.061l-2.97,2.97,2.97,2.97c.293,.293,.293,.768,0,1.061-.146,.146-.338,.22-.53,.22Z"></path>
53541      </g>
53542    </svg>
53543  `,
53544    underline: `
53545    <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" aria-hidden="true" focusable="false">
53546      <g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" stroke="currentColor">
53547        <path d="M12.75,2.75v5.75c0,2.071-1.679,3.75-3.75,3.75h0c-2.071,0-3.75-1.679-3.75-3.75V2.75"></path>
53548        <line id="color" x1="2.75" y1="15.25" x2="15.25" y2="15.25"></line>
53549      </g>
53550    </svg>
53551  `
53552  };
53553  var TOOLBAR_ICON_ALIASES = {
53554    attachment: ICONS2.attachment,
53555    audio: ICONS2.audio,
53556    blockquote: ICONS2.quote,
53557    bold: ICONS2.bold,
53558    "bullet-list": ICONS2.bulletList,
53559    callout: ICONS2.callout,
53560    checklist: ICONS2.checklist,
53561    "clear-formatting": ICONS2.clearFormatting,
53562    clearFormatting: ICONS2.clearFormatting,
53563    code: ICONS2.code,
53564    "code-block": ICONS2.code,
53565    delete: ICONS2.trash,
53566    divider: ICONS2.separator,
53567    file: ICONS2.attachment,
53568    format: ICONS2.format,
53569    h1: ICONS2.heading1,
53570    h2: ICONS2.heading2,
53571    h3: ICONS2.heading3,
53572    h4: ICONS2.heading4,
53573    "heading-1": ICONS2.heading1,
53574    "heading-2": ICONS2.heading2,
53575    "heading-3": ICONS2.heading3,
53576    "heading-4": ICONS2.heading4,
53577    "heading-large": ICONS2.heading2,
53578    "heading-medium": ICONS2.heading3,
53579    "heading-small": ICONS2.heading4,
53580    heading1: ICONS2.heading1,
53581    heading2: ICONS2.heading2,
53582    heading3: ICONS2.heading3,
53583    heading4: ICONS2.heading4,
53584    highlight: ICONS2.highlight,
53585    image: ICONS2.image,
53586    indent: ICONS2.indentIncrease,
53587    italic: ICONS2.italic,
53588    link: ICONS2.link,
53589    "number-list": ICONS2.numberList,
53590    "ordered-list": ICONS2.numberList,
53591    outdent: ICONS2.indentDecrease,
53592    paragraph: ICONS2.paragraph,
53593    pdf: ICONS2.pdf,
53594    quote: ICONS2.quote,
53595    redo: ICONS2.redo,
53596    remove: ICONS2.trash,
53597    separator: ICONS2.separator,
53598    strike: ICONS2.strike,
53599    strikethrough: ICONS2.strike,
53600    table: ICONS2.table,
53601    "toggle-list": ICONS2.toggleList,
53602    toggleList: ICONS2.toggleList,
53603    trash: ICONS2.trash,
53604    undo: ICONS2.undo,
53605    underline: ICONS2.underline,
53606    "unordered-list": ICONS2.bulletList
53607  };
53608  var FLOATING_DROPDOWN_OFFSET = 4;
53609  var FLOATING_DROPDOWN_MARGIN = 8;
53610  var FLOATING_DROPDOWN_SELECTOR = "lexxy-toolbar-dropdown, lexxy-highlight-dropdown, lexxy-link-dropdown";
53611  var LEXXY_TOOLBAR_ICONS = Object.freeze(ICONS2);
53612  function iconForToolbarButtonName(name) {
53613    return TOOLBAR_ICON_ALIASES[name] || null;
53614  }
53615  function enhanceLexxyToolbarIcons(root = document) {
53616    root.querySelectorAll("lexxy-toolbar button[name]").forEach((button) => {
53617      const command = button.name;
53618      const icon = iconForToolbarButtonName(command);
53619      if (!icon) return;
53620      const label = button.querySelector("span");
53621      if (label) {
53622        button.querySelector("svg")?.remove();
53623        button.insertAdjacentHTML("afterbegin", `${icon} `);
53624      } else {
53625        button.innerHTML = icon;
53626      }
53627      button.dataset.lexxyIcon = command;
53628    });
53629    root.querySelectorAll("lexxy-node-delete-button .lexxy-node-delete").forEach((button) => {
53630      button.querySelector("svg")?.remove();
53631      button.insertAdjacentHTML("afterbegin", `${ICONS2.trash} `);
53632      button.dataset.lexxyIcon = "trash";
53633    });
53634    root.querySelectorAll("lexxy-toolbar").forEach((toolbar) => {
53635      disableLexxyToolbarOverflow(toolbar);
53636      installFloatingToolbarDropdowns(toolbar);
53637    });
53638  }
53639  function disableLexxyToolbarOverflow(toolbar) {
53640    const overflowMenu = toolbar.querySelector(".lexxy-editor__toolbar-overflow");
53641    const overflowPanel = overflowMenu?.querySelector(":scope > [data-dropdown-panel]");
53642    if (overflowMenu && overflowPanel) {
53643      restoreToolbarOverflow(toolbar, overflowMenu, overflowPanel);
53644      setOverflowMenuState(toolbar, overflowMenu, overflowPanel, false);
53645    }
53646    toolbar.querySelectorAll(":scope > button").forEach((button) => {
53647      button.dataset.preventOverflow = "true";
53648    });
53649    toolbar.requestOverflowRefresh?.();
53650  }
53651  function restoreToolbarOverflow(toolbar, overflowMenu, overflowPanel) {
53652    Array.from(overflowPanel.children).sort((a2, b3) => itemPosition(b3) - itemPosition(a2)).forEach((item) => {
53653      const nextItem = toolbar.querySelector(`[data-position="${itemPosition(item) + 1}"]`) || overflowMenu;
53654      item.removeAttribute("role");
53655      toolbar.insertBefore(item, nextItem);
53656    });
53657  }
53658  function setOverflowMenuState(toolbar, overflowMenu, overflowPanel, isOverflowing) {
53659    toolbar.toggleAttribute("overflowing", isOverflowing);
53660    overflowMenu.style.display = isOverflowing ? "block" : "none";
53661    overflowPanel.toggleAttribute("disabled", !isOverflowing);
53662    if (!isOverflowing) overflowPanel.hidden = true;
53663  }
53664  function itemPosition(item) {
53665    return parseInt(item.dataset.position || "999", 10);
53666  }
53667  function installFloatingToolbarDropdowns(toolbar) {
53668    if (toolbar.dataset.lexxyFloatingDropdownsInstalled === "true") return;
53669    toolbar.dataset.lexxyFloatingDropdownsInstalled = "true";
53670    toolbar.querySelectorAll(FLOATING_DROPDOWN_SELECTOR).forEach((dropdown) => {
53671      const panel = dropdown.querySelector(":scope > [data-dropdown-panel]");
53672      if (!panel) return;
53673      const updatePosition = () => updateFloatingDropdownPosition(toolbar, dropdown, panel);
53674      const togglePositioning = () => {
53675        if (panel.hidden) {
53676          panel.removeAttribute("data-lexxy-floating-dropdown");
53677          panel.style.removeProperty("--lexxy-dropdown-inline-size");
53678          panel.style.removeProperty("--lexxy-dropdown-inline-start");
53679          panel.style.removeProperty("--lexxy-dropdown-block-start");
53680          return;
53681        }
53682        updatePosition();
53683      };
53684      new MutationObserver(togglePositioning).observe(panel, {
53685        attributes: true,
53686        attributeFilter: ["hidden"]
53687      });
53688      dropdown.querySelector("[data-dropdown-trigger]")?.addEventListener("click", () => {
53689        requestAnimationFrame(togglePositioning);
53690      });
53691      toolbar.addEventListener("scroll", updatePosition, { passive: true });
53692      window.addEventListener("resize", updatePosition, { passive: true });
53693      window.addEventListener("scroll", updatePosition, { passive: true });
53694      togglePositioning();
53695    });
53696  }
53697  function updateFloatingDropdownPosition(toolbar, dropdown, panel) {
53698    if (panel.hidden) return;
53699    const trigger = dropdown.querySelector(":scope > [data-dropdown-trigger]");
53700    if (!trigger) return;
53701    panel.setAttribute("data-lexxy-floating-dropdown", "");
53702    if (dropdown.matches("lexxy-link-dropdown")) {
53703      panel.style.setProperty("--lexxy-dropdown-inline-size", `${floatingDropdownWidth(toolbar)}px`);
53704    } else {
53705      panel.style.removeProperty("--lexxy-dropdown-inline-size");
53706    }
53707    const triggerRect = trigger.getBoundingClientRect();
53708    const panelRect = panel.getBoundingClientRect();
53709    const top = triggerRect.bottom + FLOATING_DROPDOWN_OFFSET;
53710    const left = dropdown.matches("lexxy-link-dropdown") ? centeredFloatingDropdownLeft(toolbar, panelRect.width) : clampedFloatingDropdownLeft(triggerRect.left, panelRect.width);
53711    panel.style.setProperty("--lexxy-dropdown-inline-start", `${left}px`);
53712    panel.style.setProperty("--lexxy-dropdown-block-start", `${top}px`);
53713  }
53714  function floatingDropdownWidth(toolbar) {
53715    return Math.min(
53716      toolbar.getBoundingClientRect().width - FLOATING_DROPDOWN_MARGIN * 2,
53717      window.innerWidth - FLOATING_DROPDOWN_MARGIN * 2
53718    );
53719  }
53720  function centeredFloatingDropdownLeft(toolbar, panelWidth) {
53721    const toolbarRect = toolbar.getBoundingClientRect();
53722    return clampedFloatingDropdownLeft(toolbarRect.left + (toolbarRect.width - panelWidth) / 2, panelWidth);
53723  }
53724  function clampedFloatingDropdownLeft(preferredLeft, panelWidth) {
53725    return Math.min(
53726      Math.max(FLOATING_DROPDOWN_MARGIN, preferredLeft),
53727      Math.max(FLOATING_DROPDOWN_MARGIN, window.innerWidth - panelWidth - FLOATING_DROPDOWN_MARGIN)
53728    );
53729  }
53730
53731  
53731// app/javascript/src/lexxy/callout_extension.js
53732  var {
53733    $createParagraphNode: $createParagraphNode5,
53734    $findMatchingParent: $findMatchingParent5,
53735    $getSelection: $getSelection5,
53736    $isElementNode: $isElementNode6,
53737    $isParagraphNode: $isParagraphNode4,
53738    $isRangeSelection: $isRangeSelection5,
53739    $isTextNode: $isTextNode3,
53740    COMMAND_PRIORITY_LOW: COMMAND_PRIORITY_LOW3,
53741    COMMAND_PRIORITY_EDITOR: COMMAND_PRIORITY_EDITOR3,
53742    INTERNAL_$isBlock: INTERNAL_$isBlock4,
53743    KEY_ARROW_DOWN_COMMAND: KEY_ARROW_DOWN_COMMAND3,
53744    KEY_ENTER_COMMAND: KEY_ENTER_COMMAND3
53745  } = Lexical_exports;
53746  function $emptyParagraphInCallout() {
53747    const selection = $getSelection5();
53748    if (!$isRangeSelection5(selection) || !selection.isCollapsed()) return null;
53749    const anchorNode = selection.anchor.getNode();
53750    const paragraph = $isParagraphNode4(anchorNode) ? anchorNode : $findMatchingParent5(anchorNode, $isParagraphNode4);
53751    if (!$isParagraphNode4(paragraph) || paragraph.getTextContent() !== "") return null;
53752    const callout = $findMatchingParent5(paragraph, $isCalloutNode);
53753    if (!$isCalloutNode(callout)) return null;
53754    return { callout, paragraph };
53755  }
53756  function $exitCalloutFromEmptyParagraph() {
53757    const context = $emptyParagraphInCallout();
53758    if (!context) return false;
53759    const nextParagraph = $createParagraphNode5();
53760    context.callout.insertAfter(nextParagraph);
53761    context.paragraph.remove();
53762    if (context.callout.getChildrenSize() === 0) {
53763      context.callout.remove();
53764    }
53765    nextParagraph.select();
53766    return true;
53767  }
53768  function $selectionBlock(selection) {
53769    const anchorNode = selection.anchor.getNode();
53770    if ($isElementNode6(anchorNode) && INTERNAL_$isBlock4(anchorNode)) return anchorNode;
53771    const block = $findMatchingParent5(
53772      anchorNode,
53773      (node) => $isElementNode6(node) && INTERNAL_$isBlock4(node)
53774    );
53775    return $isElementNode6(block) ? block : null;
53776  }
53777  function $isSelectionAtBlockEnd(selection, block) {
53778    const anchor = selection.anchor;
53779    const anchorNode = anchor.getNode();
53780    if (anchor.type === "element" && anchorNode.is(block)) {
53781      return anchor.offset === block.getChildrenSize();
53782    }
53783    if (!$isTextNode3(anchorNode)) return false;
53784    const lastDescendant = block.getLastDescendant();
53785    return anchorNode.is(lastDescendant) && anchor.offset === anchorNode.getTextContentSize();
53786  }
53787  function $selectStartOfCalloutAfterCurrentBlock() {
53788    const selection = $getSelection5();
53789    if (!$isRangeSelection5(selection) || !selection.isCollapsed()) return false;
53790    const block = $selectionBlock(selection);
53791    if (!block || !$isSelectionAtBlockEnd(selection, block)) return false;
53792    const nextBlock = block.getNextSibling();
53793    if (!$isCalloutNode(nextBlock)) return false;
53794    const firstContentBlock = nextBlock.getFirstChild();
53795    if (!firstContentBlock?.selectStart) return false;
53796    firstContentBlock.selectStart();
53797    return true;
53798  }
53799  var CalloutExtension = class extends LexxyExtension {
53800    #button = null;
53801    #updateListener = null;
53802    get enabled() {
53803      return this.editorElement.supportsRichText;
53804    }
53805    get allowedElements() {
53806      return [
53807        {
53808          tag: "aside",
53809          attributes: [
53810            "class",
53811            "data-border-variant",
53812            "data-bg-variant",
53813            "data-icon",
53814            "data-icon-id",
53815            "data-icon-type",
53816            "data-icon-src"
53817          ]
53818        },
53819        {
53820          tag: "div",
53821          attributes: [
53822            "class",
53823            "data-border-variant",
53824            "data-bg-variant",
53825            "data-icon",
53826            "data-icon-id",
53827            "data-icon-type",
53828            "data-icon-src"
53829          ]
53830        }
53831      ];
53832    }
53833    get lexicalExtension() {
53834      return this.defineExtension({
53835        name: "lexxy/callout",
53836        nodes: [CalloutNode],
53837        register: (editor) => mergeRegister3(
53838          editor.registerNodeTransform(CalloutNode, (callout) => {
53839            $normalizeCalloutContent(callout);
53840          }),
53841          editor.registerCommand(
53842            KEY_ARROW_DOWN_COMMAND3,
53843            (event) => {
53844              if (event?.shiftKey || event?.altKey || event?.ctrlKey || event?.metaKey) return false;
53845              if (!$selectStartOfCalloutAfterCurrentBlock()) return false;
53846              event?.preventDefault();
53847              return true;
53848            },
53849            COMMAND_PRIORITY_EDITOR3
53850          ),
53851          editor.registerCommand(
53852            KEY_ENTER_COMMAND3,
53853            (event) => {
53854              if (!$exitCalloutFromEmptyParagraph()) return false;
53855              event?.preventDefault();
53856              return true;
53857            },
53858            COMMAND_PRIORITY_LOW3
53859          )
53860        )
53861      });
53862    }
53863    initializeToolbar(toolbar) {
53864      this.#ensureCalloutTools();
53865      const dividerButton = toolbar.querySelector('[name="divider"]');
53866      if (!dividerButton || toolbar.querySelector('[name="callout"]')) return;
53867      const button = document.createElement("button");
53868      button.type = "button";
53869      button.className = "lexxy-editor__toolbar-button";
53870      button.name = "callout";
53871      button.title = "Callout";
53872      button.innerHTML = LEXXY_TOOLBAR_ICONS.callout;
53873      button.addEventListener("click", (event) => {
53874        event.preventDefault();
53875        this.#toggleCallout();
53876      });
53877      dividerButton.insertAdjacentElement("beforebegin", button);
53878      this.#button = button;
53879      const editor = this.editorElement.editor;
53880      if (!editor) return;
53881      this.#updateListener = editor.registerUpdateListener(({ editorState }) => {
53882        editorState.read(() => {
53883          const active = this.#selectionIsInsideCallout();
53884          button.classList.toggle("lexxy-editor__toolbar-button--pressed", active);
53885          button.setAttribute("aria-pressed", active ? "true" : "false");
53886        });
53887      });
53888    }
53889    dispose() {
53890      this.#updateListener?.();
53891      this.#button = null;
53892    }
53893    #ensureCalloutTools() {
53894      if (this.editorElement.querySelector("lexxy-callout-tools")) return;
53895      this.editorElement.appendChild(document.createElement("lexxy-callout-tools"));
53896    }
53897    #toggleCallout() {
53898      const editor = this.editorElement.editor;
53899      if (!editor) return;
53900      editor.update(() => {
53901        $insertCallout();
53902      });
53903      editor.focus();
53904    }
53905    #selectionIsInsideCallout() {
53906      return this.#calloutForSelection() !== null;
53907    }
53908    #calloutForSelection() {
53909      const selection = $getSelection5();
53910      if (!$isRangeSelection5(selection)) return null;
53911      const anchorNode = selection.anchor.getNode();
53912      return $findMatchingParent5(anchorNode, $isCalloutNode);
53913    }
53914    #unwrapCallout(callout) {
53915      const children = [...callout.getChildren()];
53916      if (children.length === 0) {
53917        callout.remove();
53918        return;
53919      }
53920      children.forEach((child) => callout.insertBefore(child));
53921      callout.remove();
53922    }
53923  };
53924
53925  
53925// app/javascript/src/lexxy/checklist_extension.js
53926  var {
53927    $getSelection: $getSelection6,
53928    $isRangeSelection: $isRangeSelection6,
53929    $isTextNode: $isTextNode4,
53930    COMMAND_PRIORITY_HIGH: COMMAND_PRIORITY_HIGH3,
53931    INPUT_COMMAND: INPUT_COMMAND3,
53932    KEY_ENTER_COMMAND: KEY_ENTER_COMMAND4,
53933    KEY_SPACE_COMMAND: KEY_SPACE_COMMAND3,
53934    KEY_TAB_COMMAND: KEY_TAB_COMMAND3
53935  } = Lexical_exports;
53936  var ChecklistExtension = class extends LexxyExtension {
53937    #button = null;
53938    #updateListener = null;
53939    #shortcutListener = null;
53940    #tabListener = null;
53941    #enterListener = null;
53942    get enabled() {
53943      return this.editorElement.supportsRichText;
53944    }
53945    get allowedElements() {
53946      return [
53947        { tag: "ul", attributes: ["class"] },
53948        { tag: "li", attributes: ["role", "aria-checked", "tabindex", "class"] }
53949      ];
53950    }
53951    get lexicalExtension() {
53952      return this.defineExtension({
53953        name: "lexxy/checklist",
53954        register: (editor) => registerCheckList2(editor, { disableTakeFocusOnClick: true })
53955      });
53956    }
53957    initializeToolbar(toolbar) {
53958      const orderedListButton = toolbar.querySelector('[name="ordered-list"]');
53959      if (!orderedListButton || toolbar.querySelector('[name="checklist"]')) return;
53960      orderedListButton.classList.remove("lexxy-editor__toolbar-group-end");
53961      const button = document.createElement("button");
53962      button.type = "button";
53963      button.className = "lexxy-editor__toolbar-button lexxy-editor__toolbar-group-end";
53964      button.name = "checklist";
53965      button.title = "Checklist";
53966      button.innerHTML = LEXXY_TOOLBAR_ICONS.checklist;
53967      button.addEventListener("click", (event) => {
53968        event.preventDefault();
53969        this.#toggleChecklist();
53970      });
53971      orderedListButton.insertAdjacentElement("afterend", button);
53972      this.#button = button;
53973      const editor = this.editorElement.editor;
53974      if (!editor) return;
53975      this.#updateListener = editor.registerUpdateListener(({ editorState }) => {
53976        editorState.read(() => {
53977          const format = this.editorElement.selection?.getFormat?.();
53978          const active = format?.isInList && format?.listType === "check";
53979          button.classList.toggle("lexxy-editor__toolbar-button--pressed", active);
53980          button.setAttribute("aria-pressed", active ? "true" : "false");
53981        });
53982      });
53983      this.#shortcutListener = this.#registerChecklistShortcut(editor);
53984      this.#tabListener = this.#registerChecklistTabHandler(editor);
53985      this.#enterListener = this.#registerChecklistEnterHandler(editor);
53986    }
53987    dispose() {
53988      this.#updateListener?.();
53989      this.#shortcutListener?.();
53990      this.#tabListener?.();
53991      this.#enterListener?.();
53992      this.#button = null;
53993    }
53994    #toggleChecklist() {
53995      const editor = this.editorElement.editor;
53996      const contents = this.editorElement.contents;
53997      if (!editor || !contents) return;
53998      editor.update(() => {
53999        const selection = $getSelection6();
54000        if (!$isRangeSelection6(selection)) return;
54001        const format = this.editorElement.selection?.getFormat?.();
54002        if (format?.isInList && format?.listType === "check") {
54003          contents.applyParagraphFormat();
54004        } else {
54005          editor.dispatchCommand(INSERT_CHECK_LIST_COMMAND2, void 0);
54006        }
54007      });
54008      editor.focus();
54009    }
54010    #registerChecklistShortcut(editor) {
54011      const handleShortcut = (event) => {
54012        if (!this.#selectionHasChecklistShortcut()) return false;
54013        event?.preventDefault();
54014        editor.update(() => {
54015          this.#removeChecklistShortcutText();
54016          editor.dispatchCommand(INSERT_CHECK_LIST_COMMAND2, void 0);
54017        });
54018        return true;
54019      };
54020      const removeSpaceCommand = editor.registerCommand(
54021        KEY_SPACE_COMMAND3,
54022        handleShortcut,
54023        COMMAND_PRIORITY_HIGH3
54024      );
54025      const removeInputCommand = editor.registerCommand(
54026        INPUT_COMMAND3,
54027        (event) => {
54028          if (event.inputType !== "insertText" || event.data !== " ") return false;
54029          return handleShortcut(event);
54030        },
54031        COMMAND_PRIORITY_HIGH3
54032      );
54033      return () => {
54034        removeSpaceCommand();
54035        removeInputCommand();
54036      };
54037    }
54038    #selectionHasChecklistShortcut() {
54039      if (this.editorElement.selection?.isInsideCodeBlock) return false;
54040      const selection = $getSelection6();
54041      if (!$isRangeSelection6(selection) || !selection.isCollapsed()) return false;
54042      const anchorNode = selection.anchor.getNode();
54043      if (!$isTextNode4(anchorNode)) return false;
54044      const textBeforeCursor = anchorNode.getTextContent().slice(0, selection.anchor.offset);
54045      return /(?:^|\n)\[\]\s?$/.test(textBeforeCursor);
54046    }
54047    #removeChecklistShortcutText() {
54048      const selection = $getSelection6();
54049      if (!$isRangeSelection6(selection) || !selection.isCollapsed()) return;
54050      const anchorNode = selection.anchor.getNode();
54051      if (!$isTextNode4(anchorNode)) return;
54052      const offset3 = selection.anchor.offset;
54053      const textBeforeCursor = anchorNode.getTextContent().slice(0, offset3);
54054      const shortcutIndex = textBeforeCursor.lastIndexOf("[]");
54055      if (shortcutIndex === -1) return;
54056      const textBeforeShortcut = textBeforeCursor.slice(0, shortcutIndex);
54057      if (textBeforeShortcut && !textBeforeShortcut.endsWith("\n")) return;
54058      anchorNode.spliceText(shortcutIndex, offset3 - shortcutIndex, "", true);
54059    }
54060    #registerChecklistTabHandler(editor) {
54061      return editor.registerCommand(
54062        KEY_TAB_COMMAND3,
54063        (event) => {
54064          const listItem = editor.getEditorState().read(() => this.#checklistListItemForSelection());
54065          if (!listItem) return false;
54066          const indentTarget = this.#resolveChecklistIndentTarget(listItem);
54067          if (indentTarget !== listItem) {
54068            event.preventDefault();
54069            editor.update(() => {
54070              const currentIndent = indentTarget.getIndent();
54071              indentTarget.setIndent(event.shiftKey ? Math.max(0, currentIndent - 1) : currentIndent + 1);
54072            });
54073            return true;
54074          }
54075          return false;
54076        },
54077        COMMAND_PRIORITY_HIGH3
54078      );
54079    }
54080    #registerChecklistEnterHandler(editor) {
54081      return editor.registerCommand(
54082        KEY_ENTER_COMMAND4,
54083        (event) => {
54084          if (!event?.metaKey && !event?.ctrlKey) return false;
54085          const listItem = editor.getEditorState().read(() => this.#checklistListItemForSelection());
54086          if (!listItem) return false;
54087          event.preventDefault();
54088          editor.update(() => {
54089            this.#checklistListItemForSelection()?.toggleChecked();
54090          });
54091          return true;
54092        },
54093        COMMAND_PRIORITY_HIGH3
54094      );
54095    }
54096    #checklistListItemForSelection() {
54097      const selection = $getSelection6();
54098      if (!$isRangeSelection6(selection)) return null;
54099      return $findMatchingParent3(selection.anchor.getNode(), (node) => {
54100        if (!$isListItemNode2(node)) return false;
54101        const parent = node.getParent();
54102        return $isListNode2(parent) && parent.getListType() === "check";
54103      });
54104    }
54105    #resolveChecklistIndentTarget(listItem) {
54106      const firstChild = listItem.getFirstChild();
54107      if ($isListNode2(firstChild) && listItem.getChildrenSize() === 1) {
54108        const innerItem = firstChild.getFirstChild();
54109        if ($isListItemNode2(innerItem)) return innerItem;
54110      }
54111      return listItem;
54112    }
54113  };
54114
54115  
54115// app/javascript/src/lexxy/desktop_prompts.js
54116  function supportsDesktopPrompts() {
54117    return window.matchMedia("(hover: hover) and (pointer: fine)").matches;
54118  }
54119
54120  
54120// app/javascript/src/lexxy/popover_scroll_lock.js
54121  var lockCount = 0;
54122  var scrollPosition = 0;
54123  var previousBodyPosition = "";
54124  var previousBodyTop = "";
54125  var previousBodyWidth = "";
54126  function lockPopoverScroll() {
54127    let unlocked = false;
54128    if (lockCount === 0) {
54129      scrollPosition = window.pageYOffset || document.documentElement.scrollTop;
54130      previousBodyPosition = document.body.style.position;
54131      previousBodyTop = document.body.style.top;
54132      previousBodyWidth = document.body.style.width;
54133      document.body.style.position = "fixed";
54134      document.body.style.top = `-${scrollPosition}px`;
54135      document.body.style.width = "100%";
54136    }
54137    lockCount += 1;
54138    return () => {
54139      if (unlocked) return;
54140      unlocked = true;
54141      lockCount = Math.max(0, lockCount - 1);
54142      if (lockCount === 0) {
54143        document.body.style.position = previousBodyPosition;
54144        document.body.style.top = previousBodyTop;
54145        document.body.style.width = previousBodyWidth;
54146        window.scrollTo(0, scrollPosition);
54147      }
54148    };
54149  }
54150
54151  
54151// app/javascript/src/lexxy/emoji_prompt_extension.js
54152  var {
54153    $getNodeByKey: $getNodeByKey4,
54154    $getSelection: $getSelection7,
54155    $isRangeSelection: $isRangeSelection7,
54156    $isTextNode: $isTextNode5,
54157    COMMAND_PRIORITY_CRITICAL: COMMAND_PRIORITY_CRITICAL3,
54158    KEY_ARROW_DOWN_COMMAND: KEY_ARROW_DOWN_COMMAND4,
54159    KEY_ARROW_LEFT_COMMAND: KEY_ARROW_LEFT_COMMAND3,
54160    KEY_ARROW_RIGHT_COMMAND: KEY_ARROW_RIGHT_COMMAND3,
54161    KEY_ARROW_UP_COMMAND: KEY_ARROW_UP_COMMAND3,
54162    KEY_ENTER_COMMAND: KEY_ENTER_COMMAND5,
54163    KEY_ESCAPE_COMMAND: KEY_ESCAPE_COMMAND3,
54164    KEY_TAB_COMMAND: KEY_TAB_COMMAND4
54165  } = Lexical_exports;
54166  var EmojiPromptExtension = class extends LexxyExtension {
54167    #popover = null;
54168    #emojiPicker = null;
54169    #popoverListeners = [];
54170    #triggerListener = null;
54171    #open = false;
54172    #showId = 0;
54173    #activeTrigger = null;
54174    #dismissedTrigger = null;
54175    #searchId = 0;
54176    #unlockScroll = null;
54177    get enabled() {
54178      return this.editorElement.supportsRichText && supportsDesktopPrompts();
54179    }
54180    initializeToolbar(_toolbar) {
54181      this.#attachTriggerListener();
54182    }
54183    dispose() {
54184      this.#disposePopoverListeners();
54185      this.#unlockPopoverScroll();
54186      this.#triggerListener?.();
54187      this.#emojiPicker?._unwatchTheme?.();
54188      this.#popover?.remove();
54189      this.#emojiPicker = null;
54190      this.#popover = null;
54191    }
54192    #attachTriggerListener() {
54193      const editor = this.editorElement.editor;
54194      if (!editor) return;
54195      this.#triggerListener = editor.registerUpdateListener(({ editorState }) => {
54196        editorState.read(() => {
54197          if (this.editorElement.selection?.isInsideCodeBlock) return;
54198          const trigger = this.#readTriggerContext();
54199          if (!trigger) {
54200            this.#dismissedTrigger = null;
54201            if (this.#open) this.#hidePopover();
54202            return;
54203          }
54204          if (this.#isDismissedTrigger(trigger)) return;
54205          this.#activeTrigger = trigger;
54206          if (!this.#open) {
54207            this.#showPopover(trigger);
54208            return;
54209          }
54210          this.#syncEmojiSearch(trigger.query);
54211          this.#positionPopover();
54212        });
54213      });
54214    }
54215    #readTriggerContext() {
54216      const selection = $getSelection7();
54217      if (!$isRangeSelection7(selection) || !selection.isCollapsed()) return null;
54218      const anchorNode = selection.anchor.getNode();
54219      if (!$isTextNode5(anchorNode)) return null;
54220      const offset3 = selection.anchor.offset;
54221      const textBeforeCursor = anchorNode.getTextContent().slice(0, offset3);
54222      const lastColon = textBeforeCursor.lastIndexOf(":");
54223      if (lastColon === -1) return null;
54224      const charBeforeColon = lastColon > 0 ? textBeforeCursor[lastColon - 1] : "";
54225      if (charBeforeColon && !/[\s\n]/.test(charBeforeColon)) return null;
54226      const query = textBeforeCursor.slice(lastColon + 1);
54227      if (!query || /\s/.test(query)) return null;
54228      return {
54229        key: anchorNode.getKey(),
54230        offset: lastColon,
54231        query
54232      };
54233    }
54234    #isDismissedTrigger(trigger) {
54235      return this.#dismissedTrigger?.key === trigger.key && this.#dismissedTrigger?.offset === trigger.offset;
54236    }
54237    async #showPopover(trigger) {
54238      const showId = ++this.#showId;
54239      this.#open = true;
54240      this.#popover ??= this.#buildPopover();
54241      if (this.#showId !== showId) return;
54242      this.#ensureEmojiPicker();
54243      this.#syncEmojiSearch(trigger.query);
54244      this.#popover.classList.remove("hidden");
54245      this.#popover.classList.add("lexxy-prompt-menu--visible");
54246      this.#positionPopover();
54247      this.#unlockScroll ??= lockPopoverScroll();
54248      this.#registerPopoverListeners();
54249    }
54250    #buildPopover() {
54251      const popover = document.createElement("div");
54252      popover.className = "lexxy-callout-tools__icon-popover lexxy-callout-tools__icon-popover--portaled lexxy-emoji-menu lexxy-emoji-menu--p
54252ortaled lexxy-emoji-prompt-menu ph-no-autocapture hidden";
54253      popover.hidden = true;
54254      popover.setAttribute("role", "dialog");
54255      popover.setAttribute("aria-label", "Emoji");
54256      popover.setAttribute("data-ph-no-autocapture", "");
54257      popover.innerHTML = `<div class="lexxy-callout-tools__emoji-picker" data-emoji-picker-container></div>`;
54258      document.body.appendChild(popover);
54259      return popover;
54260    }
54261    #ensureEmojiPicker() {
54262      if (this.#emojiPicker) {
54263        this.#afterPopoverPaint(() => {
54264          this.#ensureEmojiPickerStyles();
54265          this.#focusEmojiSearch();
54266        });
54267        return;
54268      }
54269      const container = this.#popover?.querySelector("[data-emoji-picker-container]");
54270      if (!container) return;
54271      this.#emojiPicker = createCalloutEmojiPicker(container, {
54272        onSelect: (emoji) => this.#executeEmoji(emoji.native),
54273        pickerOptions: {
54274          autoFocus: true,
54275          navPosition: "none",
54276          previewPosition: "bottom",
54277          searchPosition: "none"
54278        }
54279      });
54280      this.#afterPopoverPaint(() => {
54281        this.#ensureEmojiPickerStyles();
54282        this.#focusEmojiSearch();
54283      });
54284    }
54285    #registerPopoverListeners() {
54286      this.#disposePopoverListeners();
54287      const editor = this.editorElement.editor;
54288      const register = (command, handler) => {
54289        this.#popoverListeners.push(editor.registerCommand(command, handler, COMMAND_PRIORITY_CRITICAL3));
54290      };
54291      register(KEY_ARROW_UP_COMMAND3, (event) => {
54292        this.#navigateEmojiPicker(event, "up");
54293        return true;
54294      });
54295      register(KEY_ARROW_DOWN_COMMAND4, (event) => {
54296        this.#navigateEmojiPicker(event, "down");
54297        return true;
54298      });
54299      register(KEY_ARROW_LEFT_COMMAND3, (event) => {
54300        this.#navigateEmojiPicker(event, "left");
54301        return true;
54302      });
54303      register(KEY_ARROW_RIGHT_COMMAND3, (event) => {
54304        this.#navigateEmojiPicker(event, "right");
54305        return true;
54306      });
54307      register(KEY_ENTER_COMMAND5, (event) => {
54308        this.#executeSelectedEmoji(event);
54309        return true;
54310      });
54311      register(KEY_TAB_COMMAND4, (event) => {
54312        this.#executeSelectedEmoji(event);
54313        return true;
54314      });
54315      register(KEY_ESCAPE_COMMAND3, (event) => {
54316        event.preventDefault();
54317        this.#dismissCurrentTrigger();
54318        this.#hidePopover();
54319        editor.focus();
54320        return true;
54321      });
54322      const onKeyDown2 = (event) => {
54323        if (event.key !== "Escape") return;
54324        event.preventDefault();
54325        event.stopPropagation();
54326        this.#dismissCurrentTrigger();
54327        this.#hidePopover();
54328        this.editorElement.editor.focus();
54329      };
54330      this.#popover.addEventListener("keydown", onKeyDown2, true);
54331      this.#popoverListeners.push(() => this.#popover?.removeEventListener("keydown", onKeyDown2, true));
54332      this.#popoverListeners.push(this.#bindViewportRepositioning());
54333    }
54334    #bindViewportRepositioning() {
54335      const reposition = () => this.#positionPopover();
54336      window.addEventListener("scroll", reposition, true);
54337      window.addEventListener("resize", reposition);
54338      return () => {
54339        window.removeEventListener("scroll", reposition, true);
54340        window.removeEventListener("resize", reposition);
54341      };
54342    }
54343    #disposePopoverListeners() {
54344      this.#popoverListeners.forEach((dispose) => dispose());
54345      this.#popoverListeners = [];
54346    }
54347    #unlockPopoverScroll() {
54348      this.#unlockScroll?.();
54349      this.#unlockScroll = null;
54350    }
54351    #emojiPickerComponent() {
54352      return this.#emojiPicker?.component;
54353    }
54354    #emojiNavigationInput() {
54355      const query = this.#activeTrigger?.query || "";
54356      return {
54357        selectionStart: query.length,
54358        value: query
54359      };
54360    }
54361    #navigateEmojiPicker(event, direction) {
54362      const component = this.#emojiPickerComponent();
54363      if (!component?.navigate) return;
54364      component.navigate({
54365        e: event,
54366        input: this.#emojiNavigationInput(),
54367        [direction]: true
54368      });
54369    }
54370    #executeSelectedEmoji(event) {
54371      event.preventDefault();
54372      const component = this.#emojiPickerComponent();
54373      if (!component?.handleEmojiClick) return;
54374      let pos = component.state?.pos;
54375      if (!Array.isArray(pos) || pos[0] < 0) pos = [0, 0];
54376      component.handleEmojiClick({ e: event, pos });
54377    }
54378    #executeEmoji(emoji) {
54379      const editor = this.editorElement.editor;
54380      const trigger = this.#activeTrigger;
54381      if (!trigger) return;
54382      editor.update(() => {
54383        const node = $getNodeByKey4(trigger.key);
54384        if (!$isTextNode5(node)) return;
54385        const text2 = node.getTextContent();
54386        const queryEnd = trigger.offset + trigger.query.length + 1;
54387        node.setTextContent(`${text2.slice(0, trigger.offset)}${emoji}${text2.slice(queryEnd)}`);
54388        node.select(trigger.offset + emoji.length, trigger.offset + emoji.length);
54389      });
54390      this.#dismissedTrigger = null;
54391      this.#hidePopover();
54392      editor.focus();
54393    }
54394    #dismissCurrentTrigger() {
54395      this.editorElement.editor.getEditorState().read(() => {
54396        this.#dismissedTrigger = this.#readTriggerContext();
54397      });
54398    }
54399    #hidePopover() {
54400      this.#showId++;
54401      this.#open = false;
54402      this.#activeTrigger = null;
54403      this.#disposePopoverListeners();
54404      this.#unlockPopoverScroll();
54405      this.#popover?.classList.remove("lexxy-prompt-menu--visible");
54406      this.#popover?.classList.add("hidden");
54407      this.#popover?.removeAttribute("data-anchored");
54408      if (this.#popover) this.#popover.hidden = true;
54409    }
54410    #afterPopoverPaint(callback) {
54411      requestAnimationFrame(() => requestAnimationFrame(callback));
54412    }
54413    #ensureEmojiPickerStyles(attempts = 6) {
54414      const root = this.#popover?.querySelector("em-emoji-picker")?.shadowRoot;
54415      if (root) {
54416        applyCalloutEmojiPickerStyles(root);
54417        return;
54418      }
54419      if (attempts > 0) this.#afterPopoverPaint(() => this.#ensureEmojiPickerStyles(attempts - 1));
54420    }
54421    #emojiSearchInput() {
54422      const root = this.#popover?.querySelector("em-emoji-picker")?.shadowRoot;
54423      return root?.querySelector(
54424        'input[type="search"], input[placeholder*="Search" i], input[aria-label*="Search" i], input'
54425      );
54426    }
54427    #focusEmojiSearch(attempts = 6) {
54428      const searchInput = this.#emojiSearchInput();
54429      if (searchInput instanceof HTMLElement) {
54430        searchInput.focus({ preventScroll: true });
54431        return;
54432      }
54433      if (attempts > 0) this.#afterPopoverPaint(() => this.#focusEmojiSearch(attempts - 1));
54434    }
54435    #syncEmojiSearch(query, attempts = 6) {
54436      const component = this.#emojiPickerComponent();
54437      if (component) {
54438        this.#applyEmojiSearch(component, query);
54439        return;
54440      }
54441      if (attempts > 0) this.#afterPopoverPaint(() => this.#syncEmojiSearch(query, attempts - 1));
54442    }
54443    async #applyEmojiSearch(component, query) {
54444      const searchId = ++this.#searchId;
54445      const normalizedQuery = query.trim();
54446      if (!normalizedQuery) {
54447        component.setState?.({
54448          pos: [-1, -1],
54449          searchResults: null
54450        });
54451        return;
54452      }
54453      const searchResults = await this.#searchEmojis(normalizedQuery);
54454      if (searchId !== this.#searchId) return;
54455      if (!searchResults) {
54456        component.setState?.({
54457          pos: [-1, -1],
54458          searchResults
54459        });
54460        return;
54461      }
54462      const grid = [];
54463      grid.setsize = searchResults.length;
54464      let row = null;
54465      for (const emoji of searchResults) {
54466        if (!grid.length || row.length === component.getPerLine()) {
54467          row = [];
54468          row.__categoryId = "search";
54469          row.__index = grid.length;
54470          grid.push(row);
54471        }
54472        row.push(emoji);
54473      }
54474      component.ignoreMouse?.();
54475      component.setState?.(
54476        {
54477          pos: grid.length ? [0, 0] : [-1, -1],
54478          searchResults: grid
54479        },
54480        () => {
54481          if (component.refs?.scroll?.current) component.refs.scroll.current.scrollTop = 0;
54482        }
54483      );
54484    }
54485    async #searchEmojis(query) {
54486      const colonPrefixedQuery = `:${query}`;
54487      const [afterColonResults, emoticonResults] = await Promise.all([
54488        $c4d155af13ad4d4b$export$2e2bcd8739ae039.search(query),
54489        $c4d155af13ad4d4b$export$2e2bcd8739ae039.search(colonPrefixedQuery)
54490      ]);
54491      return this.#mergeEmojiSearchResults(emoticonResults, afterColonResults);
54492    }
54493    #mergeEmojiSearchResults(...resultSets) {
54494      const merged = [];
54495      const seen = /* @__PURE__ */ new Set();
54496      for (const results of resultSets) {
54497        if (!results?.length) continue;
54498        for (const emoji of results) {
54499          const id3 = emoji?.id;
54500          if (!id3 || seen.has(id3)) continue;
54501          seen.add(id3);
54502          merged.push(emoji);
54503        }
54504      }
54505      return merged.length ? merged : null;
54506    }
54507    #positionPopover() {
54508      if (!this.#popover) return;
54509      const anchorRect = this.#triggerAnchorRect();
54510      const cursorPosition = this.editorElement.selection?.cursorPosition;
54511      const contentRect = this.editorElement.editorContentElement?.getBoundingClientRect();
54512      if (!anchorRect && (!cursorPosition || !contentRect)) return;
54513      const x3 = anchorRect ? anchorRect.left : contentRect.left + cursorPosition.x;
54514      const y3 = anchorRect ? anchorRect.bottom : contentRect.top + curs
54514orPosition.y + (cursorPosition.fontSize || 16);
54515      this.#popover.hidden = false;
54516      this.#popover.style.setProperty("--lexxy-prompt-offset-x", `${x3}px`);
54517      this.#popover.style.setProperty("--lexxy-prompt-offset-y", `${y3}px`);
54518      this.#popover.removeAttribute("data-clipped-at-right");
54519      this.#popover.removeAttribute("data-clipped-at-bottom");
54520      this.#popover.toggleAttribute("data-anchored", true);
54521      const popoverRect = this.#popover.getBoundingClientRect();
54522      if (popoverRect.right > window.innerWidth) {
54523        this.#popover.style.setProperty(
54524          "--lexxy-prompt-offset-x",
54525          `${Math.max(8, window.innerWidth - popoverRect.width - 8)}px`
54526        );
54527      }
54528      if (popoverRect.bottom > window.innerHeight) {
54529        const fallbackTop = anchorRect ? anchorRect.top : contentRect.top + cursorPosition.y;
54530        this.#popover.style.setProperty(
54531          "--lexxy-prompt-offset-y",
54532          `${Math.max(8, fallbackTop - popoverRect.height - 6)}px`
54533        );
54534        this.#popover.toggleAttribute("data-clipped-at-bottom", true);
54535      }
54536    }
54537    #triggerAnchorRect() {
54538      const trigger = this.#activeTrigger;
54539      if (!trigger) return null;
54540      const textElement = this.editorElement.editor.getElementByKey(trigger.key);
54541      if (!textElement) return null;
54542      const position = this.#textNodePosition(textElement, trigger.offset);
54543      if (!position) return textElement.getBoundingClientRect();
54544      const range2 = document.createRange();
54545      range2.setStart(position.node, position.offset);
54546      range2.collapse(true);
54547      const rect = range2.getClientRects()[0] || range2.getBoundingClientRect();
54548      range2.detach();
54549      return rect && (rect.width || rect.height) ? rect : textElement.getBoundingClientRect();
54550    }
54551    #textNodePosition(element, offset3) {
54552      const walker = document.createTreeWalker(element, NodeFilter.SHOW_TEXT);
54553      let remaining = offset3;
54554      let node = walker.nextNode();
54555      while (node) {
54556        const length = node.textContent.length;
54557        if (remaining <= length) return { node, offset: remaining };
54558        remaining -= length;
54559        node = walker.nextNode();
54560      }
54561      return null;
54562    }
54563  };
54564
54565  
54565// app/javascript/src/lexxy/hex_color_extension.js
54566  var {
54567    $createTextNode: $createTextNode3,
54568    $findMatchingParent: $findMatchingParent6,
54569    $getSelection: $getSelection8,
54570    $isElementNode: $isElementNode7,
54571    $isRangeSelection: $isRangeSelection8,
54572    $isTextNode: $isTextNode6,
54573    COMMAND_PRIORITY_HIGH: COMMAND_PRIORITY_HIGH4,
54574    COMMAND_PRIORITY_LOW: COMMAND_PRIORITY_LOW4,
54575    KEY_ARROW_RIGHT_COMMAND: KEY_ARROW_RIGHT_COMMAND4,
54576    SELECTION_CHANGE_COMMAND: SELECTION_CHANGE_COMMAND3,
54577    TextNode: TextNode4
54578  } = Lexical_exports;
54579  var CARET_ANCHOR = "\u200B";
54580  function $shouldSkipHexColor(node) {
54581    if (!node.isSimpleText() || node.hasFormat("code")) return true;
54582    return $findMatchingParent6(node, $isCodeNode3) != null;
54583  }
54584  function $transformTextNodeToHexColor(node) {
54585    if ($isHexColorNode(node) || $shouldSkipHexColor(node)) return;
54586    const text2 = node.getTextContent().replaceAll(CARET_ANCHOR, "");
54587    const match = getHexColorMatch(text2);
54588    if (!match) return;
54589    const rawText = node.getTextContent();
54590    const rawMatch = getHexColorMatch(rawText);
54591    if (!rawMatch) return;
54592    let targetNode;
54593    if (rawMatch.start === 0) {
54594      [targetNode] = node.splitText(rawMatch.end);
54595    } else {
54596      [, targetNode] = node.splitText(rawMatch.start, rawMatch.end);
54597    }
54598    if (!targetNode) return;
54599    const hexNode = $createHexColorNode(targetNode.getTextContent());
54600    hexNode.setFormat(targetNode.getFormat());
54601    targetNode.replace(hexNode);
54602    $ensureTextAnchorBefore(hexNode);
54603    const next = hexNode.getNextSibling();
54604    if ($isTextNode6(next) && !$isHexColorNode(next)) {
54605      next.selectEnd();
54606    } else {
54607      hexNode.selectEnd();
54608    }
54609  }
54610  function $reverseInvalidHexColor(node) {
54611    if (!$isHexColorNode(node)) return;
54612    const text2 = node.getTextContent();
54613    if (isHexColorValue(text2)) return;
54614    const textNode = $createTextNode3(text2);
54615    textNode.setFormat(node.getFormat());
54616    node.replace(textNode);
54617  }
54618  function $isCaretAnchorText(node) {
54619    return $isTextNode6(node) && !$isHexColorNode(node);
54620  }
54621  function $ensureTextAnchorBefore(node) {
54622    const prev = node.getPreviousSibling();
54623    if ($isCaretAnchorText(prev)) {
54624      if (prev.getTextContent() === "") {
54625        prev.setTextContent(CARET_ANCHOR);
54626      }
54627      return prev;
54628    }
54629    const spacer = $createTextNode3(CARET_ANCHOR);
54630    node.insertBefore(spacer);
54631    return spacer;
54632  }
54633  function $selectBeforeHexColor(node) {
54634    $ensureTextAnchorBefore(node).selectEnd();
54635  }
54636  function $stripConsumedCaretAnchors(node) {
54637    if ($isHexColorNode(node) || !$isTextNode6(node)) return;
54638    const text2 = node.getTextContent();
54639    if (!text2.includes(CARET_ANCHOR)) return;
54640    if (text2 === CARET_ANCHOR) {
54641      const next = node.getNextSibling();
54642      if ($isHexColorNode(next)) return;
54643      node.remove();
54644      return;
54645    }
54646    const cleaned = text2.replaceAll(CARET_ANCHOR, "");
54647    if (cleaned === text2) return;
54648    if (cleaned === "") {
54649      node.setTextContent(CARET_ANCHOR);
54650      return;
54651    }
54652    const selection = $getSelection8();
54653    const hadFocus = $isRangeSelection8(selection) && selection.anchor.key === node.getKey();
54654    const anchorOffset = hadFocus ? selection.anchor.offset : null;
54655    const removedBefore = hadFocus && anchorOffset != null ? (text2.slice(0, anchorOffset).match(new RegExp(CARET_ANCHOR, "g")) || []).length : 0;
54656    node.setTextContent(cleaned);
54657    if (hadFocus && anchorOffset != null) {
54658      const nextOffset = Math.max(
54659        0,
54660        Math.min(anchorOffset - removedBefore, cleaned.length)
54661      );
54662      node.select(nextOffset, nextOffset);
54663    }
54664  }
54665  function $moveCaretBeforeHexColorAtStart() {
54666    const selection = $getSelection8();
54667    if (!$isRangeSelection8(selection) || !selection.isCollapsed()) return false;
54668    const anchorNode = selection.anchor.getNode();
54669    if ($isHexColorNode(anchorNode) && selection.anchor.offset === 0) {
54670      $selectBeforeHexColor(anchorNode);
54671      return true;
54672    }
54673    if ($isElementNode7(anchorNode)) {
54674      const child = anchorNode.getChildAtIndex(selection.anchor.offset);
54675      if ($isHexColorNode(child)) {
54676        $selectBeforeHexColor(child);
54677        return true;
54678      }
54679    }
54680    return false;
54681  }
54682  function $enterHexColorFromLeft(event) {
54683    const selection = $getSelection8();
54684    if (!$isRangeSelection8(selection) || !selection.isCollapsed()) return false;
54685    const anchorNode = selection.anchor.getNode();
54686    if ($isHexColorNode(anchorNode) && selection.anchor.offset === 0) {
54687      event.preventDefault();
54688      const size2 = anchorNode.getTextContentSize();
54689      anchorNode.select(Math.min(1, size2), Math.min(1, size2));
54690      return true;
54691    }
54692    if ($isTextNode6(anchorNode) && !$isHexColorNode(anchorNode)) {
54693      const atEnd = selection.anchor.offset === anchorNode.getTextContentSize();
54694      const next = atEnd ? anchorNode.getNextSibling() : null;
54695      if ($isHexColorNode(next)) {
54696        event.preventDefault();
54697        const size2 = next.getTextContentSize();
54698        next.select(Math.min(1, size2), Math.min(1, size2));
54699        return true;
54700      }
54701    }
54702    if ($isElementNode7(anchorNode)) {
54703      const child = anchorNode.getChildAtIndex(selection.anchor.offset);
54704      if ($isHexColorNode(child)) {
54705        event.preventDefault();
54706        const size2 = child.getTextContentSize();
54707        child.select(Math.min(1, size2), Math.min(1, size2));
54708        return true;
54709      }
54710    }
54711    return false;
54712  }
54713  var HexColorExtension = class extends LexxyExtension {
54714    get enabled() {
54715      return this.editorElement.supportsRichText;
54716    }
54717    get allowedElements() {
54718      return [
54719        {
54720          tag: "span",
54721          attributes: ["class", "style"]
54722        }
54723      ];
54724    }
54725    get lexicalExtension() {
54726      return this.defineExtension({
54727        name: "lexxy/hex-color",
54728        nodes: [HexColorNode],
54729        register: (editor) => mergeRegister3(
54730          editor.registerNodeTransform(TextNode4, $transformTextNodeToHexColor),
54731          editor.registerNodeTransform(TextNode4, $stripConsumedCaretAnchors),
54732          editor.registerNodeTransform(HexColorNode, $reverseInvalidHexColor),
54733          editor.registerCommand(
54734            SELECTION_CHANGE_COMMAND3,
54735            () => $moveCaretBeforeHexColorAtStart(),
54736            COMMAND_PRIORITY_HIGH4
54737          ),
54738          editor.registerCommand(
54739            KEY_ARROW_RIGHT_COMMAND4,
54740            (event) =>
54740 $enterHexColorFromLeft(event),
54741            COMMAND_PRIORITY_LOW4
54742          )
54743        )
54744      });
54745    }
54746  };
54747
54748  
54748// app/javascript/src/lexxy/image_layout.js
54749  var IMAGE_LAYOUT_CONTENT_KEY = "lexxyImage";
54750  var IMAGE_SIZE_OPTIONS = [
54751    { value: "auto", label: "Auto" },
54752    { value: "small", label: "Small" },
54753    { value: "medium", label: "Medium" },
54754    { value: "full", label: "Full" }
54755  ];
54756  var IMAGE_ALIGN_OPTIONS = [
54757    { value: "left", label: "Left" },
54758    { value: "center", label: "Center" },
54759    { value: "right", label: "Right" }
54760  ];
54761  function parseLayoutContent(content) {
54762    if (!content) return {};
54763    if (typeof content === "object") return content;
54764    return JSON.parse(content);
54765  }
54766  function parseImageLayout(content) {
54767    if (!content) return defaultImageLayout();
54768    try {
54769      const parsed = parseLayoutContent(content);
54770      const layout = parsed?.[IMAGE_LAYOUT_CONTENT_KEY] || {};
54771      return {
54772        size: validValue(layout.size, IMAGE_SIZE_OPTIONS, "auto"),
54773        align: validValue(layout.align, IMAGE_ALIGN_OPTIONS, "center")
54774      };
54775    } catch {
54776      return defaultImageLayout();
54777    }
54778  }
54779  function serializeImageLayout(content, layout) {
54780    let parsed = {};
54781    try {
54782      parsed = content ? parseLayoutContent(content) : {};
54783    } catch {
54784      parsed = {};
54785    }
54786    const normalized = {
54787      size: validValue(layout.size, IMAGE_SIZE_OPTIONS, "auto"),
54788      align: validValue(layout.align, IMAGE_ALIGN_OPTIONS, "center")
54789    };
54790    if (normalized.size === "auto" && normalized.align === "center") {
54791      delete parsed[IMAGE_LAYOUT_CONTENT_KEY];
54792    } else {
54793      parsed[IMAGE_LAYOUT_CONTENT_KEY] = normalized;
54794    }
54795    return Object.keys(parsed).length ? JSON.stringify(parsed) : null;
54796  }
54797  function defaultImageLayout() {
54798    return { size: "auto", align: "center" };
54799  }
54800  function validValue(value, options, fallback) {
54801    return options.some((option) => option.value === value) ? value : fallback;
54802  }
54803
54804  
54804// app/javascript/src/lexxy/image_tools.js
54805  var {
54806    $getNodeByKey: $getNodeByKey5,
54807    $getSelection: $getSelection9,
54808    $isNodeSelection: $isNodeSelection3
54809  } = Lexical_exports;
54810  var SIZE_ICONS = {
54811    auto: `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><g stroke-linejoin="round" stroke-linecap="round" stroke-width="2" fill="none" stroke="currentColor"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M4 12v-6a2 2 0 0 1 2 -2h12a2 2 0 0 1 2 2v6"></path><path d="M10 18h-7"></path><path d="M21 18h-7"></path><path d="M6 15l-3 3l3 3"></path><path d="M18 15l3 3l-3 3"></path></g></svg>`,
54812    small: `<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12" class="!size-3" aria-hidden="true" focusable="false"><g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.25" stroke="currentColor"><rect x="1.25" y="1.25" width="9.5" height="9.5" rx="2" ry="2"></rect></g></svg>`,
54813    medium: `<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" aria-hidden="true" focusable="false"><g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.25" stroke="currentColor"><rect x="2.75" y="2.75" width="12.5" height="12.5" rx="2" ry="2"></rect></g></svg>`,
54814    full: `<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 18 18" aria-hidden="true" focusable="false"><g fill="none" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.25" stroke="currentColor"><rect x="2.75" y="2.75" width="12.5" height="12.5" rx="2" ry="2"></rect><polyline points="12.25 8.75 12.25 5.75 9.25 5.75"></polyline><polyline points="8.75 12.25 5.75 12.25 5.75 9.25"></polyline></g></svg>`
54815  };
54816  var ALIGN_ICONS = {
54817    left: `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><g stroke-linejoin="round" stroke-linecap="round" stroke-width="2" fill="none" stroke="currentColor"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M4 6l16 0"></path><path d="M4 12l10 0"></path><path d="M4 18l14 0"></path></g></svg>`,
54818    center: `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><g stroke-linejoin="round" stroke-linecap="round" stroke-width="2" fill="none" stroke="currentColor"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M4 6l16 0"></path><path d="M8 12l8 0"></path><path d="M6 18l12 0"></path></g></svg>`,
54819    right: `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><g stroke-linejoin="round" stroke-linecap="round" stroke-width="2" fill="none" stroke="currentColor"><path stroke="none" d="M0 0h24v24H0z" fill="none"></path><path d="M4 6l16 0"></path><path d="M10 12l10 0"></path><path d="M6 18l14 0"></path></g></svg>`
54820  };
54821  var ImageToolsElement = class extends HTMLElement {
54822    #updateListener = null;
54823    #activeImageKey = null;
54824    connectedCallback() {
54825      this.editorElement = this.closest("lexxy-editor");
54826      this.editor = this.editorElement.editor;
54827      this.classList.add("lexxy-floating-controls", "lexxy-image-tools");
54828      this.#buildUI();
54829      this.#hide();
54830      this.#monitorSelection();
54831    }
54832    disconnectedCallback() {
54833      this.#updateListener?.();
54834      this.#updateListener = null;
54835      this.editor = null;
54836      this.editorElement = null;
54837    }
54838    #buildUI() {
54839      this.innerHTML = `
54840      <div class="lexxy-floating-controls__group lexxy-image-tools__bar" role="toolbar" aria-label="Image options">
54841        <div class="lexxy-image-tools__section" aria-label="Image width">
54842          ${IMAGE_SIZE_OPTIONS.map((option) => this.#button("size", option, SIZE_ICONS[option.value])).join("")}
54843        </div>
54844        <div class="lexxy-image-tools__section" aria-label="Image alignment">
54845          ${IMAGE_ALIGN_OPTIONS.map((option) => this.#button("align", option, ALIGN_ICONS[option.value])).join("")}
54846        </div>
54847      </div>
54848    `;
54849      this.addEventListener("mousedown", (event) => {
54850        if (event.target.closest("button")) event.preventDefault();
54851      });
54852      this.addEventListener("click", (event) => this.#handleClick(event));
54853    }
54854    #button(type, option, icon) {
54855      return `
54856      <button
54857        type="button"
54858        data-image-${type}="${option.value}"
54859        aria-label="${option.label}"
54860        title="${option.label}"
54861      >
54862        ${icon}
54863        <span>${option.label}</span>
54864      </button>
54865    `;
54866    }
54867    #handleClick(event) {
54868      const sizeButton = event.target.closest("[data-image-size]");
54869      if (sizeButton) {
54870        event.preventDefault();
54871        this.#setLayout({ size: sizeButton.dataset.imageSize });
54872        return;
54873      }
54874      const alignButton = event.target.closest("[data-image-align]");
54875      if (alignButton) {
54876        event.preventDefault();
54877        this.#setLayout({ align: alignButton.dataset.imageAlign });
54878      }
54879    }
54880    #setLayout(patch2) {
54881      const imageKey = this.#activeImageKey;
54882      if (!imageKey) return;
54883      let content = null;
54884      let imageFound = false;
54885      this.editor.getEditorState().read(() => {
54886        const image = $getNodeByKey5(imageKey);
54887        if (!$isResizableImageNode(image)) return;
54888        imageFound = true;
54889        const layout = { ...parseImageLayout(image.content), ...patch2 };
54890        content = serializeImageLayout(image.content, layout);
54891      });
54892      if (!imageFound) return;
54893      this.editor.dispatchCommand(REWRITE_HISTORY_COMMAND, {
54894        [imageKey]: { patch: { content } }
54895      });
54896      this.editor.focus();
54897    }
54898    #monitorSelection() {
54899      this.#updateListener = this.editor.registerUpdateListener(({ editorState }) => {
54900        editorState.read(() => {
54901          const image = $getSelectedImageNode();
54902          if (image) {
54903            this.#activeImageKey = image.getKey();
54904            this.#syncUI(image);
54905            this.#show(image);
54906          } else {
54907            this.#activeImageKey = null;
54908            this.#hide();
54909          }
54910        });
54911      });
54912    }
54913    #syncUI(image) {
54914      const layout = parseImageLayout(image.content);
54915      this.querySelectorAll("[data-image-size]").forEach((button) => {
54916        button.toggleAttribute("aria-selected", button.dataset.imageSize === layout.size);
54917      });
54918      this.querySelectorAll("[data-image-align]").forEach((button) => {
54919        button.toggleAttribute("aria-selected", button.dataset.imageAlign === layout.align);
54920      });
54921    }
54922    #show(image) {
54923      const imageElement = this.editor.getElementByKey(image.getKey());
54924      if (!imageElement) return;
54925      const imageRect = imageElement.getBoundingClientRect();
54926      const editorRect = this.editorElement.getBoundingClientRect();
54927      const top = imageRect.top - editorRect.top;
54928      const left = imageRect.left - editorRect.left + imageRect.width / 2;
54929      this.style.top = `${top}px`;
54930      this.style.left = `${left}px`;
54931      this.hidden = false;
54932    }
54933    #hide() {
54934      this.hidden = true;
54935    }
54936  };
54937  function $getSelectedImageNode() {
54938    const selection = $getSelection9();
54939    if (!$isNodeSelection3(selection)) return null;
54940    return selection.getNodes().find($isResizableImageNode) || null;
54941  }
54942  function $isResizableImageNode(node) {
54943    return $isActionTextAttachmentNode(node) && (node.isPreviewableImage || node.fileName?.toLowerCase().endsWith(".avif"));
54944  }
54945  if (!customElements.get("lexxy-image-tools")) {
54946    customElements.define("lexxy-image-tools", ImageToolsElement);
54947  }
54948
54949  
54949// app/javascript/src/lexxy/image_extension.js
54950  var ImageExtension = class extends LexxyExtension {
54951    get enabled() {
54952      return this.editorElement.supportsRichText && this.editorElement.supportsAttachments;
54953    }
54954    initializeToolbar(_toolbar) {
54955      this.#ensureImageTools();
54956    }
54957    #ensureImageTools() {
54958      if (this.editorElement.querySelector("lexxy-image-tools")) return;
54959      this.editorElement.appendChild(document.createElement("lexxy-image-tools"));
54960    }
54961  };
54962
54963  
54963// app/javascript/src/lexxy/toggle_list_node.js
54964  var {
54965    $applyNodeReplacement: $applyNodeReplacement5,
54966    $createParagraphNode: $createParagraphNode6,
54967    $findMatchingParent: $findMatchingParent7,
54968    $getSelection: $getSelection10,
54969    $isElementNode: $isElementNode8,
54970    $isParagraphNode: $isParagraphNode5,
54971    $isRangeSelection: $isRangeSelection9,
54972    ElementNode: ElementNode4,
54973    INTERNAL_$isBlock: INTERNAL_$isBlock5
54974  } = Lexical_exports;
54975  var TOGGLE_LIST_CLASS = "lexxy-toggle-list";
54976  var TOGGLE_LIST_BUTTON_CLASS = "lexxy-toggle-list__button";
54977  var ToggleListNode = class _ToggleListNode extends ElementNode4 {
54978    __open = true;
54979    static getType() {
54980      return "lexxy-toggle-list";
54981    }
54982    static clone(node) {
54983      return new _ToggleListNode(node.__open, node.__key);
54984    }
54985    constructor(open = true, key) {
54986      super(key);
54987      this.__open = open !== false;
54988    }
54989    createDOM() {
54990      const element = document.createElement("div");
54991      element.className = TOGGLE_LIST_CLASS;
54992      element.dataset.lexxyToggleKey = this.getKey();
54993      const button = document.createElement("button");
54994      button.type = "button";
54995      button.className = TOGGLE_LIST_BUTTON_CLASS;
54996      button.contentEditable = "false";
54997      button.tabIndex = -1;
54998      button.setAttribute("aria-label", "Toggle list contents");
54999      button.innerHTML = `
55000      <svg aria-hidden="true" focusable="false" viewBox="0 0 12 12">
55001        <path d="M1.5 2.31061C1.5 0.943037 2.99801 0.103919 4.16406 0.818427L10.1855 4.50788C11.2997 5.19065 11.2997 6.80949 10.1855 7.49226L4.16406 11.1817C2.99802 11.8962 1.5 11.0571 1.5 9.68952V2.31061Z" fill="currentColor"></path>
55002      </svg>
55003    `;
55004      element.append(button);
55005      this.#syncDom(element);
55006      return element;
55007    }
55008    updateDOM(prevNode, dom) {
55009      dom.dataset.lexxyToggleKey = this.getKey();
55010      if (prevNode.__open !== this.__open) {
55011        this.#syncDom(dom);
55012      }
55013      return false;
55014    }
55015    #syncDom(element) {
55016      const open = this.__open ? "true" : "false";
55017      element.dataset.open = open;
55018      element.setAttribute("aria-expanded", open);
55019      element.querySelector(`.${TOGGLE_LIST_BUTTON_CLASS}`)?.setAttribute("aria-expanded", open);
55020    }
55021    static importDOM() {
55022      const convert = (domNode) => {
55023        if (!domNode.classList.contains(TOGGLE_LIST_CLASS)) return null;
55024        return {
55025          conversion: () => ({
55026            node: $createToggleListNode(domNode.dataset.open !== "false")
55027          }),
55028          priority: 2
55029        };
55030      };
55031      return { div: convert };
55032    }
55033    exportDOM(editor) {
55034      const { element } = super.exportDOM(editor);
55035      if (element) {
55036        element.className = TOGGLE_LIST_CLASS;
55037        this.#syncDom(element);
55038        element.removeAttribute("data-lexxy-toggle-key");
55039        element.querySelector(`.${TOGGLE_LIST_BUTTON_CLASS}`)?.remove();
55040      }
55041      return { element };
55042    }
55043    static importJSON(serializedNode) {
55044      return $createToggleListNode(serializedNode.open !== false);
55045    }
55046    exportJSON() {
55047      return {
55048        ...super.exportJSON(),
55049        type: "lexxy-toggle-list",
55050        open: this.__open,
55051        version: 1
55052      };
55053    }
55054    insertNewAfter(_selection, restoreSelection) {
55055      const paragraph = $createParagraphNode6();
55056      this.insertAfter(paragraph, restoreSelection);
55057      return paragraph;
55058    }
55059    collapseAtStart() {
55060      const children = [...this.getChildren()];
55061      const firstChild = children[0];
55062      if (!firstChild) {
55063        const paragraph = $createParagraphNode6();
55064        this.replace(paragraph);
55065        paragraph.selectStart();
55066        return true;
55067      }
55068      children.forEach((child) => this.insertBefore(child));
55069      this.remove();
55070      firstChild.selectStart?.();
55071      return true;
55072    }
55073    canBeEmpty() {
55074      return false;
55075    }
55076    isShadowRoot() {
55077      return true;
55078    }
55079    canIndent() {
55080      return false;
55081    }
55082    canMergeWhenEmpty() {
55083      return true;
55084    }
55085    setOpen(open) {
55086      const self2 = this.getWritable();
55087      self2.__open = open !== false;
55088      return self2;
55089    }
55090    toggleOpen() {
55091      return this.setOpen(!this.getOpen());
55092    }
55093    getOpen() {
55094      return this.getLatest().__open;
55095    }
55096  };
55097  function $createToggleListNode(open = true) {
55098    return $applyNodeReplacement5(new ToggleListNode(open));
55099  }
55100  function $isToggleListNode(node) {
55101    return node instanceof ToggleListNode;
55102  }
55103  function $isToggleTitleBlock(node) {
55104    return $isParagraphNode5(node) || $isHeadingNode2(node);
55105  }
55106  function $selectionBlock2(selection) {
55107    const anchorNode = selection.anchor.getNode();
55108    if ($isElementNode8(anchorNode) && INTERNAL_$isBlock5(anchorNode)) return anchorNode;
55109    const block = $findMatchingParent7(
55110      anchorNode,
55111      (node) => $isElementNode8(node) && INTERNAL_$isBlock5(node)
55112    );
55113    if ($isElementNode8(block)) return block;
55114    if ($isElementNode8(anchorNode) && anchorNode.isShadowRoot() && selection.anchor.type === "element") {
55115      const index = selection.anchor.offset;
55116      const child = anchorNode.getChildAtIndex(index) || anchorNode.getChildAtIndex(Math.max(0, index - 1));
55117      if ($isElementNode8(child) && INTERNAL_$isBlock5(child)) return child;
55118    }
55119    return null;
55120  }
55121  function $selectionListItem(selection) {
55122    return $findMatchingParent7(selection.anchor.getNode(), $isListItemNode2);
55123  }
55124  function $normalizeToggleListBody(toggleList) {
55125    const children = [...toggleList.getLatest().getChildren()];
55126    if (children.length <= 1) return;
55127    let inlineRun = [];
55128    const flushInlineRun = () => {
55129      if (inlineRun.length === 0) return;
55130      const paragraph = $createParagraphNode6();
55131      inlineRun[0].insertBefore(paragraph);
55132      inlineRun.forEach((node) => paragraph.append(node));
55133      inlineRun = [];
55134    };
55135    for (let index = 1; index < children.length; index += 1) {
55136      const child = children[index];
55137      if ($isValidContainerContentNode(child)) {
55138        flushInlineRun();
55139      } else {
55140        inlineRun.push(child);
55141      }
55142    }
55143    flushInlineRun();
55144  }
55145  function $normalizeToggleListTitle(toggleList) {
55146    const children = [...toggleList.getLatest().getChildren()];
55147    if (children.length === 0) return;
55148    if ($isToggleTitleBlock(children[0])) return;
55149    let inlineRun = [];
55150    const flushInlineRun = () => {
55151      if (inlineRun.length === 0) return;
55152      const paragraph = $createParagraphNode6();
55153      inlineRun[0].insertBefore(paragraph);
55154      inlineRun.forEach((node) => paragraph.append(node));
55155      inlineRun = [];
55156    };
55157    for (const child of children) {
55158      if ($isToggleTitleBlock(child)) {
55159        flushInlineRun();
55160        break;
55161      }
55162      if ($isValidContainerContentNode(child)) {
55163        flushInlineRun();
55164        break;
55165      }
55166      inlineRun.push(child);
55167    }
55168    flushInlineRun();
55169  }
55170  function $extractToggleTitleAttachments(toggleList) {
55171    const title = toggleList.getFirstChild();
55172    if (!$isToggleTitleBlock(title)) return;
55173    const attachments = title.getChildren().filter($isCustomActionTextAttachmentNode);
55174    let insertionPoint = toggleList;
55175    attachments.forEach((attachment) => {
55176      const paragraph = $createParagraphNode6();
55177      insertionPoint.insertAfter(paragraph);
55178      paragraph.append(attachment);
55179      insertionPoint = paragraph;
55180    });
55181  }
55182  function $extractToggleTitleAttachment(attachment) {
55183    const title = $findMatchingParent7(attachment, $isToggleTitleBlock);
55184    if (!$isToggleTitleBlock(title)) return;
55185    const toggleList = $findMatchingParent7(title, $isToggleListNode);
55186    if (!$isToggleListNode(toggleList) || !toggleList.getFirstChild()?.is(title)) return;
55187    $extractToggleTitleAttachments(toggleList);
55188  }
55189  function $normalizeToggleListContent(toggleList) {
55190    if (toggleList.getLatest().getChildrenSize() === 0) {
55191      toggleList.append($createParagraphNode6());
55192      return;
55193    }
55194    $normalizeToggleListTitle(toggleList);
55195    $normalizeToggleListBody(toggleList);
55196  }
55197  function $insertToggleList() {
55198    const selection = $getSelection10();
55199    if (!$isRangeSelection9(selection)) return;
55200    const listItem = $selectionListItem(selection);
55201    if ($isListItemNode2(listItem)) {
55202      $insertToggleListFromListItem(listItem);
55203      return;
55204    }
55205    const toggleList = $createToggleListNode(false);
55206    const block = $selectionBlock2(selection);
55207    if (!block || $isToggleListNode(block)) return;
55208    block.insertBefore(toggleList);
55209    toggleList.append(block);
55210    block.selectStart();
55211  }
55212  function $insertToggleListFromListItem(listItem) {
55213    const toggleList = $createToggleListNode(false);
55214    const title = $createParagraphNode6();
55215    const children = [...listItem.getChildren()];
55216    const bodyChildren = [];
55217    children.forEach((child) => {
55218      if ($isListNode2(child)) {
55219        bodyChildren.push(child);
55220      } else if ($isElementNode8(child) && INTERNAL_$isBlock5(child)) {
55221        title.append(...child.getChildren());
55222        child.remove();
55223      } else {
55224        title.append(child);
55225      }
55226    });
55227    toggleList.append(title, ...bodyChildren);
55228    listItem.insertAfter(toggleList);
55229    listItem.remove();
55230    title.selectStart();
55231  }
55232
55233  
55233// app/javascript/src/lexxy/toggle_list_content_blocks.js
55234  var { $isElementNode: $isElementNode9, $isParagraphNode: $isParagraphNode6, $isTextNode: $isTextNode7 } = Lexical_exports;
55235  var TOGGLE_BODY_STRUCTURE_SELECTOR = ".lexxy-toggle-list, .lexxy-callout, .lexxy-content__table-wrapper, table, ul, ol, blockquote, pre, figure.horizontal-divider, figure, action-text-attachment, .attachment, .attachment-gallery, hr, h1, h2, h3, h4, h5, h6";
55236  function domToggleBlockHasContent(block) {
55237    if (!block?.matches) return false;
55238    if (block.matches(TOGGLE_BODY_STRUCTURE_SELECTOR)) return true;
55239    if (block.querySelector(TOGGLE_BODY_STRUCTURE_SELECTOR)) return true;
55240    if (block.textContent.trim() !== "") return true;
55241    if (block.matches("figure, action-text-attachment, .attachment, .attachment-gallery")) return true;
55242    if (block.querySelector("img, video, iframe, figure, action-text-attachment, .attachment, .attachment-gallery")) {
55243      return true;
55244    }
55245    return Array.from(block.childNodes).some((child) => {
55246      if (child.nodeType === Node.TEXT_NODE) return child.textContent.trim() !== "";
55247      if (child.nodeName === "BR") return false;
55248      return child.nodeType === Node.ELEMENT_NODE && child.textContent.trim() !== "";
55249    });
55250  }
55251  function $lexicalToggleBlockHasContent(node) {
55252    if (node.getTextContent().trim() !== "") return true;
55253    if ($isToggleListNode(node) || $isCalloutNode(node)) return true;
55254    if (!$isElementNode9(node)) return false;
55255    if (!$isParagraphNode6(node)) return true;
55256    return node.getChildren().some((child) => !$isTextNode7(child));
55257  }
55258
55259  
55259// app/javascript/src/lexxy/toggle_list_title_commands.js
55260  var {
55261    $createNodeSelection: $createNodeSelection3,
55262    $createParagraphNode: $createParagraphNode7,
55263    $createTextNode: $createTextNode4,
55264    $findMatchingParent: $findMatchingParent8,
55265    $getSelection: $getSelection11,
55266    $isElementNode: $isElementNode10,
55267    $isParagraphNode: $isParagraphNode7,
55268    $isRangeSelection: $isRangeSelection10,
55269    $isTextNode: $isTextNode8,
55270    $setSelection: $setSelection3
55271  } = Lexical_exports;
55272  var CONVERTIBLE_KINDS = /* @__PURE__ */ new Set(["toggle", "bullet", "number", "check", "quote", "callout", "code"]);
55273  var TITLE_FORMAT_KINDS = /* @__PURE__ */ new Set(["paragraph", "h1", "h2", "h3", "h4"]);
55274  function $toggleTitleContext(selection) {
55275    const anchorNode = selection.anchor.getNode();
55276    const block = $isToggleTitleBlock(anchorNode) ? anchorNode : $findMatchingParent8(anchorNode, $isToggleTitleBlock);
55277    if (!block) return null;
55278    const toggleList = $findMatchingParent8(block, $isToggleListNode);
55279    if (!$isToggleListNode(toggleList) || !toggleList.getFirstChild()?.is(block)) return null;
55280    return { toggleList, title: block };
55281  }
55282  function $isToggleListFullyEmpty(context) {
55283    if (context.title.getTextContent().trim() !== "") return false;
55284    const bodyChildren = context.toggleList.getChildren().filter((child) => !child.is(context.title));
55285    return bodyChildren.every((child) => !$lexicalToggleBlockHasContent(child));
55286  }
55287  function $routeToggleTitleCommand(kind, { editor } = {}) {
55288    const selection = $getSelection11();
55289    if (!$isRangeSelection10(selection)) return false;
55290    const context = $toggleTitleContext(selection);
55291    if (!context) return false;
55292    if (TITLE_FORMAT_KINDS.has(kind)) {
55293      return $formatToggleTitle(context, kind);
55294    }
55295    const fullyEmpty = $isToggleListFullyEmpty(context);
55296    if (fullyEmpty && CONVERTIBLE_KINDS.has(kind)) {
55297      return $convertToggleTitleByKind(context, kind);
55298    }
55299    return $insertAfterToggleByKind(context, kind, { editor });
55300  }
55301  function $removeToggleTitleShortcutText(marker) {
55302    const selection = $getSelection11();
55303    if (!$isRangeSelection10(selection) || !selection.isCollapsed()) return;
55304    const anchorNode = selection.anchor.getNode();
55305    if (!$isTextNode8(anchorNode)) return;
55306    const offset3 = selection.anchor.offset;
55307    const textBeforeCursor = anchorNode.getTextContent().slice(0, offset3);
55308    const markerText = typeof marker === "string" ? marker : marker.source;
55309    const shortcutIndex = typeof marker === "string" ? textBeforeCursor.lastIndexOf(marker) : (() => {
55310      const match = textBeforeCursor.match(marker);
55311      if (!match || match.index === void 0) return -1;
55312      return match.index;
55313    })();
55314    if (shortcutIndex === -1) return;
55315    const textBeforeShortcut = textBeforeCursor.slice(0, shortcutIndex);
55316    if (textBeforeShortcut && !textBeforeShortcut.endsWith("\n")) return;
55317    anchorNode.spliceText(shortcutIndex, offset3 - shortcutIndex, "", true);
55318  }
55319  function $replaceToggleWithNode(context, replacement) {
55320    const body = context.toggleList.getChildren().filter((child) => !child.is(context.title));
55321    context.toggleList.insertBefore(replacement);
55322    let previous = replacement;
55323    body.forEach((child) => {
55324      previous.insertAfter(child);
55325      previous = child;
55326    });
55327    context.toggleList.remove();
55328    $selectInsertedNode(replacement);
55329    return true;
55330  }
55331  function $moveTitleChildrenInto(node, title) {
55332    const children = [...title.getChildren()];
55333    if (children.length > 0) {
55334      node.append(...children);
55335      return;
55336    }
55337    if ($isParagraphNode7(node) || $isElementNode10(node)) {
55338      node.append($createParagraphNode7());
55339    }
55340  }
55341  function $formatToggleTitle(context, kind) {
55342    const replacement = kind === "paragraph" ? $createParagraphNode7() : $createHeadingNode2(kind);
55343    context.title.replace(replacement, true);
55344    return true;
55345  }
55346  function $convertToggleTitleByKind(context, kind) {
55347    switch (kind) {
55348      case "toggle":
55349        return $convertEmptyToggleToParagraph(context);
55350      case "bullet":
55351        return $convertToggleToList(context, "bullet");
55352      case "number":
55353        return $convertToggleToList(context, "number");
55354      case "check":
55355        return $convertToggleToList(context, "check");
55356      case "quote":
55357        return $convertToggleToQuote(context);
55358      case "callout":
55359        return $convertToggleToCallout(context);
55360      case "code":
55361        return $convertToggleToCode(context);
55362      default:
55363        return false;
55364    }
55365  }
55366  function $convertEmptyToggleToParagraph(context) {
55367    const paragraph = $createParagraphNode7();
55368    $moveTitleChildrenInto(paragraph, context.title);
55369    return $replaceToggleWithNode(context, paragraph);
55370  }
55371  function $convertToggleToList(context, listType) {
55372    const list = $createListNode2(listType);
55373    const item = $createListItemNode2(listType === "check" ? false : void 0);
55374    $moveTitleChildrenInto(item, context.title);
55375    list.append(item);
55376    return $replaceToggleWithNode(context, list);
55377  }
55378  function $convertToggleToQuote(context) {
55379    const quote = $createQuoteNode2();
55380    $moveTitleChildrenInto(quote, context.title);
55381    return $replaceToggleWithNode(context, quote);
55382  }
55383  function $convertToggleToCallout(context) {
55384    const callout = $createCalloutNode();
55385    $moveTitleChildrenInto(callout, context.title);
55386    return $replaceToggleWithNode(context, callout);
55387  }
55388  function $convertToggleToCode(context) {
55389    const code = $createCodeNode3();
55390    const titleText = context.title.getTextContent();
55391    if (titleText) code.append($createTextNode4(titleText));
55392    return $replaceToggleWithNode(context, code);
55393  }
55394  function $insertAfterToggleByKind(context, kind, { editor } = {}) {
55395    switch (kind) {
55396      case "toggle":
55397        return $insertToggleListAfterToggle(context);
55398      case "bullet":
55399        return $insertListAfterToggle(context, "bullet");
55400      case "number":
55401        return $insertListAfterToggle(context, "number");
55402      case "check":
55403        return $insertListAfterToggle(context, "check");
55404      case "quote":
55405        return $insertQuoteAfterToggle(context);
55406      case "callout":
55407        return $insertCalloutAfterToggle(context);
55408      case "code":
55409        return $insertCodeAfterToggle(context);
55410      case "table":
55411        return $insertTableAfterToggle(context, editor);
55412      case "divider":
55413        return $insertDividerAfterToggle(context);
55414      default:
55415        return false;
55416    }
55417  }
55418  function $insertToggleListAfterToggle(context) {
55419    const toggleList = $createToggleListNode(false);
55420    const title = $createParagraphNode7();
55421    toggleList.append(title);
55422    context.toggleList.insertAfter(toggleList);
55423    title.selectStart();
55424    return true;
55425  }
55426  function $insertListAfterToggle(context, listType) {
55427    const list = $createListNode2(listType);
55428    const item = $createListItemNode2(listType === "check" ? false : void 0);
55429    list.append(item);
55430    context.toggleList.insertAfter(list);
55431    item.selectStart();
55432    return true;
55433  }
55434  function $insertQuoteAfterToggle(context) {
55435    const quote = $createQuoteNode2();
55436    const paragraph = $createParagraphNode7();
55437    quote.append(paragraph);
55438    context.toggleList.insertAfter(quote);
55439    paragraph.selectStart();
55440    return true;
55441  }
55442  function $insertCalloutAfterToggle(context) {
55443    const callout = $createCalloutNode();
55444    const paragraph = $createParagraphNode7();
55445    callout.append(paragraph);
55446    context.toggleList.insertAfter(callout);
55447    paragraph.selectStart();
55448    return true;
55449  }
55450  function $insertCodeAfterToggle(context) {
55451    const code = $createCodeNode3();
55452    context.toggleList.insertAfter(code);
55453    code.selectStart();
55454    return true;
55455  }
55456  function $insertDividerAfterToggle(context) {
55457    const divider = new HorizontalDividerNode();
55458    context.toggleList.insertAfter(divider);
55459    const selection = $createNodeSelection3();
55460    selection.add(divider.getKey());
55461    $setSelection3(selection);
55462    return true;
55463  }
55464  function $insertTableAfterToggle(context, editor) {
55465    if (!editor) return false;
55466    const paragraph = $createParagraphNode7();
55467    context.toggleList.insertAfter(paragraph);
55468    paragraph.selectStart();
55469    editor.dispatchCommand(INSERT_TABLE_COMMAND2, { rows: 3, columns: 3, includeHeaders: true });
55470    const table = context.toggleList.getNextSibling() instanceof TableNode2 && context.toggleList.getNextSibling() || $findMatchingParent8(paragraph, (node) => node instanceof TableNode2);
55471    if (table instanceof TableNode2) $selectFirstTableCell(table);
55472    return true;
55473  }
55474  function $selectFirstTableCell(table) {
55475    const firstCell = table?.getFirstChild()?.getFirstChild();
55476    const firstCellContent = firstCell?.getFirstChild();
55477    if (firstCellContent?.selectStart) {
55478      firstCellContent.selectStart();
55479    } else {
55480      firstCell?.selectStart?.();
55481    }
55482  }
55483  function $selectInsertedNode(node) {
55484    if (node.selectStart) {
55485      node.selectStart();
55486      return;
55487    }
55488    const firstChild = node.getFirstChild();
55489    if (firstChild?.selectStart) {
55490      firstChild.selectStart();
55491      return;
55492    }
55493    node.selectEnd?.();
55494  }
55495  var TOGGLE_TITLE_MARKDOWN_SHORTCUTS = [
55496    { kind: "toggle", pattern: /(?:^|\n)>\s?$/, marker: ">" },
55497    { kind: "bullet", pattern: /(?:^|\n)-\s?$/, marker: "-" },
55498    { kind: "number", pattern: /(?:^|\n)\d+\.\s?$/, marker: /\d+\.$/ },
55499    { kind: "check", pattern: /(?:^|\n)\[\]\s?$/, marker: "[]" },
55500    { kind: "quote", pattern: /(?:^|\n)"\s?$/, marker: '"' },
55501    { kind: "divider", pattern: /(?:^|\n)---\s?$/, marker: "---" },
55502    { kind: "code", pattern: /(?:^|\n)```\s?$/, marker: "```" }
55503  ];
55504  function $toggleTitleMarkdownShortcutMatch() {
55505    const selection = $getSelection11();
55506    if (!$isRangeSelection10(selection) || !selection.isCollapsed()) return null;
55507    if (!$toggleTitleContext(selection)) return null;
55508    const anchorNode = selection.anchor.getNode();
55509    if (!$isTextNode8(anchorNode)) return null;
55510    const textBeforeCursor = anchorNode.getTextContent().slice(0, selection.anchor.offset);
55511    return TOGGLE_TITLE_MARKDOWN_SHORTCUTS.find((shortcut) => shortcut.pattern.test(textBeforeCursor)) || null;
55512  }
55513  var TOGGLE_TITLE_TOOLBAR_ACTIONS = {
55514    "toggle-list": "toggle",
55515    "bullet-list": "bullet",
55516    "unordered-list": "bullet",
55517    "number-list": "number",
55518    "ordered-list": "number",
55519    checklist: "check",
55520    quote: "quote",
55521    blockquote: "quote",
55522    callout: "callout",
55523    code: "code",
55524    "code-block": "code",
55525    divider: "divider",
55526    separator: "divider",
55527    table: "table"
55528  };
55529
55530  
55530// app/javascript/src/lexxy/toggle_list_extension.js
55531  var {
55532    $createParagraphNode: $createParagraphNode8,
55533    $getNodeByKey: $getNodeByKey6,
55534    $getSelection: $getSelection12,
55535    $isParagraphNode: $isParagraphNode8,
55536    $isRangeSelection: $isRangeSelection11,
55537    $isTextNode: $isTextNode9,
55538    COMMAND_PRIORITY_CRITICAL: COMMAND_PRIORITY_CRITICAL4,
55539    INPUT_COMMAND: INPUT_COMMAND4,
55540    KEY_ENTER_COMMAND: KEY_ENTER_COMMAND6,
55541    KEY_SPACE_COMMAND: KEY_SPACE_COMMAND4
55542  } = Lexical_exports;
55543  var ToggleListExtension = class extends LexxyExtension {
55544    #button = null;
55545    #emptyMarkerFrame = null;
55546    #interactionListener = null;
55547    #toolbarCommandListener = null;
55548    #updateListener = null;
55549    get enabled() {
55550      return this.editorElement.supportsRichText;
55551    }
55552    get allowedElements() {
55553      return [
55554        {
55555          tag: "div",
55556          attributes: ["class", "data-open", "aria-expanded"]
55557        }
55558      ];
55559    }
55560    get lexicalExtension() {
55561      return this.defineExtension({
55562        name: "lexxy/toggle-list",
55563        nodes: [ToggleListNode],
55564        register: (editor) => mergeRegister3(
55565          editor.registerNodeTransform(ToggleListNode, (toggleList) => {
55566            $normalizeToggleListContent(toggleList);
55567          }),
55568          editor.registerNodeTransform(CustomActionTextAttachmentNode, $extractToggleTitleAttachment),
55569          registerToggleTitleMarkdownShortcuts(editor),
55570          registerToggleTitleListTransforms(editor),
55571          editor.registerCommand(
55572            KEY_ENTER_COMMAND6,
55573            (event) => {
55574              if (this.editorElement.hasAttribute("data-lexxy-slash-menu-open")) return false;
55575              if ((event?.metaKey || event?.ctrlKey) && $toggleTitleOpenState()) {
55576                event?.preventDefault();
55577                return true;
55578              }
55579              if ($insertToggleListAfterCollapsedTitle()) {
55580                event?.preventDefault();
55581                return true;
55582              }
55583              if (!$exitToggleListFromEmptyParagraph()) return false;
55584              event?.preventDefault();
55585              return true;
55586            },
55587            COMMAND_PRIORITY_CRITICAL4
55588          )
55589        )
55590      });
55591    }
55592    initializeToolbar(toolbar) {
55593      this.#bindToggleButtonClicks();
55594      const checklistButton = toolbar.querySelector('[name="checklist"]');
55595      if (!checklistButton || toolbar.querySelector('[name="toggle-list"]')) return;
55596      checklistButton.classList.remove("lexxy-editor__toolbar-group-end");
55597      const button = document.createElement("button");
55598      button.type = "button";
55599      button.className = "lexxy-editor__toolbar-button lexxy-editor__toolbar-group-end";
55600      button.name = "toggle-list";
55601      button.title = "Toggle list";
55602      button.innerHTML = LEXXY_TOOLBAR_ICONS.toggleList;
55603      button.addEventListener("click", (event) => {
55604        event.preventDefault();
55605        this.#toggleToggleList();
55606      });
55607      checklistButton.insertAdjacentElement("afterend", button);
55608      this.#button = button;
55609      this.#bindTitleToolbarCommands(toolbar);
55610      const editor = this.editorElement.editor;
55611      if (!editor) return;
55612      this.#updateListener = editor.registerUpdateListener(({ editorState }) => {
55613        editorState.read(() => {
55614          const active = this.#selectionIsInToggleTitle();
55615          button.classList.toggle("lexxy-editor__toolbar-button--pressed", active);
55616          button.setAttribute("aria-pressed", active ? "true" : "false");
55617          this.#scheduleEmptyContentMarkerSync();
55618        });
55619      });
55620      this.#scheduleEmptyContentMarkerSync();
55621    }
55622    dispose() {
55623      if (this.#emptyMarkerFrame) cancelAnimationFrame(this.#emptyMarkerFrame);
55624      this.#interactionListener?.();
55625      this.#toolbarCommandListener?.();
55626      this.#updateListener?.();
55627      this.#button = null;
55628    }
55629    #bindTitleToolbarCommands(toolbar) {
55630      if (this.#toolbarCommandListener) return;
55631      const handleClick2 = (event) => {
55632        const button = event.target?.closest?.("button[name]");
55633        if (!button || !toolbar.contains(button)) return;
55634        const kind = TOGGLE_TITLE_TOOLBAR_ACTIONS[button.name];
55635        if (!kind) return;
55636        const editor = this.editorElement.editor;
55637        if (!editor) return;
55638        let handled = false;
55639        editor.update(() => {
55640          handled = $routeToggleTitleCommand(kind, { editor });
55641        });
55642        if (!handled) return;
55643        event.preventDefault();
55644        event.stopPropagation();
55645        editor.focus();
55646      };
55647      toolbar.addEventListener("click", handleClick2, true);
55648      this.#toolbarCommandListener = () => toolbar.removeEventListener("click", handleClick2, true);
55649    }
55650    #bindToggleButtonClicks() {
55651      if (this.#interactionListener) return;
55652      const handlePointerDown = (event) => {
55653        const button = event.target?.closest?.(".lexxy-toggle-list__button");
55654        if (!button || !this.editorElement.contains(button)) {
55655          this.#handleEmptyPlaceholderPointerDown(event);
55656          return;
55657        }
55658        const toggleListElement = button.closest(".lexxy-toggle-list");
55659        const key = toggleListElement?.dataset.lexxyToggleKey;
55660        if (!key) return;
55661        event.preventDefault();
55662        event.stopPropagation();
55663        const open = toggleListElement.dataset.open === "false";
55664        this.#syncToggleListElement(toggleListElement, open);
55665        this.#persistToggleState(key, open);
55666      };
55667      const handlePointerMove = (event) => {
55668        this.editorElement.querySelectorAll(".lexxy-toggle-list[data-empty-content='true'][data-open='true']").forEach((toggleListElement) => {
55669          const hovered = this.#eventTargetsEmptyPlaceholder(event, toggleListElement);
55670          const next = hovered ? "true" : "false";
55671          if (toggleListElement.dataset.emptyContentHover !== next) {
55672            toggleListElement.dataset.emptyContentHover = next;
55673          }
55674        });
55675      };
55676      const clearEmptyContentHover = () => {
55677        this.editorElement.querySelectorAll(".lexxy-toggle-list[data-empty-content-hover]").forEach((toggleListElement) => {
55678          delete toggleListElement.dataset.emptyContentHover;
55679        });
55680      };
55681      this.editorElement.addEventListener("pointerdown", handlePointerDown);
55682      this.editorElement.addEventListener("pointermove", handlePointerMove);
55683      this.editorElement.addEventListener("pointerleave", clearEmptyContentHover);
55684      this.#interactionListener = () => {
55685        this.editorElement.removeEventListener("pointerdown", handlePointerDown);
55686        this.editorElement.removeEventListener("pointermove", handlePointerMove);
55687        this.editorElement.removeEventListener("pointerleave", clearEmptyContentHover);
55688      };
55689    }
55690    #handleEmptyPlaceholderPointerDown(event) {
55691      const toggleListElement = event.target?.closest?.(
55692        ".lexxy-toggle-list[data-empty-content='true'][data-open='true']"
55693      );
55694      if (!toggleListElement || !this.editorElement.contains(toggleListElement)) return;
55695      if (!this.#eventTargetsEmptyPlaceholder(event, toggleListElement)) return;
55696      const key = toggleListElement.dataset.lexxyToggleKey;
55697      if (!key) return;
55698      event.preventDefault();
55699      event.stopPropagation();
55700      const editor = this.editorElement.editor;
55701      editor.update(() => {
55702        const node = $getNodeByKey6(key);
55703        if (!$isToggleListNode(node)) return;
55704        const title = node.getFirstChild();
55705        const paragraph = title?.getNextSibling() || $createParagraphNode8();
55706        if (!paragraph.getParent()) {
55707          if (title) title.insertAfter(paragraph);
55708          else node.append(paragraph);
55709        }
55710        paragraph.selectStart();
55711      });
55712      editor.focus();
55713    }
55714    #eventTargetsEmptyPlaceholder(event, toggleListElement) {
55715      const [titleElement, ...bodyElements] = this.#toggleContentBlocks(toggleListElement);
55716      if (bodyElements.length > 0 && toggleListElement.dataset.hasBodyBlock === "true" && toggleListElement.dataset.emptyContentFocused !== "true") {
55717        return bodyElements.some((bodyElement) => this.#pointerIsOverElement(event, bodyElement));
55718      }
55719      if (!titleElement) return true;
55720      const titleRect = titleElement.getBoundingClientRect();
55721      const lineHeight = parseFloat(getComputedStyle(titleElement).lineHeight) || titleRect.height;
55722      if (event.clientY <= titleRect.top + lineHeight) return false;
55723      const toggleRect = toggleListElement.getBoundingClientRect();
55724      return event.clientY <= toggleRect.bottom && event.clientX >= toggleRect.left && event.clientX <= toggleRect.right;
55725    }
55726    #pointerIsOverElement(event, element) {
55727      const rect = element.getBoundingClientRect();
55728      return event.clientX >= rect.left && event.clientX <= rect.right && event.clientY >= rect.top && event.clientY <= rect.bottom;
55729    }
55730    #syncToggleListElement(toggleListElement, open) {
55731      const value = open ? "true" : "false";
55732      toggleListElement.dataset.open = value;
55733      toggleListElement.setAttribute("aria-expanded", value);
55734      toggleListElement.querySelector(".lexxy-toggle-list__button")?.setAttribute("aria-expanded", value);
55735    }
55736    #persistToggleState(key, open) {
55737      const editor = this.editorElement.editor;
55738      if (!editor) return;
55739      editor.update(() => {
55740        const node = $getNodeByKey6(key);
55741        if ($isToggleListNode(node)) node.setOpen(open);
55742      });
55743    }
55744    #scheduleEmptyContentMarkerSync() {
55745      if (this.#emptyMarkerFrame) return;
55746      this.#emptyMarkerFrame = requestAnimationFrame(() => {
55747        this.#emptyMarkerFrame = null;
55748        this.#syncEmptyContentMarkers();
55749      });
55750    }
55751    #syncEmptyContentMarkers() {
55752      const selectedBlock = this.#selectedToggleContentBlock();
55753      this.editorElement.querySelectorAll(".lexxy-toggle-list").forEach((toggleListElement) => {
55754        const blocks = this.#toggleContentBlocks(toggleListElement);
55755        const titleBlock = blocks[0];
55756        const bodyBlocks = blocks.slice(1);
55757        const hasBodyContent = bodyBlocks.some((block) => domToggleBlockHasContent(block));
55758        toggleListElement.dataset.emptyTitle = titleBlock?.textContent.trim() ? "false" : "true";
55759        toggleListElement.dataset.emptyContent = hasBodyContent ? "false" : "true";
55760        toggleListElement.dataset.hasBodyBlock = bodyBlocks.length > 0 ? "true" : "false";
55761        toggleListElement.dataset.emptyContentFocused = !hasBodyContent && bodyBlocks.includes(selectedBlock) ? "true" : "false";
55762        if (toggleListElement.dataset.emptyContent !== "true" || toggleListElement.dataset.open !== "true") {
55763          delete toggleListElement.dataset.emptyContentHover;
55764        }
55765      });
55766    }
55767    #toggleContentBlocks(toggleListElement) {
55768      return Array.from(toggleListElement.children).filter(
55769        (child) => !child.classList.contains("lexxy-toggle-list__button")
55770      );
55771    }
55772    #selectedToggleContentBlock() {
55773      const selection = window.getSelection();
55774      const anchorNode = selection?.anchorNode;
55775      const anchorElement = anchorNode?.nodeType === Node.ELEMENT_NODE ? anchorNode : anchorNode?.parentElement;
55776      return anchorElement?.closest?.(".lexxy-toggle-list > :not(.lexxy-toggle-list__button)") || null;
55777    }
55778    #toggleToggleList() {
55779      const editor = this.editorElement.editor;
55780      if (!editor) return;
55781      editor.update(() => {
55782        if ($routeToggleTitleCommand("toggle", { editor })) return;
55783        $insertToggleList();
55784      });
55785      editor.focus();
55786    }
55787    #selectionIsInToggleTitle() {
55788      return this.#toggleTitleContextForSelection() !== null;
55789    }
55790    #toggleTitleContextForSelection() {
55791      const selection = $getSelection12();
55792      if (!$isRangeSelection11(selection)) return null;
55793      return $toggleTitleContext(selection);
55794    }
55795  };
55796  function registerToggleTitleMarkdownShortcuts(editor) {
55797    const handleShortcut = (event) => {
55798      let toggleTitleShortcut = null;
55799      let hasToggleShortcut = false;
55800      editor.getEditorState().read(() => {
55801        toggleTitleShortcut = $toggleTitleMarkdownShortcutMatch();
55802        if (!toggleTitleShortcut) hasToggleShortcut = $selectionHasToggleListShortcut();
55803      });
55804      if (toggleTitleShortcut) {
55805        event?.preventDefault();
55806        editor.update(() => {
55807          $removeToggleTitleShortcutText(toggleTitleShortcut.marker);
55808          $routeToggleTitleCommand(toggleTitleShortcut.kind, { editor });
55809        });
55810        return true;
55811      }
55812      if (!hasToggleShortcut) return false;
55813      event?.preventDefault();
55814      editor.update(() => {
55815        $removeToggleTitleShortcutText(">");
55816        $insertToggleList();
55817      });
55818      return true;
55819    };
55820    const removeSpaceCommand = editor.registerCommand(KEY_SPACE_COMMAND4, handleShortcut, COMMAND_PRIORITY_CRITICAL4);
55821    const removeInputCommand = editor.registerCommand(
55822      INPUT_COMMAND4,
55823      (event) => {
55824        if (event.inputType !== "insertText" || event.data !== " ") return false;
55825        return handleShortcut(event);
55826      },
55827      COMMAND_PRIORITY_CRITICAL4
55828    );
55829    return () => {
55830      removeSpaceCommand();
55831      removeInputCommand();
55832    };
55833  }
55834  function registerToggleTitleListTransforms(editor) {
55835    return mergeRegister3(
55836      editor.registerCommand(
55837        INSERT_UNORDERED_LIST_COMMAND2,
55838        () => $routeToggleTitleCommand("bullet"),
55839        COMMAND_PRIORITY_CRITICAL4
55840      ),
55841      editor.registerCommand(
55842        INSERT_ORDERED_LIST_COMMAND2,
55843        () => $routeToggleTitleCommand("number"),
55844        COMMAND_PRIORITY_CRITICAL4
55845      ),
55846      editor.registerCommand(
55847        INSERT_CHECK_LIST_COMMAND2,
55848        () => $routeToggleTitleCommand("check"),
55849        COMMAND_PRIORITY_CRITICAL4
55850      )
55851    );
55852  }
55853  function $selectionHasToggleListShortcut() {
55854    const selection = $getSelection12();
55855    if (!$isRangeSelection11(selection) || !selection.isCollapsed()) return false;
55856    const anchorNode = selection.anchor.getNode();
55857    if (!$isTextNode9(anchorNode)) return false;
55858    const textBeforeCursor = anchorNode.getTextContent().slice(0, selection.anchor.offset);
55859    return /(?:^|\n)>\s?$/.test(textBeforeCursor);
55860  }
55861  function $exitToggleListFromEmptyParagraph() {
55862    const selection = $getSelection12();
55863    if (!$isRangeSelection11(selection) || !selection.isCollapsed()) return false;
55864    const anchorNode = selection.anchor.getNode();
55865    const paragraph = $isParagraphNode8(anchorNode) ? anchorNode : $findMatchingParent3(anchorNode, $isParagraphNode8);
55866    if (!$isParagraphNode8(paragraph) || paragraph.getTextContent() !== "") return false;
55867    const toggleList = $findMatchingParent3(paragraph, $isToggleListNode);
55868    if (!$isToggleListNode(toggleList)) return false;
55869    if (toggleList.getFirstChild()?.is(paragraph)) return false;
55870    const nextParagraph = $createParagraphNode8();
55871    toggleList.insertAfter(nextParagraph);
55872    paragraph.remove();
55873    if (toggleList.getChildrenSize() === 0) toggleList.remove();
55874    nextParagraph.select();
55875    return true;
55876  }
55877  function $toggleTitleOpenState() {
55878    const selection = $getSelection12();
55879    if (!$isRangeSelection11(selection) || !selection.isCollapsed()) return false;
55880    const context = $toggleTitleContext(selection);
55881    if (!context) return false;
55882    context.toggleList.toggleOpen();
55883    return true;
55884  }
55885  function $insertToggleListAfterCollapsedTitle() {
55886    const selection = $getSelection12();
55887    if (!$isRangeSelection11(selection) || !selection.isCollapsed()) return false;
55888    const context = $toggleTitleContext(selection);
55889    if (!context || context.toggleList.getOpen()) return false;
55890    if (context.title.getTextContent() === "") {
55891      const paragraph = $createParagraphNode8();
55892      context.toggleList.replace(paragraph);
55893      paragraph.selectStart();
55894      return true;
55895    }
55896    if (!$isSelectionAtBlockEnd2(selection, context.title)) return false;
55897    const nextToggleList = $createToggleListNode(false);
55898    const nextTitle = $createParagraphNode8();
55899    nextToggleList.append(nextTitle);
55900    context.toggleList.insertAfter(nextToggleList);
55901    nextTitle.selectStart();
55902    return true;
55903  }
55904  function $isSelectionAtBlockEnd2(selection, block) {
55905    const anchor = selection.anchor;
55906    const anchorNode = anchor.getNode();
55907    if (anchor.type === "element" && anchorNode.is(block)) {
55908      return anchor.offset === block.getChildrenSize();
55909    }
55910    if (!$isTextNode9(anchorNode)) return false;
55911    const lastDescendant = block.getLastDescendant();
55912    return anchorNode.is(lastDescendant) && anchor.offset === anchorNode.getTextContentSize();
55913  }
55914
55915  
55915// app/javascript/src/lexxy/slash_commands_extension.js
55916  var {
55917    COMMAND_PRIORITY_CRITICAL: COMMAND_PRIORITY_CRITICAL5,
55918    INPUT_COMMAND: INPUT_COMMAND5,
55919    KEY_ARROW_DOWN_COMMAND: KEY_ARROW_DOWN_COMMAND5,
55920    KEY_ARROW_UP_COMMAND: KEY_ARROW_UP_COMMAND4,
55921    KEY_ENTER_COMMAND: KEY_ENTER_COMMAND7,
55922    KEY_ESCAPE_COMMAND: KEY_ESCAPE_COMMAND4,
55923    KEY_SPACE_COMMAND: KEY_SPACE_COMMAND5,
55924    KEY_TAB_COMMAND: KEY_TAB_COMMAND5,
55925    $createNodeSelection: $createNodeSelection4,
55926    $findMatchingParent: $findMatchingParent9,
55927    $getSelection: $getSelection13,
55928    $isRangeSelection: $isRangeSelection12,
55929    $isTextNode: $isTextNode10,
55930    $setSelection: $setSelection4
55931  } = Lexical_exports;
55932  var SLASH_COMMANDS = [
55933    {
55934      id: "text",
55935      label: "Text",
55936      description: "Plain paragraph",
55937      icon: LEXXY_TOOLBAR_ICONS.text,
55938      shortcut: "",
55939      keywords: "text paragraph plain",
55940      run: ({ contents, editor }) => {
55941        if ($routeToggleTitleCommand("paragraph", { editor })) return;
55942        contents.applyParagraphFormat();
55943      }
55944    },
55945    {
55946      id: "h1",
55947      label: "Heading 1",
55948      description: "Large page heading",
55949      icon: LEXXY_TOOLBAR_ICONS.heading1,
55950      shortcut: "#",
55951      keywords: "heading h1 title",
55952      run: ({ contents, editor }) => {
55953        if ($routeToggleTitleCommand("h1", { editor })) return;
55954        contents.applyHeadingFormat("h1");
55955      }
55956    },
55957    {
55958      id: "h2",
55959      label: "Heading 2",
55960      description: "Large section heading",
55961      icon: LEXXY_TOOLBAR_ICONS.heading2,
55962      shortcut: "##",
55963      keywords: "heading h2 title",
55964      run: ({ contents, editor }) => {
55965        if ($routeToggleTitleCommand("h2", { editor })) return;
55966        contents.applyHeadingFormat("h2");
55967      }
55968    },
55969    {
55970      id: "h3",
55971      label: "Heading 3",
55972      description: "Medium section heading",
55973      icon: LEXXY_TOOLBAR_ICONS.heading3,
55974      shortcut: "###",
55975      keywords: "heading h3 subtitle",
55976      run: ({ contents, editor }) => {
55977        if ($routeToggleTitleCommand("h3", { editor })) return;
55978        contents.applyHeadingFormat("h3");
55979      }
55980    },
55981    {
55982      id: "h4",
55983      label: "Heading 4",
55984      description: "Small section heading",
55985      icon: LEXXY_TOOLBAR_ICONS.heading4,
55986      shortcut: "####",
55987      keywords: "heading h4",
55988      run: ({ contents, editor }) => {
55989        if ($routeToggleTitleCommand("h4", { editor })) return;
55990        contents.applyHeadingFormat("h4");
55991      }
55992    },
55993    {
55994      id: "bullet",
55995      label: "Bullet list",
55996      description: "Unordered list",
55997      icon: LEXXY_TOOLBAR_ICONS.bulletList,
55998      shortcut: "-",
55999      keywords: "bullet unordered list ul",
56000      run: ({ contents, editor }) => {
56001        if ($routeToggleTitleCommand("bullet", { editor })) return;
56002        contents.applyUnorderedListFormat();
56003      }
56004    },
56005    {
56006      id: "number",
56007      label: "Numbered list",
56008      description: "Ordered list",
56009      icon: LEXXY_TOOLBAR_ICONS.numberList,
56010      shortcut: "1.",
56011      keywords: "numbered ordered list ol num",
56012      run: ({ contents, editor }) => {
56013        if ($routeToggleTitleCommand("number", { editor })) return;
56014        contents.applyOrderedListFormat();
56015      }
56016    },
56017    {
56018      id: "checklist",
56019      label: "Checklist",
56020      description: "Task list with checkboxes",
56021      icon: LEXXY_TOOLBAR_ICONS.checklist,
56022      shortcut: "[]",
56023      keywords: "checklist todo task checkbox",
56024      run: ({ editor }) => {
56025        if ($routeToggleTitleCommand("check", { editor })) return;
56026        editor.dispatchCommand(INSERT_CHECK_LIST_COMMAND2, void 0);
56027      }
56028    },
56029    {
56030      id: "toggle-list",
56031      label: "Toggle list",
56032      description: "Collapsible section",
56033      icon: LEXXY_TOOLBAR_ICONS.toggleList,
56034      shortcut: ">",
56035      keywords: "toggle list collapsible disclosure details fold",
56036      run: ({ editor }) => {
56037        if ($routeToggleTitleCommand("toggle", { editor })) return;
56038        $insertToggleList();
56039      }
56040    },
56041    {
56042      id: "quote",
56043      label: "Quote",
56044      description: "Block quote",
56045      icon: LEXXY_TOOLBAR_ICONS.quote,
56046      shortcut: '"',
56047      keywords: "quote blockquote",
56048      run: ({ contents, editor }) => {
56049        if ($routeToggleTitleCommand("quote", { editor })) return;
56050        contents.toggleBlockquote();
56051      }
56052    },
56053    {
56054      id: "callout",
56055      label: "Callout",
56056      description: "Tip or callout block",
56057      icon: LEXXY_TOOLBAR_ICONS.callout,
56058      shortcut: "",
56059      keywords: "callout tip note info warning",
56060      run: ({ editor }) => {
56061        if ($routeToggleTitleCommand("callout", { editor })) return;
56062        $insertCallout();
56063      }
56064    },
56065    {
56066      id: "code",
56067      label: "Code",
56068      description: "Code block",
56069      icon: LEXXY_TOOLBAR_ICONS.code,
56070      shortcut: "```",
56071      keywords: "code snippet pre",
56072      run: ({ contents, editor }) => {
56073        if ($routeToggleTitleCommand("code", { editor })) return;
56074        contents.toggleCodeBlock();
56075      }
56076    },
56077    {
56078      id: "divider",
56079      label: "Divider",
56080      description: "Horizontal divider",
56081      icon: LEXXY_TOOLBAR_ICONS.separator,
56082      shortcut: "---",
56083      keywords: "divider hr line separator",
56084      run: ({ contents, editor }) => {
56085        if ($routeToggleTitleCommand("divider", { editor })) return;
56086        $insertDividerAndSelect(contents);
56087      }
56088    },
56089    {
56090      id: "table",
56091      label: "Table",
56092      description: "Insert a table",
56093      icon: LEXXY_TOOLBAR_ICONS.table,
56094      shortcut: "",
56095      keywords: "table grid",
56096      run: ({ editor }) => {
56097        if ($routeToggleTitleCommand("table", { editor })) return;
56098        $insertTableAndFocusFirstCell(editor);
56099      }
56100    },
56101    {
56102      id: "image",
56103      label: "Media (image or video)",
56104      description: "Upload an image or video file",
56105      icon: LEXXY_TOOLBAR_ICONS.image,
56106      shortcut: "",
56107      keywords: "image photo video upload",
56108      run: ({ contents, editorElement }) => $triggerFileUpload({ contents, editorElement, accept: "image/*,video/*" })
56109    },
56110    {
56111      id: "audio",
56112      label: "Audio",
56113      description: "Upload an audio file",
56114      icon: LEXXY_TOOLBAR_ICONS.audio,
56115      shortcut: "",
56116      keywords: "audio sound music mp3 wav upload",
56117      run: ({ contents, editorElement }) => $triggerFileUpload({ contents, editorElement, accept: "audio/*" })
56118    },
56119    {
56120      id: "pdf",
56121      label: "PDF",
56122      description: "Upload a PDF document",
56123      icon: LEXXY_TOOLBAR_ICONS.pdf,
56124      shortcut: "",
56125      keywords: "pdf document file upload",
56126      run: ({ contents, editorElement }) => $triggerFileUpload({ contents, editorElement, accept: "application/pdf,.pdf" })
56127    },
56128    {
56129      id: "attachment",
56130      label: "Attachment",
56131      description: "Upload a file",
56132      icon: LEXXY_TOOLBAR_ICONS.attachment,
56133      shortcut: "",
56134      keywords: "attachment attachement file upload document",
56135      run: ({ editorElement }) => editorElement.querySelector('[name="file"]')?.click()
56136    }
56137  ];
56138  function $triggerFileUpload({ contents, editorElement, accept }) {
56139    const input = document.createElement("input");
56140    input.type = "file";
56141    input.multiple = true;
56142    input.accept = accept;
56143    input.style.display = "none";
56144    input.addEventListener("change", () => {
56145      if (input.files?.length) contents.uploadFiles(input.files, { selectLast: true });
56146    });
56147    editorElement.appendChild(input);
56148    input.click();
56149    setTimeout(() => input.remove(), 1e3);
56150  }
56151  function $insertDividerAndSelect(contents) {
56152    const divider = new HorizontalDividerNode();
56153    contents.insertAtCursor(divider);
56154    const selection = $createNodeSelection4();
56155    selection.add(divider.getKey());
56156    $setSelection4(selection);
56157  }
56158  function $insertTableAndFocusFirstCell(editor) {
56159    editor.dispatchCommand(INSERT_TABLE_COMMAND2, { rows: 3, columns: 3, includeHeaders: true });
56160    const selection = $getSelection13();
56161    if (!$isRangeSelection12(selection)) return;
56162    const table = $findMatchingParent9(selection.anchor.getNode(), (node) => node instanceof TableNode2);
56163    $selectFirstTableCell2(table);
56164  }
56165  function $selectFirstTableCell2(table) {
56166    const firstCell = table?.getFirstChild()?.getFirstChild();
56167    const firstCellContent = firstCell?.getFirstChild();
56168    if (firstCellContent?.selectStart) {
56169      firstCellContent.selectStart();
56170    } else {
56171      firstCell?.selectStart?.();
56172    }
56173  }
56174  function shouldDismissSlashQuery(query) {
56175    if (!query) return false;
56176    if (/^\s/.test(query)) return true;
56177    if (/\s{2,}/.test(query)) return true;
56178    return !query.trim();
56179  }
56180  function matchCommands(query) {
56181    const normalized = query.trim().toLowerCase();
56182    if (!normalized) return SLASH_COMMANDS;
56183    const tokens = normalized.split(/\s+/).filter(Boolean);
56184    return SLASH_COMMANDS.filter((command) => {
56185      const haystack = `${command.label} ${command.description} ${command.shortcut} ${command.keywords}`.toLowerCase();
56186      const words = haystack.split(/\s+/);
56187      return tokens.every((token) => {
56188        if (haystack.includes(token)) return true;
56189        return words.some((word) => word.startsWith(token));
56190      });
56191    });
56192  }
56193  var SlashCommandsExtension = class extends LexxyExtension {
56194    #popover = null;
56195    #popoverListeners = [];
56196    #triggerListener = null;
56197    #open = false;
56198    #selectedIndex = 0;
56199    #closeMenuFocused = false;
56200    #showId = 0;
56201    #unlockScroll = null;
56202    #activeTrigger = null;
56203    #dismissedTrigger = null;
56204    #slashJustTyped = false;
56205    #noResultsCharacterCount = 0;
56206    #lastNoResultsQuery = null;
56207    #isOptionsScrolling = false;
56208    #optionsScrollEndTimer = null;
56209    #lastPointerPosition = null;
56210    #isUserOptionsScroll = false;
56211    get enabled() {
56212      return this.editorElement.supportsRichText && supportsDesktopPrompts();
56213    }
56214    initializeToolbar(_toolbar) {
56215      this.#attachTriggerListener();
56216    }
56217    dispose() {
56218      this.editorElement.removeAttribute("data-lexxy-slash-menu-open");
56219      this.#disposePopoverListeners();
56220      this.#unlockPopoverScroll();
56221      this.#triggerListener?.();
56222      this.#popover?.remove();
56223      this.#popover = null;
56224    }
56225    #attachTriggerListener() {
56226      const editor = this.editorElement.editor;
56227      if (!editor) return;
56228      const markSlashTyped = (event) => {
56229        if (event.inputType?.startsWith("insert") && event.data === "/") {
56230          this.#slashJustTyped = true;
56231        }
56232      };
56233      this.editorElement.addEventListener("beforeinput", markSlashTyped, true);
56234      const disposeInputListener = editor.registerCommand(
56235        INPUT_COMMAND5,
56236        (event) => {
56237          if (event.inputType?.startsWith("insert") && event.data === "/") {
56238            this.#slashJustTyped = true;
56239          }
56240          return false;
56241        },
56242        COMMAND_PRIORITY_CRITICAL5
56243      );
56244      const disposeUpdateListener = editor.registerUpdateListener(({ editorState }) => {
56245        if (this.#open) return;
56246        editorState.read(() => {
56247          if (!this.#slashJustTyped) return;
56248          this.#slashJustTyped = false;
56249          this.#dismissedTrigger = null;
56250          this.#showPopoverForSlashQuery();
56251        });
56252      });
56253      this.#triggerListener = () => {
56254        this.editorElement.removeEventListener("beforeinput", markSlashTyped, true);
56255        disposeInputListener();
56256        disposeUpdateListener();
56257      };
56258    }
56259    #showPopoverForSlashQuery() {
56260      if (this.#open || this.editorElement.selection?.isInsideCodeBlock) return;
56261      const trigger = this.#readTriggerContext();
56262      if (!trigger) return;
56263      if (this.#isDismissedTrigger(trigger)) return;
56264      this.#activeTrigger = trigger;
56265      this.#showPopover(trigger.query);
56266    }
56267    #readTriggerContext() {
56268      const selection = $getSelection13();
56269      if (!$isRangeSelection12(selection) || !selection.isCollapsed()) return null;
56270      const anchorNode = selection.anchor.getNode();
56271      if (!$isTextNode10(anchorNode)) return null;
56272      const offset3 = selection.anchor.offset;
56273      const textBeforeCursor = anchorNode.getTextContent().slice(0, offset3);
56274      const lastSlash = textBeforeCursor.lastIndexOf("/");
56275      if (lastSlash === -1) return null;
56276      const charBeforeSlash = lastSlash > 0 ? textBeforeCursor[lastSlash - 1] : "";
56277      if (charBeforeSlash && !/[\s\n]/.test(charBeforeSlash)) return null;
56278      const query = textBeforeCursor.slice(lastSlash + 1);
56279      if (shouldDismissSlashQuery(query)) return null;
56280      return {
56281        key: anchorNode.getKey(),
56282        offset: lastSlash,
56283        query
56284      };
56285    }
56286    #isDismissedTrigger(trigger) {
56287      return this.#dismissedTrigger?.key === trigger.key && this.#dismissedTrigger?.offset === trigger.offset;
56288    }
56289    async #showPopover(query) {
56290      const showId = ++this.#showId;
56291      this.#open = true;
56292      this.editorElement.setAttribute("data-lexxy-slash-menu-open", "");
56293      this.#resetNoResultsCounter();
56294      this.#popover ??= this.#buildPopover();
56295      if (this.#showId !== showId) return;
56296      this.#renderOptions(query);
56297      if (this.#showId !== showId) return;
56298      this.#selectedIndex = 0;
56299      this.#closeMenuFocused = false;
56300      this.#setKeyboardNavigation(true);
56301      this.#highlightSelection();
56302      this.#positionPopover();
56303      this.#popover.classList.add("lexxy-prompt-menu--visible");
56304      this.#unlockScroll ??= lockPopoverScroll();
56305      this.#registerPopoverListeners();
56306    }
56307    #buildPopover() {
56308      const popover = document.createElement("div");
56309      popover.className = "lexxy-prompt-menu lexxy-prompt-menu--portaled lexxy-slash-menu lexxy-slash-menu--portaled ph-no-autocapture";
56310      popover.hidden = true;
56311      popover.setAttribute("data-ph-no-autocapture", "");
56312      popover.innerHTML = `
56313      <div class="lexxy-slash-menu__options" data-slash-menu-options role="listbox"></div>
56314      <div class="lexxy-slash-menu__footer">
56315        <button type="button" class="lexxy-slash-menu__close" data-slash-menu-close>
56316          <span class="lexxy-slash-menu__close-label">Close menu</span>
56317          <kbd class="lexxy-slash-menu__shortcut">esc</kbd>
56318        </button>
56319      </div>
56320    `;
56321      const options = popover.querySelector("[data-slash-menu-options]");
56322      options?.addEventListener("wheel", (event) => {
56323        this.#trackPointerPosition(event);
56324        this.#isUserOptionsScroll = true;
56325      });
56326      options?.addEventListener("scroll", () => this.#handleOptionsScroll());
56327      popover.querySelector("[data-slash-menu-close]")?.addEventListener("click", () => this.#hidePopover());
56328      popover.querySelector("[data-slash-menu-close]")?.addEventListener("pointermove", (event) => {
56329        this.#trackPointerPosition(event);
56330        if (this.#isOptionsScrolling) return;
56331        this.#setKeyboardNavigation(false);
56332        this.#highlightCloseMenu();
56333      });
56334      document.body.appendChild(popover);
56335      return popover;
56336    }
56337    #optionsList() {
56338      return this.#popover?.querySelector("[data-slash-menu-options]");
56339    }
56340    #renderOptions(query) {
56341      const matches = matchCommands(query);
56342      const options = this.#optionsList();
56343      if (!options) return;
56344      if (matches.length === 0) {
56345        options.innerHTML = "";
56346        options.hidden = true;
56347        this.#clearOptionsOverflow();
56348        this.#trackNoResultsQuery(query);
56349      } else {
56350        options.hidden = false;
56351        options.innerHTML = matches.map(
56352          (command) => `
56353      <div class="lexxy-prompt-menu__item lexxy-slash-menu__item" role="option" data-command-id="${command.id}">
56354        <span class="lexxy-slash-menu__icon" aria-hidden="true">${command.icon}</span>
56355        <span class="lexxy-slash-menu__content">
56356          <span class="lexxy-slash-menu__label">${command.label}</span>
56357          <span class="lexxy-slash-menu__description">${command.description}</span>
56358        </span>
56359        <span class="lexxy-slash-menu__shortcut" aria-hidden="true">${command.shortcut || ""}</span>
56360      </div>
56361    `
56362        ).join("");
56363        this.#resetNoResultsCounter();
56364      }
56365      this.#popover.dataset.matches = String(matches.length);
56366      options.querySelectorAll("[data-command-id]").forEach((item, index) => {
56367        item.addEventListener("pointermove", (event) => {
56368          this.#trackPointerPosition(event);
56369          if (this.#isOptionsScrolling) return;
56370          this.#setKeyboardNavigation(false);
56371          this.#closeMenuFocused = false;
56372          this.#selectedIndex = index;
56373          this.#highlightSelection({ scroll: false });
56374        });
56375        item.addEventListener("click", () => {
56376          this.#selectedIndex = index;
56377          this.#executeSelected();
56378        });
56379      });
56380      requestAnimationFrame(() => this.#updateOptionsOverflow());
56381    }
56382    #trackNoResultsQuery(query) {
56383      if (this.#lastNoResultsQuery === null) {
56384        this.#lastNoResultsQuery = query;
56385        this.#noResultsCharacterCount = 0;
56386        return;
56387      }
56388      if (query === this.#lastNoResultsQuery) return;
56389      if (query.length > this.#lastNoResultsQuery.length) {
56390        this.#noResultsCharacterCount += query.length - this.#lastNoResultsQuery.length;
56391      }
56392      this.#lastNoResultsQuery = query;
56393      if (this.#noResultsCharacterCount > 4) {
56394        requestAnimationFrame(() => this.#hidePopover());
56395      }
56396    }
56397    #resetNoResultsCounter() {
56398      this.#noResultsCharacterCount = 0;
56399      this.#lastNoResultsQuery = null;
56400    }
56401    #registerPopoverListeners() {
56402      this.#disposePopoverListeners();
56403      const editor = this.editorElement.editor;
56404      const register = (command, handler) => {
56405        this.#popoverListeners.push(editor.registerCommand(command, handler, COMMAND_PRIORITY_CRITICAL5));
56406      };
56407      register(KEY_ARROW_DOWN_COMMAND5, (event) => {
56408        event.preventDefault();
56409        this.#moveSelection(1);
56410        return true;
56411      });
56412      register(KEY_ARROW_UP_COMMAND4, (event) => {
56413        event.preventDefault();
56414        this.#moveSelection(-1);
56415        return true;
56416      });
56417      register(KEY_ENTER_COMMAND7, (event) => {
56418        event.preventDefault();
56419        if (this.#closeMenuFocused) {
56420          this.#hidePopover();
56421        } else {
56422          this.#executeSelected();
56423        }
56424        return true;
56425      });
56426      register(KEY_TAB_COMMAND5, (event) => {
56427        event.preventDefault();
56428        if (this.#closeMenuFocused) {
56429          this.#hidePopover();
56430        } else {
56431          this.#executeSelected();
56432        }
56433        return true;
56434      });
56435      register(KEY_SPACE_COMMAND5, (event) => {
56436        const query = this.editorElement.contents.textBackUntil("/");
56437        const command = this.#commandForSpaceShortcut(query);
56438        if (command) {
56439          event.preventDefault();
56440          this.#executeCommand(command);
56441          return true;
56442        }
56443        if (this.#shouldDismissOnSpace(query)) {
56444          this.#hidePopover();
56445        }
56446        return false;
56447      });
56448      register(KEY_ESCAPE_COMMAND4, () => {
56449        this.#hidePopover();
56450        return true;
56451      });
56452      register(INPUT_COMMAND5, (event) => {
56453        if (event.inputType !== "insertText" || event.data !== " ") return false;
56454        const query = this.editorElement.contents.textBackUntil("/");
56455        const command = this.#commandForSpaceShortcut(query);
56456        if (command) {
56457          event.preventDefault();
56458          this.#executeCommand(command);
56459          return true;
56460        }
56461        if (this.#shouldDismissOnSpace(query)) {
56462          this.#hidePopover();
56463        }
56464        return false;
56465      });
56466      const filterListener = editor.registerUpdateListener(({ editorState }) => {
56467        editorState.read(() => {
56468          const trigger = this.#readTriggerContext();
56469          if (!trigger) {
56470            this.#hidePopover();
56471            return;
56472          }
56473          this.#activeTrigger = trigger;
56474          this.#renderOptions(trigger.query);
56475          this.#selectedIndex = 0;
56476          this.#closeMenuFocused = false;
56477          this.#setKeyboardNavigation(true);
56478          this.#highlightSelection();
56479          requestAnimationFrame(() => this.#positionPopover());
56480        });
56481      });
56482      this.#popoverListeners.push(filterListener);
56483      this.#popoverListeners.push(this.#bindViewportRepositioning());
56484    }
56485    #bindViewportRepositioning() {
56486      let frame = null;
56487      const reposition = () => {
56488        if (frame) cancelAnimationFrame(frame);
56489        frame = requestAnimationFrame(() => {
56490          frame = null;
56491          if (this.#open) this.#positionPopover();
56492        });
56493      };
56494      window.addEventListener("scroll", reposition, true);
56495      window.addEventListener("resize", reposition);
56496      const editorContent = this.editorElement.editorContentElement;
56497      const resizeObserver = new ResizeObserver(reposition);
56498      if (editorContent) resizeObserver.observe(editorContent);
56499      if (this.#popover) resizeObserver.observe(this.#popover);
56500      const onImageLoad = (event) => {
56501        if (event.target?.tagName === "IMG") reposition();
56502      };
56503      this.editorElement.addEventListener("load", onImageLoad, true);
56504      return () => {
56505        if (frame) cancelAnimationFrame(frame);
56506        window.removeEventListener("scroll", reposition, true);
56507        window.removeEventListener("resize", reposition);
56508        resizeObserver.disconnect();
56509        this.editorElement.removeEventListener("load", onImageLoad, true);
56510      };
56511    }
56512    #disposePopoverListeners() {
56513      this.#clearOptionsScrollEndTimer();
56514      this.#isOptionsScrolling = false;
56515      this.#isUserOptionsScroll = false;
56516      this.#popoverListeners.forEach((dispose) => dispose());
56517      this.#popoverListeners = [];
56518    }
56519    #unlockPopoverScroll() {
56520      this.#unlockScroll?.();
56521      this.#unlockScroll = null;
56522    }
56523    #listItems() {
56524      return Array.from(this.#popover?.querySelectorAll("[data-command-id]") || []);
56525    }
56526    #closeButton() {
56527      return this.#popover?.querySelector("[data-slash-menu-close]");
56528    }
56529    #moveSelection(delta) {
56530      const items = this.#listItems();
56531      if (!items.length) {
56532        this.#highlightCloseMenu();
56533        return;
56534      }
56535      this.#setKeyboardNavigation(true);
56536      const count = items.length + 1;
56537      let position = this.#closeMenuFocused ? items.length : this.#selectedIndex;
56538      position = (position + delta + count) % count;
56539      if (position === items.length) {
56540        this.#highlightCloseMenu();
56541        return;
56542      }
56543      this.#selectedIndex = position;
56544      this.#highlightSelection();
56545    }
56546    #highlightCloseMenu() {
56547      this.#closeMenuFocused = true;
56548      this.#listItems().forEach((item) => item.removeAttribute("aria-selected"));
56549      this.#closeButton()?.setAttribute("aria-selected", "true");
56550      this.#setKeyboardNavigation(true);
56551    }
56552    #highlightSelection({ scroll = true } = {}) {
56553      const items = this.#listItems();
56554      if (!items.length) {
56555        this.#highlightCloseMenu();
56556        return;
56557      }
56558      this.#closeMenuFocused = false;
56559      this.#closeButton()?.removeAttribute("aria-selected");
56560      items.forEach((item, index) => {
56561        item.toggleAttribute("aria-selected", index === this.#selectedIndex);
56562      });
56563      if (scroll) this.#scrollToOption(items[this.#selectedIndex]);
56564    }
56565    #setKeyboardNavigation(active) {
56566      if (!this.#popover) return;
56567      this.#popover.toggleAttribute("data-keyboard-nav", active);
56568      if (active) this.#clearStuckHover();
56569    }
56570    #clearStuckHover() {
56571      if (!this.#popover) return;
56572      this.#popover.style.pointerEvents = "none";
56573      requestAnimationFrame(() => {
56574        if (this.#popover) this.#popover.style.pointerEvents = "";
56575      });
56576    }
56577    #trackPointerPosition(event) {
56578      this.#lastPointerPosition = { x: event.clientX, y: event.clientY };
56579    }
56580    #handleOptionsScroll() {
56581      this.#updateOptionsOverflow();
56582      if (!this.#isUserOptionsScroll) return;
56583      if (!this.#isOptionsScrolling) {
56584        this.#isOptionsScrolling = true;
56585        this.#setKeyboardNavigation(true);
56586      }
56587      this.#clearOptionsScrollEndTimer();
56588      this.#optionsScrollEndTimer = setTimeout(() => {
56589        this.#isOptionsScrolling = false;
56590        this.#isUserOptionsScroll = false;
56591        this.#optionsScrollEndTimer = null;
56592        this.#selectOptionAtPointer();
56593      }, 120);
56594    }
56595    #clearOptionsScrollEndTimer() {
56596      if (!this.#optionsScrollEndTimer) return;
56597      clearTimeout(this.#optionsScrollEndTimer);
56598      this.#optionsScrollEndTimer = null;
56599    }
56600    #selectOptionAtPointer() {
56601      if (!this.#open || !this.#lastPointerPosition) return;
56602      const { x: x3, y: y3 } = this.#lastPointerPosition;
56603      const element = document.elementFromPoint(x3, y3);
56604      if (!element || !this.#popover?.contains(element)) return;
56605      const closeButton = element.closest("[data-slash-menu-close]");
56606      if (closeButton) {
56607        this.#setKeyboardNavigation(false);
56608        this.#highlightCloseMenu();
56609        return;
56610      }
56611      const item = element.closest("[data-command-id]");
56612      if (!item) return;
56613      const index = this.#listItems().indexOf(item);
56614      if (index === -1) return;
56615      this.#setKeyboardNavigation(false);
56616      this.#closeMenuFocused = false;
56617      this.#selectedIndex = index;
56618      this.#highlightSelection({ scroll: false });
56619    }
56620    #scrollToOption(optionEl) {
56621      const content = this.#optionsList();
56622      if (!optionEl || !content) return;
56623      const contentRect = content.getBoundingClientRect();
56624      const optionRect = optionEl.getBoundingClientRect();
56625      const optionRelativeTop = optionRect.top - contentRect.top;
56626      const optionRelativeBottom = optionRelativeTop + optionRect.height;
56627      const contentScrollTop = content.scrollTop;
56628      const contentHeight = contentRect.height;
56629      const scrollPadding = optionRect.height + 6;
56630      if (optionRelativeBottom > contentHeight - scrollPadding) {
56631        content.scrollTop = contentScrollTop + (optionRelativeBottom - contentHeight + scrollPadding);
56632      } else if (optionRelativeTop < scrollPadding) {
56633        content.scrollTop = contentScrollTop + (optionRelativeTop - scrollPadding);
56634      }
56635      this.#updateOptionsOverflow();
56636    }
56637    #updateOptionsOverflow() {
56638      const options = this.#optionsList();
56639      if (!options || options.hidden) return;
56640      const maxScrollTop = Math.max(0, options.scrollHeight - options.clientHeight);
56641      const hasOverflowAtStart = options.scrollTop > 1;
56642      const hasOverflowAtEnd = options.scrollTop < maxScrollTop - 1;
56643      options.toggleAttribute("data-overflow-y-start", hasOverflowAtStart);
56644      options.toggleAttribute("data-overflow-y-end", hasOverflowAtEnd);
56645      this.#popover?.toggleAttribute("data-overflow-y-start", hasOverflowAtStart);
56646      this.#popover?.toggleAttribute("data-overflow-y-end", hasOverflowAtEnd);
56647    }
56648    #clearOptionsOverflow() {
56649      const options = this.#optionsList();
56650      options?.removeAttribute("data-overflow-y-start");
56651      options?.removeAttribute("data-overflow-y-end");
56652      this.#popover?.removeAttribute("data-overflow-y-start");
56653      this.#popover?.removeAttribute("data-overflow-y-end");
56654    }
56655    #shouldDismissOnSpace(query) {
56656      return shouldDismissSlashQuery(query) || shouldDismissSlashQuery(`${query} `);
56657    }
56658    #commandForSpaceShortcut(query = this.editorElement.contents.textBackUntil("/")) {
56659      if (!query || /\s/.test(query)) return null;
56660      const normalized = query.trim().toLowerCase();
56661      if (!normalized) return null;
56662      return SLASH_COMMANDS.find((command) => this.#shortcutTermsFor(command).includes(normalized)) || null;
56663    }
56664    #shortcutTermsFor(command) {
56665      return [command.shortcut].map((term) =>
56665 term.trim().toLowerCase()).filter(Boolean);
56666    }
56667    #selectedCommand() {
56668      const item = this.#listItems()[this.#selectedIndex];
56669      if (!item) return null;
56670      return SLASH_COMMANDS.find((entry) => entry.id === item.dataset.commandId) || null;
56671    }
56672    #executeSelected() {
56673      const command = this.#selectedCommand();
56674      if (!command) {
56675        this.#hidePopover();
56676        return;
56677      }
56678      this.#executeCommand(command);
56679    }
56680    #executeCommand(command) {
56681      const editor = this.editorElement.editor;
56682      const contents = this.editorElement.contents;
56683      editor.update(() => {
56684        this.#removeSlashTriggerText();
56685        command.run({ editor, contents, editorElement: this.editorElement });
56686      });
56687      this.#hidePopover();
56688      editor.focus();
56689    }
56690    #removeSlashTriggerText() {
56691      const selection = $getSelection13();
56692      if (!$isRangeSelection12(selection) || !selection.isCollapsed()) return;
56693      const anchorNode = selection.anchor.getNode();
56694      if (!$isTextNode10(anchorNode)) return;
56695      const offset3 = selection.anchor.offset;
56696      const textBeforeCursor = anchorNode.getTextContent().slice(0, offset3);
56697      const slashIndex = textBeforeCursor.lastIndexOf("/");
56698      if (slashIndex === -1) return;
56699      anchorNode.spliceText(slashIndex, offset3 - slashIndex, "", true);
56700    }
56701    #hidePopover() {
56702      this.#showId++;
56703      this.#open = false;
56704      this.editorElement.removeAttribute("data-lexxy-slash-menu-open");
56705      if (this.#activeTrigger) {
56706        this.#dismissedTrigger = {
56707          key: this.#activeTrigger.key,
56708          offset: this.#activeTrigger.offset
56709        };
56710      }
56711      this.#activeTrigger = null;
56712      this.#closeMenuFocused = false;
56713      this.#resetNoResultsCounter();
56714      this.#disposePopoverListeners();
56715      this.#unlockPopoverScroll();
56716      this.#popover?.classList.remove("lexxy-prompt-menu--visible");
56717      this.#popover?.removeAttribute("data-anchored");
56718      this.#popover?.removeAttribute("data-keyboard-nav");
56719      if (this.#popover) this.#popover.hidden = true;
56720      this.#closeButton()?.removeAttribute("aria-selected");
56721    }
56722    #positionPopover() {
56723      if (!this.#popover || !this.#open) return;
56724      const anchorRect = this.#triggerAnchorRect();
56725      if (!anchorRect) return;
56726      const x3 = anchorRect.left;
56727      const y3 = anchorRect.bottom;
56728      this.#popover.hidden = false;
56729      this.#popover.style.setProperty("--lexxy-prompt-offset-x", `${x3}px`);
56730      this.#popover.style.setProperty("--lexxy-prompt-offset-y", `${y3}px`);
56731      this.#popover.removeAttribute("data-clipped-at-right");
56732      this.#popover.removeAttribute("data-clipped-at-bottom");
56733      this.#popover.toggleAttribute("data-anchored", true);
56734      const popoverRect = this.#popover.getBoundingClientRect();
56735      if (popoverRect.right > window.innerWidth) {
56736        this.#popover.style.setProperty(
56737          "--lexxy-prompt-offset-x",
56738          `${Math.max(8, window.innerWidth - popoverRect.width - 8)}px`
56739        );
56740      }
56741      if (popoverRect.bottom > window.innerHeight) {
56742        this.#popover.style.setProperty(
56743          "--lexxy-prompt-offset-y",
56744          `${Math.max(8, anchorRect.top - popoverRect.height - 6)}px`
56745        );
56746      }
56747      this.#updateOptionsOverflow();
56748    }
56749    #triggerAnchorRect(offset3 = this.#activeTrigger?.offset) {
56750      const trigger = this.#activeTrigger;
56751      if (!trigger || offset3 == null) return null;
56752      const textElement = this.editorElement.editor.getElementByKey(trigger.key);
56753      if (!textElement) return null;
56754      const position = this.#textNodePosition(textElement, offset3);
56755      if (!position) return null;
56756      const range2 = document.createRange();
56757      range2.setStart(position.node, position.offset);
56758      range2.collapse(true);
56759      const rect = range2.getClientRects()[0] || range2.getBoundingClientRect();
56760      range2.detach();
56761      return rect || null;
56762    }
56763    #textNodePosition(element, offset3) {
56764      const walker = document.createTreeWalker(element, NodeFilter.SHOW_TEXT);
56765      let remaining = offset3;
56766      let node = walker.nextNode();
56767      while (node) {
56768        const length = node.textContent.length;
56769        if (remaining <= length) return { node, offset: remaining };
56770        remaining -= length;
56771        node = walker.nextNode();
56772      }
56773      return null;
56774    }
56775  };
56776
56777  
56777// app/javascript/src/lexxy/typography_rules.js
56778  var RULES = [
56779    { pattern: /\.\.\./, replacement: "\u2026" },
56780    // Multi-character arrows / comparisons
56781    { pattern: /<=>/, replacement: "\u21D4" },
56782    { pattern: /<->/, replacement: "\u2194" },
56783    { pattern: /<--/, replacement: "\u2190" },
56784    { pattern: /-->/, replacement: "\u2192" },
56785    // Recover when a short rule already ran mid-sequence
56786    { pattern: /←=>/, replacement: "\u21D4" },
56787    { pattern: /←>/, replacement: "\u2194" },
56788    { pattern: /≤>/, replacement: "\u21D4" },
56789    { pattern: /—>/, replacement: "\u2192" },
56790    { pattern: /<—/, replacement: "\u2190" },
56791    { pattern: /≠=/, replacement: "\u2262" },
56792    // Short forms that can still grow: require a following char that isn't a
56793    // continuation (so "<->" / "<=>" / "-->" / "!==" can be typed fully).
56794    { pattern: /<=(?=[^>])/, replacement: "\u2264" },
56795    { pattern: />=/, replacement: "\u2265" },
56796    { pattern: /<-(?=[^-=])/, replacement: "\u2190" },
56797    { pattern: /->/, replacement: "\u2192" },
56798    { pattern: /--(?=[^>])/, replacement: "\u2014" },
56799    { pattern: /!==/, replacement: "\u2262" },
56800    { pattern: /!=(?=[^=])/, replacement: "\u2260" },
56801    { pattern: /\(c\)/i, replacement: "\xA9" },
56802    { pattern: /\(tm\)/i, replacement: "\u2122" },
56803    { pattern: /\(sm\)/i, replacement: "\u2120" },
56804    { pattern: /\(r\)/i, replacement: "\xAE" },
56805    { pattern: /(?:^|\s)(1\/2)(?=\s|$)/d, replacement: "\xBD", group: 1 },
56806    { pattern: /(?:^|\s)(1\/4)(?=\s|$)/d, replacement: "\xBC", group: 1 },
56807    { pattern: /(?:^|\s)(3\/4)(?=\s|$)/d, replacement: "\xBE", group: 1 },
56808    { pattern: /\+\/-/, replacement: "\xB1" },
56809    { pattern: /<</, replacement: "\xAB" },
56810    { pattern: />>/, replacement: "\xBB" },
56811    { pattern: /\^2/, replacement: "\xB2" },
56812    { pattern: /\^3/, replacement: "\xB3" },
56813    { pattern: /\d+\s?([*x])\s?\d+/id, replacement: "\xD7", group: 1 },
56814    {
56815      pattern: /(?:^|[\s{[(<'"\u2018\u201C])(")/d,
56816      replacement: "\u201C",
56817      group: 1
56818    },
56819    { pattern: /"/, replacement: "\u201D" },
56820    {
56821      pattern: /(?:^|[\s{[(<'"\u2018\u201C])(')/d,
56822      replacement: "\u2018",
56823      group: 1
56824    },
56825    { pattern: /'/, replacement: "\u2019" }
56826  ];
56827  function matchFromRule(text2, rule) {
56828    const match = rule.pattern.exec(text2);
56829    if (!match) return null;
56830    if (rule.group != null) {
56831      const indices = match.indices?.[rule.group];
56832      if (!indices) return null;
56833      return {
56834        start: indices[0],
56835        end: indices[1],
56836        replacement: rule.replacement
56837      };
56838    }
56839    return {
56840      start: match.index,
56841      end: match.index + match[0].length,
56842      replacement: rule.replacement
56843    };
56844  }
56845  function isBetterMatch(candidate, current) {
56846    if (!current) return true;
56847    if (candidate.start !== current.start) return candidate.start < current.start;
56848    return candidate.end > current.end;
56849  }
56850  function findTypographyMatch(text2) {
56851    if (!text2) return null;
56852    let best = null;
56853    for (const rule of RULES) {
56854      const candidate = matchFromRule(text2, rule);
56855      if (candidate && isBetterMatch(candidate, best)) {
56856        best = candidate;
56857      }
56858    }
56859    return best;
56860  }
56861
56862  
56862// app/javascript/src/lexxy/typography_extension.js
56863  var {
56864    $findMatchingParent: $findMatchingParent10,
56865    $getSelection: $getSelection14,
56866    $isRangeSelection: $isRangeSelection13,
56867    $isTextNode: $isTextNode11,
56868    TextNode: TextNode5
56869  } = Lexical_exports;
56870  function $shouldSkipTypography(node) {
56871    if (!$isTextNode11(node) || !node.isSimpleText() || node.isTextEntity()) return true;
56872    if (node.hasFormat("code")) return true;
56873    return $findMatchingParent10(node, $isCodeNode3) != null;
56874  }
56875  function $applyTypographyTransform(node) {
56876    if ($shouldSkipTypography(node)) return;
56877    const text2 = node.getTextContent();
56878    const match = findTypographyMatch(text2);
56879    if (!match) return;
56880    const nextText = text2.slice(0, match.start) + match.replacement + text2.slice(match.end);
56881    if (nextText === text2) return;
56882    const selection = $getSelection14();
56883    const hadFocus = $isRangeSelection13(selection) && selection.anchor.key === node.getKey();
56884    const anchorOffset = hadFocus ? selection.anchor.offset : null;
56885    node.setTextContent(nextText);
56886    if (hadFocus && anchorOffset != null) {
56887      const delta = match.replacement.length - (match.end - match.start);
56888      const nextOffset = anchorOffset <= match.start ? anchorOffset : anchorOffset >= match.end ? anchorOffset + delta : match.start + match.replacement.length;
56889      const latest = node.getLatest();
56890      const size2 = latest.getTextContentSize();
56891      latest.select(Math.max(0, Math.min(nextOffset, size2)));
56892    }
56893  }
56894  var TypographyExtension = class extends LexxyExtension {
56895    get enabled() {
56896      return this.editorElement.supportsRichText;
56897    }
56898    get lexicalExtension() {
56899      return this.defineExtension({
56900        name: "lexxy/typography",
56901        register: (editor) => editor.registerNodeTransform(TextNode5, $applyTypographyTransform)
56902      });
56903    }
56904  };
56905
56906  
56906// app/javascript/src/lexxy/caption_editor.js
56907  var CAPTION_SELECTOR = "[data-lexxy-caption-editor]";
56908  function isCaptionEditorEmpty(input) {
56909    return !input.textContent?.trim();
56910  }
56911  function placeCaptionEditorCaret(input) {
56912    const selection = window.getSelection();
56913    if (!selection || document.activeElement !== input) return;
56914    const range2 = document.createRange();
56915    range2.selectNodeContents(input);
56916    range2.collapse(true);
56917    selection.removeAllRanges();
56918    selection.addRange(range2);
56919  }
56920  function syncCaptionEditor(input, { placeCaret = false } = {}) {
56921    if (isCaptionEditorEmpty(input)) {
56922      input.dataset.captionEmpty = "true";
56923      if (document.activeElement === input && !input.querySelector("br")) {
56924        input.innerHTML = "<br>";
56925      }
56926    } else {
56927      delete input.dataset.captionEmpty;
56928    }
56929    if (placeCaret && isCaptionEditorEmpty(input)) {
56930      requestAnimationFrame(() => placeCaptionEditorCaret(input));
56931    }
56932  }
56933  function finalizeCaptionEditor(input) {
56934    if (isCaptionEditorEmpty(input)) {
56935      input.dataset.captionEmpty = "true";
56936      input.innerHTML = "";
56937    } else {
56938      delete input.dataset.captionEmpty;
56939    }
56940  }
56941  function handleCaptionEditorFocusIn(event) {
56942    const input = event.target.closest?.(CAPTION_SELECTOR);
56943    if (!input) return;
56944    syncCaptionEditor(input, { placeCaret: true });
56945  }
56946  function handleCaptionEditorFocusOut(event) {
56947    const input = event.target.closest?.(CAPTION_SELECTOR);
56948    if (!input) return;
56949    finalizeCaptionEditor(input);
56950  }
56951  function handleCaptionEditorInput(event) {
56952    const input = event.target.closest?.(CAPTION_SELECTOR);
56953    if (!input) return;
56954    syncCaptionEditor(input);
56955  }
56956  var installed = false;
56957  function installCaptionEditorSupport() {
56958    if (installed) return;
56959    installed = true;
56960    document.addEventListener("focusin", handleCaptionEditorFocusIn, true);
56961    document.addEventListener("focusout", handleCaptionEditorFocusOut, true);
56962    document.addEventListener("input", handleCaptionEditorInput, true);
56963  }
56964  function scheduleCaptionEditorSync(root = document) {
56965    root.querySelectorAll(CAPTION_SELECTOR).forEach((input) => syncCaptionEditor(input));
56966  }
56967
56968  
56968// app/javascript/src/lexxy/toggle_list_content.js
56969  var READONLY_TOGGLE_LIST_SELECTOR = ":is(.trix-content, .lexxy-content) .lexxy-toggle-list";
56970  var TOGGLE_LIST_BUTTON_CLASS2 = "lexxy-toggle-list__button";
56971  function readOnlyToggleLists(root = document) {
56972    return root.querySelectorAll(READONLY_TOGGLE_LIST_SELECTOR);
56973  }
56974  function isReadOnlyToggleList(toggleList) {
56975    return toggleList && !toggleList.closest("lexxy-editor");
56976  }
56977  function createReadOnlyToggleButton(toggleList) {
56978    const button = document.createElement("button");
56979    button.type = "button";
56980    button.className = TOGGLE_LIST_BUTTON_CLASS2;
56981    button.tabIndex = 0;
56982    button.setAttribute("aria-label", "Toggle list contents");
56983    button.innerHTML = `
56984    <svg aria-hidden="true" focusable="false" viewBox="0 0 12 12">
56985      <path d="M1.5 2.31061C1.5 0.943037 2.99801 0.103919 4.16406 0.818427L10.1855 4.50788C11.2997 5.19065 11.2997 6.80949 10.1855 7.49226L4.16406 11.1817C2.99802 11.8962 1.5 11.0571 1.5 9.68952V2.31061Z" fill="currentColor"></path>
56986    </svg>
56987  `;
56988    button.setAttribute("aria-expanded", toggleList.getAttribute("aria-expanded") || "true");
56989    return button;
56990  }
56991  function hydrateReadOnlyToggleList(toggleList) {
56992    if (!isReadOnlyToggleList(toggleList)) return;
56993    if (toggleList.querySelector(`.${TOGGLE_LIST_BUTTON_CLASS2}`)) return;
56994    toggleList.insertBefore(createReadOnlyToggleButton(toggleList), toggleList.firstChild);
56995  }
56996  function restoreReadOnlyToggleLists(root = document) {
56997    readOnlyToggleLists(root).forEach((toggleList) => {
56998      if (!isReadOnlyToggleList(toggleList)) return;
56999      toggleList.querySelector(`.${TOGGLE_LIST_BUTTON_CLASS2}`)?.remove();
57000    });
57001  }
57002  function syncToggleList(toggleList) {
57003    const open = toggleList.dataset.open !== "false";
57004    toggleList.dataset.open = open ? "true" : "false";
57005    toggleList.setAttribute("aria-expanded", open ? "true" : "false");
57006    toggleList.querySelector(`.${TOGGLE_LIST_BUTTON_CLASS2}`)?.setAttribute("aria-expanded", open ? "true" : "false");
57007  }
57008  function toggleReadOnlyToggleList(toggleList) {
57009    toggleList.dataset.open = toggleList.dataset.open === "false" ? "true" : "false";
57010    syncToggleList(toggleList);
57011  }
57012  function readOnlyToggleListForButton(target) {
57013    if (!(target instanceof Element)) return null;
57014    const button = target.closest(`.${TOGGLE_LIST_BUTTON_CLASS2}`);
57015    if (!button) return null;
57016    const toggleList = button.closest(READONLY_TOGGLE_LIST_SELECTOR);
57017    return isReadOnlyToggleList(toggleList) ? toggleList : null;
57018  }
57019  function handleReadOnlyToggleListClick(event) {
57020    const toggleList = readOnlyToggleListForButton(event.target);
57021    if (!toggleList) return;
57022    event.preventDefault();
57023    toggleReadOnlyToggleList(toggleList);
57024  }
57025  function handleReadOnlyToggleListKeydown(event) {
57026    if (event.key !== " " && event.key !== "Enter") return;
57027    const toggleList = readOnlyToggleListForButton(event.target);
57028    if (!toggleList) return;
57029    event.preventDefault();
57030    toggleReadOnlyToggleList(toggleList);
57031  }
57032  function prepareReadOnlyToggleLists(root = document) {
57033    readOnlyToggleLists(root).forEach((toggleList) => {
57034      if (!isReadOnlyToggleList(toggleList)) return;
57035      hydrateReadOnlyToggleList(toggleList);
57036      syncToggleList(toggleList);
57037    });
57038  }
57039  document.addEventListener("click", handleReadOnlyToggleListClick);
57040  document.addEventListener("keydown", handleReadOnlyToggleListKeydown);
57041  document.addEventListener("turbo:load", () => prepareReadOnlyToggleLists());
57042  document.addEventListener("turbo:render", () => prepareReadOnlyToggleLists());
57043  document.addEventListener("turbo:frame-load", (event) => prepareReadOnlyToggleLists(event.target));
57044  document.addEventListener("turbo:before-cache", () => restoreReadOnlyToggleLists());
57045  if (document.readyState === "complete" || document.readyState === "interactive") {
57046    prepareReadOnlyToggleLists();
57047  } else {
57048    document.addEventListener("DOMContentLoaded", () => prepareReadOnlyToggleLists(), { once: true });
57049  }
57050
57051  
57051// app/javascript/src/actiontext.js
57052  installCaptionEditorSupport();
57053  configure({
57054    global: {
57055      extensions: [
57056        CalloutExtension,
57057        ChecklistExtension,
57058        EmojiPromptExtension,
57059        HexColorExtension,
57060        ImageExtension,
57061        SlashCommandsExtension,
57062        ToggleListExtension,
57063        TypographyExtension
57064      ]
57065    },
57066    default: {
57067      toolbar: {
57068        upload: "both"
57069      }
57070    }
57071  });
57072  Promise.resolve().then(() => init_actiontext_esm());
57073  function refreshRichEmbeds() {
57074    highlightCode();
57075    scheduleCodeBlockCopyButtons();
57076    scheduleCalloutHydration();
57077    scheduleHexColorHydration();
57078    renderTwitterEmbeds();
57079    renderInstagramEmbeds();
57080    renderTikTokEmbeds();
57081    renderFacebookEmbeds();
57082    renderAirtableEmbeds();
57083    renderResponsiveEmbeds();
57084    decorateEmbedBadges();
57085  }
57086  function refreshLexxyToolbarIcons(root = document) {
57087    requestAnimationFrame(() => enhanceLexxyToolbarIcons(root));
57088  }
57089  document.addEventListener("turbo:load", refreshRichEmbeds);
57090  document.addEventListener("turbo:load", () => refreshLexxyToolbarIcons());
57091  document.addEventListener("turbo:render", refreshRichEmbeds);
57092  document.addEventListener("turbo:render", () => refreshLexxyToolbarIcons());
57093  document.addEventListener("turbo:morph", refreshRichEmbeds);
57094  document.addEventListener("turbo:morph", () => refreshLexxyToolbarIcons());
57095  document.addEventListener("lexxy:initialize", (event) => {
57096    scheduleCaptionEditorSync(event.target);
57097    scheduleCalloutHydration(event.target);
57098    scheduleHexColorHydration(event.target);
57099    scheduleTwitterEmbeds(event.target);
57100    scheduleInstagramEmbeds(event.target);
57101    scheduleTikTokEmbeds(event.target);
57102    scheduleFacebookEmbeds(event.target);
57103    scheduleAirtableEmbeds(event.target);
57104    scheduleResponsiveEmbeds(event.target);
57105    decorateEmbedBadges(event.target);
57106    refreshLexxyToolbarIcons(event.target);
57107  });
57108  document.addEventListener("lexxy:editor-initialized", (event) => {
57109    scheduleCaptionEditorSync(event.target);
57110    scheduleCalloutHydration(event.target);
57111    scheduleHexColorHydration(event.target);
57112    scheduleTwitterEmbeds(event.target);
57113    scheduleInstagramEmbeds(event.target);
57114    scheduleTikTokEmbeds(event.target);
57115    scheduleFacebookEmbeds(event.target);
57116    scheduleAirtableEmbeds(event.target);
57117    scheduleResponsiveEmbeds(event.target);
57118    decorateEmbedBadges(event.target);
57119    refreshLexxyToolbarIcons(event.target);
57120  });
57121  document.addEventListener("lexxy:change", (event) => {
57122    if (event.target?.matches?.("lexxy-editor")) {
57123      scheduleCalloutHydration(event.target);
57124      scheduleHexColorHydration(event.target);
57125      scheduleTwitterEmbeds(event.target);
57126      scheduleInstagramEmbeds(event.target);
57127      scheduleTikTokEmbeds(event.target);
57128      scheduleFacebookEmbeds(event.target);
57129      scheduleAirtableEmbeds(event.target);
57130      scheduleResponsiveEmbeds(event.target);
57131      decorateEmbedBadges(event.target);
57132      refreshLexxyToolbarIcons(event.target);
57133    }
57134  });
57135
57136  
vendor: 16,768 bytes, lines 57136-57614
57136// node_modules/@hotwired/stimulus/dist/stimulus.js
57137  function camelize(value) {
57138    return value.replace(/(?:[_-])([a-z0-9])/g, (_3, char) => char.toUpperCase());
57139  }
57140  function namespaceCamelize(value) {
57141    return camelize(value.replace(/--/g, "-").replace(/__/g, "_"));
57142  }
57143  function capitalize2(value) {
57144    return value.charAt(0).toUpperCase() + value.slice(1);
57145  }
57146  function dasherize2(value) {
57147    return value.replace(/([A-Z])/g, (_3, char) => `-${char.toLowerCase()}`);
57148  }
57149  function isSomething(object) {
57150    return object !== null && object !== void 0;
57151  }
57152  function hasProperty(object, property) {
57153    return Object.prototype.hasOwnProperty.call(object, property);
57154  }
57155  function readInheritableStaticArrayValues(constructor, propertyName) {
57156    const ancestors = getAncestorsForConstructor(constructor);
57157    return Array.from(ancestors.reduce((values, constructor2) => {
57158      getOwnStaticArrayValues(constructor2, propertyName).forEach((name) => values.add(name));
57159      return values;
57160    }, /* @__PURE__ */ new Set()));
57161  }
57162  function readInheritableStaticObjectPairs(constructor, propertyName) {
57163    const ancestors = getAncestorsForConstructor(constructor);
57164    return ancestors.reduce((pairs, constructor2) => {
57165      pairs.push(...getOwnStaticObjectPairs(constructor2, propertyName));
57166      return pairs;
57167    }, []);
57168  }
57169  function getAncestorsForConstructor(constructor) {
57170    const ancestors = [];
57171    while (constructor) {
57172      ancestors.push(constructor);
57173      constructor = Object.getPrototypeOf(constructor);
57174    }
57175    return ancestors.reverse();
57176  }
57177  function getOwnStaticArrayValues(constructor, propertyName) {
57178    const definition = constructor[propertyName];
57179    return Array.isArray(definition) ? definition : [];
57180  }
57181  function getOwnStaticObjectPairs(constructor, propertyName) {
57182    const definition = constructor[propertyName];
57183    return definition ? Object.keys(definition).map((key) => [key, definition[key]]) : [];
57184  }
57185  var getOwnKeys = (() => {
57186    if (typeof Object.getOwnPropertySymbols == "function") {
57187      return (object) => [...Object.getOwnPropertyNames(object), ...Object.getOwnPropertySymbols(object)];
57188    } else {
57189      return Object.getOwnPropertyNames;
57190    }
57191  })();
57192  var extend = (() => {
57193    function extendWithReflect(constructor) {
57194      function extended() {
57195        return Reflect.construct(constructor, arguments, new.target);
57196      }
57197      extended.prototype = Object.create(constructor.prototype, {
57198        constructor: { value: extended }
57199      });
57200      Reflect.setPrototypeOf(extended, constructor);
57201      return extended;
57202    }
57203    function testReflectExtension() {
57204      const a2 = function() {
57205        this.a.call(this);
57206      };
57207      const b3 = extendWithReflect(a2);
57208      b3.prototype.a = function() {
57209      };
57210      return new b3();
57211    }
57212    try {
57213      testReflectExtension();
57214      return extendWithReflect;
57215    } catch (error) {
57216      return (constructor) => class extended extends constructor {
57217      };
57218    }
57219  })();
57220  var defaultSchema = {
57221    controllerAttribute: "data-controller",
57222    actionAttribute: "data-action",
57223    targetAttribute: "data-target",
57224    targetAttributeForScope: (identifier) => `data-${identifier}-target`,
57225    outletAttributeForScope: (identifier, outlet) => `data-${identifier}-${outlet}-outlet`,
57226    keyMappings: Object.assign(Object.assign({ enter: "Enter", tab: "Tab", esc: "Escape", space: " ", up: "ArrowUp", down: "ArrowDown", left: "ArrowLeft", right: "ArrowRight", home: "Home", end: "End", page_up: "PageUp", page_down: "PageDown" }, objectFromEntries("abcdefghijklmnopqrstuvwxyz".split("").map((c2) => [c2, c2]))), objectFromEntries("0123456789".split("").map((n2) => [n2, n2])))
57227  };
57228  function objectFromEntries(array) {
57229    return array.reduce((memo, [k2, v3]) => Object.assign(Object.assign({}, memo), { [k2]: v3 }), {});
57230  }
57231  function ClassPropertiesBlessing(constructor) {
57232    const classes = readInheritableStaticArrayValues(constructor, "classes");
57233    return classes.reduce((properties, classDefinition) => {
57234      return Object.assign(properties, propertiesForClassDefinition(classDefinition));
57235    }, {});
57236  }
57237  function propertiesForClassDefinition(key) {
57238    return {
57239      [`${key}Class`]: {
57240        get() {
57241          const { classes } = this;
57242          if (classes.has(key)) {
57243            return classes.get(key);
57244          } else {
57245            const attribute = classes.getAttributeName(key);
57246            throw new Error(`Missing attribute "${attribute}"`);
57247          }
57248        }
57249      },
57250      [`${key}Classes`]: {
57251        get() {
57252          return this.classes.getAll(key);
57253        }
57254      },
57255      [`has${capitalize2(key)}Class`]: {
57256        get() {
57257          return this.classes.has(key);
57258        }
57259      }
57260    };
57261  }
57262  function OutletPropertiesBlessing(constructor) {
57263    const outlets = readInheritableStaticArrayValues(constructor, "outlets");
57264    return outlets.reduce((properties, outletDefinition) => {
57265      return Object.assign(properties, propertiesForOutletDefinition(outletDefinition));
57266    }, {});
57267  }
57268  function getOutletController(controller, element, identifier) {
57269    return controller.application.getControllerForElementAndIdentifier(element, identifier);
57270  }
57271  function getControllerAndEnsureConnectedScope(controller, element, outletName) {
57272    let outletController = getOutletController(controller, element, outletName);
57273    if (outletController)
57274      return outletController;
57275    controller.application.router.proposeToConnectScopeForElementAndIdentifier(element, outletName);
57276    outletController = getOutletController(controller, element, outletName);
57277    if (outletController)
57278      return outletController;
57279  }
57280  function propertiesForOutletDefinition(name) {
57281    const camelizedName = namespaceCamelize(name);
57282    return {
57283      [`${camelizedName}Outlet`]: {
57284        get() {
57285          const outletElement = this.outlets.find(name);
57286          const selector = this.outlets.getSelectorForOutletName(name);
57287          if (outletElement) {
57288            const outletController = getControllerAndEnsureConnectedScope(this, outletElement, name);
57289            if (outletController)
57290              return outletController;
57291            throw new Error(`The provided outlet element is missing an outlet controller "${name}" instance for host controller "${this.identifier}"`);
57292          }
57293          throw new Error(`Missing outlet element "${name}" for host controller "${this.identifier}". Stimulus couldn't find a matching outlet element using selector "${selector}".`);
57294        }
57295      },
57296      [`${camelizedName}Outlets`]: {
57297        get() {
57298          const outlets = this.outlets.findAll(name);
57299          if (outlets.length > 0) {
57300            return outlets.map((outletElement) => {
57301              const outletController = getControllerAndEnsureConnectedScope(this, outletElement, name);
57302              if (outletController)
57303                return outletController;
57304              console.warn(`The provided outlet element is missing an outlet controller "${name}" instance for host controller "${this.identifier}"`, outletElement);
57305            }).filter((controller) => controller);
57306          }
57307          return [];
57308        }
57309      },
57310      [`${camelizedName}OutletElement`]: {
57311        get() {
57312          const outletElement = this.outlets.find(name);
57313          const selector = this.outlets.getSelectorForOutletName(name);
57314          if (outletElement) {
57315            return outletElement;
57316          } else {
57317            throw new Error(`Missing outlet element "${name}" for host controller "${this.identifier}". Stimulus couldn't find a matching outlet element using selector "${selector}".`);
57318          }
57319        }
57320      },
57321      [`${camelizedName}OutletElements`]: {
57322        get() {
57323          return this.outlets.findAll(name);
57324        }
57325      },
57326      [`has${capitalize2(camelizedName)}Outlet`]: {
57327        get() {
57328          return this.outlets.has(name);
57329        }
57330      }
57331    };
57332  }
57333  function TargetPropertiesBlessing(constructor) {
57334    const targets = readInheritableStaticArrayValues(constructor, "targets");
57335    return targets.reduce((properties, targetDefinition) => {
57336      return Object.assign(properties, propertiesForTargetDefinition(targetDefinition));
57337    }, {});
57338  }
57339  function propertiesForTargetDefinition(name) {
57340    return {
57341      [`${name}Target`]: {
57342        get() {
57343          const target = this.targets.find(name);
57344          if (target) {
57345            return target;
57346          } else {
57347            throw new Error(`Missing target element "${name}" for "${this.identifier}" controller`);
57348          }
57349        }
57350      },
57351      [`${name}Targets`]: {
57352        get() {
57353          return this.targets.findAll(name);
57354        }
57355      },
57356      [`has${capitalize2(name)}Target`]: {
57357        get() {
57358          return this.targets.has(name);
57359        }
57360      }
57361    };
57362  }
57363  function ValuePropertiesBlessing(constructor) {
57364    const valueDefinitionPairs = readInheritableStaticObjectPairs(constructor, "values");
57365    const propertyDescriptorMap = {
57366      valueDescriptorMap: {
57367        get() {
57368          return valueDefinitionPairs.reduce((result, valueDefinitionPair) => {
57369            const valueDescriptor = parseValueDefinitionPair(valueDefinitionPair, this.identifier);
57370            const attributeName = this.data.getAttributeNameForKey(valueDescriptor.key);
57371            return Object.assign(result, { [attributeName]: valueDescriptor });
57372          }, {});
57373        }
57374      }
57375    };
57376    return valueDefinitionPairs.reduce((properties, valueDefinitionPair) => {
57377      return Object.assign(properties, propertiesForValueDefinitionPair(valueDefinitionPair));
57378    }, propertyDescriptorMap);
57379  }
57380  function propertiesForValueDefinitionPair(valueDefinitionPair, controller) {
57381    const definition = parseValueDefinitionPair(valueDefinitionPair, controller);
57382    const { key, name, reader: read, writer: write } = definition;
57383    return {
57384      [name]: {
57385        get() {
57386          const value = this.data.get(key);
57387          if (value !== null) {
57388            return read(value);
57389          } else {
57390            return definition.defaultValue;
57391          }
57392        },
57393        set(value) {
57394          if (value === void 0) {
57395            this.data.delete(key);
57396          } else {
57397            this.data.set(key, write(value));
57398          }
57399        }
57400      },
57401      [`has${capitalize2(name)}`]: {
57402        get() {
57403          return this.data.has(key) || definition.hasCustomDefaultValue;
57404        }
57405      }
57406    };
57407  }
57408  function parseValueDefinitionPair([token, typeDefinition], controller) {
57409    return valueDescriptorForTokenAndTypeDefinition({
57410      controller,
57411      token,
57412      typeDefinition
57413    });
57414  }
57415  function parseValueTypeConstant(constant) {
57416    switch (constant) {
57417      case Array:
57418        return "array";
57419      case Boolean:
57420        return "boolean";
57421      case Number:
57422        return "number";
57423      case Object:
57424        return "object";
57425      case String:
57426        return "string";
57427    }
57428  }
57429  function parseValueTypeDefault(defaultValue) {
57430    switch (typeof defaultValue) {
57431      case "boolean":
57432        return "boolean";
57433      case "number":
57434        return "number";
57435      case "string":
57436        return "string";
57437    }
57438    if (Array.isArray(defaultValue))
57439      return "array";
57440    if (Object.prototype.toString.call(defaultValue) === "[object Object]")
57441      return "object";
57442  }
57443  function parseValueTypeObject(payload) {
57444    const { controller, token, typeObject } = payload;
57445    const hasType = isSomething(typeObject.type);
57446    const hasDefault = isSomething(typeObject.default);
57447    const fullObject = hasType && hasDefault;
57448    const onlyType = hasType && !hasDefault;
57449    const onlyDefault = !hasType && hasDefault;
57450    const typeFromObject = parseValueTypeConstant(typeObject.type);
57451    const typeFromDefaultValue = parseValueTypeDefault(payload.typeObject.default);
57452    if (onlyType)
57453      return typeFromObject;
57454    if (onlyDefault)
57455      return typeFromDefaultValue;
57456    if (typeFromObject !== typeFromDefaultValue) {
57457      const propertyPath = controller ? `${controller}.${token}` : token;
57458      throw new Error(`The specified default value for the Stimulus Value "${propertyPath}" must match the defined type "${typeFromObject}". The provided default value of "${typeObject.default}" is of type "${typeFromDefaultValue}".`);
57459    }
57460    if (fullObject)
57461      return typeFromObject;
57462  }
57463  function parseValueTypeDefinition(payload) {
57464    const { controller, token, typeDefinition } = payload;
57465    const typeObject = { controller, token, typeObject: typeDefinition };
57466    const typeFromObject = parseValueTypeObject(typeObject);
57467    const typeFromDefaultValue = parseValueTypeDefault(typeDefinition);
57468    const typeFromConstant = parseValueTypeConstant(typeDefinition);
57469    const type = typeFromObject || typeFromDefaultValue || typeFromConstant;
57470    if (type)
57471      return type;
57472    const propertyPath = controller ? `${controller}.${typeDefinition}` : token;
57473    throw new Error(`Unknown value type "${propertyPath}" for "${token}" value`);
57474  }
57475  function defaultValueForDefinition(typeDefinition) {
57476    const constant = parseValueTypeConstant(typeDefinition);
57477    if (constant)
57478      return defaultValuesByType[constant];
57479    const hasDefault = hasProperty(typeDefinition, "default");
57480    const hasType = hasProperty(typeDefinition, "type");
57481    const typeObject = typeDefinition;
57482    if (hasDefault)
57483      return typeObject.default;
57484    if (hasType) {
57485      const { type } = typeObject;
57486      const constantFromType = parseValueTypeConstant(type);
57487      if (constantFromType)
57488        return defaultValuesByType[constantFromType];
57489    }
57490    return typeDefinition;
57491  }
57492  function valueDescriptorForTokenAndTypeDefinition(payload) {
57493    const { token, typeDefinition } = payload;
57494    const key = `${dasherize2(token)}-value`;
57495    const type = parseValueTypeDefinition(payload);
57496    return {
57497      type,
57498      key,
57499      name: camelize(key),
57500      get defaultValue() {
57501        return defaultValueForDefinition(typeDefinition);
57502      },
57503      get hasCustomDefaultValue() {
57504        return parseValueTypeDefault(typeDefinition) !== void 0;
57505      },
57506      reader: readers[type],
57507      writer: writers[type] || writers.default
57508    };
57509  }
57510  var defaultValuesByType = {
57511    get array() {
57512      return [];
57513    },
57514    boolean: false,
57515    number: 0,
57516    get object() {
57517      return {};
57518    },
57519    string: ""
57520  };
57521  var readers = {
57522    array(value) {
57523      const array = JSON.parse(value);
57524      if (!Array.isArray(array)) {
57525        throw new TypeError(`expected value of type "array" but instead got value "${value}" of type "${parseValueTypeDefault(array)}"`);
57526      }
57527      return array;
57528    },
57529    boolean(value) {
57530      return !(value == "0" || String(value).toLowerCase() == "false");
57531    },
57532    number(value) {
57533      return Number(value.replace(/_/g, ""));
57534    },
57535    object(value) {
57536      const object = JSON.parse(value);
57537      if (object === null || typeof object != "object" || Array.isArray(object)) {
57538        throw new TypeError(`expected value of type "object" but instead got value "${value}" of type "${parseValueTypeDefault(object)}"`);
57539      }
57540      return object;
57541    },
57542    string(value) {
57543      return value;
57544    }
57545  };
57546  var writers = {
57547    default: writeString,
57548    array: writeJSON,
57549    object: writeJSON
57550  };
57551  function writeJSON(value) {
57552    return JSON.stringify(value);
57553  }
57554  function writeString(value) {
57555    return `${value}`;
57556  }
57557  var Controller = class {
57558    constructor(context) {
57559      this.context = context;
57560    }
57561    static get shouldLoad() {
57562      return true;
57563    }
57564    static afterLoad(_identifier, _application) {
57565      return;
57566    }
57567    get application() {
57568      return this.context.application;
57569    }
57570    get scope() {
57571      return this.context.scope;
57572    }
57573    get element() {
57574      return this.scope.element;
57575    }
57576    get identifier() {
57577      return this.scope.identifier;
57578    }
57579    get targets() {
57580      return this.scope.targets;
57581    }
57582    get outlets() {
57583      return this.scope.outlets;
57584    }
57585    get classes() {
57586      return this.scope.classes;
57587    }
57588    get data() {
57589      return this.scope.data;
57590    }
57591    initialize() {
57592    }
57593    connect() {
57594    }
57595    disconnect() {
57596    }
57597    dispatch(eventName, { target = this.element, detail = {}, prefix = this.identifier, bubbles = true, cancelable = true } = {}) {
57598      const type = prefix ? `${prefix}:${eventName}` : eventName;
57599      const event = new CustomEvent(type, { detail, bubbles, cancelable });
57600      target.dispatchEvent(event);
57601      return event;
57602    }
57603  };
57604  Controller.blessings = [
57605    ClassPropertiesBlessing,
57606    TargetPropertiesBlessing,
57607    ValuePropertiesBlessing,
57608    OutletPropertiesBlessing
57609  ];
57610  Controller.targets = [];
57611  Controller.outlets = [];
57612  Controller.values = {};
57613
57614  
vendor: 2,678 bytes, lines 57614-57694
57614// node_modules/@rails/request.js/src/fetch_response.js
57615  var FetchResponse = class {
57616    constructor(response) {
57617      this.response = response;
57618    }
57619    get statusCode() {
57620      return this.response.status;
57621    }
57622    get redirected() {
57623      return this.response.redirected;
57624    }
57625    get ok() {
57626      return this.response.ok;
57627    }
57628    get unauthenticated() {
57629      return this.statusCode === 401;
57630    }
57631    get unprocessableEntity() {
57632      return this.statusCode === 422;
57633    }
57634    get authenticationURL() {
57635      return this.response.headers.get("WWW-Authenticate");
57636    }
57637    get contentType() {
57638      const contentType = this.response.headers.get("Content-Type") || "";
57639      return contentType.replace(/;.*$/, "");
57640    }
57641    get headers() {
57642      return this.response.headers;
57643    }
57644    get html() {
57645      if (this.contentType.match(/^(application|text)\/(html|xhtml\+xml)$/)) {
57646        return this.text;
57647      }
57648      return Promise.reject(new Error(`Expected an HTML response but got "${this.contentType}" instead`));
57649    }
57650    get json() {
57651      if (this.contentType.match(/^application\/.*json$/)) {
57652        return this.responseJson || (this.responseJson = this.response.json());
57653      }
57654      return Promise.reject(new Error(`Expected a JSON response but got "${this.contentType}" instead`));
57655    }
57656    get text() {
57657      return this.responseText || (this.responseText = this.response.text());
57658    }
57659    get isTurboStream() {
57660      return this.contentType.match(/^text\/vnd\.turbo-stream\.html/);
57661    }
57662    get isScript() {
57663      return this.contentType.match(/\b(?:java|ecma)script\b/);
57664    }
57665    async renderTurboStream() {
57666      if (this.isTurboStream) {
57667        if (window.Turbo) {
57668          await window.Turbo.renderStreamMessage(await this.text);
57669        } else {
57670          console.warn("You must set `window.Turbo = Turbo` to automatically process Turbo Stream events with request.js");
57671        }
57672      } else {
57673        return Promise.reject(new Error(`Expected a Turbo Stream response but got "${this.contentType}" instead`));
57674      }
57675    }
57676    async activeScript() {
57677      if (this.isScript) {
57678        const script = document.createElement("script");
57679        const metaTag = document.querySelector("meta[name=csp-nonce]");
57680        if (metaTag) {
57681          const nonce = metaTag.nonce === "" ? metaTag.content : metaTag.nonce;
57682          if (nonce) {
57683            script.setAttribute("nonce", nonce);
57684          }
57685        }
57686        script.innerHTML = await this.text;
57687        document.body.appendChild(script);
57688      } else {
57689        return Promise.reject(new Error(`Expected a Script response but got "${this.contentType}" instead`));
57690      }
57691    }
57692  };
57693
57694  
vendor: 299 bytes, lines 57694-57707
57694// node_modules/@rails/request.js/src/request_interceptor.js
57695  var RequestInterceptor = class {
57696    static register(interceptor) {
57697      this.interceptor = interceptor;
57698    }
57699    static get() {
57700      return this.interceptor;
57701    }
57702    static reset() {
57703      this.interceptor = void 0;
57704    }
57705  };
57706
57707  
vendor: 1,356 bytes, lines 57707-57750
57707// node_modules/@rails/request.js/src/lib/utils.js
57708  function getCookie(name) {
57709    const cookies = document.cookie ? document.cookie.split("; ") : [];
57710    const prefix = `${encodeURIComponent(name)}=`;
57711    const cookie = cookies.find((cookie2) => cookie2.startsWith(prefix));
57712    if (cookie) {
57713      const value = cookie.split("=").slice(1).join("=");
57714      if (value) {
57715        return decodeURIComponent(value);
57716      }
57717    }
57718  }
57719  function compact(object) {
57720    const result = {};
57721    for (const key in object) {
57722      const value = object[key];
57723      if (value !== void 0) {
57724        result[key] = value;
57725      }
57726    }
57727    return result;
57728  }
57729  function metaContent(name) {
57730    const element = document.head.querySelector(`meta[name="${name}"]`);
57731    return element && element.content;
57732  }
57733  function stringEntriesFromFormData(formData) {
57734    return [...formData].reduce((entries2, [name, value]) => {
57735      return entries2.concat(typeof value === "string" ? [[name, value]] : []);
57736    }, []);
57737  }
57738  function mergeEntries(searchParams, entries2) {
57739    for (const [name, value] of entries2) {
57740      if (value instanceof window.File) continue;
57741      if (searchParams.has(name) && !name.includes("[]")) {
57742        searchParams.delete(name);
57743        searchParams.set(name, value);
57744      } else {
57745        searchParams.append(name, value);
57746      }
57747    }
57748  }
57749
57750  
vendor: 4,748 bytes, lines 57750-57895
57750// node_modules/@rails/request.js/src/fetch_request.js
57751  var FetchRequest = class {
57752    constructor(method, url, options = {}) {
57753      this.method = method;
57754      this.options = options;
57755      this.originalUrl = url.toString();
57756    }
57757    async perform() {
57758      try {
57759        const requestInterceptor = RequestInterceptor.get();
57760        if (requestInterceptor) {
57761          await requestInterceptor(this);
57762        }
57763      } catch (error) {
57764        console.error(error);
57765      }
57766      const fetch2 = this.responseKind === "turbo-stream" && window.Turbo ? window.Turbo.fetch : window.fetch;
57767      const response = new FetchResponse(await fetch2(this.url, this.fetchOptions));
57768      if (response.unauthenticated && response.authenticationURL) {
57769        return Promise.reject(window.location.href = response.authenticationURL);
57770      }
57771      if (response.isScript) {
57772        await response.activeScript();
57773      }
57774      const responseStatusIsTurboStreamable = response.ok || response.unprocessableEntity;
57775      if (responseStatusIsTurboStreamable && response.isTurboStream) {
57776        await response.renderTurboStream();
57777      }
57778      return response;
57779    }
57780    addHeader(key, value) {
57781      const headers = this.additionalHeaders;
57782      headers[key] = value;
57783      this.options.headers = headers;
57784    }
57785    sameHostname() {
57786      if (!this.originalUrl.startsWith("http:") && !this.originalUrl.startsWith("https:")) {
57787        return true;
57788      }
57789      try {
57790        return new URL(this.originalUrl).hostname === window.location.hostname;
57791      } catch (_3) {
57792        return true;
57793      }
57794    }
57795    get fetchOptions() {
57796      return {
57797        method: this.method.toUpperCase(),
57798        headers: this.headers,
57799        body: this.formattedBody,
57800        signal: this.signal,
57801        credentials: this.credentials,
57802        redirect: this.redirect,
57803        keepalive: this.keepalive
57804      };
57805    }
57806    get headers() {
57807      const baseHeaders = {
57808        "X-Requested-With": "XMLHttpRequest",
57809        "Content-Type": this.contentType,
57810        Accept: this.accept
57811      };
57812      if (this.sameHostname()) {
57813        baseHeaders["X-CSRF-Token"] = this.csrfToken;
57814      }
57815      return compact(
57816        Object.assign(baseHeaders, this.additionalHeaders)
57817      );
57818    }
57819    get csrfToken() {
57820      return getCookie(metaContent("csrf-param")) || metaContent("csrf-token");
57821    }
57822    get contentType() {
57823      if (this.options.contentType) {
57824        return this.options.contentType;
57825      } else if (this.body == null || this.body instanceof window.FormData) {
57826        return void 0;
57827      } else if (this.body instanceof window.File) {
57828        return this.body.type;
57829      }
57830      return "application/json";
57831    }
57832    get accept() {
57833      switch (this.responseKind) {
57834        case "html":
57835          return "text/html, application/xhtml+xml";
57836        case "turbo-stream":
57837          return "text/vnd.turbo-stream.html, text/html, application/xhtml+xml";
57838        case "json":
57839          return "application/json, application/vnd.api+json";
57840        case "script":
57841          return "text/javascript, application/javascript";
57842        default:
57843          return "*/*";
57844      }
57845    }
57846    get body() {
57847      return this.options.body;
57848    }
57849    get query() {
57850      const originalQuery = (this.originalUrl.split("?")[1] || "").split("#")[0];
57851      const params = new URLSearchParams(originalQuery);
57852      let requestQuery = this.options.query;
57853      if (requestQuery instanceof window.FormData) {
57854        requestQuery = stringEntriesFromFormData(requestQuery);
57855      } else if (requestQuery instanceof window.URLSearchParams) {
57856        requestQuery = requestQuery.entries();
57857      } else {
57858        requestQuery = Object.entries(requestQuery || {});
57859      }
57860      mergeEntries(params, requestQuery);
57861      const query = params.toString();
57862      return query.length > 0 ? `?${query}` : "";
57863    }
57864    get url() {
57865      return this.originalUrl.split("?")[0].split("#")[0] + this.query;
57866    }
57867    get responseKind() {
57868      return this.options.responseKind || "html";
57869    }
57870    get signal() {
57871      return this.options.signal;
57872    }
57873    get redirect() {
57874      return this.options.redirect || "follow";
57875    }
57876    get credentials() {
57877      return this.options.credentials || "same-origin";
57878    }
57879    get keepalive() {
57880      return this.options.keepalive || false;
57881    }
57882    get additionalHeaders() {
57883      return this.options.headers || {};
57884    }
57885    get formattedBody() {
57886      const bodyIsAString = Object.prototype.toString.call(this.body) === "[object String]";
57887      const contentTypeIsJson = this.headers["Content-Type"] === "application/json";
57888      if (contentTypeIsJson && !bodyIsAString) {
57889        return JSON.stringify(this.body);
57890      }
57891      return this.body;
57892    }
57893  };
57894
57895  
vendor: 312 bytes, lines 57895-57905
57895// node_modules/@rails/request.js/src/verbs.js
57896  async function get(url, options) {
57897    const request = new FetchRequest("get", url, options);
57898    return request.perform();
57899  }
57900  async function post(url, options) {
57901    const request = new FetchRequest("post", url, options);
57902    return request.perform();
57903  }
57904
57905  
57905// app/javascript/src/unfurl_link_controller.js
57906  var unfurl_link_controller_default = class extends Controller {
57907    static values = {
57908      url: { type: String, default: "/action_text/embeds" }
57909    };
57910    connect() {
57911      this.patterns = void 0;
57912      this.currentEmbed = null;
57913      this.embedRequestId = 0;
57914      this.installEmbedPrompt = this.installEmbedPrompt.bind(this);
57915      this.element.addEventListener("lexxy:initialize", this.installEmbedPrompt);
57916      this.element.addEventListener("lexxy:editor-initialized", this.installEmbedPrompt);
57917      queueMicrotask(this.installEmbedPrompt);
57918    }
57919    disconnect() {
57920      this.element.removeEventListener("lexxy:initialize", this.installEmbedPrompt);
57921      this.element.removeEventListener("lexxy:editor-initialized", this.installEmbedPrompt);
57922    }
57923    unfurl(event) {
57924      this.#unfurlLink(event.detail.url, event.detail);
57925    }
57926    installEmbedPrompt() {
57927      const dropdown = this.element.querySelector("lexxy-link-dropdown");
57928      const panel = dropdown?.querySelector("[data-dropdown-panel]");
57929      const input = dropdown?.querySelector("input[type='url']");
57930      if (!dropdown || !panel || !input || panel.querySelector("[data-unfurl-link-embed-hint]")) return;
57931      const hint = document.createElement("div");
57932      hint.dataset.unfurlLinkEmbedHint = "";
57933      hint.className = "link_to_embed link_to_embed--hint";
57934      hint.innerHTML = `
57935      <p class="link_to_embed__label">Paste a link, or embed using a url from</p>
57936      <div class="link_to_embed__providers" role="group" aria-label="Supported embed providers">
57937        ${EMBED_PROVIDERS.map((provider) => embedProviderPill(provider)).join("")}
57938      </div>
57939    `;
57940      const container = document.createElement("div");
57941      container.dataset.unfurlLinkEmbedContainer = "";
57942      container.dataset.behavior = "embed_container";
57943      container.className = "link_to_embed link_to_embed--offer";
57944      container.hidden = true;
57945      container.setAttribute("aria-hidden", "true");
57946      container.innerHTML = `
57947      <div class="link_to_embed__card">
57948        <div class="link_to_embed__details">
57949          <span class="link_to_embed__provider" data-unfurl-link-embed-provider></span>
57950          <span class="link_to_embed__title" data-unfurl-link-embed-title hidden></span>
57951        </div>
57952        <button type="button" class="link_to_embed__embed-button lexxy-editor__toolbar-button" data-behavior="embed_url" data-unfurl-link-embed-button>
57953          Embed
57954        </button>
57955      </div>
57956    `;
57957      panel.append(hint, container);
57958      const card = container.querySelector(".link_to_embed__card");
57959      const providerElement = container.querySelector("[data-unfurl-link-embed-provider]");
57960      const titleElement = container.querySelector("[data-unfurl-link-embed-title]");
57961      const embedButton = container.querySelector("[data-unfurl-link-embed-button]");
57962      this.#resetEmbedPrompt(hint, container, providerElement, titleElement, card);
57963      new MutationObserver(() => {
57964        if (panel.hidden) this.#resetEmbedPrompt(hint, container, providerElement, titleElement, card);
57965      }).observe(panel, { attributes: true, attributeFilter: ["hidden"] });
57966      input.addEventListener(
57967        "input",
57968        () => this.#didInputUrl(input, hint, container, providerElement, titleElement, card)
57969      );
57970      input.addEventListener(
57971        "focusin",
57972        () => this.#didInputUrl(input, hint, container, providerElement, titleElement, card)
57973      );
57974      dropdown.querySelector("[data-dropdown-trigger]")?.addEventListener("click", () => {
57975        requestAnimationFrame(() => {
57976          this.#resetEmbedPrompt(hint, container, providerElement, titleElement, card);
57977          this.#didInputUrl(input, hint, container, providerElement, titleElement, card);
57978        });
57979      });
57980      embedButton.addEventListener("click", (event) => this.#embedFromPrompt(event, dropdown));
57981    }
57982    #didInputUrl(input, hint, container, providerElement, titleElement, card) {
57983      const value = input.value.trim();
57984      if (!value || !input.validity.valid) {
57985        this.#resetEmbedPrompt(hint, container, providerElement, titleElement, card);
57986        return;
57987      }
57988      if (this.patterns === void 0) {
57989        this.#loadPatterns(value, hint, container, providerElement, titleElement, card);
57990      } else if (this.#matchesPattern(value)) {
57991        this.#fetchAndShowEmbed(value, hint, container, providerElement, titleElement, card);
57992      } else {
57993        this.#resetEmbedPrompt(hint, container, providerElement, titleElement, card);
57994      }
57995    }
57996    async #loadPatterns(value, hint, container, providerElement, titleElement, card) {
57997      const response = await get(`${this.urlValue}/patterns.json`, { responseKind: "json" });
57998      if (response.ok) {
57999        const patterns = await response.json;
58000        this.patterns = patterns.map((pattern) => new RegExp(pattern.source, pattern.options));
58001      } else {
58002        this.patterns = [];
58003      }
58004      if (this.#matchesPattern(value)) {
58005        this.#fetchAndShowEmbed(value, hint, container, providerElement, titleElement, card);
58006      } else {
58007        this.#resetEmbedPrompt(hint, container, providerElement, titleElement, card);
58008      }
58009    }
58010    #matchesPattern(value) {
58011      return this.patterns?.some((pattern) => pattern.test(value)) ?? false;
58012    }
58013    async #fetchAndShowEmbed(url, hint, container, providerElement, titleElement, card) {
58014      const requestId = ++this.embedRequestId;
58015      const metadata = await this.#fetchEmbedMetadata(url);
58016      if (requestId !== this.embedRequestId) return;
58017      if (metadata) {
58018        this.#showEmbedPrompt(metadata, hint, container, providerElement, titleElement, card, requestId);
58019      } else {
58020        this.#resetEmbedPrompt(hint, container, providerElement, titleElement, card);
58021      }
58022    }
58023    #showEmbedPrompt(metadata, hint, container, providerElement, titleElement, card, requestId) {
58024      this.currentEmbed = metadata;
58025      const providerName = embedProviderDisplayName(metadata.provider_name || "this site");
58026      const providerIcon = embedProviderIconForName(providerName);
58027      providerElement.innerHTML = `${providerIcon}<span>${providerName}</span>`;
58028      if (metadata.title) {
58029        titleElement.textContent = metadata.title;
58030        titleElement.hidden = false;
58031      } else {
58032        titleElement.textContent = "";
58033        titleElement.hidden = true;
58034      }
58035      this.#setThumbnail(card, metadata.thumbnail_url, requestId);
58036      hint.hidden = true;
58037      hint.setAttribute("aria-hidden", "true");
58038      container.hidden = false;
58039      container.removeAttribute("aria-hidden");
58040    }
58041    #clearThumbnail(card) {
58042      card.querySelector("[data-unfurl-link-embed-thumbnail]")?.remove();
58043      card.classList.remove("link_to_embed--has-thumbnail");
58044    }
58045    #setThumbnail(card, url, requestId) {
58046      this.#clearThumbnail(card);
58047      const thumbnailUrl = url?.trim();
58048      if (!thumbnailUrl || ["undefined", "null"].includes(thumbnailUrl)) return;
58049      const thumbnail = document.createElement("img");
58050      thumbnail.className = "link_to_embed__thumbnail";
58051      thumbnail.alt = "";
58052      thumbnail.dataset.unfurlLinkEmbedThumbnail = "";
58053      const isCurrentRequest = () => requestId === this.embedRequestId;
58054      thumbnail.addEventListener(
58055        "load",
58056        () => {
58057          if (!isCurrentRequest()) return;
58058          if (thumbnail.naturalWidth === 0) {
58059            this.#clearThumbnail(card);
58060            return;
58061          }
58062          card.classList.add("link_to_embed--has-thumbnail");
58063          card.prepend(thumbnail);
58064        },
58065        { once: true }
58066      );
58067      thumbnail.addEventListener(
58068        "error",
58069        () => {
58070          if (!isCurrentRequest()) return;
58071          this.#clearThumbnail(card);
58072        },
58073        { once: true }
58074      );
58075      thumbnail.src = thumbnailUrl;
58076    }
58077    #resetEmbedPrompt(hint, container, providerElement, titleElement, card) {
58078      this.embedRequestId += 1;
58079      hint.hidden = false;
58080      hint.removeAttribute("aria-hidden");
58081      container.hidden = true;
58082      container.setAttribute("aria-hidden", "true");
58083      this.currentEmbed = null;
58084      providerElement.innerHTML = "";
58085      titleElement.textContent = "";
58086      titleElement.hidden = true;
58087      this.#clearThumbnail(card);
58088    }
58089    async #unfurlLink(url, callbacks) {
58090      if (!url || !callbacks?.insertBelowLink) return;
58091      const metadata = await this.#fetchEmbedMetadata(url);
58092      if (!metadata) return;
58093      this.#insertUnfurledLink(metadata, callbacks);
58094    }
58095    #insertUnfurledLink(metadata, callbacks) {
58096      callbacks.insertBelowLink(metadata.content, {
58097        attachment: {
58098          sgid: metadata.sgid,
58099          contentType: metadata.content_type
58100        }
58101      });
58102    }
58103    async #embedFromPrompt(event, dropdown) {
58104      event.preventDefault();
58105      event.stopPropagation();
58106      if (!this.currentEmbed) return;
58107      const metadata = this.currentEmbed;
58108      this.#closeDropdown(dropdown);
58109      await new Promise((resolve) => requestAnimationFrame(resolve));
58110      this.#insertEmbedAttachment(metadata);
58111      this.currentEmbed = null;
58112    }
58113    #insertEmbedAttachment(metadata) {
58114      const attachment = document.createElement("action-text-attachment");
58115      attachment.setAttribute("sgid", metadata.sgid);
58116      attachment.setAttribute("content-type", metadata.content_type);
58117      attachment.setAttribute("content", metadata.content);
58118      const doc = document.implementation.createHTMLDocument("");
58119      doc.body.appendChild(attachment);
58120      this.element.contents?.insertDOM(doc);
58121      scheduleTwitterEmbeds(this.element);
58122      scheduleInstagramEmbeds(this.element);
58123      scheduleTikTokEmbeds(this.element);
58124      scheduleFacebookEmbeds(this.element);
58125      scheduleAirtableEmbeds(this.element);
58126      scheduleResponsiveEmbeds(this.element);
58127    }
58128    async #fetchEmbedMetadata(url) {
58129      const response = await post(this.urlValue, {
58130        body: { id: url },
58131        responseKind: "json"
58132      });
58133      if (!response.ok) return null;
58134      return response.json;
58135    }
58136    #closeDropdown(dropdown) {
58137      if (typeof dropdown.close === "function") {
58138        dropdown.close();
58139        return;
58140      }
58141      dropdown.querySelector("[data-dropdown-trigger]")?.setAttribute("aria-expanded", "false");
58142      const panel = dropdown.querySelector("[data-dropdown-panel]");
58143      if (panel) panel.hidden = true;
58144      this.element.focus();
58145    }
58146  };
58147
58148  
58148// app/javascript/lexxy_extensions.js
58149  var unfurlLinkRegistered = false;
58150  function registerUnfurlLinkController() {
58151    if (unfurlLinkRegistered || !window.Stimulus) return;
58152    window.Stimulus.register("unfurl-link", unfurl_link_controller_default);
58153    unfurlLinkRegistered = true;
58154  }
58155  queueMicrotask(registerUnfurlLinkController);
58156  document.addEventListener("DOMContentLoaded", registerUnfurlLinkController);
58157  document.addEventListener("turbo:load", registerUnfurlLinkController);
58158})();
58159/*! Bundled license information:
58160
58161prismjs/prism.js:
58162  (**
58163   * Prism: Lightweight, robust, elegant syntax highlighting
58164   *
58165   * @license MIT <https://opensource.org/licenses/MIT>
58166   * @author Lea Verou <https://lea.verou.me>
58167   * @namespace
58168   * @public
58169   *)
58170
58171dompurify/dist/purify.es.mjs:
58172  (*! @license DOMPurify 3.4.11 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.4.11/LICENSE *)
58173*/
58174;

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.