lexxy 0.1.21.beta → 0.1.23.beta

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5207,7 +5207,24 @@ function extendConversion(nodeKlass, conversionName, callback = (output => outpu
5207
5207
  }
5208
5208
  }
5209
5209
 
5210
+ function isSelectionHighlighted(selection) {
5211
+ if (!yr(selection)) return false
5212
+
5213
+ if (selection.isCollapsed()) {
5214
+ return hasHighlightStyles(selection.style)
5215
+ } else {
5216
+ return selection.hasFormat("highlight")
5217
+ }
5218
+ }
5219
+
5220
+ function hasHighlightStyles(cssOrStyles) {
5221
+ const styles = typeof cssOrStyles === "string" ? b$3(cssOrStyles) : cssOrStyles;
5222
+ return !!(styles.color || styles["background-color"])
5223
+ }
5224
+
5210
5225
  class LexicalToolbarElement extends HTMLElement {
5226
+ static observedAttributes = [ "connected" ]
5227
+
5211
5228
  constructor() {
5212
5229
  super();
5213
5230
  this.internals = this.attachInternals();
@@ -5226,6 +5243,13 @@ class LexicalToolbarElement extends HTMLElement {
5226
5243
  this._resizeObserver.disconnect();
5227
5244
  this._resizeObserver = null;
5228
5245
  }
5246
+ this.#unbindHotkeys();
5247
+ }
5248
+
5249
+ attributeChangedCallback(name, oldValue, newValue) {
5250
+ if (name === "connected" && this.isConnected && oldValue != null && oldValue !== newValue) {
5251
+ requestAnimationFrame(() => this.#reconnect());
5252
+ }
5229
5253
  }
5230
5254
 
5231
5255
  setEditor(editorElement) {
@@ -5233,7 +5257,8 @@ class LexicalToolbarElement extends HTMLElement {
5233
5257
  this.editor = editorElement.editor;
5234
5258
  this.#bindButtons();
5235
5259
  this.#bindHotkeys();
5236
- this.#assignButtonTabindex();
5260
+ this.#setTabIndexValues();
5261
+ this.#setItemPositionValues();
5237
5262
  this.#monitorSelectionChanges();
5238
5263
  this.#monitorHistoryChanges();
5239
5264
  this.#refreshToolbarOverflow();
@@ -5241,10 +5266,9 @@ class LexicalToolbarElement extends HTMLElement {
5241
5266
  this.toggleAttribute("connected", true);
5242
5267
  }
5243
5268
 
5244
- get #dialogs() {
5245
- const dialogButtons = this.querySelectorAll("[data-dialog-target]");
5246
- const dialogTags = Array.from(dialogButtons).map(button => `lexxy-${button.dataset.dialogTarget}`);
5247
- return Array.from(this.querySelectorAll(dialogTags))
5269
+ #reconnect() {
5270
+ this.disconnectedCallback();
5271
+ this.connectedCallback();
5248
5272
  }
5249
5273
 
5250
5274
  #bindButtons() {
@@ -5253,7 +5277,6 @@ class LexicalToolbarElement extends HTMLElement {
5253
5277
 
5254
5278
  #handleButtonClicked({ target }) {
5255
5279
  this.#handleTargetClicked(target, "[data-command]", this.#dispatchButtonCommand.bind(this));
5256
- this.#handleTargetClicked(target, "[data-dialog-target]", this.#toggleDialog.bind(this));
5257
5280
  }
5258
5281
 
5259
5282
  #handleTargetClicked(target, selector, callback) {
@@ -5268,38 +5291,23 @@ class LexicalToolbarElement extends HTMLElement {
5268
5291
  this.editor.dispatchCommand(command, payload);
5269
5292
  }
5270
5293
 
5271
- // Not using popover because of CSS anchoring still not widely available.
5272
- #toggleDialog(button) {
5273
- const dialogTarget = button.dataset.dialogTarget;
5274
- const dialog = this.querySelector("lexxy-" + dialogTarget);
5275
- if (!dialog) return
5276
-
5277
- if (dialog.open) {
5278
- dialog.close();
5279
- } else {
5280
- this.#closeOpenDialogs();
5281
- dialog.show(button);
5282
- }
5294
+ #bindHotkeys() {
5295
+ this.editorElement.addEventListener("keydown", this.#handleHotkey);
5283
5296
  }
5284
5297
 
5285
- #closeOpenDialogs() {
5286
- const openDialogs = this.querySelectorAll("dialog[open]");
5287
- openDialogs.forEach(openDialog => {
5288
- openDialog.closest(".lexxy-dialog").close();
5289
- });
5298
+ #unbindHotkeys() {
5299
+ this.editorElement?.removeEventListener("keydown", this.#handleHotkey);
5290
5300
  }
5291
5301
 
5292
- #bindHotkeys() {
5293
- this.editorElement.addEventListener("keydown", (event) => {
5294
- const buttons = this.querySelectorAll("[data-hotkey]");
5295
- buttons.forEach((button) => {
5296
- const hotkeys = button.dataset.hotkey.toLowerCase().split(/\s+/);
5297
- if (hotkeys.includes(this.#keyCombinationFor(event))) {
5298
- event.preventDefault();
5299
- event.stopPropagation();
5300
- button.click();
5301
- }
5302
- });
5302
+ #handleHotkey = (event) => {
5303
+ const buttons = this.querySelectorAll("[data-hotkey]");
5304
+ buttons.forEach((button) => {
5305
+ const hotkeys = button.dataset.hotkey.toLowerCase().split(/\s+/);
5306
+ if (hotkeys.includes(this.#keyCombinationFor(event))) {
5307
+ event.preventDefault();
5308
+ event.stopPropagation();
5309
+ button.click();
5310
+ }
5303
5311
  });
5304
5312
  }
5305
5313
 
@@ -5315,10 +5323,9 @@ class LexicalToolbarElement extends HTMLElement {
5315
5323
  return [ ...modifiers, pressedKey ].join("+")
5316
5324
  }
5317
5325
 
5318
- #assignButtonTabindex() {
5319
- const baseTabIndex = parseInt(this.editorElement.editorContentElement.getAttribute("tabindex") ?? "0");
5320
- this.#buttons.forEach((button, index) => {
5321
- button.setAttribute("tabindex", `${baseTabIndex + index + 1}`);
5326
+ #setTabIndexValues() {
5327
+ this.#buttons.forEach((button) => {
5328
+ button.setAttribute("tabindex", 0);
5322
5329
  });
5323
5330
  }
5324
5331
 
@@ -5326,7 +5333,6 @@ class LexicalToolbarElement extends HTMLElement {
5326
5333
  this.editor.registerUpdateListener(() => {
5327
5334
  this.editor.getEditorState().read(() => {
5328
5335
  this.#updateButtonStates();
5329
- this.#updateDialogStates();
5330
5336
  });
5331
5337
  });
5332
5338
  }
@@ -5359,7 +5365,7 @@ class LexicalToolbarElement extends HTMLElement {
5359
5365
  const isBold = selection.hasFormat("bold");
5360
5366
  const isItalic = selection.hasFormat("italic");
5361
5367
  const isStrikethrough = selection.hasFormat("strikethrough");
5362
- const isHighlight = selection.hasFormat("highlight");
5368
+ const isHighlight = isSelectionHighlighted(selection);
5363
5369
  const isInLink = this.#isInLink(anchorNode);
5364
5370
  const isInQuote = Ot$1(topLevelElement);
5365
5371
  const isInHeading = It$1(topLevelElement);
@@ -5381,10 +5387,6 @@ class LexicalToolbarElement extends HTMLElement {
5381
5387
  this.#updateUndoRedoButtonStates();
5382
5388
  }
5383
5389
 
5384
- #updateDialogStates() {
5385
- this.#dialogs.forEach(dialog => dialog.updateStateCallback());
5386
- }
5387
-
5388
5390
  #isInList(node) {
5389
5391
  let current = node;
5390
5392
  while (current) {
@@ -5433,6 +5435,43 @@ class LexicalToolbarElement extends HTMLElement {
5433
5435
  this.toggleAttribute("overflowing", isOverflowing);
5434
5436
  }
5435
5437
 
5438
+ #compactMenu() {
5439
+ const buttons = this.#buttons.reverse();
5440
+ let movedToOverflow = false;
5441
+
5442
+ for (const button of buttons) {
5443
+ if (this.#toolbarIsOverflowing()) {
5444
+ this.#overflowMenu.prepend(button);
5445
+ movedToOverflow = true;
5446
+ } else {
5447
+ if (movedToOverflow) this.#overflowMenu.prepend(button);
5448
+ break
5449
+ }
5450
+ }
5451
+ }
5452
+
5453
+ #resetToolbar() {
5454
+ const items = Array.from(this.#overflowMenu.children);
5455
+ items.sort((a, b) => this.#itemPosition(b) - this.#itemPosition(a));
5456
+
5457
+ items.forEach((item) => {
5458
+ const nextItem = this.querySelector(`[data-position="${this.#itemPosition(item) + 1}"]`) ?? this.#overflow;
5459
+ this.insertBefore(item, nextItem);
5460
+ });
5461
+ }
5462
+
5463
+ #itemPosition(item) {
5464
+ return parseInt(item.dataset.position ?? "999")
5465
+ }
5466
+
5467
+ #setItemPositionValues() {
5468
+ this.#toolbarItems.forEach((item, index) => {
5469
+ if (item.dataset.position === undefined) {
5470
+ item.dataset.position = index;
5471
+ }
5472
+ });
5473
+ }
5474
+
5436
5475
  get #overflow() {
5437
5476
  return this.querySelector(".lexxy-editor__toolbar-overflow")
5438
5477
  }
@@ -5441,128 +5480,994 @@ class LexicalToolbarElement extends HTMLElement {
5441
5480
  return this.querySelector(".lexxy-editor__toolbar-overflow-menu")
5442
5481
  }
5443
5482
 
5444
- #resetToolbar() {
5445
- while (this.#overflowMenu.children.length > 0) {
5446
- this.insertBefore(this.#overflowMenu.children[0], this.#overflow);
5447
- }
5483
+ get #buttons() {
5484
+ return Array.from(this.querySelectorAll(":scope > button"))
5448
5485
  }
5449
5486
 
