autumnnote 1.0.8 → 1.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +331 -637
- package/dist/autumnnote.es.js +2865 -158
- package/dist/autumnnote.es.js.map +1 -1
- package/dist/autumnnote.umd.js +2864 -157
- package/dist/autumnnote.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/js/Context.js +4 -0
- package/src/js/i18n/de.js +320 -0
- package/src/js/i18n/en.js +328 -0
- package/src/js/i18n/es.js +320 -0
- package/src/js/i18n/fr.js +321 -0
- package/src/js/i18n/index.js +59 -0
- package/src/js/i18n/ja.js +321 -0
- package/src/js/i18n/ko.js +320 -0
- package/src/js/i18n/vi.js +321 -0
- package/src/js/i18n/zh.js +321 -0
- package/src/js/index.js +2 -1
- package/src/js/module/CodeTooltip.js +12 -9
- package/src/js/module/ContextMenu.js +13 -11
- package/src/js/module/EmojiDialog.js +8 -7
- package/src/js/module/FindReplace.js +14 -13
- package/src/js/module/IconDialog.js +14 -13
- package/src/js/module/ImageDialog.js +17 -16
- package/src/js/module/ImageTooltip.js +13 -12
- package/src/js/module/LinkDialog.js +10 -9
- package/src/js/module/LinkTooltip.js +6 -5
- package/src/js/module/ShortcutsDialog.js +5 -4
- package/src/js/module/Statusbar.js +6 -5
- package/src/js/module/TableTooltip.js +22 -19
- package/src/js/module/Toolbar.js +21 -15
- package/src/js/module/VideoDialog.js +10 -9
- package/src/js/module/VideoTooltip.js +12 -11
- package/src/js/settings.js +4 -0
- package/types/index.d.ts +58 -1
|
@@ -63,7 +63,8 @@ export class LinkTooltip {
|
|
|
63
63
|
// ---------------------------------------------------------------------------
|
|
64
64
|
|
|
65
65
|
_buildTooltip() {
|
|
66
|
-
const
|
|
66
|
+
const L = this.context.locale.tooltips.link;
|
|
67
|
+
const el = createElement('div', { class: 'an-link-tooltip', role: 'toolbar', 'aria-label': L.ariaLabel });
|
|
67
68
|
el.style.display = 'none';
|
|
68
69
|
|
|
69
70
|
// URL preview text (truncated)
|
|
@@ -74,10 +75,10 @@ export class LinkTooltip {
|
|
|
74
75
|
el.appendChild(createElement('div', { class: 'an-link-tooltip-sep' }));
|
|
75
76
|
|
|
76
77
|
// Action buttons
|
|
77
|
-
this._openBtn = this._makeBtn(ICONS.open,
|
|
78
|
-
this._copyBtn = this._makeBtn(ICONS.copy,
|
|
79
|
-
this._editBtn = this._makeBtn(ICONS.edit,
|
|
80
|
-
this._unlinkBtn = this._makeBtn(ICONS.unlink,
|
|
78
|
+
this._openBtn = this._makeBtn(ICONS.open, L.openLink, () => this._openLink());
|
|
79
|
+
this._copyBtn = this._makeBtn(ICONS.copy, L.copyUrl, () => this._copyLink());
|
|
80
|
+
this._editBtn = this._makeBtn(ICONS.edit, L.editLink, () => this._editLink());
|
|
81
|
+
this._unlinkBtn = this._makeBtn(ICONS.unlink, L.removeLink, () => this._unlink());
|
|
81
82
|
|
|
82
83
|
el.appendChild(this._openBtn);
|
|
83
84
|
el.appendChild(this._copyBtn);
|
|
@@ -93,7 +93,7 @@ export class ShortcutsDialog {
|
|
|
93
93
|
class: 'an-dialog-overlay',
|
|
94
94
|
role: 'dialog',
|
|
95
95
|
'aria-modal': 'true',
|
|
96
|
-
'aria-label':
|
|
96
|
+
'aria-label': this.context.locale.shortcutsDialog.ariaLabel,
|
|
97
97
|
});
|
|
98
98
|
|
|
99
99
|
const box = createElement('div', { class: 'an-dialog-box an-shortcuts-box' });
|
|
@@ -101,18 +101,19 @@ export class ShortcutsDialog {
|
|
|
101
101
|
// Title row with close button
|
|
102
102
|
const titleRow = createElement('div', { class: 'an-icon-title-row' });
|
|
103
103
|
const title = createElement('h3', { class: 'an-dialog-title' });
|
|
104
|
-
title.textContent =
|
|
104
|
+
title.textContent = this.context.locale.shortcutsDialog.title;
|
|
105
105
|
const closeBtn = createElement('button', {
|
|
106
106
|
type: 'button',
|
|
107
107
|
class: 'an-icon-close',
|
|
108
|
-
'aria-label':
|
|
108
|
+
'aria-label': this.context.locale.shortcutsDialog.close,
|
|
109
109
|
});
|
|
110
110
|
closeBtn.textContent = '×';
|
|
111
111
|
this._closeBtn = closeBtn;
|
|
112
112
|
titleRow.append(title, closeBtn);
|
|
113
113
|
box.appendChild(titleRow);
|
|
114
114
|
|
|
115
|
-
|
|
115
|
+
const shortcuts = this.context.locale.shortcutsDialog.shortcuts || SHORTCUTS;
|
|
116
|
+
shortcuts.forEach(({ category, items }) => {
|
|
116
117
|
const catEl = createElement('div', { class: 'an-shortcuts-cat' });
|
|
117
118
|
catEl.textContent = category;
|
|
118
119
|
box.appendChild(catEl);
|
|
@@ -82,7 +82,7 @@ export class Statusbar {
|
|
|
82
82
|
if (this.options.resizable !== false) {
|
|
83
83
|
const handle = createElement('div', {
|
|
84
84
|
class: 'an-resize-handle',
|
|
85
|
-
title:
|
|
85
|
+
title: this.context.locale.statusbar.resizeHandle,
|
|
86
86
|
'aria-hidden': 'true',
|
|
87
87
|
});
|
|
88
88
|
this._bindResize(handle);
|
|
@@ -220,12 +220,13 @@ export class Statusbar {
|
|
|
220
220
|
const maxWords = this.options.maxWords || 0;
|
|
221
221
|
const maxChars = this.options.maxChars || 0;
|
|
222
222
|
|
|
223
|
+
const LS = this.context.locale.statusbar;
|
|
223
224
|
this._wordCountEl.textContent = maxWords
|
|
224
|
-
?
|
|
225
|
-
:
|
|
225
|
+
? LS.wordsLimit(words, maxWords)
|
|
226
|
+
: LS.words(words);
|
|
226
227
|
this._charCountEl.textContent = maxChars
|
|
227
|
-
?
|
|
228
|
-
:
|
|
228
|
+
? LS.charsLimit(chars, maxChars)
|
|
229
|
+
: LS.chars(chars);
|
|
229
230
|
|
|
230
231
|
// Apply warning / exceeded styles
|
|
231
232
|
_applyLimitClass(this._wordCountEl, words, maxWords);
|
|
@@ -376,55 +376,56 @@ export class TableTooltip {
|
|
|
376
376
|
// ---------------------------------------------------------------------------
|
|
377
377
|
|
|
378
378
|
_buildTooltip() {
|
|
379
|
+
const L = this.context.locale.tooltips.table;
|
|
379
380
|
const el = createElement('div', {
|
|
380
381
|
class: 'an-link-tooltip an-table-tooltip',
|
|
381
382
|
role: 'toolbar',
|
|
382
|
-
'aria-label':
|
|
383
|
+
'aria-label': L.ariaLabel,
|
|
383
384
|
});
|
|
384
385
|
el.style.display = 'none';
|
|
385
386
|
|
|
386
387
|
// Label
|
|
387
388
|
this._label = createElement('span', { class: 'an-link-tooltip-url' });
|
|
388
|
-
this._label.textContent =
|
|
389
|
+
this._label.textContent = L.label;
|
|
389
390
|
el.appendChild(this._label);
|
|
390
391
|
|
|
391
392
|
el.appendChild(this._sep());
|
|
392
393
|
|
|
393
394
|
// Select-cells toggle
|
|
394
|
-
this._selectBtn = this._makeBtn(ICONS.selectCells,
|
|
395
|
+
this._selectBtn = this._makeBtn(ICONS.selectCells, L.selectCells, () => this._toggleSelectMode());
|
|
395
396
|
el.appendChild(this._selectBtn);
|
|
396
397
|
|
|
397
398
|
el.appendChild(this._sep());
|
|
398
399
|
|
|
399
400
|
// Row operations
|
|
400
|
-
el.appendChild(this._makeBtn(ICONS.rowAbove,
|
|
401
|
-
el.appendChild(this._makeBtn(ICONS.rowBelow,
|
|
402
|
-
el.appendChild(this._makeBtn(ICONS.deleteRow,
|
|
401
|
+
el.appendChild(this._makeBtn(ICONS.rowAbove, L.addRowAbove, () => this._addRow('above')));
|
|
402
|
+
el.appendChild(this._makeBtn(ICONS.rowBelow, L.addRowBelow, () => this._addRow('below')));
|
|
403
|
+
el.appendChild(this._makeBtn(ICONS.deleteRow, L.deleteRow, () => this._deleteRow()));
|
|
403
404
|
|
|
404
405
|
el.appendChild(this._sep());
|
|
405
406
|
|
|
406
407
|
// Column operations
|
|
407
|
-
el.appendChild(this._makeBtn(ICONS.colLeft,
|
|
408
|
-
el.appendChild(this._makeBtn(ICONS.colRight,
|
|
409
|
-
el.appendChild(this._makeBtn(ICONS.deleteCol,
|
|
408
|
+
el.appendChild(this._makeBtn(ICONS.colLeft, L.addColumnLeft, () => this._addColumn('left')));
|
|
409
|
+
el.appendChild(this._makeBtn(ICONS.colRight, L.addColumnRight, () => this._addColumn('right')));
|
|
410
|
+
el.appendChild(this._makeBtn(ICONS.deleteCol, L.deleteColumn, () => this._deleteColumn()));
|
|
410
411
|
|
|
411
412
|
el.appendChild(this._sep());
|
|
412
413
|
|
|
413
414
|
// Merge cells
|
|
414
|
-
el.appendChild(this._makeBtn(ICONS.mergeCells,
|
|
415
|
-
el.appendChild(this._makeBtn(ICONS.unmergeCells,
|
|
415
|
+
el.appendChild(this._makeBtn(ICONS.mergeCells, L.mergeCells, () => this._mergeCells()));
|
|
416
|
+
el.appendChild(this._makeBtn(ICONS.unmergeCells, L.unmergeCells, () => this._unmergeCells()));
|
|
416
417
|
|
|
417
418
|
el.appendChild(this._sep());
|
|
418
419
|
|
|
419
420
|
// Resize
|
|
420
|
-
el.appendChild(this._makeBtn(ICONS.colWidth,
|
|
421
|
-
el.appendChild(this._makeBtn(ICONS.rowHeight,
|
|
422
|
-
el.appendChild(this._makeBtn(ICONS.tableBorder,
|
|
421
|
+
el.appendChild(this._makeBtn(ICONS.colWidth, L.columnWidth, () => this._openSizePopover('col')));
|
|
422
|
+
el.appendChild(this._makeBtn(ICONS.rowHeight, L.rowHeight, () => this._openSizePopover('row')));
|
|
423
|
+
el.appendChild(this._makeBtn(ICONS.tableBorder,L.tableBorderWidth, () => this._openSizePopover('border')));
|
|
423
424
|
|
|
424
425
|
el.appendChild(this._sep());
|
|
425
426
|
|
|
426
427
|
// Delete table (danger)
|
|
427
|
-
el.appendChild(this._makeBtn(ICONS.deleteTable,
|
|
428
|
+
el.appendChild(this._makeBtn(ICONS.deleteTable, L.deleteTable, () => this._deleteTable(), true));
|
|
428
429
|
|
|
429
430
|
// Keep tooltip alive while hovering.
|
|
430
431
|
// Don't schedule hide on mouseleave when the size popover is open —
|
|
@@ -909,9 +910,9 @@ export class TableTooltip {
|
|
|
909
910
|
|
|
910
911
|
const actionsEl = createElement('div', { class: 'an-size-popover-actions' });
|
|
911
912
|
const cancelBtn = createElement('button', { type: 'button', class: 'an-btn' });
|
|
912
|
-
cancelBtn.textContent =
|
|
913
|
+
cancelBtn.textContent = this.context.locale.tooltips.table.cancelBtn;
|
|
913
914
|
const applyBtn = createElement('button', { type: 'button', class: 'an-btn an-btn-primary' });
|
|
914
|
-
applyBtn.textContent =
|
|
915
|
+
applyBtn.textContent = this.context.locale.tooltips.table.applyBtn;
|
|
915
916
|
actionsEl.appendChild(cancelBtn);
|
|
916
917
|
actionsEl.appendChild(applyBtn);
|
|
917
918
|
|
|
@@ -960,7 +961,7 @@ export class TableTooltip {
|
|
|
960
961
|
? (parseInt(firstCell.style.borderWidth, 10) ||
|
|
961
962
|
parseInt(window.getComputedStyle(firstCell).borderWidth, 10) || 1)
|
|
962
963
|
: 1;
|
|
963
|
-
this._sizeTitleEl.textContent =
|
|
964
|
+
this._sizeTitleEl.textContent = this.context.locale.tooltips.table.tableBorderWidthPx;
|
|
964
965
|
this._sizeInputEl.min = '0';
|
|
965
966
|
this._sizeInputEl.max = '10';
|
|
966
967
|
this._sizeInputEl.value = currentPx;
|
|
@@ -979,7 +980,9 @@ export class TableTooltip {
|
|
|
979
980
|
const t = c.closest('table');
|
|
980
981
|
return t && t === cell.closest('table');
|
|
981
982
|
});
|
|
982
|
-
this._sizeTitleEl.textContent = isCol
|
|
983
|
+
this._sizeTitleEl.textContent = isCol
|
|
984
|
+
? this.context.locale.tooltips.table.columnWidthPx
|
|
985
|
+
: this.context.locale.tooltips.table.rowHeightPx;
|
|
983
986
|
this._sizeInputEl.min = '1';
|
|
984
987
|
this._sizeInputEl.max = '2000';
|
|
985
988
|
this._sizeInputEl.value = isCol
|
package/src/js/module/Toolbar.js
CHANGED
|
@@ -182,9 +182,9 @@ export class Toolbar {
|
|
|
182
182
|
const btn = createElement('button', {
|
|
183
183
|
type: 'button',
|
|
184
184
|
class: baseClass,
|
|
185
|
-
title: def.tooltip || '',
|
|
185
|
+
title: this.context.locale.toolbar[def.name] || def.tooltip || '',
|
|
186
186
|
'data-btn': def.name,
|
|
187
|
-
'aria-label': def.tooltip || def.name,
|
|
187
|
+
'aria-label': this.context.locale.toolbar[def.name] || def.tooltip || def.name,
|
|
188
188
|
'aria-haspopup': 'true',
|
|
189
189
|
'aria-expanded': 'false',
|
|
190
190
|
});
|
|
@@ -206,7 +206,7 @@ export class Toolbar {
|
|
|
206
206
|
});
|
|
207
207
|
const grid = createElement('div', { class: 'an-table-grid' });
|
|
208
208
|
const label = createElement('div', { class: 'an-table-label' });
|
|
209
|
-
label.textContent = 'Insert Table';
|
|
209
|
+
label.textContent = this.context.locale.toolbar.insertTableLabel || 'Insert Table';
|
|
210
210
|
|
|
211
211
|
const cells = [];
|
|
212
212
|
for (let r = 1; r <= ROWS; r++) {
|
|
@@ -232,7 +232,7 @@ export class Toolbar {
|
|
|
232
232
|
const c = +cell.getAttribute('data-col');
|
|
233
233
|
cell.classList.toggle('active', r <= rows && c <= cols);
|
|
234
234
|
});
|
|
235
|
-
label.textContent = (rows && cols) ? `${rows} × ${cols}` : 'Insert Table';
|
|
235
|
+
label.textContent = (rows && cols) ? `${rows} × ${cols}` : (this.context.locale.toolbar.insertTableLabel || 'Insert Table');
|
|
236
236
|
};
|
|
237
237
|
|
|
238
238
|
const openPopup = () => {
|
|
@@ -307,9 +307,9 @@ export class Toolbar {
|
|
|
307
307
|
const applyBtn = createElement('button', {
|
|
308
308
|
type: 'button',
|
|
309
309
|
class: `${baseClass} an-color-btn`,
|
|
310
|
-
title: def.tooltip || '',
|
|
310
|
+
title: this.context.locale.toolbar[def.name] || def.tooltip || '',
|
|
311
311
|
'data-btn': def.name,
|
|
312
|
-
'aria-label': def.tooltip || def.name,
|
|
312
|
+
'aria-label': this.context.locale.toolbar[def.name] || def.tooltip || def.name,
|
|
313
313
|
});
|
|
314
314
|
|
|
315
315
|
const S = 'stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"';
|
|
@@ -326,7 +326,9 @@ export class Toolbar {
|
|
|
326
326
|
const arrowBtn = createElement('button', {
|
|
327
327
|
type: 'button',
|
|
328
328
|
class: `${baseClass} an-color-arrow`,
|
|
329
|
-
title:
|
|
329
|
+
title: def.name === 'foreColor'
|
|
330
|
+
? (this.context.locale.toolbar.chooseTextColor || 'Choose text color')
|
|
331
|
+
: (this.context.locale.toolbar.chooseHighlightColor || 'Choose highlight color'),
|
|
330
332
|
'aria-haspopup': 'true',
|
|
331
333
|
'aria-expanded': 'false',
|
|
332
334
|
});
|
|
@@ -346,8 +348,8 @@ export class Toolbar {
|
|
|
346
348
|
});
|
|
347
349
|
|
|
348
350
|
const customRow = createElement('div', { class: 'an-color-custom' });
|
|
349
|
-
const colorInput = createElement('input', { type: 'color', value: currentColor, title: 'Custom color' });
|
|
350
|
-
const customLabel = createElement('span', {}, ['Custom color']);
|
|
351
|
+
const colorInput = createElement('input', { type: 'color', value: currentColor, title: this.context.locale.toolbar.customColor || 'Custom color' });
|
|
352
|
+
const customLabel = createElement('span', {}, [this.context.locale.toolbar.customColor || 'Custom color']);
|
|
351
353
|
customRow.appendChild(colorInput);
|
|
352
354
|
customRow.appendChild(customLabel);
|
|
353
355
|
|
|
@@ -491,19 +493,23 @@ export class Toolbar {
|
|
|
491
493
|
const cls = def.selectClass ? `an-select ${def.selectClass}` : 'an-select';
|
|
492
494
|
const select = createElement('select', {
|
|
493
495
|
class: cls,
|
|
494
|
-
title: def.tooltip || '',
|
|
496
|
+
title: this.context.locale.toolbar[def.name] || def.tooltip || '',
|
|
495
497
|
'data-btn': def.name,
|
|
496
|
-
'aria-label': def.tooltip || def.name,
|
|
498
|
+
'aria-label': this.context.locale.toolbar[def.name] || def.tooltip || def.name,
|
|
497
499
|
});
|
|
498
500
|
|
|
499
501
|
// Blank "placeholder" option (non-selectable header)
|
|
500
|
-
const placeholderText = def.placeholder || 'Font';
|
|
502
|
+
const placeholderText = this.context.locale.toolbar[def.name + 'Placeholder'] || def.placeholder || 'Font';
|
|
501
503
|
const placeholder = createElement('option', { value: '', disabled: '', hidden: '' }, [placeholderText]);
|
|
502
504
|
select.appendChild(placeholder);
|
|
503
505
|
|
|
504
506
|
items.forEach((item) => {
|
|
505
507
|
const value = (typeof item === 'object') ? item.value : item;
|
|
506
|
-
const label = (typeof item === 'object')
|
|
508
|
+
const label = (typeof item === 'object')
|
|
509
|
+
? (def.name === 'paragraphStyle'
|
|
510
|
+
? ((this.context.locale.toolbar.paragraphItems || {})[item.value] || item.label)
|
|
511
|
+
: item.label)
|
|
512
|
+
: item;
|
|
507
513
|
const isHeader = (typeof item === 'object') && !!item.disabled;
|
|
508
514
|
const attrs = { value };
|
|
509
515
|
if (isHeader) attrs.disabled = '';
|
|
@@ -558,9 +564,9 @@ export class Toolbar {
|
|
|
558
564
|
const btn = createElement('button', {
|
|
559
565
|
type: 'button',
|
|
560
566
|
class: classAttr,
|
|
561
|
-
title: btnDef.tooltip || '',
|
|
567
|
+
title: this.context.locale.toolbar[btnDef.name] || btnDef.tooltip || '',
|
|
562
568
|
'data-btn': btnDef.name,
|
|
563
|
-
'aria-label': btnDef.tooltip || btnDef.name,
|
|
569
|
+
'aria-label': this.context.locale.toolbar[btnDef.name] || btnDef.tooltip || btnDef.name,
|
|
564
570
|
});
|
|
565
571
|
|
|
566
572
|
// Render icon: prefer FontAwesome if enabled; otherwise fall back to SVG or text.
|
|
@@ -59,24 +59,25 @@ export class VideoDialog {
|
|
|
59
59
|
// ---------------------------------------------------------------------------
|
|
60
60
|
|
|
61
61
|
_buildDialog() {
|
|
62
|
+
const L = this.context.locale.videoDialog;
|
|
62
63
|
const overlay = createElement('div', {
|
|
63
64
|
class: 'an-dialog-overlay',
|
|
64
65
|
role: 'dialog',
|
|
65
66
|
'aria-modal': 'true',
|
|
66
|
-
'aria-label':
|
|
67
|
+
'aria-label': L.ariaLabel,
|
|
67
68
|
});
|
|
68
69
|
const box = createElement('div', { class: 'an-dialog-box' });
|
|
69
70
|
|
|
70
71
|
const title = createElement('h3', { class: 'an-dialog-title' });
|
|
71
|
-
title.textContent =
|
|
72
|
+
title.textContent = L.title;
|
|
72
73
|
|
|
73
74
|
// URL input
|
|
74
75
|
const urlLabel = createElement('label', { class: 'an-label' });
|
|
75
|
-
urlLabel.textContent =
|
|
76
|
+
urlLabel.textContent = L.videoUrl;
|
|
76
77
|
const urlInput = /** @type {HTMLInputElement} */ (createElement('input', {
|
|
77
78
|
type: 'url',
|
|
78
79
|
class: 'an-input',
|
|
79
|
-
placeholder:
|
|
80
|
+
placeholder: L.urlPlaceholder,
|
|
80
81
|
autocomplete: 'off',
|
|
81
82
|
}));
|
|
82
83
|
this._urlInput = urlInput;
|
|
@@ -87,7 +88,7 @@ export class VideoDialog {
|
|
|
87
88
|
|
|
88
89
|
// Width
|
|
89
90
|
const widthLabel = createElement('label', { class: 'an-label' });
|
|
90
|
-
widthLabel.textContent =
|
|
91
|
+
widthLabel.textContent = L.widthLabel;
|
|
91
92
|
const widthInput = /** @type {HTMLInputElement} */ (createElement('input', {
|
|
92
93
|
type: 'number',
|
|
93
94
|
class: 'an-input',
|
|
@@ -101,9 +102,9 @@ export class VideoDialog {
|
|
|
101
102
|
// Buttons
|
|
102
103
|
const btnRow = createElement('div', { class: 'an-dialog-actions' });
|
|
103
104
|
const insertBtn = createElement('button', { type: 'button', class: 'an-btn an-btn-primary' });
|
|
104
|
-
insertBtn.textContent =
|
|
105
|
+
insertBtn.textContent = L.insertBtn;
|
|
105
106
|
const cancelBtn = createElement('button', { type: 'button', class: 'an-btn' });
|
|
106
|
-
cancelBtn.textContent =
|
|
107
|
+
cancelBtn.textContent = L.cancelBtn;
|
|
107
108
|
btnRow.appendChild(insertBtn);
|
|
108
109
|
btnRow.appendChild(cancelBtn);
|
|
109
110
|
|
|
@@ -113,7 +114,7 @@ export class VideoDialog {
|
|
|
113
114
|
// Live URL hint
|
|
114
115
|
const d0 = on(urlInput, 'input', () => {
|
|
115
116
|
const info = this._parseVideoUrl(urlInput.value.trim());
|
|
116
|
-
hintEl.textContent = info ?
|
|
117
|
+
hintEl.textContent = info ? this.context.locale.videoDialog.detected(info.type) : (urlInput.value ? this.context.locale.videoDialog.unknownFormat : '');
|
|
117
118
|
});
|
|
118
119
|
|
|
119
120
|
const d1 = on(insertBtn, 'click', () => this._onInsert());
|
|
@@ -140,7 +141,7 @@ export class VideoDialog {
|
|
|
140
141
|
|
|
141
142
|
const html = this._buildEmbedHtml(rawUrl, width);
|
|
142
143
|
if (!html) {
|
|
143
|
-
this._hintEl.textContent =
|
|
144
|
+
this._hintEl.textContent = this.context.locale.videoDialog.invalidUrl;
|
|
144
145
|
this._urlInput.focus();
|
|
145
146
|
return;
|
|
146
147
|
}
|
|
@@ -78,24 +78,25 @@ export class VideoTooltip {
|
|
|
78
78
|
// ---------------------------------------------------------------------------
|
|
79
79
|
|
|
80
80
|
_buildTooltip() {
|
|
81
|
+
const L = this.context.locale.tooltips.video;
|
|
81
82
|
const el = createElement('div', {
|
|
82
83
|
class: 'an-link-tooltip an-video-tooltip',
|
|
83
84
|
role: 'toolbar',
|
|
84
|
-
'aria-label':
|
|
85
|
+
'aria-label': L.ariaLabel,
|
|
85
86
|
});
|
|
86
87
|
el.style.display = 'none';
|
|
87
88
|
|
|
88
89
|
// Label
|
|
89
90
|
this._label = createElement('span', { class: 'an-link-tooltip-url' });
|
|
90
|
-
this._label.textContent =
|
|
91
|
+
this._label.textContent = L.label;
|
|
91
92
|
el.appendChild(this._label);
|
|
92
93
|
|
|
93
94
|
el.appendChild(createElement('div', { class: 'an-link-tooltip-sep' }));
|
|
94
95
|
|
|
95
|
-
this._floatLeftBtn = this._makeBtn(ICONS.floatLeft,
|
|
96
|
-
this._floatNoneBtn = this._makeBtn(ICONS.floatNone,
|
|
97
|
-
this._alignCenterBtn = this._makeBtn(ICONS.alignCenter,
|
|
98
|
-
this._floatRightBtn = this._makeBtn(ICONS.floatRight,
|
|
96
|
+
this._floatLeftBtn = this._makeBtn(ICONS.floatLeft, L.floatLeft, () => this._setFloat('left'));
|
|
97
|
+
this._floatNoneBtn = this._makeBtn(ICONS.floatNone, L.noFloat, () => this._setFloat(''));
|
|
98
|
+
this._alignCenterBtn = this._makeBtn(ICONS.alignCenter, L.alignCenter, () => this._setCenter());
|
|
99
|
+
this._floatRightBtn = this._makeBtn(ICONS.floatRight, L.floatRight, () => this._setFloat('right'));
|
|
99
100
|
|
|
100
101
|
el.appendChild(this._floatLeftBtn);
|
|
101
102
|
el.appendChild(this._floatNoneBtn);
|
|
@@ -104,18 +105,18 @@ export class VideoTooltip {
|
|
|
104
105
|
|
|
105
106
|
el.appendChild(createElement('div', { class: 'an-link-tooltip-sep' }));
|
|
106
107
|
|
|
107
|
-
this._originalBtn = this._makeBtn(ICONS.originalSize,
|
|
108
|
+
this._originalBtn = this._makeBtn(ICONS.originalSize, L.originalSize, () => this._resetSize());
|
|
108
109
|
|
|
109
110
|
el.appendChild(this._originalBtn);
|
|
110
111
|
|
|
111
112
|
el.appendChild(createElement('div', { class: 'an-link-tooltip-sep' }));
|
|
112
113
|
|
|
113
|
-
this._previewBtn = this._makeBtn(ICONS.preview,
|
|
114
|
+
this._previewBtn = this._makeBtn(ICONS.preview, L.previewVideo, () => this._togglePreview());
|
|
114
115
|
el.appendChild(this._previewBtn);
|
|
115
116
|
|
|
116
117
|
el.appendChild(createElement('div', { class: 'an-link-tooltip-sep' }));
|
|
117
118
|
|
|
118
|
-
this._deleteBtn = this._makeBtn(ICONS.deleteVideo,
|
|
119
|
+
this._deleteBtn = this._makeBtn(ICONS.deleteVideo, L.deleteVideo, () => this._delete(), true);
|
|
119
120
|
|
|
120
121
|
el.appendChild(this._deleteBtn);
|
|
121
122
|
|
|
@@ -292,7 +293,7 @@ export class VideoTooltip {
|
|
|
292
293
|
|
|
293
294
|
// Visual feedback: button turns primary-coloured
|
|
294
295
|
this._previewBtn.classList.add('an-link-tooltip-btn--copied');
|
|
295
|
-
this._previewBtn.title =
|
|
296
|
+
this._previewBtn.title = this.context.locale.tooltips.video.exitPreview;
|
|
296
297
|
|
|
297
298
|
// Exit preview on mousedown outside the wrapper.
|
|
298
299
|
// Using 'mousedown' (not 'click') so clicks inside an iframe
|
|
@@ -319,7 +320,7 @@ export class VideoTooltip {
|
|
|
319
320
|
|
|
320
321
|
// Reset button appearance
|
|
321
322
|
this._previewBtn.classList.remove('an-link-tooltip-btn--copied');
|
|
322
|
-
this._previewBtn.title =
|
|
323
|
+
this._previewBtn.title = this.context.locale.tooltips.video.previewVideo;
|
|
323
324
|
|
|
324
325
|
if (this._previewClickOff) {
|
|
325
326
|
document.removeEventListener('mousedown', this._previewClickOff, true);
|
package/src/js/settings.js
CHANGED
|
@@ -135,4 +135,8 @@ export const defaultOptions = {
|
|
|
135
135
|
// Custom focus ring colour — overrides the default blue when set.
|
|
136
136
|
// Accepts any valid CSS colour string, e.g. '#f97316', 'hsl(25,90%,55%)'.
|
|
137
137
|
focusColor: null,
|
|
138
|
+
// Display language for the editor UI.
|
|
139
|
+
// Built-in values: 'en' (default), 'vi', 'ja', 'zh', 'fr'.
|
|
140
|
+
// Pass a partial or full locale object to override individual strings.
|
|
141
|
+
lang: 'en',
|
|
138
142
|
};
|
package/types/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* AutumnNote – TypeScript declarations
|
|
3
|
-
* @version 1.0.
|
|
3
|
+
* @version 1.0.9
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
// ---------------------------------------------------------------------------
|
|
@@ -104,6 +104,12 @@ export interface AsnOptions {
|
|
|
104
104
|
onPaste?: (data: { text: string; html: string | null }) => void;
|
|
105
105
|
/** Additional color swatches shown at the top of the color picker. */
|
|
106
106
|
colorSwatches?: string[];
|
|
107
|
+
/**
|
|
108
|
+
* Display language for the editor UI.
|
|
109
|
+
* Built-in: 'en' (default) | 'vi' | 'ja' | 'zh' | 'fr'.
|
|
110
|
+
* Pass a partial locale object to override individual strings.
|
|
111
|
+
*/
|
|
112
|
+
lang?: string | Partial<AsnLocale>;
|
|
107
113
|
}
|
|
108
114
|
|
|
109
115
|
// ---------------------------------------------------------------------------
|
|
@@ -179,6 +185,57 @@ export type ToolbarItemDef = ButtonDef | DropdownDef | GridButtonDef | ColorPick
|
|
|
179
185
|
/** Runtime default options object (same export as `src/js/index.js`). */
|
|
180
186
|
export declare const defaultOptions: Required<AsnOptions>;
|
|
181
187
|
|
|
188
|
+
// ---------------------------------------------------------------------------
|
|
189
|
+
// Locale / i18n
|
|
190
|
+
// ---------------------------------------------------------------------------
|
|
191
|
+
|
|
192
|
+
/** Full locale object shape used by the editor. All leaf values are strings or template functions. */
|
|
193
|
+
export interface AsnLocale {
|
|
194
|
+
toolbar: Record<string, string | ((n: string | number) => string) | Record<string, string>>;
|
|
195
|
+
linkDialog: Record<string, string>;
|
|
196
|
+
imageDialog: Record<string, string>;
|
|
197
|
+
videoDialog: Record<string, string | ((type: string) => string)>;
|
|
198
|
+
emojiDialog: Record<string, string | Record<string, string>>;
|
|
199
|
+
iconDialog: Record<string, string | Record<string, string>>;
|
|
200
|
+
findReplace: Record<string, string>;
|
|
201
|
+
shortcutsDialog: {
|
|
202
|
+
title: string;
|
|
203
|
+
ariaLabel: string;
|
|
204
|
+
close: string;
|
|
205
|
+
shortcuts: Array<{ category: string; items: Array<{ keys: string; action: string }> }>;
|
|
206
|
+
};
|
|
207
|
+
contextMenu: Record<string, string>;
|
|
208
|
+
statusbar: {
|
|
209
|
+
resizeHandle: string;
|
|
210
|
+
words: (n: number) => string;
|
|
211
|
+
wordsLimit: (n: number, max: number) => string;
|
|
212
|
+
chars: (n: number) => string;
|
|
213
|
+
charsLimit: (n: number, max: number) => string;
|
|
214
|
+
};
|
|
215
|
+
tooltips: {
|
|
216
|
+
link: Record<string, string>;
|
|
217
|
+
image: Record<string, string>;
|
|
218
|
+
code: Record<string, string>;
|
|
219
|
+
table: Record<string, string>;
|
|
220
|
+
video: Record<string, string>;
|
|
221
|
+
};
|
|
222
|
+
errors: {
|
|
223
|
+
imageFormat: (type: string) => string;
|
|
224
|
+
imageSize: (maxMb: number) => string;
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/** Registry of all built-in locales (keys: 'en', 'vi', 'ja', 'zh', 'fr'). */
|
|
229
|
+
export declare const locales: Record<string, AsnLocale>;
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Resolves a lang value to a full AsnLocale.
|
|
233
|
+
* - string key → looks up locales registry, deep-merges with 'en' fallback.
|
|
234
|
+
* - object → deep-merges with 'en' as base.
|
|
235
|
+
* - falsy / 'en' → returns the canonical English locale.
|
|
236
|
+
*/
|
|
237
|
+
export declare function resolveLocale(lang: string | Partial<AsnLocale> | null | undefined): AsnLocale;
|
|
238
|
+
|
|
182
239
|
// Re-export core utility modules exposed by the package entry-point.
|
|
183
240
|
export * from '../src/js/core/dom.js';
|
|
184
241
|
export * from '../src/js/core/range.js';
|