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