autumnnote 1.6.1 → 1.6.3
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/autumnnote.es.js +147 -348
- package/dist/autumnnote.es.js.map +1 -1
- package/dist/autumnnote.umd.js +147 -348
- package/dist/autumnnote.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/js/Context.js +5 -2
- package/src/js/index.js +1 -1
- package/src/js/module/BaseDialog.js +126 -0
- package/src/js/module/EmojiDialog.js +7 -44
- package/src/js/module/FindReplace.js +4 -18
- package/src/js/module/IconDialog.js +9 -41
- package/src/js/module/ImageDialog.js +12 -82
- package/src/js/module/LinkDialog.js +12 -78
- package/src/js/module/ShortcutsDialog.js +20 -49
- package/src/js/module/VideoDialog.js +10 -80
package/dist/autumnnote.umd.js
CHANGED
|
@@ -6978,15 +6978,13 @@
|
|
|
6978
6978
|
}
|
|
6979
6979
|
};
|
|
6980
6980
|
//#endregion
|
|
6981
|
-
//#region src/js/module/
|
|
6981
|
+
//#region src/js/module/BaseDialog.js
|
|
6982
6982
|
/**
|
|
6983
|
-
*
|
|
6984
|
-
*
|
|
6983
|
+
* Shared lifecycle and shell-building logic for all modal dialogs.
|
|
6984
|
+
* Subclasses implement _buildDialog() for their specific form fields.
|
|
6985
6985
|
*/
|
|
6986
|
-
var
|
|
6987
|
-
/**
|
|
6988
|
-
* @param {import('../Context.js').Context} context
|
|
6989
|
-
*/
|
|
6986
|
+
var BaseDialog = class {
|
|
6987
|
+
/** @param {import('../Context.js').Context} context */
|
|
6990
6988
|
constructor(context) {
|
|
6991
6989
|
this.context = context;
|
|
6992
6990
|
this.options = context.options;
|
|
@@ -6994,6 +6992,9 @@
|
|
|
6994
6992
|
this._dialog = null;
|
|
6995
6993
|
this._disposers = [];
|
|
6996
6994
|
this._savedRange = null;
|
|
6995
|
+
/** @type {HTMLElement|null} First focusable input; set by subclass in _buildDialog(). */
|
|
6996
|
+
this._firstInput = null;
|
|
6997
|
+
this._removeTrap = null;
|
|
6997
6998
|
}
|
|
6998
6999
|
initialize() {
|
|
6999
7000
|
this._dialog = this._buildDialog();
|
|
@@ -7003,36 +7004,113 @@
|
|
|
7003
7004
|
destroy() {
|
|
7004
7005
|
this._disposers.forEach((d) => d());
|
|
7005
7006
|
this._disposers = [];
|
|
7006
|
-
if (this._dialog
|
|
7007
|
+
if (this._dialog?.parentNode) this._dialog.remove();
|
|
7007
7008
|
this._dialog = null;
|
|
7008
7009
|
}
|
|
7009
|
-
/**
|
|
7010
|
-
|
|
7011
|
-
* Pre-fills with the currently selected link if present.
|
|
7012
|
-
*/
|
|
7013
|
-
show() {
|
|
7010
|
+
/** Saves the current selection range before opening the dialog. */
|
|
7011
|
+
_saveRange() {
|
|
7014
7012
|
withSavedRange((range) => {
|
|
7015
7013
|
this._savedRange = range;
|
|
7016
7014
|
});
|
|
7017
|
-
this._prefill();
|
|
7018
|
-
this._open();
|
|
7019
7015
|
}
|
|
7020
|
-
|
|
7021
|
-
|
|
7016
|
+
_open() {
|
|
7017
|
+
if (this._dialog) {
|
|
7018
|
+
this._dialog.style.display = "flex";
|
|
7019
|
+
this._removeTrap = trapFocus(this._dialog, () => this._close());
|
|
7020
|
+
setTimeout(() => this._firstInput && this._firstInput.focus(), 50);
|
|
7021
|
+
}
|
|
7022
|
+
}
|
|
7023
|
+
_close() {
|
|
7024
|
+
if (this._dialog) this._dialog.style.display = "none";
|
|
7025
|
+
if (this._removeTrap) {
|
|
7026
|
+
this._removeTrap();
|
|
7027
|
+
this._removeTrap = null;
|
|
7028
|
+
}
|
|
7029
|
+
this._savedRange = null;
|
|
7030
|
+
}
|
|
7031
|
+
/**
|
|
7032
|
+
* Builds the overlay + box + header shell common to all dialogs.
|
|
7033
|
+
* Also wires up draggable and overlay-click-to-close.
|
|
7034
|
+
* @param {string} ariaLabel
|
|
7035
|
+
* @param {string} iconHtml Raw SVG string for the dialog icon
|
|
7036
|
+
* @param {string} titleText
|
|
7037
|
+
* @returns {{ overlay: HTMLElement, box: HTMLElement }}
|
|
7038
|
+
*/
|
|
7039
|
+
_buildDialogShell(ariaLabel, iconHtml, titleText) {
|
|
7022
7040
|
const overlay = createElement("div", {
|
|
7023
7041
|
class: "an-dialog-overlay",
|
|
7024
7042
|
role: "dialog",
|
|
7025
7043
|
"aria-modal": "true",
|
|
7026
|
-
"aria-label":
|
|
7044
|
+
"aria-label": ariaLabel
|
|
7027
7045
|
});
|
|
7028
7046
|
const box = createElement("div", { class: "an-dialog-box" });
|
|
7029
7047
|
const header = createElement("div", { class: "an-dialog-header" });
|
|
7030
7048
|
const iconEl = createElement("span", { class: "an-dialog-icon" });
|
|
7031
|
-
iconEl.innerHTML =
|
|
7032
|
-
const
|
|
7033
|
-
|
|
7049
|
+
iconEl.innerHTML = iconHtml;
|
|
7050
|
+
const titleEl = createElement("h3", { class: "an-dialog-title" });
|
|
7051
|
+
titleEl.textContent = titleText;
|
|
7034
7052
|
header.appendChild(iconEl);
|
|
7035
|
-
header.appendChild(
|
|
7053
|
+
header.appendChild(titleEl);
|
|
7054
|
+
box.appendChild(header);
|
|
7055
|
+
overlay.appendChild(box);
|
|
7056
|
+
makeDraggable(header, box);
|
|
7057
|
+
const d = on(overlay, "click", (e) => {
|
|
7058
|
+
if (e.target === overlay) this._close();
|
|
7059
|
+
});
|
|
7060
|
+
this._disposers.push(d);
|
|
7061
|
+
return {
|
|
7062
|
+
overlay,
|
|
7063
|
+
box
|
|
7064
|
+
};
|
|
7065
|
+
}
|
|
7066
|
+
/**
|
|
7067
|
+
* Builds an action button row with a primary insert button and a cancel button.
|
|
7068
|
+
* Disposers are registered automatically.
|
|
7069
|
+
* @param {string} insertLabel
|
|
7070
|
+
* @param {string} cancelLabel
|
|
7071
|
+
* @param {() => void} onInsert
|
|
7072
|
+
* @returns {HTMLElement}
|
|
7073
|
+
*/
|
|
7074
|
+
_buildButtonRow(insertLabel, cancelLabel, onInsert) {
|
|
7075
|
+
const btnRow = createElement("div", { class: "an-dialog-actions" });
|
|
7076
|
+
const insertBtn = createElement("button", {
|
|
7077
|
+
type: "button",
|
|
7078
|
+
class: "an-btn an-btn-primary"
|
|
7079
|
+
});
|
|
7080
|
+
insertBtn.textContent = insertLabel;
|
|
7081
|
+
const cancelBtn = createElement("button", {
|
|
7082
|
+
type: "button",
|
|
7083
|
+
class: "an-btn"
|
|
7084
|
+
});
|
|
7085
|
+
cancelBtn.textContent = cancelLabel;
|
|
7086
|
+
btnRow.appendChild(insertBtn);
|
|
7087
|
+
btnRow.appendChild(cancelBtn);
|
|
7088
|
+
const d1 = on(insertBtn, "click", onInsert);
|
|
7089
|
+
const d2 = on(cancelBtn, "click", () => this._close());
|
|
7090
|
+
this._disposers.push(d1, d2);
|
|
7091
|
+
return btnRow;
|
|
7092
|
+
}
|
|
7093
|
+
};
|
|
7094
|
+
//#endregion
|
|
7095
|
+
//#region src/js/module/LinkDialog.js
|
|
7096
|
+
/**
|
|
7097
|
+
* LinkDialog.js - Dialog for inserting / editing hyperlinks
|
|
7098
|
+
* Inspired by Summernote's LinkDialog — rewritten without jQuery
|
|
7099
|
+
*/
|
|
7100
|
+
var ICON_SVG$3 = `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg>`;
|
|
7101
|
+
var LinkDialog = class extends BaseDialog {
|
|
7102
|
+
/**
|
|
7103
|
+
* Opens the link dialog.
|
|
7104
|
+
* Pre-fills with the currently selected link if present.
|
|
7105
|
+
*/
|
|
7106
|
+
show() {
|
|
7107
|
+
this._saveRange();
|
|
7108
|
+
this._prefill();
|
|
7109
|
+
this._open();
|
|
7110
|
+
}
|
|
7111
|
+
_buildDialog() {
|
|
7112
|
+
const L = this.context.locale.linkDialog;
|
|
7113
|
+
const { overlay, box } = this._buildDialogShell(L.ariaLabel, ICON_SVG$3, L.title);
|
|
7036
7114
|
const urlLabel = createElement("label", { class: "an-label" });
|
|
7037
7115
|
urlLabel.textContent = L.url;
|
|
7038
7116
|
const urlInput = createElement("input", {
|
|
@@ -7044,6 +7122,7 @@
|
|
|
7044
7122
|
autocomplete: "off"
|
|
7045
7123
|
});
|
|
7046
7124
|
this._urlInput = urlInput;
|
|
7125
|
+
this._firstInput = urlInput;
|
|
7047
7126
|
const textLabel = createElement("label", { class: "an-label" });
|
|
7048
7127
|
textLabel.textContent = L.displayText;
|
|
7049
7128
|
const textInput = createElement("input", {
|
|
@@ -7064,27 +7143,8 @@
|
|
|
7064
7143
|
this._tabCheckbox = tabCheckbox;
|
|
7065
7144
|
tabLabel.appendChild(tabCheckbox);
|
|
7066
7145
|
tabLabel.appendChild(document.createTextNode(" " + L.openInNewTab));
|
|
7067
|
-
const btnRow =
|
|
7068
|
-
|
|
7069
|
-
type: "button",
|
|
7070
|
-
class: "an-btn an-btn-primary"
|
|
7071
|
-
});
|
|
7072
|
-
insertBtn.textContent = L.insertBtn;
|
|
7073
|
-
const cancelBtn = createElement("button", {
|
|
7074
|
-
type: "button",
|
|
7075
|
-
class: "an-btn"
|
|
7076
|
-
});
|
|
7077
|
-
cancelBtn.textContent = L.cancelBtn;
|
|
7078
|
-
btnRow.appendChild(insertBtn);
|
|
7079
|
-
btnRow.appendChild(cancelBtn);
|
|
7080
|
-
box.append(header, urlLabel, urlInput, textLabel, textInput, tabLabel, btnRow);
|
|
7081
|
-
overlay.appendChild(box);
|
|
7082
|
-
makeDraggable(header, box);
|
|
7083
|
-
const d1 = on(insertBtn, "click", () => this._onInsert());
|
|
7084
|
-
const d2 = on(cancelBtn, "click", () => this._close());
|
|
7085
|
-
const d3 = on(overlay, "click", (e) => {
|
|
7086
|
-
if (e.target === overlay) this._close();
|
|
7087
|
-
});
|
|
7146
|
+
const btnRow = this._buildButtonRow(L.insertBtn, L.cancelBtn, () => this._onInsert());
|
|
7147
|
+
box.append(urlLabel, urlInput, textLabel, textInput, tabLabel, btnRow);
|
|
7088
7148
|
const d4 = on(urlInput, "keydown", (e) => {
|
|
7089
7149
|
if (e.key === "Enter") {
|
|
7090
7150
|
e.preventDefault();
|
|
@@ -7097,7 +7157,7 @@
|
|
|
7097
7157
|
this._onInsert();
|
|
7098
7158
|
}
|
|
7099
7159
|
});
|
|
7100
|
-
this._disposers.push(
|
|
7160
|
+
this._disposers.push(d4, d5);
|
|
7101
7161
|
return overlay;
|
|
7102
7162
|
}
|
|
7103
7163
|
_prefill() {
|
|
@@ -7146,21 +7206,6 @@
|
|
|
7146
7206
|
this.context.invoke("editor.insertLink", url, text, newTab);
|
|
7147
7207
|
this._close();
|
|
7148
7208
|
}
|
|
7149
|
-
_open() {
|
|
7150
|
-
if (this._dialog) {
|
|
7151
|
-
this._dialog.style.display = "flex";
|
|
7152
|
-
this._removeTrap = trapFocus(this._dialog, () => this._close());
|
|
7153
|
-
setTimeout(() => this._urlInput && this._urlInput.focus(), 50);
|
|
7154
|
-
}
|
|
7155
|
-
}
|
|
7156
|
-
_close() {
|
|
7157
|
-
if (this._dialog) this._dialog.style.display = "none";
|
|
7158
|
-
if (this._removeTrap) {
|
|
7159
|
-
this._removeTrap();
|
|
7160
|
-
this._removeTrap = null;
|
|
7161
|
-
}
|
|
7162
|
-
this._savedRange = null;
|
|
7163
|
-
}
|
|
7164
7209
|
};
|
|
7165
7210
|
//#endregion
|
|
7166
7211
|
//#region src/js/module/ImageDialog.js
|
|
@@ -7168,33 +7213,10 @@
|
|
|
7168
7213
|
* ImageDialog.js - Dialog for inserting images (by URL or file upload)
|
|
7169
7214
|
* Inspired by Summernote's ImageDialog — rewritten without jQuery
|
|
7170
7215
|
*/
|
|
7171
|
-
var
|
|
7172
|
-
|
|
7173
|
-
* @param {import('../Context.js').Context} context
|
|
7174
|
-
*/
|
|
7175
|
-
constructor(context) {
|
|
7176
|
-
this.context = context;
|
|
7177
|
-
this.options = context.options;
|
|
7178
|
-
/** @type {HTMLElement|null} */
|
|
7179
|
-
this._dialog = null;
|
|
7180
|
-
this._disposers = [];
|
|
7181
|
-
this._savedRange = null;
|
|
7182
|
-
}
|
|
7183
|
-
initialize() {
|
|
7184
|
-
this._dialog = this._buildDialog();
|
|
7185
|
-
document.body.appendChild(this._dialog);
|
|
7186
|
-
return this;
|
|
7187
|
-
}
|
|
7188
|
-
destroy() {
|
|
7189
|
-
this._disposers.forEach((d) => d());
|
|
7190
|
-
this._disposers = [];
|
|
7191
|
-
if (this._dialog && this._dialog.parentNode) this._dialog.remove();
|
|
7192
|
-
this._dialog = null;
|
|
7193
|
-
}
|
|
7216
|
+
var ICON_SVG$2 = `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" 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="2"/><circle cx="8.5" cy="8.5" r="1.5"/><polyline points="21 15 16 10 5 21"/></svg>`;
|
|
7217
|
+
var ImageDialog = class extends BaseDialog {
|
|
7194
7218
|
show() {
|
|
7195
|
-
|
|
7196
|
-
this._savedRange = range;
|
|
7197
|
-
});
|
|
7219
|
+
this._saveRange();
|
|
7198
7220
|
this._urlInput.value = "";
|
|
7199
7221
|
this._altInput.value = "";
|
|
7200
7222
|
if (this._fileInput) this._fileInput.value = "";
|
|
@@ -7202,20 +7224,7 @@
|
|
|
7202
7224
|
}
|
|
7203
7225
|
_buildDialog() {
|
|
7204
7226
|
const L = this.context.locale.imageDialog;
|
|
7205
|
-
const overlay =
|
|
7206
|
-
class: "an-dialog-overlay",
|
|
7207
|
-
role: "dialog",
|
|
7208
|
-
"aria-modal": "true",
|
|
7209
|
-
"aria-label": L.ariaLabel
|
|
7210
|
-
});
|
|
7211
|
-
const box = createElement("div", { class: "an-dialog-box" });
|
|
7212
|
-
const header = createElement("div", { class: "an-dialog-header" });
|
|
7213
|
-
const iconEl = createElement("span", { class: "an-dialog-icon" });
|
|
7214
|
-
iconEl.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" 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="2"/><circle cx="8.5" cy="8.5" r="1.5"/><polyline points="21 15 16 10 5 21"/></svg>`;
|
|
7215
|
-
const title = createElement("h3", { class: "an-dialog-title" });
|
|
7216
|
-
title.textContent = L.title;
|
|
7217
|
-
header.appendChild(iconEl);
|
|
7218
|
-
header.appendChild(title);
|
|
7227
|
+
const { overlay, box } = this._buildDialogShell(L.ariaLabel, ICON_SVG$2, L.title);
|
|
7219
7228
|
const urlLabel = createElement("label", { class: "an-label" });
|
|
7220
7229
|
urlLabel.textContent = L.imageUrl;
|
|
7221
7230
|
const urlInput = createElement("input", {
|
|
@@ -7225,6 +7234,7 @@
|
|
|
7225
7234
|
autocomplete: "off"
|
|
7226
7235
|
});
|
|
7227
7236
|
this._urlInput = urlInput;
|
|
7237
|
+
this._firstInput = urlInput;
|
|
7228
7238
|
const altLabel = createElement("label", { class: "an-label" });
|
|
7229
7239
|
altLabel.textContent = L.altText;
|
|
7230
7240
|
const altInput = createElement("input", {
|
|
@@ -7234,7 +7244,7 @@
|
|
|
7234
7244
|
autocomplete: "off"
|
|
7235
7245
|
});
|
|
7236
7246
|
this._altInput = altInput;
|
|
7237
|
-
box.append(
|
|
7247
|
+
box.append(urlLabel, urlInput, altLabel, altInput);
|
|
7238
7248
|
const alignLabel = createElement("label", { class: "an-label" });
|
|
7239
7249
|
alignLabel.textContent = L.alignment;
|
|
7240
7250
|
const alignRow = createElement("div", { class: "an-align-row" });
|
|
@@ -7288,27 +7298,8 @@
|
|
|
7288
7298
|
this._disposers.push(d);
|
|
7289
7299
|
box.append(fileLabel, fileInput, fileHint);
|
|
7290
7300
|
}
|
|
7291
|
-
const btnRow =
|
|
7292
|
-
const insertBtn = createElement("button", {
|
|
7293
|
-
type: "button",
|
|
7294
|
-
class: "an-btn an-btn-primary"
|
|
7295
|
-
});
|
|
7296
|
-
insertBtn.textContent = L.insertBtn;
|
|
7297
|
-
const cancelBtn = createElement("button", {
|
|
7298
|
-
type: "button",
|
|
7299
|
-
class: "an-btn"
|
|
7300
|
-
});
|
|
7301
|
-
cancelBtn.textContent = L.cancelBtn;
|
|
7302
|
-
btnRow.appendChild(insertBtn);
|
|
7303
|
-
btnRow.appendChild(cancelBtn);
|
|
7301
|
+
const btnRow = this._buildButtonRow(L.insertBtn, L.cancelBtn, () => this._onInsert());
|
|
7304
7302
|
box.append(btnRow);
|
|
7305
|
-
overlay.appendChild(box);
|
|
7306
|
-
makeDraggable(header, box);
|
|
7307
|
-
const d1 = on(insertBtn, "click", () => this._onInsert());
|
|
7308
|
-
const d2 = on(cancelBtn, "click", () => this._close());
|
|
7309
|
-
const d3 = on(overlay, "click", (e) => {
|
|
7310
|
-
if (e.target === overlay) this._close();
|
|
7311
|
-
});
|
|
7312
7303
|
const d4 = on(urlInput, "keydown", (e) => {
|
|
7313
7304
|
if (e.key === "Enter") {
|
|
7314
7305
|
e.preventDefault();
|
|
@@ -7321,7 +7312,7 @@
|
|
|
7321
7312
|
this._onInsert();
|
|
7322
7313
|
}
|
|
7323
7314
|
});
|
|
7324
|
-
this._disposers.push(
|
|
7315
|
+
this._disposers.push(d4, d5);
|
|
7325
7316
|
return overlay;
|
|
7326
7317
|
}
|
|
7327
7318
|
_onFileChange() {
|
|
@@ -7376,21 +7367,6 @@
|
|
|
7376
7367
|
this.context.invoke("editor.insertImage", src, alt, align);
|
|
7377
7368
|
this._close();
|
|
7378
7369
|
}
|
|
7379
|
-
_open() {
|
|
7380
|
-
if (this._dialog) {
|
|
7381
|
-
this._dialog.style.display = "flex";
|
|
7382
|
-
this._removeTrap = trapFocus(this._dialog, () => this._close());
|
|
7383
|
-
setTimeout(() => this._urlInput && this._urlInput.focus(), 50);
|
|
7384
|
-
}
|
|
7385
|
-
}
|
|
7386
|
-
_close() {
|
|
7387
|
-
if (this._dialog) this._dialog.style.display = "none";
|
|
7388
|
-
if (this._removeTrap) {
|
|
7389
|
-
this._removeTrap();
|
|
7390
|
-
this._removeTrap = null;
|
|
7391
|
-
}
|
|
7392
|
-
this._savedRange = null;
|
|
7393
|
-
}
|
|
7394
7370
|
};
|
|
7395
7371
|
//#endregion
|
|
7396
7372
|
//#region src/js/module/VideoDialog.js
|
|
@@ -7402,31 +7378,10 @@
|
|
|
7402
7378
|
* • Vimeo URLs → <iframe> embed
|
|
7403
7379
|
* • Direct video URLs → <video> element (.mp4 / .webm / .ogg)
|
|
7404
7380
|
*/
|
|
7405
|
-
var
|
|
7406
|
-
|
|
7407
|
-
constructor(context) {
|
|
7408
|
-
this.context = context;
|
|
7409
|
-
this.options = context.options;
|
|
7410
|
-
/** @type {HTMLElement|null} */
|
|
7411
|
-
this._dialog = null;
|
|
7412
|
-
this._disposers = [];
|
|
7413
|
-
this._savedRange = null;
|
|
7414
|
-
}
|
|
7415
|
-
initialize() {
|
|
7416
|
-
this._dialog = this._buildDialog();
|
|
7417
|
-
document.body.appendChild(this._dialog);
|
|
7418
|
-
return this;
|
|
7419
|
-
}
|
|
7420
|
-
destroy() {
|
|
7421
|
-
this._disposers.forEach((d) => d());
|
|
7422
|
-
this._disposers = [];
|
|
7423
|
-
if (this._dialog && this._dialog.parentNode) this._dialog.remove();
|
|
7424
|
-
this._dialog = null;
|
|
7425
|
-
}
|
|
7381
|
+
var ICON_SVG$1 = `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="23 7 16 12 23 17 23 7"/><rect x="1" y="5" width="15" height="14" rx="2"/></svg>`;
|
|
7382
|
+
var VideoDialog = class extends BaseDialog {
|
|
7426
7383
|
show() {
|
|
7427
|
-
|
|
7428
|
-
this._savedRange = range;
|
|
7429
|
-
});
|
|
7384
|
+
this._saveRange();
|
|
7430
7385
|
this._urlInput.value = "";
|
|
7431
7386
|
this._widthInput.value = "560";
|
|
7432
7387
|
this._hintEl.textContent = "";
|
|
@@ -7434,20 +7389,7 @@
|
|
|
7434
7389
|
}
|
|
7435
7390
|
_buildDialog() {
|
|
7436
7391
|
const L = this.context.locale.videoDialog;
|
|
7437
|
-
const overlay =
|
|
7438
|
-
class: "an-dialog-overlay",
|
|
7439
|
-
role: "dialog",
|
|
7440
|
-
"aria-modal": "true",
|
|
7441
|
-
"aria-label": L.ariaLabel
|
|
7442
|
-
});
|
|
7443
|
-
const box = createElement("div", { class: "an-dialog-box" });
|
|
7444
|
-
const header = createElement("div", { class: "an-dialog-header" });
|
|
7445
|
-
const iconEl = createElement("span", { class: "an-dialog-icon" });
|
|
7446
|
-
iconEl.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="23 7 16 12 23 17 23 7"/><rect x="1" y="5" width="15" height="14" rx="2"/></svg>`;
|
|
7447
|
-
const title = createElement("h3", { class: "an-dialog-title" });
|
|
7448
|
-
title.textContent = L.title;
|
|
7449
|
-
header.appendChild(iconEl);
|
|
7450
|
-
header.appendChild(title);
|
|
7392
|
+
const { overlay, box } = this._buildDialogShell(L.ariaLabel, ICON_SVG$1, L.title);
|
|
7451
7393
|
const urlLabel = createElement("label", { class: "an-label" });
|
|
7452
7394
|
urlLabel.textContent = L.videoUrl;
|
|
7453
7395
|
const urlInput = createElement("input", {
|
|
@@ -7457,6 +7399,7 @@
|
|
|
7457
7399
|
autocomplete: "off"
|
|
7458
7400
|
});
|
|
7459
7401
|
this._urlInput = urlInput;
|
|
7402
|
+
this._firstInput = urlInput;
|
|
7460
7403
|
const hintEl = createElement("p", { class: "an-dialog-hint" });
|
|
7461
7404
|
this._hintEl = hintEl;
|
|
7462
7405
|
const widthLabel = createElement("label", { class: "an-label" });
|
|
@@ -7470,38 +7413,19 @@
|
|
|
7470
7413
|
value: "560"
|
|
7471
7414
|
});
|
|
7472
7415
|
this._widthInput = widthInput;
|
|
7473
|
-
const btnRow =
|
|
7474
|
-
|
|
7475
|
-
type: "button",
|
|
7476
|
-
class: "an-btn an-btn-primary"
|
|
7477
|
-
});
|
|
7478
|
-
insertBtn.textContent = L.insertBtn;
|
|
7479
|
-
const cancelBtn = createElement("button", {
|
|
7480
|
-
type: "button",
|
|
7481
|
-
class: "an-btn"
|
|
7482
|
-
});
|
|
7483
|
-
cancelBtn.textContent = L.cancelBtn;
|
|
7484
|
-
btnRow.appendChild(insertBtn);
|
|
7485
|
-
btnRow.appendChild(cancelBtn);
|
|
7486
|
-
box.append(header, urlLabel, urlInput, hintEl, widthLabel, widthInput, btnRow);
|
|
7487
|
-
overlay.appendChild(box);
|
|
7488
|
-
makeDraggable(header, box);
|
|
7416
|
+
const btnRow = this._buildButtonRow(L.insertBtn, L.cancelBtn, () => this._onInsert());
|
|
7417
|
+
box.append(urlLabel, urlInput, hintEl, widthLabel, widthInput, btnRow);
|
|
7489
7418
|
const d0 = on(urlInput, "input", () => {
|
|
7490
7419
|
const info = this._parseVideoUrl(urlInput.value.trim());
|
|
7491
7420
|
hintEl.textContent = info ? this.context.locale.videoDialog.detected(info.type) : urlInput.value ? this.context.locale.videoDialog.unknownFormat : "";
|
|
7492
7421
|
});
|
|
7493
|
-
const d1 = on(insertBtn, "click", () => this._onInsert());
|
|
7494
|
-
const d2 = on(cancelBtn, "click", () => this._close());
|
|
7495
|
-
const d3 = on(overlay, "click", (e) => {
|
|
7496
|
-
if (e.target === overlay) this._close();
|
|
7497
|
-
});
|
|
7498
7422
|
const d4 = on(urlInput, "keydown", (e) => {
|
|
7499
7423
|
if (e.key === "Enter") {
|
|
7500
7424
|
e.preventDefault();
|
|
7501
7425
|
this._onInsert();
|
|
7502
7426
|
}
|
|
7503
7427
|
});
|
|
7504
|
-
this._disposers.push(d0,
|
|
7428
|
+
this._disposers.push(d0, d4);
|
|
7505
7429
|
return overlay;
|
|
7506
7430
|
}
|
|
7507
7431
|
_onInsert() {
|
|
@@ -7521,21 +7445,6 @@
|
|
|
7521
7445
|
this.context.invoke("editor.insertVideo", html);
|
|
7522
7446
|
this._close();
|
|
7523
7447
|
}
|
|
7524
|
-
_open() {
|
|
7525
|
-
if (this._dialog) {
|
|
7526
|
-
this._dialog.style.display = "flex";
|
|
7527
|
-
this._removeTrap = trapFocus(this._dialog, () => this._close());
|
|
7528
|
-
setTimeout(() => this._urlInput && this._urlInput.focus(), 50);
|
|
7529
|
-
}
|
|
7530
|
-
}
|
|
7531
|
-
_close() {
|
|
7532
|
-
if (this._dialog) this._dialog.style.display = "none";
|
|
7533
|
-
if (this._removeTrap) {
|
|
7534
|
-
this._removeTrap();
|
|
7535
|
-
this._removeTrap = null;
|
|
7536
|
-
}
|
|
7537
|
-
this._savedRange = null;
|
|
7538
|
-
}
|
|
7539
7448
|
/**
|
|
7540
7449
|
* Parses a video URL and returns { type, embedUrl } or null.
|
|
7541
7450
|
* @param {string} url
|
|
@@ -12443,35 +12352,17 @@
|
|
|
12443
12352
|
"symbols"
|
|
12444
12353
|
]
|
|
12445
12354
|
];
|
|
12446
|
-
var EmojiDialog = class {
|
|
12447
|
-
|
|
12448
|
-
* @param {import('../Context.js').Context} context
|
|
12449
|
-
*/
|
|
12450
|
-
constructor(context) {
|
|
12451
|
-
this.context = context;
|
|
12452
|
-
/** @type {HTMLElement|null} */
|
|
12453
|
-
this._dialog = null;
|
|
12454
|
-
this._disposers = [];
|
|
12455
|
-
this._savedRange = null;
|
|
12456
|
-
this._activeCat = "all";
|
|
12457
|
-
}
|
|
12355
|
+
var EmojiDialog = class extends BaseDialog {
|
|
12356
|
+
_activeCat = "all";
|
|
12458
12357
|
initialize() {
|
|
12459
12358
|
return this;
|
|
12460
12359
|
}
|
|
12461
|
-
destroy() {
|
|
12462
|
-
this._disposers.forEach((d) => d());
|
|
12463
|
-
this._disposers = [];
|
|
12464
|
-
if (this._dialog && this._dialog.parentNode) this._dialog.remove();
|
|
12465
|
-
this._dialog = null;
|
|
12466
|
-
}
|
|
12467
12360
|
show() {
|
|
12468
12361
|
if (!this._dialog) {
|
|
12469
12362
|
this._dialog = this._buildDialog();
|
|
12470
12363
|
document.body.appendChild(this._dialog);
|
|
12471
12364
|
}
|
|
12472
|
-
|
|
12473
|
-
this._savedRange = range;
|
|
12474
|
-
});
|
|
12365
|
+
this._saveRange();
|
|
12475
12366
|
this._activeCat = "all";
|
|
12476
12367
|
this._searchInput.value = "";
|
|
12477
12368
|
this._updateCatTabs();
|
|
@@ -12540,6 +12431,7 @@
|
|
|
12540
12431
|
grid.appendChild(cell);
|
|
12541
12432
|
});
|
|
12542
12433
|
this._grid = grid;
|
|
12434
|
+
this._firstInput = searchInput;
|
|
12543
12435
|
const btnRow = createElement("div", { class: "an-dialog-actions" });
|
|
12544
12436
|
const cancelBtn = createElement("button", {
|
|
12545
12437
|
type: "button",
|
|
@@ -12629,21 +12521,6 @@
|
|
|
12629
12521
|
editable.focus();
|
|
12630
12522
|
this.context.invoke("editor.afterCommand");
|
|
12631
12523
|
}
|
|
12632
|
-
_open() {
|
|
12633
|
-
if (this._dialog) {
|
|
12634
|
-
this._dialog.style.display = "flex";
|
|
12635
|
-
this._removeTrap = trapFocus(this._dialog, () => this._close());
|
|
12636
|
-
setTimeout(() => this._searchInput?.focus(), 50);
|
|
12637
|
-
}
|
|
12638
|
-
}
|
|
12639
|
-
_close() {
|
|
12640
|
-
if (this._dialog) this._dialog.style.display = "none";
|
|
12641
|
-
if (this._removeTrap) {
|
|
12642
|
-
this._removeTrap();
|
|
12643
|
-
this._removeTrap = null;
|
|
12644
|
-
}
|
|
12645
|
-
this._savedRange = null;
|
|
12646
|
-
}
|
|
12647
12524
|
};
|
|
12648
12525
|
//#endregion
|
|
12649
12526
|
//#region src/js/module/IconDialog.js
|
|
@@ -12901,19 +12778,9 @@
|
|
|
12901
12778
|
["gift", "objects"],
|
|
12902
12779
|
["puzzle-piece", "objects"]
|
|
12903
12780
|
];
|
|
12904
|
-
var IconDialog = class {
|
|
12905
|
-
|
|
12906
|
-
|
|
12907
|
-
*/
|
|
12908
|
-
constructor(context) {
|
|
12909
|
-
this.context = context;
|
|
12910
|
-
/** @type {HTMLElement|null} */
|
|
12911
|
-
this._dialog = null;
|
|
12912
|
-
this._disposers = [];
|
|
12913
|
-
this._savedRange = null;
|
|
12914
|
-
this._selectedIcon = null;
|
|
12915
|
-
this._activeCat = "all";
|
|
12916
|
-
}
|
|
12781
|
+
var IconDialog = class extends BaseDialog {
|
|
12782
|
+
_selectedIcon = null;
|
|
12783
|
+
_activeCat = "all";
|
|
12917
12784
|
initialize() {
|
|
12918
12785
|
this._ensureFontAwesome();
|
|
12919
12786
|
return this;
|
|
@@ -12937,20 +12804,12 @@
|
|
|
12937
12804
|
link.referrerPolicy = "no-referrer";
|
|
12938
12805
|
document.head.appendChild(link);
|
|
12939
12806
|
}
|
|
12940
|
-
destroy() {
|
|
12941
|
-
this._disposers.forEach((d) => d());
|
|
12942
|
-
this._disposers = [];
|
|
12943
|
-
this._dialog?.remove();
|
|
12944
|
-
this._dialog = null;
|
|
12945
|
-
}
|
|
12946
12807
|
show() {
|
|
12947
12808
|
if (!this._dialog) {
|
|
12948
12809
|
this._dialog = this._buildDialog();
|
|
12949
12810
|
document.body.appendChild(this._dialog);
|
|
12950
12811
|
}
|
|
12951
|
-
|
|
12952
|
-
this._savedRange = range;
|
|
12953
|
-
});
|
|
12812
|
+
this._saveRange();
|
|
12954
12813
|
this._selectedIcon = null;
|
|
12955
12814
|
this._activeCat = "all";
|
|
12956
12815
|
this._searchInput.value = "";
|
|
@@ -12991,6 +12850,7 @@
|
|
|
12991
12850
|
autocomplete: "off"
|
|
12992
12851
|
});
|
|
12993
12852
|
this._searchInput = searchInput;
|
|
12853
|
+
this._firstInput = searchInput;
|
|
12994
12854
|
const catBar = createElement("div", { class: "an-icon-cats" });
|
|
12995
12855
|
const allTab = createElement("button", {
|
|
12996
12856
|
type: "button",
|
|
@@ -13229,21 +13089,9 @@
|
|
|
13229
13089
|
}
|
|
13230
13090
|
this.context.invoke("editor.afterCommand");
|
|
13231
13091
|
}
|
|
13232
|
-
_open() {
|
|
13233
|
-
if (this._dialog) {
|
|
13234
|
-
this._dialog.style.display = "flex";
|
|
13235
|
-
this._removeTrap = trapFocus(this._dialog, () => this._close());
|
|
13236
|
-
setTimeout(() => this._searchInput?.focus(), 50);
|
|
13237
|
-
}
|
|
13238
|
-
}
|
|
13239
13092
|
_close() {
|
|
13240
|
-
if (this._dialog) this._dialog.style.display = "none";
|
|
13241
|
-
if (this._removeTrap) {
|
|
13242
|
-
this._removeTrap();
|
|
13243
|
-
this._removeTrap = null;
|
|
13244
|
-
}
|
|
13245
|
-
this._savedRange = null;
|
|
13246
13093
|
this._selectedIcon = null;
|
|
13094
|
+
super._close();
|
|
13247
13095
|
}
|
|
13248
13096
|
};
|
|
13249
13097
|
//#endregion
|
|
@@ -13984,59 +13832,25 @@
|
|
|
13984
13832
|
}]
|
|
13985
13833
|
}
|
|
13986
13834
|
];
|
|
13987
|
-
var
|
|
13988
|
-
|
|
13989
|
-
constructor(context) {
|
|
13990
|
-
this.context = context;
|
|
13991
|
-
this._dialog = null;
|
|
13992
|
-
this._closeBtn = null;
|
|
13993
|
-
this._disposers = [];
|
|
13994
|
-
}
|
|
13995
|
-
initialize() {
|
|
13996
|
-
this._dialog = this._buildDialog();
|
|
13997
|
-
document.body.appendChild(this._dialog);
|
|
13998
|
-
return this;
|
|
13999
|
-
}
|
|
14000
|
-
destroy() {
|
|
14001
|
-
this._disposers.forEach((d) => d());
|
|
14002
|
-
this._disposers = [];
|
|
14003
|
-
this._dialog?.remove();
|
|
14004
|
-
this._dialog = null;
|
|
14005
|
-
}
|
|
13835
|
+
var ICON_SVG = `<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="7" width="20" height="14" rx="2"/><path d="M6 11h.01M10 11h.01M14 11h.01M18 11h.01M6 15h.01M18 15h.01M10 15h4"/><path d="M7 3l5 4 5-4"/></svg>`;
|
|
13836
|
+
var ShortcutsDialog = class extends BaseDialog {
|
|
14006
13837
|
show() {
|
|
14007
|
-
|
|
14008
|
-
this._dialog.style.display = "flex";
|
|
14009
|
-
this._removeTrap = trapFocus(this._dialog, () => this._close());
|
|
14010
|
-
setTimeout(() => this._closeBtn?.focus(), 50);
|
|
14011
|
-
}
|
|
14012
|
-
}
|
|
14013
|
-
_close() {
|
|
14014
|
-
if (this._dialog) this._dialog.style.display = "none";
|
|
14015
|
-
if (this._removeTrap) {
|
|
14016
|
-
this._removeTrap();
|
|
14017
|
-
this._removeTrap = null;
|
|
14018
|
-
}
|
|
13838
|
+
this._open();
|
|
14019
13839
|
}
|
|
14020
13840
|
_buildDialog() {
|
|
14021
|
-
const
|
|
14022
|
-
|
|
14023
|
-
|
|
14024
|
-
"aria-modal": "true",
|
|
14025
|
-
"aria-label": this.context.locale.shortcutsDialog.ariaLabel
|
|
14026
|
-
});
|
|
14027
|
-
const box = createElement("div", { class: "an-dialog-box an-shortcuts-box" });
|
|
14028
|
-
const titleRow = createElement("div", { class: "an-icon-title-row" });
|
|
14029
|
-
const title = createElement("h3", { class: "an-dialog-title" });
|
|
14030
|
-
title.textContent = this.context.locale.shortcutsDialog.title;
|
|
13841
|
+
const L = this.context.locale.shortcutsDialog;
|
|
13842
|
+
const { overlay, box } = this._buildDialogShell(L.ariaLabel, ICON_SVG, L.title);
|
|
13843
|
+
box.classList.add("an-shortcuts-box");
|
|
14031
13844
|
const closeBtn = createElement("button", {
|
|
14032
13845
|
type: "button",
|
|
14033
13846
|
class: "an-icon-close",
|
|
14034
|
-
"aria-label":
|
|
13847
|
+
"aria-label": L.close,
|
|
13848
|
+
style: "margin-left:auto"
|
|
14035
13849
|
});
|
|
14036
13850
|
closeBtn.textContent = "×";
|
|
14037
13851
|
this._closeBtn = closeBtn;
|
|
14038
|
-
|
|
14039
|
-
box.appendChild(
|
|
13852
|
+
this._firstInput = closeBtn;
|
|
13853
|
+
box.querySelector(".an-dialog-header").appendChild(closeBtn);
|
|
14040
13854
|
(this.context.locale.shortcutsDialog.shortcuts || SHORTCUTS).forEach(({ category, items }) => {
|
|
14041
13855
|
const catEl = createElement("div", { class: "an-shortcuts-cat" });
|
|
14042
13856
|
catEl.textContent = category;
|
|
@@ -14053,12 +13867,8 @@
|
|
|
14053
13867
|
});
|
|
14054
13868
|
box.appendChild(table);
|
|
14055
13869
|
});
|
|
14056
|
-
overlay.appendChild(box);
|
|
14057
13870
|
const d1 = on(closeBtn, "click", () => this._close());
|
|
14058
|
-
|
|
14059
|
-
if (e.target === overlay) this._close();
|
|
14060
|
-
});
|
|
14061
|
-
this._disposers.push(d1, d2);
|
|
13871
|
+
this._disposers.push(d1);
|
|
14062
13872
|
return overlay;
|
|
14063
13873
|
}
|
|
14064
13874
|
};
|
|
@@ -14072,12 +13882,10 @@
|
|
|
14072
13882
|
* for highlighting. Supports case-sensitive search, Prev/Next navigation and
|
|
14073
13883
|
* single / replace-all replacement.
|
|
14074
13884
|
*/
|
|
14075
|
-
var FindReplace = class {
|
|
13885
|
+
var FindReplace = class extends BaseDialog {
|
|
14076
13886
|
/** @param {import('../Context.js').Context} context */
|
|
14077
13887
|
constructor(context) {
|
|
14078
|
-
|
|
14079
|
-
/** @type {HTMLElement|null} */
|
|
14080
|
-
this._dialog = null;
|
|
13888
|
+
super(context);
|
|
14081
13889
|
/** @type {HTMLInputElement|null} */
|
|
14082
13890
|
this._findInput = null;
|
|
14083
13891
|
/** @type {HTMLInputElement|null} */
|
|
@@ -14098,23 +13906,13 @@
|
|
|
14098
13906
|
this._queryRegex = null;
|
|
14099
13907
|
this._lastQuery = null;
|
|
14100
13908
|
this._lastCaseSensitive = null;
|
|
14101
|
-
this._disposers = [];
|
|
14102
|
-
this._removeTrap = null;
|
|
14103
13909
|
this._focusTimer = null;
|
|
14104
13910
|
}
|
|
14105
|
-
initialize() {
|
|
14106
|
-
this._dialog = this._buildDialog();
|
|
14107
|
-
document.body.appendChild(this._dialog);
|
|
14108
|
-
return this;
|
|
14109
|
-
}
|
|
14110
13911
|
destroy() {
|
|
14111
13912
|
clearTimeout(this._focusTimer);
|
|
14112
13913
|
this._focusTimer = null;
|
|
14113
13914
|
this._clearHighlights();
|
|
14114
|
-
|
|
14115
|
-
this._disposers = [];
|
|
14116
|
-
if (this._dialog && this._dialog.parentNode) this._dialog.remove();
|
|
14117
|
-
this._dialog = null;
|
|
13915
|
+
super.destroy();
|
|
14118
13916
|
}
|
|
14119
13917
|
/**
|
|
14120
13918
|
* Opens the dialog in 'find' or 'replace' mode.
|
|
@@ -16029,7 +15827,7 @@
|
|
|
16029
15827
|
register("markdownShortcuts", MarkdownShortcuts);
|
|
16030
15828
|
register("bubbleToolbar", BubbleToolbar);
|
|
16031
15829
|
register("mention", Mention);
|
|
16032
|
-
for (const [name, ModuleClass] of _customModules) register(name, ModuleClass);
|
|
15830
|
+
if (_customModules.size > 0) for (const [name, ModuleClass] of _customModules) register(name, ModuleClass);
|
|
16033
15831
|
}
|
|
16034
15832
|
/**
|
|
16035
15833
|
* Registers and initialises a custom module on this instance.
|
|
@@ -16082,6 +15880,7 @@
|
|
|
16082
15880
|
});
|
|
16083
15881
|
}
|
|
16084
15882
|
_applyGlobalPlugins() {
|
|
15883
|
+
if (_globalPlugins.size === 0) return;
|
|
16085
15884
|
for (const { plugin, options } of _globalPlugins.values()) this._installPlugin(plugin, options);
|
|
16086
15885
|
}
|
|
16087
15886
|
_bindEditorEvents(editable) {
|
|
@@ -16478,7 +16277,7 @@
|
|
|
16478
16277
|
return this;
|
|
16479
16278
|
},
|
|
16480
16279
|
/** Library version */
|
|
16481
|
-
version: "1.
|
|
16280
|
+
version: "1.6.3"
|
|
16482
16281
|
};
|
|
16483
16282
|
/**
|
|
16484
16283
|
* @param {string|Element|NodeList|Element[]} selector
|