autumnnote 1.0.8 → 1.1.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 +401 -628
- package/dist/autumnnote.css +169 -0
- package/dist/autumnnote.es.js +3669 -179
- package/dist/autumnnote.es.js.map +1 -1
- package/dist/autumnnote.umd.js +3668 -178
- package/dist/autumnnote.umd.js.map +1 -1
- package/package.json +3 -2
- package/src/js/Context.js +18 -2
- package/src/js/core/func.js +5 -5
- 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/AutoSaveRestore.js +126 -0
- package/src/js/module/BubbleToolbar.js +243 -0
- package/src/js/module/CodeTooltip.js +12 -9
- package/src/js/module/ContextMenu.js +41 -37
- 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/MarkdownShortcuts.js +253 -0
- package/src/js/module/Mention.js +337 -0
- 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 +23 -0
- package/src/styles/autumnnote.scss +191 -0
- package/types/index.d.ts +114 -1
package/dist/autumnnote.umd.js
CHANGED
|
@@ -28,8 +28,7 @@
|
|
|
28
28
|
function mergeDeep(target, source) {
|
|
29
29
|
const output = {};
|
|
30
30
|
for (const key of Object.keys(target)) output[key] = Array.isArray(target[key]) ? [...target[key]] : target[key];
|
|
31
|
-
if (isPlainObject(target) && isPlainObject(source)) for (const key of Object.keys(source)) if (isPlainObject(source[key]))
|
|
32
|
-
else output[key] = mergeDeep(target[key], source[key]);
|
|
31
|
+
if (isPlainObject(target) && isPlainObject(source)) for (const key of Object.keys(source)) if (isPlainObject(source[key])) output[key] = mergeDeep(isPlainObject(target[key]) ? target[key] : {}, source[key]);
|
|
33
32
|
else if (Array.isArray(source[key])) output[key] = [...source[key]];
|
|
34
33
|
else output[key] = source[key];
|
|
35
34
|
return output;
|
|
@@ -1161,9 +1160,2713 @@
|
|
|
1161
1160
|
onDestroy: null,
|
|
1162
1161
|
onCharLimitReached: null,
|
|
1163
1162
|
onWordLimitReached: null,
|
|
1164
|
-
focusColor: null
|
|
1163
|
+
focusColor: null,
|
|
1164
|
+
lang: "en",
|
|
1165
|
+
autoSaveRestore: false,
|
|
1166
|
+
autoSaveRestoreTimeout: 7,
|
|
1167
|
+
onAutoSaveRestore: null,
|
|
1168
|
+
markdownShortcuts: true,
|
|
1169
|
+
bubbleToolbar: false,
|
|
1170
|
+
bubbleToolbarItems: [
|
|
1171
|
+
"bold",
|
|
1172
|
+
"italic",
|
|
1173
|
+
"underline",
|
|
1174
|
+
"link",
|
|
1175
|
+
"foreColor",
|
|
1176
|
+
"removeFormat"
|
|
1177
|
+
],
|
|
1178
|
+
mention: null
|
|
1165
1179
|
};
|
|
1166
1180
|
//#endregion
|
|
1181
|
+
//#region src/js/i18n/en.js
|
|
1182
|
+
/**
|
|
1183
|
+
* en.js - English locale (canonical reference)
|
|
1184
|
+
* All other locales deep-merge against this to fill missing keys.
|
|
1185
|
+
*/
|
|
1186
|
+
/** @type {import('../../../types/index.js').AsnLocale} */
|
|
1187
|
+
var en = {
|
|
1188
|
+
toolbar: {
|
|
1189
|
+
bold: "Bold (Ctrl+B)",
|
|
1190
|
+
italic: "Italic (Ctrl+I)",
|
|
1191
|
+
underline: "Underline (Ctrl+U)",
|
|
1192
|
+
strikethrough: "Strikethrough",
|
|
1193
|
+
superscript: "Superscript",
|
|
1194
|
+
subscript: "Subscript",
|
|
1195
|
+
alignLeft: "Align Left",
|
|
1196
|
+
alignCenter: "Align Center",
|
|
1197
|
+
alignRight: "Align Right",
|
|
1198
|
+
alignJustify: "Justify",
|
|
1199
|
+
ul: "Unordered List",
|
|
1200
|
+
ol: "Ordered List",
|
|
1201
|
+
checklist: "Checklist",
|
|
1202
|
+
indent: "Indent",
|
|
1203
|
+
outdent: "Outdent",
|
|
1204
|
+
undo: "Undo (Ctrl+Z)",
|
|
1205
|
+
redo: "Redo (Ctrl+Y)",
|
|
1206
|
+
hr: "Horizontal Rule",
|
|
1207
|
+
link: "Insert Link",
|
|
1208
|
+
image: "Insert Image",
|
|
1209
|
+
video: "Insert Video",
|
|
1210
|
+
emoji: "Insert Emoji",
|
|
1211
|
+
icon: "Insert FA Icon",
|
|
1212
|
+
table: "Insert Table",
|
|
1213
|
+
fontSize: "Font Size",
|
|
1214
|
+
fontSizePlaceholder: "Size",
|
|
1215
|
+
removeFormat: "Remove Format",
|
|
1216
|
+
direction: "Toggle Text Direction (LTR / RTL)",
|
|
1217
|
+
fontFamily: "Font Family",
|
|
1218
|
+
paragraphStyle: "Paragraph Style",
|
|
1219
|
+
paragraphStylePlaceholder: "Style",
|
|
1220
|
+
lineHeight: "Line Height",
|
|
1221
|
+
lineHeightPlaceholder: "↕ Line",
|
|
1222
|
+
codeview: "HTML Code View",
|
|
1223
|
+
fullscreen: "Fullscreen",
|
|
1224
|
+
shortcuts: "Keyboard Shortcuts (Ctrl+Shift+/)",
|
|
1225
|
+
find: "Find (Ctrl+F)",
|
|
1226
|
+
findReplace: "Find & Replace (Ctrl+H)",
|
|
1227
|
+
inlineCode: "Inline Code (Ctrl+`)",
|
|
1228
|
+
print: "Print",
|
|
1229
|
+
foreColor: "Text Color",
|
|
1230
|
+
backColor: "Highlight Color",
|
|
1231
|
+
chooseTextColor: "Choose text color",
|
|
1232
|
+
chooseHighlightColor: "Choose highlight color",
|
|
1233
|
+
customColor: "Custom color",
|
|
1234
|
+
insertTableLabel: "Insert Table",
|
|
1235
|
+
paragraphItems: {
|
|
1236
|
+
p: "Normal",
|
|
1237
|
+
blockquote: "Quote",
|
|
1238
|
+
pre: "Code"
|
|
1239
|
+
}
|
|
1240
|
+
},
|
|
1241
|
+
linkDialog: {
|
|
1242
|
+
ariaLabel: "Insert link",
|
|
1243
|
+
title: "Insert Link",
|
|
1244
|
+
url: "URL",
|
|
1245
|
+
urlPlaceholder: "https://",
|
|
1246
|
+
displayText: "Display Text",
|
|
1247
|
+
textPlaceholder: "Link text",
|
|
1248
|
+
openInNewTab: "Open in new tab",
|
|
1249
|
+
insertBtn: "Insert",
|
|
1250
|
+
cancelBtn: "Cancel"
|
|
1251
|
+
},
|
|
1252
|
+
imageDialog: {
|
|
1253
|
+
ariaLabel: "Insert image",
|
|
1254
|
+
title: "Insert Image",
|
|
1255
|
+
imageUrl: "Image URL",
|
|
1256
|
+
urlPlaceholder: "https://example.com/image.png",
|
|
1257
|
+
altText: "Alt Text",
|
|
1258
|
+
altPlaceholder: "Describe the image",
|
|
1259
|
+
alignment: "Alignment",
|
|
1260
|
+
alignNone: "None",
|
|
1261
|
+
alignLeft: "Left",
|
|
1262
|
+
alignCenter: "Center",
|
|
1263
|
+
alignRight: "Right",
|
|
1264
|
+
uploadLabel: "Or upload a file",
|
|
1265
|
+
insertBtn: "Insert",
|
|
1266
|
+
cancelBtn: "Cancel"
|
|
1267
|
+
},
|
|
1268
|
+
videoDialog: {
|
|
1269
|
+
ariaLabel: "Insert video",
|
|
1270
|
+
title: "Insert Video",
|
|
1271
|
+
videoUrl: "Video URL",
|
|
1272
|
+
urlPlaceholder: "YouTube, Vimeo, or direct .mp4 URL",
|
|
1273
|
+
widthLabel: "Width (px)",
|
|
1274
|
+
widthPlaceholder: "560",
|
|
1275
|
+
insertBtn: "Insert",
|
|
1276
|
+
cancelBtn: "Cancel",
|
|
1277
|
+
detected: (type) => `Detected: ${type}`,
|
|
1278
|
+
unknownFormat: "Unknown format — will try direct video embed",
|
|
1279
|
+
invalidUrl: "Invalid URL — please enter a valid video link."
|
|
1280
|
+
},
|
|
1281
|
+
emojiDialog: {
|
|
1282
|
+
ariaLabel: "Insert emoji",
|
|
1283
|
+
title: "Insert Emoji",
|
|
1284
|
+
searchPlaceholder: "Search emojis…",
|
|
1285
|
+
all: "All",
|
|
1286
|
+
cancelBtn: "Cancel",
|
|
1287
|
+
close: "Close",
|
|
1288
|
+
categories: {
|
|
1289
|
+
smileys: "Smileys",
|
|
1290
|
+
people: "People",
|
|
1291
|
+
animals: "Animals",
|
|
1292
|
+
food: "Food",
|
|
1293
|
+
travel: "Travel",
|
|
1294
|
+
objects: "Objects",
|
|
1295
|
+
symbols: "Symbols"
|
|
1296
|
+
}
|
|
1297
|
+
},
|
|
1298
|
+
iconDialog: {
|
|
1299
|
+
ariaLabel: "Insert FA icon",
|
|
1300
|
+
title: "Insert FA Icon",
|
|
1301
|
+
searchPlaceholder: "Search icons…",
|
|
1302
|
+
all: "All",
|
|
1303
|
+
style: "Style",
|
|
1304
|
+
size: "Size",
|
|
1305
|
+
color: "Color",
|
|
1306
|
+
useColor: " Use color",
|
|
1307
|
+
selectHint: "Select an icon",
|
|
1308
|
+
insertBtn: "Insert FA Icon",
|
|
1309
|
+
cancelBtn: "Cancel",
|
|
1310
|
+
close: "Close",
|
|
1311
|
+
categories: {
|
|
1312
|
+
popular: "Popular",
|
|
1313
|
+
interface: "Interface",
|
|
1314
|
+
navigation: "Navigation",
|
|
1315
|
+
media: "Media",
|
|
1316
|
+
communication: "Communication",
|
|
1317
|
+
files: "Files",
|
|
1318
|
+
people: "People",
|
|
1319
|
+
objects: "Objects"
|
|
1320
|
+
}
|
|
1321
|
+
},
|
|
1322
|
+
findReplace: {
|
|
1323
|
+
findTitle: "Find",
|
|
1324
|
+
findReplaceTitle: "Find & Replace",
|
|
1325
|
+
findPlaceholder: "Find…",
|
|
1326
|
+
searchAriaLabel: "Search text",
|
|
1327
|
+
caseSensitive: "\xA0Case sensitive",
|
|
1328
|
+
prevBtn: "← Prev",
|
|
1329
|
+
nextBtn: "Next →",
|
|
1330
|
+
replacePlaceholder: "Replace with…",
|
|
1331
|
+
replaceAriaLabel: "Replace with",
|
|
1332
|
+
replaceBtn: "Replace",
|
|
1333
|
+
replaceAllBtn: "Replace All",
|
|
1334
|
+
close: "×"
|
|
1335
|
+
},
|
|
1336
|
+
shortcutsDialog: {
|
|
1337
|
+
title: "Keyboard Shortcuts",
|
|
1338
|
+
ariaLabel: "Keyboard Shortcuts",
|
|
1339
|
+
close: "Close",
|
|
1340
|
+
shortcuts: [
|
|
1341
|
+
{
|
|
1342
|
+
category: "Text Formatting",
|
|
1343
|
+
items: [
|
|
1344
|
+
{
|
|
1345
|
+
keys: "Ctrl + B",
|
|
1346
|
+
action: "Bold"
|
|
1347
|
+
},
|
|
1348
|
+
{
|
|
1349
|
+
keys: "Ctrl + I",
|
|
1350
|
+
action: "Italic"
|
|
1351
|
+
},
|
|
1352
|
+
{
|
|
1353
|
+
keys: "Ctrl + U",
|
|
1354
|
+
action: "Underline"
|
|
1355
|
+
},
|
|
1356
|
+
{
|
|
1357
|
+
keys: "Ctrl + K",
|
|
1358
|
+
action: "Insert / edit link"
|
|
1359
|
+
}
|
|
1360
|
+
]
|
|
1361
|
+
},
|
|
1362
|
+
{
|
|
1363
|
+
category: "History",
|
|
1364
|
+
items: [{
|
|
1365
|
+
keys: "Ctrl + Z",
|
|
1366
|
+
action: "Undo"
|
|
1367
|
+
}, {
|
|
1368
|
+
keys: "Ctrl + Y / Ctrl + Shift + Z",
|
|
1369
|
+
action: "Redo"
|
|
1370
|
+
}]
|
|
1371
|
+
},
|
|
1372
|
+
{
|
|
1373
|
+
category: "Selection & Navigation",
|
|
1374
|
+
items: [
|
|
1375
|
+
{
|
|
1376
|
+
keys: "Ctrl + A",
|
|
1377
|
+
action: "Select all content"
|
|
1378
|
+
},
|
|
1379
|
+
{
|
|
1380
|
+
keys: "Tab",
|
|
1381
|
+
action: "Indent list item / insert spaces"
|
|
1382
|
+
},
|
|
1383
|
+
{
|
|
1384
|
+
keys: "Shift + Tab",
|
|
1385
|
+
action: "Outdent list item"
|
|
1386
|
+
}
|
|
1387
|
+
]
|
|
1388
|
+
},
|
|
1389
|
+
{
|
|
1390
|
+
category: "Clipboard",
|
|
1391
|
+
items: [{
|
|
1392
|
+
keys: "Ctrl + Shift + V",
|
|
1393
|
+
action: "Paste as plain text"
|
|
1394
|
+
}]
|
|
1395
|
+
},
|
|
1396
|
+
{
|
|
1397
|
+
category: "Find & Replace",
|
|
1398
|
+
items: [{
|
|
1399
|
+
keys: "Ctrl + F",
|
|
1400
|
+
action: "Find in document"
|
|
1401
|
+
}, {
|
|
1402
|
+
keys: "Ctrl + H",
|
|
1403
|
+
action: "Find & Replace"
|
|
1404
|
+
}]
|
|
1405
|
+
},
|
|
1406
|
+
{
|
|
1407
|
+
category: "Editor",
|
|
1408
|
+
items: [{
|
|
1409
|
+
keys: "Ctrl + Shift + /",
|
|
1410
|
+
action: "Show this keyboard shortcuts dialog"
|
|
1411
|
+
}]
|
|
1412
|
+
}
|
|
1413
|
+
]
|
|
1414
|
+
},
|
|
1415
|
+
contextMenu: {
|
|
1416
|
+
cut: "Cut",
|
|
1417
|
+
copy: "Copy",
|
|
1418
|
+
paste: "Paste",
|
|
1419
|
+
bold: "Bold",
|
|
1420
|
+
italic: "Italic",
|
|
1421
|
+
underline: "Underline",
|
|
1422
|
+
textColor: "Text Color",
|
|
1423
|
+
highlightColor: "Highlight Color",
|
|
1424
|
+
copyFormat: "Copy Format",
|
|
1425
|
+
pasteFormat: "Paste Format",
|
|
1426
|
+
removeFormat: "Remove Format",
|
|
1427
|
+
link: "Insert Link",
|
|
1428
|
+
image: "Insert Image",
|
|
1429
|
+
video: "Insert Video",
|
|
1430
|
+
table: "Insert Table",
|
|
1431
|
+
back: "Back",
|
|
1432
|
+
noHighlight: "No highlight",
|
|
1433
|
+
customColor: "Custom color",
|
|
1434
|
+
customColorLabel: "Custom…"
|
|
1435
|
+
},
|
|
1436
|
+
statusbar: {
|
|
1437
|
+
resizeHandle: "Resize editor",
|
|
1438
|
+
words: (n) => `Words: ${n}`,
|
|
1439
|
+
wordsLimit: (n, max) => `Words: ${n}/${max}`,
|
|
1440
|
+
chars: (n) => `Chars: ${n}`,
|
|
1441
|
+
charsLimit: (n, max) => `Chars: ${n}/${max}`
|
|
1442
|
+
},
|
|
1443
|
+
tooltips: {
|
|
1444
|
+
link: {
|
|
1445
|
+
ariaLabel: "Link actions",
|
|
1446
|
+
openLink: "Open link",
|
|
1447
|
+
copyUrl: "Copy URL",
|
|
1448
|
+
editLink: "Edit link",
|
|
1449
|
+
removeLink: "Remove link"
|
|
1450
|
+
},
|
|
1451
|
+
image: {
|
|
1452
|
+
ariaLabel: "Image actions",
|
|
1453
|
+
label: "Image",
|
|
1454
|
+
floatLeft: "Float Left",
|
|
1455
|
+
noFloat: "No Float",
|
|
1456
|
+
alignCenter: "Align Center",
|
|
1457
|
+
floatRight: "Float Right",
|
|
1458
|
+
originalSize: "Original Size",
|
|
1459
|
+
rotateLeft: "Rotate Left",
|
|
1460
|
+
rotateRight: "Rotate Right",
|
|
1461
|
+
cropImage: "Crop Image",
|
|
1462
|
+
addCaption: "Add / Edit Caption",
|
|
1463
|
+
deleteImage: "Delete Image"
|
|
1464
|
+
},
|
|
1465
|
+
code: {
|
|
1466
|
+
ariaLabel: "Code block actions",
|
|
1467
|
+
label: "Code",
|
|
1468
|
+
syntaxLanguage: "Syntax Language",
|
|
1469
|
+
syntaxAriaLabel: "Syntax language",
|
|
1470
|
+
copyCode: "Copy Code",
|
|
1471
|
+
toggleWordWrap: "Toggle Word Wrap",
|
|
1472
|
+
enableWordWrap: "Enable Word Wrap",
|
|
1473
|
+
disableWordWrap: "Disable Word Wrap",
|
|
1474
|
+
convertToParagraph: "Convert to Paragraph",
|
|
1475
|
+
deleteCodeBlock: "Delete Code Block"
|
|
1476
|
+
},
|
|
1477
|
+
table: {
|
|
1478
|
+
ariaLabel: "Table actions",
|
|
1479
|
+
label: "Table",
|
|
1480
|
+
selectCells: "Select Cells",
|
|
1481
|
+
addRowAbove: "Add Row Above",
|
|
1482
|
+
addRowBelow: "Add Row Below",
|
|
1483
|
+
deleteRow: "Delete Row",
|
|
1484
|
+
addColumnLeft: "Add Column Left",
|
|
1485
|
+
addColumnRight: "Add Column Right",
|
|
1486
|
+
deleteColumn: "Delete Column",
|
|
1487
|
+
mergeCells: "Merge Cells",
|
|
1488
|
+
unmergeCells: "Unmerge Cells",
|
|
1489
|
+
columnWidth: "Column Width",
|
|
1490
|
+
rowHeight: "Row Height",
|
|
1491
|
+
tableBorderWidth: "Table Border Width",
|
|
1492
|
+
deleteTable: "Delete Table",
|
|
1493
|
+
columnWidthPx: "Column Width (px)",
|
|
1494
|
+
rowHeightPx: "Row Height (px)",
|
|
1495
|
+
tableBorderWidthPx: "Table Border Width (px)",
|
|
1496
|
+
cancelBtn: "Cancel",
|
|
1497
|
+
applyBtn: "Apply"
|
|
1498
|
+
},
|
|
1499
|
+
video: {
|
|
1500
|
+
ariaLabel: "Video actions",
|
|
1501
|
+
label: "Video",
|
|
1502
|
+
floatLeft: "Float Left",
|
|
1503
|
+
noFloat: "No Float",
|
|
1504
|
+
alignCenter: "Align Center",
|
|
1505
|
+
floatRight: "Float Right",
|
|
1506
|
+
originalSize: "Original Size",
|
|
1507
|
+
previewVideo: "Preview Video",
|
|
1508
|
+
exitPreview: "Exit Preview",
|
|
1509
|
+
deleteVideo: "Delete Video"
|
|
1510
|
+
}
|
|
1511
|
+
},
|
|
1512
|
+
errors: {
|
|
1513
|
+
imageFormat: (type) => `Format "${type}" is not supported for display in web browsers. Please convert to JPEG, PNG, or WebP first.`,
|
|
1514
|
+
imageSize: (maxSize) => `Image file is too large. Maximum allowed size is ${maxSize} MB.`
|
|
1515
|
+
}
|
|
1516
|
+
};
|
|
1517
|
+
//#endregion
|
|
1518
|
+
//#region src/js/i18n/index.js
|
|
1519
|
+
/**
|
|
1520
|
+
* i18n/index.js — Locale registry and resolver for autumn-note-ce.
|
|
1521
|
+
*
|
|
1522
|
+
* Usage:
|
|
1523
|
+
* lang: 'en' → built-in English (default)
|
|
1524
|
+
* lang: 'vi' → built-in Vietnamese
|
|
1525
|
+
* lang: 'ja' → built-in Japanese
|
|
1526
|
+
* lang: 'zh' → built-in Simplified Chinese
|
|
1527
|
+
* lang: 'fr' → built-in French
|
|
1528
|
+
* lang: 'de' → built-in German
|
|
1529
|
+
* lang: 'es' → built-in Spanish
|
|
1530
|
+
* lang: 'ko' → built-in Korean
|
|
1531
|
+
* lang: { ... } → custom locale object, deep-merged over English
|
|
1532
|
+
*/
|
|
1533
|
+
/**
|
|
1534
|
+
* All built-in locales keyed by their language code.
|
|
1535
|
+
* @type {Record<string, Partial<AsnLocale>>}
|
|
1536
|
+
*/
|
|
1537
|
+
var locales = {
|
|
1538
|
+
en,
|
|
1539
|
+
vi: {
|
|
1540
|
+
toolbar: {
|
|
1541
|
+
bold: "Đậm (Ctrl+B)",
|
|
1542
|
+
italic: "Nghiêng (Ctrl+I)",
|
|
1543
|
+
underline: "Gạch chân (Ctrl+U)",
|
|
1544
|
+
strikethrough: "Gạch ngang",
|
|
1545
|
+
superscript: "Chỉ số trên",
|
|
1546
|
+
subscript: "Chỉ số dưới",
|
|
1547
|
+
alignLeft: "Căn trái",
|
|
1548
|
+
alignCenter: "Căn giữa",
|
|
1549
|
+
alignRight: "Căn phải",
|
|
1550
|
+
alignJustify: "Căn đều",
|
|
1551
|
+
ul: "Danh sách không thứ tự",
|
|
1552
|
+
ol: "Danh sách có thứ tự",
|
|
1553
|
+
checklist: "Danh sách kiểm tra",
|
|
1554
|
+
indent: "Tăng thụt đầu dòng",
|
|
1555
|
+
outdent: "Giảm thụt đầu dòng",
|
|
1556
|
+
undo: "Hoàn tác (Ctrl+Z)",
|
|
1557
|
+
redo: "Làm lại (Ctrl+Y)",
|
|
1558
|
+
hr: "Đường kẻ ngang",
|
|
1559
|
+
link: "Chèn liên kết",
|
|
1560
|
+
image: "Chèn hình ảnh",
|
|
1561
|
+
video: "Chèn video",
|
|
1562
|
+
emoji: "Chèn biểu tượng cảm xúc",
|
|
1563
|
+
icon: "Chèn biểu tượng FA",
|
|
1564
|
+
table: "Chèn bảng",
|
|
1565
|
+
fontSize: "Cỡ chữ",
|
|
1566
|
+
fontSizePlaceholder: "Cỡ",
|
|
1567
|
+
removeFormat: "Xóa định dạng",
|
|
1568
|
+
direction: "Chuyển hướng văn bản (LTR / RTL)",
|
|
1569
|
+
fontFamily: "Phông chữ",
|
|
1570
|
+
paragraphStyle: "Kiểu đoạn văn",
|
|
1571
|
+
paragraphStylePlaceholder: "Kiểu",
|
|
1572
|
+
lineHeight: "Khoảng cách dòng",
|
|
1573
|
+
lineHeightPlaceholder: "↕ Dòng",
|
|
1574
|
+
codeview: "Xem mã HTML",
|
|
1575
|
+
fullscreen: "Toàn màn hình",
|
|
1576
|
+
shortcuts: "Phím tắt (Ctrl+Shift+/)",
|
|
1577
|
+
find: "Tìm kiếm (Ctrl+F)",
|
|
1578
|
+
findReplace: "Tìm & Thay thế (Ctrl+H)",
|
|
1579
|
+
inlineCode: "Mã nội tuyến (Ctrl+`)",
|
|
1580
|
+
print: "In",
|
|
1581
|
+
foreColor: "Màu chữ",
|
|
1582
|
+
backColor: "Màu nền chữ",
|
|
1583
|
+
chooseTextColor: "Chọn màu chữ",
|
|
1584
|
+
chooseHighlightColor: "Chọn màu nền",
|
|
1585
|
+
customColor: "Màu tùy chỉnh",
|
|
1586
|
+
insertTableLabel: "Chèn bảng",
|
|
1587
|
+
paragraphItems: {
|
|
1588
|
+
p: "Bình thường",
|
|
1589
|
+
blockquote: "Trích dẫn",
|
|
1590
|
+
pre: "Mã"
|
|
1591
|
+
}
|
|
1592
|
+
},
|
|
1593
|
+
linkDialog: {
|
|
1594
|
+
ariaLabel: "Chèn liên kết",
|
|
1595
|
+
title: "Chèn liên kết",
|
|
1596
|
+
url: "Địa chỉ URL",
|
|
1597
|
+
urlPlaceholder: "https://",
|
|
1598
|
+
displayText: "Văn bản hiển thị",
|
|
1599
|
+
textPlaceholder: "Nội dung liên kết",
|
|
1600
|
+
openInNewTab: "Mở trong tab mới",
|
|
1601
|
+
insertBtn: "Chèn",
|
|
1602
|
+
cancelBtn: "Hủy"
|
|
1603
|
+
},
|
|
1604
|
+
imageDialog: {
|
|
1605
|
+
ariaLabel: "Chèn hình ảnh",
|
|
1606
|
+
title: "Chèn hình ảnh",
|
|
1607
|
+
imageUrl: "URL hình ảnh",
|
|
1608
|
+
urlPlaceholder: "https://example.com/anh.png",
|
|
1609
|
+
altText: "Văn bản thay thế",
|
|
1610
|
+
altPlaceholder: "Mô tả hình ảnh",
|
|
1611
|
+
alignment: "Căn chỉnh",
|
|
1612
|
+
alignNone: "Không",
|
|
1613
|
+
alignLeft: "Trái",
|
|
1614
|
+
alignCenter: "Giữa",
|
|
1615
|
+
alignRight: "Phải",
|
|
1616
|
+
uploadLabel: "Hoặc tải lên tệp",
|
|
1617
|
+
insertBtn: "Chèn",
|
|
1618
|
+
cancelBtn: "Hủy"
|
|
1619
|
+
},
|
|
1620
|
+
videoDialog: {
|
|
1621
|
+
ariaLabel: "Chèn video",
|
|
1622
|
+
title: "Chèn video",
|
|
1623
|
+
videoUrl: "URL video",
|
|
1624
|
+
urlPlaceholder: "YouTube, Vimeo, hoặc URL .mp4 trực tiếp",
|
|
1625
|
+
widthLabel: "Chiều rộng (px)",
|
|
1626
|
+
widthPlaceholder: "560",
|
|
1627
|
+
insertBtn: "Chèn",
|
|
1628
|
+
cancelBtn: "Hủy",
|
|
1629
|
+
detected: (type) => `Đã phát hiện: ${type}`,
|
|
1630
|
+
unknownFormat: "Định dạng không xác định — sẽ thử nhúng video trực tiếp",
|
|
1631
|
+
invalidUrl: "URL không hợp lệ — vui lòng nhập đường dẫn video hợp lệ."
|
|
1632
|
+
},
|
|
1633
|
+
emojiDialog: {
|
|
1634
|
+
ariaLabel: "Chèn biểu tượng cảm xúc",
|
|
1635
|
+
title: "Chèn biểu tượng cảm xúc",
|
|
1636
|
+
searchPlaceholder: "Tìm kiếm biểu tượng…",
|
|
1637
|
+
all: "Tất cả",
|
|
1638
|
+
cancelBtn: "Hủy",
|
|
1639
|
+
close: "Đóng",
|
|
1640
|
+
categories: {
|
|
1641
|
+
smileys: "Mặt cười",
|
|
1642
|
+
people: "Con người",
|
|
1643
|
+
animals: "Động vật",
|
|
1644
|
+
food: "Thức ăn",
|
|
1645
|
+
travel: "Du lịch",
|
|
1646
|
+
objects: "Đồ vật",
|
|
1647
|
+
symbols: "Ký hiệu"
|
|
1648
|
+
}
|
|
1649
|
+
},
|
|
1650
|
+
iconDialog: {
|
|
1651
|
+
ariaLabel: "Chèn biểu tượng FA",
|
|
1652
|
+
title: "Chèn biểu tượng FA",
|
|
1653
|
+
searchPlaceholder: "Tìm kiếm biểu tượng…",
|
|
1654
|
+
all: "Tất cả",
|
|
1655
|
+
style: "Kiểu",
|
|
1656
|
+
size: "Kích thước",
|
|
1657
|
+
color: "Màu sắc",
|
|
1658
|
+
useColor: " Dùng màu",
|
|
1659
|
+
selectHint: "Chọn một biểu tượng",
|
|
1660
|
+
insertBtn: "Chèn biểu tượng FA",
|
|
1661
|
+
cancelBtn: "Hủy",
|
|
1662
|
+
close: "Đóng",
|
|
1663
|
+
categories: {
|
|
1664
|
+
popular: "Phổ biến",
|
|
1665
|
+
interface: "Giao diện",
|
|
1666
|
+
navigation: "Điều hướng",
|
|
1667
|
+
media: "Phương tiện",
|
|
1668
|
+
communication: "Liên lạc",
|
|
1669
|
+
files: "Tệp tin",
|
|
1670
|
+
people: "Con người",
|
|
1671
|
+
objects: "Đồ vật"
|
|
1672
|
+
}
|
|
1673
|
+
},
|
|
1674
|
+
findReplace: {
|
|
1675
|
+
findTitle: "Tìm kiếm",
|
|
1676
|
+
findReplaceTitle: "Tìm & Thay thế",
|
|
1677
|
+
findPlaceholder: "Tìm…",
|
|
1678
|
+
searchAriaLabel: "Văn bản tìm kiếm",
|
|
1679
|
+
caseSensitive: "\xA0Phân biệt hoa thường",
|
|
1680
|
+
prevBtn: "← Trước",
|
|
1681
|
+
nextBtn: "Tiếp →",
|
|
1682
|
+
replacePlaceholder: "Thay thế bằng…",
|
|
1683
|
+
replaceAriaLabel: "Thay thế bằng",
|
|
1684
|
+
replaceBtn: "Thay thế",
|
|
1685
|
+
replaceAllBtn: "Thay thế tất cả",
|
|
1686
|
+
close: "×"
|
|
1687
|
+
},
|
|
1688
|
+
shortcutsDialog: {
|
|
1689
|
+
title: "Phím tắt bàn phím",
|
|
1690
|
+
ariaLabel: "Phím tắt bàn phím",
|
|
1691
|
+
close: "Đóng",
|
|
1692
|
+
shortcuts: [
|
|
1693
|
+
{
|
|
1694
|
+
category: "Định dạng văn bản",
|
|
1695
|
+
items: [
|
|
1696
|
+
{
|
|
1697
|
+
keys: "Ctrl + B",
|
|
1698
|
+
action: "Đậm"
|
|
1699
|
+
},
|
|
1700
|
+
{
|
|
1701
|
+
keys: "Ctrl + I",
|
|
1702
|
+
action: "Nghiêng"
|
|
1703
|
+
},
|
|
1704
|
+
{
|
|
1705
|
+
keys: "Ctrl + U",
|
|
1706
|
+
action: "Gạch chân"
|
|
1707
|
+
},
|
|
1708
|
+
{
|
|
1709
|
+
keys: "Ctrl + K",
|
|
1710
|
+
action: "Chèn / sửa liên kết"
|
|
1711
|
+
}
|
|
1712
|
+
]
|
|
1713
|
+
},
|
|
1714
|
+
{
|
|
1715
|
+
category: "Lịch sử",
|
|
1716
|
+
items: [{
|
|
1717
|
+
keys: "Ctrl + Z",
|
|
1718
|
+
action: "Hoàn tác"
|
|
1719
|
+
}, {
|
|
1720
|
+
keys: "Ctrl + Y / Ctrl + Shift + Z",
|
|
1721
|
+
action: "Làm lại"
|
|
1722
|
+
}]
|
|
1723
|
+
},
|
|
1724
|
+
{
|
|
1725
|
+
category: "Chọn & Điều hướng",
|
|
1726
|
+
items: [
|
|
1727
|
+
{
|
|
1728
|
+
keys: "Ctrl + A",
|
|
1729
|
+
action: "Chọn tất cả"
|
|
1730
|
+
},
|
|
1731
|
+
{
|
|
1732
|
+
keys: "Tab",
|
|
1733
|
+
action: "Tăng thụt đầu dòng / chèn khoảng trắng"
|
|
1734
|
+
},
|
|
1735
|
+
{
|
|
1736
|
+
keys: "Shift + Tab",
|
|
1737
|
+
action: "Giảm thụt đầu dòng"
|
|
1738
|
+
}
|
|
1739
|
+
]
|
|
1740
|
+
},
|
|
1741
|
+
{
|
|
1742
|
+
category: "Bảng nhớ tạm",
|
|
1743
|
+
items: [{
|
|
1744
|
+
keys: "Ctrl + Shift + V",
|
|
1745
|
+
action: "Dán dưới dạng văn bản thuần"
|
|
1746
|
+
}]
|
|
1747
|
+
},
|
|
1748
|
+
{
|
|
1749
|
+
category: "Tìm & Thay thế",
|
|
1750
|
+
items: [{
|
|
1751
|
+
keys: "Ctrl + F",
|
|
1752
|
+
action: "Tìm trong tài liệu"
|
|
1753
|
+
}, {
|
|
1754
|
+
keys: "Ctrl + H",
|
|
1755
|
+
action: "Tìm & Thay thế"
|
|
1756
|
+
}]
|
|
1757
|
+
},
|
|
1758
|
+
{
|
|
1759
|
+
category: "Trình soạn thảo",
|
|
1760
|
+
items: [{
|
|
1761
|
+
keys: "Ctrl + Shift + /",
|
|
1762
|
+
action: "Hiện hộp thoại phím tắt"
|
|
1763
|
+
}]
|
|
1764
|
+
}
|
|
1765
|
+
]
|
|
1766
|
+
},
|
|
1767
|
+
contextMenu: {
|
|
1768
|
+
cut: "Cắt",
|
|
1769
|
+
copy: "Sao chép",
|
|
1770
|
+
paste: "Dán",
|
|
1771
|
+
bold: "Đậm",
|
|
1772
|
+
italic: "Nghiêng",
|
|
1773
|
+
underline: "Gạch chân",
|
|
1774
|
+
textColor: "Màu chữ",
|
|
1775
|
+
highlightColor: "Màu nền chữ",
|
|
1776
|
+
copyFormat: "Sao chép định dạng",
|
|
1777
|
+
pasteFormat: "Dán định dạng",
|
|
1778
|
+
removeFormat: "Xóa định dạng",
|
|
1779
|
+
link: "Chèn liên kết",
|
|
1780
|
+
image: "Chèn hình ảnh",
|
|
1781
|
+
video: "Chèn video",
|
|
1782
|
+
table: "Chèn bảng",
|
|
1783
|
+
back: "Quay lại",
|
|
1784
|
+
noHighlight: "Không tô màu",
|
|
1785
|
+
customColor: "Màu tùy chỉnh",
|
|
1786
|
+
customColorLabel: "Tùy chỉnh…"
|
|
1787
|
+
},
|
|
1788
|
+
statusbar: {
|
|
1789
|
+
resizeHandle: "Kéo để thay đổi kích thước",
|
|
1790
|
+
words: (n) => `Từ: ${n}`,
|
|
1791
|
+
wordsLimit: (n, max) => `Từ: ${n}/${max}`,
|
|
1792
|
+
chars: (n) => `Ký tự: ${n}`,
|
|
1793
|
+
charsLimit: (n, max) => `Ký tự: ${n}/${max}`
|
|
1794
|
+
},
|
|
1795
|
+
tooltips: {
|
|
1796
|
+
link: {
|
|
1797
|
+
ariaLabel: "Hành động liên kết",
|
|
1798
|
+
openLink: "Mở liên kết",
|
|
1799
|
+
copyUrl: "Sao chép URL",
|
|
1800
|
+
editLink: "Sửa liên kết",
|
|
1801
|
+
removeLink: "Xóa liên kết"
|
|
1802
|
+
},
|
|
1803
|
+
image: {
|
|
1804
|
+
ariaLabel: "Hành động hình ảnh",
|
|
1805
|
+
label: "Hình ảnh",
|
|
1806
|
+
floatLeft: "Nổi trái",
|
|
1807
|
+
noFloat: "Không nổi",
|
|
1808
|
+
alignCenter: "Căn giữa",
|
|
1809
|
+
floatRight: "Nổi phải",
|
|
1810
|
+
originalSize: "Kích thước gốc",
|
|
1811
|
+
rotateLeft: "Xoay trái",
|
|
1812
|
+
rotateRight: "Xoay phải",
|
|
1813
|
+
cropImage: "Cắt ảnh",
|
|
1814
|
+
addCaption: "Thêm / Sửa chú thích",
|
|
1815
|
+
deleteImage: "Xóa hình ảnh"
|
|
1816
|
+
},
|
|
1817
|
+
code: {
|
|
1818
|
+
ariaLabel: "Hành động khối mã",
|
|
1819
|
+
label: "Mã",
|
|
1820
|
+
syntaxLanguage: "Ngôn ngữ cú pháp",
|
|
1821
|
+
syntaxAriaLabel: "Ngôn ngữ cú pháp",
|
|
1822
|
+
copyCode: "Sao chép mã",
|
|
1823
|
+
toggleWordWrap: "Chuyển đổi xuống dòng",
|
|
1824
|
+
enableWordWrap: "Bật xuống dòng",
|
|
1825
|
+
disableWordWrap: "Tắt xuống dòng",
|
|
1826
|
+
convertToParagraph: "Chuyển thành đoạn văn",
|
|
1827
|
+
deleteCodeBlock: "Xóa khối mã"
|
|
1828
|
+
},
|
|
1829
|
+
table: {
|
|
1830
|
+
ariaLabel: "Hành động bảng",
|
|
1831
|
+
label: "Bảng",
|
|
1832
|
+
selectCells: "Chọn ô",
|
|
1833
|
+
addRowAbove: "Thêm hàng phía trên",
|
|
1834
|
+
addRowBelow: "Thêm hàng phía dưới",
|
|
1835
|
+
deleteRow: "Xóa hàng",
|
|
1836
|
+
addColumnLeft: "Thêm cột bên trái",
|
|
1837
|
+
addColumnRight: "Thêm cột bên phải",
|
|
1838
|
+
deleteColumn: "Xóa cột",
|
|
1839
|
+
mergeCells: "Gộp ô",
|
|
1840
|
+
unmergeCells: "Tách ô",
|
|
1841
|
+
columnWidth: "Chiều rộng cột",
|
|
1842
|
+
rowHeight: "Chiều cao hàng",
|
|
1843
|
+
tableBorderWidth: "Độ rộng viền bảng",
|
|
1844
|
+
deleteTable: "Xóa bảng",
|
|
1845
|
+
columnWidthPx: "Chiều rộng cột (px)",
|
|
1846
|
+
rowHeightPx: "Chiều cao hàng (px)",
|
|
1847
|
+
tableBorderWidthPx: "Độ rộng viền bảng (px)",
|
|
1848
|
+
cancelBtn: "Hủy",
|
|
1849
|
+
applyBtn: "Áp dụng"
|
|
1850
|
+
},
|
|
1851
|
+
video: {
|
|
1852
|
+
ariaLabel: "Hành động video",
|
|
1853
|
+
label: "Video",
|
|
1854
|
+
floatLeft: "Nổi trái",
|
|
1855
|
+
noFloat: "Không nổi",
|
|
1856
|
+
alignCenter: "Căn giữa",
|
|
1857
|
+
floatRight: "Nổi phải",
|
|
1858
|
+
originalSize: "Kích thước gốc",
|
|
1859
|
+
previewVideo: "Xem trước",
|
|
1860
|
+
exitPreview: "Thoát xem trước",
|
|
1861
|
+
deleteVideo: "Xóa video"
|
|
1862
|
+
}
|
|
1863
|
+
},
|
|
1864
|
+
errors: {
|
|
1865
|
+
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.`,
|
|
1866
|
+
imageSize: (maxSize) => `Tệp hình ảnh quá lớn. Kích thước tối đa cho phép là ${maxSize} MB.`
|
|
1867
|
+
}
|
|
1868
|
+
},
|
|
1869
|
+
ja: {
|
|
1870
|
+
toolbar: {
|
|
1871
|
+
bold: "太字 (Ctrl+B)",
|
|
1872
|
+
italic: "斜体 (Ctrl+I)",
|
|
1873
|
+
underline: "下線 (Ctrl+U)",
|
|
1874
|
+
strikethrough: "取り消し線",
|
|
1875
|
+
superscript: "上付き文字",
|
|
1876
|
+
subscript: "下付き文字",
|
|
1877
|
+
alignLeft: "左揃え",
|
|
1878
|
+
alignCenter: "中央揃え",
|
|
1879
|
+
alignRight: "右揃え",
|
|
1880
|
+
alignJustify: "両端揃え",
|
|
1881
|
+
ul: "箇条書きリスト",
|
|
1882
|
+
ol: "番号付きリスト",
|
|
1883
|
+
checklist: "チェックリスト",
|
|
1884
|
+
indent: "インデントを増やす",
|
|
1885
|
+
outdent: "インデントを減らす",
|
|
1886
|
+
undo: "元に戻す (Ctrl+Z)",
|
|
1887
|
+
redo: "やり直す (Ctrl+Y)",
|
|
1888
|
+
hr: "水平線",
|
|
1889
|
+
link: "リンクを挿入",
|
|
1890
|
+
image: "画像を挿入",
|
|
1891
|
+
video: "動画を挿入",
|
|
1892
|
+
emoji: "絵文字を挿入",
|
|
1893
|
+
icon: "FAアイコンを挿入",
|
|
1894
|
+
table: "テーブルを挿入",
|
|
1895
|
+
fontSize: "フォントサイズ",
|
|
1896
|
+
fontSizePlaceholder: "サイズ",
|
|
1897
|
+
removeFormat: "書式をリセット",
|
|
1898
|
+
direction: "文字方向を切り替え (LTR / RTL)",
|
|
1899
|
+
fontFamily: "フォント",
|
|
1900
|
+
paragraphStyle: "段落スタイル",
|
|
1901
|
+
paragraphStylePlaceholder: "スタイル",
|
|
1902
|
+
lineHeight: "行の高さ",
|
|
1903
|
+
lineHeightPlaceholder: "↕ 行間",
|
|
1904
|
+
codeview: "HTMLソースを表示",
|
|
1905
|
+
fullscreen: "全画面表示",
|
|
1906
|
+
shortcuts: "キーボードショートカット (Ctrl+Shift+/)",
|
|
1907
|
+
find: "検索 (Ctrl+F)",
|
|
1908
|
+
findReplace: "検索と置換 (Ctrl+H)",
|
|
1909
|
+
inlineCode: "インラインコード (Ctrl+`)",
|
|
1910
|
+
print: "印刷",
|
|
1911
|
+
foreColor: "文字色",
|
|
1912
|
+
backColor: "ハイライト色",
|
|
1913
|
+
chooseTextColor: "文字色を選択",
|
|
1914
|
+
chooseHighlightColor: "ハイライト色を選択",
|
|
1915
|
+
customColor: "カスタムカラー",
|
|
1916
|
+
insertTableLabel: "テーブルを挿入",
|
|
1917
|
+
paragraphItems: {
|
|
1918
|
+
p: "標準",
|
|
1919
|
+
blockquote: "引用",
|
|
1920
|
+
pre: "コード"
|
|
1921
|
+
}
|
|
1922
|
+
},
|
|
1923
|
+
linkDialog: {
|
|
1924
|
+
ariaLabel: "リンクを挿入",
|
|
1925
|
+
title: "リンクを挿入",
|
|
1926
|
+
url: "URL",
|
|
1927
|
+
urlPlaceholder: "https://",
|
|
1928
|
+
displayText: "表示テキスト",
|
|
1929
|
+
textPlaceholder: "リンクテキスト",
|
|
1930
|
+
openInNewTab: "新しいタブで開く",
|
|
1931
|
+
insertBtn: "挿入",
|
|
1932
|
+
cancelBtn: "キャンセル"
|
|
1933
|
+
},
|
|
1934
|
+
imageDialog: {
|
|
1935
|
+
ariaLabel: "画像を挿入",
|
|
1936
|
+
title: "画像を挿入",
|
|
1937
|
+
imageUrl: "画像URL",
|
|
1938
|
+
urlPlaceholder: "https://example.com/image.png",
|
|
1939
|
+
altText: "代替テキスト",
|
|
1940
|
+
altPlaceholder: "画像の説明",
|
|
1941
|
+
alignment: "配置",
|
|
1942
|
+
alignNone: "なし",
|
|
1943
|
+
alignLeft: "左",
|
|
1944
|
+
alignCenter: "中央",
|
|
1945
|
+
alignRight: "右",
|
|
1946
|
+
uploadLabel: "ファイルをアップロード",
|
|
1947
|
+
insertBtn: "挿入",
|
|
1948
|
+
cancelBtn: "キャンセル"
|
|
1949
|
+
},
|
|
1950
|
+
videoDialog: {
|
|
1951
|
+
ariaLabel: "動画を挿入",
|
|
1952
|
+
title: "動画を挿入",
|
|
1953
|
+
videoUrl: "動画URL",
|
|
1954
|
+
urlPlaceholder: "YouTube、Vimeo、または直接動画URL",
|
|
1955
|
+
widthLabel: "幅 (px)",
|
|
1956
|
+
widthPlaceholder: "560",
|
|
1957
|
+
insertBtn: "挿入",
|
|
1958
|
+
cancelBtn: "キャンセル",
|
|
1959
|
+
detected: (type) => `検出: ${type}`,
|
|
1960
|
+
unknownFormat: "不明な形式 — 直接動画埋め込みを試みます",
|
|
1961
|
+
invalidUrl: "URLが無効です — 有効な動画URLを入力してください。"
|
|
1962
|
+
},
|
|
1963
|
+
emojiDialog: {
|
|
1964
|
+
ariaLabel: "絵文字を挿入",
|
|
1965
|
+
title: "絵文字を挿入",
|
|
1966
|
+
searchPlaceholder: "絵文字を検索…",
|
|
1967
|
+
all: "すべて",
|
|
1968
|
+
cancelBtn: "キャンセル",
|
|
1969
|
+
close: "閉じる",
|
|
1970
|
+
categories: {
|
|
1971
|
+
smileys: "顔文字",
|
|
1972
|
+
people: "人物",
|
|
1973
|
+
animals: "動物",
|
|
1974
|
+
food: "食べ物",
|
|
1975
|
+
travel: "旅行",
|
|
1976
|
+
objects: "モノ",
|
|
1977
|
+
symbols: "記号"
|
|
1978
|
+
}
|
|
1979
|
+
},
|
|
1980
|
+
iconDialog: {
|
|
1981
|
+
ariaLabel: "FAアイコンを挿入",
|
|
1982
|
+
title: "FAアイコンを挿入",
|
|
1983
|
+
searchPlaceholder: "アイコンを検索…",
|
|
1984
|
+
all: "すべて",
|
|
1985
|
+
style: "スタイル",
|
|
1986
|
+
size: "サイズ",
|
|
1987
|
+
color: "カラー",
|
|
1988
|
+
useColor: " カラーを使用",
|
|
1989
|
+
selectHint: "アイコンを選択してください",
|
|
1990
|
+
insertBtn: "FAアイコンを挿入",
|
|
1991
|
+
cancelBtn: "キャンセル",
|
|
1992
|
+
close: "閉じる",
|
|
1993
|
+
categories: {
|
|
1994
|
+
popular: "人気",
|
|
1995
|
+
interface: "インターフェース",
|
|
1996
|
+
navigation: "ナビゲーション",
|
|
1997
|
+
media: "メディア",
|
|
1998
|
+
communication: "通信",
|
|
1999
|
+
files: "ファイル",
|
|
2000
|
+
people: "人物",
|
|
2001
|
+
objects: "モノ"
|
|
2002
|
+
}
|
|
2003
|
+
},
|
|
2004
|
+
findReplace: {
|
|
2005
|
+
findTitle: "検索",
|
|
2006
|
+
findReplaceTitle: "検索と置換",
|
|
2007
|
+
findPlaceholder: "検索…",
|
|
2008
|
+
searchAriaLabel: "検索テキスト",
|
|
2009
|
+
caseSensitive: "\xA0大文字/小文字を区別",
|
|
2010
|
+
prevBtn: "← 前へ",
|
|
2011
|
+
nextBtn: "次へ →",
|
|
2012
|
+
replacePlaceholder: "置換後…",
|
|
2013
|
+
replaceAriaLabel: "置換後のテキスト",
|
|
2014
|
+
replaceBtn: "置換",
|
|
2015
|
+
replaceAllBtn: "すべて置換",
|
|
2016
|
+
close: "×"
|
|
2017
|
+
},
|
|
2018
|
+
shortcutsDialog: {
|
|
2019
|
+
title: "キーボードショートカット",
|
|
2020
|
+
ariaLabel: "キーボードショートカット",
|
|
2021
|
+
close: "閉じる",
|
|
2022
|
+
shortcuts: [
|
|
2023
|
+
{
|
|
2024
|
+
category: "テキスト書式",
|
|
2025
|
+
items: [
|
|
2026
|
+
{
|
|
2027
|
+
keys: "Ctrl + B",
|
|
2028
|
+
action: "太字"
|
|
2029
|
+
},
|
|
2030
|
+
{
|
|
2031
|
+
keys: "Ctrl + I",
|
|
2032
|
+
action: "斜体"
|
|
2033
|
+
},
|
|
2034
|
+
{
|
|
2035
|
+
keys: "Ctrl + U",
|
|
2036
|
+
action: "下線"
|
|
2037
|
+
},
|
|
2038
|
+
{
|
|
2039
|
+
keys: "Ctrl + K",
|
|
2040
|
+
action: "リンクの挿入 / 編集"
|
|
2041
|
+
}
|
|
2042
|
+
]
|
|
2043
|
+
},
|
|
2044
|
+
{
|
|
2045
|
+
category: "履歴",
|
|
2046
|
+
items: [{
|
|
2047
|
+
keys: "Ctrl + Z",
|
|
2048
|
+
action: "元に戻す"
|
|
2049
|
+
}, {
|
|
2050
|
+
keys: "Ctrl + Y / Ctrl + Shift + Z",
|
|
2051
|
+
action: "やり直す"
|
|
2052
|
+
}]
|
|
2053
|
+
},
|
|
2054
|
+
{
|
|
2055
|
+
category: "選択と移動",
|
|
2056
|
+
items: [
|
|
2057
|
+
{
|
|
2058
|
+
keys: "Ctrl + A",
|
|
2059
|
+
action: "すべて選択"
|
|
2060
|
+
},
|
|
2061
|
+
{
|
|
2062
|
+
keys: "Tab",
|
|
2063
|
+
action: "インデント増加 / スペース挿入"
|
|
2064
|
+
},
|
|
2065
|
+
{
|
|
2066
|
+
keys: "Shift + Tab",
|
|
2067
|
+
action: "インデント減少"
|
|
2068
|
+
}
|
|
2069
|
+
]
|
|
2070
|
+
},
|
|
2071
|
+
{
|
|
2072
|
+
category: "クリップボード",
|
|
2073
|
+
items: [{
|
|
2074
|
+
keys: "Ctrl + Shift + V",
|
|
2075
|
+
action: "プレーンテキストとして貼り付け"
|
|
2076
|
+
}]
|
|
2077
|
+
},
|
|
2078
|
+
{
|
|
2079
|
+
category: "検索と置換",
|
|
2080
|
+
items: [{
|
|
2081
|
+
keys: "Ctrl + F",
|
|
2082
|
+
action: "文書内を検索"
|
|
2083
|
+
}, {
|
|
2084
|
+
keys: "Ctrl + H",
|
|
2085
|
+
action: "検索と置換"
|
|
2086
|
+
}]
|
|
2087
|
+
},
|
|
2088
|
+
{
|
|
2089
|
+
category: "エディター",
|
|
2090
|
+
items: [{
|
|
2091
|
+
keys: "Ctrl + Shift + /",
|
|
2092
|
+
action: "ショートカットダイアログを表示"
|
|
2093
|
+
}]
|
|
2094
|
+
}
|
|
2095
|
+
]
|
|
2096
|
+
},
|
|
2097
|
+
contextMenu: {
|
|
2098
|
+
cut: "切り取り",
|
|
2099
|
+
copy: "コピー",
|
|
2100
|
+
paste: "貼り付け",
|
|
2101
|
+
bold: "太字",
|
|
2102
|
+
italic: "斜体",
|
|
2103
|
+
underline: "下線",
|
|
2104
|
+
textColor: "文字色",
|
|
2105
|
+
highlightColor: "ハイライト色",
|
|
2106
|
+
copyFormat: "書式をコピー",
|
|
2107
|
+
pasteFormat: "書式を貼り付け",
|
|
2108
|
+
removeFormat: "書式をリセット",
|
|
2109
|
+
link: "リンクを挿入",
|
|
2110
|
+
image: "画像を挿入",
|
|
2111
|
+
video: "動画を挿入",
|
|
2112
|
+
table: "テーブルを挿入",
|
|
2113
|
+
back: "戻る",
|
|
2114
|
+
noHighlight: "ハイライトなし",
|
|
2115
|
+
customColor: "カスタムカラー",
|
|
2116
|
+
customColorLabel: "カスタム…"
|
|
2117
|
+
},
|
|
2118
|
+
statusbar: {
|
|
2119
|
+
resizeHandle: "ドラッグしてリサイズ",
|
|
2120
|
+
words: (n) => `単語数: ${n}`,
|
|
2121
|
+
wordsLimit: (n, max) => `単語数: ${n}/${max}`,
|
|
2122
|
+
chars: (n) => `文字数: ${n}`,
|
|
2123
|
+
charsLimit: (n, max) => `文字数: ${n}/${max}`
|
|
2124
|
+
},
|
|
2125
|
+
tooltips: {
|
|
2126
|
+
link: {
|
|
2127
|
+
ariaLabel: "リンク操作",
|
|
2128
|
+
openLink: "リンクを開く",
|
|
2129
|
+
copyUrl: "URLをコピー",
|
|
2130
|
+
editLink: "リンクを編集",
|
|
2131
|
+
removeLink: "リンクを削除"
|
|
2132
|
+
},
|
|
2133
|
+
image: {
|
|
2134
|
+
ariaLabel: "画像操作",
|
|
2135
|
+
label: "画像",
|
|
2136
|
+
floatLeft: "左に回り込み",
|
|
2137
|
+
noFloat: "回り込みなし",
|
|
2138
|
+
alignCenter: "中央揃え",
|
|
2139
|
+
floatRight: "右に回り込み",
|
|
2140
|
+
originalSize: "元のサイズ",
|
|
2141
|
+
rotateLeft: "左に回転",
|
|
2142
|
+
rotateRight: "右に回転",
|
|
2143
|
+
cropImage: "画像をトリミング",
|
|
2144
|
+
addCaption: "キャプションを追加 / 編集",
|
|
2145
|
+
deleteImage: "画像を削除"
|
|
2146
|
+
},
|
|
2147
|
+
code: {
|
|
2148
|
+
ariaLabel: "コードブロック操作",
|
|
2149
|
+
label: "コード",
|
|
2150
|
+
syntaxLanguage: "言語",
|
|
2151
|
+
syntaxAriaLabel: "構文言語",
|
|
2152
|
+
copyCode: "コードをコピー",
|
|
2153
|
+
toggleWordWrap: "折り返しを切り替え",
|
|
2154
|
+
enableWordWrap: "折り返しを有効にする",
|
|
2155
|
+
disableWordWrap: "折り返しを無効にする",
|
|
2156
|
+
convertToParagraph: "段落に変換",
|
|
2157
|
+
deleteCodeBlock: "コードブロックを削除"
|
|
2158
|
+
},
|
|
2159
|
+
table: {
|
|
2160
|
+
ariaLabel: "テーブル操作",
|
|
2161
|
+
label: "テーブル",
|
|
2162
|
+
selectCells: "セルを選択",
|
|
2163
|
+
addRowAbove: "上に行を追加",
|
|
2164
|
+
addRowBelow: "下に行を追加",
|
|
2165
|
+
deleteRow: "行を削除",
|
|
2166
|
+
addColumnLeft: "左に列を追加",
|
|
2167
|
+
addColumnRight: "右に列を追加",
|
|
2168
|
+
deleteColumn: "列を削除",
|
|
2169
|
+
mergeCells: "セルを結合",
|
|
2170
|
+
unmergeCells: "セルの結合を解除",
|
|
2171
|
+
columnWidth: "列幅",
|
|
2172
|
+
rowHeight: "行の高さ",
|
|
2173
|
+
tableBorderWidth: "テーブルの枠幅",
|
|
2174
|
+
deleteTable: "テーブルを削除",
|
|
2175
|
+
columnWidthPx: "列幅 (px)",
|
|
2176
|
+
rowHeightPx: "行の高さ (px)",
|
|
2177
|
+
tableBorderWidthPx: "テーブルの枠幅 (px)",
|
|
2178
|
+
cancelBtn: "キャンセル",
|
|
2179
|
+
applyBtn: "適用"
|
|
2180
|
+
},
|
|
2181
|
+
video: {
|
|
2182
|
+
ariaLabel: "動画操作",
|
|
2183
|
+
label: "動画",
|
|
2184
|
+
floatLeft: "左に回り込み",
|
|
2185
|
+
noFloat: "回り込みなし",
|
|
2186
|
+
alignCenter: "中央揃え",
|
|
2187
|
+
floatRight: "右に回り込み",
|
|
2188
|
+
originalSize: "元のサイズ",
|
|
2189
|
+
previewVideo: "プレビュー",
|
|
2190
|
+
exitPreview: "プレビューを終了",
|
|
2191
|
+
deleteVideo: "動画を削除"
|
|
2192
|
+
}
|
|
2193
|
+
},
|
|
2194
|
+
errors: {
|
|
2195
|
+
imageFormat: (type) => `形式 "${type}" はブラウザでの表示をサポートしていません。JPEG、PNG、または WebP に変換してください。`,
|
|
2196
|
+
imageSize: (maxSize) => `画像ファイルが大きすぎます。最大許容サイズは ${maxSize} MB です。`
|
|
2197
|
+
}
|
|
2198
|
+
},
|
|
2199
|
+
zh: {
|
|
2200
|
+
toolbar: {
|
|
2201
|
+
bold: "粗体 (Ctrl+B)",
|
|
2202
|
+
italic: "斜体 (Ctrl+I)",
|
|
2203
|
+
underline: "下划线 (Ctrl+U)",
|
|
2204
|
+
strikethrough: "删除线",
|
|
2205
|
+
superscript: "上标",
|
|
2206
|
+
subscript: "下标",
|
|
2207
|
+
alignLeft: "左对齐",
|
|
2208
|
+
alignCenter: "居中",
|
|
2209
|
+
alignRight: "右对齐",
|
|
2210
|
+
alignJustify: "两端对齐",
|
|
2211
|
+
ul: "无序列表",
|
|
2212
|
+
ol: "有序列表",
|
|
2213
|
+
checklist: "待办列表",
|
|
2214
|
+
indent: "增加缩进",
|
|
2215
|
+
outdent: "减少缩进",
|
|
2216
|
+
undo: "撤销 (Ctrl+Z)",
|
|
2217
|
+
redo: "重做 (Ctrl+Y)",
|
|
2218
|
+
hr: "水平分割线",
|
|
2219
|
+
link: "插入链接",
|
|
2220
|
+
image: "插入图片",
|
|
2221
|
+
video: "插入视频",
|
|
2222
|
+
emoji: "插入表情",
|
|
2223
|
+
icon: "插入 FA 图标",
|
|
2224
|
+
table: "插入表格",
|
|
2225
|
+
fontSize: "字号",
|
|
2226
|
+
fontSizePlaceholder: "大小",
|
|
2227
|
+
removeFormat: "清除格式",
|
|
2228
|
+
direction: "切换文字方向 (LTR / RTL)",
|
|
2229
|
+
fontFamily: "字体",
|
|
2230
|
+
paragraphStyle: "段落样式",
|
|
2231
|
+
paragraphStylePlaceholder: "样式",
|
|
2232
|
+
lineHeight: "行高",
|
|
2233
|
+
lineHeightPlaceholder: "↕ 行距",
|
|
2234
|
+
codeview: "查看 HTML 源码",
|
|
2235
|
+
fullscreen: "全屏",
|
|
2236
|
+
shortcuts: "键盘快捷键 (Ctrl+Shift+/)",
|
|
2237
|
+
find: "搜索 (Ctrl+F)",
|
|
2238
|
+
findReplace: "查找和替换 (Ctrl+H)",
|
|
2239
|
+
inlineCode: "行内代码 (Ctrl+`)",
|
|
2240
|
+
print: "打印",
|
|
2241
|
+
foreColor: "文字颜色",
|
|
2242
|
+
backColor: "高亮颜色",
|
|
2243
|
+
chooseTextColor: "选择文字颜色",
|
|
2244
|
+
chooseHighlightColor: "选择高亮颜色",
|
|
2245
|
+
customColor: "自定义颜色",
|
|
2246
|
+
insertTableLabel: "插入表格",
|
|
2247
|
+
paragraphItems: {
|
|
2248
|
+
p: "正文",
|
|
2249
|
+
blockquote: "引用",
|
|
2250
|
+
pre: "代码"
|
|
2251
|
+
}
|
|
2252
|
+
},
|
|
2253
|
+
linkDialog: {
|
|
2254
|
+
ariaLabel: "插入链接",
|
|
2255
|
+
title: "插入链接",
|
|
2256
|
+
url: "链接地址",
|
|
2257
|
+
urlPlaceholder: "https://",
|
|
2258
|
+
displayText: "显示文字",
|
|
2259
|
+
textPlaceholder: "链接文字",
|
|
2260
|
+
openInNewTab: "在新标签页中打开",
|
|
2261
|
+
insertBtn: "插入",
|
|
2262
|
+
cancelBtn: "取消"
|
|
2263
|
+
},
|
|
2264
|
+
imageDialog: {
|
|
2265
|
+
ariaLabel: "插入图片",
|
|
2266
|
+
title: "插入图片",
|
|
2267
|
+
imageUrl: "图片地址",
|
|
2268
|
+
urlPlaceholder: "https://example.com/image.png",
|
|
2269
|
+
altText: "替代文字",
|
|
2270
|
+
altPlaceholder: "图片描述",
|
|
2271
|
+
alignment: "对齐方式",
|
|
2272
|
+
alignNone: "无",
|
|
2273
|
+
alignLeft: "左",
|
|
2274
|
+
alignCenter: "居中",
|
|
2275
|
+
alignRight: "右",
|
|
2276
|
+
uploadLabel: "或上传文件",
|
|
2277
|
+
insertBtn: "插入",
|
|
2278
|
+
cancelBtn: "取消"
|
|
2279
|
+
},
|
|
2280
|
+
videoDialog: {
|
|
2281
|
+
ariaLabel: "插入视频",
|
|
2282
|
+
title: "插入视频",
|
|
2283
|
+
videoUrl: "视频地址",
|
|
2284
|
+
urlPlaceholder: "YouTube、Vimeo 或直接 .mp4 链接",
|
|
2285
|
+
widthLabel: "宽度 (px)",
|
|
2286
|
+
widthPlaceholder: "560",
|
|
2287
|
+
insertBtn: "插入",
|
|
2288
|
+
cancelBtn: "取消",
|
|
2289
|
+
detected: (type) => `已识别: ${type}`,
|
|
2290
|
+
unknownFormat: "未知格式 — 将尝试直接嵌入视频",
|
|
2291
|
+
invalidUrl: "URL 无效 — 请输入有效的视频链接。"
|
|
2292
|
+
},
|
|
2293
|
+
emojiDialog: {
|
|
2294
|
+
ariaLabel: "插入表情",
|
|
2295
|
+
title: "插入表情",
|
|
2296
|
+
searchPlaceholder: "搜索表情…",
|
|
2297
|
+
all: "全部",
|
|
2298
|
+
cancelBtn: "取消",
|
|
2299
|
+
close: "关闭",
|
|
2300
|
+
categories: {
|
|
2301
|
+
smileys: "笑脸",
|
|
2302
|
+
people: "人物",
|
|
2303
|
+
animals: "动物",
|
|
2304
|
+
food: "食物",
|
|
2305
|
+
travel: "旅行",
|
|
2306
|
+
objects: "物品",
|
|
2307
|
+
symbols: "符号"
|
|
2308
|
+
}
|
|
2309
|
+
},
|
|
2310
|
+
iconDialog: {
|
|
2311
|
+
ariaLabel: "插入 FA 图标",
|
|
2312
|
+
title: "插入 FA 图标",
|
|
2313
|
+
searchPlaceholder: "搜索图标…",
|
|
2314
|
+
all: "全部",
|
|
2315
|
+
style: "样式",
|
|
2316
|
+
size: "大小",
|
|
2317
|
+
color: "颜色",
|
|
2318
|
+
useColor: " 使用颜色",
|
|
2319
|
+
selectHint: "请选择一个图标",
|
|
2320
|
+
insertBtn: "插入 FA 图标",
|
|
2321
|
+
cancelBtn: "取消",
|
|
2322
|
+
close: "关闭",
|
|
2323
|
+
categories: {
|
|
2324
|
+
popular: "热门",
|
|
2325
|
+
interface: "界面",
|
|
2326
|
+
navigation: "导航",
|
|
2327
|
+
media: "媒体",
|
|
2328
|
+
communication: "通讯",
|
|
2329
|
+
files: "文件",
|
|
2330
|
+
people: "人物",
|
|
2331
|
+
objects: "物品"
|
|
2332
|
+
}
|
|
2333
|
+
},
|
|
2334
|
+
findReplace: {
|
|
2335
|
+
findTitle: "搜索",
|
|
2336
|
+
findReplaceTitle: "查找和替换",
|
|
2337
|
+
findPlaceholder: "查找…",
|
|
2338
|
+
searchAriaLabel: "搜索文字",
|
|
2339
|
+
caseSensitive: "\xA0区分大小写",
|
|
2340
|
+
prevBtn: "← 上一个",
|
|
2341
|
+
nextBtn: "下一个 →",
|
|
2342
|
+
replacePlaceholder: "替换为…",
|
|
2343
|
+
replaceAriaLabel: "替换为",
|
|
2344
|
+
replaceBtn: "替换",
|
|
2345
|
+
replaceAllBtn: "全部替换",
|
|
2346
|
+
close: "×"
|
|
2347
|
+
},
|
|
2348
|
+
shortcutsDialog: {
|
|
2349
|
+
title: "键盘快捷键",
|
|
2350
|
+
ariaLabel: "键盘快捷键",
|
|
2351
|
+
close: "关闭",
|
|
2352
|
+
shortcuts: [
|
|
2353
|
+
{
|
|
2354
|
+
category: "文字格式",
|
|
2355
|
+
items: [
|
|
2356
|
+
{
|
|
2357
|
+
keys: "Ctrl + B",
|
|
2358
|
+
action: "粗体"
|
|
2359
|
+
},
|
|
2360
|
+
{
|
|
2361
|
+
keys: "Ctrl + I",
|
|
2362
|
+
action: "斜体"
|
|
2363
|
+
},
|
|
2364
|
+
{
|
|
2365
|
+
keys: "Ctrl + U",
|
|
2366
|
+
action: "下划线"
|
|
2367
|
+
},
|
|
2368
|
+
{
|
|
2369
|
+
keys: "Ctrl + K",
|
|
2370
|
+
action: "插入 / 编辑链接"
|
|
2371
|
+
}
|
|
2372
|
+
]
|
|
2373
|
+
},
|
|
2374
|
+
{
|
|
2375
|
+
category: "历史记录",
|
|
2376
|
+
items: [{
|
|
2377
|
+
keys: "Ctrl + Z",
|
|
2378
|
+
action: "撤销"
|
|
2379
|
+
}, {
|
|
2380
|
+
keys: "Ctrl + Y / Ctrl + Shift + Z",
|
|
2381
|
+
action: "重做"
|
|
2382
|
+
}]
|
|
2383
|
+
},
|
|
2384
|
+
{
|
|
2385
|
+
category: "选择与导航",
|
|
2386
|
+
items: [
|
|
2387
|
+
{
|
|
2388
|
+
keys: "Ctrl + A",
|
|
2389
|
+
action: "全选"
|
|
2390
|
+
},
|
|
2391
|
+
{
|
|
2392
|
+
keys: "Tab",
|
|
2393
|
+
action: "增加缩进 / 插入空格"
|
|
2394
|
+
},
|
|
2395
|
+
{
|
|
2396
|
+
keys: "Shift + Tab",
|
|
2397
|
+
action: "减少缩进"
|
|
2398
|
+
}
|
|
2399
|
+
]
|
|
2400
|
+
},
|
|
2401
|
+
{
|
|
2402
|
+
category: "剪贴板",
|
|
2403
|
+
items: [{
|
|
2404
|
+
keys: "Ctrl + Shift + V",
|
|
2405
|
+
action: "粘贴为纯文本"
|
|
2406
|
+
}]
|
|
2407
|
+
},
|
|
2408
|
+
{
|
|
2409
|
+
category: "查找和替换",
|
|
2410
|
+
items: [{
|
|
2411
|
+
keys: "Ctrl + F",
|
|
2412
|
+
action: "在文档中搜索"
|
|
2413
|
+
}, {
|
|
2414
|
+
keys: "Ctrl + H",
|
|
2415
|
+
action: "查找和替换"
|
|
2416
|
+
}]
|
|
2417
|
+
},
|
|
2418
|
+
{
|
|
2419
|
+
category: "编辑器",
|
|
2420
|
+
items: [{
|
|
2421
|
+
keys: "Ctrl + Shift + /",
|
|
2422
|
+
action: "显示快捷键对话框"
|
|
2423
|
+
}]
|
|
2424
|
+
}
|
|
2425
|
+
]
|
|
2426
|
+
},
|
|
2427
|
+
contextMenu: {
|
|
2428
|
+
cut: "剪切",
|
|
2429
|
+
copy: "复制",
|
|
2430
|
+
paste: "粘贴",
|
|
2431
|
+
bold: "粗体",
|
|
2432
|
+
italic: "斜体",
|
|
2433
|
+
underline: "下划线",
|
|
2434
|
+
textColor: "文字颜色",
|
|
2435
|
+
highlightColor: "高亮颜色",
|
|
2436
|
+
copyFormat: "复制格式",
|
|
2437
|
+
pasteFormat: "粘贴格式",
|
|
2438
|
+
removeFormat: "清除格式",
|
|
2439
|
+
link: "插入链接",
|
|
2440
|
+
image: "插入图片",
|
|
2441
|
+
video: "插入视频",
|
|
2442
|
+
table: "插入表格",
|
|
2443
|
+
back: "返回",
|
|
2444
|
+
noHighlight: "无高亮",
|
|
2445
|
+
customColor: "自定义颜色",
|
|
2446
|
+
customColorLabel: "自定义…"
|
|
2447
|
+
},
|
|
2448
|
+
statusbar: {
|
|
2449
|
+
resizeHandle: "拖动以调整大小",
|
|
2450
|
+
words: (n) => `字数: ${n}`,
|
|
2451
|
+
wordsLimit: (n, max) => `字数: ${n}/${max}`,
|
|
2452
|
+
chars: (n) => `字符数: ${n}`,
|
|
2453
|
+
charsLimit: (n, max) => `字符数: ${n}/${max}`
|
|
2454
|
+
},
|
|
2455
|
+
tooltips: {
|
|
2456
|
+
link: {
|
|
2457
|
+
ariaLabel: "链接操作",
|
|
2458
|
+
openLink: "打开链接",
|
|
2459
|
+
copyUrl: "复制 URL",
|
|
2460
|
+
editLink: "编辑链接",
|
|
2461
|
+
removeLink: "删除链接"
|
|
2462
|
+
},
|
|
2463
|
+
image: {
|
|
2464
|
+
ariaLabel: "图片操作",
|
|
2465
|
+
label: "图片",
|
|
2466
|
+
floatLeft: "左浮动",
|
|
2467
|
+
noFloat: "不浮动",
|
|
2468
|
+
alignCenter: "居中对齐",
|
|
2469
|
+
floatRight: "右浮动",
|
|
2470
|
+
originalSize: "原始尺寸",
|
|
2471
|
+
rotateLeft: "向左旋转",
|
|
2472
|
+
rotateRight: "向右旋转",
|
|
2473
|
+
cropImage: "裁剪图片",
|
|
2474
|
+
addCaption: "添加 / 编辑说明",
|
|
2475
|
+
deleteImage: "删除图片"
|
|
2476
|
+
},
|
|
2477
|
+
code: {
|
|
2478
|
+
ariaLabel: "代码块操作",
|
|
2479
|
+
label: "代码",
|
|
2480
|
+
syntaxLanguage: "语法语言",
|
|
2481
|
+
syntaxAriaLabel: "语法语言",
|
|
2482
|
+
copyCode: "复制代码",
|
|
2483
|
+
toggleWordWrap: "切换自动换行",
|
|
2484
|
+
enableWordWrap: "启用自动换行",
|
|
2485
|
+
disableWordWrap: "禁用自动换行",
|
|
2486
|
+
convertToParagraph: "转换为段落",
|
|
2487
|
+
deleteCodeBlock: "删除代码块"
|
|
2488
|
+
},
|
|
2489
|
+
table: {
|
|
2490
|
+
ariaLabel: "表格操作",
|
|
2491
|
+
label: "表格",
|
|
2492
|
+
selectCells: "选择单元格",
|
|
2493
|
+
addRowAbove: "在上方插入行",
|
|
2494
|
+
addRowBelow: "在下方插入行",
|
|
2495
|
+
deleteRow: "删除行",
|
|
2496
|
+
addColumnLeft: "在左侧插入列",
|
|
2497
|
+
addColumnRight: "在右侧插入列",
|
|
2498
|
+
deleteColumn: "删除列",
|
|
2499
|
+
mergeCells: "合并单元格",
|
|
2500
|
+
unmergeCells: "拆分单元格",
|
|
2501
|
+
columnWidth: "列宽",
|
|
2502
|
+
rowHeight: "行高",
|
|
2503
|
+
tableBorderWidth: "表格边框宽度",
|
|
2504
|
+
deleteTable: "删除表格",
|
|
2505
|
+
columnWidthPx: "列宽 (px)",
|
|
2506
|
+
rowHeightPx: "行高 (px)",
|
|
2507
|
+
tableBorderWidthPx: "表格边框宽度 (px)",
|
|
2508
|
+
cancelBtn: "取消",
|
|
2509
|
+
applyBtn: "应用"
|
|
2510
|
+
},
|
|
2511
|
+
video: {
|
|
2512
|
+
ariaLabel: "视频操作",
|
|
2513
|
+
label: "视频",
|
|
2514
|
+
floatLeft: "左浮动",
|
|
2515
|
+
noFloat: "不浮动",
|
|
2516
|
+
alignCenter: "居中对齐",
|
|
2517
|
+
floatRight: "右浮动",
|
|
2518
|
+
originalSize: "原始尺寸",
|
|
2519
|
+
previewVideo: "预览视频",
|
|
2520
|
+
exitPreview: "退出预览",
|
|
2521
|
+
deleteVideo: "删除视频"
|
|
2522
|
+
}
|
|
2523
|
+
},
|
|
2524
|
+
errors: {
|
|
2525
|
+
imageFormat: (type) => `格式 "${type}" 不支持在浏览器中显示。请转换为 JPEG、PNG 或 WebP。`,
|
|
2526
|
+
imageSize: (maxSize) => `图片文件过大。最大允许大小为 ${maxSize} MB。`
|
|
2527
|
+
}
|
|
2528
|
+
},
|
|
2529
|
+
fr: {
|
|
2530
|
+
toolbar: {
|
|
2531
|
+
bold: "Gras (Ctrl+B)",
|
|
2532
|
+
italic: "Italique (Ctrl+I)",
|
|
2533
|
+
underline: "Souligné (Ctrl+U)",
|
|
2534
|
+
strikethrough: "Barré",
|
|
2535
|
+
superscript: "Exposant",
|
|
2536
|
+
subscript: "Indice",
|
|
2537
|
+
alignLeft: "Aligner à gauche",
|
|
2538
|
+
alignCenter: "Centrer",
|
|
2539
|
+
alignRight: "Aligner à droite",
|
|
2540
|
+
alignJustify: "Justifier",
|
|
2541
|
+
ul: "Liste à puces",
|
|
2542
|
+
ol: "Liste numérotée",
|
|
2543
|
+
checklist: "Liste de tâches",
|
|
2544
|
+
indent: "Augmenter le retrait",
|
|
2545
|
+
outdent: "Diminuer le retrait",
|
|
2546
|
+
undo: "Annuler (Ctrl+Z)",
|
|
2547
|
+
redo: "Rétablir (Ctrl+Y)",
|
|
2548
|
+
hr: "Ligne horizontale",
|
|
2549
|
+
link: "Insérer un lien",
|
|
2550
|
+
image: "Insérer une image",
|
|
2551
|
+
video: "Insérer une vidéo",
|
|
2552
|
+
emoji: "Insérer un emoji",
|
|
2553
|
+
icon: "Insérer une icône FA",
|
|
2554
|
+
table: "Insérer un tableau",
|
|
2555
|
+
fontSize: "Taille de police",
|
|
2556
|
+
fontSizePlaceholder: "Taille",
|
|
2557
|
+
removeFormat: "Effacer la mise en forme",
|
|
2558
|
+
direction: "Basculer la direction du texte (LTR / RTL)",
|
|
2559
|
+
fontFamily: "Police",
|
|
2560
|
+
paragraphStyle: "Style de paragraphe",
|
|
2561
|
+
paragraphStylePlaceholder: "Style",
|
|
2562
|
+
lineHeight: "Interligne",
|
|
2563
|
+
lineHeightPlaceholder: "↕ Ligne",
|
|
2564
|
+
codeview: "Afficher le code HTML",
|
|
2565
|
+
fullscreen: "Plein écran",
|
|
2566
|
+
shortcuts: "Raccourcis clavier (Ctrl+Shift+/)",
|
|
2567
|
+
find: "Rechercher (Ctrl+F)",
|
|
2568
|
+
findReplace: "Rechercher et remplacer (Ctrl+H)",
|
|
2569
|
+
inlineCode: "Code inline (Ctrl+`)",
|
|
2570
|
+
print: "Imprimer",
|
|
2571
|
+
foreColor: "Couleur du texte",
|
|
2572
|
+
backColor: "Couleur de surbrillance",
|
|
2573
|
+
chooseTextColor: "Choisir la couleur du texte",
|
|
2574
|
+
chooseHighlightColor: "Choisir la couleur de surbrillance",
|
|
2575
|
+
customColor: "Couleur personnalisée",
|
|
2576
|
+
insertTableLabel: "Insérer un tableau",
|
|
2577
|
+
paragraphItems: {
|
|
2578
|
+
p: "Normal",
|
|
2579
|
+
blockquote: "Citation",
|
|
2580
|
+
pre: "Code"
|
|
2581
|
+
}
|
|
2582
|
+
},
|
|
2583
|
+
linkDialog: {
|
|
2584
|
+
ariaLabel: "Insérer un lien",
|
|
2585
|
+
title: "Insérer un lien",
|
|
2586
|
+
url: "URL",
|
|
2587
|
+
urlPlaceholder: "https://",
|
|
2588
|
+
displayText: "Texte affiché",
|
|
2589
|
+
textPlaceholder: "Texte du lien",
|
|
2590
|
+
openInNewTab: "Ouvrir dans un nouvel onglet",
|
|
2591
|
+
insertBtn: "Insérer",
|
|
2592
|
+
cancelBtn: "Annuler"
|
|
2593
|
+
},
|
|
2594
|
+
imageDialog: {
|
|
2595
|
+
ariaLabel: "Insérer une image",
|
|
2596
|
+
title: "Insérer une image",
|
|
2597
|
+
imageUrl: "URL de l'image",
|
|
2598
|
+
urlPlaceholder: "https://example.com/image.png",
|
|
2599
|
+
altText: "Texte alternatif",
|
|
2600
|
+
altPlaceholder: "Description de l'image",
|
|
2601
|
+
alignment: "Alignement",
|
|
2602
|
+
alignNone: "Aucun",
|
|
2603
|
+
alignLeft: "Gauche",
|
|
2604
|
+
alignCenter: "Centre",
|
|
2605
|
+
alignRight: "Droite",
|
|
2606
|
+
uploadLabel: "Ou téléverser un fichier",
|
|
2607
|
+
insertBtn: "Insérer",
|
|
2608
|
+
cancelBtn: "Annuler"
|
|
2609
|
+
},
|
|
2610
|
+
videoDialog: {
|
|
2611
|
+
ariaLabel: "Insérer une vidéo",
|
|
2612
|
+
title: "Insérer une vidéo",
|
|
2613
|
+
videoUrl: "URL de la vidéo",
|
|
2614
|
+
urlPlaceholder: "YouTube, Vimeo ou URL .mp4 directe",
|
|
2615
|
+
widthLabel: "Largeur (px)",
|
|
2616
|
+
widthPlaceholder: "560",
|
|
2617
|
+
insertBtn: "Insérer",
|
|
2618
|
+
cancelBtn: "Annuler",
|
|
2619
|
+
detected: (type) => `Détecté\u00a0: ${type}`,
|
|
2620
|
+
unknownFormat: "Format inconnu — tentative d'intégration directe",
|
|
2621
|
+
invalidUrl: "URL invalide — veuillez saisir un lien vidéo valide."
|
|
2622
|
+
},
|
|
2623
|
+
emojiDialog: {
|
|
2624
|
+
ariaLabel: "Insérer un emoji",
|
|
2625
|
+
title: "Insérer un emoji",
|
|
2626
|
+
searchPlaceholder: "Rechercher des emojis…",
|
|
2627
|
+
all: "Tout",
|
|
2628
|
+
cancelBtn: "Annuler",
|
|
2629
|
+
close: "Fermer",
|
|
2630
|
+
categories: {
|
|
2631
|
+
smileys: "Smileys",
|
|
2632
|
+
people: "Personnes",
|
|
2633
|
+
animals: "Animaux",
|
|
2634
|
+
food: "Nourriture",
|
|
2635
|
+
travel: "Voyage",
|
|
2636
|
+
objects: "Objets",
|
|
2637
|
+
symbols: "Symboles"
|
|
2638
|
+
}
|
|
2639
|
+
},
|
|
2640
|
+
iconDialog: {
|
|
2641
|
+
ariaLabel: "Insérer une icône FA",
|
|
2642
|
+
title: "Insérer une icône FA",
|
|
2643
|
+
searchPlaceholder: "Rechercher des icônes…",
|
|
2644
|
+
all: "Tout",
|
|
2645
|
+
style: "Style",
|
|
2646
|
+
size: "Taille",
|
|
2647
|
+
color: "Couleur",
|
|
2648
|
+
useColor: " Utiliser la couleur",
|
|
2649
|
+
selectHint: "Sélectionner une icône",
|
|
2650
|
+
insertBtn: "Insérer une icône FA",
|
|
2651
|
+
cancelBtn: "Annuler",
|
|
2652
|
+
close: "Fermer",
|
|
2653
|
+
categories: {
|
|
2654
|
+
popular: "Populaire",
|
|
2655
|
+
interface: "Interface",
|
|
2656
|
+
navigation: "Navigation",
|
|
2657
|
+
media: "Média",
|
|
2658
|
+
communication: "Communication",
|
|
2659
|
+
files: "Fichiers",
|
|
2660
|
+
people: "Personnes",
|
|
2661
|
+
objects: "Objets"
|
|
2662
|
+
}
|
|
2663
|
+
},
|
|
2664
|
+
findReplace: {
|
|
2665
|
+
findTitle: "Rechercher",
|
|
2666
|
+
findReplaceTitle: "Rechercher et remplacer",
|
|
2667
|
+
findPlaceholder: "Rechercher…",
|
|
2668
|
+
searchAriaLabel: "Texte à rechercher",
|
|
2669
|
+
caseSensitive: "\xA0Respecter la casse",
|
|
2670
|
+
prevBtn: "← Préc.",
|
|
2671
|
+
nextBtn: "Suiv. →",
|
|
2672
|
+
replacePlaceholder: "Remplacer par…",
|
|
2673
|
+
replaceAriaLabel: "Remplacer par",
|
|
2674
|
+
replaceBtn: "Remplacer",
|
|
2675
|
+
replaceAllBtn: "Tout remplacer",
|
|
2676
|
+
close: "×"
|
|
2677
|
+
},
|
|
2678
|
+
shortcutsDialog: {
|
|
2679
|
+
title: "Raccourcis clavier",
|
|
2680
|
+
ariaLabel: "Raccourcis clavier",
|
|
2681
|
+
close: "Fermer",
|
|
2682
|
+
shortcuts: [
|
|
2683
|
+
{
|
|
2684
|
+
category: "Mise en forme du texte",
|
|
2685
|
+
items: [
|
|
2686
|
+
{
|
|
2687
|
+
keys: "Ctrl + B",
|
|
2688
|
+
action: "Gras"
|
|
2689
|
+
},
|
|
2690
|
+
{
|
|
2691
|
+
keys: "Ctrl + I",
|
|
2692
|
+
action: "Italique"
|
|
2693
|
+
},
|
|
2694
|
+
{
|
|
2695
|
+
keys: "Ctrl + U",
|
|
2696
|
+
action: "Souligné"
|
|
2697
|
+
},
|
|
2698
|
+
{
|
|
2699
|
+
keys: "Ctrl + K",
|
|
2700
|
+
action: "Insérer / modifier un lien"
|
|
2701
|
+
}
|
|
2702
|
+
]
|
|
2703
|
+
},
|
|
2704
|
+
{
|
|
2705
|
+
category: "Historique",
|
|
2706
|
+
items: [{
|
|
2707
|
+
keys: "Ctrl + Z",
|
|
2708
|
+
action: "Annuler"
|
|
2709
|
+
}, {
|
|
2710
|
+
keys: "Ctrl + Y / Ctrl + Shift + Z",
|
|
2711
|
+
action: "Rétablir"
|
|
2712
|
+
}]
|
|
2713
|
+
},
|
|
2714
|
+
{
|
|
2715
|
+
category: "Sélection et navigation",
|
|
2716
|
+
items: [
|
|
2717
|
+
{
|
|
2718
|
+
keys: "Ctrl + A",
|
|
2719
|
+
action: "Tout sélectionner"
|
|
2720
|
+
},
|
|
2721
|
+
{
|
|
2722
|
+
keys: "Tab",
|
|
2723
|
+
action: "Augmenter le retrait / insérer des espaces"
|
|
2724
|
+
},
|
|
2725
|
+
{
|
|
2726
|
+
keys: "Shift + Tab",
|
|
2727
|
+
action: "Diminuer le retrait"
|
|
2728
|
+
}
|
|
2729
|
+
]
|
|
2730
|
+
},
|
|
2731
|
+
{
|
|
2732
|
+
category: "Presse-papiers",
|
|
2733
|
+
items: [{
|
|
2734
|
+
keys: "Ctrl + Shift + V",
|
|
2735
|
+
action: "Coller en texte brut"
|
|
2736
|
+
}]
|
|
2737
|
+
},
|
|
2738
|
+
{
|
|
2739
|
+
category: "Rechercher et remplacer",
|
|
2740
|
+
items: [{
|
|
2741
|
+
keys: "Ctrl + F",
|
|
2742
|
+
action: "Rechercher dans le document"
|
|
2743
|
+
}, {
|
|
2744
|
+
keys: "Ctrl + H",
|
|
2745
|
+
action: "Rechercher et remplacer"
|
|
2746
|
+
}]
|
|
2747
|
+
},
|
|
2748
|
+
{
|
|
2749
|
+
category: "Éditeur",
|
|
2750
|
+
items: [{
|
|
2751
|
+
keys: "Ctrl + Shift + /",
|
|
2752
|
+
action: "Afficher les raccourcis clavier"
|
|
2753
|
+
}]
|
|
2754
|
+
}
|
|
2755
|
+
]
|
|
2756
|
+
},
|
|
2757
|
+
contextMenu: {
|
|
2758
|
+
cut: "Couper",
|
|
2759
|
+
copy: "Copier",
|
|
2760
|
+
paste: "Coller",
|
|
2761
|
+
bold: "Gras",
|
|
2762
|
+
italic: "Italique",
|
|
2763
|
+
underline: "Souligné",
|
|
2764
|
+
textColor: "Couleur du texte",
|
|
2765
|
+
highlightColor: "Couleur de surbrillance",
|
|
2766
|
+
copyFormat: "Copier la mise en forme",
|
|
2767
|
+
pasteFormat: "Coller la mise en forme",
|
|
2768
|
+
removeFormat: "Effacer la mise en forme",
|
|
2769
|
+
link: "Insérer un lien",
|
|
2770
|
+
image: "Insérer une image",
|
|
2771
|
+
video: "Insérer une vidéo",
|
|
2772
|
+
table: "Insérer un tableau",
|
|
2773
|
+
back: "Retour",
|
|
2774
|
+
noHighlight: "Sans surbrillance",
|
|
2775
|
+
customColor: "Couleur personnalisée",
|
|
2776
|
+
customColorLabel: "Personnaliser…"
|
|
2777
|
+
},
|
|
2778
|
+
statusbar: {
|
|
2779
|
+
resizeHandle: "Faire glisser pour redimensionner",
|
|
2780
|
+
words: (n) => `Mots\u00a0: ${n}`,
|
|
2781
|
+
wordsLimit: (n, max) => `Mots\u00a0: ${n}/${max}`,
|
|
2782
|
+
chars: (n) => `Caractères\u00a0: ${n}`,
|
|
2783
|
+
charsLimit: (n, max) => `Caractères\u00a0: ${n}/${max}`
|
|
2784
|
+
},
|
|
2785
|
+
tooltips: {
|
|
2786
|
+
link: {
|
|
2787
|
+
ariaLabel: "Actions du lien",
|
|
2788
|
+
openLink: "Ouvrir le lien",
|
|
2789
|
+
copyUrl: "Copier l'URL",
|
|
2790
|
+
editLink: "Modifier le lien",
|
|
2791
|
+
removeLink: "Supprimer le lien"
|
|
2792
|
+
},
|
|
2793
|
+
image: {
|
|
2794
|
+
ariaLabel: "Actions de l'image",
|
|
2795
|
+
label: "Image",
|
|
2796
|
+
floatLeft: "Flottant à gauche",
|
|
2797
|
+
noFloat: "Sans flottant",
|
|
2798
|
+
alignCenter: "Centré",
|
|
2799
|
+
floatRight: "Flottant à droite",
|
|
2800
|
+
originalSize: "Taille originale",
|
|
2801
|
+
rotateLeft: "Rotation à gauche",
|
|
2802
|
+
rotateRight: "Rotation à droite",
|
|
2803
|
+
cropImage: "Recadrer l'image",
|
|
2804
|
+
addCaption: "Ajouter / modifier la légende",
|
|
2805
|
+
deleteImage: "Supprimer l'image"
|
|
2806
|
+
},
|
|
2807
|
+
code: {
|
|
2808
|
+
ariaLabel: "Actions du bloc de code",
|
|
2809
|
+
label: "Code",
|
|
2810
|
+
syntaxLanguage: "Langage de syntaxe",
|
|
2811
|
+
syntaxAriaLabel: "Langage de syntaxe",
|
|
2812
|
+
copyCode: "Copier le code",
|
|
2813
|
+
toggleWordWrap: "Activer/désactiver le retour à la ligne",
|
|
2814
|
+
enableWordWrap: "Activer le retour à la ligne",
|
|
2815
|
+
disableWordWrap: "Désactiver le retour à la ligne",
|
|
2816
|
+
convertToParagraph: "Convertir en paragraphe",
|
|
2817
|
+
deleteCodeBlock: "Supprimer le bloc de code"
|
|
2818
|
+
},
|
|
2819
|
+
table: {
|
|
2820
|
+
ariaLabel: "Actions du tableau",
|
|
2821
|
+
label: "Tableau",
|
|
2822
|
+
selectCells: "Sélectionner des cellules",
|
|
2823
|
+
addRowAbove: "Ajouter une ligne au-dessus",
|
|
2824
|
+
addRowBelow: "Ajouter une ligne en-dessous",
|
|
2825
|
+
deleteRow: "Supprimer la ligne",
|
|
2826
|
+
addColumnLeft: "Ajouter une colonne à gauche",
|
|
2827
|
+
addColumnRight: "Ajouter une colonne à droite",
|
|
2828
|
+
deleteColumn: "Supprimer la colonne",
|
|
2829
|
+
mergeCells: "Fusionner les cellules",
|
|
2830
|
+
unmergeCells: "Scinder les cellules",
|
|
2831
|
+
columnWidth: "Largeur de colonne",
|
|
2832
|
+
rowHeight: "Hauteur de ligne",
|
|
2833
|
+
tableBorderWidth: "Épaisseur des bordures",
|
|
2834
|
+
deleteTable: "Supprimer le tableau",
|
|
2835
|
+
columnWidthPx: "Largeur de colonne (px)",
|
|
2836
|
+
rowHeightPx: "Hauteur de ligne (px)",
|
|
2837
|
+
tableBorderWidthPx: "Épaisseur des bordures (px)",
|
|
2838
|
+
cancelBtn: "Annuler",
|
|
2839
|
+
applyBtn: "Appliquer"
|
|
2840
|
+
},
|
|
2841
|
+
video: {
|
|
2842
|
+
ariaLabel: "Actions de la vidéo",
|
|
2843
|
+
label: "Vidéo",
|
|
2844
|
+
floatLeft: "Flottant à gauche",
|
|
2845
|
+
noFloat: "Sans flottant",
|
|
2846
|
+
alignCenter: "Centré",
|
|
2847
|
+
floatRight: "Flottant à droite",
|
|
2848
|
+
originalSize: "Taille originale",
|
|
2849
|
+
previewVideo: "Aperçu",
|
|
2850
|
+
exitPreview: "Quitter l'aperçu",
|
|
2851
|
+
deleteVideo: "Supprimer la vidéo"
|
|
2852
|
+
}
|
|
2853
|
+
},
|
|
2854
|
+
errors: {
|
|
2855
|
+
imageFormat: (type) => `Le format "${type}" n'est pas pris en charge par le navigateur. Veuillez le convertir en JPEG, PNG ou WebP.`,
|
|
2856
|
+
imageSize: (maxSize) => `Le fichier image est trop volumineux. La taille maximale autorisée est de ${maxSize}\u00a0Mo.`
|
|
2857
|
+
}
|
|
2858
|
+
},
|
|
2859
|
+
de: {
|
|
2860
|
+
toolbar: {
|
|
2861
|
+
bold: "Fett (Ctrl+B)",
|
|
2862
|
+
italic: "Kursiv (Ctrl+I)",
|
|
2863
|
+
underline: "Unterstrichen (Ctrl+U)",
|
|
2864
|
+
strikethrough: "Durchgestrichen",
|
|
2865
|
+
superscript: "Hochgestellt",
|
|
2866
|
+
subscript: "Tiefgestellt",
|
|
2867
|
+
alignLeft: "Linksbündig",
|
|
2868
|
+
alignCenter: "Zentriert",
|
|
2869
|
+
alignRight: "Rechtsbündig",
|
|
2870
|
+
alignJustify: "Blocksatz",
|
|
2871
|
+
ul: "Ungeordnete Liste",
|
|
2872
|
+
ol: "Geordnete Liste",
|
|
2873
|
+
checklist: "Checkliste",
|
|
2874
|
+
indent: "Einzug vergrößern",
|
|
2875
|
+
outdent: "Einzug verkleinern",
|
|
2876
|
+
undo: "Rückgängig (Ctrl+Z)",
|
|
2877
|
+
redo: "Wiederholen (Ctrl+Y)",
|
|
2878
|
+
hr: "Horizontale Linie",
|
|
2879
|
+
link: "Link einfügen",
|
|
2880
|
+
image: "Bild einfügen",
|
|
2881
|
+
video: "Video einfügen",
|
|
2882
|
+
emoji: "Emoji einfügen",
|
|
2883
|
+
icon: "FA-Symbol einfügen",
|
|
2884
|
+
table: "Tabelle einfügen",
|
|
2885
|
+
fontSize: "Schriftgröße",
|
|
2886
|
+
fontSizePlaceholder: "Größe",
|
|
2887
|
+
removeFormat: "Formatierung entfernen",
|
|
2888
|
+
direction: "Textrichtung umschalten (LTR / RTL)",
|
|
2889
|
+
fontFamily: "Schriftart",
|
|
2890
|
+
paragraphStyle: "Absatzstil",
|
|
2891
|
+
paragraphStylePlaceholder: "Stil",
|
|
2892
|
+
lineHeight: "Zeilenhöhe",
|
|
2893
|
+
lineHeightPlaceholder: "↕ Zeile",
|
|
2894
|
+
codeview: "HTML-Code-Ansicht",
|
|
2895
|
+
fullscreen: "Vollbild",
|
|
2896
|
+
shortcuts: "Tastenkürzel (Ctrl+Shift+/)",
|
|
2897
|
+
find: "Suchen (Ctrl+F)",
|
|
2898
|
+
findReplace: "Suchen & Ersetzen (Ctrl+H)",
|
|
2899
|
+
inlineCode: "Inline-Code (Ctrl+`)",
|
|
2900
|
+
print: "Drucken",
|
|
2901
|
+
foreColor: "Textfarbe",
|
|
2902
|
+
backColor: "Hervorhebungsfarbe",
|
|
2903
|
+
chooseTextColor: "Textfarbe auswählen",
|
|
2904
|
+
chooseHighlightColor: "Hervorhebungsfarbe auswählen",
|
|
2905
|
+
customColor: "Benutzerdefinierte Farbe",
|
|
2906
|
+
insertTableLabel: "Tabelle einfügen",
|
|
2907
|
+
paragraphItems: {
|
|
2908
|
+
p: "Normal",
|
|
2909
|
+
blockquote: "Zitat",
|
|
2910
|
+
pre: "Code"
|
|
2911
|
+
}
|
|
2912
|
+
},
|
|
2913
|
+
linkDialog: {
|
|
2914
|
+
ariaLabel: "Link einfügen",
|
|
2915
|
+
title: "Link einfügen",
|
|
2916
|
+
url: "URL",
|
|
2917
|
+
urlPlaceholder: "https://",
|
|
2918
|
+
displayText: "Anzeigetext",
|
|
2919
|
+
textPlaceholder: "Linktext",
|
|
2920
|
+
openInNewTab: "In neuem Tab öffnen",
|
|
2921
|
+
insertBtn: "Einfügen",
|
|
2922
|
+
cancelBtn: "Abbrechen"
|
|
2923
|
+
},
|
|
2924
|
+
imageDialog: {
|
|
2925
|
+
ariaLabel: "Bild einfügen",
|
|
2926
|
+
title: "Bild einfügen",
|
|
2927
|
+
imageUrl: "Bild-URL",
|
|
2928
|
+
urlPlaceholder: "https://example.com/image.png",
|
|
2929
|
+
altText: "Alt-Text",
|
|
2930
|
+
altPlaceholder: "Bild beschreiben",
|
|
2931
|
+
alignment: "Ausrichtung",
|
|
2932
|
+
alignNone: "Keine",
|
|
2933
|
+
alignLeft: "Links",
|
|
2934
|
+
alignCenter: "Mitte",
|
|
2935
|
+
alignRight: "Rechts",
|
|
2936
|
+
uploadLabel: "Oder Datei hochladen",
|
|
2937
|
+
insertBtn: "Einfügen",
|
|
2938
|
+
cancelBtn: "Abbrechen"
|
|
2939
|
+
},
|
|
2940
|
+
videoDialog: {
|
|
2941
|
+
ariaLabel: "Video einfügen",
|
|
2942
|
+
title: "Video einfügen",
|
|
2943
|
+
videoUrl: "Video-URL",
|
|
2944
|
+
urlPlaceholder: "YouTube, Vimeo oder direkte .mp4-URL",
|
|
2945
|
+
widthLabel: "Breite (px)",
|
|
2946
|
+
widthPlaceholder: "560",
|
|
2947
|
+
insertBtn: "Einfügen",
|
|
2948
|
+
cancelBtn: "Abbrechen",
|
|
2949
|
+
detected: (type) => `Erkannt: ${type}`,
|
|
2950
|
+
unknownFormat: "Unbekanntes Format — direktes Video-Einbetten wird versucht",
|
|
2951
|
+
invalidUrl: "Ungültige URL — bitte geben Sie einen gültigen Videolink ein."
|
|
2952
|
+
},
|
|
2953
|
+
emojiDialog: {
|
|
2954
|
+
ariaLabel: "Emoji einfügen",
|
|
2955
|
+
title: "Emoji einfügen",
|
|
2956
|
+
searchPlaceholder: "Emojis suchen…",
|
|
2957
|
+
all: "Alle",
|
|
2958
|
+
cancelBtn: "Abbrechen",
|
|
2959
|
+
close: "Schließen",
|
|
2960
|
+
categories: {
|
|
2961
|
+
smileys: "Smileys",
|
|
2962
|
+
people: "Menschen",
|
|
2963
|
+
animals: "Tiere",
|
|
2964
|
+
food: "Essen",
|
|
2965
|
+
travel: "Reisen",
|
|
2966
|
+
objects: "Objekte",
|
|
2967
|
+
symbols: "Symbole"
|
|
2968
|
+
}
|
|
2969
|
+
},
|
|
2970
|
+
iconDialog: {
|
|
2971
|
+
ariaLabel: "FA-Symbol einfügen",
|
|
2972
|
+
title: "FA-Symbol einfügen",
|
|
2973
|
+
searchPlaceholder: "Symbole suchen…",
|
|
2974
|
+
all: "Alle",
|
|
2975
|
+
style: "Stil",
|
|
2976
|
+
size: "Größe",
|
|
2977
|
+
color: "Farbe",
|
|
2978
|
+
useColor: " Farbe verwenden",
|
|
2979
|
+
selectHint: "Symbol auswählen",
|
|
2980
|
+
insertBtn: "FA-Symbol einfügen",
|
|
2981
|
+
cancelBtn: "Abbrechen",
|
|
2982
|
+
close: "Schließen",
|
|
2983
|
+
categories: {
|
|
2984
|
+
popular: "Beliebt",
|
|
2985
|
+
interface: "Benutzeroberfläche",
|
|
2986
|
+
navigation: "Navigation",
|
|
2987
|
+
media: "Medien",
|
|
2988
|
+
communication: "Kommunikation",
|
|
2989
|
+
files: "Dateien",
|
|
2990
|
+
people: "Menschen",
|
|
2991
|
+
objects: "Objekte"
|
|
2992
|
+
}
|
|
2993
|
+
},
|
|
2994
|
+
findReplace: {
|
|
2995
|
+
findTitle: "Suchen",
|
|
2996
|
+
findReplaceTitle: "Suchen & Ersetzen",
|
|
2997
|
+
findPlaceholder: "Suchen…",
|
|
2998
|
+
searchAriaLabel: "Suchtext",
|
|
2999
|
+
caseSensitive: "\xA0Groß-/Kleinschreibung",
|
|
3000
|
+
prevBtn: "← Zurück",
|
|
3001
|
+
nextBtn: "Weiter →",
|
|
3002
|
+
replacePlaceholder: "Ersetzen durch…",
|
|
3003
|
+
replaceAriaLabel: "Ersetzen durch",
|
|
3004
|
+
replaceBtn: "Ersetzen",
|
|
3005
|
+
replaceAllBtn: "Alle ersetzen",
|
|
3006
|
+
close: "×"
|
|
3007
|
+
},
|
|
3008
|
+
shortcutsDialog: {
|
|
3009
|
+
title: "Tastenkürzel",
|
|
3010
|
+
ariaLabel: "Tastenkürzel",
|
|
3011
|
+
close: "Schließen",
|
|
3012
|
+
shortcuts: [
|
|
3013
|
+
{
|
|
3014
|
+
category: "Textformatierung",
|
|
3015
|
+
items: [
|
|
3016
|
+
{
|
|
3017
|
+
keys: "Ctrl + B",
|
|
3018
|
+
action: "Fett"
|
|
3019
|
+
},
|
|
3020
|
+
{
|
|
3021
|
+
keys: "Ctrl + I",
|
|
3022
|
+
action: "Kursiv"
|
|
3023
|
+
},
|
|
3024
|
+
{
|
|
3025
|
+
keys: "Ctrl + U",
|
|
3026
|
+
action: "Unterstrichen"
|
|
3027
|
+
},
|
|
3028
|
+
{
|
|
3029
|
+
keys: "Ctrl + K",
|
|
3030
|
+
action: "Link einfügen / bearbeiten"
|
|
3031
|
+
}
|
|
3032
|
+
]
|
|
3033
|
+
},
|
|
3034
|
+
{
|
|
3035
|
+
category: "Verlauf",
|
|
3036
|
+
items: [{
|
|
3037
|
+
keys: "Ctrl + Z",
|
|
3038
|
+
action: "Rückgängig"
|
|
3039
|
+
}, {
|
|
3040
|
+
keys: "Ctrl + Y / Ctrl + Shift + Z",
|
|
3041
|
+
action: "Wiederholen"
|
|
3042
|
+
}]
|
|
3043
|
+
},
|
|
3044
|
+
{
|
|
3045
|
+
category: "Auswahl & Navigation",
|
|
3046
|
+
items: [
|
|
3047
|
+
{
|
|
3048
|
+
keys: "Ctrl + A",
|
|
3049
|
+
action: "Alles auswählen"
|
|
3050
|
+
},
|
|
3051
|
+
{
|
|
3052
|
+
keys: "Tab",
|
|
3053
|
+
action: "Listenebene erhöhen / Leerzeichen einfügen"
|
|
3054
|
+
},
|
|
3055
|
+
{
|
|
3056
|
+
keys: "Shift + Tab",
|
|
3057
|
+
action: "Listenebene verringern"
|
|
3058
|
+
}
|
|
3059
|
+
]
|
|
3060
|
+
},
|
|
3061
|
+
{
|
|
3062
|
+
category: "Zwischenablage",
|
|
3063
|
+
items: [{
|
|
3064
|
+
keys: "Ctrl + Shift + V",
|
|
3065
|
+
action: "Als einfachen Text einfügen"
|
|
3066
|
+
}]
|
|
3067
|
+
},
|
|
3068
|
+
{
|
|
3069
|
+
category: "Suchen & Ersetzen",
|
|
3070
|
+
items: [{
|
|
3071
|
+
keys: "Ctrl + F",
|
|
3072
|
+
action: "Im Dokument suchen"
|
|
3073
|
+
}, {
|
|
3074
|
+
keys: "Ctrl + H",
|
|
3075
|
+
action: "Suchen & Ersetzen"
|
|
3076
|
+
}]
|
|
3077
|
+
},
|
|
3078
|
+
{
|
|
3079
|
+
category: "Editor",
|
|
3080
|
+
items: [{
|
|
3081
|
+
keys: "Ctrl + Shift + /",
|
|
3082
|
+
action: "Diesen Tastenkürzel-Dialog anzeigen"
|
|
3083
|
+
}]
|
|
3084
|
+
}
|
|
3085
|
+
]
|
|
3086
|
+
},
|
|
3087
|
+
contextMenu: {
|
|
3088
|
+
cut: "Ausschneiden",
|
|
3089
|
+
copy: "Kopieren",
|
|
3090
|
+
paste: "Einfügen",
|
|
3091
|
+
bold: "Fett",
|
|
3092
|
+
italic: "Kursiv",
|
|
3093
|
+
underline: "Unterstrichen",
|
|
3094
|
+
textColor: "Textfarbe",
|
|
3095
|
+
highlightColor: "Hervorhebungsfarbe",
|
|
3096
|
+
copyFormat: "Format kopieren",
|
|
3097
|
+
pasteFormat: "Format einfügen",
|
|
3098
|
+
removeFormat: "Formatierung entfernen",
|
|
3099
|
+
link: "Link einfügen",
|
|
3100
|
+
image: "Bild einfügen",
|
|
3101
|
+
video: "Video einfügen",
|
|
3102
|
+
table: "Tabelle einfügen",
|
|
3103
|
+
back: "Zurück",
|
|
3104
|
+
noHighlight: "Keine Hervorhebung",
|
|
3105
|
+
customColor: "Benutzerdefinierte Farbe",
|
|
3106
|
+
customColorLabel: "Benutzerdefiniert…"
|
|
3107
|
+
},
|
|
3108
|
+
statusbar: {
|
|
3109
|
+
resizeHandle: "Editor-Größe ändern",
|
|
3110
|
+
words: (n) => `Wörter: ${n}`,
|
|
3111
|
+
wordsLimit: (n, max) => `Wörter: ${n}/${max}`,
|
|
3112
|
+
chars: (n) => `Zeichen: ${n}`,
|
|
3113
|
+
charsLimit: (n, max) => `Zeichen: ${n}/${max}`
|
|
3114
|
+
},
|
|
3115
|
+
tooltips: {
|
|
3116
|
+
link: {
|
|
3117
|
+
ariaLabel: "Link-Aktionen",
|
|
3118
|
+
openLink: "Link öffnen",
|
|
3119
|
+
copyUrl: "URL kopieren",
|
|
3120
|
+
editLink: "Link bearbeiten",
|
|
3121
|
+
removeLink: "Link entfernen"
|
|
3122
|
+
},
|
|
3123
|
+
image: {
|
|
3124
|
+
ariaLabel: "Bild-Aktionen",
|
|
3125
|
+
label: "Bild",
|
|
3126
|
+
floatLeft: "Links umfließen",
|
|
3127
|
+
noFloat: "Kein Umfluss",
|
|
3128
|
+
alignCenter: "Zentriert",
|
|
3129
|
+
floatRight: "Rechts umfließen",
|
|
3130
|
+
originalSize: "Originalgröße",
|
|
3131
|
+
rotateLeft: "Links drehen",
|
|
3132
|
+
rotateRight: "Rechts drehen",
|
|
3133
|
+
cropImage: "Bild zuschneiden",
|
|
3134
|
+
addCaption: "Beschriftung hinzufügen / bearbeiten",
|
|
3135
|
+
deleteImage: "Bild löschen"
|
|
3136
|
+
},
|
|
3137
|
+
code: {
|
|
3138
|
+
ariaLabel: "Codeblock-Aktionen",
|
|
3139
|
+
label: "Code",
|
|
3140
|
+
syntaxLanguage: "Syntaxsprache",
|
|
3141
|
+
syntaxAriaLabel: "Syntaxsprache",
|
|
3142
|
+
copyCode: "Code kopieren",
|
|
3143
|
+
toggleWordWrap: "Zeilenumbruch umschalten",
|
|
3144
|
+
enableWordWrap: "Zeilenumbruch aktivieren",
|
|
3145
|
+
disableWordWrap: "Zeilenumbruch deaktivieren",
|
|
3146
|
+
convertToParagraph: "In Absatz umwandeln",
|
|
3147
|
+
deleteCodeBlock: "Codeblock löschen"
|
|
3148
|
+
},
|
|
3149
|
+
table: {
|
|
3150
|
+
ariaLabel: "Tabellen-Aktionen",
|
|
3151
|
+
label: "Tabelle",
|
|
3152
|
+
selectCells: "Zellen auswählen",
|
|
3153
|
+
addRowAbove: "Zeile oben hinzufügen",
|
|
3154
|
+
addRowBelow: "Zeile unten hinzufügen",
|
|
3155
|
+
deleteRow: "Zeile löschen",
|
|
3156
|
+
addColumnLeft: "Spalte links hinzufügen",
|
|
3157
|
+
addColumnRight: "Spalte rechts hinzufügen",
|
|
3158
|
+
deleteColumn: "Spalte löschen",
|
|
3159
|
+
mergeCells: "Zellen zusammenführen",
|
|
3160
|
+
unmergeCells: "Zellen trennen",
|
|
3161
|
+
columnWidth: "Spaltenbreite",
|
|
3162
|
+
rowHeight: "Zeilenhöhe",
|
|
3163
|
+
tableBorderWidth: "Tabellenrahmenbreite",
|
|
3164
|
+
deleteTable: "Tabelle löschen",
|
|
3165
|
+
columnWidthPx: "Spaltenbreite (px)",
|
|
3166
|
+
rowHeightPx: "Zeilenhöhe (px)",
|
|
3167
|
+
tableBorderWidthPx: "Tabellenrahmenbreite (px)",
|
|
3168
|
+
cancelBtn: "Abbrechen",
|
|
3169
|
+
applyBtn: "Anwenden"
|
|
3170
|
+
},
|
|
3171
|
+
video: {
|
|
3172
|
+
ariaLabel: "Video-Aktionen",
|
|
3173
|
+
label: "Video",
|
|
3174
|
+
floatLeft: "Links umfließen",
|
|
3175
|
+
noFloat: "Kein Umfluss",
|
|
3176
|
+
alignCenter: "Zentriert",
|
|
3177
|
+
floatRight: "Rechts umfließen",
|
|
3178
|
+
originalSize: "Originalgröße",
|
|
3179
|
+
previewVideo: "Video-Vorschau",
|
|
3180
|
+
exitPreview: "Vorschau beenden",
|
|
3181
|
+
deleteVideo: "Video löschen"
|
|
3182
|
+
}
|
|
3183
|
+
},
|
|
3184
|
+
errors: {
|
|
3185
|
+
imageFormat: (type) => `Das Format „${type}" wird in Webbrowsern nicht unterstützt. Bitte konvertieren Sie es zuerst in JPEG, PNG oder WebP.`,
|
|
3186
|
+
imageSize: (maxSize) => `Die Bilddatei ist zu groß. Die maximal zulässige Größe beträgt ${maxSize} MB.`
|
|
3187
|
+
}
|
|
3188
|
+
},
|
|
3189
|
+
es: {
|
|
3190
|
+
toolbar: {
|
|
3191
|
+
bold: "Negrita (Ctrl+B)",
|
|
3192
|
+
italic: "Cursiva (Ctrl+I)",
|
|
3193
|
+
underline: "Subrayado (Ctrl+U)",
|
|
3194
|
+
strikethrough: "Tachado",
|
|
3195
|
+
superscript: "Superíndice",
|
|
3196
|
+
subscript: "Subíndice",
|
|
3197
|
+
alignLeft: "Alinear a la izquierda",
|
|
3198
|
+
alignCenter: "Centrar",
|
|
3199
|
+
alignRight: "Alinear a la derecha",
|
|
3200
|
+
alignJustify: "Justificar",
|
|
3201
|
+
ul: "Lista sin orden",
|
|
3202
|
+
ol: "Lista ordenada",
|
|
3203
|
+
checklist: "Lista de verificación",
|
|
3204
|
+
indent: "Aumentar sangría",
|
|
3205
|
+
outdent: "Reducir sangría",
|
|
3206
|
+
undo: "Deshacer (Ctrl+Z)",
|
|
3207
|
+
redo: "Rehacer (Ctrl+Y)",
|
|
3208
|
+
hr: "Línea horizontal",
|
|
3209
|
+
link: "Insertar enlace",
|
|
3210
|
+
image: "Insertar imagen",
|
|
3211
|
+
video: "Insertar vídeo",
|
|
3212
|
+
emoji: "Insertar emoji",
|
|
3213
|
+
icon: "Insertar icono FA",
|
|
3214
|
+
table: "Insertar tabla",
|
|
3215
|
+
fontSize: "Tamaño de fuente",
|
|
3216
|
+
fontSizePlaceholder: "Tamaño",
|
|
3217
|
+
removeFormat: "Eliminar formato",
|
|
3218
|
+
direction: "Cambiar dirección del texto (LTR / RTL)",
|
|
3219
|
+
fontFamily: "Fuente",
|
|
3220
|
+
paragraphStyle: "Estilo de párrafo",
|
|
3221
|
+
paragraphStylePlaceholder: "Estilo",
|
|
3222
|
+
lineHeight: "Interlineado",
|
|
3223
|
+
lineHeightPlaceholder: "↕ Línea",
|
|
3224
|
+
codeview: "Vista de código HTML",
|
|
3225
|
+
fullscreen: "Pantalla completa",
|
|
3226
|
+
shortcuts: "Atajos de teclado (Ctrl+Shift+/)",
|
|
3227
|
+
find: "Buscar (Ctrl+F)",
|
|
3228
|
+
findReplace: "Buscar y reemplazar (Ctrl+H)",
|
|
3229
|
+
inlineCode: "Código en línea (Ctrl+`)",
|
|
3230
|
+
print: "Imprimir",
|
|
3231
|
+
foreColor: "Color del texto",
|
|
3232
|
+
backColor: "Color de resaltado",
|
|
3233
|
+
chooseTextColor: "Elegir color del texto",
|
|
3234
|
+
chooseHighlightColor: "Elegir color de resaltado",
|
|
3235
|
+
customColor: "Color personalizado",
|
|
3236
|
+
insertTableLabel: "Insertar tabla",
|
|
3237
|
+
paragraphItems: {
|
|
3238
|
+
p: "Normal",
|
|
3239
|
+
blockquote: "Cita",
|
|
3240
|
+
pre: "Código"
|
|
3241
|
+
}
|
|
3242
|
+
},
|
|
3243
|
+
linkDialog: {
|
|
3244
|
+
ariaLabel: "Insertar enlace",
|
|
3245
|
+
title: "Insertar enlace",
|
|
3246
|
+
url: "URL",
|
|
3247
|
+
urlPlaceholder: "https://",
|
|
3248
|
+
displayText: "Texto a mostrar",
|
|
3249
|
+
textPlaceholder: "Texto del enlace",
|
|
3250
|
+
openInNewTab: "Abrir en nueva pestaña",
|
|
3251
|
+
insertBtn: "Insertar",
|
|
3252
|
+
cancelBtn: "Cancelar"
|
|
3253
|
+
},
|
|
3254
|
+
imageDialog: {
|
|
3255
|
+
ariaLabel: "Insertar imagen",
|
|
3256
|
+
title: "Insertar imagen",
|
|
3257
|
+
imageUrl: "URL de imagen",
|
|
3258
|
+
urlPlaceholder: "https://example.com/image.png",
|
|
3259
|
+
altText: "Texto alternativo",
|
|
3260
|
+
altPlaceholder: "Describir la imagen",
|
|
3261
|
+
alignment: "Alineación",
|
|
3262
|
+
alignNone: "Ninguna",
|
|
3263
|
+
alignLeft: "Izquierda",
|
|
3264
|
+
alignCenter: "Centro",
|
|
3265
|
+
alignRight: "Derecha",
|
|
3266
|
+
uploadLabel: "O subir un archivo",
|
|
3267
|
+
insertBtn: "Insertar",
|
|
3268
|
+
cancelBtn: "Cancelar"
|
|
3269
|
+
},
|
|
3270
|
+
videoDialog: {
|
|
3271
|
+
ariaLabel: "Insertar vídeo",
|
|
3272
|
+
title: "Insertar vídeo",
|
|
3273
|
+
videoUrl: "URL del vídeo",
|
|
3274
|
+
urlPlaceholder: "YouTube, Vimeo o URL directa .mp4",
|
|
3275
|
+
widthLabel: "Ancho (px)",
|
|
3276
|
+
widthPlaceholder: "560",
|
|
3277
|
+
insertBtn: "Insertar",
|
|
3278
|
+
cancelBtn: "Cancelar",
|
|
3279
|
+
detected: (type) => `Detectado: ${type}`,
|
|
3280
|
+
unknownFormat: "Formato desconocido — se intentará incrustar el vídeo directamente",
|
|
3281
|
+
invalidUrl: "URL no válida — introduzca un enlace de vídeo válido."
|
|
3282
|
+
},
|
|
3283
|
+
emojiDialog: {
|
|
3284
|
+
ariaLabel: "Insertar emoji",
|
|
3285
|
+
title: "Insertar emoji",
|
|
3286
|
+
searchPlaceholder: "Buscar emojis…",
|
|
3287
|
+
all: "Todos",
|
|
3288
|
+
cancelBtn: "Cancelar",
|
|
3289
|
+
close: "Cerrar",
|
|
3290
|
+
categories: {
|
|
3291
|
+
smileys: "Caritas",
|
|
3292
|
+
people: "Personas",
|
|
3293
|
+
animals: "Animales",
|
|
3294
|
+
food: "Comida",
|
|
3295
|
+
travel: "Viajes",
|
|
3296
|
+
objects: "Objetos",
|
|
3297
|
+
symbols: "Símbolos"
|
|
3298
|
+
}
|
|
3299
|
+
},
|
|
3300
|
+
iconDialog: {
|
|
3301
|
+
ariaLabel: "Insertar icono FA",
|
|
3302
|
+
title: "Insertar icono FA",
|
|
3303
|
+
searchPlaceholder: "Buscar iconos…",
|
|
3304
|
+
all: "Todos",
|
|
3305
|
+
style: "Estilo",
|
|
3306
|
+
size: "Tamaño",
|
|
3307
|
+
color: "Color",
|
|
3308
|
+
useColor: " Usar color",
|
|
3309
|
+
selectHint: "Seleccionar un icono",
|
|
3310
|
+
insertBtn: "Insertar icono FA",
|
|
3311
|
+
cancelBtn: "Cancelar",
|
|
3312
|
+
close: "Cerrar",
|
|
3313
|
+
categories: {
|
|
3314
|
+
popular: "Popular",
|
|
3315
|
+
interface: "Interfaz",
|
|
3316
|
+
navigation: "Navegación",
|
|
3317
|
+
media: "Medios",
|
|
3318
|
+
communication: "Comunicación",
|
|
3319
|
+
files: "Archivos",
|
|
3320
|
+
people: "Personas",
|
|
3321
|
+
objects: "Objetos"
|
|
3322
|
+
}
|
|
3323
|
+
},
|
|
3324
|
+
findReplace: {
|
|
3325
|
+
findTitle: "Buscar",
|
|
3326
|
+
findReplaceTitle: "Buscar y reemplazar",
|
|
3327
|
+
findPlaceholder: "Buscar…",
|
|
3328
|
+
searchAriaLabel: "Texto de búsqueda",
|
|
3329
|
+
caseSensitive: "\xA0Distinguir mayúsculas",
|
|
3330
|
+
prevBtn: "← Anterior",
|
|
3331
|
+
nextBtn: "Siguiente →",
|
|
3332
|
+
replacePlaceholder: "Reemplazar con…",
|
|
3333
|
+
replaceAriaLabel: "Reemplazar con",
|
|
3334
|
+
replaceBtn: "Reemplazar",
|
|
3335
|
+
replaceAllBtn: "Reemplazar todo",
|
|
3336
|
+
close: "×"
|
|
3337
|
+
},
|
|
3338
|
+
shortcutsDialog: {
|
|
3339
|
+
title: "Atajos de teclado",
|
|
3340
|
+
ariaLabel: "Atajos de teclado",
|
|
3341
|
+
close: "Cerrar",
|
|
3342
|
+
shortcuts: [
|
|
3343
|
+
{
|
|
3344
|
+
category: "Formato de texto",
|
|
3345
|
+
items: [
|
|
3346
|
+
{
|
|
3347
|
+
keys: "Ctrl + B",
|
|
3348
|
+
action: "Negrita"
|
|
3349
|
+
},
|
|
3350
|
+
{
|
|
3351
|
+
keys: "Ctrl + I",
|
|
3352
|
+
action: "Cursiva"
|
|
3353
|
+
},
|
|
3354
|
+
{
|
|
3355
|
+
keys: "Ctrl + U",
|
|
3356
|
+
action: "Subrayado"
|
|
3357
|
+
},
|
|
3358
|
+
{
|
|
3359
|
+
keys: "Ctrl + K",
|
|
3360
|
+
action: "Insertar / editar enlace"
|
|
3361
|
+
}
|
|
3362
|
+
]
|
|
3363
|
+
},
|
|
3364
|
+
{
|
|
3365
|
+
category: "Historial",
|
|
3366
|
+
items: [{
|
|
3367
|
+
keys: "Ctrl + Z",
|
|
3368
|
+
action: "Deshacer"
|
|
3369
|
+
}, {
|
|
3370
|
+
keys: "Ctrl + Y / Ctrl + Shift + Z",
|
|
3371
|
+
action: "Rehacer"
|
|
3372
|
+
}]
|
|
3373
|
+
},
|
|
3374
|
+
{
|
|
3375
|
+
category: "Selección y navegación",
|
|
3376
|
+
items: [
|
|
3377
|
+
{
|
|
3378
|
+
keys: "Ctrl + A",
|
|
3379
|
+
action: "Seleccionar todo"
|
|
3380
|
+
},
|
|
3381
|
+
{
|
|
3382
|
+
keys: "Tab",
|
|
3383
|
+
action: "Aumentar sangría / insertar espacios"
|
|
3384
|
+
},
|
|
3385
|
+
{
|
|
3386
|
+
keys: "Shift + Tab",
|
|
3387
|
+
action: "Reducir sangría"
|
|
3388
|
+
}
|
|
3389
|
+
]
|
|
3390
|
+
},
|
|
3391
|
+
{
|
|
3392
|
+
category: "Portapapeles",
|
|
3393
|
+
items: [{
|
|
3394
|
+
keys: "Ctrl + Shift + V",
|
|
3395
|
+
action: "Pegar como texto plano"
|
|
3396
|
+
}]
|
|
3397
|
+
},
|
|
3398
|
+
{
|
|
3399
|
+
category: "Buscar y reemplazar",
|
|
3400
|
+
items: [{
|
|
3401
|
+
keys: "Ctrl + F",
|
|
3402
|
+
action: "Buscar en el documento"
|
|
3403
|
+
}, {
|
|
3404
|
+
keys: "Ctrl + H",
|
|
3405
|
+
action: "Buscar y reemplazar"
|
|
3406
|
+
}]
|
|
3407
|
+
},
|
|
3408
|
+
{
|
|
3409
|
+
category: "Editor",
|
|
3410
|
+
items: [{
|
|
3411
|
+
keys: "Ctrl + Shift + /",
|
|
3412
|
+
action: "Mostrar este diálogo de atajos"
|
|
3413
|
+
}]
|
|
3414
|
+
}
|
|
3415
|
+
]
|
|
3416
|
+
},
|
|
3417
|
+
contextMenu: {
|
|
3418
|
+
cut: "Cortar",
|
|
3419
|
+
copy: "Copiar",
|
|
3420
|
+
paste: "Pegar",
|
|
3421
|
+
bold: "Negrita",
|
|
3422
|
+
italic: "Cursiva",
|
|
3423
|
+
underline: "Subrayado",
|
|
3424
|
+
textColor: "Color del texto",
|
|
3425
|
+
highlightColor: "Color de resaltado",
|
|
3426
|
+
copyFormat: "Copiar formato",
|
|
3427
|
+
pasteFormat: "Pegar formato",
|
|
3428
|
+
removeFormat: "Eliminar formato",
|
|
3429
|
+
link: "Insertar enlace",
|
|
3430
|
+
image: "Insertar imagen",
|
|
3431
|
+
video: "Insertar vídeo",
|
|
3432
|
+
table: "Insertar tabla",
|
|
3433
|
+
back: "Atrás",
|
|
3434
|
+
noHighlight: "Sin resaltado",
|
|
3435
|
+
customColor: "Color personalizado",
|
|
3436
|
+
customColorLabel: "Personalizado…"
|
|
3437
|
+
},
|
|
3438
|
+
statusbar: {
|
|
3439
|
+
resizeHandle: "Redimensionar editor",
|
|
3440
|
+
words: (n) => `Palabras: ${n}`,
|
|
3441
|
+
wordsLimit: (n, max) => `Palabras: ${n}/${max}`,
|
|
3442
|
+
chars: (n) => `Caracteres: ${n}`,
|
|
3443
|
+
charsLimit: (n, max) => `Caracteres: ${n}/${max}`
|
|
3444
|
+
},
|
|
3445
|
+
tooltips: {
|
|
3446
|
+
link: {
|
|
3447
|
+
ariaLabel: "Acciones de enlace",
|
|
3448
|
+
openLink: "Abrir enlace",
|
|
3449
|
+
copyUrl: "Copiar URL",
|
|
3450
|
+
editLink: "Editar enlace",
|
|
3451
|
+
removeLink: "Eliminar enlace"
|
|
3452
|
+
},
|
|
3453
|
+
image: {
|
|
3454
|
+
ariaLabel: "Acciones de imagen",
|
|
3455
|
+
label: "Imagen",
|
|
3456
|
+
floatLeft: "Flotar a la izquierda",
|
|
3457
|
+
noFloat: "Sin flotado",
|
|
3458
|
+
alignCenter: "Centrar",
|
|
3459
|
+
floatRight: "Flotar a la derecha",
|
|
3460
|
+
originalSize: "Tamaño original",
|
|
3461
|
+
rotateLeft: "Rotar a la izquierda",
|
|
3462
|
+
rotateRight: "Rotar a la derecha",
|
|
3463
|
+
cropImage: "Recortar imagen",
|
|
3464
|
+
addCaption: "Añadir / editar pie de foto",
|
|
3465
|
+
deleteImage: "Eliminar imagen"
|
|
3466
|
+
},
|
|
3467
|
+
code: {
|
|
3468
|
+
ariaLabel: "Acciones de bloque de código",
|
|
3469
|
+
label: "Código",
|
|
3470
|
+
syntaxLanguage: "Lenguaje de sintaxis",
|
|
3471
|
+
syntaxAriaLabel: "Lenguaje de sintaxis",
|
|
3472
|
+
copyCode: "Copiar código",
|
|
3473
|
+
toggleWordWrap: "Alternar ajuste de línea",
|
|
3474
|
+
enableWordWrap: "Activar ajuste de línea",
|
|
3475
|
+
disableWordWrap: "Desactivar ajuste de línea",
|
|
3476
|
+
convertToParagraph: "Convertir en párrafo",
|
|
3477
|
+
deleteCodeBlock: "Eliminar bloque de código"
|
|
3478
|
+
},
|
|
3479
|
+
table: {
|
|
3480
|
+
ariaLabel: "Acciones de tabla",
|
|
3481
|
+
label: "Tabla",
|
|
3482
|
+
selectCells: "Seleccionar celdas",
|
|
3483
|
+
addRowAbove: "Añadir fila encima",
|
|
3484
|
+
addRowBelow: "Añadir fila debajo",
|
|
3485
|
+
deleteRow: "Eliminar fila",
|
|
3486
|
+
addColumnLeft: "Añadir columna a la izquierda",
|
|
3487
|
+
addColumnRight: "Añadir columna a la derecha",
|
|
3488
|
+
deleteColumn: "Eliminar columna",
|
|
3489
|
+
mergeCells: "Combinar celdas",
|
|
3490
|
+
unmergeCells: "Separar celdas",
|
|
3491
|
+
columnWidth: "Ancho de columna",
|
|
3492
|
+
rowHeight: "Alto de fila",
|
|
3493
|
+
tableBorderWidth: "Grosor del borde de la tabla",
|
|
3494
|
+
deleteTable: "Eliminar tabla",
|
|
3495
|
+
columnWidthPx: "Ancho de columna (px)",
|
|
3496
|
+
rowHeightPx: "Alto de fila (px)",
|
|
3497
|
+
tableBorderWidthPx: "Grosor del borde (px)",
|
|
3498
|
+
cancelBtn: "Cancelar",
|
|
3499
|
+
applyBtn: "Aplicar"
|
|
3500
|
+
},
|
|
3501
|
+
video: {
|
|
3502
|
+
ariaLabel: "Acciones de vídeo",
|
|
3503
|
+
label: "Vídeo",
|
|
3504
|
+
floatLeft: "Flotar a la izquierda",
|
|
3505
|
+
noFloat: "Sin flotado",
|
|
3506
|
+
alignCenter: "Centrar",
|
|
3507
|
+
floatRight: "Flotar a la derecha",
|
|
3508
|
+
originalSize: "Tamaño original",
|
|
3509
|
+
previewVideo: "Vista previa de vídeo",
|
|
3510
|
+
exitPreview: "Salir de la vista previa",
|
|
3511
|
+
deleteVideo: "Eliminar vídeo"
|
|
3512
|
+
}
|
|
3513
|
+
},
|
|
3514
|
+
errors: {
|
|
3515
|
+
imageFormat: (type) => `El formato "${type}" no es compatible con los navegadores web. Por favor, conviértalo primero a JPEG, PNG o WebP.`,
|
|
3516
|
+
imageSize: (maxSize) => `El archivo de imagen es demasiado grande. El tamaño máximo permitido es ${maxSize} MB.`
|
|
3517
|
+
}
|
|
3518
|
+
},
|
|
3519
|
+
ko: {
|
|
3520
|
+
toolbar: {
|
|
3521
|
+
bold: "굵게 (Ctrl+B)",
|
|
3522
|
+
italic: "기울임꼴 (Ctrl+I)",
|
|
3523
|
+
underline: "밑줄 (Ctrl+U)",
|
|
3524
|
+
strikethrough: "취소선",
|
|
3525
|
+
superscript: "위 첨자",
|
|
3526
|
+
subscript: "아래 첨자",
|
|
3527
|
+
alignLeft: "왼쪽 정렬",
|
|
3528
|
+
alignCenter: "가운데 정렬",
|
|
3529
|
+
alignRight: "오른쪽 정렬",
|
|
3530
|
+
alignJustify: "양쪽 정렬",
|
|
3531
|
+
ul: "순서 없는 목록",
|
|
3532
|
+
ol: "순서 있는 목록",
|
|
3533
|
+
checklist: "체크리스트",
|
|
3534
|
+
indent: "들여쓰기",
|
|
3535
|
+
outdent: "내어쓰기",
|
|
3536
|
+
undo: "실행 취소 (Ctrl+Z)",
|
|
3537
|
+
redo: "다시 실행 (Ctrl+Y)",
|
|
3538
|
+
hr: "수평선",
|
|
3539
|
+
link: "링크 삽입",
|
|
3540
|
+
image: "이미지 삽입",
|
|
3541
|
+
video: "동영상 삽입",
|
|
3542
|
+
emoji: "이모지 삽입",
|
|
3543
|
+
icon: "FA 아이콘 삽입",
|
|
3544
|
+
table: "표 삽입",
|
|
3545
|
+
fontSize: "글꼴 크기",
|
|
3546
|
+
fontSizePlaceholder: "크기",
|
|
3547
|
+
removeFormat: "서식 제거",
|
|
3548
|
+
direction: "텍스트 방향 전환 (LTR / RTL)",
|
|
3549
|
+
fontFamily: "글꼴",
|
|
3550
|
+
paragraphStyle: "단락 스타일",
|
|
3551
|
+
paragraphStylePlaceholder: "스타일",
|
|
3552
|
+
lineHeight: "줄 간격",
|
|
3553
|
+
lineHeightPlaceholder: "↕ 줄",
|
|
3554
|
+
codeview: "HTML 코드 보기",
|
|
3555
|
+
fullscreen: "전체 화면",
|
|
3556
|
+
shortcuts: "키보드 단축키 (Ctrl+Shift+/)",
|
|
3557
|
+
find: "찾기 (Ctrl+F)",
|
|
3558
|
+
findReplace: "찾기 및 바꾸기 (Ctrl+H)",
|
|
3559
|
+
inlineCode: "인라인 코드 (Ctrl+`)",
|
|
3560
|
+
print: "인쇄",
|
|
3561
|
+
foreColor: "글자 색",
|
|
3562
|
+
backColor: "강조 색",
|
|
3563
|
+
chooseTextColor: "글자 색 선택",
|
|
3564
|
+
chooseHighlightColor: "강조 색 선택",
|
|
3565
|
+
customColor: "사용자 지정 색",
|
|
3566
|
+
insertTableLabel: "표 삽입",
|
|
3567
|
+
paragraphItems: {
|
|
3568
|
+
p: "기본",
|
|
3569
|
+
blockquote: "인용",
|
|
3570
|
+
pre: "코드"
|
|
3571
|
+
}
|
|
3572
|
+
},
|
|
3573
|
+
linkDialog: {
|
|
3574
|
+
ariaLabel: "링크 삽입",
|
|
3575
|
+
title: "링크 삽입",
|
|
3576
|
+
url: "URL",
|
|
3577
|
+
urlPlaceholder: "https://",
|
|
3578
|
+
displayText: "표시 텍스트",
|
|
3579
|
+
textPlaceholder: "링크 텍스트",
|
|
3580
|
+
openInNewTab: "새 탭에서 열기",
|
|
3581
|
+
insertBtn: "삽입",
|
|
3582
|
+
cancelBtn: "취소"
|
|
3583
|
+
},
|
|
3584
|
+
imageDialog: {
|
|
3585
|
+
ariaLabel: "이미지 삽입",
|
|
3586
|
+
title: "이미지 삽입",
|
|
3587
|
+
imageUrl: "이미지 URL",
|
|
3588
|
+
urlPlaceholder: "https://example.com/image.png",
|
|
3589
|
+
altText: "대체 텍스트",
|
|
3590
|
+
altPlaceholder: "이미지 설명",
|
|
3591
|
+
alignment: "정렬",
|
|
3592
|
+
alignNone: "없음",
|
|
3593
|
+
alignLeft: "왼쪽",
|
|
3594
|
+
alignCenter: "가운데",
|
|
3595
|
+
alignRight: "오른쪽",
|
|
3596
|
+
uploadLabel: "또는 파일 업로드",
|
|
3597
|
+
insertBtn: "삽입",
|
|
3598
|
+
cancelBtn: "취소"
|
|
3599
|
+
},
|
|
3600
|
+
videoDialog: {
|
|
3601
|
+
ariaLabel: "동영상 삽입",
|
|
3602
|
+
title: "동영상 삽입",
|
|
3603
|
+
videoUrl: "동영상 URL",
|
|
3604
|
+
urlPlaceholder: "YouTube, Vimeo 또는 직접 .mp4 URL",
|
|
3605
|
+
widthLabel: "너비 (px)",
|
|
3606
|
+
widthPlaceholder: "560",
|
|
3607
|
+
insertBtn: "삽입",
|
|
3608
|
+
cancelBtn: "취소",
|
|
3609
|
+
detected: (type) => `감지됨: ${type}`,
|
|
3610
|
+
unknownFormat: "알 수 없는 형식 — 직접 동영상 임베드를 시도합니다",
|
|
3611
|
+
invalidUrl: "유효하지 않은 URL — 올바른 동영상 링크를 입력하세요."
|
|
3612
|
+
},
|
|
3613
|
+
emojiDialog: {
|
|
3614
|
+
ariaLabel: "이모지 삽입",
|
|
3615
|
+
title: "이모지 삽입",
|
|
3616
|
+
searchPlaceholder: "이모지 검색…",
|
|
3617
|
+
all: "전체",
|
|
3618
|
+
cancelBtn: "취소",
|
|
3619
|
+
close: "닫기",
|
|
3620
|
+
categories: {
|
|
3621
|
+
smileys: "스마일",
|
|
3622
|
+
people: "사람",
|
|
3623
|
+
animals: "동물",
|
|
3624
|
+
food: "음식",
|
|
3625
|
+
travel: "여행",
|
|
3626
|
+
objects: "사물",
|
|
3627
|
+
symbols: "기호"
|
|
3628
|
+
}
|
|
3629
|
+
},
|
|
3630
|
+
iconDialog: {
|
|
3631
|
+
ariaLabel: "FA 아이콘 삽입",
|
|
3632
|
+
title: "FA 아이콘 삽입",
|
|
3633
|
+
searchPlaceholder: "아이콘 검색…",
|
|
3634
|
+
all: "전체",
|
|
3635
|
+
style: "스타일",
|
|
3636
|
+
size: "크기",
|
|
3637
|
+
color: "색상",
|
|
3638
|
+
useColor: " 색상 사용",
|
|
3639
|
+
selectHint: "아이콘을 선택하세요",
|
|
3640
|
+
insertBtn: "FA 아이콘 삽입",
|
|
3641
|
+
cancelBtn: "취소",
|
|
3642
|
+
close: "닫기",
|
|
3643
|
+
categories: {
|
|
3644
|
+
popular: "인기",
|
|
3645
|
+
interface: "인터페이스",
|
|
3646
|
+
navigation: "탐색",
|
|
3647
|
+
media: "미디어",
|
|
3648
|
+
communication: "커뮤니케이션",
|
|
3649
|
+
files: "파일",
|
|
3650
|
+
people: "사람",
|
|
3651
|
+
objects: "사물"
|
|
3652
|
+
}
|
|
3653
|
+
},
|
|
3654
|
+
findReplace: {
|
|
3655
|
+
findTitle: "찾기",
|
|
3656
|
+
findReplaceTitle: "찾기 및 바꾸기",
|
|
3657
|
+
findPlaceholder: "찾기…",
|
|
3658
|
+
searchAriaLabel: "검색 텍스트",
|
|
3659
|
+
caseSensitive: "\xA0대소문자 구분",
|
|
3660
|
+
prevBtn: "← 이전",
|
|
3661
|
+
nextBtn: "다음 →",
|
|
3662
|
+
replacePlaceholder: "바꿀 내용…",
|
|
3663
|
+
replaceAriaLabel: "바꿀 내용",
|
|
3664
|
+
replaceBtn: "바꾸기",
|
|
3665
|
+
replaceAllBtn: "모두 바꾸기",
|
|
3666
|
+
close: "×"
|
|
3667
|
+
},
|
|
3668
|
+
shortcutsDialog: {
|
|
3669
|
+
title: "키보드 단축키",
|
|
3670
|
+
ariaLabel: "키보드 단축키",
|
|
3671
|
+
close: "닫기",
|
|
3672
|
+
shortcuts: [
|
|
3673
|
+
{
|
|
3674
|
+
category: "텍스트 서식",
|
|
3675
|
+
items: [
|
|
3676
|
+
{
|
|
3677
|
+
keys: "Ctrl + B",
|
|
3678
|
+
action: "굵게"
|
|
3679
|
+
},
|
|
3680
|
+
{
|
|
3681
|
+
keys: "Ctrl + I",
|
|
3682
|
+
action: "기울임꼴"
|
|
3683
|
+
},
|
|
3684
|
+
{
|
|
3685
|
+
keys: "Ctrl + U",
|
|
3686
|
+
action: "밑줄"
|
|
3687
|
+
},
|
|
3688
|
+
{
|
|
3689
|
+
keys: "Ctrl + K",
|
|
3690
|
+
action: "링크 삽입 / 편집"
|
|
3691
|
+
}
|
|
3692
|
+
]
|
|
3693
|
+
},
|
|
3694
|
+
{
|
|
3695
|
+
category: "실행 기록",
|
|
3696
|
+
items: [{
|
|
3697
|
+
keys: "Ctrl + Z",
|
|
3698
|
+
action: "실행 취소"
|
|
3699
|
+
}, {
|
|
3700
|
+
keys: "Ctrl + Y / Ctrl + Shift + Z",
|
|
3701
|
+
action: "다시 실행"
|
|
3702
|
+
}]
|
|
3703
|
+
},
|
|
3704
|
+
{
|
|
3705
|
+
category: "선택 및 탐색",
|
|
3706
|
+
items: [
|
|
3707
|
+
{
|
|
3708
|
+
keys: "Ctrl + A",
|
|
3709
|
+
action: "전체 선택"
|
|
3710
|
+
},
|
|
3711
|
+
{
|
|
3712
|
+
keys: "Tab",
|
|
3713
|
+
action: "목록 들여쓰기 / 공백 삽입"
|
|
3714
|
+
},
|
|
3715
|
+
{
|
|
3716
|
+
keys: "Shift + Tab",
|
|
3717
|
+
action: "목록 내어쓰기"
|
|
3718
|
+
}
|
|
3719
|
+
]
|
|
3720
|
+
},
|
|
3721
|
+
{
|
|
3722
|
+
category: "클립보드",
|
|
3723
|
+
items: [{
|
|
3724
|
+
keys: "Ctrl + Shift + V",
|
|
3725
|
+
action: "일반 텍스트로 붙여넣기"
|
|
3726
|
+
}]
|
|
3727
|
+
},
|
|
3728
|
+
{
|
|
3729
|
+
category: "찾기 및 바꾸기",
|
|
3730
|
+
items: [{
|
|
3731
|
+
keys: "Ctrl + F",
|
|
3732
|
+
action: "문서에서 찾기"
|
|
3733
|
+
}, {
|
|
3734
|
+
keys: "Ctrl + H",
|
|
3735
|
+
action: "찾기 및 바꾸기"
|
|
3736
|
+
}]
|
|
3737
|
+
},
|
|
3738
|
+
{
|
|
3739
|
+
category: "편집기",
|
|
3740
|
+
items: [{
|
|
3741
|
+
keys: "Ctrl + Shift + /",
|
|
3742
|
+
action: "이 단축키 대화상자 표시"
|
|
3743
|
+
}]
|
|
3744
|
+
}
|
|
3745
|
+
]
|
|
3746
|
+
},
|
|
3747
|
+
contextMenu: {
|
|
3748
|
+
cut: "잘라내기",
|
|
3749
|
+
copy: "복사",
|
|
3750
|
+
paste: "붙여넣기",
|
|
3751
|
+
bold: "굵게",
|
|
3752
|
+
italic: "기울임꼴",
|
|
3753
|
+
underline: "밑줄",
|
|
3754
|
+
textColor: "글자 색",
|
|
3755
|
+
highlightColor: "강조 색",
|
|
3756
|
+
copyFormat: "서식 복사",
|
|
3757
|
+
pasteFormat: "서식 붙여넣기",
|
|
3758
|
+
removeFormat: "서식 제거",
|
|
3759
|
+
link: "링크 삽입",
|
|
3760
|
+
image: "이미지 삽입",
|
|
3761
|
+
video: "동영상 삽입",
|
|
3762
|
+
table: "표 삽입",
|
|
3763
|
+
back: "뒤로",
|
|
3764
|
+
noHighlight: "강조 없음",
|
|
3765
|
+
customColor: "사용자 지정 색",
|
|
3766
|
+
customColorLabel: "사용자 지정…"
|
|
3767
|
+
},
|
|
3768
|
+
statusbar: {
|
|
3769
|
+
resizeHandle: "편집기 크기 조정",
|
|
3770
|
+
words: (n) => `단어: ${n}`,
|
|
3771
|
+
wordsLimit: (n, max) => `단어: ${n}/${max}`,
|
|
3772
|
+
chars: (n) => `글자: ${n}`,
|
|
3773
|
+
charsLimit: (n, max) => `글자: ${n}/${max}`
|
|
3774
|
+
},
|
|
3775
|
+
tooltips: {
|
|
3776
|
+
link: {
|
|
3777
|
+
ariaLabel: "링크 작업",
|
|
3778
|
+
openLink: "링크 열기",
|
|
3779
|
+
copyUrl: "URL 복사",
|
|
3780
|
+
editLink: "링크 편집",
|
|
3781
|
+
removeLink: "링크 제거"
|
|
3782
|
+
},
|
|
3783
|
+
image: {
|
|
3784
|
+
ariaLabel: "이미지 작업",
|
|
3785
|
+
label: "이미지",
|
|
3786
|
+
floatLeft: "왼쪽 배치",
|
|
3787
|
+
noFloat: "배치 없음",
|
|
3788
|
+
alignCenter: "가운데 정렬",
|
|
3789
|
+
floatRight: "오른쪽 배치",
|
|
3790
|
+
originalSize: "원본 크기",
|
|
3791
|
+
rotateLeft: "왼쪽 회전",
|
|
3792
|
+
rotateRight: "오른쪽 회전",
|
|
3793
|
+
cropImage: "이미지 자르기",
|
|
3794
|
+
addCaption: "캡션 추가 / 편집",
|
|
3795
|
+
deleteImage: "이미지 삭제"
|
|
3796
|
+
},
|
|
3797
|
+
code: {
|
|
3798
|
+
ariaLabel: "코드 블록 작업",
|
|
3799
|
+
label: "코드",
|
|
3800
|
+
syntaxLanguage: "구문 언어",
|
|
3801
|
+
syntaxAriaLabel: "구문 언어",
|
|
3802
|
+
copyCode: "코드 복사",
|
|
3803
|
+
toggleWordWrap: "줄 바꿈 전환",
|
|
3804
|
+
enableWordWrap: "줄 바꿈 사용",
|
|
3805
|
+
disableWordWrap: "줄 바꿈 해제",
|
|
3806
|
+
convertToParagraph: "단락으로 변환",
|
|
3807
|
+
deleteCodeBlock: "코드 블록 삭제"
|
|
3808
|
+
},
|
|
3809
|
+
table: {
|
|
3810
|
+
ariaLabel: "표 작업",
|
|
3811
|
+
label: "표",
|
|
3812
|
+
selectCells: "셀 선택",
|
|
3813
|
+
addRowAbove: "위에 행 추가",
|
|
3814
|
+
addRowBelow: "아래에 행 추가",
|
|
3815
|
+
deleteRow: "행 삭제",
|
|
3816
|
+
addColumnLeft: "왼쪽에 열 추가",
|
|
3817
|
+
addColumnRight: "오른쪽에 열 추가",
|
|
3818
|
+
deleteColumn: "열 삭제",
|
|
3819
|
+
mergeCells: "셀 병합",
|
|
3820
|
+
unmergeCells: "셀 분할",
|
|
3821
|
+
columnWidth: "열 너비",
|
|
3822
|
+
rowHeight: "행 높이",
|
|
3823
|
+
tableBorderWidth: "표 테두리 너비",
|
|
3824
|
+
deleteTable: "표 삭제",
|
|
3825
|
+
columnWidthPx: "열 너비 (px)",
|
|
3826
|
+
rowHeightPx: "행 높이 (px)",
|
|
3827
|
+
tableBorderWidthPx: "표 테두리 너비 (px)",
|
|
3828
|
+
cancelBtn: "취소",
|
|
3829
|
+
applyBtn: "적용"
|
|
3830
|
+
},
|
|
3831
|
+
video: {
|
|
3832
|
+
ariaLabel: "동영상 작업",
|
|
3833
|
+
label: "동영상",
|
|
3834
|
+
floatLeft: "왼쪽 배치",
|
|
3835
|
+
noFloat: "배치 없음",
|
|
3836
|
+
alignCenter: "가운데 정렬",
|
|
3837
|
+
floatRight: "오른쪽 배치",
|
|
3838
|
+
originalSize: "원본 크기",
|
|
3839
|
+
previewVideo: "동영상 미리보기",
|
|
3840
|
+
exitPreview: "미리보기 종료",
|
|
3841
|
+
deleteVideo: "동영상 삭제"
|
|
3842
|
+
}
|
|
3843
|
+
},
|
|
3844
|
+
errors: {
|
|
3845
|
+
imageFormat: (type) => `"${type}" 형식은 웹 브라우저에서 지원되지 않습니다. JPEG, PNG 또는 WebP로 변환해 주세요.`,
|
|
3846
|
+
imageSize: (maxSize) => `이미지 파일이 너무 큽니다. 최대 허용 크기는 ${maxSize} MB입니다.`
|
|
3847
|
+
}
|
|
3848
|
+
}
|
|
3849
|
+
};
|
|
3850
|
+
/**
|
|
3851
|
+
* Resolve a locale object from a lang option value.
|
|
3852
|
+
*
|
|
3853
|
+
* @param {string | Partial<AsnLocale> | null | undefined} lang
|
|
3854
|
+
* @returns {AsnLocale} A fully-populated locale (always contains every key from en.js).
|
|
3855
|
+
*/
|
|
3856
|
+
function resolveLocale(lang) {
|
|
3857
|
+
if (!lang || lang === "en") return en;
|
|
3858
|
+
if (typeof lang === "string") {
|
|
3859
|
+
const partial = locales[lang];
|
|
3860
|
+
if (!partial) return en;
|
|
3861
|
+
return mergeDeep(mergeDeep({}, en), partial);
|
|
3862
|
+
}
|
|
3863
|
+
if (typeof lang === "object") return mergeDeep(mergeDeep({}, en), lang);
|
|
3864
|
+
return en;
|
|
3865
|
+
}
|
|
3866
|
+
/**
|
|
3867
|
+
* @typedef {Object} AsnLocale (see types/index.d.ts for the full definition)
|
|
3868
|
+
*/
|
|
3869
|
+
//#endregion
|
|
1167
3870
|
//#region src/js/core/sanitise.js
|
|
1168
3871
|
/**
|
|
1169
3872
|
* sanitise.js - Shared HTML and URL sanitisation utilities
|
|
@@ -2683,8 +5386,8 @@
|
|
|
2683
5386
|
* Inspired by Summernote's Toolbar module — rewritten without jQuery
|
|
2684
5387
|
*/
|
|
2685
5388
|
var _faPageLevelReady = null;
|
|
2686
|
-
var _S = "stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"";
|
|
2687
|
-
var _svgWrap = (paths) => `<svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24" fill="none" ${_S} style="display:block">${paths}</svg>`;
|
|
5389
|
+
var _S$1 = "stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"";
|
|
5390
|
+
var _svgWrap = (paths) => `<svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24" fill="none" ${_S$1} style="display:block">${paths}</svg>`;
|
|
2688
5391
|
var _SVG_MAP = new Map([
|
|
2689
5392
|
["bold", _svgWrap("<path d=\"M6 4h8a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z\"/><path d=\"M6 12h9a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z\"/>")],
|
|
2690
5393
|
["italic", _svgWrap("<line x1=\"19\" y1=\"4\" x2=\"10\" y2=\"4\"/><line x1=\"14\" y1=\"20\" x2=\"5\" y2=\"20\"/><line x1=\"15\" y1=\"4\" x2=\"9\" y2=\"20\"/>")],
|
|
@@ -2814,9 +5517,9 @@
|
|
|
2814
5517
|
const btn = createElement("button", {
|
|
2815
5518
|
type: "button",
|
|
2816
5519
|
class: !!this.options.useBootstrap ? this.options.toolbarButtonClass || "btn btn-sm btn-light" : "an-btn",
|
|
2817
|
-
title: def.tooltip || "",
|
|
5520
|
+
title: this.context.locale.toolbar[def.name] || def.tooltip || "",
|
|
2818
5521
|
"data-btn": def.name,
|
|
2819
|
-
"aria-label": def.tooltip || def.name,
|
|
5522
|
+
"aria-label": this.context.locale.toolbar[def.name] || def.tooltip || def.name,
|
|
2820
5523
|
"aria-haspopup": "true",
|
|
2821
5524
|
"aria-expanded": "false"
|
|
2822
5525
|
});
|
|
@@ -2829,7 +5532,7 @@
|
|
|
2829
5532
|
});
|
|
2830
5533
|
const grid = createElement("div", { class: "an-table-grid" });
|
|
2831
5534
|
const label = createElement("div", { class: "an-table-label" });
|
|
2832
|
-
label.textContent = "Insert Table";
|
|
5535
|
+
label.textContent = this.context.locale.toolbar.insertTableLabel || "Insert Table";
|
|
2833
5536
|
const cells = [];
|
|
2834
5537
|
for (let r = 1; r <= ROWS; r++) for (let c = 1; c <= COLS; c++) {
|
|
2835
5538
|
const cell = createElement("div", {
|
|
@@ -2849,7 +5552,7 @@
|
|
|
2849
5552
|
const c = +cell.getAttribute("data-col");
|
|
2850
5553
|
cell.classList.toggle("active", r <= rows && c <= cols);
|
|
2851
5554
|
});
|
|
2852
|
-
label.textContent = rows && cols ? `${rows} × ${cols}` : "Insert Table";
|
|
5555
|
+
label.textContent = rows && cols ? `${rows} × ${cols}` : this.context.locale.toolbar.insertTableLabel || "Insert Table";
|
|
2853
5556
|
};
|
|
2854
5557
|
const openPopup = () => {
|
|
2855
5558
|
isOpen = true;
|
|
@@ -2929,9 +5632,9 @@
|
|
|
2929
5632
|
const applyBtn = createElement("button", {
|
|
2930
5633
|
type: "button",
|
|
2931
5634
|
class: `${baseClass} an-color-btn`,
|
|
2932
|
-
title: def.tooltip || "",
|
|
5635
|
+
title: this.context.locale.toolbar[def.name] || def.tooltip || "",
|
|
2933
5636
|
"data-btn": def.name,
|
|
2934
|
-
"aria-label": def.tooltip || def.name
|
|
5637
|
+
"aria-label": this.context.locale.toolbar[def.name] || def.tooltip || def.name
|
|
2935
5638
|
});
|
|
2936
5639
|
const S = "stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"";
|
|
2937
5640
|
applyBtn.innerHTML = def.name === "foreColor" ? `<svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24" fill="none" ${S} style="display:block"><path d="M4 20L12 4L20 20"/><line x1="7.5" y1="14" x2="16.5" y2="14"/></svg>` : `<svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 24 24" fill="none" ${S} style="display:block"><path d="M3 21v-4l9-9 4 4-9 9z"/><path d="M12 8l4 4"/></svg>`;
|
|
@@ -2941,7 +5644,7 @@
|
|
|
2941
5644
|
const arrowBtn = createElement("button", {
|
|
2942
5645
|
type: "button",
|
|
2943
5646
|
class: `${baseClass} an-color-arrow`,
|
|
2944
|
-
title:
|
|
5647
|
+
title: def.name === "foreColor" ? this.context.locale.toolbar.chooseTextColor || "Choose text color" : this.context.locale.toolbar.chooseHighlightColor || "Choose highlight color",
|
|
2945
5648
|
"aria-haspopup": "true",
|
|
2946
5649
|
"aria-expanded": "false"
|
|
2947
5650
|
});
|
|
@@ -2963,9 +5666,9 @@
|
|
|
2963
5666
|
const colorInput = createElement("input", {
|
|
2964
5667
|
type: "color",
|
|
2965
5668
|
value: currentColor,
|
|
2966
|
-
title: "Custom color"
|
|
5669
|
+
title: this.context.locale.toolbar.customColor || "Custom color"
|
|
2967
5670
|
});
|
|
2968
|
-
const customLabel = createElement("span", {}, ["Custom color"]);
|
|
5671
|
+
const customLabel = createElement("span", {}, [this.context.locale.toolbar.customColor || "Custom color"]);
|
|
2969
5672
|
customRow.appendChild(colorInput);
|
|
2970
5673
|
customRow.appendChild(customLabel);
|
|
2971
5674
|
popup.appendChild(swatches);
|
|
@@ -3075,19 +5778,19 @@
|
|
|
3075
5778
|
const items = def.name === "fontFamily" ? this.options.fontFamilies || [] : def.items || [];
|
|
3076
5779
|
const select = createElement("select", {
|
|
3077
5780
|
class: def.selectClass ? `an-select ${def.selectClass}` : "an-select",
|
|
3078
|
-
title: def.tooltip || "",
|
|
5781
|
+
title: this.context.locale.toolbar[def.name] || def.tooltip || "",
|
|
3079
5782
|
"data-btn": def.name,
|
|
3080
|
-
"aria-label": def.tooltip || def.name
|
|
5783
|
+
"aria-label": this.context.locale.toolbar[def.name] || def.tooltip || def.name
|
|
3081
5784
|
});
|
|
3082
5785
|
const placeholder = createElement("option", {
|
|
3083
5786
|
value: "",
|
|
3084
5787
|
disabled: "",
|
|
3085
5788
|
hidden: ""
|
|
3086
|
-
}, [def.placeholder || "Font"]);
|
|
5789
|
+
}, [this.context.locale.toolbar[def.name + "Placeholder"] || def.placeholder || "Font"]);
|
|
3087
5790
|
select.appendChild(placeholder);
|
|
3088
5791
|
items.forEach((item) => {
|
|
3089
5792
|
const value = typeof item === "object" ? item.value : item;
|
|
3090
|
-
const label = typeof item === "object" ? item.label : item;
|
|
5793
|
+
const label = typeof item === "object" ? def.name === "paragraphStyle" ? (this.context.locale.toolbar.paragraphItems || {})[item.value] || item.label : item.label : item;
|
|
3091
5794
|
const isHeader = typeof item === "object" && !!item.disabled;
|
|
3092
5795
|
const attrs = { value };
|
|
3093
5796
|
if (isHeader) attrs.disabled = "";
|
|
@@ -3127,9 +5830,9 @@
|
|
|
3127
5830
|
const btn = createElement("button", {
|
|
3128
5831
|
type: "button",
|
|
3129
5832
|
class: `${!!this.options.useBootstrap ? this.options.toolbarButtonClass || "btn btn-sm btn-light" : `an-btn`}${btnDef.className ? ` ${btnDef.className}` : ""}`,
|
|
3130
|
-
title: btnDef.tooltip || "",
|
|
5833
|
+
title: this.context.locale.toolbar[btnDef.name] || btnDef.tooltip || "",
|
|
3131
5834
|
"data-btn": btnDef.name,
|
|
3132
|
-
"aria-label": btnDef.tooltip || btnDef.name
|
|
5835
|
+
"aria-label": this.context.locale.toolbar[btnDef.name] || btnDef.tooltip || btnDef.name
|
|
3133
5836
|
});
|
|
3134
5837
|
const faPrefix = this.options.fontAwesomeClass || "fas";
|
|
3135
5838
|
if (this._faReady) {
|
|
@@ -3254,7 +5957,7 @@
|
|
|
3254
5957
|
if (this.options.resizable !== false) {
|
|
3255
5958
|
const handle = createElement("div", {
|
|
3256
5959
|
class: "an-resize-handle",
|
|
3257
|
-
title:
|
|
5960
|
+
title: this.context.locale.statusbar.resizeHandle,
|
|
3258
5961
|
"aria-hidden": "true"
|
|
3259
5962
|
});
|
|
3260
5963
|
this._bindResize(handle);
|
|
@@ -3344,8 +6047,9 @@
|
|
|
3344
6047
|
const chars = text.replace(/\n/g, "").length;
|
|
3345
6048
|
const maxWords = this.options.maxWords || 0;
|
|
3346
6049
|
const maxChars = this.options.maxChars || 0;
|
|
3347
|
-
this.
|
|
3348
|
-
this.
|
|
6050
|
+
const LS = this.context.locale.statusbar;
|
|
6051
|
+
this._wordCountEl.textContent = maxWords ? LS.wordsLimit(words, maxWords) : LS.words(words);
|
|
6052
|
+
this._charCountEl.textContent = maxChars ? LS.charsLimit(chars, maxChars) : LS.chars(chars);
|
|
3349
6053
|
_applyLimitClass(this._wordCountEl, words, maxWords);
|
|
3350
6054
|
_applyLimitClass(this._charCountEl, chars, maxChars);
|
|
3351
6055
|
}
|
|
@@ -3942,32 +6646,33 @@
|
|
|
3942
6646
|
this._open();
|
|
3943
6647
|
}
|
|
3944
6648
|
_buildDialog() {
|
|
6649
|
+
const L = this.context.locale.linkDialog;
|
|
3945
6650
|
const overlay = createElement("div", {
|
|
3946
6651
|
class: "an-dialog-overlay",
|
|
3947
6652
|
role: "dialog",
|
|
3948
6653
|
"aria-modal": "true",
|
|
3949
|
-
"aria-label":
|
|
6654
|
+
"aria-label": L.ariaLabel
|
|
3950
6655
|
});
|
|
3951
6656
|
const box = createElement("div", { class: "an-dialog-box" });
|
|
3952
6657
|
const title = createElement("h3", { class: "an-dialog-title" });
|
|
3953
|
-
title.textContent =
|
|
6658
|
+
title.textContent = L.title;
|
|
3954
6659
|
const urlLabel = createElement("label", { class: "an-label" });
|
|
3955
|
-
urlLabel.textContent =
|
|
6660
|
+
urlLabel.textContent = L.url;
|
|
3956
6661
|
const urlInput = createElement("input", {
|
|
3957
6662
|
type: "url",
|
|
3958
6663
|
class: "an-input",
|
|
3959
|
-
placeholder:
|
|
6664
|
+
placeholder: L.urlPlaceholder,
|
|
3960
6665
|
id: "an-link-url",
|
|
3961
6666
|
name: "url",
|
|
3962
6667
|
autocomplete: "off"
|
|
3963
6668
|
});
|
|
3964
6669
|
this._urlInput = urlInput;
|
|
3965
6670
|
const textLabel = createElement("label", { class: "an-label" });
|
|
3966
|
-
textLabel.textContent =
|
|
6671
|
+
textLabel.textContent = L.displayText;
|
|
3967
6672
|
const textInput = createElement("input", {
|
|
3968
6673
|
type: "text",
|
|
3969
6674
|
class: "an-input",
|
|
3970
|
-
placeholder:
|
|
6675
|
+
placeholder: L.textPlaceholder,
|
|
3971
6676
|
id: "an-link-text",
|
|
3972
6677
|
name: "linkText",
|
|
3973
6678
|
autocomplete: "off"
|
|
@@ -3981,18 +6686,18 @@
|
|
|
3981
6686
|
});
|
|
3982
6687
|
this._tabCheckbox = tabCheckbox;
|
|
3983
6688
|
tabLabel.appendChild(tabCheckbox);
|
|
3984
|
-
tabLabel.appendChild(document.createTextNode("
|
|
6689
|
+
tabLabel.appendChild(document.createTextNode(" " + L.openInNewTab));
|
|
3985
6690
|
const btnRow = createElement("div", { class: "an-dialog-actions" });
|
|
3986
6691
|
const insertBtn = createElement("button", {
|
|
3987
6692
|
type: "button",
|
|
3988
6693
|
class: "an-btn an-btn-primary"
|
|
3989
6694
|
});
|
|
3990
|
-
insertBtn.textContent =
|
|
6695
|
+
insertBtn.textContent = L.insertBtn;
|
|
3991
6696
|
const cancelBtn = createElement("button", {
|
|
3992
6697
|
type: "button",
|
|
3993
6698
|
class: "an-btn"
|
|
3994
6699
|
});
|
|
3995
|
-
cancelBtn.textContent =
|
|
6700
|
+
cancelBtn.textContent = L.cancelBtn;
|
|
3996
6701
|
btnRow.appendChild(insertBtn);
|
|
3997
6702
|
btnRow.appendChild(cancelBtn);
|
|
3998
6703
|
box.append(title, urlLabel, urlInput, textLabel, textInput, tabLabel, btnRow);
|
|
@@ -4118,53 +6823,54 @@
|
|
|
4118
6823
|
this._open();
|
|
4119
6824
|
}
|
|
4120
6825
|
_buildDialog() {
|
|
6826
|
+
const L = this.context.locale.imageDialog;
|
|
4121
6827
|
const overlay = createElement("div", {
|
|
4122
6828
|
class: "an-dialog-overlay",
|
|
4123
6829
|
role: "dialog",
|
|
4124
6830
|
"aria-modal": "true",
|
|
4125
|
-
"aria-label":
|
|
6831
|
+
"aria-label": L.ariaLabel
|
|
4126
6832
|
});
|
|
4127
6833
|
const box = createElement("div", { class: "an-dialog-box" });
|
|
4128
6834
|
const title = createElement("h3", { class: "an-dialog-title" });
|
|
4129
|
-
title.textContent =
|
|
6835
|
+
title.textContent = L.title;
|
|
4130
6836
|
const urlLabel = createElement("label", { class: "an-label" });
|
|
4131
|
-
urlLabel.textContent =
|
|
6837
|
+
urlLabel.textContent = L.imageUrl;
|
|
4132
6838
|
const urlInput = createElement("input", {
|
|
4133
6839
|
type: "url",
|
|
4134
6840
|
class: "an-input",
|
|
4135
|
-
placeholder:
|
|
6841
|
+
placeholder: L.urlPlaceholder,
|
|
4136
6842
|
autocomplete: "off"
|
|
4137
6843
|
});
|
|
4138
6844
|
this._urlInput = urlInput;
|
|
4139
6845
|
const altLabel = createElement("label", { class: "an-label" });
|
|
4140
|
-
altLabel.textContent =
|
|
6846
|
+
altLabel.textContent = L.altText;
|
|
4141
6847
|
const altInput = createElement("input", {
|
|
4142
6848
|
type: "text",
|
|
4143
6849
|
class: "an-input",
|
|
4144
|
-
placeholder:
|
|
6850
|
+
placeholder: L.altPlaceholder,
|
|
4145
6851
|
autocomplete: "off"
|
|
4146
6852
|
});
|
|
4147
6853
|
this._altInput = altInput;
|
|
4148
6854
|
box.append(title, urlLabel, urlInput, altLabel, altInput);
|
|
4149
6855
|
const alignLabel = createElement("label", { class: "an-label" });
|
|
4150
|
-
alignLabel.textContent =
|
|
6856
|
+
alignLabel.textContent = L.alignment;
|
|
4151
6857
|
const alignRow = createElement("div", { class: "an-align-row" });
|
|
4152
6858
|
[
|
|
4153
6859
|
{
|
|
4154
6860
|
value: "",
|
|
4155
|
-
label:
|
|
6861
|
+
label: L.alignNone
|
|
4156
6862
|
},
|
|
4157
6863
|
{
|
|
4158
6864
|
value: "left",
|
|
4159
|
-
label:
|
|
6865
|
+
label: L.alignLeft
|
|
4160
6866
|
},
|
|
4161
6867
|
{
|
|
4162
6868
|
value: "center",
|
|
4163
|
-
label:
|
|
6869
|
+
label: L.alignCenter
|
|
4164
6870
|
},
|
|
4165
6871
|
{
|
|
4166
6872
|
value: "right",
|
|
4167
|
-
label:
|
|
6873
|
+
label: L.alignRight
|
|
4168
6874
|
}
|
|
4169
6875
|
].forEach(({ value, label }) => {
|
|
4170
6876
|
const radioId = `an-align-${value || "none"}`;
|
|
@@ -4186,7 +6892,7 @@
|
|
|
4186
6892
|
box.append(alignLabel, alignRow);
|
|
4187
6893
|
if (this.options.allowImageUpload !== false) {
|
|
4188
6894
|
const fileLabel = createElement("label", { class: "an-label" });
|
|
4189
|
-
fileLabel.textContent =
|
|
6895
|
+
fileLabel.textContent = L.uploadLabel;
|
|
4190
6896
|
const fileInput = createElement("input", {
|
|
4191
6897
|
type: "file",
|
|
4192
6898
|
class: "an-input",
|
|
@@ -4204,12 +6910,12 @@
|
|
|
4204
6910
|
type: "button",
|
|
4205
6911
|
class: "an-btn an-btn-primary"
|
|
4206
6912
|
});
|
|
4207
|
-
insertBtn.textContent =
|
|
6913
|
+
insertBtn.textContent = L.insertBtn;
|
|
4208
6914
|
const cancelBtn = createElement("button", {
|
|
4209
6915
|
type: "button",
|
|
4210
6916
|
class: "an-btn"
|
|
4211
6917
|
});
|
|
4212
|
-
cancelBtn.textContent =
|
|
6918
|
+
cancelBtn.textContent = L.cancelBtn;
|
|
4213
6919
|
btnRow.appendChild(insertBtn);
|
|
4214
6920
|
btnRow.appendChild(cancelBtn);
|
|
4215
6921
|
box.append(btnRow);
|
|
@@ -4245,7 +6951,7 @@
|
|
|
4245
6951
|
"image/svg+xml",
|
|
4246
6952
|
"image/avif"
|
|
4247
6953
|
]).has(file.type)) {
|
|
4248
|
-
const message =
|
|
6954
|
+
const message = this.context.locale.errors.imageFormat(file.type);
|
|
4249
6955
|
if (this._fileHint) this._fileHint.textContent = message;
|
|
4250
6956
|
this.context.triggerEvent("imageError", {
|
|
4251
6957
|
file,
|
|
@@ -4257,7 +6963,7 @@
|
|
|
4257
6963
|
if (this._fileHint) this._fileHint.textContent = "";
|
|
4258
6964
|
const maxSize = (this.options.maxImageSize || 5) * 1024 * 1024;
|
|
4259
6965
|
if (file.size > maxSize) {
|
|
4260
|
-
const message =
|
|
6966
|
+
const message = this.context.locale.errors.imageSize(this.options.maxImageSize || 5);
|
|
4261
6967
|
if (this._fileHint) this._fileHint.textContent = message;
|
|
4262
6968
|
console.warn("[AutumnNote] ImageDialog:", message);
|
|
4263
6969
|
this.context.triggerEvent("imageError", {
|
|
@@ -4343,28 +7049,29 @@
|
|
|
4343
7049
|
this._open();
|
|
4344
7050
|
}
|
|
4345
7051
|
_buildDialog() {
|
|
7052
|
+
const L = this.context.locale.videoDialog;
|
|
4346
7053
|
const overlay = createElement("div", {
|
|
4347
7054
|
class: "an-dialog-overlay",
|
|
4348
7055
|
role: "dialog",
|
|
4349
7056
|
"aria-modal": "true",
|
|
4350
|
-
"aria-label":
|
|
7057
|
+
"aria-label": L.ariaLabel
|
|
4351
7058
|
});
|
|
4352
7059
|
const box = createElement("div", { class: "an-dialog-box" });
|
|
4353
7060
|
const title = createElement("h3", { class: "an-dialog-title" });
|
|
4354
|
-
title.textContent =
|
|
7061
|
+
title.textContent = L.title;
|
|
4355
7062
|
const urlLabel = createElement("label", { class: "an-label" });
|
|
4356
|
-
urlLabel.textContent =
|
|
7063
|
+
urlLabel.textContent = L.videoUrl;
|
|
4357
7064
|
const urlInput = createElement("input", {
|
|
4358
7065
|
type: "url",
|
|
4359
7066
|
class: "an-input",
|
|
4360
|
-
placeholder:
|
|
7067
|
+
placeholder: L.urlPlaceholder,
|
|
4361
7068
|
autocomplete: "off"
|
|
4362
7069
|
});
|
|
4363
7070
|
this._urlInput = urlInput;
|
|
4364
7071
|
const hintEl = createElement("p", { class: "an-dialog-hint" });
|
|
4365
7072
|
this._hintEl = hintEl;
|
|
4366
7073
|
const widthLabel = createElement("label", { class: "an-label" });
|
|
4367
|
-
widthLabel.textContent =
|
|
7074
|
+
widthLabel.textContent = L.widthLabel;
|
|
4368
7075
|
const widthInput = createElement("input", {
|
|
4369
7076
|
type: "number",
|
|
4370
7077
|
class: "an-input",
|
|
@@ -4379,19 +7086,19 @@
|
|
|
4379
7086
|
type: "button",
|
|
4380
7087
|
class: "an-btn an-btn-primary"
|
|
4381
7088
|
});
|
|
4382
|
-
insertBtn.textContent =
|
|
7089
|
+
insertBtn.textContent = L.insertBtn;
|
|
4383
7090
|
const cancelBtn = createElement("button", {
|
|
4384
7091
|
type: "button",
|
|
4385
7092
|
class: "an-btn"
|
|
4386
7093
|
});
|
|
4387
|
-
cancelBtn.textContent =
|
|
7094
|
+
cancelBtn.textContent = L.cancelBtn;
|
|
4388
7095
|
btnRow.appendChild(insertBtn);
|
|
4389
7096
|
btnRow.appendChild(cancelBtn);
|
|
4390
7097
|
box.append(title, urlLabel, urlInput, hintEl, widthLabel, widthInput, btnRow);
|
|
4391
7098
|
overlay.appendChild(box);
|
|
4392
7099
|
const d0 = on(urlInput, "input", () => {
|
|
4393
7100
|
const info = this._parseVideoUrl(urlInput.value.trim());
|
|
4394
|
-
hintEl.textContent = info ?
|
|
7101
|
+
hintEl.textContent = info ? this.context.locale.videoDialog.detected(info.type) : urlInput.value ? this.context.locale.videoDialog.unknownFormat : "";
|
|
4395
7102
|
});
|
|
4396
7103
|
const d1 = on(insertBtn, "click", () => this._onInsert());
|
|
4397
7104
|
const d2 = on(cancelBtn, "click", () => this._close());
|
|
@@ -4416,7 +7123,7 @@
|
|
|
4416
7123
|
}
|
|
4417
7124
|
const html = this._buildEmbedHtml(rawUrl, width);
|
|
4418
7125
|
if (!html) {
|
|
4419
|
-
this._hintEl.textContent =
|
|
7126
|
+
this._hintEl.textContent = this.context.locale.videoDialog.invalidUrl;
|
|
4420
7127
|
this._urlInput.focus();
|
|
4421
7128
|
return;
|
|
4422
7129
|
}
|
|
@@ -4988,19 +7695,20 @@
|
|
|
4988
7695
|
this._el = null;
|
|
4989
7696
|
}
|
|
4990
7697
|
_buildTooltip() {
|
|
7698
|
+
const L = this.context.locale.tooltips.link;
|
|
4991
7699
|
const el = createElement("div", {
|
|
4992
7700
|
class: "an-link-tooltip",
|
|
4993
7701
|
role: "toolbar",
|
|
4994
|
-
"aria-label":
|
|
7702
|
+
"aria-label": L.ariaLabel
|
|
4995
7703
|
});
|
|
4996
7704
|
el.style.display = "none";
|
|
4997
7705
|
this._urlLabel = createElement("span", { class: "an-link-tooltip-url" });
|
|
4998
7706
|
el.appendChild(this._urlLabel);
|
|
4999
7707
|
el.appendChild(createElement("div", { class: "an-link-tooltip-sep" }));
|
|
5000
|
-
this._openBtn = this._makeBtn(ICONS$5.open,
|
|
5001
|
-
this._copyBtn = this._makeBtn(ICONS$5.copy,
|
|
5002
|
-
this._editBtn = this._makeBtn(ICONS$5.edit,
|
|
5003
|
-
this._unlinkBtn = this._makeBtn(ICONS$5.unlink,
|
|
7708
|
+
this._openBtn = this._makeBtn(ICONS$5.open, L.openLink, () => this._openLink());
|
|
7709
|
+
this._copyBtn = this._makeBtn(ICONS$5.copy, L.copyUrl, () => this._copyLink());
|
|
7710
|
+
this._editBtn = this._makeBtn(ICONS$5.edit, L.editLink, () => this._editLink());
|
|
7711
|
+
this._unlinkBtn = this._makeBtn(ICONS$5.unlink, L.removeLink, () => this._unlink());
|
|
5004
7712
|
el.appendChild(this._openBtn);
|
|
5005
7713
|
el.appendChild(this._copyBtn);
|
|
5006
7714
|
el.appendChild(this._editBtn);
|
|
@@ -5179,38 +7887,39 @@
|
|
|
5179
7887
|
this._el = null;
|
|
5180
7888
|
}
|
|
5181
7889
|
_buildTooltip() {
|
|
7890
|
+
const L = this.context.locale.tooltips.image;
|
|
5182
7891
|
const el = createElement("div", {
|
|
5183
7892
|
class: "an-link-tooltip an-image-tooltip",
|
|
5184
7893
|
role: "toolbar",
|
|
5185
|
-
"aria-label":
|
|
7894
|
+
"aria-label": L.ariaLabel
|
|
5186
7895
|
});
|
|
5187
7896
|
el.style.display = "none";
|
|
5188
7897
|
this._label = createElement("span", { class: "an-link-tooltip-url" });
|
|
5189
|
-
this._label.textContent =
|
|
7898
|
+
this._label.textContent = L.label;
|
|
5190
7899
|
el.appendChild(this._label);
|
|
5191
7900
|
el.appendChild(createElement("div", { class: "an-link-tooltip-sep" }));
|
|
5192
|
-
this._floatLeftBtn = this._makeBtn(ICONS$4.floatLeft,
|
|
5193
|
-
this._floatNoneBtn = this._makeBtn(ICONS$4.floatNone,
|
|
5194
|
-
this._alignCenterBtn = this._makeBtn(ICONS$4.alignCenter,
|
|
5195
|
-
this._floatRightBtn = this._makeBtn(ICONS$4.floatRight,
|
|
7901
|
+
this._floatLeftBtn = this._makeBtn(ICONS$4.floatLeft, L.floatLeft, () => this._setFloat("left"));
|
|
7902
|
+
this._floatNoneBtn = this._makeBtn(ICONS$4.floatNone, L.noFloat, () => this._setFloat(""));
|
|
7903
|
+
this._alignCenterBtn = this._makeBtn(ICONS$4.alignCenter, L.alignCenter, () => this._setCenter());
|
|
7904
|
+
this._floatRightBtn = this._makeBtn(ICONS$4.floatRight, L.floatRight, () => this._setFloat("right"));
|
|
5196
7905
|
el.appendChild(this._floatLeftBtn);
|
|
5197
7906
|
el.appendChild(this._floatNoneBtn);
|
|
5198
7907
|
el.appendChild(this._alignCenterBtn);
|
|
5199
7908
|
el.appendChild(this._floatRightBtn);
|
|
5200
7909
|
el.appendChild(createElement("div", { class: "an-link-tooltip-sep" }));
|
|
5201
|
-
this._originalBtn = this._makeBtn(ICONS$4.originalSize,
|
|
7910
|
+
this._originalBtn = this._makeBtn(ICONS$4.originalSize, L.originalSize, () => this._resetSize());
|
|
5202
7911
|
el.appendChild(this._originalBtn);
|
|
5203
7912
|
el.appendChild(createElement("div", { class: "an-link-tooltip-sep" }));
|
|
5204
|
-
el.appendChild(this._makeBtn(ICONS$4.rotateLeft,
|
|
5205
|
-
el.appendChild(this._makeBtn(ICONS$4.rotateRight,
|
|
7913
|
+
el.appendChild(this._makeBtn(ICONS$4.rotateLeft, L.rotateLeft, () => this._rotate(-90)));
|
|
7914
|
+
el.appendChild(this._makeBtn(ICONS$4.rotateRight, L.rotateRight, () => this._rotate(90)));
|
|
5206
7915
|
el.appendChild(createElement("div", { class: "an-link-tooltip-sep" }));
|
|
5207
|
-
this._cropBtn = this._makeBtn(ICONS$4.crop,
|
|
7916
|
+
this._cropBtn = this._makeBtn(ICONS$4.crop, L.cropImage, () => this._crop());
|
|
5208
7917
|
el.appendChild(this._cropBtn);
|
|
5209
7918
|
el.appendChild(createElement("div", { class: "an-link-tooltip-sep" }));
|
|
5210
|
-
this._captionBtn = this._makeBtn(ICONS$4.caption,
|
|
7919
|
+
this._captionBtn = this._makeBtn(ICONS$4.caption, L.addCaption, () => this._toggleCaption());
|
|
5211
7920
|
el.appendChild(this._captionBtn);
|
|
5212
7921
|
el.appendChild(createElement("div", { class: "an-link-tooltip-sep" }));
|
|
5213
|
-
this._deleteBtn = this._makeBtn(ICONS$4.deleteImg,
|
|
7922
|
+
this._deleteBtn = this._makeBtn(ICONS$4.deleteImg, L.deleteImage, () => this._delete(), true);
|
|
5214
7923
|
el.appendChild(this._deleteBtn);
|
|
5215
7924
|
this._disposers.push(on(el, "mouseenter", () => this._clearTimers()), on(el, "mouseleave", () => this._scheduleHide()));
|
|
5216
7925
|
return el;
|
|
@@ -5462,32 +8171,33 @@
|
|
|
5462
8171
|
this._el = null;
|
|
5463
8172
|
}
|
|
5464
8173
|
_buildTooltip() {
|
|
8174
|
+
const L = this.context.locale.tooltips.video;
|
|
5465
8175
|
const el = createElement("div", {
|
|
5466
8176
|
class: "an-link-tooltip an-video-tooltip",
|
|
5467
8177
|
role: "toolbar",
|
|
5468
|
-
"aria-label":
|
|
8178
|
+
"aria-label": L.ariaLabel
|
|
5469
8179
|
});
|
|
5470
8180
|
el.style.display = "none";
|
|
5471
8181
|
this._label = createElement("span", { class: "an-link-tooltip-url" });
|
|
5472
|
-
this._label.textContent =
|
|
8182
|
+
this._label.textContent = L.label;
|
|
5473
8183
|
el.appendChild(this._label);
|
|
5474
8184
|
el.appendChild(createElement("div", { class: "an-link-tooltip-sep" }));
|
|
5475
|
-
this._floatLeftBtn = this._makeBtn(ICONS$3.floatLeft,
|
|
5476
|
-
this._floatNoneBtn = this._makeBtn(ICONS$3.floatNone,
|
|
5477
|
-
this._alignCenterBtn = this._makeBtn(ICONS$3.alignCenter,
|
|
5478
|
-
this._floatRightBtn = this._makeBtn(ICONS$3.floatRight,
|
|
8185
|
+
this._floatLeftBtn = this._makeBtn(ICONS$3.floatLeft, L.floatLeft, () => this._setFloat("left"));
|
|
8186
|
+
this._floatNoneBtn = this._makeBtn(ICONS$3.floatNone, L.noFloat, () => this._setFloat(""));
|
|
8187
|
+
this._alignCenterBtn = this._makeBtn(ICONS$3.alignCenter, L.alignCenter, () => this._setCenter());
|
|
8188
|
+
this._floatRightBtn = this._makeBtn(ICONS$3.floatRight, L.floatRight, () => this._setFloat("right"));
|
|
5479
8189
|
el.appendChild(this._floatLeftBtn);
|
|
5480
8190
|
el.appendChild(this._floatNoneBtn);
|
|
5481
8191
|
el.appendChild(this._alignCenterBtn);
|
|
5482
8192
|
el.appendChild(this._floatRightBtn);
|
|
5483
8193
|
el.appendChild(createElement("div", { class: "an-link-tooltip-sep" }));
|
|
5484
|
-
this._originalBtn = this._makeBtn(ICONS$3.originalSize,
|
|
8194
|
+
this._originalBtn = this._makeBtn(ICONS$3.originalSize, L.originalSize, () => this._resetSize());
|
|
5485
8195
|
el.appendChild(this._originalBtn);
|
|
5486
8196
|
el.appendChild(createElement("div", { class: "an-link-tooltip-sep" }));
|
|
5487
|
-
this._previewBtn = this._makeBtn(ICONS$3.preview,
|
|
8197
|
+
this._previewBtn = this._makeBtn(ICONS$3.preview, L.previewVideo, () => this._togglePreview());
|
|
5488
8198
|
el.appendChild(this._previewBtn);
|
|
5489
8199
|
el.appendChild(createElement("div", { class: "an-link-tooltip-sep" }));
|
|
5490
|
-
this._deleteBtn = this._makeBtn(ICONS$3.deleteVideo,
|
|
8200
|
+
this._deleteBtn = this._makeBtn(ICONS$3.deleteVideo, L.deleteVideo, () => this._delete(), true);
|
|
5491
8201
|
el.appendChild(this._deleteBtn);
|
|
5492
8202
|
this._disposers.push(on(el, "mouseenter", () => this._clearTimers()), on(el, "mouseleave", () => this._scheduleHide()));
|
|
5493
8203
|
return el;
|
|
@@ -5624,7 +8334,7 @@
|
|
|
5624
8334
|
if (shield) shield.style.display = "none";
|
|
5625
8335
|
this.context.invoke("videoResizer.deselect");
|
|
5626
8336
|
this._previewBtn.classList.add("an-link-tooltip-btn--copied");
|
|
5627
|
-
this._previewBtn.title =
|
|
8337
|
+
this._previewBtn.title = this.context.locale.tooltips.video.exitPreview;
|
|
5628
8338
|
this._previewClickOff = (e) => {
|
|
5629
8339
|
if (!wrapper.contains(e.target) && !this._el.contains(e.target)) this._exitPreview();
|
|
5630
8340
|
};
|
|
@@ -5638,7 +8348,7 @@
|
|
|
5638
8348
|
if (shield) shield.style.display = "";
|
|
5639
8349
|
}
|
|
5640
8350
|
this._previewBtn.classList.remove("an-link-tooltip-btn--copied");
|
|
5641
|
-
this._previewBtn.title =
|
|
8351
|
+
this._previewBtn.title = this.context.locale.tooltips.video.previewVideo;
|
|
5642
8352
|
if (this._previewClickOff) {
|
|
5643
8353
|
document.removeEventListener("mousedown", this._previewClickOff, true);
|
|
5644
8354
|
this._previewClickOff = null;
|
|
@@ -5952,35 +8662,36 @@
|
|
|
5952
8662
|
this._sizePopover = null;
|
|
5953
8663
|
}
|
|
5954
8664
|
_buildTooltip() {
|
|
8665
|
+
const L = this.context.locale.tooltips.table;
|
|
5955
8666
|
const el = createElement("div", {
|
|
5956
8667
|
class: "an-link-tooltip an-table-tooltip",
|
|
5957
8668
|
role: "toolbar",
|
|
5958
|
-
"aria-label":
|
|
8669
|
+
"aria-label": L.ariaLabel
|
|
5959
8670
|
});
|
|
5960
8671
|
el.style.display = "none";
|
|
5961
8672
|
this._label = createElement("span", { class: "an-link-tooltip-url" });
|
|
5962
|
-
this._label.textContent =
|
|
8673
|
+
this._label.textContent = L.label;
|
|
5963
8674
|
el.appendChild(this._label);
|
|
5964
8675
|
el.appendChild(this._sep());
|
|
5965
|
-
this._selectBtn = this._makeBtn(ICONS$2.selectCells,
|
|
8676
|
+
this._selectBtn = this._makeBtn(ICONS$2.selectCells, L.selectCells, () => this._toggleSelectMode());
|
|
5966
8677
|
el.appendChild(this._selectBtn);
|
|
5967
8678
|
el.appendChild(this._sep());
|
|
5968
|
-
el.appendChild(this._makeBtn(ICONS$2.rowAbove,
|
|
5969
|
-
el.appendChild(this._makeBtn(ICONS$2.rowBelow,
|
|
5970
|
-
el.appendChild(this._makeBtn(ICONS$2.deleteRow,
|
|
8679
|
+
el.appendChild(this._makeBtn(ICONS$2.rowAbove, L.addRowAbove, () => this._addRow("above")));
|
|
8680
|
+
el.appendChild(this._makeBtn(ICONS$2.rowBelow, L.addRowBelow, () => this._addRow("below")));
|
|
8681
|
+
el.appendChild(this._makeBtn(ICONS$2.deleteRow, L.deleteRow, () => this._deleteRow()));
|
|
5971
8682
|
el.appendChild(this._sep());
|
|
5972
|
-
el.appendChild(this._makeBtn(ICONS$2.colLeft,
|
|
5973
|
-
el.appendChild(this._makeBtn(ICONS$2.colRight,
|
|
5974
|
-
el.appendChild(this._makeBtn(ICONS$2.deleteCol,
|
|
8683
|
+
el.appendChild(this._makeBtn(ICONS$2.colLeft, L.addColumnLeft, () => this._addColumn("left")));
|
|
8684
|
+
el.appendChild(this._makeBtn(ICONS$2.colRight, L.addColumnRight, () => this._addColumn("right")));
|
|
8685
|
+
el.appendChild(this._makeBtn(ICONS$2.deleteCol, L.deleteColumn, () => this._deleteColumn()));
|
|
5975
8686
|
el.appendChild(this._sep());
|
|
5976
|
-
el.appendChild(this._makeBtn(ICONS$2.mergeCells,
|
|
5977
|
-
el.appendChild(this._makeBtn(ICONS$2.unmergeCells,
|
|
8687
|
+
el.appendChild(this._makeBtn(ICONS$2.mergeCells, L.mergeCells, () => this._mergeCells()));
|
|
8688
|
+
el.appendChild(this._makeBtn(ICONS$2.unmergeCells, L.unmergeCells, () => this._unmergeCells()));
|
|
5978
8689
|
el.appendChild(this._sep());
|
|
5979
|
-
el.appendChild(this._makeBtn(ICONS$2.colWidth,
|
|
5980
|
-
el.appendChild(this._makeBtn(ICONS$2.rowHeight,
|
|
5981
|
-
el.appendChild(this._makeBtn(ICONS$2.tableBorder,
|
|
8690
|
+
el.appendChild(this._makeBtn(ICONS$2.colWidth, L.columnWidth, () => this._openSizePopover("col")));
|
|
8691
|
+
el.appendChild(this._makeBtn(ICONS$2.rowHeight, L.rowHeight, () => this._openSizePopover("row")));
|
|
8692
|
+
el.appendChild(this._makeBtn(ICONS$2.tableBorder, L.tableBorderWidth, () => this._openSizePopover("border")));
|
|
5982
8693
|
el.appendChild(this._sep());
|
|
5983
|
-
el.appendChild(this._makeBtn(ICONS$2.deleteTable,
|
|
8694
|
+
el.appendChild(this._makeBtn(ICONS$2.deleteTable, L.deleteTable, () => this._deleteTable(), true));
|
|
5984
8695
|
this._disposers.push(on(el, "mouseenter", () => this._clearTimers()), on(el, "mouseleave", () => {
|
|
5985
8696
|
if (this._selectMode) return;
|
|
5986
8697
|
if (this._sizePopover && this._sizePopover.style.display !== "none") return;
|
|
@@ -6378,12 +9089,12 @@
|
|
|
6378
9089
|
type: "button",
|
|
6379
9090
|
class: "an-btn"
|
|
6380
9091
|
});
|
|
6381
|
-
cancelBtn.textContent =
|
|
9092
|
+
cancelBtn.textContent = this.context.locale.tooltips.table.cancelBtn;
|
|
6382
9093
|
const applyBtn = createElement("button", {
|
|
6383
9094
|
type: "button",
|
|
6384
9095
|
class: "an-btn an-btn-primary"
|
|
6385
9096
|
});
|
|
6386
|
-
applyBtn.textContent =
|
|
9097
|
+
applyBtn.textContent = this.context.locale.tooltips.table.applyBtn;
|
|
6387
9098
|
actionsEl.appendChild(cancelBtn);
|
|
6388
9099
|
actionsEl.appendChild(applyBtn);
|
|
6389
9100
|
popover.appendChild(titleEl);
|
|
@@ -6421,7 +9132,7 @@
|
|
|
6421
9132
|
if (!table) return;
|
|
6422
9133
|
const firstCell = table.querySelector("td, th");
|
|
6423
9134
|
const currentPx = firstCell ? parseInt(firstCell.style.borderWidth, 10) || parseInt(window.getComputedStyle(firstCell).borderWidth, 10) || 1 : 1;
|
|
6424
|
-
this._sizeTitleEl.textContent =
|
|
9135
|
+
this._sizeTitleEl.textContent = this.context.locale.tooltips.table.tableBorderWidthPx;
|
|
6425
9136
|
this._sizeInputEl.min = "0";
|
|
6426
9137
|
this._sizeInputEl.max = "10";
|
|
6427
9138
|
this._sizeInputEl.value = currentPx;
|
|
@@ -6443,7 +9154,7 @@
|
|
|
6443
9154
|
const t = c.closest("table");
|
|
6444
9155
|
return t && t === cell.closest("table");
|
|
6445
9156
|
});
|
|
6446
|
-
this._sizeTitleEl.textContent = isCol ?
|
|
9157
|
+
this._sizeTitleEl.textContent = isCol ? this.context.locale.tooltips.table.columnWidthPx : this.context.locale.tooltips.table.rowHeightPx;
|
|
6447
9158
|
this._sizeInputEl.min = "1";
|
|
6448
9159
|
this._sizeInputEl.max = "2000";
|
|
6449
9160
|
this._sizeInputEl.value = isCol ? cell.offsetWidth || 120 : cell.closest("tr") ? cell.closest("tr").offsetHeight || 40 : 40;
|
|
@@ -6543,20 +9254,21 @@
|
|
|
6543
9254
|
this._el = null;
|
|
6544
9255
|
}
|
|
6545
9256
|
_buildTooltip() {
|
|
9257
|
+
const L = this.context.locale.tooltips.code;
|
|
6546
9258
|
const el = createElement("div", {
|
|
6547
9259
|
class: "an-link-tooltip an-code-tooltip",
|
|
6548
9260
|
role: "toolbar",
|
|
6549
|
-
"aria-label":
|
|
9261
|
+
"aria-label": L.ariaLabel
|
|
6550
9262
|
});
|
|
6551
9263
|
el.style.display = "none";
|
|
6552
9264
|
this._label = createElement("span", { class: "an-link-tooltip-url" });
|
|
6553
|
-
this._label.textContent =
|
|
9265
|
+
this._label.textContent = L.label;
|
|
6554
9266
|
el.appendChild(this._label);
|
|
6555
9267
|
el.appendChild(this._sep());
|
|
6556
9268
|
this._langSelect = createElement("select", {
|
|
6557
9269
|
class: "an-code-lang-select",
|
|
6558
|
-
title:
|
|
6559
|
-
"aria-label":
|
|
9270
|
+
title: L.syntaxLanguage,
|
|
9271
|
+
"aria-label": L.syntaxAriaLabel
|
|
6560
9272
|
});
|
|
6561
9273
|
[
|
|
6562
9274
|
["", "Plain text"],
|
|
@@ -6587,15 +9299,15 @@
|
|
|
6587
9299
|
this._disposers.push(on(this._langSelect, "change", () => this._onLangChange()));
|
|
6588
9300
|
el.appendChild(this._langSelect);
|
|
6589
9301
|
el.appendChild(this._sep());
|
|
6590
|
-
this._copyBtn = this._makeBtn(ICONS$1.copy,
|
|
9302
|
+
this._copyBtn = this._makeBtn(ICONS$1.copy, L.copyCode, () => this._copyCode());
|
|
6591
9303
|
el.appendChild(this._copyBtn);
|
|
6592
9304
|
el.appendChild(this._sep());
|
|
6593
|
-
this._wrapBtn = this._makeBtn(ICONS$1.wrapOn,
|
|
9305
|
+
this._wrapBtn = this._makeBtn(ICONS$1.wrapOn, L.toggleWordWrap, () => this._toggleWrap());
|
|
6594
9306
|
el.appendChild(this._wrapBtn);
|
|
6595
9307
|
el.appendChild(this._sep());
|
|
6596
|
-
el.appendChild(this._makeBtn(ICONS$1.toParagraph,
|
|
9308
|
+
el.appendChild(this._makeBtn(ICONS$1.toParagraph, L.convertToParagraph, () => this._toParagraph()));
|
|
6597
9309
|
el.appendChild(this._sep());
|
|
6598
|
-
el.appendChild(this._makeBtn(ICONS$1.deleteCode,
|
|
9310
|
+
el.appendChild(this._makeBtn(ICONS$1.deleteCode, L.deleteCodeBlock, () => this._delete(), true));
|
|
6599
9311
|
this._disposers.push(on(el, "mouseenter", () => this._clearTimers()), on(el, "mouseleave", () => this._scheduleHide()));
|
|
6600
9312
|
return el;
|
|
6601
9313
|
}
|
|
@@ -6672,7 +9384,7 @@
|
|
|
6672
9384
|
if (!this._activePre || !this._wrapBtn) return;
|
|
6673
9385
|
const wrapped = (this._activePre.style.whiteSpace || "").includes("pre-wrap") || window.getComputedStyle(this._activePre).whiteSpace === "pre-wrap";
|
|
6674
9386
|
this._wrapBtn.classList.toggle("active", wrapped);
|
|
6675
|
-
this._wrapBtn.title = wrapped ?
|
|
9387
|
+
this._wrapBtn.title = wrapped ? this.context.locale.tooltips.code.disableWordWrap : this.context.locale.tooltips.code.enableWordWrap;
|
|
6676
9388
|
}
|
|
6677
9389
|
_syncLangSelect() {
|
|
6678
9390
|
if (!this._activePre || !this._langSelect) return;
|
|
@@ -9202,27 +11914,28 @@
|
|
|
9202
11914
|
this._open();
|
|
9203
11915
|
}
|
|
9204
11916
|
_buildDialog() {
|
|
11917
|
+
const L = this.context.locale.emojiDialog;
|
|
9205
11918
|
const overlay = createElement("div", {
|
|
9206
11919
|
class: "an-dialog-overlay",
|
|
9207
11920
|
role: "dialog",
|
|
9208
11921
|
"aria-modal": "true",
|
|
9209
|
-
"aria-label":
|
|
11922
|
+
"aria-label": L.ariaLabel
|
|
9210
11923
|
});
|
|
9211
11924
|
const box = createElement("div", { class: "an-dialog-box an-emoji-box" });
|
|
9212
11925
|
const titleRow = createElement("div", { class: "an-icon-title-row" });
|
|
9213
11926
|
const title = createElement("h3", { class: "an-dialog-title" });
|
|
9214
|
-
title.textContent =
|
|
11927
|
+
title.textContent = L.title;
|
|
9215
11928
|
const closeBtn = createElement("button", {
|
|
9216
11929
|
type: "button",
|
|
9217
11930
|
class: "an-icon-close",
|
|
9218
|
-
"aria-label":
|
|
11931
|
+
"aria-label": L.close
|
|
9219
11932
|
});
|
|
9220
11933
|
closeBtn.innerHTML = "×";
|
|
9221
11934
|
titleRow.append(title, closeBtn);
|
|
9222
11935
|
const searchInput = createElement("input", {
|
|
9223
11936
|
type: "search",
|
|
9224
11937
|
class: "an-input an-icon-search",
|
|
9225
|
-
placeholder:
|
|
11938
|
+
placeholder: L.searchPlaceholder,
|
|
9226
11939
|
autocomplete: "off"
|
|
9227
11940
|
});
|
|
9228
11941
|
this._searchInput = searchInput;
|
|
@@ -9232,7 +11945,7 @@
|
|
|
9232
11945
|
class: "an-icon-cat active",
|
|
9233
11946
|
"data-cat": "all"
|
|
9234
11947
|
});
|
|
9235
|
-
allTab.textContent =
|
|
11948
|
+
allTab.textContent = L.all;
|
|
9236
11949
|
catBar.appendChild(allTab);
|
|
9237
11950
|
EMOJI_CATS.forEach(({ id, label }) => {
|
|
9238
11951
|
const tab = createElement("button", {
|
|
@@ -9240,7 +11953,7 @@
|
|
|
9240
11953
|
class: "an-icon-cat",
|
|
9241
11954
|
"data-cat": id
|
|
9242
11955
|
});
|
|
9243
|
-
tab.textContent = label;
|
|
11956
|
+
tab.textContent = L.categories && L.categories[id] || label;
|
|
9244
11957
|
catBar.appendChild(tab);
|
|
9245
11958
|
});
|
|
9246
11959
|
this._catBar = catBar;
|
|
@@ -9263,7 +11976,7 @@
|
|
|
9263
11976
|
type: "button",
|
|
9264
11977
|
class: "an-btn"
|
|
9265
11978
|
});
|
|
9266
|
-
cancelBtn.textContent =
|
|
11979
|
+
cancelBtn.textContent = L.cancelBtn;
|
|
9267
11980
|
btnRow.appendChild(cancelBtn);
|
|
9268
11981
|
box.append(titleRow, searchInput, catBar, grid, btnRow);
|
|
9269
11982
|
overlay.appendChild(box);
|
|
@@ -9674,27 +12387,28 @@
|
|
|
9674
12387
|
this._open();
|
|
9675
12388
|
}
|
|
9676
12389
|
_buildDialog() {
|
|
12390
|
+
const L = this.context.locale.iconDialog;
|
|
9677
12391
|
const overlay = createElement("div", {
|
|
9678
12392
|
class: "an-dialog-overlay",
|
|
9679
12393
|
role: "dialog",
|
|
9680
12394
|
"aria-modal": "true",
|
|
9681
|
-
"aria-label":
|
|
12395
|
+
"aria-label": L.ariaLabel
|
|
9682
12396
|
});
|
|
9683
12397
|
const box = createElement("div", { class: "an-dialog-box an-icon-box" });
|
|
9684
12398
|
const titleRow = createElement("div", { class: "an-icon-title-row" });
|
|
9685
12399
|
const title = createElement("h3", { class: "an-dialog-title" });
|
|
9686
|
-
title.textContent =
|
|
12400
|
+
title.textContent = L.title;
|
|
9687
12401
|
const closeBtn = createElement("button", {
|
|
9688
12402
|
type: "button",
|
|
9689
12403
|
class: "an-icon-close",
|
|
9690
|
-
"aria-label":
|
|
12404
|
+
"aria-label": L.close
|
|
9691
12405
|
});
|
|
9692
12406
|
closeBtn.innerHTML = "×";
|
|
9693
12407
|
titleRow.append(title, closeBtn);
|
|
9694
12408
|
const searchInput = createElement("input", {
|
|
9695
12409
|
type: "search",
|
|
9696
12410
|
class: "an-input an-icon-search",
|
|
9697
|
-
placeholder:
|
|
12411
|
+
placeholder: L.searchPlaceholder,
|
|
9698
12412
|
autocomplete: "off"
|
|
9699
12413
|
});
|
|
9700
12414
|
this._searchInput = searchInput;
|
|
@@ -9704,7 +12418,7 @@
|
|
|
9704
12418
|
class: "an-icon-cat active",
|
|
9705
12419
|
"data-cat": "all"
|
|
9706
12420
|
});
|
|
9707
|
-
allTab.textContent =
|
|
12421
|
+
allTab.textContent = L.all;
|
|
9708
12422
|
catBar.appendChild(allTab);
|
|
9709
12423
|
ICON_CATEGORIES.forEach(({ id, label }) => {
|
|
9710
12424
|
const tab = createElement("button", {
|
|
@@ -9712,7 +12426,7 @@
|
|
|
9712
12426
|
class: "an-icon-cat",
|
|
9713
12427
|
"data-cat": id
|
|
9714
12428
|
});
|
|
9715
|
-
tab.textContent = label;
|
|
12429
|
+
tab.textContent = L.categories && L.categories[id] || label;
|
|
9716
12430
|
catBar.appendChild(tab);
|
|
9717
12431
|
});
|
|
9718
12432
|
this._catBar = catBar;
|
|
@@ -9737,7 +12451,7 @@
|
|
|
9737
12451
|
this._grid = grid;
|
|
9738
12452
|
const optRow = createElement("div", { class: "an-icon-options" });
|
|
9739
12453
|
const styleLabel = createElement("label", { class: "an-label" });
|
|
9740
|
-
styleLabel.textContent =
|
|
12454
|
+
styleLabel.textContent = L.style;
|
|
9741
12455
|
const styleSelect = createElement("select", { class: "an-input an-icon-option-select" });
|
|
9742
12456
|
[
|
|
9743
12457
|
["fa-solid", "Solid"],
|
|
@@ -9751,7 +12465,7 @@
|
|
|
9751
12465
|
styleSelect.value = "fa-solid";
|
|
9752
12466
|
this._styleSelect = styleSelect;
|
|
9753
12467
|
const sizeLabel = createElement("label", { class: "an-label" });
|
|
9754
|
-
sizeLabel.textContent =
|
|
12468
|
+
sizeLabel.textContent = L.size;
|
|
9755
12469
|
const sizeSelect = createElement("select", { class: "an-input an-icon-option-select" });
|
|
9756
12470
|
[
|
|
9757
12471
|
["", "Inherit"],
|
|
@@ -9769,7 +12483,7 @@
|
|
|
9769
12483
|
});
|
|
9770
12484
|
this._sizeSelect = sizeSelect;
|
|
9771
12485
|
const colorLabel = createElement("label", { class: "an-label" });
|
|
9772
|
-
colorLabel.textContent =
|
|
12486
|
+
colorLabel.textContent = L.color;
|
|
9773
12487
|
const colorInput = createElement("input", {
|
|
9774
12488
|
type: "color",
|
|
9775
12489
|
class: "an-icon-color",
|
|
@@ -9782,11 +12496,11 @@
|
|
|
9782
12496
|
checked: ""
|
|
9783
12497
|
});
|
|
9784
12498
|
this._useColorCb = useColorCb;
|
|
9785
|
-
useColorLabel.append(useColorCb, document.createTextNode(
|
|
12499
|
+
useColorLabel.append(useColorCb, document.createTextNode(L.useColor));
|
|
9786
12500
|
optRow.append(styleLabel, styleSelect, sizeLabel, sizeSelect, colorLabel, colorInput, useColorLabel);
|
|
9787
12501
|
const preview = createElement("div", { class: "an-icon-preview" });
|
|
9788
12502
|
const previewHint = createElement("span", { class: "an-icon-preview-hint" });
|
|
9789
|
-
previewHint.textContent =
|
|
12503
|
+
previewHint.textContent = L.selectHint;
|
|
9790
12504
|
preview.appendChild(previewHint);
|
|
9791
12505
|
this._preview = preview;
|
|
9792
12506
|
const btnRow = createElement("div", { class: "an-dialog-actions" });
|
|
@@ -9795,12 +12509,12 @@
|
|
|
9795
12509
|
class: "an-btn an-btn-primary",
|
|
9796
12510
|
disabled: ""
|
|
9797
12511
|
});
|
|
9798
|
-
insertBtn.textContent =
|
|
12512
|
+
insertBtn.textContent = L.insertBtn;
|
|
9799
12513
|
const cancelBtn = createElement("button", {
|
|
9800
12514
|
type: "button",
|
|
9801
12515
|
class: "an-btn"
|
|
9802
12516
|
});
|
|
9803
|
-
cancelBtn.textContent =
|
|
12517
|
+
cancelBtn.textContent = L.cancelBtn;
|
|
9804
12518
|
btnRow.append(insertBtn, cancelBtn);
|
|
9805
12519
|
this._insertBtn = insertBtn;
|
|
9806
12520
|
box.append(titleRow, searchInput, catBar, grid, optRow, preview, btnRow);
|
|
@@ -10001,9 +12715,11 @@
|
|
|
10001
12715
|
];
|
|
10002
12716
|
function makeColorSubItems(colorType) {
|
|
10003
12717
|
const label = colorType === "foreColor" ? "Text Color" : "Highlight Color";
|
|
12718
|
+
const localeKey = colorType === "foreColor" ? "textColor" : "highlightColor";
|
|
10004
12719
|
return () => [{
|
|
10005
12720
|
back: true,
|
|
10006
12721
|
label,
|
|
12722
|
+
localeKey,
|
|
10007
12723
|
navigate: () => defaultItems
|
|
10008
12724
|
}, {
|
|
10009
12725
|
colorPalette: true,
|
|
@@ -10200,7 +12916,8 @@
|
|
|
10200
12916
|
});
|
|
10201
12917
|
iconSpan.innerHTML = ICONS.back;
|
|
10202
12918
|
backBtn.appendChild(iconSpan);
|
|
10203
|
-
|
|
12919
|
+
const backLabel = it.localeKey && this.context.locale.contextMenu[it.localeKey] || it.label || this.context.locale.contextMenu.back || "Back";
|
|
12920
|
+
backBtn.appendChild(createElement("span", { class: "an-context-label" }, [backLabel]));
|
|
10204
12921
|
const off = on(backBtn, "click", (e) => {
|
|
10205
12922
|
e.stopPropagation();
|
|
10206
12923
|
const curLeft = parseFloat(this.el.style.left);
|
|
@@ -10238,7 +12955,7 @@
|
|
|
10238
12955
|
iconSpan.innerHTML = it.icon;
|
|
10239
12956
|
btn.appendChild(iconSpan);
|
|
10240
12957
|
}
|
|
10241
|
-
btn.appendChild(createElement("span", { class: "an-context-label" }, [it.label || it.name]));
|
|
12958
|
+
btn.appendChild(createElement("span", { class: "an-context-label" }, [this.context.locale.contextMenu[it.name] || it.label || it.name]));
|
|
10242
12959
|
const chevron = createElement("span", {
|
|
10243
12960
|
class: "an-context-chevron",
|
|
10244
12961
|
"aria-hidden": "true"
|
|
@@ -10276,9 +12993,9 @@
|
|
|
10276
12993
|
if (it.colorType === "hiliteColor") {
|
|
10277
12994
|
const noColor = createElement("div", {
|
|
10278
12995
|
class: "an-context-color-swatch an-context-color-none",
|
|
10279
|
-
title: "No highlight",
|
|
12996
|
+
title: this.context.locale.contextMenu.noHighlight || "No highlight",
|
|
10280
12997
|
role: "button",
|
|
10281
|
-
"aria-label": "No highlight"
|
|
12998
|
+
"aria-label": this.context.locale.contextMenu.noHighlight || "No highlight"
|
|
10282
12999
|
});
|
|
10283
13000
|
noColor.innerHTML = ICONS.noColor;
|
|
10284
13001
|
const offNo = on(noColor, "click", (e) => {
|
|
@@ -10293,10 +13010,10 @@
|
|
|
10293
13010
|
const colorInput = createElement("input", {
|
|
10294
13011
|
type: "color",
|
|
10295
13012
|
value: it.colorType === "foreColor" ? "#000000" : "#ffff00",
|
|
10296
|
-
title: "Custom color",
|
|
10297
|
-
"aria-label": "Custom color"
|
|
13013
|
+
title: this.context.locale.contextMenu.customColor || "Custom color",
|
|
13014
|
+
"aria-label": this.context.locale.contextMenu.customColor || "Custom color"
|
|
10298
13015
|
});
|
|
10299
|
-
const customLabel = createElement("span", {}, ["Custom…"]);
|
|
13016
|
+
const customLabel = createElement("span", {}, [this.context.locale.contextMenu.customColorLabel || "Custom…"]);
|
|
10300
13017
|
const offCustom = on(colorInput, "change", () => this._applyColor(it.colorType, colorInput.value));
|
|
10301
13018
|
this._menuDisposers.push(offCustom);
|
|
10302
13019
|
customRow.appendChild(colorInput);
|
|
@@ -10320,7 +13037,7 @@
|
|
|
10320
13037
|
iconSpan.innerHTML = it.icon;
|
|
10321
13038
|
headerBtn.appendChild(iconSpan);
|
|
10322
13039
|
}
|
|
10323
|
-
headerBtn.appendChild(createElement("span", { class: "an-context-label" }, [it.label || "Insert Table"]));
|
|
13040
|
+
headerBtn.appendChild(createElement("span", { class: "an-context-label" }, [this.context.locale.contextMenu.table || it.label || "Insert Table"]));
|
|
10324
13041
|
const chevron = createElement("span", {
|
|
10325
13042
|
class: "an-context-chevron",
|
|
10326
13043
|
"aria-hidden": "true"
|
|
@@ -10349,7 +13066,7 @@
|
|
|
10349
13066
|
cells.forEach((cell) => {
|
|
10350
13067
|
cell.classList.toggle("active", +cell.dataset.row <= rows && +cell.dataset.col <= cols);
|
|
10351
13068
|
});
|
|
10352
|
-
labelEl.textContent = rows && cols ? `${cols} × ${rows}` : "Insert Table";
|
|
13069
|
+
labelEl.textContent = rows && cols ? `${cols} × ${rows}` : this.context.locale.contextMenu.table || "Insert Table";
|
|
10353
13070
|
};
|
|
10354
13071
|
panel.appendChild(gridEl);
|
|
10355
13072
|
panel.appendChild(labelEl);
|
|
@@ -10403,7 +13120,7 @@
|
|
|
10403
13120
|
iconSpan.innerHTML = it.icon;
|
|
10404
13121
|
btn.appendChild(iconSpan);
|
|
10405
13122
|
}
|
|
10406
|
-
btn.appendChild(createElement("span", { class: "an-context-label" }, [it.label || it.name]));
|
|
13123
|
+
btn.appendChild(createElement("span", { class: "an-context-label" }, [this.context.locale.contextMenu[it.name] || it.label || it.name]));
|
|
10407
13124
|
const off = on(btn, "click", (e) => {
|
|
10408
13125
|
e.stopPropagation();
|
|
10409
13126
|
this.hide();
|
|
@@ -10423,12 +13140,18 @@
|
|
|
10423
13140
|
if (!editable.contains(event.target)) return;
|
|
10424
13141
|
if (this.context.layoutInfo.container.classList.contains("an-disabled")) return;
|
|
10425
13142
|
event.preventDefault();
|
|
10426
|
-
this._lastX = event.clientX;
|
|
10427
|
-
this._lastY = event.clientY;
|
|
10428
13143
|
const winSel = window.getSelection();
|
|
10429
13144
|
this._savedRange = winSel && winSel.rangeCount > 0 ? winSel.getRangeAt(0).cloneRange() : null;
|
|
10430
13145
|
this._renderItems(this._items);
|
|
10431
|
-
|
|
13146
|
+
let openX = event.clientX;
|
|
13147
|
+
let openY = event.clientY;
|
|
13148
|
+
if (this._savedRange && !this._savedRange.collapsed) try {
|
|
13149
|
+
const selRect = this._savedRange.getBoundingClientRect();
|
|
13150
|
+
if (selRect.width > 0 && selRect.height > 0) openY = selRect.bottom + 4;
|
|
13151
|
+
} catch (_) {}
|
|
13152
|
+
this._lastX = openX;
|
|
13153
|
+
this._lastY = openY;
|
|
13154
|
+
this.showAt(openX, openY);
|
|
10432
13155
|
}
|
|
10433
13156
|
_maybeHide(event) {
|
|
10434
13157
|
if (!this.el) return;
|
|
@@ -10439,28 +13162,20 @@
|
|
|
10439
13162
|
this.el.style.display = "block";
|
|
10440
13163
|
this._reposition(x, y);
|
|
10441
13164
|
this.el.setAttribute("aria-hidden", "false");
|
|
13165
|
+
this.context.triggerEvent("contextMenu:show");
|
|
10442
13166
|
}
|
|
10443
13167
|
_reposition(x, y) {
|
|
10444
13168
|
if (!this.el) return;
|
|
10445
13169
|
const rx = x !== void 0 ? x : this._lastX;
|
|
10446
13170
|
const ry = y !== void 0 ? y : this._lastY;
|
|
10447
|
-
const
|
|
13171
|
+
const w = this.el.offsetWidth;
|
|
13172
|
+
const h = this.el.offsetHeight;
|
|
10448
13173
|
let left = rx;
|
|
10449
13174
|
let top = ry;
|
|
10450
|
-
if (left +
|
|
13175
|
+
if (left + w > window.innerWidth - 8) left = window.innerWidth - w - 8;
|
|
10451
13176
|
if (left < 8) left = 8;
|
|
10452
|
-
if (top +
|
|
13177
|
+
if (top + h > window.innerHeight - 8) top = window.innerHeight - h - 8;
|
|
10453
13178
|
if (top < 8) top = 8;
|
|
10454
|
-
if (this._savedRange) try {
|
|
10455
|
-
const sel = this._savedRange.getBoundingClientRect();
|
|
10456
|
-
if (sel.width > 0 || sel.height > 0) {
|
|
10457
|
-
if (top < sel.bottom && top + rect.height > sel.top && left < sel.right && left + rect.width > sel.left) {
|
|
10458
|
-
const belowTop = sel.bottom + 6;
|
|
10459
|
-
if (belowTop + rect.height <= window.innerHeight - 8) top = belowTop;
|
|
10460
|
-
else top = Math.max(8, sel.top - rect.height - 6);
|
|
10461
|
-
}
|
|
10462
|
-
}
|
|
10463
|
-
} catch (_) {}
|
|
10464
13179
|
this.el.style.left = `${left}px`;
|
|
10465
13180
|
this.el.style.top = `${top}px`;
|
|
10466
13181
|
}
|
|
@@ -10468,6 +13183,7 @@
|
|
|
10468
13183
|
if (!this.el) return;
|
|
10469
13184
|
this.el.style.display = "none";
|
|
10470
13185
|
this.el.setAttribute("aria-hidden", "true");
|
|
13186
|
+
this.context.triggerEvent("contextMenu:hide");
|
|
10471
13187
|
}
|
|
10472
13188
|
/** Read the current selection's text or highlight color for the strip.
|
|
10473
13189
|
* @param {'foreColor'|'hiliteColor'} type
|
|
@@ -10717,22 +13433,22 @@
|
|
|
10717
13433
|
class: "an-dialog-overlay",
|
|
10718
13434
|
role: "dialog",
|
|
10719
13435
|
"aria-modal": "true",
|
|
10720
|
-
"aria-label":
|
|
13436
|
+
"aria-label": this.context.locale.shortcutsDialog.ariaLabel
|
|
10721
13437
|
});
|
|
10722
13438
|
const box = createElement("div", { class: "an-dialog-box an-shortcuts-box" });
|
|
10723
13439
|
const titleRow = createElement("div", { class: "an-icon-title-row" });
|
|
10724
13440
|
const title = createElement("h3", { class: "an-dialog-title" });
|
|
10725
|
-
title.textContent =
|
|
13441
|
+
title.textContent = this.context.locale.shortcutsDialog.title;
|
|
10726
13442
|
const closeBtn = createElement("button", {
|
|
10727
13443
|
type: "button",
|
|
10728
13444
|
class: "an-icon-close",
|
|
10729
|
-
"aria-label":
|
|
13445
|
+
"aria-label": this.context.locale.shortcutsDialog.close
|
|
10730
13446
|
});
|
|
10731
13447
|
closeBtn.textContent = "×";
|
|
10732
13448
|
this._closeBtn = closeBtn;
|
|
10733
13449
|
titleRow.append(title, closeBtn);
|
|
10734
13450
|
box.appendChild(titleRow);
|
|
10735
|
-
SHORTCUTS.forEach(({ category, items }) => {
|
|
13451
|
+
(this.context.locale.shortcutsDialog.shortcuts || SHORTCUTS).forEach(({ category, items }) => {
|
|
10736
13452
|
const catEl = createElement("div", { class: "an-shortcuts-cat" });
|
|
10737
13453
|
catEl.textContent = category;
|
|
10738
13454
|
box.appendChild(catEl);
|
|
@@ -10857,25 +13573,26 @@
|
|
|
10857
13573
|
const isReplace = this._mode === "replace";
|
|
10858
13574
|
if (replaceRow) replaceRow.style.display = isReplace ? "" : "none";
|
|
10859
13575
|
if (replaceActions) replaceActions.style.display = isReplace ? "" : "none";
|
|
10860
|
-
if (title) title.textContent = isReplace ?
|
|
13576
|
+
if (title) title.textContent = isReplace ? this.context.locale.findReplace.findReplaceTitle : this.context.locale.findReplace.findTitle;
|
|
10861
13577
|
}
|
|
10862
13578
|
_buildDialog() {
|
|
13579
|
+
const L = this.context.locale.findReplace;
|
|
10863
13580
|
const overlay = createElement("div", {
|
|
10864
13581
|
class: "an-dialog-overlay an-fr-dialog",
|
|
10865
13582
|
role: "dialog",
|
|
10866
13583
|
"aria-modal": "true",
|
|
10867
|
-
"aria-label":
|
|
13584
|
+
"aria-label": L.findReplaceTitle
|
|
10868
13585
|
});
|
|
10869
13586
|
const box = createElement("div", { class: "an-dialog-box" });
|
|
10870
13587
|
const titleRow = createElement("div", { class: "an-icon-title-row" });
|
|
10871
13588
|
const title = createElement("h3", { class: "an-dialog-title" });
|
|
10872
|
-
title.textContent =
|
|
13589
|
+
title.textContent = L.findTitle;
|
|
10873
13590
|
const closeBtn = createElement("button", {
|
|
10874
13591
|
type: "button",
|
|
10875
13592
|
class: "an-icon-close",
|
|
10876
13593
|
"aria-label": "Close"
|
|
10877
13594
|
});
|
|
10878
|
-
closeBtn.textContent =
|
|
13595
|
+
closeBtn.textContent = L.close;
|
|
10879
13596
|
this._closeBtn = closeBtn;
|
|
10880
13597
|
titleRow.append(title, closeBtn);
|
|
10881
13598
|
box.appendChild(titleRow);
|
|
@@ -10883,8 +13600,8 @@
|
|
|
10883
13600
|
const findInput = createElement("input", {
|
|
10884
13601
|
type: "text",
|
|
10885
13602
|
class: "an-input",
|
|
10886
|
-
placeholder:
|
|
10887
|
-
"aria-label":
|
|
13603
|
+
placeholder: L.findPlaceholder,
|
|
13604
|
+
"aria-label": L.searchAriaLabel
|
|
10888
13605
|
});
|
|
10889
13606
|
this._findInput = findInput;
|
|
10890
13607
|
findRow.appendChild(findInput);
|
|
@@ -10896,7 +13613,7 @@
|
|
|
10896
13613
|
"aria-label": "Case sensitive"
|
|
10897
13614
|
});
|
|
10898
13615
|
this._caseCheckbox = caseCheckbox;
|
|
10899
|
-
caseLabel.append(caseCheckbox, document.createTextNode(
|
|
13616
|
+
caseLabel.append(caseCheckbox, document.createTextNode(L.caseSensitive));
|
|
10900
13617
|
const counter = createElement("span", { class: "an-fr-counter" });
|
|
10901
13618
|
this._counterEl = counter;
|
|
10902
13619
|
optRow.append(caseLabel, counter);
|
|
@@ -10906,12 +13623,12 @@
|
|
|
10906
13623
|
type: "button",
|
|
10907
13624
|
class: "an-btn"
|
|
10908
13625
|
});
|
|
10909
|
-
prevBtn.textContent =
|
|
13626
|
+
prevBtn.textContent = L.prevBtn;
|
|
10910
13627
|
const nextBtn = createElement("button", {
|
|
10911
13628
|
type: "button",
|
|
10912
13629
|
class: "an-btn an-btn-primary"
|
|
10913
13630
|
});
|
|
10914
|
-
nextBtn.textContent =
|
|
13631
|
+
nextBtn.textContent = L.nextBtn;
|
|
10915
13632
|
findActions.append(prevBtn, nextBtn);
|
|
10916
13633
|
box.appendChild(findActions);
|
|
10917
13634
|
const replaceRow = createElement("div", { class: "an-fr-replace-row" });
|
|
@@ -10919,8 +13636,8 @@
|
|
|
10919
13636
|
const replaceInput = createElement("input", {
|
|
10920
13637
|
type: "text",
|
|
10921
13638
|
class: "an-input",
|
|
10922
|
-
placeholder:
|
|
10923
|
-
"aria-label":
|
|
13639
|
+
placeholder: L.replacePlaceholder,
|
|
13640
|
+
"aria-label": L.replaceAriaLabel
|
|
10924
13641
|
});
|
|
10925
13642
|
this._replaceInput = replaceInput;
|
|
10926
13643
|
replaceRow.appendChild(replaceInput);
|
|
@@ -10931,12 +13648,12 @@
|
|
|
10931
13648
|
type: "button",
|
|
10932
13649
|
class: "an-btn"
|
|
10933
13650
|
});
|
|
10934
|
-
replaceBtn.textContent =
|
|
13651
|
+
replaceBtn.textContent = L.replaceBtn;
|
|
10935
13652
|
const replaceAllBtn = createElement("button", {
|
|
10936
13653
|
type: "button",
|
|
10937
13654
|
class: "an-btn an-btn-primary"
|
|
10938
13655
|
});
|
|
10939
|
-
replaceAllBtn.textContent =
|
|
13656
|
+
replaceAllBtn.textContent = L.replaceAllBtn;
|
|
10940
13657
|
replaceActions.append(replaceBtn, replaceAllBtn);
|
|
10941
13658
|
box.appendChild(replaceActions);
|
|
10942
13659
|
overlay.appendChild(box);
|
|
@@ -11581,6 +14298,771 @@
|
|
|
11581
14298
|
}
|
|
11582
14299
|
};
|
|
11583
14300
|
//#endregion
|
|
14301
|
+
//#region src/js/module/AutoSaveRestore.js
|
|
14302
|
+
/**
|
|
14303
|
+
* AutoSaveRestore.js — Detects a previously auto-saved draft and offers the
|
|
14304
|
+
* user a banner to restore or discard it.
|
|
14305
|
+
*
|
|
14306
|
+
* Activated when both `autoSave` and `autoSaveRestore` options are true.
|
|
14307
|
+
* On initialize it checks localStorage for a draft that is within the
|
|
14308
|
+
* `autoSaveRestoreTimeout` day window. If one is found a dismissible banner
|
|
14309
|
+
* is prepended to the editor container.
|
|
14310
|
+
*/
|
|
14311
|
+
var AutoSaveRestore = class {
|
|
14312
|
+
/** @param {import('../Context.js').Context} context */
|
|
14313
|
+
constructor(context) {
|
|
14314
|
+
this.context = context;
|
|
14315
|
+
this.options = context.options;
|
|
14316
|
+
/** @type {HTMLElement|null} */
|
|
14317
|
+
this._banner = null;
|
|
14318
|
+
}
|
|
14319
|
+
initialize() {
|
|
14320
|
+
if (!this.options.autoSave || !this.options.autoSaveRestore) return this;
|
|
14321
|
+
const key = this.options.autoSaveKey;
|
|
14322
|
+
const metaKey = key + ":asrmeta";
|
|
14323
|
+
let saved;
|
|
14324
|
+
let meta;
|
|
14325
|
+
try {
|
|
14326
|
+
saved = localStorage.getItem(key);
|
|
14327
|
+
meta = JSON.parse(localStorage.getItem(metaKey) || "{}");
|
|
14328
|
+
} catch (_) {
|
|
14329
|
+
return this;
|
|
14330
|
+
}
|
|
14331
|
+
if (!saved) return this;
|
|
14332
|
+
const timeout = this.options.autoSaveRestoreTimeout;
|
|
14333
|
+
if (timeout > 0) {
|
|
14334
|
+
if (Date.now() - (meta.savedAt || 0) > timeout * 864e5) {
|
|
14335
|
+
try {
|
|
14336
|
+
localStorage.removeItem(key);
|
|
14337
|
+
localStorage.removeItem(metaKey);
|
|
14338
|
+
} catch (_) {}
|
|
14339
|
+
return this;
|
|
14340
|
+
}
|
|
14341
|
+
}
|
|
14342
|
+
this._showBanner(saved, meta);
|
|
14343
|
+
return this;
|
|
14344
|
+
}
|
|
14345
|
+
destroy() {
|
|
14346
|
+
this._removeBanner();
|
|
14347
|
+
}
|
|
14348
|
+
_showBanner(draftHtml, meta) {
|
|
14349
|
+
const t = this.context.locale.autoSaveRestore || {};
|
|
14350
|
+
const label = t.found || "Draft found. Restore?";
|
|
14351
|
+
const restoreLabel = t.restore || "Restore";
|
|
14352
|
+
const discardLabel = t.discard || "Discard";
|
|
14353
|
+
const banner = document.createElement("div");
|
|
14354
|
+
banner.className = "an-asr-banner";
|
|
14355
|
+
banner.setAttribute("role", "alert");
|
|
14356
|
+
const msg = document.createElement("span");
|
|
14357
|
+
msg.className = "an-asr-msg";
|
|
14358
|
+
if (meta.savedAt) {
|
|
14359
|
+
const formatted = new Date(meta.savedAt).toLocaleString();
|
|
14360
|
+
msg.textContent = (t.foundAt || "Draft from {date}. Restore?").replace("{date}", formatted);
|
|
14361
|
+
} else msg.textContent = label;
|
|
14362
|
+
const restoreBtn = document.createElement("button");
|
|
14363
|
+
restoreBtn.type = "button";
|
|
14364
|
+
restoreBtn.className = "an-btn an-asr-btn-restore";
|
|
14365
|
+
restoreBtn.textContent = restoreLabel;
|
|
14366
|
+
restoreBtn.addEventListener("click", () => this._restore(draftHtml));
|
|
14367
|
+
const discardBtn = document.createElement("button");
|
|
14368
|
+
discardBtn.type = "button";
|
|
14369
|
+
discardBtn.className = "an-btn an-asr-btn-discard";
|
|
14370
|
+
discardBtn.textContent = discardLabel;
|
|
14371
|
+
discardBtn.addEventListener("click", () => this._discard());
|
|
14372
|
+
banner.appendChild(msg);
|
|
14373
|
+
banner.appendChild(restoreBtn);
|
|
14374
|
+
banner.appendChild(discardBtn);
|
|
14375
|
+
this._banner = banner;
|
|
14376
|
+
const container = this.context.layoutInfo.container;
|
|
14377
|
+
container.insertBefore(banner, container.firstChild);
|
|
14378
|
+
}
|
|
14379
|
+
_restore(draftHtml) {
|
|
14380
|
+
this.context.setHTML(draftHtml);
|
|
14381
|
+
this.context.clearHistory();
|
|
14382
|
+
this._removeBanner();
|
|
14383
|
+
if (typeof this.options.onAutoSaveRestore === "function") this.options.onAutoSaveRestore(draftHtml, this.context);
|
|
14384
|
+
}
|
|
14385
|
+
_discard() {
|
|
14386
|
+
const key = this.options.autoSaveKey;
|
|
14387
|
+
try {
|
|
14388
|
+
localStorage.removeItem(key);
|
|
14389
|
+
localStorage.removeItem(key + ":asrmeta");
|
|
14390
|
+
} catch (_) {}
|
|
14391
|
+
this._removeBanner();
|
|
14392
|
+
}
|
|
14393
|
+
_removeBanner() {
|
|
14394
|
+
if (this._banner && this._banner.parentNode) this._banner.parentNode.removeChild(this._banner);
|
|
14395
|
+
this._banner = null;
|
|
14396
|
+
}
|
|
14397
|
+
};
|
|
14398
|
+
//#endregion
|
|
14399
|
+
//#region src/js/module/MarkdownShortcuts.js
|
|
14400
|
+
/**
|
|
14401
|
+
* MarkdownShortcuts.js — Convert Markdown-style syntax typed directly in the
|
|
14402
|
+
* editor into rich HTML elements (input rules / auto-format).
|
|
14403
|
+
*
|
|
14404
|
+
* Activated when `markdownShortcuts: true` (the default).
|
|
14405
|
+
*
|
|
14406
|
+
* Block rules — triggered by Space or Enter at the start of a line:
|
|
14407
|
+
* #[#[#]]· → H1 / H2 / H3
|
|
14408
|
+
* >· → blockquote
|
|
14409
|
+
* -· or *· → unordered list item
|
|
14410
|
+
* 1.· → ordered list item
|
|
14411
|
+
* [ ]· → checklist item
|
|
14412
|
+
* --- → horizontal rule (on Enter)
|
|
14413
|
+
* ``` → code block (on Enter)
|
|
14414
|
+
*
|
|
14415
|
+
* Inline rules — triggered when the closing marker is typed:
|
|
14416
|
+
* **text** → <strong>
|
|
14417
|
+
* *text* → <em>
|
|
14418
|
+
* ~~text~~ → <s>
|
|
14419
|
+
* `code` → <code>
|
|
14420
|
+
*/
|
|
14421
|
+
var MarkdownShortcuts = class {
|
|
14422
|
+
/** @param {import('../Context.js').Context} context */
|
|
14423
|
+
constructor(context) {
|
|
14424
|
+
this.context = context;
|
|
14425
|
+
this.options = context.options;
|
|
14426
|
+
this._disposers = [];
|
|
14427
|
+
}
|
|
14428
|
+
initialize() {
|
|
14429
|
+
if (!this.options.markdownShortcuts) return this;
|
|
14430
|
+
const editable = this.context.layoutInfo.editable;
|
|
14431
|
+
const d1 = on(
|
|
14432
|
+
editable,
|
|
14433
|
+
"keydown",
|
|
14434
|
+
/** @param {KeyboardEvent} e */
|
|
14435
|
+
(e) => this._onKeydown(e)
|
|
14436
|
+
);
|
|
14437
|
+
const d2 = on(editable, "input", () => this._onInput());
|
|
14438
|
+
this._disposers.push(d1, d2);
|
|
14439
|
+
return this;
|
|
14440
|
+
}
|
|
14441
|
+
destroy() {
|
|
14442
|
+
this._disposers.forEach((d) => d());
|
|
14443
|
+
this._disposers = [];
|
|
14444
|
+
}
|
|
14445
|
+
_onKeydown(e) {
|
|
14446
|
+
if (e.key === " ") {
|
|
14447
|
+
if (this._applyBlockRule()) e.preventDefault();
|
|
14448
|
+
} else if (e.key === "Enter") {
|
|
14449
|
+
if (this._applyEnterRule()) e.preventDefault();
|
|
14450
|
+
}
|
|
14451
|
+
}
|
|
14452
|
+
/**
|
|
14453
|
+
* Returns the plain text of the line the cursor is on, up to the cursor.
|
|
14454
|
+
* @returns {{ text: string, range: Range, lineNode: Node } | null}
|
|
14455
|
+
*/
|
|
14456
|
+
_getLineContext() {
|
|
14457
|
+
const sel = window.getSelection();
|
|
14458
|
+
if (!sel || !sel.rangeCount) return null;
|
|
14459
|
+
const range = sel.getRangeAt(0);
|
|
14460
|
+
if (!range.collapsed) return null;
|
|
14461
|
+
const editable = this.context.layoutInfo.editable;
|
|
14462
|
+
if (!editable.contains(range.startContainer)) return null;
|
|
14463
|
+
let node = range.startContainer;
|
|
14464
|
+
while (node && node !== editable && !this._isBlock(node)) node = node.parentNode;
|
|
14465
|
+
if (!node || node === editable) node = range.startContainer;
|
|
14466
|
+
const tmpRange = document.createRange();
|
|
14467
|
+
tmpRange.setStart(node, 0);
|
|
14468
|
+
tmpRange.setEnd(range.startContainer, range.startOffset);
|
|
14469
|
+
return {
|
|
14470
|
+
text: tmpRange.toString(),
|
|
14471
|
+
range,
|
|
14472
|
+
lineNode: node
|
|
14473
|
+
};
|
|
14474
|
+
}
|
|
14475
|
+
_isBlock(node) {
|
|
14476
|
+
if (node.nodeType !== Node.ELEMENT_NODE) return false;
|
|
14477
|
+
const display = window.getComputedStyle(node).display;
|
|
14478
|
+
return display === "block" || display === "list-item" || display === "table-cell";
|
|
14479
|
+
}
|
|
14480
|
+
/** Applies block rule on Space key. Returns true if a rule fired. */
|
|
14481
|
+
_applyBlockRule() {
|
|
14482
|
+
const ctx = this._getLineContext();
|
|
14483
|
+
if (!ctx) return false;
|
|
14484
|
+
const { text } = ctx;
|
|
14485
|
+
const blockPatterns = [
|
|
14486
|
+
{
|
|
14487
|
+
re: /^(#{1,3})$/,
|
|
14488
|
+
handler: (m) => this._convertToHeading(m[1].length)
|
|
14489
|
+
},
|
|
14490
|
+
{
|
|
14491
|
+
re: /^>$/,
|
|
14492
|
+
handler: () => this._convertToBlockquote()
|
|
14493
|
+
},
|
|
14494
|
+
{
|
|
14495
|
+
re: /^[-*]$/,
|
|
14496
|
+
handler: () => this._convertToList("ul")
|
|
14497
|
+
},
|
|
14498
|
+
{
|
|
14499
|
+
re: /^1\.$/,
|
|
14500
|
+
handler: () => this._convertToList("ol")
|
|
14501
|
+
},
|
|
14502
|
+
{
|
|
14503
|
+
re: /^\[ \]$/,
|
|
14504
|
+
handler: () => this._convertToChecklist()
|
|
14505
|
+
}
|
|
14506
|
+
];
|
|
14507
|
+
for (const { re, handler } of blockPatterns) {
|
|
14508
|
+
const m = text.match(re);
|
|
14509
|
+
if (m) {
|
|
14510
|
+
handler(m);
|
|
14511
|
+
return true;
|
|
14512
|
+
}
|
|
14513
|
+
}
|
|
14514
|
+
return false;
|
|
14515
|
+
}
|
|
14516
|
+
/** Applies block rule on Enter key (---, ```). Returns true if a rule fired. */
|
|
14517
|
+
_applyEnterRule() {
|
|
14518
|
+
const ctx = this._getLineContext();
|
|
14519
|
+
if (!ctx) return false;
|
|
14520
|
+
const { text } = ctx;
|
|
14521
|
+
if (/^-{3,}$/.test(text)) {
|
|
14522
|
+
this._convertToHr();
|
|
14523
|
+
return true;
|
|
14524
|
+
}
|
|
14525
|
+
if (/^`{3}/.test(text)) {
|
|
14526
|
+
this._convertToCodeBlock();
|
|
14527
|
+
return true;
|
|
14528
|
+
}
|
|
14529
|
+
return false;
|
|
14530
|
+
}
|
|
14531
|
+
_selectLineAndDelete() {
|
|
14532
|
+
const sel = window.getSelection();
|
|
14533
|
+
if (!sel || !sel.rangeCount) return;
|
|
14534
|
+
const range = sel.getRangeAt(0);
|
|
14535
|
+
const startRange = document.createRange();
|
|
14536
|
+
startRange.setStart(range.startContainer.parentNode || range.startContainer, 0);
|
|
14537
|
+
startRange.setEnd(range.startContainer, range.startOffset);
|
|
14538
|
+
startRange.deleteContents();
|
|
14539
|
+
}
|
|
14540
|
+
_convertToHeading(level) {
|
|
14541
|
+
this._selectLineAndDelete();
|
|
14542
|
+
document.execCommand("formatBlock", false, `h${level}`);
|
|
14543
|
+
this.context.triggerEvent("change", this.context.getHTML());
|
|
14544
|
+
}
|
|
14545
|
+
_convertToBlockquote() {
|
|
14546
|
+
this._selectLineAndDelete();
|
|
14547
|
+
document.execCommand("formatBlock", false, "blockquote");
|
|
14548
|
+
this.context.triggerEvent("change", this.context.getHTML());
|
|
14549
|
+
}
|
|
14550
|
+
_convertToList(type) {
|
|
14551
|
+
this._selectLineAndDelete();
|
|
14552
|
+
document.execCommand(type === "ul" ? "insertUnorderedList" : "insertOrderedList");
|
|
14553
|
+
this.context.triggerEvent("change", this.context.getHTML());
|
|
14554
|
+
}
|
|
14555
|
+
_convertToChecklist() {
|
|
14556
|
+
this._selectLineAndDelete();
|
|
14557
|
+
this.context.invoke("editor.checklist");
|
|
14558
|
+
this.context.triggerEvent("change", this.context.getHTML());
|
|
14559
|
+
}
|
|
14560
|
+
_convertToHr() {
|
|
14561
|
+
this._selectLineAndDelete();
|
|
14562
|
+
this.context.invoke("editor.insertHR");
|
|
14563
|
+
this.context.triggerEvent("change", this.context.getHTML());
|
|
14564
|
+
}
|
|
14565
|
+
_convertToCodeBlock() {
|
|
14566
|
+
this._selectLineAndDelete();
|
|
14567
|
+
document.execCommand("formatBlock", false, "pre");
|
|
14568
|
+
this.context.triggerEvent("change", this.context.getHTML());
|
|
14569
|
+
}
|
|
14570
|
+
_onInput() {
|
|
14571
|
+
const sel = window.getSelection();
|
|
14572
|
+
if (!sel || !sel.rangeCount) return;
|
|
14573
|
+
const range = sel.getRangeAt(0);
|
|
14574
|
+
if (!range.collapsed) return;
|
|
14575
|
+
if (!this.context.layoutInfo.editable.contains(range.startContainer)) return;
|
|
14576
|
+
const node = range.startContainer;
|
|
14577
|
+
if (node.nodeType !== Node.TEXT_NODE) return;
|
|
14578
|
+
const text = node.textContent;
|
|
14579
|
+
const offset = range.startOffset;
|
|
14580
|
+
const inlineRules = [
|
|
14581
|
+
{
|
|
14582
|
+
re: /\*\*(.+?)\*\*$/,
|
|
14583
|
+
tag: "strong"
|
|
14584
|
+
},
|
|
14585
|
+
{
|
|
14586
|
+
re: /(?<!\*)\*(?!\*)(.+?)(?<!\*)\*(?!\*)$/,
|
|
14587
|
+
tag: "em"
|
|
14588
|
+
},
|
|
14589
|
+
{
|
|
14590
|
+
re: /~~(.+?)~~$/,
|
|
14591
|
+
tag: "s"
|
|
14592
|
+
},
|
|
14593
|
+
{
|
|
14594
|
+
re: /`([^`]+)`$/,
|
|
14595
|
+
tag: "code"
|
|
14596
|
+
}
|
|
14597
|
+
];
|
|
14598
|
+
const upToCursor = text.slice(0, offset);
|
|
14599
|
+
for (const { re, tag } of inlineRules) {
|
|
14600
|
+
const m = upToCursor.match(re);
|
|
14601
|
+
if (!m) continue;
|
|
14602
|
+
const matchStart = upToCursor.length - m[0].length;
|
|
14603
|
+
const matchEnd = offset;
|
|
14604
|
+
const innerText = m[1];
|
|
14605
|
+
const before = text.slice(0, matchStart);
|
|
14606
|
+
const after = text.slice(matchEnd);
|
|
14607
|
+
const el = document.createElement(tag);
|
|
14608
|
+
el.textContent = innerText;
|
|
14609
|
+
const beforeNode = document.createTextNode(before);
|
|
14610
|
+
const afterNode = document.createTextNode("" + after);
|
|
14611
|
+
const parent = node.parentNode;
|
|
14612
|
+
parent.insertBefore(beforeNode, node);
|
|
14613
|
+
parent.insertBefore(el, node);
|
|
14614
|
+
parent.insertBefore(afterNode, node);
|
|
14615
|
+
parent.removeChild(node);
|
|
14616
|
+
const newRange = document.createRange();
|
|
14617
|
+
newRange.setStart(afterNode, 1);
|
|
14618
|
+
newRange.collapse(true);
|
|
14619
|
+
sel.removeAllRanges();
|
|
14620
|
+
sel.addRange(newRange);
|
|
14621
|
+
this.context.triggerEvent("change", this.context.getHTML());
|
|
14622
|
+
break;
|
|
14623
|
+
}
|
|
14624
|
+
}
|
|
14625
|
+
};
|
|
14626
|
+
//#endregion
|
|
14627
|
+
//#region src/js/module/BubbleToolbar.js
|
|
14628
|
+
/**
|
|
14629
|
+
* BubbleToolbar.js — A mini floating toolbar that appears above the current
|
|
14630
|
+
* text selection, allowing quick access to common formatting actions without
|
|
14631
|
+
* reaching for the main toolbar.
|
|
14632
|
+
*
|
|
14633
|
+
* Activated when `bubbleToolbar: true`. The set of visible buttons is
|
|
14634
|
+
* controlled by `bubbleToolbarItems` (array of button name strings).
|
|
14635
|
+
*
|
|
14636
|
+
* Built-in names: 'bold', 'italic', 'underline', 'strikethrough',
|
|
14637
|
+
* 'link', 'foreColor', 'removeFormat', 'inlineCode'.
|
|
14638
|
+
* Any name not found in the built-in map is silently ignored.
|
|
14639
|
+
*/
|
|
14640
|
+
var _S = "stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"";
|
|
14641
|
+
var _svg = (p) => `<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" ${_S} style="display:block">${p}</svg>`;
|
|
14642
|
+
var _ICONS = {
|
|
14643
|
+
bold: _svg("<path d=\"M6 4h8a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z\"/><path d=\"M6 12h9a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z\"/>"),
|
|
14644
|
+
italic: _svg("<line x1=\"19\" y1=\"4\" x2=\"10\" y2=\"4\"/><line x1=\"14\" y1=\"20\" x2=\"5\" y2=\"20\"/><line x1=\"15\" y1=\"4\" x2=\"9\" y2=\"20\"/>"),
|
|
14645
|
+
underline: _svg("<path d=\"M6 3v7a6 6 0 0 0 6 6 6 6 0 0 0 6-6V3\"/><line x1=\"4\" y1=\"21\" x2=\"20\" y2=\"21\"/>"),
|
|
14646
|
+
strikethrough: _svg("<path d=\"M17.3 12H6.7\"/><path d=\"M10 6.5C10 5.1 11.1 4 12.5 4c1.4 0 2.5 1.1 2.5 2.5 0 .8-.4 1.5-1 2\"/><path d=\"M14 17.5C14 19 12.9 20 11.5 20 10.1 20 9 18.9 9 17.5c0-.8.4-1.5 1-2\"/>"),
|
|
14647
|
+
link: _svg("<path d=\"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\"/><path d=\"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\"/>"),
|
|
14648
|
+
foreColor: _svg("<path d=\"M4 20L12 4L20 20\"/><line x1=\"7.5\" y1=\"14\" x2=\"16.5\" y2=\"14\"/>"),
|
|
14649
|
+
removeFormat: _svg("<path d=\"m7 21-4.3-4.3c-1-1-1-2.5 0-3.4l9.6-9.6c1-1 2.5-1 3.4 0l5.6 5.6c1 1 1 2.5 0 3.4L13 21\"/><path d=\"M22 21H7\"/><path d=\"m5 11 9 9\"/>"),
|
|
14650
|
+
inlineCode: _svg("<path d=\"M8 3H7a2 2 0 0 0-2 2v5a2 2 0 0 1-2 2 2 2 0 0 1 2 2v5c0 1.1.9 2 2 2h1\"/><path d=\"M16 3h1a2 2 0 0 1 2 2v5c0 1.1.9 2 2 2a2 2 0 0 1-2 2v5a2 2 0 0 1-2 2h-1\"/>")
|
|
14651
|
+
};
|
|
14652
|
+
var _ACTIONS = {
|
|
14653
|
+
bold: (ctx) => ctx.invoke("editor.bold"),
|
|
14654
|
+
italic: (ctx) => ctx.invoke("editor.italic"),
|
|
14655
|
+
underline: (ctx) => ctx.invoke("editor.underline"),
|
|
14656
|
+
strikethrough: (ctx) => ctx.invoke("editor.strikethrough"),
|
|
14657
|
+
link: (ctx) => ctx.invoke("linkDialog.show"),
|
|
14658
|
+
foreColor: (ctx) => {
|
|
14659
|
+
const color = window.prompt("Text color (hex or name):", "#000000");
|
|
14660
|
+
if (color) ctx.invoke("editor.foreColor", color);
|
|
14661
|
+
},
|
|
14662
|
+
removeFormat: (ctx) => ctx.invoke("editor.removeFormat"),
|
|
14663
|
+
inlineCode: (ctx) => ctx.invoke("editor.inlineCode")
|
|
14664
|
+
};
|
|
14665
|
+
var _ACTIVE = {
|
|
14666
|
+
bold: () => document.queryCommandState("bold"),
|
|
14667
|
+
italic: () => document.queryCommandState("italic"),
|
|
14668
|
+
underline: () => document.queryCommandState("underline"),
|
|
14669
|
+
strikethrough: () => document.queryCommandState("strikeThrough")
|
|
14670
|
+
};
|
|
14671
|
+
var BubbleToolbar = class {
|
|
14672
|
+
/** @param {import('../Context.js').Context} context */
|
|
14673
|
+
constructor(context) {
|
|
14674
|
+
this.context = context;
|
|
14675
|
+
this.options = context.options;
|
|
14676
|
+
/** @type {HTMLElement|null} */
|
|
14677
|
+
this._el = null;
|
|
14678
|
+
this._visible = false;
|
|
14679
|
+
this._rafId = null;
|
|
14680
|
+
this._contextMenuOpen = false;
|
|
14681
|
+
this._disposers = [];
|
|
14682
|
+
this._onSelectionChange = this._onSelectionChange.bind(this);
|
|
14683
|
+
this._onMousedown = this._onMousedown.bind(this);
|
|
14684
|
+
this._onKeydown = this._onKeydown.bind(this);
|
|
14685
|
+
this._onContextMenu = this._onContextMenu.bind(this);
|
|
14686
|
+
}
|
|
14687
|
+
initialize() {
|
|
14688
|
+
if (!this.options.bubbleToolbar) return this;
|
|
14689
|
+
this._build();
|
|
14690
|
+
const d1 = on(document, "selectionchange", this._onSelectionChange);
|
|
14691
|
+
const d2 = on(document, "mousedown", this._onMousedown);
|
|
14692
|
+
const d3 = on(document, "keydown", this._onKeydown);
|
|
14693
|
+
const d4 = on(document, "contextmenu", this._onContextMenu);
|
|
14694
|
+
const d5 = this.context.on("contextMenu:show", () => {
|
|
14695
|
+
this._contextMenuOpen = true;
|
|
14696
|
+
this._hide();
|
|
14697
|
+
});
|
|
14698
|
+
const d6 = this.context.on("contextMenu:hide", () => {
|
|
14699
|
+
this._contextMenuOpen = false;
|
|
14700
|
+
});
|
|
14701
|
+
this._disposers.push(d1, d2, d3, d4, d5, d6);
|
|
14702
|
+
return this;
|
|
14703
|
+
}
|
|
14704
|
+
destroy() {
|
|
14705
|
+
if (this._el && this._el.parentNode) this._el.parentNode.removeChild(this._el);
|
|
14706
|
+
this._el = null;
|
|
14707
|
+
this._disposers.forEach((d) => d());
|
|
14708
|
+
this._disposers = [];
|
|
14709
|
+
cancelAnimationFrame(this._rafId);
|
|
14710
|
+
}
|
|
14711
|
+
_build() {
|
|
14712
|
+
const el = document.createElement("div");
|
|
14713
|
+
el.className = "an-bubble-toolbar";
|
|
14714
|
+
el.setAttribute("role", "toolbar");
|
|
14715
|
+
el.setAttribute("aria-label", "Formatting");
|
|
14716
|
+
const items = this.options.bubbleToolbarItems || [
|
|
14717
|
+
"bold",
|
|
14718
|
+
"italic",
|
|
14719
|
+
"underline",
|
|
14720
|
+
"link",
|
|
14721
|
+
"foreColor",
|
|
14722
|
+
"removeFormat"
|
|
14723
|
+
];
|
|
14724
|
+
for (const name of items) {
|
|
14725
|
+
if (!_ICONS[name] || !_ACTIONS[name]) continue;
|
|
14726
|
+
const btn = document.createElement("button");
|
|
14727
|
+
btn.type = "button";
|
|
14728
|
+
btn.className = "an-bubble-btn";
|
|
14729
|
+
btn.dataset.name = name;
|
|
14730
|
+
btn.setAttribute("aria-label", name);
|
|
14731
|
+
btn.innerHTML = _ICONS[name];
|
|
14732
|
+
btn.addEventListener("mousedown", (e) => {
|
|
14733
|
+
e.preventDefault();
|
|
14734
|
+
});
|
|
14735
|
+
btn.addEventListener("click", (e) => {
|
|
14736
|
+
e.preventDefault();
|
|
14737
|
+
e.stopPropagation();
|
|
14738
|
+
this.context.invoke("editor.focus");
|
|
14739
|
+
_ACTIONS[name](this.context);
|
|
14740
|
+
this.context.invoke("editor.afterCommand");
|
|
14741
|
+
this._syncActive();
|
|
14742
|
+
});
|
|
14743
|
+
el.appendChild(btn);
|
|
14744
|
+
}
|
|
14745
|
+
document.body.appendChild(el);
|
|
14746
|
+
this._el = el;
|
|
14747
|
+
}
|
|
14748
|
+
_show(rect) {
|
|
14749
|
+
if (!this._el) return;
|
|
14750
|
+
const el = this._el;
|
|
14751
|
+
el.style.visibility = "hidden";
|
|
14752
|
+
el.style.display = "flex";
|
|
14753
|
+
const bw = el.offsetWidth;
|
|
14754
|
+
const bh = el.offsetHeight;
|
|
14755
|
+
const gap = 8;
|
|
14756
|
+
let left = rect.left + rect.width / 2 - bw / 2;
|
|
14757
|
+
let top = rect.top - bh - gap;
|
|
14758
|
+
left = Math.max(8, Math.min(left, window.innerWidth - bw - 8));
|
|
14759
|
+
if (top < 8) top = rect.bottom + gap;
|
|
14760
|
+
el.style.top = `${top}px`;
|
|
14761
|
+
el.style.left = `${left}px`;
|
|
14762
|
+
el.style.visibility = "";
|
|
14763
|
+
this._syncActive();
|
|
14764
|
+
this._visible = true;
|
|
14765
|
+
}
|
|
14766
|
+
_hide() {
|
|
14767
|
+
if (!this._el) return;
|
|
14768
|
+
this._el.style.display = "none";
|
|
14769
|
+
this._visible = false;
|
|
14770
|
+
}
|
|
14771
|
+
_syncActive() {
|
|
14772
|
+
if (!this._el) return;
|
|
14773
|
+
this._el.querySelectorAll(".an-bubble-btn").forEach((btn) => {
|
|
14774
|
+
const activeFn = _ACTIVE[btn.dataset.name];
|
|
14775
|
+
btn.classList.toggle("an-active", !!(activeFn && activeFn()));
|
|
14776
|
+
});
|
|
14777
|
+
}
|
|
14778
|
+
_onSelectionChange() {
|
|
14779
|
+
cancelAnimationFrame(this._rafId);
|
|
14780
|
+
this._rafId = requestAnimationFrame(() => {
|
|
14781
|
+
if (this._contextMenuOpen) return;
|
|
14782
|
+
const sel = window.getSelection();
|
|
14783
|
+
if (!sel || sel.isCollapsed || !sel.rangeCount) {
|
|
14784
|
+
this._hide();
|
|
14785
|
+
return;
|
|
14786
|
+
}
|
|
14787
|
+
if (!this.context.layoutInfo.editable.contains(sel.anchorNode)) {
|
|
14788
|
+
this._hide();
|
|
14789
|
+
return;
|
|
14790
|
+
}
|
|
14791
|
+
if (this.context.options.readOnly) {
|
|
14792
|
+
this._hide();
|
|
14793
|
+
return;
|
|
14794
|
+
}
|
|
14795
|
+
const rect = sel.getRangeAt(0).getBoundingClientRect();
|
|
14796
|
+
if (!rect || rect.width === 0) {
|
|
14797
|
+
this._hide();
|
|
14798
|
+
return;
|
|
14799
|
+
}
|
|
14800
|
+
this._show(rect);
|
|
14801
|
+
});
|
|
14802
|
+
}
|
|
14803
|
+
_onMousedown(e) {
|
|
14804
|
+
if (!this._visible) return;
|
|
14805
|
+
if (this._el && this._el.contains(e.target)) return;
|
|
14806
|
+
if (this.context.layoutInfo.editable.contains(e.target)) return;
|
|
14807
|
+
this._hide();
|
|
14808
|
+
}
|
|
14809
|
+
_onKeydown(e) {
|
|
14810
|
+
if (e.key === "Escape" && this._visible) this._hide();
|
|
14811
|
+
}
|
|
14812
|
+
_onContextMenu() {
|
|
14813
|
+
this._hide();
|
|
14814
|
+
}
|
|
14815
|
+
};
|
|
14816
|
+
//#endregion
|
|
14817
|
+
//#region src/js/module/Mention.js
|
|
14818
|
+
/**
|
|
14819
|
+
* Mention.js — @mention autocomplete support.
|
|
14820
|
+
*
|
|
14821
|
+
* Activated when `mention.onSearch` option is provided.
|
|
14822
|
+
*
|
|
14823
|
+
* When the user types the trigger character (default `@`) followed by at least
|
|
14824
|
+
* `mention.minChars` characters, `onSearch(query, callback)` is called.
|
|
14825
|
+
* The callback receives an array of `{ id, label, avatar? }` items which are
|
|
14826
|
+
* rendered in a floating dropdown. Selecting an item inserts a non-editable
|
|
14827
|
+
* mention chip and fires `onInsert` (if provided) to override the default HTML.
|
|
14828
|
+
*
|
|
14829
|
+
* Options shape (passed as `mention` option object):
|
|
14830
|
+
* {
|
|
14831
|
+
* trigger: '@',
|
|
14832
|
+
* minChars: 1,
|
|
14833
|
+
* maxResults: 8,
|
|
14834
|
+
* debounce: 200,
|
|
14835
|
+
* onSearch: (query, callback) => void,
|
|
14836
|
+
* onInsert: (item) => string | null,
|
|
14837
|
+
* mentionClass: 'an-mention',
|
|
14838
|
+
* allowSpaces: false,
|
|
14839
|
+
* }
|
|
14840
|
+
*/
|
|
14841
|
+
var Mention = class {
|
|
14842
|
+
/** @param {import('../Context.js').Context} context */
|
|
14843
|
+
constructor(context) {
|
|
14844
|
+
this.context = context;
|
|
14845
|
+
/** @type {HTMLElement|null} */
|
|
14846
|
+
this._dropdown = null;
|
|
14847
|
+
/** @type {string} */
|
|
14848
|
+
this._query = "";
|
|
14849
|
+
/** @type {number|null} */
|
|
14850
|
+
this._debounceTimer = null;
|
|
14851
|
+
/** @type {number} current highlighted index */
|
|
14852
|
+
this._activeIndex = -1;
|
|
14853
|
+
/** @type {Array<{id, label, avatar?}>} */
|
|
14854
|
+
this._items = [];
|
|
14855
|
+
/** @type {boolean} */
|
|
14856
|
+
this._open = false;
|
|
14857
|
+
/** Position of trigger character in the text node */
|
|
14858
|
+
this._triggerNode = null;
|
|
14859
|
+
this._triggerOffset = 0;
|
|
14860
|
+
/** @type {DOMRect|null} Caret rect captured synchronously during input event */
|
|
14861
|
+
this._caretRect = null;
|
|
14862
|
+
this._disposers = [];
|
|
14863
|
+
}
|
|
14864
|
+
initialize() {
|
|
14865
|
+
const cfg = this.context.options.mention;
|
|
14866
|
+
if (!cfg || typeof cfg.onSearch !== "function") return this;
|
|
14867
|
+
this._cfg = {
|
|
14868
|
+
trigger: cfg.trigger || "@",
|
|
14869
|
+
minChars: cfg.minChars ?? 0,
|
|
14870
|
+
maxResults: cfg.maxResults ?? 8,
|
|
14871
|
+
debounce: cfg.debounce ?? 200,
|
|
14872
|
+
onSearch: cfg.onSearch,
|
|
14873
|
+
onInsert: cfg.onInsert || null,
|
|
14874
|
+
mentionClass: cfg.mentionClass || "an-mention",
|
|
14875
|
+
allowSpaces: cfg.allowSpaces || false
|
|
14876
|
+
};
|
|
14877
|
+
this._buildDropdown();
|
|
14878
|
+
const editable = this.context.layoutInfo.editable;
|
|
14879
|
+
const d1 = on(editable, "keydown", (e) => this._onKeydown(e));
|
|
14880
|
+
const d2 = on(editable, "input", () => this._onInput());
|
|
14881
|
+
const d3 = on(document, "click", (e) => this._onDocClick(e));
|
|
14882
|
+
this._disposers.push(d1, d2, d3);
|
|
14883
|
+
return this;
|
|
14884
|
+
}
|
|
14885
|
+
destroy() {
|
|
14886
|
+
clearTimeout(this._debounceTimer);
|
|
14887
|
+
if (this._dropdown && this._dropdown.parentNode) this._dropdown.parentNode.removeChild(this._dropdown);
|
|
14888
|
+
this._dropdown = null;
|
|
14889
|
+
this._disposers.forEach((d) => d());
|
|
14890
|
+
this._disposers = [];
|
|
14891
|
+
}
|
|
14892
|
+
_buildDropdown() {
|
|
14893
|
+
const el = document.createElement("div");
|
|
14894
|
+
el.className = "an-mention-dropdown";
|
|
14895
|
+
el.setAttribute("role", "listbox");
|
|
14896
|
+
document.body.appendChild(el);
|
|
14897
|
+
this._dropdown = el;
|
|
14898
|
+
}
|
|
14899
|
+
_renderItems(items) {
|
|
14900
|
+
const dd = this._dropdown;
|
|
14901
|
+
dd.innerHTML = "";
|
|
14902
|
+
this._items = items.slice(0, this._cfg.maxResults);
|
|
14903
|
+
this._activeIndex = this._items.length > 0 ? 0 : -1;
|
|
14904
|
+
this._items.forEach((item, i) => {
|
|
14905
|
+
const li = document.createElement("div");
|
|
14906
|
+
li.className = "an-mention-item";
|
|
14907
|
+
li.setAttribute("role", "option");
|
|
14908
|
+
li.dataset.index = i;
|
|
14909
|
+
if (item.avatar) {
|
|
14910
|
+
const img = document.createElement("img");
|
|
14911
|
+
img.src = item.avatar;
|
|
14912
|
+
img.className = "an-mention-avatar";
|
|
14913
|
+
img.alt = "";
|
|
14914
|
+
li.appendChild(img);
|
|
14915
|
+
}
|
|
14916
|
+
const label = document.createElement("span");
|
|
14917
|
+
label.textContent = item.label;
|
|
14918
|
+
li.appendChild(label);
|
|
14919
|
+
li.addEventListener("mousedown", (e) => e.preventDefault());
|
|
14920
|
+
li.addEventListener("click", () => this._select(i));
|
|
14921
|
+
dd.appendChild(li);
|
|
14922
|
+
});
|
|
14923
|
+
this._highlightItem(this._activeIndex);
|
|
14924
|
+
}
|
|
14925
|
+
_highlightItem(index) {
|
|
14926
|
+
if (!this._dropdown) return;
|
|
14927
|
+
this._dropdown.querySelectorAll(".an-mention-item").forEach((el, i) => {
|
|
14928
|
+
el.classList.toggle("an-mention-active", i === index);
|
|
14929
|
+
});
|
|
14930
|
+
this._activeIndex = index;
|
|
14931
|
+
}
|
|
14932
|
+
_positionDropdown() {
|
|
14933
|
+
const dd = this._dropdown;
|
|
14934
|
+
const rect = this._caretRect;
|
|
14935
|
+
if (!rect || rect.height === 0) return;
|
|
14936
|
+
dd.style.visibility = "hidden";
|
|
14937
|
+
dd.style.display = "block";
|
|
14938
|
+
const ddh = dd.offsetHeight;
|
|
14939
|
+
const ddw = dd.offsetWidth;
|
|
14940
|
+
let top = rect.bottom + 4;
|
|
14941
|
+
let left = rect.left;
|
|
14942
|
+
if (rect.bottom + ddh + 8 > window.innerHeight) top = rect.top - ddh - 4;
|
|
14943
|
+
left = Math.max(8, Math.min(left, window.innerWidth - ddw - 8));
|
|
14944
|
+
dd.style.top = `${top}px`;
|
|
14945
|
+
dd.style.left = `${left}px`;
|
|
14946
|
+
dd.style.visibility = "";
|
|
14947
|
+
}
|
|
14948
|
+
_showDropdown() {
|
|
14949
|
+
this._open = true;
|
|
14950
|
+
this._positionDropdown();
|
|
14951
|
+
}
|
|
14952
|
+
_hideDropdown() {
|
|
14953
|
+
if (this._dropdown) this._dropdown.style.display = "none";
|
|
14954
|
+
this._open = false;
|
|
14955
|
+
this._items = [];
|
|
14956
|
+
this._activeIndex = -1;
|
|
14957
|
+
this._triggerNode = null;
|
|
14958
|
+
this._caretRect = null;
|
|
14959
|
+
this._query = "";
|
|
14960
|
+
}
|
|
14961
|
+
/**
|
|
14962
|
+
* Captures the caret rect synchronously during the input event.
|
|
14963
|
+
* Must be called while the DOM event is still live — getClientRects() on a
|
|
14964
|
+
* collapsed range is reliable at this point but often empty inside async callbacks.
|
|
14965
|
+
*/
|
|
14966
|
+
_captureCaretRect() {
|
|
14967
|
+
if (this._triggerNode && this._triggerNode.isConnected) try {
|
|
14968
|
+
const r = document.createRange();
|
|
14969
|
+
const end = Math.min(this._triggerOffset + 1, this._triggerNode.textContent.length);
|
|
14970
|
+
r.setStart(this._triggerNode, this._triggerOffset);
|
|
14971
|
+
r.setEnd(this._triggerNode, end);
|
|
14972
|
+
const candidate = r.getBoundingClientRect();
|
|
14973
|
+
if (candidate.height > 0) {
|
|
14974
|
+
this._caretRect = candidate;
|
|
14975
|
+
return;
|
|
14976
|
+
}
|
|
14977
|
+
} catch (_) {}
|
|
14978
|
+
const sel = window.getSelection();
|
|
14979
|
+
if (!sel || !sel.rangeCount) return;
|
|
14980
|
+
const rects = sel.getRangeAt(0).getClientRects();
|
|
14981
|
+
if (rects.length > 0) this._caretRect = rects[rects.length - 1];
|
|
14982
|
+
}
|
|
14983
|
+
_getQueryAtCursor() {
|
|
14984
|
+
const sel = window.getSelection();
|
|
14985
|
+
if (!sel || !sel.rangeCount) return null;
|
|
14986
|
+
const range = sel.getRangeAt(0);
|
|
14987
|
+
if (!range.collapsed) return null;
|
|
14988
|
+
const node = range.startContainer;
|
|
14989
|
+
if (node.nodeType !== Node.TEXT_NODE) return null;
|
|
14990
|
+
const text = node.textContent.slice(0, range.startOffset);
|
|
14991
|
+
const trigger = this._cfg.trigger;
|
|
14992
|
+
const triggerIdx = text.lastIndexOf(trigger);
|
|
14993
|
+
if (triggerIdx === -1) return null;
|
|
14994
|
+
const afterTrigger = text.slice(triggerIdx + trigger.length);
|
|
14995
|
+
if (!this._cfg.allowSpaces && /\s/.test(afterTrigger)) return null;
|
|
14996
|
+
if (afterTrigger.length < this._cfg.minChars) return null;
|
|
14997
|
+
this._triggerNode = node;
|
|
14998
|
+
this._triggerOffset = triggerIdx;
|
|
14999
|
+
return afterTrigger;
|
|
15000
|
+
}
|
|
15001
|
+
_onInput() {
|
|
15002
|
+
if (!this._cfg) return;
|
|
15003
|
+
const query = this._getQueryAtCursor();
|
|
15004
|
+
if (query === null) {
|
|
15005
|
+
this._hideDropdown();
|
|
15006
|
+
return;
|
|
15007
|
+
}
|
|
15008
|
+
this._captureCaretRect();
|
|
15009
|
+
this._query = query;
|
|
15010
|
+
clearTimeout(this._debounceTimer);
|
|
15011
|
+
this._debounceTimer = setTimeout(() => {
|
|
15012
|
+
this._cfg.onSearch(this._query, (items) => {
|
|
15013
|
+
if (!Array.isArray(items) || items.length === 0) {
|
|
15014
|
+
this._hideDropdown();
|
|
15015
|
+
return;
|
|
15016
|
+
}
|
|
15017
|
+
this._renderItems(items);
|
|
15018
|
+
this._showDropdown();
|
|
15019
|
+
});
|
|
15020
|
+
}, this._cfg.debounce);
|
|
15021
|
+
}
|
|
15022
|
+
_onKeydown(e) {
|
|
15023
|
+
if (!this._cfg || !this._open) return;
|
|
15024
|
+
if (e.key === "ArrowDown") {
|
|
15025
|
+
e.preventDefault();
|
|
15026
|
+
const next = (this._activeIndex + 1) % this._items.length;
|
|
15027
|
+
this._highlightItem(next);
|
|
15028
|
+
} else if (e.key === "ArrowUp") {
|
|
15029
|
+
e.preventDefault();
|
|
15030
|
+
const prev = (this._activeIndex - 1 + this._items.length) % this._items.length;
|
|
15031
|
+
this._highlightItem(prev);
|
|
15032
|
+
} else if (e.key === "Enter" || e.key === "Tab") {
|
|
15033
|
+
if (this._activeIndex >= 0) {
|
|
15034
|
+
e.preventDefault();
|
|
15035
|
+
this._select(this._activeIndex);
|
|
15036
|
+
}
|
|
15037
|
+
} else if (e.key === "Escape") this._hideDropdown();
|
|
15038
|
+
}
|
|
15039
|
+
_onDocClick(e) {
|
|
15040
|
+
if (!this._open) return;
|
|
15041
|
+
if (this._dropdown && this._dropdown.contains(e.target)) return;
|
|
15042
|
+
this._hideDropdown();
|
|
15043
|
+
}
|
|
15044
|
+
_select(index) {
|
|
15045
|
+
const item = this._items[index];
|
|
15046
|
+
if (!item) return;
|
|
15047
|
+
if (this._triggerNode) {
|
|
15048
|
+
const node = this._triggerNode;
|
|
15049
|
+
node.textContent = node.textContent.slice(0, this._triggerOffset) + node.textContent.slice(this._triggerOffset + this._cfg.trigger.length + this._query.length);
|
|
15050
|
+
const sel = window.getSelection();
|
|
15051
|
+
const range = document.createRange();
|
|
15052
|
+
range.setStart(node, this._triggerOffset);
|
|
15053
|
+
range.collapse(true);
|
|
15054
|
+
sel.removeAllRanges();
|
|
15055
|
+
sel.addRange(range);
|
|
15056
|
+
}
|
|
15057
|
+
let html;
|
|
15058
|
+
if (typeof this._cfg.onInsert === "function") html = this._cfg.onInsert(item);
|
|
15059
|
+
if (!html) html = `<span class="${this._cfg.mentionClass}" data-mention-id="${item.id}" contenteditable="false">@${item.label}</span>`;
|
|
15060
|
+
this.context.invoke("editor.insertHTML", html + "​");
|
|
15061
|
+
this._hideDropdown();
|
|
15062
|
+
this.context.triggerEvent("change", this.context.getHTML());
|
|
15063
|
+
}
|
|
15064
|
+
};
|
|
15065
|
+
//#endregion
|
|
11584
15066
|
//#region src/js/Context.js
|
|
11585
15067
|
/**
|
|
11586
15068
|
* Context.js - Central hub for the editor instance
|
|
@@ -11597,6 +15079,8 @@
|
|
|
11597
15079
|
constructor(targetEl, userOptions = {}) {
|
|
11598
15080
|
this.targetEl = targetEl;
|
|
11599
15081
|
this.options = mergeDeep(defaultOptions, userOptions);
|
|
15082
|
+
/** @type {import('./i18n/index.js').AsnLocale} */
|
|
15083
|
+
this.locale = resolveLocale(this.options.lang);
|
|
11600
15084
|
/** @type {{ container: HTMLElement, editable: HTMLElement, toolbar?: HTMLElement, statusbar?: HTMLElement }} */
|
|
11601
15085
|
this.layoutInfo = {};
|
|
11602
15086
|
/** @type {Map<string, Function[]>} */
|
|
@@ -11657,6 +15141,10 @@
|
|
|
11657
15141
|
register("shortcutsDialog", ShortcutsDialog);
|
|
11658
15142
|
register("findReplace", FindReplace);
|
|
11659
15143
|
register("imageCropOverlay", ImageCropOverlay);
|
|
15144
|
+
register("autoSaveRestore", AutoSaveRestore);
|
|
15145
|
+
register("markdownShortcuts", MarkdownShortcuts);
|
|
15146
|
+
register("bubbleToolbar", BubbleToolbar);
|
|
15147
|
+
register("mention", Mention);
|
|
11660
15148
|
for (const [name, ModuleClass] of _customModules) register(name, ModuleClass);
|
|
11661
15149
|
}
|
|
11662
15150
|
/**
|
|
@@ -11688,7 +15176,9 @@
|
|
|
11688
15176
|
if (this.options.autoSave && this.options.autoSaveKey) {
|
|
11689
15177
|
const d4 = this.on("change", () => {
|
|
11690
15178
|
try {
|
|
11691
|
-
|
|
15179
|
+
const key = this.options.autoSaveKey;
|
|
15180
|
+
localStorage.setItem(key, this.getHTML());
|
|
15181
|
+
localStorage.setItem(key + ":asrmeta", JSON.stringify({ savedAt: Date.now() }));
|
|
11692
15182
|
} catch (_) {}
|
|
11693
15183
|
});
|
|
11694
15184
|
this._disposers.push(d4);
|
|
@@ -11988,7 +15478,7 @@
|
|
|
11988
15478
|
registerModule(name, ModuleClass) {
|
|
11989
15479
|
_customModules.set(name, ModuleClass);
|
|
11990
15480
|
},
|
|
11991
|
-
version: "1.0.
|
|
15481
|
+
version: "1.0.9"
|
|
11992
15482
|
};
|
|
11993
15483
|
/**
|
|
11994
15484
|
* @param {string|Element|NodeList|Element[]} selector
|