lakelib 0.1.13 → 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 +167 -166
- package/dist/lake.min.js +24 -24
- package/dist/lake.min.js.map +1 -1
- package/lib/lake.css +167 -166
- package/lib/lake.js +157 -126
- package/lib/lake.js.map +1 -1
- package/lib/types/css/index.d.ts +3 -4
- package/lib/types/editor.d.ts +6 -9
- package/lib/types/managers/command.d.ts +0 -2
- package/lib/types/managers/history.d.ts +11 -5
- package/package.json +1 -1
package/lib/lake.js
CHANGED
|
@@ -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
|
}
|
|
@@ -3566,7 +3571,7 @@ class Box {
|
|
|
3566
3571
|
container.removeClass('lake-box-hovered');
|
|
3567
3572
|
});
|
|
3568
3573
|
container.on('click', () => {
|
|
3569
|
-
debug(`Box
|
|
3574
|
+
debug(`Box "${this.name}" (id = ${this.node.id}) value:`);
|
|
3570
3575
|
debug(this.value);
|
|
3571
3576
|
});
|
|
3572
3577
|
if (this.type === 'block' && this.node.isContentEditable) {
|
|
@@ -3667,7 +3672,7 @@ class Box {
|
|
|
3667
3672
|
newContainer.append(content);
|
|
3668
3673
|
morph(container, newContainer);
|
|
3669
3674
|
}
|
|
3670
|
-
debug(`Box
|
|
3675
|
+
debug(`Box "${this.name}" (id: ${this.node.id}) rendered`);
|
|
3671
3676
|
}
|
|
3672
3677
|
// Destroys a rendered box.
|
|
3673
3678
|
unmount() {
|
|
@@ -3676,7 +3681,7 @@ class Box {
|
|
|
3676
3681
|
boxData[this.node.id] = {};
|
|
3677
3682
|
this.event.removeAllListeners();
|
|
3678
3683
|
this.node.empty();
|
|
3679
|
-
debug(`Box
|
|
3684
|
+
debug(`Box "${this.name}" (id: ${this.node.id}) unmounted`);
|
|
3680
3685
|
}
|
|
3681
3686
|
// Returns a HTML string of the box.
|
|
3682
3687
|
getHTML() {
|
|
@@ -4287,9 +4292,8 @@ function insertBookmark(range) {
|
|
|
4287
4292
|
function removeAndNormalizeNode(node, range) {
|
|
4288
4293
|
const previousNode = node.prev();
|
|
4289
4294
|
const nextNode = node.next();
|
|
4290
|
-
if (previousNode.isText
|
|
4295
|
+
if (previousNode.isText || nextNode.isText) {
|
|
4291
4296
|
const parentNode = node.parent();
|
|
4292
|
-
removeZWS(parentNode);
|
|
4293
4297
|
node.remove();
|
|
4294
4298
|
parentNode.get(0).normalize();
|
|
4295
4299
|
}
|
|
@@ -4593,7 +4597,7 @@ function splitBlock$1(range) {
|
|
|
4593
4597
|
}
|
|
4594
4598
|
|
|
4595
4599
|
// Removes empty marks that contain no content.
|
|
4596
|
-
function removeEmptyMarks$
|
|
4600
|
+
function removeEmptyMarks$2(node) {
|
|
4597
4601
|
if (node.isMark && node.isEmpty) {
|
|
4598
4602
|
node.remove();
|
|
4599
4603
|
return;
|
|
@@ -4615,8 +4619,8 @@ function splitMarksAtPoint(node, offset, removeEmptyMark) {
|
|
|
4615
4619
|
const parts = splitNodes(node, offset, limitBlock);
|
|
4616
4620
|
if (parts) {
|
|
4617
4621
|
if (removeEmptyMark) {
|
|
4618
|
-
removeEmptyMarks$
|
|
4619
|
-
removeEmptyMarks$
|
|
4622
|
+
removeEmptyMarks$2(parts.start);
|
|
4623
|
+
removeEmptyMarks$2(parts.end);
|
|
4620
4624
|
if (!parts.start.isEmpty) {
|
|
4621
4625
|
start = parts.start;
|
|
4622
4626
|
}
|
|
@@ -4802,7 +4806,7 @@ function addMark(range, value) {
|
|
|
4802
4806
|
}
|
|
4803
4807
|
|
|
4804
4808
|
// Removes empty marks that contain no content.
|
|
4805
|
-
function removeEmptyMarks(node) {
|
|
4809
|
+
function removeEmptyMarks$1(node) {
|
|
4806
4810
|
if (node.isMark && node.isEmpty) {
|
|
4807
4811
|
node.remove();
|
|
4808
4812
|
return;
|
|
@@ -4860,13 +4864,13 @@ function removeMark(range, value) {
|
|
|
4860
4864
|
return;
|
|
4861
4865
|
}
|
|
4862
4866
|
if (parts.end) {
|
|
4863
|
-
removeEmptyMarks(parts.end);
|
|
4867
|
+
removeEmptyMarks$1(parts.end);
|
|
4864
4868
|
}
|
|
4865
4869
|
const zeroWidthSpace = new Nodes(document.createTextNode('\u200B'));
|
|
4866
4870
|
const newMark = copyNestedMarks(parts.start, tagName);
|
|
4867
4871
|
if (!newMark) {
|
|
4868
4872
|
parts.start.after(zeroWidthSpace);
|
|
4869
|
-
removeEmptyMarks(parts.start);
|
|
4873
|
+
removeEmptyMarks$1(parts.start);
|
|
4870
4874
|
if (zeroWidthSpace.prev().isText) {
|
|
4871
4875
|
range.setStartAfter(zeroWidthSpace.prev());
|
|
4872
4876
|
range.collapseToStart();
|
|
@@ -4879,7 +4883,7 @@ function removeMark(range, value) {
|
|
|
4879
4883
|
}
|
|
4880
4884
|
appendDeepest(newMark, zeroWidthSpace);
|
|
4881
4885
|
parts.start.after(newMark);
|
|
4882
|
-
removeEmptyMarks(parts.start);
|
|
4886
|
+
removeEmptyMarks$1(parts.start);
|
|
4883
4887
|
range.shrinkAfter(newMark);
|
|
4884
4888
|
return;
|
|
4885
4889
|
}
|
|
@@ -4947,7 +4951,7 @@ function insertLink(range, value) {
|
|
|
4947
4951
|
return linkNode;
|
|
4948
4952
|
}
|
|
4949
4953
|
|
|
4950
|
-
var version = "0.1.
|
|
4954
|
+
var version = "0.1.14";
|
|
4951
4955
|
|
|
4952
4956
|
// Inserts a box into the specified range.
|
|
4953
4957
|
function insertBox(range, boxName, boxValue) {
|
|
@@ -5116,7 +5120,10 @@ class Selection {
|
|
|
5116
5120
|
// Updates the saved range with the range of the native selection.
|
|
5117
5121
|
updateByRange() {
|
|
5118
5122
|
const newRange = this.getRangeFromNativeSelection();
|
|
5119
|
-
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) {
|
|
5120
5127
|
return;
|
|
5121
5128
|
}
|
|
5122
5129
|
this.range = newRange;
|
|
@@ -5218,7 +5225,6 @@ class Selection {
|
|
|
5218
5225
|
class Command {
|
|
5219
5226
|
constructor(selection) {
|
|
5220
5227
|
this.commandMap = new Map();
|
|
5221
|
-
this.event = new EventEmitter();
|
|
5222
5228
|
this.selection = selection;
|
|
5223
5229
|
}
|
|
5224
5230
|
add(name, commandItem) {
|
|
@@ -5266,10 +5272,8 @@ class Command {
|
|
|
5266
5272
|
}
|
|
5267
5273
|
execute(name, ...data) {
|
|
5268
5274
|
const commandItem = this.getItem(name);
|
|
5269
|
-
this.event.emit('beforeexecute', name);
|
|
5270
5275
|
commandItem.execute.apply(this, data);
|
|
5271
|
-
|
|
5272
|
-
debug(`Command '${name}' executed`);
|
|
5276
|
+
debug(`Command "${name}" executed`);
|
|
5273
5277
|
}
|
|
5274
5278
|
}
|
|
5275
5279
|
|
|
@@ -5287,11 +5291,11 @@ class Command {
|
|
|
5287
5291
|
// inputs 'e': value: 'abe', list: ['a', 'ab', 'abe'], index: 3, canRedo: false
|
|
5288
5292
|
class History {
|
|
5289
5293
|
constructor(selection) {
|
|
5294
|
+
this.canSave = true;
|
|
5290
5295
|
// an array for storing the history items
|
|
5291
5296
|
this.list = [];
|
|
5292
5297
|
// the next index of the list
|
|
5293
5298
|
this.index = 0;
|
|
5294
|
-
this.canSave = true;
|
|
5295
5299
|
this.limit = 100;
|
|
5296
5300
|
this.event = new EventEmitter();
|
|
5297
5301
|
this.selection = selection;
|
|
@@ -5343,6 +5347,12 @@ class History {
|
|
|
5343
5347
|
this.removeIdfromBoxes(container);
|
|
5344
5348
|
this.removeIdfromBoxes(otherContainer);
|
|
5345
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
|
+
}
|
|
5346
5356
|
cloneContainer() {
|
|
5347
5357
|
const range = this.selection.range;
|
|
5348
5358
|
const newContainer = this.container.clone(true);
|
|
@@ -5354,6 +5364,12 @@ class History {
|
|
|
5354
5364
|
return newContainer;
|
|
5355
5365
|
}
|
|
5356
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);
|
|
5357
5373
|
return newContainer;
|
|
5358
5374
|
}
|
|
5359
5375
|
const startNodePath = range.startNode.path();
|
|
@@ -5366,23 +5382,14 @@ class History {
|
|
|
5366
5382
|
insertBookmark(newRange);
|
|
5367
5383
|
return newContainer;
|
|
5368
5384
|
}
|
|
5369
|
-
get count() {
|
|
5370
|
-
return this.list.length;
|
|
5371
|
-
}
|
|
5372
|
-
get canUndo() {
|
|
5373
|
-
return this.index > 1 && !!this.list[this.index - 1];
|
|
5374
|
-
}
|
|
5375
|
-
get canRedo() {
|
|
5376
|
-
return !!this.list[this.index];
|
|
5377
|
-
}
|
|
5378
5385
|
undo() {
|
|
5379
|
-
if (!this.list[this.index -
|
|
5386
|
+
if (!this.list[this.index - 2]) {
|
|
5380
5387
|
return;
|
|
5381
5388
|
}
|
|
5382
5389
|
this.selection.insertBookmark();
|
|
5383
5390
|
const value = this.getValue(this.container);
|
|
5384
|
-
while (this.index >
|
|
5385
|
-
const prevItem = this.list[this.index -
|
|
5391
|
+
while (this.index > 1) {
|
|
5392
|
+
const prevItem = this.list[this.index - 2];
|
|
5386
5393
|
if (!prevItem) {
|
|
5387
5394
|
break;
|
|
5388
5395
|
}
|
|
@@ -5394,9 +5401,6 @@ class History {
|
|
|
5394
5401
|
break;
|
|
5395
5402
|
}
|
|
5396
5403
|
}
|
|
5397
|
-
if (this.index < 1) {
|
|
5398
|
-
this.index = 1;
|
|
5399
|
-
}
|
|
5400
5404
|
this.selection.updateByBookmark();
|
|
5401
5405
|
debug(`History undone (index: ${this.index})`);
|
|
5402
5406
|
}
|
|
@@ -5428,7 +5432,11 @@ class History {
|
|
|
5428
5432
|
pause() {
|
|
5429
5433
|
this.canSave = false;
|
|
5430
5434
|
}
|
|
5431
|
-
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;
|
|
5432
5440
|
if (!this.canSave) {
|
|
5433
5441
|
return;
|
|
5434
5442
|
}
|
|
@@ -5438,16 +5446,25 @@ class History {
|
|
|
5438
5446
|
this.removeBookmark(this.getValue(this.list[this.index - 1])) === this.removeBookmark(value)) {
|
|
5439
5447
|
return;
|
|
5440
5448
|
}
|
|
5441
|
-
|
|
5442
|
-
|
|
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
|
+
}
|
|
5443
5456
|
if (this.list.length > this.limit) {
|
|
5444
5457
|
this.list.shift();
|
|
5445
5458
|
this.index = this.list.length;
|
|
5446
5459
|
}
|
|
5447
|
-
|
|
5448
|
-
|
|
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
|
+
});
|
|
5449
5467
|
}
|
|
5450
|
-
debug(`History saved (index: ${this.index})`);
|
|
5451
5468
|
}
|
|
5452
5469
|
}
|
|
5453
5470
|
|
|
@@ -5571,6 +5588,7 @@ const defaultConfig = {
|
|
|
5571
5588
|
class Editor {
|
|
5572
5589
|
constructor(config) {
|
|
5573
5590
|
this.unsavedInputData = '';
|
|
5591
|
+
this.unsavedInputCount = 0;
|
|
5574
5592
|
this.state = {
|
|
5575
5593
|
appliedItems: [],
|
|
5576
5594
|
disabledNameMap: new Map(),
|
|
@@ -5601,9 +5619,6 @@ class Editor {
|
|
|
5601
5619
|
}
|
|
5602
5620
|
this.event.emit('paste', event);
|
|
5603
5621
|
};
|
|
5604
|
-
this.beforeunloadListener = () => {
|
|
5605
|
-
this.history.save();
|
|
5606
|
-
};
|
|
5607
5622
|
this.selectionchangeListener = () => {
|
|
5608
5623
|
this.selection.updateByRange();
|
|
5609
5624
|
this.updateBoxSelectionStyle();
|
|
@@ -5619,6 +5634,7 @@ class Editor {
|
|
|
5619
5634
|
this.resizeListener = () => {
|
|
5620
5635
|
this.event.emit('resize');
|
|
5621
5636
|
};
|
|
5637
|
+
// Updates the classes of all boxes when the current selection of the editor is changed.
|
|
5622
5638
|
this.updateBoxSelectionStyle = debounce(() => {
|
|
5623
5639
|
// The editor has been unmounted.
|
|
5624
5640
|
if (this.root.first().length === 0) {
|
|
@@ -5669,6 +5685,7 @@ class Editor {
|
|
|
5669
5685
|
trailing: true,
|
|
5670
5686
|
maxWait: 50,
|
|
5671
5687
|
});
|
|
5688
|
+
// Triggers the statechange event when the current selection of the editor is changed.
|
|
5672
5689
|
this.emitStateChangeEvent = debounce(() => {
|
|
5673
5690
|
const commandNames = this.command.getNames();
|
|
5674
5691
|
let appliedItems = this.selection.getAppliedItems();
|
|
@@ -5715,13 +5732,6 @@ class Editor {
|
|
|
5715
5732
|
trailing: true,
|
|
5716
5733
|
maxWait: 100,
|
|
5717
5734
|
});
|
|
5718
|
-
this.emitChangeEvent = (value) => {
|
|
5719
|
-
this.fixContent();
|
|
5720
|
-
this.emitStateChangeEvent();
|
|
5721
|
-
this.togglePlaceholderClass(value);
|
|
5722
|
-
this.scrollToCaret();
|
|
5723
|
-
this.event.emit('change', value);
|
|
5724
|
-
};
|
|
5725
5735
|
if (!config.root) {
|
|
5726
5736
|
throw new Error('The root of the config must be specified.');
|
|
5727
5737
|
}
|
|
@@ -5751,6 +5761,7 @@ class Editor {
|
|
|
5751
5761
|
this.keystroke = new Keystroke(this.container);
|
|
5752
5762
|
editors.set(this.container.id, this);
|
|
5753
5763
|
}
|
|
5764
|
+
// Adds or Removes a placeholder class.
|
|
5754
5765
|
togglePlaceholderClass(value) {
|
|
5755
5766
|
value = denormalizeValue(value);
|
|
5756
5767
|
const className = 'lake-show-placeholder';
|
|
@@ -5761,7 +5772,8 @@ class Editor {
|
|
|
5761
5772
|
this.container.removeClass(className);
|
|
5762
5773
|
}
|
|
5763
5774
|
}
|
|
5764
|
-
|
|
5775
|
+
// Moves the input text from box strip to normal position.
|
|
5776
|
+
moveBoxStripText() {
|
|
5765
5777
|
const selection = this.selection;
|
|
5766
5778
|
const range = selection.range;
|
|
5767
5779
|
const stripNode = range.startNode.closest('.lake-box-strip');
|
|
@@ -5791,6 +5803,12 @@ class Editor {
|
|
|
5791
5803
|
stripNode.html('<br />');
|
|
5792
5804
|
selection.insertNode(document.createTextNode(text));
|
|
5793
5805
|
}
|
|
5806
|
+
// Resets the value of unsaved input property.
|
|
5807
|
+
resetUnsavedInputData() {
|
|
5808
|
+
this.unsavedInputData = '';
|
|
5809
|
+
this.unsavedInputCount = 0;
|
|
5810
|
+
}
|
|
5811
|
+
// Binds events about input.
|
|
5794
5812
|
bindInputEvents() {
|
|
5795
5813
|
this.container.on('compositionstart', () => {
|
|
5796
5814
|
this.isComposing = true;
|
|
@@ -5798,19 +5816,6 @@ class Editor {
|
|
|
5798
5816
|
this.container.on('compositionend', () => {
|
|
5799
5817
|
this.isComposing = false;
|
|
5800
5818
|
});
|
|
5801
|
-
this.container.on('beforeinput', event => {
|
|
5802
|
-
const inputEvent = event;
|
|
5803
|
-
const range = this.selection.range;
|
|
5804
|
-
if (range.isBoxStart || range.isBoxEnd) {
|
|
5805
|
-
this.commitUnsavedInputData();
|
|
5806
|
-
return;
|
|
5807
|
-
}
|
|
5808
|
-
if (inputEvent.inputType === 'insertText' ||
|
|
5809
|
-
inputEvent.inputType === 'insertCompositionText') {
|
|
5810
|
-
return;
|
|
5811
|
-
}
|
|
5812
|
-
this.commitUnsavedInputData();
|
|
5813
|
-
});
|
|
5814
5819
|
this.container.on('input', event => {
|
|
5815
5820
|
const inputEvent = event;
|
|
5816
5821
|
// Here setTimeout is necessary because isComposing is not false after ending composition.
|
|
@@ -5826,7 +5831,7 @@ class Editor {
|
|
|
5826
5831
|
return;
|
|
5827
5832
|
}
|
|
5828
5833
|
if (range.isBoxStart || range.isBoxEnd) {
|
|
5829
|
-
this.
|
|
5834
|
+
this.moveBoxStripText();
|
|
5830
5835
|
this.history.save();
|
|
5831
5836
|
this.event.emit('input', inputEvent);
|
|
5832
5837
|
return;
|
|
@@ -5834,30 +5839,60 @@ class Editor {
|
|
|
5834
5839
|
if (inputEvent.inputType === 'insertText' ||
|
|
5835
5840
|
inputEvent.inputType === 'insertCompositionText') {
|
|
5836
5841
|
this.unsavedInputData += (_a = inputEvent.data) !== null && _a !== void 0 ? _a : '';
|
|
5842
|
+
this.unsavedInputCount++;
|
|
5837
5843
|
if (this.unsavedInputData.length < this.config.minChangeSize) {
|
|
5838
|
-
this.
|
|
5839
|
-
|
|
5840
|
-
|
|
5844
|
+
this.history.save({
|
|
5845
|
+
inputType: 'insertText',
|
|
5846
|
+
update: this.unsavedInputCount > 1,
|
|
5847
|
+
});
|
|
5841
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;
|
|
5842
5858
|
}
|
|
5843
5859
|
this.history.save();
|
|
5844
5860
|
this.event.emit('input', inputEvent);
|
|
5845
5861
|
}, 0);
|
|
5846
5862
|
});
|
|
5847
|
-
this.command.event.on('beforeexecute', () => this.commitUnsavedInputData());
|
|
5848
5863
|
}
|
|
5864
|
+
// Binds events about history.
|
|
5849
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
|
+
};
|
|
5850
5879
|
this.history.event.on('undo', value => {
|
|
5851
5880
|
this.renderBoxes();
|
|
5852
|
-
|
|
5881
|
+
executeCommonMethods(value);
|
|
5882
|
+
this.resetUnsavedInputData();
|
|
5853
5883
|
});
|
|
5854
5884
|
this.history.event.on('redo', value => {
|
|
5855
5885
|
this.renderBoxes();
|
|
5856
|
-
|
|
5886
|
+
executeCommonMethods(value);
|
|
5887
|
+
this.resetUnsavedInputData();
|
|
5857
5888
|
});
|
|
5858
|
-
this.history.event.on('save', value => {
|
|
5889
|
+
this.history.event.on('save', (value, options) => {
|
|
5859
5890
|
this.removeBoxGarbage();
|
|
5860
|
-
|
|
5891
|
+
executeCommonMethods(value);
|
|
5892
|
+
this.selection.sync();
|
|
5893
|
+
if (options.inputType !== 'insertText') {
|
|
5894
|
+
this.resetUnsavedInputData();
|
|
5895
|
+
}
|
|
5861
5896
|
});
|
|
5862
5897
|
}
|
|
5863
5898
|
// Returns a boolean value indicating whether the editor has focus.
|
|
@@ -5874,47 +5909,34 @@ class Editor {
|
|
|
5874
5909
|
}
|
|
5875
5910
|
// Fixes wrong content, especially empty tag.
|
|
5876
5911
|
fixContent() {
|
|
5912
|
+
let changed = false;
|
|
5877
5913
|
let children = this.container.children();
|
|
5878
5914
|
for (const child of children) {
|
|
5879
5915
|
if ((child.isBlock || child.isMark) && child.html() === '') {
|
|
5880
5916
|
child.remove();
|
|
5881
|
-
|
|
5917
|
+
changed = true;
|
|
5918
|
+
debug(`Content fixed: empty tag "${child.name}" was removed`);
|
|
5882
5919
|
}
|
|
5883
5920
|
}
|
|
5884
5921
|
children = this.container.children();
|
|
5885
5922
|
if (children.length === 0) {
|
|
5886
5923
|
this.container.html('<p><br /></p>');
|
|
5887
5924
|
this.selection.range.shrinkAfter(this.container);
|
|
5888
|
-
|
|
5889
|
-
|
|
5925
|
+
changed = true;
|
|
5926
|
+
debug('Content fixed: default paragraph was added');
|
|
5890
5927
|
}
|
|
5891
|
-
if (children.length === 1) {
|
|
5928
|
+
else if (children.length === 1) {
|
|
5892
5929
|
const child = children[0];
|
|
5893
5930
|
if (child.isVoid) {
|
|
5894
5931
|
const paragraph = query('<p />');
|
|
5895
5932
|
child.before(paragraph);
|
|
5896
5933
|
paragraph.append(child);
|
|
5897
5934
|
this.selection.range.shrinkAfter(paragraph);
|
|
5898
|
-
|
|
5935
|
+
changed = true;
|
|
5936
|
+
debug(`Content fixed: void element "${child.name}" was wrapped in paragraph`);
|
|
5899
5937
|
}
|
|
5900
5938
|
}
|
|
5901
|
-
|
|
5902
|
-
// Saves the input data which is unsaved.
|
|
5903
|
-
commitUnsavedInputData() {
|
|
5904
|
-
if (this.unsavedInputData.length > 0) {
|
|
5905
|
-
this.history.save(false);
|
|
5906
|
-
this.unsavedInputData = '';
|
|
5907
|
-
}
|
|
5908
|
-
}
|
|
5909
|
-
// Updates some state before custom modifications.
|
|
5910
|
-
prepareOperation() {
|
|
5911
|
-
this.commitUnsavedInputData();
|
|
5912
|
-
this.history.pause();
|
|
5913
|
-
}
|
|
5914
|
-
// Saves custom modifications to the history.
|
|
5915
|
-
commitOperation() {
|
|
5916
|
-
this.history.continue();
|
|
5917
|
-
this.history.save();
|
|
5939
|
+
return changed;
|
|
5918
5940
|
}
|
|
5919
5941
|
// Sets default config for a plugin.
|
|
5920
5942
|
setPluginConfig(name, config) {
|
|
@@ -5951,11 +5973,11 @@ class Editor {
|
|
|
5951
5973
|
box.render();
|
|
5952
5974
|
});
|
|
5953
5975
|
}
|
|
5954
|
-
// Sets focus on the editor
|
|
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;
|
|
@@ -5991,7 +6016,7 @@ class Editor {
|
|
|
5991
6016
|
}
|
|
5992
6017
|
artificialCaret.remove();
|
|
5993
6018
|
}
|
|
5994
|
-
// Sets the specified
|
|
6019
|
+
// Sets the specified value to the editor.
|
|
5995
6020
|
setValue(value) {
|
|
5996
6021
|
value = normalizeValue(value);
|
|
5997
6022
|
const htmlParser = new HTMLParser(value);
|
|
@@ -6002,15 +6027,14 @@ class Editor {
|
|
|
6002
6027
|
this.renderBoxes();
|
|
6003
6028
|
this.selection.updateByBookmark();
|
|
6004
6029
|
}
|
|
6005
|
-
// Returns the
|
|
6030
|
+
// Returns the value of the editor.
|
|
6006
6031
|
getValue() {
|
|
6007
|
-
const
|
|
6008
|
-
let value = new HTMLParser(
|
|
6032
|
+
const item = this.history.cloneContainer();
|
|
6033
|
+
let value = new HTMLParser(item).getHTML();
|
|
6009
6034
|
value = denormalizeValue(value);
|
|
6010
|
-
this.selection.toBookmark(bookmark);
|
|
6011
6035
|
return value;
|
|
6012
6036
|
}
|
|
6013
|
-
// Renders an editor area and
|
|
6037
|
+
// Renders an editor area and sets default value to it.
|
|
6014
6038
|
render() {
|
|
6015
6039
|
const value = normalizeValue(this.config.value);
|
|
6016
6040
|
const htmlParser = new HTMLParser(value);
|
|
@@ -6025,7 +6049,9 @@ class Editor {
|
|
|
6025
6049
|
Editor.plugin.loadAll(this);
|
|
6026
6050
|
if (!this.readonly) {
|
|
6027
6051
|
this.selection.updateByBookmark();
|
|
6028
|
-
this.history.save(
|
|
6052
|
+
this.history.save({
|
|
6053
|
+
emitEvent: false,
|
|
6054
|
+
});
|
|
6029
6055
|
}
|
|
6030
6056
|
this.renderBoxes();
|
|
6031
6057
|
if (this.toolbar) {
|
|
@@ -6035,7 +6061,6 @@ class Editor {
|
|
|
6035
6061
|
if (!this.readonly) {
|
|
6036
6062
|
document.addEventListener('cut', this.cutListener);
|
|
6037
6063
|
document.addEventListener('paste', this.pasteListener);
|
|
6038
|
-
window.addEventListener('beforeunload', this.beforeunloadListener);
|
|
6039
6064
|
document.addEventListener('selectionchange', this.selectionchangeListener);
|
|
6040
6065
|
document.addEventListener('click', this.clickListener);
|
|
6041
6066
|
window.addEventListener('resize', this.resizeListener);
|
|
@@ -6043,10 +6068,9 @@ class Editor {
|
|
|
6043
6068
|
this.bindHistoryEvents();
|
|
6044
6069
|
}
|
|
6045
6070
|
}
|
|
6046
|
-
// Destroys
|
|
6071
|
+
// Destroys the rendered editor.
|
|
6047
6072
|
unmount() {
|
|
6048
6073
|
this.event.removeAllListeners();
|
|
6049
|
-
this.command.event.removeAllListeners();
|
|
6050
6074
|
this.history.event.removeAllListeners();
|
|
6051
6075
|
this.root.empty();
|
|
6052
6076
|
this.popupContainer.remove();
|
|
@@ -6054,7 +6078,6 @@ class Editor {
|
|
|
6054
6078
|
if (!this.readonly) {
|
|
6055
6079
|
document.removeEventListener('cut', this.cutListener);
|
|
6056
6080
|
document.removeEventListener('paste', this.pasteListener);
|
|
6057
|
-
window.removeEventListener('beforeunload', this.beforeunloadListener);
|
|
6058
6081
|
document.removeEventListener('selectionchange', this.selectionchangeListener);
|
|
6059
6082
|
document.removeEventListener('click', this.clickListener);
|
|
6060
6083
|
window.removeEventListener('resize', this.resizeListener);
|
|
@@ -7103,7 +7126,6 @@ function appendButtonGroup(box) {
|
|
|
7103
7126
|
event.stopPropagation();
|
|
7104
7127
|
editor.selection.removeBox(box);
|
|
7105
7128
|
editor.history.save();
|
|
7106
|
-
editor.selection.sync();
|
|
7107
7129
|
});
|
|
7108
7130
|
videoNode.append(buttonGroupNode);
|
|
7109
7131
|
}
|
|
@@ -7825,7 +7847,6 @@ const imageBox = {
|
|
|
7825
7847
|
}
|
|
7826
7848
|
editor.selection.removeBox(box);
|
|
7827
7849
|
editor.history.save();
|
|
7828
|
-
editor.selection.sync();
|
|
7829
7850
|
});
|
|
7830
7851
|
}
|
|
7831
7852
|
box.event.emit('render');
|
|
@@ -7862,7 +7883,6 @@ const boxToolbarItems = [
|
|
|
7862
7883
|
}
|
|
7863
7884
|
editor.selection.removeBox(box);
|
|
7864
7885
|
editor.history.save();
|
|
7865
|
-
editor.selection.sync();
|
|
7866
7886
|
},
|
|
7867
7887
|
},
|
|
7868
7888
|
];
|
|
@@ -8554,7 +8574,6 @@ var list = (editor) => {
|
|
|
8554
8574
|
}
|
|
8555
8575
|
}
|
|
8556
8576
|
editor.history.save();
|
|
8557
|
-
editor.selection.sync();
|
|
8558
8577
|
},
|
|
8559
8578
|
});
|
|
8560
8579
|
editor.container.on('click', event => {
|
|
@@ -9166,14 +9185,12 @@ var link = (editor) => {
|
|
|
9166
9185
|
const range = editor.selection.range;
|
|
9167
9186
|
range.setStartAfter(node);
|
|
9168
9187
|
range.collapseToStart();
|
|
9169
|
-
editor.selection.sync();
|
|
9170
9188
|
editor.history.save();
|
|
9171
9189
|
},
|
|
9172
9190
|
onRemove: node => {
|
|
9173
9191
|
const range = editor.selection.range;
|
|
9174
9192
|
range.setStartAfter(node);
|
|
9175
9193
|
range.collapseToStart();
|
|
9176
|
-
editor.selection.sync();
|
|
9177
9194
|
editor.history.save();
|
|
9178
9195
|
},
|
|
9179
9196
|
});
|
|
@@ -9554,7 +9571,7 @@ function executeMarkCommand(editor, point) {
|
|
|
9554
9571
|
// <p>foobold\u200B<focus /></p>,
|
|
9555
9572
|
// to
|
|
9556
9573
|
// <p>foo[bold]\u200B<focus /></p>, startOffset = 3, endOffset = 7
|
|
9557
|
-
editor.
|
|
9574
|
+
editor.history.pause();
|
|
9558
9575
|
const bookmark = selection.insertBookmark();
|
|
9559
9576
|
const node = bookmark.focus.prev();
|
|
9560
9577
|
const oldValue = node.text();
|
|
@@ -9564,7 +9581,8 @@ function executeMarkCommand(editor, point) {
|
|
|
9564
9581
|
range.setEnd(node, offset - (oldValue.length - newValue.length) - 1);
|
|
9565
9582
|
editor.command.execute(commandName, ...parameters);
|
|
9566
9583
|
selection.toBookmark(bookmark);
|
|
9567
|
-
editor.
|
|
9584
|
+
editor.history.continue();
|
|
9585
|
+
editor.history.save();
|
|
9568
9586
|
return true;
|
|
9569
9587
|
}
|
|
9570
9588
|
}
|
|
@@ -9586,16 +9604,14 @@ function spaceKeyExecutesBlockCommand(editor, point) {
|
|
|
9586
9604
|
// <p>#<focus />foo</p>
|
|
9587
9605
|
// to
|
|
9588
9606
|
// <h1><focus />foo</h1>
|
|
9589
|
-
editor.prepareOperation();
|
|
9590
9607
|
const bookmark = selection.insertBookmark();
|
|
9591
9608
|
const node = bookmark.focus.prev();
|
|
9592
9609
|
node.remove();
|
|
9593
9610
|
const block = bookmark.focus.closestBlock();
|
|
9594
9611
|
fixEmptyBlock(block);
|
|
9595
9612
|
selection.range.shrinkAfter(block);
|
|
9596
|
-
editor.command.execute(commandName, ...parameters);
|
|
9597
9613
|
selection.toBookmark(bookmark);
|
|
9598
|
-
editor.
|
|
9614
|
+
editor.command.execute(commandName, ...parameters);
|
|
9599
9615
|
return true;
|
|
9600
9616
|
}
|
|
9601
9617
|
}
|
|
@@ -9616,12 +9632,10 @@ function enterKeyExecutesBlockCommand(editor, block) {
|
|
|
9616
9632
|
// <p>---<focus /></p>
|
|
9617
9633
|
// to
|
|
9618
9634
|
// <lake-box type="block" name="hr" focus="end"></lake-box>
|
|
9619
|
-
editor.prepareOperation();
|
|
9620
9635
|
block.empty();
|
|
9621
9636
|
fixEmptyBlock(block);
|
|
9622
9637
|
selection.range.shrinkAfter(block);
|
|
9623
9638
|
editor.command.execute(commandName, ...parameters);
|
|
9624
|
-
editor.commitOperation();
|
|
9625
9639
|
return true;
|
|
9626
9640
|
}
|
|
9627
9641
|
}
|
|
@@ -9848,6 +9862,14 @@ var shiftEnterKey = (editor) => {
|
|
|
9848
9862
|
});
|
|
9849
9863
|
};
|
|
9850
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
|
+
}
|
|
9851
9873
|
function mergeWithPreviousBlock(editor, block) {
|
|
9852
9874
|
const range = editor.selection.range;
|
|
9853
9875
|
let prevBlock = block.prev();
|
|
@@ -9878,6 +9900,7 @@ function mergeWithPreviousBlock(editor, block) {
|
|
|
9878
9900
|
prevBlock.remove();
|
|
9879
9901
|
return;
|
|
9880
9902
|
}
|
|
9903
|
+
removeEmptyMarks(range);
|
|
9881
9904
|
const bookmark = editor.selection.insertBookmark();
|
|
9882
9905
|
mergeNodes(prevBlock, block);
|
|
9883
9906
|
editor.selection.toBookmark(bookmark);
|
|
@@ -9890,6 +9913,14 @@ var backspaceKey = (editor) => {
|
|
|
9890
9913
|
editor.keystroke.setKeydown('backspace', event => {
|
|
9891
9914
|
const range = editor.selection.range;
|
|
9892
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
|
+
}
|
|
9893
9924
|
return;
|
|
9894
9925
|
}
|
|
9895
9926
|
editor.fixContent();
|
|
@@ -9948,7 +9979,7 @@ var backspaceKey = (editor) => {
|
|
|
9948
9979
|
editor.history.save();
|
|
9949
9980
|
return;
|
|
9950
9981
|
}
|
|
9951
|
-
if (prevNode.isText && prevNode.text().length === 1) {
|
|
9982
|
+
if (prevNode.isText && prevNode.text().length === 1 && prevNode.parent().isBlock) {
|
|
9952
9983
|
event.preventDefault();
|
|
9953
9984
|
const block = prevNode.closestBlock();
|
|
9954
9985
|
range.setStartBefore(prevNode);
|