lakelib 0.1.21 → 0.1.23
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 +4 -4
- package/dist/lake.css +45 -36
- package/dist/lake.min.js +37 -29
- package/dist/lake.min.js.map +1 -1
- package/lib/lake.css +45 -36
- package/lib/lake.js +989 -299
- package/lib/lake.js.map +1 -1
- package/lib/types/boxes/code-block.d.ts +2 -1
- package/lib/types/boxes/emoji.d.ts +2 -1
- package/lib/types/boxes/equation.d.ts +2 -1
- package/lib/types/boxes/file.d.ts +2 -1
- package/lib/types/boxes/hr.d.ts +2 -1
- package/lib/types/boxes/image.d.ts +2 -1
- package/lib/types/boxes/video.d.ts +2 -1
- package/lib/types/config/slash-items.d.ts +2 -0
- package/lib/types/css/index.d.ts +1 -1
- package/lib/types/editor.d.ts +3 -0
- package/lib/types/i18n/en-US/index.d.ts +36 -0
- package/lib/types/i18n/ja/index.d.ts +36 -0
- package/lib/types/i18n/ko/index.d.ts +36 -0
- package/lib/types/i18n/types.d.ts +278 -2
- package/lib/types/i18n/zh-CN/index.d.ts +36 -0
- package/lib/types/index.d.ts +3 -2
- package/lib/types/managers/keystroke.d.ts +0 -1
- package/lib/types/managers/plugin.d.ts +4 -5
- package/lib/types/managers/selection.d.ts +1 -1
- package/lib/types/models/box.d.ts +1 -1
- package/lib/types/models/nodes.d.ts +2 -0
- package/lib/types/plugins/slash.d.ts +3 -0
- package/lib/types/types/plugin.d.ts +3 -0
- package/lib/types/types/{commands.d.ts → slash.d.ts} +4 -4
- package/lib/types/ui/box-toolbar.d.ts +2 -1
- package/lib/types/ui/dropdown.d.ts +1 -0
- package/lib/types/ui/link-popup.d.ts +2 -3
- package/lib/types/ui/slash-popup.d.ts +34 -0
- package/lib/types/ui/toolbar.d.ts +5 -3
- package/lib/types/utils/index.d.ts +2 -1
- package/lib/types/utils/{node-and-view.d.ts → node-position.d.ts} +1 -1
- package/lib/types/utils/scroll-to-node.d.ts +2 -0
- package/package.json +1 -1
- package/lib/types/ui/commands-popup.d.ts +0 -24
package/lib/lake.js
CHANGED
|
@@ -1098,6 +1098,15 @@ class Nodes {
|
|
|
1098
1098
|
element.innerText = value;
|
|
1099
1099
|
});
|
|
1100
1100
|
}
|
|
1101
|
+
value(value) {
|
|
1102
|
+
if (value === undefined) {
|
|
1103
|
+
const inputElement = this.get(0);
|
|
1104
|
+
return inputElement.value;
|
|
1105
|
+
}
|
|
1106
|
+
return this.eachElement(element => {
|
|
1107
|
+
element.value = value;
|
|
1108
|
+
});
|
|
1109
|
+
}
|
|
1101
1110
|
outerHTML() {
|
|
1102
1111
|
const element = this.get(0);
|
|
1103
1112
|
return element.outerHTML;
|
|
@@ -1506,7 +1515,7 @@ class Range {
|
|
|
1506
1515
|
selectBox(boxNode) {
|
|
1507
1516
|
const boxContainer = boxNode.find('.lake-box-container');
|
|
1508
1517
|
if (boxContainer.length === 0) {
|
|
1509
|
-
throw new Error(`The box
|
|
1518
|
+
throw new Error(`The box "${boxNode.attr('name')}" (id=${boxNode.id}) cannot be selected because it has not been rendered yet.`);
|
|
1510
1519
|
}
|
|
1511
1520
|
this.setStart(boxContainer, 0);
|
|
1512
1521
|
this.collapseToStart();
|
|
@@ -1515,7 +1524,7 @@ class Range {
|
|
|
1515
1524
|
selectBoxStart(boxNode) {
|
|
1516
1525
|
const boxStrip = boxNode.find('.lake-box-strip');
|
|
1517
1526
|
if (boxStrip.length === 0) {
|
|
1518
|
-
throw new Error(`The box
|
|
1527
|
+
throw new Error(`The box "${boxNode.attr('name')}" (id=${boxNode.id}) cannot be selected because it has not been rendered yet.`);
|
|
1519
1528
|
}
|
|
1520
1529
|
this.selectNodeContents(boxStrip.eq(0));
|
|
1521
1530
|
this.collapseToStart();
|
|
@@ -1524,7 +1533,7 @@ class Range {
|
|
|
1524
1533
|
selectBoxEnd(boxNode) {
|
|
1525
1534
|
const boxStrip = boxNode.find('.lake-box-strip');
|
|
1526
1535
|
if (boxStrip.length === 0) {
|
|
1527
|
-
throw new Error(`The box
|
|
1536
|
+
throw new Error(`The box "${boxNode.attr('name')}" (id=${boxNode.id}) cannot be selected because it has not been rendered yet.`);
|
|
1528
1537
|
}
|
|
1529
1538
|
this.selectNodeContents(boxStrip.eq(1));
|
|
1530
1539
|
this.collapseToStart();
|
|
@@ -2770,7 +2779,7 @@ function morph(node, otherNode, config = {}) {
|
|
|
2770
2779
|
}
|
|
2771
2780
|
|
|
2772
2781
|
// Returns an object that indicates the specified node's position relative to the viewport.
|
|
2773
|
-
function
|
|
2782
|
+
function nodePosition(node) {
|
|
2774
2783
|
const nativeNode = node.get(0);
|
|
2775
2784
|
const rect = nativeNode.getBoundingClientRect();
|
|
2776
2785
|
let left = rect.left;
|
|
@@ -2801,6 +2810,15 @@ function nodeAndView(node) {
|
|
|
2801
2810
|
return position;
|
|
2802
2811
|
}
|
|
2803
2812
|
|
|
2813
|
+
// If a node is not visible, scrolls the container that contains this node to its position to make it visible.
|
|
2814
|
+
// If the node is visible, then scrolling takes place.
|
|
2815
|
+
function scrollToNode(node, options) {
|
|
2816
|
+
const position = nodePosition(node);
|
|
2817
|
+
if (position.left < 0 || position.right < 0 || position.top < 0 || position.bottom < 0) {
|
|
2818
|
+
node.get(0).scrollIntoView(options);
|
|
2819
|
+
}
|
|
2820
|
+
}
|
|
2821
|
+
|
|
2804
2822
|
const boxInstances = new Map();
|
|
2805
2823
|
function getInstanceMap(id) {
|
|
2806
2824
|
let instanceMap = boxInstances.get(id);
|
|
@@ -2916,6 +2934,42 @@ var enUS = {
|
|
|
2916
2934
|
equation: 'Equation',
|
|
2917
2935
|
removeColor: 'Remove color',
|
|
2918
2936
|
},
|
|
2937
|
+
slash: {
|
|
2938
|
+
heading1: 'Heading 1',
|
|
2939
|
+
heading1Desc: 'Create a heading level 1',
|
|
2940
|
+
heading2: 'Heading 2',
|
|
2941
|
+
heading2Desc: 'Create a heading level 2',
|
|
2942
|
+
heading3: 'Heading 3',
|
|
2943
|
+
heading3Desc: 'Create a heading level 3',
|
|
2944
|
+
heading4: 'Heading 4',
|
|
2945
|
+
heading4Desc: 'Create a heading level 4',
|
|
2946
|
+
heading5: 'Heading 5',
|
|
2947
|
+
heading5Desc: 'Create a heading level 5',
|
|
2948
|
+
heading6: 'Heading 6',
|
|
2949
|
+
heading6Desc: 'Create a heading level 6',
|
|
2950
|
+
paragraph: 'Paragraph',
|
|
2951
|
+
paragraphDesc: 'Create a paragraph',
|
|
2952
|
+
blockQuote: 'Block quotation',
|
|
2953
|
+
blockQuoteDesc: 'Create a block quotation',
|
|
2954
|
+
numberedList: 'Numbered list',
|
|
2955
|
+
numberedListDesc: 'Create a numbered list',
|
|
2956
|
+
bulletedList: 'Bulleted list',
|
|
2957
|
+
bulletedListDesc: 'Create a bulleted list',
|
|
2958
|
+
checklist: 'Checklist',
|
|
2959
|
+
checklistDesc: 'Create a checklist',
|
|
2960
|
+
hr: 'Horizontal line',
|
|
2961
|
+
hrDesc: 'Insert a horizontal line',
|
|
2962
|
+
codeBlock: 'Code block',
|
|
2963
|
+
codeBlockDesc: 'Insert a code block',
|
|
2964
|
+
video: 'Video',
|
|
2965
|
+
videoDesc: 'Insert a video from YouTube',
|
|
2966
|
+
equation: 'Equation',
|
|
2967
|
+
equationDesc: 'Insert TeX expression in text',
|
|
2968
|
+
image: 'Image',
|
|
2969
|
+
imageDesc: 'Upload an image',
|
|
2970
|
+
file: 'File',
|
|
2971
|
+
fileDesc: 'Upload a file',
|
|
2972
|
+
},
|
|
2919
2973
|
link: {
|
|
2920
2974
|
newLink: 'New link',
|
|
2921
2975
|
url: 'Link URL',
|
|
@@ -3005,6 +3059,42 @@ var zhCN = {
|
|
|
3005
3059
|
equation: '公式',
|
|
3006
3060
|
removeColor: '默认',
|
|
3007
3061
|
},
|
|
3062
|
+
slash: {
|
|
3063
|
+
heading1: '标题 1',
|
|
3064
|
+
heading1Desc: '创建标题 1',
|
|
3065
|
+
heading2: '标题 2',
|
|
3066
|
+
heading2Desc: '创建标题 2',
|
|
3067
|
+
heading3: '标题 3',
|
|
3068
|
+
heading3Desc: '创建标题 3',
|
|
3069
|
+
heading4: '标题 4',
|
|
3070
|
+
heading4Desc: '创建标题 4',
|
|
3071
|
+
heading5: '标题 5',
|
|
3072
|
+
heading5Desc: '创建标题 5',
|
|
3073
|
+
heading6: '标题 6',
|
|
3074
|
+
heading6Desc: '创建标题 6',
|
|
3075
|
+
paragraph: '正文',
|
|
3076
|
+
paragraphDesc: '把当前段落改成正文',
|
|
3077
|
+
blockQuote: '引用',
|
|
3078
|
+
blockQuoteDesc: '创建引用',
|
|
3079
|
+
numberedList: '编号',
|
|
3080
|
+
numberedListDesc: '创建编号列表',
|
|
3081
|
+
bulletedList: '项目符号',
|
|
3082
|
+
bulletedListDesc: '创建项目符号列表',
|
|
3083
|
+
checklist: '任务列表',
|
|
3084
|
+
checklistDesc: '创建任务列表',
|
|
3085
|
+
hr: '分割线',
|
|
3086
|
+
hrDesc: '插入分割线',
|
|
3087
|
+
codeBlock: '代码块',
|
|
3088
|
+
codeBlockDesc: '插入代码块',
|
|
3089
|
+
video: '视频',
|
|
3090
|
+
videoDesc: '插入 YouTube 视频',
|
|
3091
|
+
equation: '公式',
|
|
3092
|
+
equationDesc: '支持 TeX 语法',
|
|
3093
|
+
image: '图片',
|
|
3094
|
+
imageDesc: '上传图片',
|
|
3095
|
+
file: '文件',
|
|
3096
|
+
fileDesc: '上传文件',
|
|
3097
|
+
},
|
|
3008
3098
|
link: {
|
|
3009
3099
|
newLink: '新链接',
|
|
3010
3100
|
url: '链接 URL',
|
|
@@ -3050,7 +3140,7 @@ var ja = {
|
|
|
3050
3140
|
redo: `やり直し (${modifierText('mod+Y')})`,
|
|
3051
3141
|
selectAll: `すべて選択 (${modifierText('mod+A')})`,
|
|
3052
3142
|
paragraph: 'テキスト',
|
|
3053
|
-
blockQuote: '
|
|
3143
|
+
blockQuote: '引用ブロック',
|
|
3054
3144
|
numberedList: '番号付きリスト',
|
|
3055
3145
|
bulletedList: '箇条書きリスト',
|
|
3056
3146
|
checklist: 'タスクリスト',
|
|
@@ -3094,6 +3184,42 @@ var ja = {
|
|
|
3094
3184
|
equation: '公式',
|
|
3095
3185
|
removeColor: 'デフォルト',
|
|
3096
3186
|
},
|
|
3187
|
+
slash: {
|
|
3188
|
+
heading1: 'タイトル 1',
|
|
3189
|
+
heading1Desc: 'レベル 1 のタイトルを作成',
|
|
3190
|
+
heading2: 'タイトル 2',
|
|
3191
|
+
heading2Desc: 'レベル 2 のタイトルを作成',
|
|
3192
|
+
heading3: 'タイトル 3',
|
|
3193
|
+
heading3Desc: 'レベル 3 のタイトルを作成',
|
|
3194
|
+
heading4: 'タイトル 4',
|
|
3195
|
+
heading4Desc: 'レベル 4 のタイトルを作成',
|
|
3196
|
+
heading5: 'タイトル 5',
|
|
3197
|
+
heading5Desc: 'レベル 5 のタイトルを作成',
|
|
3198
|
+
heading6: 'タイトル 6',
|
|
3199
|
+
heading6Desc: 'レベル 6 のタイトルを作成',
|
|
3200
|
+
paragraph: 'テキスト',
|
|
3201
|
+
paragraphDesc: '段落を作成',
|
|
3202
|
+
blockQuote: '引用ブロック',
|
|
3203
|
+
blockQuoteDesc: '引用ブロックを作成',
|
|
3204
|
+
numberedList: '番号付きリスト',
|
|
3205
|
+
numberedListDesc: '番号付きリストを作成',
|
|
3206
|
+
bulletedList: '箇条書きリスト',
|
|
3207
|
+
bulletedListDesc: '箇条書きリストを作成',
|
|
3208
|
+
checklist: 'タスクリスト',
|
|
3209
|
+
checklistDesc: 'タスクリストを作成',
|
|
3210
|
+
hr: '区切り線',
|
|
3211
|
+
hrDesc: '水平線を挿入',
|
|
3212
|
+
codeBlock: 'コードブロック',
|
|
3213
|
+
codeBlockDesc: 'コードブロックを挿入',
|
|
3214
|
+
video: '動画',
|
|
3215
|
+
videoDesc: 'YouTube から動画を挿入',
|
|
3216
|
+
equation: '公式',
|
|
3217
|
+
equationDesc: 'TeX 式を挿入',
|
|
3218
|
+
image: '画像',
|
|
3219
|
+
imageDesc: '画像をアップロード',
|
|
3220
|
+
file: 'ファイル',
|
|
3221
|
+
fileDesc: 'ファイルをアップロード',
|
|
3222
|
+
},
|
|
3097
3223
|
link: {
|
|
3098
3224
|
newLink: '新しいリンク',
|
|
3099
3225
|
url: 'リンク URL',
|
|
@@ -3183,6 +3309,42 @@ var ko = {
|
|
|
3183
3309
|
equation: '수식',
|
|
3184
3310
|
removeColor: '기본색',
|
|
3185
3311
|
},
|
|
3312
|
+
slash: {
|
|
3313
|
+
heading1: '제목 1',
|
|
3314
|
+
heading1Desc: '1 단계 제목을 작성',
|
|
3315
|
+
heading2: '제목 2',
|
|
3316
|
+
heading2Desc: '2 단계 제목을 작성',
|
|
3317
|
+
heading3: '제목 3',
|
|
3318
|
+
heading3Desc: '3 단계 제목을 작성',
|
|
3319
|
+
heading4: '제목 4',
|
|
3320
|
+
heading4Desc: '4 단계 제목을 작성',
|
|
3321
|
+
heading5: '제목 5',
|
|
3322
|
+
heading5Desc: '5 단계 제목을 작성',
|
|
3323
|
+
heading6: '제목 6',
|
|
3324
|
+
heading6Desc: '6 단계 제목을 작성',
|
|
3325
|
+
paragraph: '텍스트',
|
|
3326
|
+
paragraphDesc: '단락을 작성',
|
|
3327
|
+
blockQuote: '인용문',
|
|
3328
|
+
blockQuoteDesc: '인용문을 작성',
|
|
3329
|
+
numberedList: '순서 목록',
|
|
3330
|
+
numberedListDesc: '순서 목록을 작성',
|
|
3331
|
+
bulletedList: '비순서 목록',
|
|
3332
|
+
bulletedListDesc: '비순서 목록을 작성',
|
|
3333
|
+
checklist: '체크리스트',
|
|
3334
|
+
checklistDesc: '체크리스트를 작성',
|
|
3335
|
+
hr: '구분선',
|
|
3336
|
+
hrDesc: '구분선을 삽입',
|
|
3337
|
+
codeBlock: '코드 블록',
|
|
3338
|
+
codeBlockDesc: '코드 블록을 삽입',
|
|
3339
|
+
video: '동영상',
|
|
3340
|
+
videoDesc: '유튜브 동영상을 삽입',
|
|
3341
|
+
equation: '수식',
|
|
3342
|
+
equationDesc: '텍스 표현식을 삽입',
|
|
3343
|
+
image: '이미지',
|
|
3344
|
+
imageDesc: '이미지를 업로드',
|
|
3345
|
+
file: '파일',
|
|
3346
|
+
fileDesc: '파일을 업로드',
|
|
3347
|
+
},
|
|
3186
3348
|
link: {
|
|
3187
3349
|
newLink: '새 링크',
|
|
3188
3350
|
url: '링크 URL',
|
|
@@ -3256,12 +3418,10 @@ class Dropdown {
|
|
|
3256
3418
|
this.documentClickListener = (event) => {
|
|
3257
3419
|
const targetNode = new Nodes(event.target);
|
|
3258
3420
|
const titleNode = this.node.find('.lake-dropdown-title');
|
|
3259
|
-
const menuNode = this.node.find('.lake-dropdown-menu');
|
|
3260
3421
|
if (targetNode.closest('.lake-dropdown-title').get(0) === titleNode.get(0)) {
|
|
3261
3422
|
return;
|
|
3262
3423
|
}
|
|
3263
|
-
|
|
3264
|
-
document.removeEventListener('click', this.documentClickListener);
|
|
3424
|
+
this.hideMenu();
|
|
3265
3425
|
};
|
|
3266
3426
|
this.config = config;
|
|
3267
3427
|
this.root = config.root;
|
|
@@ -3323,6 +3483,15 @@ class Dropdown {
|
|
|
3323
3483
|
`;
|
|
3324
3484
|
const listNode = query(listContent);
|
|
3325
3485
|
menuNode.append(listNode);
|
|
3486
|
+
listNode.on('mouseenter', () => {
|
|
3487
|
+
if (listNode.hasClass('lake-dropdown-item-selected')) {
|
|
3488
|
+
return;
|
|
3489
|
+
}
|
|
3490
|
+
listNode.addClass('lake-dropdown-item-hovered');
|
|
3491
|
+
});
|
|
3492
|
+
listNode.on('mouseleave', () => {
|
|
3493
|
+
listNode.removeClass('lake-dropdown-item-hovered');
|
|
3494
|
+
});
|
|
3326
3495
|
if (config.menuType === 'character') {
|
|
3327
3496
|
listNode.attr('title', menuText);
|
|
3328
3497
|
listNode.find('.lake-dropdown-menu-text').text(menuItem.value);
|
|
@@ -3355,15 +3524,6 @@ class Dropdown {
|
|
|
3355
3524
|
menuNode.find('.lake-dropdown-menu-check').css('visibility', 'hidden');
|
|
3356
3525
|
menuNode.find('li').each(node => {
|
|
3357
3526
|
const listNode = query(node);
|
|
3358
|
-
listNode.on('mouseenter', () => {
|
|
3359
|
-
if (listNode.hasClass('lake-dropdown-item-selected')) {
|
|
3360
|
-
return;
|
|
3361
|
-
}
|
|
3362
|
-
listNode.addClass('lake-dropdown-item-hovered');
|
|
3363
|
-
});
|
|
3364
|
-
listNode.on('mouseleave', () => {
|
|
3365
|
-
listNode.removeClass('lake-dropdown-item-hovered');
|
|
3366
|
-
});
|
|
3367
3527
|
if (currentValues.indexOf(listNode.attr('value')) >= 0) {
|
|
3368
3528
|
listNode.find('.lake-dropdown-menu-check').css('visibility', 'visible');
|
|
3369
3529
|
}
|
|
@@ -3387,6 +3547,12 @@ class Dropdown {
|
|
|
3387
3547
|
menuNode.css('visibility', '');
|
|
3388
3548
|
document.addEventListener('click', this.documentClickListener);
|
|
3389
3549
|
}
|
|
3550
|
+
hideMenu() {
|
|
3551
|
+
const dropdownNode = this.node;
|
|
3552
|
+
const menuNode = dropdownNode.find('.lake-dropdown-menu');
|
|
3553
|
+
menuNode.hide();
|
|
3554
|
+
document.removeEventListener('click', this.documentClickListener);
|
|
3555
|
+
}
|
|
3390
3556
|
bindEvents() {
|
|
3391
3557
|
const config = this.config;
|
|
3392
3558
|
const dropdownNode = this.node;
|
|
@@ -3458,8 +3624,7 @@ class Dropdown {
|
|
|
3458
3624
|
this.updateColorAccent(titleNode, value);
|
|
3459
3625
|
}
|
|
3460
3626
|
config.onSelect(value);
|
|
3461
|
-
|
|
3462
|
-
document.removeEventListener('click', this.documentClickListener);
|
|
3627
|
+
this.hideMenu();
|
|
3463
3628
|
});
|
|
3464
3629
|
}
|
|
3465
3630
|
render() {
|
|
@@ -3512,8 +3677,8 @@ class Dropdown {
|
|
|
3512
3677
|
this.bindEvents();
|
|
3513
3678
|
}
|
|
3514
3679
|
unmount() {
|
|
3680
|
+
this.hideMenu();
|
|
3515
3681
|
this.node.remove();
|
|
3516
|
-
document.removeEventListener('click', this.documentClickListener);
|
|
3517
3682
|
}
|
|
3518
3683
|
}
|
|
3519
3684
|
|
|
@@ -3521,13 +3686,13 @@ class BoxToolbar {
|
|
|
3521
3686
|
constructor(config) {
|
|
3522
3687
|
this.buttonItemList = [];
|
|
3523
3688
|
this.dropdownItemList = [];
|
|
3689
|
+
this.dropdownList = [];
|
|
3524
3690
|
this.root = query(config.root);
|
|
3525
3691
|
this.box = config.box;
|
|
3526
3692
|
this.items = config.items;
|
|
3527
3693
|
this.locale = config.locale || i18nObject('en-US');
|
|
3528
3694
|
this.placement = config.placement || 'top';
|
|
3529
3695
|
this.container = query('<div class="lake-box-toolbar" />');
|
|
3530
|
-
this.root.addClass('lake-custom-properties');
|
|
3531
3696
|
}
|
|
3532
3697
|
appendDivider() {
|
|
3533
3698
|
this.container.append('<div class="lake-toolbar-divider" />');
|
|
@@ -3565,12 +3730,13 @@ class BoxToolbar {
|
|
|
3565
3730
|
},
|
|
3566
3731
|
});
|
|
3567
3732
|
dropdown.render();
|
|
3733
|
+
this.dropdownList.push(dropdown);
|
|
3568
3734
|
}
|
|
3569
|
-
|
|
3735
|
+
position() {
|
|
3570
3736
|
const boxNode = this.box.node;
|
|
3571
3737
|
const boxNativeNode = boxNode.get(0);
|
|
3572
3738
|
const boxRect = boxNativeNode.getBoundingClientRect();
|
|
3573
|
-
const position =
|
|
3739
|
+
const position = nodePosition(boxNode);
|
|
3574
3740
|
if (position.top < 0 || position.bottom + boxRect.height < 0) {
|
|
3575
3741
|
this.container.hide();
|
|
3576
3742
|
return;
|
|
@@ -3601,9 +3767,13 @@ class BoxToolbar {
|
|
|
3601
3767
|
this.appendDropdown(item);
|
|
3602
3768
|
}
|
|
3603
3769
|
}
|
|
3604
|
-
this.
|
|
3770
|
+
this.position();
|
|
3605
3771
|
}
|
|
3772
|
+
// Destroys the toolbar.
|
|
3606
3773
|
unmount() {
|
|
3774
|
+
for (const dropdown of this.dropdownList) {
|
|
3775
|
+
dropdown.unmount();
|
|
3776
|
+
}
|
|
3607
3777
|
this.container.remove();
|
|
3608
3778
|
}
|
|
3609
3779
|
}
|
|
@@ -3705,7 +3875,11 @@ class Box {
|
|
|
3705
3875
|
// Returns an instance of the editor that includes the box.
|
|
3706
3876
|
getEditor() {
|
|
3707
3877
|
const container = this.node.closest('div[contenteditable]');
|
|
3708
|
-
|
|
3878
|
+
const editor = container.length > 0 ? editors.get(container.id) : undefined;
|
|
3879
|
+
if (!editor) {
|
|
3880
|
+
throw new Error(`The box "${this.name}" (id=${this.node.id}) is not rendered in the editor.`);
|
|
3881
|
+
}
|
|
3882
|
+
return editor;
|
|
3709
3883
|
}
|
|
3710
3884
|
// Returns the container node of the box.
|
|
3711
3885
|
getContainer() {
|
|
@@ -3713,11 +3887,15 @@ class Box {
|
|
|
3713
3887
|
}
|
|
3714
3888
|
// Sets a popup toolbar for the box.
|
|
3715
3889
|
setToolbar(items) {
|
|
3716
|
-
|
|
3890
|
+
let editor;
|
|
3891
|
+
try {
|
|
3892
|
+
editor = this.getEditor();
|
|
3893
|
+
}
|
|
3894
|
+
catch ( /* empty */_a) { /* empty */ }
|
|
3717
3895
|
let toolbar = null;
|
|
3718
3896
|
const scrollListener = () => {
|
|
3719
3897
|
if (toolbar) {
|
|
3720
|
-
toolbar.
|
|
3898
|
+
toolbar.position();
|
|
3721
3899
|
}
|
|
3722
3900
|
};
|
|
3723
3901
|
this.event.on('focus', () => {
|
|
@@ -3859,7 +4037,7 @@ function getBody(xhr) {
|
|
|
3859
4037
|
try {
|
|
3860
4038
|
return JSON.parse(text);
|
|
3861
4039
|
}
|
|
3862
|
-
catch (
|
|
4040
|
+
catch (_a) {
|
|
3863
4041
|
return text;
|
|
3864
4042
|
}
|
|
3865
4043
|
}
|
|
@@ -4021,7 +4199,7 @@ var index = /*#__PURE__*/Object.freeze({
|
|
|
4021
4199
|
mergeNodes: mergeNodes,
|
|
4022
4200
|
modifierText: modifierText,
|
|
4023
4201
|
morph: morph,
|
|
4024
|
-
|
|
4202
|
+
nodePosition: nodePosition,
|
|
4025
4203
|
normalizeValue: normalizeValue,
|
|
4026
4204
|
parseStyle: parseStyle,
|
|
4027
4205
|
query: query,
|
|
@@ -4029,6 +4207,7 @@ var index = /*#__PURE__*/Object.freeze({
|
|
|
4029
4207
|
removeZWS: removeZWS,
|
|
4030
4208
|
request: request,
|
|
4031
4209
|
safeTemplate: safeTemplate,
|
|
4210
|
+
scrollToNode: scrollToNode,
|
|
4032
4211
|
setBlockIndent: setBlockIndent,
|
|
4033
4212
|
splitNodes: splitNodes,
|
|
4034
4213
|
template: template,
|
|
@@ -5173,7 +5352,7 @@ function removeBox(range) {
|
|
|
5173
5352
|
return box;
|
|
5174
5353
|
}
|
|
5175
5354
|
|
|
5176
|
-
var version = "0.1.
|
|
5355
|
+
var version = "0.1.23";
|
|
5177
5356
|
|
|
5178
5357
|
// Returns the attributes of the element as an key-value object.
|
|
5179
5358
|
function getAttributes(node) {
|
|
@@ -5247,10 +5426,10 @@ class Selection {
|
|
|
5247
5426
|
}
|
|
5248
5427
|
this.selection = selection;
|
|
5249
5428
|
this.container = container;
|
|
5250
|
-
this.range = this.
|
|
5429
|
+
this.range = this.getCurrentRange();
|
|
5251
5430
|
}
|
|
5252
|
-
// Returns
|
|
5253
|
-
|
|
5431
|
+
// Returns a range object currently selected.
|
|
5432
|
+
getCurrentRange() {
|
|
5254
5433
|
if (this.selection.rangeCount > 0) {
|
|
5255
5434
|
const range = this.selection.getRangeAt(0);
|
|
5256
5435
|
return new Range(range);
|
|
@@ -5264,7 +5443,7 @@ class Selection {
|
|
|
5264
5443
|
}
|
|
5265
5444
|
// Updates the saved range with the range of the native selection.
|
|
5266
5445
|
updateByRange() {
|
|
5267
|
-
const newRange = this.
|
|
5446
|
+
const newRange = this.getCurrentRange();
|
|
5268
5447
|
if (!this.container.contains(newRange.commonAncestor)) {
|
|
5269
5448
|
return;
|
|
5270
5449
|
}
|
|
@@ -5416,6 +5595,11 @@ class Command {
|
|
|
5416
5595
|
return commandItem.selectedValues(appliedItems);
|
|
5417
5596
|
}
|
|
5418
5597
|
execute(name, ...data) {
|
|
5598
|
+
const container = this.selection.container;
|
|
5599
|
+
const range = this.selection.range;
|
|
5600
|
+
if (!container.contains(range.commonAncestor)) {
|
|
5601
|
+
range.shrinkAfter(container);
|
|
5602
|
+
}
|
|
5419
5603
|
const commandItem = this.getItem(name);
|
|
5420
5604
|
commandItem.execute.apply(this, data);
|
|
5421
5605
|
debug(`Command "${name}" executed`);
|
|
@@ -5614,12 +5798,6 @@ class History {
|
|
|
5614
5798
|
}
|
|
5615
5799
|
}
|
|
5616
5800
|
|
|
5617
|
-
const aliasMap = new Map([
|
|
5618
|
-
['arrow-left', 'left'],
|
|
5619
|
-
['arrow-right', 'right'],
|
|
5620
|
-
['arrow-up', 'up'],
|
|
5621
|
-
['arrow-down', 'down'],
|
|
5622
|
-
]);
|
|
5623
5801
|
class Keystroke {
|
|
5624
5802
|
constructor(container) {
|
|
5625
5803
|
this.keydownEventList = [];
|
|
@@ -5630,6 +5808,9 @@ class Keystroke {
|
|
|
5630
5808
|
if (keyboardEvent.isComposing) {
|
|
5631
5809
|
return;
|
|
5632
5810
|
}
|
|
5811
|
+
if (keyboardEvent.defaultPrevented) {
|
|
5812
|
+
return;
|
|
5813
|
+
}
|
|
5633
5814
|
for (const item of this.keydownEventList) {
|
|
5634
5815
|
if (isKeyHotkey(item.type, keyboardEvent)) {
|
|
5635
5816
|
if (item.listener(keyboardEvent) === false) {
|
|
@@ -5643,6 +5824,9 @@ class Keystroke {
|
|
|
5643
5824
|
if (keyboardEvent.isComposing) {
|
|
5644
5825
|
return;
|
|
5645
5826
|
}
|
|
5827
|
+
if (keyboardEvent.defaultPrevented) {
|
|
5828
|
+
return;
|
|
5829
|
+
}
|
|
5646
5830
|
for (const item of this.keyupEventList) {
|
|
5647
5831
|
if (isKeyHotkey(item.type, keyboardEvent)) {
|
|
5648
5832
|
if (item.listener(keyboardEvent) === false) {
|
|
@@ -5652,14 +5836,8 @@ class Keystroke {
|
|
|
5652
5836
|
}
|
|
5653
5837
|
});
|
|
5654
5838
|
}
|
|
5655
|
-
normalizeType(type) {
|
|
5656
|
-
var _a;
|
|
5657
|
-
type = (_a = aliasMap.get(type)) !== null && _a !== void 0 ? _a : type;
|
|
5658
|
-
return type;
|
|
5659
|
-
}
|
|
5660
5839
|
// Sets a keydown shortcut.
|
|
5661
5840
|
setKeydown(type, listener) {
|
|
5662
|
-
type = this.normalizeType(type);
|
|
5663
5841
|
this.keydownEventList.push({
|
|
5664
5842
|
type,
|
|
5665
5843
|
listener,
|
|
@@ -5667,7 +5845,6 @@ class Keystroke {
|
|
|
5667
5845
|
}
|
|
5668
5846
|
// Sets a keyup shortcut.
|
|
5669
5847
|
setKeyup(type, listener) {
|
|
5670
|
-
type = this.normalizeType(type);
|
|
5671
5848
|
this.keyupEventList.push({
|
|
5672
5849
|
type,
|
|
5673
5850
|
listener,
|
|
@@ -5675,7 +5852,6 @@ class Keystroke {
|
|
|
5675
5852
|
}
|
|
5676
5853
|
// Executes the keydown shortcuts.
|
|
5677
5854
|
keydown(type) {
|
|
5678
|
-
type = this.normalizeType(type);
|
|
5679
5855
|
for (const item of this.keydownEventList) {
|
|
5680
5856
|
if (item.type === type) {
|
|
5681
5857
|
if (item.listener(new KeyboardEvent(type)) === false) {
|
|
@@ -5686,7 +5862,6 @@ class Keystroke {
|
|
|
5686
5862
|
}
|
|
5687
5863
|
// Executes the keyup shortcuts.
|
|
5688
5864
|
keyup(type) {
|
|
5689
|
-
type = this.normalizeType(type);
|
|
5690
5865
|
for (const item of this.keyupEventList) {
|
|
5691
5866
|
if (item.type === type) {
|
|
5692
5867
|
if (item.listener(new KeyboardEvent(type)) === false) {
|
|
@@ -5711,15 +5886,26 @@ class BoxManager {
|
|
|
5711
5886
|
|
|
5712
5887
|
class Plugin {
|
|
5713
5888
|
constructor() {
|
|
5714
|
-
this.
|
|
5889
|
+
this.pluginMap = new Map();
|
|
5715
5890
|
}
|
|
5716
|
-
add(plugin) {
|
|
5717
|
-
this.
|
|
5891
|
+
add(name, plugin) {
|
|
5892
|
+
if (this.pluginMap.get(name)) {
|
|
5893
|
+
throw new Error(`Plugin "${name}" is already defined.`);
|
|
5894
|
+
}
|
|
5895
|
+
this.pluginMap.set(name, plugin);
|
|
5718
5896
|
}
|
|
5719
5897
|
loadAll(editor) {
|
|
5720
|
-
|
|
5721
|
-
|
|
5898
|
+
const unmountPluginMap = new Map();
|
|
5899
|
+
for (const name of this.pluginMap.keys()) {
|
|
5900
|
+
const plugin = this.pluginMap.get(name);
|
|
5901
|
+
if (plugin && editor.config[name] !== false) {
|
|
5902
|
+
const result = plugin(editor);
|
|
5903
|
+
if (result) {
|
|
5904
|
+
unmountPluginMap.set(name, result);
|
|
5905
|
+
}
|
|
5906
|
+
}
|
|
5722
5907
|
}
|
|
5908
|
+
return unmountPluginMap;
|
|
5723
5909
|
}
|
|
5724
5910
|
}
|
|
5725
5911
|
|
|
@@ -5749,6 +5935,7 @@ const defaultConfig = {
|
|
|
5749
5935
|
console.error(message);
|
|
5750
5936
|
}
|
|
5751
5937
|
},
|
|
5938
|
+
slash: false,
|
|
5752
5939
|
};
|
|
5753
5940
|
class Editor {
|
|
5754
5941
|
constructor(config) {
|
|
@@ -5760,25 +5947,26 @@ class Editor {
|
|
|
5760
5947
|
selectedNameMap: new Map(),
|
|
5761
5948
|
selectedValuesMap: new Map(),
|
|
5762
5949
|
};
|
|
5950
|
+
this.unmountPluginMap = new Map();
|
|
5763
5951
|
this.isComposing = false;
|
|
5764
5952
|
this.event = new EventEmitter();
|
|
5765
5953
|
this.box = Editor.box;
|
|
5766
5954
|
this.copyListener = event => {
|
|
5767
|
-
const range = this.selection.
|
|
5955
|
+
const range = this.selection.getCurrentRange();
|
|
5768
5956
|
if (!this.container.contains(range.commonAncestor)) {
|
|
5769
5957
|
return;
|
|
5770
5958
|
}
|
|
5771
5959
|
this.event.emit('copy', event);
|
|
5772
5960
|
};
|
|
5773
5961
|
this.cutListener = event => {
|
|
5774
|
-
const range = this.selection.
|
|
5962
|
+
const range = this.selection.getCurrentRange();
|
|
5775
5963
|
if (!this.container.contains(range.commonAncestor)) {
|
|
5776
5964
|
return;
|
|
5777
5965
|
}
|
|
5778
5966
|
this.event.emit('cut', event);
|
|
5779
5967
|
};
|
|
5780
5968
|
this.pasteListener = event => {
|
|
5781
|
-
const range = this.selection.
|
|
5969
|
+
const range = this.selection.getCurrentRange();
|
|
5782
5970
|
if (!this.container.contains(range.commonAncestor)) {
|
|
5783
5971
|
return;
|
|
5784
5972
|
}
|
|
@@ -5791,7 +5979,7 @@ class Editor {
|
|
|
5791
5979
|
};
|
|
5792
5980
|
this.clickListener = event => {
|
|
5793
5981
|
const targetNode = new Nodes(event.target);
|
|
5794
|
-
if (!targetNode.get(0).isConnected
|
|
5982
|
+
if (!targetNode.get(0).isConnected) {
|
|
5795
5983
|
return;
|
|
5796
5984
|
}
|
|
5797
5985
|
this.event.emit('click', targetNode);
|
|
@@ -5799,6 +5987,9 @@ class Editor {
|
|
|
5799
5987
|
this.resizeListener = () => {
|
|
5800
5988
|
this.event.emit('resize');
|
|
5801
5989
|
};
|
|
5990
|
+
this.scrollListener = () => {
|
|
5991
|
+
this.event.emit('scroll');
|
|
5992
|
+
};
|
|
5802
5993
|
this.updateSelectionRange = debounce(() => {
|
|
5803
5994
|
this.selection.updateByRange();
|
|
5804
5995
|
}, 1, {
|
|
@@ -5974,60 +6165,65 @@ class Editor {
|
|
|
5974
6165
|
this.unsavedInputData = '';
|
|
5975
6166
|
this.unsavedInputCount = 0;
|
|
5976
6167
|
}
|
|
5977
|
-
//
|
|
6168
|
+
// Handles input event.
|
|
6169
|
+
handleInputEvent(event) {
|
|
6170
|
+
var _a;
|
|
6171
|
+
this.selection.updateByRange();
|
|
6172
|
+
const range = this.selection.range;
|
|
6173
|
+
if (range.isInsideBox) {
|
|
6174
|
+
return;
|
|
6175
|
+
}
|
|
6176
|
+
if (range.isBoxStart || range.isBoxEnd) {
|
|
6177
|
+
this.moveBoxStripText();
|
|
6178
|
+
this.history.save();
|
|
6179
|
+
return;
|
|
6180
|
+
}
|
|
6181
|
+
const inputType = event instanceof CompositionEvent ? 'insertText' : event.inputType;
|
|
6182
|
+
if (inputType === 'insertText') {
|
|
6183
|
+
const inputData = (_a = event.data) !== null && _a !== void 0 ? _a : '';
|
|
6184
|
+
if (inputData.length > 1) {
|
|
6185
|
+
this.history.save({
|
|
6186
|
+
inputType: 'insertText',
|
|
6187
|
+
update: false,
|
|
6188
|
+
});
|
|
6189
|
+
return;
|
|
6190
|
+
}
|
|
6191
|
+
this.unsavedInputData += inputData;
|
|
6192
|
+
this.unsavedInputCount++;
|
|
6193
|
+
if (this.unsavedInputData.length < this.config.minChangeSize) {
|
|
6194
|
+
this.history.save({
|
|
6195
|
+
inputType: 'insertText',
|
|
6196
|
+
update: this.unsavedInputCount > 1,
|
|
6197
|
+
});
|
|
6198
|
+
}
|
|
6199
|
+
else {
|
|
6200
|
+
this.history.save({
|
|
6201
|
+
inputType: 'insertText',
|
|
6202
|
+
update: true,
|
|
6203
|
+
});
|
|
6204
|
+
this.resetUnsavedInputData();
|
|
6205
|
+
}
|
|
6206
|
+
return;
|
|
6207
|
+
}
|
|
6208
|
+
this.history.save();
|
|
6209
|
+
}
|
|
6210
|
+
// Binds events about inputting text.
|
|
5978
6211
|
bindInputEvents() {
|
|
5979
6212
|
this.container.on('compositionstart', () => {
|
|
5980
6213
|
this.isComposing = true;
|
|
6214
|
+
this.container.removeClass('lake-placeholder');
|
|
5981
6215
|
});
|
|
5982
|
-
this.container.on('compositionend',
|
|
6216
|
+
this.container.on('compositionend', event => {
|
|
5983
6217
|
this.isComposing = false;
|
|
6218
|
+
this.handleInputEvent(event);
|
|
5984
6219
|
});
|
|
5985
6220
|
this.container.on('input', event => {
|
|
5986
6221
|
const inputEvent = event;
|
|
5987
|
-
|
|
5988
|
-
|
|
5989
|
-
|
|
5990
|
-
|
|
5991
|
-
|
|
5992
|
-
return;
|
|
5993
|
-
}
|
|
5994
|
-
// isComposing is false after ending composition because compositionend event has been emitted.
|
|
5995
|
-
if (this.isComposing) {
|
|
5996
|
-
if (inputEvent.inputType === 'insertCompositionText') {
|
|
5997
|
-
this.container.removeClass('lake-placeholder');
|
|
5998
|
-
}
|
|
5999
|
-
this.event.emit('input', inputEvent);
|
|
6000
|
-
return;
|
|
6001
|
-
}
|
|
6002
|
-
if (range.isBoxStart || range.isBoxEnd) {
|
|
6003
|
-
this.moveBoxStripText();
|
|
6004
|
-
this.history.save();
|
|
6005
|
-
this.event.emit('input', inputEvent);
|
|
6006
|
-
return;
|
|
6007
|
-
}
|
|
6008
|
-
if (inputEvent.inputType === 'insertText' ||
|
|
6009
|
-
inputEvent.inputType === 'insertCompositionText') {
|
|
6010
|
-
this.unsavedInputData += (_a = inputEvent.data) !== null && _a !== void 0 ? _a : '';
|
|
6011
|
-
this.unsavedInputCount++;
|
|
6012
|
-
if (this.unsavedInputData.length < this.config.minChangeSize) {
|
|
6013
|
-
this.history.save({
|
|
6014
|
-
inputType: 'insertText',
|
|
6015
|
-
update: this.unsavedInputCount > 1,
|
|
6016
|
-
});
|
|
6017
|
-
}
|
|
6018
|
-
else {
|
|
6019
|
-
this.history.save({
|
|
6020
|
-
inputType: 'insertText',
|
|
6021
|
-
update: true,
|
|
6022
|
-
});
|
|
6023
|
-
this.resetUnsavedInputData();
|
|
6024
|
-
}
|
|
6025
|
-
this.event.emit('input', inputEvent);
|
|
6026
|
-
return;
|
|
6027
|
-
}
|
|
6028
|
-
this.history.save();
|
|
6029
|
-
this.event.emit('input', inputEvent);
|
|
6030
|
-
}, 0);
|
|
6222
|
+
this.isComposing = inputEvent.isComposing;
|
|
6223
|
+
if (this.isComposing) {
|
|
6224
|
+
return;
|
|
6225
|
+
}
|
|
6226
|
+
this.handleInputEvent(event);
|
|
6031
6227
|
});
|
|
6032
6228
|
}
|
|
6033
6229
|
// Binds events about history.
|
|
@@ -6058,8 +6254,8 @@ class Editor {
|
|
|
6058
6254
|
this.history.event.on('save', (value, options) => {
|
|
6059
6255
|
this.removeBoxGarbage();
|
|
6060
6256
|
executeCommonMethods(value);
|
|
6061
|
-
this.selection.sync();
|
|
6062
6257
|
if (options.inputType !== 'insertText') {
|
|
6258
|
+
this.selection.sync();
|
|
6063
6259
|
this.resetUnsavedInputData();
|
|
6064
6260
|
}
|
|
6065
6261
|
});
|
|
@@ -6111,7 +6307,7 @@ class Editor {
|
|
|
6111
6307
|
}
|
|
6112
6308
|
// Sets default config for a plugin.
|
|
6113
6309
|
setPluginConfig(name, config) {
|
|
6114
|
-
if (
|
|
6310
|
+
if (typeof this.config[name] !== 'object') {
|
|
6115
6311
|
this.config[name] = {};
|
|
6116
6312
|
}
|
|
6117
6313
|
for (const key of Object.keys(config)) {
|
|
@@ -6178,17 +6374,11 @@ class Editor {
|
|
|
6178
6374
|
});
|
|
6179
6375
|
this.overlayContainer.find('.lake-artificial-caret').remove();
|
|
6180
6376
|
this.overlayContainer.append(artificialCaret);
|
|
6181
|
-
|
|
6182
|
-
|
|
6183
|
-
|
|
6184
|
-
|
|
6185
|
-
|
|
6186
|
-
artificialCaret.get(0).scrollIntoView({
|
|
6187
|
-
behavior: 'instant',
|
|
6188
|
-
block: 'center',
|
|
6189
|
-
inline: 'nearest',
|
|
6190
|
-
});
|
|
6191
|
-
}
|
|
6377
|
+
scrollToNode(artificialCaret, {
|
|
6378
|
+
behavior: 'instant',
|
|
6379
|
+
block: 'center',
|
|
6380
|
+
inline: 'nearest',
|
|
6381
|
+
});
|
|
6192
6382
|
artificialCaret.remove();
|
|
6193
6383
|
}
|
|
6194
6384
|
// Sets the specified value to the editor.
|
|
@@ -6221,7 +6411,7 @@ class Editor {
|
|
|
6221
6411
|
query(document.body).append(this.popupContainer);
|
|
6222
6412
|
this.togglePlaceholderClass(htmlParser.getHTML());
|
|
6223
6413
|
this.container.append(fragment);
|
|
6224
|
-
Editor.plugin.loadAll(this);
|
|
6414
|
+
this.unmountPluginMap = Editor.plugin.loadAll(this);
|
|
6225
6415
|
if (!this.readonly) {
|
|
6226
6416
|
this.selection.updateByBookmark();
|
|
6227
6417
|
this.history.save({
|
|
@@ -6232,30 +6422,53 @@ class Editor {
|
|
|
6232
6422
|
if (this.toolbar) {
|
|
6233
6423
|
this.toolbar.render(this);
|
|
6234
6424
|
}
|
|
6425
|
+
this.root.on('scroll', this.scrollListener);
|
|
6235
6426
|
document.addEventListener('copy', this.copyListener);
|
|
6427
|
+
window.addEventListener('resize', this.resizeListener);
|
|
6236
6428
|
if (!this.readonly) {
|
|
6237
6429
|
document.addEventListener('cut', this.cutListener);
|
|
6238
6430
|
document.addEventListener('paste', this.pasteListener);
|
|
6239
6431
|
document.addEventListener('selectionchange', this.selectionchangeListener);
|
|
6240
6432
|
document.addEventListener('click', this.clickListener);
|
|
6241
|
-
window.addEventListener('resize', this.resizeListener);
|
|
6242
6433
|
this.bindInputEvents();
|
|
6243
6434
|
this.bindHistoryEvents();
|
|
6244
6435
|
}
|
|
6245
6436
|
}
|
|
6246
|
-
// Destroys the
|
|
6437
|
+
// Destroys the editor.
|
|
6247
6438
|
unmount() {
|
|
6439
|
+
// Executes delayed executions immediately.
|
|
6440
|
+
this.updateSelectionRange.flush();
|
|
6441
|
+
this.updateBoxSelectionStyle.flush();
|
|
6442
|
+
this.emitStateChangeEvent.flush();
|
|
6443
|
+
for (const name of this.unmountPluginMap.keys()) {
|
|
6444
|
+
const unmountPlugin = this.unmountPluginMap.get(name);
|
|
6445
|
+
if (unmountPlugin) {
|
|
6446
|
+
unmountPlugin();
|
|
6447
|
+
debug(`The plugin "${name}" unmounted`);
|
|
6448
|
+
}
|
|
6449
|
+
}
|
|
6450
|
+
if (this.toolbar) {
|
|
6451
|
+
this.toolbar.unmount();
|
|
6452
|
+
}
|
|
6453
|
+
this.removeBoxGarbage();
|
|
6454
|
+
this.container.find('lake-box').each(boxNativeNode => {
|
|
6455
|
+
const boxNode = query(boxNativeNode);
|
|
6456
|
+
const box = getBox(boxNode);
|
|
6457
|
+
box.unmount();
|
|
6458
|
+
});
|
|
6248
6459
|
this.event.removeAllListeners();
|
|
6249
6460
|
this.history.event.removeAllListeners();
|
|
6461
|
+
this.root.off();
|
|
6462
|
+
this.root.removeClass('lake-custom-properties');
|
|
6250
6463
|
this.root.empty();
|
|
6251
6464
|
this.popupContainer.remove();
|
|
6252
6465
|
document.removeEventListener('copy', this.copyListener);
|
|
6466
|
+
window.removeEventListener('resize', this.resizeListener);
|
|
6253
6467
|
if (!this.readonly) {
|
|
6254
6468
|
document.removeEventListener('cut', this.cutListener);
|
|
6255
6469
|
document.removeEventListener('paste', this.pasteListener);
|
|
6256
6470
|
document.removeEventListener('selectionchange', this.selectionchangeListener);
|
|
6257
6471
|
document.removeEventListener('click', this.clickListener);
|
|
6258
|
-
window.removeEventListener('resize', this.resizeListener);
|
|
6259
6472
|
}
|
|
6260
6473
|
}
|
|
6261
6474
|
}
|
|
@@ -6902,7 +7115,7 @@ const toolbarItems = [
|
|
|
6902
7115
|
},
|
|
6903
7116
|
];
|
|
6904
7117
|
|
|
6905
|
-
const defaultItems = [
|
|
7118
|
+
const defaultItems$1 = [
|
|
6906
7119
|
'undo',
|
|
6907
7120
|
'redo',
|
|
6908
7121
|
'|',
|
|
@@ -6933,8 +7146,9 @@ class Toolbar {
|
|
|
6933
7146
|
this.allMenuMap = new Map();
|
|
6934
7147
|
this.buttonItemList = [];
|
|
6935
7148
|
this.dropdownItemList = [];
|
|
7149
|
+
this.dropdownList = [];
|
|
6936
7150
|
this.root = query(config.root);
|
|
6937
|
-
this.items = config.items || defaultItems;
|
|
7151
|
+
this.items = config.items || defaultItems$1;
|
|
6938
7152
|
if (config.placement) {
|
|
6939
7153
|
this.placement = config.placement;
|
|
6940
7154
|
}
|
|
@@ -6944,7 +7158,7 @@ class Toolbar {
|
|
|
6944
7158
|
appendDivider() {
|
|
6945
7159
|
this.container.append('<div class="lake-toolbar-divider" />');
|
|
6946
7160
|
}
|
|
6947
|
-
|
|
7161
|
+
appendNormalButton(editor, item) {
|
|
6948
7162
|
const button = new Button({
|
|
6949
7163
|
root: this.container,
|
|
6950
7164
|
name: item.name,
|
|
@@ -6953,10 +7167,6 @@ class Toolbar {
|
|
|
6953
7167
|
tabIndex: -1,
|
|
6954
7168
|
onClick: () => {
|
|
6955
7169
|
editor.focus();
|
|
6956
|
-
const range = editor.selection.range;
|
|
6957
|
-
if (!editor.container.contains(range.commonAncestor)) {
|
|
6958
|
-
range.shrinkAfter(editor.container);
|
|
6959
|
-
}
|
|
6960
7170
|
item.onClick(editor, item.name);
|
|
6961
7171
|
},
|
|
6962
7172
|
});
|
|
@@ -6985,8 +7195,9 @@ class Toolbar {
|
|
|
6985
7195
|
},
|
|
6986
7196
|
});
|
|
6987
7197
|
dropdown.render();
|
|
7198
|
+
this.dropdownList.push(dropdown);
|
|
6988
7199
|
}
|
|
6989
|
-
|
|
7200
|
+
appendUploadButton(editor, item) {
|
|
6990
7201
|
const uploadNode = query(safeTemplate `
|
|
6991
7202
|
<div class="lake-upload" name="${item.name}">
|
|
6992
7203
|
<input type="file" />
|
|
@@ -7088,7 +7299,6 @@ class Toolbar {
|
|
|
7088
7299
|
}
|
|
7089
7300
|
// Renders a toolbar for the specified editor.
|
|
7090
7301
|
render(editor) {
|
|
7091
|
-
this.root.empty();
|
|
7092
7302
|
this.root.append(this.container);
|
|
7093
7303
|
for (const name of this.items) {
|
|
7094
7304
|
if (name === '|') {
|
|
@@ -7107,7 +7317,7 @@ class Toolbar {
|
|
|
7107
7317
|
}
|
|
7108
7318
|
if (item.type === 'button') {
|
|
7109
7319
|
this.buttonItemList.push(item);
|
|
7110
|
-
this.
|
|
7320
|
+
this.appendNormalButton(editor, item);
|
|
7111
7321
|
}
|
|
7112
7322
|
else if (item.type === 'dropdown') {
|
|
7113
7323
|
this.allMenuMap.set(item.name, Dropdown.getMenuMap(item.menuItems, editor.locale));
|
|
@@ -7115,21 +7325,26 @@ class Toolbar {
|
|
|
7115
7325
|
this.appendDropdown(editor, item);
|
|
7116
7326
|
}
|
|
7117
7327
|
else if (item.type === 'upload') {
|
|
7118
|
-
this.
|
|
7328
|
+
this.appendUploadButton(editor, item);
|
|
7119
7329
|
}
|
|
7120
7330
|
}
|
|
7121
7331
|
}
|
|
7122
7332
|
}
|
|
7333
|
+
// Destroys the toolbar.
|
|
7334
|
+
unmount() {
|
|
7335
|
+
for (const dropdown of this.dropdownList) {
|
|
7336
|
+
dropdown.unmount();
|
|
7337
|
+
}
|
|
7338
|
+
this.root.removeClass('lake-custom-properties');
|
|
7339
|
+
this.container.remove();
|
|
7340
|
+
}
|
|
7123
7341
|
}
|
|
7124
7342
|
|
|
7125
|
-
|
|
7343
|
+
var hrBox = {
|
|
7126
7344
|
type: 'block',
|
|
7127
7345
|
name: 'hr',
|
|
7128
7346
|
render: box => {
|
|
7129
7347
|
const editor = box.getEditor();
|
|
7130
|
-
if (!editor) {
|
|
7131
|
-
return;
|
|
7132
|
-
}
|
|
7133
7348
|
const boxContainer = box.getContainer();
|
|
7134
7349
|
const rootNode = query('<div class="lake-hr"><hr /></div>');
|
|
7135
7350
|
boxContainer.empty();
|
|
@@ -7218,15 +7433,12 @@ function getHighlightStyle(CodeMirror) {
|
|
|
7218
7433
|
{ tag: [tags.special(tags.variableName)], color: config.special },
|
|
7219
7434
|
]);
|
|
7220
7435
|
}
|
|
7221
|
-
|
|
7436
|
+
var codeBlockBox = {
|
|
7222
7437
|
type: 'block',
|
|
7223
7438
|
name: 'codeBlock',
|
|
7224
7439
|
render: box => {
|
|
7225
7440
|
var _a;
|
|
7226
7441
|
const editor = box.getEditor();
|
|
7227
|
-
if (!editor) {
|
|
7228
|
-
return;
|
|
7229
|
-
}
|
|
7230
7442
|
const rootNode = query('<div class="lake-code-block" />');
|
|
7231
7443
|
const boxContainer = box.getContainer();
|
|
7232
7444
|
boxContainer.css('width', `${editor.container.innerWidth() - 2}px`);
|
|
@@ -7265,16 +7477,16 @@ const codeBlockBox = {
|
|
|
7265
7477
|
const boxValue = box.value;
|
|
7266
7478
|
const langItem = langItemMap.get(boxValue.lang);
|
|
7267
7479
|
const language = new Compartment();
|
|
7268
|
-
const changeHandler = (value) => {
|
|
7269
|
-
|
|
7270
|
-
|
|
7271
|
-
|
|
7272
|
-
|
|
7273
|
-
|
|
7274
|
-
|
|
7275
|
-
|
|
7276
|
-
|
|
7277
|
-
};
|
|
7480
|
+
const changeHandler = debounce((value) => {
|
|
7481
|
+
editor.selection.updateByRange();
|
|
7482
|
+
if (editor.isComposing) {
|
|
7483
|
+
return;
|
|
7484
|
+
}
|
|
7485
|
+
box.updateValue('code', value);
|
|
7486
|
+
editor.history.save();
|
|
7487
|
+
}, 1, {
|
|
7488
|
+
immediate: false,
|
|
7489
|
+
});
|
|
7278
7490
|
const updateListener = EditorView.updateListener.of((update) => {
|
|
7279
7491
|
if (!update.docChanged) {
|
|
7280
7492
|
return;
|
|
@@ -7333,6 +7545,7 @@ const codeBlockBox = {
|
|
|
7333
7545
|
codeEditor.focus();
|
|
7334
7546
|
});
|
|
7335
7547
|
box.event.on('beforeunmount', () => {
|
|
7548
|
+
dropdown.unmount();
|
|
7336
7549
|
codeEditor.destroy();
|
|
7337
7550
|
editor.event.off('resize', resizeListener);
|
|
7338
7551
|
debug('CodeMirror destroyed');
|
|
@@ -7410,7 +7623,11 @@ class BoxResizer {
|
|
|
7410
7623
|
const pointerNativeNode = pointerNode.get(0);
|
|
7411
7624
|
// The capture will be implicitly released after a pointerup or pointercancel event.
|
|
7412
7625
|
// https://developer.mozilla.org/en-US/docs/Web/API/Element/setPointerCapture
|
|
7413
|
-
|
|
7626
|
+
try {
|
|
7627
|
+
// Test case throws an exception on Firefox.
|
|
7628
|
+
pointerNativeNode.setPointerCapture(pointerEvent.pointerId);
|
|
7629
|
+
}
|
|
7630
|
+
catch ( /* empty */_a) { /* empty */ }
|
|
7414
7631
|
clientX = pointerEvent.clientX;
|
|
7415
7632
|
width = boxContainer.width();
|
|
7416
7633
|
infoNode.show();
|
|
@@ -7490,9 +7707,6 @@ function getImageInfo(url) {
|
|
|
7490
7707
|
// Opens full screen view.
|
|
7491
7708
|
function openFullScreen(box) {
|
|
7492
7709
|
const editor = box.getEditor();
|
|
7493
|
-
if (!editor) {
|
|
7494
|
-
return;
|
|
7495
|
-
}
|
|
7496
7710
|
const dataSource = [];
|
|
7497
7711
|
let currentIndex = 0;
|
|
7498
7712
|
const allImageBox = editor.container.find('lake-box[name="image"]');
|
|
@@ -7570,20 +7784,11 @@ function openFullScreen(box) {
|
|
|
7570
7784
|
}
|
|
7571
7785
|
return placeholderSrc;
|
|
7572
7786
|
});
|
|
7573
|
-
let savedRange;
|
|
7574
7787
|
lightbox.on('openingAnimationEnd', () => {
|
|
7575
|
-
savedRange = editor.selection.range;
|
|
7576
7788
|
box.event.emit('openfullscreen');
|
|
7577
7789
|
});
|
|
7578
7790
|
lightbox.on('destroy', () => {
|
|
7579
|
-
|
|
7580
|
-
if (savedRange) {
|
|
7581
|
-
// fix(image): lose focus when zooming in the iOS
|
|
7582
|
-
editor.selection.range = savedRange;
|
|
7583
|
-
editor.selection.sync();
|
|
7584
|
-
}
|
|
7585
|
-
box.event.emit('closefullscreen');
|
|
7586
|
-
}, 0);
|
|
7791
|
+
box.event.emit('closefullscreen');
|
|
7587
7792
|
});
|
|
7588
7793
|
lightbox.init();
|
|
7589
7794
|
lightbox.loadAndOpen(currentIndex);
|
|
@@ -7592,9 +7797,6 @@ function openFullScreen(box) {
|
|
|
7592
7797
|
function renderError$1(rootNode, box) {
|
|
7593
7798
|
return __awaiter(this, void 0, void 0, function* () {
|
|
7594
7799
|
const editor = box.getEditor();
|
|
7595
|
-
if (!editor) {
|
|
7596
|
-
return;
|
|
7597
|
-
}
|
|
7598
7800
|
const value = box.value;
|
|
7599
7801
|
box.getContainer().css({
|
|
7600
7802
|
width: '',
|
|
@@ -7628,9 +7830,6 @@ function renderError$1(rootNode, box) {
|
|
|
7628
7830
|
function renderUploading(rootNode, box) {
|
|
7629
7831
|
return __awaiter(this, void 0, void 0, function* () {
|
|
7630
7832
|
const editor = box.getEditor();
|
|
7631
|
-
if (!editor) {
|
|
7632
|
-
return;
|
|
7633
|
-
}
|
|
7634
7833
|
const value = box.value;
|
|
7635
7834
|
const imageInfo = yield getImageInfo(value.url);
|
|
7636
7835
|
if (!imageInfo.width || !imageInfo.height) {
|
|
@@ -7688,9 +7887,6 @@ function renderUploading(rootNode, box) {
|
|
|
7688
7887
|
function renderDone(rootNode, box) {
|
|
7689
7888
|
return __awaiter(this, void 0, void 0, function* () {
|
|
7690
7889
|
const editor = box.getEditor();
|
|
7691
|
-
if (!editor) {
|
|
7692
|
-
return;
|
|
7693
|
-
}
|
|
7694
7890
|
const boxContainer = box.getContainer();
|
|
7695
7891
|
const value = box.value;
|
|
7696
7892
|
const imageInfo = yield getImageInfo(value.url);
|
|
@@ -7758,14 +7954,11 @@ function renderDone(rootNode, box) {
|
|
|
7758
7954
|
rootNode.append(imgNode);
|
|
7759
7955
|
});
|
|
7760
7956
|
}
|
|
7761
|
-
|
|
7957
|
+
var imageBox = {
|
|
7762
7958
|
type: 'inline',
|
|
7763
7959
|
name: 'image',
|
|
7764
7960
|
render: box => {
|
|
7765
7961
|
const editor = box.getEditor();
|
|
7766
|
-
if (!editor) {
|
|
7767
|
-
return;
|
|
7768
|
-
}
|
|
7769
7962
|
const value = box.value;
|
|
7770
7963
|
if (editor.readonly && ['uploading', 'loading', 'error'].indexOf(value.status) >= 0) {
|
|
7771
7964
|
box.node.hide();
|
|
@@ -7838,16 +8031,8 @@ function getVideoId(url) {
|
|
|
7838
8031
|
const result = /\w+$/i.exec(url || '');
|
|
7839
8032
|
return result ? result[0] : '';
|
|
7840
8033
|
}
|
|
7841
|
-
function getInputValue(videoNode, name) {
|
|
7842
|
-
const inputElement = videoNode.find(`input[name="${name}"]`);
|
|
7843
|
-
const nativeInputElement = inputElement.get(0);
|
|
7844
|
-
return nativeInputElement.value;
|
|
7845
|
-
}
|
|
7846
8034
|
function appendButtonGroup(box) {
|
|
7847
8035
|
const editor = box.getEditor();
|
|
7848
|
-
if (!editor) {
|
|
7849
|
-
return;
|
|
7850
|
-
}
|
|
7851
8036
|
const boxContainer = box.getContainer();
|
|
7852
8037
|
const videoNode = boxContainer.find('.lake-video');
|
|
7853
8038
|
const buttonGroupNode = query(safeTemplate `
|
|
@@ -7869,9 +8054,6 @@ function appendButtonGroup(box) {
|
|
|
7869
8054
|
}
|
|
7870
8055
|
function showVideo(box) {
|
|
7871
8056
|
const editor = box.getEditor();
|
|
7872
|
-
if (!editor) {
|
|
7873
|
-
return;
|
|
7874
|
-
}
|
|
7875
8057
|
const boxContainer = box.getContainer();
|
|
7876
8058
|
const value = box.value;
|
|
7877
8059
|
const width = value.width || 560;
|
|
@@ -7920,14 +8102,11 @@ function showVideo(box) {
|
|
|
7920
8102
|
}
|
|
7921
8103
|
rootNode.append(iframeNode);
|
|
7922
8104
|
}
|
|
7923
|
-
|
|
8105
|
+
var videoBox = {
|
|
7924
8106
|
type: 'inline',
|
|
7925
8107
|
name: 'video',
|
|
7926
8108
|
render: box => {
|
|
7927
8109
|
const editor = box.getEditor();
|
|
7928
|
-
if (!editor) {
|
|
7929
|
-
return;
|
|
7930
|
-
}
|
|
7931
8110
|
const locale = editor.locale;
|
|
7932
8111
|
const value = box.value;
|
|
7933
8112
|
const boxContainer = box.getContainer();
|
|
@@ -7959,7 +8138,7 @@ const videoBox = {
|
|
|
7959
8138
|
type: 'primary',
|
|
7960
8139
|
text: locale.video.embed(),
|
|
7961
8140
|
onClick: () => {
|
|
7962
|
-
const url =
|
|
8141
|
+
const url = formNode.find('input[name="url"]').value();
|
|
7963
8142
|
if (url.indexOf('https://www.youtube.com/') < 0 || getVideoId(url) === '') {
|
|
7964
8143
|
editor.config.onMessage('error', locale.video.urlError());
|
|
7965
8144
|
return;
|
|
@@ -8003,9 +8182,6 @@ const boxToolbarItems = [
|
|
|
8003
8182
|
tooltip: locale => locale.file.remove(),
|
|
8004
8183
|
onClick: box => {
|
|
8005
8184
|
const editor = box.getEditor();
|
|
8006
|
-
if (!editor) {
|
|
8007
|
-
return;
|
|
8008
|
-
}
|
|
8009
8185
|
editor.selection.removeBox(box);
|
|
8010
8186
|
editor.history.save();
|
|
8011
8187
|
},
|
|
@@ -8013,10 +8189,6 @@ const boxToolbarItems = [
|
|
|
8013
8189
|
];
|
|
8014
8190
|
function appendContent(rootNode, box) {
|
|
8015
8191
|
return __awaiter(this, void 0, void 0, function* () {
|
|
8016
|
-
const editor = box.getEditor();
|
|
8017
|
-
if (!editor) {
|
|
8018
|
-
return;
|
|
8019
|
-
}
|
|
8020
8192
|
const value = box.value;
|
|
8021
8193
|
const infoNode = query(safeTemplate `
|
|
8022
8194
|
<div class="lake-file-info">
|
|
@@ -8047,14 +8219,11 @@ function appendContent(rootNode, box) {
|
|
|
8047
8219
|
rootNode.append(infoNode);
|
|
8048
8220
|
});
|
|
8049
8221
|
}
|
|
8050
|
-
|
|
8222
|
+
var fileBox = {
|
|
8051
8223
|
type: 'inline',
|
|
8052
8224
|
name: 'file',
|
|
8053
8225
|
render: box => {
|
|
8054
8226
|
const editor = box.getEditor();
|
|
8055
|
-
if (!editor) {
|
|
8056
|
-
return;
|
|
8057
|
-
}
|
|
8058
8227
|
const value = box.value;
|
|
8059
8228
|
if (editor.readonly && ['uploading', 'error'].indexOf(value.status) >= 0) {
|
|
8060
8229
|
box.node.hide();
|
|
@@ -8081,14 +8250,11 @@ const fileBox = {
|
|
|
8081
8250
|
},
|
|
8082
8251
|
};
|
|
8083
8252
|
|
|
8084
|
-
|
|
8253
|
+
var emojiBox = {
|
|
8085
8254
|
type: 'inline',
|
|
8086
8255
|
name: 'emoji',
|
|
8087
8256
|
render: box => {
|
|
8088
8257
|
const editor = box.getEditor();
|
|
8089
|
-
if (!editor) {
|
|
8090
|
-
return;
|
|
8091
|
-
}
|
|
8092
8258
|
const value = box.value;
|
|
8093
8259
|
const boxContainer = box.getContainer();
|
|
8094
8260
|
const rootNode = query(safeTemplate `
|
|
@@ -8105,9 +8271,6 @@ const emojiBox = {
|
|
|
8105
8271
|
const defaultExpression = String.raw `\sqrt{x}`;
|
|
8106
8272
|
function renderError(box) {
|
|
8107
8273
|
const editor = box.getEditor();
|
|
8108
|
-
if (!editor) {
|
|
8109
|
-
return;
|
|
8110
|
-
}
|
|
8111
8274
|
if (editor.readonly) {
|
|
8112
8275
|
box.node.hide();
|
|
8113
8276
|
return;
|
|
@@ -8124,14 +8287,11 @@ function renderError(box) {
|
|
|
8124
8287
|
Please check if the "katex" library is added to this page.
|
|
8125
8288
|
`.trim());
|
|
8126
8289
|
}
|
|
8127
|
-
|
|
8290
|
+
var equationBox = {
|
|
8128
8291
|
type: 'inline',
|
|
8129
8292
|
name: 'equation',
|
|
8130
8293
|
render: box => {
|
|
8131
8294
|
const editor = box.getEditor();
|
|
8132
|
-
if (!editor) {
|
|
8133
|
-
return;
|
|
8134
|
-
}
|
|
8135
8295
|
const rootNode = query('<div class="lake-equation" />');
|
|
8136
8296
|
const boxContainer = box.getContainer();
|
|
8137
8297
|
boxContainer.empty();
|
|
@@ -8160,10 +8320,9 @@ const equationBox = {
|
|
|
8160
8320
|
`);
|
|
8161
8321
|
rootNode.append(formNode);
|
|
8162
8322
|
const textareaNode = formNode.find('textarea');
|
|
8163
|
-
|
|
8164
|
-
textareaNativeNode.value = defaultCode;
|
|
8323
|
+
textareaNode.value(defaultCode);
|
|
8165
8324
|
textareaNode.on('input', () => {
|
|
8166
|
-
const code =
|
|
8325
|
+
const code = textareaNode.value().trim();
|
|
8167
8326
|
viewNode.html(window.katex.renderToString(code || defaultExpression, {
|
|
8168
8327
|
throwOnError: false,
|
|
8169
8328
|
}));
|
|
@@ -9145,8 +9304,7 @@ var formatPainter = (editor) => {
|
|
|
9145
9304
|
if (editor.container.contains(targetNode)) {
|
|
9146
9305
|
return;
|
|
9147
9306
|
}
|
|
9148
|
-
|
|
9149
|
-
if (buttonNode.length > 0) {
|
|
9307
|
+
if (targetNode.closest('button[name="formatPainter"]').length > 0) {
|
|
9150
9308
|
return;
|
|
9151
9309
|
}
|
|
9152
9310
|
editor.container.removeClass(formatPainterClassName);
|
|
@@ -9207,7 +9365,7 @@ class LinkPopup {
|
|
|
9207
9365
|
if (!this.linkNode) {
|
|
9208
9366
|
return;
|
|
9209
9367
|
}
|
|
9210
|
-
const url = this.
|
|
9368
|
+
const url = this.container.find('input[name="url"]').value();
|
|
9211
9369
|
this.writeClipboardText(url).then((error) => {
|
|
9212
9370
|
const svgNode = this.container.find('button[name="copy"] svg');
|
|
9213
9371
|
svgNode.hide();
|
|
@@ -9253,7 +9411,7 @@ class LinkPopup {
|
|
|
9253
9411
|
if (!this.linkNode) {
|
|
9254
9412
|
return;
|
|
9255
9413
|
}
|
|
9256
|
-
const url = this.
|
|
9414
|
+
const url = this.container.find('input[name="url"]').value();
|
|
9257
9415
|
window.open(url);
|
|
9258
9416
|
},
|
|
9259
9417
|
});
|
|
@@ -9313,22 +9471,15 @@ class LinkPopup {
|
|
|
9313
9471
|
});
|
|
9314
9472
|
button.render();
|
|
9315
9473
|
}
|
|
9316
|
-
|
|
9317
|
-
|
|
9318
|
-
const nativeInputElement = inputElement.get(0);
|
|
9319
|
-
return nativeInputElement.value;
|
|
9320
|
-
}
|
|
9321
|
-
setInputValue(name, value) {
|
|
9322
|
-
const inputElement = this.container.find(`input[name="${name}"]`);
|
|
9323
|
-
const nativeInputElement = inputElement.get(0);
|
|
9324
|
-
nativeInputElement.value = value;
|
|
9474
|
+
get visible() {
|
|
9475
|
+
return this.container.get(0).isConnected && this.container.computedCSS('display') !== 'none';
|
|
9325
9476
|
}
|
|
9326
9477
|
save() {
|
|
9327
9478
|
if (!this.linkNode) {
|
|
9328
9479
|
return;
|
|
9329
9480
|
}
|
|
9330
|
-
const url = this.
|
|
9331
|
-
let title = this.
|
|
9481
|
+
const url = this.container.find('input[name="url"]').value();
|
|
9482
|
+
let title = this.container.find('input[name="title"]').value();
|
|
9332
9483
|
if (url === '' && title === '') {
|
|
9333
9484
|
this.linkNode.remove();
|
|
9334
9485
|
return;
|
|
@@ -9339,32 +9490,27 @@ class LinkPopup {
|
|
|
9339
9490
|
this.linkNode.attr('href', url);
|
|
9340
9491
|
this.linkNode.text(title);
|
|
9341
9492
|
}
|
|
9342
|
-
|
|
9493
|
+
position() {
|
|
9343
9494
|
if (!this.linkNode) {
|
|
9344
9495
|
return;
|
|
9345
9496
|
}
|
|
9346
|
-
const position =
|
|
9497
|
+
const position = nodePosition(this.linkNode);
|
|
9347
9498
|
if (position.left < 0 || position.right < 0 || position.top < 0 || position.bottom < 0) {
|
|
9348
9499
|
this.container.css('visibility', 'hidden');
|
|
9349
9500
|
return;
|
|
9350
9501
|
}
|
|
9351
9502
|
this.container.css('visibility', '');
|
|
9352
9503
|
const linkNativeNode = this.linkNode.get(0);
|
|
9353
|
-
// Returns a DOMRect object providing information about the size of an element and its position relative to the viewport.
|
|
9354
9504
|
const linkRect = linkNativeNode.getBoundingClientRect();
|
|
9355
9505
|
const linkX = linkRect.x + window.scrollX;
|
|
9356
9506
|
const linkY = linkRect.y + window.scrollY;
|
|
9357
|
-
// link.x + popup.width > window.width
|
|
9358
9507
|
if (linkRect.x + this.container.width() > window.innerWidth) {
|
|
9359
|
-
// link.x + window.scrollX - (popup.width - link.width)
|
|
9360
9508
|
this.container.css('left', `${linkX - this.container.width() + linkRect.width}px`);
|
|
9361
9509
|
}
|
|
9362
9510
|
else {
|
|
9363
9511
|
this.container.css('left', `${linkX}px`);
|
|
9364
9512
|
}
|
|
9365
|
-
// link.y + link.height + popup.height > window.height
|
|
9366
9513
|
if (linkRect.y + linkRect.height + this.container.height() > window.innerHeight) {
|
|
9367
|
-
// link.y + window.scrollY - popup.height
|
|
9368
9514
|
this.container.css('top', `${linkY - this.container.height()}px`);
|
|
9369
9515
|
}
|
|
9370
9516
|
else {
|
|
@@ -9388,13 +9534,13 @@ class LinkPopup {
|
|
|
9388
9534
|
this.linkNode = linkNode;
|
|
9389
9535
|
const url = linkNode.attr('href');
|
|
9390
9536
|
const title = linkNode.text();
|
|
9391
|
-
this.
|
|
9537
|
+
this.container.find('input[name="url"]').value(url);
|
|
9392
9538
|
if (title !== url) {
|
|
9393
|
-
this.
|
|
9539
|
+
this.container.find('input[name="title"]').value(title);
|
|
9394
9540
|
}
|
|
9395
9541
|
this.container.css('visibility', 'hidden');
|
|
9396
9542
|
this.container.show();
|
|
9397
|
-
this.
|
|
9543
|
+
this.position();
|
|
9398
9544
|
this.container.css('visibility', '');
|
|
9399
9545
|
this.container.find('input[name="url"]').focus();
|
|
9400
9546
|
}
|
|
@@ -9415,31 +9561,38 @@ var link = (editor) => {
|
|
|
9415
9561
|
const range = editor.selection.range;
|
|
9416
9562
|
range.setStartAfter(node);
|
|
9417
9563
|
range.collapseToStart();
|
|
9564
|
+
editor.selection.sync();
|
|
9418
9565
|
editor.history.save();
|
|
9419
9566
|
},
|
|
9420
9567
|
onRemove: node => {
|
|
9421
9568
|
const range = editor.selection.range;
|
|
9422
9569
|
range.setStartAfter(node);
|
|
9423
9570
|
range.collapseToStart();
|
|
9571
|
+
editor.selection.sync();
|
|
9424
9572
|
editor.history.save();
|
|
9425
9573
|
},
|
|
9426
9574
|
});
|
|
9427
|
-
editor.
|
|
9428
|
-
popup.
|
|
9575
|
+
editor.event.on('scroll', () => {
|
|
9576
|
+
popup.position();
|
|
9429
9577
|
});
|
|
9430
9578
|
editor.event.on('resize', () => {
|
|
9431
|
-
popup.
|
|
9579
|
+
popup.position();
|
|
9432
9580
|
});
|
|
9433
9581
|
editor.event.on('click', (targetNode) => {
|
|
9434
|
-
if (
|
|
9582
|
+
if (popup.container.contains(targetNode)) {
|
|
9435
9583
|
return;
|
|
9436
9584
|
}
|
|
9437
|
-
|
|
9438
|
-
if (linkNode.length === 0) {
|
|
9439
|
-
popup.hide();
|
|
9585
|
+
if (targetNode.closest('button[name="link"]').length > 0) {
|
|
9440
9586
|
return;
|
|
9441
9587
|
}
|
|
9442
|
-
|
|
9588
|
+
const linkNode = targetNode.closest('a');
|
|
9589
|
+
if (linkNode.length === 0 ||
|
|
9590
|
+
!editor.container.contains(linkNode) ||
|
|
9591
|
+
linkNode.closest('lake-box').length > 0) {
|
|
9592
|
+
if (!popup.visible) {
|
|
9593
|
+
return;
|
|
9594
|
+
}
|
|
9595
|
+
editor.selection.sync();
|
|
9443
9596
|
popup.hide();
|
|
9444
9597
|
return;
|
|
9445
9598
|
}
|
|
@@ -9621,8 +9774,10 @@ var equation = (editor) => {
|
|
|
9621
9774
|
editor.command.add('equation', {
|
|
9622
9775
|
execute: (value) => {
|
|
9623
9776
|
const box = editor.selection.insertBox('equation', value);
|
|
9624
|
-
editor.selection.selectBox(box);
|
|
9625
9777
|
editor.history.save();
|
|
9778
|
+
const boxContainer = box.getContainer();
|
|
9779
|
+
boxContainer.addClass('lake-box-activated');
|
|
9780
|
+
boxContainer.find('textarea').focus();
|
|
9626
9781
|
},
|
|
9627
9782
|
});
|
|
9628
9783
|
};
|
|
@@ -10194,7 +10349,8 @@ var backspaceKey = (editor) => {
|
|
|
10194
10349
|
const boxNode = range.commonAncestor.closest('lake-box');
|
|
10195
10350
|
const box = getBox(boxNode);
|
|
10196
10351
|
const boxValue = box.value;
|
|
10197
|
-
if (box.name === 'codeBlock' &&
|
|
10352
|
+
if (range.isCollapsed && box.name === 'codeBlock' &&
|
|
10353
|
+
(boxValue.code === undefined || boxValue.code === '')) {
|
|
10198
10354
|
event.preventDefault();
|
|
10199
10355
|
editor.selection.removeBox(box);
|
|
10200
10356
|
editor.history.save();
|
|
@@ -10442,7 +10598,7 @@ var arrowKeys = (editor) => {
|
|
|
10442
10598
|
if (editor.readonly) {
|
|
10443
10599
|
return;
|
|
10444
10600
|
}
|
|
10445
|
-
editor.keystroke.setKeydown('
|
|
10601
|
+
editor.keystroke.setKeydown('left', event => {
|
|
10446
10602
|
const range = editor.selection.range;
|
|
10447
10603
|
if (range.isInsideBox) {
|
|
10448
10604
|
return;
|
|
@@ -10482,7 +10638,7 @@ var arrowKeys = (editor) => {
|
|
|
10482
10638
|
range.selectBox(prevNode);
|
|
10483
10639
|
}
|
|
10484
10640
|
});
|
|
10485
|
-
editor.keystroke.setKeydown('
|
|
10641
|
+
editor.keystroke.setKeydown('right', event => {
|
|
10486
10642
|
const range = editor.selection.range;
|
|
10487
10643
|
if (range.isInsideBox) {
|
|
10488
10644
|
return;
|
|
@@ -10522,7 +10678,7 @@ var arrowKeys = (editor) => {
|
|
|
10522
10678
|
range.selectBox(nextNode);
|
|
10523
10679
|
}
|
|
10524
10680
|
});
|
|
10525
|
-
editor.keystroke.setKeydown('
|
|
10681
|
+
editor.keystroke.setKeydown('up', event => {
|
|
10526
10682
|
const range = editor.selection.range;
|
|
10527
10683
|
if (range.isInsideBox) {
|
|
10528
10684
|
return;
|
|
@@ -10541,7 +10697,7 @@ var arrowKeys = (editor) => {
|
|
|
10541
10697
|
range.collapseToStart();
|
|
10542
10698
|
}
|
|
10543
10699
|
});
|
|
10544
|
-
editor.keystroke.setKeydown('
|
|
10700
|
+
editor.keystroke.setKeydown('down', event => {
|
|
10545
10701
|
const range = editor.selection.range;
|
|
10546
10702
|
if (range.isInsideBox) {
|
|
10547
10703
|
return;
|
|
@@ -10583,6 +10739,539 @@ var escapeKey = (editor) => {
|
|
|
10583
10739
|
});
|
|
10584
10740
|
};
|
|
10585
10741
|
|
|
10742
|
+
const slashItems = [
|
|
10743
|
+
{
|
|
10744
|
+
name: 'heading1',
|
|
10745
|
+
type: 'button',
|
|
10746
|
+
icon: icons.get('heading1'),
|
|
10747
|
+
title: locale => locale.slash.heading1(),
|
|
10748
|
+
description: locale => locale.slash.heading1Desc(),
|
|
10749
|
+
onClick: editor => {
|
|
10750
|
+
editor.command.execute('heading', 'h1');
|
|
10751
|
+
},
|
|
10752
|
+
},
|
|
10753
|
+
{
|
|
10754
|
+
name: 'heading2',
|
|
10755
|
+
type: 'button',
|
|
10756
|
+
icon: icons.get('heading2'),
|
|
10757
|
+
title: locale => locale.slash.heading2(),
|
|
10758
|
+
description: locale => locale.slash.heading2Desc(),
|
|
10759
|
+
onClick: editor => {
|
|
10760
|
+
editor.command.execute('heading', 'h2');
|
|
10761
|
+
},
|
|
10762
|
+
},
|
|
10763
|
+
{
|
|
10764
|
+
name: 'heading3',
|
|
10765
|
+
type: 'button',
|
|
10766
|
+
icon: icons.get('heading3'),
|
|
10767
|
+
title: locale => locale.slash.heading3(),
|
|
10768
|
+
description: locale => locale.slash.heading3Desc(),
|
|
10769
|
+
onClick: editor => {
|
|
10770
|
+
editor.command.execute('heading', 'h3');
|
|
10771
|
+
},
|
|
10772
|
+
},
|
|
10773
|
+
{
|
|
10774
|
+
name: 'heading4',
|
|
10775
|
+
type: 'button',
|
|
10776
|
+
icon: icons.get('heading4'),
|
|
10777
|
+
title: locale => locale.slash.heading4(),
|
|
10778
|
+
description: locale => locale.slash.heading4Desc(),
|
|
10779
|
+
onClick: editor => {
|
|
10780
|
+
editor.command.execute('heading', 'h4');
|
|
10781
|
+
},
|
|
10782
|
+
},
|
|
10783
|
+
{
|
|
10784
|
+
name: 'heading5',
|
|
10785
|
+
type: 'button',
|
|
10786
|
+
icon: icons.get('heading5'),
|
|
10787
|
+
title: locale => locale.slash.heading5(),
|
|
10788
|
+
description: locale => locale.slash.heading5Desc(),
|
|
10789
|
+
onClick: editor => {
|
|
10790
|
+
editor.command.execute('heading', 'h5');
|
|
10791
|
+
},
|
|
10792
|
+
},
|
|
10793
|
+
{
|
|
10794
|
+
name: 'heading6',
|
|
10795
|
+
type: 'button',
|
|
10796
|
+
icon: icons.get('heading6'),
|
|
10797
|
+
title: locale => locale.slash.heading6(),
|
|
10798
|
+
description: locale => locale.slash.heading6Desc(),
|
|
10799
|
+
onClick: editor => {
|
|
10800
|
+
editor.command.execute('heading', 'h6');
|
|
10801
|
+
},
|
|
10802
|
+
},
|
|
10803
|
+
{
|
|
10804
|
+
name: 'paragraph',
|
|
10805
|
+
type: 'button',
|
|
10806
|
+
icon: icons.get('paragraph'),
|
|
10807
|
+
title: locale => locale.slash.paragraph(),
|
|
10808
|
+
description: locale => locale.slash.paragraphDesc(),
|
|
10809
|
+
onClick: editor => {
|
|
10810
|
+
editor.command.execute('heading', 'p');
|
|
10811
|
+
},
|
|
10812
|
+
},
|
|
10813
|
+
{
|
|
10814
|
+
name: 'blockQuote',
|
|
10815
|
+
type: 'button',
|
|
10816
|
+
icon: icons.get('blockQuote'),
|
|
10817
|
+
title: locale => locale.slash.blockQuote(),
|
|
10818
|
+
description: locale => locale.slash.blockQuoteDesc(),
|
|
10819
|
+
onClick: (editor, value) => {
|
|
10820
|
+
editor.command.execute(value);
|
|
10821
|
+
},
|
|
10822
|
+
},
|
|
10823
|
+
{
|
|
10824
|
+
name: 'numberedList',
|
|
10825
|
+
type: 'button',
|
|
10826
|
+
icon: icons.get('numberedList'),
|
|
10827
|
+
title: locale => locale.slash.numberedList(),
|
|
10828
|
+
description: locale => locale.slash.numberedListDesc(),
|
|
10829
|
+
onClick: editor => {
|
|
10830
|
+
editor.command.execute('list', 'numbered');
|
|
10831
|
+
},
|
|
10832
|
+
},
|
|
10833
|
+
{
|
|
10834
|
+
name: 'bulletedList',
|
|
10835
|
+
type: 'button',
|
|
10836
|
+
icon: icons.get('bulletedList'),
|
|
10837
|
+
title: locale => locale.slash.bulletedList(),
|
|
10838
|
+
description: locale => locale.slash.bulletedListDesc(),
|
|
10839
|
+
onClick: editor => {
|
|
10840
|
+
editor.command.execute('list', 'bulleted');
|
|
10841
|
+
},
|
|
10842
|
+
},
|
|
10843
|
+
{
|
|
10844
|
+
name: 'checklist',
|
|
10845
|
+
type: 'button',
|
|
10846
|
+
icon: icons.get('checklist'),
|
|
10847
|
+
title: locale => locale.slash.checklist(),
|
|
10848
|
+
description: locale => locale.slash.checklistDesc(),
|
|
10849
|
+
onClick: editor => {
|
|
10850
|
+
editor.command.execute('list', 'checklist');
|
|
10851
|
+
},
|
|
10852
|
+
},
|
|
10853
|
+
{
|
|
10854
|
+
name: 'hr',
|
|
10855
|
+
type: 'button',
|
|
10856
|
+
icon: icons.get('hr'),
|
|
10857
|
+
title: locale => locale.slash.hr(),
|
|
10858
|
+
description: locale => locale.slash.hrDesc(),
|
|
10859
|
+
onClick: (editor, value) => {
|
|
10860
|
+
editor.command.execute(value);
|
|
10861
|
+
},
|
|
10862
|
+
},
|
|
10863
|
+
{
|
|
10864
|
+
name: 'codeBlock',
|
|
10865
|
+
type: 'button',
|
|
10866
|
+
icon: icons.get('codeBlock'),
|
|
10867
|
+
title: locale => locale.slash.codeBlock(),
|
|
10868
|
+
description: locale => locale.slash.codeBlockDesc(),
|
|
10869
|
+
onClick: (editor, value) => {
|
|
10870
|
+
editor.command.execute(value);
|
|
10871
|
+
},
|
|
10872
|
+
},
|
|
10873
|
+
{
|
|
10874
|
+
name: 'video',
|
|
10875
|
+
type: 'button',
|
|
10876
|
+
icon: icons.get('video'),
|
|
10877
|
+
title: locale => locale.slash.video(),
|
|
10878
|
+
description: locale => locale.slash.videoDesc(),
|
|
10879
|
+
onClick: (editor, value) => {
|
|
10880
|
+
editor.command.execute(value);
|
|
10881
|
+
},
|
|
10882
|
+
},
|
|
10883
|
+
{
|
|
10884
|
+
name: 'equation',
|
|
10885
|
+
type: 'button',
|
|
10886
|
+
icon: icons.get('equation'),
|
|
10887
|
+
title: locale => locale.slash.equation(),
|
|
10888
|
+
description: locale => locale.slash.equationDesc(),
|
|
10889
|
+
onClick: (editor, value) => {
|
|
10890
|
+
editor.command.execute(value);
|
|
10891
|
+
},
|
|
10892
|
+
},
|
|
10893
|
+
{
|
|
10894
|
+
name: 'image',
|
|
10895
|
+
type: 'upload',
|
|
10896
|
+
icon: icons.get('image'),
|
|
10897
|
+
title: locale => locale.slash.image(),
|
|
10898
|
+
description: locale => locale.slash.imageDesc(),
|
|
10899
|
+
accept: 'image/*',
|
|
10900
|
+
multiple: true,
|
|
10901
|
+
},
|
|
10902
|
+
{
|
|
10903
|
+
name: 'file',
|
|
10904
|
+
type: 'upload',
|
|
10905
|
+
icon: icons.get('attachment'),
|
|
10906
|
+
title: locale => locale.slash.file(),
|
|
10907
|
+
description: locale => locale.slash.fileDesc(),
|
|
10908
|
+
accept: '*',
|
|
10909
|
+
multiple: true,
|
|
10910
|
+
},
|
|
10911
|
+
];
|
|
10912
|
+
|
|
10913
|
+
const slashItemMap = new Map();
|
|
10914
|
+
for (const item of slashItems) {
|
|
10915
|
+
slashItemMap.set(item.name, item);
|
|
10916
|
+
}
|
|
10917
|
+
class SlashPopup {
|
|
10918
|
+
constructor(config) {
|
|
10919
|
+
this.range = null;
|
|
10920
|
+
this.noMouseEvent = false;
|
|
10921
|
+
this.keyword = null;
|
|
10922
|
+
this.keydownListener = (event) => {
|
|
10923
|
+
if (isKeyHotkey('escape', event)) {
|
|
10924
|
+
event.preventDefault();
|
|
10925
|
+
this.hide();
|
|
10926
|
+
return;
|
|
10927
|
+
}
|
|
10928
|
+
const isDownKey = isKeyHotkey('down', event);
|
|
10929
|
+
const isUpKey = isKeyHotkey('up', event);
|
|
10930
|
+
const isEnterKey = isKeyHotkey('enter', event);
|
|
10931
|
+
if (!isDownKey && !isUpKey && !isEnterKey) {
|
|
10932
|
+
return;
|
|
10933
|
+
}
|
|
10934
|
+
const selectedItemNode = this.container.find('.lake-slash-item-selected');
|
|
10935
|
+
if (selectedItemNode.length === 0) {
|
|
10936
|
+
const firstItem = this.container.find('.lake-slash-item').eq(0);
|
|
10937
|
+
scrollToNode(firstItem, {
|
|
10938
|
+
behavior: 'instant',
|
|
10939
|
+
block: 'start',
|
|
10940
|
+
});
|
|
10941
|
+
firstItem.addClass('lake-slash-item-selected');
|
|
10942
|
+
return;
|
|
10943
|
+
}
|
|
10944
|
+
this.noMouseEvent = true;
|
|
10945
|
+
if (isDownKey) {
|
|
10946
|
+
event.preventDefault();
|
|
10947
|
+
let nextItemNode = selectedItemNode.next();
|
|
10948
|
+
if (nextItemNode.length === 0) {
|
|
10949
|
+
nextItemNode = this.container.find('.lake-slash-item').eq(0);
|
|
10950
|
+
}
|
|
10951
|
+
scrollToNode(nextItemNode, {
|
|
10952
|
+
behavior: 'instant',
|
|
10953
|
+
block: 'end',
|
|
10954
|
+
});
|
|
10955
|
+
this.container.find('.lake-slash-item').removeClass('lake-slash-item-selected');
|
|
10956
|
+
nextItemNode.addClass('lake-slash-item-selected');
|
|
10957
|
+
}
|
|
10958
|
+
else if (isUpKey) {
|
|
10959
|
+
event.preventDefault();
|
|
10960
|
+
let prevItemNode = selectedItemNode.prev();
|
|
10961
|
+
if (prevItemNode.length === 0) {
|
|
10962
|
+
const itemNode = this.container.find('.lake-slash-item');
|
|
10963
|
+
prevItemNode = itemNode.eq(itemNode.length - 1);
|
|
10964
|
+
}
|
|
10965
|
+
scrollToNode(prevItemNode, {
|
|
10966
|
+
behavior: 'instant',
|
|
10967
|
+
block: 'start',
|
|
10968
|
+
});
|
|
10969
|
+
this.container.find('.lake-slash-item').removeClass('lake-slash-item-selected');
|
|
10970
|
+
prevItemNode.addClass('lake-slash-item-selected');
|
|
10971
|
+
}
|
|
10972
|
+
else if (isEnterKey) {
|
|
10973
|
+
event.preventDefault();
|
|
10974
|
+
selectedItemNode.emit('click');
|
|
10975
|
+
}
|
|
10976
|
+
window.setTimeout(() => {
|
|
10977
|
+
this.noMouseEvent = false;
|
|
10978
|
+
}, 50);
|
|
10979
|
+
};
|
|
10980
|
+
this.clickListener = (targetNode) => {
|
|
10981
|
+
if (this.container.contains(targetNode)) {
|
|
10982
|
+
return;
|
|
10983
|
+
}
|
|
10984
|
+
this.hide();
|
|
10985
|
+
};
|
|
10986
|
+
this.scrollListener = () => this.position();
|
|
10987
|
+
this.resizeListener = () => this.position();
|
|
10988
|
+
this.editor = config.editor;
|
|
10989
|
+
this.items = config.items;
|
|
10990
|
+
this.root = config.editor.popupContainer;
|
|
10991
|
+
this.container = query('<ul class="lake-slash-popup" />');
|
|
10992
|
+
}
|
|
10993
|
+
getItem(name) {
|
|
10994
|
+
if (typeof name !== 'string') {
|
|
10995
|
+
return name;
|
|
10996
|
+
}
|
|
10997
|
+
const item = slashItemMap.get(name);
|
|
10998
|
+
if (!item) {
|
|
10999
|
+
throw new Error(`SlashItem "${name}" has not been defined yet.`);
|
|
11000
|
+
}
|
|
11001
|
+
return item;
|
|
11002
|
+
}
|
|
11003
|
+
emptyBlock() {
|
|
11004
|
+
const range = this.editor.selection.range;
|
|
11005
|
+
const block = range.commonAncestor.closestBlock();
|
|
11006
|
+
this.hide();
|
|
11007
|
+
block.empty();
|
|
11008
|
+
appendBreak(block);
|
|
11009
|
+
range.shrinkBefore(block);
|
|
11010
|
+
}
|
|
11011
|
+
appendItem(item) {
|
|
11012
|
+
const editor = this.editor;
|
|
11013
|
+
const itemTitle = typeof item.title === 'string' ? item.title : item.title(editor.locale);
|
|
11014
|
+
const itemDescription = typeof item.description === 'string' ? item.description : item.description(editor.locale);
|
|
11015
|
+
const itemNode = query(safeTemplate `
|
|
11016
|
+
<li class="lake-slash-item" name="${item.name}">
|
|
11017
|
+
<div class="lake-slash-icon"></div>
|
|
11018
|
+
<div class="lake-slash-text">
|
|
11019
|
+
<div class="lake-slash-title">${itemTitle}</div>
|
|
11020
|
+
<div class="lake-slash-description">${itemDescription}</div>
|
|
11021
|
+
</div>
|
|
11022
|
+
</li>
|
|
11023
|
+
`);
|
|
11024
|
+
const icon = item.icon;
|
|
11025
|
+
if (icon) {
|
|
11026
|
+
itemNode.find('.lake-slash-icon').append(icon);
|
|
11027
|
+
}
|
|
11028
|
+
this.container.append(itemNode);
|
|
11029
|
+
itemNode.on('mouseenter', () => {
|
|
11030
|
+
if (this.noMouseEvent) {
|
|
11031
|
+
return;
|
|
11032
|
+
}
|
|
11033
|
+
this.container.find('.lake-slash-item').removeClass('lake-slash-item-selected');
|
|
11034
|
+
itemNode.addClass('lake-slash-item-selected');
|
|
11035
|
+
});
|
|
11036
|
+
itemNode.on('mouseleave', () => {
|
|
11037
|
+
if (this.noMouseEvent) {
|
|
11038
|
+
return;
|
|
11039
|
+
}
|
|
11040
|
+
itemNode.removeClass('lake-slash-item-selected');
|
|
11041
|
+
});
|
|
11042
|
+
if (item.type === 'upload') {
|
|
11043
|
+
itemNode.append('<input type="file" />');
|
|
11044
|
+
const fileNode = itemNode.find('input[type="file"]');
|
|
11045
|
+
const fileNativeNode = fileNode.get(0);
|
|
11046
|
+
if (item.accept) {
|
|
11047
|
+
fileNode.attr('accept', item.accept);
|
|
11048
|
+
}
|
|
11049
|
+
if (item.multiple === true) {
|
|
11050
|
+
fileNode.attr('multiple', 'true');
|
|
11051
|
+
}
|
|
11052
|
+
fileNode.on('click', event => event.stopPropagation());
|
|
11053
|
+
fileNode.on('change', event => {
|
|
11054
|
+
editor.focus();
|
|
11055
|
+
this.emptyBlock();
|
|
11056
|
+
const target = event.target;
|
|
11057
|
+
const files = target.files || [];
|
|
11058
|
+
for (const file of files) {
|
|
11059
|
+
uploadFile({
|
|
11060
|
+
editor,
|
|
11061
|
+
name: item.name,
|
|
11062
|
+
file,
|
|
11063
|
+
onError: error => editor.config.onMessage('error', error),
|
|
11064
|
+
});
|
|
11065
|
+
}
|
|
11066
|
+
});
|
|
11067
|
+
itemNode.on('click', () => {
|
|
11068
|
+
fileNativeNode.click();
|
|
11069
|
+
});
|
|
11070
|
+
}
|
|
11071
|
+
else {
|
|
11072
|
+
itemNode.on('click', () => {
|
|
11073
|
+
editor.focus();
|
|
11074
|
+
this.emptyBlock();
|
|
11075
|
+
item.onClick(editor, item.name);
|
|
11076
|
+
});
|
|
11077
|
+
}
|
|
11078
|
+
}
|
|
11079
|
+
get visible() {
|
|
11080
|
+
return this.container.get(0).isConnected && this.container.computedCSS('display') !== 'none';
|
|
11081
|
+
}
|
|
11082
|
+
search(keyword) {
|
|
11083
|
+
const editor = this.editor;
|
|
11084
|
+
const localeEnglish = i18nObject('en-US');
|
|
11085
|
+
keyword = keyword.toLowerCase();
|
|
11086
|
+
const items = [];
|
|
11087
|
+
for (const name of this.items) {
|
|
11088
|
+
const item = this.getItem(name);
|
|
11089
|
+
let itemTitle = typeof item.title === 'string' ? item.title : item.title(editor.locale);
|
|
11090
|
+
itemTitle = itemTitle.toLowerCase();
|
|
11091
|
+
let itemTitleEnglish = typeof item.title === 'string' ? item.title : item.title(localeEnglish);
|
|
11092
|
+
itemTitleEnglish = itemTitleEnglish.toLowerCase();
|
|
11093
|
+
if (itemTitle.indexOf(keyword) >= 0 ||
|
|
11094
|
+
itemTitle.replace(/\s+/g, '').indexOf(keyword) >= 0 ||
|
|
11095
|
+
itemTitleEnglish.indexOf(keyword) >= 0 ||
|
|
11096
|
+
itemTitleEnglish.replace(/\s+/g, '').indexOf(keyword) >= 0) {
|
|
11097
|
+
items.push(typeof name === 'string' ? item.name : name);
|
|
11098
|
+
}
|
|
11099
|
+
}
|
|
11100
|
+
return items;
|
|
11101
|
+
}
|
|
11102
|
+
position() {
|
|
11103
|
+
if (!this.range) {
|
|
11104
|
+
return;
|
|
11105
|
+
}
|
|
11106
|
+
this.container.css('visibility', '');
|
|
11107
|
+
const rangeRect = this.range.get().getBoundingClientRect();
|
|
11108
|
+
const rangeX = rangeRect.x + window.scrollX;
|
|
11109
|
+
const rangeY = rangeRect.y + window.scrollY;
|
|
11110
|
+
if (rangeRect.x + this.container.width() > window.innerWidth) {
|
|
11111
|
+
this.container.css('left', `${rangeX - this.container.width() + rangeRect.width}px`);
|
|
11112
|
+
}
|
|
11113
|
+
else {
|
|
11114
|
+
this.container.css('left', `${rangeX}px`);
|
|
11115
|
+
}
|
|
11116
|
+
if (rangeRect.y + rangeRect.height + this.container.height() > window.innerHeight) {
|
|
11117
|
+
this.container.css('top', `${rangeY - this.container.height() - 5}px`);
|
|
11118
|
+
}
|
|
11119
|
+
else {
|
|
11120
|
+
this.container.css('top', `${rangeY + rangeRect.height + 5}px`);
|
|
11121
|
+
}
|
|
11122
|
+
}
|
|
11123
|
+
render() {
|
|
11124
|
+
this.root.append(this.container);
|
|
11125
|
+
this.update();
|
|
11126
|
+
}
|
|
11127
|
+
update(keyword = null) {
|
|
11128
|
+
if (keyword !== null && this.keyword === keyword) {
|
|
11129
|
+
return;
|
|
11130
|
+
}
|
|
11131
|
+
const items = keyword !== null ? this.search(keyword) : this.items;
|
|
11132
|
+
if (items.length === 0) {
|
|
11133
|
+
this.hide();
|
|
11134
|
+
return;
|
|
11135
|
+
}
|
|
11136
|
+
this.keyword = keyword;
|
|
11137
|
+
this.container.empty();
|
|
11138
|
+
for (const name of items) {
|
|
11139
|
+
const item = this.getItem(name);
|
|
11140
|
+
this.appendItem(item);
|
|
11141
|
+
}
|
|
11142
|
+
const selectedItemNode = this.container.find('.lake-slash-item-selected');
|
|
11143
|
+
if (selectedItemNode.length === 0) {
|
|
11144
|
+
this.container.find('.lake-slash-item').eq(0).addClass('lake-slash-item-selected');
|
|
11145
|
+
}
|
|
11146
|
+
this.position();
|
|
11147
|
+
}
|
|
11148
|
+
show(range, keyword) {
|
|
11149
|
+
const editor = this.editor;
|
|
11150
|
+
if (this.root.find('.lake-slash-popup').length === 0) {
|
|
11151
|
+
this.render();
|
|
11152
|
+
}
|
|
11153
|
+
else {
|
|
11154
|
+
this.update();
|
|
11155
|
+
}
|
|
11156
|
+
this.range = range;
|
|
11157
|
+
this.container.css('visibility', 'hidden');
|
|
11158
|
+
this.container.show();
|
|
11159
|
+
this.position();
|
|
11160
|
+
// for fixing the container's width
|
|
11161
|
+
this.container.css('width', '');
|
|
11162
|
+
this.container.css('width', `${this.container.width()}px`);
|
|
11163
|
+
if (keyword) {
|
|
11164
|
+
this.update(keyword);
|
|
11165
|
+
}
|
|
11166
|
+
this.container.css('visibility', '');
|
|
11167
|
+
document.addEventListener('keydown', this.keydownListener, true);
|
|
11168
|
+
editor.event.on('click', this.clickListener);
|
|
11169
|
+
editor.event.on('scroll', this.scrollListener);
|
|
11170
|
+
editor.event.on('resize', this.resizeListener);
|
|
11171
|
+
}
|
|
11172
|
+
hide() {
|
|
11173
|
+
const editor = this.editor;
|
|
11174
|
+
this.range = null;
|
|
11175
|
+
this.container.hide();
|
|
11176
|
+
document.removeEventListener('keydown', this.keydownListener, true);
|
|
11177
|
+
editor.event.off('click', this.clickListener);
|
|
11178
|
+
editor.event.off('scroll', this.scrollListener);
|
|
11179
|
+
editor.event.off('resize', this.resizeListener);
|
|
11180
|
+
}
|
|
11181
|
+
unmount() {
|
|
11182
|
+
this.hide();
|
|
11183
|
+
this.container.remove();
|
|
11184
|
+
}
|
|
11185
|
+
}
|
|
11186
|
+
|
|
11187
|
+
const defaultItems = [
|
|
11188
|
+
'heading1',
|
|
11189
|
+
'heading2',
|
|
11190
|
+
'heading3',
|
|
11191
|
+
'heading4',
|
|
11192
|
+
'heading5',
|
|
11193
|
+
'heading6',
|
|
11194
|
+
'paragraph',
|
|
11195
|
+
'blockQuote',
|
|
11196
|
+
'numberedList',
|
|
11197
|
+
'bulletedList',
|
|
11198
|
+
'checklist',
|
|
11199
|
+
'hr',
|
|
11200
|
+
];
|
|
11201
|
+
function getKeyword(block) {
|
|
11202
|
+
let text = block.text().trim();
|
|
11203
|
+
text = text.replace(/[\u200B\u2060]/g, '');
|
|
11204
|
+
if (!/^\//.test(text)) {
|
|
11205
|
+
return null;
|
|
11206
|
+
}
|
|
11207
|
+
return text.substring(1);
|
|
11208
|
+
}
|
|
11209
|
+
function showPopup(editor, popup) {
|
|
11210
|
+
const range = editor.selection.range;
|
|
11211
|
+
if (!range.isCollapsed) {
|
|
11212
|
+
return;
|
|
11213
|
+
}
|
|
11214
|
+
const block = range.getBlocks()[0];
|
|
11215
|
+
if (!block) {
|
|
11216
|
+
return;
|
|
11217
|
+
}
|
|
11218
|
+
if (block.find('lake-box').length > 0) {
|
|
11219
|
+
return;
|
|
11220
|
+
}
|
|
11221
|
+
const keyword = getKeyword(block);
|
|
11222
|
+
if (keyword === null) {
|
|
11223
|
+
return;
|
|
11224
|
+
}
|
|
11225
|
+
const slashRange = range.clone();
|
|
11226
|
+
slashRange.selectNodeContents(block);
|
|
11227
|
+
popup.show(slashRange, keyword);
|
|
11228
|
+
}
|
|
11229
|
+
var slash = (editor) => {
|
|
11230
|
+
editor.setPluginConfig('slash', {
|
|
11231
|
+
items: defaultItems,
|
|
11232
|
+
});
|
|
11233
|
+
if (editor.readonly) {
|
|
11234
|
+
return;
|
|
11235
|
+
}
|
|
11236
|
+
const popup = new SlashPopup({
|
|
11237
|
+
editor,
|
|
11238
|
+
items: editor.config.slash.items,
|
|
11239
|
+
});
|
|
11240
|
+
editor.container.on('keyup', event => {
|
|
11241
|
+
if (editor.isComposing) {
|
|
11242
|
+
return;
|
|
11243
|
+
}
|
|
11244
|
+
const keyboardEvent = event;
|
|
11245
|
+
if (isKeyHotkey(['down', 'up', 'enter'], keyboardEvent)) {
|
|
11246
|
+
return;
|
|
11247
|
+
}
|
|
11248
|
+
if (!popup.visible) {
|
|
11249
|
+
if (isKeyHotkey('/', keyboardEvent)) {
|
|
11250
|
+
showPopup(editor, popup);
|
|
11251
|
+
return;
|
|
11252
|
+
}
|
|
11253
|
+
if (isKeyHotkey(['backspace', 'delete'], keyboardEvent)) {
|
|
11254
|
+
showPopup(editor, popup);
|
|
11255
|
+
}
|
|
11256
|
+
else {
|
|
11257
|
+
return;
|
|
11258
|
+
}
|
|
11259
|
+
}
|
|
11260
|
+
const range = editor.selection.range;
|
|
11261
|
+
const block = range.getBlocks()[0];
|
|
11262
|
+
if (!block) {
|
|
11263
|
+
return;
|
|
11264
|
+
}
|
|
11265
|
+
const keyword = getKeyword(block);
|
|
11266
|
+
if (keyword === null) {
|
|
11267
|
+
popup.hide();
|
|
11268
|
+
return;
|
|
11269
|
+
}
|
|
11270
|
+
popup.update(keyword);
|
|
11271
|
+
});
|
|
11272
|
+
return () => popup.unmount();
|
|
11273
|
+
};
|
|
11274
|
+
|
|
10586
11275
|
Editor.box.add(hrBox);
|
|
10587
11276
|
Editor.box.add(codeBlockBox);
|
|
10588
11277
|
Editor.box.add(imageBox);
|
|
@@ -10590,48 +11279,49 @@ Editor.box.add(videoBox);
|
|
|
10590
11279
|
Editor.box.add(fileBox);
|
|
10591
11280
|
Editor.box.add(emojiBox);
|
|
10592
11281
|
Editor.box.add(equationBox);
|
|
10593
|
-
Editor.plugin.add(copy);
|
|
10594
|
-
Editor.plugin.add(cut);
|
|
10595
|
-
Editor.plugin.add(paste);
|
|
10596
|
-
Editor.plugin.add(drop);
|
|
10597
|
-
Editor.plugin.add(undo);
|
|
10598
|
-
Editor.plugin.add(redo);
|
|
10599
|
-
Editor.plugin.add(selectAll);
|
|
10600
|
-
Editor.plugin.add(heading);
|
|
10601
|
-
Editor.plugin.add(blockQuote);
|
|
10602
|
-
Editor.plugin.add(list);
|
|
10603
|
-
Editor.plugin.add(align);
|
|
10604
|
-
Editor.plugin.add(indent);
|
|
10605
|
-
Editor.plugin.add(bold);
|
|
10606
|
-
Editor.plugin.add(italic);
|
|
10607
|
-
Editor.plugin.add(underline);
|
|
10608
|
-
Editor.plugin.add(strikethrough);
|
|
10609
|
-
Editor.plugin.add(subscript);
|
|
10610
|
-
Editor.plugin.add(superscript);
|
|
10611
|
-
Editor.plugin.add(code);
|
|
10612
|
-
Editor.plugin.add(fontFamily);
|
|
10613
|
-
Editor.plugin.add(fontSize);
|
|
10614
|
-
Editor.plugin.add(fontColor);
|
|
10615
|
-
Editor.plugin.add(highlight);
|
|
10616
|
-
Editor.plugin.add(removeFormat);
|
|
10617
|
-
Editor.plugin.add(formatPainter);
|
|
10618
|
-
Editor.plugin.add(link);
|
|
10619
|
-
Editor.plugin.add(hr);
|
|
10620
|
-
Editor.plugin.add(codeBlock);
|
|
10621
|
-
Editor.plugin.add(image);
|
|
10622
|
-
Editor.plugin.add(video);
|
|
10623
|
-
Editor.plugin.add(file);
|
|
10624
|
-
Editor.plugin.add(emoji);
|
|
10625
|
-
Editor.plugin.add(equation);
|
|
10626
|
-
Editor.plugin.add(specialCharacter);
|
|
10627
|
-
Editor.plugin.add(markdown);
|
|
10628
|
-
Editor.plugin.add(enterKey);
|
|
10629
|
-
Editor.plugin.add(shiftEnterKey);
|
|
10630
|
-
Editor.plugin.add(backspaceKey);
|
|
10631
|
-
Editor.plugin.add(deleteKey);
|
|
10632
|
-
Editor.plugin.add(tabKey);
|
|
10633
|
-
Editor.plugin.add(arrowKeys);
|
|
10634
|
-
Editor.plugin.add(escapeKey);
|
|
11282
|
+
Editor.plugin.add('copy', copy);
|
|
11283
|
+
Editor.plugin.add('cut', cut);
|
|
11284
|
+
Editor.plugin.add('paste', paste);
|
|
11285
|
+
Editor.plugin.add('drop', drop);
|
|
11286
|
+
Editor.plugin.add('undo', undo);
|
|
11287
|
+
Editor.plugin.add('redo', redo);
|
|
11288
|
+
Editor.plugin.add('selectAll', selectAll);
|
|
11289
|
+
Editor.plugin.add('heading', heading);
|
|
11290
|
+
Editor.plugin.add('blockQuote', blockQuote);
|
|
11291
|
+
Editor.plugin.add('list', list);
|
|
11292
|
+
Editor.plugin.add('align', align);
|
|
11293
|
+
Editor.plugin.add('indent', indent);
|
|
11294
|
+
Editor.plugin.add('bold', bold);
|
|
11295
|
+
Editor.plugin.add('italic', italic);
|
|
11296
|
+
Editor.plugin.add('underline', underline);
|
|
11297
|
+
Editor.plugin.add('strikethrough', strikethrough);
|
|
11298
|
+
Editor.plugin.add('subscript', subscript);
|
|
11299
|
+
Editor.plugin.add('superscript', superscript);
|
|
11300
|
+
Editor.plugin.add('code', code);
|
|
11301
|
+
Editor.plugin.add('fontFamily', fontFamily);
|
|
11302
|
+
Editor.plugin.add('fontSize', fontSize);
|
|
11303
|
+
Editor.plugin.add('fontColor', fontColor);
|
|
11304
|
+
Editor.plugin.add('highlight', highlight);
|
|
11305
|
+
Editor.plugin.add('removeFormat', removeFormat);
|
|
11306
|
+
Editor.plugin.add('formatPainter', formatPainter);
|
|
11307
|
+
Editor.plugin.add('link', link);
|
|
11308
|
+
Editor.plugin.add('hr', hr);
|
|
11309
|
+
Editor.plugin.add('codeBlock', codeBlock);
|
|
11310
|
+
Editor.plugin.add('image', image);
|
|
11311
|
+
Editor.plugin.add('video', video);
|
|
11312
|
+
Editor.plugin.add('file', file);
|
|
11313
|
+
Editor.plugin.add('emoji', emoji);
|
|
11314
|
+
Editor.plugin.add('equation', equation);
|
|
11315
|
+
Editor.plugin.add('specialCharacter', specialCharacter);
|
|
11316
|
+
Editor.plugin.add('markdown', markdown);
|
|
11317
|
+
Editor.plugin.add('enterKey', enterKey);
|
|
11318
|
+
Editor.plugin.add('shiftEnterKey', shiftEnterKey);
|
|
11319
|
+
Editor.plugin.add('backspaceKey', backspaceKey);
|
|
11320
|
+
Editor.plugin.add('deleteKey', deleteKey);
|
|
11321
|
+
Editor.plugin.add('tabKey', tabKey);
|
|
11322
|
+
Editor.plugin.add('arrowKeys', arrowKeys);
|
|
11323
|
+
Editor.plugin.add('escapeKey', escapeKey);
|
|
11324
|
+
Editor.plugin.add('slash', slash);
|
|
10635
11325
|
|
|
10636
11326
|
export { Box, Button, Dropdown, Editor, Fragment, HTMLParser, Nodes, Range, TextParser, Toolbar, index as Utils, addMark, deleteContents, fixList, icons, insertBookmark, insertBox, insertFragment, insertLink, insertNode, removeBox, removeMark, setBlocks, splitBlock$1 as splitBlock, splitMarks, toBookmark };
|
|
10637
11327
|
//# sourceMappingURL=lake.js.map
|