lakelib 0.1.18 → 0.1.19

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.css CHANGED
@@ -126,13 +126,13 @@ lake-box {
126
126
  margin: 0;
127
127
  padding: 0;
128
128
  text-indent: 0;
129
- grid-template-columns: 1px 1fr 1px;
130
129
  }
131
130
  lake-box[type="inline"] {
132
- display: inline grid;
131
+ display: inline flex;
133
132
  }
134
133
  lake-box[type="block"] {
135
134
  display: block grid;
135
+ grid-template-columns: 1px 1fr 1px;
136
136
  }
137
137
  lake-box .lake-box-strip {
138
138
  display: block;
package/lib/lake.js CHANGED
@@ -1414,7 +1414,7 @@ class Range {
1414
1414
  const height = rect.height;
1415
1415
  return DOMRect.fromRect({
1416
1416
  x,
1417
- y: rect.y,
1417
+ y: height > 0 ? rect.y : 0,
1418
1418
  width: width > 0 ? width : 1,
1419
1419
  height: height > 0 ? height : 1,
1420
1420
  });
@@ -1568,6 +1568,7 @@ class Range {
1568
1568
  this.setEnd(child, child.children().length);
1569
1569
  }
1570
1570
  this.collapseToEnd();
1571
+ this.adjustBr();
1571
1572
  }
1572
1573
  // Reduces the boundary of the range.
1573
1574
  // <div>[<p><strong>foo</strong></p>]</div>
@@ -1671,6 +1672,21 @@ class Range {
1671
1672
  this.adjustTable();
1672
1673
  this.adjustBlock();
1673
1674
  }
1675
+ // Relocates the start and end points of the range for <br /> element.
1676
+ // In composition mode (e.g., when a user starts entering a Chinese character using a Pinyin IME),
1677
+ // uncompleted text is inserted if the caret is positioned behind a <br> tag.
1678
+ // To fix this bug, the caret needs to be moved to the front of the <br> tag.
1679
+ adjustBr() {
1680
+ if (!this.isCollapsed) {
1681
+ return;
1682
+ }
1683
+ const prevNode = this.getPrevNode();
1684
+ const nextNode = this.getNextNode();
1685
+ if (prevNode.name === 'br' && nextNode.length === 0) {
1686
+ this.setStartBefore(prevNode);
1687
+ this.collapseToStart();
1688
+ }
1689
+ }
1674
1690
  // Returns the previous node of the beginning point of the range.
1675
1691
  getPrevNode() {
1676
1692
  let prevNode;
@@ -1907,31 +1923,36 @@ function splitNodes(node, offset, limitNode) {
1907
1923
  };
1908
1924
  }
1909
1925
 
1910
- // Appends a node to the deepest element of the specified element.
1911
- function appendDeepest(element, node) {
1912
- let child = element;
1913
- while (child.length > 0) {
1914
- let firstChild = child.first();
1915
- while (firstChild.isText && firstChild.isEmpty) {
1916
- firstChild = firstChild.next();
1917
- }
1918
- if (child.isText || child.isBox) {
1919
- break;
1920
- }
1921
- if (child.isElement && child.children().length === 1 && firstChild.isBookmark) {
1922
- child.prepend(node);
1923
- break;
1924
- }
1925
- if (child.isElement && !child.isVoid && firstChild.length === 0) {
1926
- child.append(node);
1926
+ // Appends a line break to the end of a block.
1927
+ // Example:
1928
+ // case 1: <p></p> to <p><br /></p>
1929
+ // case 2: <p><br /></p> to <p><br /></p>
1930
+ // case 3: <p>foo</p> to <p>foo<br /></p>
1931
+ // case 4: <ul><li></li></ul> to <ul><li><br /></li></ul>
1932
+ // case 5: <p><focus /></p> to <p><focus /><br /></p>
1933
+ function appendBreak(block) {
1934
+ const breakNode = query('<br />');
1935
+ let child = block;
1936
+ while (child.isBlock) {
1937
+ let lastChild = child.last();
1938
+ while (lastChild.isText && lastChild.isEmpty) {
1939
+ lastChild = lastChild.prev();
1940
+ }
1941
+ if (!lastChild.isBlock && lastChild.name !== 'br') {
1942
+ child.append(breakNode);
1927
1943
  break;
1928
1944
  }
1929
- child = firstChild;
1945
+ child = lastChild;
1930
1946
  }
1947
+ return breakNode;
1931
1948
  }
1932
1949
 
1933
- // Removes The <br /> element in the specified block which is empty.
1934
- function removeBr(block) {
1950
+ // Removes a line break in the specified empty block.
1951
+ // Example:
1952
+ // case 1: <p><br /></p> to <p></p>
1953
+ // case 2: <p><br /><focus /></p> to <p><focus /></p>
1954
+ // case 3: <p><focus /><br /></p> to <p><focus /></p>
1955
+ function removeBreak(block) {
1935
1956
  if (block.length === 0) {
1936
1957
  return;
1937
1958
  }
@@ -1993,10 +2014,10 @@ function mergeNodes(node, otherNode) {
1993
2014
  if (node.isText || otherNode.isText || node.isVoid || otherNode.isVoid) {
1994
2015
  return getAfterPoint(node);
1995
2016
  }
1996
- removeBr(node);
1997
- removeBr(otherNode);
2017
+ removeBreak(node);
2018
+ removeBreak(otherNode);
1998
2019
  if (node.isBlock && node.isEmpty && otherNode.isEmpty) {
1999
- appendDeepest(node, query('<br />'));
2020
+ appendBreak(node);
2000
2021
  }
2001
2022
  const nextNode = node.last();
2002
2023
  const nextOtherNode = otherNode.first();
@@ -2024,7 +2045,7 @@ function mergeNodes(node, otherNode) {
2024
2045
  }
2025
2046
 
2026
2047
  // Returns the deepest element of the specified element.
2027
- function getDeepest(element) {
2048
+ function getDeepElement(element) {
2028
2049
  let child = element;
2029
2050
  while (child.length > 0) {
2030
2051
  let firstChild = child.first();
@@ -2045,7 +2066,7 @@ function wrapNodeList(nodeList, wrapper) {
2045
2066
  return wrapper;
2046
2067
  }
2047
2068
  wrapper = wrapper.clone(true);
2048
- const deepestElement = getDeepest(wrapper);
2069
+ const deepestElement = getDeepElement(wrapper);
2049
2070
  nodeList[0].before(wrapper);
2050
2071
  for (const node of nodeList) {
2051
2072
  deepestElement.append(node);
@@ -3975,7 +3996,7 @@ function uploadFile(config) {
3975
3996
 
3976
3997
  var index = /*#__PURE__*/Object.freeze({
3977
3998
  __proto__: null,
3978
- appendDeepest: appendDeepest,
3999
+ appendBreak: appendBreak,
3979
4000
  camelCase: camelCase,
3980
4001
  changeTagName: changeTagName,
3981
4002
  debug: debug,
@@ -3986,7 +4007,7 @@ var index = /*#__PURE__*/Object.freeze({
3986
4007
  fromBase64: fromBase64,
3987
4008
  getBox: getBox,
3988
4009
  getCSS: getCSS,
3989
- getDeepest: getDeepest,
4010
+ getDeepElement: getDeepElement,
3990
4011
  inString: inString,
3991
4012
  mergeNodes: mergeNodes,
3992
4013
  modifierText: modifierText,
@@ -3995,7 +4016,7 @@ var index = /*#__PURE__*/Object.freeze({
3995
4016
  normalizeValue: normalizeValue,
3996
4017
  parseStyle: parseStyle,
3997
4018
  query: query,
3998
- removeBr: removeBr,
4019
+ removeBreak: removeBreak,
3999
4020
  removeZWS: removeZWS,
4000
4021
  request: request,
4001
4022
  safeTemplate: safeTemplate,
@@ -4044,7 +4065,7 @@ class Fragment {
4044
4065
 
4045
4066
  const blockAttributeRules = {
4046
4067
  id: /^[\w-]+$/,
4047
- class: /^[\w-]+$/,
4068
+ class: /^[\w- ]+$/,
4048
4069
  style: {
4049
4070
  'text-align': ['left', 'center', 'right', 'justify', 'start', 'end'],
4050
4071
  'margin-left': /^-?\d+px$/i,
@@ -4117,7 +4138,7 @@ function getElementRules() {
4117
4138
  },
4118
4139
  },
4119
4140
  span: {
4120
- class: /^[\w-]+$/,
4141
+ class: /^[\w- ]+$/,
4121
4142
  style: {
4122
4143
  color: /^[^"]+$/,
4123
4144
  'background-color': /^[^"]+$/,
@@ -4135,7 +4156,7 @@ function getElementRules() {
4135
4156
  sup: {},
4136
4157
  code: {},
4137
4158
  a: {
4138
- class: /^[\w-]+$/,
4159
+ class: /^[\w- ]+$/,
4139
4160
  name: /^[\w-]+$/,
4140
4161
  href: /^[^"]+$/,
4141
4162
  target: /^[\w-]+$/,
@@ -4510,8 +4531,9 @@ function deleteContents(range) {
4510
4531
  if (noMerge) {
4511
4532
  const block = range.getBlocks()[0];
4512
4533
  if (block && block.isEmpty) {
4513
- appendDeepest(block, query('<br />'));
4514
- range.shrinkAfter(block);
4534
+ const breakNode = appendBreak(block);
4535
+ range.setStartBefore(breakNode);
4536
+ range.collapseToStart();
4515
4537
  }
4516
4538
  return;
4517
4539
  }
@@ -4544,7 +4566,7 @@ function insertFragment(range, fragment) {
4544
4566
  deleteContents(range);
4545
4567
  }
4546
4568
  const block = range.startNode.closestBlock();
4547
- removeBr(block);
4569
+ removeBreak(block);
4548
4570
  const bookmark = insertBookmark(range);
4549
4571
  bookmark.focus.before(fragment);
4550
4572
  toBookmark(range, bookmark);
@@ -4615,7 +4637,7 @@ function setBlocks(range, value) {
4615
4637
  if (block.isList && node.isList && node.attr('indent') !== '') {
4616
4638
  block.attr('indent', node.attr('indent'));
4617
4639
  }
4618
- const deepestBlock = getDeepest(block);
4640
+ const deepestBlock = getDeepElement(block);
4619
4641
  let child = node.first();
4620
4642
  while (child.length > 0) {
4621
4643
  const nextNode = child.next();
@@ -4639,8 +4661,9 @@ function setBlocks(range, value) {
4639
4661
  toBookmark(range, bookmark);
4640
4662
  fixList(range);
4641
4663
  if (block.isEmpty) {
4642
- appendDeepest(block, query('<br />'));
4643
- range.shrinkAfter(block);
4664
+ const breakNode = appendBreak(block);
4665
+ range.setStartBefore(breakNode);
4666
+ range.collapseToStart();
4644
4667
  }
4645
4668
  }
4646
4669
 
@@ -4691,16 +4714,13 @@ function splitBlock$1(range) {
4691
4714
  }
4692
4715
  }
4693
4716
  if (start && start.isEmpty) {
4694
- appendDeepest(start, query('<br />'));
4717
+ appendBreak(start);
4695
4718
  }
4696
4719
  if (end) {
4697
4720
  if (end.isEmpty) {
4698
- appendDeepest(end, query('<br />'));
4699
- range.shrinkAfter(end);
4700
- }
4701
- else {
4702
- range.shrinkBefore(end);
4721
+ appendBreak(end);
4703
4722
  }
4723
+ range.shrinkBefore(end);
4704
4724
  }
4705
4725
  fixList(range);
4706
4726
  return {
@@ -4872,7 +4892,7 @@ function addMark(range, value) {
4872
4892
  }
4873
4893
  }
4874
4894
  const block = range.startNode.closestBlock();
4875
- removeBr(block);
4895
+ removeBreak(block);
4876
4896
  // https://en.wikipedia.org/wiki/Zero-width_space
4877
4897
  const zeroWidthSpace = new Nodes(document.createTextNode('\u200B'));
4878
4898
  const parts = splitMarks(range);
@@ -4884,7 +4904,8 @@ function addMark(range, value) {
4884
4904
  valueNode = newMark;
4885
4905
  }
4886
4906
  else {
4887
- appendDeepest(newMark, zeroWidthSpace);
4907
+ const deepestMark = getDeepElement(newMark);
4908
+ deepestMark.append(zeroWidthSpace);
4888
4909
  valueNode.append(newMark);
4889
4910
  }
4890
4911
  }
@@ -4994,7 +5015,8 @@ function removeMark(range, value) {
4994
5015
  range.collapseToStart();
4995
5016
  return;
4996
5017
  }
4997
- appendDeepest(newMark, zeroWidthSpace);
5018
+ const deepestMark = getDeepElement(newMark);
5019
+ deepestMark.append(zeroWidthSpace);
4998
5020
  parts.start.after(newMark);
4999
5021
  removeEmptyMarks$1(parts.start);
5000
5022
  range.shrinkAfter(newMark);
@@ -5027,7 +5049,7 @@ function insertLink(range, value) {
5027
5049
  if (linkNode.length === 0) {
5028
5050
  linkNode = valueNode.clone(true);
5029
5051
  const block = range.startNode.closestBlock();
5030
- removeBr(block);
5052
+ removeBreak(block);
5031
5053
  insertNode(range, linkNode);
5032
5054
  return linkNode;
5033
5055
  }
@@ -5135,13 +5157,14 @@ function removeBox(range) {
5135
5157
  const parentNode = boxNode.parent();
5136
5158
  unmountBox(box);
5137
5159
  if (parentNode.isEmpty) {
5138
- appendDeepest(parentNode, query('<br />'));
5139
- range.shrinkAfter(parentNode);
5160
+ const breakNode = appendBreak(parentNode);
5161
+ range.setStartBefore(breakNode);
5162
+ range.collapseToStart();
5140
5163
  }
5141
5164
  return box;
5142
5165
  }
5143
5166
 
5144
- var version = "0.1.18";
5167
+ var version = "0.1.19";
5145
5168
 
5146
5169
  // Returns the attributes of the element as an key-value object.
5147
5170
  function getAttributes(node) {
@@ -5923,7 +5946,8 @@ class Editor {
5923
5946
  else {
5924
5947
  boxNode.after(paragraph);
5925
5948
  }
5926
- range.shrinkAfter(paragraph);
5949
+ range.setStart(paragraph, 0);
5950
+ range.collapseToStart();
5927
5951
  }
5928
5952
  const text = stripNode.text();
5929
5953
  stripNode.html('<br />');
@@ -5942,18 +5966,6 @@ class Editor {
5942
5966
  this.container.on('compositionend', () => {
5943
5967
  this.isComposing = false;
5944
5968
  });
5945
- this.container.on('beforeinput', event => {
5946
- const inputEvent = event;
5947
- // <p><br /><focus /></p>
5948
- // When the caret is positioned behind a <br> tag, the input event is triggered twice after inserting a sharp(#) in composition mode.
5949
- if (this.isComposing && inputEvent.inputType === 'insertText') {
5950
- inputEvent.preventDefault();
5951
- this.isComposing = false;
5952
- this.history.save({
5953
- inputType: 'insertText',
5954
- });
5955
- }
5956
- });
5957
5969
  this.container.on('input', event => {
5958
5970
  const inputEvent = event;
5959
5971
  // Here setTimeout is necessary because isComposing is not false after ending composition.
@@ -6063,7 +6075,7 @@ class Editor {
6063
6075
  children = this.container.children();
6064
6076
  if (children.length === 0) {
6065
6077
  this.container.html('<p><br /></p>');
6066
- range.shrinkAfter(this.container);
6078
+ range.shrinkBefore(this.container);
6067
6079
  changed = true;
6068
6080
  debug('Content fixed: default paragraph was added');
6069
6081
  }
@@ -6078,18 +6090,7 @@ class Editor {
6078
6090
  debug(`Content fixed: void element "${child.name}" was wrapped in paragraph`);
6079
6091
  }
6080
6092
  }
6081
- // In composition mode (e.g., when a user starts entering a Chinese character using a Pinyin IME),
6082
- // uncompleted text is inserted if the caret is positioned behind a <br> tag.
6083
- // To fix this bug, the caret needs to be moved to the front of the <br> tag.
6084
- if (range.isCollapsed) {
6085
- const prevNode = range.getPrevNode();
6086
- const nextNode = range.getNextNode();
6087
- if (prevNode.name === 'br' && nextNode.length === 0) {
6088
- range.setStartBefore(prevNode);
6089
- range.collapseToStart();
6090
- debug('Range fixed: the caret has been moved to the front of the <br> tag');
6091
- }
6092
- }
6093
+ range.adjustBr();
6093
6094
  return changed;
6094
6095
  }
6095
6096
  // Sets default config for a plugin.
@@ -8326,7 +8327,7 @@ function insertFirstNode(editor, otherNode) {
8326
8327
  return;
8327
8328
  }
8328
8329
  if (otherNode.first().length > 0) {
8329
- removeBr(block);
8330
+ removeBreak(block);
8330
8331
  }
8331
8332
  if (block.isEmpty && block.name === 'p') {
8332
8333
  block.replaceWith(otherNode);
@@ -10118,8 +10119,9 @@ function removeEmptyMarks(range) {
10118
10119
  const block = range.getBlocks()[0];
10119
10120
  if (block && block.isEmpty && block.first().name !== 'br') {
10120
10121
  block.empty();
10121
- appendDeepest(block, query('<br />'));
10122
- range.shrinkAfter(block);
10122
+ const breakNode = appendBreak(block);
10123
+ range.setStartBefore(breakNode);
10124
+ range.collapseToStart();
10123
10125
  }
10124
10126
  }
10125
10127
  function mergeWithPreviousBlock(editor, block) {
@@ -10244,8 +10246,9 @@ var backspaceKey = (editor) => {
10244
10246
  range.collapseToStart();
10245
10247
  prevNode.remove();
10246
10248
  if (block.isEmpty) {
10247
- appendDeepest(block, query('<br />'));
10248
- range.shrinkAfter(block);
10249
+ const breakNode = appendBreak(block);
10250
+ range.setStartBefore(breakNode);
10251
+ range.collapseToStart();
10249
10252
  }
10250
10253
  editor.history.save();
10251
10254
  return;