lakelib 0.1.16 → 0.1.18
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 +17 -12
- package/dist/lake.css +121 -1
- package/dist/lake.min.js +29 -22
- package/dist/lake.min.js.map +1 -1
- package/lib/lake.css +121 -1
- package/lib/lake.js +303 -91
- package/lib/lake.js.map +1 -1
- package/lib/types/boxes/equation.d.ts +2 -0
- package/lib/types/css/index.d.ts +2 -0
- package/lib/types/editor.d.ts +1 -2
- package/lib/types/i18n/en-US/index.d.ts +5 -0
- package/lib/types/i18n/ja/index.d.ts +5 -0
- package/lib/types/i18n/ko/index.d.ts +5 -0
- package/lib/types/i18n/types.d.ts +28 -0
- package/lib/types/i18n/zh-CN/index.d.ts +5 -0
- package/lib/types/index.d.ts +1 -1
- package/lib/types/models/box.d.ts +1 -2
- package/lib/types/models/fragment.d.ts +1 -2
- package/lib/types/models/nodes.d.ts +10 -11
- package/lib/types/models/range.d.ts +1 -1
- package/lib/types/operations/insert-node.d.ts +1 -2
- package/lib/types/parsers/html-parser.d.ts +0 -1
- package/lib/types/plugins/equation.d.ts +3 -0
- package/lib/types/plugins/special-character.d.ts +3 -0
- package/lib/types/types/commands.d.ts +20 -0
- package/lib/types/types/native.d.ts +0 -23
- package/lib/types/ui/commands-popup.d.ts +24 -0
- package/lib/types/ui/toolbar.d.ts +1 -2
- package/lib/types/utils/get-box.d.ts +1 -2
- package/lib/types/utils/query.d.ts +1 -2
- package/lib/types/utils/to-node-list.d.ts +1 -2
- package/package.json +4 -2
package/lib/lake.js
CHANGED
|
@@ -2,7 +2,7 @@ import EventEmitter from 'eventemitter3';
|
|
|
2
2
|
import { i18nObject as i18nObject$1 } from 'typesafe-i18n';
|
|
3
3
|
import debounce from 'debounce';
|
|
4
4
|
import isEqual from 'fast-deep-equal/es6';
|
|
5
|
-
import {
|
|
5
|
+
import { isKeyHotkey } from 'is-hotkey';
|
|
6
6
|
import 'photoswipe/style.css';
|
|
7
7
|
import PhotoSwipeLightbox from 'photoswipe/lightbox';
|
|
8
8
|
import PhotoSwipe from 'photoswipe';
|
|
@@ -143,7 +143,9 @@ var attachment = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"32\" height=
|
|
|
143
143
|
|
|
144
144
|
var emoji$1 = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"32\" height=\"32\" fill=\"#000000\" viewBox=\"0 0 256 256\"><path d=\"M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm0,192a88,88,0,1,1,88-88A88.1,88.1,0,0,1,128,216ZM80,108a12,12,0,1,1,12,12A12,12,0,0,1,80,108Zm96,0a12,12,0,1,1-12-12A12,12,0,0,1,176,108Zm-1.07,48c-10.29,17.79-27.4,28-46.93,28s-36.63-10.2-46.92-28a8,8,0,1,1,13.84-8c7.47,12.91,19.21,20,33.08,20s25.61-7.1,33.07-20a8,8,0,0,1,13.86,8Z\"></path></svg>";
|
|
145
145
|
|
|
146
|
-
var specialCharacter = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"32\" height=\"32\" fill=\"#000000\" viewBox=\"0 0 32 32\"><path d=\"M22.7373,25A14.3093,14.3093,0,0,0,27,15C27,8.42,22.58,4,16,4S5,8.42,5,15A14.3093,14.3093,0,0,0,9.2627,25H4v2h8V24.7617A12.5683,12.5683,0,0,1,7,15c0-5.4673,3.5327-9,9-9s9,3.5327,9,9a12.5683,12.5683,0,0,1-5,9.7617V27h8V25Z\"/></svg>";
|
|
146
|
+
var specialCharacter$1 = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"32\" height=\"32\" fill=\"#000000\" viewBox=\"0 0 32 32\"><path d=\"M22.7373,25A14.3093,14.3093,0,0,0,27,15C27,8.42,22.58,4,16,4S5,8.42,5,15A14.3093,14.3093,0,0,0,9.2627,25H4v2h8V24.7617A12.5683,12.5683,0,0,1,7,15c0-5.4673,3.5327-9,9-9s9,3.5327,9,9a12.5683,12.5683,0,0,1-5,9.7617V27h8V25Z\"/></svg>";
|
|
147
|
+
|
|
148
|
+
var equation$1 = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"32\" height=\"32\" fill=\"#000000\" viewBox=\"0 0 256 256\"><path d=\"M184,72V56H80.65l53.6,67a8,8,0,0,1,0,10l-53.6,67H184V184a8,8,0,0,1,16,0v24a8,8,0,0,1-8,8H64a8,8,0,0,1-6.25-13l60-75-60-75A8,8,0,0,1,64,40H192a8,8,0,0,1,8,8V72a8,8,0,0,1-16,0Z\"></path></svg>";
|
|
147
149
|
|
|
148
150
|
var table = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"32\" height=\"32\" fill=\"#000000\" viewBox=\"0 0 256 256\"><path d=\"M224,48H32a8,8,0,0,0-8,8V192a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A8,8,0,0,0,224,48ZM40,112H80v32H40Zm56,0H216v32H96ZM216,64V96H40V64ZM40,160H80v32H40Zm176,32H96V160H216v32Z\"></path></svg>";
|
|
149
151
|
|
|
@@ -224,7 +226,8 @@ const icons = new Map([
|
|
|
224
226
|
['video', video$1],
|
|
225
227
|
['attachment', attachment],
|
|
226
228
|
['emoji', emoji$1],
|
|
227
|
-
['specialCharacter', specialCharacter],
|
|
229
|
+
['specialCharacter', specialCharacter$1],
|
|
230
|
+
['equation', equation$1],
|
|
228
231
|
['table', table],
|
|
229
232
|
]);
|
|
230
233
|
|
|
@@ -428,8 +431,6 @@ function toNodeList(content, valueType) {
|
|
|
428
431
|
return nodeList;
|
|
429
432
|
}
|
|
430
433
|
|
|
431
|
-
const NativeNode = Node;
|
|
432
|
-
|
|
433
434
|
const blockTagNames = new Set([
|
|
434
435
|
'h1',
|
|
435
436
|
'h2',
|
|
@@ -538,7 +539,7 @@ class Nodes {
|
|
|
538
539
|
return false;
|
|
539
540
|
}
|
|
540
541
|
const node = this.get(0);
|
|
541
|
-
return node.nodeType ===
|
|
542
|
+
return node.nodeType === Node.ELEMENT_NODE;
|
|
542
543
|
}
|
|
543
544
|
// Returns a boolean value indicating whether the node is a text node.
|
|
544
545
|
get isText() {
|
|
@@ -546,7 +547,7 @@ class Nodes {
|
|
|
546
547
|
return false;
|
|
547
548
|
}
|
|
548
549
|
const node = this.get(0);
|
|
549
|
-
return node.nodeType ===
|
|
550
|
+
return node.nodeType === Node.TEXT_NODE;
|
|
550
551
|
}
|
|
551
552
|
// Returns a boolean value indicating whether the node is a block element.
|
|
552
553
|
get isBlock() {
|
|
@@ -662,10 +663,18 @@ class Nodes {
|
|
|
662
663
|
}
|
|
663
664
|
const nodeText = this.text();
|
|
664
665
|
const isEmptyText = nodeText === '' || /^[\r\n\u200B\u2060]+$/.test(nodeText);
|
|
665
|
-
if (
|
|
666
|
-
return
|
|
666
|
+
if (!isEmptyText) {
|
|
667
|
+
return false;
|
|
668
|
+
}
|
|
669
|
+
if (this.isElement) {
|
|
670
|
+
if (this.find('lake-box').length > 0) {
|
|
671
|
+
return false;
|
|
672
|
+
}
|
|
673
|
+
if (this.find('br').length > 1) {
|
|
674
|
+
return false;
|
|
675
|
+
}
|
|
667
676
|
}
|
|
668
|
-
return
|
|
677
|
+
return true;
|
|
669
678
|
}
|
|
670
679
|
// Returns a boolean value indicating whether the node and the target node are siblings.
|
|
671
680
|
isSibling(target) {
|
|
@@ -702,7 +711,7 @@ class Nodes {
|
|
|
702
711
|
eachElement(callback) {
|
|
703
712
|
const nodes = this.getAll();
|
|
704
713
|
for (let i = 0; i < nodes.length; i++) {
|
|
705
|
-
if (nodes[i].nodeType ===
|
|
714
|
+
if (nodes[i].nodeType === Node.ELEMENT_NODE) {
|
|
706
715
|
if (callback(nodes[i], i) === false) {
|
|
707
716
|
return this;
|
|
708
717
|
}
|
|
@@ -1237,7 +1246,7 @@ class Nodes {
|
|
|
1237
1246
|
return `node (${node.lakeId}): ${nodeValue}`;
|
|
1238
1247
|
}
|
|
1239
1248
|
// Prints information of the first node.
|
|
1240
|
-
|
|
1249
|
+
info() {
|
|
1241
1250
|
debug(this.toString());
|
|
1242
1251
|
}
|
|
1243
1252
|
}
|
|
@@ -1378,12 +1387,12 @@ class Range {
|
|
|
1378
1387
|
reference = 'right';
|
|
1379
1388
|
}
|
|
1380
1389
|
}
|
|
1381
|
-
else {
|
|
1390
|
+
else if (range.startNode.isText) {
|
|
1382
1391
|
const text = range.startNode.text();
|
|
1383
1392
|
if (range.startOffset < text.length) {
|
|
1384
1393
|
range.setEnd(range.startNode, range.startOffset + 1);
|
|
1385
1394
|
}
|
|
1386
|
-
else {
|
|
1395
|
+
else if (range.startOffset > 0) {
|
|
1387
1396
|
range.setStart(range.startNode, range.startOffset - 1);
|
|
1388
1397
|
reference = 'right';
|
|
1389
1398
|
}
|
|
@@ -1836,7 +1845,7 @@ class Range {
|
|
|
1836
1845
|
return this.range.cloneContents();
|
|
1837
1846
|
}
|
|
1838
1847
|
// Prints information of the range.
|
|
1839
|
-
|
|
1848
|
+
info() {
|
|
1840
1849
|
debug('--- range information ---');
|
|
1841
1850
|
debug('start node:', this.startNode.toString(), ', offset:', this.startOffset);
|
|
1842
1851
|
debug('end node:', this.endNode.toString(), ', offset:', this.endOffset);
|
|
@@ -2874,6 +2883,7 @@ var enUS = {
|
|
|
2874
2883
|
image: 'Image',
|
|
2875
2884
|
file: 'File',
|
|
2876
2885
|
emoji: 'Emoji',
|
|
2886
|
+
equation: 'Equation',
|
|
2877
2887
|
removeColor: 'Remove color',
|
|
2878
2888
|
},
|
|
2879
2889
|
link: {
|
|
@@ -2909,6 +2919,10 @@ var enUS = {
|
|
|
2909
2919
|
codeBlock: {
|
|
2910
2920
|
langType: 'Select language',
|
|
2911
2921
|
},
|
|
2922
|
+
equation: {
|
|
2923
|
+
save: 'Done',
|
|
2924
|
+
placeholder: 'Type a TeX expression',
|
|
2925
|
+
},
|
|
2912
2926
|
};
|
|
2913
2927
|
|
|
2914
2928
|
var zhCN = {
|
|
@@ -2958,6 +2972,7 @@ var zhCN = {
|
|
|
2958
2972
|
image: '图片',
|
|
2959
2973
|
file: '文件',
|
|
2960
2974
|
emoji: '表情',
|
|
2975
|
+
equation: '公式',
|
|
2961
2976
|
removeColor: '默认',
|
|
2962
2977
|
},
|
|
2963
2978
|
link: {
|
|
@@ -2993,6 +3008,10 @@ var zhCN = {
|
|
|
2993
3008
|
codeBlock: {
|
|
2994
3009
|
langType: '选择代码语言',
|
|
2995
3010
|
},
|
|
3011
|
+
equation: {
|
|
3012
|
+
save: '确定',
|
|
3013
|
+
placeholder: '请输入 TeX 公式',
|
|
3014
|
+
},
|
|
2996
3015
|
};
|
|
2997
3016
|
|
|
2998
3017
|
var ja = {
|
|
@@ -3042,6 +3061,7 @@ var ja = {
|
|
|
3042
3061
|
image: '画像',
|
|
3043
3062
|
file: 'ファイル',
|
|
3044
3063
|
emoji: '絵文字',
|
|
3064
|
+
equation: '公式',
|
|
3045
3065
|
removeColor: 'デフォルト',
|
|
3046
3066
|
},
|
|
3047
3067
|
link: {
|
|
@@ -3077,6 +3097,10 @@ var ja = {
|
|
|
3077
3097
|
codeBlock: {
|
|
3078
3098
|
langType: 'コード言語を選択',
|
|
3079
3099
|
},
|
|
3100
|
+
equation: {
|
|
3101
|
+
save: '確認',
|
|
3102
|
+
placeholder: 'TeX 公式を入力してください。',
|
|
3103
|
+
},
|
|
3080
3104
|
};
|
|
3081
3105
|
|
|
3082
3106
|
var ko = {
|
|
@@ -3126,6 +3150,7 @@ var ko = {
|
|
|
3126
3150
|
image: '이미지',
|
|
3127
3151
|
file: '파일',
|
|
3128
3152
|
emoji: '이모지',
|
|
3153
|
+
equation: '수식',
|
|
3129
3154
|
removeColor: '기본색',
|
|
3130
3155
|
},
|
|
3131
3156
|
link: {
|
|
@@ -3161,6 +3186,10 @@ var ko = {
|
|
|
3161
3186
|
codeBlock: {
|
|
3162
3187
|
langType: '코드언어 선택',
|
|
3163
3188
|
},
|
|
3189
|
+
equation: {
|
|
3190
|
+
save: '확인',
|
|
3191
|
+
placeholder: 'TeX 수식을 입력하세요',
|
|
3192
|
+
},
|
|
3164
3193
|
};
|
|
3165
3194
|
|
|
3166
3195
|
const localeTranslations = {
|
|
@@ -3560,7 +3589,7 @@ class Box {
|
|
|
3560
3589
|
if (typeof node === 'string') {
|
|
3561
3590
|
const component = boxes.get(node);
|
|
3562
3591
|
if (component === undefined) {
|
|
3563
|
-
throw new Error(`
|
|
3592
|
+
throw new Error(`The box "${node}" has not been defined yet.`);
|
|
3564
3593
|
}
|
|
3565
3594
|
const type = encode(component.type);
|
|
3566
3595
|
const name = encode(component.name);
|
|
@@ -3573,7 +3602,7 @@ class Box {
|
|
|
3573
3602
|
this.node = query(node);
|
|
3574
3603
|
const component = boxes.get(this.name);
|
|
3575
3604
|
if (component === undefined) {
|
|
3576
|
-
throw new Error(`
|
|
3605
|
+
throw new Error(`The box "${this.name}" has not been defined yet.`);
|
|
3577
3606
|
}
|
|
3578
3607
|
if (component.value && !this.node.hasAttr('value')) {
|
|
3579
3608
|
this.value = component.value;
|
|
@@ -3604,7 +3633,7 @@ class Box {
|
|
|
3604
3633
|
container.removeClass('lake-box-hovered');
|
|
3605
3634
|
});
|
|
3606
3635
|
container.on('click', () => {
|
|
3607
|
-
debug(`
|
|
3636
|
+
debug(`The box "${this.name}" (id = ${this.node.id}) value:`);
|
|
3608
3637
|
debug(this.value);
|
|
3609
3638
|
});
|
|
3610
3639
|
if (this.type === 'block' && this.node.isContentEditable) {
|
|
@@ -3643,7 +3672,7 @@ class Box {
|
|
|
3643
3672
|
}
|
|
3644
3673
|
this.value = value;
|
|
3645
3674
|
}
|
|
3646
|
-
// Returns the editor
|
|
3675
|
+
// Returns an instance of the editor that includes the box.
|
|
3647
3676
|
getEditor() {
|
|
3648
3677
|
const container = this.node.closest('div[contenteditable]');
|
|
3649
3678
|
return container.length > 0 ? editors.get(container.id) : undefined;
|
|
@@ -3689,15 +3718,16 @@ class Box {
|
|
|
3689
3718
|
if (component === undefined) {
|
|
3690
3719
|
return;
|
|
3691
3720
|
}
|
|
3721
|
+
this.event.emit('beforeunmount');
|
|
3722
|
+
this.event.removeAllListeners();
|
|
3692
3723
|
this.addFramework();
|
|
3693
3724
|
const content = component.render(this);
|
|
3694
3725
|
if (content !== undefined) {
|
|
3695
3726
|
const container = this.getContainer();
|
|
3696
|
-
|
|
3697
|
-
|
|
3698
|
-
morph(container, newContainer);
|
|
3727
|
+
container.empty();
|
|
3728
|
+
container.append(content);
|
|
3699
3729
|
}
|
|
3700
|
-
debug(`
|
|
3730
|
+
debug(`The box "${this.name}" (id: ${this.node.id}) rendered`);
|
|
3701
3731
|
}
|
|
3702
3732
|
// Destroys a rendered box.
|
|
3703
3733
|
unmount() {
|
|
@@ -3705,7 +3735,7 @@ class Box {
|
|
|
3705
3735
|
this.event.emit('beforeunmount');
|
|
3706
3736
|
this.event.removeAllListeners();
|
|
3707
3737
|
this.node.empty();
|
|
3708
|
-
debug(`
|
|
3738
|
+
debug(`The box "${this.name}" (id: ${this.node.id}) unmounted`);
|
|
3709
3739
|
}
|
|
3710
3740
|
// Returns a HTML string of the box.
|
|
3711
3741
|
getHTML() {
|
|
@@ -4273,13 +4303,7 @@ class HTMLParser {
|
|
|
4273
4303
|
}
|
|
4274
4304
|
return html.trim();
|
|
4275
4305
|
}
|
|
4276
|
-
// Returns
|
|
4277
|
-
getNodeList() {
|
|
4278
|
-
const html = this.getHTML();
|
|
4279
|
-
const body = this.parseHTML(html);
|
|
4280
|
-
return body.children();
|
|
4281
|
-
}
|
|
4282
|
-
// Returns the result as document fragment.
|
|
4306
|
+
// Returns a document fragment.
|
|
4283
4307
|
getFragment() {
|
|
4284
4308
|
const html = this.getHTML();
|
|
4285
4309
|
const body = this.parseHTML(html);
|
|
@@ -5117,7 +5141,7 @@ function removeBox(range) {
|
|
|
5117
5141
|
return box;
|
|
5118
5142
|
}
|
|
5119
5143
|
|
|
5120
|
-
var version = "0.1.
|
|
5144
|
+
var version = "0.1.18";
|
|
5121
5145
|
|
|
5122
5146
|
// Returns the attributes of the element as an key-value object.
|
|
5123
5147
|
function getAttributes(node) {
|
|
@@ -5295,7 +5319,7 @@ class Selection {
|
|
|
5295
5319
|
insertBox(boxName, boxValue) {
|
|
5296
5320
|
const box = insertBox(this.range, boxName, boxValue);
|
|
5297
5321
|
if (!box) {
|
|
5298
|
-
throw new Error(`
|
|
5322
|
+
throw new Error(`The box "${boxName}" cannot be inserted outside the editor.`);
|
|
5299
5323
|
}
|
|
5300
5324
|
return box;
|
|
5301
5325
|
}
|
|
@@ -5418,7 +5442,8 @@ class History {
|
|
|
5418
5442
|
},
|
|
5419
5443
|
afterAttributeUpdated: (attributeName, nativeNode) => {
|
|
5420
5444
|
const node = new Nodes(nativeNode);
|
|
5421
|
-
if (
|
|
5445
|
+
if (['name', 'value'].indexOf(attributeName) >= 0 && node.name === 'lake-box') {
|
|
5446
|
+
getBox(node).unmount();
|
|
5422
5447
|
const instanceMap = getInstanceMap(container.id);
|
|
5423
5448
|
instanceMap.delete(node.id);
|
|
5424
5449
|
}
|
|
@@ -5434,7 +5459,7 @@ class History {
|
|
|
5434
5459
|
this.removeIdfromBoxes(otherContainer);
|
|
5435
5460
|
}
|
|
5436
5461
|
get canUndo() {
|
|
5437
|
-
return this.index > 1 && !!this.list[this.index -
|
|
5462
|
+
return this.index > 1 && !!this.list[this.index - 2];
|
|
5438
5463
|
}
|
|
5439
5464
|
get canRedo() {
|
|
5440
5465
|
return !!this.list[this.index];
|
|
@@ -5554,53 +5579,71 @@ class History {
|
|
|
5554
5579
|
}
|
|
5555
5580
|
}
|
|
5556
5581
|
|
|
5557
|
-
const
|
|
5558
|
-
['
|
|
5582
|
+
const aliasMap = new Map([
|
|
5583
|
+
['arrow-left', 'left'],
|
|
5584
|
+
['arrow-right', 'right'],
|
|
5585
|
+
['arrow-up', 'up'],
|
|
5586
|
+
['arrow-down', 'down'],
|
|
5559
5587
|
]);
|
|
5560
5588
|
class Keystroke {
|
|
5561
5589
|
constructor(container) {
|
|
5562
5590
|
this.keydownEventList = [];
|
|
5563
5591
|
this.keyupEventList = [];
|
|
5564
5592
|
this.container = container;
|
|
5593
|
+
this.container.on('keydown', event => {
|
|
5594
|
+
const keyboardEvent = event;
|
|
5595
|
+
if (keyboardEvent.isComposing) {
|
|
5596
|
+
return;
|
|
5597
|
+
}
|
|
5598
|
+
for (const item of this.keydownEventList) {
|
|
5599
|
+
if (isKeyHotkey(item.type, keyboardEvent)) {
|
|
5600
|
+
if (item.listener(keyboardEvent) === false) {
|
|
5601
|
+
break;
|
|
5602
|
+
}
|
|
5603
|
+
}
|
|
5604
|
+
}
|
|
5605
|
+
});
|
|
5606
|
+
this.container.on('keyup', event => {
|
|
5607
|
+
const keyboardEvent = event;
|
|
5608
|
+
if (keyboardEvent.isComposing) {
|
|
5609
|
+
return;
|
|
5610
|
+
}
|
|
5611
|
+
for (const item of this.keyupEventList) {
|
|
5612
|
+
if (isKeyHotkey(item.type, keyboardEvent)) {
|
|
5613
|
+
if (item.listener(keyboardEvent) === false) {
|
|
5614
|
+
break;
|
|
5615
|
+
}
|
|
5616
|
+
}
|
|
5617
|
+
}
|
|
5618
|
+
});
|
|
5565
5619
|
}
|
|
5566
5620
|
normalizeType(type) {
|
|
5567
5621
|
var _a;
|
|
5568
|
-
type = (_a =
|
|
5569
|
-
type = type.replace(/(^|\+|\s)mod(\+|\s|$)/g, '$1$mod$2').
|
|
5570
|
-
replace(/shift|control|alt|meta|enter|tab|backspace|delete|space|escape|arrow-left|arrow-right|arrow-up|arrow-down/, (match) => match.charAt(0).toUpperCase() + camelCase(match.substring(1))).
|
|
5571
|
-
replace(/(^|\+|\s)([a-z])(\+|\s|$)/g, (match, p1, p2, p3) => `${p1}Key${p2.toUpperCase()}${p3}`);
|
|
5622
|
+
type = (_a = aliasMap.get(type)) !== null && _a !== void 0 ? _a : type;
|
|
5572
5623
|
return type;
|
|
5573
5624
|
}
|
|
5574
5625
|
// Sets a keydown shortcut.
|
|
5575
5626
|
setKeydown(type, listener) {
|
|
5576
5627
|
type = this.normalizeType(type);
|
|
5577
|
-
const handler = createKeybindingsHandler({
|
|
5578
|
-
[type]: event => listener(event),
|
|
5579
|
-
});
|
|
5580
5628
|
this.keydownEventList.push({
|
|
5581
5629
|
type,
|
|
5582
5630
|
listener,
|
|
5583
5631
|
});
|
|
5584
|
-
this.container.on('keydown', handler);
|
|
5585
5632
|
}
|
|
5586
5633
|
// Sets a keyup shortcut.
|
|
5587
5634
|
setKeyup(type, listener) {
|
|
5588
5635
|
type = this.normalizeType(type);
|
|
5589
|
-
const handler = createKeybindingsHandler({
|
|
5590
|
-
[type]: event => listener(event),
|
|
5591
|
-
});
|
|
5592
5636
|
this.keyupEventList.push({
|
|
5593
5637
|
type,
|
|
5594
5638
|
listener,
|
|
5595
5639
|
});
|
|
5596
|
-
this.container.on('keyup', handler);
|
|
5597
5640
|
}
|
|
5598
5641
|
// Executes the keydown shortcuts.
|
|
5599
5642
|
keydown(type) {
|
|
5600
5643
|
type = this.normalizeType(type);
|
|
5601
5644
|
for (const item of this.keydownEventList) {
|
|
5602
5645
|
if (item.type === type) {
|
|
5603
|
-
if (item.listener(new
|
|
5646
|
+
if (item.listener(new KeyboardEvent(type)) === false) {
|
|
5604
5647
|
break;
|
|
5605
5648
|
}
|
|
5606
5649
|
}
|
|
@@ -5611,7 +5654,7 @@ class Keystroke {
|
|
|
5611
5654
|
type = this.normalizeType(type);
|
|
5612
5655
|
for (const item of this.keyupEventList) {
|
|
5613
5656
|
if (item.type === type) {
|
|
5614
|
-
if (item.listener(new
|
|
5657
|
+
if (item.listener(new KeyboardEvent(type)) === false) {
|
|
5615
5658
|
break;
|
|
5616
5659
|
}
|
|
5617
5660
|
}
|
|
@@ -5847,7 +5890,7 @@ class Editor {
|
|
|
5847
5890
|
// Adds or Removes a placeholder class.
|
|
5848
5891
|
togglePlaceholderClass(value) {
|
|
5849
5892
|
value = denormalizeValue(value);
|
|
5850
|
-
const className = 'lake-
|
|
5893
|
+
const className = 'lake-placeholder';
|
|
5851
5894
|
if (value.replace('<focus />', '') === '<p><br /></p>') {
|
|
5852
5895
|
this.container.addClass(className);
|
|
5853
5896
|
}
|
|
@@ -5899,6 +5942,18 @@ class Editor {
|
|
|
5899
5942
|
this.container.on('compositionend', () => {
|
|
5900
5943
|
this.isComposing = false;
|
|
5901
5944
|
});
|
|
5945
|
+
this.container.on('beforeinput', event => {
|
|
5946
|
+
const inputEvent = event;
|
|
5947
|
+
// <p><br /><focus /></p>
|
|
5948
|
+
// When the caret is positioned behind a <br> tag, the input event is triggered twice after inserting a sharp(#) in composition mode.
|
|
5949
|
+
if (this.isComposing && inputEvent.inputType === 'insertText') {
|
|
5950
|
+
inputEvent.preventDefault();
|
|
5951
|
+
this.isComposing = false;
|
|
5952
|
+
this.history.save({
|
|
5953
|
+
inputType: 'insertText',
|
|
5954
|
+
});
|
|
5955
|
+
}
|
|
5956
|
+
});
|
|
5902
5957
|
this.container.on('input', event => {
|
|
5903
5958
|
const inputEvent = event;
|
|
5904
5959
|
// Here setTimeout is necessary because isComposing is not false after ending composition.
|
|
@@ -5910,6 +5965,9 @@ class Editor {
|
|
|
5910
5965
|
}
|
|
5911
5966
|
// isComposing is false after ending composition because compositionend event has been emitted.
|
|
5912
5967
|
if (this.isComposing) {
|
|
5968
|
+
if (inputEvent.inputType === 'insertCompositionText') {
|
|
5969
|
+
this.container.removeClass('lake-placeholder');
|
|
5970
|
+
}
|
|
5913
5971
|
this.event.emit('input', inputEvent);
|
|
5914
5972
|
return;
|
|
5915
5973
|
}
|
|
@@ -5992,6 +6050,7 @@ class Editor {
|
|
|
5992
6050
|
}
|
|
5993
6051
|
// Fixes wrong content, especially empty tag.
|
|
5994
6052
|
fixContent() {
|
|
6053
|
+
const range = this.selection.range;
|
|
5995
6054
|
let changed = false;
|
|
5996
6055
|
let children = this.container.children();
|
|
5997
6056
|
for (const child of children) {
|
|
@@ -6004,7 +6063,7 @@ class Editor {
|
|
|
6004
6063
|
children = this.container.children();
|
|
6005
6064
|
if (children.length === 0) {
|
|
6006
6065
|
this.container.html('<p><br /></p>');
|
|
6007
|
-
|
|
6066
|
+
range.shrinkAfter(this.container);
|
|
6008
6067
|
changed = true;
|
|
6009
6068
|
debug('Content fixed: default paragraph was added');
|
|
6010
6069
|
}
|
|
@@ -6014,11 +6073,23 @@ class Editor {
|
|
|
6014
6073
|
const paragraph = query('<p />');
|
|
6015
6074
|
child.before(paragraph);
|
|
6016
6075
|
paragraph.append(child);
|
|
6017
|
-
|
|
6076
|
+
range.shrinkAfter(paragraph);
|
|
6018
6077
|
changed = true;
|
|
6019
6078
|
debug(`Content fixed: void element "${child.name}" was wrapped in paragraph`);
|
|
6020
6079
|
}
|
|
6021
6080
|
}
|
|
6081
|
+
// In composition mode (e.g., when a user starts entering a Chinese character using a Pinyin IME),
|
|
6082
|
+
// uncompleted text is inserted if the caret is positioned behind a <br> tag.
|
|
6083
|
+
// To fix this bug, the caret needs to be moved to the front of the <br> tag.
|
|
6084
|
+
if (range.isCollapsed) {
|
|
6085
|
+
const prevNode = range.getPrevNode();
|
|
6086
|
+
const nextNode = range.getNextNode();
|
|
6087
|
+
if (prevNode.name === 'br' && nextNode.length === 0) {
|
|
6088
|
+
range.setStartBefore(prevNode);
|
|
6089
|
+
range.collapseToStart();
|
|
6090
|
+
debug('Range fixed: the caret has been moved to the front of the <br> tag');
|
|
6091
|
+
}
|
|
6092
|
+
}
|
|
6022
6093
|
return changed;
|
|
6023
6094
|
}
|
|
6024
6095
|
// Sets default config for a plugin.
|
|
@@ -6660,6 +6731,15 @@ const toolbarItems = [
|
|
|
6660
6731
|
editor.command.execute(value);
|
|
6661
6732
|
},
|
|
6662
6733
|
},
|
|
6734
|
+
{
|
|
6735
|
+
name: 'equation',
|
|
6736
|
+
type: 'button',
|
|
6737
|
+
icon: icons.get('equation'),
|
|
6738
|
+
tooltip: locale => locale.toolbar.equation(),
|
|
6739
|
+
onClick: (editor, value) => {
|
|
6740
|
+
editor.command.execute(value);
|
|
6741
|
+
},
|
|
6742
|
+
},
|
|
6663
6743
|
{
|
|
6664
6744
|
name: 'heading',
|
|
6665
6745
|
type: 'dropdown',
|
|
@@ -7029,8 +7109,10 @@ const hrBox = {
|
|
|
7029
7109
|
if (!editor) {
|
|
7030
7110
|
return;
|
|
7031
7111
|
}
|
|
7112
|
+
const boxContainer = box.getContainer();
|
|
7032
7113
|
const rootNode = query('<div class="lake-hr"><hr /></div>');
|
|
7033
|
-
|
|
7114
|
+
boxContainer.empty();
|
|
7115
|
+
boxContainer.append(rootNode);
|
|
7034
7116
|
rootNode.on('click', () => {
|
|
7035
7117
|
editor.selection.selectBox(box);
|
|
7036
7118
|
});
|
|
@@ -7125,10 +7207,10 @@ const codeBlockBox = {
|
|
|
7125
7207
|
return;
|
|
7126
7208
|
}
|
|
7127
7209
|
const rootNode = query('<div class="lake-code-block" />');
|
|
7128
|
-
const
|
|
7129
|
-
|
|
7130
|
-
|
|
7131
|
-
|
|
7210
|
+
const boxContainer = box.getContainer();
|
|
7211
|
+
boxContainer.css('width', `${editor.container.innerWidth() - 2}px`);
|
|
7212
|
+
boxContainer.empty();
|
|
7213
|
+
boxContainer.append(rootNode);
|
|
7132
7214
|
const codeBlockNativeNode = rootNode.get(0);
|
|
7133
7215
|
if (!codeBlockNativeNode) {
|
|
7134
7216
|
return;
|
|
@@ -7220,7 +7302,7 @@ const codeBlockBox = {
|
|
|
7220
7302
|
});
|
|
7221
7303
|
dropdown.render();
|
|
7222
7304
|
const resizeListener = () => {
|
|
7223
|
-
|
|
7305
|
+
boxContainer.css('width', `${editor.container.innerWidth() - 2}px`);
|
|
7224
7306
|
};
|
|
7225
7307
|
editor.event.on('resize', resizeListener);
|
|
7226
7308
|
rootNode.on('click', () => {
|
|
@@ -7486,7 +7568,7 @@ function openFullScreen(box) {
|
|
|
7486
7568
|
lightbox.loadAndOpen(currentIndex);
|
|
7487
7569
|
}
|
|
7488
7570
|
// Displays error icon and filename.
|
|
7489
|
-
function renderError(rootNode, box) {
|
|
7571
|
+
function renderError$1(rootNode, box) {
|
|
7490
7572
|
return __awaiter(this, void 0, void 0, function* () {
|
|
7491
7573
|
const editor = box.getEditor();
|
|
7492
7574
|
if (!editor) {
|
|
@@ -7531,7 +7613,7 @@ function renderUploading(rootNode, box) {
|
|
|
7531
7613
|
const value = box.value;
|
|
7532
7614
|
const imageInfo = yield getImageInfo(value.url);
|
|
7533
7615
|
if (!imageInfo.width || !imageInfo.height) {
|
|
7534
|
-
yield renderError(rootNode, box);
|
|
7616
|
+
yield renderError$1(rootNode, box);
|
|
7535
7617
|
return;
|
|
7536
7618
|
}
|
|
7537
7619
|
const maxWidth = editor.container.innerWidth() - 2;
|
|
@@ -7595,7 +7677,7 @@ function renderDone(rootNode, box) {
|
|
|
7595
7677
|
return;
|
|
7596
7678
|
}
|
|
7597
7679
|
if (!imageInfo.width || !imageInfo.height) {
|
|
7598
|
-
yield renderError(rootNode, box);
|
|
7680
|
+
yield renderError$1(rootNode, box);
|
|
7599
7681
|
return;
|
|
7600
7682
|
}
|
|
7601
7683
|
let width = value.width;
|
|
@@ -7668,26 +7750,26 @@ const imageBox = {
|
|
|
7668
7750
|
box.node.hide();
|
|
7669
7751
|
return;
|
|
7670
7752
|
}
|
|
7671
|
-
const
|
|
7672
|
-
if (value.width && value.height &&
|
|
7673
|
-
|
|
7753
|
+
const boxContainer = box.getContainer();
|
|
7754
|
+
if (value.width && value.height && boxContainer.find('.lake-progress').length === 0) {
|
|
7755
|
+
boxContainer.css({
|
|
7674
7756
|
width: `${value.width}px`,
|
|
7675
7757
|
height: `${value.height}px`,
|
|
7676
7758
|
});
|
|
7677
|
-
|
|
7759
|
+
boxContainer.empty();
|
|
7678
7760
|
const placeholderNode = query('<div class="lake-image-placeholder" />');
|
|
7679
|
-
|
|
7761
|
+
boxContainer.append(placeholderNode);
|
|
7680
7762
|
const imageIcon = icons.get('image');
|
|
7681
7763
|
if (imageIcon) {
|
|
7682
7764
|
placeholderNode.append(imageIcon);
|
|
7683
7765
|
}
|
|
7684
7766
|
}
|
|
7685
|
-
if (
|
|
7767
|
+
if (boxContainer.first().length === 0) {
|
|
7686
7768
|
// The following code is for unit testing because some test cases need to
|
|
7687
7769
|
// select the content of the box before it is completely loaded.
|
|
7688
7770
|
// Example:
|
|
7689
7771
|
// range.setStart(box.getContainer(), 1);
|
|
7690
|
-
|
|
7772
|
+
boxContainer.append('<div />');
|
|
7691
7773
|
}
|
|
7692
7774
|
// for test
|
|
7693
7775
|
if (value.status === 'loading') {
|
|
@@ -7700,14 +7782,14 @@ const imageBox = {
|
|
|
7700
7782
|
promise = renderUploading(rootNode, box);
|
|
7701
7783
|
}
|
|
7702
7784
|
else if (value.status === 'error') {
|
|
7703
|
-
promise = renderError(rootNode, box);
|
|
7785
|
+
promise = renderError$1(rootNode, box);
|
|
7704
7786
|
}
|
|
7705
7787
|
else {
|
|
7706
7788
|
promise = renderDone(rootNode, box);
|
|
7707
7789
|
}
|
|
7708
7790
|
promise.then(() => {
|
|
7709
|
-
|
|
7710
|
-
|
|
7791
|
+
boxContainer.empty();
|
|
7792
|
+
boxContainer.append(rootNode);
|
|
7711
7793
|
rootNode.find('.lake-button-view').on('click', () => openFullScreen(box));
|
|
7712
7794
|
if (editor.readonly) {
|
|
7713
7795
|
rootNode.find('.lake-button-remove').hide();
|
|
@@ -7867,12 +7949,12 @@ const videoBox = {
|
|
|
7867
7949
|
showVideo(box);
|
|
7868
7950
|
},
|
|
7869
7951
|
});
|
|
7870
|
-
formNode.find('input[name="url"]').on('keydown',
|
|
7871
|
-
'
|
|
7952
|
+
formNode.find('input[name="url"]').on('keydown', event => {
|
|
7953
|
+
if (isKeyHotkey('enter', event)) {
|
|
7872
7954
|
event.preventDefault();
|
|
7873
7955
|
button.node.emit('click');
|
|
7874
|
-
}
|
|
7875
|
-
})
|
|
7956
|
+
}
|
|
7957
|
+
});
|
|
7876
7958
|
button.render();
|
|
7877
7959
|
rootNode.append(formNode);
|
|
7878
7960
|
appendButtonGroup(box);
|
|
@@ -7957,12 +8039,12 @@ const fileBox = {
|
|
|
7957
8039
|
box.node.hide();
|
|
7958
8040
|
return;
|
|
7959
8041
|
}
|
|
7960
|
-
const
|
|
8042
|
+
const boxContainer = box.getContainer();
|
|
7961
8043
|
const rootNode = query('<div class="lake-file" />');
|
|
7962
8044
|
rootNode.addClass(`lake-file-${value.status}`);
|
|
7963
8045
|
appendContent(rootNode, box);
|
|
7964
|
-
|
|
7965
|
-
|
|
8046
|
+
boxContainer.empty();
|
|
8047
|
+
boxContainer.append(rootNode);
|
|
7966
8048
|
if (!editor.readonly) {
|
|
7967
8049
|
rootNode.on('click', () => {
|
|
7968
8050
|
editor.selection.selectBox(box);
|
|
@@ -7987,16 +8069,100 @@ const emojiBox = {
|
|
|
7987
8069
|
return;
|
|
7988
8070
|
}
|
|
7989
8071
|
const value = box.value;
|
|
8072
|
+
const boxContainer = box.getContainer();
|
|
7990
8073
|
const rootNode = query(safeTemplate `
|
|
7991
8074
|
<div class="lake-emoji"><img src="${value.url}" title="${value.title}" /></div>
|
|
7992
8075
|
`);
|
|
7993
|
-
|
|
8076
|
+
boxContainer.empty();
|
|
8077
|
+
boxContainer.append(rootNode);
|
|
7994
8078
|
rootNode.on('click', () => {
|
|
7995
8079
|
editor.selection.selectBox(box);
|
|
7996
8080
|
});
|
|
7997
8081
|
},
|
|
7998
8082
|
};
|
|
7999
8083
|
|
|
8084
|
+
const defaultExpression = String.raw `\sqrt{x}`;
|
|
8085
|
+
function renderError(box) {
|
|
8086
|
+
const editor = box.getEditor();
|
|
8087
|
+
if (!editor) {
|
|
8088
|
+
return;
|
|
8089
|
+
}
|
|
8090
|
+
if (editor.readonly) {
|
|
8091
|
+
box.node.hide();
|
|
8092
|
+
return;
|
|
8093
|
+
}
|
|
8094
|
+
const defaultCode = (box.value.code || '').trim();
|
|
8095
|
+
const rootNode = box.getContainer().find('.lake-equation');
|
|
8096
|
+
rootNode.addClass('lake-equation-error');
|
|
8097
|
+
rootNode.text(defaultCode);
|
|
8098
|
+
rootNode.on('click', () => {
|
|
8099
|
+
editor.selection.selectBox(box);
|
|
8100
|
+
});
|
|
8101
|
+
editor.config.onMessage('warning', `
|
|
8102
|
+
The box "${box.name}" (id: ${box.node.id}) failed to display because window.katex was not found.
|
|
8103
|
+
Please check if the "katex" library is added to this page.
|
|
8104
|
+
`.trim());
|
|
8105
|
+
}
|
|
8106
|
+
const equationBox = {
|
|
8107
|
+
type: 'inline',
|
|
8108
|
+
name: 'equation',
|
|
8109
|
+
render: box => {
|
|
8110
|
+
const editor = box.getEditor();
|
|
8111
|
+
if (!editor) {
|
|
8112
|
+
return;
|
|
8113
|
+
}
|
|
8114
|
+
const rootNode = query('<div class="lake-equation" />');
|
|
8115
|
+
const boxContainer = box.getContainer();
|
|
8116
|
+
boxContainer.empty();
|
|
8117
|
+
boxContainer.append(rootNode);
|
|
8118
|
+
const katex = window.katex;
|
|
8119
|
+
if (!katex) {
|
|
8120
|
+
renderError(box);
|
|
8121
|
+
return;
|
|
8122
|
+
}
|
|
8123
|
+
const defaultCode = (box.value.code || '').trim();
|
|
8124
|
+
const viewNode = query('<div class="lake-equation-view" />');
|
|
8125
|
+
rootNode.append(viewNode);
|
|
8126
|
+
viewNode.html(window.katex.renderToString(defaultCode || defaultExpression, {
|
|
8127
|
+
throwOnError: false,
|
|
8128
|
+
}));
|
|
8129
|
+
viewNode.on('click', () => {
|
|
8130
|
+
editor.selection.selectBox(box);
|
|
8131
|
+
});
|
|
8132
|
+
const formNode = query(safeTemplate `
|
|
8133
|
+
<div class="lake-equation-form">
|
|
8134
|
+
<div class="lake-row">
|
|
8135
|
+
<textarea name="code" placeholder="${editor.locale.equation.placeholder()}"></textarea>
|
|
8136
|
+
</div>
|
|
8137
|
+
<div class="lake-row lake-button-row"></div>
|
|
8138
|
+
</div>
|
|
8139
|
+
`);
|
|
8140
|
+
rootNode.append(formNode);
|
|
8141
|
+
const textareaNode = formNode.find('textarea');
|
|
8142
|
+
const textareaNativeNode = textareaNode.get(0);
|
|
8143
|
+
textareaNativeNode.value = defaultCode;
|
|
8144
|
+
textareaNode.on('input', () => {
|
|
8145
|
+
const code = textareaNativeNode.value.trim();
|
|
8146
|
+
viewNode.html(window.katex.renderToString(code || defaultExpression, {
|
|
8147
|
+
throwOnError: false,
|
|
8148
|
+
}));
|
|
8149
|
+
box.updateValue('code', code);
|
|
8150
|
+
});
|
|
8151
|
+
const button = new Button({
|
|
8152
|
+
root: formNode.find('.lake-button-row'),
|
|
8153
|
+
name: 'save',
|
|
8154
|
+
type: 'primary',
|
|
8155
|
+
text: editor.locale.equation.save(),
|
|
8156
|
+
onClick: () => {
|
|
8157
|
+
editor.selection.range.selectBoxEnd(box.node);
|
|
8158
|
+
editor.selection.sync();
|
|
8159
|
+
editor.history.save();
|
|
8160
|
+
},
|
|
8161
|
+
});
|
|
8162
|
+
button.render();
|
|
8163
|
+
},
|
|
8164
|
+
};
|
|
8165
|
+
|
|
8000
8166
|
var copy = (editor) => {
|
|
8001
8167
|
editor.event.on('copy', event => {
|
|
8002
8168
|
const range = editor.selection.range;
|
|
@@ -8431,6 +8597,7 @@ var undo = (editor) => {
|
|
|
8431
8597
|
return;
|
|
8432
8598
|
}
|
|
8433
8599
|
editor.command.add('undo', {
|
|
8600
|
+
isDisabled: () => !editor.history.canUndo,
|
|
8434
8601
|
execute: () => {
|
|
8435
8602
|
editor.history.undo();
|
|
8436
8603
|
},
|
|
@@ -8450,6 +8617,7 @@ var redo = (editor) => {
|
|
|
8450
8617
|
return;
|
|
8451
8618
|
}
|
|
8452
8619
|
editor.command.add('redo', {
|
|
8620
|
+
isDisabled: () => !editor.history.canRedo,
|
|
8453
8621
|
execute: () => {
|
|
8454
8622
|
editor.history.redo();
|
|
8455
8623
|
},
|
|
@@ -9090,18 +9258,18 @@ class LinkPopup {
|
|
|
9090
9258
|
},
|
|
9091
9259
|
});
|
|
9092
9260
|
button.render();
|
|
9093
|
-
this.container.find('input[name="url"]').on('keydown',
|
|
9094
|
-
'
|
|
9261
|
+
this.container.find('input[name="url"]').on('keydown', event => {
|
|
9262
|
+
if (isKeyHotkey('enter', event)) {
|
|
9095
9263
|
event.preventDefault();
|
|
9096
9264
|
button.node.emit('click');
|
|
9097
|
-
}
|
|
9098
|
-
})
|
|
9099
|
-
this.container.find('input[name="title"]').on('keydown',
|
|
9100
|
-
'
|
|
9265
|
+
}
|
|
9266
|
+
});
|
|
9267
|
+
this.container.find('input[name="title"]').on('keydown', event => {
|
|
9268
|
+
if (isKeyHotkey('enter', event)) {
|
|
9101
9269
|
event.preventDefault();
|
|
9102
9270
|
button.node.emit('click');
|
|
9103
|
-
}
|
|
9104
|
-
})
|
|
9271
|
+
}
|
|
9272
|
+
});
|
|
9105
9273
|
}
|
|
9106
9274
|
// Remove link
|
|
9107
9275
|
appendUnlinkButton() {
|
|
@@ -9424,6 +9592,36 @@ var emoji = (editor) => {
|
|
|
9424
9592
|
});
|
|
9425
9593
|
};
|
|
9426
9594
|
|
|
9595
|
+
var equation = (editor) => {
|
|
9596
|
+
if (!window.katex) {
|
|
9597
|
+
return;
|
|
9598
|
+
}
|
|
9599
|
+
if (editor.readonly) {
|
|
9600
|
+
return;
|
|
9601
|
+
}
|
|
9602
|
+
editor.command.add('equation', {
|
|
9603
|
+
execute: (value) => {
|
|
9604
|
+
const box = editor.selection.insertBox('equation', value);
|
|
9605
|
+
editor.selection.selectBox(box);
|
|
9606
|
+
editor.history.save();
|
|
9607
|
+
},
|
|
9608
|
+
});
|
|
9609
|
+
};
|
|
9610
|
+
|
|
9611
|
+
var specialCharacter = (editor) => {
|
|
9612
|
+
if (editor.readonly) {
|
|
9613
|
+
return;
|
|
9614
|
+
}
|
|
9615
|
+
editor.command.add('specialCharacter', {
|
|
9616
|
+
execute: (value) => {
|
|
9617
|
+
const fragment = new Fragment();
|
|
9618
|
+
fragment.append(document.createTextNode(value));
|
|
9619
|
+
editor.selection.insertFragment(fragment);
|
|
9620
|
+
editor.history.save();
|
|
9621
|
+
},
|
|
9622
|
+
});
|
|
9623
|
+
};
|
|
9624
|
+
|
|
9427
9625
|
const headingTypeMap = new Map([
|
|
9428
9626
|
['#', 'h1'],
|
|
9429
9627
|
['##', 'h2'],
|
|
@@ -9955,6 +10153,12 @@ function mergeWithPreviousBlock(editor, block) {
|
|
|
9955
10153
|
return;
|
|
9956
10154
|
}
|
|
9957
10155
|
removeEmptyMarks(range);
|
|
10156
|
+
const nextNode = range.getNextNode();
|
|
10157
|
+
if (nextNode.name === 'br' && prevBlock.name !== 'p') {
|
|
10158
|
+
nextNode.remove();
|
|
10159
|
+
range.shrinkAfter(prevBlock);
|
|
10160
|
+
return;
|
|
10161
|
+
}
|
|
9958
10162
|
const bookmark = editor.selection.insertBookmark();
|
|
9959
10163
|
mergeNodes(prevBlock, block);
|
|
9960
10164
|
editor.selection.toBookmark(bookmark);
|
|
@@ -10046,7 +10250,8 @@ var backspaceKey = (editor) => {
|
|
|
10046
10250
|
editor.history.save();
|
|
10047
10251
|
return;
|
|
10048
10252
|
}
|
|
10049
|
-
|
|
10253
|
+
const nextNode = range.getNextNode();
|
|
10254
|
+
if (prevNode.name === 'br' && nextNode.length > 0) {
|
|
10050
10255
|
event.preventDefault();
|
|
10051
10256
|
range.setStartBefore(prevNode);
|
|
10052
10257
|
range.collapseToStart();
|
|
@@ -10194,8 +10399,12 @@ var tabKey = (editor) => {
|
|
|
10194
10399
|
if (editor.config.indentWithTab === false) {
|
|
10195
10400
|
return;
|
|
10196
10401
|
}
|
|
10402
|
+
const range = editor.selection.range;
|
|
10403
|
+
if (range.isInsideBox) {
|
|
10404
|
+
return;
|
|
10405
|
+
}
|
|
10197
10406
|
event.preventDefault();
|
|
10198
|
-
const blocks =
|
|
10407
|
+
const blocks = range.getBlocks();
|
|
10199
10408
|
for (const block of blocks) {
|
|
10200
10409
|
if (block.name !== 'p' || block.css('text-indent') === '2em') {
|
|
10201
10410
|
setBlockIndent(block, 'increase');
|
|
@@ -10359,6 +10568,7 @@ Editor.box.add(imageBox);
|
|
|
10359
10568
|
Editor.box.add(videoBox);
|
|
10360
10569
|
Editor.box.add(fileBox);
|
|
10361
10570
|
Editor.box.add(emojiBox);
|
|
10571
|
+
Editor.box.add(equationBox);
|
|
10362
10572
|
Editor.plugin.add(copy);
|
|
10363
10573
|
Editor.plugin.add(cut);
|
|
10364
10574
|
Editor.plugin.add(paste);
|
|
@@ -10391,6 +10601,8 @@ Editor.plugin.add(image);
|
|
|
10391
10601
|
Editor.plugin.add(video);
|
|
10392
10602
|
Editor.plugin.add(file);
|
|
10393
10603
|
Editor.plugin.add(emoji);
|
|
10604
|
+
Editor.plugin.add(equation);
|
|
10605
|
+
Editor.plugin.add(specialCharacter);
|
|
10394
10606
|
Editor.plugin.add(markdown);
|
|
10395
10607
|
Editor.plugin.add(enterKey);
|
|
10396
10608
|
Editor.plugin.add(shiftEnterKey);
|