5450
- #compactMenu() {
5451
- const buttons = this.#buttonsWithSeparator.reverse();
5452
- let movedToOverflow = false;
5487
+ get #toolbarItems() {
5488
+ return Array.from(this.querySelectorAll(":scope > *:not(.lexxy-editor__toolbar-overflow)"))
5489
+ }
5490
+
5491
+ static get defaultTemplate() {
5492
+ return `
5493
+ <button class="lexxy-editor__toolbar-button" type="button" name="bold" data-command="bold" title="Bold">
5494
+ <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M5 22V2h8.183c1.764 0 3.174.435 4.228 1.304 1.055.87 1.582 2.076 1.582 3.62 0 .8-.148 1.503-.445 2.109a3.94 3.94 0 01-1.194 1.465 4.866 4.866 0 01-1.726.806v.176c.786.078 1.51.312 2.172.703a4.293 4.293 0 011.596 1.627c.403.693.604 1.543.604 2.549 0 1.192-.292 2.207-.877 3.048-.585.84-1.39 1.484-2.416 1.934-1.026.44-2.206.659-3.538.659H5zM8.854 4.974v5.348h2.56c.873 0 1.582-.107 2.129-.322.556-.215.963-.523 1.222-.923.269-.41.403-.904.403-1.48 0-.82-.254-1.46-.762-1.92-.499-.468-1.204-.703-2.115-.703H8.854zm0 8.103v5.949h2.877c1.534 0 2.636-.245 3.307-.733.671-.498 1.007-1.221 1.007-2.168 0-.635-.134-1.178-.403-1.627-.268-.459-.666-.81-1.193-1.055-.518-.244-1.156-.366-1.913-.366H8.854z"/></svg>
5495
+ </button>
5496
+
5497
+ <button class="lexxy-editor__toolbar-button" type="button" name="italic" data-command="italic" title="Italic">
5498
+ <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M17.1 4h-1.5l-3.2 16h1.5l-.4 2h-7l.4-2h1.5l3.2-16h-1.5l.4-2h7l-.4 2z"/></svg>
5499
+ </button>
5500
+
5501
+ <button class="lexxy-editor__toolbar-button" type="button" name="strikethrough" data-command="strikethrough" title="Strikethrough">
5502
+ <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
5503
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M4.70588 16.1591C4.81459 19.7901 7.48035 22 11.6668 22C15.9854 22 18.724 19.6296 18.724 15.8779C18.724 15.5007 18.6993 15.1427 18.6474 14.8066H14.3721C14.8637 15.2085 15.0799 15.7037 15.0799 16.3471C15.0799 17.7668 13.7532 18.7984 11.8113 18.7984C9.88053 18.7984 8.38582 17.7531 8.21659 16.1591H4.70588ZM5.23953 9.31962H9.88794C9.10723 8.88889 8.75888 8.33882 8.75888 7.57339C8.75888 6.13992 9.96576 5.18793 11.7631 5.18793C13.5852 5.18793 14.8761 6.1797 14.9959 7.81344H18.4102C18.3485 4.31824 15.8038 2 11.752 2C7.867 2 5.09129 4.35802 5.09129 7.92044C5.09129 8.41838 5.14071 8.88477 5.23953 9.31962ZM2.23529 10.6914C1.90767 10.6914 1.59347 10.8359 1.36181 11.0931C1.13015 11.3504 1 11.6993 1 12.0631C1 12.4269 1.13015 12.7758 1.36181 13.0331C1.59347 13.2903 1.90767 13.4348 2.23529 13.4348H20.7647C21.0923 13.4348 21.4065 13.2903 21.6382 13.0331C21.8699 12.7758 22 12.4269 22 12.0631C22 11.6993 21.8699 11.3504 21.6382 11.0931C21.4065 10.8359 21.0923 10.6914 20.7647 10.6914H2.23529Z"/>
5504
+ </svg>
5505
+ </button>
5506
+
5507
+ <details class="lexxy-editor__toolbar-dropdown" name="lexxy-dropdown">
5508
+ <summary class="lexxy-editor__toolbar-button" name="highlight" title="Color highlight">
5509
+ <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M7.65422 0.711575C7.1856 0.242951 6.42579 0.242951 5.95717 0.711575C5.48853 1.18021 5.48853 1.94 5.95717 2.40864L8.70864 5.16011L2.85422 11.0145C1.44834 12.4204 1.44833 14.6998 2.85422 16.1057L7.86011 21.1115C9.26599 22.5174 11.5454 22.5174 12.9513 21.1115L19.6542 14.4087C20.1228 13.94 20.1228 13.1802 19.6542 12.7115L11.8544 4.91171L11.2542 4.31158L7.65422 0.711575ZM4.55127 12.7115L10.4057 6.85716L17.1087 13.56H4.19981C4.19981 13.253 4.31696 12.9459 4.55127 12.7115ZM23.6057 20.76C23.6057 22.0856 22.5311 23.16 21.2057 23.16C19.8802 23.16 18.8057 22.0856 18.8057 20.76C18.8057 19.5408 19.8212 18.5339 20.918 17.4462C21.0135 17.3516 21.1096 17.2563 21.2057 17.16C21.3018 17.2563 21.398 17.3516 21.4935 17.4462C22.5903 18.5339 23.6057 19.5408 23.6057 20.76Z"/></svg>
5510
+ </summary>
5511
+ <lexxy-highlight-dropdown class="lexxy-editor__toolbar-dropdown-content">
5512
+ <div data-button-group="color" data-values="var(--highlight-1); var(--highlight-2); var(--highlight-3); var(--highlight-4); var(--highlight-5); var(--highlight-6); var(--highlight-7); var(--highlight-8); var(--highlight-9)"></div>
5513
+ <div data-button-group="background-color" data-values="var(--highlight-bg-1); var(--highlight-bg-2); var(--highlight-bg-3); var(--highlight-bg-4); var(--highlight-bg-5); var(--highlight-bg-6); var(--highlight-bg-7); var(--highlight-bg-8); var(--highlight-bg-9)"></div>
5514
+ <button data-command="removeHighlight" class="lexxy-editor__toolbar-dropdown-reset">Remove all coloring</button>
5515
+ </lexxy-highlight-dropdown>
5516
+ </details>
5517
+
5518
+ <details class="lexxy-editor__toolbar-dropdown" name="lexxy-dropdown">
5519
+ <summary class="lexxy-editor__toolbar-button" name="link" title="Link" data-hotkey="cmd+k ctrl+k">
5520
+ <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12.111 9.546a1.5 1.5 0 012.121 0 5.5 5.5 0 010 7.778l-2.828 2.828a5.5 5.5 0 01-7.778 0 5.498 5.498 0 010-7.777l2.828-2.83a1.5 1.5 0 01.355-.262 6.52 6.52 0 00.351 3.799l-1.413 1.414a2.499 2.499 0 000 3.535 2.499 2.499 0 003.535 0l2.83-2.828a2.5 2.5 0 000-3.536 1.5 1.5 0 010-2.121z"/><path d="M12.111 3.89a5.5 5.5 0 117.778 7.777l-2.828 2.829a1.496 1.496 0 01-.355.262 6.522 6.522 0 00-.351-3.8l1.413-1.412a2.5 2.5 0 10-3.536-3.535l-2.828 2.828a2.5 2.5 0 000 3.536 1.5 1.5 0 01-2.122 2.12 5.5 5.5 0 010-7.777l2.83-2.829z"/></svg>
5521
+ </summary>
5522
+ <lexxy-link-dropdown class="lexxy-editor__toolbar-dropdown-content">
5523
+ <form method="dialog">
5524
+ <input type="url" placeholder="Enter a URL…" class="input">
5525
+ <div class="lexxy-editor__toolbar-dropdown-actions">
5526
+ <button type="submit" class="btn" value="link">Link</button>
5527
+ <button type="button" class="btn" value="unlink">Unlink</button>
5528
+ </div>
5529
+ </form>
5530
+ </lexxy-link-dropdown>
5531
+ </details>
5532
+
5533
+ <button class="lexxy-editor__toolbar-button" type="button" name="quote" data-command="insertQuoteBlock" title="Quote">
5534
+ <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M6.5 5C8.985 5 11 7.09 11 9.667c0 2.694-.962 5.005-2.187 6.644-.613.82-1.3 1.481-1.978 1.943-.668.454-1.375.746-2.022.746a.563.563 0 01-.52-.36.602.602 0 01.067-.57l.055-.066.009-.009.041-.048a4.25 4.25 0 00.168-.21c.143-.188.336-.47.53-.84a6.743 6.743 0 00.75-2.605C3.705 13.994 2 12.038 2 9.667 2 7.089 4.015 5 6.5 5zM17.5 5C19.985 5 22 7.09 22 9.667c0 2.694-.962 5.005-2.187 6.644-.613.82-1.3 1.481-1.978 1.943-.668.454-1.375.746-2.023.746a.563.563 0 01-.52-.36.602.602 0 01.068-.57l.055-.066.009-.009.041-.048c.039-.045.097-.115.168-.21a6.16 6.16 0 00.53-.84 6.745 6.745 0 00.75-2.605C14.705 13.994 13 12.038 13 9.667 13 7.089 15.015 5 17.5 5z"/></svg>
5535
+ </button>
5536
+
5537
+ <button class="lexxy-editor__toolbar-button" type="button" name="heading" data-command="rotateHeadingFormat" title="Heading">
5538
+ <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M15.322 5.315H9.64V22H5.684V5.315H0v-3.31h15.322v3.31z"/><path d="M23.957 11.79H19.92V22h-3.402V11.79H12.48V9.137h11.477v2.653z"/></svg>
5539
+ </button>
5540
+
5541
+ <button class="lexxy-editor__toolbar-button" type="button" name="code" data-command="insertCodeBlock" title="Code">
5542
+ <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M10.121 6l-6 6 6 6-2.12 2.121-7.061-7.06a1.5 1.5 0 010-2.121L8 3.879 10.121 6zM23.06 10.94a1.5 1.5 0 010 2.12L16 20.121 13.88 18l6-6-6-6L16 3.879l7.06 7.06z"/></svg>
5543
+ </button>
5544
+
5545
+ <button class="lexxy-editor__toolbar-button" type="button" name="unordered-list" data-command="insertUnorderedList" title="Bullet list">
5546
+ <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M5 5a2 2 0 11-4 0 2 2 0 014 0zM5 12a2 2 0 11-4 0 2 2 0 014 0zM5 19a2 2 0 11-4 0 2 2 0 014 0zM7 5.25C7 4.56 7.56 4 8.25 4h13.5a1.25 1.25 0 110 2.5H8.25C7.56 6.5 7 5.94 7 5.25zM7 12.25c0-.69.56-1.25 1.25-1.25h13.5a1.25 1.25 0 110 2.5H8.25c-.69 0-1.25-.56-1.25-1.25zM7 19.25c0-.69.56-1.25 1.25-1.25h13.5a1.25 1.25 0 110 2.5H8.25c-.69 0-1.25-.56-1.25-1.25z"/></svg>
5547
+ </button>
5548
+
5549
+ <button class="lexxy-editor__toolbar-button" type="button" name="ordered-list" data-command="insertOrderedList" title="Numbered list">
5550
+ <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M7 5.25C7 4.56 7.56 4 8.25 4h13.5a1.25 1.25 0 110 2.5H8.25C7.56 6.5 7 5.94 7 5.25zM7 12.25c0-.69.56-1.25 1.25-1.25h13.5a1.25 1.25 0 110 2.5H8.25c-.69 0-1.25-.56-1.25-1.25zM7 19.25c0-.69.56-1.25 1.25-1.25h13.5a1.25 1.25 0 110 2.5H8.25c-.69 0-1.25-.56-1.25-1.25zM4.438 8H3.39V3.684H3.34c-.133.093-.267.188-.402.285l-.407.289a129.5 129.5 0 00-.402.285v-.969l.633-.453c.21-.15.42-.302.629-.453h1.046V8zM2.672 11.258h-1v-.051c0-.206.036-.405.11-.598.075-.195.188-.37.34-.527.15-.156.339-.281.566-.375.229-.094.498-.14.808-.14.367 0 .688.065.961.195s.484.308.633.535c.15.224.226.478.226.762 0 .244-.046.463-.14.656-.091.19-.209.368-.352.535-.14.164-.289.332-.445.504L3.168 14.09v.05h2.238V15H1.723v-.656l1.949-2.102c.096-.101.19-.207.281-.316.091-.112.167-.232.227-.36a.953.953 0 00.09-.41.712.712 0 00-.387-.648.845.845 0 00-.41-.098.81.81 0 00-.43.11.75.75 0 00-.277.293.824.824 0 00-.094.386V11.258zM2.852 19.66v-.812h.562a.917.917 0 00.43-.098.742.742 0 00.293-.266.673.673 0 00.101-.379.654.654 0 00-.234-.523.87.87 0 00-.59-.2.987.987 0 00-.336.055.837.837 0 00-.258.149.712.712 0 00-.172.215.66.66 0 00-.066.25h-.98c.007-.209.053-.403.136-.582.084-.18.203-.336.36-.469.156-.135.346-.24.57-.316.227-.076.486-.115.777-.118a2.33 2.33 0 01.965.176c.271.12.48.285.63.496.15.209.227.448.23.719a1.11 1.11 0 01-.16.637 1.28 1.28 0 01-.825.586v.054c.162.016.33.07.504.164.177.094.328.232.453.415.125.18.189.411.192.695a1.37 1.37 0 01-.157.676c-.104.197-.25.365-.437.503-.188.136-.404.24-.649.313-.242.07-.5.105-.777.105-.401 0-.743-.067-1.027-.203a1.608 1.608 0 01-.649-.547 1.46 1.46 0 01-.238-.75h.969c.01.128.057.243.14.344a.885.885 0 00.332.238c.141.058.3.088.477.09.195 0 .366-.034.512-.101a.798.798 0 00.336-.29.744.744 0 00.117-.425.74.74 0 00-.446-.695 1.082 1.082 0 00-.496-.106h-.59z"/></svg>
5551
+ </button>
5552
+
5553
+ <button class="lexxy-editor__toolbar-button" type="button" name="upload" data-command="uploadAttachments" title="Upload file">
5554
+ <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M16 8a2 2 0 110 4 2 2 0 010-4z""/><path d="M22 2a1 1 0 011 1v18a1 1 0 01-1 1H2a1 1 0 01-1-1V3a1 1 0 011-1h20zM3 18.714L9 11l5.25 6.75L17 15l4 4V4H3v14.714z"/></svg>
5555
+ </button>
5556
+
5557
+ <button class="lexxy-editor__toolbar-button" type="button" name="divider" data-command="insertHorizontalDivider" title="Insert a divider">
5558
+ <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M0 12C0 11.4477 0.447715 11 1 11H23C23.5523 11 24 11.4477 24 12C24 12.5523 23.5523 13 23 13H1C0.447716 13 0 12.5523 0 12Z"/><path d="M4 5C4 3.89543 4.89543 3 6 3H18C19.1046 3 20 3.89543 20 5C20 6.10457 19.1046 7 18 7H6C4.89543 7 4 6.10457 4 5Z"/><path d="M4 19C4 17.8954 4.89543 17 6 17H18C19.1046 17 20 17.8954 20 19C20 20.1046 19.1046 21 18 21H6C4.89543 21 4 20.1046 4 19Z"/></svg>
5559
+ </button>
5560
+
5561
+ <div class="lexxy-editor__toolbar-spacer" role="separator"></div>
5562
+
5563
+ <button class="lexxy-editor__toolbar-button" type="button" name="undo" data-command="undo" title="Undo" data-hotkey="cmd+z ctrl+z">
5564
+ <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M5.64648 8.26531C7.93911 6.56386 10.7827 5.77629 13.624 6.05535C16.4655 6.33452 19.1018 7.66079 21.0195 9.77605C22.5839 11.5016 23.5799 13.6516 23.8936 15.9352C24.0115 16.7939 23.2974 17.4997 22.4307 17.4997C21.5641 17.4997 20.8766 16.7915 20.7148 15.9401C20.4295 14.4379 19.7348 13.0321 18.6943 11.8844C17.3 10.3464 15.3835 9.38139 13.3174 9.17839C11.2514 8.97546 9.18359 9.54856 7.5166 10.7858C6.38259 11.6275 5.48981 12.7361 4.90723 13.9997H8.5C9.3283 13.9997 9.99979 14.6714 10 15.4997C10 16.3281 9.32843 16.9997 8.5 16.9997H1.5C0.671573 16.9997 0 16.3281 0 15.4997V8.49968C0.000213656 7.67144 0.671705 6.99968 1.5 6.99968C2.3283 6.99968 2.99979 7.67144 3 8.49968V11.0212C3.7166 9.9704 4.60793 9.03613 5.64648 8.26531Z"/></svg>
5565
+ </button>
5566
+
5567
+ <button class="lexxy-editor__toolbar-button" type="button" name="redo" data-command="redo" title="Redo" data-hotkey="cmd+shift+z ctrl+shift+z ctrl+y">
5568
+ <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M18.2599 8.26531C15.9672 6.56386 13.1237 5.77629 10.2823 6.05535C7.4408 6.33452 4.80455 7.66079 2.88681 9.77605C1.32245 11.5016 0.326407 13.6516 0.0127834 15.9352C-0.105117 16.7939 0.608975 17.4997 1.47567 17.4997C2.34228 17.4997 3.02969 16.7915 3.19149 15.9401C3.47682 14.4379 4.17156 13.0321 5.212 11.8844C6.60637 10.3464 8.52287 9.38139 10.589 9.17839C12.655 8.97546 14.7227 9.54856 16.3897 10.7858C17.5237 11.6275 18.4165 12.7361 18.9991 13.9997H15.4063C14.578 13.9997 13.9066 14.6714 13.9063 15.4997C13.9063 16.3281 14.5779 16.9997 15.4063 16.9997H22.4063C23.2348 16.9997 23.9063 16.3281 23.9063 15.4997V8.49968C23.9061 7.67144 23.2346 6.99968 22.4063 6.99968C21.578 6.99968 20.9066 7.67144 20.9063 8.49968V11.0212C20.1897 9.9704 19.2984 9.03613 18.2599 8.26531Z"/></svg>
5569
+ </button>
5570
+
5571
+ <details class="lexxy-editor__toolbar-overflow">
5572
+ <summary class="lexxy-editor__toolbar-button" aria-label="Show more toolbar buttons">•••</summary>
5573
+ <div class="lexxy-editor__toolbar-overflow-menu" aria-label="More toolbar buttons"></div>
5574
+ </details>
5575
+ `
5576
+ }
5577
+ }
5578
+
5579
+ customElements.define("lexxy-toolbar", LexicalToolbarElement);
5580
+
5581
+ /**
5582
+ * Original by Samuel Flores
5583
+ *
5584
+ * Adds the following new token classes:
5585
+ * constant, builtin, variable, symbol, regex
5586
+ */
5587
+ (function (Prism) {
5588
+ Prism.languages.ruby = Prism.languages.extend('clike', {
5589
+ 'comment': {
5590
+ pattern: /#.*|^=begin\s[\s\S]*?^=end/m,
5591
+ greedy: true
5592
+ },
5593
+ 'class-name': {
5594
+ pattern: /(\b(?:class|module)\s+|\bcatch\s+\()[\w.\\]+|\b[A-Z_]\w*(?=\s*\.\s*new\b)/,
5595
+ lookbehind: true,
5596
+ inside: {
5597
+ 'punctuation': /[.\\]/
5598
+ }
5599
+ },
5600
+ '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/,
5601
+ 'operator': /\.{2,3}|&\.|===|<?=>|[!=]?~|(?:&&|\|\||<<|>>|\*\*|[+\-*/%<>!^&|=])=?|[?:]/,
5602
+ 'punctuation': /[(){}[\].,;]/,
5603
+ });
5604
+
5605
+ Prism.languages.insertBefore('ruby', 'operator', {
5606
+ 'double-colon': {
5607
+ pattern: /::/,
5608
+ alias: 'punctuation'
5609
+ },
5610
+ });
5611
+
5612
+ var interpolation = {
5613
+ pattern: /((?:^|[^\\])(?:\\{2})*)#\{(?:[^{}]|\{[^{}]*\})*\}/,
5614
+ lookbehind: true,
5615
+ inside: {
5616
+ 'content': {
5617
+ pattern: /^(#\{)[\s\S]+(?=\}$)/,
5618
+ lookbehind: true,
5619
+ inside: Prism.languages.ruby
5620
+ },
5621
+ 'delimiter': {
5622
+ pattern: /^#\{|\}$/,
5623
+ alias: 'punctuation'
5624
+ }
5625
+ }
5626
+ };
5627
+
5628
+ delete Prism.languages.ruby.function;
5629
+
5630
+ var percentExpression = '(?:' + [
5631
+ /([^a-zA-Z0-9\s{(\[<=])(?:(?!\1)[^\\]|\\[\s\S])*\1/.source,
5632
+ /\((?:[^()\\]|\\[\s\S]|\((?:[^()\\]|\\[\s\S])*\))*\)/.source,
5633
+ /\{(?:[^{}\\]|\\[\s\S]|\{(?:[^{}\\]|\\[\s\S])*\})*\}/.source,
5634
+ /\[(?:[^\[\]\\]|\\[\s\S]|\[(?:[^\[\]\\]|\\[\s\S])*\])*\]/.source,
5635
+ /<(?:[^<>\\]|\\[\s\S]|<(?:[^<>\\]|\\[\s\S])*>)*>/.source
5636
+ ].join('|') + ')';
5637
+
5638
+ var symbolName = /(?:"(?:\\.|[^"\\\r\n])*"|(?:\b[a-zA-Z_]\w*|[^\s\0-\x7F]+)[?!]?|\$.)/.source;
5639
+
5640
+ Prism.languages.insertBefore('ruby', 'keyword', {
5641
+ 'regex-literal': [
5642
+ {
5643
+ pattern: RegExp(/%r/.source + percentExpression + /[egimnosux]{0,6}/.source),
5644
+ greedy: true,
5645
+ inside: {
5646
+ 'interpolation': interpolation,
5647
+ 'regex': /[\s\S]+/
5648
+ }
5649
+ },
5650
+ {
5651
+ pattern: /(^|[^/])\/(?!\/)(?:\[[^\r\n\]]+\]|\\.|[^[/\\\r\n])+\/[egimnosux]{0,6}(?=\s*(?:$|[\r\n,.;})#]))/,
5652
+ lookbehind: true,
5653
+ greedy: true,
5654
+ inside: {
5655
+ 'interpolation': interpolation,
5656
+ 'regex': /[\s\S]+/
5657
+ }
5658
+ }
5659
+ ],
5660
+ 'variable': /[@$]+[a-zA-Z_]\w*(?:[?!]|\b)/,
5661
+ 'symbol': [
5662
+ {
5663
+ pattern: RegExp(/(^|[^:]):/.source + symbolName),
5664
+ lookbehind: true,
5665
+ greedy: true
5666
+ },
5667
+ {
5668
+ pattern: RegExp(/([\r\n{(,][ \t]*)/.source + symbolName + /(?=:(?!:))/.source),
5669
+ lookbehind: true,
5670
+ greedy: true
5671
+ },
5672
+ ],
5673
+ 'method-definition': {
5674
+ pattern: /(\bdef\s+)\w+(?:\s*\.\s*\w+)?/,
5675
+ lookbehind: true,
5676
+ inside: {
5677
+ 'function': /\b\w+$/,
5678
+ 'keyword': /^self\b/,
5679
+ 'class-name': /^\w+/,
5680
+ 'punctuation': /\./
5681
+ }
5682
+ }
5683
+ });
5684
+
5685
+ Prism.languages.insertBefore('ruby', 'string', {
5686
+ 'string-literal': [
5687
+ {
5688
+ pattern: RegExp(/%[qQiIwWs]?/.source + percentExpression),
5689
+ greedy: true,
5690
+ inside: {
5691
+ 'interpolation': interpolation,
5692
+ 'string': /[\s\S]+/
5693
+ }
5694
+ },
5695
+ {
5696
+ pattern: /("|')(?:#\{[^}]+\}|#(?!\{)|\\(?:\r\n|[\s\S])|(?!\1)[^\\#\r\n])*\1/,
5697
+ greedy: true,
5698
+ inside: {
5699
+ 'interpolation': interpolation,
5700
+ 'string': /[\s\S]+/
5701
+ }
5702
+ },
5703
+ {
5704
+ pattern: /<<[-~]?([a-z_]\w*)[\r\n](?:.*[\r\n])*?[\t ]*\1/i,
5705
+ alias: 'heredoc-string',
5706
+ greedy: true,
5707
+ inside: {
5708
+ 'delimiter': {
5709
+ pattern: /^<<[-~]?[a-z_]\w*|\b[a-z_]\w*$/i,
5710
+ inside: {
5711
+ 'symbol': /\b\w+/,
5712
+ 'punctuation': /^<<[-~]?/
5713
+ }
5714
+ },
5715
+ 'interpolation': interpolation,
5716
+ 'string': /[\s\S]+/
5717
+ }
5718
+ },
5719
+ {
5720
+ pattern: /<<[-~]?'([a-z_]\w*)'[\r\n](?:.*[\r\n])*?[\t ]*\1/i,
5721
+ alias: 'heredoc-string',
5722
+ greedy: true,
5723
+ inside: {
5724
+ 'delimiter': {
5725
+ pattern: /^<<[-~]?'[a-z_]\w*'|\b[a-z_]\w*$/i,
5726
+ inside: {
5727
+ 'symbol': /\b\w+/,
5728
+ 'punctuation': /^<<[-~]?'|'$/,
5729
+ }
5730
+ },
5731
+ 'string': /[\s\S]+/
5732
+ }
5733
+ }
5734
+ ],
5735
+ 'command-literal': [
5736
+ {
5737
+ pattern: RegExp(/%x/.source + percentExpression),
5738
+ greedy: true,
5739
+ inside: {
5740
+ 'interpolation': interpolation,
5741
+ 'command': {
5742
+ pattern: /[\s\S]+/,
5743
+ alias: 'string'
5744
+ }
5745
+ }
5746
+ },
5747
+ {
5748
+ pattern: /`(?:#\{[^}]+\}|#(?!\{)|\\(?:\r\n|[\s\S])|[^\\`#\r\n])*`/,
5749
+ greedy: true,
5750
+ inside: {
5751
+ 'interpolation': interpolation,
5752
+ 'command': {
5753
+ pattern: /[\s\S]+/,
5754
+ alias: 'string'
5755
+ }
5756
+ }
5757
+ }
5758
+ ]
5759
+ });
5760
+
5761
+ delete Prism.languages.ruby.string;
5762
+
5763
+ Prism.languages.insertBefore('ruby', 'number', {
5764
+ '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/,
5765
+ 'constant': /\b[A-Z][A-Z0-9_]*(?:[?!]|\b)/
5766
+ });
5767
+
5768
+ Prism.languages.rb = Prism.languages.ruby;
5769
+ }(Prism));
5770
+
5771
+ /**
5772
+ * Original by Aaron Harun: http://aahacreative.com/2012/07/31/php-syntax-highlighting-prism/
5773
+ * Modified by Miles Johnson: http://milesj.me
5774
+ * Rewritten by Tom Pavelec
5775
+ *
5776
+ * Supports PHP 5.3 - 8.0
5777
+ */
5778
+ (function (Prism) {
5779
+ var comment = /\/\*[\s\S]*?\*\/|\/\/.*|#(?!\[).*/;
5780
+ var constant = [
5781
+ {
5782
+ pattern: /\b(?:false|true)\b/i,
5783
+ alias: 'boolean'
5784
+ },
5785
+ {
5786
+ pattern: /(::\s*)\b[a-z_]\w*\b(?!\s*\()/i,
5787
+ greedy: true,
5788
+ lookbehind: true,
5789
+ },
5790
+ {
5791
+ pattern: /(\b(?:case|const)\s+)\b[a-z_]\w*(?=\s*[;=])/i,
5792
+ greedy: true,
5793
+ lookbehind: true,
5794
+ },
5795
+ /\b(?:null)\b/i,
5796
+ /\b[A-Z_][A-Z0-9_]*\b(?!\s*\()/,
5797
+ ];
5798
+ 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;
5799
+ var operator = /<?=>|\?\?=?|\.{3}|\??->|[!=]=?=?|::|\*\*=?|--|\+\+|&&|\|\||<<|>>|[?~]|[/^|%*&<>.+-]=?/;
5800
+ var punctuation = /[{}\[\](),:;]/;
5801
+
5802
+ Prism.languages.php = {
5803
+ 'delimiter': {
5804
+ pattern: /\?>$|^<\?(?:php(?=\s)|=)?/i,
5805
+ alias: 'important'
5806
+ },
5807
+ 'comment': comment,
5808
+ 'variable': /\$+(?:\w+\b|(?=\{))/,
5809
+ 'package': {
5810
+ pattern: /(namespace\s+|use\s+(?:function\s+)?)(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,
5811
+ lookbehind: true,
5812
+ inside: {
5813
+ 'punctuation': /\\/
5814
+ }
5815
+ },
5816
+ 'class-name-definition': {
5817
+ pattern: /(\b(?:class|enum|interface|trait)\s+)\b[a-z_]\w*(?!\\)\b/i,
5818
+ lookbehind: true,
5819
+ alias: 'class-name'
5820
+ },
5821
+ 'function-definition': {
5822
+ pattern: /(\bfunction\s+)[a-z_]\w*(?=\s*\()/i,
5823
+ lookbehind: true,
5824
+ alias: 'function'
5825
+ },
5826
+ 'keyword': [
5827
+ {
5828
+ pattern: /(\(\s*)\b(?:array|bool|boolean|float|int|integer|object|string)\b(?=\s*\))/i,
5829
+ alias: 'type-casting',
5830
+ greedy: true,
5831
+ lookbehind: true
5832
+ },
5833
+ {
5834
+ pattern: /([(,?]\s*)\b(?:array(?!\s*\()|bool|callable|(?:false|null)(?=\s*\|)|float|int|iterable|mixed|object|self|static|string)\b(?=\s*\$)/i,
5835
+ alias: 'type-hint',
5836
+ greedy: true,
5837
+ lookbehind: true
5838
+ },
5839
+ {
5840
+ pattern: /(\)\s*:\s*(?:\?\s*)?)\b(?:array(?!\s*\()|bool|callable|(?:false|null)(?=\s*\|)|float|int|iterable|mixed|never|object|self|static|string|void)\b/i,
5841
+ alias: 'return-type',
5842
+ greedy: true,
5843
+ lookbehind: true
5844
+ },
5845
+ {
5846
+ pattern: /\b(?:array(?!\s*\()|bool|float|int|iterable|mixed|object|string|void)\b/i,
5847
+ alias: 'type-declaration',
5848
+ greedy: true
5849
+ },
5850
+ {
5851
+ pattern: /(\|\s*)(?:false|null)\b|\b(?:false|null)(?=\s*\|)/i,
5852
+ alias: 'type-declaration',
5853
+ greedy: true,
5854
+ lookbehind: true
5855
+ },
5856
+ {
5857
+ pattern: /\b(?:parent|self|static)(?=\s*::)/i,
5858
+ alias: 'static-context',
5859
+ greedy: true
5860
+ },
5861
+ {
5862
+ // yield from
5863
+ pattern: /(\byield\s+)from\b/i,
5864
+ lookbehind: true
5865
+ },
5866
+ // `class` is always a keyword unlike other keywords
5867
+ /\bclass\b/i,
5868
+ {
5869
+ // https://www.php.net/manual/en/reserved.keywords.php
5870
+ //
5871
+ // keywords cannot be preceded by "->"
5872
+ // the complex lookbehind means `(?<!(?:->|::)\s*)`
5873
+ 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,
5874
+ lookbehind: true
5875
+ }
5876
+ ],
5877
+ 'argument-name': {
5878
+ pattern: /([(,]\s*)\b[a-z_]\w*(?=\s*:(?!:))/i,
5879
+ lookbehind: true
5880
+ },
5881
+ 'class-name': [
5882
+ {
5883
+ pattern: /(\b(?:extends|implements|instanceof|new(?!\s+self|\s+static))\s+|\bcatch\s*\()\b[a-z_]\w*(?!\\)\b/i,
5884
+ greedy: true,
5885
+ lookbehind: true
5886
+ },
5887
+ {
5888
+ pattern: /(\|\s*)\b[a-z_]\w*(?!\\)\b/i,
5889
+ greedy: true,
5890
+ lookbehind: true
5891
+ },
5892
+ {
5893
+ pattern: /\b[a-z_]\w*(?!\\)\b(?=\s*\|)/i,
5894
+ greedy: true
5895
+ },
5896
+ {
5897
+ pattern: /(\|\s*)(?:\\?\b[a-z_]\w*)+\b/i,
5898
+ alias: 'class-name-fully-qualified',
5899
+ greedy: true,
5900
+ lookbehind: true,
5901
+ inside: {
5902
+ 'punctuation': /\\/
5903
+ }
5904
+ },
5905
+ {
5906
+ pattern: /(?:\\?\b[a-z_]\w*)+\b(?=\s*\|)/i,
5907
+ alias: 'class-name-fully-qualified',
5908
+ greedy: true,
5909
+ inside: {
5910
+ 'punctuation': /\\/
5911
+ }
5912
+ },
5913
+ {
5914
+ pattern: /(\b(?:extends|implements|instanceof|new(?!\s+self\b|\s+static\b))\s+|\bcatch\s*\()(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,
5915
+ alias: 'class-name-fully-qualified',
5916
+ greedy: true,
5917
+ lookbehind: true,
5918
+ inside: {
5919
+ 'punctuation': /\\/
5920
+ }
5921
+ },
5922
+ {
5923
+ pattern: /\b[a-z_]\w*(?=\s*\$)/i,
5924
+ alias: 'type-declaration',
5925
+ greedy: true
5926
+ },
5927
+ {
5928
+ pattern: /(?:\\?\b[a-z_]\w*)+(?=\s*\$)/i,
5929
+ alias: ['class-name-fully-qualified', 'type-declaration'],
5930
+ greedy: true,
5931
+ inside: {
5932
+ 'punctuation': /\\/
5933
+ }
5934
+ },
5935
+ {
5936
+ pattern: /\b[a-z_]\w*(?=\s*::)/i,
5937
+ alias: 'static-context',
5938
+ greedy: true
5939
+ },
5940
+ {
5941
+ pattern: /(?:\\?\b[a-z_]\w*)+(?=\s*::)/i,
5942
+ alias: ['class-name-fully-qualified', 'static-context'],
5943
+ greedy: true,
5944
+ inside: {
5945
+ 'punctuation': /\\/
5946
+ }
5947
+ },
5948
+ {
5949
+ pattern: /([(,?]\s*)[a-z_]\w*(?=\s*\$)/i,
5950
+ alias: 'type-hint',
5951
+ greedy: true,
5952
+ lookbehind: true
5953
+ },
5954
+ {
5955
+ pattern: /([(,?]\s*)(?:\\?\b[a-z_]\w*)+(?=\s*\$)/i,
5956
+ alias: ['class-name-fully-qualified', 'type-hint'],
5957
+ greedy: true,
5958
+ lookbehind: true,
5959
+ inside: {
5960
+ 'punctuation': /\\/
5961
+ }
5962
+ },
5963
+ {
5964
+ pattern: /(\)\s*:\s*(?:\?\s*)?)\b[a-z_]\w*(?!\\)\b/i,
5965
+ alias: 'return-type',
5966
+ greedy: true,
5967
+ lookbehind: true
5968
+ },
5969
+ {
5970
+ pattern: /(\)\s*:\s*(?:\?\s*)?)(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,
5971
+ alias: ['class-name-fully-qualified', 'return-type'],
5972
+ greedy: true,
5973
+ lookbehind: true,
5974
+ inside: {
5975
+ 'punctuation': /\\/
5976
+ }
5977
+ }
5978
+ ],
5979
+ 'constant': constant,
5980
+ 'function': {
5981
+ pattern: /(^|[^\\\w])\\?[a-z_](?:[\w\\]*\w)?(?=\s*\()/i,
5982
+ lookbehind: true,
5983
+ inside: {
5984
+ 'punctuation': /\\/
5985
+ }
5986
+ },
5987
+ 'property': {
5988
+ pattern: /(->\s*)\w+/,
5989
+ lookbehind: true
5990
+ },
5991
+ 'number': number,
5992
+ 'operator': operator,
5993
+ 'punctuation': punctuation
5994
+ };
5995
+
5996
+ var string_interpolation = {
5997
+ pattern: /\{\$(?:\{(?:\{[^{}]+\}|[^{}]+)\}|[^{}])+\}|(^|[^\\{])\$+(?:\w+(?:\[[^\r\n\[\]]+\]|->\w+)?)/,
5998
+ lookbehind: true,
5999
+ inside: Prism.languages.php
6000
+ };
6001
+
6002
+ var string = [
6003
+ {
6004
+ pattern: /<<<'([^']+)'[\r\n](?:.*[\r\n])*?\1;/,
6005
+ alias: 'nowdoc-string',
6006
+ greedy: true,
6007
+ inside: {
6008
+ 'delimiter': {
6009
+ pattern: /^<<<'[^']+'|[a-z_]\w*;$/i,
6010
+ alias: 'symbol',
6011
+ inside: {
6012
+ 'punctuation': /^<<<'?|[';]$/
6013
+ }
6014
+ }
6015
+ }
6016
+ },
6017
+ {
6018
+ pattern: /<<<(?:"([^"]+)"[\r\n](?:.*[\r\n])*?\1;|([a-z_]\w*)[\r\n](?:.*[\r\n])*?\2;)/i,
6019
+ alias: 'heredoc-string',
6020
+ greedy: true,
6021
+ inside: {
6022
+ 'delimiter': {
6023
+ pattern: /^<<<(?:"[^"]+"|[a-z_]\w*)|[a-z_]\w*;$/i,
6024
+ alias: 'symbol',
6025
+ inside: {
6026
+ 'punctuation': /^<<<"?|[";]$/
6027
+ }
6028
+ },
6029
+ 'interpolation': string_interpolation
6030
+ }
6031
+ },
6032
+ {
6033
+ pattern: /`(?:\\[\s\S]|[^\\`])*`/,
6034
+ alias: 'backtick-quoted-string',
6035
+ greedy: true
6036
+ },
6037
+ {
6038
+ pattern: /'(?:\\[\s\S]|[^\\'])*'/,
6039
+ alias: 'single-quoted-string',
6040
+ greedy: true
6041
+ },
6042
+ {
6043
+ pattern: /"(?:\\[\s\S]|[^\\"])*"/,
6044
+ alias: 'double-quoted-string',
6045
+ greedy: true,
6046
+ inside: {
6047
+ 'interpolation': string_interpolation
6048
+ }
6049
+ }
6050
+ ];
6051
+
6052
+ Prism.languages.insertBefore('php', 'variable', {
6053
+ 'string': string,
6054
+ 'attribute': {
6055
+ pattern: /#\[(?:[^"'\/#]|\/(?![*/])|\/\/.*$|#(?!\[).*$|\/\*(?:[^*]|\*(?!\/))*\*\/|"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*')+\](?=\s*[a-z$#])/im,
6056
+ greedy: true,
6057
+ inside: {
6058
+ 'attribute-content': {
6059
+ pattern: /^(#\[)[\s\S]+(?=\]$)/,
6060
+ lookbehind: true,
6061
+ // inside can appear subset of php
6062
+ inside: {
6063
+ 'comment': comment,
6064
+ 'string': string,
6065
+ 'attribute-class-name': [
6066
+ {
6067
+ pattern: /([^:]|^)\b[a-z_]\w*(?!\\)\b/i,
6068
+ alias: 'class-name',
6069
+ greedy: true,
6070
+ lookbehind: true
6071
+ },
6072
+ {
6073
+ pattern: /([^:]|^)(?:\\?\b[a-z_]\w*)+/i,
6074
+ alias: [
6075
+ 'class-name',
6076
+ 'class-name-fully-qualified'
6077
+ ],
6078
+ greedy: true,
6079
+ lookbehind: true,
6080
+ inside: {
6081
+ 'punctuation': /\\/
6082
+ }
6083
+ }
6084
+ ],
6085
+ 'constant': constant,
6086
+ 'number': number,
6087
+ 'operator': operator,
6088
+ 'punctuation': punctuation
6089
+ }
6090
+ },
6091
+ 'delimiter': {
6092
+ pattern: /^#\[|\]$/,
6093
+ alias: 'punctuation'
6094
+ }
6095
+ }
6096
+ },
6097
+ });
6098
+
6099
+ Prism.hooks.add('before-tokenize', function (env) {
6100
+ if (!/<\?/.test(env.code)) {
6101
+ return;
6102
+ }
6103
+
6104
+ var phpPattern = /<\?(?:[^"'/#]|\/(?![*/])|("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|(?:\/\/|#(?!\[))(?:[^?\n\r]|\?(?!>))*(?=$|\?>|[\r\n])|#\[|\/\*(?:[^*]|\*(?!\/))*(?:\*\/|$))*?(?:\?>|$)/g;
6105
+ Prism.languages['markup-templating'].buildPlaceholders(env, 'php', phpPattern);
6106
+ });
6107
+
6108
+ Prism.hooks.add('after-tokenize', function (env) {
6109
+ Prism.languages['markup-templating'].tokenizePlaceholders(env, 'php');
6110
+ });
6111
+
6112
+ }(Prism));
6113
+
6114
+ Prism.languages.go = Prism.languages.extend('clike', {
6115
+ 'string': {
6116
+ pattern: /(^|[^\\])"(?:\\.|[^"\\\r\n])*"|`[^`]*`/,
6117
+ lookbehind: true,
6118
+ greedy: true
6119
+ },
6120
+ '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/,
6121
+ 'boolean': /\b(?:_|false|iota|nil|true)\b/,
6122
+ 'number': [
6123
+ // binary and octal integers
6124
+ /\b0(?:b[01_]+|o[0-7_]+)i?\b/i,
6125
+ // hexadecimal integers and floats
6126
+ /\b0x(?:[a-f\d_]+(?:\.[a-f\d_]*)?|\.[a-f\d_]+)(?:p[+-]?\d+(?:_\d+)*)?i?(?!\w)/i,
6127
+ // decimal integers and floats
6128
+ /(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?[\d_]+)?i?(?!\w)/i
6129
+ ],
6130
+ 'operator': /[*\/%^!=]=?|\+[=+]?|-[=-]?|\|[=|]?|&(?:=|&|\^=?)?|>(?:>=?|=)?|<(?:<=?|=|-)?|:=|\.\.\./,
6131
+ '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/
6132
+ });
5453
6133
 
5454
- for (const button of buttons) {
5455
- if (this.#toolbarIsOverflowing()) {
5456
- this.#overflowMenu.prepend(button);
5457
- movedToOverflow = true;
5458
- } else {
5459
- if (movedToOverflow) this.#overflowMenu.prepend(button);
5460
- break
5461
- }
5462
- }
5463
- }
6134
+ Prism.languages.insertBefore('go', 'string', {
6135
+ 'char': {
6136
+ pattern: /'(?:\\.|[^'\\\r\n]){0,10}'/,
6137
+ greedy: true
6138
+ }
6139
+ });
5464
6140
 
5465
- get #buttons() {
5466
- return Array.from(this.querySelectorAll(":scope > button"))
5467
- }
6141
+ delete Prism.languages.go['class-name'];
5468
6142
 
5469
- get #buttonsWithSeparator() {
5470
- return Array.from(this.querySelectorAll(":scope > button, :scope > [role=separator]"))
5471
- }
6143
+ (function (Prism) {
6144
+ // $ set | grep '^[A-Z][^[:space:]]*=' | cut -d= -f1 | tr '\n' '|'
6145
+ // + LC_ALL, RANDOM, REPLY, SECONDS.
6146
+ // + make sure PS1..4 are here as they are not always set,
6147
+ // - some useless things.
6148
+ 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';
6149
+
6150
+ var commandAfterHeredoc = {
6151
+ pattern: /(^(["']?)\w+\2)[ \t]+\S.*/,
6152
+ lookbehind: true,
6153
+ alias: 'punctuation', // this looks reasonably well in all themes
6154
+ inside: null // see below
6155
+ };
5472
6156
 
5473
- static get defaultTemplate() {
5474
- return `
5475
- <button class="lexxy-editor__toolbar-button" type="button" name="bold" data-command="bold" title="Bold">
5476
- <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M5 22V2h8.183c1.764 0 3.174.435 4.228 1.304 1.055.87 1.582 2.076 1.582 3.62 0 .8-.148 1.503-.445 2.109a3.94 3.94 0 01-1.194 1.465 4.866 4.866 0 01-1.726.806v.176c.786.078 1.51.312 2.172.703a4.293 4.293 0 011.596 1.627c.403.693.604 1.543.604 2.549 0 1.192-.292 2.207-.877 3.048-.585.84-1.39 1.484-2.416 1.934-1.026.44-2.206.659-3.538.659H5zM8.854 4.974v5.348h2.56c.873 0 1.582-.107 2.129-.322.556-.215.963-.523 1.222-.923.269-.41.403-.904.403-1.48 0-.82-.254-1.46-.762-1.92-.499-.468-1.204-.703-2.115-.703H8.854zm0 8.103v5.949h2.877c1.534 0 2.636-.245 3.307-.733.671-.498 1.007-1.221 1.007-2.168 0-.635-.134-1.178-.403-1.627-.268-.459-.666-.81-1.193-1.055-.518-.244-1.156-.366-1.913-.366H8.854z"/></svg>
5477
- </button>
6157
+ var insideString = {
6158
+ 'bash': commandAfterHeredoc,
6159
+ 'environment': {
6160
+ pattern: RegExp('\\$' + envVars),
6161
+ alias: 'constant'
6162
+ },
6163
+ 'variable': [
6164
+ // [0]: Arithmetic Environment
6165
+ {
6166
+ pattern: /\$?\(\([\s\S]+?\)\)/,
6167
+ greedy: true,
6168
+ inside: {
6169
+ // If there is a $ sign at the beginning highlight $(( and )) as variable
6170
+ 'variable': [
6171
+ {
6172
+ pattern: /(^\$\(\([\s\S]+)\)\)/,
6173
+ lookbehind: true
6174
+ },
6175
+ /^\$\(\(/
6176
+ ],
6177
+ 'number': /\b0x[\dA-Fa-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee]-?\d+)?/,
6178
+ // Operators according to https://www.gnu.org/software/bash/manual/bashref.html#Shell-Arithmetic
6179
+ 'operator': /--|\+\+|\*\*=?|<<=?|>>=?|&&|\|\||[=!+\-*/%<>^&|]=?|[?~:]/,
6180
+ // If there is no $ sign at the beginning highlight (( and )) as punctuation
6181
+ 'punctuation': /\(\(?|\)\)?|,|;/
6182
+ }
6183
+ },
6184
+ // [1]: Command Substitution
6185
+ {
6186
+ pattern: /\$\((?:\([^)]+\)|[^()])+\)|`[^`]+`/,
6187
+ greedy: true,
6188
+ inside: {
6189
+ 'variable': /^\$\(|^`|\)$|`$/
6190
+ }
6191
+ },
6192
+ // [2]: Brace expansion
6193
+ {
6194
+ pattern: /\$\{[^}]+\}/,
6195
+ greedy: true,
6196
+ inside: {
6197
+ 'operator': /:[-=?+]?|[!\/]|##?|%%?|\^\^?|,,?/,
6198
+ 'punctuation': /[\[\]]/,
6199
+ 'environment': {
6200
+ pattern: RegExp('(\\{)' + envVars),
6201
+ lookbehind: true,
6202
+ alias: 'constant'
6203
+ }
6204
+ }
6205
+ },
6206
+ /\$(?:\w+|[#?*!@$])/
6207
+ ],
6208
+ // Escape sequences from echo and printf's manuals, and escaped quotes.
6209
+ '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})/
6210
+ };
5478
6211
 
5479
- <button class="lexxy-editor__toolbar-button" type="button" name="italic" data-command="italic" title="Italic">
5480
- <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M17.1 4h-1.5l-3.2 16h1.5l-.4 2h-7l.4-2h1.5l3.2-16h-1.5l.4-2h7l-.4 2z"/></svg>
5481
- </button>
6212
+ Prism.languages.bash = {
6213
+ 'shebang': {
6214
+ pattern: /^#!\s*\/.*/,
6215
+ alias: 'important'
6216
+ },
6217
+ 'comment': {
6218
+ pattern: /(^|[^"{\\$])#.*/,
6219
+ lookbehind: true
6220
+ },
6221
+ 'function-name': [
6222
+ // a) function foo {
6223
+ // b) foo() {
6224
+ // c) function foo() {
6225
+ // but not “foo {”
6226
+ {
6227
+ // a) and c)
6228
+ pattern: /(\bfunction\s+)[\w-]+(?=(?:\s*\(?:\s*\))?\s*\{)/,
6229
+ lookbehind: true,
6230
+ alias: 'function'
6231
+ },
6232
+ {
6233
+ // b)
6234
+ pattern: /\b[\w-]+(?=\s*\(\s*\)\s*\{)/,
6235
+ alias: 'function'
6236
+ }
6237
+ ],
6238
+ // Highlight variable names as variables in for and select beginnings.
6239
+ 'for-or-select': {
6240
+ pattern: /(\b(?:for|select)\s+)\w+(?=\s+in\s)/,
6241
+ alias: 'variable',
6242
+ lookbehind: true
6243
+ },
6244
+ // Highlight variable names as variables in the left-hand part
6245
+ // of assignments (“=” and “+=”).
6246
+ 'assign-left': {
6247
+ pattern: /(^|[\s;|&]|[<>]\()\w+(?:\.\w+)*(?=\+?=)/,
6248
+ inside: {
6249
+ 'environment': {
6250
+ pattern: RegExp('(^|[\\s;|&]|[<>]\\()' + envVars),
6251
+ lookbehind: true,
6252
+ alias: 'constant'
6253
+ }
6254
+ },
6255
+ alias: 'variable',
6256
+ lookbehind: true
6257
+ },
6258
+ // Highlight parameter names as variables
6259
+ 'parameter': {
6260
+ pattern: /(^|\s)-{1,2}(?:\w+:[+-]?)?\w+(?:\.\w+)*(?=[=\s]|$)/,
6261
+ alias: 'variable',
6262
+ lookbehind: true
6263
+ },
6264
+ 'string': [
6265
+ // Support for Here-documents https://en.wikipedia.org/wiki/Here_document
6266
+ {
6267
+ pattern: /((?:^|[^<])<<-?\s*)(\w+)\s[\s\S]*?(?:\r?\n|\r)\2/,
6268
+ lookbehind: true,
6269
+ greedy: true,
6270
+ inside: insideString
6271
+ },
6272
+ // Here-document with quotes around the tag
6273
+ // → No expansion (so no “inside”).
6274
+ {
6275
+ pattern: /((?:^|[^<])<<-?\s*)(["'])(\w+)\2\s[\s\S]*?(?:\r?\n|\r)\3/,
6276
+ lookbehind: true,
6277
+ greedy: true,
6278
+ inside: {
6279
+ 'bash': commandAfterHeredoc
6280
+ }
6281
+ },
6282
+ // “Normal” string
6283
+ {
6284
+ // https://www.gnu.org/software/bash/manual/html_node/Double-Quotes.html
6285
+ pattern: /(^|[^\\](?:\\\\)*)"(?:\\[\s\S]|\$\([^)]+\)|\$(?!\()|`[^`]+`|[^"\\`$])*"/,
6286
+ lookbehind: true,
6287
+ greedy: true,
6288
+ inside: insideString
6289
+ },
6290
+ {
6291
+ // https://www.gnu.org/software/bash/manual/html_node/Single-Quotes.html
6292
+ pattern: /(^|[^$\\])'[^']*'/,
6293
+ lookbehind: true,
6294
+ greedy: true
6295
+ },
6296
+ {
6297
+ // https://www.gnu.org/software/bash/manual/html_node/ANSI_002dC-Quoting.html
6298
+ pattern: /\$'(?:[^'\\]|\\[\s\S])*'/,
6299
+ greedy: true,
6300
+ inside: {
6301
+ 'entity': insideString.entity
6302
+ }
6303
+ }
6304
+ ],
6305
+ 'environment': {
6306
+ pattern: RegExp('\\$?' + envVars),
6307
+ alias: 'constant'
6308
+ },
6309
+ 'variable': insideString.variable,
6310
+ 'function': {
6311
+ 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;|&])/,
6312
+ lookbehind: true
6313
+ },
6314
+ 'keyword': {
6315
+ pattern: /(^|[\s;|&]|[<>]\()(?:case|do|done|elif|else|esac|fi|for|function|if|in|select|then|until|while)(?=$|[)\s;|&])/,
6316
+ lookbehind: true
6317
+ },
6318
+ // https://www.gnu.org/software/bash/manual/html_node/Shell-Builtin-Commands.html
6319
+ 'builtin': {
6320
+ 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;|&])/,
6321
+ lookbehind: true,
6322
+ // Alias added to make those easier to distinguish from strings.
6323
+ alias: 'class-name'
6324
+ },
6325
+ 'boolean': {
6326
+ pattern: /(^|[\s;|&]|[<>]\()(?:false|true)(?=$|[)\s;|&])/,
6327
+ lookbehind: true
6328
+ },
6329
+ 'file-descriptor': {
6330
+ pattern: /\B&\d\b/,
6331
+ alias: 'important'
6332
+ },
6333
+ 'operator': {
6334
+ // Lots of redirections here, but not just that.
6335
+ pattern: /\d?<>|>\||\+=|=[=~]?|!=?|<<[<-]?|[&\d]?>>|\d[<>]&?|[<>][&=]?|&[>&]?|\|[&|]?/,
6336
+ inside: {
6337
+ 'file-descriptor': {
6338
+ pattern: /^\d/,
6339
+ alias: 'important'
6340
+ }
6341
+ }
6342
+ },
6343
+ 'punctuation': /\$?\(\(?|\)\)?|\.\.|[{}[\];\\]/,
6344
+ 'number': {
6345
+ pattern: /(^|\s)(?:[1-9]\d*|0)(?:[.,]\d+)?\b/,
6346
+ lookbehind: true
6347
+ }
6348
+ };
5482
6349
 
5483
- <button class="lexxy-editor__toolbar-button" type="button" name="strikethrough" data-command="strikethrough" title="Strikethrough">
5484
- <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
5485
- <path fill-rule="evenodd" clip-rule="evenodd" d="M4.70588 16.1591C4.81459 19.7901 7.48035 22 11.6668 22C15.9854 22 18.724 19.6296 18.724 15.8779C18.724 15.5007 18.6993 15.1427 18.6474 14.8066H14.3721C14.8637 15.2085 15.0799 15.7037 15.0799 16.3471C15.0799 17.7668 13.7532 18.7984 11.8113 18.7984C9.88053 18.7984 8.38582 17.7531 8.21659 16.1591H4.70588ZM5.23953 9.31962H9.88794C9.10723 8.88889 8.75888 8.33882 8.75888 7.57339C8.75888 6.13992 9.96576 5.18793 11.7631 5.18793C13.5852 5.18793 14.8761 6.1797 14.9959 7.81344H18.4102C18.3485 4.31824 15.8038 2 11.752 2C7.867 2 5.09129 4.35802 5.09129 7.92044C5.09129 8.41838 5.14071 8.88477 5.23953 9.31962ZM2.23529 10.6914C1.90767 10.6914 1.59347 10.8359 1.36181 11.0931C1.13015 11.3504 1 11.6993 1 12.0631C1 12.4269 1.13015 12.7758 1.36181 13.0331C1.59347 13.2903 1.90767 13.4348 2.23529 13.4348H20.7647C21.0923 13.4348 21.4065 13.2903 21.6382 13.0331C21.8699 12.7758 22 12.4269 22 12.0631C22 11.6993 21.8699 11.3504 21.6382 11.0931C21.4065 10.8359 21.0923 10.6914 20.7647 10.6914H2.23529Z"/>
5486
- </svg>
5487
- </button>
6350
+ commandAfterHeredoc.inside = Prism.languages.bash;
6351
+
6352
+ /* Patterns in command substitution. */
6353
+ var toBeCopied = [
6354
+ 'comment',
6355
+ 'function-name',
6356
+ 'for-or-select',
6357
+ 'assign-left',
6358
+ 'parameter',
6359
+ 'string',
6360
+ 'environment',
6361
+ 'function',
6362
+ 'keyword',
6363
+ 'builtin',
6364
+ 'boolean',
6365
+ 'file-descriptor',
6366
+ 'operator',
6367
+ 'punctuation',
6368
+ 'number'
6369
+ ];
6370
+ var inside = insideString.variable[1].inside;
6371
+ for (var i = 0; i < toBeCopied.length; i++) {
6372
+ inside[toBeCopied[i]] = Prism.languages.bash[toBeCopied[i]];
6373
+ }
5488
6374
 
5489
- <lexxy-highlight-dialog class="lexxy-dialog lexxy-highlight-dialog">
5490
- <dialog class="highlight-dialog">
5491
- <div class="lexxy-highlight-dialog-content">
5492
- <div data-button-group="color" data-values="var(--highlight-1); var(--highlight-2); var(--highlight-3); var(--highlight-4); var(--highlight-5); var(--highlight-6); var(--highlight-7); var(--highlight-8); var(--highlight-9)"></div>
5493
- <div data-button-group="background-color" data-values="var(--highlight-bg-1); var(--highlight-bg-2); var(--highlight-bg-3); var(--highlight-bg-4); var(--highlight-bg-5); var(--highlight-bg-6); var(--highlight-bg-7); var(--highlight-bg-8); var(--highlight-bg-9)"></div>
5494
- <button data-command="removeHighlight" class="lexxy-highlight-dialog-reset">Remove all coloring</button>
5495
- </div>
5496
- </dialog>
5497
- </lexxy-highlight-dialog>
5498
-
5499
- <button class="lexxy-editor__toolbar-button" type="button" name="highlight" title="Color highlight" data-dialog-target="highlight-dialog">
5500
- <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M7.65422 0.711575C7.1856 0.242951 6.42579 0.242951 5.95717 0.711575C5.48853 1.18021 5.48853 1.94 5.95717 2.40864L8.70864 5.16011L2.85422 11.0145C1.44834 12.4204 1.44833 14.6998 2.85422 16.1057L7.86011 21.1115C9.26599 22.5174 11.5454 22.5174 12.9513 21.1115L19.6542 14.4087C20.1228 13.94 20.1228 13.1802 19.6542 12.7115L11.8544 4.91171L11.2542 4.31158L7.65422 0.711575ZM4.55127 12.7115L10.4057 6.85716L17.1087 13.56H4.19981C4.19981 13.253 4.31696 12.9459 4.55127 12.7115ZM23.6057 20.76C23.6057 22.0856 22.5311 23.16 21.2057 23.16C19.8802 23.16 18.8057 22.0856 18.8057 20.76C18.8057 19.5408 19.8212 18.5339 20.918 17.4462C21.0135 17.3516 21.1096 17.2563 21.2057 17.16C21.3018 17.2563 21.398 17.3516 21.4935 17.4462C22.5903 18.5339 23.6057 19.5408 23.6057 20.76Z"/></svg>
5501
- </button>
6375
+ Prism.languages.sh = Prism.languages.bash;
6376
+ Prism.languages.shell = Prism.languages.bash;
6377
+ }(Prism));
5502
6378
 
5503
- <lexxy-link-dialog class="lexxy-dialog lexxy-link-dialog">
5504
- <dialog class="link-dialog">
5505
- <form method="dialog">
5506
- <input type="url" placeholder="Enter a URL…" class="input" required>
5507
- <div class="lexxy-dialog-actions">
5508
- <button type="submit" class="btn" value="link">Link</button>
5509
- <button type="button" class="btn" value="unlink">Unlink</button>
5510
- </div>
5511
- </form>
5512
- </dialog>
5513
- </lexxy-link-dialog>
6379
+ // https://www.json.org/json-en.html
6380
+ Prism.languages.json = {
6381
+ 'property': {
6382
+ pattern: /(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?=\s*:)/,
6383
+ lookbehind: true,
6384
+ greedy: true
6385
+ },
6386
+ 'string': {
6387
+ pattern: /(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?!\s*:)/,
6388
+ lookbehind: true,
6389
+ greedy: true
6390
+ },
6391
+ 'comment': {
6392
+ pattern: /\/\/.*|\/\*[\s\S]*?(?:\*\/|$)/,
6393
+ greedy: true
6394
+ },
6395
+ 'number': /-?\b\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,
6396
+ 'punctuation': /[{}[\],]/,
6397
+ 'operator': /:/,
6398
+ 'boolean': /\b(?:false|true)\b/,
6399
+ 'null': {
6400
+ pattern: /\bnull\b/,
6401
+ alias: 'keyword'
6402
+ }
6403
+ };
5514
6404
 
5515
- <button class="lexxy-editor__toolbar-button" type="button" name="link" title="Link" data-dialog-target="link-dialog" data-hotkey="cmd+k ctrl+k">
5516
- <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12.111 9.546a1.5 1.5 0 012.121 0 5.5 5.5 0 010 7.778l-2.828 2.828a5.5 5.5 0 01-7.778 0 5.498 5.498 0 010-7.777l2.828-2.83a1.5 1.5 0 01.355-.262 6.52 6.52 0 00.351 3.799l-1.413 1.414a2.499 2.499 0 000 3.535 2.499 2.499 0 003.535 0l2.83-2.828a2.5 2.5 0 000-3.536 1.5 1.5 0 010-2.121z"/><path d="M12.111 3.89a5.5 5.5 0 117.778 7.777l-2.828 2.829a1.496 1.496 0 01-.355.262 6.522 6.522 0 00-.351-3.8l1.413-1.412a2.5 2.5 0 10-3.536-3.535l-2.828 2.828a2.5 2.5 0 000 3.536 1.5 1.5 0 01-2.122 2.12 5.5 5.5 0 010-7.777l2.83-2.829z"/></svg>
5517
- </button>
6405
+ Prism.languages.webmanifest = Prism.languages.json;
5518
6406
 
5519
- <button class="lexxy-editor__toolbar-button" type="button" name="quote" data-command="insertQuoteBlock" title="Quote">
5520
- <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M6.5 5C8.985 5 11 7.09 11 9.667c0 2.694-.962 5.005-2.187 6.644-.613.82-1.3 1.481-1.978 1.943-.668.454-1.375.746-2.022.746a.563.563 0 01-.52-.36.602.602 0 01.067-.57l.055-.066.009-.009.041-.048a4.25 4.25 0 00.168-.21c.143-.188.336-.47.53-.84a6.743 6.743 0 00.75-2.605C3.705 13.994 2 12.038 2 9.667 2 7.089 4.015 5 6.5 5zM17.5 5C19.985 5 22 7.09 22 9.667c0 2.694-.962 5.005-2.187 6.644-.613.82-1.3 1.481-1.978 1.943-.668.454-1.375.746-2.023.746a.563.563 0 01-.52-.36.602.602 0 01.068-.57l.055-.066.009-.009.041-.048c.039-.045.097-.115.168-.21a6.16 6.16 0 00.53-.84 6.745 6.745 0 00.75-2.605C14.705 13.994 13 12.038 13 9.667 13 7.089 15.015 5 17.5 5z"/></svg>
5521
- </button>
6407
+ (function (Prism) {
5522
6408
 
5523
- <button class="lexxy-editor__toolbar-button" type="button" name="heading" data-command="rotateHeadingFormat" title="Heading">
5524
- <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M15.322 5.315H9.64V22H5.684V5.315H0v-3.31h15.322v3.31z"/><path d="M23.957 11.79H19.92V22h-3.402V11.79H12.48V9.137h11.477v2.653z"/></svg>
5525
- </button>
6409
+ Prism.languages.diff = {
6410
+ 'coord': [
6411
+ // Match all kinds of coord lines (prefixed by "+++", "---" or "***").
6412
+ /^(?:\*{3}|-{3}|\+{3}).*$/m,
6413
+ // Match "@@ ... @@" coord lines in unified diff.
6414
+ /^@@.*@@$/m,
6415
+ // Match coord lines in normal diff (starts with a number).
6416
+ /^\d.*$/m
6417
+ ]
5526
6418
 
5527
- <button class="lexxy-editor__toolbar-button" type="button" name="code" data-command="insertCodeBlock" title="Code">
5528
- <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M10.121 6l-6 6 6 6-2.12 2.121-7.061-7.06a1.5 1.5 0 010-2.121L8 3.879 10.121 6zM23.06 10.94a1.5 1.5 0 010 2.12L16 20.121 13.88 18l6-6-6-6L16 3.879l7.06 7.06z"/></svg>
5529
- </button>
6419
+ // deleted, inserted, unchanged, diff
6420
+ };
5530
6421
 
5531
- <button class="lexxy-editor__toolbar-button" type="button" name="unordered-list" data-command="insertUnorderedList" title="Bullet list">
5532
- <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M5 5a2 2 0 11-4 0 2 2 0 014 0zM5 12a2 2 0 11-4 0 2 2 0 014 0zM5 19a2 2 0 11-4 0 2 2 0 014 0zM7 5.25C7 4.56 7.56 4 8.25 4h13.5a1.25 1.25 0 110 2.5H8.25C7.56 6.5 7 5.94 7 5.25zM7 12.25c0-.69.56-1.25 1.25-1.25h13.5a1.25 1.25 0 110 2.5H8.25c-.69 0-1.25-.56-1.25-1.25zM7 19.25c0-.69.56-1.25 1.25-1.25h13.5a1.25 1.25 0 110 2.5H8.25c-.69 0-1.25-.56-1.25-1.25z"/></svg>
5533
- </button>
6422
+ /**
6423
+ * A map from the name of a block to its line prefix.
6424
+ *
6425
+ * @type {Object<string, string>}
6426
+ */
6427
+ var PREFIXES = {
6428
+ 'deleted-sign': '-',
6429
+ 'deleted-arrow': '<',
6430
+ 'inserted-sign': '+',
6431
+ 'inserted-arrow': '>',
6432
+ 'unchanged': ' ',
6433
+ 'diff': '!',
6434
+ };
5534
6435
 
5535
- <button class="lexxy-editor__toolbar-button" type="button" name="ordered-list" data-command="insertOrderedList" title="Numbered list">
5536
- <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M7 5.25C7 4.56 7.56 4 8.25 4h13.5a1.25 1.25 0 110 2.5H8.25C7.56 6.5 7 5.94 7 5.25zM7 12.25c0-.69.56-1.25 1.25-1.25h13.5a1.25 1.25 0 110 2.5H8.25c-.69 0-1.25-.56-1.25-1.25zM7 19.25c0-.69.56-1.25 1.25-1.25h13.5a1.25 1.25 0 110 2.5H8.25c-.69 0-1.25-.56-1.25-1.25zM4.438 8H3.39V3.684H3.34c-.133.093-.267.188-.402.285l-.407.289a129.5 129.5 0 00-.402.285v-.969l.633-.453c.21-.15.42-.302.629-.453h1.046V8zM2.672 11.258h-1v-.051c0-.206.036-.405.11-.598.075-.195.188-.37.34-.527.15-.156.339-.281.566-.375.229-.094.498-.14.808-.14.367 0 .688.065.961.195s.484.308.633.535c.15.224.226.478.226.762 0 .244-.046.463-.14.656-.091.19-.209.368-.352.535-.14.164-.289.332-.445.504L3.168 14.09v.05h2.238V15H1.723v-.656l1.949-2.102c.096-.101.19-.207.281-.316.091-.112.167-.232.227-.36a.953.953 0 00.09-.41.712.712 0 00-.387-.648.845.845 0 00-.41-.098.81.81 0 00-.43.11.75.75 0 00-.277.293.824.824 0 00-.094.386V11.258zM2.852 19.66v-.812h.562a.917.917 0 00.43-.098.742.742 0 00.293-.266.673.673 0 00.101-.379.654.654 0 00-.234-.523.87.87 0 00-.59-.2.987.987 0 00-.336.055.837.837 0 00-.258.149.712.712 0 00-.172.215.66.66 0 00-.066.25h-.98c.007-.209.053-.403.136-.582.084-.18.203-.336.36-.469.156-.135.346-.24.57-.316.227-.076.486-.115.777-.118a2.33 2.33 0 01.965.176c.271.12.48.285.63.496.15.209.227.448.23.719a1.11 1.11 0 01-.16.637 1.28 1.28 0 01-.825.586v.054c.162.016.33.07.504.164.177.094.328.232.453.415.125.18.189.411.192.695a1.37 1.37 0 01-.157.676c-.104.197-.25.365-.437.503-.188.136-.404.24-.649.313-.242.07-.5.105-.777.105-.401 0-.743-.067-1.027-.203a1.608 1.608 0 01-.649-.547 1.46 1.46 0 01-.238-.75h.969c.01.128.057.243.14.344a.885.885 0 00.332.238c.141.058.3.088.477.09.195 0 .366-.034.512-.101a.798.798 0 00.336-.29.744.744 0 00.117-.425.74.74 0 00-.446-.695 1.082 1.082 0 00-.496-.106h-.59z"/></svg>
5537
- </button>
6436
+ // add a token for each prefix
6437
+ Object.keys(PREFIXES).forEach(function (name) {
6438
+ var prefix = PREFIXES[name];
5538
6439
 
5539
- <button class="lexxy-editor__toolbar-button" type="button" name="upload" data-command="uploadAttachments" title="Upload file">
5540
- <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M16 8a2 2 0 110 4 2 2 0 010-4z""/><path d="M22 2a1 1 0 011 1v18a1 1 0 01-1 1H2a1 1 0 01-1-1V3a1 1 0 011-1h20zM3 18.714L9 11l5.25 6.75L17 15l4 4V4H3v14.714z"/></svg>
5541
- </button>
6440
+ var alias = [];
6441
+ if (!/^\w+$/.test(name)) { // "deleted-sign" -> "deleted"
6442
+ alias.push(/\w+/.exec(name)[0]);
6443
+ }
6444
+ if (name === 'diff') {
6445
+ alias.push('bold');
6446
+ }
5542
6447
 
5543
- <button class="lexxy-editor__toolbar-button" type="button" name="divider" data-command="insertHorizontalDivider" title="Insert a divider">
5544
- <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M0 12C0 11.4477 0.447715 11 1 11H23C23.5523 11 24 11.4477 24 12C24 12.5523 23.5523 13 23 13H1C0.447716 13 0 12.5523 0 12Z"/><path d="M4 5C4 3.89543 4.89543 3 6 3H18C19.1046 3 20 3.89543 20 5C20 6.10457 19.1046 7 18 7H6C4.89543 7 4 6.10457 4 5Z"/><path d="M4 19C4 17.8954 4.89543 17 6 17H18C19.1046 17 20 17.8954 20 19C20 20.1046 19.1046 21 18 21H6C4.89543 21 4 20.1046 4 19Z"/></svg>
5545
- </button>
5546
-
5547
- <div class="lexxy-editor__toolbar-spacer" role="separator"></div>
5548
-
5549
- <button class="lexxy-editor__toolbar-button" type="button" name="undo" data-command="undo" title="Undo" data-hotkey="cmd+z ctrl+z">
5550
- <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M5.64648 8.26531C7.93911 6.56386 10.7827 5.77629 13.624 6.05535C16.4655 6.33452 19.1018 7.66079 21.0195 9.77605C22.5839 11.5016 23.5799 13.6516 23.8936 15.9352C24.0115 16.7939 23.2974 17.4997 22.4307 17.4997C21.5641 17.4997 20.8766 16.7915 20.7148 15.9401C20.4295 14.4379 19.7348 13.0321 18.6943 11.8844C17.3 10.3464 15.3835 9.38139 13.3174 9.17839C11.2514 8.97546 9.18359 9.54856 7.5166 10.7858C6.38259 11.6275 5.48981 12.7361 4.90723 13.9997H8.5C9.3283 13.9997 9.99979 14.6714 10 15.4997C10 16.3281 9.32843 16.9997 8.5 16.9997H1.5C0.671573 16.9997 0 16.3281 0 15.4997V8.49968C0.000213656 7.67144 0.671705 6.99968 1.5 6.99968C2.3283 6.99968 2.99979 7.67144 3 8.49968V11.0212C3.7166 9.9704 4.60793 9.03613 5.64648 8.26531Z"/></svg>
5551
- </button>
6448
+ Prism.languages.diff[name] = {
6449
+ pattern: RegExp('^(?:[' + prefix + '].*(?:\r\n?|\n|(?![\\s\\S])))+', 'm'),
6450
+ alias: alias,
6451
+ inside: {
6452
+ 'line': {
6453
+ pattern: /(.)(?=[\s\S]).*(?:\r\n?|\n)?/,
6454
+ lookbehind: true
6455
+ },
6456
+ 'prefix': {
6457
+ pattern: /[\s\S]/,
6458
+ alias: /\w+/.exec(name)[0]
6459
+ }
6460
+ }
6461
+ };
5552
6462
 
5553
- <button class="lexxy-editor__toolbar-button" type="button" name="redo" data-command="redo" title="Redo" data-hotkey="cmd+shift+z ctrl+shift+z ctrl+y">
5554
- <svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M18.2599 8.26531C15.9672 6.56386 13.1237 5.77629 10.2823 6.05535C7.4408 6.33452 4.80455 7.66079 2.88681 9.77605C1.32245 11.5016 0.326407 13.6516 0.0127834 15.9352C-0.105117 16.7939 0.608975 17.4997 1.47567 17.4997C2.34228 17.4997 3.02969 16.7915 3.19149 15.9401C3.47682 14.4379 4.17156 13.0321 5.212 11.8844C6.60637 10.3464 8.52287 9.38139 10.589 9.17839C12.655 8.97546 14.7227 9.54856 16.3897 10.7858C17.5237 11.6275 18.4165 12.7361 18.9991 13.9997H15.4063C14.578 13.9997 13.9066 14.6714 13.9063 15.4997C13.9063 16.3281 14.5779 16.9997 15.4063 16.9997H22.4063C23.2348 16.9997 23.9063 16.3281 23.9063 15.4997V8.49968C23.9061 7.67144 23.2346 6.99968 22.4063 6.99968C21.578 6.99968 20.9066 7.67144 20.9063 8.49968V11.0212C20.1897 9.9704 19.2984 9.03613 18.2599 8.26531Z"/></svg>
5555
- </button>
6463
+ });
5556
6464
 
5557
- <details class="lexxy-editor__toolbar-overflow">
5558
- <summary class="lexxy-editor__toolbar-button" aria-label="Show more toolbar buttons">•••</summary>
5559
- <div class="lexxy-editor__toolbar-overflow-menu" aria-label="More toolbar buttons"></div>
5560
- </details>
5561
- `
5562
- }
5563
- }
6465
+ // make prefixes available to Diff plugin
6466
+ Object.defineProperty(Prism.languages.diff, 'PREFIXES', {
6467
+ value: PREFIXES
6468
+ });
5564
6469
 
5565
- customElements.define("lexxy-toolbar", LexicalToolbarElement);
6470
+ }(Prism));
5566
6471
 
5567
6472
  /**
5568
6473
  * Copyright (c) Meta Platforms, Inc. and affiliates.
@@ -5598,6 +6503,7 @@ var theme = {
5598
6503
  }
5599
6504
  },
5600
6505
  codeHighlight: {
6506
+ addition: "code-token__selector",
5601
6507
  atrule: "code-token__attr",
5602
6508
  attr: "code-token__attr",
5603
6509
  "attr-name": "code-token__attr",
@@ -5612,24 +6518,30 @@ var theme = {
5612
6518
  color: "code-token__property",
5613
6519
  comment: "code-token__comment",
5614
6520
  constant: "code-token__property",
5615
- coord: "code-token__property",
6521
+ coord: "code-token__comment",
5616
6522
  decorator: "code-token__function",
5617
- deleted: "code-token__property",
6523
+ deleted: "code-token__operator",
6524
+ deletion: "code-token__operator",
6525
+ directive: "code-token__attr",
6526
+ "directive-hash": "code-token__property",
5618
6527
  doctype: "code-token__comment",
5619
6528
  entity: "code-token__operator",
5620
6529
  function: "code-token__function",
5621
6530
  hexcode: "code-token__property",
5622
- important: "code-token__variable",
6531
+ important: "code-token__function",
5623
6532
  inserted: "code-token__selector",
5624
6533
  italic: "code-token__comment",
5625
6534
  keyword: "code-token__attr",
6535
+ line: "code-token__selector",
5626
6536
  namespace: "code-token__variable",
5627
6537
  number: "code-token__property",
6538
+ macro: "code-token__function",
5628
6539
  operator: "code-token__operator",
5629
6540
  parameter: "code-token__variable",
5630
6541
  prolog: "code-token__comment",
5631
6542
  property: "code-token__property",
5632
6543
  punctuation: "code-token__punctuation",
6544
+ "raw-string": "code-token__operator",
5633
6545
  regex: "code-token__variable",
5634
6546
  script: "code-token__function",
5635
6547
  selector: "code-token__selector",
@@ -5638,6 +6550,7 @@ var theme = {
5638
6550
  symbol: "code-token__property",
5639
6551
  tag: "code-token__property",
5640
6552
  title: "code-token__function",
6553
+ "type-definition": "code-token__function",
5641
6554
  url: "code-token__operator",
5642
6555
  variable: "code-token__variable",
5643
6556
  }
@@ -6220,6 +7133,7 @@ class CommandDispatcher {
6220
7133
  this.highlighter = editorElement.highlighter;
6221
7134
 
6222
7135
  this.#registerCommands();
7136
+ this.#registerKeyboardCommands();
6223
7137
  this.#registerDragAndDropHandlers();
6224
7138
  }
6225
7139
 
@@ -6384,15 +7298,8 @@ class CommandDispatcher {
6384
7298
  this.editor.registerCommand(command, handler, priority);
6385
7299
  }
6386
7300
 
6387
- // Not using TOGGLE_LINK_COMMAND because it's not handled unless you use React/LinkPlugin
6388
- #toggleLink(url) {
6389
- this.editor.update(() => {
6390
- if (url === null) {
6391
- J$1(null);
6392
- } else {
6393
- J$1(url);
6394
- }
6395
- });
7301
+ #registerKeyboardCommands() {
7302
+ this.editor.registerCommand(Me$1, this.#handleListIndentation.bind(this), Ri);
6396
7303
  }
6397
7304
 
6398
7305
  #registerDragAndDropHandlers() {
@@ -6441,6 +7348,29 @@ class CommandDispatcher {
6441
7348
 
6442
7349
  this.editor.focus();
6443
7350
  }
7351
+
7352
+ #handleListIndentation(event) {
7353
+ if (this.selection.isInsideList) {
7354
+ event.preventDefault();
7355
+ if (event.shiftKey) {
7356
+ return this.editor.dispatchCommand(De$1, undefined)
7357
+ } else {
7358
+ return this.editor.dispatchCommand(Pe$1, undefined)
7359
+ }
7360
+ }
7361
+ return false
7362
+ }
7363
+
7364
+ // Not using TOGGLE_LINK_COMMAND because it's not handled unless you use React/LinkPlugin
7365
+ #toggleLink(url) {
7366
+ this.editor.update(() => {
7367
+ if (url === null) {
7368
+ J$1(null);
7369
+ } else {
7370
+ J$1(url);
7371
+ }
7372
+ });
7373
+ }
6444
7374
  }
6445
7375
 
6446
7376
  function capitalize(str) {
@@ -8418,27 +9348,37 @@ class Clipboard {
8418
9348
  class Highlighter {
8419
9349
  constructor(editorElement) {
8420
9350
  this.editor = editorElement.editor;
9351
+
9352
+ this.#registerHighlightTransform();
8421
9353
  }
8422
9354
 
8423
9355
  toggle(styles) {
8424
9356
  this.editor.update(() => {
8425
9357
  this.#toggleSelectionStyles(styles);
8426
- j$2(node => this.#syncHighlightWithStyle(node));
8427
9358
  });
8428
9359
  }
8429
9360
 
8430
9361
  remove() {
8431
- this.toggle({ "color": undefined, "background-color": undefined });
9362
+ this.toggle({ "color": null, "background-color": null });
9363
+ }
9364
+
9365
+ #registerHighlightTransform() {
9366
+ return this.editor.registerNodeTransform(Xn, (textNode) => {
9367
+ this.#syncHighlightWithStyle(textNode);
9368
+ })
8432
9369
  }
8433
9370
 
8434
9371
  #toggleSelectionStyles(styles) {
8435
9372
  const selection = Lr();
9373
+ if (!yr(selection)) return
8436
9374
 
9375
+ const patch = {};
8437
9376
  for (const property in styles) {
8438
9377
  const oldValue = le$1(selection, property);
8439
- const patch = { [property]: this.#toggleOrReplace(oldValue, styles[property]) };
8440
- U$5(selection, patch);
9378
+ patch[property] = this.#toggleOrReplace(oldValue, styles[property]);
8441
9379
  }
9380
+
9381
+ U$5(selection, patch);
8442
9382
  }
8443
9383
 
8444
9384
  #toggleOrReplace(oldValue, newValue) {
@@ -8446,15 +9386,10 @@ class Highlighter {
8446
9386
  }
8447
9387
 
8448
9388
  #syncHighlightWithStyle(node) {
8449
- if (this.#hasHighlightStyles(node) !== node.hasFormat("highlight")) {
9389
+ if (hasHighlightStyles(node.getStyle()) !== node.hasFormat("highlight")) {
8450
9390
  node.toggleFormat("highlight");
8451
9391
  }
8452
9392
  }
8453
-
8454
- #hasHighlightStyles(node) {
8455
- const styles = b$3(node.getStyle());
8456
- return !!(styles.color || styles["background-color"])
8457
- }
8458
9393
  }
8459
9394
 
8460
9395
  class HighlightNode extends Xn {
@@ -8626,6 +9561,10 @@ class LexicalEditorElement extends HTMLElement {
8626
9561
  return this.getAttribute("attachments") !== "false"
8627
9562
  }
8628
9563
 
9564
+ get contentTabIndex() {
9565
+ return parseInt(this.editorContentElement?.getAttribute("tabindex") ?? "0")
9566
+ }
9567
+
8629
9568
  focus() {
8630
9569
  this.editor.focus();
8631
9570
  }
@@ -8937,41 +9876,28 @@ class LexicalEditorElement extends HTMLElement {
8937
9876
  document.removeEventListener("turbo:before-cache", this.#handleTurboBeforeCache);
8938
9877
  }
8939
9878
 
8940
- #reconnect() {
8941
- this.disconnectedCallback();
8942
- this.connectedCallback();
8943
- }
8944
- }
8945
-
8946
- customElements.define("lexxy-editor", LexicalEditorElement);
8947
-
8948
- class ToolbarDialog extends HTMLElement {
8949
- connectedCallback() {
8950
- this.dialog = this.querySelector("dialog");
8951
- if ("closedBy" in this.dialog.constructor.prototype) {
8952
- this.dialog.closedBy = "any";
8953
- }
8954
- this.#registerHandlers();
8955
- }
8956
-
8957
- disconnectedCallback() {
8958
- this.#removeClickOutsideHandler();
9879
+ #reconnect() {
9880
+ this.disconnectedCallback();
9881
+ this.valueBeforeDisconnect = null;
9882
+ this.connectedCallback();
8959
9883
  }
9884
+ }
8960
9885
 
8961
- updateStateCallback() { }
9886
+ customElements.define("lexxy-editor", LexicalEditorElement);
8962
9887
 
8963
- show(triggerButton) {
8964
- if (this.preventImmediateReopen) { return }
9888
+ class ToolbarDropdown extends HTMLElement {
9889
+ connectedCallback() {
9890
+ this.container = this.closest("details");
8965
9891
 
8966
- this.triggerButton = triggerButton;
8967
- this.#positionDialog();
8968
- this.dialog.show();
9892
+ this.container.addEventListener("toggle", this.#handleToggle.bind(this));
9893
+ this.container.addEventListener("keydown", this.#handleKeyDown.bind(this));
8969
9894
 
8970
- this.#setupClickOutsideHandler();
9895
+ this.#setTabIndexValues();
8971
9896
  }
8972
9897
 
8973
- close() {
8974
- this.dialog.close();
9898
+ disconnectedCallback() {
9899
+ this.#removeClickOutsideHandler();
9900
+ this.container.removeEventListener("keydown", this.#handleKeyDown.bind(this));
8975
9901
  }
8976
9902
 
8977
9903
  get toolbar() {
@@ -8982,32 +9908,32 @@ class ToolbarDialog extends HTMLElement {
8982
9908
  return this.toolbar.editor
8983
9909
  }
8984
9910
 
8985
- get open() { return this.dialog.open }
8986
-
8987
- #registerHandlers() {
8988
- this.#setupKeydownHandler();
8989
- this.dialog.addEventListener("cancel", this.#handleCancel.bind(this));
8990
- this.dialog.addEventListener("close", this.#handleClose.bind(this));
9911
+ close() {
9912
+ this.container.removeAttribute("open");
8991
9913
  }
8992
9914
 
8993
- #handleClose() {
8994
- this.#removeClickOutsideHandler();
8995
- this.triggerButton = null;
8996
- this.editor.focus();
9915
+ #handleToggle(event) {
9916
+ if (this.container.open) {
9917
+ this.#handleOpen(event.target);
9918
+ } else {
9919
+ this.#handleClose();
9920
+ }
8997
9921
  }
8998
9922
 
8999
- #handleCancel() {
9000
- this.preventImmediateReopen = true;
9001
- requestAnimationFrame(() => this.preventImmediateReopen = undefined);
9923
+ #handleOpen(trigger) {
9924
+ this.trigger = trigger;
9925
+ this.#interactiveElements[0].focus();
9926
+ this.#setupClickOutsideHandler();
9002
9927
  }
9003
9928
 
9004
- #positionDialog() {
9005
- const left = this.triggerButton.offsetLeft;
9006
- this.dialog.style.insetInlineStart = `${left}px`;
9929
+ #handleClose() {
9930
+ this.trigger = null;
9931
+ this.#removeClickOutsideHandler();
9932
+ this.editor.focus();
9007
9933
  }
9008
9934
 
9009
9935
  #setupClickOutsideHandler() {
9010
- if (this.#browserHandlesClose || this.clickOutsideHandler) return
9936
+ if (this.clickOutsideHandler) return
9011
9937
 
9012
9938
  this.clickOutsideHandler = this.#handleClickOutside.bind(this);
9013
9939
  document.addEventListener("click", this.clickOutsideHandler, true);
@@ -9021,22 +9947,7 @@ class ToolbarDialog extends HTMLElement {
9021
9947
  }
9022
9948
 
9023
9949
  #handleClickOutside({ target }) {
9024
- if (!this.dialog.open) return
9025
-
9026
- const isClickInsideDialog = this.dialog.contains(target);
9027
- const isClickOnTrigger = this.triggerButton.contains(target);
9028
-
9029
- if (!isClickInsideDialog && !isClickOnTrigger) {
9030
- this.close();
9031
- }
9032
- }
9033
-
9034
- #setupKeydownHandler() {
9035
- if (!this.#browserHandlesClose) { this.addEventListener("keydown", this.#handleKeyDown.bind(this)); }
9036
- }
9037
-
9038
- get #browserHandlesClose() {
9039
- return this.dialog.closedBy === "any"
9950
+ if (this.container.open && !this.container.contains(target)) this.close();
9040
9951
  }
9041
9952
 
9042
9953
  #handleKeyDown(event) {
@@ -9045,9 +9956,20 @@ class ToolbarDialog extends HTMLElement {
9045
9956
  this.close();
9046
9957
  }
9047
9958
  }
9959
+
9960
+ async #setTabIndexValues() {
9961
+ await nextFrame();
9962
+ this.#interactiveElements.forEach((element) => {
9963
+ element.setAttribute("tabindex", 0);
9964
+ });
9965
+ }
9966
+
9967
+ get #interactiveElements() {
9968
+ return Array.from(this.querySelectorAll("button, input"))
9969
+ }
9048
9970
  }
9049
9971
 
9050
- class LinkDialog extends ToolbarDialog {
9972
+ class LinkDropdown extends ToolbarDropdown {
9051
9973
  connectedCallback() {
9052
9974
  super.connectedCallback();
9053
9975
  this.input = this.querySelector("input");
@@ -9055,23 +9977,21 @@ class LinkDialog extends ToolbarDialog {
9055
9977
  this.#registerHandlers();
9056
9978
  }
9057
9979
 
9058
- updateStateCallback() {
9059
- this.input.value = this.#selectedLinkUrl;
9060
- }
9061
-
9062
9980
  #registerHandlers() {
9063
- this.dialog.addEventListener("beforetoggle", this.#handleBeforeToggle.bind(this));
9064
- this.dialog.addEventListener("submit", this.#handleSubmit.bind(this));
9981
+ this.container.addEventListener("toggle", this.#handleToggle.bind(this));
9982
+ this.addEventListener("submit", this.#handleSubmit.bind(this));
9065
9983
  this.querySelector("[value='unlink']").addEventListener("click", this.#handleUnlink.bind(this));
9066
9984
  }
9067
9985
 
9068
- #handleBeforeToggle({ newState }) {
9986
+ #handleToggle({ newState }) {
9987
+ this.input.value = this.#selectedLinkUrl;
9069
9988
  this.input.required = newState === "open";
9070
9989
  }
9071
9990
 
9072
9991
  #handleSubmit(event) {
9073
9992
  const command = event.submitter?.value;
9074
9993
  this.editor.dispatchCommand(command, this.input.value);
9994
+ this.close();
9075
9995
  }
9076
9996
 
9077
9997
  #handleUnlink() {
@@ -9100,14 +10020,17 @@ class LinkDialog extends ToolbarDialog {
9100
10020
  }
9101
10021
  }
9102
10022
 
9103
- // We should extend the native dialog and avoid the intermediary <dialog> but not
9104
- // supported by Safari yet: customElements.define("lexxy-link-dialog", LinkDialog, { extends: "dialog" })
9105
- customElements.define("lexxy-link-dialog", LinkDialog);
10023
+ customElements.define("lexxy-link-dropdown", LinkDropdown);
9106
10024
 
9107
10025
  const APPLY_HIGHLIGHT_SELECTOR = "button.lexxy-highlight-button";
9108
10026
  const REMOVE_HIGHLIGHT_SELECTOR = "[data-command='removeHighlight']";
9109
10027
 
9110
- class HighlightDialog extends ToolbarDialog {
10028
+ // Use Symbol instead of null since $getSelectionStyleValueForProperty
10029
+ // responds differently for backward selections if null is the default
10030
+ // see https://github.com/facebook/lexical/issues/8013
10031
+ const NO_STYLE = Symbol("no_style");
10032
+
10033
+ class HighlightDropdown extends ToolbarDropdown {
9111
10034
  connectedCallback() {
9112
10035
  super.connectedCallback();
9113
10036
 
@@ -9115,13 +10038,10 @@ class HighlightDialog extends ToolbarDialog {
9115
10038
  this.#registerHandlers();
9116
10039
  }
9117
10040
 
9118
- updateStateCallback() {
9119
- this.#updateColorButtonStates(Lr());
9120
- }
9121
-
9122
10041
  #registerHandlers() {
9123
- this.querySelector(REMOVE_HIGHLIGHT_SELECTOR).addEventListener("click", this.#handleRemoveHighlightClick.bind(this));
10042
+ this.container.addEventListener("toggle", this.#handleToggle.bind(this));
9124
10043
  this.#colorButtons.forEach(button => button.addEventListener("click", this.#handleColorButtonClick.bind(this)));
10044
+ this.querySelector(REMOVE_HIGHLIGHT_SELECTOR).addEventListener("click", this.#handleRemoveHighlightClick.bind(this));
9125
10045
  }
9126
10046
 
9127
10047
  #setUpButtons() {
@@ -9148,6 +10068,14 @@ class HighlightDialog extends ToolbarDialog {
9148
10068
  return button
9149
10069
  }
9150
10070
 
10071
+ #handleToggle({ newState }) {
10072
+ if (newState === "open") {
10073
+ this.editor.getEditorState().read(() => {
10074
+ this.#updateColorButtonStates(Lr());
10075
+ });
10076
+ }
10077
+ }
10078
+
9151
10079
  #handleColorButtonClick(event) {
9152
10080
  event.preventDefault();
9153
10081
 
@@ -9171,16 +10099,16 @@ class HighlightDialog extends ToolbarDialog {
9171
10099
  #updateColorButtonStates(selection) {
9172
10100
  if (!yr(selection)) { return }
9173
10101
 
9174
- // Use null default, so "" indicates mixed highlighting
9175
- const textColor = le$1(selection, "color", null);
9176
- const backgroundColor = le$1(selection, "background-color", null);
10102
+ // Use non-"" default, so "" indicates mixed highlighting
10103
+ const textColor = le$1(selection, "color", NO_STYLE);
10104
+ const backgroundColor = le$1(selection, "background-color", NO_STYLE);
9177
10105
 
9178
10106
  this.#colorButtons.forEach(button => {
9179
10107
  const matchesSelection = button.dataset.value === textColor || button.dataset.value === backgroundColor;
9180
10108
  button.setAttribute("aria-pressed", matchesSelection);
9181
10109
  });
9182
10110
 
9183
- const hasHighlight = textColor !== null || backgroundColor !== null;
10111
+ const hasHighlight = textColor !== NO_STYLE || backgroundColor !== NO_STYLE;
9184
10112
  this.querySelector(REMOVE_HIGHLIGHT_SELECTOR).disabled = !hasHighlight;
9185
10113
  }
9186
10114
 
@@ -9193,9 +10121,7 @@ class HighlightDialog extends ToolbarDialog {
9193
10121
  }
9194
10122
  }
9195
10123
 
9196
- // We should extend the native dialog and avoid the intermediary <dialog> but not
9197
- // supported by Safari yet: customElements.define("lexxy-hightlight-dialog", HighlightDialog, { extends: "dialog" })
9198
- customElements.define("lexxy-highlight-dialog", HighlightDialog);
10124
+ customElements.define("lexxy-highlight-dropdown", HighlightDropdown);
9199
10125
 
9200
10126
  class BaseSource {
9201
10127
  // Template method to override
@@ -9340,10 +10266,13 @@ class LexicalPromptElement extends HTMLElement {
9340
10266
  this.keyListeners = [];
9341
10267
  }
9342
10268
 
10269
+ static observedAttributes = [ "connected" ]
10270
+
9343
10271
  connectedCallback() {
9344
10272
  this.source = this.#createSource();
9345
10273
 
9346
10274
  this.#addTriggerListener();
10275
+ this.toggleAttribute("connected", true);
9347
10276
  }
9348
10277
 
9349
10278
  disconnectedCallback() {
@@ -9351,6 +10280,13 @@ class LexicalPromptElement extends HTMLElement {
9351
10280
  this.popoverElement = null;
9352
10281
  }
9353
10282
 
10283
+
10284
+ attributeChangedCallback(name, oldValue, newValue) {
10285
+ if (name === "connected" && this.isConnected && oldValue != null && oldValue !== newValue) {
10286
+ requestAnimationFrame(() => this.#reconnect());
10287
+ }
10288
+ }
10289
+
9354
10290
  get name() {
9355
10291
  return this.getAttribute("name")
9356
10292
  }
@@ -9720,6 +10656,11 @@ class LexicalPromptElement extends HTMLElement {
9720
10656
  this.#optionWasSelected();
9721
10657
  }
9722
10658
  }
10659
+
10660
+ #reconnect() {
10661
+ this.disconnectedCallback();
10662
+ this.connectedCallback();
10663
+ }
9723
10664
  }
9724
10665
 
9725
10666
  customElements.define("lexxy-prompt", LexicalPromptElement);
@@ -9762,6 +10703,11 @@ class CodeLanguagePicker extends HTMLElement {
9762
10703
  const languages = { ...pt };
9763
10704
 
9764
10705
  if (!languages.ruby) languages.ruby = "Ruby";
10706
+ if (!languages.php) languages.php = "PHP";
10707
+ if (!languages.go) languages.go = "Go";
10708
+ if (!languages.bash) languages.bash = "Bash";
10709
+ if (!languages.json) languages.json = "JSON";
10710
+ if (!languages.diff) languages.diff = "Diff";
9765
10711
 
9766
10712
  const sortedEntries = Object.entries(languages)
9767
10713
  .sort(([ , a ], [ , b ]) => a.localeCompare(b));
@@ -9852,196 +10798,6 @@ class CodeLanguagePicker extends HTMLElement {
9852
10798
 
9853
10799
  customElements.define("lexxy-code-language-picker", CodeLanguagePicker);
9854
10800
 
9855
- /**
9856
- * Original by Samuel Flores
9857
- *
9858
- * Adds the following new token classes:
9859
- * constant, builtin, variable, symbol, regex
9860
- */
9861
- (function (Prism) {
9862
- Prism.languages.ruby = Prism.languages.extend('clike', {
9863
- 'comment': {
9864
- pattern: /#.*|^=begin\s[\s\S]*?^=end/m,
9865
- greedy: true
9866
- },
9867
- 'class-name': {
9868
- pattern: /(\b(?:class|module)\s+|\bcatch\s+\()[\w.\\]+|\b[A-Z_]\w*(?=\s*\.\s*new\b)/,
9869
- lookbehind: true,
9870
- inside: {
9871
- 'punctuation': /[.\\]/
9872
- }
9873
- },
9874
- '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/,
9875
- 'operator': /\.{2,3}|&\.|===|<?=>|[!=]?~|(?:&&|\|\||<<|>>|\*\*|[+\-*/%<>!^&|=])=?|[?:]/,
9876
- 'punctuation': /[(){}[\].,;]/,
9877
- });
9878
-
9879
- Prism.languages.insertBefore('ruby', 'operator', {
9880
- 'double-colon': {
9881
- pattern: /::/,
9882
- alias: 'punctuation'
9883
- },
9884
- });
9885
-
9886
- var interpolation = {
9887
- pattern: /((?:^|[^\\])(?:\\{2})*)#\{(?:[^{}]|\{[^{}]*\})*\}/,
9888
- lookbehind: true,
9889
- inside: {
9890
- 'content': {
9891
- pattern: /^(#\{)[\s\S]+(?=\}$)/,
9892
- lookbehind: true,
9893
- inside: Prism.languages.ruby
9894
- },
9895
- 'delimiter': {
9896
- pattern: /^#\{|\}$/,
9897
- alias: 'punctuation'
9898
- }
9899
- }
9900
- };
9901
-
9902
- delete Prism.languages.ruby.function;
9903
-
9904
- var percentExpression = '(?:' + [
9905
- /([^a-zA-Z0-9\s{(\[<=])(?:(?!\1)[^\\]|\\[\s\S])*\1/.source,
9906
- /\((?:[^()\\]|\\[\s\S]|\((?:[^()\\]|\\[\s\S])*\))*\)/.source,
9907
- /\{(?:[^{}\\]|\\[\s\S]|\{(?:[^{}\\]|\\[\s\S])*\})*\}/.source,
9908
- /\[(?:[^\[\]\\]|\\[\s\S]|\[(?:[^\[\]\\]|\\[\s\S])*\])*\]/.source,
9909
- /<(?:[^<>\\]|\\[\s\S]|<(?:[^<>\\]|\\[\s\S])*>)*>/.source
9910
- ].join('|') + ')';
9911
-
9912
- var symbolName = /(?:"(?:\\.|[^"\\\r\n])*"|(?:\b[a-zA-Z_]\w*|[^\s\0-\x7F]+)[?!]?|\$.)/.source;
9913
-
9914
- Prism.languages.insertBefore('ruby', 'keyword', {
9915
- 'regex-literal': [
9916
- {
9917
- pattern: RegExp(/%r/.source + percentExpression + /[egimnosux]{0,6}/.source),
9918
- greedy: true,
9919
- inside: {
9920
- 'interpolation': interpolation,
9921
- 'regex': /[\s\S]+/
9922
- }
9923
- },
9924
- {
9925
- pattern: /(^|[^/])\/(?!\/)(?:\[[^\r\n\]]+\]|\\.|[^[/\\\r\n])+\/[egimnosux]{0,6}(?=\s*(?:$|[\r\n,.;})#]))/,
9926
- lookbehind: true,
9927
- greedy: true,
9928
- inside: {
9929
- 'interpolation': interpolation,
9930
- 'regex': /[\s\S]+/
9931
- }
9932
- }
9933
- ],
9934
- 'variable': /[@$]+[a-zA-Z_]\w*(?:[?!]|\b)/,
9935
- 'symbol': [
9936
- {
9937
- pattern: RegExp(/(^|[^:]):/.source + symbolName),
9938
- lookbehind: true,
9939
- greedy: true
9940
- },
9941
- {
9942
- pattern: RegExp(/([\r\n{(,][ \t]*)/.source + symbolName + /(?=:(?!:))/.source),
9943
- lookbehind: true,
9944
- greedy: true
9945
- },
9946
- ],
9947
- 'method-definition': {
9948
- pattern: /(\bdef\s+)\w+(?:\s*\.\s*\w+)?/,
9949
- lookbehind: true,
9950
- inside: {
9951
- 'function': /\b\w+$/,
9952
- 'keyword': /^self\b/,
9953
- 'class-name': /^\w+/,
9954
- 'punctuation': /\./
9955
- }
9956
- }
9957
- });
9958
-
9959
- Prism.languages.insertBefore('ruby', 'string', {
9960
- 'string-literal': [
9961
- {
9962
- pattern: RegExp(/%[qQiIwWs]?/.source + percentExpression),
9963
- greedy: true,
9964
- inside: {
9965
- 'interpolation': interpolation,
9966
- 'string': /[\s\S]+/
9967
- }
9968
- },
9969
- {
9970
- pattern: /("|')(?:#\{[^}]+\}|#(?!\{)|\\(?:\r\n|[\s\S])|(?!\1)[^\\#\r\n])*\1/,
9971
- greedy: true,
9972
- inside: {
9973
- 'interpolation': interpolation,
9974
- 'string': /[\s\S]+/
9975
- }
9976
- },
9977
- {
9978
- pattern: /<<[-~]?([a-z_]\w*)[\r\n](?:.*[\r\n])*?[\t ]*\1/i,
9979
- alias: 'heredoc-string',
9980
- greedy: true,
9981
- inside: {
9982
- 'delimiter': {
9983
- pattern: /^<<[-~]?[a-z_]\w*|\b[a-z_]\w*$/i,
9984
- inside: {
9985
- 'symbol': /\b\w+/,
9986
- 'punctuation': /^<<[-~]?/
9987
- }
9988
- },
9989
- 'interpolation': interpolation,
9990
- 'string': /[\s\S]+/
9991
- }
9992
- },
9993
- {
9994
- pattern: /<<[-~]?'([a-z_]\w*)'[\r\n](?:.*[\r\n])*?[\t ]*\1/i,
9995
- alias: 'heredoc-string',
9996
- greedy: true,
9997
- inside: {
9998
- 'delimiter': {
9999
- pattern: /^<<[-~]?'[a-z_]\w*'|\b[a-z_]\w*$/i,
10000
- inside: {
10001
- 'symbol': /\b\w+/,
10002
- 'punctuation': /^<<[-~]?'|'$/,
10003
- }
10004
- },
10005
- 'string': /[\s\S]+/
10006
- }
10007
- }
10008
- ],
10009
- 'command-literal': [
10010
- {
10011
- pattern: RegExp(/%x/.source + percentExpression),
10012
- greedy: true,
10013
- inside: {
10014
- 'interpolation': interpolation,
10015
- 'command': {
10016
- pattern: /[\s\S]+/,
10017
- alias: 'string'
10018
- }
10019
- }
10020
- },
10021
- {
10022
- pattern: /`(?:#\{[^}]+\}|#(?!\{)|\\(?:\r\n|[\s\S])|[^\\`#\r\n])*`/,
10023
- greedy: true,
10024
- inside: {
10025
- 'interpolation': interpolation,
10026
- 'command': {
10027
- pattern: /[\s\S]+/,
10028
- alias: 'string'
10029
- }
10030
- }
10031
- }
10032
- ]
10033
- });
10034
-
10035
- delete Prism.languages.ruby.string;
10036
-
10037
- Prism.languages.insertBefore('ruby', 'number', {
10038
- '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/,
10039
- 'constant': /\b[A-Z][A-Z0-9_]*(?:[?!]|\b)/
10040
- });
10041
-
10042
- Prism.languages.rb = Prism.languages.ruby;
10043
- }(Prism));
10044
-
10045
10801
  function highlightAll() {
10046
10802
  const elements = document.querySelectorAll("pre[data-language]");
10047
10803