autumnnote 1.6.7 → 1.8.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/README.md +11 -5
- package/dist/autumnnote.css +164 -0
- package/dist/autumnnote.es.js +580 -39
- package/dist/autumnnote.es.js.map +1 -1
- package/dist/autumnnote.umd.js +658 -100
- package/dist/autumnnote.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/js/Context.js +63 -2
- package/src/js/editing/History.js +10 -0
- package/src/js/i18n/de.js +14 -0
- package/src/js/i18n/en.js +22 -0
- package/src/js/i18n/es.js +14 -0
- package/src/js/i18n/fr.js +15 -1
- package/src/js/i18n/ja.js +14 -0
- package/src/js/i18n/ko.js +14 -0
- package/src/js/i18n/vi.js +14 -0
- package/src/js/i18n/zh.js +14 -0
- package/src/js/index.js +5 -2
- package/src/js/module/BaseDialog.js +7 -0
- package/src/js/module/Buttons.js +49 -0
- package/src/js/module/Clipboard.js +12 -0
- package/src/js/module/CodeTooltip.js +23 -0
- package/src/js/module/Editor.js +8 -0
- package/src/js/module/FindReplace.js +50 -6
- package/src/js/module/ImageResizer.js +8 -7
- package/src/js/module/Mention.js +9 -2
- package/src/js/module/Statusbar.js +3 -3
- package/src/js/module/TableTooltip.js +287 -2
- package/src/js/renderer.js +5 -2
- package/src/styles/autumnnote.scss +181 -0
- package/types/index.d.ts +99 -4
package/dist/autumnnote.umd.js
CHANGED
|
@@ -968,6 +968,13 @@
|
|
|
968
968
|
}
|
|
969
969
|
};
|
|
970
970
|
var removeFormatBtn = btn("removeFormat", "remove-format", "Remove Format", () => execCommand("removeFormat"));
|
|
971
|
+
var directionBtn = btn("direction", "direction", "Toggle Text Direction (LTR / RTL)", (ctx) => {
|
|
972
|
+
const editable = ctx.layoutInfo.editable;
|
|
973
|
+
const next = (editable.getAttribute("dir") || "ltr") === "ltr" ? "rtl" : "ltr";
|
|
974
|
+
editable.setAttribute("dir", next);
|
|
975
|
+
editable.style.textAlign = next === "rtl" ? "right" : "left";
|
|
976
|
+
ctx.invoke("editor.afterCommand");
|
|
977
|
+
});
|
|
971
978
|
/** @type {DropdownDef} */
|
|
972
979
|
var fontFamilyBtn = {
|
|
973
980
|
name: "fontFamily",
|
|
@@ -1090,9 +1097,122 @@
|
|
|
1090
1097
|
var fullscreenBtn = btn("fullscreen", "expand", "Fullscreen", (ctx) => ctx.invoke("fullscreen.toggle"), (ctx) => ctx.invoke("fullscreen.isActive"));
|
|
1091
1098
|
var shortcutsBtn = btn("shortcuts", "keyboard", "Keyboard Shortcuts (Ctrl+Shift+/)", (ctx) => ctx.invoke("shortcutsDialog.show"));
|
|
1092
1099
|
var findBtn = btn("find", "search", "Find (Ctrl+F)", (ctx) => ctx.invoke("findReplace.show", "find"));
|
|
1100
|
+
var findReplaceBtn = btn("findReplace", "find-replace", "Find & Replace (Ctrl+H)", (ctx) => ctx.invoke("findReplace.show", "replace"));
|
|
1093
1101
|
var inlineCodeBtn = btn("inlineCode", "inline-code", "Inline Code (Ctrl+`)", (ctx) => ctx.invoke("editor.inlineCode"), () => isInlineCode());
|
|
1094
1102
|
var checklistBtn = btn("checklist", "checklist", "Checklist", (ctx) => ctx.invoke("editor.toggleChecklist"), () => isInChecklist());
|
|
1095
1103
|
var printBtn = btn("print", "print", "Print", (ctx) => ctx.invoke("editor.print"));
|
|
1104
|
+
/** @type {{ name: string, type: 'colorpicker', icon: string, tooltip: string, defaultColor: string, action: Function }} */
|
|
1105
|
+
var foreColorBtn = {
|
|
1106
|
+
name: "foreColor",
|
|
1107
|
+
type: "colorpicker",
|
|
1108
|
+
icon: "foreColor",
|
|
1109
|
+
tooltip: "Text Color",
|
|
1110
|
+
defaultColor: "#e11d48",
|
|
1111
|
+
action: (ctx, color) => foreColor(color)
|
|
1112
|
+
};
|
|
1113
|
+
/** @type {{ name: string, type: 'colorpicker', icon: string, tooltip: string, defaultColor: string, action: Function }} */
|
|
1114
|
+
var backColorBtn = {
|
|
1115
|
+
name: "backColor",
|
|
1116
|
+
type: "colorpicker",
|
|
1117
|
+
icon: "backColor",
|
|
1118
|
+
tooltip: "Highlight Color",
|
|
1119
|
+
defaultColor: "#fbbf24",
|
|
1120
|
+
action: (ctx, color) => backColor(color)
|
|
1121
|
+
};
|
|
1122
|
+
/**
|
|
1123
|
+
* The default toolbar button groups.
|
|
1124
|
+
* Each sub-array is a button group (separated by a divider).
|
|
1125
|
+
*/
|
|
1126
|
+
var defaultToolbar = [
|
|
1127
|
+
[
|
|
1128
|
+
paragraphStyleBtn,
|
|
1129
|
+
fontFamilyBtn,
|
|
1130
|
+
fontSizeBtn,
|
|
1131
|
+
lineHeightBtn
|
|
1132
|
+
],
|
|
1133
|
+
[undoBtn, redoBtn],
|
|
1134
|
+
[
|
|
1135
|
+
boldBtn,
|
|
1136
|
+
italicBtn,
|
|
1137
|
+
underlineBtn,
|
|
1138
|
+
strikeBtn,
|
|
1139
|
+
inlineCodeBtn
|
|
1140
|
+
],
|
|
1141
|
+
[superscriptBtn, subscriptBtn],
|
|
1142
|
+
[foreColorBtn, backColorBtn],
|
|
1143
|
+
[
|
|
1144
|
+
alignLeftBtn,
|
|
1145
|
+
alignCenterBtn,
|
|
1146
|
+
alignRightBtn,
|
|
1147
|
+
alignJustifyBtn
|
|
1148
|
+
],
|
|
1149
|
+
[
|
|
1150
|
+
ulBtn,
|
|
1151
|
+
olBtn,
|
|
1152
|
+
checklistBtn,
|
|
1153
|
+
indentBtn,
|
|
1154
|
+
outdentBtn
|
|
1155
|
+
],
|
|
1156
|
+
[
|
|
1157
|
+
hrBtn,
|
|
1158
|
+
linkBtn,
|
|
1159
|
+
imageBtn,
|
|
1160
|
+
videoBtn,
|
|
1161
|
+
tableBtn,
|
|
1162
|
+
emojiBtn,
|
|
1163
|
+
iconBtn
|
|
1164
|
+
],
|
|
1165
|
+
[
|
|
1166
|
+
removeFormatBtn,
|
|
1167
|
+
codeviewBtn,
|
|
1168
|
+
fullscreenBtn,
|
|
1169
|
+
findBtn,
|
|
1170
|
+
printBtn,
|
|
1171
|
+
shortcutsBtn
|
|
1172
|
+
]
|
|
1173
|
+
];
|
|
1174
|
+
var buttons = {
|
|
1175
|
+
boldBtn,
|
|
1176
|
+
italicBtn,
|
|
1177
|
+
underlineBtn,
|
|
1178
|
+
strikeBtn,
|
|
1179
|
+
superscriptBtn,
|
|
1180
|
+
subscriptBtn,
|
|
1181
|
+
alignLeftBtn,
|
|
1182
|
+
alignCenterBtn,
|
|
1183
|
+
alignRightBtn,
|
|
1184
|
+
alignJustifyBtn,
|
|
1185
|
+
ulBtn,
|
|
1186
|
+
olBtn,
|
|
1187
|
+
indentBtn,
|
|
1188
|
+
outdentBtn,
|
|
1189
|
+
undoBtn,
|
|
1190
|
+
redoBtn,
|
|
1191
|
+
hrBtn,
|
|
1192
|
+
linkBtn,
|
|
1193
|
+
imageBtn,
|
|
1194
|
+
videoBtn,
|
|
1195
|
+
emojiBtn,
|
|
1196
|
+
iconBtn,
|
|
1197
|
+
tableBtn,
|
|
1198
|
+
fontSizeBtn,
|
|
1199
|
+
removeFormatBtn,
|
|
1200
|
+
directionBtn,
|
|
1201
|
+
fontFamilyBtn,
|
|
1202
|
+
paragraphStyleBtn,
|
|
1203
|
+
lineHeightBtn,
|
|
1204
|
+
codeviewBtn,
|
|
1205
|
+
fullscreenBtn,
|
|
1206
|
+
shortcutsBtn,
|
|
1207
|
+
findBtn,
|
|
1208
|
+
findReplaceBtn,
|
|
1209
|
+
inlineCodeBtn,
|
|
1210
|
+
checklistBtn,
|
|
1211
|
+
printBtn,
|
|
1212
|
+
foreColorBtn,
|
|
1213
|
+
backColorBtn,
|
|
1214
|
+
defaultToolbar
|
|
1215
|
+
};
|
|
1096
1216
|
//#endregion
|
|
1097
1217
|
//#region src/js/settings.js
|
|
1098
1218
|
/**
|
|
@@ -1166,68 +1286,7 @@
|
|
|
1166
1286
|
maxHeight: 0,
|
|
1167
1287
|
focus: false,
|
|
1168
1288
|
resizable: true,
|
|
1169
|
-
toolbar:
|
|
1170
|
-
[
|
|
1171
|
-
paragraphStyleBtn,
|
|
1172
|
-
fontFamilyBtn,
|
|
1173
|
-
fontSizeBtn,
|
|
1174
|
-
lineHeightBtn
|
|
1175
|
-
],
|
|
1176
|
-
[undoBtn, redoBtn],
|
|
1177
|
-
[
|
|
1178
|
-
boldBtn,
|
|
1179
|
-
italicBtn,
|
|
1180
|
-
underlineBtn,
|
|
1181
|
-
strikeBtn,
|
|
1182
|
-
inlineCodeBtn
|
|
1183
|
-
],
|
|
1184
|
-
[superscriptBtn, subscriptBtn],
|
|
1185
|
-
[{
|
|
1186
|
-
name: "foreColor",
|
|
1187
|
-
type: "colorpicker",
|
|
1188
|
-
icon: "foreColor",
|
|
1189
|
-
tooltip: "Text Color",
|
|
1190
|
-
defaultColor: "#e11d48",
|
|
1191
|
-
action: (ctx, color) => foreColor(color)
|
|
1192
|
-
}, {
|
|
1193
|
-
name: "backColor",
|
|
1194
|
-
type: "colorpicker",
|
|
1195
|
-
icon: "backColor",
|
|
1196
|
-
tooltip: "Highlight Color",
|
|
1197
|
-
defaultColor: "#fbbf24",
|
|
1198
|
-
action: (ctx, color) => backColor(color)
|
|
1199
|
-
}],
|
|
1200
|
-
[
|
|
1201
|
-
alignLeftBtn,
|
|
1202
|
-
alignCenterBtn,
|
|
1203
|
-
alignRightBtn,
|
|
1204
|
-
alignJustifyBtn
|
|
1205
|
-
],
|
|
1206
|
-
[
|
|
1207
|
-
ulBtn,
|
|
1208
|
-
olBtn,
|
|
1209
|
-
checklistBtn,
|
|
1210
|
-
indentBtn,
|
|
1211
|
-
outdentBtn
|
|
1212
|
-
],
|
|
1213
|
-
[
|
|
1214
|
-
hrBtn,
|
|
1215
|
-
linkBtn,
|
|
1216
|
-
imageBtn,
|
|
1217
|
-
videoBtn,
|
|
1218
|
-
tableBtn,
|
|
1219
|
-
emojiBtn,
|
|
1220
|
-
iconBtn
|
|
1221
|
-
],
|
|
1222
|
-
[
|
|
1223
|
-
removeFormatBtn,
|
|
1224
|
-
codeviewBtn,
|
|
1225
|
-
fullscreenBtn,
|
|
1226
|
-
findBtn,
|
|
1227
|
-
printBtn,
|
|
1228
|
-
shortcutsBtn
|
|
1229
|
-
]
|
|
1230
|
-
],
|
|
1289
|
+
toolbar: defaultToolbar,
|
|
1231
1290
|
useBootstrap: false,
|
|
1232
1291
|
toolbarButtonClass: "btn btn-sm btn-light",
|
|
1233
1292
|
useFontAwesome: true,
|
|
@@ -1448,6 +1507,7 @@
|
|
|
1448
1507
|
findPlaceholder: "Find…",
|
|
1449
1508
|
searchAriaLabel: "Search text",
|
|
1450
1509
|
caseSensitive: "\xA0Case sensitive",
|
|
1510
|
+
wholeWord: "Whole Word",
|
|
1451
1511
|
prevBtn: "← Prev",
|
|
1452
1512
|
nextBtn: "Next →",
|
|
1453
1513
|
replacePlaceholder: "Replace with…",
|
|
@@ -1455,8 +1515,15 @@
|
|
|
1455
1515
|
replaceBtn: "Replace",
|
|
1456
1516
|
replaceAllBtn: "Replace All",
|
|
1457
1517
|
noResults: "No results",
|
|
1518
|
+
useRegex: "Use Regular Expression",
|
|
1458
1519
|
close: "×"
|
|
1459
1520
|
},
|
|
1521
|
+
autoSaveRestore: {
|
|
1522
|
+
found: "Draft found. Restore?",
|
|
1523
|
+
foundAt: "Draft from {date}. Restore?",
|
|
1524
|
+
restore: "Restore",
|
|
1525
|
+
discard: "Discard"
|
|
1526
|
+
},
|
|
1460
1527
|
shortcutsDialog: {
|
|
1461
1528
|
title: "Keyboard Shortcuts",
|
|
1462
1529
|
ariaLabel: "Keyboard Shortcuts",
|
|
@@ -1600,7 +1667,8 @@
|
|
|
1600
1667
|
enableWordWrap: "Enable Word Wrap",
|
|
1601
1668
|
disableWordWrap: "Disable Word Wrap",
|
|
1602
1669
|
convertToParagraph: "Convert to Paragraph",
|
|
1603
|
-
deleteCodeBlock: "Delete Code Block"
|
|
1670
|
+
deleteCodeBlock: "Delete Code Block",
|
|
1671
|
+
lineNumbers: "Toggle Line Numbers"
|
|
1604
1672
|
},
|
|
1605
1673
|
table: {
|
|
1606
1674
|
ariaLabel: "Table actions",
|
|
@@ -1617,14 +1685,26 @@
|
|
|
1617
1685
|
columnWidth: "Column Width",
|
|
1618
1686
|
rowHeight: "Row Height",
|
|
1619
1687
|
tableBorderWidth: "Table Border Width",
|
|
1688
|
+
tableBorderColor: "Table Border Color",
|
|
1620
1689
|
deleteTable: "Delete Table",
|
|
1690
|
+
cellAlignLeft: "Align Left",
|
|
1691
|
+
cellAlignCenter: "Align Center",
|
|
1692
|
+
cellAlignRight: "Align Right",
|
|
1693
|
+
cellAlignJustify: "Align Justify",
|
|
1694
|
+
toggleHeaderRow: "Toggle Header Row",
|
|
1621
1695
|
cellBackground: "Cell Background",
|
|
1622
1696
|
noShading: "No Shading",
|
|
1697
|
+
noBorderColor: "No Border Color",
|
|
1623
1698
|
columnWidthPx: "Column Width (px)",
|
|
1624
1699
|
rowHeightPx: "Row Height (px)",
|
|
1625
1700
|
tableBorderWidthPx: "Table Border Width (px)",
|
|
1626
1701
|
cancelBtn: "Cancel",
|
|
1627
|
-
applyBtn: "Apply"
|
|
1702
|
+
applyBtn: "Apply",
|
|
1703
|
+
sortAsc: "Sort Ascending",
|
|
1704
|
+
sortDesc: "Sort Descending",
|
|
1705
|
+
exportCSV: "Export as CSV",
|
|
1706
|
+
cellPadding: "Cell Padding",
|
|
1707
|
+
cellPaddingPx: "Cell Padding (px)"
|
|
1628
1708
|
},
|
|
1629
1709
|
video: {
|
|
1630
1710
|
ariaLabel: "Video actions",
|
|
@@ -1816,6 +1896,7 @@
|
|
|
1816
1896
|
replaceBtn: "Thay thế",
|
|
1817
1897
|
replaceAllBtn: "Thay thế tất cả",
|
|
1818
1898
|
noResults: "Không có kết quả",
|
|
1899
|
+
useRegex: "Dùng biểu thức chính quy",
|
|
1819
1900
|
close: "×"
|
|
1820
1901
|
},
|
|
1821
1902
|
shortcutsDialog: {
|
|
@@ -1957,7 +2038,8 @@
|
|
|
1957
2038
|
enableWordWrap: "Bật xuống dòng",
|
|
1958
2039
|
disableWordWrap: "Tắt xuống dòng",
|
|
1959
2040
|
convertToParagraph: "Chuyển thành đoạn văn",
|
|
1960
|
-
deleteCodeBlock: "Xóa khối mã"
|
|
2041
|
+
deleteCodeBlock: "Xóa khối mã",
|
|
2042
|
+
lineNumbers: "Bật/Tắt số dòng"
|
|
1961
2043
|
},
|
|
1962
2044
|
table: {
|
|
1963
2045
|
ariaLabel: "Hành động bảng",
|
|
@@ -1981,7 +2063,12 @@
|
|
|
1981
2063
|
rowHeightPx: "Chiều cao hàng (px)",
|
|
1982
2064
|
tableBorderWidthPx: "Độ rộng viền bảng (px)",
|
|
1983
2065
|
cancelBtn: "Hủy",
|
|
1984
|
-
applyBtn: "Áp dụng"
|
|
2066
|
+
applyBtn: "Áp dụng",
|
|
2067
|
+
sortAsc: "Sắp xếp tăng dần",
|
|
2068
|
+
sortDesc: "Sắp xếp giảm dần",
|
|
2069
|
+
exportCSV: "Xuất CSV",
|
|
2070
|
+
cellPadding: "Khoảng đệm ô",
|
|
2071
|
+
cellPaddingPx: "Khoảng đệm ô (px)"
|
|
1985
2072
|
},
|
|
1986
2073
|
video: {
|
|
1987
2074
|
ariaLabel: "Hành động video",
|
|
@@ -1999,6 +2086,12 @@
|
|
|
1999
2086
|
errors: {
|
|
2000
2087
|
imageFormat: (type) => `Định dạng "${type}" không được hỗ trợ hiển thị trên trình duyệt. Vui lòng chuyển đổi sang JPEG, PNG hoặc WebP.`,
|
|
2001
2088
|
imageSize: (maxSize) => `Tệp hình ảnh quá lớn. Kích thước tối đa cho phép là ${maxSize} MB.`
|
|
2089
|
+
},
|
|
2090
|
+
autoSaveRestore: {
|
|
2091
|
+
found: "Tìm thấy bản nháp. Khôi phục?",
|
|
2092
|
+
foundAt: "Bản nháp từ {date}. Khôi phục?",
|
|
2093
|
+
restore: "Khôi phục",
|
|
2094
|
+
discard: "Bỏ qua"
|
|
2002
2095
|
}
|
|
2003
2096
|
},
|
|
2004
2097
|
ja: {
|
|
@@ -2148,6 +2241,7 @@
|
|
|
2148
2241
|
replaceAriaLabel: "置換後のテキスト",
|
|
2149
2242
|
replaceBtn: "置換",
|
|
2150
2243
|
noResults: "結果なし",
|
|
2244
|
+
useRegex: "正規表現を使用",
|
|
2151
2245
|
replaceAllBtn: "すべて置換",
|
|
2152
2246
|
close: "×"
|
|
2153
2247
|
},
|
|
@@ -2290,7 +2384,8 @@
|
|
|
2290
2384
|
enableWordWrap: "折り返しを有効にする",
|
|
2291
2385
|
disableWordWrap: "折り返しを無効にする",
|
|
2292
2386
|
convertToParagraph: "段落に変換",
|
|
2293
|
-
deleteCodeBlock: "コードブロックを削除"
|
|
2387
|
+
deleteCodeBlock: "コードブロックを削除",
|
|
2388
|
+
lineNumbers: "行番号を切り替え"
|
|
2294
2389
|
},
|
|
2295
2390
|
table: {
|
|
2296
2391
|
ariaLabel: "テーブル操作",
|
|
@@ -2312,7 +2407,12 @@
|
|
|
2312
2407
|
rowHeightPx: "行の高さ (px)",
|
|
2313
2408
|
tableBorderWidthPx: "テーブルの枠幅 (px)",
|
|
2314
2409
|
cancelBtn: "キャンセル",
|
|
2315
|
-
applyBtn: "適用"
|
|
2410
|
+
applyBtn: "適用",
|
|
2411
|
+
sortAsc: "昇順で並べ替え",
|
|
2412
|
+
sortDesc: "降順で並べ替え",
|
|
2413
|
+
exportCSV: "CSVとしてエクスポート",
|
|
2414
|
+
cellPadding: "セルの余白",
|
|
2415
|
+
cellPaddingPx: "セルの余白 (px)"
|
|
2316
2416
|
},
|
|
2317
2417
|
video: {
|
|
2318
2418
|
ariaLabel: "動画操作",
|
|
@@ -2330,6 +2430,12 @@
|
|
|
2330
2430
|
errors: {
|
|
2331
2431
|
imageFormat: (type) => `形式 "${type}" はブラウザでの表示をサポートしていません。JPEG、PNG、または WebP に変換してください。`,
|
|
2332
2432
|
imageSize: (maxSize) => `画像ファイルが大きすぎます。最大許容サイズは ${maxSize} MB です。`
|
|
2433
|
+
},
|
|
2434
|
+
autoSaveRestore: {
|
|
2435
|
+
found: "下書きが見つかりました。復元しますか?",
|
|
2436
|
+
foundAt: "{date} の下書きが見つかりました。復元しますか?",
|
|
2437
|
+
restore: "復元",
|
|
2438
|
+
discard: "破棄"
|
|
2333
2439
|
}
|
|
2334
2440
|
},
|
|
2335
2441
|
zh: {
|
|
@@ -2479,6 +2585,7 @@
|
|
|
2479
2585
|
replaceAriaLabel: "替换为",
|
|
2480
2586
|
replaceBtn: "替换",
|
|
2481
2587
|
noResults: "没有结果",
|
|
2588
|
+
useRegex: "使用正则表达式",
|
|
2482
2589
|
replaceAllBtn: "全部替换",
|
|
2483
2590
|
close: "×"
|
|
2484
2591
|
},
|
|
@@ -2621,7 +2728,8 @@
|
|
|
2621
2728
|
enableWordWrap: "启用自动换行",
|
|
2622
2729
|
disableWordWrap: "禁用自动换行",
|
|
2623
2730
|
convertToParagraph: "转换为段落",
|
|
2624
|
-
deleteCodeBlock: "删除代码块"
|
|
2731
|
+
deleteCodeBlock: "删除代码块",
|
|
2732
|
+
lineNumbers: "切换行号"
|
|
2625
2733
|
},
|
|
2626
2734
|
table: {
|
|
2627
2735
|
ariaLabel: "表格操作",
|
|
@@ -2643,7 +2751,12 @@
|
|
|
2643
2751
|
rowHeightPx: "行高 (px)",
|
|
2644
2752
|
tableBorderWidthPx: "表格边框宽度 (px)",
|
|
2645
2753
|
cancelBtn: "取消",
|
|
2646
|
-
applyBtn: "应用"
|
|
2754
|
+
applyBtn: "应用",
|
|
2755
|
+
sortAsc: "升序排列",
|
|
2756
|
+
sortDesc: "降序排列",
|
|
2757
|
+
exportCSV: "导出为 CSV",
|
|
2758
|
+
cellPadding: "单元格内边距",
|
|
2759
|
+
cellPaddingPx: "单元格内边距 (px)"
|
|
2647
2760
|
},
|
|
2648
2761
|
video: {
|
|
2649
2762
|
ariaLabel: "视频操作",
|
|
@@ -2661,6 +2774,12 @@
|
|
|
2661
2774
|
errors: {
|
|
2662
2775
|
imageFormat: (type) => `格式 "${type}" 不支持在浏览器中显示。请转换为 JPEG、PNG 或 WebP。`,
|
|
2663
2776
|
imageSize: (maxSize) => `图片文件过大。最大允许大小为 ${maxSize} MB。`
|
|
2777
|
+
},
|
|
2778
|
+
autoSaveRestore: {
|
|
2779
|
+
found: "找到草稿。是否恢复?",
|
|
2780
|
+
foundAt: "发现 {date} 的草稿。是否恢复?",
|
|
2781
|
+
restore: "恢复",
|
|
2782
|
+
discard: "放弃"
|
|
2664
2783
|
}
|
|
2665
2784
|
},
|
|
2666
2785
|
fr: {
|
|
@@ -2810,6 +2929,7 @@
|
|
|
2810
2929
|
replaceAriaLabel: "Remplacer par",
|
|
2811
2930
|
replaceBtn: "Remplacer",
|
|
2812
2931
|
noResults: "Aucun résultat",
|
|
2932
|
+
useRegex: "Utiliser une expression régulière",
|
|
2813
2933
|
replaceAllBtn: "Tout remplacer",
|
|
2814
2934
|
close: "×"
|
|
2815
2935
|
},
|
|
@@ -2952,7 +3072,8 @@
|
|
|
2952
3072
|
enableWordWrap: "Activer le retour à la ligne",
|
|
2953
3073
|
disableWordWrap: "Désactiver le retour à la ligne",
|
|
2954
3074
|
convertToParagraph: "Convertir en paragraphe",
|
|
2955
|
-
deleteCodeBlock: "Supprimer le bloc de code"
|
|
3075
|
+
deleteCodeBlock: "Supprimer le bloc de code",
|
|
3076
|
+
lineNumbers: "Activer/désactiver les numéros de ligne"
|
|
2956
3077
|
},
|
|
2957
3078
|
table: {
|
|
2958
3079
|
ariaLabel: "Actions du tableau",
|
|
@@ -2974,7 +3095,12 @@
|
|
|
2974
3095
|
rowHeightPx: "Hauteur de ligne (px)",
|
|
2975
3096
|
tableBorderWidthPx: "Épaisseur des bordures (px)",
|
|
2976
3097
|
cancelBtn: "Annuler",
|
|
2977
|
-
applyBtn: "Appliquer"
|
|
3098
|
+
applyBtn: "Appliquer",
|
|
3099
|
+
sortAsc: "Trier par ordre croissant",
|
|
3100
|
+
sortDesc: "Trier par ordre décroissant",
|
|
3101
|
+
exportCSV: "Exporter en CSV",
|
|
3102
|
+
cellPadding: "Rembourrage des cellules",
|
|
3103
|
+
cellPaddingPx: "Rembourrage des cellules (px)"
|
|
2978
3104
|
},
|
|
2979
3105
|
video: {
|
|
2980
3106
|
ariaLabel: "Actions de la vidéo",
|
|
@@ -2992,6 +3118,12 @@
|
|
|
2992
3118
|
errors: {
|
|
2993
3119
|
imageFormat: (type) => `Le format "${type}" n'est pas pris en charge par le navigateur. Veuillez le convertir en JPEG, PNG ou WebP.`,
|
|
2994
3120
|
imageSize: (maxSize) => `Le fichier image est trop volumineux. La taille maximale autorisée est de ${maxSize}\u00a0Mo.`
|
|
3121
|
+
},
|
|
3122
|
+
autoSaveRestore: {
|
|
3123
|
+
found: "Brouillon trouvé. Restaurer ?",
|
|
3124
|
+
foundAt: "Brouillon du {date}. Restaurer ?",
|
|
3125
|
+
restore: "Restaurer",
|
|
3126
|
+
discard: "Ignorer"
|
|
2995
3127
|
}
|
|
2996
3128
|
},
|
|
2997
3129
|
de: {
|
|
@@ -3141,6 +3273,7 @@
|
|
|
3141
3273
|
replaceAriaLabel: "Ersetzen durch",
|
|
3142
3274
|
replaceBtn: "Ersetzen",
|
|
3143
3275
|
noResults: "Keine Ergebnisse",
|
|
3276
|
+
useRegex: "Regulären Ausdruck verwenden",
|
|
3144
3277
|
replaceAllBtn: "Alle ersetzen",
|
|
3145
3278
|
close: "×"
|
|
3146
3279
|
},
|
|
@@ -3283,7 +3416,8 @@
|
|
|
3283
3416
|
enableWordWrap: "Zeilenumbruch aktivieren",
|
|
3284
3417
|
disableWordWrap: "Zeilenumbruch deaktivieren",
|
|
3285
3418
|
convertToParagraph: "In Absatz umwandeln",
|
|
3286
|
-
deleteCodeBlock: "Codeblock löschen"
|
|
3419
|
+
deleteCodeBlock: "Codeblock löschen",
|
|
3420
|
+
lineNumbers: "Zeilennummern umschalten"
|
|
3287
3421
|
},
|
|
3288
3422
|
table: {
|
|
3289
3423
|
ariaLabel: "Tabellen-Aktionen",
|
|
@@ -3305,7 +3439,12 @@
|
|
|
3305
3439
|
rowHeightPx: "Zeilenhöhe (px)",
|
|
3306
3440
|
tableBorderWidthPx: "Tabellenrahmenbreite (px)",
|
|
3307
3441
|
cancelBtn: "Abbrechen",
|
|
3308
|
-
applyBtn: "Anwenden"
|
|
3442
|
+
applyBtn: "Anwenden",
|
|
3443
|
+
sortAsc: "Aufsteigend sortieren",
|
|
3444
|
+
sortDesc: "Absteigend sortieren",
|
|
3445
|
+
exportCSV: "Als CSV exportieren",
|
|
3446
|
+
cellPadding: "Zellauffüllung",
|
|
3447
|
+
cellPaddingPx: "Zellauffüllung (px)"
|
|
3309
3448
|
},
|
|
3310
3449
|
video: {
|
|
3311
3450
|
ariaLabel: "Video-Aktionen",
|
|
@@ -3323,6 +3462,12 @@
|
|
|
3323
3462
|
errors: {
|
|
3324
3463
|
imageFormat: (type) => `Das Format „${type}" wird in Webbrowsern nicht unterstützt. Bitte konvertieren Sie es zuerst in JPEG, PNG oder WebP.`,
|
|
3325
3464
|
imageSize: (maxSize) => `Die Bilddatei ist zu groß. Die maximal zulässige Größe beträgt ${maxSize} MB.`
|
|
3465
|
+
},
|
|
3466
|
+
autoSaveRestore: {
|
|
3467
|
+
found: "Entwurf gefunden. Wiederherstellen?",
|
|
3468
|
+
foundAt: "Entwurf vom {date}. Wiederherstellen?",
|
|
3469
|
+
restore: "Wiederherstellen",
|
|
3470
|
+
discard: "Verwerfen"
|
|
3326
3471
|
}
|
|
3327
3472
|
},
|
|
3328
3473
|
es: {
|
|
@@ -3472,6 +3617,7 @@
|
|
|
3472
3617
|
replaceAriaLabel: "Reemplazar con",
|
|
3473
3618
|
replaceBtn: "Reemplazar",
|
|
3474
3619
|
noResults: "Sin resultados",
|
|
3620
|
+
useRegex: "Usar expresión regular",
|
|
3475
3621
|
replaceAllBtn: "Reemplazar todo",
|
|
3476
3622
|
close: "×"
|
|
3477
3623
|
},
|
|
@@ -3614,7 +3760,8 @@
|
|
|
3614
3760
|
enableWordWrap: "Activar ajuste de línea",
|
|
3615
3761
|
disableWordWrap: "Desactivar ajuste de línea",
|
|
3616
3762
|
convertToParagraph: "Convertir en párrafo",
|
|
3617
|
-
deleteCodeBlock: "Eliminar bloque de código"
|
|
3763
|
+
deleteCodeBlock: "Eliminar bloque de código",
|
|
3764
|
+
lineNumbers: "Alternar números de línea"
|
|
3618
3765
|
},
|
|
3619
3766
|
table: {
|
|
3620
3767
|
ariaLabel: "Acciones de tabla",
|
|
@@ -3636,7 +3783,12 @@
|
|
|
3636
3783
|
rowHeightPx: "Alto de fila (px)",
|
|
3637
3784
|
tableBorderWidthPx: "Grosor del borde (px)",
|
|
3638
3785
|
cancelBtn: "Cancelar",
|
|
3639
|
-
applyBtn: "Aplicar"
|
|
3786
|
+
applyBtn: "Aplicar",
|
|
3787
|
+
sortAsc: "Ordenar ascendente",
|
|
3788
|
+
sortDesc: "Ordenar descendente",
|
|
3789
|
+
exportCSV: "Exportar como CSV",
|
|
3790
|
+
cellPadding: "Relleno de celda",
|
|
3791
|
+
cellPaddingPx: "Relleno de celda (px)"
|
|
3640
3792
|
},
|
|
3641
3793
|
video: {
|
|
3642
3794
|
ariaLabel: "Acciones de vídeo",
|
|
@@ -3654,6 +3806,12 @@
|
|
|
3654
3806
|
errors: {
|
|
3655
3807
|
imageFormat: (type) => `El formato "${type}" no es compatible con los navegadores web. Por favor, conviértalo primero a JPEG, PNG o WebP.`,
|
|
3656
3808
|
imageSize: (maxSize) => `El archivo de imagen es demasiado grande. El tamaño máximo permitido es ${maxSize} MB.`
|
|
3809
|
+
},
|
|
3810
|
+
autoSaveRestore: {
|
|
3811
|
+
found: "Borrador encontrado. ¿Restaurar?",
|
|
3812
|
+
foundAt: "Borrador del {date}. ¿Restaurar?",
|
|
3813
|
+
restore: "Restaurar",
|
|
3814
|
+
discard: "Descartar"
|
|
3657
3815
|
}
|
|
3658
3816
|
},
|
|
3659
3817
|
ko: {
|
|
@@ -3803,6 +3961,7 @@
|
|
|
3803
3961
|
replaceAriaLabel: "바꿀 내용",
|
|
3804
3962
|
replaceBtn: "바꾸기",
|
|
3805
3963
|
noResults: "결과 없음",
|
|
3964
|
+
useRegex: "정규식 사용",
|
|
3806
3965
|
replaceAllBtn: "모두 바꾸기",
|
|
3807
3966
|
close: "×"
|
|
3808
3967
|
},
|
|
@@ -3945,7 +4104,8 @@
|
|
|
3945
4104
|
enableWordWrap: "줄 바꿈 사용",
|
|
3946
4105
|
disableWordWrap: "줄 바꿈 해제",
|
|
3947
4106
|
convertToParagraph: "단락으로 변환",
|
|
3948
|
-
deleteCodeBlock: "코드 블록 삭제"
|
|
4107
|
+
deleteCodeBlock: "코드 블록 삭제",
|
|
4108
|
+
lineNumbers: "줄 번호 전환"
|
|
3949
4109
|
},
|
|
3950
4110
|
table: {
|
|
3951
4111
|
ariaLabel: "표 작업",
|
|
@@ -3967,7 +4127,12 @@
|
|
|
3967
4127
|
rowHeightPx: "행 높이 (px)",
|
|
3968
4128
|
tableBorderWidthPx: "표 테두리 너비 (px)",
|
|
3969
4129
|
cancelBtn: "취소",
|
|
3970
|
-
applyBtn: "적용"
|
|
4130
|
+
applyBtn: "적용",
|
|
4131
|
+
sortAsc: "오름차순 정렬",
|
|
4132
|
+
sortDesc: "내림차순 정렬",
|
|
4133
|
+
exportCSV: "CSV로 내보내기",
|
|
4134
|
+
cellPadding: "셀 패딩",
|
|
4135
|
+
cellPaddingPx: "셀 패딩 (px)"
|
|
3971
4136
|
},
|
|
3972
4137
|
video: {
|
|
3973
4138
|
ariaLabel: "동영상 작업",
|
|
@@ -3985,6 +4150,12 @@
|
|
|
3985
4150
|
errors: {
|
|
3986
4151
|
imageFormat: (type) => `"${type}" 형식은 웹 브라우저에서 지원되지 않습니다. JPEG, PNG 또는 WebP로 변환해 주세요.`,
|
|
3987
4152
|
imageSize: (maxSize) => `이미지 파일이 너무 큽니다. 최대 허용 크기는 ${maxSize} MB입니다.`
|
|
4153
|
+
},
|
|
4154
|
+
autoSaveRestore: {
|
|
4155
|
+
found: "초안을 찾았습니다. 복원하시겠습니까?",
|
|
4156
|
+
foundAt: "{date}의 초안을 찾았습니다. 복원하시겠습니까?",
|
|
4157
|
+
restore: "복원",
|
|
4158
|
+
discard: "삭제"
|
|
3988
4159
|
}
|
|
3989
4160
|
}
|
|
3990
4161
|
};
|
|
@@ -4181,6 +4352,9 @@
|
|
|
4181
4352
|
if (options.theme === "dark") {
|
|
4182
4353
|
container.classList.add("an-theme-dark");
|
|
4183
4354
|
document.body.classList.add("an-theme-dark");
|
|
4355
|
+
} else if (options.theme === "auto") {
|
|
4356
|
+
container.classList.add("an-theme-auto");
|
|
4357
|
+
document.body.classList.add("an-theme-auto");
|
|
4184
4358
|
}
|
|
4185
4359
|
if (options.readOnly) {
|
|
4186
4360
|
container.classList.add("an-disabled");
|
|
@@ -4406,6 +4580,14 @@
|
|
|
4406
4580
|
canRedo() {
|
|
4407
4581
|
return this.stackOffset < this.stack.length - 1;
|
|
4408
4582
|
}
|
|
4583
|
+
/** @returns {number} */
|
|
4584
|
+
getUndoCount() {
|
|
4585
|
+
return Math.max(0, this.stackOffset);
|
|
4586
|
+
}
|
|
4587
|
+
/** @returns {number} */
|
|
4588
|
+
getRedoCount() {
|
|
4589
|
+
return Math.max(0, this.stack.length - 1 - this.stackOffset);
|
|
4590
|
+
}
|
|
4409
4591
|
};
|
|
4410
4592
|
//#endregion
|
|
4411
4593
|
//#region src/js/editing/Table.js
|
|
@@ -5478,6 +5660,12 @@
|
|
|
5478
5660
|
canRedo() {
|
|
5479
5661
|
return this._history ? this._history.canRedo() : false;
|
|
5480
5662
|
}
|
|
5663
|
+
getUndoCount() {
|
|
5664
|
+
return this._history ? this._history.getUndoCount() : 0;
|
|
5665
|
+
}
|
|
5666
|
+
getRedoCount() {
|
|
5667
|
+
return this._history ? this._history.getRedoCount() : 0;
|
|
5668
|
+
}
|
|
5481
5669
|
bold() {
|
|
5482
5670
|
bold();
|
|
5483
5671
|
this.afterCommand();
|
|
@@ -6339,9 +6527,21 @@
|
|
|
6339
6527
|
this._bindResize(handle);
|
|
6340
6528
|
this.el.appendChild(handle);
|
|
6341
6529
|
}
|
|
6342
|
-
this._wordCountEl = createElement("span", {
|
|
6343
|
-
|
|
6344
|
-
|
|
6530
|
+
this._wordCountEl = createElement("span", {
|
|
6531
|
+
class: "an-word-count",
|
|
6532
|
+
role: "status",
|
|
6533
|
+
"aria-live": "polite",
|
|
6534
|
+
"aria-atomic": "true"
|
|
6535
|
+
});
|
|
6536
|
+
this._charCountEl = createElement("span", {
|
|
6537
|
+
class: "an-char-count",
|
|
6538
|
+
"aria-live": "polite",
|
|
6539
|
+
"aria-atomic": "true"
|
|
6540
|
+
});
|
|
6541
|
+
const info = createElement("div", {
|
|
6542
|
+
class: "an-status-info",
|
|
6543
|
+
"aria-label": "Editor statistics"
|
|
6544
|
+
});
|
|
6345
6545
|
info.appendChild(this._wordCountEl);
|
|
6346
6546
|
info.appendChild(this._charCountEl);
|
|
6347
6547
|
this.el.appendChild(info);
|
|
@@ -6581,6 +6781,15 @@
|
|
|
6581
6781
|
if (!clipboardData) return;
|
|
6582
6782
|
const forcePlain = this._forcePlain;
|
|
6583
6783
|
this._forcePlain = false;
|
|
6784
|
+
const maxBytes = (this.options.maxPasteSize ?? 5) * 1024 * 1024;
|
|
6785
|
+
if (maxBytes > 0) {
|
|
6786
|
+
const text = clipboardData.getData("text/plain") || "";
|
|
6787
|
+
const html = clipboardData.getData("text/html") || "";
|
|
6788
|
+
if (Math.max(text.length, html.length) > maxBytes) {
|
|
6789
|
+
event.preventDefault();
|
|
6790
|
+
return;
|
|
6791
|
+
}
|
|
6792
|
+
}
|
|
6584
6793
|
if (clipboardData.items) {
|
|
6585
6794
|
const imageItems = Array.from(clipboardData.items).filter((item) => item.kind === "file" && item.type.startsWith("image/"));
|
|
6586
6795
|
if (imageItems.length > 0) {
|
|
@@ -6999,6 +7208,10 @@
|
|
|
6999
7208
|
this._firstInput = null;
|
|
7000
7209
|
this._removeTrap = null;
|
|
7001
7210
|
}
|
|
7211
|
+
/** @returns {HTMLElement} */
|
|
7212
|
+
_buildDialog() {
|
|
7213
|
+
throw new Error("_buildDialog() must be implemented by subclass");
|
|
7214
|
+
}
|
|
7002
7215
|
initialize() {
|
|
7003
7216
|
this._dialog = this._buildDialog();
|
|
7004
7217
|
document.body.appendChild(this._dialog);
|
|
@@ -7699,6 +7912,7 @@
|
|
|
7699
7912
|
const aspectRatio = startW / (startH || 1);
|
|
7700
7913
|
const isCorner = pos.length === 2;
|
|
7701
7914
|
const editable = this.context.layoutInfo.editable;
|
|
7915
|
+
const minSz = this.context.options?.minImageSize ?? 20;
|
|
7702
7916
|
let _raf = null;
|
|
7703
7917
|
const onMove = (me) => {
|
|
7704
7918
|
if (_raf !== null) return;
|
|
@@ -7711,15 +7925,15 @@
|
|
|
7711
7925
|
const maxW = editable.clientWidth || Infinity;
|
|
7712
7926
|
let newW = startW;
|
|
7713
7927
|
let newH = startH;
|
|
7714
|
-
if (pos.includes("e")) newW = Math.max(
|
|
7715
|
-
if (pos.includes("w")) newW = Math.max(
|
|
7716
|
-
if (pos.includes("s")) newH = Math.max(
|
|
7717
|
-
if (pos.includes("n")) newH = Math.max(
|
|
7928
|
+
if (pos.includes("e")) newW = Math.max(minSz, startW + dx);
|
|
7929
|
+
if (pos.includes("w")) newW = Math.max(minSz, startW - dx);
|
|
7930
|
+
if (pos.includes("s")) newH = Math.max(minSz, startH + dy);
|
|
7931
|
+
if (pos.includes("n")) newH = Math.max(minSz, startH - dy);
|
|
7718
7932
|
newW = Math.min(newW, maxW);
|
|
7719
|
-
if (isCorner) if (Math.abs(dx) >= Math.abs(dy)) newH = Math.max(
|
|
7933
|
+
if (isCorner) if (Math.abs(dx) >= Math.abs(dy)) newH = Math.max(minSz, Math.round(newW / aspectRatio));
|
|
7720
7934
|
else {
|
|
7721
|
-
newW = Math.min(Math.max(
|
|
7722
|
-
newH = Math.max(
|
|
7935
|
+
newW = Math.min(Math.max(minSz, Math.round(newH * aspectRatio)), maxW);
|
|
7936
|
+
newH = Math.max(minSz, Math.round(newW / aspectRatio));
|
|
7723
7937
|
}
|
|
7724
7938
|
img.style.width = `${newW}px`;
|
|
7725
7939
|
img.style.height = `${newH}px`;
|
|
@@ -8781,7 +8995,17 @@
|
|
|
8781
8995
|
tableBorder: `<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round"><line x1="3" y1="6" x2="21" y2="6" stroke-width="1"/><line x1="3" y1="13" x2="21" y2="13" stroke-width="2"/><line x1="3" y1="20" x2="21" y2="20" stroke-width="3"/></svg>`,
|
|
8782
8996
|
deleteTable: `<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" 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"/><line x1="16" y1="16" x2="22" y2="22" stroke="#ef4444"/><line x1="22" y1="16" x2="16" y2="22" stroke="#ef4444"/></svg>`,
|
|
8783
8997
|
selectCells: `<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><path d="M4 4 L4 20 L9 15 L12 21 L14 20 L11 14 L17 14 Z" fill="currentColor" opacity="0.15"/><path d="M4 4 L4 20 L9 15 L12 21 L14 20 L11 14 L17 14 Z"/></svg>`,
|
|
8784
|
-
cellShade: `<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 11L8.93 3.36a1 1 0 0 0-1.29.08L3.22 7.8a1 1 0 0 0-.07 1.29L11 20"/><path d="m5 14 5-5"/><path d="M22 22a2 2 0 0 1-2 2h-3a2 2 0 0 1-2-2c0-1.5 2.5-5 3.5-5s3.5 3.5 3.5 5z"/></svg
|
|
8998
|
+
cellShade: `<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 11L8.93 3.36a1 1 0 0 0-1.29.08L3.22 7.8a1 1 0 0 0-.07 1.29L11 20"/><path d="m5 14 5-5"/><path d="M22 22a2 2 0 0 1-2 2h-3a2 2 0 0 1-2-2c0-1.5 2.5-5 3.5-5s3.5 3.5 3.5 5z"/></svg>`,
|
|
8999
|
+
borderColor: `<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" 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="14" rx="1"/><line x1="3" y1="10" x2="21" y2="10" stroke-width="1.5"/><line x1="12" y1="3" x2="12" y2="17" stroke-width="1.5"/><path d="M3 21h18" stroke-width="3"/></svg>`,
|
|
9000
|
+
alignLeft: `<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="21" y1="6" x2="3" y2="6"/><line x1="15" y1="12" x2="3" y2="12"/><line x1="17" y1="18" x2="3" y2="18"/></svg>`,
|
|
9001
|
+
alignCenter: `<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="21" y1="6" x2="3" y2="6"/><line x1="17" y1="12" x2="7" y2="12"/><line x1="19" y1="18" x2="5" y2="18"/></svg>`,
|
|
9002
|
+
alignRight: `<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="21" y1="6" x2="3" y2="6"/><line x1="21" y1="12" x2="9" y2="12"/><line x1="21" y1="18" x2="7" y2="18"/></svg>`,
|
|
9003
|
+
alignJustify: `<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="21" y1="6" x2="3" y2="6"/><line x1="21" y1="12" x2="3" y2="12"/><line x1="21" y1="18" x2="3" y2="18"/></svg>`,
|
|
9004
|
+
headerRow: `<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" 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"/><rect x="3" y="3" width="18" height="8" rx="1" fill="currentColor" opacity="0.2"/><line x1="3" y1="11" x2="21" y2="11"/><line x1="3" y1="16" x2="21" y2="16"/><line x1="9" y1="11" x2="9" y2="21"/><line x1="15" y1="11" x2="15" y2="21"/></svg>`,
|
|
9005
|
+
sortAsc: `<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="4" y1="6" x2="11" y2="6"/><line x1="4" y1="12" x2="11" y2="12"/><line x1="4" y1="18" x2="13" y2="18"/><path d="M15 9l3-3 3 3"/><line x1="18" y1="6" x2="18" y2="18"/></svg>`,
|
|
9006
|
+
sortDesc: `<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="4" y1="6" x2="13" y2="6"/><line x1="4" y1="12" x2="11" y2="12"/><line x1="4" y1="18" x2="11" y2="18"/><path d="M15 15l3 3 3-3"/><line x1="18" y1="6" x2="18" y2="18"/></svg>`,
|
|
9007
|
+
exportCSV: `<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>`,
|
|
9008
|
+
cellPadding: `<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" 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"/><rect x="7" y="7" width="10" height="10" rx="0.5" stroke-dasharray="2 1.5"/></svg>`
|
|
8785
9009
|
};
|
|
8786
9010
|
var SHADE_PRESETS = [
|
|
8787
9011
|
"#000000",
|
|
@@ -8826,6 +9050,10 @@
|
|
|
8826
9050
|
this._shadePopover = null;
|
|
8827
9051
|
this._shadeTitleEl = null;
|
|
8828
9052
|
this._shadeColorStrip = null;
|
|
9053
|
+
this._borderColorPopover = null;
|
|
9054
|
+
this._borderColorTitleEl = null;
|
|
9055
|
+
this._borderColorStrip = null;
|
|
9056
|
+
this._borderColorNoBtn = null;
|
|
8829
9057
|
this._selectMode = false;
|
|
8830
9058
|
this._selectedCells = [];
|
|
8831
9059
|
this._selectStart = null;
|
|
@@ -8840,6 +9068,8 @@
|
|
|
8840
9068
|
document.body.appendChild(this._sizePopover);
|
|
8841
9069
|
this._shadePopover = this._buildCellShadePopover();
|
|
8842
9070
|
document.body.appendChild(this._shadePopover);
|
|
9071
|
+
this._borderColorPopover = this._buildBorderColorPopover();
|
|
9072
|
+
document.body.appendChild(this._borderColorPopover);
|
|
8843
9073
|
const editable = this.context.layoutInfo.editable;
|
|
8844
9074
|
this._editable = editable;
|
|
8845
9075
|
const onSelMousedown = (e) => {
|
|
@@ -8881,7 +9111,7 @@
|
|
|
8881
9111
|
}, { passive: true }), on(document, "click", (e) => {
|
|
8882
9112
|
const et = e.target;
|
|
8883
9113
|
if (this._selectMode && this._activeTable?.contains(et)) return;
|
|
8884
|
-
if (this._activeTable && !this._activeTable.contains(et) && !this._el.contains(et) && !this._sizePopover?.contains(et)) this._hide();
|
|
9114
|
+
if (this._activeTable && !this._activeTable.contains(et) && !this._el.contains(et) && !this._sizePopover?.contains(et) && !this._borderColorPopover?.contains(et)) this._hide();
|
|
8885
9115
|
}), on(document, "selectionchange", () => this._syncShadeStrip()), on(globalThis, "scroll", () => this._hide(), { passive: true }), on(globalThis, "resize", () => this._hide(), { passive: true }));
|
|
8886
9116
|
this._initResize();
|
|
8887
9117
|
return this;
|
|
@@ -9016,6 +9246,8 @@
|
|
|
9016
9246
|
this._sizePopover = null;
|
|
9017
9247
|
if (this._shadePopover?.parentNode) this._shadePopover.remove();
|
|
9018
9248
|
this._shadePopover = null;
|
|
9249
|
+
if (this._borderColorPopover?.parentNode) this._borderColorPopover.remove();
|
|
9250
|
+
this._borderColorPopover = null;
|
|
9019
9251
|
}
|
|
9020
9252
|
_buildTooltip() {
|
|
9021
9253
|
const L = this.context.locale.tooltips.table;
|
|
@@ -9039,10 +9271,18 @@
|
|
|
9039
9271
|
el.appendChild(this._makeBtn(ICONS$2.colLeft, L.addColumnLeft, () => this._addColumn("left")));
|
|
9040
9272
|
el.appendChild(this._makeBtn(ICONS$2.colRight, L.addColumnRight, () => this._addColumn("right")));
|
|
9041
9273
|
el.appendChild(this._makeBtn(ICONS$2.deleteCol, L.deleteColumn, () => this._deleteColumn()));
|
|
9274
|
+
el.appendChild(this._makeBtn(ICONS$2.sortAsc, L.sortAsc, () => this._sortColumn("asc")));
|
|
9275
|
+
el.appendChild(this._makeBtn(ICONS$2.sortDesc, L.sortDesc, () => this._sortColumn("desc")));
|
|
9042
9276
|
el.appendChild(this._sep());
|
|
9043
9277
|
el.appendChild(this._makeBtn(ICONS$2.mergeCells, L.mergeCells, () => this._mergeCells()));
|
|
9044
9278
|
el.appendChild(this._makeBtn(ICONS$2.unmergeCells, L.unmergeCells, () => this._unmergeCells()));
|
|
9045
9279
|
el.appendChild(this._sep());
|
|
9280
|
+
el.appendChild(this._makeBtn(ICONS$2.alignLeft, L.cellAlignLeft, () => this._applyCellAlign("left")));
|
|
9281
|
+
el.appendChild(this._makeBtn(ICONS$2.alignCenter, L.cellAlignCenter, () => this._applyCellAlign("center")));
|
|
9282
|
+
el.appendChild(this._makeBtn(ICONS$2.alignRight, L.cellAlignRight, () => this._applyCellAlign("right")));
|
|
9283
|
+
el.appendChild(this._makeBtn(ICONS$2.alignJustify, L.cellAlignJustify, () => this._applyCellAlign("justify")));
|
|
9284
|
+
el.appendChild(this._makeBtn(ICONS$2.headerRow, L.toggleHeaderRow, () => this._toggleHeaderRow()));
|
|
9285
|
+
el.appendChild(this._sep());
|
|
9046
9286
|
const shadeBtn = createElement("button", {
|
|
9047
9287
|
type: "button",
|
|
9048
9288
|
class: "an-link-tooltip-btn an-link-tooltip-btn--shade",
|
|
@@ -9064,12 +9304,33 @@
|
|
|
9064
9304
|
el.appendChild(this._makeBtn(ICONS$2.colWidth, L.columnWidth, () => this._openSizePopover("col")));
|
|
9065
9305
|
el.appendChild(this._makeBtn(ICONS$2.rowHeight, L.rowHeight, () => this._openSizePopover("row")));
|
|
9066
9306
|
el.appendChild(this._makeBtn(ICONS$2.tableBorder, L.tableBorderWidth, () => this._openSizePopover("border")));
|
|
9307
|
+
el.appendChild(this._makeBtn(ICONS$2.cellPadding, L.cellPadding, () => this._openSizePopover("cellPadding")));
|
|
9308
|
+
const borderColorBtn = createElement("button", {
|
|
9309
|
+
type: "button",
|
|
9310
|
+
class: "an-link-tooltip-btn an-link-tooltip-btn--shade",
|
|
9311
|
+
title: L.tableBorderColor
|
|
9312
|
+
});
|
|
9313
|
+
const borderColorSvgWrap = createElement("span", { class: "an-bubble-btn-svg" });
|
|
9314
|
+
borderColorSvgWrap.innerHTML = ICONS$2.borderColor;
|
|
9315
|
+
const borderColorStrip = createElement("span", { class: "an-link-tooltip-color-strip" });
|
|
9316
|
+
borderColorBtn.appendChild(borderColorSvgWrap);
|
|
9317
|
+
borderColorBtn.appendChild(borderColorStrip);
|
|
9318
|
+
this._borderColorStrip = borderColorStrip;
|
|
9319
|
+
this._disposers.push(on(borderColorBtn, "click", (e) => {
|
|
9320
|
+
e.preventDefault();
|
|
9321
|
+
e.stopPropagation();
|
|
9322
|
+
this._openBorderColorPopover();
|
|
9323
|
+
}));
|
|
9324
|
+
el.appendChild(borderColorBtn);
|
|
9067
9325
|
el.appendChild(this._sep());
|
|
9068
9326
|
el.appendChild(this._makeBtn(ICONS$2.deleteTable, L.deleteTable, () => this._deleteTable(), true));
|
|
9327
|
+
el.appendChild(this._sep());
|
|
9328
|
+
el.appendChild(this._makeBtn(ICONS$2.exportCSV, L.exportCSV, () => this._exportTableCSV()));
|
|
9069
9329
|
this._disposers.push(on(el, "mouseenter", () => this._clearTimers()), on(el, "mouseleave", () => {
|
|
9070
9330
|
if (this._selectMode) return;
|
|
9071
9331
|
if (this._sizePopover && this._sizePopover.style.display !== "none") return;
|
|
9072
9332
|
if (this._shadePopover && this._shadePopover.style.display !== "none") return;
|
|
9333
|
+
if (this._borderColorPopover && this._borderColorPopover.style.display !== "none") return;
|
|
9073
9334
|
this._scheduleHide();
|
|
9074
9335
|
}));
|
|
9075
9336
|
return el;
|
|
@@ -9117,6 +9378,7 @@
|
|
|
9117
9378
|
if (!this._activeTable) return;
|
|
9118
9379
|
this._el.style.display = "flex";
|
|
9119
9380
|
this._syncShadeStrip();
|
|
9381
|
+
this._syncBorderColorStrip();
|
|
9120
9382
|
requestAnimationFrame(() => {
|
|
9121
9383
|
if (this._activeTable) this._positionNear(this._activeTable);
|
|
9122
9384
|
});
|
|
@@ -9138,6 +9400,7 @@
|
|
|
9138
9400
|
this._clearSelection();
|
|
9139
9401
|
this._clearTimers();
|
|
9140
9402
|
this._hideSizePopover();
|
|
9403
|
+
this._hideBorderColorPopover();
|
|
9141
9404
|
}
|
|
9142
9405
|
_clearTimers() {
|
|
9143
9406
|
clearTimeout(this._showTimer);
|
|
@@ -9537,6 +9800,19 @@
|
|
|
9537
9800
|
});
|
|
9538
9801
|
this.context.invoke("editor.afterCommand");
|
|
9539
9802
|
};
|
|
9803
|
+
} else if (type === "cellPadding") {
|
|
9804
|
+
const firstCell = this._getSelectedCells()[0] || this._getCell();
|
|
9805
|
+
const currentPad = firstCell ? Number.parseInt(firstCell.style.padding, 10) || Number.parseInt(firstCell.style.paddingTop, 10) || 4 : 4;
|
|
9806
|
+
this._sizeTitleEl.textContent = this.context.locale.tooltips.table.cellPaddingPx;
|
|
9807
|
+
this._sizeInputEl.min = "0";
|
|
9808
|
+
this._sizeInputEl.max = "40";
|
|
9809
|
+
this._sizeInputEl.value = String(currentPad);
|
|
9810
|
+
this._sizeApply = (val) => {
|
|
9811
|
+
this._getSelectedCells().forEach((c) => {
|
|
9812
|
+
if (c) c.style.padding = `${val}px`;
|
|
9813
|
+
});
|
|
9814
|
+
this.context.invoke("editor.afterCommand");
|
|
9815
|
+
};
|
|
9540
9816
|
} else {
|
|
9541
9817
|
const isCol = type === "col";
|
|
9542
9818
|
const activeCells = this._getSelectedCells().filter((c) => {
|
|
@@ -9633,7 +9909,7 @@
|
|
|
9633
9909
|
value: "#ffffff"
|
|
9634
9910
|
});
|
|
9635
9911
|
const customLabel = createElement("span");
|
|
9636
|
-
customLabel.textContent =
|
|
9912
|
+
customLabel.textContent = this.context.locale.contextMenu.customColorLabel;
|
|
9637
9913
|
this._disposers.push(on(colorInput, "change", () => this._applyCellShade(colorInput.value)));
|
|
9638
9914
|
customRow.appendChild(colorInput);
|
|
9639
9915
|
customRow.appendChild(customLabel);
|
|
@@ -9674,6 +9950,172 @@
|
|
|
9674
9950
|
this._hideCellShadePopover();
|
|
9675
9951
|
this.context.invoke("editor.afterCommand");
|
|
9676
9952
|
}
|
|
9953
|
+
_buildBorderColorPopover() {
|
|
9954
|
+
const pop = createElement("div", { class: "an-cell-shade-popover" });
|
|
9955
|
+
pop.style.display = "none";
|
|
9956
|
+
const title = createElement("div", { class: "an-size-popover-title" });
|
|
9957
|
+
pop.appendChild(title);
|
|
9958
|
+
this._borderColorTitleEl = title;
|
|
9959
|
+
const palette = createElement("div", { class: "an-context-color-palette" });
|
|
9960
|
+
SHADE_PRESETS.forEach((color) => {
|
|
9961
|
+
const sw = createElement("div", {
|
|
9962
|
+
class: "an-context-color-swatch",
|
|
9963
|
+
title: color
|
|
9964
|
+
});
|
|
9965
|
+
sw.style.background = color;
|
|
9966
|
+
this._disposers.push(on(sw, "click", (e) => {
|
|
9967
|
+
e.stopPropagation();
|
|
9968
|
+
this._applyBorderColor(color);
|
|
9969
|
+
}));
|
|
9970
|
+
palette.appendChild(sw);
|
|
9971
|
+
});
|
|
9972
|
+
pop.appendChild(palette);
|
|
9973
|
+
const noColorRow = createElement("div", { class: "an-context-color-custom" });
|
|
9974
|
+
const noColorBtn = createElement("button", {
|
|
9975
|
+
type: "button",
|
|
9976
|
+
class: "an-shade-no-color"
|
|
9977
|
+
});
|
|
9978
|
+
this._disposers.push(on(noColorBtn, "click", () => this._applyBorderColor("")));
|
|
9979
|
+
noColorRow.appendChild(noColorBtn);
|
|
9980
|
+
pop.appendChild(noColorRow);
|
|
9981
|
+
this._borderColorNoBtn = noColorBtn;
|
|
9982
|
+
const customRow = createElement("div", { class: "an-context-color-custom" });
|
|
9983
|
+
const colorInput = createElement("input", {
|
|
9984
|
+
type: "color",
|
|
9985
|
+
class: "an-shade-color-input",
|
|
9986
|
+
value: "#000000"
|
|
9987
|
+
});
|
|
9988
|
+
const customLabel = createElement("span");
|
|
9989
|
+
customLabel.textContent = this.context.locale.contextMenu.customColorLabel;
|
|
9990
|
+
this._disposers.push(on(colorInput, "change", () => this._applyBorderColor(colorInput.value)));
|
|
9991
|
+
customRow.appendChild(colorInput);
|
|
9992
|
+
customRow.appendChild(customLabel);
|
|
9993
|
+
pop.appendChild(customRow);
|
|
9994
|
+
this._disposers.push(on(pop, "mousedown", (e) => e.preventDefault()), on(pop, "mouseenter", () => this._clearTimers()), on(pop, "mouseleave", () => this._scheduleHide()), on(document, "click", (e) => {
|
|
9995
|
+
const et = e.target;
|
|
9996
|
+
if (this._borderColorPopover && this._borderColorPopover.style.display !== "none" && !this._borderColorPopover.contains(et) && !this._el?.contains(et)) this._hideBorderColorPopover();
|
|
9997
|
+
}));
|
|
9998
|
+
return pop;
|
|
9999
|
+
}
|
|
10000
|
+
_openBorderColorPopover() {
|
|
10001
|
+
if (!this._borderColorPopover) return;
|
|
10002
|
+
const L = this.context.locale.tooltips.table;
|
|
10003
|
+
if (this._borderColorTitleEl) this._borderColorTitleEl.textContent = L.tableBorderColor;
|
|
10004
|
+
if (this._borderColorNoBtn) this._borderColorNoBtn.textContent = L.noBorderColor;
|
|
10005
|
+
this._borderColorPopover.style.display = "block";
|
|
10006
|
+
requestAnimationFrame(() => {
|
|
10007
|
+
if (!this._borderColorPopover || !this._el) return;
|
|
10008
|
+
const pw = this._borderColorPopover.offsetWidth || 170;
|
|
10009
|
+
const ph = this._borderColorPopover.offsetHeight || 120;
|
|
10010
|
+
const tipRect = this._el.getBoundingClientRect();
|
|
10011
|
+
let left = tipRect.left;
|
|
10012
|
+
let top = tipRect.bottom + 6;
|
|
10013
|
+
if (left + pw > globalThis.innerWidth - 8) left = globalThis.innerWidth - pw - 8;
|
|
10014
|
+
if (top + ph > globalThis.innerHeight - 8) top = tipRect.top - ph - 6;
|
|
10015
|
+
this._borderColorPopover.style.left = `${Math.max(8, left)}px`;
|
|
10016
|
+
this._borderColorPopover.style.top = `${Math.max(8, top)}px`;
|
|
10017
|
+
});
|
|
10018
|
+
}
|
|
10019
|
+
_hideBorderColorPopover() {
|
|
10020
|
+
if (this._borderColorPopover) this._borderColorPopover.style.display = "none";
|
|
10021
|
+
}
|
|
10022
|
+
_applyBorderColor(color) {
|
|
10023
|
+
const table = this._activeTable;
|
|
10024
|
+
if (!table) return;
|
|
10025
|
+
Array.from(table.querySelectorAll("td, th")).forEach((c) => {
|
|
10026
|
+
c.style.borderColor = color;
|
|
10027
|
+
});
|
|
10028
|
+
if (this._borderColorStrip) this._borderColorStrip.style.background = color || "transparent";
|
|
10029
|
+
this._hideBorderColorPopover();
|
|
10030
|
+
this.context.invoke("editor.afterCommand");
|
|
10031
|
+
}
|
|
10032
|
+
_syncBorderColorStrip() {
|
|
10033
|
+
if (!this._borderColorStrip || !this._el || this._el.style.display === "none") return;
|
|
10034
|
+
const firstCell = this._activeTable?.querySelector("td, th");
|
|
10035
|
+
this._borderColorStrip.style.background = firstCell?.style.borderColor || "transparent";
|
|
10036
|
+
}
|
|
10037
|
+
_applyCellAlign(align) {
|
|
10038
|
+
this._getSelectedCells().forEach((c) => {
|
|
10039
|
+
if (c) c.style.textAlign = align;
|
|
10040
|
+
});
|
|
10041
|
+
this.context.invoke("editor.afterCommand");
|
|
10042
|
+
}
|
|
10043
|
+
_toggleHeaderRow() {
|
|
10044
|
+
const table = this._activeTable;
|
|
10045
|
+
if (!table) return;
|
|
10046
|
+
const firstRow = table.querySelector("tr");
|
|
10047
|
+
if (!firstRow) return;
|
|
10048
|
+
if (firstRow.closest("thead") !== null) {
|
|
10049
|
+
let tbody = table.querySelector("tbody");
|
|
10050
|
+
if (!tbody) {
|
|
10051
|
+
tbody = document.createElement("tbody");
|
|
10052
|
+
table.appendChild(tbody);
|
|
10053
|
+
}
|
|
10054
|
+
Array.from(firstRow.cells).forEach((cell) => {
|
|
10055
|
+
const td = document.createElement("td");
|
|
10056
|
+
td.innerHTML = cell.innerHTML;
|
|
10057
|
+
td.style.cssText = cell.style.cssText;
|
|
10058
|
+
firstRow.replaceChild(td, cell);
|
|
10059
|
+
});
|
|
10060
|
+
tbody.insertBefore(firstRow, tbody.firstChild);
|
|
10061
|
+
const thead = table.querySelector("thead");
|
|
10062
|
+
if (thead && thead.rows.length === 0) thead.remove();
|
|
10063
|
+
} else {
|
|
10064
|
+
let thead = table.querySelector("thead");
|
|
10065
|
+
if (!thead) {
|
|
10066
|
+
thead = document.createElement("thead");
|
|
10067
|
+
table.insertBefore(thead, table.firstChild);
|
|
10068
|
+
}
|
|
10069
|
+
Array.from(firstRow.cells).forEach((cell) => {
|
|
10070
|
+
const th = document.createElement("th");
|
|
10071
|
+
th.innerHTML = cell.innerHTML;
|
|
10072
|
+
th.style.cssText = cell.style.cssText;
|
|
10073
|
+
firstRow.replaceChild(th, cell);
|
|
10074
|
+
});
|
|
10075
|
+
thead.appendChild(firstRow);
|
|
10076
|
+
}
|
|
10077
|
+
this.context.invoke("editor.afterCommand");
|
|
10078
|
+
}
|
|
10079
|
+
_sortColumn(direction) {
|
|
10080
|
+
const table = this._activeTable;
|
|
10081
|
+
if (!table) return;
|
|
10082
|
+
const cell = this._getCell();
|
|
10083
|
+
if (!cell) return;
|
|
10084
|
+
const colIdx = getVisualColIndex(cell);
|
|
10085
|
+
if (colIdx === -1) return;
|
|
10086
|
+
const tbody = table.querySelector("tbody") || table;
|
|
10087
|
+
const rows = Array.from(tbody.querySelectorAll(":scope > tr"));
|
|
10088
|
+
if (rows.length < 2) return;
|
|
10089
|
+
rows.sort((a, b) => {
|
|
10090
|
+
const aCell = getCellAtVisualCol(a, colIdx);
|
|
10091
|
+
const bCell = getCellAtVisualCol(b, colIdx);
|
|
10092
|
+
const aText = (aCell?.textContent || "").trim();
|
|
10093
|
+
const bText = (bCell?.textContent || "").trim();
|
|
10094
|
+
const aNum = parseFloat(aText);
|
|
10095
|
+
const bNum = parseFloat(bText);
|
|
10096
|
+
if (!isNaN(aNum) && !isNaN(bNum)) return direction === "asc" ? aNum - bNum : bNum - aNum;
|
|
10097
|
+
return direction === "asc" ? aText.localeCompare(bText) : bText.localeCompare(aText);
|
|
10098
|
+
});
|
|
10099
|
+
rows.forEach((row) => tbody.appendChild(row));
|
|
10100
|
+
this.context.invoke("editor.afterCommand");
|
|
10101
|
+
}
|
|
10102
|
+
_exportTableCSV() {
|
|
10103
|
+
const table = this._activeTable;
|
|
10104
|
+
if (!table) return;
|
|
10105
|
+
const csv = Array.from(table.querySelectorAll("tr")).map((row) => Array.from(row.querySelectorAll("td, th")).map((cell) => {
|
|
10106
|
+
return `"${(cell.textContent || "").trim().replace(/"/g, "\"\"")}"`;
|
|
10107
|
+
}).join(",")).join("\n");
|
|
10108
|
+
const blob = new Blob(["" + csv], { type: "text/csv;charset=utf-8;" });
|
|
10109
|
+
const url = URL.createObjectURL(blob);
|
|
10110
|
+
const a = document.createElement("a");
|
|
10111
|
+
a.href = url;
|
|
10112
|
+
a.download = "table.csv";
|
|
10113
|
+
a.style.display = "none";
|
|
10114
|
+
document.body.appendChild(a);
|
|
10115
|
+
a.click();
|
|
10116
|
+
a.remove();
|
|
10117
|
+
URL.revokeObjectURL(url);
|
|
10118
|
+
}
|
|
9677
10119
|
};
|
|
9678
10120
|
//#endregion
|
|
9679
10121
|
//#region src/js/module/CodeTooltip.js
|
|
@@ -9684,7 +10126,8 @@
|
|
|
9684
10126
|
copy: `<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>`,
|
|
9685
10127
|
wrapOn: `<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="3" y1="6" x2="21" y2="6"/><path d="M3 12h15a3 3 0 0 1 0 6H3"/><polyline points="6 15 3 18 6 21"/></svg>`,
|
|
9686
10128
|
toParagraph: `<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" 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="M9 4h8a4 4 0 0 1 0 8H9V4z"/></svg>`,
|
|
9687
|
-
deleteCode: `<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2"/></svg
|
|
10129
|
+
deleteCode: `<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2"/></svg>`,
|
|
10130
|
+
lineNumbers: `<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="10" y1="6" x2="21" y2="6"/><line x1="10" y1="12" x2="21" y2="12"/><line x1="10" y1="18" x2="21" y2="18"/><path d="M4 6h1v4"/><path d="M4 10h2"/><path d="M6 18H4c0-1 2-2 2-3s-1-2-2-2"/></svg>`
|
|
9688
10131
|
};
|
|
9689
10132
|
var CodeTooltip = class {
|
|
9690
10133
|
/** @param {import('../Context.js').Context} context */
|
|
@@ -9696,6 +10139,8 @@
|
|
|
9696
10139
|
this._hideTimer = null;
|
|
9697
10140
|
this._disposers = [];
|
|
9698
10141
|
this._copyBtn = null;
|
|
10142
|
+
this._wrapBtn = null;
|
|
10143
|
+
this._lineNumbersBtn = null;
|
|
9699
10144
|
this._langSelect = null;
|
|
9700
10145
|
this._prismScript = null;
|
|
9701
10146
|
}
|
|
@@ -9776,6 +10221,8 @@
|
|
|
9776
10221
|
el.appendChild(this._sep());
|
|
9777
10222
|
this._wrapBtn = this._makeBtn(ICONS$1.wrapOn, L.toggleWordWrap, () => this._toggleWrap());
|
|
9778
10223
|
el.appendChild(this._wrapBtn);
|
|
10224
|
+
this._lineNumbersBtn = this._makeBtn(ICONS$1.lineNumbers, L.lineNumbers, () => this._toggleLineNumbers());
|
|
10225
|
+
el.appendChild(this._lineNumbersBtn);
|
|
9779
10226
|
el.appendChild(this._sep());
|
|
9780
10227
|
el.appendChild(this._makeBtn(ICONS$1.toParagraph, L.convertToParagraph, () => this._toParagraph()));
|
|
9781
10228
|
el.appendChild(this._sep());
|
|
@@ -9814,6 +10261,7 @@
|
|
|
9814
10261
|
this._showTimer = setTimeout(() => {
|
|
9815
10262
|
this._activePre = pre;
|
|
9816
10263
|
this._syncWrapBtn();
|
|
10264
|
+
this._syncLineNumbersBtn();
|
|
9817
10265
|
this._syncLangSelect();
|
|
9818
10266
|
this._show(pre);
|
|
9819
10267
|
}, SHOW_DELAY);
|
|
@@ -9858,6 +10306,12 @@
|
|
|
9858
10306
|
this._wrapBtn.classList.toggle("active", wrapped);
|
|
9859
10307
|
this._wrapBtn.title = wrapped ? this.context.locale.tooltips.code.disableWordWrap : this.context.locale.tooltips.code.enableWordWrap;
|
|
9860
10308
|
}
|
|
10309
|
+
_syncLineNumbersBtn() {
|
|
10310
|
+
if (!this._activePre || !this._lineNumbersBtn) return;
|
|
10311
|
+
const on = this._activePre.classList.contains("an-code-line-numbers");
|
|
10312
|
+
this._lineNumbersBtn.classList.toggle("active", on);
|
|
10313
|
+
this._lineNumbersBtn.title = this.context.locale.tooltips.code.lineNumbers;
|
|
10314
|
+
}
|
|
9861
10315
|
_syncLangSelect() {
|
|
9862
10316
|
if (!this._activePre || !this._langSelect) return;
|
|
9863
10317
|
const codeEl = this._activePre.querySelector("code");
|
|
@@ -9904,6 +10358,13 @@
|
|
|
9904
10358
|
this.context.invoke("editor.afterCommand");
|
|
9905
10359
|
this._positionNear(pre);
|
|
9906
10360
|
}
|
|
10361
|
+
_toggleLineNumbers() {
|
|
10362
|
+
const pre = this._activePre;
|
|
10363
|
+
if (!pre) return;
|
|
10364
|
+
pre.classList.toggle("an-code-line-numbers");
|
|
10365
|
+
this._syncLineNumbersBtn();
|
|
10366
|
+
this.context.invoke("editor.afterCommand");
|
|
10367
|
+
}
|
|
9907
10368
|
/**
|
|
9908
10369
|
* Applies a language to a given <pre> element: sets classes, data-language,
|
|
9909
10370
|
* and triggers Prism highlighting. Called by the auto-detect flow.
|
|
@@ -13914,12 +14375,16 @@
|
|
|
13914
14375
|
this._matches = [];
|
|
13915
14376
|
this._currentIndex = -1;
|
|
13916
14377
|
this._caseSensitive = false;
|
|
14378
|
+
this._useRegex = false;
|
|
14379
|
+
this._wholeWord = false;
|
|
13917
14380
|
/** @type {'find'|'replace'} */
|
|
13918
14381
|
this._mode = "find";
|
|
13919
14382
|
/** Cached compiled regex — reused when query and case-sensitivity are unchanged */
|
|
13920
14383
|
this._queryRegex = null;
|
|
13921
14384
|
this._lastQuery = null;
|
|
13922
14385
|
this._lastCaseSensitive = null;
|
|
14386
|
+
this._lastUseRegex = null;
|
|
14387
|
+
this._lastWholeWord = null;
|
|
13923
14388
|
this._focusTimer = null;
|
|
13924
14389
|
}
|
|
13925
14390
|
destroy() {
|
|
@@ -14023,6 +14488,20 @@
|
|
|
14023
14488
|
"aria-label": "Case sensitive"
|
|
14024
14489
|
});
|
|
14025
14490
|
caseBtn.textContent = "Aa";
|
|
14491
|
+
const regexBtn = createElement("button", {
|
|
14492
|
+
type: "button",
|
|
14493
|
+
class: "an-fr-icon-btn",
|
|
14494
|
+
title: L.useRegex,
|
|
14495
|
+
"aria-label": L.useRegex
|
|
14496
|
+
});
|
|
14497
|
+
regexBtn.textContent = ".*";
|
|
14498
|
+
const wholeWordBtn = createElement("button", {
|
|
14499
|
+
type: "button",
|
|
14500
|
+
class: "an-fr-icon-btn",
|
|
14501
|
+
title: L.wholeWord,
|
|
14502
|
+
"aria-label": L.wholeWord
|
|
14503
|
+
});
|
|
14504
|
+
wholeWordBtn.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="7" width="18" height="10" rx="2"/><line x1="7" y1="21" x2="7" y2="17"/><line x1="17" y1="21" x2="17" y2="17"/></svg>`;
|
|
14026
14505
|
const prevBtn = createElement("button", {
|
|
14027
14506
|
type: "button",
|
|
14028
14507
|
class: "an-fr-icon-btn",
|
|
@@ -14039,7 +14518,7 @@
|
|
|
14039
14518
|
nextBtn.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 12 15 18 9"/></svg>`;
|
|
14040
14519
|
const counter = createElement("span", { class: "an-fr-counter" });
|
|
14041
14520
|
this._counterEl = counter;
|
|
14042
|
-
searchBar.append(findInput, caseCheckbox, caseBtn, prevBtn, nextBtn, counter);
|
|
14521
|
+
searchBar.append(findInput, caseCheckbox, caseBtn, regexBtn, wholeWordBtn, prevBtn, nextBtn, counter);
|
|
14043
14522
|
box.appendChild(searchBar);
|
|
14044
14523
|
const replaceRow = createElement("div", { class: "an-fr-replace-row" });
|
|
14045
14524
|
replaceRow.style.display = "none";
|
|
@@ -14100,7 +14579,21 @@
|
|
|
14100
14579
|
this._replace();
|
|
14101
14580
|
}
|
|
14102
14581
|
});
|
|
14103
|
-
|
|
14582
|
+
const dRegex = on(regexBtn, "click", () => {
|
|
14583
|
+
this._useRegex = !this._useRegex;
|
|
14584
|
+
regexBtn.classList.toggle("an-fr-icon-btn--active", this._useRegex);
|
|
14585
|
+
this._queryRegex = null;
|
|
14586
|
+
this._lastQuery = null;
|
|
14587
|
+
this._onSearch();
|
|
14588
|
+
});
|
|
14589
|
+
const dWholeWord = on(wholeWordBtn, "click", () => {
|
|
14590
|
+
this._wholeWord = !this._wholeWord;
|
|
14591
|
+
wholeWordBtn.classList.toggle("an-fr-icon-btn--active", this._wholeWord);
|
|
14592
|
+
this._queryRegex = null;
|
|
14593
|
+
this._lastQuery = null;
|
|
14594
|
+
this._onSearch();
|
|
14595
|
+
});
|
|
14596
|
+
this._disposers.push(d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, dRegex, dWholeWord);
|
|
14104
14597
|
return overlay;
|
|
14105
14598
|
}
|
|
14106
14599
|
_onSearch() {
|
|
@@ -14158,13 +14651,21 @@
|
|
|
14158
14651
|
*/
|
|
14159
14652
|
_findRawMatches(query, root) {
|
|
14160
14653
|
const results = [];
|
|
14161
|
-
if (this._lastQuery !== query || this._lastCaseSensitive !== this._caseSensitive) {
|
|
14654
|
+
if (this._lastQuery !== query || this._lastCaseSensitive !== this._caseSensitive || this._lastUseRegex !== this._useRegex || this._lastWholeWord !== this._wholeWord) {
|
|
14162
14655
|
const flags = this._caseSensitive ? "g" : "gi";
|
|
14163
|
-
|
|
14164
|
-
|
|
14656
|
+
try {
|
|
14657
|
+
let pattern = this._useRegex ? query : query.replace(/[.*+?^${}()|[\]\\]/g, String.raw`\$&`);
|
|
14658
|
+
if (this._wholeWord) pattern = `\\b${pattern}\\b`;
|
|
14659
|
+
this._queryRegex = new RegExp(pattern, flags);
|
|
14660
|
+
} catch (_) {
|
|
14661
|
+
this._queryRegex = null;
|
|
14662
|
+
}
|
|
14165
14663
|
this._lastQuery = query;
|
|
14166
14664
|
this._lastCaseSensitive = this._caseSensitive;
|
|
14665
|
+
this._lastUseRegex = this._useRegex;
|
|
14666
|
+
this._lastWholeWord = this._wholeWord;
|
|
14167
14667
|
}
|
|
14668
|
+
if (!this._queryRegex) return results;
|
|
14168
14669
|
const re = this._queryRegex;
|
|
14169
14670
|
const MAX_RESULTS = 500;
|
|
14170
14671
|
const walker = document.createTreeWalker(root, 4);
|
|
@@ -15700,13 +16201,18 @@
|
|
|
15700
16201
|
this._query = query;
|
|
15701
16202
|
clearTimeout(this._debounceTimer);
|
|
15702
16203
|
this._debounceTimer = setTimeout(() => {
|
|
15703
|
-
|
|
16204
|
+
const cb = (items) => {
|
|
15704
16205
|
if (!Array.isArray(items) || items.length === 0) {
|
|
15705
16206
|
this._hideDropdown();
|
|
15706
16207
|
return;
|
|
15707
16208
|
}
|
|
15708
16209
|
this._renderItems(items);
|
|
15709
16210
|
this._showDropdown();
|
|
16211
|
+
};
|
|
16212
|
+
const result = this._cfg.onSearch(this._query, cb);
|
|
16213
|
+
if (result && typeof result.then === "function") result.then(cb).catch((err) => {
|
|
16214
|
+
this._hideDropdown();
|
|
16215
|
+
if (typeof this._cfg.onError === "function") this._cfg.onError(err);
|
|
15710
16216
|
});
|
|
15711
16217
|
}, this._cfg.debounce);
|
|
15712
16218
|
}
|
|
@@ -15975,10 +16481,13 @@
|
|
|
15975
16481
|
}
|
|
15976
16482
|
/**
|
|
15977
16483
|
* Returns the current HTML content of the editor.
|
|
16484
|
+
* Zero-width spaces (U+200B) inserted by inline editing helpers are stripped
|
|
16485
|
+
* from the output so they don't leak into the consumer's HTML.
|
|
15978
16486
|
* @returns {string}
|
|
15979
16487
|
*/
|
|
15980
16488
|
getHTML() {
|
|
15981
|
-
|
|
16489
|
+
const html = this.invoke("editor.getHTML");
|
|
16490
|
+
return typeof html === "string" ? html.replace(//g, "") : html;
|
|
15982
16491
|
}
|
|
15983
16492
|
/**
|
|
15984
16493
|
* Sets the HTML content of the editor.
|
|
@@ -16016,6 +16525,20 @@
|
|
|
16016
16525
|
this.invoke("editor.clearHistory");
|
|
16017
16526
|
}
|
|
16018
16527
|
/**
|
|
16528
|
+
* Returns the number of available undo steps.
|
|
16529
|
+
* @returns {number}
|
|
16530
|
+
*/
|
|
16531
|
+
getUndoCount() {
|
|
16532
|
+
return this.invoke("editor.getUndoCount") ?? 0;
|
|
16533
|
+
}
|
|
16534
|
+
/**
|
|
16535
|
+
* Returns the number of available redo steps.
|
|
16536
|
+
* @returns {number}
|
|
16537
|
+
*/
|
|
16538
|
+
getRedoCount() {
|
|
16539
|
+
return this.invoke("editor.getRedoCount") ?? 0;
|
|
16540
|
+
}
|
|
16541
|
+
/**
|
|
16019
16542
|
* Returns true when the editor has no meaningful content.
|
|
16020
16543
|
* @returns {boolean}
|
|
16021
16544
|
*/
|
|
@@ -16123,6 +16646,37 @@
|
|
|
16123
16646
|
});
|
|
16124
16647
|
}
|
|
16125
16648
|
/**
|
|
16649
|
+
* Returns an array of heading objects representing the table of contents.
|
|
16650
|
+
* Each entry has: level (1-6), text (heading text), element (DOM element).
|
|
16651
|
+
* @returns {{ level: number, text: string, element: HTMLElement }[]}
|
|
16652
|
+
*/
|
|
16653
|
+
getTableOfContents() {
|
|
16654
|
+
return Array.from(this.layoutInfo.editable.querySelectorAll("h1,h2,h3,h4,h5,h6")).map((el) => ({
|
|
16655
|
+
level: parseInt(el.tagName[1], 10),
|
|
16656
|
+
text: el.textContent?.trim() ?? "",
|
|
16657
|
+
element: el
|
|
16658
|
+
}));
|
|
16659
|
+
}
|
|
16660
|
+
/**
|
|
16661
|
+
* Moves focus into the editable area.
|
|
16662
|
+
*/
|
|
16663
|
+
focus() {
|
|
16664
|
+
this.layoutInfo.editable.focus();
|
|
16665
|
+
}
|
|
16666
|
+
/**
|
|
16667
|
+
* Removes focus from the editable area.
|
|
16668
|
+
*/
|
|
16669
|
+
blur() {
|
|
16670
|
+
this.layoutInfo.editable.blur();
|
|
16671
|
+
}
|
|
16672
|
+
/**
|
|
16673
|
+
* Returns true when the editor is currently in fullscreen mode.
|
|
16674
|
+
* @returns {boolean}
|
|
16675
|
+
*/
|
|
16676
|
+
isFullscreen() {
|
|
16677
|
+
return this.invoke("fullscreen.isActive") === true;
|
|
16678
|
+
}
|
|
16679
|
+
/**
|
|
16126
16680
|
* Sets whether the editor is disabled (readonly).
|
|
16127
16681
|
* @param {boolean} disabled
|
|
16128
16682
|
*/
|
|
@@ -16159,11 +16713,13 @@
|
|
|
16159
16713
|
this._disposers = [];
|
|
16160
16714
|
const container = this.layoutInfo.container;
|
|
16161
16715
|
const wasDark = container?.classList.contains("an-theme-dark");
|
|
16716
|
+
const wasAuto = container?.classList.contains("an-theme-auto");
|
|
16162
16717
|
if (container?.parentNode) {
|
|
16163
16718
|
this.targetEl.style.display = "";
|
|
16164
16719
|
container.remove();
|
|
16165
16720
|
}
|
|
16166
16721
|
if (wasDark && !document.querySelector(".an-container.an-theme-dark")) document.body.classList.remove("an-theme-dark");
|
|
16722
|
+
if (wasAuto && !document.querySelector(".an-container.an-theme-auto")) document.body.classList.remove("an-theme-auto");
|
|
16167
16723
|
if (typeof this.options.onDestroy === "function") this.options.onDestroy(this);
|
|
16168
16724
|
this._alive = false;
|
|
16169
16725
|
this._listeners.clear();
|
|
@@ -16290,8 +16846,10 @@
|
|
|
16290
16846
|
registerButton(btnDef);
|
|
16291
16847
|
return this;
|
|
16292
16848
|
},
|
|
16849
|
+
/** All pre-built button definitions — accessible in every module format including UMD/CJS. */
|
|
16850
|
+
buttons,
|
|
16293
16851
|
/** Library version */
|
|
16294
|
-
version: "1.
|
|
16852
|
+
version: "1.8.0"
|
|
16295
16853
|
};
|
|
16296
16854
|
/**
|
|
16297
16855
|
* @param {string|Element|NodeList|Element[]} selector
|