lakelib 0.1.14 → 0.1.15

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
@@ -135,17 +135,19 @@ var unlink = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"32\" height=\"32
135
135
 
136
136
  var hr$1 = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"32\" height=\"32\" fill=\"#000000\" viewBox=\"0 0 256 256\"><path d=\"M224,128a8,8,0,0,1-8,8H40a8,8,0,0,1,0-16H216A8,8,0,0,1,224,128Z\"></path></svg>";
137
137
 
138
+ var codeBlock$1 = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"32\" height=\"32\" fill=\"#000000\" viewBox=\"0 0 256 256\"><path d=\"M58.34,101.66l-32-32a8,8,0,0,1,0-11.32l32-32A8,8,0,0,1,69.66,37.66L43.31,64,69.66,90.34a8,8,0,0,1-11.32,11.32Zm40,0a8,8,0,0,0,11.32,0l32-32a8,8,0,0,0,0-11.32l-32-32A8,8,0,0,0,98.34,37.66L124.69,64,98.34,90.34A8,8,0,0,0,98.34,101.66ZM200,40H176a8,8,0,0,0,0,16h24V200H56V136a8,8,0,0,0-16,0v64a16,16,0,0,0,16,16H200a16,16,0,0,0,16-16V56A16,16,0,0,0,200,40Z\"></path></svg>";
139
+
138
140
  var image$1 = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"32\" height=\"32\" fill=\"#000000\" viewBox=\"0 0 256 256\"><path d=\"M216,40H40A16,16,0,0,0,24,56V200a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A16,16,0,0,0,216,40Zm0,16V158.75l-26.07-26.06a16,16,0,0,0-22.63,0l-20,20-44-44a16,16,0,0,0-22.62,0L40,149.37V56ZM40,172l52-52,80,80H40Zm176,28H194.63l-36-36,20-20L216,181.38V200ZM144,100a12,12,0,1,1,12,12A12,12,0,0,1,144,100Z\"></path></svg>";
139
141
 
140
142
  var video$1 = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"32\" height=\"32\" fill=\"#000000\" viewBox=\"0 0 256 256\"><path d=\"M164.44,121.34l-48-32A8,8,0,0,0,104,96v64a8,8,0,0,0,12.44,6.66l48-32a8,8,0,0,0,0-13.32ZM120,145.05V111l25.58,17ZM234.33,69.52a24,24,0,0,0-14.49-16.4C185.56,39.88,131,40,128,40s-57.56-.12-91.84,13.12a24,24,0,0,0-14.49,16.4C19.08,79.5,16,97.74,16,128s3.08,48.5,5.67,58.48a24,24,0,0,0,14.49,16.41C69,215.56,120.4,216,127.34,216h1.32c6.94,0,58.37-.44,91.18-13.11a24,24,0,0,0,14.49-16.41c2.59-10,5.67-28.22,5.67-58.48S236.92,79.5,234.33,69.52Zm-15.49,113a8,8,0,0,1-4.77,5.49c-31.65,12.22-85.48,12-86,12H128c-.54,0-54.33.2-86-12a8,8,0,0,1-4.77-5.49C34.8,173.39,32,156.57,32,128s2.8-45.39,5.16-54.47A8,8,0,0,1,41.93,68c30.52-11.79,81.66-12,85.85-12h.27c.54,0,54.38-.18,86,12a8,8,0,0,1,4.77,5.49C221.2,82.61,224,99.43,224,128S221.2,173.39,218.84,182.47Z\"></path></svg>";
141
143
 
142
144
  var attachment = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"32\" height=\"32\" fill=\"#000000\" viewBox=\"0 0 256 256\"><path d=\"M209.66,122.34a8,8,0,0,1,0,11.32l-82.05,82a56,56,0,0,1-79.2-79.21L147.67,35.73a40,40,0,1,1,56.61,56.55L105,193A24,24,0,1,1,71,159L154.3,74.38A8,8,0,1,1,165.7,85.6L82.39,170.31a8,8,0,1,0,11.27,11.36L192.93,81A24,24,0,1,0,159,47L59.76,147.68a40,40,0,1,0,56.53,56.62l82.06-82A8,8,0,0,1,209.66,122.34Z\"></path></svg>";
143
145
 
144
- var codeBlock$1 = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"32\" height=\"32\" fill=\"#000000\" viewBox=\"0 0 256 256\"><path d=\"M58.34,101.66l-32-32a8,8,0,0,1,0-11.32l32-32A8,8,0,0,1,69.66,37.66L43.31,64,69.66,90.34a8,8,0,0,1-11.32,11.32Zm40,0a8,8,0,0,0,11.32,0l32-32a8,8,0,0,0,0-11.32l-32-32A8,8,0,0,0,98.34,37.66L124.69,64,98.34,90.34A8,8,0,0,0,98.34,101.66ZM200,40H176a8,8,0,0,0,0,16h24V200H56V136a8,8,0,0,0-16,0v64a16,16,0,0,0,16,16H200a16,16,0,0,0,16-16V56A16,16,0,0,0,200,40Z\"></path></svg>";
146
+ var emoji$1 = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"32\" height=\"32\" fill=\"#000000\" viewBox=\"0 0 256 256\"><path d=\"M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm0,192a88,88,0,1,1,88-88A88.1,88.1,0,0,1,128,216ZM80,108a12,12,0,1,1,12,12A12,12,0,0,1,80,108Zm96,0a12,12,0,1,1-12-12A12,12,0,0,1,176,108Zm-1.07,48c-10.29,17.79-27.4,28-46.93,28s-36.63-10.2-46.92-28a8,8,0,1,1,13.84-8c7.47,12.91,19.21,20,33.08,20s25.61-7.1,33.07-20a8,8,0,0,1,13.86,8Z\"></path></svg>";
145
147
 
146
148
  var table = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"32\" height=\"32\" fill=\"#000000\" viewBox=\"0 0 256 256\"><path d=\"M224,48H32a8,8,0,0,0-8,8V192a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A8,8,0,0,0,224,48ZM40,112H80v32H40Zm56,0H216v32H96ZM216,64V96H40V64ZM40,160H80v32H40Zm176,32H96V160H216v32Z\"></path></svg>";
147
149
 
148
- // These icons are from open source projects.
150
+ // These icons are sourced from open source projects.
149
151
  //
150
152
  // Fluent Icons by Microsoft (https://fluenticons.co/).
151
153
  // - superscript.svg
@@ -217,10 +219,11 @@ const icons = new Map([
217
219
  ['link', link$1],
218
220
  ['unlink', unlink],
219
221
  ['hr', hr$1],
222
+ ['codeBlock', codeBlock$1],
220
223
  ['image', image$1],
221
224
  ['video', video$1],
222
225
  ['attachment', attachment],
223
- ['codeBlock', codeBlock$1],
226
+ ['emoji', emoji$1],
224
227
  ['table', table],
225
228
  ]);
226
229
 
@@ -269,9 +272,10 @@ function safeTemplate(strings, ...keys) {
269
272
  function camelCase(value) {
270
273
  const valueList = value.split('-');
271
274
  let camelString = '';
272
- valueList.forEach((val, index) => {
273
- camelString += (index > 0) ? val.charAt(0).toUpperCase() + val.substring(1) : val;
274
- });
275
+ for (let i = 0; i < valueList.length; i++) {
276
+ const val = valueList[i];
277
+ camelString += (i > 0) ? val.charAt(0).toUpperCase() + val.substring(1) : val;
278
+ }
275
279
  return camelString;
276
280
  }
277
281
 
@@ -876,15 +880,16 @@ class Nodes {
876
880
  var _a;
877
881
  const elementId = element.lakeId;
878
882
  const eventItems = (_a = eventData[elementId]) !== null && _a !== void 0 ? _a : [];
879
- eventItems.forEach((item, index) => {
883
+ for (let i = 0; i < eventItems.length; i++) {
884
+ const item = eventItems[i];
880
885
  if (!type || type === item.type && (!listener || listener === item.listener)) {
881
886
  element.removeEventListener(item.type, item.listener, false);
882
- eventItems[index] = {
887
+ eventItems[i] = {
883
888
  type: '',
884
889
  listener: () => { },
885
890
  };
886
891
  }
887
- });
892
+ }
888
893
  eventData[elementId] = eventItems.filter((item) => item.type !== '');
889
894
  });
890
895
  }
@@ -893,11 +898,11 @@ class Nodes {
893
898
  return this.eachElement(element => {
894
899
  const elementId = element.lakeId;
895
900
  const eventItems = eventData[elementId];
896
- eventItems.forEach(item => {
901
+ for (const item of eventItems) {
897
902
  if (item.type === type) {
898
903
  item.listener(event !== null && event !== void 0 ? event : new Event(type));
899
904
  }
900
- });
905
+ }
901
906
  });
902
907
  }
903
908
  // Gets all event listeners attached to the Nodes object.
@@ -953,9 +958,9 @@ class Nodes {
953
958
  }
