lakelib 0.1.16 → 0.1.17
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 +3 -3
- 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 +280 -88
- 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() {
|
|
@@ -702,7 +703,7 @@ class Nodes {
|
|
|
702
703
|
eachElement(callback) {
|
|
703
704
|
const nodes = this.getAll();
|
|
704
705
|
for (let i = 0; i < nodes.length; i++) {
|
|
705
|
-
if (nodes[i].nodeType ===
|
|
706
|
+
if (nodes[i].nodeType === Node.ELEMENT_NODE) {
|
|
706
707
|
if (callback(nodes[i], i) === false) {
|
|
707
708
|
return this;
|
|
708
709
|
}
|
|
@@ -1237,7 +1238,7 @@ class Nodes {
|
|
|
1237
1238
|
return `node (${node.lakeId}): ${nodeValue}`;
|
|
1238
1239
|
}
|
|
1239
1240
|
// Prints information of the first node.
|
|
1240
|
-
|
|
1241
|
+
info() {
|
|
1241
1242
|
debug(this.toString());
|
|
1242
1243
|
}
|
|
1243
1244
|
}
|
|
@@ -1378,12 +1379,12 @@ class Range {
|
|
|
1378
1379
|
reference = 'right';
|
|
1379
1380
|
}
|
|
1380
1381
|
}
|
|
1381
|
-
else {
|
|
1382
|
+
else if (range.startNode.isText) {
|
|
1382
1383
|
const text = range.startNode.text();
|
|
1383
1384
|
if (range.startOffset < text.length) {
|
|
1384
1385
|
range.setEnd(range.startNode, range.startOffset + 1);
|
|
1385
1386
|
}
|
|
1386
|
-
else {
|
|
1387
|
+
else if (range.startOffset > 0) {
|
|
1387
1388
|
range.setStart(range.startNode, range.startOffset - 1);
|
|
1388
1389
|
reference = 'right';
|
|
1389
1390
|
}
|
|
@@ -1836,7 +1837,7 @@ class Range {
|
|
|
1836
1837
|
return this.range.cloneContents();
|
|
1837
1838
|
}
|
|
1838
1839
|
// Prints information of the range.
|
|
1839
|
-
|
|
1840
|
+
info() {
|
|
1840
1841
|
debug('--- range information ---');
|
|
1841
1842
|
debug('start node:', this.startNode.toString(), ', offset:', this.startOffset);
|
|
1842
1843
|
debug('end node:', this.endNode.toString(), ', offset:', this.endOffset);
|
|
@@ -2874,6 +2875,7 @@ var enUS = {
|
|
|
2874
2875
|
image: 'Image',
|
|
2875
2876
|
file: 'File',
|
|
2876
2877
|
emoji: 'Emoji',
|
|
2878
|
+
equation: 'Equation',
|
|
2877
2879
|
removeColor: 'Remove color',
|
|
2878
2880
|
},
|
|
2879
2881
|
link: {
|
|
@@ -2909,6 +2911,10 @@ var enUS = {
|
|
|
2909
2911
|
codeBlock: {
|
|
2910
2912
|
langType: 'Select language',
|
|
2911
2913
|
},
|
|
2914
|
+
equation: {
|
|
2915
|
+
save: 'Done',
|
|
2916
|
+
placeholder: 'Type a TeX expression',
|
|
2917
|
+
},
|
|
2912
2918
|
};
|
|
2913
2919
|
|
|
2914
2920
|
var zhCN = {
|
|
@@ -2958,6 +2964,7 @@ var zhCN = {
|
|
|
2958
2964
|
image: '图片',
|
|
2959
2965
|
file: '文件',
|
|
2960
2966
|
emoji: '表情',
|
|
2967
|
+
equation: '公式',
|
|
2961
2968
|
removeColor: '默认',
|
|
2962
2969
|
},
|
|
2963
2970
|
link: {
|
|
@@ -2993,6 +3000,10 @@ var zhCN = {
|
|
|
2993
3000
|
codeBlock: {
|
|
2994
3001
|
langType: '选择代码语言',
|
|
2995
3002
|
},
|
|
3003
|
+
equation: {
|
|
3004
|
+
save: '确定',
|
|
3005
|
+
placeholder: '请输入 TeX 公式',
|
|
3006
|
+
},
|
|
2996
3007
|
};
|
|
2997
3008
|
|
|
2998
3009
|
var ja = {
|
|
@@ -3042,6 +3053,7 @@ var ja = {
|
|
|
3042
3053
|
image: '画像',
|
|
3043
3054
|
file: 'ファイル',
|
|
3044
3055
|
emoji: '絵文字',
|
|
3056
|
+
equation: '公式',
|
|
3045
3057
|
removeColor: 'デフォルト',
|
|
3046
3058
|
},
|
|
3047
3059
|
link: {
|
|
@@ -3077,6 +3089,10 @@ var ja = {
|
|
|
3077
3089
|
codeBlock: {
|
|
3078
3090
|
langType: 'コード言語を選択',
|
|
3079
3091
|
},
|
|
3092
|
+
equation: {
|
|
3093
|
+
save: '確認',
|
|
3094
|
+
placeholder: 'TeX 公式を入力してください。',
|
|
3095
|
+
},
|
|
3080
3096
|
};
|
|
3081
3097
|
|
|
3082
3098
|
var ko = {
|
|
@@ -3126,6 +3142,7 @@ var ko = {
|
|
|
3126
3142
|
image: '이미지',
|
|
3127
3143
|
file: '파일',
|
|
3128
3144
|
emoji: '이모지',
|
|
3145
|
+
equation: '수식',
|
|
3129
3146
|
removeColor: '기본색',
|
|
3130
3147
|
},
|
|
3131
3148
|
link: {
|
|
@@ -3161,6 +3178,10 @@ var ko = {
|
|
|
3161
3178
|
codeBlock: {
|
|
3162
3179
|
langType: '코드언어 선택',
|
|
3163
3180
|
},
|
|
3181
|
+
equation: {
|
|
3182
|
+
save: '확인',
|
|
3183
|
+
placeholder: 'TeX 수식을 입력하세요',
|
|
3184
|
+
},
|
|
3164
3185
|
};
|
|
3165
3186
|
|
|
3166
3187
|
const localeTranslations = {
|
|
@@ -3560,7 +3581,7 @@ class Box {
|
|
|
3560
3581
|
if (typeof node === 'string') {
|
|
3561
3582
|
const component = boxes.get(node);
|
|
3562
3583
|
if (component === undefined) {
|
|
3563
|
-
throw new Error(`
|
|
3584
|
+
throw new Error(`The box "${node}" has not been defined yet.`);
|
|
3564
3585
|
}
|
|
3565
3586
|
const type = encode(component.type);
|
|
3566
3587
|
const name = encode(component.name);
|
|
@@ -3573,7 +3594,7 @@ class Box {
|
|
|
3573
3594
|
this.node = query(node);
|
|
3574
3595
|
const component = boxes.get(this.name);
|
|
3575
3596
|
if (component === undefined) {
|
|
3576
|
-
throw new Error(`
|
|
3597
|
+
throw new Error(`The box "${this.name}" has not been defined yet.`);
|
|
3577
3598
|
}
|
|
3578
3599
|
if (component.value && !this.node.hasAttr('value')) {
|
|
3579
3600
|
this.value = component.value;
|
|
@@ -3604,7 +3625,7 @@ class Box {
|
|
|
3604
3625
|
container.removeClass('lake-box-hovered');
|
|
3605
3626
|
});
|
|
3606
3627
|
container.on('click', () => {
|
|
3607
|
-
debug(`
|
|
3628
|
+
debug(`The box "${this.name}" (id = ${this.node.id}) value:`);
|
|
3608
3629
|
debug(this.value);
|
|
3609
3630
|
});
|
|
3610
3631
|
if (this.type === 'block' && this.node.isContentEditable) {
|
|
@@ -3643,7 +3664,7 @@ class Box {
|
|
|
3643
3664
|
}
|
|
3644
3665
|
this.value = value;
|
|
3645
3666
|
}
|
|
3646
|
-
// Returns the editor
|
|
3667
|
+
// Returns an instance of the editor that includes the box.
|
|
3647
3668
|
getEditor() {
|
|
3648
3669
|
const container = this.node.closest('div[contenteditable]');
|
|
3649
3670
|
return container.length > 0 ? editors.get(container.id) : undefined;
|
|
@@ -3689,15 +3710,16 @@ class Box {
|
|
|
3689
3710
|
if (component === undefined) {
|
|
3690
3711
|
return;
|
|
3691
3712
|
}
|
|
3713
|
+
this.event.emit('beforeunmount');
|
|
3714
|
+
this.event.removeAllListeners();
|
|
3692
3715
|
this.addFramework();
|
|
3693
3716
|
const content = component.render(this);
|
|
3694
3717
|
if (content !== undefined) {
|
|
3695
3718
|
const container = this.getContainer();
|
|
3696
|
-
|
|
3697
|
-
|
|
3698
|
-
morph(container, newContainer);
|
|
3719
|
+
container.empty();
|
|
3720
|
+
container.append(content);
|
|
3699
3721
|
}
|
|
3700
|
-
debug(`
|
|
3722
|
+
debug(`The box "${this.name}" (id: ${this.node.id}) rendered`);
|
|
3701
3723
|
}
|
|
3702
3724
|
// Destroys a rendered box.
|
|
3703
3725
|
unmount() {
|
|
@@ -3705,7 +3727,7 @@ class Box {
|
|
|
3705
3727
|
this.event.emit('beforeunmount');
|
|
3706
3728
|
this.event.removeAllListeners();
|
|
3707
3729
|
this.node.empty();
|
|
3708
|
-
debug(`
|
|
3730
|
+
debug(`The box "${this.name}" (id: ${this.node.id}) unmounted`);
|
|
3709
3731
|
}
|
|
3710
3732
|
// Returns a HTML string of the box.
|
|
3711
3733
|
getHTML() {
|
|
@@ -4273,13 +4295,7 @@ class HTMLParser {
|
|
|
4273
4295
|
}
|
|
4274
4296
|
return html.trim();
|
|
4275
4297
|
}
|
|
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.
|
|
4298
|
+
// Returns a document fragment.
|
|
4283
4299
|
getFragment() {
|
|
4284
4300
|
const html = this.getHTML();
|
|
4285
4301
|
const body = this.parseHTML(html);
|
|
@@ -5117,7 +5133,7 @@ function removeBox(range) {
|
|
|
5117
5133
|
return box;
|
|
5118
5134
|
}
|
|
5119
5135
|
|
|
5120
|
-
var version = "0.1.
|
|
5136
|
+
var version = "0.1.17";
|
|
5121
5137
|
|
|
5122
5138
|
// Returns the attributes of the element as an key-value object.
|
|
5123
5139
|
function getAttributes(node) {
|
|
@@ -5295,7 +5311,7 @@ class Selection {
|
|
|
5295
5311
|
insertBox(boxName, boxValue) {
|
|
5296
5312
|
const box = insertBox(this.range, boxName, boxValue);
|
|
5297
5313
|
if (!box) {
|
|
5298
|
-
throw new Error(`
|
|
5314
|
+
throw new Error(`The box "${boxName}" cannot be inserted outside the editor.`);
|
|
5299
5315
|
}
|
|
5300
5316
|
return box;
|
|
5301
5317
|
}
|
|
@@ -5418,7 +5434,8 @@ class History {
|
|
|
5418
5434
|
},
|
|
5419
5435
|
afterAttributeUpdated: (attributeName, nativeNode) => {
|
|
5420
5436
|
const node = new Nodes(nativeNode);
|
|
5421
|
-
if (
|
|
5437
|
+
if (['name', 'value'].indexOf(attributeName) >= 0 && node.name === 'lake-box') {
|
|
5438
|
+
getBox(node).unmount();
|
|
5422
5439
|
const instanceMap = getInstanceMap(container.id);
|
|
5423
5440
|
instanceMap.delete(node.id);
|
|
5424
5441
|
}
|
|
@@ -5434,7 +5451,7 @@ class History {
|
|
|
5434
5451
|
this.removeIdfromBoxes(otherContainer);
|
|
5435
5452
|
}
|
|
5436
5453
|
get canUndo() {
|
|
5437
|
-
return this.index > 1 && !!this.list[this.index -
|
|
5454
|
+
return this.index > 1 && !!this.list[this.index - 2];
|
|
5438
5455
|
}
|
|
5439
5456
|
get canRedo() {
|
|
5440
5457
|
return !!this.list[this.index];
|
|
@@ -5554,53 +5571,65 @@ class History {
|
|
|
5554
5571
|
}
|
|
5555
5572
|
}
|
|
5556
5573
|
|
|
5557
|
-
const
|
|
5558
|
-
['
|
|
5574
|
+
const aliasMap = new Map([
|
|
5575
|
+
['arrow-left', 'left'],
|
|
5576
|
+
['arrow-right', 'right'],
|
|
5577
|
+
['arrow-up', 'up'],
|
|
5578
|
+
['arrow-down', 'down'],
|
|
5559
5579
|
]);
|
|
5560
5580
|
class Keystroke {
|
|
5561
5581
|
constructor(container) {
|
|
5562
5582
|
this.keydownEventList = [];
|
|
5563
5583
|
this.keyupEventList = [];
|
|
5564
5584
|
this.container = container;
|
|
5585
|
+
this.container.on('keydown', event => {
|
|
5586
|
+
const keyboardEvent = event;
|
|
5587
|
+
for (const item of this.keydownEventList) {
|
|
5588
|
+
if (isKeyHotkey(item.type, keyboardEvent)) {
|
|
5589
|
+
if (item.listener(keyboardEvent) === false) {
|
|
5590
|
+
break;
|
|
5591
|
+
}
|
|
5592
|
+
}
|
|
5593
|
+
}
|
|
5594
|
+
});
|
|
5595
|
+
this.container.on('keyup', event => {
|
|
5596
|
+
const keyboardEvent = event;
|
|
5597
|
+
for (const item of this.keyupEventList) {
|
|
5598
|
+
if (isKeyHotkey(item.type, keyboardEvent)) {
|
|
5599
|
+
if (item.listener(keyboardEvent) === false) {
|
|
5600
|
+
break;
|
|
5601
|
+
}
|
|
5602
|
+
}
|
|
5603
|
+
}
|
|
5604
|
+
});
|
|
5565
5605
|
}
|
|
5566
5606
|
normalizeType(type) {
|
|
5567
5607
|
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}`);
|
|
5608
|
+
type = (_a = aliasMap.get(type)) !== null && _a !== void 0 ? _a : type;
|
|
5572
5609
|
return type;
|
|
5573
5610
|
}
|
|
5574
5611
|
// Sets a keydown shortcut.
|
|
5575
5612
|
setKeydown(type, listener) {
|
|
5576
5613
|
type = this.normalizeType(type);
|
|
5577
|
-
const handler = createKeybindingsHandler({
|
|
5578
|
-
[type]: event => listener(event),
|
|
5579
|
-
});
|
|
5580
5614
|
this.keydownEventList.push({
|
|
5581
5615
|
type,
|
|
5582
5616
|
listener,
|
|
5583
5617
|
});
|
|
5584
|
-
this.container.on('keydown', handler);
|
|
5585
5618
|
}
|
|
5586
5619
|
// Sets a keyup shortcut.
|
|
5587
5620
|
setKeyup(type, listener) {
|
|
5588
5621
|
type = this.normalizeType(type);
|
|
5589
|
-
const handler = createKeybindingsHandler({
|
|
5590
|
-
[type]: event => listener(event),
|
|
5591
|
-
});
|
|
5592
5622
|
this.keyupEventList.push({
|
|
5593
5623
|
type,
|
|
5594
5624
|
listener,
|
|
5595
5625
|
});
|
|
5596
|
-
this.container.on('keyup', handler);
|
|
5597
5626
|
}
|
|
5598
5627
|
// Executes the keydown shortcuts.
|
|
5599
5628
|
keydown(type) {
|
|
5600
5629
|
type = this.normalizeType(type);
|
|
5601
5630
|
for (const item of this.keydownEventList) {
|
|
5602
5631
|
if (item.type === type) {
|
|
5603
|
-
if (item.listener(new
|
|
5632
|
+
if (item.listener(new KeyboardEvent(type)) === false) {
|
|
5604
5633
|
break;
|
|
5605
5634
|
}
|
|
5606
5635
|
}
|
|
@@ -5611,7 +5640,7 @@ class Keystroke {
|
|
|
5611
5640
|
type = this.normalizeType(type);
|
|
5612
5641
|
for (const item of this.keyupEventList) {
|
|
5613
5642
|
if (item.type === type) {
|
|
5614
|
-
if (item.listener(new
|
|
5643
|
+
if (item.listener(new KeyboardEvent(type)) === false) {
|
|
5615
5644
|
break;
|
|
5616
5645
|
}
|
|
5617
5646
|
}
|
|
@@ -5847,7 +5876,7 @@ class Editor {
|
|
|
5847
5876
|
// Adds or Removes a placeholder class.
|
|
5848
5877
|
togglePlaceholderClass(value) {
|
|
5849
5878
|
value = denormalizeValue(value);
|
|
5850
|
-
const className = 'lake-
|
|
5879
|
+
const className = 'lake-placeholder';
|
|
5851
5880
|
if (value.replace('<focus />', '') === '<p><br /></p>') {
|
|
5852
5881
|
this.container.addClass(className);
|
|
5853
5882
|
}
|
|
@@ -5899,6 +5928,18 @@ class Editor {
|
|
|
5899
5928
|
this.container.on('compositionend', () => {
|
|
5900
5929
|
this.isComposing = false;
|
|
5901
5930
|
});
|
|
5931
|
+
this.container.on('beforeinput', event => {
|
|
5932
|
+
const inputEvent = event;
|
|
5933
|
+
// <p><br /><focus /></p>
|
|
5934
|
+
// When the caret is positioned behind a <br> tag, the input event is triggered twice after inserting a sharp(#) in composition mode.
|
|
5935
|
+
if (this.isComposing && inputEvent.inputType === 'insertText') {
|
|
5936
|
+
inputEvent.preventDefault();
|
|
5937
|
+
this.isComposing = false;
|
|
5938
|
+
this.history.save({
|
|
5939
|
+
inputType: 'insertText',
|
|
5940
|
+
});
|
|
5941
|
+
}
|
|
5942
|
+
});
|
|
5902
5943
|
this.container.on('input', event => {
|
|
5903
5944
|
const inputEvent = event;
|
|
5904
5945
|
// Here setTimeout is necessary because isComposing is not false after ending composition.
|
|
@@ -5910,6 +5951,9 @@ class Editor {
|
|
|
5910
5951
|
}
|
|
5911
5952
|
// isComposing is false after ending composition because compositionend event has been emitted.
|
|
5912
5953
|
if (this.isComposing) {
|
|
5954
|
+
if (inputEvent.inputType === 'insertCompositionText') {
|
|
5955
|
+
this.container.removeClass('lake-placeholder');
|
|
5956
|
+
}
|
|
5913
5957
|
this.event.emit('input', inputEvent);
|
|
5914
5958
|
return;
|
|
5915
5959
|
}
|
|
@@ -5992,6 +6036,7 @@ class Editor {
|
|
|
5992
6036
|
}
|
|
5993
6037
|
// Fixes wrong content, especially empty tag.
|
|
5994
6038
|
fixContent() {
|
|
6039
|
+
const range = this.selection.range;
|
|
5995
6040
|
let changed = false;
|
|
5996
6041
|
let children = this.container.children();
|
|
5997
6042
|
for (const child of children) {
|
|
@@ -6004,7 +6049,7 @@ class Editor {
|
|
|
6004
6049
|
children = this.container.children();
|
|
6005
6050
|
if (children.length === 0) {
|
|
6006
6051
|
this.container.html('<p><br /></p>');
|
|
6007
|
-
|
|
6052
|
+
range.shrinkAfter(this.container);
|
|
6008
6053
|
changed = true;
|
|
6009
6054
|
debug('Content fixed: default paragraph was added');
|
|
6010
6055
|
}
|
|
@@ -6014,11 +6059,23 @@ class Editor {
|
|
|
6014
6059
|
const paragraph = query('<p />');
|
|
6015
6060
|
child.before(paragraph);
|
|
6016
6061
|
paragraph.append(child);
|
|
6017
|
-
|
|
6062
|
+
range.shrinkAfter(paragraph);
|
|
6018
6063
|
changed = true;
|
|
6019
6064
|
debug(`Content fixed: void element "${child.name}" was wrapped in paragraph`);
|
|
6020
6065
|
}
|
|
6021
6066
|
}
|
|
6067
|
+
// In composition mode (e.g., when a user starts entering a Chinese character using a Pinyin IME),
|
|
6068
|
+
// uncompleted text is inserted if the caret is positioned behind a <br> tag.
|
|
6069
|
+
// To fix this bug, the caret needs to be moved to the front of the <br> tag.
|
|
6070
|
+
if (range.isCollapsed) {
|
|
6071
|
+
const prevNode = range.getPrevNode();
|
|
6072
|
+
const nextNode = range.getNextNode();
|
|
6073
|
+
if (prevNode.name === 'br' && nextNode.length === 0) {
|
|
6074
|
+
range.setStartBefore(prevNode);
|
|
6075
|
+
range.collapseToStart();
|
|
6076
|
+
debug('Range fixed: the caret has been moved to the front of the <br> tag');
|
|
6077
|
+
}
|
|
6078
|
+
}
|
|
6022
6079
|
return changed;
|
|
6023
6080
|
}
|
|
6024
6081
|
// Sets default config for a plugin.
|
|
@@ -6660,6 +6717,15 @@ const toolbarItems = [
|
|
|
6660
6717
|
editor.command.execute(value);
|
|
6661
6718
|
},
|
|
6662
6719
|
},
|
|
6720
|
+
{
|
|
6721
|
+
name: 'equation',
|
|
6722
|
+
type: 'button',
|
|
6723
|
+
icon: icons.get('equation'),
|
|
6724
|
+
tooltip: locale => locale.toolbar.equation(),
|
|
6725
|
+
onClick: (editor, value) => {
|
|
6726
|
+
editor.command.execute(value);
|
|
6727
|
+
},
|
|
6728
|
+
},
|
|
6663
6729
|
{
|
|
6664
6730
|
name: 'heading',
|
|
6665
6731
|
type: 'dropdown',
|
|
@@ -7029,8 +7095,10 @@ const hrBox = {
|
|
|
7029
7095
|
if (!editor) {
|
|
7030
7096
|
return;
|
|
7031
7097
|
}
|
|
7098
|
+
const boxContainer = box.getContainer();
|
|
7032
7099
|
const rootNode = query('<div class="lake-hr"><hr /></div>');
|
|
7033
|
-
|
|
7100
|
+
boxContainer.empty();
|
|
7101
|
+
boxContainer.append(rootNode);
|
|
7034
7102
|
rootNode.on('click', () => {
|
|
7035
7103
|
editor.selection.selectBox(box);
|
|
7036
7104
|
});
|
|
@@ -7125,10 +7193,10 @@ const codeBlockBox = {
|
|
|
7125
7193
|
return;
|
|
7126
7194
|
}
|
|
7127
7195
|
const rootNode = query('<div class="lake-code-block" />');
|
|
7128
|
-
const
|
|
7129
|
-
|
|
7130
|
-
|
|
7131
|
-
|
|
7196
|
+
const boxContainer = box.getContainer();
|
|
7197
|
+
boxContainer.css('width', `${editor.container.innerWidth() - 2}px`);
|
|
7198
|
+
boxContainer.empty();
|
|
7199
|
+
boxContainer.append(rootNode);
|
|
7132
7200
|
const codeBlockNativeNode = rootNode.get(0);
|
|
7133
7201
|
if (!codeBlockNativeNode) {
|
|
7134
7202
|
return;
|
|
@@ -7220,7 +7288,7 @@ const codeBlockBox = {
|
|
|
7220
7288
|
});
|
|
7221
7289
|
dropdown.render();
|
|
7222
7290
|
const resizeListener = () => {
|
|
7223
|
-
|
|
7291
|
+
boxContainer.css('width', `${editor.container.innerWidth() - 2}px`);
|
|
7224
7292
|
};
|
|
7225
7293
|
editor.event.on('resize', resizeListener);
|
|
7226
7294
|
rootNode.on('click', () => {
|
|
@@ -7486,7 +7554,7 @@ function openFullScreen(box) {
|
|
|
7486
7554
|
lightbox.loadAndOpen(currentIndex);
|
|
7487
7555
|
}
|
|
7488
7556
|
// Displays error icon and filename.
|
|
7489
|
-
function renderError(rootNode, box) {
|
|
7557
|
+
function renderError$1(rootNode, box) {
|
|
7490
7558
|
return __awaiter(this, void 0, void 0, function* () {
|
|
7491
7559
|
const editor = box.getEditor();
|
|
7492
7560
|
if (!editor) {
|
|
@@ -7531,7 +7599,7 @@ function renderUploading(rootNode, box) {
|
|
|
7531
7599
|
const value = box.value;
|
|
7532
7600
|
const imageInfo = yield getImageInfo(value.url);
|
|
7533
7601
|
if (!imageInfo.width || !imageInfo.height) {
|
|
7534
|
-
yield renderError(rootNode, box);
|
|
7602
|
+
yield renderError$1(rootNode, box);
|
|
7535
7603
|
return;
|
|
7536
7604
|
}
|
|
7537
7605
|
const maxWidth = editor.container.innerWidth() - 2;
|
|
@@ -7595,7 +7663,7 @@ function renderDone(rootNode, box) {
|
|
|
7595
7663
|
return;
|
|
7596
7664
|
}
|
|
7597
7665
|
if (!imageInfo.width || !imageInfo.height) {
|
|
7598
|
-
yield renderError(rootNode, box);
|
|
7666
|
+
yield renderError$1(rootNode, box);
|
|
7599
7667
|
return;
|
|
7600
7668
|
}
|
|
7601
7669
|
let width = value.width;
|
|
@@ -7668,26 +7736,26 @@ const imageBox = {
|
|
|
7668
7736
|
box.node.hide();
|
|
7669
7737
|
return;
|
|
7670
7738
|
}
|
|
7671
|
-
const
|
|
7672
|
-
if (value.width && value.height &&
|
|
7673
|
-
|
|
7739
|
+
const boxContainer = box.getContainer();
|
|
7740
|
+
if (value.width && value.height && boxContainer.find('.lake-progress').length === 0) {
|
|
7741
|
+
boxContainer.css({
|
|
7674
7742
|
width: `${value.width}px`,
|
|
7675
7743
|
height: `${value.height}px`,
|
|
7676
7744
|
});
|
|
7677
|
-
|
|
7745
|
+
boxContainer.empty();
|
|
7678
7746
|
const placeholderNode = query('<div class="lake-image-placeholder" />');
|
|
7679
|
-
|
|
7747
|
+
boxContainer.append(placeholderNode);
|
|
7680
7748
|
const imageIcon = icons.get('image');
|
|
7681
7749
|
if (imageIcon) {
|
|
7682
7750
|
placeholderNode.append(imageIcon);
|
|
7683
7751
|
}
|
|
7684
7752
|
}
|
|
7685
|
-
if (
|
|
7753
|
+
if (boxContainer.first().length === 0) {
|
|
7686
7754
|
// The following code is for unit testing because some test cases need to
|
|
7687
7755
|
// select the content of the box before it is completely loaded.
|
|
7688
7756
|
// Example:
|
|
7689
7757
|
// range.setStart(box.getContainer(), 1);
|
|
7690
|
-
|
|
7758
|
+
boxContainer.append('<div />');
|
|
7691
7759
|
}
|
|
7692
7760
|
// for test
|
|
7693
7761
|
if (value.status === 'loading') {
|
|
@@ -7700,14 +7768,14 @@ const imageBox = {
|
|
|
7700
7768
|
promise = renderUploading(rootNode, box);
|
|
7701
7769
|
}
|
|
7702
7770
|
else if (value.status === 'error') {
|
|
7703
|
-
promise = renderError(rootNode, box);
|
|
7771
|
+
promise = renderError$1(rootNode, box);
|
|
7704
7772
|
}
|
|
7705
7773
|
else {
|
|
7706
7774
|
promise = renderDone(rootNode, box);
|
|
7707
7775
|
}
|
|
7708
7776
|
promise.then(() => {
|
|
7709
|
-
|
|
7710
|
-
|
|
7777
|
+
boxContainer.empty();
|
|
7778
|
+
boxContainer.append(rootNode);
|
|
7711
7779
|
rootNode.find('.lake-button-view').on('click', () => openFullScreen(box));
|
|
7712
7780
|
if (editor.readonly) {
|
|
7713
7781
|
rootNode.find('.lake-button-remove').hide();
|
|
@@ -7867,12 +7935,12 @@ const videoBox = {
|
|
|
7867
7935
|
showVideo(box);
|
|
7868
7936
|
},
|
|
7869
7937
|
});
|
|
7870
|
-
formNode.find('input[name="url"]').on('keydown',
|
|
7871
|
-
'
|
|
7938
|
+
formNode.find('input[name="url"]').on('keydown', event => {
|
|
7939
|
+
if (isKeyHotkey('enter', event)) {
|
|
7872
7940
|
event.preventDefault();
|
|
7873
7941
|
button.node.emit('click');
|
|
7874
|
-
}
|
|
7875
|
-
})
|
|
7942
|
+
}
|
|
7943
|
+
});
|
|
7876
7944
|
button.render();
|
|
7877
7945
|
rootNode.append(formNode);
|
|
7878
7946
|
appendButtonGroup(box);
|
|
@@ -7957,12 +8025,12 @@ const fileBox = {
|
|
|
7957
8025
|
box.node.hide();
|
|
7958
8026
|
return;
|
|
7959
8027
|
}
|
|
7960
|
-
const
|
|
8028
|
+
const boxContainer = box.getContainer();
|
|
7961
8029
|
const rootNode = query('<div class="lake-file" />');
|
|
7962
8030
|
rootNode.addClass(`lake-file-${value.status}`);
|
|
7963
8031
|
appendContent(rootNode, box);
|
|
7964
|
-
|
|
7965
|
-
|
|
8032
|
+
boxContainer.empty();
|
|
8033
|
+
boxContainer.append(rootNode);
|
|
7966
8034
|
if (!editor.readonly) {
|
|
7967
8035
|
rootNode.on('click', () => {
|
|
7968
8036
|
editor.selection.selectBox(box);
|
|
@@ -7987,16 +8055,100 @@ const emojiBox = {
|
|
|
7987
8055
|
return;
|
|
7988
8056
|
}
|
|
7989
8057
|
const value = box.value;
|
|
8058
|
+
const boxContainer = box.getContainer();
|
|
7990
8059
|
const rootNode = query(safeTemplate `
|
|
7991
8060
|
<div class="lake-emoji"><img src="${value.url}" title="${value.title}" /></div>
|
|
7992
8061
|
`);
|
|
7993
|
-
|
|
8062
|
+
boxContainer.empty();
|
|
8063
|
+
boxContainer.append(rootNode);
|
|
7994
8064
|
rootNode.on('click', () => {
|
|
7995
8065
|
editor.selection.selectBox(box);
|
|
7996
8066
|
});
|
|
7997
8067
|
},
|
|
7998
8068
|
};
|
|
7999
8069
|
|
|
8070
|
+
const defaultExpression = String.raw `\sqrt{x}`;
|
|
8071
|
+
function renderError(box) {
|
|
8072
|
+
const editor = box.getEditor();
|
|
8073
|
+
if (!editor) {
|
|
8074
|
+
return;
|
|
8075
|
+
}
|
|
8076
|
+
if (editor.readonly) {
|
|
8077
|
+
box.node.hide();
|
|
8078
|
+
return;
|
|
8079
|
+
}
|
|
8080
|
+
const defaultCode = (box.value.code || '').trim();
|
|
8081
|
+
const rootNode = box.getContainer().find('.lake-equation');
|
|
8082
|
+
rootNode.addClass('lake-equation-error');
|
|
8083
|
+
rootNode.text(defaultCode);
|
|
8084
|
+
rootNode.on('click', () => {
|
|
8085
|
+
editor.selection.selectBox(box);
|
|
8086
|
+
});
|
|
8087
|
+
editor.config.onMessage('warning', `
|
|
8088
|
+
The box "${box.name}" (id: ${box.node.id}) failed to display because window.katex was not found.
|
|
8089
|
+
Please check if the "katex" library is added to this page.
|
|
8090
|
+
`.trim());
|
|
8091
|
+
}
|
|
8092
|
+
const equationBox = {
|
|
8093
|
+
type: 'inline',
|
|
8094
|
+
name: 'equation',
|
|
8095
|
+
render: box => {
|
|
8096
|
+
const editor = box.getEditor();
|
|
8097
|
+
if (!editor) {
|
|
8098
|
+
return;
|
|
8099
|
+
}
|
|
8100
|
+
const rootNode = query('<div class="lake-equation" />');
|
|
8101
|
+
const boxContainer = box.getContainer();
|
|
8102
|
+
boxContainer.empty();
|
|
8103
|
+
boxContainer.append(rootNode);
|
|
8104
|
+
const katex = window.katex;
|
|
8105
|
+
if (!katex) {
|
|
8106
|
+
renderError(box);
|
|
8107
|
+
return;
|
|
8108
|
+
}
|
|
8109
|
+
const defaultCode = (box.value.code || '').trim();
|
|
8110
|
+
const viewNode = query('<div class="lake-equation-view" />');
|
|
8111
|
+
rootNode.append(viewNode);
|
|
8112
|
+
viewNode.html(window.katex.renderToString(defaultCode || defaultExpression, {
|
|
8113
|
+
throwOnError: false,
|
|
8114
|
+
}));
|
|
8115
|
+
viewNode.on('click', () => {
|
|
8116
|
+
editor.selection.selectBox(box);
|
|
8117
|
+
});
|
|
8118
|
+
const formNode = query(safeTemplate `
|
|
8119
|
+
<div class="lake-equation-form">
|
|
8120
|
+
<div class="lake-row">
|
|
8121
|
+
<textarea name="code" placeholder="${editor.locale.equation.placeholder()}"></textarea>
|
|
8122
|
+
</div>
|
|
8123
|
+
<div class="lake-row lake-button-row"></div>
|
|
8124
|
+
</div>
|
|
8125
|
+
`);
|
|
8126
|
+
rootNode.append(formNode);
|
|
8127
|
+
const textareaNode = formNode.find('textarea');
|
|
8128
|
+
const textareaNativeNode = textareaNode.get(0);
|
|
8129
|
+
textareaNativeNode.value = defaultCode;
|
|
8130
|
+
textareaNode.on('input', () => {
|
|
8131
|
+
const code = textareaNativeNode.value.trim();
|
|
8132
|
+
viewNode.html(window.katex.renderToString(code || defaultExpression, {
|
|
8133
|
+
throwOnError: false,
|
|
8134
|
+
}));
|
|
8135
|
+
box.updateValue('code', code);
|
|
8136
|
+
});
|
|
8137
|
+
const button = new Button({
|
|
8138
|
+
root: formNode.find('.lake-button-row'),
|
|
8139
|
+
name: 'save',
|
|
8140
|
+
type: 'primary',
|
|
8141
|
+
text: editor.locale.equation.save(),
|
|
8142
|
+
onClick: () => {
|
|
8143
|
+
editor.selection.range.selectBoxEnd(box.node);
|
|
8144
|
+
editor.selection.sync();
|
|
8145
|
+
editor.history.save();
|
|
8146
|
+
},
|
|
8147
|
+
});
|
|
8148
|
+
button.render();
|
|
8149
|
+
},
|
|
8150
|
+
};
|
|
8151
|
+
|
|
8000
8152
|
var copy = (editor) => {
|
|
8001
8153
|
editor.event.on('copy', event => {
|
|
8002
8154
|
const range = editor.selection.range;
|
|
@@ -8431,6 +8583,7 @@ var undo = (editor) => {
|
|
|
8431
8583
|
return;
|
|
8432
8584
|
}
|
|
8433
8585
|
editor.command.add('undo', {
|
|
8586
|
+
isDisabled: () => !editor.history.canUndo,
|
|
8434
8587
|
execute: () => {
|
|
8435
8588
|
editor.history.undo();
|
|
8436
8589
|
},
|
|
@@ -8450,6 +8603,7 @@ var redo = (editor) => {
|
|
|
8450
8603
|
return;
|
|
8451
8604
|
}
|
|
8452
8605
|
editor.command.add('redo', {
|
|
8606
|
+
isDisabled: () => !editor.history.canRedo,
|
|
8453
8607
|
execute: () => {
|
|
8454
8608
|
editor.history.redo();
|
|
8455
8609
|
},
|
|
@@ -9090,18 +9244,18 @@ class LinkPopup {
|
|
|
9090
9244
|
},
|
|
9091
9245
|
});
|
|
9092
9246
|
button.render();
|
|
9093
|
-
this.container.find('input[name="url"]').on('keydown',
|
|
9094
|
-
'
|
|
9247
|
+
this.container.find('input[name="url"]').on('keydown', event => {
|
|
9248
|
+
if (isKeyHotkey('enter', event)) {
|
|
9095
9249
|
event.preventDefault();
|
|
9096
9250
|
button.node.emit('click');
|
|
9097
|
-
}
|
|
9098
|
-
})
|
|
9099
|
-
this.container.find('input[name="title"]').on('keydown',
|
|
9100
|
-
'
|
|
9251
|
+
}
|
|
9252
|
+
});
|
|
9253
|
+
this.container.find('input[name="title"]').on('keydown', event => {
|
|
9254
|
+
if (isKeyHotkey('enter', event)) {
|
|
9101
9255
|
event.preventDefault();
|
|
9102
9256
|
button.node.emit('click');
|
|
9103
|
-
}
|
|
9104
|
-
})
|
|
9257
|
+
}
|
|
9258
|
+
});
|
|
9105
9259
|
}
|
|
9106
9260
|
// Remove link
|
|
9107
9261
|
appendUnlinkButton() {
|
|
@@ -9424,6 +9578,36 @@ var emoji = (editor) => {
|
|
|
9424
9578
|
});
|
|
9425
9579
|
};
|
|
9426
9580
|
|
|
9581
|
+
var equation = (editor) => {
|
|
9582
|
+
if (!window.katex) {
|
|
9583
|
+
return;
|
|
9584
|
+
}
|
|
9585
|
+
if (editor.readonly) {
|
|
9586
|
+
return;
|
|
9587
|
+
}
|
|
9588
|
+
editor.command.add('equation', {
|
|
9589
|
+
execute: (value) => {
|
|
9590
|
+
const box = editor.selection.insertBox('equation', value);
|
|
9591
|
+
editor.selection.selectBox(box);
|
|
9592
|
+
editor.history.save();
|
|
9593
|
+
},
|
|
9594
|
+
});
|
|
9595
|
+
};
|
|
9596
|
+
|
|
9597
|
+
var specialCharacter = (editor) => {
|
|
9598
|
+
if (editor.readonly) {
|
|
9599
|
+
return;
|
|
9600
|
+
}
|
|
9601
|
+
editor.command.add('specialCharacter', {
|
|
9602
|
+
execute: (value) => {
|
|
9603
|
+
const fragment = new Fragment();
|
|
9604
|
+
fragment.append(document.createTextNode(value));
|
|
9605
|
+
editor.selection.insertFragment(fragment);
|
|
9606
|
+
editor.history.save();
|
|
9607
|
+
},
|
|
9608
|
+
});
|
|
9609
|
+
};
|
|
9610
|
+
|
|
9427
9611
|
const headingTypeMap = new Map([
|
|
9428
9612
|
['#', 'h1'],
|
|
9429
9613
|
['##', 'h2'],
|
|
@@ -10046,7 +10230,8 @@ var backspaceKey = (editor) => {
|
|
|
10046
10230
|
editor.history.save();
|
|
10047
10231
|
return;
|
|
10048
10232
|
}
|
|
10049
|
-
|
|
10233
|
+
const nextNode = range.getNextNode();
|
|
10234
|
+
if (prevNode.name === 'br' && nextNode.length > 0) {
|
|
10050
10235
|
event.preventDefault();
|
|
10051
10236
|
range.setStartBefore(prevNode);
|
|
10052
10237
|
range.collapseToStart();
|
|
@@ -10194,8 +10379,12 @@ var tabKey = (editor) => {
|
|
|
10194
10379
|
if (editor.config.indentWithTab === false) {
|
|
10195
10380
|
return;
|
|
10196
10381
|
}
|
|
10382
|
+
const range = editor.selection.range;
|
|
10383
|
+
if (range.isInsideBox) {
|
|
10384
|
+
return;
|
|
10385
|
+
}
|
|
10197
10386
|
event.preventDefault();
|
|
10198
|
-
const blocks =
|
|
10387
|
+
const blocks = range.getBlocks();
|
|
10199
10388
|
for (const block of blocks) {
|
|
10200
10389
|
if (block.name !== 'p' || block.css('text-indent') === '2em') {
|
|
10201
10390
|
setBlockIndent(block, 'increase');
|
|
@@ -10359,6 +10548,7 @@ Editor.box.add(imageBox);
|
|
|
10359
10548
|
Editor.box.add(videoBox);
|
|
10360
10549
|
Editor.box.add(fileBox);
|
|
10361
10550
|
Editor.box.add(emojiBox);
|
|
10551
|
+
Editor.box.add(equationBox);
|
|
10362
10552
|
Editor.plugin.add(copy);
|
|
10363
10553
|
Editor.plugin.add(cut);
|
|
10364
10554
|
Editor.plugin.add(paste);
|
|
@@ -10391,6 +10581,8 @@ Editor.plugin.add(image);
|
|
|
10391
10581
|
Editor.plugin.add(video);
|
|
10392
10582
|
Editor.plugin.add(file);
|
|
10393
10583
|
Editor.plugin.add(emoji);
|
|
10584
|
+
Editor.plugin.add(equation);
|
|
10585
|
+
Editor.plugin.add(specialCharacter);
|
|
10394
10586
|
Editor.plugin.add(markdown);
|
|
10395
10587
|
Editor.plugin.add(enterKey);
|
|
10396
10588
|
Editor.plugin.add(shiftEnterKey);
|