@mdaemon/html-editor 1.3.0 → 1.4.0

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
@@ -23057,6 +23057,96 @@ var StarterKit = Extension.create({
23057
23057
  return extensions;
23058
23058
  }
23059
23059
  });
23060
+ var Subscript = Mark2.create({
23061
+ name: "subscript",
23062
+ addOptions() {
23063
+ return {
23064
+ HTMLAttributes: {}
23065
+ };
23066
+ },
23067
+ parseHTML() {
23068
+ return [
23069
+ {
23070
+ tag: "sub"
23071
+ },
23072
+ {
23073
+ style: "vertical-align",
23074
+ getAttrs(value) {
23075
+ if (value !== "sub") {
23076
+ return false;
23077
+ }
23078
+ return null;
23079
+ }
23080
+ }
23081
+ ];
23082
+ },
23083
+ renderHTML({ HTMLAttributes }) {
23084
+ return ["sub", mergeAttributes(this.options.HTMLAttributes, HTMLAttributes), 0];
23085
+ },
23086
+ addCommands() {
23087
+ return {
23088
+ setSubscript: () => ({ commands }) => {
23089
+ return commands.setMark(this.name);
23090
+ },
23091
+ toggleSubscript: () => ({ commands }) => {
23092
+ return commands.toggleMark(this.name);
23093
+ },
23094
+ unsetSubscript: () => ({ commands }) => {
23095
+ return commands.unsetMark(this.name);
23096
+ }
23097
+ };
23098
+ },
23099
+ addKeyboardShortcuts() {
23100
+ return {
23101
+ "Mod-,": () => this.editor.commands.toggleSubscript()
23102
+ };
23103
+ }
23104
+ });
23105
+ var Superscript = Mark2.create({
23106
+ name: "superscript",
23107
+ addOptions() {
23108
+ return {
23109
+ HTMLAttributes: {}
23110
+ };
23111
+ },
23112
+ parseHTML() {
23113
+ return [
23114
+ {
23115
+ tag: "sup"
23116
+ },
23117
+ {
23118
+ style: "vertical-align",
23119
+ getAttrs(value) {
23120
+ if (value !== "super") {
23121
+ return false;
23122
+ }
23123
+ return null;
23124
+ }
23125
+ }
23126
+ ];
23127
+ },
23128
+ renderHTML({ HTMLAttributes }) {
23129
+ return ["sup", mergeAttributes(this.options.HTMLAttributes, HTMLAttributes), 0];
23130
+ },
23131
+ addCommands() {
23132
+ return {
23133
+ setSuperscript: () => ({ commands }) => {
23134
+ return commands.setMark(this.name);
23135
+ },
23136
+ toggleSuperscript: () => ({ commands }) => {
23137
+ return commands.toggleMark(this.name);
23138
+ },
23139
+ unsetSuperscript: () => ({ commands }) => {
23140
+ return commands.unsetMark(this.name);
23141
+ }
23142
+ };
23143
+ },
23144
+ addKeyboardShortcuts() {
23145
+ return {
23146
+ "Mod-.": () => this.editor.commands.toggleSuperscript()
23147
+ };
23148
+ }
23149
+ });
23060
23150
  var TextAlign = Extension.create({
23061
23151
  name: "textAlign",
23062
23152
  addOptions() {
@@ -41871,7 +41961,22 @@ class EmojiPicker {
41871
41961
  }
41872
41962
  }
41873
41963
  const DEFAULT_MAX_FILE_SIZE = 10 * 1024 * 1024;
41874
- const ACCEPTED_IMAGE_TYPES = ["image/jpeg", "image/png", "image/gif", "image/webp", "image/svg+xml"];
41964
+ const ACCEPTED_IMAGE_TYPES = ["image/jpeg", "image/png", "image/gif", "image/webp", "image/svg+xml", "image/bmp"];
41965
+ const EXT_TO_MIME = {
41966
+ jpg: "image/jpeg",
41967
+ jpeg: "image/jpeg",
41968
+ jpe: "image/jpeg",
41969
+ png: "image/png",
41970
+ gif: "image/gif",
41971
+ bmp: "image/bmp",
41972
+ webp: "image/webp",
41973
+ svg: "image/svg+xml"
41974
+ };
41975
+ function parseImageFileTypes(spec) {
41976
+ if (!spec) return null;
41977
+ const exts = spec.split(/[\s,|]+/).map((s) => s.trim().toLowerCase().replace(/^\./, "")).filter(Boolean);
41978
+ return exts.length > 0 ? exts : null;
41979
+ }
41875
41980
  const SVG_DANGEROUS_TAGS = [
41876
41981
  "script",
41877
41982
  "foreignobject",
@@ -42146,16 +42251,44 @@ class ImageUpload {
42146
42251
  errorEl.textContent = "";
42147
42252
  }
42148
42253
  }
42149
- handleFileSelected(file) {
42150
- this.clearError();
42254
+ /** Whether the file matches the configured/default accepted image types. */
42255
+ isAcceptedType(file) {
42256
+ const exts = parseImageFileTypes(this.options.fileTypes);
42257
+ if (!exts) {
42258
+ return ACCEPTED_IMAGE_TYPES.includes(file.type);
42259
+ }
42260
+ const name = (file.name ?? "").toLowerCase();
42261
+ const dot = name.lastIndexOf(".");
42262
+ const ext = dot >= 0 ? name.slice(dot + 1) : "";
42263
+ if (ext && exts.includes(ext)) return true;
42264
+ const acceptedMimes = exts.map((e) => EXT_TO_MIME[e]).filter(Boolean);
42265
+ return !!file.type && acceptedMimes.includes(file.type);
42266
+ }
42267
+ /**
42268
+ * Validate a file before upload. Returns an error message (translated) to
42269
+ * reject, or null to allow. Runs the caller's validate hook, then the
42270
+ * type and size guards.
42271
+ */
42272
+ validateFile(file) {
42151
42273
  const t = this.options.trans;
42152
- if (!ACCEPTED_IMAGE_TYPES.includes(file.type)) {
42153
- this.showError(t("Invalid file type"));
42154
- return;
42274
+ if (this.options.validate) {
42275
+ const msg = this.options.validate(file);
42276
+ if (msg) return msg;
42277
+ }
42278
+ if (!this.isAcceptedType(file)) {
42279
+ return t("Invalid file type");
42155
42280
  }
42156
42281
  const maxSize = this.options.uploadMaxSize ?? DEFAULT_MAX_FILE_SIZE;
42157
42282
  if (file.size > maxSize) {
42158
- this.showError(t("File too large"));
42283
+ return t("File too large");
42284
+ }
42285
+ return null;
42286
+ }
42287
+ handleFileSelected(file) {
42288
+ this.clearError();
42289
+ const validationError = this.validateFile(file);
42290
+ if (validationError) {
42291
+ this.showError(validationError);
42159
42292
  return;
42160
42293
  }
42161
42294
  this.currentFile = file;
@@ -42242,16 +42375,14 @@ class ImageUpload {
42242
42375
  this.options.onInsert(src, alt);
42243
42376
  this.close();
42244
42377
  } catch (err) {
42245
- this.showError(this.options.trans("Upload failed"));
42378
+ const message = err instanceof Error && err.message ? err.message : this.options.trans("Upload failed");
42379
+ this.showError(message);
42246
42380
  }
42247
42381
  }
42248
42382
  uploadFile(file) {
42249
- if (!ACCEPTED_IMAGE_TYPES.includes(file.type)) {
42250
- return Promise.reject(new Error("Invalid file type"));
42251
- }
42252
- const maxSize = this.options.uploadMaxSize ?? DEFAULT_MAX_FILE_SIZE;
42253
- if (file.size > maxSize) {
42254
- return Promise.reject(new Error("File too large"));
42383
+ const validationError = this.validateFile(file);
42384
+ if (validationError) {
42385
+ return Promise.reject(new Error(validationError));
42255
42386
  }
42256
42387
  if (file.type === "image/svg+xml") {
42257
42388
  return this.sanitizeAndUploadSVG(file);
@@ -42887,6 +43018,126 @@ class LinkEditor {
42887
43018
  }
42888
43019
  }
42889
43020
  }
43021
+ class AnchorDialog {
43022
+ options;
43023
+ overlay = null;
43024
+ dialog = null;
43025
+ nameInput = null;
43026
+ errorEl = null;
43027
+ constructor(options) {
43028
+ this.options = options;
43029
+ }
43030
+ get tiptap() {
43031
+ return this.options.editor.getTipTap();
43032
+ }
43033
+ open() {
43034
+ if (!this.overlay) {
43035
+ this.createDialog();
43036
+ }
43037
+ if (this.nameInput) this.nameInput.value = "";
43038
+ this.clearError();
43039
+ this.overlay.style.display = "flex";
43040
+ this.nameInput?.focus();
43041
+ }
43042
+ close() {
43043
+ if (this.overlay) {
43044
+ this.overlay.style.display = "none";
43045
+ }
43046
+ }
43047
+ clearError() {
43048
+ if (this.errorEl) {
43049
+ this.errorEl.style.display = "none";
43050
+ this.errorEl.textContent = "";
43051
+ }
43052
+ }
43053
+ showError(message) {
43054
+ if (this.errorEl) {
43055
+ this.errorEl.textContent = message;
43056
+ this.errorEl.style.display = "block";
43057
+ }
43058
+ }
43059
+ save() {
43060
+ const trans = this.options.trans;
43061
+ const name = this.nameInput?.value.trim() ?? "";
43062
+ if (!name) {
43063
+ this.showError(trans("Anchor name is required"));
43064
+ return;
43065
+ }
43066
+ if (/\s/.test(name)) {
43067
+ this.showError(trans("Anchor name cannot contain spaces"));
43068
+ return;
43069
+ }
43070
+ this.tiptap?.chain().focus().insertContent({ type: "anchor", attrs: { id: name, name } }).run();
43071
+ this.close();
43072
+ }
43073
+ createDialog() {
43074
+ const trans = this.options.trans;
43075
+ const skin = this.options.editor.getConfig().skin ?? "oxide";
43076
+ this.overlay = document.createElement("div");
43077
+ this.overlay.className = "md-dialog-overlay";
43078
+ this.overlay.addEventListener("click", (e) => {
43079
+ if (e.target === this.overlay) {
43080
+ this.close();
43081
+ }
43082
+ });
43083
+ const themeWrapper = document.createElement("div");
43084
+ themeWrapper.className = `md-editor-${skin}`;
43085
+ themeWrapper.style.display = "contents";
43086
+ this.dialog = document.createElement("div");
43087
+ this.dialog.className = "md-dialog md-anchor-dialog";
43088
+ const header = document.createElement("div");
43089
+ header.className = "md-dialog-header";
43090
+ header.innerHTML = `
43091
+ <h3>${trans("Insert anchor")}</h3>
43092
+ <button type="button" class="md-dialog-close">×</button>
43093
+ `;
43094
+ header.querySelector(".md-dialog-close")?.addEventListener("click", () => this.close());
43095
+ const body = document.createElement("div");
43096
+ body.className = "md-dialog-body";
43097
+ const nameRow = document.createElement("div");
43098
+ nameRow.className = "md-anchor-dialog-row";
43099
+ nameRow.innerHTML = `<label>${trans("Anchor name")}</label>`;
43100
+ this.nameInput = document.createElement("input");
43101
+ this.nameInput.type = "text";
43102
+ this.nameInput.className = "md-anchor-dialog-input";
43103
+ nameRow.appendChild(this.nameInput);
43104
+ this.errorEl = document.createElement("div");
43105
+ this.errorEl.className = "md-anchor-dialog-error";
43106
+ this.errorEl.style.display = "none";
43107
+ const footer = document.createElement("div");
43108
+ footer.className = "md-anchor-dialog-footer";
43109
+ footer.innerHTML = `
43110
+ <button type="button" class="md-btn md-anchor-dialog-cancel">${trans("Cancel")}</button>
43111
+ <button type="button" class="md-btn md-btn-primary md-anchor-dialog-save">${trans("Save")}</button>
43112
+ `;
43113
+ footer.querySelector(".md-anchor-dialog-cancel")?.addEventListener("click", () => this.close());
43114
+ footer.querySelector(".md-anchor-dialog-save")?.addEventListener("click", () => this.save());
43115
+ body.appendChild(nameRow);
43116
+ body.appendChild(this.errorEl);
43117
+ body.appendChild(footer);
43118
+ this.dialog.appendChild(header);
43119
+ this.dialog.appendChild(body);
43120
+ themeWrapper.appendChild(this.dialog);
43121
+ this.overlay.appendChild(themeWrapper);
43122
+ this.overlay.addEventListener("keydown", (e) => {
43123
+ if (e.key === "Escape") {
43124
+ this.close();
43125
+ } else if (e.key === "Enter") {
43126
+ this.save();
43127
+ }
43128
+ });
43129
+ document.body.appendChild(this.overlay);
43130
+ }
43131
+ destroy() {
43132
+ if (this.overlay) {
43133
+ this.overlay.remove();
43134
+ this.overlay = null;
43135
+ this.dialog = null;
43136
+ this.nameInput = null;
43137
+ this.errorEl = null;
43138
+ }
43139
+ }
43140
+ }
42890
43141
  const SPEECH_LANGUAGES = [
42891
43142
  { code: "ar-SA", name: "العربية" },
42892
43143
  { code: "ca-ES", name: "Català" },
@@ -43457,6 +43708,13 @@ const DEFAULT_BUTTON_PRIORITY = {
43457
43708
  link: 1,
43458
43709
  forecolor: 1
43459
43710
  };
43711
+ const DEFAULT_BLOCK_FORMATS = "Paragraph=p;Heading 1=h1;Heading 2=h2;Heading 3=h3;Heading 4=h4;Heading 5=h5;Heading 6=h6";
43712
+ const DEFAULT_STYLE_FORMATS = [
43713
+ { title: "Blue Title", block: "h3", styles: { color: "Blue" } },
43714
+ { title: "Red Title", block: "h3", styles: { color: "Red" } },
43715
+ { title: "Marker: Yellow", inline: "span", styles: { "background-color": "Yellow" } },
43716
+ { title: "Marker: Green", inline: "span", styles: { "background-color": "Lime" } }
43717
+ ];
43460
43718
  const DEFAULT_COLORS = [
43461
43719
  { value: "#000000", label: "Black" },
43462
43720
  { value: "#434343", label: "Dark Gray 4" },
@@ -43510,6 +43768,7 @@ class Toolbar {
43510
43768
  searchReplace = null;
43511
43769
  sourceEditor = null;
43512
43770
  linkEditor = null;
43771
+ anchorDialog = null;
43513
43772
  speechToText = null;
43514
43773
  dictation = null;
43515
43774
  updateInterval = null;
@@ -43706,6 +43965,33 @@ class Toolbar {
43706
43965
  return this.createActionButton("strikethrough", this.icon("strikethrough"), this.trans("Strikethrough"), () => {
43707
43966
  this.tiptap?.chain().focus().toggleStrike().run();
43708
43967
  }, () => this.tiptap?.isActive("strike") ?? false);
43968
+ case "subscript":
43969
+ return this.createActionButton("subscript", this.icon("subscript"), this.trans("Subscript"), () => {
43970
+ this.tiptap?.chain().focus().toggleSubscript().run();
43971
+ }, () => this.tiptap?.isActive("subscript") ?? false);
43972
+ case "superscript":
43973
+ return this.createActionButton("superscript", this.icon("superscript"), this.trans("Superscript"), () => {
43974
+ this.tiptap?.chain().focus().toggleSuperscript().run();
43975
+ }, () => this.tiptap?.isActive("superscript") ?? false);
43976
+ case "hr":
43977
+ return this.createActionButton("hr", this.icon("hr"), this.trans("Horizontal rule"), () => {
43978
+ this.tiptap?.chain().focus().setHorizontalRule().run();
43979
+ });
43980
+ case "blocks":
43981
+ case "formatselect":
43982
+ return this.createFormatDropdown();
43983
+ case "styles":
43984
+ return this.createStylesDropdown();
43985
+ case "table":
43986
+ return this.createTableDropdown();
43987
+ case "anchor":
43988
+ return this.createActionButton("anchor", this.icon("anchor"), this.trans("Insert anchor"), () => {
43989
+ this.openAnchorDialog();
43990
+ });
43991
+ case "unlink":
43992
+ return this.createActionButton("unlink", this.icon("unlink"), this.trans("Unlink"), () => {
43993
+ this.tiptap?.chain().focus().unsetLink().run();
43994
+ }, () => this.tiptap?.isActive("link") ?? false);
43709
43995
  case "bullist":
43710
43996
  return this.createActionButton("bullist", this.icon("bullist"), this.trans("Bullet list"), () => {
43711
43997
  this.tiptap?.chain().focus().toggleBulletList().run();
@@ -43958,6 +44244,126 @@ class Toolbar {
43958
44244
  }
43959
44245
  });
43960
44246
  }
44247
+ createFormatDropdown() {
44248
+ const spec = this.options.config.block_formats ?? DEFAULT_BLOCK_FORMATS;
44249
+ const options = spec.split(";").map((entry) => {
44250
+ const [label, value] = entry.split("=");
44251
+ return { label: this.trans(label.trim()), value: (value ?? label).trim().toLowerCase() };
44252
+ }).filter((o) => o.value);
44253
+ return this.createDropdown("blocks", this.trans("Format"), options, (option) => {
44254
+ const chain = this.tiptap?.chain().focus();
44255
+ if (!chain) return;
44256
+ const m = /^h([1-6])$/.exec(option.value);
44257
+ if (m) {
44258
+ chain.toggleHeading({ level: Number(m[1]) }).run();
44259
+ } else {
44260
+ chain.setParagraph().run();
44261
+ }
44262
+ }, () => {
44263
+ for (let level = 1; level <= 6; level++) {
44264
+ if (this.tiptap?.isActive("heading", { level })) return `h${level}`;
44265
+ }
44266
+ return this.tiptap?.isActive("paragraph") ? "p" : "";
44267
+ });
44268
+ }
44269
+ getStyleFormats() {
44270
+ return this.options.config.style_formats ?? DEFAULT_STYLE_FORMATS;
44271
+ }
44272
+ createStylesDropdown() {
44273
+ const formats = this.getStyleFormats();
44274
+ const options = formats.map((f, i) => ({ label: f.title, value: String(i) }));
44275
+ return this.createDropdown("styles", this.trans("Styles"), options, (option) => {
44276
+ const fmt = formats[Number(option.value)];
44277
+ if (fmt) this.applyStyleFormat(fmt);
44278
+ });
44279
+ }
44280
+ /**
44281
+ * Apply a StyleFormat to the current selection. Block elements map to
44282
+ * heading/paragraph; color and background map to the existing Color /
44283
+ * Highlight marks; classes map to the InlineStyle textStyle class.
44284
+ * (Arbitrary element wrapping from CKEditor stylesSet is not supported.)
44285
+ */
44286
+ applyStyleFormat(fmt) {
44287
+ const chain = this.tiptap?.chain().focus();
44288
+ if (!chain) return;
44289
+ const blockEl = fmt.block;
44290
+ if (blockEl) {
44291
+ const m = /^h([1-6])$/.exec(blockEl);
44292
+ if (m) {
44293
+ chain.setHeading({ level: Number(m[1]) });
44294
+ } else if (blockEl === "p") {
44295
+ chain.setParagraph();
44296
+ }
44297
+ }
44298
+ if (fmt.styles) {
44299
+ if (fmt.styles.color) {
44300
+ chain.setColor(fmt.styles.color);
44301
+ }
44302
+ const bg = fmt.styles["background-color"];
44303
+ if (bg) {
44304
+ chain.setHighlight({ color: bg });
44305
+ }
44306
+ }
44307
+ if (fmt.classes) {
44308
+ chain.setInlineClass(fmt.classes);
44309
+ }
44310
+ chain.run();
44311
+ }
44312
+ createTableDropdown() {
44313
+ const t = this.trans;
44314
+ const options = [
44315
+ { label: t("Insert table"), value: "insert" },
44316
+ { label: t("Insert row before"), value: "rowBefore" },
44317
+ { label: t("Insert row after"), value: "rowAfter" },
44318
+ { label: t("Delete row"), value: "deleteRow" },
44319
+ { label: t("Insert column before"), value: "colBefore" },
44320
+ { label: t("Insert column after"), value: "colAfter" },
44321
+ { label: t("Delete column"), value: "deleteCol" },
44322
+ { label: t("Merge cells"), value: "merge" },
44323
+ { label: t("Split cell"), value: "split" },
44324
+ { label: t("Toggle header row"), value: "headerRow" },
44325
+ { label: t("Delete table"), value: "deleteTable" }
44326
+ ];
44327
+ return this.createDropdown("table", this.trans("Table"), options, (option) => {
44328
+ const chain = this.tiptap?.chain().focus();
44329
+ if (!chain) return;
44330
+ switch (option.value) {
44331
+ case "insert":
44332
+ chain.insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run();
44333
+ break;
44334
+ case "rowBefore":
44335
+ chain.addRowBefore().run();
44336
+ break;
44337
+ case "rowAfter":
44338
+ chain.addRowAfter().run();
44339
+ break;
44340
+ case "deleteRow":
44341
+ chain.deleteRow().run();
44342
+ break;
44343
+ case "colBefore":
44344
+ chain.addColumnBefore().run();
44345
+ break;
44346
+ case "colAfter":
44347
+ chain.addColumnAfter().run();
44348
+ break;
44349
+ case "deleteCol":
44350
+ chain.deleteColumn().run();
44351
+ break;
44352
+ case "merge":
44353
+ chain.mergeCells().run();
44354
+ break;
44355
+ case "split":
44356
+ chain.splitCell().run();
44357
+ break;
44358
+ case "headerRow":
44359
+ chain.toggleHeaderRow().run();
44360
+ break;
44361
+ case "deleteTable":
44362
+ chain.deleteTable().run();
44363
+ break;
44364
+ }
44365
+ });
44366
+ }
43961
44367
  /**
43962
44368
  * Position a fixed-position menu below its trigger button.
43963
44369
  * Uses getBoundingClientRect so the menu escapes any overflow:hidden ancestor.
@@ -44195,6 +44601,15 @@ class Toolbar {
44195
44601
  case "strikethrough":
44196
44602
  isActive2 = this.tiptap?.isActive("strike") ?? false;
44197
44603
  break;
44604
+ case "subscript":
44605
+ isActive2 = this.tiptap?.isActive("subscript") ?? false;
44606
+ break;
44607
+ case "superscript":
44608
+ isActive2 = this.tiptap?.isActive("superscript") ?? false;
44609
+ break;
44610
+ case "unlink":
44611
+ isActive2 = this.tiptap?.isActive("link") ?? false;
44612
+ break;
44198
44613
  case "bullist":
44199
44614
  isActive2 = this.tiptap?.isActive("bulletList") ?? false;
44200
44615
  break;
@@ -44241,6 +44656,9 @@ class Toolbar {
44241
44656
  uploadBasePath: this.options.config.images_upload_base_path,
44242
44657
  uploadMaxSize: this.options.config.images_upload_max_size,
44243
44658
  uploadHeaders: this.options.config.images_upload_headers,
44659
+ fileTypes: this.options.config.images_file_types,
44660
+ validate: this.options.config.images_upload_validate,
44661
+ onError: this.options.config.images_upload_error,
44244
44662
  trans: this.trans
44245
44663
  });
44246
44664
  }
@@ -44255,6 +44673,25 @@ class Toolbar {
44255
44673
  }
44256
44674
  this.linkEditor.open();
44257
44675
  }
44676
+ openAnchorDialog() {
44677
+ if (!this.anchorDialog) {
44678
+ this.anchorDialog = new AnchorDialog({
44679
+ editor: this.options.editor,
44680
+ trans: this.trans
44681
+ });
44682
+ }
44683
+ this.anchorDialog.open();
44684
+ }
44685
+ /**
44686
+ * Enable or disable the whole toolbar (used for read-only mode).
44687
+ * Blocks pointer interaction and dims the toolbar via CSS.
44688
+ */
44689
+ setEnabled(enabled) {
44690
+ this.container.classList.toggle("md-toolbar-disabled", !enabled);
44691
+ if (!enabled) {
44692
+ this.closeAllDropdowns();
44693
+ }
44694
+ }
44258
44695
  openCharMap() {
44259
44696
  if (!this.charMap) {
44260
44697
  this.charMap = new CharacterMap({
@@ -44363,6 +44800,12 @@ class Toolbar {
44363
44800
  this.speechToText = null;
44364
44801
  this.dictation?.destroy();
44365
44802
  this.dictation = null;
44803
+ this.anchorDialog?.destroy();
44804
+ this.anchorDialog = null;
44805
+ this.linkEditor?.destroy();
44806
+ this.linkEditor = null;
44807
+ this.sourceEditor?.destroy();
44808
+ this.sourceEditor = null;
44366
44809
  this.buttonElements.clear();
44367
44810
  this.dropdowns.clear();
44368
44811
  this.removeBodyMenus();
@@ -44387,6 +44830,9 @@ class Toolbar {
44387
44830
  this.searchReplace?.destroy();
44388
44831
  this.speechToText?.destroy();
44389
44832
  this.dictation?.destroy();
44833
+ this.anchorDialog?.destroy();
44834
+ this.linkEditor?.destroy();
44835
+ this.sourceEditor?.destroy();
44390
44836
  this.buttonElements.clear();
44391
44837
  this.dropdowns.clear();
44392
44838
  this.removeBodyMenus();
@@ -44405,6 +44851,10 @@ const SVG_ALIGN_RIGHT = '<svg width="16" height="16" viewBox="0 0 24 24" fill="n
44405
44851
  const SVG_ALIGN_JUSTIFY = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="3" y1="6" x2="21" y2="6"/><line x1="3" y1="12" x2="21" y2="12"/><line x1="3" y1="18" x2="21" y2="18"/></svg>';
44406
44852
  const SVG_IMAGE = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/><polyline points="21 15 16 10 5 21"/></svg>';
44407
44853
  const SVG_CODE = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/></svg>';
44854
+ const SVG_HR = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><line x1="3" y1="12" x2="21" y2="12"/></svg>';
44855
+ const SVG_TABLE = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="1"/><line x1="3" y1="9" x2="21" y2="9"/><line x1="3" y1="15" x2="21" y2="15"/><line x1="9" y1="3" x2="9" y2="21"/><line x1="15" y1="3" x2="15" y2="21"/></svg>';
44856
+ const SVG_ANCHOR = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="5" r="3"/><line x1="12" y1="22" x2="12" y2="8"/><path d="M5 12H2a10 10 0 0 0 20 0h-3"/></svg>';
44857
+ const SVG_UNLINK = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18.84 12.25l1.72-1.71a4 4 0 0 0-5.66-5.66l-1.71 1.72"/><path d="M5.17 11.75l-1.71 1.71a4 4 0 0 0 5.66 5.66l1.71-1.71"/><line x1="2" y1="2" x2="22" y2="22"/></svg>';
44408
44858
  const DEFAULT_ICONS = {
44409
44859
  bold: "B",
44410
44860
  italic: "I",
@@ -44438,7 +44888,15 @@ const DEFAULT_ICONS = {
44438
44888
  searchreplace: "🔍",
44439
44889
  speechtotext: "🎤",
44440
44890
  dictate: "🎙️",
44441
- togglemore: "…"
44891
+ togglemore: "…",
44892
+ subscript: "X₂",
44893
+ superscript: "X²",
44894
+ hr: SVG_HR,
44895
+ table: SVG_TABLE,
44896
+ anchor: SVG_ANCHOR,
44897
+ unlink: SVG_UNLINK,
44898
+ blocks: "¶",
44899
+ styles: "A"
44442
44900
  };
44443
44901
  const CONFAB_ICONS = {
44444
44902
  bold: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 4h8a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z"/><path d="M6 12h9a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z"/></svg>',
@@ -44473,7 +44931,15 @@ const CONFAB_ICONS = {
44473
44931
  searchreplace: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.6" y2="16.6"/></svg>',
44474
44932
  speechtotext: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"/><path d="M19 10v2a7 7 0 0 1-14 0v-2"/><line x1="12" y1="19" x2="12" y2="23"/><line x1="8" y1="23" x2="16" y2="23"/></svg>',
44475
44933
  dictate: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"/><path d="M19 10v2a7 7 0 0 1-14 0v-2"/><circle cx="12" cy="12" r="1" fill="currentColor" stroke="none"/><circle cx="12" cy="8" r="1" fill="currentColor" stroke="none"/><circle cx="12" cy="16" r="0.5" fill="currentColor" stroke="none"/></svg>',
44476
- togglemore: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="1" fill="currentColor"/><circle cx="5" cy="12" r="1" fill="currentColor"/><circle cx="19" cy="12" r="1" fill="currentColor"/></svg>'
44934
+ togglemore: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="1" fill="currentColor"/><circle cx="5" cy="12" r="1" fill="currentColor"/><circle cx="19" cy="12" r="1" fill="currentColor"/></svg>',
44935
+ subscript: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 5l8 10M12 5L4 15"/><path d="M20 19h-4c0-1.5.44-2 1.5-2.5S20 15.33 20 14c0-.47-.17-.93-.48-1.29a2 2 0 0 0-2.62-.44c-.42.24-.74.62-.9 1.07"/></svg>',
44936
+ superscript: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 9l8 10M12 9l-8 10"/><path d="M20 8h-4c0-1.5.44-2 1.5-2.5S20 4.33 20 3c0-.47-.17-.93-.48-1.29a2 2 0 0 0-2.62-.44c-.42.24-.74.62-.9 1.07"/></svg>',
44937
+ hr: SVG_HR,
44938
+ table: SVG_TABLE,
44939
+ anchor: SVG_ANCHOR,
44940
+ unlink: SVG_UNLINK,
44941
+ blocks: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M13 4v16"/><path d="M17 4v16"/><path d="M19 4H9.5a4.5 4.5 0 0 0 0 9H13"/></svg>',
44942
+ styles: '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3l4 7h-8z"/><path d="M8 10h8l-4 11z"/></svg>'
44477
44943
  };
44478
44944
  const FontSize = Extension.create({
44479
44945
  name: "fontSize",
@@ -44618,7 +45084,10 @@ const SignatureBlock = Node3.create({
44618
45084
  parseHTML() {
44619
45085
  return [
44620
45086
  {
44621
- tag: 'div[id="signature"]'
45087
+ // Higher priority than the generic div->paragraph rule used when
45088
+ // forced_root_block is 'div', so the signature wrapper still matches.
45089
+ tag: 'div[id="signature"]',
45090
+ priority: 100
44622
45091
  }
44623
45092
  ];
44624
45093
  },
@@ -44674,6 +45143,80 @@ const Mention = Node3.create({
44674
45143
  ];
44675
45144
  }
44676
45145
  });
45146
+ const Anchor = Node3.create({
45147
+ name: "anchor",
45148
+ inline: true,
45149
+ group: "inline",
45150
+ atom: true,
45151
+ selectable: true,
45152
+ addOptions() {
45153
+ return {
45154
+ HTMLAttributes: { class: "md-anchor" }
45155
+ };
45156
+ },
45157
+ addAttributes() {
45158
+ return {
45159
+ id: {
45160
+ default: null,
45161
+ parseHTML: (element) => element.getAttribute("id"),
45162
+ renderHTML: (attributes) => attributes.id ? { id: attributes.id } : {}
45163
+ },
45164
+ name: {
45165
+ default: null,
45166
+ parseHTML: (element) => element.getAttribute("name"),
45167
+ renderHTML: (attributes) => attributes.name ? { name: attributes.name } : {}
45168
+ }
45169
+ };
45170
+ },
45171
+ parseHTML() {
45172
+ return [{ tag: "a[id]:not([href])", priority: 60 }];
45173
+ },
45174
+ renderHTML({ HTMLAttributes }) {
45175
+ return ["a", mergeAttributes(this.options.HTMLAttributes, HTMLAttributes)];
45176
+ },
45177
+ addCommands() {
45178
+ return {
45179
+ setAnchor: (name) => ({ commands }) => commands.insertContent({ type: this.name, attrs: { id: name, name } })
45180
+ };
45181
+ }
45182
+ });
45183
+ const InlineStyle = Extension.create({
45184
+ name: "inlineStyle",
45185
+ addOptions() {
45186
+ return {
45187
+ types: ["textStyle"]
45188
+ };
45189
+ },
45190
+ addGlobalAttributes() {
45191
+ return [
45192
+ {
45193
+ types: this.options.types,
45194
+ attributes: {
45195
+ styleClass: {
45196
+ default: null,
45197
+ parseHTML: (element) => element.getAttribute("class") || null,
45198
+ renderHTML: (attributes) => {
45199
+ if (!attributes.styleClass) {
45200
+ return {};
45201
+ }
45202
+ return { class: attributes.styleClass };
45203
+ }
45204
+ }
45205
+ }
45206
+ }
45207
+ ];
45208
+ },
45209
+ addCommands() {
45210
+ return {
45211
+ setInlineClass: (className) => ({ chain }) => {
45212
+ return chain().setMark("textStyle", { styleClass: className }).run();
45213
+ },
45214
+ unsetInlineClass: () => ({ chain }) => {
45215
+ return chain().setMark("textStyle", { styleClass: null }).removeEmptyTextStyle().run();
45216
+ }
45217
+ };
45218
+ }
45219
+ });
44677
45220
  const WORD_MARKERS = [
44678
45221
  'xmlns:o="urn:schemas-microsoft-com:office:office"',
44679
45222
  'xmlns:w="urn:schemas-microsoft-com:office:word"',
@@ -45135,7 +45678,37 @@ const en = {
45135
45678
  "No speech detected": "No speech detected",
45136
45679
  "Microphone access denied": "Microphone access denied",
45137
45680
  "No microphone found": "No microphone found",
45138
- "Network error - speech recognition requires internet": "Network error - speech recognition requires internet"
45681
+ "Network error - speech recognition requires internet": "Network error - speech recognition requires internet",
45682
+ "Subscript": "Subscript",
45683
+ "Superscript": "Superscript",
45684
+ "Horizontal rule": "Horizontal rule",
45685
+ "Unlink": "Unlink",
45686
+ "Format": "Format",
45687
+ "Paragraph": "Paragraph",
45688
+ "Heading 1": "Heading 1",
45689
+ "Heading 2": "Heading 2",
45690
+ "Heading 3": "Heading 3",
45691
+ "Heading 4": "Heading 4",
45692
+ "Heading 5": "Heading 5",
45693
+ "Heading 6": "Heading 6",
45694
+ "Styles": "Styles",
45695
+ "Insert anchor": "Insert anchor",
45696
+ "Anchor": "Anchor",
45697
+ "Anchor name": "Anchor name",
45698
+ "Anchor name is required": "Anchor name is required",
45699
+ "Anchor name cannot contain spaces": "Anchor name cannot contain spaces",
45700
+ "Table": "Table",
45701
+ "Insert table": "Insert table",
45702
+ "Insert row before": "Insert row before",
45703
+ "Insert row after": "Insert row after",
45704
+ "Delete row": "Delete row",
45705
+ "Insert column before": "Insert column before",
45706
+ "Insert column after": "Insert column after",
45707
+ "Delete column": "Delete column",
45708
+ "Merge cells": "Merge cells",
45709
+ "Split cell": "Split cell",
45710
+ "Toggle header row": "Toggle header row",
45711
+ "Delete table": "Delete table"
45139
45712
  };
45140
45713
  const ar = {
45141
45714
  "Bold": "غامق",
@@ -45220,7 +45793,37 @@ const ar = {
45220
45793
  "No speech detected": "?? ??? ?????? ????",
45221
45794
  "Microphone access denied": "?? ??? ?????? ??? ??????????",
45222
45795
  "No microphone found": "No microphone found",
45223
- "Network error - speech recognition requires internet": "Network error - speech recognition requires internet"
45796
+ "Network error - speech recognition requires internet": "Network error - speech recognition requires internet",
45797
+ "Subscript": "منخفض",
45798
+ "Superscript": "مرتفع",
45799
+ "Horizontal rule": "خط أفقي",
45800
+ "Unlink": "إزالة الرابط",
45801
+ "Format": "تنسيق",
45802
+ "Paragraph": "فقرة",
45803
+ "Heading 1": "عنوان 1",
45804
+ "Heading 2": "عنوان 2",
45805
+ "Heading 3": "عنوان 3",
45806
+ "Heading 4": "عنوان 4",
45807
+ "Heading 5": "عنوان 5",
45808
+ "Heading 6": "عنوان 6",
45809
+ "Styles": "أنماط",
45810
+ "Insert anchor": "إدراج مرساة",
45811
+ "Anchor": "مرساة",
45812
+ "Anchor name": "اسم المرساة",
45813
+ "Anchor name is required": "اسم المرساة مطلوب",
45814
+ "Anchor name cannot contain spaces": "لا يمكن أن يحتوي اسم المرساة على مسافات",
45815
+ "Table": "جدول",
45816
+ "Insert table": "إدراج جدول",
45817
+ "Insert row before": "إدراج صف قبل",
45818
+ "Insert row after": "إدراج صف بعد",
45819
+ "Delete row": "حذف الصف",
45820
+ "Insert column before": "إدراج عمود قبل",
45821
+ "Insert column after": "إدراج عمود بعد",
45822
+ "Delete column": "حذف العمود",
45823
+ "Merge cells": "دمج الخلايا",
45824
+ "Split cell": "تقسيم الخلية",
45825
+ "Toggle header row": "تبديل صف الرأس",
45826
+ "Delete table": "حذف الجدول"
45224
45827
  };
45225
45828
  const ca = {
45226
45829
  "Bold": "Negreta",
@@ -45305,7 +45908,37 @@ const ca = {
45305
45908
  "No speech detected": "No s'ha detectat veu",
45306
45909
  "Microphone access denied": "Acc�s al micr�fon denegat",
45307
45910
  "No microphone found": "No microphone found",
45308
- "Network error - speech recognition requires internet": "Network error - speech recognition requires internet"
45911
+ "Network error - speech recognition requires internet": "Network error - speech recognition requires internet",
45912
+ "Subscript": "Subíndex",
45913
+ "Superscript": "Superíndex",
45914
+ "Horizontal rule": "Línia horitzontal",
45915
+ "Unlink": "Treure enllaç",
45916
+ "Format": "Format",
45917
+ "Paragraph": "Paràgraf",
45918
+ "Heading 1": "Encapçalament 1",
45919
+ "Heading 2": "Encapçalament 2",
45920
+ "Heading 3": "Encapçalament 3",
45921
+ "Heading 4": "Encapçalament 4",
45922
+ "Heading 5": "Encapçalament 5",
45923
+ "Heading 6": "Encapçalament 6",
45924
+ "Styles": "Estils",
45925
+ "Insert anchor": "Inserir àncora",
45926
+ "Anchor": "Àncora",
45927
+ "Anchor name": "Nom de l'àncora",
45928
+ "Anchor name is required": "El nom de l'àncora és obligatori",
45929
+ "Anchor name cannot contain spaces": "El nom de l'àncora no pot contenir espais",
45930
+ "Table": "Taula",
45931
+ "Insert table": "Inserir taula",
45932
+ "Insert row before": "Inserir fila a sobre",
45933
+ "Insert row after": "Inserir fila a sota",
45934
+ "Delete row": "Eliminar fila",
45935
+ "Insert column before": "Inserir columna abans",
45936
+ "Insert column after": "Inserir columna després",
45937
+ "Delete column": "Eliminar columna",
45938
+ "Merge cells": "Combinar cel·les",
45939
+ "Split cell": "Dividir cel·la",
45940
+ "Toggle header row": "Alternar fila de capçalera",
45941
+ "Delete table": "Eliminar taula"
45309
45942
  };
45310
45943
  const zh = {
45311
45944
  "Bold": "粗体",
@@ -45390,7 +46023,37 @@ const zh = {
45390
46023
  "No speech detected": "??????",
45391
46024
  "Microphone access denied": "????????",
45392
46025
  "No microphone found": "No microphone found",
45393
- "Network error - speech recognition requires internet": "Network error - speech recognition requires internet"
46026
+ "Network error - speech recognition requires internet": "Network error - speech recognition requires internet",
46027
+ "Subscript": "下标",
46028
+ "Superscript": "上标",
46029
+ "Horizontal rule": "水平线",
46030
+ "Unlink": "取消链接",
46031
+ "Format": "格式",
46032
+ "Paragraph": "段落",
46033
+ "Heading 1": "标题 1",
46034
+ "Heading 2": "标题 2",
46035
+ "Heading 3": "标题 3",
46036
+ "Heading 4": "标题 4",
46037
+ "Heading 5": "标题 5",
46038
+ "Heading 6": "标题 6",
46039
+ "Styles": "样式",
46040
+ "Insert anchor": "插入锚点",
46041
+ "Anchor": "锚点",
46042
+ "Anchor name": "锚点名称",
46043
+ "Anchor name is required": "锚点名称为必填项",
46044
+ "Anchor name cannot contain spaces": "锚点名称不能包含空格",
46045
+ "Table": "表格",
46046
+ "Insert table": "插入表格",
46047
+ "Insert row before": "在上方插入行",
46048
+ "Insert row after": "在下方插入行",
46049
+ "Delete row": "删除行",
46050
+ "Insert column before": "在左侧插入列",
46051
+ "Insert column after": "在右侧插入列",
46052
+ "Delete column": "删除列",
46053
+ "Merge cells": "合并单元格",
46054
+ "Split cell": "拆分单元格",
46055
+ "Toggle header row": "切换标题行",
46056
+ "Delete table": "删除表格"
45394
46057
  };
45395
46058
  const cs = {
45396
46059
  "Bold": "Tučné",
@@ -45475,7 +46138,37 @@ const cs = {
45475
46138
  "No speech detected": "Nebyla detekov�na rec",
45476
46139
  "Microphone access denied": "Pr�stup k mikrofonu zam�tnut",
45477
46140
  "No microphone found": "No microphone found",
45478
- "Network error - speech recognition requires internet": "Network error - speech recognition requires internet"
46141
+ "Network error - speech recognition requires internet": "Network error - speech recognition requires internet",
46142
+ "Subscript": "Dolní index",
46143
+ "Superscript": "Horní index",
46144
+ "Horizontal rule": "Vodorovná čára",
46145
+ "Unlink": "Odebrat odkaz",
46146
+ "Format": "Formát",
46147
+ "Paragraph": "Odstavec",
46148
+ "Heading 1": "Nadpis 1",
46149
+ "Heading 2": "Nadpis 2",
46150
+ "Heading 3": "Nadpis 3",
46151
+ "Heading 4": "Nadpis 4",
46152
+ "Heading 5": "Nadpis 5",
46153
+ "Heading 6": "Nadpis 6",
46154
+ "Styles": "Styly",
46155
+ "Insert anchor": "Vložit kotvu",
46156
+ "Anchor": "Kotva",
46157
+ "Anchor name": "Název kotvy",
46158
+ "Anchor name is required": "Název kotvy je povinný",
46159
+ "Anchor name cannot contain spaces": "Název kotvy nesmí obsahovat mezery",
46160
+ "Table": "Tabulka",
46161
+ "Insert table": "Vložit tabulku",
46162
+ "Insert row before": "Vložit řádek před",
46163
+ "Insert row after": "Vložit řádek za",
46164
+ "Delete row": "Odstranit řádek",
46165
+ "Insert column before": "Vložit sloupec před",
46166
+ "Insert column after": "Vložit sloupec za",
46167
+ "Delete column": "Odstranit sloupec",
46168
+ "Merge cells": "Sloučit buňky",
46169
+ "Split cell": "Rozdělit buňku",
46170
+ "Toggle header row": "Přepnout řádek záhlaví",
46171
+ "Delete table": "Odstranit tabulku"
45479
46172
  };
45480
46173
  const da = {
45481
46174
  "Bold": "Fed",
@@ -45560,7 +46253,37 @@ const da = {
45560
46253
  "No speech detected": "Ingen tale registreret",
45561
46254
  "Microphone access denied": "Mikrofonadgang n�gtet",
45562
46255
  "No microphone found": "No microphone found",
45563
- "Network error - speech recognition requires internet": "Network error - speech recognition requires internet"
46256
+ "Network error - speech recognition requires internet": "Network error - speech recognition requires internet",
46257
+ "Subscript": "Sænket skrift",
46258
+ "Superscript": "Hævet skrift",
46259
+ "Horizontal rule": "Vandret streg",
46260
+ "Unlink": "Fjern link",
46261
+ "Format": "Format",
46262
+ "Paragraph": "Afsnit",
46263
+ "Heading 1": "Overskrift 1",
46264
+ "Heading 2": "Overskrift 2",
46265
+ "Heading 3": "Overskrift 3",
46266
+ "Heading 4": "Overskrift 4",
46267
+ "Heading 5": "Overskrift 5",
46268
+ "Heading 6": "Overskrift 6",
46269
+ "Styles": "Typografier",
46270
+ "Insert anchor": "Indsæt anker",
46271
+ "Anchor": "Anker",
46272
+ "Anchor name": "Ankernavn",
46273
+ "Anchor name is required": "Ankernavn er påkrævet",
46274
+ "Anchor name cannot contain spaces": "Ankernavn må ikke indeholde mellemrum",
46275
+ "Table": "Tabel",
46276
+ "Insert table": "Indsæt tabel",
46277
+ "Insert row before": "Indsæt række før",
46278
+ "Insert row after": "Indsæt række efter",
46279
+ "Delete row": "Slet række",
46280
+ "Insert column before": "Indsæt kolonne før",
46281
+ "Insert column after": "Indsæt kolonne efter",
46282
+ "Delete column": "Slet kolonne",
46283
+ "Merge cells": "Flet celler",
46284
+ "Split cell": "Opdel celle",
46285
+ "Toggle header row": "Skift overskriftsrække",
46286
+ "Delete table": "Slet tabel"
45564
46287
  };
45565
46288
  const enGb = {
45566
46289
  "Bold": "Bold",
@@ -45645,7 +46368,37 @@ const enGb = {
45645
46368
  "No speech detected": "No speech detected",
45646
46369
  "Microphone access denied": "Microphone access denied",
45647
46370
  "No microphone found": "No microphone found",
45648
- "Network error - speech recognition requires internet": "Network error - speech recognition requires internet"
46371
+ "Network error - speech recognition requires internet": "Network error - speech recognition requires internet",
46372
+ "Subscript": "Subscript",
46373
+ "Superscript": "Superscript",
46374
+ "Horizontal rule": "Horizontal rule",
46375
+ "Unlink": "Unlink",
46376
+ "Format": "Format",
46377
+ "Paragraph": "Paragraph",
46378
+ "Heading 1": "Heading 1",
46379
+ "Heading 2": "Heading 2",
46380
+ "Heading 3": "Heading 3",
46381
+ "Heading 4": "Heading 4",
46382
+ "Heading 5": "Heading 5",
46383
+ "Heading 6": "Heading 6",
46384
+ "Styles": "Styles",
46385
+ "Insert anchor": "Insert anchor",
46386
+ "Anchor": "Anchor",
46387
+ "Anchor name": "Anchor name",
46388
+ "Anchor name is required": "Anchor name is required",
46389
+ "Anchor name cannot contain spaces": "Anchor name cannot contain spaces",
46390
+ "Table": "Table",
46391
+ "Insert table": "Insert table",
46392
+ "Insert row before": "Insert row before",
46393
+ "Insert row after": "Insert row after",
46394
+ "Delete row": "Delete row",
46395
+ "Insert column before": "Insert column before",
46396
+ "Insert column after": "Insert column after",
46397
+ "Delete column": "Delete column",
46398
+ "Merge cells": "Merge cells",
46399
+ "Split cell": "Split cell",
46400
+ "Toggle header row": "Toggle header row",
46401
+ "Delete table": "Delete table"
45649
46402
  };
45650
46403
  const fi = {
45651
46404
  "Bold": "Lihavoitu",
@@ -45730,7 +46483,37 @@ const fi = {
45730
46483
  "No speech detected": "Puhetta ei havaittu",
45731
46484
  "Microphone access denied": "Mikrofonin k�ytt� estetty",
45732
46485
  "No microphone found": "No microphone found",
45733
- "Network error - speech recognition requires internet": "Network error - speech recognition requires internet"
46486
+ "Network error - speech recognition requires internet": "Network error - speech recognition requires internet",
46487
+ "Subscript": "Alaindeksi",
46488
+ "Superscript": "Yläindeksi",
46489
+ "Horizontal rule": "Vaakaviiva",
46490
+ "Unlink": "Poista linkki",
46491
+ "Format": "Muotoilu",
46492
+ "Paragraph": "Kappale",
46493
+ "Heading 1": "Otsikko 1",
46494
+ "Heading 2": "Otsikko 2",
46495
+ "Heading 3": "Otsikko 3",
46496
+ "Heading 4": "Otsikko 4",
46497
+ "Heading 5": "Otsikko 5",
46498
+ "Heading 6": "Otsikko 6",
46499
+ "Styles": "Tyylit",
46500
+ "Insert anchor": "Lisää ankkuri",
46501
+ "Anchor": "Ankkuri",
46502
+ "Anchor name": "Ankkurin nimi",
46503
+ "Anchor name is required": "Ankkurin nimi vaaditaan",
46504
+ "Anchor name cannot contain spaces": "Ankkurin nimi ei voi sisältää välilyöntejä",
46505
+ "Table": "Taulukko",
46506
+ "Insert table": "Lisää taulukko",
46507
+ "Insert row before": "Lisää rivi ennen",
46508
+ "Insert row after": "Lisää rivi jälkeen",
46509
+ "Delete row": "Poista rivi",
46510
+ "Insert column before": "Lisää sarake ennen",
46511
+ "Insert column after": "Lisää sarake jälkeen",
46512
+ "Delete column": "Poista sarake",
46513
+ "Merge cells": "Yhdistä solut",
46514
+ "Split cell": "Jaa solu",
46515
+ "Toggle header row": "Vaihda otsikkorivi",
46516
+ "Delete table": "Poista taulukko"
45734
46517
  };
45735
46518
  const fr = {
45736
46519
  "Bold": "Gras",
@@ -45815,7 +46598,37 @@ const fr = {
45815
46598
  "No speech detected": "Aucune parole d�tect�e",
45816
46599
  "Microphone access denied": "Acc�s au microphone refus�",
45817
46600
  "No microphone found": "No microphone found",
45818
- "Network error - speech recognition requires internet": "Network error - speech recognition requires internet"
46601
+ "Network error - speech recognition requires internet": "Network error - speech recognition requires internet",
46602
+ "Subscript": "Indice",
46603
+ "Superscript": "Exposant",
46604
+ "Horizontal rule": "Ligne horizontale",
46605
+ "Unlink": "Supprimer le lien",
46606
+ "Format": "Format",
46607
+ "Paragraph": "Paragraphe",
46608
+ "Heading 1": "Titre 1",
46609
+ "Heading 2": "Titre 2",
46610
+ "Heading 3": "Titre 3",
46611
+ "Heading 4": "Titre 4",
46612
+ "Heading 5": "Titre 5",
46613
+ "Heading 6": "Titre 6",
46614
+ "Styles": "Styles",
46615
+ "Insert anchor": "Insérer une ancre",
46616
+ "Anchor": "Ancre",
46617
+ "Anchor name": "Nom de l'ancre",
46618
+ "Anchor name is required": "Le nom de l'ancre est requis",
46619
+ "Anchor name cannot contain spaces": "Le nom de l'ancre ne peut pas contenir d'espaces",
46620
+ "Table": "Tableau",
46621
+ "Insert table": "Insérer un tableau",
46622
+ "Insert row before": "Insérer une ligne avant",
46623
+ "Insert row after": "Insérer une ligne après",
46624
+ "Delete row": "Supprimer la ligne",
46625
+ "Insert column before": "Insérer une colonne avant",
46626
+ "Insert column after": "Insérer une colonne après",
46627
+ "Delete column": "Supprimer la colonne",
46628
+ "Merge cells": "Fusionner les cellules",
46629
+ "Split cell": "Diviser la cellule",
46630
+ "Toggle header row": "Basculer la ligne d'en-tête",
46631
+ "Delete table": "Supprimer le tableau"
45819
46632
  };
45820
46633
  const frCa = {
45821
46634
  "Bold": "Gras",
@@ -45900,7 +46713,37 @@ const frCa = {
45900
46713
  "No speech detected": "Aucune parole d�tect�e",
45901
46714
  "Microphone access denied": "Acc�s au microphone refus�",
45902
46715
  "No microphone found": "No microphone found",
45903
- "Network error - speech recognition requires internet": "Network error - speech recognition requires internet"
46716
+ "Network error - speech recognition requires internet": "Network error - speech recognition requires internet",
46717
+ "Subscript": "Indice",
46718
+ "Superscript": "Exposant",
46719
+ "Horizontal rule": "Ligne horizontale",
46720
+ "Unlink": "Supprimer le lien",
46721
+ "Format": "Format",
46722
+ "Paragraph": "Paragraphe",
46723
+ "Heading 1": "Titre 1",
46724
+ "Heading 2": "Titre 2",
46725
+ "Heading 3": "Titre 3",
46726
+ "Heading 4": "Titre 4",
46727
+ "Heading 5": "Titre 5",
46728
+ "Heading 6": "Titre 6",
46729
+ "Styles": "Styles",
46730
+ "Insert anchor": "Insérer une ancre",
46731
+ "Anchor": "Ancre",
46732
+ "Anchor name": "Nom de l'ancre",
46733
+ "Anchor name is required": "Le nom de l'ancre est requis",
46734
+ "Anchor name cannot contain spaces": "Le nom de l'ancre ne peut pas contenir d'espaces",
46735
+ "Table": "Tableau",
46736
+ "Insert table": "Insérer un tableau",
46737
+ "Insert row before": "Insérer une ligne avant",
46738
+ "Insert row after": "Insérer une ligne après",
46739
+ "Delete row": "Supprimer la ligne",
46740
+ "Insert column before": "Insérer une colonne avant",
46741
+ "Insert column after": "Insérer une colonne après",
46742
+ "Delete column": "Supprimer la colonne",
46743
+ "Merge cells": "Fusionner les cellules",
46744
+ "Split cell": "Diviser la cellule",
46745
+ "Toggle header row": "Basculer la ligne d'en-tête",
46746
+ "Delete table": "Supprimer le tableau"
45904
46747
  };
45905
46748
  const de = {
45906
46749
  "Bold": "Fett",
@@ -45985,7 +46828,37 @@ const de = {
45985
46828
  "No speech detected": "Keine Sprache erkannt",
45986
46829
  "Microphone access denied": "Mikrofonzugriff verweigert",
45987
46830
  "No microphone found": "No microphone found",
45988
- "Network error - speech recognition requires internet": "Network error - speech recognition requires internet"
46831
+ "Network error - speech recognition requires internet": "Network error - speech recognition requires internet",
46832
+ "Subscript": "Tiefgestellt",
46833
+ "Superscript": "Hochgestellt",
46834
+ "Horizontal rule": "Horizontale Linie",
46835
+ "Unlink": "Link entfernen",
46836
+ "Format": "Format",
46837
+ "Paragraph": "Absatz",
46838
+ "Heading 1": "Überschrift 1",
46839
+ "Heading 2": "Überschrift 2",
46840
+ "Heading 3": "Überschrift 3",
46841
+ "Heading 4": "Überschrift 4",
46842
+ "Heading 5": "Überschrift 5",
46843
+ "Heading 6": "Überschrift 6",
46844
+ "Styles": "Formatvorlagen",
46845
+ "Insert anchor": "Anker einfügen",
46846
+ "Anchor": "Anker",
46847
+ "Anchor name": "Ankername",
46848
+ "Anchor name is required": "Ankername ist erforderlich",
46849
+ "Anchor name cannot contain spaces": "Ankername darf keine Leerzeichen enthalten",
46850
+ "Table": "Tabelle",
46851
+ "Insert table": "Tabelle einfügen",
46852
+ "Insert row before": "Zeile davor einfügen",
46853
+ "Insert row after": "Zeile danach einfügen",
46854
+ "Delete row": "Zeile löschen",
46855
+ "Insert column before": "Spalte davor einfügen",
46856
+ "Insert column after": "Spalte danach einfügen",
46857
+ "Delete column": "Spalte löschen",
46858
+ "Merge cells": "Zellen verbinden",
46859
+ "Split cell": "Zelle teilen",
46860
+ "Toggle header row": "Kopfzeile umschalten",
46861
+ "Delete table": "Tabelle löschen"
45989
46862
  };
45990
46863
  const el = {
45991
46864
  "Bold": "Έντονα",
@@ -46070,7 +46943,37 @@ const el = {
46070
46943
  "No speech detected": "?e? a????e????e ?�???a",
46071
46944
  "Microphone access denied": "? p??s�as? st? �????f??? ap????f???e",
46072
46945
  "No microphone found": "No microphone found",
46073
- "Network error - speech recognition requires internet": "Network error - speech recognition requires internet"
46946
+ "Network error - speech recognition requires internet": "Network error - speech recognition requires internet",
46947
+ "Subscript": "Δείκτης",
46948
+ "Superscript": "Εκθέτης",
46949
+ "Horizontal rule": "Οριζόντια γραμμή",
46950
+ "Unlink": "Κατάργηση συνδέσμου",
46951
+ "Format": "Μορφή",
46952
+ "Paragraph": "Παράγραφος",
46953
+ "Heading 1": "Επικεφαλίδα 1",
46954
+ "Heading 2": "Επικεφαλίδα 2",
46955
+ "Heading 3": "Επικεφαλίδα 3",
46956
+ "Heading 4": "Επικεφαλίδα 4",
46957
+ "Heading 5": "Επικεφαλίδα 5",
46958
+ "Heading 6": "Επικεφαλίδα 6",
46959
+ "Styles": "Στυλ",
46960
+ "Insert anchor": "Εισαγωγή αγκύρωσης",
46961
+ "Anchor": "Αγκύρωση",
46962
+ "Anchor name": "Όνομα αγκύρωσης",
46963
+ "Anchor name is required": "Απαιτείται όνομα αγκύρωσης",
46964
+ "Anchor name cannot contain spaces": "Το όνομα αγκύρωσης δεν μπορεί να περιέχει κενά",
46965
+ "Table": "Πίνακας",
46966
+ "Insert table": "Εισαγωγή πίνακα",
46967
+ "Insert row before": "Εισαγωγή γραμμής πριν",
46968
+ "Insert row after": "Εισαγωγή γραμμής μετά",
46969
+ "Delete row": "Διαγραφή γραμμής",
46970
+ "Insert column before": "Εισαγωγή στήλης πριν",
46971
+ "Insert column after": "Εισαγωγή στήλης μετά",
46972
+ "Delete column": "Διαγραφή στήλης",
46973
+ "Merge cells": "Συγχώνευση κελιών",
46974
+ "Split cell": "Διαίρεση κελιού",
46975
+ "Toggle header row": "Εναλλαγή γραμμής κεφαλίδας",
46976
+ "Delete table": "Διαγραφή πίνακα"
46074
46977
  };
46075
46978
  const hu = {
46076
46979
  "Bold": "Félkövér",
@@ -46155,7 +47058,37 @@ const hu = {
46155
47058
  "No speech detected": "Nem �szlelheto besz�d",
46156
47059
  "Microphone access denied": "Mikrofon hozz�f�r�s megtagadva",
46157
47060
  "No microphone found": "No microphone found",
46158
- "Network error - speech recognition requires internet": "Network error - speech recognition requires internet"
47061
+ "Network error - speech recognition requires internet": "Network error - speech recognition requires internet",
47062
+ "Subscript": "Alsó index",
47063
+ "Superscript": "Felső index",
47064
+ "Horizontal rule": "Vízszintes vonal",
47065
+ "Unlink": "Hivatkozás eltávolítása",
47066
+ "Format": "Formátum",
47067
+ "Paragraph": "Bekezdés",
47068
+ "Heading 1": "Címsor 1",
47069
+ "Heading 2": "Címsor 2",
47070
+ "Heading 3": "Címsor 3",
47071
+ "Heading 4": "Címsor 4",
47072
+ "Heading 5": "Címsor 5",
47073
+ "Heading 6": "Címsor 6",
47074
+ "Styles": "Stílusok",
47075
+ "Insert anchor": "Horgony beszúrása",
47076
+ "Anchor": "Horgony",
47077
+ "Anchor name": "Horgony neve",
47078
+ "Anchor name is required": "A horgony neve kötelező",
47079
+ "Anchor name cannot contain spaces": "A horgony neve nem tartalmazhat szóközöket",
47080
+ "Table": "Táblázat",
47081
+ "Insert table": "Táblázat beszúrása",
47082
+ "Insert row before": "Sor beszúrása elé",
47083
+ "Insert row after": "Sor beszúrása mögé",
47084
+ "Delete row": "Sor törlése",
47085
+ "Insert column before": "Oszlop beszúrása elé",
47086
+ "Insert column after": "Oszlop beszúrása mögé",
47087
+ "Delete column": "Oszlop törlése",
47088
+ "Merge cells": "Cellák egyesítése",
47089
+ "Split cell": "Cella felosztása",
47090
+ "Toggle header row": "Fejlécsor be-/kikapcsolása",
47091
+ "Delete table": "Táblázat törlése"
46159
47092
  };
46160
47093
  const id = {
46161
47094
  "Bold": "Tebal",
@@ -46240,7 +47173,37 @@ const id = {
46240
47173
  "No speech detected": "Tidak ada ucapan terdeteksi",
46241
47174
  "Microphone access denied": "Akses mikrofon ditolak",
46242
47175
  "No microphone found": "No microphone found",
46243
- "Network error - speech recognition requires internet": "Network error - speech recognition requires internet"
47176
+ "Network error - speech recognition requires internet": "Network error - speech recognition requires internet",
47177
+ "Subscript": "Subskrip",
47178
+ "Superscript": "Superskrip",
47179
+ "Horizontal rule": "Garis horizontal",
47180
+ "Unlink": "Hapus tautan",
47181
+ "Format": "Format",
47182
+ "Paragraph": "Paragraf",
47183
+ "Heading 1": "Judul 1",
47184
+ "Heading 2": "Judul 2",
47185
+ "Heading 3": "Judul 3",
47186
+ "Heading 4": "Judul 4",
47187
+ "Heading 5": "Judul 5",
47188
+ "Heading 6": "Judul 6",
47189
+ "Styles": "Gaya",
47190
+ "Insert anchor": "Sisipkan jangkar",
47191
+ "Anchor": "Jangkar",
47192
+ "Anchor name": "Nama jangkar",
47193
+ "Anchor name is required": "Nama jangkar wajib diisi",
47194
+ "Anchor name cannot contain spaces": "Nama jangkar tidak boleh mengandung spasi",
47195
+ "Table": "Tabel",
47196
+ "Insert table": "Sisipkan tabel",
47197
+ "Insert row before": "Sisipkan baris sebelum",
47198
+ "Insert row after": "Sisipkan baris sesudah",
47199
+ "Delete row": "Hapus baris",
47200
+ "Insert column before": "Sisipkan kolom sebelum",
47201
+ "Insert column after": "Sisipkan kolom sesudah",
47202
+ "Delete column": "Hapus kolom",
47203
+ "Merge cells": "Gabungkan sel",
47204
+ "Split cell": "Pisahkan sel",
47205
+ "Toggle header row": "Alihkan baris header",
47206
+ "Delete table": "Hapus tabel"
46244
47207
  };
46245
47208
  const it = {
46246
47209
  "Bold": "Grassetto",
@@ -46325,7 +47288,37 @@ const it = {
46325
47288
  "No speech detected": "Nessun discorso rilevato",
46326
47289
  "Microphone access denied": "Accesso al microfono negato",
46327
47290
  "No microphone found": "No microphone found",
46328
- "Network error - speech recognition requires internet": "Network error - speech recognition requires internet"
47291
+ "Network error - speech recognition requires internet": "Network error - speech recognition requires internet",
47292
+ "Subscript": "Pedice",
47293
+ "Superscript": "Apice",
47294
+ "Horizontal rule": "Linea orizzontale",
47295
+ "Unlink": "Rimuovi collegamento",
47296
+ "Format": "Formato",
47297
+ "Paragraph": "Paragrafo",
47298
+ "Heading 1": "Titolo 1",
47299
+ "Heading 2": "Titolo 2",
47300
+ "Heading 3": "Titolo 3",
47301
+ "Heading 4": "Titolo 4",
47302
+ "Heading 5": "Titolo 5",
47303
+ "Heading 6": "Titolo 6",
47304
+ "Styles": "Stili",
47305
+ "Insert anchor": "Inserisci ancora",
47306
+ "Anchor": "Ancora",
47307
+ "Anchor name": "Nome ancora",
47308
+ "Anchor name is required": "Il nome dell'ancora è obbligatorio",
47309
+ "Anchor name cannot contain spaces": "Il nome dell'ancora non può contenere spazi",
47310
+ "Table": "Tabella",
47311
+ "Insert table": "Inserisci tabella",
47312
+ "Insert row before": "Inserisci riga prima",
47313
+ "Insert row after": "Inserisci riga dopo",
47314
+ "Delete row": "Elimina riga",
47315
+ "Insert column before": "Inserisci colonna prima",
47316
+ "Insert column after": "Inserisci colonna dopo",
47317
+ "Delete column": "Elimina colonna",
47318
+ "Merge cells": "Unisci celle",
47319
+ "Split cell": "Dividi cella",
47320
+ "Toggle header row": "Attiva/disattiva riga di intestazione",
47321
+ "Delete table": "Elimina tabella"
46329
47322
  };
46330
47323
  const ja = {
46331
47324
  "Bold": "太字",
@@ -46410,7 +47403,37 @@ const ja = {
46410
47403
  "No speech detected": "?????????????",
46411
47404
  "Microphone access denied": "?????????????????",
46412
47405
  "No microphone found": "No microphone found",
46413
- "Network error - speech recognition requires internet": "Network error - speech recognition requires internet"
47406
+ "Network error - speech recognition requires internet": "Network error - speech recognition requires internet",
47407
+ "Subscript": "下付き文字",
47408
+ "Superscript": "上付き文字",
47409
+ "Horizontal rule": "水平線",
47410
+ "Unlink": "リンクの解除",
47411
+ "Format": "書式",
47412
+ "Paragraph": "段落",
47413
+ "Heading 1": "見出し 1",
47414
+ "Heading 2": "見出し 2",
47415
+ "Heading 3": "見出し 3",
47416
+ "Heading 4": "見出し 4",
47417
+ "Heading 5": "見出し 5",
47418
+ "Heading 6": "見出し 6",
47419
+ "Styles": "スタイル",
47420
+ "Insert anchor": "アンカーの挿入",
47421
+ "Anchor": "アンカー",
47422
+ "Anchor name": "アンカー名",
47423
+ "Anchor name is required": "アンカー名は必須です",
47424
+ "Anchor name cannot contain spaces": "アンカー名にスペースを含めることはできません",
47425
+ "Table": "テーブル",
47426
+ "Insert table": "テーブルの挿入",
47427
+ "Insert row before": "上に行を挿入",
47428
+ "Insert row after": "下に行を挿入",
47429
+ "Delete row": "行の削除",
47430
+ "Insert column before": "左に列を挿入",
47431
+ "Insert column after": "右に列を挿入",
47432
+ "Delete column": "列の削除",
47433
+ "Merge cells": "セルの結合",
47434
+ "Split cell": "セルの分割",
47435
+ "Toggle header row": "ヘッダー行の切り替え",
47436
+ "Delete table": "テーブルの削除"
46414
47437
  };
46415
47438
  const ko = {
46416
47439
  "Bold": "굵게",
@@ -46495,7 +47518,37 @@ const ko = {
46495
47518
  "No speech detected": "??? ???? ?????",
46496
47519
  "Microphone access denied": "??? ??? ???????",
46497
47520
  "No microphone found": "No microphone found",
46498
- "Network error - speech recognition requires internet": "Network error - speech recognition requires internet"
47521
+ "Network error - speech recognition requires internet": "Network error - speech recognition requires internet",
47522
+ "Subscript": "아래 첨자",
47523
+ "Superscript": "위 첨자",
47524
+ "Horizontal rule": "가로줄",
47525
+ "Unlink": "링크 제거",
47526
+ "Format": "형식",
47527
+ "Paragraph": "단락",
47528
+ "Heading 1": "제목 1",
47529
+ "Heading 2": "제목 2",
47530
+ "Heading 3": "제목 3",
47531
+ "Heading 4": "제목 4",
47532
+ "Heading 5": "제목 5",
47533
+ "Heading 6": "제목 6",
47534
+ "Styles": "스타일",
47535
+ "Insert anchor": "앵커 삽입",
47536
+ "Anchor": "앵커",
47537
+ "Anchor name": "앵커 이름",
47538
+ "Anchor name is required": "앵커 이름은 필수입니다",
47539
+ "Anchor name cannot contain spaces": "앵커 이름에 공백을 포함할 수 없습니다",
47540
+ "Table": "표",
47541
+ "Insert table": "표 삽입",
47542
+ "Insert row before": "위에 행 삽입",
47543
+ "Insert row after": "아래에 행 삽입",
47544
+ "Delete row": "행 삭제",
47545
+ "Insert column before": "왼쪽에 열 삽입",
47546
+ "Insert column after": "오른쪽에 열 삽입",
47547
+ "Delete column": "열 삭제",
47548
+ "Merge cells": "셀 병합",
47549
+ "Split cell": "셀 분할",
47550
+ "Toggle header row": "머리글 행 전환",
47551
+ "Delete table": "표 삭제"
46499
47552
  };
46500
47553
  const nl = {
46501
47554
  "Bold": "Vet",
@@ -46580,7 +47633,37 @@ const nl = {
46580
47633
  "No speech detected": "Geen spraak gedetecteerd",
46581
47634
  "Microphone access denied": "Toegang tot microfoon geweigerd",
46582
47635
  "No microphone found": "No microphone found",
46583
- "Network error - speech recognition requires internet": "Network error - speech recognition requires internet"
47636
+ "Network error - speech recognition requires internet": "Network error - speech recognition requires internet",
47637
+ "Subscript": "Subscript",
47638
+ "Superscript": "Superscript",
47639
+ "Horizontal rule": "Horizontale lijn",
47640
+ "Unlink": "Link verwijderen",
47641
+ "Format": "Opmaak",
47642
+ "Paragraph": "Alinea",
47643
+ "Heading 1": "Kop 1",
47644
+ "Heading 2": "Kop 2",
47645
+ "Heading 3": "Kop 3",
47646
+ "Heading 4": "Kop 4",
47647
+ "Heading 5": "Kop 5",
47648
+ "Heading 6": "Kop 6",
47649
+ "Styles": "Stijlen",
47650
+ "Insert anchor": "Anker invoegen",
47651
+ "Anchor": "Anker",
47652
+ "Anchor name": "Ankernaam",
47653
+ "Anchor name is required": "Ankernaam is verplicht",
47654
+ "Anchor name cannot contain spaces": "Ankernaam mag geen spaties bevatten",
47655
+ "Table": "Tabel",
47656
+ "Insert table": "Tabel invoegen",
47657
+ "Insert row before": "Rij ervoor invoegen",
47658
+ "Insert row after": "Rij erna invoegen",
47659
+ "Delete row": "Rij verwijderen",
47660
+ "Insert column before": "Kolom ervoor invoegen",
47661
+ "Insert column after": "Kolom erna invoegen",
47662
+ "Delete column": "Kolom verwijderen",
47663
+ "Merge cells": "Cellen samenvoegen",
47664
+ "Split cell": "Cel splitsen",
47665
+ "Toggle header row": "Koprij in-/uitschakelen",
47666
+ "Delete table": "Tabel verwijderen"
46584
47667
  };
46585
47668
  const nb = {
46586
47669
  "Bold": "Fet",
@@ -46665,7 +47748,37 @@ const nb = {
46665
47748
  "No speech detected": "Ingen tale oppdaget",
46666
47749
  "Microphone access denied": "Mikrofontilgang nektet",
46667
47750
  "No microphone found": "No microphone found",
46668
- "Network error - speech recognition requires internet": "Network error - speech recognition requires internet"
47751
+ "Network error - speech recognition requires internet": "Network error - speech recognition requires internet",
47752
+ "Subscript": "Senket skrift",
47753
+ "Superscript": "Hevet skrift",
47754
+ "Horizontal rule": "Horisontal linje",
47755
+ "Unlink": "Fjern lenke",
47756
+ "Format": "Format",
47757
+ "Paragraph": "Avsnitt",
47758
+ "Heading 1": "Overskrift 1",
47759
+ "Heading 2": "Overskrift 2",
47760
+ "Heading 3": "Overskrift 3",
47761
+ "Heading 4": "Overskrift 4",
47762
+ "Heading 5": "Overskrift 5",
47763
+ "Heading 6": "Overskrift 6",
47764
+ "Styles": "Stiler",
47765
+ "Insert anchor": "Sett inn anker",
47766
+ "Anchor": "Anker",
47767
+ "Anchor name": "Ankernavn",
47768
+ "Anchor name is required": "Ankernavn er påkrevd",
47769
+ "Anchor name cannot contain spaces": "Ankernavn kan ikke inneholde mellomrom",
47770
+ "Table": "Tabell",
47771
+ "Insert table": "Sett inn tabell",
47772
+ "Insert row before": "Sett inn rad før",
47773
+ "Insert row after": "Sett inn rad etter",
47774
+ "Delete row": "Slett rad",
47775
+ "Insert column before": "Sett inn kolonne før",
47776
+ "Insert column after": "Sett inn kolonne etter",
47777
+ "Delete column": "Slett kolonne",
47778
+ "Merge cells": "Slå sammen celler",
47779
+ "Split cell": "Del celle",
47780
+ "Toggle header row": "Veksle overskriftsrad",
47781
+ "Delete table": "Slett tabell"
46669
47782
  };
46670
47783
  const pl = {
46671
47784
  "Bold": "Pogrubienie",
@@ -46750,7 +47863,37 @@ const pl = {
46750
47863
  "No speech detected": "Nie wykryto mowy",
46751
47864
  "Microphone access denied": "Odmowa dostepu do mikrofonu",
46752
47865
  "No microphone found": "No microphone found",
46753
- "Network error - speech recognition requires internet": "Network error - speech recognition requires internet"
47866
+ "Network error - speech recognition requires internet": "Network error - speech recognition requires internet",
47867
+ "Subscript": "Indeks dolny",
47868
+ "Superscript": "Indeks górny",
47869
+ "Horizontal rule": "Linia pozioma",
47870
+ "Unlink": "Usuń odnośnik",
47871
+ "Format": "Format",
47872
+ "Paragraph": "Akapit",
47873
+ "Heading 1": "Nagłówek 1",
47874
+ "Heading 2": "Nagłówek 2",
47875
+ "Heading 3": "Nagłówek 3",
47876
+ "Heading 4": "Nagłówek 4",
47877
+ "Heading 5": "Nagłówek 5",
47878
+ "Heading 6": "Nagłówek 6",
47879
+ "Styles": "Style",
47880
+ "Insert anchor": "Wstaw kotwicę",
47881
+ "Anchor": "Kotwica",
47882
+ "Anchor name": "Nazwa kotwicy",
47883
+ "Anchor name is required": "Nazwa kotwicy jest wymagana",
47884
+ "Anchor name cannot contain spaces": "Nazwa kotwicy nie może zawierać spacji",
47885
+ "Table": "Tabela",
47886
+ "Insert table": "Wstaw tabelę",
47887
+ "Insert row before": "Wstaw wiersz przed",
47888
+ "Insert row after": "Wstaw wiersz po",
47889
+ "Delete row": "Usuń wiersz",
47890
+ "Insert column before": "Wstaw kolumnę przed",
47891
+ "Insert column after": "Wstaw kolumnę po",
47892
+ "Delete column": "Usuń kolumnę",
47893
+ "Merge cells": "Scal komórki",
47894
+ "Split cell": "Podziel komórkę",
47895
+ "Toggle header row": "Przełącz wiersz nagłówka",
47896
+ "Delete table": "Usuń tabelę"
46754
47897
  };
46755
47898
  const pt = {
46756
47899
  "Bold": "Negrito",
@@ -46835,7 +47978,37 @@ const pt = {
46835
47978
  "No speech detected": "Nenhuma fala detectada",
46836
47979
  "Microphone access denied": "Acesso ao microfone negado",
46837
47980
  "No microphone found": "No microphone found",
46838
- "Network error - speech recognition requires internet": "Network error - speech recognition requires internet"
47981
+ "Network error - speech recognition requires internet": "Network error - speech recognition requires internet",
47982
+ "Subscript": "Subscrito",
47983
+ "Superscript": "Sobrescrito",
47984
+ "Horizontal rule": "Linha horizontal",
47985
+ "Unlink": "Remover link",
47986
+ "Format": "Formato",
47987
+ "Paragraph": "Parágrafo",
47988
+ "Heading 1": "Título 1",
47989
+ "Heading 2": "Título 2",
47990
+ "Heading 3": "Título 3",
47991
+ "Heading 4": "Título 4",
47992
+ "Heading 5": "Título 5",
47993
+ "Heading 6": "Título 6",
47994
+ "Styles": "Estilos",
47995
+ "Insert anchor": "Inserir âncora",
47996
+ "Anchor": "Âncora",
47997
+ "Anchor name": "Nome da âncora",
47998
+ "Anchor name is required": "O nome da âncora é obrigatório",
47999
+ "Anchor name cannot contain spaces": "O nome da âncora não pode conter espaços",
48000
+ "Table": "Tabela",
48001
+ "Insert table": "Inserir tabela",
48002
+ "Insert row before": "Inserir linha antes",
48003
+ "Insert row after": "Inserir linha depois",
48004
+ "Delete row": "Excluir linha",
48005
+ "Insert column before": "Inserir coluna antes",
48006
+ "Insert column after": "Inserir coluna depois",
48007
+ "Delete column": "Excluir coluna",
48008
+ "Merge cells": "Mesclar células",
48009
+ "Split cell": "Dividir célula",
48010
+ "Toggle header row": "Alternar linha de cabeçalho",
48011
+ "Delete table": "Excluir tabela"
46839
48012
  };
46840
48013
  const ro = {
46841
48014
  "Bold": "Îngroșat",
@@ -46920,7 +48093,37 @@ const ro = {
46920
48093
  "No speech detected": "Nu a fost detectata nicio voce",
46921
48094
  "Microphone access denied": "Accesul la microfon a fost refuzat",
46922
48095
  "No microphone found": "No microphone found",
46923
- "Network error - speech recognition requires internet": "Network error - speech recognition requires internet"
48096
+ "Network error - speech recognition requires internet": "Network error - speech recognition requires internet",
48097
+ "Subscript": "Indice",
48098
+ "Superscript": "Exponent",
48099
+ "Horizontal rule": "Linie orizontală",
48100
+ "Unlink": "Eliminare link",
48101
+ "Format": "Format",
48102
+ "Paragraph": "Paragraf",
48103
+ "Heading 1": "Titlu 1",
48104
+ "Heading 2": "Titlu 2",
48105
+ "Heading 3": "Titlu 3",
48106
+ "Heading 4": "Titlu 4",
48107
+ "Heading 5": "Titlu 5",
48108
+ "Heading 6": "Titlu 6",
48109
+ "Styles": "Stiluri",
48110
+ "Insert anchor": "Inserare ancoră",
48111
+ "Anchor": "Ancoră",
48112
+ "Anchor name": "Nume ancoră",
48113
+ "Anchor name is required": "Numele ancorei este obligatoriu",
48114
+ "Anchor name cannot contain spaces": "Numele ancorei nu poate conține spații",
48115
+ "Table": "Tabel",
48116
+ "Insert table": "Inserare tabel",
48117
+ "Insert row before": "Inserare rând înainte",
48118
+ "Insert row after": "Inserare rând după",
48119
+ "Delete row": "Ștergere rând",
48120
+ "Insert column before": "Inserare coloană înainte",
48121
+ "Insert column after": "Inserare coloană după",
48122
+ "Delete column": "Ștergere coloană",
48123
+ "Merge cells": "Îmbinare celule",
48124
+ "Split cell": "Divizare celulă",
48125
+ "Toggle header row": "Comutare rând antet",
48126
+ "Delete table": "Ștergere tabel"
46924
48127
  };
46925
48128
  const ru = {
46926
48129
  "Bold": "Полужирный",
@@ -47005,7 +48208,37 @@ const ru = {
47005
48208
  "No speech detected": "???? ?? ??????????",
47006
48209
  "Microphone access denied": "?????? ? ????????? ????????",
47007
48210
  "No microphone found": "No microphone found",
47008
- "Network error - speech recognition requires internet": "Network error - speech recognition requires internet"
48211
+ "Network error - speech recognition requires internet": "Network error - speech recognition requires internet",
48212
+ "Subscript": "Подстрочный",
48213
+ "Superscript": "Надстрочный",
48214
+ "Horizontal rule": "Горизонтальная линия",
48215
+ "Unlink": "Удалить ссылку",
48216
+ "Format": "Формат",
48217
+ "Paragraph": "Абзац",
48218
+ "Heading 1": "Заголовок 1",
48219
+ "Heading 2": "Заголовок 2",
48220
+ "Heading 3": "Заголовок 3",
48221
+ "Heading 4": "Заголовок 4",
48222
+ "Heading 5": "Заголовок 5",
48223
+ "Heading 6": "Заголовок 6",
48224
+ "Styles": "Стили",
48225
+ "Insert anchor": "Вставить якорь",
48226
+ "Anchor": "Якорь",
48227
+ "Anchor name": "Имя якоря",
48228
+ "Anchor name is required": "Требуется имя якоря",
48229
+ "Anchor name cannot contain spaces": "Имя якоря не может содержать пробелы",
48230
+ "Table": "Таблица",
48231
+ "Insert table": "Вставить таблицу",
48232
+ "Insert row before": "Вставить строку выше",
48233
+ "Insert row after": "Вставить строку ниже",
48234
+ "Delete row": "Удалить строку",
48235
+ "Insert column before": "Вставить столбец слева",
48236
+ "Insert column after": "Вставить столбец справа",
48237
+ "Delete column": "Удалить столбец",
48238
+ "Merge cells": "Объединить ячейки",
48239
+ "Split cell": "Разделить ячейку",
48240
+ "Toggle header row": "Переключить строку заголовка",
48241
+ "Delete table": "Удалить таблицу"
47009
48242
  };
47010
48243
  const sr = {
47011
48244
  "Bold": "Подебљано",
@@ -47090,7 +48323,37 @@ const sr = {
47090
48323
  "No speech detected": "????? ???? ????????",
47091
48324
  "Microphone access denied": "??????? ????????? ???????",
47092
48325
  "No microphone found": "No microphone found",
47093
- "Network error - speech recognition requires internet": "Network error - speech recognition requires internet"
48326
+ "Network error - speech recognition requires internet": "Network error - speech recognition requires internet",
48327
+ "Subscript": "Индекс",
48328
+ "Superscript": "Експонент",
48329
+ "Horizontal rule": "Хоризонтална линија",
48330
+ "Unlink": "Уклони везу",
48331
+ "Format": "Формат",
48332
+ "Paragraph": "Пасус",
48333
+ "Heading 1": "Наслов 1",
48334
+ "Heading 2": "Наслов 2",
48335
+ "Heading 3": "Наслов 3",
48336
+ "Heading 4": "Наслов 4",
48337
+ "Heading 5": "Наслов 5",
48338
+ "Heading 6": "Наслов 6",
48339
+ "Styles": "Стилови",
48340
+ "Insert anchor": "Уметни сидро",
48341
+ "Anchor": "Сидро",
48342
+ "Anchor name": "Назив сидра",
48343
+ "Anchor name is required": "Назив сидра је обавезан",
48344
+ "Anchor name cannot contain spaces": "Назив сидра не може садржати размаке",
48345
+ "Table": "Табела",
48346
+ "Insert table": "Уметни табелу",
48347
+ "Insert row before": "Уметни ред изнад",
48348
+ "Insert row after": "Уметни ред испод",
48349
+ "Delete row": "Обриши ред",
48350
+ "Insert column before": "Уметни колону лево",
48351
+ "Insert column after": "Уметни колону десно",
48352
+ "Delete column": "Обриши колону",
48353
+ "Merge cells": "Споји ћелије",
48354
+ "Split cell": "Подели ћелију",
48355
+ "Toggle header row": "Укључи/искључи ред заглавља",
48356
+ "Delete table": "Обриши табелу"
47094
48357
  };
47095
48358
  const sl = {
47096
48359
  "Bold": "Krepko",
@@ -47175,7 +48438,37 @@ const sl = {
47175
48438
  "No speech detected": "Govor ni bil zaznan",
47176
48439
  "Microphone access denied": "Dostop do mikrofona zavrnjen",
47177
48440
  "No microphone found": "No microphone found",
47178
- "Network error - speech recognition requires internet": "Network error - speech recognition requires internet"
48441
+ "Network error - speech recognition requires internet": "Network error - speech recognition requires internet",
48442
+ "Subscript": "Podpisano",
48443
+ "Superscript": "Nadpisano",
48444
+ "Horizontal rule": "Vodoravna črta",
48445
+ "Unlink": "Odstrani povezavo",
48446
+ "Format": "Oblika",
48447
+ "Paragraph": "Odstavek",
48448
+ "Heading 1": "Naslov 1",
48449
+ "Heading 2": "Naslov 2",
48450
+ "Heading 3": "Naslov 3",
48451
+ "Heading 4": "Naslov 4",
48452
+ "Heading 5": "Naslov 5",
48453
+ "Heading 6": "Naslov 6",
48454
+ "Styles": "Slogi",
48455
+ "Insert anchor": "Vstavi sidro",
48456
+ "Anchor": "Sidro",
48457
+ "Anchor name": "Ime sidra",
48458
+ "Anchor name is required": "Ime sidra je obvezno",
48459
+ "Anchor name cannot contain spaces": "Ime sidra ne sme vsebovati presledkov",
48460
+ "Table": "Tabela",
48461
+ "Insert table": "Vstavi tabelo",
48462
+ "Insert row before": "Vstavi vrstico pred",
48463
+ "Insert row after": "Vstavi vrstico za",
48464
+ "Delete row": "Izbriši vrstico",
48465
+ "Insert column before": "Vstavi stolpec pred",
48466
+ "Insert column after": "Vstavi stolpec za",
48467
+ "Delete column": "Izbriši stolpec",
48468
+ "Merge cells": "Združi celice",
48469
+ "Split cell": "Razdeli celico",
48470
+ "Toggle header row": "Preklopi vrstico glave",
48471
+ "Delete table": "Izbriši tabelo"
47179
48472
  };
47180
48473
  const es = {
47181
48474
  "Bold": "Negrita",
@@ -47260,7 +48553,37 @@ const es = {
47260
48553
  "No speech detected": "No se detect� voz",
47261
48554
  "Microphone access denied": "Acceso al micr�fono denegado",
47262
48555
  "No microphone found": "No microphone found",
47263
- "Network error - speech recognition requires internet": "Network error - speech recognition requires internet"
48556
+ "Network error - speech recognition requires internet": "Network error - speech recognition requires internet",
48557
+ "Subscript": "Subíndice",
48558
+ "Superscript": "Superíndice",
48559
+ "Horizontal rule": "Línea horizontal",
48560
+ "Unlink": "Quitar enlace",
48561
+ "Format": "Formato",
48562
+ "Paragraph": "Párrafo",
48563
+ "Heading 1": "Encabezado 1",
48564
+ "Heading 2": "Encabezado 2",
48565
+ "Heading 3": "Encabezado 3",
48566
+ "Heading 4": "Encabezado 4",
48567
+ "Heading 5": "Encabezado 5",
48568
+ "Heading 6": "Encabezado 6",
48569
+ "Styles": "Estilos",
48570
+ "Insert anchor": "Insertar ancla",
48571
+ "Anchor": "Ancla",
48572
+ "Anchor name": "Nombre del ancla",
48573
+ "Anchor name is required": "El nombre del ancla es obligatorio",
48574
+ "Anchor name cannot contain spaces": "El nombre del ancla no puede contener espacios",
48575
+ "Table": "Tabla",
48576
+ "Insert table": "Insertar tabla",
48577
+ "Insert row before": "Insertar fila antes",
48578
+ "Insert row after": "Insertar fila después",
48579
+ "Delete row": "Eliminar fila",
48580
+ "Insert column before": "Insertar columna antes",
48581
+ "Insert column after": "Insertar columna después",
48582
+ "Delete column": "Eliminar columna",
48583
+ "Merge cells": "Combinar celdas",
48584
+ "Split cell": "Dividir celda",
48585
+ "Toggle header row": "Alternar fila de encabezado",
48586
+ "Delete table": "Eliminar tabla"
47264
48587
  };
47265
48588
  const sv = {
47266
48589
  "Bold": "Fet",
@@ -47345,7 +48668,37 @@ const sv = {
47345
48668
  "No speech detected": "Inget tal detekterat",
47346
48669
  "Microphone access denied": "Mikrofon�tkomst nekad",
47347
48670
  "No microphone found": "No microphone found",
47348
- "Network error - speech recognition requires internet": "Network error - speech recognition requires internet"
48671
+ "Network error - speech recognition requires internet": "Network error - speech recognition requires internet",
48672
+ "Subscript": "Nedsänkt",
48673
+ "Superscript": "Upphöjd",
48674
+ "Horizontal rule": "Vågrät linje",
48675
+ "Unlink": "Ta bort länk",
48676
+ "Format": "Format",
48677
+ "Paragraph": "Stycke",
48678
+ "Heading 1": "Rubrik 1",
48679
+ "Heading 2": "Rubrik 2",
48680
+ "Heading 3": "Rubrik 3",
48681
+ "Heading 4": "Rubrik 4",
48682
+ "Heading 5": "Rubrik 5",
48683
+ "Heading 6": "Rubrik 6",
48684
+ "Styles": "Stilar",
48685
+ "Insert anchor": "Infoga ankare",
48686
+ "Anchor": "Ankare",
48687
+ "Anchor name": "Ankarnamn",
48688
+ "Anchor name is required": "Ankarnamn krävs",
48689
+ "Anchor name cannot contain spaces": "Ankarnamn får inte innehålla mellanslag",
48690
+ "Table": "Tabell",
48691
+ "Insert table": "Infoga tabell",
48692
+ "Insert row before": "Infoga rad före",
48693
+ "Insert row after": "Infoga rad efter",
48694
+ "Delete row": "Ta bort rad",
48695
+ "Insert column before": "Infoga kolumn före",
48696
+ "Insert column after": "Infoga kolumn efter",
48697
+ "Delete column": "Ta bort kolumn",
48698
+ "Merge cells": "Slå samman celler",
48699
+ "Split cell": "Dela cell",
48700
+ "Toggle header row": "Växla rubrikrad",
48701
+ "Delete table": "Ta bort tabell"
47349
48702
  };
47350
48703
  const zhTw = {
47351
48704
  "Bold": "粗體",
@@ -47430,7 +48783,37 @@ const zhTw = {
47430
48783
  "No speech detected": "??????",
47431
48784
  "Microphone access denied": "????????",
47432
48785
  "No microphone found": "No microphone found",
47433
- "Network error - speech recognition requires internet": "Network error - speech recognition requires internet"
48786
+ "Network error - speech recognition requires internet": "Network error - speech recognition requires internet",
48787
+ "Subscript": "下標",
48788
+ "Superscript": "上標",
48789
+ "Horizontal rule": "水平線",
48790
+ "Unlink": "移除連結",
48791
+ "Format": "格式",
48792
+ "Paragraph": "段落",
48793
+ "Heading 1": "標題 1",
48794
+ "Heading 2": "標題 2",
48795
+ "Heading 3": "標題 3",
48796
+ "Heading 4": "標題 4",
48797
+ "Heading 5": "標題 5",
48798
+ "Heading 6": "標題 6",
48799
+ "Styles": "樣式",
48800
+ "Insert anchor": "插入錨點",
48801
+ "Anchor": "錨點",
48802
+ "Anchor name": "錨點名稱",
48803
+ "Anchor name is required": "錨點名稱為必填",
48804
+ "Anchor name cannot contain spaces": "錨點名稱不能包含空格",
48805
+ "Table": "表格",
48806
+ "Insert table": "插入表格",
48807
+ "Insert row before": "在上方插入列",
48808
+ "Insert row after": "在下方插入列",
48809
+ "Delete row": "刪除列",
48810
+ "Insert column before": "在左側插入欄",
48811
+ "Insert column after": "在右側插入欄",
48812
+ "Delete column": "刪除欄",
48813
+ "Merge cells": "合併儲存格",
48814
+ "Split cell": "分割儲存格",
48815
+ "Toggle header row": "切換標題列",
48816
+ "Delete table": "刪除表格"
47434
48817
  };
47435
48818
  const th = {
47436
48819
  "Bold": "ตัวหนา",
@@ -47515,7 +48898,37 @@ const th = {
47515
48898
  "No speech detected": "?????????????",
47516
48899
  "Microphone access denied": "???????????????????????????",
47517
48900
  "No microphone found": "No microphone found",
47518
- "Network error - speech recognition requires internet": "Network error - speech recognition requires internet"
48901
+ "Network error - speech recognition requires internet": "Network error - speech recognition requires internet",
48902
+ "Subscript": "ตัวห้อย",
48903
+ "Superscript": "ตัวยก",
48904
+ "Horizontal rule": "เส้นแนวนอน",
48905
+ "Unlink": "ลบลิงก์",
48906
+ "Format": "รูปแบบ",
48907
+ "Paragraph": "ย่อหน้า",
48908
+ "Heading 1": "หัวข้อ 1",
48909
+ "Heading 2": "หัวข้อ 2",
48910
+ "Heading 3": "หัวข้อ 3",
48911
+ "Heading 4": "หัวข้อ 4",
48912
+ "Heading 5": "หัวข้อ 5",
48913
+ "Heading 6": "หัวข้อ 6",
48914
+ "Styles": "สไตล์",
48915
+ "Insert anchor": "แทรกจุดยึด",
48916
+ "Anchor": "จุดยึด",
48917
+ "Anchor name": "ชื่อจุดยึด",
48918
+ "Anchor name is required": "ต้องระบุชื่อจุดยึด",
48919
+ "Anchor name cannot contain spaces": "ชื่อจุดยึดต้องไม่มีช่องว่าง",
48920
+ "Table": "ตาราง",
48921
+ "Insert table": "แทรกตาราง",
48922
+ "Insert row before": "แทรกแถวก่อนหน้า",
48923
+ "Insert row after": "แทรกแถวถัดไป",
48924
+ "Delete row": "ลบแถว",
48925
+ "Insert column before": "แทรกคอลัมน์ก่อนหน้า",
48926
+ "Insert column after": "แทรกคอลัมน์ถัดไป",
48927
+ "Delete column": "ลบคอลัมน์",
48928
+ "Merge cells": "ผสานเซลล์",
48929
+ "Split cell": "แยกเซลล์",
48930
+ "Toggle header row": "สลับแถวส่วนหัว",
48931
+ "Delete table": "ลบตาราง"
47519
48932
  };
47520
48933
  const tr = {
47521
48934
  "Bold": "Kalın",
@@ -47600,7 +49013,37 @@ const tr = {
47600
49013
  "No speech detected": "Konusma algilanmadi",
47601
49014
  "Microphone access denied": "Mikrofon erisimi reddedildi",
47602
49015
  "No microphone found": "No microphone found",
47603
- "Network error - speech recognition requires internet": "Network error - speech recognition requires internet"
49016
+ "Network error - speech recognition requires internet": "Network error - speech recognition requires internet",
49017
+ "Subscript": "Alt simge",
49018
+ "Superscript": "Üst simge",
49019
+ "Horizontal rule": "Yatay çizgi",
49020
+ "Unlink": "Bağlantıyı kaldır",
49021
+ "Format": "Biçim",
49022
+ "Paragraph": "Paragraf",
49023
+ "Heading 1": "Başlık 1",
49024
+ "Heading 2": "Başlık 2",
49025
+ "Heading 3": "Başlık 3",
49026
+ "Heading 4": "Başlık 4",
49027
+ "Heading 5": "Başlık 5",
49028
+ "Heading 6": "Başlık 6",
49029
+ "Styles": "Stiller",
49030
+ "Insert anchor": "Çapa ekle",
49031
+ "Anchor": "Çapa",
49032
+ "Anchor name": "Çapa adı",
49033
+ "Anchor name is required": "Çapa adı gereklidir",
49034
+ "Anchor name cannot contain spaces": "Çapa adı boşluk içeremez",
49035
+ "Table": "Tablo",
49036
+ "Insert table": "Tablo ekle",
49037
+ "Insert row before": "Önceye satır ekle",
49038
+ "Insert row after": "Sonraya satır ekle",
49039
+ "Delete row": "Satırı sil",
49040
+ "Insert column before": "Önceye sütun ekle",
49041
+ "Insert column after": "Sonraya sütun ekle",
49042
+ "Delete column": "Sütunu sil",
49043
+ "Merge cells": "Hücreleri birleştir",
49044
+ "Split cell": "Hücreyi böl",
49045
+ "Toggle header row": "Başlık satırını aç/kapat",
49046
+ "Delete table": "Tabloyu sil"
47604
49047
  };
47605
49048
  const vi = {
47606
49049
  "Bold": "In đậm",
@@ -47685,7 +49128,37 @@ const vi = {
47685
49128
  "No speech detected": "Kh�ng ph�t hi?n gi?ng n�i",
47686
49129
  "Microphone access denied": "Quy?n truy c?p micr� b? t? ch?i",
47687
49130
  "No microphone found": "No microphone found",
47688
- "Network error - speech recognition requires internet": "Network error - speech recognition requires internet"
49131
+ "Network error - speech recognition requires internet": "Network error - speech recognition requires internet",
49132
+ "Subscript": "Chỉ số dưới",
49133
+ "Superscript": "Chỉ số trên",
49134
+ "Horizontal rule": "Đường kẻ ngang",
49135
+ "Unlink": "Bỏ liên kết",
49136
+ "Format": "Định dạng",
49137
+ "Paragraph": "Đoạn văn",
49138
+ "Heading 1": "Tiêu đề 1",
49139
+ "Heading 2": "Tiêu đề 2",
49140
+ "Heading 3": "Tiêu đề 3",
49141
+ "Heading 4": "Tiêu đề 4",
49142
+ "Heading 5": "Tiêu đề 5",
49143
+ "Heading 6": "Tiêu đề 6",
49144
+ "Styles": "Kiểu",
49145
+ "Insert anchor": "Chèn neo",
49146
+ "Anchor": "Neo",
49147
+ "Anchor name": "Tên neo",
49148
+ "Anchor name is required": "Tên neo là bắt buộc",
49149
+ "Anchor name cannot contain spaces": "Tên neo không được chứa khoảng trắng",
49150
+ "Table": "Bảng",
49151
+ "Insert table": "Chèn bảng",
49152
+ "Insert row before": "Chèn hàng phía trước",
49153
+ "Insert row after": "Chèn hàng phía sau",
49154
+ "Delete row": "Xóa hàng",
49155
+ "Insert column before": "Chèn cột phía trước",
49156
+ "Insert column after": "Chèn cột phía sau",
49157
+ "Delete column": "Xóa cột",
49158
+ "Merge cells": "Gộp ô",
49159
+ "Split cell": "Tách ô",
49160
+ "Toggle header row": "Bật/tắt hàng tiêu đề",
49161
+ "Delete table": "Xóa bảng"
47689
49162
  };
47690
49163
  const locales = {
47691
49164
  en,
@@ -47731,8 +49204,8 @@ const availableLocales = Object.keys(locales);
47731
49204
  const TRANSLATION_KEYS = Object.keys(en);
47732
49205
  const lowlight = createLowlight(grammars);
47733
49206
  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";
47734
- 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";
47735
- 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";
49207
+ const FULL_TOOLBAR = "bold italic underline strikethrough subscript superscript | blocks styles | bullist numlist outdent indent blockquote | fontfamily fontsize | lineheight alignleft aligncenter alignright alignjustify | forecolor backcolor | removeformat copy cut paste | undo redo | image table charmap emoticons hr | fullscreen preview | code link unlink anchor codesample | ltr rtl | searchreplace";
49208
+ const BASIC_TOOLBAR = "bold italic underline strikethrough subscript superscript | bullist numlist outdent indent | fontfamily fontsize blockquote | lineheight alignleft aligncenter alignright alignjustify | forecolor backcolor | removeformat copy cut paste | undo redo | charmap emoticons | link unlink | ltr rtl | searchreplace";
47736
49209
  const DEFAULT_FONT_SIZES = "8pt 9pt 10pt 12pt 14pt 18pt 24pt 36pt";
47737
49210
  let editorIdCounter = 0;
47738
49211
  let globalTranslate = (key) => key;
@@ -47788,6 +49261,8 @@ class HTMLEditor {
47788
49261
  normalizeConfig(config) {
47789
49262
  return {
47790
49263
  basicEditor: config.basicEditor ?? false,
49264
+ readonly: config.readonly ?? false,
49265
+ forced_root_block: config.forced_root_block ?? "p",
47791
49266
  includeTemplates: config.includeTemplates ?? false,
47792
49267
  templates: config.templates ?? [],
47793
49268
  dropbox: config.dropbox ?? false,
@@ -47796,8 +49271,14 @@ class HTMLEditor {
47796
49271
  images_upload_base_path: config.images_upload_base_path ?? "/",
47797
49272
  images_upload_max_size: config.images_upload_max_size,
47798
49273
  images_upload_headers: config.images_upload_headers,
47799
- font_family_formats: config.font_family_formats ?? fontNames,
47800
- font_size_formats: config.font_size_formats ?? DEFAULT_FONT_SIZES,
49274
+ images_file_types: config.images_file_types,
49275
+ images_upload_validate: config.images_upload_validate,
49276
+ images_upload_error: config.images_upload_error,
49277
+ // CKEditor aliases: font_names / fontSize_sizes map to the TinyMCE keys
49278
+ font_family_formats: config.font_family_formats ?? config.font_names ?? fontNames,
49279
+ font_size_formats: config.font_size_formats ?? config.fontSize_sizes ?? DEFAULT_FONT_SIZES,
49280
+ block_formats: config.block_formats,
49281
+ style_formats: config.style_formats,
47801
49282
  fontName: config.fontName,
47802
49283
  fontSize: config.fontSize,
47803
49284
  directionality: config.directionality ?? "ltr",
@@ -47871,6 +49352,7 @@ class HTMLEditor {
47871
49352
  element: editorContent,
47872
49353
  extensions,
47873
49354
  content: "",
49355
+ editable: !this.config.readonly,
47874
49356
  editorProps: {
47875
49357
  attributes: {
47876
49358
  class: "md-editor-body",
@@ -47909,6 +49391,10 @@ class HTMLEditor {
47909
49391
  narrowBreakpoint: this.config.toolbar_narrow_breakpoint ?? 768,
47910
49392
  priorityOverrides: this.config.toolbar_priority ?? {}
47911
49393
  });
49394
+ if (this.config.readonly) {
49395
+ this.editorWrapper.classList.add("md-editor-readonly");
49396
+ this.toolbar.setEnabled(false);
49397
+ }
47912
49398
  if (this.config.auto_focus) {
47913
49399
  setTimeout(() => this.focus(), 10);
47914
49400
  } else if (this.config.setFocus) {
@@ -47933,6 +49419,9 @@ class HTMLEditor {
47933
49419
  uploadBasePath: this.config.images_upload_base_path,
47934
49420
  uploadMaxSize: this.config.images_upload_max_size,
47935
49421
  uploadHeaders: this.config.images_upload_headers,
49422
+ fileTypes: this.config.images_file_types,
49423
+ validate: this.config.images_upload_validate,
49424
+ onError: this.config.images_upload_error,
47936
49425
  trans: globalTranslate
47937
49426
  });
47938
49427
  }
@@ -47981,19 +49470,29 @@ class HTMLEditor {
47981
49470
  const helper = this.getImageUploadHelper();
47982
49471
  helper.uploadFile(file).then((src) => {
47983
49472
  this.tiptap?.chain().focus().setImage({ src }).run();
47984
- }).catch(() => {
49473
+ }).catch((err) => {
49474
+ const message = err instanceof Error && err.message ? err.message : globalTranslate("Upload failed");
49475
+ this.config.images_upload_error?.(message);
47985
49476
  });
47986
49477
  }
47987
49478
  buildExtensions() {
49479
+ const useDivBlocks = this.config.forced_root_block === "div";
47988
49480
  const extensions = [
47989
49481
  StarterKit.configure({
47990
- codeBlock: false
49482
+ codeBlock: false,
47991
49483
  // We use CodeBlockLowlight instead
49484
+ // When forced_root_block is 'div', swap StarterKit's <p> paragraph for
49485
+ // a custom Paragraph that renders as <div> (CKEditor ENTER_DIV parity).
49486
+ ...useDivBlocks ? { paragraph: false } : {}
47992
49487
  }),
47993
49488
  SignatureBlock,
47994
49489
  Mention,
49490
+ Anchor,
49491
+ Subscript,
49492
+ Superscript,
47995
49493
  Underline,
47996
49494
  TextStyle,
49495
+ InlineStyle,
47997
49496
  FontFamily,
47998
49497
  FontSize,
47999
49498
  LineHeight,
@@ -48030,6 +49529,18 @@ class HTMLEditor {
48030
49529
  }),
48031
49530
  TextDirection
48032
49531
  ];
49532
+ if (useDivBlocks) {
49533
+ extensions.push(
49534
+ Paragraph.extend({
49535
+ parseHTML() {
49536
+ return [{ tag: "p" }, { tag: "div" }];
49537
+ },
49538
+ renderHTML({ HTMLAttributes }) {
49539
+ return ["div", mergeAttributes(this.options.HTMLAttributes, HTMLAttributes), 0];
49540
+ }
49541
+ })
49542
+ );
49543
+ }
48033
49544
  if (this.config.paste_from_office !== false) {
48034
49545
  extensions.push(PasteFromOffice);
48035
49546
  }
@@ -48099,6 +49610,12 @@ class HTMLEditor {
48099
49610
  case "strikethrough":
48100
49611
  chain.toggleStrike().run();
48101
49612
  return true;
49613
+ case "subscript":
49614
+ chain.toggleSubscript().run();
49615
+ return true;
49616
+ case "superscript":
49617
+ chain.toggleSuperscript().run();
49618
+ return true;
48102
49619
  case "fontname":
48103
49620
  if (typeof value === "string") {
48104
49621
  chain.setFontFamily(value).run();
@@ -48162,6 +49679,12 @@ class HTMLEditor {
48162
49679
  case "removeformat":
48163
49680
  chain.unsetAllMarks().clearNodes().run();
48164
49681
  return true;
49682
+ case "unlink":
49683
+ chain.unsetLink().run();
49684
+ return true;
49685
+ case "inserthorizontalrule":
49686
+ chain.setHorizontalRule().run();
49687
+ return true;
48165
49688
  case "mceremoveeditor":
48166
49689
  this.destroy();
48167
49690
  return true;
@@ -48179,6 +49702,19 @@ class HTMLEditor {
48179
49702
  this.fire("dirty", false);
48180
49703
  }
48181
49704
  }
49705
+ /**
49706
+ * Toggle read-only mode. Disables editing and dims the toolbar.
49707
+ * Mirrors CKEditor's editor.setReadOnly(bool).
49708
+ */
49709
+ setReadOnly(state) {
49710
+ this.config.readonly = state;
49711
+ this.tiptap?.setEditable(!state);
49712
+ this.editorWrapper?.classList.toggle("md-editor-readonly", state);
49713
+ this.toolbar?.setEnabled(!state);
49714
+ }
49715
+ isReadOnly() {
49716
+ return this.config.readonly ?? false;
49717
+ }
48182
49718
  focus() {
48183
49719
  this.tiptap?.commands.focus();
48184
49720
  }
@@ -48246,6 +49782,8 @@ class HTMLEditor {
48246
49782
  return this.config.basicEditor ?? false;
48247
49783
  }
48248
49784
  }
49785
+ exports.Anchor = Anchor;
49786
+ exports.AnchorDialog = AnchorDialog;
48249
49787
  exports.CHAR_MAP = CHAR_MAP;
48250
49788
  exports.CONFAB_ICONS = CONFAB_ICONS;
48251
49789
  exports.CharacterMap = CharacterMap;
@@ -48255,6 +49793,7 @@ exports.EMOJI_CATEGORIES = EMOJI_CATEGORIES;
48255
49793
  exports.EmojiPicker = EmojiPicker;
48256
49794
  exports.FontSize = FontSize;
48257
49795
  exports.HTMLEditor = HTMLEditor;
49796
+ exports.InlineStyle = InlineStyle;
48258
49797
  exports.LineHeight = LineHeight;
48259
49798
  exports.LinkEditor = LinkEditor;
48260
49799
  exports.Mention = Mention;