954
959
  addClass(className) {
955
960
  if (Array.isArray(className)) {
956
- className.forEach(name => {
961
+ for (const name of className) {
957
962
  this.addClass(name);
958
- });
963
+ }
959
964
  return this;
960
965
  }
961
966
  return this.eachElement(element => {
@@ -967,9 +972,9 @@ class Nodes {
967
972
  }
968
973
  removeClass(className) {
969
974
  if (Array.isArray(className)) {
970
- className.forEach(name => {
975
+ for (const name of className) {
971
976
  this.removeClass(name);
972
- });
977
+ }
973
978
  return this;
974
979
  }
975
980
  return this.eachElement(element => {
@@ -1061,22 +1066,21 @@ class Nodes {
1061
1066
  this.html('');
1062
1067
  return this;
1063
1068
  }
1064
- // Inserts the specified content as the first child of each element.
1069
+ // Inserts the specified content to the beginning of the first element.
1065
1070
  prepend(content) {
1071
+ const element = this.get(0);
1066
1072
  if (typeof content === 'string') {
1067
- return this.eachElement(element => {
1068
- const list = toNodeList(content).reverse();
1069
- list.forEach((node) => {
1070
- if (element.firstChild) {
1071
- element.insertBefore(node, element.firstChild);
1072
- }
1073
- else {
1074
- element.appendChild(node);
1075
- }
1076
- });
1077
- });
1073
+ const list = toNodeList(content).reverse();
1074
+ for (const node of list) {
1075
+ if (element.firstChild) {
1076
+ element.insertBefore(node, element.firstChild);
1077
+ }
1078
+ else {
1079
+ element.appendChild(node);
1080
+ }
1081
+ }
1082
+ return this;
1078
1083
  }
1079
- const element = this.get(0);
1080
1084
  if (content instanceof Nodes) {
1081
1085
  content = content.get(0);
1082
1086
  }
@@ -1088,71 +1092,62 @@ class Nodes {
1088
1092
  }
1089
1093
  return this;
1090
1094
  }
1091
- // Inserts the specified content as the last child of each element.
1095
+ // Inserts the specified content to the end of the first element.
1092
1096
  append(content) {
1097
+ const element = this.get(0);
1093
1098
  if (typeof content === 'string') {
1094
- return this.eachElement(element => {
1095
- const list = toNodeList(content);
1096
- list.forEach((node) => {
1097
- element.appendChild(node);
1098
- });
1099
- });
1099
+ const list = toNodeList(content);
1100
+ for (const node of list) {
1101
+ element.appendChild(node);
1102
+ }
1103
+ return this;
1100
1104
  }
1101
- const element = this.get(0);
1102
1105
  if (content instanceof Nodes) {
1103
1106
  content = content.get(0);
1104
1107
  }
1105
1108
  element.appendChild(content);
1106
1109
  return this;
1107
1110
  }
1108
- // Inserts the specified content before each node.
1111
+ // Inserts the specified content before the first node.
1109
1112
  before(content) {
1113
+ const node = this.get(0);
1114
+ if (!node.parentNode) {
1115
+ return this;
1116
+ }
1110
1117
  if (typeof content === 'string') {
1111
- return this.each(node => {
1112
- const list = toNodeList(content);
1113
- list.forEach(target => {
1114
- if (!node.parentNode) {
1115
- return;
1116
- }
1117
- node.parentNode.insertBefore(target, node);
1118
- });
1119
- });
1118
+ const list = toNodeList(content);
1119
+ for (const target of list) {
1120
+ node.parentNode.insertBefore(target, node);
1121
+ }
1122
+ return this;
1120
1123
  }
1121
- const node = this.get(0);
1122
1124
  if (content instanceof Nodes) {
1123
1125
  content = content.get(0);
1124
1126
  }
1125
- if (!node.parentNode) {
1126
- return this;
1127
- }
1128
1127
  node.parentNode.insertBefore(content, node);
1129
1128
  return this;
1130
1129
  }
1131
- // Inserts the specified content after each node.
1130
+ // Inserts the specified content after the first node.
1132
1131
  after(content) {
1132
+ const node = this.get(0);
1133
+ if (!node.parentNode) {
1134
+ return this;
1135
+ }
1133
1136
  if (typeof content === 'string') {
1134
- return this.each(node => {
1135
- const list = toNodeList(content).reverse();
1136
- list.forEach(target => {
1137
- if (!node.parentNode) {
1138
- return;
1139
- }
1140
- if (node.nextSibling) {
1141
- node.parentNode.insertBefore(target, node.nextSibling);
1142
- }
1143
- else {
1144
- node.parentNode.appendChild(target);
1145
- }
1146
- });
1147
- });
1137
+ const list = toNodeList(content).reverse();
1138
+ for (const target of list) {
1139
+ if (node.nextSibling) {
1140
+ node.parentNode.insertBefore(target, node.nextSibling);
1141
+ }
1142
+ else {
1143
+ node.parentNode.appendChild(target);
1144
+ }
1145
+ }
1146
+ return this;
1148
1147
  }
1149
- const node = this.get(0);
1150
1148
  if (content instanceof Nodes) {
1151
1149
  content = content.get(0);
1152
1150
  }
1153
- if (!node.parentNode) {
1154
- return this;
1155
- }
1156
1151
  if (node.nextSibling) {
1157
1152
  node.parentNode.insertBefore(content, node.nextSibling);
1158
1153
  }
@@ -1161,21 +1156,21 @@ class Nodes {
1161
1156
  }
1162
1157
  return this;
1163
1158
  }
1164
- // Replaces each node with the provided new content.
1159
+ // Replaces the first node with the provided new content.
1165
1160
  replaceWith(newContent) {
1166
- return this.each(node => {
1167
- let target;
1168
- if (newContent instanceof Nodes) {
1169
- target = newContent.get(0);
1170
- }
1171
- else {
1172
- target = toNodeList(newContent)[0];
1173
- }
1174
- if (!node.parentNode) {
1175
- return;
1176
- }
1177
- node.parentNode.replaceChild(target, node);
1178
- });
1161
+ const node = this.get(0);
1162
+ if (!node.parentNode) {
1163
+ return this;
1164
+ }
1165
+ let target;
1166
+ if (newContent instanceof Nodes) {
1167
+ target = newContent.get(0);
1168
+ }
1169
+ else {
1170
+ target = toNodeList(newContent)[0];
1171
+ }
1172
+ node.parentNode.replaceChild(target, node);
1173
+ return this;
1179
1174
  }
1180
1175
  // Removes each node from the DOM.
1181
1176
  // keepChildren parameter:
@@ -1470,7 +1465,7 @@ class Range {
1470
1465
  selectBox(boxNode) {
1471
1466
  const boxContainer = boxNode.find('.lake-box-container');
1472
1467
  if (boxContainer.length === 0) {
1473
- throw new Error(`The box cannot be selected because the box '${boxNode.attr('name')}' (id=${boxNode.id}) has not been rendered yet.`);
1468
+ throw new Error(`The box cannot be selected because the box "${boxNode.attr('name')}" (id=${boxNode.id}) has not been rendered yet.`);
1474
1469
  }
1475
1470
  this.setStart(boxContainer, 0);
1476
1471
  this.collapseToStart();
@@ -1479,7 +1474,7 @@ class Range {
1479
1474
  selectBoxStart(boxNode) {
1480
1475
  const boxStrip = boxNode.find('.lake-box-strip');
1481
1476
  if (boxStrip.length === 0) {
1482
- throw new Error(`The box cannot be selected because the box '${boxNode.attr('name')}' (id=${boxNode.id}) has not been rendered yet.`);
1477
+ throw new Error(`The box cannot be selected because the box "${boxNode.attr('name')}" (id=${boxNode.id}) has not been rendered yet.`);
1483
1478
  }
1484
1479
  this.selectNodeContents(boxStrip.eq(0));
1485
1480
  this.collapseToStart();
@@ -1488,7 +1483,7 @@ class Range {
1488
1483
  selectBoxEnd(boxNode) {
1489
1484
  const boxStrip = boxNode.find('.lake-box-strip');
1490
1485
  if (boxStrip.length === 0) {
1491
- throw new Error(`The box cannot be selected because the box '${boxNode.attr('name')}' (id=${boxNode.id}) has not been rendered yet.`);
1486
+ throw new Error(`The box cannot be selected because the box "${boxNode.attr('name')}" (id=${boxNode.id}) has not been rendered yet.`);
1492
1487
  }
1493
1488
  this.selectNodeContents(boxStrip.eq(1));
1494
1489
  this.collapseToStart();
@@ -2020,9 +2015,9 @@ function wrapNodeList(nodeList, wrapper) {
2020
2015
  wrapper = wrapper.clone(true);
2021
2016
  const deepestElement = getDeepest(wrapper);
2022
2017
  nodeList[0].before(wrapper);
2023
- nodeList.forEach(node => {
2018
+ for (const node of nodeList) {
2024
2019
  deepestElement.append(node);
2025
- });
2020
+ }
2026
2021
  return wrapper;
2027
2022
  }
2028
2023
 
@@ -2855,6 +2850,7 @@ var enUS = {
2855
2850
  highlight: 'Highlight',
2856
2851
  image: 'Image',
2857
2852
  file: 'File',
2853
+ emoji: 'Emoji',
2858
2854
  removeColor: 'Remove color',
2859
2855
  },
2860
2856
  link: {
@@ -2938,6 +2934,7 @@ var zhCN = {
2938
2934
  highlight: '文字背景',
2939
2935
  image: '图片',
2940
2936
  file: '文件',
2937
+ emoji: '表情',
2941
2938
  removeColor: '默认',
2942
2939
  },
2943
2940
  link: {
@@ -3021,6 +3018,7 @@ var ja = {
3021
3018
  highlight: '文字の背景',
3022
3019
  image: '画像',
3023
3020
  file: 'ファイル',
3021
+ emoji: '絵文字',
3024
3022
  removeColor: 'デフォルト',
3025
3023
  },
3026
3024
  link: {
@@ -3104,6 +3102,7 @@ var ko = {
3104
3102
  highlight: '글자 배경',
3105
3103
  image: '이미지',
3106
3104
  file: '파일',
3105
+ emoji: '이모지',
3107
3106
  removeColor: '기본색',
3108
3107
  },
3109
3108
  link: {
@@ -3284,7 +3283,7 @@ class Dropdown {
3284
3283
  }
3285
3284
  });
3286
3285
  menuNode.css('visibility', 'hidden');
3287
- menuNode.show(config.menuType === 'color' ? 'flex' : 'block');
3286
+ menuNode.show(config.menuType === 'list' ? 'block' : 'flex');
3288
3287
  const dropdownNativeNode = dropdownNode.get(0);
3289
3288
  const dropdownRect = dropdownNativeNode.getBoundingClientRect();
3290
3289
  // A overflow width on the left side, greater than 0 indicates an overflow.
@@ -3347,7 +3346,7 @@ class Dropdown {
3347
3346
  if (dropdownNode.attr('disabled')) {
3348
3347
  return;
3349
3348
  }
3350
- const value = dropdownNode.attr('color') || config.defaultValue;
3349
+ const value = dropdownNode.attr('color') || config.defaultValue || '';
3351
3350
  config.onSelect(value);
3352
3351
  });
3353
3352
  }
@@ -3374,14 +3373,17 @@ class Dropdown {
3374
3373
  });
3375
3374
  }
3376
3375
  render() {
3377
- var _a;
3376
+ var _a, _b;
3378
3377
  const config = this.config;
3378
+ const defaultValue = (_a = config.defaultValue) !== null && _a !== void 0 ? _a : '';
3379
3379
  const dropdownNode = this.node;
3380
3380
  const titleNode = dropdownNode.find('.lake-dropdown-title');
3381
3381
  if (!config.downIcon) {
3382
3382
  titleNode.addClass('lake-dropdown-title-no-down');
3383
3383
  }
3384
- titleNode.css('width', config.width);
3384
+ if (config.width) {
3385
+ titleNode.css('width', config.width);
3386
+ }
3385
3387
  const tooltip = typeof config.tooltip === 'string' ? config.tooltip : config.tooltip(this.locale);
3386
3388
  titleNode.attr('title', tooltip);
3387
3389
  const textNode = titleNode.find('.lake-dropdown-text');
@@ -3398,13 +3400,16 @@ class Dropdown {
3398
3400
  }
3399
3401
  const menuNode = query('<ul class="lake-dropdown-menu" />');
3400
3402
  menuNode.addClass(`lake-${config.menuType}-dropdown-menu`);
3401
- Dropdown.setValue(dropdownNode, [config.defaultValue]);
3403
+ if (config.menuWidth) {
3404
+ menuNode.css('width', config.menuWidth);
3405
+ }
3406
+ Dropdown.setValue(dropdownNode, [defaultValue]);
3402
3407
  if (textNode.length > 0) {
3403
3408
  const menuMap = Dropdown.getMenuMap(config.menuItems, this.locale);
3404
- textNode.text((_a = menuMap.get(config.defaultValue)) !== null && _a !== void 0 ? _a : config.defaultValue);
3409
+ textNode.text((_b = menuMap.get(defaultValue)) !== null && _b !== void 0 ? _b : defaultValue);
3405
3410
  }
3406
3411
  if (config.menuType === 'color') {
3407
- this.updateColorAccent(titleNode, config.defaultValue);
3412
+ this.updateColorAccent(titleNode, defaultValue);
3408
3413
  }
3409
3414
  this.apppendMenuItems(menuNode);
3410
3415
  dropdownNode.append(titleNode);
@@ -3489,21 +3494,19 @@ class BoxToolbar {
3489
3494
  // Renders a toolbar for the specified box.
3490
3495
  render() {
3491
3496
  this.root.append(this.container);
3492
- this.items.forEach(item => {
3497
+ for (const item of this.items) {
3493
3498
  if (item === '|') {
3494
3499
  this.appendDivider();
3495
- return;
3496
3500
  }
3497
- if (item.type === 'button') {
3501
+ else if (item.type === 'button') {
3498
3502
  this.buttonItemList.push(item);
3499
3503
  this.appendButton(item);
3500
- return;
3501
3504
  }
3502
- if (item.type === 'dropdown') {
3505
+ else if (item.type === 'dropdown') {
3503
3506
  this.dropdownItemList.push(item);
3504
3507
  this.appendDropdown(item);
3505
3508
  }
3506
- });
3509
+ }
3507
3510
  this.updatePosition();
3508
3511
  }
3509
3512
  unmount() {
@@ -3511,8 +3514,6 @@ class BoxToolbar {
3511
3514
  }
3512
3515
  }
3513
3516
 
3514
- // A key-value object for storing data about box.
3515
- const boxData = {};
3516
3517
  const framework = safeTemplate `
3517
3518
  <span class="lake-box-strip"><br /></span>
3518
3519
  <div class="lake-box-container" contenteditable="false"></div>
@@ -3524,7 +3525,7 @@ class Box {
3524
3525
  if (typeof node === 'string') {
3525
3526
  const component = boxes.get(node);
3526
3527
  if (component === undefined) {
3527
- throw new Error(`Box '${node}' has not been defined yet.`);
3528
+ throw new Error(`Box "${node}" has not been defined yet.`);
3528
3529
  }
3529
3530
  const type = encode(component.type);
3530
3531
  const name = encode(component.name);
@@ -3537,15 +3538,12 @@ class Box {
3537
3538
  this.node = query(node);
3538
3539
  const component = boxes.get(this.name);
3539
3540
  if (component === undefined) {
3540
- throw new Error(`Box '${this.name}' has not been defined yet.`);
3541
+ throw new Error(`Box "${this.name}" has not been defined yet.`);
3541
3542
  }
3542
3543
  if (component.value && !this.node.hasAttr('value')) {
3543
3544
  this.value = component.value;
3544
3545
  }
3545
3546
  }
3546
- if (!boxData[this.node.id]) {
3547
- boxData[this.node.id] = {};
3548
- }
3549
3547
  }
3550
3548
  // Adds the framework of the box.
3551
3549
  addFramework() {
@@ -3610,14 +3608,6 @@ class Box {
3610
3608
  }
3611
3609
  this.value = value;
3612
3610
  }
3613
- // Returns data of the box.
3614
- getData(key) {
3615
- return boxData[this.node.id][key];
3616
- }
3617
- // Updates data of the box.
3618
- setData(key, value) {
3619
- boxData[this.node.id][key] = value;
3620
- }
3621
3611
  // Returns the editor instance of the box.
3622
3612
  getEditor() {
3623
3613
  const container = this.node.closest('div[contenteditable]');
@@ -3678,7 +3668,6 @@ class Box {
3678
3668
  unmount() {
3679
3669
  this.event.emit('blur');
3680
3670
  this.event.emit('beforeunmount');
3681
- boxData[this.node.id] = {};
3682
3671
  this.event.removeAllListeners();
3683
3672
  this.node.empty();
3684
3673
  debug(`Box "${this.name}" (id: ${this.node.id}) unmounted`);
@@ -3852,6 +3841,71 @@ function request(option) {
3852
3841
  return xhr;
3853
3842
  }
3854
3843
 
3844
+ function uploadFile(config) {
3845
+ const { editor, name, file, onError, onSuccess } = config;
3846
+ const { requestMethod, requestAction, requestTypes } = editor.config[name];
3847
+ if (requestTypes.indexOf(file.type) < 0) {
3848
+ if (onError) {
3849
+ onError(`File "${file.name}" is not allowed for uploading.`);
3850
+ }
3851
+ throw new Error(`Cannot upload file "${file.name}" because its type "${file.type}" is not found in ['${requestTypes.join('\', \'')}'].`);
3852
+ }
3853
+ const box = editor.selection.insertBox(name, {
3854
+ url: URL.createObjectURL(file),
3855
+ status: 'uploading',
3856
+ name: file.name,
3857
+ size: file.size,
3858
+ type: file.type,
3859
+ lastModified: file.lastModified,
3860
+ });
3861
+ let xhr = request({
3862
+ onProgress: e => {
3863
+ const percentNode = box.node.find('.lake-percent');
3864
+ const percent = Math.round(e.percent);
3865
+ percentNode.text(`${percent < 100 ? percent : 99} %`);
3866
+ },
3867
+ onError: (error, body) => {
3868
+ xhr = null;
3869
+ debug(error.toString(), body);
3870
+ box.updateValue('status', 'error');
3871
+ box.render();
3872
+ if (onError) {
3873
+ onError(error.toString());
3874
+ }
3875
+ },
3876
+ onSuccess: body => {
3877
+ xhr = null;
3878
+ if (!body.url) {
3879
+ box.updateValue('status', 'error');
3880
+ box.render();
3881
+ if (onError) {
3882
+ onError('Cannot find the url field.');
3883
+ }
3884
+ return;
3885
+ }
3886
+ box.updateValue({
3887
+ status: 'done',
3888
+ url: body.url,
3889
+ });
3890
+ box.render();
3891
+ editor.history.save();
3892
+ if (onSuccess) {
3893
+ onSuccess();
3894
+ }
3895
+ },
3896
+ file,
3897
+ action: requestAction,
3898
+ method: requestMethod,
3899
+ });
3900
+ box.event.on('beforeunmount', () => {
3901
+ if (xhr) {
3902
+ xhr.abort();
3903
+ debug('Upload canceled');
3904
+ }
3905
+ });
3906
+ return box;
3907
+ }
3908
+
3855
3909
  // String
3856
3910
 
3857
3911
  var index = /*#__PURE__*/Object.freeze({
@@ -3884,6 +3938,7 @@ var index = /*#__PURE__*/Object.freeze({
3884
3938
  template: template,
3885
3939
  toHex: toHex,
3886
3940
  toNodeList: toNodeList,
3941
+ uploadFile: uploadFile,
3887
3942
  wrapNodeList: wrapNodeList
3888
3943
  });
3889
3944
 
@@ -3891,6 +3946,10 @@ class Fragment {
3891
3946
  constructor(fragment) {
3892
3947
  this.fragment = fragment !== null && fragment !== void 0 ? fragment : document.createDocumentFragment();
3893
3948
  }
3949
+ // Gets a native fragment.
3950
+ get() {
3951
+ return this.fragment;
3952
+ }
3894
3953
  // Returns the descendants of the fragment which are selected by the specified CSS selector.
3895
3954
  find(selector) {
3896
3955
  const nodeList = [];
@@ -3910,7 +3969,7 @@ class Fragment {
3910
3969
  }
3911
3970
  // Inserts the specified node as the last child.
3912
3971
  append(node) {
3913
- node.each(nativeNode => {
3972
+ query(node).each(nativeNode => {
3914
3973
  this.fragment.appendChild(nativeNode);
3915
3974
  });
3916
3975
  }
@@ -4411,6 +4470,9 @@ function deleteContents(range) {
4411
4470
 
4412
4471
  // Inserts a DocumentFragment object into the specified range.
4413
4472
  function insertFragment(range, fragment) {
4473
+ if (fragment instanceof Fragment) {
4474
+ fragment = fragment.get();
4475
+ }
4414
4476
  if (range.commonAncestor.isOutside) {
4415
4477
  return;
4416
4478
  }
@@ -4428,16 +4490,6 @@ function insertFragment(range, fragment) {
4428
4490
  range.adjustBlock();
4429
4491
  }
4430
4492
 
4431
- // Inserts a HTML string into the specified range.
4432
- function insertContents(range, value) {
4433
- const nodes = query(value);
4434
- const fragment = document.createDocumentFragment();
4435
- nodes.each(nativeNode => {
4436
- fragment.appendChild(nativeNode);
4437
- });
4438
- insertFragment(range, fragment);
4439
- }
4440
-
4441
4493
  function getTopNonBlockNodes(range) {
4442
4494
  const container = range.commonAncestor.closest('div[contenteditable="true"],td');
4443
4495
  let nodeList = [];
@@ -4499,7 +4551,7 @@ function setBlocks(range, value) {
4499
4551
  }
4500
4552
  else {
4501
4553
  const block = valueNode.clone(true);
4502
- if (node.isList && node.attr('indent') !== '') {
4554
+ if (block.isList && node.isList && node.attr('indent') !== '') {
4503
4555
  block.attr('indent', node.attr('indent'));
4504
4556
  }
4505
4557
  const deepestBlock = getDeepest(block);
@@ -4951,8 +5003,6 @@ function insertLink(range, value) {
4951
5003
  return linkNode;
4952
5004
  }
4953
5005
 
4954
- var version = "0.1.14";
4955
-
4956
5006
  // Inserts a box into the specified range.
4957
5007
  function insertBox(range, boxName, boxValue) {
4958
5008
  if (range.commonAncestor.isOutside) {
@@ -5030,6 +5080,8 @@ function removeBox(range) {
5030
5080
  return box;
5031
5081
  }
5032
5082
 
5083
+ var version = "0.1.15";
5084
+
5033
5085
  // Returns the attributes of the element as an key-value object.
5034
5086
  function getAttributes(node) {
5035
5087
  const nativeNode = node.get(0);
@@ -5167,9 +5219,6 @@ class Selection {
5167
5219
  insertFragment(fragment) {
5168
5220
  return insertFragment(this.range, fragment);
5169
5221
  }
5170
- insertContents(value) {
5171
- return insertContents(this.range, value);
5172
- }
5173
5222
  deleteContents() {
5174
5223
  return deleteContents(this.range);
5175
5224
  }
@@ -5209,7 +5258,7 @@ class Selection {
5209
5258
  insertBox(boxName, boxValue) {
5210
5259
  const box = insertBox(this.range, boxName, boxValue);
5211
5260
  if (!box) {
5212
- throw new Error(`Box '${boxName}' cannot be inserted outside the editor.`);
5261
+ throw new Error(`Box "${boxName}" cannot be inserted outside the editor.`);
5213
5262
  }
5214
5263
  return box;
5215
5264
  }
@@ -5242,7 +5291,7 @@ class Command {
5242
5291
  getItem(name) {
5243
5292
  const commandItem = this.commandMap.get(name);
5244
5293
  if (commandItem === undefined) {
5245
- throw new Error(`Command '${name}' does not exist`);
5294
+ throw new Error(`Command "${name}" has not been defined yet.`);
5246
5295
  }
5247
5296
  return commandItem;
5248
5297
  }
@@ -5553,9 +5602,9 @@ class Plugin {
5553
5602
  this.pluginList.push(plugin);
5554
5603
  }
5555
5604
  loadAll(editor) {
5556
- this.pluginList.forEach(plugin => {
5605
+ for (const plugin of this.pluginList) {
5557
5606
  plugin(editor);
5558
- });
5607
+ }
5559
5608
  }
5560
5609
  }
5561
5610
 
@@ -5568,6 +5617,7 @@ const defaultConfig = {
5568
5617
  indentWithTab: true,
5569
5618
  lang: 'en-US',
5570
5619
  minChangeSize: 5,
5620
+ historySize: 100,
5571
5621
  onMessage: (type, message) => {
5572
5622
  if (type === 'success') {
5573
5623
  // eslint-disable-next-line no-console
@@ -5679,7 +5729,6 @@ class Editor {
5679
5729
  boxContainer.removeClass('lake-box-selected');
5680
5730
  box.event.emit('blur');
5681
5731
  });
5682
- this.event.emit('boxselectionstylechange');
5683
5732
  }, 50, {
5684
5733
  leading: false,
5685
5734
  trailing: true,
@@ -5758,6 +5807,7 @@ class Editor {
5758
5807
  this.selection = new Selection(this.container);
5759
5808
  this.command = new Command(this.selection);
5760
5809
  this.history = new History(this.selection);
5810
+ this.history.limit = this.config.historySize;
5761
5811
  this.keystroke = new Keystroke(this.container);
5762
5812
  editors.set(this.container.id, this);
5763
5813
  }
@@ -6281,7 +6331,7 @@ const moreStyleMenuItems = [
6281
6331
  text: locale => locale.toolbar.code(),
6282
6332
  },
6283
6333
  ];
6284
- // These colors are from Ant Design (https://ant.design/docs/spec/colors)
6334
+ // These colors are sourced from Ant Design (https://ant.design/docs/spec/colors)
6285
6335
  const colors = [
6286
6336
  // Dust Red, Volcano, Sunset Orange, Calendula Gold, Sunrise Yellow, Lime, Polar Green, Cyan, Daybreak Blue, Geek Blue, Golden Purple, Magenta
6287
6337
  '#f5222d', '#fa541c', '#fa8c16', '#faad14', '#fadb14', '#a0d911', '#52c41a', '#13c2c2', '#1677ff', '#2f54eb', '#722ed1', '#eb2f96', // color 6
@@ -6556,19 +6606,19 @@ const toolbarItems = [
6556
6606
  },
6557
6607
  },
6558
6608
  {
6559
- name: 'video',
6609
+ name: 'codeBlock',
6560
6610
  type: 'button',
6561
- icon: icons.get('video'),
6562
- tooltip: locale => locale.toolbar.video(),
6611
+ icon: icons.get('codeBlock'),
6612
+ tooltip: locale => locale.toolbar.codeBlock(),
6563
6613
  onClick: (editor, value) => {
6564
6614
  editor.command.execute(value);
6565
6615
  },
6566
6616
  },
6567
6617
  {
6568
- name: 'codeBlock',
6618
+ name: 'video',
6569
6619
  type: 'button',
6570
- icon: icons.get('codeBlock'),
6571
- tooltip: locale => locale.toolbar.codeBlock(),
6620
+ icon: icons.get('video'),
6621
+ tooltip: locale => locale.toolbar.video(),
6572
6622
  onClick: (editor, value) => {
6573
6623
  editor.command.execute(value);
6574
6624
  },
@@ -6591,9 +6641,7 @@ const toolbarItems = [
6591
6641
  type: 'dropdown',
6592
6642
  downIcon: icons.get('down'),
6593
6643
  icon: icons.get('list'),
6594
- defaultValue: '',
6595
6644
  tooltip: locale => locale.toolbar.list(),
6596
- width: 'auto',
6597
6645
  menuType: 'list',
6598
6646
  menuItems: listMenuItems,
6599
6647
  onSelect: (editor, value) => {
@@ -6605,9 +6653,7 @@ const toolbarItems = [
6605
6653
  type: 'dropdown',
6606
6654
  downIcon: icons.get('down'),
6607
6655
  icon: icons.get('alignLeft'),
6608
- defaultValue: '',
6609
6656
  tooltip: locale => locale.toolbar.align(),
6610
- width: 'auto',
6611
6657
  menuType: 'list',
6612
6658
  menuItems: alignMenuItems,
6613
6659
  onSelect: (editor, value) => {
@@ -6619,9 +6665,7 @@ const toolbarItems = [
6619
6665
  type: 'dropdown',
6620
6666
  downIcon: icons.get('down'),
6621
6667
  icon: icons.get('increaseIndent'),
6622
- defaultValue: '',
6623
6668
  tooltip: locale => locale.toolbar.indent(),
6624
- width: 'auto',
6625
6669
  menuType: 'list',
6626
6670
  menuItems: indentMenuItems,
6627
6671
  onSelect: (editor, value) => {
@@ -6658,9 +6702,7 @@ const toolbarItems = [
6658
6702
  name: 'moreStyle',
6659
6703
  type: 'dropdown',
6660
6704
  icon: icons.get('more'),
6661
- defaultValue: '',
6662
6705
  tooltip: locale => locale.toolbar.moreStyle(),
6663
- width: 'auto',
6664
6706
  menuType: 'list',
6665
6707
  menuItems: moreStyleMenuItems,
6666
6708
  selectedValues: appliedItems => {
@@ -6686,9 +6728,9 @@ const toolbarItems = [
6686
6728
  accentIcon: icons.get('fontColorAccent'),
6687
6729
  defaultValue: '#f5222d',
6688
6730
  tooltip: locale => locale.toolbar.fontColor(),
6689
- width: 'auto',
6690
6731
  menuType: 'color',
6691
6732
  menuItems: colorMenuItems,
6733
+ menuWidth: '296px',
6692
6734
  onSelect: (editor, value) => {
6693
6735
  editor.command.execute('fontColor', value);
6694
6736
  },
@@ -6701,9 +6743,9 @@ const toolbarItems = [
6701
6743
  accentIcon: icons.get('highlightAccent'),
6702
6744
  defaultValue: '#fadb14',
6703
6745
  tooltip: locale => locale.toolbar.highlight(),
6704
- width: 'auto',
6705
6746
  menuType: 'color',
6706
6747
  menuItems: colorMenuItems,
6748
+ menuWidth: '296px',
6707
6749
  onSelect: (editor, value) => {
6708
6750
  editor.command.execute('highlight', value);
6709
6751
  },
@@ -6726,64 +6768,6 @@ const toolbarItems = [
6726
6768
  },
6727
6769
  ];
6728
6770
 
6729
- function uploadFile(config) {
6730
- const { editor, name, file, onError, onSuccess } = config;
6731
- const { requestMethod, requestAction, requestTypes } = editor.config[name];
6732
- if (requestTypes.indexOf(file.type) < 0) {
6733
- if (onError) {
6734
- onError(`File '${file.name}' is not allowed for uploading.`);
6735
- }
6736
- throw new Error(`Cannot upload file '${file.name}' because its type '${file.type}' is not found in ['${requestTypes.join('\', \'')}'].`);
6737
- }
6738
- const box = editor.selection.insertBox(name, {
6739
- url: URL.createObjectURL(file),
6740
- status: 'uploading',
6741
- name: file.name,
6742
- size: file.size,
6743
- type: file.type,
6744
- lastModified: file.lastModified,
6745
- });
6746
- const xhr = request({
6747
- onProgress: e => {
6748
- const percentNode = box.node.find('.lake-percent');
6749
- const percent = Math.round(e.percent);
6750
- percentNode.text(`${percent < 100 ? percent : 99} %`);
6751
- },
6752
- onError: (error, body) => {
6753
- debug(error.toString(), body);
6754
- box.updateValue('status', 'error');
6755
- box.render();
6756
- if (onError) {
6757
- onError(error.toString());
6758
- }
6759
- },
6760
- onSuccess: body => {
6761
- if (!body.url) {
6762
- box.updateValue('status', 'error');
6763
- box.render();
6764
- if (onError) {
6765
- onError('Cannot find the url field.');
6766
- }
6767
- return;
6768
- }
6769
- box.updateValue({
6770
- status: 'done',
6771
- url: body.url,
6772
- });
6773
- box.render();
6774
- editor.history.save();
6775
- if (onSuccess) {
6776
- onSuccess();
6777
- }
6778
- },
6779
- file,
6780
- action: requestAction,
6781
- method: requestMethod,
6782
- });
6783
- box.setData('xhr', xhr);
6784
- return box;
6785
- }
6786
-
6787
6771
  const defaultItems = [
6788
6772
  'undo',
6789
6773
  'redo',
@@ -6806,9 +6790,9 @@ const defaultItems = [
6806
6790
  'hr',
6807
6791
  ];
6808
6792
  const toolbarItemMap = new Map();
6809
- toolbarItems.forEach(item => {
6793
+ for (const item of toolbarItems) {
6810
6794
  toolbarItemMap.set(item.name, item);
6811
- });
6795
+ }
6812
6796
  class Toolbar {
6813
6797
  constructor(config) {
6814
6798
  this.placement = 'top';
@@ -6853,6 +6837,7 @@ class Toolbar {
6853
6837
  width: item.width,
6854
6838
  menuType: item.menuType,
6855
6839
  menuItems: item.menuItems,
6840
+ menuWidth: item.menuWidth,
6856
6841
  tabIndex: -1,
6857
6842
  placement: this.placement === 'top' ? 'bottom' : 'top',
6858
6843
  onSelect: value => {
@@ -6954,7 +6939,7 @@ class Toolbar {
6954
6939
  Dropdown.setValue(dropdownNode, selectedValues);
6955
6940
  const textNode = dropdownNode.find('.lake-dropdown-text');
6956
6941
  if (textNode.length > 0) {
6957
- const key = selectedValues[0] || item.defaultValue;
6942
+ const key = selectedValues[0] || item.defaultValue || '';
6958
6943
  const menuMap = this.allMenuMap.get(item.name);
6959
6944
  const text = (_a = (menuMap && menuMap.get(key))) !== null && _a !== void 0 ? _a : key;
6960
6945
  textNode.text(text);
@@ -6966,36 +6951,35 @@ class Toolbar {
6966
6951
  render(editor) {
6967
6952
  this.root.empty();
6968
6953
  this.root.append(this.container);
6969
- this.items.forEach(name => {
6954
+ for (const name of this.items) {
6970
6955
  if (name === '|') {
6971
6956
  this.appendDivider();
6972
- return;
6973
- }
6974
- let item;
6975
- if (typeof name === 'string') {
6976
- item = toolbarItemMap.get(name);
6977
- if (!item) {
6978
- return;
6979
- }
6980
6957
  }
6981
6958
  else {
6982
- item = name;
6983
- }
6984
- if (item.type === 'button') {
6985
- this.buttonItemList.push(item);
6986
- this.appendButton(editor, item);
6987
- return;
6988
- }
6989
- if (item.type === 'dropdown') {
6990
- this.allMenuMap.set(item.name, Dropdown.getMenuMap(item.menuItems, editor.locale));
6991
- this.dropdownItemList.push(item);
6992
- this.appendDropdown(editor, item);
6993
- return;
6994
- }
6995
- if (item.type === 'upload') {
6996
- this.appendUpload(editor, item);
6959
+ let item;
6960
+ if (typeof name === 'string') {
6961
+ item = toolbarItemMap.get(name);
6962
+ if (!item) {
6963
+ throw new Error(`ToolbarItem "${name}" has not been defined yet.`);
6964
+ }
6965
+ }
6966
+ else {
6967
+ item = name;
6968
+ }
6969
+ if (item.type === 'button') {
6970
+ this.buttonItemList.push(item);
6971
+ this.appendButton(editor, item);
6972
+ }
6973
+ else if (item.type === 'dropdown') {
6974
+ this.allMenuMap.set(item.name, Dropdown.getMenuMap(item.menuItems, editor.locale));
6975
+ this.dropdownItemList.push(item);
6976
+ this.appendDropdown(editor, item);
6977
+ }
6978
+ else if (item.type === 'upload') {
6979
+ this.appendUpload(editor, item);
6980
+ }
6997
6981
  }
6998
- });
6982
+ }
6999
6983
  }
7000
6984
  }
7001
6985
 
@@ -7007,247 +6991,15 @@ const hrBox = {
7007
6991
  if (!editor) {
7008
6992
  return;
7009
6993
  }
7010
- const hrNode = query('<div class="lake-hr"><hr /></div>');
7011
- box.getContainer().append(hrNode);
7012
- hrNode.on('click', () => {
6994
+ const rootNode = query('<div class="lake-hr"><hr /></div>');
6995
+ box.getContainer().append(rootNode);
6996
+ rootNode.on('click', () => {
7013
6997
  editor.selection.selectBox(box);
7014
6998
  });
7015
6999
  },
7016
7000
  html: () => '<hr />',
7017
7001
  };
7018
7002
 
7019
- class BoxResizer {
7020
- constructor(config) {
7021
- this.config = config;
7022
- this.root = config.root;
7023
- this.box = config.box;
7024
- }
7025
- bindEvents(pointerNode) {
7026
- const box = this.box;
7027
- const boxContainer = box.getContainer();
7028
- const resizerNode = pointerNode.closest('.lake-resizer');
7029
- const infoNode = resizerNode.find('.lake-resizer-info');
7030
- const isPlus = pointerNode.attr('class').indexOf('-right') >= 0;
7031
- const initialWidth = boxContainer.width();
7032
- const initialHeight = boxContainer.height();
7033
- const rate = initialHeight / initialWidth;
7034
- let clientX = 0;
7035
- let width = 0;
7036
- // resizing box
7037
- const pointermoveListener = (event) => {
7038
- const pointerEvent = event;
7039
- const diffX = pointerEvent.clientX - clientX;
7040
- const newWidth = Math.round(isPlus ? width + diffX : width - diffX);
7041
- const newHeight = Math.round(rate * newWidth);
7042
- infoNode.text(`${newWidth} x ${newHeight}`);
7043
- boxContainer.css({
7044
- width: `${newWidth}px`,
7045
- height: `${newHeight}px`,
7046
- });
7047
- if (this.config.onResize) {
7048
- this.config.onResize(newWidth, newHeight);
7049
- }
7050
- };
7051
- // start resizing
7052
- const pointerdownListener = (event) => {
7053
- const pointerEvent = event;
7054
- const pointerNativeNode = pointerNode.get(0);
7055
- // The capture will be implicitly released after a pointerup or pointercancel event.
7056
- // https://developer.mozilla.org/en-US/docs/Web/API/Element/setPointerCapture
7057
- pointerNativeNode.setPointerCapture(pointerEvent.pointerId);
7058
- clientX = pointerEvent.clientX;
7059
- width = boxContainer.width();
7060
- infoNode.show();
7061
- pointerNode.on('pointermove', pointermoveListener);
7062
- };
7063
- // stop resizing
7064
- const pointerupListner = () => {
7065
- pointerNode.off('pointermove');
7066
- infoNode.hide();
7067
- width = box.getContainer().width();
7068
- const height = Math.round(rate * width);
7069
- this.config.onStop(width, height);
7070
- };
7071
- // cancel resizing
7072
- const pointercancelListner = () => {
7073
- pointerNode.off('pointermove');
7074
- infoNode.hide();
7075
- };
7076
- pointerNode.on('pointerdown', pointerdownListener);
7077
- pointerNode.on('pointerup', pointerupListner);
7078
- pointerNode.on('pointercancel', pointercancelListner);
7079
- }
7080
- render() {
7081
- const { width, height } = this.config;
7082
- const resizerNode = query(safeTemplate `
7083
- <div class="lake-resizer">
7084
- <div class="lake-resizer-top-left"></div>
7085
- <div class="lake-resizer-top-right"></div>
7086
- <div class="lake-resizer-bottom-left"></div>
7087
- <div class="lake-resizer-bottom-right"></div>
7088
- <div class="lake-resizer-info">${width} x ${height}</div>
7089
- </div>
7090
- `);
7091
- this.bindEvents(resizerNode.find('.lake-resizer-top-left'));
7092
- this.bindEvents(resizerNode.find('.lake-resizer-top-right'));
7093
- this.bindEvents(resizerNode.find('.lake-resizer-bottom-left'));
7094
- this.bindEvents(resizerNode.find('.lake-resizer-bottom-right'));
7095
- this.root.append(resizerNode);
7096
- }
7097
- }
7098
-
7099
- function getVideoId(url) {
7100
- const result = /\w+$/i.exec(url || '');
7101
- return result ? result[0] : '';
7102
- }
7103
- function getInputValue(videoNode, name) {
7104
- const inputElement = videoNode.find(`input[name="${name}"]`);
7105
- const nativeInputElement = inputElement.get(0);
7106
- return nativeInputElement.value;
7107
- }
7108
- function appendButtonGroup(box) {
7109
- const editor = box.getEditor();
7110
- if (!editor) {
7111
- return;
7112
- }
7113
- const boxContainer = box.getContainer();
7114
- const videoNode = boxContainer.find('.lake-video');
7115
- const buttonGroupNode = query(safeTemplate `
7116
- <div class="lake-button-group">
7117
- <button type="button" tabindex="-1" class="lake-button-remove" title="${editor.locale.video.remove()}"></button>
7118
- </div>
7119
- `);
7120
- const removeButton = buttonGroupNode.find('.lake-button-remove');
7121
- const removeIcon = icons.get('remove');
7122
- if (removeIcon) {
7123
- removeButton.append(removeIcon);
7124
- }
7125
- buttonGroupNode.find('.lake-button-remove').on('click', event => {
7126
- event.stopPropagation();
7127
- editor.selection.removeBox(box);
7128
- editor.history.save();
7129
- });
7130
- videoNode.append(buttonGroupNode);
7131
- }
7132
- function showVideo(box) {
7133
- const editor = box.getEditor();
7134
- if (!editor) {
7135
- return;
7136
- }
7137
- const boxContainer = box.getContainer();
7138
- const value = box.value;
7139
- const width = value.width || 560;
7140
- const height = value.height || 315;
7141
- boxContainer.css({
7142
- width: `${width}px`,
7143
- height: `${height}px`,
7144
- });
7145
- const videoId = getVideoId(value.url);
7146
- if (videoId === '') {
7147
- throw new Error(`Invalid link: ${value.url}`);
7148
- }
7149
- // YouTube URL: https://www.youtube.com/watch?v=5sMBhDv4sik
7150
- // The script for embedding YouTube:
7151
- // <iframe width="560" height="315" src="https://www.youtube.com/embed/5sMBhDv4sik" title="YouTube video player"
7152
- // frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
7153
- // referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
7154
- const iframeNode = query(safeTemplate `
7155
- <iframe width="100%" height="${height}" src="https://www.youtube.com/embed/${videoId}" title="YouTube video player"
7156
- frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
7157
- referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
7158
- `);
7159
- const videoNode = boxContainer.find('.lake-video');
7160
- if (!editor.readonly) {
7161
- iframeNode.on('load', () => {
7162
- appendButtonGroup(box);
7163
- new BoxResizer({
7164
- root: videoNode,
7165
- box,
7166
- width,
7167
- height,
7168
- onResize: (newWidth, newHeight) => {
7169
- iframeNode.attr({
7170
- height: newHeight.toString(),
7171
- });
7172
- },
7173
- onStop: (newWidth, newHeight) => {
7174
- box.updateValue({
7175
- width: newWidth,
7176
- height: newHeight,
7177
- });
7178
- editor.history.save();
7179
- },
7180
- }).render();
7181
- });
7182
- }
7183
- videoNode.append(iframeNode);
7184
- }
7185
- const videoBox = {
7186
- type: 'inline',
7187
- name: 'video',
7188
- render: box => {
7189
- const editor = box.getEditor();
7190
- if (!editor) {
7191
- return;
7192
- }
7193
- const locale = editor.locale;
7194
- const value = box.value;
7195
- const boxContainer = box.getContainer();
7196
- const videoNode = query('<div class="lake-video" />');
7197
- boxContainer.empty();
7198
- boxContainer.css({
7199
- width: '',
7200
- height: '',
7201
- });
7202
- boxContainer.append(videoNode);
7203
- if (!value.url) {
7204
- if (editor.readonly) {
7205
- box.node.hide();
7206
- return;
7207
- }
7208
- const formNode = query(safeTemplate `
7209
- <div class="lake-video-form">
7210
- <div class="lake-row lake-desc-row">${locale.video.description()}</div>
7211
- <div class="lake-row">${locale.video.url()}</div>
7212
- <div class="lake-row">
7213
- <input type="text" name="url" placeholder="https://www.youtube.com/watch?v=..." />
7214
- </div>
7215
- <div class="lake-row lake-button-row"></div>
7216
- </div>
7217
- `);
7218
- const button = new Button({
7219
- root: formNode.find('.lake-button-row'),
7220
- name: 'embed',
7221
- type: 'primary',
7222
- text: locale.video.embed(),
7223
- onClick: () => {
7224
- const url = getInputValue(formNode, 'url');
7225
- if (url.indexOf('https://www.youtube.com/') < 0 || getVideoId(url) === '') {
7226
- editor.config.onMessage('error', locale.video.urlError());
7227
- return;
7228
- }
7229
- box.updateValue('url', url);
7230
- editor.history.save();
7231
- formNode.remove();
7232
- showVideo(box);
7233
- },
7234
- });
7235
- formNode.find('input[name="url"]').on('keydown', createKeybindingsHandler({
7236
- 'Enter': event => {
7237
- event.preventDefault();
7238
- button.node.emit('click');
7239
- },
7240
- }));
7241
- button.render();
7242
- videoNode.append(formNode);
7243
- appendButtonGroup(box);
7244
- }
7245
- else {
7246
- showVideo(box);
7247
- }
7248
- },
7249
- };
7250
-
7251
7003
  const config = {
7252
7004
  comment: '#57606a',
7253
7005
  name: '#444d56',
@@ -7334,12 +7086,12 @@ const codeBlockBox = {
7334
7086
  if (!editor) {
7335
7087
  return;
7336
7088
  }
7337
- const codeBlockNode = query('<div class="lake-code-block" />');
7089
+ const rootNode = query('<div class="lake-code-block" />');
7338
7090
  const container = box.getContainer();
7339
7091
  container.css('width', `${editor.container.innerWidth() - 2}px`);
7340
7092
  container.empty();
7341
- container.append(codeBlockNode);
7342
- const codeBlockNativeNode = codeBlockNode.get(0);
7093
+ container.append(rootNode);
7094
+ const codeBlockNativeNode = rootNode.get(0);
7343
7095
  if (!codeBlockNativeNode) {
7344
7096
  return;
7345
7097
  }
@@ -7350,12 +7102,12 @@ const codeBlockBox = {
7350
7102
  box.node.hide();
7351
7103
  return;
7352
7104
  }
7353
- codeBlockNode.addClass('lake-code-block-error');
7354
- codeBlockNode.text(`
7105
+ rootNode.addClass('lake-code-block-error');
7106
+ rootNode.text(`
7355
7107
  The code cannot be displayed because window.LakeCodeMirror is not found.
7356
7108
  Please check if the "lake-codemirror" library is added to this page.
7357
7109
  `.trim());
7358
- codeBlockNode.on('click', () => {
7110
+ rootNode.on('click', () => {
7359
7111
  editor.selection.selectBox(box);
7360
7112
  });
7361
7113
  return;
@@ -7405,14 +7157,13 @@ const codeBlockBox = {
7405
7157
  updateListener,
7406
7158
  ],
7407
7159
  });
7408
- codeBlockNode.find('[contenteditable="true"]').attr('tabindex', '-1');
7160
+ rootNode.find('[contenteditable="true"]').attr('tabindex', '-1');
7409
7161
  const dropdown = new Dropdown({
7410
- root: codeBlockNode,
7162
+ root: rootNode,
7411
7163
  name: 'langType',
7412
7164
  downIcon: icons.get('down'),
7413
7165
  defaultValue: langItem ? boxValue.lang : codeBlockConfig.defaultLang,
7414
7166
  tooltip: editor.locale.codeBlock.langType(),
7415
- width: 'auto',
7416
7167
  menuType: 'list',
7417
7168
  menuItems: langItems.map((item) => ({
7418
7169
  value: item.value,
@@ -7430,11 +7181,16 @@ const codeBlockBox = {
7430
7181
  },
7431
7182
  });
7432
7183
  dropdown.render();
7433
- box.setData('codeEditor', codeEditor);
7434
7184
  const resizeListener = () => {
7435
7185
  container.css('width', `${editor.container.innerWidth() - 2}px`);
7436
7186
  };
7437
7187
  editor.event.on('resize', resizeListener);
7188
+ rootNode.on('click', () => {
7189
+ if (codeEditor.hasFocus) {
7190
+ return;
7191
+ }
7192
+ codeEditor.focus();
7193
+ });
7438
7194
  box.event.on('beforeunmount', () => {
7439
7195
  codeEditor.destroy();
7440
7196
  editor.event.off('resize', resizeListener);
@@ -7475,6 +7231,86 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
7475
7231
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
7476
7232
  };
7477
7233
 
7234
+ class BoxResizer {
7235
+ constructor(config) {
7236
+ this.config = config;
7237
+ this.root = config.root;
7238
+ this.box = config.box;
7239
+ }
7240
+ bindEvents(pointerNode) {
7241
+ const box = this.box;
7242
+ const boxContainer = box.getContainer();
7243
+ const resizerNode = pointerNode.closest('.lake-resizer');
7244
+ const infoNode = resizerNode.find('.lake-resizer-info');
7245
+ const isPlus = pointerNode.attr('class').indexOf('-right') >= 0;
7246
+ const initialWidth = boxContainer.width();
7247
+ const initialHeight = boxContainer.height();
7248
+ const rate = initialHeight / initialWidth;
7249
+ let clientX = 0;
7250
+ let width = 0;
7251
+ // resizing box
7252
+ const pointermoveListener = (event) => {
7253
+ const pointerEvent = event;
7254
+ const diffX = pointerEvent.clientX - clientX;
7255
+ const newWidth = Math.round(isPlus ? width + diffX : width - diffX);
7256
+ const newHeight = Math.round(rate * newWidth);
7257
+ infoNode.text(`${newWidth} x ${newHeight}`);
7258
+ boxContainer.css({
7259
+ width: `${newWidth}px`,
7260
+ height: `${newHeight}px`,
7261
+ });
7262
+ if (this.config.onResize) {
7263
+ this.config.onResize(newWidth, newHeight);
7264
+ }
7265
+ };
7266
+ // start resizing
7267
+ const pointerdownListener = (event) => {
7268
+ const pointerEvent = event;
7269
+ const pointerNativeNode = pointerNode.get(0);
7270
+ // The capture will be implicitly released after a pointerup or pointercancel event.
7271
+ // https://developer.mozilla.org/en-US/docs/Web/API/Element/setPointerCapture
7272
+ pointerNativeNode.setPointerCapture(pointerEvent.pointerId);
7273
+ clientX = pointerEvent.clientX;
7274
+ width = boxContainer.width();
7275
+ infoNode.show();
7276
+ pointerNode.on('pointermove', pointermoveListener);
7277
+ };
7278
+ // stop resizing
7279
+ const pointerupListner = () => {
7280
+ pointerNode.off('pointermove');
7281
+ infoNode.hide();
7282
+ width = box.getContainer().width();
7283
+ const height = Math.round(rate * width);
7284
+ this.config.onStop(width, height);
7285
+ };
7286
+ // cancel resizing
7287
+ const pointercancelListner = () => {
7288
+ pointerNode.off('pointermove');
7289
+ infoNode.hide();
7290
+ };
7291
+ pointerNode.on('pointerdown', pointerdownListener);
7292
+ pointerNode.on('pointerup', pointerupListner);
7293
+ pointerNode.on('pointercancel', pointercancelListner);
7294
+ }
7295
+ render() {
7296
+ const { width, height } = this.config;
7297
+ const resizerNode = query(safeTemplate `
7298
+ <div class="lake-resizer">
7299
+ <div class="lake-resizer-top-left"></div>
7300
+ <div class="lake-resizer-top-right"></div>
7301
+ <div class="lake-resizer-bottom-left"></div>
7302
+ <div class="lake-resizer-bottom-right"></div>
7303
+ <div class="lake-resizer-info">${width} x ${height}</div>
7304
+ </div>
7305
+ `);
7306
+ this.bindEvents(resizerNode.find('.lake-resizer-top-left'));
7307
+ this.bindEvents(resizerNode.find('.lake-resizer-top-right'));
7308
+ this.bindEvents(resizerNode.find('.lake-resizer-bottom-left'));
7309
+ this.bindEvents(resizerNode.find('.lake-resizer-bottom-right'));
7310
+ this.root.append(resizerNode);
7311
+ }
7312
+ }
7313
+
7478
7314
  // Loads an image and get its width and height.
7479
7315
  function getImageInfo(url) {
7480
7316
  return __awaiter(this, void 0, void 0, function* () {
@@ -7612,7 +7448,7 @@ function openFullScreen(box) {
7612
7448
  lightbox.loadAndOpen(currentIndex);
7613
7449
  }
7614
7450
  // Displays error icon and filename.
7615
- function renderError(imageNode, box) {
7451
+ function renderError(rootNode, box) {
7616
7452
  return __awaiter(this, void 0, void 0, function* () {
7617
7453
  const editor = box.getEditor();
7618
7454
  if (!editor) {
@@ -7643,12 +7479,12 @@ function renderError(imageNode, box) {
7643
7479
  if (imageIcon) {
7644
7480
  errorNode.find('.lake-error-icon').append(imageIcon);
7645
7481
  }
7646
- imageNode.append(buttonGroupNode);
7647
- imageNode.append(errorNode);
7482
+ rootNode.append(buttonGroupNode);
7483
+ rootNode.append(errorNode);
7648
7484
  });
7649
7485
  }
7650
7486
  // Displays an image with uplaoding progress.
7651
- function renderUploading(imageNode, box) {
7487
+ function renderUploading(rootNode, box) {
7652
7488
  return __awaiter(this, void 0, void 0, function* () {
7653
7489
  const editor = box.getEditor();
7654
7490
  if (!editor) {
@@ -7657,7 +7493,7 @@ function renderUploading(imageNode, box) {
7657
7493
  const value = box.value;
7658
7494
  const imageInfo = yield getImageInfo(value.url);
7659
7495
  if (!imageInfo.width || !imageInfo.height) {
7660
- yield renderError(imageNode, box);
7496
+ yield renderError(rootNode, box);
7661
7497
  return;
7662
7498
  }
7663
7499
  const maxWidth = editor.container.innerWidth() - 2;
@@ -7702,13 +7538,13 @@ function renderUploading(imageNode, box) {
7702
7538
  draggable: 'false',
7703
7539
  alt: value.name,
7704
7540
  });
7705
- imageNode.append(buttonGroupNode);
7706
- imageNode.append(progressNode);
7707
- imageNode.append(imgNode);
7541
+ rootNode.append(buttonGroupNode);
7542
+ rootNode.append(progressNode);
7543
+ rootNode.append(imgNode);
7708
7544
  });
7709
7545
  }
7710
7546
  // Displays an image that can be previewed or removed.
7711
- function renderDone(imageNode, box) {
7547
+ function renderDone(rootNode, box) {
7712
7548
  return __awaiter(this, void 0, void 0, function* () {
7713
7549
  const editor = box.getEditor();
7714
7550
  if (!editor) {
@@ -7721,7 +7557,7 @@ function renderDone(imageNode, box) {
7721
7557
  return;
7722
7558
  }
7723
7559
  if (!imageInfo.width || !imageInfo.height) {
7724
- yield renderError(imageNode, box);
7560
+ yield renderError(rootNode, box);
7725
7561
  return;
7726
7562
  }
7727
7563
  let width = value.width;
@@ -7764,9 +7600,9 @@ function renderDone(imageNode, box) {
7764
7600
  draggable: 'false',
7765
7601
  alt: value.name,
7766
7602
  });
7767
- imageNode.append(buttonGroupNode);
7603
+ rootNode.append(buttonGroupNode);
7768
7604
  new BoxResizer({
7769
- root: imageNode,
7605
+ root: rootNode,
7770
7606
  box,
7771
7607
  width,
7772
7608
  height,
@@ -7778,7 +7614,7 @@ function renderDone(imageNode, box) {
7778
7614
  editor.history.save();
7779
7615
  },
7780
7616
  }).render();
7781
- imageNode.append(imgNode);
7617
+ rootNode.append(imgNode);
7782
7618
  });
7783
7619
  }
7784
7620
  const imageBox = {
@@ -7819,45 +7655,193 @@ const imageBox = {
7819
7655
  if (value.status === 'loading') {
7820
7656
  return;
7821
7657
  }
7822
- const imageNode = query('<div class="lake-image" />');
7823
- imageNode.addClass(`lake-image-${value.status}`);
7658
+ const rootNode = query('<div class="lake-image" />');
7659
+ rootNode.addClass(`lake-image-${value.status}`);
7824
7660
  let promise;
7825
7661
  if (value.status === 'uploading') {
7826
- promise = renderUploading(imageNode, box);
7662
+ promise = renderUploading(rootNode, box);
7827
7663
  }
7828
7664
  else if (value.status === 'error') {
7829
- promise = renderError(imageNode, box);
7665
+ promise = renderError(rootNode, box);
7830
7666
  }
7831
7667
  else {
7832
- promise = renderDone(imageNode, box);
7668
+ promise = renderDone(rootNode, box);
7833
7669
  }
7834
7670
  promise.then(() => {
7835
7671
  container.empty();
7836
- container.append(imageNode);
7837
- imageNode.find('.lake-button-view').on('click', () => openFullScreen(box));
7672
+ container.append(rootNode);
7673
+ rootNode.find('.lake-button-view').on('click', () => openFullScreen(box));
7838
7674
  if (editor.readonly) {
7839
- imageNode.find('.lake-button-remove').hide();
7675
+ rootNode.find('.lake-button-remove').hide();
7840
7676
  }
7841
7677
  else {
7842
- imageNode.find('.lake-button-remove').on('click', event => {
7678
+ rootNode.find('.lake-button-remove').on('click', event => {
7843
7679
  event.stopPropagation();
7844
- const xhr = box.getData('xhr');
7845
- if (xhr) {
7846
- xhr.abort();
7847
- }
7848
7680
  editor.selection.removeBox(box);
7849
7681
  editor.history.save();
7850
7682
  });
7851
7683
  }
7852
7684
  box.event.emit('render');
7853
7685
  });
7854
- imageNode.on('click', () => {
7686
+ rootNode.on('click', () => {
7855
7687
  editor.selection.selectBox(box);
7856
7688
  });
7857
7689
  },
7858
7690
  html: box => {
7859
- const value = box.node.attr('value');
7860
- return safeTemplate `<img src="${box.value.url}" data-lake-value="${value}" />`;
7691
+ const rawValue = box.node.attr('value');
7692
+ return safeTemplate `<img src="${box.value.url}" data-lake-value="${rawValue}" />`;
7693
+ },
7694
+ };
7695
+
7696
+ function getVideoId(url) {
7697
+ const result = /\w+$/i.exec(url || '');
7698
+ return result ? result[0] : '';
7699
+ }
7700
+ function getInputValue(videoNode, name) {
7701
+ const inputElement = videoNode.find(`input[name="${name}"]`);
7702
+ const nativeInputElement = inputElement.get(0);
7703
+ return nativeInputElement.value;
7704
+ }
7705
+ function appendButtonGroup(box) {
7706
+ const editor = box.getEditor();
7707
+ if (!editor) {
7708
+ return;
7709
+ }
7710
+ const boxContainer = box.getContainer();
7711
+ const videoNode = boxContainer.find('.lake-video');
7712
+ const buttonGroupNode = query(safeTemplate `
7713
+ <div class="lake-button-group">
7714
+ <button type="button" tabindex="-1" class="lake-button-remove" title="${editor.locale.video.remove()}"></button>
7715
+ </div>
7716
+ `);
7717
+ const removeButton = buttonGroupNode.find('.lake-button-remove');
7718
+ const removeIcon = icons.get('remove');
7719
+ if (removeIcon) {
7720
+ removeButton.append(removeIcon);
7721
+ }
7722
+ buttonGroupNode.find('.lake-button-remove').on('click', event => {
7723
+ event.stopPropagation();
7724
+ editor.selection.removeBox(box);
7725
+ editor.history.save();
7726
+ });
7727
+ videoNode.append(buttonGroupNode);
7728
+ }
7729
+ function showVideo(box) {
7730
+ const editor = box.getEditor();
7731
+ if (!editor) {
7732
+ return;
7733
+ }
7734
+ const boxContainer = box.getContainer();
7735
+ const value = box.value;
7736
+ const width = value.width || 560;
7737
+ const height = value.height || 315;
7738
+ boxContainer.css({
7739
+ width: `${width}px`,
7740
+ height: `${height}px`,
7741
+ });
7742
+ const videoId = getVideoId(value.url);
7743
+ if (videoId === '') {
7744
+ throw new Error(`Invalid link: ${value.url}`);
7745
+ }
7746
+ // YouTube URL: https://www.youtube.com/watch?v=5sMBhDv4sik
7747
+ // The script for embedding YouTube:
7748
+ // <iframe width="560" height="315" src="https://www.youtube.com/embed/5sMBhDv4sik" title="YouTube video player"
7749
+ // frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
7750
+ // referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
7751
+ const iframeNode = query(safeTemplate `
7752
+ <iframe width="100%" height="${height}" src="https://www.youtube.com/embed/${videoId}" title="YouTube video player"
7753
+ frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
7754
+ referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
7755
+ `);
7756
+ const rootNode = boxContainer.find('.lake-video');
7757
+ if (!editor.readonly) {
7758
+ iframeNode.on('load', () => {
7759
+ appendButtonGroup(box);
7760
+ new BoxResizer({
7761
+ root: rootNode,
7762
+ box,
7763
+ width,
7764
+ height,
7765
+ onResize: (newWidth, newHeight) => {
7766
+ iframeNode.attr({
7767
+ height: newHeight.toString(),
7768
+ });
7769
+ },
7770
+ onStop: (newWidth, newHeight) => {
7771
+ box.updateValue({
7772
+ width: newWidth,
7773
+ height: newHeight,
7774
+ });
7775
+ editor.history.save();
7776
+ },
7777
+ }).render();
7778
+ });
7779
+ }
7780
+ rootNode.append(iframeNode);
7781
+ }
7782
+ const videoBox = {
7783
+ type: 'inline',
7784
+ name: 'video',
7785
+ render: box => {
7786
+ const editor = box.getEditor();
7787
+ if (!editor) {
7788
+ return;
7789
+ }
7790
+ const locale = editor.locale;
7791
+ const value = box.value;
7792
+ const boxContainer = box.getContainer();
7793
+ const rootNode = query('<div class="lake-video" />');
7794
+ boxContainer.empty();
7795
+ boxContainer.css({
7796
+ width: '',
7797
+ height: '',
7798
+ });
7799
+ boxContainer.append(rootNode);
7800
+ if (!value.url) {
7801
+ if (editor.readonly) {
7802
+ box.node.hide();
7803
+ return;
7804
+ }
7805
+ const formNode = query(safeTemplate `
7806
+ <div class="lake-video-form">
7807
+ <div class="lake-row lake-desc-row">${locale.video.description()}</div>
7808
+ <div class="lake-row">${locale.video.url()}</div>
7809
+ <div class="lake-row">
7810
+ <input type="text" name="url" placeholder="https://www.youtube.com/watch?v=..." />
7811
+ </div>
7812
+ <div class="lake-row lake-button-row"></div>
7813
+ </div>
7814
+ `);
7815
+ const button = new Button({
7816
+ root: formNode.find('.lake-button-row'),
7817
+ name: 'embed',
7818
+ type: 'primary',
7819
+ text: locale.video.embed(),
7820
+ onClick: () => {
7821
+ const url = getInputValue(formNode, 'url');
7822
+ if (url.indexOf('https://www.youtube.com/') < 0 || getVideoId(url) === '') {
7823
+ editor.config.onMessage('error', locale.video.urlError());
7824
+ return;
7825
+ }
7826
+ box.updateValue('url', url);
7827
+ editor.history.save();
7828
+ formNode.remove();
7829
+ showVideo(box);
7830
+ },
7831
+ });
7832
+ formNode.find('input[name="url"]').on('keydown', createKeybindingsHandler({
7833
+ 'Enter': event => {
7834
+ event.preventDefault();
7835
+ button.node.emit('click');
7836
+ },
7837
+ }));
7838
+ button.render();
7839
+ rootNode.append(formNode);
7840
+ appendButtonGroup(box);
7841
+ }
7842
+ else {
7843
+ showVideo(box);
7844
+ }
7861
7845
  },
7862
7846
  };
7863
7847
 
@@ -7886,7 +7870,7 @@ const boxToolbarItems = [
7886
7870
  },
7887
7871
  },
7888
7872
  ];
7889
- function appendContent(fileNode, box) {
7873
+ function appendContent(rootNode, box) {
7890
7874
  return __awaiter(this, void 0, void 0, function* () {
7891
7875
  const editor = box.getEditor();
7892
7876
  if (!editor) {
@@ -7919,7 +7903,7 @@ function appendContent(fileNode, box) {
7919
7903
  typeNode.append(fileIcon);
7920
7904
  }
7921
7905
  }
7922
- fileNode.append(infoNode);
7906
+ rootNode.append(infoNode);
7923
7907
  });
7924
7908
  }
7925
7909
  const fileBox = {
@@ -7936,26 +7920,45 @@ const fileBox = {
7936
7920
  return;
7937
7921
  }
7938
7922
  const container = box.getContainer();
7939
- const fileNode = query('<div class="lake-file" />');
7940
- fileNode.addClass(`lake-file-${value.status}`);
7941
- appendContent(fileNode, box);
7923
+ const rootNode = query('<div class="lake-file" />');
7924
+ rootNode.addClass(`lake-file-${value.status}`);
7925
+ appendContent(rootNode, box);
7942
7926
  container.empty();
7943
- container.append(fileNode);
7927
+ container.append(rootNode);
7944
7928
  if (!editor.readonly) {
7945
- fileNode.on('click', () => {
7929
+ rootNode.on('click', () => {
7946
7930
  editor.selection.selectBox(box);
7947
7931
  });
7948
7932
  const items = value.status === 'done' ? boxToolbarItems : boxToolbarItems.filter(item => item.name === 'remove');
7949
7933
  box.setToolbar(items);
7950
7934
  }
7951
7935
  else {
7952
- fileNode.on('click', () => {
7936
+ rootNode.on('click', () => {
7953
7937
  window.open(value.url);
7954
7938
  });
7955
7939
  }
7956
7940
  },
7957
7941
  };
7958
7942
 
7943
+ const emojiBox = {
7944
+ type: 'inline',
7945
+ name: 'emoji',
7946
+ render: box => {
7947
+ const editor = box.getEditor();
7948
+ if (!editor) {
7949
+ return;
7950
+ }
7951
+ const value = box.value;
7952
+ const rootNode = query(safeTemplate `
7953
+ <div class="lake-emoji"><img src="${value.url}" title="${value.title}" /></div>
7954
+ `);
7955
+ box.getContainer().append(rootNode);
7956
+ rootNode.on('click', () => {
7957
+ editor.selection.selectBox(box);
7958
+ });
7959
+ },
7960
+ };
7961
+
7959
7962
  var copy = (editor) => {
7960
7963
  editor.event.on('copy', event => {
7961
7964
  const range = editor.selection.range;
@@ -9249,21 +9252,6 @@ var hr = (editor) => {
9249
9252
  });
9250
9253
  };
9251
9254
 
9252
- var video = (editor) => {
9253
- if (editor.readonly) {
9254
- return;
9255
- }
9256
- editor.command.add('video', {
9257
- execute: (value) => {
9258
- const box = editor.selection.insertBox('video', value);
9259
- editor.history.save();
9260
- if (box) {
9261
- box.getContainer().find('input[name="url"]').focus();
9262
- }
9263
- },
9264
- });
9265
- };
9266
-
9267
9255
  const langList = [
9268
9256
  'text',
9269
9257
  'c',
@@ -9299,8 +9287,7 @@ var codeBlock = (editor) => {
9299
9287
  execute: (value) => {
9300
9288
  const box = editor.selection.insertBox('codeBlock', value);
9301
9289
  editor.history.save();
9302
- const codeEditor = box.getData('codeEditor');
9303
- codeEditor.focus();
9290
+ box.getContainer().find('.lake-code-block').emit('click');
9304
9291
  },
9305
9292
  });
9306
9293
  };
@@ -9339,6 +9326,21 @@ var image = (editor) => {
9339
9326
  });
9340
9327
  };
9341
9328
 
9329
+ var video = (editor) => {
9330
+ if (editor.readonly) {
9331
+ return;
9332
+ }
9333
+ editor.command.add('video', {
9334
+ execute: (value) => {
9335
+ const box = editor.selection.insertBox('video', value);
9336
+ editor.history.save();
9337
+ if (box) {
9338
+ box.getContainer().find('input[name="url"]').focus();
9339
+ }
9340
+ },
9341
+ });
9342
+ };
9343
+
9342
9344
  var file = (editor) => {
9343
9345
  editor.setPluginConfig('file', {
9344
9346
  requestMethod: 'POST',
@@ -9372,6 +9374,18 @@ var file = (editor) => {
9372
9374
  });
9373
9375
  };
9374
9376
 
9377
+ var emoji = (editor) => {
9378
+ if (editor.readonly) {
9379
+ return;
9380
+ }
9381
+ editor.command.add('emoji', {
9382
+ execute: (value) => {
9383
+ editor.selection.insertBox('emoji', value);
9384
+ editor.history.save();
9385
+ },
9386
+ });
9387
+ };
9388
+
9375
9389
  const headingTypeMap = new Map([
9376
9390
  ['#', 'h1'],
9377
9391
  ['##', 'h2'],
@@ -9714,7 +9728,7 @@ function splitBlock(editor, block) {
9714
9728
  block.find('li').attr('value', 'false');
9715
9729
  }
9716
9730
  }
9717
- function addBlockOrSplitBlockForBox(editor) {
9731
+ function addOrSplitBlockForBox(editor) {
9718
9732
  const range = editor.selection.range;
9719
9733
  const boxNode = range.startNode.closest('lake-box');
9720
9734
  const block = boxNode.closestBlock();
@@ -9758,7 +9772,7 @@ var enterKey = (editor) => {
9758
9772
  event.preventDefault();
9759
9773
  editor.fixContent();
9760
9774
  if (range.isBox) {
9761
- addBlockOrSplitBlockForBox(editor);
9775
+ addOrSplitBlockForBox(editor);
9762
9776
  editor.history.save();
9763
9777
  return;
9764
9778
  }
@@ -9767,7 +9781,7 @@ var enterKey = (editor) => {
9767
9781
  return;
9768
9782
  }
9769
9783
  if (range.isBox) {
9770
- addBlockOrSplitBlockForBox(editor);
9784
+ addOrSplitBlockForBox(editor);
9771
9785
  editor.history.save();
9772
9786
  return;
9773
9787
  }
@@ -9793,7 +9807,9 @@ function addLineBreak(editor) {
9793
9807
  const prevNode = range.getPrevNode();
9794
9808
  const endText = range.getEndText();
9795
9809
  if (prevNode.name !== 'br' && endText === '') {
9796
- editor.selection.insertContents('<br /><br />');
9810
+ const fragment = new Fragment();
9811
+ fragment.append('<br /><br />');
9812
+ editor.selection.insertFragment(fragment);
9797
9813
  editor.history.save();
9798
9814
  return;
9799
9815
  }
@@ -10142,13 +10158,14 @@ var tabKey = (editor) => {
10142
10158
  }
10143
10159
  event.preventDefault();
10144
10160
  const blocks = editor.selection.range.getBlocks();
10145
- blocks.forEach(block => {
10161
+ for (const block of blocks) {
10146
10162
  if (block.name !== 'p' || block.css('text-indent') === '2em') {
10147
10163
  setBlockIndent(block, 'increase');
10148
- return;
10149
10164
  }
10150
- block.css('text-indent', '2em');
10151
- });
10165
+ else {
10166
+ block.css('text-indent', '2em');
10167
+ }
10168
+ }
10152
10169
  editor.history.save();
10153
10170
  });
10154
10171
  };
@@ -10299,10 +10316,11 @@ var escapeKey = (editor) => {
10299
10316
  };
10300
10317
 
10301
10318
  Editor.box.add(hrBox);
10302
- Editor.box.add(videoBox);
10303
10319
  Editor.box.add(codeBlockBox);
10304
10320
  Editor.box.add(imageBox);
10321
+ Editor.box.add(videoBox);
10305
10322
  Editor.box.add(fileBox);
10323
+ Editor.box.add(emojiBox);
10306
10324
  Editor.plugin.add(copy);
10307
10325
  Editor.plugin.add(cut);
10308
10326
  Editor.plugin.add(paste);
@@ -10330,10 +10348,11 @@ Editor.plugin.add(removeFormat);
10330
10348
  Editor.plugin.add(formatPainter);
10331
10349
  Editor.plugin.add(link);
10332
10350
  Editor.plugin.add(hr);
10333
- Editor.plugin.add(video);
10334
10351
  Editor.plugin.add(codeBlock);
10335
10352
  Editor.plugin.add(image);
10353
+ Editor.plugin.add(video);
10336
10354
  Editor.plugin.add(file);
10355
+ Editor.plugin.add(emoji);
10337
10356
  Editor.plugin.add(markdown);
10338
10357
  Editor.plugin.add(enterKey);
10339
10358
  Editor.plugin.add(shiftEnterKey);
@@ -10343,5 +10362,5 @@ Editor.plugin.add(tabKey);
10343
10362
  Editor.plugin.add(arrowKeys);
10344
10363
  Editor.plugin.add(escapeKey);
10345
10364
 
10346
- 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 };
10365
+ export { Box, Button, Dropdown, Editor, Fragment, HTMLParser, Nodes, Range, TextParser, Toolbar, index as Utils, addMark, deleteContents, fixList, icons, insertBookmark, insertBox, insertFragment, insertLink, insertNode, removeBox, removeMark, setBlocks, splitBlock$1 as splitBlock, splitMarks, toBookmark };
10347
10366
  //# sourceMappingURL=lake.js.map