@mdaemon/html-editor 1.0.7 → 1.0.9

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.
package/dist/index.mjs CHANGED
@@ -42462,6 +42462,284 @@ class SearchReplace {
42462
42462
  }
42463
42463
  }
42464
42464
  }
42465
+ class SourceEditor {
42466
+ options;
42467
+ overlay = null;
42468
+ dialog = null;
42469
+ textarea = null;
42470
+ constructor(options) {
42471
+ this.options = options;
42472
+ }
42473
+ get tiptap() {
42474
+ return this.options.editor.getTipTap();
42475
+ }
42476
+ open() {
42477
+ if (this.overlay) {
42478
+ if (this.textarea) {
42479
+ this.textarea.value = this.tiptap?.getHTML() ?? "";
42480
+ }
42481
+ this.overlay.style.display = "flex";
42482
+ this.textarea?.focus();
42483
+ return;
42484
+ }
42485
+ this.createDialog();
42486
+ }
42487
+ close() {
42488
+ if (this.overlay) {
42489
+ this.overlay.style.display = "none";
42490
+ }
42491
+ }
42492
+ save() {
42493
+ if (this.textarea) {
42494
+ this.tiptap?.commands.setContent(this.textarea.value);
42495
+ }
42496
+ this.close();
42497
+ }
42498
+ createDialog() {
42499
+ const trans = this.options.trans;
42500
+ const skin = this.options.editor.getConfig().skin ?? "oxide";
42501
+ this.overlay = document.createElement("div");
42502
+ this.overlay.className = "md-dialog-overlay";
42503
+ this.overlay.addEventListener("click", (e) => {
42504
+ if (e.target === this.overlay) {
42505
+ this.close();
42506
+ }
42507
+ });
42508
+ const themeWrapper = document.createElement("div");
42509
+ themeWrapper.className = `md-editor-${skin}`;
42510
+ themeWrapper.style.display = "contents";
42511
+ this.dialog = document.createElement("div");
42512
+ this.dialog.className = "md-dialog md-source-editor-dialog";
42513
+ const header = document.createElement("div");
42514
+ header.className = "md-dialog-header";
42515
+ header.innerHTML = `
42516
+ <h3>${trans("Source code")}</h3>
42517
+ <button type="button" class="md-dialog-close">×</button>
42518
+ `;
42519
+ header.querySelector(".md-dialog-close")?.addEventListener("click", () => this.close());
42520
+ const body = document.createElement("div");
42521
+ body.className = "md-dialog-body";
42522
+ this.textarea = document.createElement("textarea");
42523
+ this.textarea.className = "md-source-editor-textarea";
42524
+ this.textarea.value = this.tiptap?.getHTML() ?? "";
42525
+ this.textarea.spellcheck = false;
42526
+ this.textarea.addEventListener("keydown", (e) => {
42527
+ if (e.key === "Tab") {
42528
+ e.preventDefault();
42529
+ const start = this.textarea.selectionStart;
42530
+ const end = this.textarea.selectionEnd;
42531
+ this.textarea.value = this.textarea.value.substring(0, start) + " " + this.textarea.value.substring(end);
42532
+ this.textarea.selectionStart = this.textarea.selectionEnd = start + 2;
42533
+ }
42534
+ });
42535
+ body.appendChild(this.textarea);
42536
+ const footer = document.createElement("div");
42537
+ footer.className = "md-source-editor-footer";
42538
+ footer.innerHTML = `
42539
+ <button type="button" class="md-btn md-source-editor-cancel">${trans("Cancel")}</button>
42540
+ <button type="button" class="md-btn md-btn-primary md-source-editor-save">${trans("Save")}</button>
42541
+ `;
42542
+ footer.querySelector(".md-source-editor-cancel")?.addEventListener("click", () => this.close());
42543
+ footer.querySelector(".md-source-editor-save")?.addEventListener("click", () => this.save());
42544
+ body.appendChild(footer);
42545
+ this.dialog.appendChild(header);
42546
+ this.dialog.appendChild(body);
42547
+ themeWrapper.appendChild(this.dialog);
42548
+ this.overlay.appendChild(themeWrapper);
42549
+ this.overlay.addEventListener("keydown", (e) => {
42550
+ if (e.key === "Escape") {
42551
+ this.close();
42552
+ }
42553
+ });
42554
+ document.body.appendChild(this.overlay);
42555
+ this.textarea.focus();
42556
+ }
42557
+ destroy() {
42558
+ if (this.overlay) {
42559
+ this.overlay.remove();
42560
+ this.overlay = null;
42561
+ this.dialog = null;
42562
+ this.textarea = null;
42563
+ }
42564
+ }
42565
+ }
42566
+ class LinkEditor {
42567
+ options;
42568
+ overlay = null;
42569
+ dialog = null;
42570
+ urlInput = null;
42571
+ textInput = null;
42572
+ titleInput = null;
42573
+ targetSelect = null;
42574
+ constructor(options) {
42575
+ this.options = options;
42576
+ }
42577
+ get tiptap() {
42578
+ return this.options.editor.getTipTap();
42579
+ }
42580
+ open() {
42581
+ if (!this.overlay) {
42582
+ this.createDialog();
42583
+ }
42584
+ this.populateFromSelection();
42585
+ this.overlay.style.display = "flex";
42586
+ this.urlInput?.focus();
42587
+ }
42588
+ close() {
42589
+ if (this.overlay) {
42590
+ this.overlay.style.display = "none";
42591
+ }
42592
+ }
42593
+ populateFromSelection() {
42594
+ const tiptap = this.tiptap;
42595
+ if (!tiptap) return;
42596
+ const attrs = tiptap.getAttributes("link");
42597
+ const { from: from2, to } = tiptap.state.selection;
42598
+ const selectedText = tiptap.state.doc.textBetween(from2, to, "");
42599
+ if (this.urlInput) this.urlInput.value = attrs.href ?? "";
42600
+ if (this.textInput) this.textInput.value = selectedText;
42601
+ if (this.titleInput) this.titleInput.value = attrs.title ?? "";
42602
+ if (this.targetSelect) this.targetSelect.value = attrs.target ?? "";
42603
+ }
42604
+ save() {
42605
+ const tiptap = this.tiptap;
42606
+ if (!tiptap) return;
42607
+ const url = this.urlInput?.value.trim() ?? "";
42608
+ const text = this.textInput?.value ?? "";
42609
+ const title = this.titleInput?.value.trim() ?? "";
42610
+ const target = this.targetSelect?.value ?? "";
42611
+ if (!url) {
42612
+ tiptap.chain().focus().unsetLink().run();
42613
+ this.close();
42614
+ return;
42615
+ }
42616
+ const linkAttrs = { href: url };
42617
+ if (target) {
42618
+ linkAttrs.target = target;
42619
+ } else {
42620
+ linkAttrs.target = null;
42621
+ }
42622
+ if (title) {
42623
+ linkAttrs.title = title;
42624
+ } else {
42625
+ linkAttrs.title = null;
42626
+ }
42627
+ const { from: from2, to } = tiptap.state.selection;
42628
+ const currentText = tiptap.state.doc.textBetween(from2, to, "");
42629
+ if (text && text !== currentText) {
42630
+ tiptap.chain().focus().deleteSelection().insertContent({
42631
+ type: "text",
42632
+ text,
42633
+ marks: [{ type: "link", attrs: linkAttrs }]
42634
+ }).run();
42635
+ } else if (from2 === to && text) {
42636
+ tiptap.chain().focus().insertContent({
42637
+ type: "text",
42638
+ text,
42639
+ marks: [{ type: "link", attrs: linkAttrs }]
42640
+ }).run();
42641
+ } else if (from2 === to && !text) {
42642
+ tiptap.chain().focus().insertContent({
42643
+ type: "text",
42644
+ text: url,
42645
+ marks: [{ type: "link", attrs: linkAttrs }]
42646
+ }).run();
42647
+ } else {
42648
+ tiptap.chain().focus().setLink(linkAttrs).run();
42649
+ }
42650
+ this.close();
42651
+ }
42652
+ createDialog() {
42653
+ const trans = this.options.trans;
42654
+ const skin = this.options.editor.getConfig().skin ?? "oxide";
42655
+ this.overlay = document.createElement("div");
42656
+ this.overlay.className = "md-dialog-overlay";
42657
+ this.overlay.addEventListener("click", (e) => {
42658
+ if (e.target === this.overlay) {
42659
+ this.close();
42660
+ }
42661
+ });
42662
+ const themeWrapper = document.createElement("div");
42663
+ themeWrapper.className = `md-editor-${skin}`;
42664
+ themeWrapper.style.display = "contents";
42665
+ this.dialog = document.createElement("div");
42666
+ this.dialog.className = "md-dialog md-link-editor-dialog";
42667
+ const header = document.createElement("div");
42668
+ header.className = "md-dialog-header";
42669
+ header.innerHTML = `
42670
+ <h3>${trans("Insert/Edit Link")}</h3>
42671
+ <button type="button" class="md-dialog-close">×</button>
42672
+ `;
42673
+ header.querySelector(".md-dialog-close")?.addEventListener("click", () => this.close());
42674
+ const body = document.createElement("div");
42675
+ body.className = "md-dialog-body";
42676
+ const urlRow = document.createElement("div");
42677
+ urlRow.className = "md-link-editor-row";
42678
+ urlRow.innerHTML = `<label>${trans("URL")}</label>`;
42679
+ this.urlInput = document.createElement("input");
42680
+ this.urlInput.type = "text";
42681
+ this.urlInput.className = "md-link-editor-input";
42682
+ urlRow.appendChild(this.urlInput);
42683
+ const textRow = document.createElement("div");
42684
+ textRow.className = "md-link-editor-row";
42685
+ textRow.innerHTML = `<label>${trans("Text to display")}</label>`;
42686
+ this.textInput = document.createElement("input");
42687
+ this.textInput.type = "text";
42688
+ this.textInput.className = "md-link-editor-input";
42689
+ textRow.appendChild(this.textInput);
42690
+ const titleRow = document.createElement("div");
42691
+ titleRow.className = "md-link-editor-row";
42692
+ titleRow.innerHTML = `<label>${trans("Title")}</label>`;
42693
+ this.titleInput = document.createElement("input");
42694
+ this.titleInput.type = "text";
42695
+ this.titleInput.className = "md-link-editor-input";
42696
+ titleRow.appendChild(this.titleInput);
42697
+ const targetRow = document.createElement("div");
42698
+ targetRow.className = "md-link-editor-row";
42699
+ targetRow.innerHTML = `<label>${trans("Open link in...")}</label>`;
42700
+ this.targetSelect = document.createElement("select");
42701
+ this.targetSelect.className = "md-link-editor-select";
42702
+ this.targetSelect.innerHTML = `
42703
+ <option value="">${trans("Current window")}</option>
42704
+ <option value="_blank">${trans("New window")}</option>
42705
+ `;
42706
+ targetRow.appendChild(this.targetSelect);
42707
+ body.appendChild(urlRow);
42708
+ body.appendChild(textRow);
42709
+ body.appendChild(titleRow);
42710
+ body.appendChild(targetRow);
42711
+ const footer = document.createElement("div");
42712
+ footer.className = "md-link-editor-footer";
42713
+ footer.innerHTML = `
42714
+ <button type="button" class="md-btn md-link-editor-cancel">${trans("Cancel")}</button>
42715
+ <button type="button" class="md-btn md-btn-primary md-link-editor-save">${trans("Save")}</button>
42716
+ `;
42717
+ footer.querySelector(".md-link-editor-cancel")?.addEventListener("click", () => this.close());
42718
+ footer.querySelector(".md-link-editor-save")?.addEventListener("click", () => this.save());
42719
+ body.appendChild(footer);
42720
+ this.dialog.appendChild(header);
42721
+ this.dialog.appendChild(body);
42722
+ themeWrapper.appendChild(this.dialog);
42723
+ this.overlay.appendChild(themeWrapper);
42724
+ this.overlay.addEventListener("keydown", (e) => {
42725
+ if (e.key === "Escape") {
42726
+ this.close();
42727
+ }
42728
+ });
42729
+ document.body.appendChild(this.overlay);
42730
+ }
42731
+ destroy() {
42732
+ if (this.overlay) {
42733
+ this.overlay.remove();
42734
+ this.overlay = null;
42735
+ this.dialog = null;
42736
+ this.urlInput = null;
42737
+ this.textInput = null;
42738
+ this.titleInput = null;
42739
+ this.targetSelect = null;
42740
+ }
42741
+ }
42742
+ }
42465
42743
  const DEFAULT_COLORS = [
42466
42744
  { value: "#000000", label: "Black" },
42467
42745
  { value: "#434343", label: "Dark Gray 4" },
@@ -42512,11 +42790,14 @@ class Toolbar {
42512
42790
  emojiPicker = null;
42513
42791
  imageUpload = null;
42514
42792
  searchReplace = null;
42793
+ sourceEditor = null;
42794
+ linkEditor = null;
42515
42795
  updateInterval = null;
42516
42796
  boundClickHandler = null;
42517
42797
  boundKeydownHandler = null;
42518
- overflowEl = null;
42798
+ buttonsEl = null;
42519
42799
  toggleBtn = null;
42800
+ resizeObserver = null;
42520
42801
  constructor(container, options) {
42521
42802
  this.container = container;
42522
42803
  this.options = options;
@@ -42540,27 +42821,29 @@ class Toolbar {
42540
42821
  render() {
42541
42822
  this.container.innerHTML = "";
42542
42823
  this.container.className = `md-toolbar md-toolbar-${this.options.mode}${this.options.sticky ? " md-toolbar-sticky" : ""}`;
42543
- const rows = this.options.buttons.split("||");
42544
- const hasOverflow = rows.length > 1;
42545
- if (hasOverflow) {
42546
- const primaryEl = document.createElement("div");
42547
- primaryEl.className = "md-toolbar-primary";
42548
- this.renderGroups(rows[0].trim(), primaryEl);
42549
- this.toggleBtn = this.createToggleButton();
42550
- primaryEl.appendChild(this.toggleBtn);
42551
- this.container.appendChild(primaryEl);
42552
- this.overflowEl = document.createElement("div");
42553
- this.overflowEl.className = "md-toolbar-overflow";
42554
- const overflowStr = rows.slice(1).join("||").trim();
42555
- this.renderGroups(overflowStr, this.overflowEl);
42556
- this.container.appendChild(this.overflowEl);
42557
- if (this.state.showMoreButtons) {
42558
- this.overflowEl.classList.add("md-toolbar-overflow-visible");
42559
- this.toggleBtn.classList.add("md-toolbar-btn-active");
42560
- }
42561
- } else {
42562
- this.renderGroups(this.options.buttons, this.container);
42563
- }
42824
+ this.buttonsEl = document.createElement("div");
42825
+ this.buttonsEl.className = "md-toolbar-buttons";
42826
+ const buttonsStr = this.options.buttons.replace(/\|\|/g, "|");
42827
+ this.renderGroups(buttonsStr, this.buttonsEl);
42828
+ this.container.appendChild(this.buttonsEl);
42829
+ this.toggleBtn = this.createToggleButton();
42830
+ this.container.appendChild(this.toggleBtn);
42831
+ if (this.state.showMoreButtons) {
42832
+ this.buttonsEl.classList.add("md-toolbar-expanded");
42833
+ this.toggleBtn.classList.add("md-toolbar-btn-active");
42834
+ }
42835
+ this.observeOverflow();
42836
+ }
42837
+ observeOverflow() {
42838
+ if (this.resizeObserver) {
42839
+ this.resizeObserver.disconnect();
42840
+ }
42841
+ this.resizeObserver = new ResizeObserver(() => {
42842
+ if (!this.buttonsEl || !this.toggleBtn) return;
42843
+ const hasOverflow = this.buttonsEl.scrollHeight > this.buttonsEl.clientHeight;
42844
+ this.toggleBtn.style.display = hasOverflow || this.state.showMoreButtons ? "" : "none";
42845
+ });
42846
+ this.resizeObserver.observe(this.buttonsEl);
42564
42847
  }
42565
42848
  renderGroups(buttonsStr, parent) {
42566
42849
  const groups = buttonsStr.split("|").map((g) => g.trim()).filter(Boolean);
@@ -42598,11 +42881,14 @@ class Toolbar {
42598
42881
  }
42599
42882
  toggleOverflow() {
42600
42883
  this.state.showMoreButtons = !this.state.showMoreButtons;
42601
- if (this.overflowEl) {
42602
- this.overflowEl.classList.toggle("md-toolbar-overflow-visible", this.state.showMoreButtons);
42884
+ if (this.buttonsEl) {
42885
+ this.buttonsEl.classList.toggle("md-toolbar-expanded", this.state.showMoreButtons);
42603
42886
  }
42604
42887
  if (this.toggleBtn) {
42605
42888
  this.toggleBtn.classList.toggle("md-toolbar-btn-active", this.state.showMoreButtons);
42889
+ if (this.state.showMoreButtons) {
42890
+ this.toggleBtn.style.display = "";
42891
+ }
42606
42892
  }
42607
42893
  }
42608
42894
  createButton(name) {
@@ -43115,14 +43401,13 @@ class Toolbar {
43115
43401
  this.imageUpload.open();
43116
43402
  }
43117
43403
  openLinkDialog() {
43118
- const previousUrl = this.tiptap?.getAttributes("link").href ?? "";
43119
- const url = prompt(this.trans("Enter URL:"), previousUrl);
43120
- if (url === null) return;
43121
- if (url === "") {
43122
- this.tiptap?.chain().focus().unsetLink().run();
43123
- } else {
43124
- this.tiptap?.chain().focus().setLink({ href: url }).run();
43404
+ if (!this.linkEditor) {
43405
+ this.linkEditor = new LinkEditor({
43406
+ editor: this.options.editor,
43407
+ trans: this.trans
43408
+ });
43125
43409
  }
43410
+ this.linkEditor.open();
43126
43411
  }
43127
43412
  openCharMap() {
43128
43413
  if (!this.charMap) {
@@ -43156,11 +43441,13 @@ class Toolbar {
43156
43441
  this.searchReplace.open();
43157
43442
  }
43158
43443
  openSourceCode() {
43159
- const html = this.tiptap?.getHTML() ?? "";
43160
- const newHtml = prompt(this.trans("Edit HTML source:"), html);
43161
- if (newHtml !== null) {
43162
- this.tiptap?.commands.setContent(newHtml);
43444
+ if (!this.sourceEditor) {
43445
+ this.sourceEditor = new SourceEditor({
43446
+ editor: this.options.editor,
43447
+ trans: this.trans
43448
+ });
43163
43449
  }
43450
+ this.sourceEditor.open();
43164
43451
  }
43165
43452
  openPreview() {
43166
43453
  const html = this.tiptap?.getHTML() ?? "";
@@ -43203,7 +43490,7 @@ class Toolbar {
43203
43490
  this.searchReplace = null;
43204
43491
  this.buttonElements.clear();
43205
43492
  this.dropdowns.clear();
43206
- this.overflowEl = null;
43493
+ this.buttonsEl = null;
43207
43494
  this.toggleBtn = null;
43208
43495
  this.render();
43209
43496
  this.bindEvents();
@@ -43212,6 +43499,10 @@ class Toolbar {
43212
43499
  if (this.updateInterval) {
43213
43500
  clearInterval(this.updateInterval);
43214
43501
  }
43502
+ if (this.resizeObserver) {
43503
+ this.resizeObserver.disconnect();
43504
+ this.resizeObserver = null;
43505
+ }
43215
43506
  this.unbindEvents();
43216
43507
  this.charMap?.destroy();
43217
43508
  this.emojiPicker?.destroy();
@@ -43508,7 +43799,14 @@ const en = {
43508
43799
  "Invalid image URL": "Invalid image URL",
43509
43800
  "File too large": "File too large",
43510
43801
  "Invalid file type": "Invalid file type",
43511
- "More": "More"
43802
+ "More": "More",
43803
+ "Save": "Save",
43804
+ "Insert/Edit Link": "Insert/Edit Link",
43805
+ "Text to display": "Text to display",
43806
+ "Title": "Title",
43807
+ "Open link in...": "Open link in...",
43808
+ "Current window": "Current window",
43809
+ "New window": "New window"
43512
43810
  };
43513
43811
  const ar = {
43514
43812
  "Bold": "غامق",
@@ -43573,7 +43871,14 @@ const ar = {
43573
43871
  "Invalid image URL": "رابط صورة غير صالح",
43574
43872
  "File too large": "الملف كبير جداً",
43575
43873
  "Invalid file type": "نوع ملف غير صالح",
43576
- "More": "المزيد"
43874
+ "More": "المزيد",
43875
+ "Save": "Save",
43876
+ "Insert/Edit Link": "Insert/Edit Link",
43877
+ "Text to display": "Text to display",
43878
+ "Title": "Title",
43879
+ "Open link in...": "Open link in...",
43880
+ "Current window": "Current window",
43881
+ "New window": "New window"
43577
43882
  };
43578
43883
  const ca = {
43579
43884
  "Bold": "Negreta",
@@ -43638,7 +43943,14 @@ const ca = {
43638
43943
  "Invalid image URL": "URL d'imatge no vàlida",
43639
43944
  "File too large": "Fitxer massa gran",
43640
43945
  "Invalid file type": "Tipus de fitxer no vàlid",
43641
- "More": "Més"
43946
+ "More": "Més",
43947
+ "Save": "Save",
43948
+ "Insert/Edit Link": "Insert/Edit Link",
43949
+ "Text to display": "Text to display",
43950
+ "Title": "Title",
43951
+ "Open link in...": "Open link in...",
43952
+ "Current window": "Current window",
43953
+ "New window": "New window"
43642
43954
  };
43643
43955
  const zh = {
43644
43956
  "Bold": "粗体",
@@ -43703,7 +44015,14 @@ const zh = {
43703
44015
  "Invalid image URL": "无效的图片 URL",
43704
44016
  "File too large": "文件过大",
43705
44017
  "Invalid file type": "无效的文件类型",
43706
- "More": "更多"
44018
+ "More": "更多",
44019
+ "Save": "Save",
44020
+ "Insert/Edit Link": "Insert/Edit Link",
44021
+ "Text to display": "Text to display",
44022
+ "Title": "Title",
44023
+ "Open link in...": "Open link in...",
44024
+ "Current window": "Current window",
44025
+ "New window": "New window"
43707
44026
  };
43708
44027
  const cs = {
43709
44028
  "Bold": "Tučné",
@@ -43768,7 +44087,14 @@ const cs = {
43768
44087
  "Invalid image URL": "Neplatná URL obrázku",
43769
44088
  "File too large": "Soubor je příliš velký",
43770
44089
  "Invalid file type": "Neplatný typ souboru",
43771
- "More": "Více"
44090
+ "More": "Více",
44091
+ "Save": "Save",
44092
+ "Insert/Edit Link": "Insert/Edit Link",
44093
+ "Text to display": "Text to display",
44094
+ "Title": "Title",
44095
+ "Open link in...": "Open link in...",
44096
+ "Current window": "Current window",
44097
+ "New window": "New window"
43772
44098
  };
43773
44099
  const da = {
43774
44100
  "Bold": "Fed",
@@ -43833,7 +44159,14 @@ const da = {
43833
44159
  "Invalid image URL": "Ugyldig billed-URL",
43834
44160
  "File too large": "Filen er for stor",
43835
44161
  "Invalid file type": "Ugyldig filtype",
43836
- "More": "Mere"
44162
+ "More": "Mere",
44163
+ "Save": "Save",
44164
+ "Insert/Edit Link": "Insert/Edit Link",
44165
+ "Text to display": "Text to display",
44166
+ "Title": "Title",
44167
+ "Open link in...": "Open link in...",
44168
+ "Current window": "Current window",
44169
+ "New window": "New window"
43837
44170
  };
43838
44171
  const enGb = {
43839
44172
  "Bold": "Bold",
@@ -43898,7 +44231,14 @@ const enGb = {
43898
44231
  "Invalid image URL": "Invalid image URL",
43899
44232
  "File too large": "File too large",
43900
44233
  "Invalid file type": "Invalid file type",
43901
- "More": "More"
44234
+ "More": "More",
44235
+ "Save": "Save",
44236
+ "Insert/Edit Link": "Insert/Edit Link",
44237
+ "Text to display": "Text to display",
44238
+ "Title": "Title",
44239
+ "Open link in...": "Open link in...",
44240
+ "Current window": "Current window",
44241
+ "New window": "New window"
43902
44242
  };
43903
44243
  const fi = {
43904
44244
  "Bold": "Lihavoitu",
@@ -43963,7 +44303,14 @@ const fi = {
43963
44303
  "Invalid image URL": "Virheellinen kuvan URL",
43964
44304
  "File too large": "Tiedosto on liian suuri",
43965
44305
  "Invalid file type": "Virheellinen tiedostotyyppi",
43966
- "More": "Lisää"
44306
+ "More": "Lisää",
44307
+ "Save": "Save",
44308
+ "Insert/Edit Link": "Insert/Edit Link",
44309
+ "Text to display": "Text to display",
44310
+ "Title": "Title",
44311
+ "Open link in...": "Open link in...",
44312
+ "Current window": "Current window",
44313
+ "New window": "New window"
43967
44314
  };
43968
44315
  const fr = {
43969
44316
  "Bold": "Gras",
@@ -44028,7 +44375,14 @@ const fr = {
44028
44375
  "Invalid image URL": "URL d'image invalide",
44029
44376
  "File too large": "Fichier trop volumineux",
44030
44377
  "Invalid file type": "Type de fichier invalide",
44031
- "More": "Plus"
44378
+ "More": "Plus",
44379
+ "Save": "Save",
44380
+ "Insert/Edit Link": "Insert/Edit Link",
44381
+ "Text to display": "Text to display",
44382
+ "Title": "Title",
44383
+ "Open link in...": "Open link in...",
44384
+ "Current window": "Current window",
44385
+ "New window": "New window"
44032
44386
  };
44033
44387
  const frCa = {
44034
44388
  "Bold": "Gras",
@@ -44093,7 +44447,14 @@ const frCa = {
44093
44447
  "Invalid image URL": "URL d'image invalide",
44094
44448
  "File too large": "Fichier trop volumineux",
44095
44449
  "Invalid file type": "Type de fichier invalide",
44096
- "More": "Plus"
44450
+ "More": "Plus",
44451
+ "Save": "Save",
44452
+ "Insert/Edit Link": "Insert/Edit Link",
44453
+ "Text to display": "Text to display",
44454
+ "Title": "Title",
44455
+ "Open link in...": "Open link in...",
44456
+ "Current window": "Current window",
44457
+ "New window": "New window"
44097
44458
  };
44098
44459
  const de = {
44099
44460
  "Bold": "Fett",
@@ -44158,7 +44519,14 @@ const de = {
44158
44519
  "Invalid image URL": "Ungültige Bild-URL",
44159
44520
  "File too large": "Datei zu groß",
44160
44521
  "Invalid file type": "Ungültiger Dateityp",
44161
- "More": "Mehr"
44522
+ "More": "Mehr",
44523
+ "Save": "Save",
44524
+ "Insert/Edit Link": "Insert/Edit Link",
44525
+ "Text to display": "Text to display",
44526
+ "Title": "Title",
44527
+ "Open link in...": "Open link in...",
44528
+ "Current window": "Current window",
44529
+ "New window": "New window"
44162
44530
  };
44163
44531
  const el = {
44164
44532
  "Bold": "Έντονα",
@@ -44223,7 +44591,14 @@ const el = {
44223
44591
  "Invalid image URL": "Μη έγκυρο URL εικόνας",
44224
44592
  "File too large": "Το αρχείο είναι πολύ μεγάλο",
44225
44593
  "Invalid file type": "Μη έγκυρος τύπος αρχείου",
44226
- "More": "Περισσότερα"
44594
+ "More": "Περισσότερα",
44595
+ "Save": "Save",
44596
+ "Insert/Edit Link": "Insert/Edit Link",
44597
+ "Text to display": "Text to display",
44598
+ "Title": "Title",
44599
+ "Open link in...": "Open link in...",
44600
+ "Current window": "Current window",
44601
+ "New window": "New window"
44227
44602
  };
44228
44603
  const hu = {
44229
44604
  "Bold": "Félkövér",
@@ -44288,7 +44663,14 @@ const hu = {
44288
44663
  "Invalid image URL": "Érvénytelen kép URL",
44289
44664
  "File too large": "A fájl túl nagy",
44290
44665
  "Invalid file type": "Érvénytelen fájltípus",
44291
- "More": "Több"
44666
+ "More": "Több",
44667
+ "Save": "Save",
44668
+ "Insert/Edit Link": "Insert/Edit Link",
44669
+ "Text to display": "Text to display",
44670
+ "Title": "Title",
44671
+ "Open link in...": "Open link in...",
44672
+ "Current window": "Current window",
44673
+ "New window": "New window"
44292
44674
  };
44293
44675
  const id = {
44294
44676
  "Bold": "Tebal",
@@ -44353,7 +44735,14 @@ const id = {
44353
44735
  "Invalid image URL": "URL gambar tidak valid",
44354
44736
  "File too large": "File terlalu besar",
44355
44737
  "Invalid file type": "Jenis file tidak valid",
44356
- "More": "Lainnya"
44738
+ "More": "Lainnya",
44739
+ "Save": "Save",
44740
+ "Insert/Edit Link": "Insert/Edit Link",
44741
+ "Text to display": "Text to display",
44742
+ "Title": "Title",
44743
+ "Open link in...": "Open link in...",
44744
+ "Current window": "Current window",
44745
+ "New window": "New window"
44357
44746
  };
44358
44747
  const it = {
44359
44748
  "Bold": "Grassetto",
@@ -44418,7 +44807,14 @@ const it = {
44418
44807
  "Invalid image URL": "URL immagine non valido",
44419
44808
  "File too large": "File troppo grande",
44420
44809
  "Invalid file type": "Tipo di file non valido",
44421
- "More": "Altro"
44810
+ "More": "Altro",
44811
+ "Save": "Save",
44812
+ "Insert/Edit Link": "Insert/Edit Link",
44813
+ "Text to display": "Text to display",
44814
+ "Title": "Title",
44815
+ "Open link in...": "Open link in...",
44816
+ "Current window": "Current window",
44817
+ "New window": "New window"
44422
44818
  };
44423
44819
  const ja = {
44424
44820
  "Bold": "太字",
@@ -44483,7 +44879,14 @@ const ja = {
44483
44879
  "Invalid image URL": "無効な画像URL",
44484
44880
  "File too large": "ファイルが大きすぎます",
44485
44881
  "Invalid file type": "無効なファイル形式",
44486
- "More": "もっと見る"
44882
+ "More": "もっと見る",
44883
+ "Save": "Save",
44884
+ "Insert/Edit Link": "Insert/Edit Link",
44885
+ "Text to display": "Text to display",
44886
+ "Title": "Title",
44887
+ "Open link in...": "Open link in...",
44888
+ "Current window": "Current window",
44889
+ "New window": "New window"
44487
44890
  };
44488
44891
  const ko = {
44489
44892
  "Bold": "굵게",
@@ -44548,7 +44951,14 @@ const ko = {
44548
44951
  "Invalid image URL": "잘못된 이미지 URL",
44549
44952
  "File too large": "파일이 너무 큽니다",
44550
44953
  "Invalid file type": "잘못된 파일 형식",
44551
- "More": "더 보기"
44954
+ "More": "더 보기",
44955
+ "Save": "Save",
44956
+ "Insert/Edit Link": "Insert/Edit Link",
44957
+ "Text to display": "Text to display",
44958
+ "Title": "Title",
44959
+ "Open link in...": "Open link in...",
44960
+ "Current window": "Current window",
44961
+ "New window": "New window"
44552
44962
  };
44553
44963
  const nl = {
44554
44964
  "Bold": "Vet",
@@ -44613,7 +45023,14 @@ const nl = {
44613
45023
  "Invalid image URL": "Ongeldige afbeeldings-URL",
44614
45024
  "File too large": "Bestand te groot",
44615
45025
  "Invalid file type": "Ongeldig bestandstype",
44616
- "More": "Meer"
45026
+ "More": "Meer",
45027
+ "Save": "Save",
45028
+ "Insert/Edit Link": "Insert/Edit Link",
45029
+ "Text to display": "Text to display",
45030
+ "Title": "Title",
45031
+ "Open link in...": "Open link in...",
45032
+ "Current window": "Current window",
45033
+ "New window": "New window"
44617
45034
  };
44618
45035
  const nb = {
44619
45036
  "Bold": "Fet",
@@ -44678,7 +45095,14 @@ const nb = {
44678
45095
  "Invalid image URL": "Ugyldig bilde-URL",
44679
45096
  "File too large": "Filen er for stor",
44680
45097
  "Invalid file type": "Ugyldig filtype",
44681
- "More": "Mer"
45098
+ "More": "Mer",
45099
+ "Save": "Save",
45100
+ "Insert/Edit Link": "Insert/Edit Link",
45101
+ "Text to display": "Text to display",
45102
+ "Title": "Title",
45103
+ "Open link in...": "Open link in...",
45104
+ "Current window": "Current window",
45105
+ "New window": "New window"
44682
45106
  };
44683
45107
  const pl = {
44684
45108
  "Bold": "Pogrubienie",
@@ -44743,7 +45167,14 @@ const pl = {
44743
45167
  "Invalid image URL": "Nieprawidłowy URL obrazu",
44744
45168
  "File too large": "Plik jest za duży",
44745
45169
  "Invalid file type": "Nieprawidłowy typ pliku",
44746
- "More": "Więcej"
45170
+ "More": "Więcej",
45171
+ "Save": "Save",
45172
+ "Insert/Edit Link": "Insert/Edit Link",
45173
+ "Text to display": "Text to display",
45174
+ "Title": "Title",
45175
+ "Open link in...": "Open link in...",
45176
+ "Current window": "Current window",
45177
+ "New window": "New window"
44747
45178
  };
44748
45179
  const pt = {
44749
45180
  "Bold": "Negrito",
@@ -44808,7 +45239,14 @@ const pt = {
44808
45239
  "Invalid image URL": "URL de imagem inválido",
44809
45240
  "File too large": "Arquivo muito grande",
44810
45241
  "Invalid file type": "Tipo de arquivo inválido",
44811
- "More": "Mais"
45242
+ "More": "Mais",
45243
+ "Save": "Save",
45244
+ "Insert/Edit Link": "Insert/Edit Link",
45245
+ "Text to display": "Text to display",
45246
+ "Title": "Title",
45247
+ "Open link in...": "Open link in...",
45248
+ "Current window": "Current window",
45249
+ "New window": "New window"
44812
45250
  };
44813
45251
  const ro = {
44814
45252
  "Bold": "Îngroșat",
@@ -44873,7 +45311,14 @@ const ro = {
44873
45311
  "Invalid image URL": "URL imagine invalid",
44874
45312
  "File too large": "Fișierul este prea mare",
44875
45313
  "Invalid file type": "Tip de fișier invalid",
44876
- "More": "Mai mult"
45314
+ "More": "Mai mult",
45315
+ "Save": "Save",
45316
+ "Insert/Edit Link": "Insert/Edit Link",
45317
+ "Text to display": "Text to display",
45318
+ "Title": "Title",
45319
+ "Open link in...": "Open link in...",
45320
+ "Current window": "Current window",
45321
+ "New window": "New window"
44877
45322
  };
44878
45323
  const ru = {
44879
45324
  "Bold": "Полужирный",
@@ -44938,7 +45383,14 @@ const ru = {
44938
45383
  "Invalid image URL": "Недопустимый URL изображения",
44939
45384
  "File too large": "Файл слишком большой",
44940
45385
  "Invalid file type": "Недопустимый тип файла",
44941
- "More": "Ещё"
45386
+ "More": "Ещё",
45387
+ "Save": "Save",
45388
+ "Insert/Edit Link": "Insert/Edit Link",
45389
+ "Text to display": "Text to display",
45390
+ "Title": "Title",
45391
+ "Open link in...": "Open link in...",
45392
+ "Current window": "Current window",
45393
+ "New window": "New window"
44942
45394
  };
44943
45395
  const sr = {
44944
45396
  "Bold": "Подебљано",
@@ -45003,7 +45455,14 @@ const sr = {
45003
45455
  "Invalid image URL": "Неважећи URL слике",
45004
45456
  "File too large": "Датотека је превелика",
45005
45457
  "Invalid file type": "Неважећи тип датотеке",
45006
- "More": "Још"
45458
+ "More": "Још",
45459
+ "Save": "Save",
45460
+ "Insert/Edit Link": "Insert/Edit Link",
45461
+ "Text to display": "Text to display",
45462
+ "Title": "Title",
45463
+ "Open link in...": "Open link in...",
45464
+ "Current window": "Current window",
45465
+ "New window": "New window"
45007
45466
  };
45008
45467
  const sl = {
45009
45468
  "Bold": "Krepko",
@@ -45068,7 +45527,14 @@ const sl = {
45068
45527
  "Invalid image URL": "Neveljaven URL slike",
45069
45528
  "File too large": "Datoteka je prevelika",
45070
45529
  "Invalid file type": "Neveljavna vrsta datoteke",
45071
- "More": "Več"
45530
+ "More": "Več",
45531
+ "Save": "Save",
45532
+ "Insert/Edit Link": "Insert/Edit Link",
45533
+ "Text to display": "Text to display",
45534
+ "Title": "Title",
45535
+ "Open link in...": "Open link in...",
45536
+ "Current window": "Current window",
45537
+ "New window": "New window"
45072
45538
  };
45073
45539
  const es = {
45074
45540
  "Bold": "Negrita",
@@ -45133,7 +45599,14 @@ const es = {
45133
45599
  "Invalid image URL": "URL de imagen no válida",
45134
45600
  "File too large": "Archivo demasiado grande",
45135
45601
  "Invalid file type": "Tipo de archivo no válido",
45136
- "More": "Más"
45602
+ "More": "Más",
45603
+ "Save": "Save",
45604
+ "Insert/Edit Link": "Insert/Edit Link",
45605
+ "Text to display": "Text to display",
45606
+ "Title": "Title",
45607
+ "Open link in...": "Open link in...",
45608
+ "Current window": "Current window",
45609
+ "New window": "New window"
45137
45610
  };
45138
45611
  const sv = {
45139
45612
  "Bold": "Fet",
@@ -45198,7 +45671,14 @@ const sv = {
45198
45671
  "Invalid image URL": "Ogiltig bild-URL",
45199
45672
  "File too large": "Filen är för stor",
45200
45673
  "Invalid file type": "Ogiltig filtyp",
45201
- "More": "Mer"
45674
+ "More": "Mer",
45675
+ "Save": "Save",
45676
+ "Insert/Edit Link": "Insert/Edit Link",
45677
+ "Text to display": "Text to display",
45678
+ "Title": "Title",
45679
+ "Open link in...": "Open link in...",
45680
+ "Current window": "Current window",
45681
+ "New window": "New window"
45202
45682
  };
45203
45683
  const zhTw = {
45204
45684
  "Bold": "粗體",
@@ -45263,7 +45743,14 @@ const zhTw = {
45263
45743
  "Invalid image URL": "無效的圖片 URL",
45264
45744
  "File too large": "檔案過大",
45265
45745
  "Invalid file type": "無效的檔案類型",
45266
- "More": "更多"
45746
+ "More": "更多",
45747
+ "Save": "Save",
45748
+ "Insert/Edit Link": "Insert/Edit Link",
45749
+ "Text to display": "Text to display",
45750
+ "Title": "Title",
45751
+ "Open link in...": "Open link in...",
45752
+ "Current window": "Current window",
45753
+ "New window": "New window"
45267
45754
  };
45268
45755
  const th = {
45269
45756
  "Bold": "ตัวหนา",
@@ -45328,7 +45815,14 @@ const th = {
45328
45815
  "Invalid image URL": "URL รูปภาพไม่ถูกต้อง",
45329
45816
  "File too large": "ไฟล์ใหญ่เกินไป",
45330
45817
  "Invalid file type": "ประเภทไฟล์ไม่ถูกต้อง",
45331
- "More": "เพิ่มเติม"
45818
+ "More": "เพิ่มเติม",
45819
+ "Save": "Save",
45820
+ "Insert/Edit Link": "Insert/Edit Link",
45821
+ "Text to display": "Text to display",
45822
+ "Title": "Title",
45823
+ "Open link in...": "Open link in...",
45824
+ "Current window": "Current window",
45825
+ "New window": "New window"
45332
45826
  };
45333
45827
  const tr = {
45334
45828
  "Bold": "Kalın",
@@ -45393,7 +45887,14 @@ const tr = {
45393
45887
  "Invalid image URL": "Geçersiz resim URL'si",
45394
45888
  "File too large": "Dosya çok büyük",
45395
45889
  "Invalid file type": "Geçersiz dosya türü",
45396
- "More": "Daha fazla"
45890
+ "More": "Daha fazla",
45891
+ "Save": "Save",
45892
+ "Insert/Edit Link": "Insert/Edit Link",
45893
+ "Text to display": "Text to display",
45894
+ "Title": "Title",
45895
+ "Open link in...": "Open link in...",
45896
+ "Current window": "Current window",
45897
+ "New window": "New window"
45397
45898
  };
45398
45899
  const vi = {
45399
45900
  "Bold": "In đậm",
@@ -45458,7 +45959,14 @@ const vi = {
45458
45959
  "Invalid image URL": "URL hình ảnh không hợp lệ",
45459
45960
  "File too large": "Tệp quá lớn",
45460
45961
  "Invalid file type": "Loại tệp không hợp lệ",
45461
- "More": "Thêm"
45962
+ "More": "Thêm",
45963
+ "Save": "Save",
45964
+ "Insert/Edit Link": "Insert/Edit Link",
45965
+ "Text to display": "Text to display",
45966
+ "Title": "Title",
45967
+ "Open link in...": "Open link in...",
45968
+ "Current window": "Current window",
45969
+ "New window": "New window"
45462
45970
  };
45463
45971
  const locales = {
45464
45972
  en,
@@ -45504,8 +46012,8 @@ const availableLocales = Object.keys(locales);
45504
46012
  const TRANSLATION_KEYS = Object.keys(en);
45505
46013
  const lowlight = createLowlight(grammars);
45506
46014
  const fontNames = "Andale Mono=andale mono,times; Arial=arial,helvetica,sans-serif; Arial Black=arial black,avant garde; Book Antiqua=book antiqua,palatino; Comic Sans MS=comic sans ms,sans-serif; Courier New=courier new,courier; Georgia=georgia,palatino; Helvetica=helvetica; Impact=impact,chicago; Tahoma=tahoma,arial,helvetica,sans-serif; Terminal=terminal,monaco; Times New Roman=times new roman,times; Trebuchet MS=trebuchet ms,geneva; Verdana=verdana,geneva";
45507
- const FULL_TOOLBAR = "bold italic underline strikethrough | bullist numlist outdent indent blockquote | fontfamily fontsize || lineheight alignleft aligncenter alignright alignjustify | forecolor backcolor | removeformat copy cut paste | undo redo | image charmap emoticons | fullscreen preview | code link codesample | ltr rtl | searchreplace";
45508
- const BASIC_TOOLBAR = "bold italic underline strikethrough | bullist numlist outdent indent | fontfamily fontsize blockquote || lineheight alignleft aligncenter alignright alignjustify | forecolor backcolor | removeformat copy cut paste | undo redo | charmap emoticons | link | ltr rtl | searchreplace";
46015
+ const FULL_TOOLBAR = "bold italic underline strikethrough | bullist numlist outdent indent blockquote | fontfamily fontsize | lineheight alignleft aligncenter alignright alignjustify | forecolor backcolor | removeformat copy cut paste | undo redo | image charmap emoticons | fullscreen preview | code link codesample | ltr rtl | searchreplace";
46016
+ const BASIC_TOOLBAR = "bold italic underline strikethrough | bullist numlist outdent indent | fontfamily fontsize blockquote | lineheight alignleft aligncenter alignright alignjustify | forecolor backcolor | removeformat copy cut paste | undo redo | charmap emoticons | link | ltr rtl | searchreplace";
45509
46017
  const DEFAULT_FONT_SIZES = "8pt 9pt 10pt 12pt 14pt 18pt 24pt 36pt";
45510
46018
  let editorIdCounter = 0;
45511
46019
  let globalTranslate = (key) => key;
@@ -45770,7 +46278,21 @@ class HTMLEditor {
45770
46278
  TextAlign.configure({
45771
46279
  types: ["heading", "paragraph"]
45772
46280
  }),
45773
- Link.configure({
46281
+ Link.extend({
46282
+ addAttributes() {
46283
+ return {
46284
+ ...this.parent?.(),
46285
+ title: {
46286
+ default: null,
46287
+ parseHTML: (element) => element.getAttribute("title"),
46288
+ renderHTML: (attributes) => {
46289
+ if (!attributes.title) return {};
46290
+ return { title: attributes.title };
46291
+ }
46292
+ }
46293
+ };
46294
+ }
46295
+ }).configure({
45774
46296
  openOnClick: false,
45775
46297
  HTMLAttributes: {
45776
46298
  rel: "noopener noreferrer"
@@ -46005,8 +46527,10 @@ export {
46005
46527
  FontSize,
46006
46528
  HTMLEditor,
46007
46529
  LineHeight,
46530
+ LinkEditor,
46008
46531
  SearchReplace,
46009
46532
  SignatureBlock,
46533
+ SourceEditor,
46010
46534
  TRANSLATION_KEYS,
46011
46535
  TextDirection,
46012
46536
  Toolbar,
@@ -46020,4 +46544,3 @@ export {
46020
46544
  setGetFileSrc,
46021
46545
  setTranslate
46022
46546
  };
46023
- //# sourceMappingURL=index.mjs.map