autumnnote 1.6.3 → 1.6.5
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 +46 -46
- package/dist/autumnnote.es.js.map +1 -1
- package/dist/autumnnote.umd.js +46 -46
- package/dist/autumnnote.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/js/core/detectLang.js +1 -1
- package/src/js/core/dom.js +3 -5
- package/src/js/editing/Style.js +10 -10
- package/src/js/editing/Typing.js +5 -5
- package/src/js/index.js +1 -1
- package/src/js/module/BaseDialog.js +1 -1
- package/src/js/module/BubbleToolbar.js +2 -2
- package/src/js/module/Buttons.js +8 -8
- package/src/js/module/Editor.js +4 -4
- package/src/js/module/IconDialog.js +1 -1
- package/src/js/module/ImageCropOverlay.js +1 -1
- package/src/js/module/ImageResizer.js +1 -1
- package/src/js/module/Mention.js +1 -1
- package/src/js/module/TableTooltip.js +7 -7
- package/src/js/module/Toolbar.js +9 -11
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "autumnnote",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.5",
|
|
4
4
|
"description": "WYSIWYG rich-text editor built with vanilla JavaScript — zero dependencies, no jQuery. Dark mode, @mention, markdown shortcuts, bubble toolbar. React and Vue 3 wrappers included.",
|
|
5
5
|
"main": "dist/autumnnote.umd.js",
|
|
6
6
|
"module": "dist/autumnnote.es.js",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* @returns {string|null}
|
|
14
14
|
*/
|
|
15
15
|
export function detectLang(code) {
|
|
16
|
-
if (!code
|
|
16
|
+
if (!code?.trim()) return null;
|
|
17
17
|
const s = code.trim();
|
|
18
18
|
|
|
19
19
|
// ── TypeScript ─────────────────────────────────────────────────────────────
|
package/src/js/core/dom.js
CHANGED
|
@@ -305,11 +305,9 @@ export function trapFocus(container, onEscape) {
|
|
|
305
305
|
e.preventDefault();
|
|
306
306
|
/** @type {HTMLElement} */ (last).focus();
|
|
307
307
|
}
|
|
308
|
-
} else {
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
/** @type {HTMLElement} */ (first).focus();
|
|
312
|
-
}
|
|
308
|
+
} else if (document.activeElement === last) {
|
|
309
|
+
e.preventDefault();
|
|
310
|
+
/** @type {HTMLElement} */ (first).focus();
|
|
313
311
|
}
|
|
314
312
|
};
|
|
315
313
|
|
package/src/js/editing/Style.js
CHANGED
|
@@ -41,7 +41,7 @@ export const italic = () => execCommand('italic');
|
|
|
41
41
|
*/
|
|
42
42
|
export function underline() {
|
|
43
43
|
const sel = globalThis.getSelection();
|
|
44
|
-
if (!sel
|
|
44
|
+
if (!sel?.rangeCount) return;
|
|
45
45
|
let container = sel.getRangeAt(0).commonAncestorContainer;
|
|
46
46
|
if (container.nodeType === 3) container = container.parentElement;
|
|
47
47
|
// Check if we're inside a <u> (DOM truth), to guard against unreliable queryCommandState
|
|
@@ -65,7 +65,7 @@ export function underline() {
|
|
|
65
65
|
*/
|
|
66
66
|
export function strikethrough() {
|
|
67
67
|
const sel = globalThis.getSelection();
|
|
68
|
-
if (!sel
|
|
68
|
+
if (!sel?.rangeCount) return;
|
|
69
69
|
// Use startContainer for consistent detection across collapsed and range
|
|
70
70
|
// selections — commonAncestorContainer can miss ancestor <s>/<strike> tags
|
|
71
71
|
// when the selection spans across nested inline elements.
|
|
@@ -120,7 +120,7 @@ export const fontName = (name) => execCommand('fontName', name);
|
|
|
120
120
|
*/
|
|
121
121
|
export function fontSize(size, editable = document) {
|
|
122
122
|
const sel = globalThis.getSelection();
|
|
123
|
-
const wasCollapsed = !sel
|
|
123
|
+
const wasCollapsed = !sel?.rangeCount || sel.getRangeAt(0).collapsed;
|
|
124
124
|
|
|
125
125
|
// B-I-3/4: For a collapsed (caret) selection the browser's execCommand
|
|
126
126
|
// 'fontSize' leaves an internal "pending" state of size-7 (=48px) instead of
|
|
@@ -223,7 +223,7 @@ export const indent = () => execCommand('indent');
|
|
|
223
223
|
*/
|
|
224
224
|
export function outdent() {
|
|
225
225
|
const sel = globalThis.getSelection();
|
|
226
|
-
if (sel
|
|
226
|
+
if (sel?.rangeCount) {
|
|
227
227
|
let container = sel.getRangeAt(0).commonAncestorContainer;
|
|
228
228
|
if (container.nodeType === 3) container = container.parentElement;
|
|
229
229
|
const checkLi = /** @type {Element|null} */ (container)?.closest('.an-checklist li');
|
|
@@ -286,7 +286,7 @@ function _checklistItemToP(checkLi) {
|
|
|
286
286
|
try {
|
|
287
287
|
const nr = document.createRange();
|
|
288
288
|
const firstChild = p.firstChild;
|
|
289
|
-
nr.setStart(firstChild
|
|
289
|
+
nr.setStart(firstChild?.nodeType === 3 ? firstChild : p, 0);
|
|
290
290
|
nr.collapse(true);
|
|
291
291
|
const s = globalThis.getSelection();
|
|
292
292
|
if (s) { s.removeAllRanges(); s.addRange(nr); }
|
|
@@ -406,7 +406,7 @@ export function currentStyle(editable) {
|
|
|
406
406
|
*/
|
|
407
407
|
export function toggleInlineCode(_editable) {
|
|
408
408
|
const sel = globalThis.getSelection();
|
|
409
|
-
if (!sel
|
|
409
|
+
if (!sel?.rangeCount) return;
|
|
410
410
|
const range = sel.getRangeAt(0);
|
|
411
411
|
let container = range.commonAncestorContainer;
|
|
412
412
|
if (container.nodeType === 3) container = container.parentElement;
|
|
@@ -477,7 +477,7 @@ export function toggleInlineCode(_editable) {
|
|
|
477
477
|
*/
|
|
478
478
|
export function isInlineCode() {
|
|
479
479
|
const sel = globalThis.getSelection();
|
|
480
|
-
if (!sel
|
|
480
|
+
if (!sel?.rangeCount) return false;
|
|
481
481
|
let sc = sel.getRangeAt(0).startContainer;
|
|
482
482
|
if (sc.nodeType === 3) sc = sc.parentElement;
|
|
483
483
|
const code = /** @type {Element|null} */ (sc)?.closest('code');
|
|
@@ -504,7 +504,7 @@ export function isInlineCode() {
|
|
|
504
504
|
*/
|
|
505
505
|
export function toggleChecklist() {
|
|
506
506
|
const sel = globalThis.getSelection();
|
|
507
|
-
if (!sel
|
|
507
|
+
if (!sel?.rangeCount) return;
|
|
508
508
|
const range = sel.getRangeAt(0);
|
|
509
509
|
let container = range.commonAncestorContainer;
|
|
510
510
|
if (container.nodeType === 3) container = container.parentElement;
|
|
@@ -552,7 +552,7 @@ export function toggleChecklist() {
|
|
|
552
552
|
// and convert it into a single checklist item.
|
|
553
553
|
const BLOCK_TAGS = new Set(['P', 'DIV', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'BLOCKQUOTE', 'LI']);
|
|
554
554
|
let block = /** @type {Element|null} */ (container);
|
|
555
|
-
while (block
|
|
555
|
+
while (block?.parentNode && !BLOCK_TAGS.has(block.tagName)) {
|
|
556
556
|
block = /** @type {Element|null} */ (block.parentNode);
|
|
557
557
|
}
|
|
558
558
|
// Fallback: if no block element found (e.g. cursor directly in editable root), use the
|
|
@@ -674,7 +674,7 @@ export function toggleChecklist() {
|
|
|
674
674
|
*/
|
|
675
675
|
export function isInChecklist() {
|
|
676
676
|
const sel = globalThis.getSelection();
|
|
677
|
-
if (!sel
|
|
677
|
+
if (!sel?.rangeCount) return false;
|
|
678
678
|
let container = sel.getRangeAt(0).commonAncestorContainer;
|
|
679
679
|
if (container.nodeType === 3) container = container.parentElement;
|
|
680
680
|
return !!(/** @type {Element|null} */ (container)?.closest('.an-checklist li'));
|
package/src/js/editing/Typing.js
CHANGED
|
@@ -68,7 +68,7 @@ export function handleKeydown(event, editable, options = {}) {
|
|
|
68
68
|
// (not a text node), causing the next Backspace to miss Cases A/B and
|
|
69
69
|
// requiring an extra keypress when two icons are adjacent.
|
|
70
70
|
const nr = document.createRange();
|
|
71
|
-
if (prevNode
|
|
71
|
+
if (prevNode?.nodeType === Node.TEXT_NODE) {
|
|
72
72
|
nr.setStart(prevNode, prevNode.textContent.length);
|
|
73
73
|
} else if (prevNode) {
|
|
74
74
|
nr.setStartAfter(prevNode);
|
|
@@ -168,7 +168,7 @@ export function handleKeydown(event, editable, options = {}) {
|
|
|
168
168
|
if (isFAIcon(next)) {
|
|
169
169
|
const after = next.nextSibling;
|
|
170
170
|
event.preventDefault();
|
|
171
|
-
if (after
|
|
171
|
+
if (after?.nodeType === Node.TEXT_NODE) {
|
|
172
172
|
const offset = ((after.textContent || '').startsWith('\u200B')) ? 1 : 0;
|
|
173
173
|
return moveCaret((nr) => nr.setStart(after, Math.min(offset, after.textContent.length)));
|
|
174
174
|
}
|
|
@@ -178,7 +178,7 @@ export function handleKeydown(event, editable, options = {}) {
|
|
|
178
178
|
const icon = next.nextSibling;
|
|
179
179
|
const after = icon.nextSibling;
|
|
180
180
|
event.preventDefault();
|
|
181
|
-
if (after
|
|
181
|
+
if (after?.nodeType === Node.TEXT_NODE) {
|
|
182
182
|
const offset = ((after.textContent || '').startsWith('\u200B')) ? 1 : 0;
|
|
183
183
|
return moveCaret((nr) => nr.setStart(after, Math.min(offset, after.textContent.length)));
|
|
184
184
|
}
|
|
@@ -341,11 +341,11 @@ export function handleKeydown(event, editable, options = {}) {
|
|
|
341
341
|
// may normalise it to element-level, placing the caret before the
|
|
342
342
|
// absolutely-positioned checkbox. \u200B is stripped by getHTML().
|
|
343
343
|
let cursorNode = newLi.childNodes[1]; // first child after checkbox
|
|
344
|
-
if (
|
|
344
|
+
if (cursorNode?.nodeType !== Node.TEXT_NODE) {
|
|
345
345
|
cursorNode = document.createTextNode('\u200B');
|
|
346
346
|
newLi.appendChild(cursorNode);
|
|
347
347
|
}
|
|
348
|
-
checkLi.
|
|
348
|
+
checkLi.after(newLi);
|
|
349
349
|
|
|
350
350
|
const nr = document.createRange();
|
|
351
351
|
nr.setStart(cursorNode, 0);
|
package/src/js/index.js
CHANGED
|
@@ -141,7 +141,7 @@ const AutumnNote = {
|
|
|
141
141
|
registerButton(btnDef) { registerButton(btnDef); return this; },
|
|
142
142
|
|
|
143
143
|
/** Library version */
|
|
144
|
-
version: '1.6.
|
|
144
|
+
version: '1.6.5',
|
|
145
145
|
};
|
|
146
146
|
|
|
147
147
|
// ---------------------------------------------------------------------------
|
|
@@ -51,7 +51,7 @@ export class BaseDialog {
|
|
|
51
51
|
if (this._dialog) {
|
|
52
52
|
this._dialog.style.display = 'flex';
|
|
53
53
|
this._removeTrap = trapFocus(this._dialog, () => this._close());
|
|
54
|
-
setTimeout(() => this._firstInput
|
|
54
|
+
setTimeout(() => this._firstInput?.focus(), 50);
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
|
|
@@ -389,7 +389,7 @@ export class BubbleToolbar {
|
|
|
389
389
|
if (!this._btnCache) return;
|
|
390
390
|
this._btnCache.forEach((btn) => {
|
|
391
391
|
const activeFn = _ACTIVE[/** @type {HTMLElement} */ (btn).dataset.name];
|
|
392
|
-
btn.classList.toggle('an-active', !!(activeFn
|
|
392
|
+
btn.classList.toggle('an-active', !!(activeFn?.()));
|
|
393
393
|
});
|
|
394
394
|
}
|
|
395
395
|
|
|
@@ -397,7 +397,7 @@ export class BubbleToolbar {
|
|
|
397
397
|
_syncColorStrips() {
|
|
398
398
|
if (!this._el) return;
|
|
399
399
|
const sel = globalThis.getSelection();
|
|
400
|
-
if (!sel
|
|
400
|
+
if (!sel?.rangeCount) return;
|
|
401
401
|
let node = sel.getRangeAt(0).startContainer;
|
|
402
402
|
if (node.nodeType === Node.TEXT_NODE) node = node.parentElement;
|
|
403
403
|
if (!node) return;
|
package/src/js/module/Buttons.js
CHANGED
|
@@ -102,10 +102,10 @@ export const underlineBtn = btn('underline', 'underline', 'Underline (Ctrl+U)',
|
|
|
102
102
|
// consistent behaviour across both collapsed and range selections.
|
|
103
103
|
if (document.queryCommandState('underline')) return true;
|
|
104
104
|
const sel = globalThis.getSelection();
|
|
105
|
-
if (!sel
|
|
105
|
+
if (!sel?.rangeCount) return false;
|
|
106
106
|
let sc = sel.getRangeAt(0).startContainer;
|
|
107
107
|
if (sc.nodeType === 3) sc = sc.parentElement;
|
|
108
|
-
return !!(
|
|
108
|
+
return !!(/** @type {Element} */ (sc)?.closest('u'));
|
|
109
109
|
});
|
|
110
110
|
export const strikeBtn = btn('strikethrough', 'strikethrough', 'Strikethrough', () => Style.strikethrough(), () => document.queryCommandState('strikeThrough'));
|
|
111
111
|
export const superscriptBtn = btn('superscript', 'superscript', 'Superscript', () => Style.superscript(), () => document.queryCommandState('superscript'));
|
|
@@ -180,11 +180,11 @@ export const fontSizeBtn = {
|
|
|
180
180
|
getValue: (ctx) => {
|
|
181
181
|
try {
|
|
182
182
|
const sel = globalThis.getSelection();
|
|
183
|
-
if (sel
|
|
183
|
+
if (sel?.rangeCount) {
|
|
184
184
|
let el = /** @type {Element|null} */ (sel.getRangeAt(0).startContainer);
|
|
185
|
-
if (el
|
|
186
|
-
while (el
|
|
187
|
-
const size =
|
|
185
|
+
if (el?.nodeType === 3) el = el.parentElement;
|
|
186
|
+
while (el?.nodeType === 1 && !/** @type {HTMLElement} */ (el).style.fontSize) el = el.parentElement;
|
|
187
|
+
const size = /** @type {HTMLElement} */ (el)?.style.fontSize || '';
|
|
188
188
|
if (size) return size;
|
|
189
189
|
}
|
|
190
190
|
// Fallback: read the base font size from the editable element itself
|
|
@@ -281,10 +281,10 @@ export const lineHeightBtn = {
|
|
|
281
281
|
getValue: () => {
|
|
282
282
|
try {
|
|
283
283
|
const sel = globalThis.getSelection();
|
|
284
|
-
if (!sel
|
|
284
|
+
if (!sel?.rangeCount) return '';
|
|
285
285
|
const BLOCKS = new Set(['P','DIV','H1','H2','H3','H4','H5','H6','LI','BLOCKQUOTE','PRE','TD','TH']);
|
|
286
286
|
let el = /** @type {Element|null} */ (sel.getRangeAt(0).startContainer);
|
|
287
|
-
if (el
|
|
287
|
+
if (el?.nodeType === 3) el = el.parentElement;
|
|
288
288
|
while (el && !BLOCKS.has(/** @type {Element} */ (el).tagName)) el = el.parentElement;
|
|
289
289
|
if (!el) return '';
|
|
290
290
|
return /** @type {HTMLElement} */ (el).style.lineHeight || getComputedStyle(/** @type {Element} */ (el)).lineHeight || '';
|
package/src/js/module/Editor.js
CHANGED
|
@@ -86,7 +86,7 @@ export class Editor {
|
|
|
86
86
|
// keyup : arrow-key navigation may land at <li>[0]; move to start-of-text.
|
|
87
87
|
const fixChecklistCursor = (event) => {
|
|
88
88
|
const sel = globalThis.getSelection();
|
|
89
|
-
if (!sel
|
|
89
|
+
if (!sel?.rangeCount) return;
|
|
90
90
|
const r = sel.getRangeAt(0);
|
|
91
91
|
if (!r.collapsed) return;
|
|
92
92
|
const sc = r.startContainer;
|
|
@@ -102,7 +102,7 @@ export class Editor {
|
|
|
102
102
|
|
|
103
103
|
// For mouse events: ask the browser where the pointer landed so the
|
|
104
104
|
// cursor respects the actual click position inside the text.
|
|
105
|
-
if (event
|
|
105
|
+
if (event?.type === 'mouseup') {
|
|
106
106
|
let caret = null;
|
|
107
107
|
if (document.caretRangeFromPoint) {
|
|
108
108
|
caret = document.caretRangeFromPoint(event.clientX, event.clientY);
|
|
@@ -181,7 +181,7 @@ export class Editor {
|
|
|
181
181
|
let _compositionSupSub = null;
|
|
182
182
|
const onCompositionStart = () => {
|
|
183
183
|
const sel = globalThis.getSelection();
|
|
184
|
-
if (!sel
|
|
184
|
+
if (!sel?.rangeCount) { _compositionSupSub = null; return; }
|
|
185
185
|
let node = sel.getRangeAt(0).startContainer;
|
|
186
186
|
if (node.nodeType === Node.TEXT_NODE) node = node.parentElement;
|
|
187
187
|
if (node) {
|
|
@@ -196,7 +196,7 @@ export class Editor {
|
|
|
196
196
|
_compositionSupSub = null;
|
|
197
197
|
if (!tag) return;
|
|
198
198
|
const sel = globalThis.getSelection();
|
|
199
|
-
if (!sel
|
|
199
|
+
if (!sel?.rangeCount) return;
|
|
200
200
|
let node = sel.getRangeAt(0).startContainer;
|
|
201
201
|
if (node.nodeType === Node.TEXT_NODE) node = node.parentElement;
|
|
202
202
|
const el = /** @type {Element} */ (node);
|
|
@@ -580,7 +580,7 @@ export class IconDialog extends BaseDialog {
|
|
|
580
580
|
// Keep a text anchor (\u200B) after the icon so ArrowLeft/ArrowRight and
|
|
581
581
|
// caret placement at end-of-line stay stable across browsers.
|
|
582
582
|
let caretTextNode = iconEl.nextSibling;
|
|
583
|
-
if (
|
|
583
|
+
if (caretTextNode?.nodeType !== Node.TEXT_NODE) {
|
|
584
584
|
caretTextNode = document.createTextNode('\u200B');
|
|
585
585
|
iconEl.parentNode.insertBefore(caretTextNode, iconEl.nextSibling);
|
|
586
586
|
} else if (!caretTextNode.textContent) {
|
|
@@ -399,7 +399,7 @@ export class ImageCropOverlay {
|
|
|
399
399
|
const startY = e.clientY;
|
|
400
400
|
const orig = { ...this._box };
|
|
401
401
|
const r = this._imgRect;
|
|
402
|
-
const lockAR = this._arCheck
|
|
402
|
+
const lockAR = this._arCheck?.checked;
|
|
403
403
|
const aspect = orig.w / (orig.h || 1);
|
|
404
404
|
|
|
405
405
|
const onMove = (me) => {
|
|
@@ -181,7 +181,7 @@ export class ImageResizer {
|
|
|
181
181
|
|
|
182
182
|
// Skip DOM writes when position hasn't changed (common during non-scroll rAF ticks)
|
|
183
183
|
const p = this._lastOverlayPos;
|
|
184
|
-
if (p
|
|
184
|
+
if (p?.l === rect.left && p.t === rect.top && p.w === rect.width && p.h === rect.height) return;
|
|
185
185
|
this._lastOverlayPos = { l: rect.left, t: rect.top, w: rect.width, h: rect.height };
|
|
186
186
|
|
|
187
187
|
const left = rect.left - containerRect.left + offsetParent.scrollLeft;
|
package/src/js/module/Mention.js
CHANGED
|
@@ -210,7 +210,7 @@ export class Mention {
|
|
|
210
210
|
|
|
211
211
|
// Fallback: use getClientRects() on the current collapsed selection
|
|
212
212
|
const sel = globalThis.getSelection();
|
|
213
|
-
if (!sel
|
|
213
|
+
if (!sel?.rangeCount) return;
|
|
214
214
|
const rects = sel.getRangeAt(0).getClientRects();
|
|
215
215
|
if (rects.length > 0) {
|
|
216
216
|
this._caretRect = rects[rects.length - 1];
|
|
@@ -58,7 +58,7 @@ function getCellAfterVisualCol(row, visualIdx) {
|
|
|
58
58
|
if (vIdx > visualIdx) {
|
|
59
59
|
// next cell after the one that starts at / spans visualIdx
|
|
60
60
|
const next = c.nextElementSibling;
|
|
61
|
-
return (next
|
|
61
|
+
return (next?.tagName === 'TD' || next?.tagName === 'TH') ? /** @type {HTMLTableCellElement} */ (next) : null;
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
return null;
|
|
@@ -388,11 +388,11 @@ export class TableTooltip {
|
|
|
388
388
|
this._disposers = [];
|
|
389
389
|
if (this._el && this._el.parentNode) this._el.remove();
|
|
390
390
|
this._el = null;
|
|
391
|
-
if (this._sizePopover
|
|
391
|
+
if (this._sizePopover?.parentNode) {
|
|
392
392
|
this._sizePopover.remove();
|
|
393
393
|
}
|
|
394
394
|
this._sizePopover = null;
|
|
395
|
-
if (this._shadePopover
|
|
395
|
+
if (this._shadePopover?.parentNode) {
|
|
396
396
|
this._shadePopover.remove();
|
|
397
397
|
}
|
|
398
398
|
this._shadePopover = null;
|
|
@@ -604,7 +604,7 @@ export class TableTooltip {
|
|
|
604
604
|
_getCell() {
|
|
605
605
|
// Prefer the cell under the current text cursor (most intuitive for operations)
|
|
606
606
|
const sel = globalThis.getSelection();
|
|
607
|
-
if (sel
|
|
607
|
+
if (sel?.rangeCount) {
|
|
608
608
|
let container = sel.getRangeAt(0).commonAncestorContainer;
|
|
609
609
|
if (container.nodeType === 3) container = container.parentElement;
|
|
610
610
|
const cellFromSel = /** @type {Element} */ (container)?.closest('td, th');
|
|
@@ -659,7 +659,7 @@ export class TableTooltip {
|
|
|
659
659
|
if (!startCell) return [];
|
|
660
660
|
if (!endCell || startCell === endCell) return [startCell];
|
|
661
661
|
const table = startCell.closest('table');
|
|
662
|
-
if (!table
|
|
662
|
+
if (!table?.contains(endCell)) return [startCell];
|
|
663
663
|
|
|
664
664
|
const { gridMap, cellPos } = buildGridMap(table);
|
|
665
665
|
const sp = cellPos.get(startCell);
|
|
@@ -742,8 +742,8 @@ export class TableTooltip {
|
|
|
742
742
|
for (let i = 0; i < colCount; i++) {
|
|
743
743
|
const td = createElement('td', {}, ['\u00a0']);
|
|
744
744
|
const ref = refCells[i];
|
|
745
|
-
if (ref
|
|
746
|
-
if (ref
|
|
745
|
+
if (ref?.style.width) td.style.width = ref.style.width;
|
|
746
|
+
if (ref?.style.minWidth) td.style.minWidth = ref.style.minWidth;
|
|
747
747
|
newRow.appendChild(td);
|
|
748
748
|
}
|
|
749
749
|
if (position === 'above') refRow.parentElement?.insertBefore(newRow, refRow);
|
package/src/js/module/Toolbar.js
CHANGED
|
@@ -399,7 +399,7 @@ export class Toolbar {
|
|
|
399
399
|
|
|
400
400
|
const saveSelection = () => {
|
|
401
401
|
const sel = globalThis.getSelection();
|
|
402
|
-
savedRange =
|
|
402
|
+
savedRange = sel?.rangeCount ? sel.getRangeAt(0).cloneRange() : null;
|
|
403
403
|
};
|
|
404
404
|
|
|
405
405
|
const restoreSelection = () => {
|
|
@@ -543,7 +543,7 @@ export class Toolbar {
|
|
|
543
543
|
const value = (typeof item === 'object') ? item.value : item;
|
|
544
544
|
const label = (typeof item === 'object')
|
|
545
545
|
? (def.name === 'paragraphStyle'
|
|
546
|
-
? (
|
|
546
|
+
? (this.context.locale.toolbar.paragraphItems?.[item.value] || item.label)
|
|
547
547
|
: item.label)
|
|
548
548
|
: item;
|
|
549
549
|
const isHeader = (typeof item === 'object') && !!item.disabled;
|
|
@@ -563,7 +563,7 @@ export class Toolbar {
|
|
|
563
563
|
let _savedRange = null;
|
|
564
564
|
const dMousedown = on(select, 'mousedown', () => {
|
|
565
565
|
const sel = globalThis.getSelection();
|
|
566
|
-
_savedRange =
|
|
566
|
+
_savedRange = sel?.rangeCount ? sel.getRangeAt(0).cloneRange() : null;
|
|
567
567
|
});
|
|
568
568
|
|
|
569
569
|
const disposer = on(select, 'change', (e) => {
|
|
@@ -617,15 +617,13 @@ export class Toolbar {
|
|
|
617
617
|
} else {
|
|
618
618
|
btn.textContent = btnDef.icon || btnDef.name;
|
|
619
619
|
}
|
|
620
|
-
} else {
|
|
620
|
+
} else if (_SVG_MAP.has(btnDef.icon)) {
|
|
621
621
|
// FontAwesome absent: use SVG fallback when available
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
btn.textContent = btnDef.icon || btnDef.name;
|
|
628
|
-
}
|
|
622
|
+
btn.innerHTML = _SVG_MAP.get(btnDef.icon);
|
|
623
|
+
} else if (_SVG_MAP.has(btnDef.name)) {
|
|
624
|
+
btn.innerHTML = _SVG_MAP.get(btnDef.name);
|
|
625
|
+
} else {
|
|
626
|
+
btn.textContent = btnDef.icon || btnDef.name;
|
|
629
627
|
}
|
|
630
628
|
|
|
631
629
|
const disposer = on(btn, 'click', (event) => {
|