lakelib 0.1.12 → 0.1.14
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/dist/lake.css +171 -165
- package/dist/lake.min.js +24 -24
- package/dist/lake.min.js.map +1 -1
- package/lib/lake.css +171 -165
- package/lib/lake.js +275 -250
- package/lib/lake.js.map +1 -1
- package/lib/types/css/index.d.ts +3 -4
- package/lib/types/editor.d.ts +9 -10
- package/lib/types/managers/box-manager.d.ts +0 -3
- package/lib/types/managers/command.d.ts +0 -2
- package/lib/types/managers/history.d.ts +11 -5
- package/lib/types/models/range.d.ts +4 -4
- package/package.json +1 -1
package/lib/lake.js
CHANGED
|
@@ -319,7 +319,7 @@ function parseStyle(styleValue) {
|
|
|
319
319
|
// Converts the special tags to ordinary HTML tags that can be parsed by browser.
|
|
320
320
|
function normalizeValue(value) {
|
|
321
321
|
return value.
|
|
322
|
-
replace(/(<lake-box[^>]+>)[\s\S]*?(<\/lake-box
|
|
322
|
+
replace(/(<lake-box[^>]+>)[\s\S]*?(<\/lake-box>|$)/ig, '$1</lake-box>').
|
|
323
323
|
replace(/<anchor\s*\/>/ig, '<lake-bookmark type="anchor"></lake-bookmark>').
|
|
324
324
|
replace(/<focus\s*\/>/ig, '<lake-bookmark type="focus"></lake-bookmark>');
|
|
325
325
|
}
|
|
@@ -1566,7 +1566,7 @@ class Range {
|
|
|
1566
1566
|
}
|
|
1567
1567
|
}
|
|
1568
1568
|
// Relocates the start and end points of the range for the box.
|
|
1569
|
-
|
|
1569
|
+
adjustBox() {
|
|
1570
1570
|
const startBoxNode = this.startNode.closest('lake-box');
|
|
1571
1571
|
if (startBoxNode.length > 0) {
|
|
1572
1572
|
const startRange = this.clone();
|
|
@@ -1591,7 +1591,7 @@ class Range {
|
|
|
1591
1591
|
}
|
|
1592
1592
|
}
|
|
1593
1593
|
// Relocates the beginning or end position of the range for table.
|
|
1594
|
-
|
|
1594
|
+
adjustTable() {
|
|
1595
1595
|
const startTable = this.startNode.closest('table');
|
|
1596
1596
|
const endTable = this.endNode.closest('table');
|
|
1597
1597
|
if (startTable.length === 0 && endTable.length > 0 && endTable.isInside) {
|
|
@@ -1617,7 +1617,7 @@ class Range {
|
|
|
1617
1617
|
// [<p>foo</p><p>]bar</p>
|
|
1618
1618
|
// to
|
|
1619
1619
|
// <p>[foo]</p><p>bar</p>
|
|
1620
|
-
|
|
1620
|
+
adjustBlock() {
|
|
1621
1621
|
if (!this.isCollapsed) {
|
|
1622
1622
|
// [<p>foo</p><p>]bar</p> to [<p>foo</p>]<p>bar</p>
|
|
1623
1623
|
if (this.endNode.isElement && this.endOffset === 0) {
|
|
@@ -1639,10 +1639,10 @@ class Range {
|
|
|
1639
1639
|
}
|
|
1640
1640
|
}
|
|
1641
1641
|
// Relocates the start and end points of the range.
|
|
1642
|
-
|
|
1643
|
-
this.
|
|
1644
|
-
this.
|
|
1645
|
-
this.
|
|
1642
|
+
adjust() {
|
|
1643
|
+
this.adjustBox();
|
|
1644
|
+
this.adjustTable();
|
|
1645
|
+
this.adjustBlock();
|
|
1646
1646
|
}
|
|
1647
1647
|
// Returns the previous node of the beginning point of the range.
|
|
1648
1648
|
getPrevNode() {
|
|
@@ -1684,7 +1684,7 @@ class Range {
|
|
|
1684
1684
|
}
|
|
1685
1685
|
const nodeList = [];
|
|
1686
1686
|
const clonedRange = this.clone();
|
|
1687
|
-
clonedRange.
|
|
1687
|
+
clonedRange.adjustBox();
|
|
1688
1688
|
for (const child of clonedRange.commonAncestor.getWalker()) {
|
|
1689
1689
|
if (child.isBox && clonedRange.intersectsNode(child)) {
|
|
1690
1690
|
nodeList.push(child);
|
|
@@ -2029,10 +2029,15 @@ function wrapNodeList(nodeList, wrapper) {
|
|
|
2029
2029
|
// Removes Zero-width spaces that are dependent on some other text nodes.
|
|
2030
2030
|
function removeZWS(node) {
|
|
2031
2031
|
for (const child of node.getWalker()) {
|
|
2032
|
-
if (child.isText
|
|
2033
|
-
const
|
|
2034
|
-
if (
|
|
2035
|
-
child.
|
|
2032
|
+
if (child.isText) {
|
|
2033
|
+
const text = child.text();
|
|
2034
|
+
if (text === '') {
|
|
2035
|
+
child.remove();
|
|
2036
|
+
}
|
|
2037
|
+
else if (text.length > 1) {
|
|
2038
|
+
if (/\u200B/.test(text)) {
|
|
2039
|
+
child.get(0).nodeValue = text.replace(/\u200B/g, '');
|
|
2040
|
+
}
|
|
2036
2041
|
}
|
|
2037
2042
|
}
|
|
2038
2043
|
}
|
|
@@ -2717,21 +2722,18 @@ function nodeAndView(node) {
|
|
|
2717
2722
|
let bottom = rect.bottom;
|
|
2718
2723
|
let viewportWidth = window.innerWidth;
|
|
2719
2724
|
let viewportHeight = window.innerHeight;
|
|
2720
|
-
const
|
|
2721
|
-
if (
|
|
2722
|
-
const
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
viewportWidth = viewportRect.width;
|
|
2733
|
-
viewportHeight = viewportRect.height;
|
|
2734
|
-
}
|
|
2725
|
+
const viewport = node.closestScroller();
|
|
2726
|
+
if (viewport.length > 0) {
|
|
2727
|
+
const nativeViewport = viewport.get(0);
|
|
2728
|
+
const viewportRect = nativeViewport.getBoundingClientRect();
|
|
2729
|
+
const offsetLeft = viewportRect.x;
|
|
2730
|
+
const offsetTop = viewportRect.y;
|
|
2731
|
+
left -= offsetLeft;
|
|
2732
|
+
right -= offsetLeft;
|
|
2733
|
+
top -= offsetTop;
|
|
2734
|
+
bottom -= offsetTop;
|
|
2735
|
+
viewportWidth = viewportRect.width;
|
|
2736
|
+
viewportHeight = viewportRect.height;
|
|
2735
2737
|
}
|
|
2736
2738
|
const position = {
|
|
2737
2739
|
left,
|
|
@@ -3569,7 +3571,7 @@ class Box {
|
|
|
3569
3571
|
container.removeClass('lake-box-hovered');
|
|
3570
3572
|
});
|
|
3571
3573
|
container.on('click', () => {
|
|
3572
|
-
debug(`Box
|
|
3574
|
+
debug(`Box "${this.name}" (id = ${this.node.id}) value:`);
|
|
3573
3575
|
debug(this.value);
|
|
3574
3576
|
});
|
|
3575
3577
|
if (this.type === 'block' && this.node.isContentEditable) {
|
|
@@ -3670,7 +3672,7 @@ class Box {
|
|
|
3670
3672
|
newContainer.append(content);
|
|
3671
3673
|
morph(container, newContainer);
|
|
3672
3674
|
}
|
|
3673
|
-
debug(`Box
|
|
3675
|
+
debug(`Box "${this.name}" (id: ${this.node.id}) rendered`);
|
|
3674
3676
|
}
|
|
3675
3677
|
// Destroys a rendered box.
|
|
3676
3678
|
unmount() {
|
|
@@ -3679,7 +3681,7 @@ class Box {
|
|
|
3679
3681
|
boxData[this.node.id] = {};
|
|
3680
3682
|
this.event.removeAllListeners();
|
|
3681
3683
|
this.node.empty();
|
|
3682
|
-
debug(`Box
|
|
3684
|
+
debug(`Box "${this.name}" (id: ${this.node.id}) unmounted`);
|
|
3683
3685
|
}
|
|
3684
3686
|
// Returns a HTML string of the box.
|
|
3685
3687
|
getHTML() {
|
|
@@ -4290,9 +4292,8 @@ function insertBookmark(range) {
|
|
|
4290
4292
|
function removeAndNormalizeNode(node, range) {
|
|
4291
4293
|
const previousNode = node.prev();
|
|
4292
4294
|
const nextNode = node.next();
|
|
4293
|
-
if (previousNode.isText
|
|
4295
|
+
if (previousNode.isText || nextNode.isText) {
|
|
4294
4296
|
const parentNode = node.parent();
|
|
4295
|
-
removeZWS(parentNode);
|
|
4296
4297
|
node.remove();
|
|
4297
4298
|
parentNode.get(0).normalize();
|
|
4298
4299
|
}
|
|
@@ -4375,8 +4376,8 @@ function deleteContents(range) {
|
|
|
4375
4376
|
if (range.isCollapsed) {
|
|
4376
4377
|
return;
|
|
4377
4378
|
}
|
|
4378
|
-
range.
|
|
4379
|
-
range.
|
|
4379
|
+
range.adjustBox();
|
|
4380
|
+
range.adjustTable();
|
|
4380
4381
|
if (range.isInoperative) {
|
|
4381
4382
|
return;
|
|
4382
4383
|
}
|
|
@@ -4385,7 +4386,7 @@ function deleteContents(range) {
|
|
|
4385
4386
|
const noMerge = startBlock.get(0) === endBlock.get(0);
|
|
4386
4387
|
const nativeRange = range.get();
|
|
4387
4388
|
nativeRange.deleteContents();
|
|
4388
|
-
range.
|
|
4389
|
+
range.adjustBlock();
|
|
4389
4390
|
if (noMerge) {
|
|
4390
4391
|
const block = range.getBlocks()[0];
|
|
4391
4392
|
if (block && block.isEmpty) {
|
|
@@ -4414,7 +4415,7 @@ function insertFragment(range, fragment) {
|
|
|
4414
4415
|
return;
|
|
4415
4416
|
}
|
|
4416
4417
|
if (range.isCollapsed) {
|
|
4417
|
-
range.
|
|
4418
|
+
range.adjustBox();
|
|
4418
4419
|
}
|
|
4419
4420
|
else {
|
|
4420
4421
|
deleteContents(range);
|
|
@@ -4424,7 +4425,7 @@ function insertFragment(range, fragment) {
|
|
|
4424
4425
|
const bookmark = insertBookmark(range);
|
|
4425
4426
|
bookmark.focus.before(fragment);
|
|
4426
4427
|
toBookmark(range, bookmark);
|
|
4427
|
-
range.
|
|
4428
|
+
range.adjustBlock();
|
|
4428
4429
|
}
|
|
4429
4430
|
|
|
4430
4431
|
// Inserts a HTML string into the specified range.
|
|
@@ -4543,7 +4544,7 @@ function splitBlock$1(range) {
|
|
|
4543
4544
|
};
|
|
4544
4545
|
}
|
|
4545
4546
|
if (range.isCollapsed) {
|
|
4546
|
-
range.
|
|
4547
|
+
range.adjustBox();
|
|
4547
4548
|
}
|
|
4548
4549
|
else {
|
|
4549
4550
|
deleteContents(range);
|
|
@@ -4596,7 +4597,7 @@ function splitBlock$1(range) {
|
|
|
4596
4597
|
}
|
|
4597
4598
|
|
|
4598
4599
|
// Removes empty marks that contain no content.
|
|
4599
|
-
function removeEmptyMarks$
|
|
4600
|
+
function removeEmptyMarks$2(node) {
|
|
4600
4601
|
if (node.isMark && node.isEmpty) {
|
|
4601
4602
|
node.remove();
|
|
4602
4603
|
return;
|
|
@@ -4618,8 +4619,8 @@ function splitMarksAtPoint(node, offset, removeEmptyMark) {
|
|
|
4618
4619
|
const parts = splitNodes(node, offset, limitBlock);
|
|
4619
4620
|
if (parts) {
|
|
4620
4621
|
if (removeEmptyMark) {
|
|
4621
|
-
removeEmptyMarks$
|
|
4622
|
-
removeEmptyMarks$
|
|
4622
|
+
removeEmptyMarks$2(parts.start);
|
|
4623
|
+
removeEmptyMarks$2(parts.end);
|
|
4623
4624
|
if (!parts.start.isEmpty) {
|
|
4624
4625
|
start = parts.start;
|
|
4625
4626
|
}
|
|
@@ -4649,7 +4650,7 @@ function splitMarks(range, removeEmptyMark = true) {
|
|
|
4649
4650
|
end: null,
|
|
4650
4651
|
};
|
|
4651
4652
|
}
|
|
4652
|
-
range.
|
|
4653
|
+
range.adjustBox();
|
|
4653
4654
|
if (range.isCollapsed) {
|
|
4654
4655
|
const parts = splitMarksAtPoint(range.startNode, range.startOffset, removeEmptyMark);
|
|
4655
4656
|
if (parts.start) {
|
|
@@ -4754,7 +4755,7 @@ function addMark(range, value) {
|
|
|
4754
4755
|
range.shrinkAfter(newBlock);
|
|
4755
4756
|
}
|
|
4756
4757
|
else {
|
|
4757
|
-
range.
|
|
4758
|
+
range.adjustBox();
|
|
4758
4759
|
}
|
|
4759
4760
|
}
|
|
4760
4761
|
const block = range.startNode.closestBlock();
|
|
@@ -4805,7 +4806,7 @@ function addMark(range, value) {
|
|
|
4805
4806
|
}
|
|
4806
4807
|
|
|
4807
4808
|
// Removes empty marks that contain no content.
|
|
4808
|
-
function removeEmptyMarks(node) {
|
|
4809
|
+
function removeEmptyMarks$1(node) {
|
|
4809
4810
|
if (node.isMark && node.isEmpty) {
|
|
4810
4811
|
node.remove();
|
|
4811
4812
|
return;
|
|
@@ -4863,13 +4864,13 @@ function removeMark(range, value) {
|
|
|
4863
4864
|
return;
|
|
4864
4865
|
}
|
|
4865
4866
|
if (parts.end) {
|
|
4866
|
-
removeEmptyMarks(parts.end);
|
|
4867
|
+
removeEmptyMarks$1(parts.end);
|
|
4867
4868
|
}
|
|
4868
4869
|
const zeroWidthSpace = new Nodes(document.createTextNode('\u200B'));
|
|
4869
4870
|
const newMark = copyNestedMarks(parts.start, tagName);
|
|
4870
4871
|
if (!newMark) {
|
|
4871
4872
|
parts.start.after(zeroWidthSpace);
|
|
4872
|
-
removeEmptyMarks(parts.start);
|
|
4873
|
+
removeEmptyMarks$1(parts.start);
|
|
4873
4874
|
if (zeroWidthSpace.prev().isText) {
|
|
4874
4875
|
range.setStartAfter(zeroWidthSpace.prev());
|
|
4875
4876
|
range.collapseToStart();
|
|
@@ -4882,7 +4883,7 @@ function removeMark(range, value) {
|
|
|
4882
4883
|
}
|
|
4883
4884
|
appendDeepest(newMark, zeroWidthSpace);
|
|
4884
4885
|
parts.start.after(newMark);
|
|
4885
|
-
removeEmptyMarks(parts.start);
|
|
4886
|
+
removeEmptyMarks$1(parts.start);
|
|
4886
4887
|
range.shrinkAfter(newMark);
|
|
4887
4888
|
return;
|
|
4888
4889
|
}
|
|
@@ -4950,7 +4951,7 @@ function insertLink(range, value) {
|
|
|
4950
4951
|
return linkNode;
|
|
4951
4952
|
}
|
|
4952
4953
|
|
|
4953
|
-
var version = "0.1.
|
|
4954
|
+
var version = "0.1.14";
|
|
4954
4955
|
|
|
4955
4956
|
// Inserts a box into the specified range.
|
|
4956
4957
|
function insertBox(range, boxName, boxValue) {
|
|
@@ -5119,7 +5120,10 @@ class Selection {
|
|
|
5119
5120
|
// Updates the saved range with the range of the native selection.
|
|
5120
5121
|
updateByRange() {
|
|
5121
5122
|
const newRange = this.getRangeFromNativeSelection();
|
|
5122
|
-
if (this.range.get() === newRange.get()
|
|
5123
|
+
if (this.range.startNode.get(0) === newRange.startNode.get(0) &&
|
|
5124
|
+
this.range.startOffset === newRange.startOffset &&
|
|
5125
|
+
this.range.endNode.get(0) === newRange.endNode.get(0) &&
|
|
5126
|
+
this.range.endOffset === newRange.endOffset) {
|
|
5123
5127
|
return;
|
|
5124
5128
|
}
|
|
5125
5129
|
this.range = newRange;
|
|
@@ -5221,7 +5225,6 @@ class Selection {
|
|
|
5221
5225
|
class Command {
|
|
5222
5226
|
constructor(selection) {
|
|
5223
5227
|
this.commandMap = new Map();
|
|
5224
|
-
this.event = new EventEmitter();
|
|
5225
5228
|
this.selection = selection;
|
|
5226
5229
|
}
|
|
5227
5230
|
add(name, commandItem) {
|
|
@@ -5239,7 +5242,7 @@ class Command {
|
|
|
5239
5242
|
getItem(name) {
|
|
5240
5243
|
const commandItem = this.commandMap.get(name);
|
|
5241
5244
|
if (commandItem === undefined) {
|
|
5242
|
-
throw new Error(`Command '${name}' does not exist
|
|
5245
|
+
throw new Error(`Command '${name}' does not exist`);
|
|
5243
5246
|
}
|
|
5244
5247
|
return commandItem;
|
|
5245
5248
|
}
|
|
@@ -5269,10 +5272,8 @@ class Command {
|
|
|
5269
5272
|
}
|
|
5270
5273
|
execute(name, ...data) {
|
|
5271
5274
|
const commandItem = this.getItem(name);
|
|
5272
|
-
this.event.emit('beforeexecute', name);
|
|
5273
5275
|
commandItem.execute.apply(this, data);
|
|
5274
|
-
|
|
5275
|
-
debug(`Command '${name}' executed`);
|
|
5276
|
+
debug(`Command "${name}" executed`);
|
|
5276
5277
|
}
|
|
5277
5278
|
}
|
|
5278
5279
|
|
|
@@ -5290,11 +5291,11 @@ class Command {
|
|
|
5290
5291
|
// inputs 'e': value: 'abe', list: ['a', 'ab', 'abe'], index: 3, canRedo: false
|
|
5291
5292
|
class History {
|
|
5292
5293
|
constructor(selection) {
|
|
5294
|
+
this.canSave = true;
|
|
5293
5295
|
// an array for storing the history items
|
|
5294
5296
|
this.list = [];
|
|
5295
5297
|
// the next index of the list
|
|
5296
5298
|
this.index = 0;
|
|
5297
|
-
this.canSave = true;
|
|
5298
5299
|
this.limit = 100;
|
|
5299
5300
|
this.event = new EventEmitter();
|
|
5300
5301
|
this.selection = selection;
|
|
@@ -5346,6 +5347,12 @@ class History {
|
|
|
5346
5347
|
this.removeIdfromBoxes(container);
|
|
5347
5348
|
this.removeIdfromBoxes(otherContainer);
|
|
5348
5349
|
}
|
|
5350
|
+
get canUndo() {
|
|
5351
|
+
return this.index > 1 && !!this.list[this.index - 1];
|
|
5352
|
+
}
|
|
5353
|
+
get canRedo() {
|
|
5354
|
+
return !!this.list[this.index];
|
|
5355
|
+
}
|
|
5349
5356
|
cloneContainer() {
|
|
5350
5357
|
const range = this.selection.range;
|
|
5351
5358
|
const newContainer = this.container.clone(true);
|
|
@@ -5357,6 +5364,12 @@ class History {
|
|
|
5357
5364
|
return newContainer;
|
|
5358
5365
|
}
|
|
5359
5366
|
if (range.isInsideBox) {
|
|
5367
|
+
const boxNode = range.commonAncestor.closest('lake-box');
|
|
5368
|
+
const boxNodePath = boxNode.path();
|
|
5369
|
+
const newBoxNode = newContainer.find(boxNodePath);
|
|
5370
|
+
const newRange = range.clone();
|
|
5371
|
+
newRange.selectBox(newBoxNode);
|
|
5372
|
+
insertBookmark(newRange);
|
|
5360
5373
|
return newContainer;
|
|
5361
5374
|
}
|
|
5362
5375
|
const startNodePath = range.startNode.path();
|
|
@@ -5369,39 +5382,27 @@ class History {
|
|
|
5369
5382
|
insertBookmark(newRange);
|
|
5370
5383
|
return newContainer;
|
|
5371
5384
|
}
|
|
5372
|
-
get count() {
|
|
5373
|
-
return this.list.length;
|
|
5374
|
-
}
|
|
5375
|
-
get canUndo() {
|
|
5376
|
-
return this.index > 1 && !!this.list[this.index - 1];
|
|
5377
|
-
}
|
|
5378
|
-
get canRedo() {
|
|
5379
|
-
return !!this.list[this.index];
|
|
5380
|
-
}
|
|
5381
5385
|
undo() {
|
|
5382
|
-
if (!this.list[this.index -
|
|
5386
|
+
if (!this.list[this.index - 2]) {
|
|
5383
5387
|
return;
|
|
5384
5388
|
}
|
|
5385
5389
|
this.selection.insertBookmark();
|
|
5386
5390
|
const value = this.getValue(this.container);
|
|
5387
|
-
while (this.index >
|
|
5388
|
-
const prevItem = this.list[this.index -
|
|
5391
|
+
while (this.index > 1) {
|
|
5392
|
+
const prevItem = this.list[this.index - 2];
|
|
5389
5393
|
if (!prevItem) {
|
|
5390
5394
|
break;
|
|
5391
5395
|
}
|
|
5396
|
+
this.index--;
|
|
5392
5397
|
const prevValue = this.getValue(prevItem);
|
|
5393
5398
|
if (this.removeBookmark(prevValue) !== this.removeBookmark(value)) {
|
|
5394
5399
|
this.morphContainer(prevItem);
|
|
5395
5400
|
this.event.emit('undo', prevValue);
|
|
5396
5401
|
break;
|
|
5397
5402
|
}
|
|
5398
|
-
if (this.index === 1) {
|
|
5399
|
-
break;
|
|
5400
|
-
}
|
|
5401
|
-
this.index--;
|
|
5402
5403
|
}
|
|
5403
5404
|
this.selection.updateByBookmark();
|
|
5404
|
-
debug(`History undone
|
|
5405
|
+
debug(`History undone (index: ${this.index})`);
|
|
5405
5406
|
}
|
|
5406
5407
|
redo() {
|
|
5407
5408
|
if (!this.list[this.index]) {
|
|
@@ -5423,7 +5424,7 @@ class History {
|
|
|
5423
5424
|
}
|
|
5424
5425
|
}
|
|
5425
5426
|
this.selection.updateByBookmark();
|
|
5426
|
-
debug(`History redone
|
|
5427
|
+
debug(`History redone (index: ${this.index})`);
|
|
5427
5428
|
}
|
|
5428
5429
|
continue() {
|
|
5429
5430
|
this.canSave = true;
|
|
@@ -5431,7 +5432,11 @@ class History {
|
|
|
5431
5432
|
pause() {
|
|
5432
5433
|
this.canSave = false;
|
|
5433
5434
|
}
|
|
5434
|
-
save(
|
|
5435
|
+
save(options = {}) {
|
|
5436
|
+
var _a, _b, _c;
|
|
5437
|
+
const inputType = (_a = options.inputType) !== null && _a !== void 0 ? _a : '';
|
|
5438
|
+
const update = (_b = options.update) !== null && _b !== void 0 ? _b : false;
|
|
5439
|
+
const emitEvent = (_c = options.emitEvent) !== null && _c !== void 0 ? _c : true;
|
|
5435
5440
|
if (!this.canSave) {
|
|
5436
5441
|
return;
|
|
5437
5442
|
}
|
|
@@ -5441,16 +5446,25 @@ class History {
|
|
|
5441
5446
|
this.removeBookmark(this.getValue(this.list[this.index - 1])) === this.removeBookmark(value)) {
|
|
5442
5447
|
return;
|
|
5443
5448
|
}
|
|
5444
|
-
|
|
5445
|
-
|
|
5449
|
+
if (update) {
|
|
5450
|
+
this.list.splice(this.index - 1, Infinity, item);
|
|
5451
|
+
}
|
|
5452
|
+
else {
|
|
5453
|
+
this.list.splice(this.index, Infinity, item);
|
|
5454
|
+
this.index++;
|
|
5455
|
+
}
|
|
5446
5456
|
if (this.list.length > this.limit) {
|
|
5447
5457
|
this.list.shift();
|
|
5448
5458
|
this.index = this.list.length;
|
|
5449
5459
|
}
|
|
5450
|
-
|
|
5451
|
-
|
|
5460
|
+
debug(`History saved (index: ${this.index}, inputType: "${inputType}", update: ${update}, emitEvent: ${emitEvent})`);
|
|
5461
|
+
if (emitEvent) {
|
|
5462
|
+
this.event.emit('save', denormalizeValue(value), {
|
|
5463
|
+
inputType,
|
|
5464
|
+
update,
|
|
5465
|
+
emitEvent,
|
|
5466
|
+
});
|
|
5452
5467
|
}
|
|
5453
|
-
debug(`History saved, the last index is ${this.index}`);
|
|
5454
5468
|
}
|
|
5455
5469
|
}
|
|
5456
5470
|
|
|
@@ -5529,27 +5543,6 @@ class BoxManager {
|
|
|
5529
5543
|
getNames() {
|
|
5530
5544
|
return Array.from(boxes.keys());
|
|
5531
5545
|
}
|
|
5532
|
-
rectifyInstances(container) {
|
|
5533
|
-
const instanceMap = getInstanceMap(container.id);
|
|
5534
|
-
for (const box of instanceMap.values()) {
|
|
5535
|
-
if (!box.node.get(0).isConnected) {
|
|
5536
|
-
box.unmount();
|
|
5537
|
-
instanceMap.delete(box.node.id);
|
|
5538
|
-
}
|
|
5539
|
-
}
|
|
5540
|
-
}
|
|
5541
|
-
renderAll(container) {
|
|
5542
|
-
this.rectifyInstances(container);
|
|
5543
|
-
const instanceMap = getInstanceMap(container.id);
|
|
5544
|
-
container.find('lake-box').each(boxNativeNode => {
|
|
5545
|
-
const boxNode = query(boxNativeNode);
|
|
5546
|
-
if (instanceMap.get(boxNode.id)) {
|
|
5547
|
-
return;
|
|
5548
|
-
}
|
|
5549
|
-
const box = getBox(boxNode);
|
|
5550
|
-
box.render();
|
|
5551
|
-
});
|
|
5552
|
-
}
|
|
5553
5546
|
}
|
|
5554
5547
|
|
|
5555
5548
|
class Plugin {
|
|
@@ -5595,6 +5588,7 @@ const defaultConfig = {
|
|
|
5595
5588
|
class Editor {
|
|
5596
5589
|
constructor(config) {
|
|
5597
5590
|
this.unsavedInputData = '';
|
|
5591
|
+
this.unsavedInputCount = 0;
|
|
5598
5592
|
this.state = {
|
|
5599
5593
|
appliedItems: [],
|
|
5600
5594
|
disabledNameMap: new Map(),
|
|
@@ -5625,9 +5619,6 @@ class Editor {
|
|
|
5625
5619
|
}
|
|
5626
5620
|
this.event.emit('paste', event);
|
|
5627
5621
|
};
|
|
5628
|
-
this.beforeunloadListener = () => {
|
|
5629
|
-
this.history.save();
|
|
5630
|
-
};
|
|
5631
5622
|
this.selectionchangeListener = () => {
|
|
5632
5623
|
this.selection.updateByRange();
|
|
5633
5624
|
this.updateBoxSelectionStyle();
|
|
@@ -5643,6 +5634,7 @@ class Editor {
|
|
|
5643
5634
|
this.resizeListener = () => {
|
|
5644
5635
|
this.event.emit('resize');
|
|
5645
5636
|
};
|
|
5637
|
+
// Updates the classes of all boxes when the current selection of the editor is changed.
|
|
5646
5638
|
this.updateBoxSelectionStyle = debounce(() => {
|
|
5647
5639
|
// The editor has been unmounted.
|
|
5648
5640
|
if (this.root.first().length === 0) {
|
|
@@ -5650,7 +5642,7 @@ class Editor {
|
|
|
5650
5642
|
}
|
|
5651
5643
|
const range = this.selection.range;
|
|
5652
5644
|
const clonedRange = range.clone();
|
|
5653
|
-
clonedRange.
|
|
5645
|
+
clonedRange.adjustBox();
|
|
5654
5646
|
this.container.find('lake-box').each(boxNativeNode => {
|
|
5655
5647
|
const box = getBox(boxNativeNode);
|
|
5656
5648
|
const boxContainer = box.getContainer();
|
|
@@ -5693,6 +5685,7 @@ class Editor {
|
|
|
5693
5685
|
trailing: true,
|
|
5694
5686
|
maxWait: 50,
|
|
5695
5687
|
});
|
|
5688
|
+
// Triggers the statechange event when the current selection of the editor is changed.
|
|
5696
5689
|
this.emitStateChangeEvent = debounce(() => {
|
|
5697
5690
|
const commandNames = this.command.getNames();
|
|
5698
5691
|
let appliedItems = this.selection.getAppliedItems();
|
|
@@ -5739,13 +5732,6 @@ class Editor {
|
|
|
5739
5732
|
trailing: true,
|
|
5740
5733
|
maxWait: 100,
|
|
5741
5734
|
});
|
|
5742
|
-
this.emitChangeEvent = (value) => {
|
|
5743
|
-
this.rectifyContent();
|
|
5744
|
-
this.emitStateChangeEvent();
|
|
5745
|
-
this.togglePlaceholderClass(value);
|
|
5746
|
-
this.scrollToCaret();
|
|
5747
|
-
this.event.emit('change', value);
|
|
5748
|
-
};
|
|
5749
5735
|
if (!config.root) {
|
|
5750
5736
|
throw new Error('The root of the config must be specified.');
|
|
5751
5737
|
}
|
|
@@ -5775,6 +5761,7 @@ class Editor {
|
|
|
5775
5761
|
this.keystroke = new Keystroke(this.container);
|
|
5776
5762
|
editors.set(this.container.id, this);
|
|
5777
5763
|
}
|
|
5764
|
+
// Adds or Removes a placeholder class.
|
|
5778
5765
|
togglePlaceholderClass(value) {
|
|
5779
5766
|
value = denormalizeValue(value);
|
|
5780
5767
|
const className = 'lake-show-placeholder';
|
|
@@ -5785,7 +5772,8 @@ class Editor {
|
|
|
5785
5772
|
this.container.removeClass(className);
|
|
5786
5773
|
}
|
|
5787
5774
|
}
|
|
5788
|
-
|
|
5775
|
+
// Moves the input text from box strip to normal position.
|
|
5776
|
+
moveBoxStripText() {
|
|
5789
5777
|
const selection = this.selection;
|
|
5790
5778
|
const range = selection.range;
|
|
5791
5779
|
const stripNode = range.startNode.closest('.lake-box-strip');
|
|
@@ -5815,6 +5803,12 @@ class Editor {
|
|
|
5815
5803
|
stripNode.html('<br />');
|
|
5816
5804
|
selection.insertNode(document.createTextNode(text));
|
|
5817
5805
|
}
|
|
5806
|
+
// Resets the value of unsaved input property.
|
|
5807
|
+
resetUnsavedInputData() {
|
|
5808
|
+
this.unsavedInputData = '';
|
|
5809
|
+
this.unsavedInputCount = 0;
|
|
5810
|
+
}
|
|
5811
|
+
// Binds events about input.
|
|
5818
5812
|
bindInputEvents() {
|
|
5819
5813
|
this.container.on('compositionstart', () => {
|
|
5820
5814
|
this.isComposing = true;
|
|
@@ -5822,19 +5816,6 @@ class Editor {
|
|
|
5822
5816
|
this.container.on('compositionend', () => {
|
|
5823
5817
|
this.isComposing = false;
|
|
5824
5818
|
});
|
|
5825
|
-
this.container.on('beforeinput', event => {
|
|
5826
|
-
const inputEvent = event;
|
|
5827
|
-
const range = this.selection.range;
|
|
5828
|
-
if (range.isBoxStart || range.isBoxEnd) {
|
|
5829
|
-
this.commitUnsavedInputData();
|
|
5830
|
-
return;
|
|
5831
|
-
}
|
|
5832
|
-
if (inputEvent.inputType === 'insertText' ||
|
|
5833
|
-
inputEvent.inputType === 'insertCompositionText') {
|
|
5834
|
-
return;
|
|
5835
|
-
}
|
|
5836
|
-
this.commitUnsavedInputData();
|
|
5837
|
-
});
|
|
5838
5819
|
this.container.on('input', event => {
|
|
5839
5820
|
const inputEvent = event;
|
|
5840
5821
|
// Here setTimeout is necessary because isComposing is not false after ending composition.
|
|
@@ -5850,7 +5831,7 @@ class Editor {
|
|
|
5850
5831
|
return;
|
|
5851
5832
|
}
|
|
5852
5833
|
if (range.isBoxStart || range.isBoxEnd) {
|
|
5853
|
-
this.
|
|
5834
|
+
this.moveBoxStripText();
|
|
5854
5835
|
this.history.save();
|
|
5855
5836
|
this.event.emit('input', inputEvent);
|
|
5856
5837
|
return;
|
|
@@ -5858,30 +5839,60 @@ class Editor {
|
|
|
5858
5839
|
if (inputEvent.inputType === 'insertText' ||
|
|
5859
5840
|
inputEvent.inputType === 'insertCompositionText') {
|
|
5860
5841
|
this.unsavedInputData += (_a = inputEvent.data) !== null && _a !== void 0 ? _a : '';
|
|
5842
|
+
this.unsavedInputCount++;
|
|
5861
5843
|
if (this.unsavedInputData.length < this.config.minChangeSize) {
|
|
5862
|
-
this.
|
|
5863
|
-
|
|
5864
|
-
|
|
5844
|
+
this.history.save({
|
|
5845
|
+
inputType: 'insertText',
|
|
5846
|
+
update: this.unsavedInputCount > 1,
|
|
5847
|
+
});
|
|
5865
5848
|
}
|
|
5849
|
+
else {
|
|
5850
|
+
this.history.save({
|
|
5851
|
+
inputType: 'insertText',
|
|
5852
|
+
update: true,
|
|
5853
|
+
});
|
|
5854
|
+
this.resetUnsavedInputData();
|
|
5855
|
+
}
|
|
5856
|
+
this.event.emit('input', inputEvent);
|
|
5857
|
+
return;
|
|
5866
5858
|
}
|
|
5867
5859
|
this.history.save();
|
|
5868
5860
|
this.event.emit('input', inputEvent);
|
|
5869
5861
|
}, 0);
|
|
5870
5862
|
});
|
|
5871
|
-
this.command.event.on('beforeexecute', () => this.commitUnsavedInputData());
|
|
5872
5863
|
}
|
|
5864
|
+
// Binds events about history.
|
|
5873
5865
|
bindHistoryEvents() {
|
|
5866
|
+
const executeCommonMethods = (value) => {
|
|
5867
|
+
if (this.fixContent()) {
|
|
5868
|
+
this.history.save({
|
|
5869
|
+
update: true,
|
|
5870
|
+
emitEvent: false,
|
|
5871
|
+
});
|
|
5872
|
+
value = this.getValue();
|
|
5873
|
+
}
|
|
5874
|
+
this.emitStateChangeEvent();
|
|
5875
|
+
this.togglePlaceholderClass(value);
|
|
5876
|
+
this.scrollToCaret();
|
|
5877
|
+
this.event.emit('change', value);
|
|
5878
|
+
};
|
|
5874
5879
|
this.history.event.on('undo', value => {
|
|
5875
|
-
this.
|
|
5876
|
-
|
|
5880
|
+
this.renderBoxes();
|
|
5881
|
+
executeCommonMethods(value);
|
|
5882
|
+
this.resetUnsavedInputData();
|
|
5877
5883
|
});
|
|
5878
5884
|
this.history.event.on('redo', value => {
|
|
5879
|
-
this.
|
|
5880
|
-
|
|
5885
|
+
this.renderBoxes();
|
|
5886
|
+
executeCommonMethods(value);
|
|
5887
|
+
this.resetUnsavedInputData();
|
|
5881
5888
|
});
|
|
5882
|
-
this.history.event.on('save', value => {
|
|
5883
|
-
this.
|
|
5884
|
-
|
|
5889
|
+
this.history.event.on('save', (value, options) => {
|
|
5890
|
+
this.removeBoxGarbage();
|
|
5891
|
+
executeCommonMethods(value);
|
|
5892
|
+
this.selection.sync();
|
|
5893
|
+
if (options.inputType !== 'insertText') {
|
|
5894
|
+
this.resetUnsavedInputData();
|
|
5895
|
+
}
|
|
5885
5896
|
});
|
|
5886
5897
|
}
|
|
5887
5898
|
// Returns a boolean value indicating whether the editor has focus.
|
|
@@ -5897,65 +5908,76 @@ class Editor {
|
|
|
5897
5908
|
return i18nObject(this.config.lang);
|
|
5898
5909
|
}
|
|
5899
5910
|
// Fixes wrong content, especially empty tag.
|
|
5900
|
-
|
|
5911
|
+
fixContent() {
|
|
5912
|
+
let changed = false;
|
|
5901
5913
|
let children = this.container.children();
|
|
5902
5914
|
for (const child of children) {
|
|
5903
5915
|
if ((child.isBlock || child.isMark) && child.html() === '') {
|
|
5904
5916
|
child.remove();
|
|
5905
|
-
|
|
5917
|
+
changed = true;
|
|
5918
|
+
debug(`Content fixed: empty tag "${child.name}" was removed`);
|
|
5906
5919
|
}
|
|
5907
5920
|
}
|
|
5908
5921
|
children = this.container.children();
|
|
5909
5922
|
if (children.length === 0) {
|
|
5910
5923
|
this.container.html('<p><br /></p>');
|
|
5911
5924
|
this.selection.range.shrinkAfter(this.container);
|
|
5912
|
-
|
|
5913
|
-
|
|
5925
|
+
changed = true;
|
|
5926
|
+
debug('Content fixed: default paragraph was added');
|
|
5914
5927
|
}
|
|
5915
|
-
if (children.length === 1) {
|
|
5928
|
+
else if (children.length === 1) {
|
|
5916
5929
|
const child = children[0];
|
|
5917
5930
|
if (child.isVoid) {
|
|
5918
5931
|
const paragraph = query('<p />');
|
|
5919
5932
|
child.before(paragraph);
|
|
5920
5933
|
paragraph.append(child);
|
|
5921
5934
|
this.selection.range.shrinkAfter(paragraph);
|
|
5922
|
-
|
|
5935
|
+
changed = true;
|
|
5936
|
+
debug(`Content fixed: void element "${child.name}" was wrapped in paragraph`);
|
|
5923
5937
|
}
|
|
5924
5938
|
}
|
|
5925
|
-
|
|
5926
|
-
// Saves the input data which is unsaved.
|
|
5927
|
-
commitUnsavedInputData() {
|
|
5928
|
-
if (this.unsavedInputData.length > 0) {
|
|
5929
|
-
this.history.save(false);
|
|
5930
|
-
this.unsavedInputData = '';
|
|
5931
|
-
}
|
|
5932
|
-
}
|
|
5933
|
-
// Updates some state before custom modifications.
|
|
5934
|
-
prepareOperation() {
|
|
5935
|
-
this.commitUnsavedInputData();
|
|
5936
|
-
this.history.pause();
|
|
5937
|
-
}
|
|
5938
|
-
// Saves custom modifications to the history.
|
|
5939
|
-
commitOperation() {
|
|
5940
|
-
this.history.continue();
|
|
5941
|
-
this.history.save();
|
|
5939
|
+
return changed;
|
|
5942
5940
|
}
|
|
5943
5941
|
// Sets default config for a plugin.
|
|
5944
|
-
setPluginConfig(
|
|
5945
|
-
if (!this.config[
|
|
5946
|
-
this.config[
|
|
5942
|
+
setPluginConfig(name, config) {
|
|
5943
|
+
if (!this.config[name]) {
|
|
5944
|
+
this.config[name] = {};
|
|
5945
|
+
}
|
|
5946
|
+
for (const key of Object.keys(config)) {
|
|
5947
|
+
if (this.config[name][key] === undefined) {
|
|
5948
|
+
this.config[name][key] = config[key];
|
|
5949
|
+
}
|
|
5947
5950
|
}
|
|
5948
|
-
|
|
5949
|
-
|
|
5950
|
-
|
|
5951
|
+
}
|
|
5952
|
+
// Removes all unused box instances.
|
|
5953
|
+
removeBoxGarbage() {
|
|
5954
|
+
const instanceMap = getInstanceMap(this.container.id);
|
|
5955
|
+
for (const box of instanceMap.values()) {
|
|
5956
|
+
if (!box.node.get(0).isConnected) {
|
|
5957
|
+
box.unmount();
|
|
5958
|
+
instanceMap.delete(box.node.id);
|
|
5951
5959
|
}
|
|
5952
5960
|
}
|
|
5953
5961
|
}
|
|
5954
|
-
//
|
|
5962
|
+
// Renders all boxes that haven't been rendered yet.
|
|
5963
|
+
renderBoxes() {
|
|
5964
|
+
this.removeBoxGarbage();
|
|
5965
|
+
const container = this.container;
|
|
5966
|
+
const instanceMap = getInstanceMap(container.id);
|
|
5967
|
+
container.find('lake-box').each(boxNativeNode => {
|
|
5968
|
+
const boxNode = query(boxNativeNode);
|
|
5969
|
+
if (instanceMap.get(boxNode.id)) {
|
|
5970
|
+
return;
|
|
5971
|
+
}
|
|
5972
|
+
const box = getBox(boxNode);
|
|
5973
|
+
box.render();
|
|
5974
|
+
});
|
|
5975
|
+
}
|
|
5976
|
+
// Sets focus on the editor.
|
|
5955
5977
|
focus() {
|
|
5956
5978
|
this.container.focus();
|
|
5957
5979
|
}
|
|
5958
|
-
// Removes focus from the editor
|
|
5980
|
+
// Removes focus from the editor.
|
|
5959
5981
|
blur() {
|
|
5960
5982
|
this.container.blur();
|
|
5961
5983
|
}
|
|
@@ -5963,6 +5985,9 @@ class Editor {
|
|
|
5963
5985
|
scrollToCaret() {
|
|
5964
5986
|
// Creates an artificial caret that is the same size as the caret at the current caret position.
|
|
5965
5987
|
const rangeRect = this.selection.range.getRect();
|
|
5988
|
+
if (rangeRect.x === 0 || rangeRect.y === 0) {
|
|
5989
|
+
return;
|
|
5990
|
+
}
|
|
5966
5991
|
const containerRect = this.container.get(0).getBoundingClientRect();
|
|
5967
5992
|
const artificialCaret = query('<div class="lake-artificial-caret" />');
|
|
5968
5993
|
const left = rangeRect.x - containerRect.x;
|
|
@@ -5978,48 +6003,20 @@ class Editor {
|
|
|
5978
6003
|
});
|
|
5979
6004
|
this.overlayContainer.find('.lake-artificial-caret').remove();
|
|
5980
6005
|
this.overlayContainer.append(artificialCaret);
|
|
6006
|
+
const position = nodeAndView(artificialCaret);
|
|
5981
6007
|
// Scrolls the artificial caret element into the visible area of the browser window
|
|
5982
6008
|
// if it's not already within the visible area of the browser window.
|
|
5983
|
-
// If the element is already within the
|
|
5984
|
-
|
|
5985
|
-
|
|
5986
|
-
|
|
5987
|
-
|
|
5988
|
-
|
|
5989
|
-
|
|
5990
|
-
const nativeViewport = viewport.get(0);
|
|
5991
|
-
const viewportRect = nativeViewport.getBoundingClientRect();
|
|
5992
|
-
scrollX = nativeViewport.scrollLeft;
|
|
5993
|
-
scrollY = nativeViewport.scrollTop;
|
|
5994
|
-
viewportWidth = viewportRect.width;
|
|
5995
|
-
viewportHeight = viewportRect.height;
|
|
5996
|
-
}
|
|
5997
|
-
else {
|
|
5998
|
-
const nativeContainerWrapper = this.containerWrapper.get(0);
|
|
5999
|
-
scrollX = window.scrollX;
|
|
6000
|
-
scrollY = window.scrollY;
|
|
6001
|
-
viewportWidth = window.innerWidth - nativeContainerWrapper.offsetLeft;
|
|
6002
|
-
viewportHeight = window.innerHeight - nativeContainerWrapper.offsetTop;
|
|
6003
|
-
}
|
|
6004
|
-
let needScroll = false;
|
|
6005
|
-
let alignToTop = true;
|
|
6006
|
-
if (left < scrollX || left > scrollX + viewportWidth) {
|
|
6007
|
-
needScroll = true;
|
|
6008
|
-
}
|
|
6009
|
-
if (top < scrollY) {
|
|
6010
|
-
needScroll = true;
|
|
6011
|
-
alignToTop = true;
|
|
6012
|
-
}
|
|
6013
|
-
else if (top > scrollY + viewportHeight) {
|
|
6014
|
-
needScroll = true;
|
|
6015
|
-
alignToTop = false;
|
|
6016
|
-
}
|
|
6017
|
-
if (needScroll) {
|
|
6018
|
-
artificialCaret.get(0).scrollIntoView(alignToTop);
|
|
6009
|
+
// If the element is already within the visibposition.rightle area of the browser window, then no scrolling takes place.
|
|
6010
|
+
if (position.left < 0 || position.right < 0 || position.top < 0 || position.bottom < 0) {
|
|
6011
|
+
artificialCaret.get(0).scrollIntoView({
|
|
6012
|
+
behavior: 'instant',
|
|
6013
|
+
block: 'center',
|
|
6014
|
+
inline: 'nearest',
|
|
6015
|
+
});
|
|
6019
6016
|
}
|
|
6020
6017
|
artificialCaret.remove();
|
|
6021
6018
|
}
|
|
6022
|
-
// Sets the specified
|
|
6019
|
+
// Sets the specified value to the editor.
|
|
6023
6020
|
setValue(value) {
|
|
6024
6021
|
value = normalizeValue(value);
|
|
6025
6022
|
const htmlParser = new HTMLParser(value);
|
|
@@ -6027,18 +6024,17 @@ class Editor {
|
|
|
6027
6024
|
this.container.empty();
|
|
6028
6025
|
this.togglePlaceholderClass(htmlParser.getHTML());
|
|
6029
6026
|
this.container.append(fragment);
|
|
6030
|
-
|
|
6027
|
+
this.renderBoxes();
|
|
6031
6028
|
this.selection.updateByBookmark();
|
|
6032
6029
|
}
|
|
6033
|
-
// Returns the
|
|
6030
|
+
// Returns the value of the editor.
|
|
6034
6031
|
getValue() {
|
|
6035
|
-
const
|
|
6036
|
-
let value = new HTMLParser(
|
|
6032
|
+
const item = this.history.cloneContainer();
|
|
6033
|
+
let value = new HTMLParser(item).getHTML();
|
|
6037
6034
|
value = denormalizeValue(value);
|
|
6038
|
-
this.selection.toBookmark(bookmark);
|
|
6039
6035
|
return value;
|
|
6040
6036
|
}
|
|
6041
|
-
// Renders an editor area and
|
|
6037
|
+
// Renders an editor area and sets default value to it.
|
|
6042
6038
|
render() {
|
|
6043
6039
|
const value = normalizeValue(this.config.value);
|
|
6044
6040
|
const htmlParser = new HTMLParser(value);
|
|
@@ -6053,9 +6049,11 @@ class Editor {
|
|
|
6053
6049
|
Editor.plugin.loadAll(this);
|
|
6054
6050
|
if (!this.readonly) {
|
|
6055
6051
|
this.selection.updateByBookmark();
|
|
6056
|
-
this.history.save(
|
|
6052
|
+
this.history.save({
|
|
6053
|
+
emitEvent: false,
|
|
6054
|
+
});
|
|
6057
6055
|
}
|
|
6058
|
-
|
|
6056
|
+
this.renderBoxes();
|
|
6059
6057
|
if (this.toolbar) {
|
|
6060
6058
|
this.toolbar.render(this);
|
|
6061
6059
|
}
|
|
@@ -6063,7 +6061,6 @@ class Editor {
|
|
|
6063
6061
|
if (!this.readonly) {
|
|
6064
6062
|
document.addEventListener('cut', this.cutListener);
|
|
6065
6063
|
document.addEventListener('paste', this.pasteListener);
|
|
6066
|
-
window.addEventListener('beforeunload', this.beforeunloadListener);
|
|
6067
6064
|
document.addEventListener('selectionchange', this.selectionchangeListener);
|
|
6068
6065
|
document.addEventListener('click', this.clickListener);
|
|
6069
6066
|
window.addEventListener('resize', this.resizeListener);
|
|
@@ -6071,10 +6068,9 @@ class Editor {
|
|
|
6071
6068
|
this.bindHistoryEvents();
|
|
6072
6069
|
}
|
|
6073
6070
|
}
|
|
6074
|
-
// Destroys
|
|
6071
|
+
// Destroys the rendered editor.
|
|
6075
6072
|
unmount() {
|
|
6076
6073
|
this.event.removeAllListeners();
|
|
6077
|
-
this.command.event.removeAllListeners();
|
|
6078
6074
|
this.history.event.removeAllListeners();
|
|
6079
6075
|
this.root.empty();
|
|
6080
6076
|
this.popupContainer.remove();
|
|
@@ -6082,7 +6078,6 @@ class Editor {
|
|
|
6082
6078
|
if (!this.readonly) {
|
|
6083
6079
|
document.removeEventListener('cut', this.cutListener);
|
|
6084
6080
|
document.removeEventListener('paste', this.pasteListener);
|
|
6085
|
-
window.removeEventListener('beforeunload', this.beforeunloadListener);
|
|
6086
6081
|
document.removeEventListener('selectionchange', this.selectionchangeListener);
|
|
6087
6082
|
document.removeEventListener('click', this.clickListener);
|
|
6088
6083
|
window.removeEventListener('resize', this.resizeListener);
|
|
@@ -7131,7 +7126,6 @@ function appendButtonGroup(box) {
|
|
|
7131
7126
|
event.stopPropagation();
|
|
7132
7127
|
editor.selection.removeBox(box);
|
|
7133
7128
|
editor.history.save();
|
|
7134
|
-
editor.selection.sync();
|
|
7135
7129
|
});
|
|
7136
7130
|
videoNode.append(buttonGroupNode);
|
|
7137
7131
|
}
|
|
@@ -7853,7 +7847,6 @@ const imageBox = {
|
|
|
7853
7847
|
}
|
|
7854
7848
|
editor.selection.removeBox(box);
|
|
7855
7849
|
editor.history.save();
|
|
7856
|
-
editor.selection.sync();
|
|
7857
7850
|
});
|
|
7858
7851
|
}
|
|
7859
7852
|
box.event.emit('render');
|
|
@@ -7890,7 +7883,6 @@ const boxToolbarItems = [
|
|
|
7890
7883
|
}
|
|
7891
7884
|
editor.selection.removeBox(box);
|
|
7892
7885
|
editor.history.save();
|
|
7893
|
-
editor.selection.sync();
|
|
7894
7886
|
},
|
|
7895
7887
|
},
|
|
7896
7888
|
];
|
|
@@ -7970,7 +7962,11 @@ var copy = (editor) => {
|
|
|
7970
7962
|
if (range.isInsideBox) {
|
|
7971
7963
|
return;
|
|
7972
7964
|
}
|
|
7973
|
-
|
|
7965
|
+
if (!range.isCollapsed) {
|
|
7966
|
+
range.adjust();
|
|
7967
|
+
return;
|
|
7968
|
+
}
|
|
7969
|
+
const boxNode = range.commonAncestor.closest('lake-box');
|
|
7974
7970
|
if (boxNode.length === 0) {
|
|
7975
7971
|
return;
|
|
7976
7972
|
}
|
|
@@ -7992,12 +7988,26 @@ var cut = (editor) => {
|
|
|
7992
7988
|
if (editor.readonly) {
|
|
7993
7989
|
return;
|
|
7994
7990
|
}
|
|
7995
|
-
editor.event.on('cut', event => {
|
|
7991
|
+
editor.event.on('cut', (event) => {
|
|
7992
|
+
const dataTransfer = event.clipboardData;
|
|
7993
|
+
if (!dataTransfer) {
|
|
7994
|
+
return;
|
|
7995
|
+
}
|
|
7996
7996
|
const range = editor.selection.range;
|
|
7997
7997
|
if (range.isInsideBox) {
|
|
7998
7998
|
return;
|
|
7999
7999
|
}
|
|
8000
|
-
|
|
8000
|
+
if (!range.isCollapsed) {
|
|
8001
|
+
event.preventDefault();
|
|
8002
|
+
const fragment = editor.selection.range.cloneContents();
|
|
8003
|
+
const tempContainer = query('<div />');
|
|
8004
|
+
tempContainer.append(fragment);
|
|
8005
|
+
dataTransfer.setData('text/html', tempContainer.html());
|
|
8006
|
+
editor.selection.deleteContents();
|
|
8007
|
+
editor.history.save();
|
|
8008
|
+
return;
|
|
8009
|
+
}
|
|
8010
|
+
const boxNode = range.commonAncestor.closest('lake-box');
|
|
8001
8011
|
if (boxNode.length === 0) {
|
|
8002
8012
|
return;
|
|
8003
8013
|
}
|
|
@@ -8005,10 +8015,6 @@ var cut = (editor) => {
|
|
|
8005
8015
|
return;
|
|
8006
8016
|
}
|
|
8007
8017
|
event.preventDefault();
|
|
8008
|
-
const dataTransfer = event.clipboardData;
|
|
8009
|
-
if (!dataTransfer) {
|
|
8010
|
-
return;
|
|
8011
|
-
}
|
|
8012
8018
|
const box = getBox(boxNode);
|
|
8013
8019
|
const content = box.getHTML();
|
|
8014
8020
|
dataTransfer.setData('text/html', content);
|
|
@@ -8130,6 +8136,14 @@ function insertFirstNode(editor, otherNode) {
|
|
|
8130
8136
|
}
|
|
8131
8137
|
const nextSibling = child.next();
|
|
8132
8138
|
editor.selection.insertNode(child);
|
|
8139
|
+
if (child.isBox) {
|
|
8140
|
+
getBox(child).render();
|
|
8141
|
+
}
|
|
8142
|
+
else if (child.isElement) {
|
|
8143
|
+
child.find('lake-box').each(node => {
|
|
8144
|
+
getBox(node).render();
|
|
8145
|
+
});
|
|
8146
|
+
}
|
|
8133
8147
|
child = nextSibling;
|
|
8134
8148
|
}
|
|
8135
8149
|
otherNode.remove();
|
|
@@ -8167,6 +8181,7 @@ function pasteFragment(editor, fragment) {
|
|
|
8167
8181
|
parts.end.remove();
|
|
8168
8182
|
}
|
|
8169
8183
|
selection.insertFragment(fragment);
|
|
8184
|
+
editor.renderBoxes();
|
|
8170
8185
|
range.shrinkAfter(lastNode);
|
|
8171
8186
|
}
|
|
8172
8187
|
fixNumberedList(editor.container.children().filter(node => node.isBlock));
|
|
@@ -8219,7 +8234,6 @@ var paste = (editor) => {
|
|
|
8219
8234
|
editor.event.emit('beforepaste', fragment);
|
|
8220
8235
|
fixClipboardData(fragment);
|
|
8221
8236
|
pasteFragment(editor, fragment);
|
|
8222
|
-
editor.box.renderAll(editor.container);
|
|
8223
8237
|
});
|
|
8224
8238
|
};
|
|
8225
8239
|
|
|
@@ -8560,7 +8574,6 @@ var list = (editor) => {
|
|
|
8560
8574
|
}
|
|
8561
8575
|
}
|
|
8562
8576
|
editor.history.save();
|
|
8563
|
-
editor.selection.sync();
|
|
8564
8577
|
},
|
|
8565
8578
|
});
|
|
8566
8579
|
editor.container.on('click', event => {
|
|
@@ -9172,14 +9185,12 @@ var link = (editor) => {
|
|
|
9172
9185
|
const range = editor.selection.range;
|
|
9173
9186
|
range.setStartAfter(node);
|
|
9174
9187
|
range.collapseToStart();
|
|
9175
|
-
editor.selection.sync();
|
|
9176
9188
|
editor.history.save();
|
|
9177
9189
|
},
|
|
9178
9190
|
onRemove: node => {
|
|
9179
9191
|
const range = editor.selection.range;
|
|
9180
9192
|
range.setStartAfter(node);
|
|
9181
9193
|
range.collapseToStart();
|
|
9182
|
-
editor.selection.sync();
|
|
9183
9194
|
editor.history.save();
|
|
9184
9195
|
},
|
|
9185
9196
|
});
|
|
@@ -9560,7 +9571,7 @@ function executeMarkCommand(editor, point) {
|
|
|
9560
9571
|
// <p>foobold\u200B<focus /></p>,
|
|
9561
9572
|
// to
|
|
9562
9573
|
// <p>foo[bold]\u200B<focus /></p>, startOffset = 3, endOffset = 7
|
|
9563
|
-
editor.
|
|
9574
|
+
editor.history.pause();
|
|
9564
9575
|
const bookmark = selection.insertBookmark();
|
|
9565
9576
|
const node = bookmark.focus.prev();
|
|
9566
9577
|
const oldValue = node.text();
|
|
@@ -9570,7 +9581,8 @@ function executeMarkCommand(editor, point) {
|
|
|
9570
9581
|
range.setEnd(node, offset - (oldValue.length - newValue.length) - 1);
|
|
9571
9582
|
editor.command.execute(commandName, ...parameters);
|
|
9572
9583
|
selection.toBookmark(bookmark);
|
|
9573
|
-
editor.
|
|
9584
|
+
editor.history.continue();
|
|
9585
|
+
editor.history.save();
|
|
9574
9586
|
return true;
|
|
9575
9587
|
}
|
|
9576
9588
|
}
|
|
@@ -9592,16 +9604,14 @@ function spaceKeyExecutesBlockCommand(editor, point) {
|
|
|
9592
9604
|
// <p>#<focus />foo</p>
|
|
9593
9605
|
// to
|
|
9594
9606
|
// <h1><focus />foo</h1>
|
|
9595
|
-
editor.prepareOperation();
|
|
9596
9607
|
const bookmark = selection.insertBookmark();
|
|
9597
9608
|
const node = bookmark.focus.prev();
|
|
9598
9609
|
node.remove();
|
|
9599
9610
|
const block = bookmark.focus.closestBlock();
|
|
9600
9611
|
fixEmptyBlock(block);
|
|
9601
9612
|
selection.range.shrinkAfter(block);
|
|
9602
|
-
editor.command.execute(commandName, ...parameters);
|
|
9603
9613
|
selection.toBookmark(bookmark);
|
|
9604
|
-
editor.
|
|
9614
|
+
editor.command.execute(commandName, ...parameters);
|
|
9605
9615
|
return true;
|
|
9606
9616
|
}
|
|
9607
9617
|
}
|
|
@@ -9622,12 +9632,10 @@ function enterKeyExecutesBlockCommand(editor, block) {
|
|
|
9622
9632
|
// <p>---<focus /></p>
|
|
9623
9633
|
// to
|
|
9624
9634
|
// <lake-box type="block" name="hr" focus="end"></lake-box>
|
|
9625
|
-
editor.prepareOperation();
|
|
9626
9635
|
block.empty();
|
|
9627
9636
|
fixEmptyBlock(block);
|
|
9628
9637
|
selection.range.shrinkAfter(block);
|
|
9629
9638
|
editor.command.execute(commandName, ...parameters);
|
|
9630
|
-
editor.commitOperation();
|
|
9631
9639
|
return true;
|
|
9632
9640
|
}
|
|
9633
9641
|
}
|
|
@@ -9748,13 +9756,13 @@ var enterKey = (editor) => {
|
|
|
9748
9756
|
return;
|
|
9749
9757
|
}
|
|
9750
9758
|
event.preventDefault();
|
|
9751
|
-
editor.
|
|
9759
|
+
editor.fixContent();
|
|
9752
9760
|
if (range.isBox) {
|
|
9753
9761
|
addBlockOrSplitBlockForBox(editor);
|
|
9754
9762
|
editor.history.save();
|
|
9755
9763
|
return;
|
|
9756
9764
|
}
|
|
9757
|
-
range.
|
|
9765
|
+
range.adjust();
|
|
9758
9766
|
if (range.isInoperative) {
|
|
9759
9767
|
return;
|
|
9760
9768
|
}
|
|
@@ -9833,14 +9841,14 @@ var shiftEnterKey = (editor) => {
|
|
|
9833
9841
|
if (range.isInsideBox) {
|
|
9834
9842
|
return;
|
|
9835
9843
|
}
|
|
9836
|
-
editor.
|
|
9844
|
+
editor.fixContent();
|
|
9837
9845
|
event.preventDefault();
|
|
9838
9846
|
if (range.isBox) {
|
|
9839
9847
|
addBlockOrLineBreakForBox(editor);
|
|
9840
9848
|
editor.history.save();
|
|
9841
9849
|
return;
|
|
9842
9850
|
}
|
|
9843
|
-
range.
|
|
9851
|
+
range.adjust();
|
|
9844
9852
|
if (range.isInoperative) {
|
|
9845
9853
|
return;
|
|
9846
9854
|
}
|
|
@@ -9854,6 +9862,14 @@ var shiftEnterKey = (editor) => {
|
|
|
9854
9862
|
});
|
|
9855
9863
|
};
|
|
9856
9864
|
|
|
9865
|
+
function removeEmptyMarks(range) {
|
|
9866
|
+
const block = range.getBlocks()[0];
|
|
9867
|
+
if (block && block.isEmpty && block.first().name !== 'br') {
|
|
9868
|
+
block.empty();
|
|
9869
|
+
appendDeepest(block, query('<br />'));
|
|
9870
|
+
range.shrinkAfter(block);
|
|
9871
|
+
}
|
|
9872
|
+
}
|
|
9857
9873
|
function mergeWithPreviousBlock(editor, block) {
|
|
9858
9874
|
const range = editor.selection.range;
|
|
9859
9875
|
let prevBlock = block.prev();
|
|
@@ -9884,6 +9900,7 @@ function mergeWithPreviousBlock(editor, block) {
|
|
|
9884
9900
|
prevBlock.remove();
|
|
9885
9901
|
return;
|
|
9886
9902
|
}
|
|
9903
|
+
removeEmptyMarks(range);
|
|
9887
9904
|
const bookmark = editor.selection.insertBookmark();
|
|
9888
9905
|
mergeNodes(prevBlock, block);
|
|
9889
9906
|
editor.selection.toBookmark(bookmark);
|
|
@@ -9896,9 +9913,17 @@ var backspaceKey = (editor) => {
|
|
|
9896
9913
|
editor.keystroke.setKeydown('backspace', event => {
|
|
9897
9914
|
const range = editor.selection.range;
|
|
9898
9915
|
if (range.isInsideBox) {
|
|
9916
|
+
const boxNode = range.commonAncestor.closest('lake-box');
|
|
9917
|
+
const box = getBox(boxNode);
|
|
9918
|
+
const boxValue = box.value;
|
|
9919
|
+
if (box.name === 'codeBlock' && (boxValue.code === undefined || boxValue.code === '')) {
|
|
9920
|
+
event.preventDefault();
|
|
9921
|
+
editor.selection.removeBox(box);
|
|
9922
|
+
editor.history.save();
|
|
9923
|
+
}
|
|
9899
9924
|
return;
|
|
9900
9925
|
}
|
|
9901
|
-
editor.
|
|
9926
|
+
editor.fixContent();
|
|
9902
9927
|
if (range.isBoxStart) {
|
|
9903
9928
|
const boxNode = range.startNode.closest('lake-box');
|
|
9904
9929
|
const prevNode = boxNode.prev();
|
|
@@ -9929,7 +9954,7 @@ var backspaceKey = (editor) => {
|
|
|
9929
9954
|
editor.history.save();
|
|
9930
9955
|
return;
|
|
9931
9956
|
}
|
|
9932
|
-
range.
|
|
9957
|
+
range.adjustBox();
|
|
9933
9958
|
}
|
|
9934
9959
|
if (range.isBox) {
|
|
9935
9960
|
event.preventDefault();
|
|
@@ -9946,7 +9971,7 @@ var backspaceKey = (editor) => {
|
|
|
9946
9971
|
editor.history.save();
|
|
9947
9972
|
return;
|
|
9948
9973
|
}
|
|
9949
|
-
range.
|
|
9974
|
+
range.adjust();
|
|
9950
9975
|
const prevNode = range.getPrevNode();
|
|
9951
9976
|
if (prevNode.isBox) {
|
|
9952
9977
|
event.preventDefault();
|
|
@@ -9954,7 +9979,7 @@ var backspaceKey = (editor) => {
|
|
|
9954
9979
|
editor.history.save();
|
|
9955
9980
|
return;
|
|
9956
9981
|
}
|
|
9957
|
-
if (prevNode.isText && prevNode.text().length === 1) {
|
|
9982
|
+
if (prevNode.isText && prevNode.text().length === 1 && prevNode.parent().isBlock) {
|
|
9958
9983
|
event.preventDefault();
|
|
9959
9984
|
const block = prevNode.closestBlock();
|
|
9960
9985
|
range.setStartBefore(prevNode);
|
|
@@ -10036,7 +10061,7 @@ var deleteKey = (editor) => {
|
|
|
10036
10061
|
if (range.isInsideBox) {
|
|
10037
10062
|
return;
|
|
10038
10063
|
}
|
|
10039
|
-
editor.
|
|
10064
|
+
editor.fixContent();
|
|
10040
10065
|
if (range.isBoxEnd) {
|
|
10041
10066
|
const boxNode = range.startNode.closest('lake-box');
|
|
10042
10067
|
const nextNode = boxNode.next();
|
|
@@ -10061,7 +10086,7 @@ var deleteKey = (editor) => {
|
|
|
10061
10086
|
range.shrinkBefore(nextNode);
|
|
10062
10087
|
return;
|
|
10063
10088
|
}
|
|
10064
|
-
range.
|
|
10089
|
+
range.adjustBox();
|
|
10065
10090
|
}
|
|
10066
10091
|
if (range.isBox) {
|
|
10067
10092
|
event.preventDefault();
|
|
@@ -10078,7 +10103,7 @@ var deleteKey = (editor) => {
|
|
|
10078
10103
|
editor.history.save();
|
|
10079
10104
|
return;
|
|
10080
10105
|
}
|
|
10081
|
-
range.
|
|
10106
|
+
range.adjust();
|
|
10082
10107
|
const nextNode = range.getNextNode();
|
|
10083
10108
|
if (nextNode.isBox) {
|
|
10084
10109
|
event.preventDefault();
|