lakelib 0.0.4 → 0.0.6

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/lib/lake.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { Base64 } from 'js-base64';
2
2
  import EventEmitter from 'eventemitter3';
3
3
  import debounce from 'lodash/debounce';
4
+ import isEqual from 'lodash/isEqual';
4
5
  import md5 from 'blueimp-md5';
5
6
  import { createKeybindingsHandler } from 'tinykeys';
6
7
  import { i18nObject as i18nObject$1 } from 'typesafe-i18n';
@@ -1229,11 +1230,11 @@ class Range {
1229
1230
  const boxNode = this.commonAncestor.closest('lake-box');
1230
1231
  return boxNode.length > 0;
1231
1232
  }
1232
- // Returns a boolean value indicating whether the range's common ancestor node is in the left strip of the box.
1233
+ // Returns a boolean value indicating whether the range's common ancestor node is in the start strip of the box.
1233
1234
  // case 1: <lake-box><span class="lake-box-strip">|</span><div class="lake-box-container"></div> ...
1234
1235
  // case 2: <lake-box><span class="lake-box-strip"></span>|<div class="lake-box-container"></div> ...
1235
1236
  // case 3: <lake-box>|<span class="lake-box-strip"></span><div class="lake-box-container"></div> ...
1236
- get isBoxLeft() {
1237
+ get isBoxStart() {
1237
1238
  const boxNode = this.commonAncestor.closest('lake-box');
1238
1239
  if (boxNode.length === 0) {
1239
1240
  return false;
@@ -1254,11 +1255,11 @@ class Range {
1254
1255
  // case: ... <div class="lake-box-container">|<div></div></div> ...
1255
1256
  return this.isCollapsed && this.startNode.get(0) === boxContainer.get(0) && this.startOffset === 0;
1256
1257
  }
1257
- // Returns a boolean value indicating whether the range's common ancestor node is in the right strip of the box.
1258
+ // Returns a boolean value indicating whether the range's common ancestor node is in the end strip of the box.
1258
1259
  // case 1: ... <div class="lake-box-container"></div><span class="lake-box-strip">|</span></lake-box>
1259
1260
  // case 2: ... <div class="lake-box-container"></div>|<span class="lake-box-strip"></span></lake-box>
1260
1261
  // case 3: ... <div class="lake-box-container"></div><span class="lake-box-strip"></span>|</lake-box>
1261
- get isBoxRight() {
1262
+ get isBoxEnd() {
1262
1263
  const boxNode = this.commonAncestor.closest('lake-box');
1263
1264
  if (boxNode.length === 0) {
1264
1265
  return false;
@@ -1385,28 +1386,28 @@ class Range {
1385
1386
  this.setStart(boxContainer, 0);
1386
1387
  this.collapseToStart();
1387
1388
  }
1388
- // Sets the range to the left position of the box.
1389
- selectBoxLeft(boxNode) {
1389
+ // Sets the range to the start position of the box.
1390
+ selectBoxStart(boxNode) {
1390
1391
  const boxStrip = boxNode.find('.lake-box-strip');
1391
1392
  if (boxStrip.length === 0) {
1392
1393
  throw new Error(`The box cannot be selected because the box '${boxNode.attr('name')}' (id=${boxNode.id}) has not been rendered yet.`);
1393
1394
  }
1394
1395
  this.selectNodeContents(boxStrip.eq(0));
1395
- this.collapseToEnd();
1396
+ this.collapseToStart();
1396
1397
  }
1397
- // Sets the range to the left position of the box.
1398
- selectBoxRight(boxNode) {
1398
+ // Sets the range to the start position of the box.
1399
+ selectBoxEnd(boxNode) {
1399
1400
  const boxStrip = boxNode.find('.lake-box-strip');
1400
1401
  if (boxStrip.length === 0) {
1401
1402
  throw new Error(`The box cannot be selected because the box '${boxNode.attr('name')}' (id=${boxNode.id}) has not been rendered yet.`);
1402
1403
  }
1403
1404
  this.selectNodeContents(boxStrip.eq(1));
1404
- this.collapseToEnd();
1405
+ this.collapseToStart();
1405
1406
  }
1406
1407
  // Collapses the range and sets the range to the beginning of the contents of the specified node.
1407
1408
  shrinkBefore(node) {
1408
1409
  if (node.isBox) {
1409
- this.selectBoxLeft(node);
1410
+ this.selectBoxStart(node);
1410
1411
  return;
1411
1412
  }
1412
1413
  if (node.isText) {
@@ -1420,7 +1421,7 @@ class Range {
1420
1421
  (child = this.startNode.children()[0]) &&
1421
1422
  child.isElement && !child.isVoid) {
1422
1423
  if (child.isBox) {
1423
- this.selectBoxLeft(child);
1424
+ this.selectBoxStart(child);
1424
1425
  return;
1425
1426
  }
1426
1427
  this.setStart(child, 0);
@@ -1430,7 +1431,7 @@ class Range {
1430
1431
  // Collapses the range and sets the range to the end of the contents of the specified node.
1431
1432
  shrinkAfter(node) {
1432
1433
  if (node.isBox) {
1433
- this.selectBoxRight(node);
1434
+ this.selectBoxEnd(node);
1434
1435
  return;
1435
1436
  }
1436
1437
  if (node.isText) {
@@ -1445,7 +1446,7 @@ class Range {
1445
1446
  (child = this.endNode.children()[this.endOffset - 1]) &&
1446
1447
  child.isElement && !child.isVoid) {
1447
1448
  if (child.isBox) {
1448
- this.selectBoxRight(child);
1449
+ this.selectBoxEnd(child);
1449
1450
  return;
1450
1451
  }
1451
1452
  this.setEnd(child, child.children().length);
@@ -1481,7 +1482,7 @@ class Range {
1481
1482
  if (startBoxNode.length > 0) {
1482
1483
  const startRange = this.clone();
1483
1484
  startRange.collapseToStart();
1484
- if (startRange.isBoxRight) {
1485
+ if (startRange.isBoxEnd) {
1485
1486
  this.setStartAfter(startBoxNode);
1486
1487
  }
1487
1488
  else {
@@ -1492,7 +1493,7 @@ class Range {
1492
1493
  if (endBoxNode.length > 0) {
1493
1494
  const endRange = this.clone();
1494
1495
  endRange.collapseToEnd();
1495
- if (endRange.isBoxLeft) {
1496
+ if (endRange.isBoxStart) {
1496
1497
  this.setEndBefore(endBoxNode);
1497
1498
  }
1498
1499
  else {
@@ -1673,9 +1674,9 @@ class Range {
1673
1674
  }
1674
1675
  return marks;
1675
1676
  }
1676
- // Returns the text of the left part of the closest block divided into two parts by the start point of the range.
1677
+ // Returns the text of the start part of the closest block divided into two parts by the start point of the range.
1677
1678
  // "<p>one<anchor />two<focus />three</p>" returns "three".
1678
- getLeftText() {
1679
+ getStartText() {
1679
1680
  const node = this.startNode;
1680
1681
  const offset = this.startOffset;
1681
1682
  let block = node.closestBlock();
@@ -1685,20 +1686,20 @@ class Range {
1685
1686
  if (block.length === 0) {
1686
1687
  return '';
1687
1688
  }
1688
- const leftRange = new Range();
1689
- leftRange.setStartBefore(block);
1690
- leftRange.setEnd(node, offset);
1689
+ const startRange = new Range();
1690
+ startRange.setStartBefore(block);
1691
+ startRange.setEnd(node, offset);
1691
1692
  const container = query('<div />');
1692
- container.append(leftRange.cloneContents());
1693
+ container.append(startRange.cloneContents());
1693
1694
  const text = container.text();
1694
1695
  if (text === '' && container.find('lake-box').length > 0) {
1695
1696
  return '\u200B';
1696
1697
  }
1697
1698
  return text;
1698
1699
  }
1699
- // Returns the text of the right part of the closest block divided into two parts by the end point of the range.
1700
+ // Returns the text of the end part of the closest block divided into two parts by the end point of the range.
1700
1701
  // "<p>one<anchor />two<focus />three</p>" returns "three".
1701
- getRightText() {
1702
+ getEndText() {
1702
1703
  const node = this.endNode;
1703
1704
  const offset = this.endOffset;
1704
1705
  let block = node.closestBlock();
@@ -1708,11 +1709,11 @@ class Range {
1708
1709
  if (block.length === 0) {
1709
1710
  return '';
1710
1711
  }
1711
- const rightRange = new Range();
1712
- rightRange.setStart(node, offset);
1713
- rightRange.setEndAfter(block);
1712
+ const endRange = new Range();
1713
+ endRange.setStart(node, offset);
1714
+ endRange.setEndAfter(block);
1714
1715
  const container = query('<div />');
1715
- container.append(rightRange.cloneContents());
1716
+ container.append(endRange.cloneContents());
1716
1717
  const text = container.text();
1717
1718
  if (text === '' && container.find('lake-box').length > 0) {
1718
1719
  return '\u200B';
@@ -1770,23 +1771,23 @@ function splitNodes(node, offset, limitNode) {
1770
1771
  return null;
1771
1772
  }
1772
1773
  range.collapseToStart();
1773
- const leftPart = parent.clone();
1774
+ const startPart = parent.clone();
1774
1775
  let child = parent.first();
1775
1776
  while (child.length > 0) {
1776
1777
  if (range.compareBeforeNode(child) >= 0) {
1777
1778
  break;
1778
1779
  }
1779
1780
  const nextNode = child.next();
1780
- leftPart.append(child);
1781
+ startPart.append(child);
1781
1782
  child = nextNode;
1782
1783
  }
1783
- parent.before(leftPart);
1784
+ parent.before(startPart);
1784
1785
  if (parent.parent().length > 0 && parent.parent().get(0) !== limitNode.get(0)) {
1785
1786
  return splitNodes(parent.parent(), parent.index(), limitNode);
1786
1787
  }
1787
1788
  return {
1788
- left: leftPart,
1789
- right: parent,
1789
+ start: startPart,
1790
+ end: parent,
1790
1791
  };
1791
1792
  }
1792
1793
 
@@ -2857,6 +2858,9 @@ class Box {
2857
2858
  container.off('mouseleave');
2858
2859
  container.off('click');
2859
2860
  }
2861
+ container.on('mousedown', event => {
2862
+ event.preventDefault();
2863
+ });
2860
2864
  container.on('mouseenter', () => {
2861
2865
  if (container.hasClass('lake-box-selected') ||
2862
2866
  container.hasClass('lake-box-focused') ||
@@ -3032,7 +3036,7 @@ function getElementRules() {
3032
3036
  type: ['inline', 'block'],
3033
3037
  name: /^[\w-]+$/,
3034
3038
  value: /^[^"]+$/,
3035
- focus: ['left', 'center', 'right'],
3039
+ focus: ['start', 'center', 'end'],
3036
3040
  },
3037
3041
  br: {},
3038
3042
  hr: {},
@@ -3291,8 +3295,8 @@ function insertNode(range, node) {
3291
3295
  // or the method inserts a pair of bookmarks into the beginning and the end of the range.
3292
3296
  // case 1: foo<lake-bookmark type="focus" />bar
3293
3297
  // case 2: <lake-bookmark type="anchor" />foo<lake-bookmark type="focus" />
3294
- // case 3: foo<lake-box type="inline" name="image" focus="left"></lake-box>bar
3295
- // case 4: foo<lake-box type="inline" name="image" focus="right"></lake-box>bar
3298
+ // case 3: foo<lake-box type="inline" name="image" focus="start"></lake-box>bar
3299
+ // case 4: foo<lake-box type="inline" name="image" focus="end"></lake-box>bar
3296
3300
  // case 5: <lake-bookmark type="anchor" /><lake-box type="inline" name="image"></lake-box>foo<lake-bookmark type="focus" />
3297
3301
  function insertBookmark(range) {
3298
3302
  if (range.commonAncestor.isOutside) {
@@ -3304,11 +3308,11 @@ function insertBookmark(range) {
3304
3308
  // box
3305
3309
  const boxNode = range.startNode.closest('lake-box');
3306
3310
  if (boxNode.length > 0) {
3307
- if (range.isBoxLeft) {
3308
- boxNode.attr('focus', 'left');
3311
+ if (range.isBoxStart) {
3312
+ boxNode.attr('focus', 'start');
3309
3313
  }
3310
- else if (range.isBoxRight) {
3311
- boxNode.attr('focus', 'right');
3314
+ else if (range.isBoxEnd) {
3315
+ boxNode.attr('focus', 'end');
3312
3316
  }
3313
3317
  else {
3314
3318
  boxNode.attr('focus', 'center');
@@ -3382,14 +3386,14 @@ function toBookmark(range, bookmark) {
3382
3386
  box.render();
3383
3387
  }
3384
3388
  const focusValue = focus.attr('focus');
3385
- if (focusValue === 'left') {
3386
- range.selectBoxLeft(focus);
3389
+ if (focusValue === 'start') {
3390
+ range.selectBoxStart(focus);
3387
3391
  }
3388
3392
  else if (focusValue === 'center') {
3389
3393
  range.selectBox(focus);
3390
3394
  }
3391
3395
  else {
3392
- range.selectBoxRight(focus);
3396
+ range.selectBoxEnd(focus);
3393
3397
  }
3394
3398
  focus.removeAttr('focus');
3395
3399
  return;
@@ -3593,8 +3597,8 @@ function setBlocks(range, value) {
3593
3597
  function splitBlock$1(range) {
3594
3598
  if (range.commonAncestor.isOutside) {
3595
3599
  return {
3596
- left: null,
3597
- right: null,
3600
+ start: null,
3601
+ end: null,
3598
3602
  };
3599
3603
  }
3600
3604
  if (range.isCollapsed) {
@@ -3607,8 +3611,8 @@ function splitBlock$1(range) {
3607
3611
  const closestBlock = node.closestOperableBlock();
3608
3612
  if (closestBlock.length === 0) {
3609
3613
  return {
3610
- left: null,
3611
- right: null,
3614
+ start: null,
3615
+ end: null,
3612
3616
  };
3613
3617
  }
3614
3618
  let limitBlock = closestBlock.parent();
@@ -3616,37 +3620,37 @@ function splitBlock$1(range) {
3616
3620
  limitBlock = node.closestContainer();
3617
3621
  }
3618
3622
  const parts = splitNodes(node, range.startOffset, limitBlock);
3619
- let left = null;
3620
- let right = null;
3623
+ let start = null;
3624
+ let end = null;
3621
3625
  if (parts) {
3622
- left = parts.left;
3623
- right = parts.right;
3626
+ start = parts.start;
3627
+ end = parts.end;
3624
3628
  }
3625
3629
  if (!parts && node.isBlock) {
3626
3630
  if (range.startOffset > 0) {
3627
- left = node.children()[range.startOffset - 1];
3631
+ start = node.children()[range.startOffset - 1];
3628
3632
  }
3629
- right = node.children()[range.startOffset];
3630
- if (right && !right.isBlock) {
3631
- right = null;
3633
+ end = node.children()[range.startOffset];
3634
+ if (end && !end.isBlock) {
3635
+ end = null;
3632
3636
  }
3633
3637
  }
3634
- if (left && left.isEmpty) {
3635
- appendDeepest(left, query('<br />'));
3638
+ if (start && start.isEmpty) {
3639
+ appendDeepest(start, query('<br />'));
3636
3640
  }
3637
- if (right) {
3638
- if (right.isEmpty) {
3639
- appendDeepest(right, query('<br />'));
3640
- range.shrinkAfter(right);
3641
+ if (end) {
3642
+ if (end.isEmpty) {
3643
+ appendDeepest(end, query('<br />'));
3644
+ range.shrinkAfter(end);
3641
3645
  }
3642
3646
  else {
3643
- range.shrinkBefore(right);
3647
+ range.shrinkBefore(end);
3644
3648
  }
3645
3649
  }
3646
3650
  fixList(range);
3647
3651
  return {
3648
- left,
3649
- right,
3652
+ start,
3653
+ end,
3650
3654
  };
3651
3655
  }
3652
3656
 
@@ -3664,8 +3668,8 @@ function removeEmptyMarks$1(node) {
3664
3668
  }
3665
3669
  // Splits text nodes or mark nodes at a specified position.
3666
3670
  function splitMarksAtPoint(node, offset, removeEmptyMark) {
3667
- let left = null;
3668
- let right = null;
3671
+ let start = null;
3672
+ let end = null;
3669
3673
  let limitBlock = node.closestBlock();
3670
3674
  if (limitBlock.length === 0) {
3671
3675
  limitBlock = node.closestContainer();
@@ -3673,23 +3677,23 @@ function splitMarksAtPoint(node, offset, removeEmptyMark) {
3673
3677
  const parts = splitNodes(node, offset, limitBlock);
3674
3678
  if (parts) {
3675
3679
  if (removeEmptyMark) {
3676
- removeEmptyMarks$1(parts.left);
3677
- removeEmptyMarks$1(parts.right);
3678
- if (!parts.left.isEmpty) {
3679
- left = parts.left;
3680
+ removeEmptyMarks$1(parts.start);
3681
+ removeEmptyMarks$1(parts.end);
3682
+ if (!parts.start.isEmpty) {
3683
+ start = parts.start;
3680
3684
  }
3681
- if (!parts.right.isEmpty) {
3682
- right = parts.right;
3685
+ if (!parts.end.isEmpty) {
3686
+ end = parts.end;
3683
3687
  }
3684
3688
  }
3685
3689
  else {
3686
- left = parts.left;
3687
- right = parts.right;
3690
+ start = parts.start;
3691
+ end = parts.end;
3688
3692
  }
3689
3693
  }
3690
3694
  return {
3691
- left,
3692
- right,
3695
+ start,
3696
+ end,
3693
3697
  };
3694
3698
  }
3695
3699
  // Splits text nodes or mark nodes.
@@ -3699,46 +3703,46 @@ function splitMarksAtPoint(node, offset, removeEmptyMark) {
3699
3703
  function splitMarks(range, removeEmptyMark = true) {
3700
3704
  if (range.commonAncestor.isOutside) {
3701
3705
  return {
3702
- left: null,
3706
+ start: null,
3703
3707
  center: null,
3704
- right: null,
3708
+ end: null,
3705
3709
  };
3706
3710
  }
3707
3711
  range.adaptBox();
3708
3712
  if (range.isCollapsed) {
3709
3713
  const parts = splitMarksAtPoint(range.startNode, range.startOffset, removeEmptyMark);
3710
- if (parts.left) {
3711
- range.setStartAfter(parts.left);
3714
+ if (parts.start) {
3715
+ range.setStartAfter(parts.start);
3712
3716
  range.collapseToStart();
3713
3717
  }
3714
- else if (parts.right) {
3715
- range.setStartBefore(parts.right);
3718
+ else if (parts.end) {
3719
+ range.setStartBefore(parts.end);
3716
3720
  range.collapseToStart();
3717
3721
  }
3718
3722
  return {
3719
- left: parts.left,
3723
+ start: parts.start,
3720
3724
  center: null,
3721
- right: parts.right,
3725
+ end: parts.end,
3722
3726
  };
3723
3727
  }
3724
3728
  const startParts = splitMarksAtPoint(range.startNode, range.startOffset, removeEmptyMark);
3725
- if (startParts.left) {
3726
- range.setStartAfter(startParts.left);
3729
+ if (startParts.start) {
3730
+ range.setStartAfter(startParts.start);
3727
3731
  }
3728
- else if (startParts.right) {
3729
- range.setStartBefore(startParts.right);
3732
+ else if (startParts.end) {
3733
+ range.setStartBefore(startParts.end);
3730
3734
  }
3731
3735
  const endParts = splitMarksAtPoint(range.endNode, range.endOffset, removeEmptyMark);
3732
- if (endParts.left) {
3733
- range.setEndAfter(endParts.left);
3736
+ if (endParts.start) {
3737
+ range.setEndAfter(endParts.start);
3734
3738
  }
3735
- else if (endParts.right) {
3736
- range.setEndBefore(endParts.right);
3739
+ else if (endParts.end) {
3740
+ range.setEndBefore(endParts.end);
3737
3741
  }
3738
3742
  return {
3739
- left: startParts.left,
3740
- center: endParts.left,
3741
- right: endParts.right,
3743
+ start: startParts.start,
3744
+ center: endParts.start,
3745
+ end: endParts.end,
3742
3746
  };
3743
3747
  }
3744
3748
 
@@ -3800,7 +3804,7 @@ function addMark(range, value) {
3800
3804
  const box = new Box(boxNode);
3801
3805
  if (box.type === 'block') {
3802
3806
  const newBlock = query('<p><br /></p>');
3803
- if (range.isBoxLeft) {
3807
+ if (range.isBoxStart) {
3804
3808
  boxNode.before(newBlock);
3805
3809
  }
3806
3810
  else {
@@ -3817,8 +3821,8 @@ function addMark(range, value) {
3817
3821
  // https://en.wikipedia.org/wiki/Zero-width_space
3818
3822
  const zeroWidthSpace = new Nodes(document.createTextNode('\u200B'));
3819
3823
  const parts = splitMarks(range);
3820
- if (parts.left) {
3821
- const newMark = copyNestedMarks$1(parts.left);
3824
+ if (parts.start) {
3825
+ const newMark = copyNestedMarks$1(parts.start);
3822
3826
  if (newMark) {
3823
3827
  if (newMark.name === tagName) {
3824
3828
  newMark.css(cssProperties);
@@ -3914,17 +3918,17 @@ function removeMark(range, value) {
3914
3918
  return;
3915
3919
  }
3916
3920
  const parts = splitMarks(range, false);
3917
- if (!parts.left) {
3921
+ if (!parts.start) {
3918
3922
  return;
3919
3923
  }
3920
- if (parts.right) {
3921
- removeEmptyMarks(parts.right);
3924
+ if (parts.end) {
3925
+ removeEmptyMarks(parts.end);
3922
3926
  }
3923
3927
  const zeroWidthSpace = new Nodes(document.createTextNode('\u200B'));
3924
- const newMark = copyNestedMarks(parts.left, tagName);
3928
+ const newMark = copyNestedMarks(parts.start, tagName);
3925
3929
  if (!newMark) {
3926
- parts.left.after(zeroWidthSpace);
3927
- removeEmptyMarks(parts.left);
3930
+ parts.start.after(zeroWidthSpace);
3931
+ removeEmptyMarks(parts.start);
3928
3932
  if (zeroWidthSpace.prev().isText) {
3929
3933
  range.setStartAfter(zeroWidthSpace.prev());
3930
3934
  range.collapseToStart();
@@ -3936,8 +3940,8 @@ function removeMark(range, value) {
3936
3940
  return;
3937
3941
  }
3938
3942
  appendDeepest(newMark, zeroWidthSpace);
3939
- parts.left.after(newMark);
3940
- removeEmptyMarks(parts.left);
3943
+ parts.start.after(newMark);
3944
+ removeEmptyMarks(parts.start);
3941
3945
  range.shrinkAfter(newMark);
3942
3946
  return;
3943
3947
  }
@@ -4291,7 +4295,7 @@ class Dropdown {
4291
4295
  }
4292
4296
  }
4293
4297
 
4294
- var version = "0.0.2";
4298
+ var version = "0.0.6";
4295
4299
 
4296
4300
  // Inserts a box into the specified range.
4297
4301
  function insertBox(range, boxName, boxValue) {
@@ -4308,23 +4312,23 @@ function insertBox(range, boxName, boxValue) {
4308
4312
  if (box.type === 'inline') {
4309
4313
  insertFragment(range, fragment);
4310
4314
  box.render();
4311
- range.selectBoxRight(box.node);
4315
+ range.selectBoxEnd(box.node);
4312
4316
  return box;
4313
4317
  }
4314
4318
  // block box
4315
4319
  const parts = splitBlock$1(range);
4316
- if (parts.left) {
4317
- range.setEndAfter(parts.left);
4320
+ if (parts.start) {
4321
+ range.setEndAfter(parts.start);
4318
4322
  range.collapseToEnd();
4319
4323
  }
4320
- if (parts.right && parts.right.isEmpty) {
4321
- parts.right.remove();
4324
+ if (parts.end && parts.end.isEmpty) {
4325
+ parts.end.remove();
4322
4326
  }
4323
4327
  insertFragment(range, fragment);
4324
4328
  box.render();
4325
- range.selectBoxRight(box.node);
4326
- if (parts.left && parts.left.isEmpty) {
4327
- parts.left.remove();
4329
+ range.selectBoxEnd(box.node);
4330
+ if (parts.start && parts.start.isEmpty) {
4331
+ parts.start.remove();
4328
4332
  }
4329
4333
  return box;
4330
4334
  }
@@ -4527,12 +4531,18 @@ class Command {
4527
4531
  this.event = new EventEmitter();
4528
4532
  this.selection = selection;
4529
4533
  }
4530
- add(name, handler) {
4531
- this.commandMap.set(name, handler);
4534
+ add(name, commandItem) {
4535
+ this.commandMap.set(name, commandItem);
4536
+ }
4537
+ delete(name) {
4538
+ this.commandMap.delete(name);
4532
4539
  }
4533
4540
  getNames() {
4534
4541
  return Array.from(this.commandMap.keys());
4535
4542
  }
4543
+ has(name) {
4544
+ return this.commandMap.get(name) !== undefined;
4545
+ }
4536
4546
  getItem(name) {
4537
4547
  const commandItem = this.commandMap.get(name);
4538
4548
  if (commandItem === undefined) {
@@ -4733,7 +4743,7 @@ class History {
4733
4743
  pause() {
4734
4744
  this.canSave = false;
4735
4745
  }
4736
- save() {
4746
+ save(emitSaveEvent = true) {
4737
4747
  if (!this.canSave) {
4738
4748
  return;
4739
4749
  }
@@ -4749,7 +4759,9 @@ class History {
4749
4759
  this.list.shift();
4750
4760
  this.index = this.list.length;
4751
4761
  }
4752
- this.event.emit('save', value);
4762
+ if (emitSaveEvent) {
4763
+ this.event.emit('save', denormalizeValue(value));
4764
+ }
4753
4765
  debug(`History saved, the last index is ${this.index}`);
4754
4766
  }
4755
4767
  }
@@ -4893,11 +4905,17 @@ const defaultConfig = {
4893
4905
  class Editor {
4894
4906
  constructor(config) {
4895
4907
  this.unsavedInputData = '';
4908
+ this.stateData = {
4909
+ appliedItems: [],
4910
+ disabledNameMap: new Map(),
4911
+ selectedNameMap: new Map(),
4912
+ selectedValuesMap: new Map(),
4913
+ };
4896
4914
  this.isComposing = false;
4897
4915
  this.event = new EventEmitter();
4898
4916
  this.box = Editor.box;
4899
4917
  this.beforeunloadListener = () => {
4900
- this.commitUnsavedInputData();
4918
+ this.history.save();
4901
4919
  };
4902
4920
  this.selectionchangeListener = () => {
4903
4921
  this.selection.syncByRange();
@@ -4930,6 +4948,7 @@ class Editor {
4930
4948
  }
4931
4949
  if (range.compareBeforeNode(boxContainer) < 0 && range.compareAfterNode(boxContainer) > 0) {
4932
4950
  if (!(range.isCollapsed && range.startNode.get(0) === boxContainer.get(0) && range.startOffset === 0)) {
4951
+ boxContainer.removeClass('lake-box-hovered');
4933
4952
  boxContainer.removeClass('lake-box-selected');
4934
4953
  boxContainer.removeClass('lake-box-focused');
4935
4954
  boxContainer.addClass('lake-box-activated');
@@ -4939,6 +4958,7 @@ class Editor {
4939
4958
  if (clonedRange.intersectsNode(box.node)) {
4940
4959
  boxContainer.removeClass('lake-box-activated');
4941
4960
  if (range.isCollapsed) {
4961
+ boxContainer.removeClass('lake-box-hovered');
4942
4962
  boxContainer.removeClass('lake-box-selected');
4943
4963
  boxContainer.addClass('lake-box-focused');
4944
4964
  }
@@ -4985,12 +5005,20 @@ class Editor {
4985
5005
  }
4986
5006
  }
4987
5007
  }
4988
- this.event.emit('statechange', {
5008
+ const stateData = {
4989
5009
  appliedItems,
4990
5010
  disabledNameMap,
4991
5011
  selectedNameMap,
4992
5012
  selectedValuesMap,
4993
- });
5013
+ };
5014
+ if (isEqual(stateData, this.stateData)) {
5015
+ return;
5016
+ }
5017
+ if (this.toolbar) {
5018
+ this.toolbar.updateState(stateData);
5019
+ }
5020
+ this.event.emit('statechange', stateData);
5021
+ this.stateData = stateData;
4994
5022
  }, 100, {
4995
5023
  leading: false,
4996
5024
  trailing: true,
@@ -5005,6 +5033,7 @@ class Editor {
5005
5033
  throw new Error('The root of the config must be specified.');
5006
5034
  }
5007
5035
  this.root = query(config.root);
5036
+ this.toolbar = config.toolbar;
5008
5037
  this.config = Object.assign(Object.assign({}, defaultConfig), config);
5009
5038
  this.containerWrapper = query('<div class="lake-container-wrapper" />');
5010
5039
  this.container = query('<div class="lake-container" />');
@@ -5030,7 +5059,7 @@ class Editor {
5030
5059
  const boxNode = stripNode.closest('lake-box');
5031
5060
  const box = new Box(boxNode);
5032
5061
  if (box.type === 'inline') {
5033
- if (range.isBoxLeft) {
5062
+ if (range.isBoxStart) {
5034
5063
  range.setStartBefore(boxNode);
5035
5064
  range.collapseToStart();
5036
5065
  }
@@ -5041,7 +5070,7 @@ class Editor {
5041
5070
  }
5042
5071
  else {
5043
5072
  const paragraph = query('<p />');
5044
- if (range.isBoxLeft) {
5073
+ if (range.isBoxStart) {
5045
5074
  boxNode.before(paragraph);
5046
5075
  }
5047
5076
  else {
@@ -5060,11 +5089,18 @@ class Editor {
5060
5089
  this.container.on('compositionend', () => {
5061
5090
  this.isComposing = false;
5062
5091
  });
5063
- this.container.on('beforeinput', () => {
5092
+ this.container.on('beforeinput', event => {
5093
+ const inputEvent = event;
5064
5094
  const range = this.selection.range;
5065
- if (range.isBoxLeft || range.isBoxRight) {
5095
+ if (range.isBoxStart || range.isBoxEnd) {
5066
5096
  this.commitUnsavedInputData();
5097
+ return;
5098
+ }
5099
+ if (inputEvent.inputType === 'insertText' ||
5100
+ inputEvent.inputType === 'insertCompositionText') {
5101
+ return;
5067
5102
  }
5103
+ this.commitUnsavedInputData();
5068
5104
  });
5069
5105
  this.container.on('input', event => {
5070
5106
  const inputEvent = event;
@@ -5080,21 +5116,22 @@ class Editor {
5080
5116
  this.event.emit('input', inputEvent);
5081
5117
  return;
5082
5118
  }
5119
+ if (range.isBoxStart || range.isBoxEnd) {
5120
+ this.inputInBoxStrip();
5121
+ this.history.save();
5122
+ this.event.emit('input', inputEvent);
5123
+ return;
5124
+ }
5083
5125
  if (inputEvent.inputType === 'insertText' ||
5084
5126
  inputEvent.inputType === 'insertCompositionText') {
5085
- if (range.isBoxLeft || range.isBoxRight) {
5086
- this.inputInBoxStrip();
5087
- }
5088
- else {
5089
- this.unsavedInputData += (_a = inputEvent.data) !== null && _a !== void 0 ? _a : '';
5090
- if (this.unsavedInputData.length < this.config.minChangeSize) {
5091
- this.event.emit('input', inputEvent);
5092
- return;
5093
- }
5127
+ this.unsavedInputData += (_a = inputEvent.data) !== null && _a !== void 0 ? _a : '';
5128
+ if (this.unsavedInputData.length < this.config.minChangeSize) {
5129
+ this.event.emit('input', inputEvent);
5130
+ this.emitChangeEvent(this.getValue());
5131
+ return;
5094
5132
  }
5095
5133
  }
5096
5134
  this.history.save();
5097
- this.unsavedInputData = '';
5098
5135
  this.event.emit('input', inputEvent);
5099
5136
  }, 0);
5100
5137
  });
@@ -5152,7 +5189,7 @@ class Editor {
5152
5189
  // Saves the input data which is unsaved.
5153
5190
  commitUnsavedInputData() {
5154
5191
  if (this.unsavedInputData.length > 0) {
5155
- this.history.save();
5192
+ this.history.save(false);
5156
5193
  this.unsavedInputData = '';
5157
5194
  }
5158
5195
  }
@@ -5230,6 +5267,9 @@ class Editor {
5230
5267
  Editor.plugin.loadAll(this);
5231
5268
  }
5232
5269
  Editor.box.renderAll(this);
5270
+ if (this.toolbar) {
5271
+ this.toolbar.render(this);
5272
+ }
5233
5273
  if (!this.readonly) {
5234
5274
  window.addEventListener('beforeunload', this.beforeunloadListener);
5235
5275
  document.addEventListener('selectionchange', this.selectionchangeListener);
@@ -6270,8 +6310,10 @@ toolbarItems.forEach(item => {
6270
6310
  });
6271
6311
  class Toolbar {
6272
6312
  constructor(config) {
6313
+ this.allMenuMap = new Map();
6314
+ this.buttonItemList = [];
6315
+ this.dropdownItemList = [];
6273
6316
  this.items = config.items || defaultItems;
6274
- this.editor = config.editor;
6275
6317
  this.root = query(config.root);
6276
6318
  this.container = query('<div class="lake-toolbar" />');
6277
6319
  this.root.addClass('lake-custom-properties');
@@ -6279,8 +6321,7 @@ class Toolbar {
6279
6321
  appendDivider() {
6280
6322
  this.container.append('<div class="lake-toolbar-divider" />');
6281
6323
  }
6282
- appendButton(item) {
6283
- const editor = this.editor;
6324
+ appendButton(editor, item) {
6284
6325
  const button = new Button({
6285
6326
  root: this.container,
6286
6327
  name: item.name,
@@ -6294,8 +6335,7 @@ class Toolbar {
6294
6335
  });
6295
6336
  button.render();
6296
6337
  }
6297
- appendDropdown(item) {
6298
- const editor = this.editor;
6338
+ appendDropdown(editor, item) {
6299
6339
  const dropdown = new Dropdown({
6300
6340
  root: this.container,
6301
6341
  name: item.name,
@@ -6315,8 +6355,7 @@ class Toolbar {
6315
6355
  });
6316
6356
  dropdown.render();
6317
6357
  }
6318
- appendUpload(item) {
6319
- const editor = this.editor;
6358
+ appendUpload(editor, item) {
6320
6359
  const uploadNode = query(safeTemplate `
6321
6360
  <div class="lake-upload" name="${item.name}">
6322
6361
  <input type="file" />
@@ -6355,14 +6394,69 @@ class Toolbar {
6355
6394
  }
6356
6395
  });
6357
6396
  }
6397
+ // Updates state of each item such as disabled, selected.
6398
+ updateState(stateData) {
6399
+ var _a;
6400
+ const { appliedItems, disabledNameMap, selectedNameMap, selectedValuesMap } = stateData;
6401
+ for (const item of this.buttonItemList) {
6402
+ const selectedClass = 'lake-button-selected';
6403
+ const buttonNode = this.container.find(`button[name="${item.name}"]`);
6404
+ let isDisabled = disabledNameMap.get(item.name);
6405
+ if (isDisabled === undefined) {
6406
+ isDisabled = item.isDisabled && appliedItems.length > 0 ? item.isDisabled(appliedItems) : false;
6407
+ }
6408
+ if (isDisabled) {
6409
+ buttonNode.attr('disabled', 'true');
6410
+ buttonNode.removeClass(selectedClass);
6411
+ }
6412
+ else {
6413
+ buttonNode.removeAttr('disabled');
6414
+ }
6415
+ if (!isDisabled) {
6416
+ let isSelected = selectedNameMap.get(item.name);
6417
+ if (isSelected === undefined) {
6418
+ isSelected = item.isSelected && appliedItems.length > 0 ? item.isSelected(appliedItems) : false;
6419
+ }
6420
+ if (isSelected) {
6421
+ buttonNode.addClass(selectedClass);
6422
+ }
6423
+ else {
6424
+ buttonNode.removeClass(selectedClass);
6425
+ }
6426
+ }
6427
+ }
6428
+ for (const item of this.dropdownItemList) {
6429
+ let selectedValues = selectedValuesMap.get(item.name);
6430
+ if (selectedValues === undefined) {
6431
+ selectedValues = item.selectedValues && appliedItems.length > 0 ? item.selectedValues(appliedItems) : [];
6432
+ }
6433
+ const dropdownNode = this.container.find(`div.lake-dropdown[name="${item.name}"]`);
6434
+ let isDisabled = disabledNameMap.get(item.name);
6435
+ if (isDisabled === undefined) {
6436
+ isDisabled = item.isDisabled && appliedItems.length > 0 ? item.isDisabled(appliedItems) : false;
6437
+ }
6438
+ if (isDisabled) {
6439
+ dropdownNode.attr('disabled', 'true');
6440
+ }
6441
+ else {
6442
+ dropdownNode.removeAttr('disabled');
6443
+ }
6444
+ if (!isDisabled) {
6445
+ Dropdown.setValue(dropdownNode, selectedValues);
6446
+ const textNode = dropdownNode.find('.lake-dropdown-text');
6447
+ if (textNode.length > 0) {
6448
+ const key = selectedValues[0] || item.defaultValue;
6449
+ const menuMap = this.allMenuMap.get(item.name);
6450
+ const text = (_a = (menuMap && menuMap.get(key))) !== null && _a !== void 0 ? _a : key;
6451
+ textNode.text(text);
6452
+ }
6453
+ }
6454
+ }
6455
+ }
6358
6456
  // Renders a toolbar for the specified editor.
6359
- render() {
6360
- const editor = this.editor;
6457
+ render(editor) {
6361
6458
  this.root.empty();
6362
6459
  this.root.append(this.container);
6363
- const allMenuMap = new Map();
6364
- const buttonItemList = [];
6365
- const dropdownItemList = [];
6366
6460
  this.items.forEach(name => {
6367
6461
  if (name === '|') {
6368
6462
  this.appendDivider();
@@ -6379,76 +6473,18 @@ class Toolbar {
6379
6473
  item = name;
6380
6474
  }
6381
6475
  if (item.type === 'button') {
6382
- buttonItemList.push(item);
6383
- this.appendButton(item);
6476
+ this.buttonItemList.push(item);
6477
+ this.appendButton(editor, item);
6384
6478
  return;
6385
6479
  }
6386
6480
  if (item.type === 'dropdown') {
6387
- allMenuMap.set(item.name, Dropdown.getMenuMap(item.menuItems));
6388
- dropdownItemList.push(item);
6389
- this.appendDropdown(item);
6481
+ this.allMenuMap.set(item.name, Dropdown.getMenuMap(item.menuItems));
6482
+ this.dropdownItemList.push(item);
6483
+ this.appendDropdown(editor, item);
6390
6484
  return;
6391
6485
  }
6392
6486
  if (item.type === 'upload') {
6393
- this.appendUpload(item);
6394
- }
6395
- });
6396
- editor.event.on('statechange', data => {
6397
- var _a;
6398
- const { appliedItems, disabledNameMap, selectedNameMap, selectedValuesMap } = data;
6399
- for (const item of buttonItemList) {
6400
- const selectedClass = 'lake-button-selected';
6401
- const buttonNode = this.container.find(`button[name="${item.name}"]`);
6402
- let isDisabled = disabledNameMap.get(item.name);
6403
- if (isDisabled === undefined) {
6404
- isDisabled = item.isDisabled && appliedItems.length > 0 ? item.isDisabled(appliedItems) : false;
6405
- }
6406
- if (isDisabled) {
6407
- buttonNode.attr('disabled', 'true');
6408
- buttonNode.removeClass(selectedClass);
6409
- }
6410
- else {
6411
- buttonNode.removeAttr('disabled');
6412
- }
6413
- if (!isDisabled) {
6414
- let isSelected = selectedNameMap.get(item.name);
6415
- if (isSelected === undefined) {
6416
- isSelected = item.isSelected && appliedItems.length > 0 ? item.isSelected(appliedItems) : false;
6417
- }
6418
- if (isSelected) {
6419
- buttonNode.addClass(selectedClass);
6420
- }
6421
- else {
6422
- buttonNode.removeClass(selectedClass);
6423
- }
6424
- }
6425
- }
6426
- for (const item of dropdownItemList) {
6427
- let selectedValues = selectedValuesMap.get(item.name);
6428
- if (selectedValues === undefined) {
6429
- selectedValues = item.selectedValues && appliedItems.length > 0 ? item.selectedValues(appliedItems) : [];
6430
- }
6431
- const dropdownNode = this.container.find(`div.lake-dropdown[name="${item.name}"]`);
6432
- let isDisabled = disabledNameMap.get(item.name);
6433
- if (isDisabled === undefined) {
6434
- isDisabled = item.isDisabled && appliedItems.length > 0 ? item.isDisabled(appliedItems) : false;
6435
- }
6436
- if (isDisabled) {
6437
- dropdownNode.attr('disabled', 'true');
6438
- }
6439
- else {
6440
- dropdownNode.removeAttr('disabled');
6441
- }
6442
- if (!isDisabled) {
6443
- Dropdown.setValue(dropdownNode, selectedValues);
6444
- const textNode = dropdownNode.find('.lake-dropdown-text');
6445
- if (textNode.length > 0) {
6446
- const key = selectedValues[0] || item.defaultValue;
6447
- const menuMap = allMenuMap.get(item.name);
6448
- const text = (_a = (menuMap && menuMap.get(key))) !== null && _a !== void 0 ? _a : key;
6449
- textNode.text(text);
6450
- }
6451
- }
6487
+ this.appendUpload(editor, item);
6452
6488
  }
6453
6489
  });
6454
6490
  }
@@ -6630,6 +6666,7 @@ function openFullScreen(box) {
6630
6666
  dataSource,
6631
6667
  mainClass: 'lake-pswp',
6632
6668
  zoom: false,
6669
+ returnFocus: false,
6633
6670
  arrowPrevSVG: icons.get('left'),
6634
6671
  arrowNextSVG: icons.get('right'),
6635
6672
  closeSVG: icons.get('close'),
@@ -6684,6 +6721,9 @@ function openFullScreen(box) {
6684
6721
  lightbox.on('openingAnimationEnd', () => {
6685
6722
  box.event.emit('openfullscreen');
6686
6723
  });
6724
+ lightbox.on('closingAnimationEnd', () => {
6725
+ box.event.emit('closefullscreen');
6726
+ });
6687
6727
  lightbox.init();
6688
6728
  lightbox.loadAndOpen(currentIndex);
6689
6729
  }
@@ -6932,47 +6972,80 @@ const imageBox = {
6932
6972
 
6933
6973
  const config = {
6934
6974
  defaultLang: 'text',
6935
- background: '#0000000a',
6936
- foreground: '#444d56',
6937
- selection: '#1ba2e333',
6938
- cursor: '#044289',
6939
- keyword: '#cf222e',
6940
- variable: '#1f2328',
6941
- parameter: '#24292e',
6942
- function: '#005cc5',
6975
+ comment: '#57606a',
6976
+ name: '#444d56',
6977
+ variableName: '#953800',
6978
+ typeName: '#0550ae',
6979
+ propertyName: '#444d56',
6980
+ className: '#24292e',
6981
+ labelName: '#005cc5',
6982
+ namespace: '#0550ae',
6983
+ macroName: '#444d56',
6984
+ literal: '#444d56',
6943
6985
  string: '#0a3069',
6944
- constant: '#0550ae',
6945
- type: '#24292f',
6946
- class: '#24292e',
6947
6986
  number: '#0550ae',
6948
- comment: '#57606a',
6987
+ bool: '#0550ae',
6988
+ regexp: '#116329',
6989
+ color: '#0550ae',
6990
+ keyword: '#cf222e',
6991
+ modifier: '#24292f',
6992
+ operator: '#cf222e',
6993
+ bracket: '#57606a',
6994
+ content: '#57606a',
6995
+ meta: '#8250df',
6949
6996
  heading: '#0550ae',
6950
6997
  invalid: '#f6f8fa',
6951
- regexp: '#116329',
6998
+ definition: '#cf222e',
6999
+ constant: '#0550ae',
7000
+ function: '#005cc5',
7001
+ standard: '#444d56',
7002
+ special: '#444d56',
6952
7003
  };
7004
+ // https://lezer.codemirror.net/docs/ref/#highlight.tags
6953
7005
  function getHighlightStyle(CodeMirror) {
6954
7006
  const { HighlightStyle, tags } = CodeMirror;
6955
7007
  return HighlightStyle.define([
6956
- { tag: tags.keyword, color: config.keyword },
6957
- { tag: [tags.name, tags.deleted, tags.character, tags.macroName], color: config.variable },
6958
- { tag: [tags.propertyName], color: config.function },
6959
- { tag: [tags.processingInstruction, tags.string, tags.inserted, tags.special(tags.string)], color: config.string },
6960
- { tag: [tags.function(tags.variableName), tags.labelName], color: config.function },
6961
- { tag: [tags.color, tags.constant(tags.name), tags.standard(tags.name)], color: config.constant },
6962
- { tag: [tags.definition(tags.name), tags.separator], color: config.variable },
6963
- { tag: [tags.className], color: config.class },
6964
- { tag: [tags.number, tags.changed, tags.annotation, tags.modifier, tags.self, tags.namespace], color: config.number },
6965
- { tag: [tags.typeName], color: config.type },
6966
- { tag: [tags.operator, tags.operatorKeyword], color: config.keyword },
6967
- { tag: [tags.url, tags.escape, tags.regexp, tags.link], color: config.regexp },
6968
- { tag: [tags.meta, tags.comment], color: config.comment },
7008
+ { tag: [tags.comment, tags.lineComment, tags.blockComment, tags.docComment], color: config.comment },
7009
+ { tag: [tags.name], color: config.name },
7010
+ { tag: [tags.variableName, tags.self], color: config.variableName },
7011
+ { tag: [tags.typeName, tags.tagName], color: config.typeName },
7012
+ { tag: [tags.propertyName, tags.attributeName], color: config.propertyName },
7013
+ { tag: [tags.className], color: config.className },
7014
+ { tag: [tags.labelName], color: config.labelName },
7015
+ { tag: [tags.namespace], color: config.namespace },
7016
+ { tag: [tags.macroName], color: config.macroName },
7017
+ { tag: [tags.literal], color: config.literal },
7018
+ { tag: [tags.string, tags.docString, tags.character, tags.attributeValue, tags.unit], color: config.string },
7019
+ { tag: [tags.number, tags.integer, tags.float], color: config.number },
7020
+ { tag: [tags.bool, tags.null, tags.atom], color: config.bool },
7021
+ { tag: [tags.regexp, tags.escape, tags.url], color: config.regexp },
7022
+ { tag: [tags.color], color: config.color },
7023
+ { tag: [
7024
+ tags.keyword, tags.operatorKeyword, tags.controlKeyword,
7025
+ tags.definitionKeyword, tags.moduleKeyword,
7026
+ ], color: config.keyword },
7027
+ { tag: [tags.modifier], color: config.modifier },
7028
+ { tag: [
7029
+ tags.operator, tags.derefOperator, tags.arithmeticOperator, tags.logicOperator, tags.bitwiseOperator,
7030
+ tags.compareOperator, tags.updateOperator, tags.definitionOperator, tags.typeOperator, tags.controlOperator,
7031
+ ], color: config.operator },
7032
+ { tag: [
7033
+ tags.punctuation, tags.separator, tags.bracket, tags.angleBracket, tags.squareBracket,
7034
+ tags.paren, tags.brace, tags.contentSeparator,
7035
+ ], color: config.bracket },
7036
+ { tag: [tags.content], color: config.content },
7037
+ { tag: [tags.meta, tags.documentMeta, tags.annotation, tags.processingInstruction], color: config.meta },
7038
+ { tag: tags.heading, fontWeight: 'bold', color: config.heading },
6969
7039
  { tag: tags.strong, fontWeight: 'bold' },
6970
7040
  { tag: tags.emphasis, fontStyle: 'italic' },
6971
7041
  { tag: tags.link, textDecoration: 'underline' },
6972
- { tag: tags.heading, fontWeight: 'bold', color: config.heading },
6973
- { tag: [tags.atom, tags.bool, tags.special(tags.variableName)], color: config.variable },
6974
- { tag: tags.invalid, color: config.invalid },
6975
7042
  { tag: tags.strikethrough, textDecoration: 'line-through' },
7043
+ { tag: [tags.invalid, tags.inserted, tags.deleted, tags.changed], color: config.invalid },
7044
+ { tag: [tags.definition(tags.name)], color: config.definition },
7045
+ { tag: [tags.constant(tags.name)], color: config.constant },
7046
+ { tag: [tags.function(tags.variableName)], color: config.function },
7047
+ { tag: [tags.standard(tags.name)], color: config.standard },
7048
+ { tag: [tags.special(tags.variableName)], color: config.special },
6976
7049
  ]);
6977
7050
  }
6978
7051
  const codeBlockBox = {
@@ -6996,7 +7069,10 @@ const codeBlockBox = {
6996
7069
  const CodeMirror = window.CodeMirror;
6997
7070
  if (!CodeMirror) {
6998
7071
  codeBlockNode.addClass('lake-code-block-error');
6999
- codeBlockNode.text('The code cannot be displayed because window.CodeMirror is not found. Please check if the CodeMirror file is added to this page.');
7072
+ codeBlockNode.text(`
7073
+ The code cannot be displayed because window.CodeMirror is not found.
7074
+ Please check if the CodeMirror file is added to this page.
7075
+ `.trim());
7000
7076
  codeBlockNode.on('click', () => {
7001
7077
  editor.selection.range.selectBox(box.node);
7002
7078
  });
@@ -7086,7 +7162,7 @@ var copy = (editor) => {
7086
7162
  if (boxNode.length === 0) {
7087
7163
  return;
7088
7164
  }
7089
- if (range.isBoxLeft || range.isBoxRight) {
7165
+ if (range.isBoxStart || range.isBoxEnd) {
7090
7166
  return;
7091
7167
  }
7092
7168
  event.preventDefault();
@@ -7110,7 +7186,7 @@ var cut = (editor) => {
7110
7186
  if (boxNode.length === 0) {
7111
7187
  return;
7112
7188
  }
7113
- if (range.isBoxLeft || range.isBoxRight) {
7189
+ if (range.isBoxStart || range.isBoxEnd) {
7114
7190
  return;
7115
7191
  }
7116
7192
  event.preventDefault();
@@ -7185,11 +7261,11 @@ function insertFirstNode(editor, otherNode) {
7185
7261
  if (boxNode.length > 0) {
7186
7262
  const box = new Box(boxNode);
7187
7263
  if (box.type === 'inline') {
7188
- if (range.isBoxLeft) {
7264
+ if (range.isBoxStart) {
7189
7265
  range.setStartBefore(boxNode);
7190
7266
  range.collapseToStart();
7191
7267
  }
7192
- else if (range.isBoxRight) {
7268
+ else if (range.isBoxEnd) {
7193
7269
  range.setStartAfter(boxNode);
7194
7270
  range.collapseToStart();
7195
7271
  }
@@ -7199,11 +7275,11 @@ function insertFirstNode(editor, otherNode) {
7199
7275
  }
7200
7276
  else {
7201
7277
  const paragraph = query('<p />');
7202
- if (range.isBoxLeft) {
7278
+ if (range.isBoxStart) {
7203
7279
  boxNode.before(paragraph);
7204
7280
  range.shrinkAfter(paragraph);
7205
7281
  }
7206
- else if (range.isBoxRight) {
7282
+ else if (range.isBoxEnd) {
7207
7283
  boxNode.after(paragraph);
7208
7284
  range.shrinkAfter(paragraph);
7209
7285
  }
@@ -7267,12 +7343,12 @@ function pasteFragment(editor, fragment) {
7267
7343
  // insert fragment
7268
7344
  if (fragment.childNodes.length > 0) {
7269
7345
  const parts = selection.splitBlock();
7270
- if (parts.left) {
7271
- range.setEndAfter(parts.left);
7346
+ if (parts.start) {
7347
+ range.setEndAfter(parts.start);
7272
7348
  range.collapseToEnd();
7273
7349
  }
7274
- if (parts.right && parts.right.isEmpty) {
7275
- parts.right.remove();
7350
+ if (parts.end && parts.end.isEmpty) {
7351
+ parts.end.remove();
7276
7352
  }
7277
7353
  selection.insertFragment(fragment);
7278
7354
  range.shrinkAfter(lastNode);
@@ -7901,9 +7977,10 @@ class LinkPopup {
7901
7977
  if (!this.linkNode) {
7902
7978
  return;
7903
7979
  }
7980
+ const linkNode = this.linkNode;
7904
7981
  this.save();
7905
7982
  this.hide();
7906
- this.event.emit('save');
7983
+ this.event.emit('save', linkNode);
7907
7984
  },
7908
7985
  });
7909
7986
  button.render();
@@ -7919,9 +7996,10 @@ class LinkPopup {
7919
7996
  if (!this.linkNode) {
7920
7997
  return;
7921
7998
  }
7999
+ const lastChild = this.linkNode.last();
7922
8000
  this.linkNode.remove(true);
7923
8001
  this.hide();
7924
- this.event.emit('remove');
8002
+ this.event.emit('remove', lastChild);
7925
8003
  },
7926
8004
  });
7927
8005
  button.render();
@@ -8017,10 +8095,18 @@ class LinkPopup {
8017
8095
 
8018
8096
  var link = (editor) => {
8019
8097
  const popup = new LinkPopup(editor.popupContainer);
8020
- popup.event.on('save', () => {
8098
+ popup.event.on('save', node => {
8099
+ const range = editor.selection.range;
8100
+ range.setStartAfter(node);
8101
+ range.collapseToStart();
8102
+ editor.selection.addRangeToNativeSelection();
8021
8103
  editor.history.save();
8022
8104
  });
8023
- popup.event.on('remove', () => {
8105
+ popup.event.on('remove', node => {
8106
+ const range = editor.selection.range;
8107
+ range.setStartAfter(node);
8108
+ range.collapseToStart();
8109
+ editor.selection.addRangeToNativeSelection();
8024
8110
  editor.history.save();
8025
8111
  });
8026
8112
  editor.root.on('scroll', () => {
@@ -8101,6 +8187,9 @@ var image = (editor) => {
8101
8187
  };
8102
8188
 
8103
8189
  var codeBlock = (editor) => {
8190
+ if (!window.CodeMirror) {
8191
+ return;
8192
+ }
8104
8193
  editor.command.add('codeBlock', {
8105
8194
  execute: (value) => {
8106
8195
  const box = editor.insertBox('codeBlock', value);
@@ -8278,6 +8367,11 @@ function executeMarkCommand(editor, point) {
8278
8367
  for (const item of markItemList) {
8279
8368
  const results = item.re.exec(text);
8280
8369
  if (results !== null) {
8370
+ const parameters = item.getParameters();
8371
+ const commandName = parameters.shift();
8372
+ if (!editor.command.has(commandName)) {
8373
+ return false;
8374
+ }
8281
8375
  // <p>foo**bold**<focus /></p>, offset = 11
8282
8376
  // to
8283
8377
  // <p>foobold\u200B<focus /></p>,
@@ -8291,8 +8385,7 @@ function executeMarkCommand(editor, point) {
8291
8385
  node.get(0).nodeValue = newValue;
8292
8386
  range.setStart(node, offset - results[0].length);
8293
8387
  range.setEnd(node, offset - (oldValue.length - newValue.length) - 1);
8294
- const parameters = item.getParameters();
8295
- editor.command.execute(parameters.shift(), ...parameters);
8388
+ editor.command.execute(commandName, ...parameters);
8296
8389
  selection.toBookmark(bookmark);
8297
8390
  editor.commitOperation();
8298
8391
  return true;
@@ -8308,6 +8401,11 @@ function spaceKeyExecutesBlockCommand(editor, point) {
8308
8401
  for (const item of blockItemListForSpaceKey) {
8309
8402
  const results = item.re.exec(text);
8310
8403
  if (results !== null) {
8404
+ const parameters = item.getParameters(results);
8405
+ const commandName = parameters.shift();
8406
+ if (!editor.command.has(commandName)) {
8407
+ return false;
8408
+ }
8311
8409
  // <p>#<focus />foo</p>
8312
8410
  // to
8313
8411
  // <h1><focus />foo</h1>
@@ -8318,8 +8416,7 @@ function spaceKeyExecutesBlockCommand(editor, point) {
8318
8416
  const block = bookmark.focus.closestBlock();
8319
8417
  fixEmptyBlock(block);
8320
8418
  selection.range.shrinkAfter(block);
8321
- const parameters = item.getParameters(results);
8322
- editor.command.execute(parameters.shift(), ...parameters);
8419
+ editor.command.execute(commandName, ...parameters);
8323
8420
  selection.toBookmark(bookmark);
8324
8421
  editor.commitOperation();
8325
8422
  return true;
@@ -8334,15 +8431,19 @@ function enterKeyExecutesBlockCommand(editor, block) {
8334
8431
  for (const item of blockItemListForEnterKey) {
8335
8432
  const results = item.re.exec(text);
8336
8433
  if (results !== null) {
8434
+ const parameters = item.getParameters(results);
8435
+ const commandName = parameters.shift();
8436
+ if (!editor.command.has(commandName)) {
8437
+ return false;
8438
+ }
8337
8439
  // <p>---<focus /></p>
8338
8440
  // to
8339
- // <lake-box type="block" name="hr" focus="right"></lake-box>
8441
+ // <lake-box type="block" name="hr" focus="end"></lake-box>
8340
8442
  editor.prepareOperation();
8341
8443
  block.empty();
8342
8444
  fixEmptyBlock(block);
8343
8445
  selection.range.shrinkAfter(block);
8344
- const parameters = item.getParameters(results);
8345
- editor.command.execute(parameters.shift(), ...parameters);
8446
+ editor.command.execute(commandName, ...parameters);
8346
8447
  editor.commitOperation();
8347
8448
  return true;
8348
8449
  }
@@ -8391,7 +8492,7 @@ var markdown = (editor) => {
8391
8492
  if (block.find('lake-box').length > 0) {
8392
8493
  return;
8393
8494
  }
8394
- if (range.getRightText() !== '') {
8495
+ if (range.getEndText() !== '') {
8395
8496
  return;
8396
8497
  }
8397
8498
  if (enterKeyExecutesBlockCommand(editor, block)) {
@@ -8405,14 +8506,14 @@ var markdown = (editor) => {
8405
8506
 
8406
8507
  function splitBlock(editor, block) {
8407
8508
  const range = editor.selection.range;
8408
- const rightText = range.getRightText();
8509
+ const endText = range.getEndText();
8409
8510
  editor.selection.splitBlock();
8410
8511
  block = range.getBlocks()[0];
8411
8512
  if (!block) {
8412
8513
  editor.history.save();
8413
8514
  return;
8414
8515
  }
8415
- if (rightText === '' && (block.isHeading || block.name === 'blockquote')) {
8516
+ if (endText === '' && (block.isHeading || block.name === 'blockquote')) {
8416
8517
  editor.selection.setBlocks('<p />');
8417
8518
  editor.history.save();
8418
8519
  return;
@@ -8426,12 +8527,12 @@ function addBlockOrSplitBlockForBox(editor) {
8426
8527
  const boxNode = range.startNode.closest('lake-box');
8427
8528
  const block = boxNode.closestBlock();
8428
8529
  if (block.length > 0 && !block.isContainer) {
8429
- if (range.isBoxLeft) {
8530
+ if (range.isBoxStart) {
8430
8531
  range.setStartBefore(boxNode);
8431
8532
  range.collapseToStart();
8432
8533
  splitBlock(editor, block);
8433
8534
  }
8434
- else if (range.isBoxRight) {
8535
+ else if (range.isBoxEnd) {
8435
8536
  range.setStartAfter(boxNode);
8436
8537
  range.collapseToStart();
8437
8538
  splitBlock(editor, block);
@@ -8442,10 +8543,10 @@ function addBlockOrSplitBlockForBox(editor) {
8442
8543
  return;
8443
8544
  }
8444
8545
  const newBlock = query('<p><br /></p>');
8445
- if (range.isBoxLeft) {
8546
+ if (range.isBoxStart) {
8446
8547
  boxNode.before(newBlock);
8447
8548
  }
8448
- else if (range.isBoxRight) {
8549
+ else if (range.isBoxEnd) {
8449
8550
  boxNode.after(newBlock);
8450
8551
  range.shrinkAfter(newBlock);
8451
8552
  }
@@ -8495,8 +8596,8 @@ function addLineBreak(editor) {
8495
8596
  const block = range.startNode.closestBlock();
8496
8597
  if (block.length > 0 && !block.isContainer) {
8497
8598
  const prevNode = range.getPrevNode();
8498
- const rightText = range.getRightText();
8499
- if (prevNode.name !== 'br' && rightText === '') {
8599
+ const endText = range.getEndText();
8600
+ if (prevNode.name !== 'br' && endText === '') {
8500
8601
  editor.selection.insertContents('<br /><br />');
8501
8602
  editor.history.save();
8502
8603
  return;
@@ -8509,12 +8610,12 @@ function addBlockOrLineBreakForBox(editor) {
8509
8610
  const boxNode = range.startNode.closest('lake-box');
8510
8611
  const block = boxNode.closestBlock();
8511
8612
  if (block.length > 0 && !block.isContainer) {
8512
- if (range.isBoxLeft) {
8613
+ if (range.isBoxStart) {
8513
8614
  range.setStartBefore(boxNode);
8514
8615
  range.collapseToStart();
8515
8616
  addLineBreak(editor);
8516
8617
  }
8517
- else if (range.isBoxRight) {
8618
+ else if (range.isBoxEnd) {
8518
8619
  range.setStartAfter(boxNode);
8519
8620
  range.collapseToStart();
8520
8621
  addLineBreak(editor);
@@ -8525,10 +8626,10 @@ function addBlockOrLineBreakForBox(editor) {
8525
8626
  return;
8526
8627
  }
8527
8628
  const newBlock = query('<p><br /></p>');
8528
- if (range.isBoxLeft) {
8629
+ if (range.isBoxStart) {
8529
8630
  boxNode.before(newBlock);
8530
8631
  }
8531
- else if (range.isBoxRight) {
8632
+ else if (range.isBoxEnd) {
8532
8633
  boxNode.after(newBlock);
8533
8634
  range.shrinkAfter(newBlock);
8534
8635
  }
@@ -8576,7 +8677,7 @@ function mergeWithPreviousBlock(editor, block) {
8576
8677
  if (block.isEmpty) {
8577
8678
  block.remove();
8578
8679
  }
8579
- range.selectBoxRight(prevBlock);
8680
+ range.selectBoxEnd(prevBlock);
8580
8681
  return;
8581
8682
  }
8582
8683
  if (prevBlock.name === 'br') {
@@ -8605,7 +8706,7 @@ var backspaceKey = (editor) => {
8605
8706
  return;
8606
8707
  }
8607
8708
  editor.rectifyContent();
8608
- if (range.isBoxLeft) {
8709
+ if (range.isBoxStart) {
8609
8710
  const boxNode = range.startNode.closest('lake-box');
8610
8711
  const prevNode = boxNode.prev();
8611
8712
  if (prevNode.length === 0) {
@@ -8663,8 +8764,8 @@ var backspaceKey = (editor) => {
8663
8764
  editor.history.save();
8664
8765
  return;
8665
8766
  }
8666
- const leftText = range.getLeftText();
8667
- if (leftText === '') {
8767
+ const startText = range.getStartText();
8768
+ if (startText === '') {
8668
8769
  event.preventDefault();
8669
8770
  let block = range.getBlocks()[0];
8670
8771
  if (!block) {
@@ -8700,7 +8801,7 @@ function mergeWithNextBlock(editor, block) {
8700
8801
  if (block.isEmpty) {
8701
8802
  block.remove();
8702
8803
  }
8703
- range.selectBoxLeft(nextBlock);
8804
+ range.selectBoxStart(nextBlock);
8704
8805
  editor.history.save();
8705
8806
  return;
8706
8807
  }
@@ -8722,7 +8823,7 @@ var deleteKey = (editor) => {
8722
8823
  return;
8723
8824
  }
8724
8825
  editor.rectifyContent();
8725
- if (range.isBoxRight) {
8826
+ if (range.isBoxEnd) {
8726
8827
  const boxNode = range.startNode.closest('lake-box');
8727
8828
  const nextNode = boxNode.next();
8728
8829
  if (nextNode.length === 0) {
@@ -8779,8 +8880,8 @@ var deleteKey = (editor) => {
8779
8880
  nextNode.remove();
8780
8881
  editor.history.save();
8781
8882
  }
8782
- const rightText = range.getRightText();
8783
- if (rightText === '') {
8883
+ const endText = range.getEndText();
8884
+ if (endText === '') {
8784
8885
  event.preventDefault();
8785
8886
  let block = range.getBlocks()[0];
8786
8887
  if (!block) {
@@ -8819,7 +8920,7 @@ var arrowKeys = (editor) => {
8819
8920
  }
8820
8921
  const boxNode = range.commonAncestor.closest('lake-box');
8821
8922
  if (boxNode.length > 0) {
8822
- if (range.isBoxLeft) {
8923
+ if (range.isBoxStart) {
8823
8924
  const prevNode = boxNode.prev();
8824
8925
  if (prevNode.isBlock || prevNode.isBox) {
8825
8926
  event.preventDefault();
@@ -8834,13 +8935,13 @@ var arrowKeys = (editor) => {
8834
8935
  range.collapseToStart();
8835
8936
  return;
8836
8937
  }
8837
- if (range.isBoxRight) {
8938
+ if (range.isBoxEnd) {
8838
8939
  event.preventDefault();
8839
8940
  range.selectBox(boxNode);
8840
8941
  return;
8841
8942
  }
8842
8943
  event.preventDefault();
8843
- range.selectBoxLeft(boxNode);
8944
+ range.selectBoxStart(boxNode);
8844
8945
  return;
8845
8946
  }
8846
8947
  if (!range.isCollapsed) {
@@ -8859,12 +8960,12 @@ var arrowKeys = (editor) => {
8859
8960
  }
8860
8961
  const boxNode = range.commonAncestor.closest('lake-box');
8861
8962
  if (boxNode.length > 0) {
8862
- if (range.isBoxLeft) {
8963
+ if (range.isBoxStart) {
8863
8964
  event.preventDefault();
8864
8965
  range.selectBox(boxNode);
8865
8966
  return;
8866
8967
  }
8867
- if (range.isBoxRight) {
8968
+ if (range.isBoxEnd) {
8868
8969
  const nextNode = boxNode.next();
8869
8970
  if (nextNode.isBlock || nextNode.isBox) {
8870
8971
  event.preventDefault();
@@ -8880,7 +8981,7 @@ var arrowKeys = (editor) => {
8880
8981
  return;
8881
8982
  }
8882
8983
  event.preventDefault();
8883
- range.selectBoxRight(boxNode);
8984
+ range.selectBoxEnd(boxNode);
8884
8985
  return;
8885
8986
  }
8886
8987
  if (!range.isCollapsed) {
@@ -8932,6 +9033,24 @@ var arrowKeys = (editor) => {
8932
9033
  });
8933
9034
  };
8934
9035
 
9036
+ var escapeKey = (editor) => {
9037
+ editor.keystroke.setKeydown('escape', event => {
9038
+ const selection = editor.selection;
9039
+ const range = selection.range;
9040
+ if (range.isBoxCenter || range.isInsideBox) {
9041
+ event.preventDefault();
9042
+ const boxNode = range.commonAncestor.closest('lake-box');
9043
+ range.selectBoxEnd(boxNode);
9044
+ selection.addRangeToNativeSelection();
9045
+ return;
9046
+ }
9047
+ if (editor.root.hasClass('lake-root-focused')) {
9048
+ event.preventDefault();
9049
+ editor.blur();
9050
+ }
9051
+ });
9052
+ };
9053
+
8935
9054
  Editor.box.add(hrBox);
8936
9055
  Editor.box.add(imageBox);
8937
9056
  Editor.box.add(codeBlockBox);
@@ -8970,6 +9089,7 @@ Editor.plugin.add(backspaceKey);
8970
9089
  Editor.plugin.add(deleteKey);
8971
9090
  Editor.plugin.add(tabKey);
8972
9091
  Editor.plugin.add(arrowKeys);
9092
+ Editor.plugin.add(escapeKey);
8973
9093
 
8974
9094
  export { Box, Button, Dropdown, Editor, Fragment, HTMLParser, Nodes, Range, TextParser, Toolbar, index as Utils, addMark, deleteContents, fixList, icons, insertBookmark, insertContents, insertFragment, insertLink, insertNode, removeMark, setBlocks, splitBlock$1 as splitBlock, splitMarks, toBookmark };
8975
9095
  //# sourceMappingURL=lake.js.map