lakelib 0.1.7 → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lake.css +114 -10
- package/dist/lake.min.js +30 -15
- package/dist/lake.min.js.map +1 -1
- package/lib/lake.css +114 -10
- package/lib/lake.js +1005 -292
- package/lib/lake.js.map +1 -1
- package/lib/types/boxes/file.d.ts +2 -0
- package/lib/types/css/index.d.ts +3 -0
- package/lib/types/editor.d.ts +9 -1
- package/lib/types/i18n/en-US/index.d.ts +5 -0
- package/lib/types/i18n/ja/index.d.ts +5 -0
- package/lib/types/i18n/ko/index.d.ts +5 -0
- package/lib/types/i18n/types.d.ts +40 -12
- package/lib/types/i18n/zh-CN/index.d.ts +5 -0
- package/lib/types/managers/box-manager.d.ts +3 -5
- package/lib/types/managers/selection.d.ts +3 -3
- package/lib/types/models/nodes.d.ts +1 -0
- package/lib/types/models/range.d.ts +1 -0
- package/lib/types/plugins/drop.d.ts +3 -0
- package/lib/types/plugins/file.d.ts +3 -0
- package/lib/types/types/box-toolbar.d.ts +21 -0
- package/lib/types/ui/box-toolbar.d.ts +31 -0
- package/lib/types/ui/upload.d.ts +3 -2
- package/lib/types/utils/file-size.d.ts +1 -0
- package/lib/types/utils/get-box.d.ts +4 -0
- package/lib/types/utils/index.d.ts +3 -0
- package/lib/types/utils/node-and-view.d.ts +9 -0
- package/package.json +1 -1
package/lib/lake.js
CHANGED
|
@@ -37,8 +37,12 @@ var checkCircle = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"32\" height
|
|
|
37
37
|
|
|
38
38
|
var warningCircle = "<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,216Zm-8-80V80a8,8,0,0,1,16,0v56a8,8,0,0,1-16,0Zm20,36a12,12,0,1,1-12-12A12,12,0,0,1,140,172Z\"></path></svg>";
|
|
39
39
|
|
|
40
|
+
var file$1 = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"32\" height=\"32\" fill=\"#000000\" viewBox=\"0 0 256 256\"><path d=\"M213.66,82.34l-56-56A8,8,0,0,0,152,24H56A16,16,0,0,0,40,40V216a16,16,0,0,0,16,16H200a16,16,0,0,0,16-16V88A8,8,0,0,0,213.66,82.34ZM160,51.31,188.69,80H160ZM200,216H56V40h88V88a8,8,0,0,0,8,8h48V216Z\"></path></svg>";
|
|
41
|
+
|
|
40
42
|
var open = "<svg width=\"24\" height=\"24\" fill=\"none\" viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M6.25 4.5A1.75 1.75 0 0 0 4.5 6.25v11.5c0 .966.783 1.75 1.75 1.75h11.5a1.75 1.75 0 0 0 1.75-1.75v-4a.75.75 0 0 1 1.5 0v4A3.25 3.25 0 0 1 17.75 21H6.25A3.25 3.25 0 0 1 3 17.75V6.25A3.25 3.25 0 0 1 6.25 3h4a.75.75 0 0 1 0 1.5h-4ZM13 3.75a.75.75 0 0 1 .75-.75h6.5a.75.75 0 0 1 .75.75v6.5a.75.75 0 0 1-1.5 0V5.56l-5.22 5.22a.75.75 0 0 1-1.06-1.06l5.22-5.22h-4.69a.75.75 0 0 1-.75-.75Z\" fill=\"#000000\"/></svg>";
|
|
41
43
|
|
|
44
|
+
var download = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"32\" height=\"32\" fill=\"#000000\" viewBox=\"0 0 256 256\"><path d=\"M224,144v64a8,8,0,0,1-8,8H40a8,8,0,0,1-8-8V144a8,8,0,0,1,16,0v56H208V144a8,8,0,0,1,16,0Zm-101.66,5.66a8,8,0,0,0,11.32,0l40-40a8,8,0,0,0-11.32-11.32L136,124.69V32a8,8,0,0,0-16,0v92.69L93.66,98.34a8,8,0,0,0-11.32,11.32Z\"></path></svg>";
|
|
45
|
+
|
|
42
46
|
var copy$1 = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"32\" height=\"32\" fill=\"#000000\" viewBox=\"0 0 256 256\"><path d=\"M216,32H88a8,8,0,0,0-8,8V80H40a8,8,0,0,0-8,8V216a8,8,0,0,0,8,8H168a8,8,0,0,0,8-8V176h40a8,8,0,0,0,8-8V40A8,8,0,0,0,216,32ZM160,208H48V96H160Zm48-48H176V88a8,8,0,0,0-8-8H96V48H208Z\"></path></svg>";
|
|
43
47
|
|
|
44
48
|
var remove = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"32\" height=\"32\" fill=\"#000000\" viewBox=\"0 0 256 256\"><path d=\"M216,48H176V40a24,24,0,0,0-24-24H104A24,24,0,0,0,80,40v8H40a8,8,0,0,0,0,16h8V208a16,16,0,0,0,16,16H192a16,16,0,0,0,16-16V64h8a8,8,0,0,0,0-16ZM96,40a8,8,0,0,1,8-8h48a8,8,0,0,1,8,8v8H96Zm96,168H64V64H192ZM112,104v64a8,8,0,0,1-16,0V104a8,8,0,0,1,16,0Zm48,0v64a8,8,0,0,1-16,0V104a8,8,0,0,1,16,0Z\"></path></svg>";
|
|
@@ -133,6 +137,8 @@ var hr$1 = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"32\" height=\"32\"
|
|
|
133
137
|
|
|
134
138
|
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>";
|
|
135
139
|
|
|
140
|
+
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>";
|
|
141
|
+
|
|
136
142
|
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>";
|
|
137
143
|
|
|
138
144
|
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>";
|
|
@@ -160,7 +166,9 @@ const icons = new Map([
|
|
|
160
166
|
['check', check],
|
|
161
167
|
['checkCircle', checkCircle],
|
|
162
168
|
['warningCircle', warningCircle],
|
|
169
|
+
['file', file$1],
|
|
163
170
|
['open', open],
|
|
171
|
+
['download', download],
|
|
164
172
|
['copy', copy$1],
|
|
165
173
|
['remove', remove],
|
|
166
174
|
['maximize', maximize],
|
|
@@ -208,6 +216,7 @@ const icons = new Map([
|
|
|
208
216
|
['unlink', unlink],
|
|
209
217
|
['hr', hr$1],
|
|
210
218
|
['image', image$1],
|
|
219
|
+
['attachment', attachment],
|
|
211
220
|
['codeBlock', codeBlock$1],
|
|
212
221
|
['table', table],
|
|
213
222
|
]);
|
|
@@ -324,12 +333,29 @@ function denormalizeValue(value) {
|
|
|
324
333
|
// Mac: mod+Z returns ⌘+Z
|
|
325
334
|
// Windows / Linux: mod+Z returns Ctrl+Z
|
|
326
335
|
function modifierText(value, userAgent) {
|
|
336
|
+
// for generating i18n files
|
|
337
|
+
if (typeof window === 'undefined') {
|
|
338
|
+
return value;
|
|
339
|
+
}
|
|
327
340
|
userAgent = userAgent !== null && userAgent !== void 0 ? userAgent : navigator.userAgent;
|
|
328
341
|
const isMac = userAgent.indexOf('Mac OS X') >= 0;
|
|
329
342
|
const modText = isMac ? '⌘' : 'Ctrl';
|
|
330
343
|
return value.replace(/(^|\+|\s)mod(\+|\s|$)/g, `$1${modText}$2`);
|
|
331
344
|
}
|
|
332
345
|
|
|
346
|
+
// Returns a human-readable file size string from a number.
|
|
347
|
+
function fileSize(size) {
|
|
348
|
+
const units = ['KB', 'MB', 'GB'];
|
|
349
|
+
let i = 0;
|
|
350
|
+
size /= 1024;
|
|
351
|
+
while (size > 1024 && i < 2) {
|
|
352
|
+
size /= 1024;
|
|
353
|
+
i++;
|
|
354
|
+
}
|
|
355
|
+
const sizeString = size > 0 ? Math.max(size, 0.1).toFixed(1) : 0;
|
|
356
|
+
return `${sizeString} ${units[i]}`;
|
|
357
|
+
}
|
|
358
|
+
|
|
333
359
|
// Returns a property value of all CSS properties of an element
|
|
334
360
|
function getCSS(element, propertyName) {
|
|
335
361
|
const camelPropertyName = camelCase(propertyName);
|
|
@@ -446,7 +472,7 @@ function debug(...data) {
|
|
|
446
472
|
}
|
|
447
473
|
}
|
|
448
474
|
|
|
449
|
-
//
|
|
475
|
+
// A key-value object for storing all events.
|
|
450
476
|
// value is an array which include types and listeners.
|
|
451
477
|
const eventData = {};
|
|
452
478
|
let lastNodeId = 0;
|
|
@@ -733,6 +759,17 @@ class Nodes {
|
|
|
733
759
|
closestContainer() {
|
|
734
760
|
return this.closest('div[contenteditable="true"]');
|
|
735
761
|
}
|
|
762
|
+
// Traverses the first node and its parents until it finds an element which can scroll.
|
|
763
|
+
closestScroller() {
|
|
764
|
+
let parent = this.eq(0);
|
|
765
|
+
while (parent.length > 0 && parent.isElement) {
|
|
766
|
+
if (['scroll', 'auto'].indexOf(parent.computedCSS('overflow-y')) >= 0) {
|
|
767
|
+
return parent;
|
|
768
|
+
}
|
|
769
|
+
parent = parent.parent();
|
|
770
|
+
}
|
|
771
|
+
return new Nodes();
|
|
772
|
+
}
|
|
736
773
|
// Returns the parent of the first node.
|
|
737
774
|
parent() {
|
|
738
775
|
const node = this.get(0);
|
|
@@ -1299,6 +1336,59 @@ class Range {
|
|
|
1299
1336
|
get() {
|
|
1300
1337
|
return this.range;
|
|
1301
1338
|
}
|
|
1339
|
+
// Returns the size and position of the range.
|
|
1340
|
+
getRect() {
|
|
1341
|
+
const range = this.clone();
|
|
1342
|
+
let rect;
|
|
1343
|
+
let x;
|
|
1344
|
+
let width;
|
|
1345
|
+
if (range.isCollapsed) {
|
|
1346
|
+
let reference = 'left';
|
|
1347
|
+
if (range.startNode.isElement) {
|
|
1348
|
+
const children = range.startNode.children();
|
|
1349
|
+
if (children.length === 0) {
|
|
1350
|
+
range.selectNode(range.startNode);
|
|
1351
|
+
}
|
|
1352
|
+
else if (range.startOffset < children.length) {
|
|
1353
|
+
range.setEnd(range.startNode, range.startOffset + 1);
|
|
1354
|
+
}
|
|
1355
|
+
else {
|
|
1356
|
+
range.setStart(range.startNode, range.startOffset - 1);
|
|
1357
|
+
reference = 'right';
|
|
1358
|
+
}
|
|
1359
|
+
}
|
|
1360
|
+
else {
|
|
1361
|
+
const text = range.startNode.text();
|
|
1362
|
+
if (range.startOffset < text.length) {
|
|
1363
|
+
range.setEnd(range.startNode, range.startOffset + 1);
|
|
1364
|
+
}
|
|
1365
|
+
else {
|
|
1366
|
+
range.setStart(range.startNode, range.startOffset - 1);
|
|
1367
|
+
reference = 'right';
|
|
1368
|
+
}
|
|
1369
|
+
}
|
|
1370
|
+
rect = range.get().getBoundingClientRect();
|
|
1371
|
+
if (reference === 'left') {
|
|
1372
|
+
x = rect.x;
|
|
1373
|
+
}
|
|
1374
|
+
else {
|
|
1375
|
+
x = rect.right;
|
|
1376
|
+
}
|
|
1377
|
+
width = 1;
|
|
1378
|
+
}
|
|
1379
|
+
else {
|
|
1380
|
+
rect = range.get().getBoundingClientRect();
|
|
1381
|
+
x = rect.x;
|
|
1382
|
+
width = rect.width;
|
|
1383
|
+
}
|
|
1384
|
+
const height = rect.height;
|
|
1385
|
+
return DOMRect.fromRect({
|
|
1386
|
+
x,
|
|
1387
|
+
y: rect.y,
|
|
1388
|
+
width: width > 0 ? width : 1,
|
|
1389
|
+
height: height > 0 ? height : 1,
|
|
1390
|
+
});
|
|
1391
|
+
}
|
|
1302
1392
|
// Returns −1 if the point is before the range, 0 if the point is in the range, and 1 if the point is after the range.
|
|
1303
1393
|
comparePoint(node, offset) {
|
|
1304
1394
|
return this.range.comparePoint(node.get(0), offset);
|
|
@@ -2614,192 +2704,54 @@ function morph(node, otherNode, config = {}) {
|
|
|
2614
2704
|
morphNormalizedContent(node.get(0), normalizedContent, ctx);
|
|
2615
2705
|
}
|
|
2616
2706
|
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
if (!text) {
|
|
2653
|
-
return text;
|
|
2654
|
-
}
|
|
2655
|
-
try {
|
|
2656
|
-
return JSON.parse(text);
|
|
2657
|
-
}
|
|
2658
|
-
catch (e) {
|
|
2659
|
-
return text;
|
|
2660
|
-
}
|
|
2661
|
-
}
|
|
2662
|
-
function request(option) {
|
|
2663
|
-
const xhr = new XMLHttpRequest();
|
|
2664
|
-
if (option.onProgress && xhr.upload) {
|
|
2665
|
-
xhr.upload.onprogress = (e) => {
|
|
2666
|
-
if (e.total > 0) {
|
|
2667
|
-
e.percent = (e.loaded / e.total) * 100;
|
|
2668
|
-
}
|
|
2669
|
-
if (option.onProgress) {
|
|
2670
|
-
option.onProgress(e);
|
|
2671
|
-
}
|
|
2672
|
-
};
|
|
2673
|
-
}
|
|
2674
|
-
const formData = new FormData();
|
|
2675
|
-
const data = option.data || {};
|
|
2676
|
-
Object.keys(data).forEach(key => {
|
|
2677
|
-
const value = data[key];
|
|
2678
|
-
// support key-value array data
|
|
2679
|
-
if (Array.isArray(value)) {
|
|
2680
|
-
value.forEach(item => {
|
|
2681
|
-
// { list: [ 11, 22 ] }
|
|
2682
|
-
// formData.append('list[]', 11);
|
|
2683
|
-
formData.append(`${key}[]`, item);
|
|
2684
|
-
});
|
|
2685
|
-
return;
|
|
2686
|
-
}
|
|
2687
|
-
formData.append(key, value);
|
|
2688
|
-
});
|
|
2689
|
-
const filename = option.filename || 'file';
|
|
2690
|
-
if (option.file instanceof Blob) {
|
|
2691
|
-
formData.append(filename, option.file, option.file.name);
|
|
2692
|
-
}
|
|
2693
|
-
else {
|
|
2694
|
-
formData.append(filename, option.file);
|
|
2695
|
-
}
|
|
2696
|
-
xhr.onerror = (e) => {
|
|
2697
|
-
if (option.onError) {
|
|
2698
|
-
option.onError(e);
|
|
2699
|
-
}
|
|
2700
|
-
};
|
|
2701
|
-
xhr.onload = () => {
|
|
2702
|
-
// allow success when 2xx status
|
|
2703
|
-
// see https://github.com/react-component/upload/issues/34
|
|
2704
|
-
if (xhr.status < 200 || xhr.status >= 300) {
|
|
2705
|
-
if (!option.onError) {
|
|
2706
|
-
return;
|
|
2707
|
-
}
|
|
2708
|
-
return option.onError(getError(option, xhr), getBody(xhr));
|
|
2709
|
-
}
|
|
2710
|
-
if (!option.onSuccess) {
|
|
2711
|
-
return;
|
|
2712
|
-
}
|
|
2713
|
-
return option.onSuccess(getBody(xhr), xhr);
|
|
2707
|
+
// Returns an object that indicates the specified node's position relative to the viewport.
|
|
2708
|
+
function nodeAndView(node) {
|
|
2709
|
+
const nativeNode = node.get(0);
|
|
2710
|
+
const rect = nativeNode.getBoundingClientRect();
|
|
2711
|
+
let left = rect.left;
|
|
2712
|
+
let right = rect.right;
|
|
2713
|
+
let top = rect.top;
|
|
2714
|
+
let bottom = rect.bottom;
|
|
2715
|
+
let viewportWidth = window.innerWidth;
|
|
2716
|
+
let viewportHeight = window.innerHeight;
|
|
2717
|
+
const container = node.closestContainer();
|
|
2718
|
+
if (container.length > 0) {
|
|
2719
|
+
const viewport = container.closestScroller();
|
|
2720
|
+
if (viewport.length > 0) {
|
|
2721
|
+
const containerWrapper = container.parent();
|
|
2722
|
+
if (containerWrapper.length > 0) {
|
|
2723
|
+
const nativeContainerWrapper = containerWrapper.get(0);
|
|
2724
|
+
const offsetLeft = nativeContainerWrapper.offsetLeft - window.scrollX;
|
|
2725
|
+
const offsetTop = nativeContainerWrapper.offsetTop - window.scrollY;
|
|
2726
|
+
left -= offsetLeft;
|
|
2727
|
+
right -= offsetLeft;
|
|
2728
|
+
top -= offsetTop;
|
|
2729
|
+
bottom -= offsetTop;
|
|
2730
|
+
}
|
|
2731
|
+
const nativeViewport = viewport.get(0);
|
|
2732
|
+
const viewportRect = nativeViewport.getBoundingClientRect();
|
|
2733
|
+
viewportWidth = viewportRect.width;
|
|
2734
|
+
viewportHeight = viewportRect.height;
|
|
2735
|
+
}
|
|
2736
|
+
}
|
|
2737
|
+
const position = {
|
|
2738
|
+
left,
|
|
2739
|
+
right: viewportWidth - right,
|
|
2740
|
+
top,
|
|
2741
|
+
bottom: viewportHeight - bottom,
|
|
2714
2742
|
};
|
|
2715
|
-
|
|
2716
|
-
// Has to be after `.open()`. See https://github.com/enyo/dropzone/issues/179
|
|
2717
|
-
if (option.withCredentials && 'withCredentials' in xhr) {
|
|
2718
|
-
xhr.withCredentials = true;
|
|
2719
|
-
}
|
|
2720
|
-
const headers = option.headers || {};
|
|
2721
|
-
// when set headers['X-Requested-With'] = null , can close default XHR header
|
|
2722
|
-
// see https://github.com/react-component/upload/issues/33
|
|
2723
|
-
if (headers['X-Requested-With'] !== null) {
|
|
2724
|
-
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
|
|
2725
|
-
}
|
|
2726
|
-
Object.keys(headers).forEach(h => {
|
|
2727
|
-
if (headers[h] !== null) {
|
|
2728
|
-
xhr.setRequestHeader(h, headers[h]);
|
|
2729
|
-
}
|
|
2730
|
-
});
|
|
2731
|
-
xhr.send(formData);
|
|
2732
|
-
return xhr;
|
|
2743
|
+
return position;
|
|
2733
2744
|
}
|
|
2734
2745
|
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
var index = /*#__PURE__*/Object.freeze({
|
|
2738
|
-
__proto__: null,
|
|
2739
|
-
appendDeepest: appendDeepest,
|
|
2740
|
-
camelCase: camelCase,
|
|
2741
|
-
changeTagName: changeTagName,
|
|
2742
|
-
debug: debug,
|
|
2743
|
-
denormalizeValue: denormalizeValue,
|
|
2744
|
-
encode: encode,
|
|
2745
|
-
fixNumberedList: fixNumberedList,
|
|
2746
|
-
getCSS: getCSS,
|
|
2747
|
-
getDeepest: getDeepest,
|
|
2748
|
-
inString: inString,
|
|
2749
|
-
mergeNodes: mergeNodes,
|
|
2750
|
-
modifierText: modifierText,
|
|
2751
|
-
morph: morph,
|
|
2752
|
-
normalizeValue: normalizeValue,
|
|
2753
|
-
parseStyle: parseStyle,
|
|
2754
|
-
query: query,
|
|
2755
|
-
removeBr: removeBr,
|
|
2756
|
-
removeZWS: removeZWS,
|
|
2757
|
-
request: request,
|
|
2758
|
-
safeTemplate: safeTemplate,
|
|
2759
|
-
setBlockIndent: setBlockIndent,
|
|
2760
|
-
splitNodes: splitNodes,
|
|
2761
|
-
template: template,
|
|
2762
|
-
toHex: toHex,
|
|
2763
|
-
toNodeList: toNodeList,
|
|
2764
|
-
wrapNodeList: wrapNodeList
|
|
2765
|
-
});
|
|
2766
|
-
|
|
2767
|
-
class Fragment {
|
|
2768
|
-
constructor(fragment) {
|
|
2769
|
-
this.fragment = fragment !== null && fragment !== void 0 ? fragment : document.createDocumentFragment();
|
|
2770
|
-
}
|
|
2771
|
-
// Returns the descendants of the fragment which are selected by the specified CSS selector.
|
|
2772
|
-
find(selector) {
|
|
2773
|
-
const nodeList = [];
|
|
2774
|
-
let child = new Nodes(this.fragment.firstChild);
|
|
2775
|
-
while (child.length > 0) {
|
|
2776
|
-
if (child.matches(selector)) {
|
|
2777
|
-
nodeList.push(child.get(0));
|
|
2778
|
-
}
|
|
2779
|
-
else if (child.isElement) {
|
|
2780
|
-
child.find(selector).each(node => {
|
|
2781
|
-
nodeList.push(node);
|
|
2782
|
-
});
|
|
2783
|
-
}
|
|
2784
|
-
child = child.next();
|
|
2785
|
-
}
|
|
2786
|
-
return new Nodes(nodeList);
|
|
2787
|
-
}
|
|
2788
|
-
// Inserts the specified node as the last child.
|
|
2789
|
-
append(node) {
|
|
2790
|
-
node.each(nativeNode => {
|
|
2791
|
-
this.fragment.appendChild(nativeNode);
|
|
2792
|
-
});
|
|
2793
|
-
}
|
|
2794
|
-
}
|
|
2746
|
+
const boxInstances = new Map();
|
|
2795
2747
|
|
|
2796
2748
|
const boxes = new Map();
|
|
2797
2749
|
|
|
2798
2750
|
const editors = new Map();
|
|
2799
2751
|
|
|
2800
|
-
//
|
|
2752
|
+
// A key-value object for storing data about box.
|
|
2801
2753
|
const boxData = {};
|
|
2802
|
-
//
|
|
2754
|
+
// A key-value object for storing all effects.
|
|
2803
2755
|
const effectData = {};
|
|
2804
2756
|
const framework = safeTemplate `
|
|
2805
2757
|
<span class="lake-box-strip"><br /></span>
|
|
@@ -2853,10 +2805,6 @@ class Box {
|
|
|
2853
2805
|
container.off('mouseleave');
|
|
2854
2806
|
container.off('click');
|
|
2855
2807
|
}
|
|
2856
|
-
// fix: should not activate box when clicking box
|
|
2857
|
-
container.on('mousedown', event => {
|
|
2858
|
-
event.preventDefault();
|
|
2859
|
-
});
|
|
2860
2808
|
container.on('mouseenter', () => {
|
|
2861
2809
|
if (container.hasClass('lake-box-selected') ||
|
|
2862
2810
|
container.hasClass('lake-box-focused') ||
|
|
@@ -2872,6 +2820,9 @@ class Box {
|
|
|
2872
2820
|
debug(`Box '${this.name}' (id = ${this.node.id}) value:`);
|
|
2873
2821
|
debug(this.value);
|
|
2874
2822
|
});
|
|
2823
|
+
if (this.type === 'block') {
|
|
2824
|
+
container.attr('draggable', 'true');
|
|
2825
|
+
}
|
|
2875
2826
|
}
|
|
2876
2827
|
// Returns the type of the box.
|
|
2877
2828
|
get type() {
|
|
@@ -2951,6 +2902,7 @@ class Box {
|
|
|
2951
2902
|
}
|
|
2952
2903
|
// Destroys a rendered box.
|
|
2953
2904
|
unmount() {
|
|
2905
|
+
this.event.emit('blur');
|
|
2954
2906
|
for (const cleanup of effectData[this.node.id].cleanup) {
|
|
2955
2907
|
cleanup();
|
|
2956
2908
|
}
|
|
@@ -2974,6 +2926,212 @@ class Box {
|
|
|
2974
2926
|
}
|
|
2975
2927
|
}
|
|
2976
2928
|
|
|
2929
|
+
// Returns an already generated box instance or generates a new instance if it does not exist.
|
|
2930
|
+
function getBox(boxNode) {
|
|
2931
|
+
if (typeof boxNode === 'string') {
|
|
2932
|
+
return new Box(boxNode);
|
|
2933
|
+
}
|
|
2934
|
+
boxNode = query(boxNode);
|
|
2935
|
+
const container = boxNode.closestContainer();
|
|
2936
|
+
if (container.length === 0) {
|
|
2937
|
+
return new Box(boxNode);
|
|
2938
|
+
}
|
|
2939
|
+
let instanceMap = boxInstances.get(container.id);
|
|
2940
|
+
if (!instanceMap) {
|
|
2941
|
+
instanceMap = new Map();
|
|
2942
|
+
boxInstances.set(container.id, instanceMap);
|
|
2943
|
+
}
|
|
2944
|
+
let box = instanceMap.get(boxNode.id);
|
|
2945
|
+
if (box) {
|
|
2946
|
+
return box;
|
|
2947
|
+
}
|
|
2948
|
+
box = new Box(boxNode);
|
|
2949
|
+
instanceMap.set(box.node.id, box);
|
|
2950
|
+
return box;
|
|
2951
|
+
}
|
|
2952
|
+
|
|
2953
|
+
/**
|
|
2954
|
+
The MIT License (MIT)
|
|
2955
|
+
|
|
2956
|
+
Copyright (c) 2016-present react-component
|
|
2957
|
+
|
|
2958
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
2959
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
2960
|
+
in the Software without restriction, including without limitation the rights
|
|
2961
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
2962
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
2963
|
+
furnished to do so, subject to the following conditions:
|
|
2964
|
+
|
|
2965
|
+
The above copyright notice and this permission notice shall be included in
|
|
2966
|
+
all copies or substantial portions of the Software.
|
|
2967
|
+
|
|
2968
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
2969
|
+
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
2970
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
2971
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
2972
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
2973
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
2974
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
2975
|
+
|
|
2976
|
+
Repository: https://github.com/react-component/upload
|
|
2977
|
+
*/
|
|
2978
|
+
function getError(option, xhr) {
|
|
2979
|
+
const msg = `Cannot ${option.method} ${option.action} ${xhr.status}'`;
|
|
2980
|
+
const err = new Error(msg);
|
|
2981
|
+
err.status = xhr.status;
|
|
2982
|
+
err.method = option.method;
|
|
2983
|
+
err.url = option.action;
|
|
2984
|
+
return err;
|
|
2985
|
+
}
|
|
2986
|
+
function getBody(xhr) {
|
|
2987
|
+
const text = xhr.responseText || xhr.response;
|
|
2988
|
+
if (!text) {
|
|
2989
|
+
return text;
|
|
2990
|
+
}
|
|
2991
|
+
try {
|
|
2992
|
+
return JSON.parse(text);
|
|
2993
|
+
}
|
|
2994
|
+
catch (e) {
|
|
2995
|
+
return text;
|
|
2996
|
+
}
|
|
2997
|
+
}
|
|
2998
|
+
function request(option) {
|
|
2999
|
+
const xhr = new XMLHttpRequest();
|
|
3000
|
+
if (option.onProgress && xhr.upload) {
|
|
3001
|
+
xhr.upload.onprogress = (e) => {
|
|
3002
|
+
if (e.total > 0) {
|
|
3003
|
+
e.percent = (e.loaded / e.total) * 100;
|
|
3004
|
+
}
|
|
3005
|
+
if (option.onProgress) {
|
|
3006
|
+
option.onProgress(e);
|
|
3007
|
+
}
|
|
3008
|
+
};
|
|
3009
|
+
}
|
|
3010
|
+
const formData = new FormData();
|
|
3011
|
+
const data = option.data || {};
|
|
3012
|
+
Object.keys(data).forEach(key => {
|
|
3013
|
+
const value = data[key];
|
|
3014
|
+
// support key-value array data
|
|
3015
|
+
if (Array.isArray(value)) {
|
|
3016
|
+
value.forEach(item => {
|
|
3017
|
+
// { list: [ 11, 22 ] }
|
|
3018
|
+
// formData.append('list[]', 11);
|
|
3019
|
+
formData.append(`${key}[]`, item);
|
|
3020
|
+
});
|
|
3021
|
+
return;
|
|
3022
|
+
}
|
|
3023
|
+
formData.append(key, value);
|
|
3024
|
+
});
|
|
3025
|
+
const filename = option.filename || 'file';
|
|
3026
|
+
if (option.file instanceof Blob) {
|
|
3027
|
+
formData.append(filename, option.file, option.file.name);
|
|
3028
|
+
}
|
|
3029
|
+
else {
|
|
3030
|
+
formData.append(filename, option.file);
|
|
3031
|
+
}
|
|
3032
|
+
xhr.onerror = (e) => {
|
|
3033
|
+
if (option.onError) {
|
|
3034
|
+
option.onError(e);
|
|
3035
|
+
}
|
|
3036
|
+
};
|
|
3037
|
+
xhr.onload = () => {
|
|
3038
|
+
// allow success when 2xx status
|
|
3039
|
+
// see https://github.com/react-component/upload/issues/34
|
|
3040
|
+
if (xhr.status < 200 || xhr.status >= 300) {
|
|
3041
|
+
if (!option.onError) {
|
|
3042
|
+
return;
|
|
3043
|
+
}
|
|
3044
|
+
return option.onError(getError(option, xhr), getBody(xhr));
|
|
3045
|
+
}
|
|
3046
|
+
if (!option.onSuccess) {
|
|
3047
|
+
return;
|
|
3048
|
+
}
|
|
3049
|
+
return option.onSuccess(getBody(xhr), xhr);
|
|
3050
|
+
};
|
|
3051
|
+
xhr.open(option.method, option.action, true);
|
|
3052
|
+
// Has to be after `.open()`. See https://github.com/enyo/dropzone/issues/179
|
|
3053
|
+
if (option.withCredentials && 'withCredentials' in xhr) {
|
|
3054
|
+
xhr.withCredentials = true;
|
|
3055
|
+
}
|
|
3056
|
+
const headers = option.headers || {};
|
|
3057
|
+
// when set headers['X-Requested-With'] = null , can close default XHR header
|
|
3058
|
+
// see https://github.com/react-component/upload/issues/33
|
|
3059
|
+
if (headers['X-Requested-With'] !== null) {
|
|
3060
|
+
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
|
|
3061
|
+
}
|
|
3062
|
+
Object.keys(headers).forEach(h => {
|
|
3063
|
+
if (headers[h] !== null) {
|
|
3064
|
+
xhr.setRequestHeader(h, headers[h]);
|
|
3065
|
+
}
|
|
3066
|
+
});
|
|
3067
|
+
xhr.send(formData);
|
|
3068
|
+
return xhr;
|
|
3069
|
+
}
|
|
3070
|
+
|
|
3071
|
+
// String
|
|
3072
|
+
|
|
3073
|
+
var index = /*#__PURE__*/Object.freeze({
|
|
3074
|
+
__proto__: null,
|
|
3075
|
+
appendDeepest: appendDeepest,
|
|
3076
|
+
camelCase: camelCase,
|
|
3077
|
+
changeTagName: changeTagName,
|
|
3078
|
+
debug: debug,
|
|
3079
|
+
denormalizeValue: denormalizeValue,
|
|
3080
|
+
encode: encode,
|
|
3081
|
+
fileSize: fileSize,
|
|
3082
|
+
fixNumberedList: fixNumberedList,
|
|
3083
|
+
getBox: getBox,
|
|
3084
|
+
getCSS: getCSS,
|
|
3085
|
+
getDeepest: getDeepest,
|
|
3086
|
+
inString: inString,
|
|
3087
|
+
mergeNodes: mergeNodes,
|
|
3088
|
+
modifierText: modifierText,
|
|
3089
|
+
morph: morph,
|
|
3090
|
+
nodeAndView: nodeAndView,
|
|
3091
|
+
normalizeValue: normalizeValue,
|
|
3092
|
+
parseStyle: parseStyle,
|
|
3093
|
+
query: query,
|
|
3094
|
+
removeBr: removeBr,
|
|
3095
|
+
removeZWS: removeZWS,
|
|
3096
|
+
request: request,
|
|
3097
|
+
safeTemplate: safeTemplate,
|
|
3098
|
+
setBlockIndent: setBlockIndent,
|
|
3099
|
+
splitNodes: splitNodes,
|
|
3100
|
+
template: template,
|
|
3101
|
+
toHex: toHex,
|
|
3102
|
+
toNodeList: toNodeList,
|
|
3103
|
+
wrapNodeList: wrapNodeList
|
|
3104
|
+
});
|
|
3105
|
+
|
|
3106
|
+
class Fragment {
|
|
3107
|
+
constructor(fragment) {
|
|
3108
|
+
this.fragment = fragment !== null && fragment !== void 0 ? fragment : document.createDocumentFragment();
|
|
3109
|
+
}
|
|
3110
|
+
// Returns the descendants of the fragment which are selected by the specified CSS selector.
|
|
3111
|
+
find(selector) {
|
|
3112
|
+
const nodeList = [];
|
|
3113
|
+
let child = new Nodes(this.fragment.firstChild);
|
|
3114
|
+
while (child.length > 0) {
|
|
3115
|
+
if (child.matches(selector)) {
|
|
3116
|
+
nodeList.push(child.get(0));
|
|
3117
|
+
}
|
|
3118
|
+
else if (child.isElement) {
|
|
3119
|
+
child.find(selector).each(node => {
|
|
3120
|
+
nodeList.push(node);
|
|
3121
|
+
});
|
|
3122
|
+
}
|
|
3123
|
+
child = child.next();
|
|
3124
|
+
}
|
|
3125
|
+
return new Nodes(nodeList);
|
|
3126
|
+
}
|
|
3127
|
+
// Inserts the specified node as the last child.
|
|
3128
|
+
append(node) {
|
|
3129
|
+
node.each(nativeNode => {
|
|
3130
|
+
this.fragment.appendChild(nativeNode);
|
|
3131
|
+
});
|
|
3132
|
+
}
|
|
3133
|
+
}
|
|
3134
|
+
|
|
2977
3135
|
const blockAttributeRules = {
|
|
2978
3136
|
id: /^[\w-]+$/,
|
|
2979
3137
|
class: /^[\w-]+$/,
|
|
@@ -3380,7 +3538,7 @@ function toBookmark(range, bookmark) {
|
|
|
3380
3538
|
}
|
|
3381
3539
|
if (focus.length > 0 && anchor.length === 0) {
|
|
3382
3540
|
if (focus.isBox) {
|
|
3383
|
-
const box =
|
|
3541
|
+
const box = getBox(focus);
|
|
3384
3542
|
if (box.getContainer().length === 0) {
|
|
3385
3543
|
box.render();
|
|
3386
3544
|
}
|
|
@@ -3801,7 +3959,7 @@ function addMark(range, value) {
|
|
|
3801
3959
|
if (range.isCollapsed) {
|
|
3802
3960
|
if (range.isBox) {
|
|
3803
3961
|
const boxNode = range.startNode.closest('lake-box');
|
|
3804
|
-
const box =
|
|
3962
|
+
const box = getBox(boxNode);
|
|
3805
3963
|
if (box.type === 'block') {
|
|
3806
3964
|
const newBlock = query('<p><br /></p>');
|
|
3807
3965
|
if (range.isBoxStart) {
|
|
@@ -4100,6 +4258,7 @@ var enUS = {
|
|
|
4100
4258
|
fontColor: 'Font color',
|
|
4101
4259
|
highlight: 'Highlight',
|
|
4102
4260
|
image: 'Image',
|
|
4261
|
+
file: 'File',
|
|
4103
4262
|
removeColor: 'Remove color',
|
|
4104
4263
|
},
|
|
4105
4264
|
link: {
|
|
@@ -4121,6 +4280,10 @@ var enUS = {
|
|
|
4121
4280
|
zoomOut: 'Zoom out',
|
|
4122
4281
|
zoomIn: 'Zoom in',
|
|
4123
4282
|
},
|
|
4283
|
+
file: {
|
|
4284
|
+
download: 'Download',
|
|
4285
|
+
remove: 'Delete',
|
|
4286
|
+
},
|
|
4124
4287
|
codeBlock: {
|
|
4125
4288
|
langType: 'Select language',
|
|
4126
4289
|
},
|
|
@@ -4170,6 +4333,7 @@ var zhCN = {
|
|
|
4170
4333
|
fontColor: '文字颜色',
|
|
4171
4334
|
highlight: '文字背景',
|
|
4172
4335
|
image: '图片',
|
|
4336
|
+
file: '文件',
|
|
4173
4337
|
removeColor: '默认',
|
|
4174
4338
|
},
|
|
4175
4339
|
link: {
|
|
@@ -4191,6 +4355,10 @@ var zhCN = {
|
|
|
4191
4355
|
zoomOut: '缩小',
|
|
4192
4356
|
zoomIn: '放大',
|
|
4193
4357
|
},
|
|
4358
|
+
file: {
|
|
4359
|
+
download: '下载',
|
|
4360
|
+
remove: '删除',
|
|
4361
|
+
},
|
|
4194
4362
|
codeBlock: {
|
|
4195
4363
|
langType: '选择代码语言',
|
|
4196
4364
|
},
|
|
@@ -4240,6 +4408,7 @@ var ja = {
|
|
|
4240
4408
|
fontColor: '文字色',
|
|
4241
4409
|
highlight: '文字の背景',
|
|
4242
4410
|
image: '画像',
|
|
4411
|
+
file: 'ファイル',
|
|
4243
4412
|
removeColor: 'デフォルト',
|
|
4244
4413
|
},
|
|
4245
4414
|
link: {
|
|
@@ -4261,6 +4430,10 @@ var ja = {
|
|
|
4261
4430
|
zoomOut: '縮小',
|
|
4262
4431
|
zoomIn: '拡大',
|
|
4263
4432
|
},
|
|
4433
|
+
file: {
|
|
4434
|
+
download: 'ダウンロード',
|
|
4435
|
+
remove: '削除',
|
|
4436
|
+
},
|
|
4264
4437
|
codeBlock: {
|
|
4265
4438
|
langType: 'コード言語を選択',
|
|
4266
4439
|
},
|
|
@@ -4310,6 +4483,7 @@ var ko = {
|
|
|
4310
4483
|
fontColor: '글자 색상',
|
|
4311
4484
|
highlight: '글자 배경',
|
|
4312
4485
|
image: '이미지',
|
|
4486
|
+
file: '파일',
|
|
4313
4487
|
removeColor: '기본색',
|
|
4314
4488
|
},
|
|
4315
4489
|
link: {
|
|
@@ -4331,6 +4505,10 @@ var ko = {
|
|
|
4331
4505
|
zoomOut: '축소',
|
|
4332
4506
|
zoomIn: '확대',
|
|
4333
4507
|
},
|
|
4508
|
+
file: {
|
|
4509
|
+
download: '다운로드',
|
|
4510
|
+
remove: '삭제',
|
|
4511
|
+
},
|
|
4334
4512
|
codeBlock: {
|
|
4335
4513
|
langType: '코드언어 선택',
|
|
4336
4514
|
},
|
|
@@ -4613,14 +4791,14 @@ class Dropdown {
|
|
|
4613
4791
|
}
|
|
4614
4792
|
}
|
|
4615
4793
|
|
|
4616
|
-
var version = "0.1.
|
|
4794
|
+
var version = "0.1.9";
|
|
4617
4795
|
|
|
4618
4796
|
// Inserts a box into the specified range.
|
|
4619
4797
|
function insertBox(range, boxName, boxValue) {
|
|
4620
4798
|
if (range.commonAncestor.isOutside) {
|
|
4621
4799
|
return null;
|
|
4622
4800
|
}
|
|
4623
|
-
const box =
|
|
4801
|
+
const box = getBox(boxName);
|
|
4624
4802
|
if (boxValue) {
|
|
4625
4803
|
box.value = boxValue;
|
|
4626
4804
|
}
|
|
@@ -4659,7 +4837,7 @@ function removeBox(range) {
|
|
|
4659
4837
|
if (boxNode.length === 0) {
|
|
4660
4838
|
return null;
|
|
4661
4839
|
}
|
|
4662
|
-
const box =
|
|
4840
|
+
const box = getBox(boxNode);
|
|
4663
4841
|
if (box.type === 'block') {
|
|
4664
4842
|
const paragraph = query('<p><br /></p>');
|
|
4665
4843
|
boxNode.before(paragraph);
|
|
@@ -4763,20 +4941,20 @@ class Selection {
|
|
|
4763
4941
|
return new Range();
|
|
4764
4942
|
}
|
|
4765
4943
|
// Adds the saved range to the native selection.
|
|
4766
|
-
|
|
4944
|
+
sync() {
|
|
4767
4945
|
this.selection.removeAllRanges();
|
|
4768
4946
|
this.selection.addRange(this.range.get());
|
|
4769
4947
|
}
|
|
4770
|
-
//
|
|
4771
|
-
|
|
4948
|
+
// Updates the saved range with the range of the native selection.
|
|
4949
|
+
updateByRange() {
|
|
4772
4950
|
const newRange = this.getRangeFromNativeSelection();
|
|
4773
4951
|
if (this.range.get() === newRange.get()) {
|
|
4774
4952
|
return;
|
|
4775
4953
|
}
|
|
4776
4954
|
this.range = newRange;
|
|
4777
4955
|
}
|
|
4778
|
-
//
|
|
4779
|
-
|
|
4956
|
+
// Updates the saved range with the range represented by the bookmark.
|
|
4957
|
+
updateByBookmark() {
|
|
4780
4958
|
const range = this.range;
|
|
4781
4959
|
const container = this.container;
|
|
4782
4960
|
const boxFocus = container.find('lake-box[focus]');
|
|
@@ -4785,7 +4963,7 @@ class Selection {
|
|
|
4785
4963
|
anchor: new Nodes(),
|
|
4786
4964
|
focus: boxFocus,
|
|
4787
4965
|
});
|
|
4788
|
-
this.
|
|
4966
|
+
this.sync();
|
|
4789
4967
|
return;
|
|
4790
4968
|
}
|
|
4791
4969
|
const anchor = container.find('lake-bookmark[type="anchor"]');
|
|
@@ -4794,7 +4972,7 @@ class Selection {
|
|
|
4794
4972
|
anchor,
|
|
4795
4973
|
focus,
|
|
4796
4974
|
});
|
|
4797
|
-
this.
|
|
4975
|
+
this.sync();
|
|
4798
4976
|
}
|
|
4799
4977
|
getAppliedItems() {
|
|
4800
4978
|
const appliedItems = [];
|
|
@@ -4901,8 +5079,6 @@ class Command {
|
|
|
4901
5079
|
}
|
|
4902
5080
|
}
|
|
4903
5081
|
|
|
4904
|
-
const boxInstances = new Map();
|
|
4905
|
-
|
|
4906
5082
|
// Saves and controls the history of the value of the editor.
|
|
4907
5083
|
// Example:
|
|
4908
5084
|
// before initialization: value: 'a', list: [], index: 0, canUndo: false
|
|
@@ -4980,7 +5156,7 @@ class History {
|
|
|
4980
5156
|
const range = this.selection.range;
|
|
4981
5157
|
const newContainer = this.container.clone(true);
|
|
4982
5158
|
newContainer.find('lake-box').each(nativeNode => {
|
|
4983
|
-
const box =
|
|
5159
|
+
const box = getBox(nativeNode);
|
|
4984
5160
|
box.getContainer().empty();
|
|
4985
5161
|
});
|
|
4986
5162
|
if (range.commonAncestor.isOutside) {
|
|
@@ -5030,7 +5206,7 @@ class History {
|
|
|
5030
5206
|
}
|
|
5031
5207
|
this.index--;
|
|
5032
5208
|
}
|
|
5033
|
-
this.selection.
|
|
5209
|
+
this.selection.updateByBookmark();
|
|
5034
5210
|
debug(`History undone, the last index is ${this.index}`);
|
|
5035
5211
|
}
|
|
5036
5212
|
redo() {
|
|
@@ -5052,7 +5228,7 @@ class History {
|
|
|
5052
5228
|
break;
|
|
5053
5229
|
}
|
|
5054
5230
|
}
|
|
5055
|
-
this.selection.
|
|
5231
|
+
this.selection.updateByBookmark();
|
|
5056
5232
|
debug(`History redone, the last index is ${this.index}`);
|
|
5057
5233
|
}
|
|
5058
5234
|
continue() {
|
|
@@ -5159,17 +5335,17 @@ class BoxManager {
|
|
|
5159
5335
|
getNames() {
|
|
5160
5336
|
return Array.from(boxes.keys());
|
|
5161
5337
|
}
|
|
5162
|
-
getInstances(
|
|
5163
|
-
let instanceMap = boxInstances.get(
|
|
5338
|
+
getInstances(container) {
|
|
5339
|
+
let instanceMap = boxInstances.get(container.id);
|
|
5164
5340
|
if (!instanceMap) {
|
|
5165
5341
|
instanceMap = new Map();
|
|
5166
|
-
boxInstances.set(
|
|
5342
|
+
boxInstances.set(container.id, instanceMap);
|
|
5167
5343
|
return instanceMap;
|
|
5168
5344
|
}
|
|
5169
5345
|
return instanceMap;
|
|
5170
5346
|
}
|
|
5171
|
-
rectifyInstances(
|
|
5172
|
-
const instanceMap = this.getInstances(
|
|
5347
|
+
rectifyInstances(container) {
|
|
5348
|
+
const instanceMap = this.getInstances(container);
|
|
5173
5349
|
for (const box of instanceMap.values()) {
|
|
5174
5350
|
if (!box.node.get(0).isConnected) {
|
|
5175
5351
|
box.unmount();
|
|
@@ -5177,20 +5353,16 @@ class BoxManager {
|
|
|
5177
5353
|
}
|
|
5178
5354
|
}
|
|
5179
5355
|
}
|
|
5180
|
-
|
|
5181
|
-
|
|
5182
|
-
|
|
5183
|
-
|
|
5184
|
-
|
|
5185
|
-
const instanceMap = this.getInstances(editor);
|
|
5186
|
-
this.findAll(editor).each(boxNativeNode => {
|
|
5187
|
-
const boxNode = new Nodes(boxNativeNode);
|
|
5356
|
+
renderAll(container) {
|
|
5357
|
+
this.rectifyInstances(container);
|
|
5358
|
+
const instanceMap = this.getInstances(container);
|
|
5359
|
+
container.find('lake-box').each(boxNativeNode => {
|
|
5360
|
+
const boxNode = query(boxNativeNode);
|
|
5188
5361
|
if (instanceMap.get(boxNode.id)) {
|
|
5189
5362
|
return;
|
|
5190
5363
|
}
|
|
5191
|
-
const box =
|
|
5364
|
+
const box = getBox(boxNode);
|
|
5192
5365
|
box.render();
|
|
5193
|
-
instanceMap.set(box.node.id, box);
|
|
5194
5366
|
});
|
|
5195
5367
|
}
|
|
5196
5368
|
}
|
|
@@ -5218,6 +5390,22 @@ const defaultConfig = {
|
|
|
5218
5390
|
indentWithTab: true,
|
|
5219
5391
|
lang: 'en-US',
|
|
5220
5392
|
minChangeSize: 5,
|
|
5393
|
+
onMessage: (type, message) => {
|
|
5394
|
+
if (type === 'success') {
|
|
5395
|
+
// eslint-disable-next-line no-console
|
|
5396
|
+
console.log(message);
|
|
5397
|
+
return;
|
|
5398
|
+
}
|
|
5399
|
+
if (type === 'warning') {
|
|
5400
|
+
// eslint-disable-next-line no-console
|
|
5401
|
+
console.warn(message);
|
|
5402
|
+
return;
|
|
5403
|
+
}
|
|
5404
|
+
if (type === 'error') {
|
|
5405
|
+
// eslint-disable-next-line no-console
|
|
5406
|
+
console.error(message);
|
|
5407
|
+
}
|
|
5408
|
+
},
|
|
5221
5409
|
};
|
|
5222
5410
|
class Editor {
|
|
5223
5411
|
constructor(config) {
|
|
@@ -5228,20 +5416,41 @@ class Editor {
|
|
|
5228
5416
|
selectedNameMap: new Map(),
|
|
5229
5417
|
selectedValuesMap: new Map(),
|
|
5230
5418
|
};
|
|
5231
|
-
this.isComposing = false;
|
|
5232
|
-
this.event = new EventEmitter();
|
|
5233
|
-
this.box = Editor.box;
|
|
5419
|
+
this.isComposing = false;
|
|
5420
|
+
this.event = new EventEmitter();
|
|
5421
|
+
this.box = Editor.box;
|
|
5422
|
+
this.copyListener = event => {
|
|
5423
|
+
const range = this.selection.range;
|
|
5424
|
+
if (range.commonAncestor.closestContainer().get(0) !== this.container.get(0)) {
|
|
5425
|
+
return;
|
|
5426
|
+
}
|
|
5427
|
+
this.event.emit('copy', event);
|
|
5428
|
+
};
|
|
5429
|
+
this.cutListener = event => {
|
|
5430
|
+
const range = this.selection.range;
|
|
5431
|
+
if (range.commonAncestor.closestContainer().get(0) !== this.container.get(0)) {
|
|
5432
|
+
return;
|
|
5433
|
+
}
|
|
5434
|
+
this.event.emit('cut', event);
|
|
5435
|
+
};
|
|
5436
|
+
this.pasteListener = event => {
|
|
5437
|
+
const range = this.selection.range;
|
|
5438
|
+
if (range.commonAncestor.closestContainer().get(0) !== this.container.get(0)) {
|
|
5439
|
+
return;
|
|
5440
|
+
}
|
|
5441
|
+
this.event.emit('paste', event);
|
|
5442
|
+
};
|
|
5234
5443
|
this.beforeunloadListener = () => {
|
|
5235
5444
|
this.history.save();
|
|
5236
5445
|
};
|
|
5237
5446
|
this.selectionchangeListener = () => {
|
|
5238
|
-
this.selection.
|
|
5447
|
+
this.selection.updateByRange();
|
|
5239
5448
|
this.updateBoxSelectionStyle();
|
|
5240
5449
|
this.emitStateChangeEvent();
|
|
5241
5450
|
};
|
|
5242
5451
|
this.clickListener = event => {
|
|
5243
5452
|
const targetNode = new Nodes(event.target);
|
|
5244
|
-
if (targetNode.closest('.lake-popup').length > 0) {
|
|
5453
|
+
if (!targetNode.get(0).isConnected || targetNode.closest('.lake-popup').length > 0) {
|
|
5245
5454
|
return;
|
|
5246
5455
|
}
|
|
5247
5456
|
this.event.emit('click', targetNode);
|
|
@@ -5257,8 +5466,8 @@ class Editor {
|
|
|
5257
5466
|
const range = this.selection.range;
|
|
5258
5467
|
const clonedRange = range.clone();
|
|
5259
5468
|
clonedRange.adaptBox();
|
|
5260
|
-
this.
|
|
5261
|
-
const box =
|
|
5469
|
+
this.container.find('lake-box').each(boxNativeNode => {
|
|
5470
|
+
const box = getBox(boxNativeNode);
|
|
5262
5471
|
const boxContainer = box.getContainer();
|
|
5263
5472
|
if (boxContainer.length === 0) {
|
|
5264
5473
|
return;
|
|
@@ -5269,6 +5478,7 @@ class Editor {
|
|
|
5269
5478
|
boxContainer.removeClass('lake-box-selected');
|
|
5270
5479
|
boxContainer.removeClass('lake-box-focused');
|
|
5271
5480
|
boxContainer.addClass('lake-box-activated');
|
|
5481
|
+
box.event.emit('focus');
|
|
5272
5482
|
return;
|
|
5273
5483
|
}
|
|
5274
5484
|
}
|
|
@@ -5278,16 +5488,19 @@ class Editor {
|
|
|
5278
5488
|
boxContainer.removeClass('lake-box-hovered');
|
|
5279
5489
|
boxContainer.removeClass('lake-box-selected');
|
|
5280
5490
|
boxContainer.addClass('lake-box-focused');
|
|
5491
|
+
box.event.emit('focus');
|
|
5281
5492
|
}
|
|
5282
5493
|
else {
|
|
5283
5494
|
boxContainer.removeClass('lake-box-focused');
|
|
5284
5495
|
boxContainer.addClass('lake-box-selected');
|
|
5496
|
+
box.event.emit('blur');
|
|
5285
5497
|
}
|
|
5286
5498
|
return;
|
|
5287
5499
|
}
|
|
5288
5500
|
boxContainer.removeClass('lake-box-activated');
|
|
5289
5501
|
boxContainer.removeClass('lake-box-focused');
|
|
5290
5502
|
boxContainer.removeClass('lake-box-selected');
|
|
5503
|
+
box.event.emit('blur');
|
|
5291
5504
|
});
|
|
5292
5505
|
this.event.emit('boxselectionstylechange');
|
|
5293
5506
|
}, 50, {
|
|
@@ -5345,6 +5558,7 @@ class Editor {
|
|
|
5345
5558
|
this.rectifyContent();
|
|
5346
5559
|
this.emitStateChangeEvent();
|
|
5347
5560
|
this.togglePlaceholderClass(value);
|
|
5561
|
+
this.scrollToCaret();
|
|
5348
5562
|
this.event.emit('change', value);
|
|
5349
5563
|
};
|
|
5350
5564
|
if (!config.root) {
|
|
@@ -5391,7 +5605,7 @@ class Editor {
|
|
|
5391
5605
|
const range = selection.range;
|
|
5392
5606
|
const stripNode = range.startNode.closest('.lake-box-strip');
|
|
5393
5607
|
const boxNode = stripNode.closest('lake-box');
|
|
5394
|
-
const box =
|
|
5608
|
+
const box = getBox(boxNode);
|
|
5395
5609
|
if (box.type === 'inline') {
|
|
5396
5610
|
if (range.isBoxStart) {
|
|
5397
5611
|
range.setStartBefore(boxNode);
|
|
@@ -5473,15 +5687,15 @@ class Editor {
|
|
|
5473
5687
|
}
|
|
5474
5688
|
bindHistoryEvents() {
|
|
5475
5689
|
this.history.event.on('undo', value => {
|
|
5476
|
-
this.box.renderAll(this);
|
|
5690
|
+
this.box.renderAll(this.container);
|
|
5477
5691
|
this.emitChangeEvent(value);
|
|
5478
5692
|
});
|
|
5479
5693
|
this.history.event.on('redo', value => {
|
|
5480
|
-
this.box.renderAll(this);
|
|
5694
|
+
this.box.renderAll(this.container);
|
|
5481
5695
|
this.emitChangeEvent(value);
|
|
5482
5696
|
});
|
|
5483
5697
|
this.history.event.on('save', value => {
|
|
5484
|
-
this.box.rectifyInstances(this);
|
|
5698
|
+
this.box.rectifyInstances(this.container);
|
|
5485
5699
|
this.emitChangeEvent(value);
|
|
5486
5700
|
});
|
|
5487
5701
|
}
|
|
@@ -5560,6 +5774,66 @@ class Editor {
|
|
|
5560
5774
|
blur() {
|
|
5561
5775
|
this.container.blur();
|
|
5562
5776
|
}
|
|
5777
|
+
// Scrolls to the caret or the range of the selection.
|
|
5778
|
+
scrollToCaret() {
|
|
5779
|
+
// Creates an artificial caret that is the same size as the caret at the current caret position.
|
|
5780
|
+
const rangeRect = this.selection.range.getRect();
|
|
5781
|
+
const containerRect = this.container.get(0).getBoundingClientRect();
|
|
5782
|
+
const artificialCaret = query('<div class="lake-artificial-caret" />');
|
|
5783
|
+
const left = rangeRect.x - containerRect.x;
|
|
5784
|
+
const top = rangeRect.y - containerRect.y;
|
|
5785
|
+
artificialCaret.css({
|
|
5786
|
+
position: 'absolute',
|
|
5787
|
+
top: `${top}px`,
|
|
5788
|
+
left: `${left}px`,
|
|
5789
|
+
width: `${rangeRect.width}px`,
|
|
5790
|
+
height: `${rangeRect.height}px`,
|
|
5791
|
+
// background: 'red',
|
|
5792
|
+
'z-index': '-1',
|
|
5793
|
+
});
|
|
5794
|
+
this.overlayContainer.find('.lake-artificial-caret').remove();
|
|
5795
|
+
this.overlayContainer.append(artificialCaret);
|
|
5796
|
+
// Scrolls the artificial caret element into the visible area of the browser window
|
|
5797
|
+
// if it's not already within the visible area of the browser window.
|
|
5798
|
+
// If the element is already within the visible area of the browser window, then no scrolling takes place.
|
|
5799
|
+
let scrollX;
|
|
5800
|
+
let scrollY;
|
|
5801
|
+
let viewportWidth;
|
|
5802
|
+
let viewportHeight;
|
|
5803
|
+
const viewport = this.container.closestScroller();
|
|
5804
|
+
if (viewport.length > 0) {
|
|
5805
|
+
const nativeViewport = viewport.get(0);
|
|
5806
|
+
const viewportRect = nativeViewport.getBoundingClientRect();
|
|
5807
|
+
scrollX = nativeViewport.scrollLeft;
|
|
5808
|
+
scrollY = nativeViewport.scrollTop;
|
|
5809
|
+
viewportWidth = viewportRect.width;
|
|
5810
|
+
viewportHeight = viewportRect.height;
|
|
5811
|
+
}
|
|
5812
|
+
else {
|
|
5813
|
+
const nativeContainerWrapper = this.containerWrapper.get(0);
|
|
5814
|
+
scrollX = window.scrollX;
|
|
5815
|
+
scrollY = window.scrollY;
|
|
5816
|
+
viewportWidth = window.innerWidth - nativeContainerWrapper.offsetLeft;
|
|
5817
|
+
viewportHeight = window.innerHeight - nativeContainerWrapper.offsetTop;
|
|
5818
|
+
}
|
|
5819
|
+
let needScroll = false;
|
|
5820
|
+
let alignToTop = true;
|
|
5821
|
+
if (left < scrollX || left > scrollX + viewportWidth) {
|
|
5822
|
+
needScroll = true;
|
|
5823
|
+
}
|
|
5824
|
+
if (top < scrollY) {
|
|
5825
|
+
needScroll = true;
|
|
5826
|
+
alignToTop = true;
|
|
5827
|
+
}
|
|
5828
|
+
else if (top > scrollY + viewportHeight) {
|
|
5829
|
+
needScroll = true;
|
|
5830
|
+
alignToTop = false;
|
|
5831
|
+
}
|
|
5832
|
+
if (needScroll) {
|
|
5833
|
+
artificialCaret.get(0).scrollIntoView(alignToTop);
|
|
5834
|
+
}
|
|
5835
|
+
artificialCaret.remove();
|
|
5836
|
+
}
|
|
5563
5837
|
// Sets the specified HTML string to the editor area.
|
|
5564
5838
|
setValue(value) {
|
|
5565
5839
|
value = normalizeValue(value);
|
|
@@ -5568,8 +5842,8 @@ class Editor {
|
|
|
5568
5842
|
this.container.empty();
|
|
5569
5843
|
this.togglePlaceholderClass(htmlParser.getHTML());
|
|
5570
5844
|
this.container.append(fragment);
|
|
5571
|
-
Editor.box.renderAll(this);
|
|
5572
|
-
this.selection.
|
|
5845
|
+
Editor.box.renderAll(this.container);
|
|
5846
|
+
this.selection.updateByBookmark();
|
|
5573
5847
|
}
|
|
5574
5848
|
// Returns the contents from the editor.
|
|
5575
5849
|
getValue() {
|
|
@@ -5579,21 +5853,35 @@ class Editor {
|
|
|
5579
5853
|
this.selection.toBookmark(bookmark);
|
|
5580
5854
|
return value;
|
|
5581
5855
|
}
|
|
5856
|
+
// Sets the current range to the center position of the box.
|
|
5857
|
+
selectBox(box) {
|
|
5858
|
+
let boxNode = box;
|
|
5859
|
+
if (box instanceof Box) {
|
|
5860
|
+
boxNode = box.node;
|
|
5861
|
+
}
|
|
5862
|
+
else {
|
|
5863
|
+
boxNode = box;
|
|
5864
|
+
}
|
|
5865
|
+
this.selection.range.selectBox(boxNode);
|
|
5866
|
+
}
|
|
5582
5867
|
// Inserts a box into the position of the selection.
|
|
5583
5868
|
insertBox(boxName, boxValue) {
|
|
5584
5869
|
const box = insertBox(this.selection.range, boxName, boxValue);
|
|
5585
5870
|
if (!box) {
|
|
5586
5871
|
throw new Error(`Box '${boxName}' cannot be inserted outside the editor.`);
|
|
5587
5872
|
}
|
|
5588
|
-
const instanceMap = this.box.getInstances(this);
|
|
5873
|
+
const instanceMap = this.box.getInstances(this.container);
|
|
5589
5874
|
instanceMap.set(box.node.id, box);
|
|
5590
5875
|
return box;
|
|
5591
5876
|
}
|
|
5592
5877
|
// Removes the selected box.
|
|
5593
|
-
removeBox() {
|
|
5594
|
-
|
|
5878
|
+
removeBox(box = null) {
|
|
5879
|
+
if (box) {
|
|
5880
|
+
this.selectBox(box);
|
|
5881
|
+
}
|
|
5882
|
+
box = removeBox(this.selection.range);
|
|
5595
5883
|
if (box) {
|
|
5596
|
-
const instanceMap = this.box.getInstances(this);
|
|
5884
|
+
const instanceMap = this.box.getInstances(this.container);
|
|
5597
5885
|
instanceMap.delete(box.node.id);
|
|
5598
5886
|
}
|
|
5599
5887
|
return box;
|
|
@@ -5612,14 +5900,17 @@ class Editor {
|
|
|
5612
5900
|
this.container.append(fragment);
|
|
5613
5901
|
Editor.plugin.loadAll(this);
|
|
5614
5902
|
if (!this.readonly) {
|
|
5615
|
-
this.selection.
|
|
5903
|
+
this.selection.updateByBookmark();
|
|
5616
5904
|
this.history.save();
|
|
5617
5905
|
}
|
|
5618
|
-
Editor.box.renderAll(this);
|
|
5906
|
+
Editor.box.renderAll(this.container);
|
|
5619
5907
|
if (this.toolbar) {
|
|
5620
5908
|
this.toolbar.render(this);
|
|
5621
5909
|
}
|
|
5910
|
+
document.addEventListener('copy', this.copyListener);
|
|
5622
5911
|
if (!this.readonly) {
|
|
5912
|
+
document.addEventListener('cut', this.cutListener);
|
|
5913
|
+
document.addEventListener('paste', this.pasteListener);
|
|
5623
5914
|
window.addEventListener('beforeunload', this.beforeunloadListener);
|
|
5624
5915
|
document.addEventListener('selectionchange', this.selectionchangeListener);
|
|
5625
5916
|
document.addEventListener('click', this.clickListener);
|
|
@@ -5635,7 +5926,10 @@ class Editor {
|
|
|
5635
5926
|
this.history.event.removeAllListeners();
|
|
5636
5927
|
this.root.empty();
|
|
5637
5928
|
this.popupContainer.remove();
|
|
5929
|
+
document.removeEventListener('copy', this.copyListener);
|
|
5638
5930
|
if (!this.readonly) {
|
|
5931
|
+
document.removeEventListener('cut', this.cutListener);
|
|
5932
|
+
document.removeEventListener('paste', this.pasteListener);
|
|
5639
5933
|
window.removeEventListener('beforeunload', this.beforeunloadListener);
|
|
5640
5934
|
document.removeEventListener('selectionchange', this.selectionchangeListener);
|
|
5641
5935
|
document.removeEventListener('click', this.clickListener);
|
|
@@ -6266,15 +6560,26 @@ const toolbarItems = [
|
|
|
6266
6560
|
accept: 'image/*',
|
|
6267
6561
|
multiple: true,
|
|
6268
6562
|
},
|
|
6563
|
+
{
|
|
6564
|
+
name: 'file',
|
|
6565
|
+
type: 'upload',
|
|
6566
|
+
icon: icons.get('attachment'),
|
|
6567
|
+
tooltip: locale => locale.toolbar.file(),
|
|
6568
|
+
accept: '*',
|
|
6569
|
+
multiple: true,
|
|
6570
|
+
},
|
|
6269
6571
|
];
|
|
6270
6572
|
|
|
6271
|
-
function
|
|
6272
|
-
const { editor, file, onError, onSuccess } = config;
|
|
6273
|
-
const { requestMethod, requestAction, requestTypes } = editor.config
|
|
6573
|
+
function uploadFile(config) {
|
|
6574
|
+
const { editor, name, file, onError, onSuccess } = config;
|
|
6575
|
+
const { requestMethod, requestAction, requestTypes } = editor.config[name];
|
|
6274
6576
|
if (requestTypes.indexOf(file.type) < 0) {
|
|
6275
|
-
|
|
6577
|
+
if (onError) {
|
|
6578
|
+
onError(`File '${file.name}' is not allowed for uploading.`);
|
|
6579
|
+
}
|
|
6580
|
+
throw new Error(`Cannot upload file '${file.name}' because its type '${file.type}' is not found in ['${requestTypes.join('\', \'')}'].`);
|
|
6276
6581
|
}
|
|
6277
|
-
const box = editor.insertBox(
|
|
6582
|
+
const box = editor.insertBox(name, {
|
|
6278
6583
|
url: URL.createObjectURL(file),
|
|
6279
6584
|
status: 'uploading',
|
|
6280
6585
|
name: file.name,
|
|
@@ -6293,7 +6598,7 @@ function uploadImage(config) {
|
|
|
6293
6598
|
box.updateValue('status', 'error');
|
|
6294
6599
|
box.render();
|
|
6295
6600
|
if (onError) {
|
|
6296
|
-
onError();
|
|
6601
|
+
onError(error.toString());
|
|
6297
6602
|
}
|
|
6298
6603
|
},
|
|
6299
6604
|
onSuccess: body => {
|
|
@@ -6301,7 +6606,7 @@ function uploadImage(config) {
|
|
|
6301
6606
|
box.updateValue('status', 'error');
|
|
6302
6607
|
box.render();
|
|
6303
6608
|
if (onError) {
|
|
6304
|
-
onError();
|
|
6609
|
+
onError('Cannot find the url field.');
|
|
6305
6610
|
}
|
|
6306
6611
|
return;
|
|
6307
6612
|
}
|
|
@@ -6344,9 +6649,9 @@ const defaultItems = [
|
|
|
6344
6649
|
'blockQuote',
|
|
6345
6650
|
'hr',
|
|
6346
6651
|
];
|
|
6347
|
-
const toolbarItemMap = new Map();
|
|
6652
|
+
const toolbarItemMap$1 = new Map();
|
|
6348
6653
|
toolbarItems.forEach(item => {
|
|
6349
|
-
toolbarItemMap.set(item.name, item);
|
|
6654
|
+
toolbarItemMap$1.set(item.name, item);
|
|
6350
6655
|
});
|
|
6351
6656
|
class Toolbar {
|
|
6352
6657
|
constructor(config) {
|
|
@@ -6433,9 +6738,11 @@ class Toolbar {
|
|
|
6433
6738
|
const target = event.target;
|
|
6434
6739
|
const files = target.files || [];
|
|
6435
6740
|
for (const file of files) {
|
|
6436
|
-
|
|
6741
|
+
uploadFile({
|
|
6437
6742
|
editor,
|
|
6743
|
+
name: item.name,
|
|
6438
6744
|
file,
|
|
6745
|
+
onError: error => editor.config.onMessage('error', error),
|
|
6439
6746
|
});
|
|
6440
6747
|
}
|
|
6441
6748
|
});
|
|
@@ -6510,7 +6817,7 @@ class Toolbar {
|
|
|
6510
6817
|
}
|
|
6511
6818
|
let item;
|
|
6512
6819
|
if (typeof name === 'string') {
|
|
6513
|
-
item = toolbarItemMap.get(name);
|
|
6820
|
+
item = toolbarItemMap$1.get(name);
|
|
6514
6821
|
if (!item) {
|
|
6515
6822
|
return;
|
|
6516
6823
|
}
|
|
@@ -6547,7 +6854,7 @@ const hrBox = {
|
|
|
6547
6854
|
box.useEffect(() => {
|
|
6548
6855
|
const hrNode = box.getContainer().find('.lake-hr');
|
|
6549
6856
|
hrNode.on('click', () => {
|
|
6550
|
-
editor.
|
|
6857
|
+
editor.selectBox(box);
|
|
6551
6858
|
});
|
|
6552
6859
|
});
|
|
6553
6860
|
return '<div class="lake-hr"><hr /></div>';
|
|
@@ -6691,7 +6998,7 @@ function openFullScreen(box) {
|
|
|
6691
6998
|
let currentIndex = 0;
|
|
6692
6999
|
const allImageBox = editor.container.find('lake-box[name="image"]');
|
|
6693
7000
|
allImageBox.each((node, index) => {
|
|
6694
|
-
const imageBox =
|
|
7001
|
+
const imageBox = getBox(node);
|
|
6695
7002
|
const imageValue = imageBox.value;
|
|
6696
7003
|
if (imageValue.status !== 'done') {
|
|
6697
7004
|
return;
|
|
@@ -6764,31 +7071,24 @@ function openFullScreen(box) {
|
|
|
6764
7071
|
}
|
|
6765
7072
|
return placeholderSrc;
|
|
6766
7073
|
});
|
|
7074
|
+
let savedRange;
|
|
6767
7075
|
lightbox.on('openingAnimationEnd', () => {
|
|
7076
|
+
savedRange = editor.selection.range;
|
|
6768
7077
|
box.event.emit('openfullscreen');
|
|
6769
7078
|
});
|
|
6770
7079
|
lightbox.on('destroy', () => {
|
|
6771
7080
|
window.setTimeout(() => {
|
|
7081
|
+
if (savedRange) {
|
|
7082
|
+
// fix(image): lose focus when zooming in the iOS
|
|
7083
|
+
editor.selection.range = savedRange;
|
|
7084
|
+
editor.selection.sync();
|
|
7085
|
+
}
|
|
6772
7086
|
box.event.emit('closefullscreen');
|
|
6773
7087
|
}, 0);
|
|
6774
7088
|
});
|
|
6775
7089
|
lightbox.init();
|
|
6776
7090
|
lightbox.loadAndOpen(currentIndex);
|
|
6777
7091
|
}
|
|
6778
|
-
// Removes current box.
|
|
6779
|
-
function removeImageBox(box) {
|
|
6780
|
-
const editor = box.getEditor();
|
|
6781
|
-
if (!editor) {
|
|
6782
|
-
return;
|
|
6783
|
-
}
|
|
6784
|
-
const xhr = box.getData('xhr');
|
|
6785
|
-
if (xhr) {
|
|
6786
|
-
xhr.abort();
|
|
6787
|
-
}
|
|
6788
|
-
editor.selection.range.selectBox(box.node);
|
|
6789
|
-
editor.removeBox();
|
|
6790
|
-
editor.history.save();
|
|
6791
|
-
}
|
|
6792
7092
|
// Displays error icon and filename.
|
|
6793
7093
|
function renderError(imageNode, box) {
|
|
6794
7094
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -6980,7 +7280,7 @@ const imageBox = {
|
|
|
6980
7280
|
}
|
|
6981
7281
|
}
|
|
6982
7282
|
if (container.first().length === 0) {
|
|
6983
|
-
// The code
|
|
7283
|
+
// The following code is for unit testing because some test cases need to
|
|
6984
7284
|
// select the content of the box before it is completely loaded.
|
|
6985
7285
|
// Example:
|
|
6986
7286
|
// range.setStart(box.getContainer(), 1);
|
|
@@ -7012,13 +7312,19 @@ const imageBox = {
|
|
|
7012
7312
|
else {
|
|
7013
7313
|
imageNode.find('.lake-button-remove').on('click', event => {
|
|
7014
7314
|
event.stopPropagation();
|
|
7015
|
-
|
|
7315
|
+
const xhr = box.getData('xhr');
|
|
7316
|
+
if (xhr) {
|
|
7317
|
+
xhr.abort();
|
|
7318
|
+
}
|
|
7319
|
+
editor.removeBox(box);
|
|
7320
|
+
editor.history.save();
|
|
7321
|
+
editor.selection.sync();
|
|
7016
7322
|
});
|
|
7017
7323
|
}
|
|
7018
7324
|
box.event.emit('render');
|
|
7019
7325
|
});
|
|
7020
7326
|
imageNode.on('click', () => {
|
|
7021
|
-
editor.
|
|
7327
|
+
editor.selectBox(box);
|
|
7022
7328
|
});
|
|
7023
7329
|
},
|
|
7024
7330
|
html: box => {
|
|
@@ -7027,6 +7333,232 @@ const imageBox = {
|
|
|
7027
7333
|
},
|
|
7028
7334
|
};
|
|
7029
7335
|
|
|
7336
|
+
const toolbarItemMap = new Map();
|
|
7337
|
+
class BoxToolbar {
|
|
7338
|
+
constructor(config) {
|
|
7339
|
+
this.placement = 'top';
|
|
7340
|
+
this.buttonItemList = [];
|
|
7341
|
+
this.dropdownItemList = [];
|
|
7342
|
+
this.root = query(config.root);
|
|
7343
|
+
this.editor = config.editor;
|
|
7344
|
+
this.box = config.box;
|
|
7345
|
+
this.items = config.items;
|
|
7346
|
+
if (config.placement) {
|
|
7347
|
+
this.placement = config.placement;
|
|
7348
|
+
}
|
|
7349
|
+
this.container = query('<div class="lake-box-toolbar" />');
|
|
7350
|
+
this.root.addClass('lake-custom-properties');
|
|
7351
|
+
}
|
|
7352
|
+
appendDivider() {
|
|
7353
|
+
this.container.append('<div class="lake-box-toolbar-divider" />');
|
|
7354
|
+
}
|
|
7355
|
+
appendButton(item) {
|
|
7356
|
+
const button = new Button({
|
|
7357
|
+
root: this.container,
|
|
7358
|
+
name: item.name,
|
|
7359
|
+
icon: item.icon,
|
|
7360
|
+
tooltip: typeof item.tooltip === 'string' ? item.tooltip : item.tooltip(this.editor.locale),
|
|
7361
|
+
tabIndex: -1,
|
|
7362
|
+
onClick: () => {
|
|
7363
|
+
item.onClick(this.box, item.name);
|
|
7364
|
+
},
|
|
7365
|
+
});
|
|
7366
|
+
button.render();
|
|
7367
|
+
}
|
|
7368
|
+
appendDropdown(item) {
|
|
7369
|
+
const dropdown = new Dropdown({
|
|
7370
|
+
root: this.container,
|
|
7371
|
+
locale: this.editor.locale,
|
|
7372
|
+
name: item.name,
|
|
7373
|
+
icon: item.icon,
|
|
7374
|
+
accentIcon: item.accentIcon,
|
|
7375
|
+
downIcon: item.downIcon,
|
|
7376
|
+
defaultValue: item.defaultValue,
|
|
7377
|
+
tooltip: item.tooltip,
|
|
7378
|
+
width: item.width,
|
|
7379
|
+
menuType: item.menuType,
|
|
7380
|
+
menuItems: item.menuItems,
|
|
7381
|
+
tabIndex: -1,
|
|
7382
|
+
placement: this.placement === 'top' ? 'bottom' : 'top',
|
|
7383
|
+
onSelect: value => {
|
|
7384
|
+
item.onSelect(this.box, value);
|
|
7385
|
+
},
|
|
7386
|
+
});
|
|
7387
|
+
dropdown.render();
|
|
7388
|
+
}
|
|
7389
|
+
updatePosition() {
|
|
7390
|
+
const boxNode = this.box.node;
|
|
7391
|
+
const position = nodeAndView(boxNode);
|
|
7392
|
+
if (position.left < 0 || position.right < 0 || position.top < 0 || position.bottom < 0) {
|
|
7393
|
+
this.container.hide();
|
|
7394
|
+
return;
|
|
7395
|
+
}
|
|
7396
|
+
this.container.show('flex');
|
|
7397
|
+
const boxNativeNode = this.box.node.get(0);
|
|
7398
|
+
const boxRect = boxNativeNode.getBoundingClientRect();
|
|
7399
|
+
const boxX = boxRect.x + window.scrollX;
|
|
7400
|
+
const boxY = boxRect.y + window.scrollY;
|
|
7401
|
+
const left = (boxX + boxRect.width / 2 - this.container.width() / 2).toFixed(1);
|
|
7402
|
+
const top = (boxY - this.container.height() - 6).toFixed(1);
|
|
7403
|
+
this.container.css({
|
|
7404
|
+
left: `${left}px`,
|
|
7405
|
+
top: `${top}px`,
|
|
7406
|
+
});
|
|
7407
|
+
}
|
|
7408
|
+
// Renders a toolbar for the specified box.
|
|
7409
|
+
render() {
|
|
7410
|
+
this.root.empty();
|
|
7411
|
+
this.root.append(this.container);
|
|
7412
|
+
this.items.forEach(name => {
|
|
7413
|
+
if (name === '|') {
|
|
7414
|
+
this.appendDivider();
|
|
7415
|
+
return;
|
|
7416
|
+
}
|
|
7417
|
+
let item;
|
|
7418
|
+
if (typeof name === 'string') {
|
|
7419
|
+
item = toolbarItemMap.get(name);
|
|
7420
|
+
if (!item) {
|
|
7421
|
+
return;
|
|
7422
|
+
}
|
|
7423
|
+
}
|
|
7424
|
+
else {
|
|
7425
|
+
item = name;
|
|
7426
|
+
}
|
|
7427
|
+
if (item.type === 'button') {
|
|
7428
|
+
this.buttonItemList.push(item);
|
|
7429
|
+
this.appendButton(item);
|
|
7430
|
+
return;
|
|
7431
|
+
}
|
|
7432
|
+
if (item.type === 'dropdown') {
|
|
7433
|
+
this.dropdownItemList.push(item);
|
|
7434
|
+
this.appendDropdown(item);
|
|
7435
|
+
}
|
|
7436
|
+
});
|
|
7437
|
+
this.updatePosition();
|
|
7438
|
+
}
|
|
7439
|
+
unmount() {
|
|
7440
|
+
this.container.remove();
|
|
7441
|
+
}
|
|
7442
|
+
}
|
|
7443
|
+
|
|
7444
|
+
const boxToolbarItems = [
|
|
7445
|
+
{
|
|
7446
|
+
name: 'download',
|
|
7447
|
+
type: 'button',
|
|
7448
|
+
icon: icons.get('download'),
|
|
7449
|
+
tooltip: locale => locale.file.download(),
|
|
7450
|
+
onClick: box => {
|
|
7451
|
+
window.open(box.value.url);
|
|
7452
|
+
},
|
|
7453
|
+
},
|
|
7454
|
+
{
|
|
7455
|
+
name: 'remove',
|
|
7456
|
+
type: 'button',
|
|
7457
|
+
icon: icons.get('remove'),
|
|
7458
|
+
tooltip: locale => locale.file.remove(),
|
|
7459
|
+
onClick: box => {
|
|
7460
|
+
const editor = box.getEditor();
|
|
7461
|
+
if (!editor) {
|
|
7462
|
+
return;
|
|
7463
|
+
}
|
|
7464
|
+
editor.removeBox(box);
|
|
7465
|
+
editor.history.save();
|
|
7466
|
+
editor.selection.sync();
|
|
7467
|
+
},
|
|
7468
|
+
},
|
|
7469
|
+
];
|
|
7470
|
+
function appendContent(fileNode, box) {
|
|
7471
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
7472
|
+
const editor = box.getEditor();
|
|
7473
|
+
if (!editor) {
|
|
7474
|
+
return;
|
|
7475
|
+
}
|
|
7476
|
+
const value = box.value;
|
|
7477
|
+
const infoNode = query(safeTemplate `
|
|
7478
|
+
<div class="lake-file-info">
|
|
7479
|
+
<div class="lake-file-type"></div>
|
|
7480
|
+
<div class="lake-file-name">${value.name} (${fileSize(value.size)})</div>
|
|
7481
|
+
</div>
|
|
7482
|
+
`);
|
|
7483
|
+
const typeNode = infoNode.find('.lake-file-type');
|
|
7484
|
+
if (value.status === 'uploading') {
|
|
7485
|
+
const percent = Math.round(value.percent || 0);
|
|
7486
|
+
const progressNode = query(safeTemplate `
|
|
7487
|
+
<div class="lake-progress">
|
|
7488
|
+
<div class="lake-percent">${percent} %</div>
|
|
7489
|
+
</div>
|
|
7490
|
+
`);
|
|
7491
|
+
const circleNotchIcon = icons.get('circleNotch');
|
|
7492
|
+
if (circleNotchIcon) {
|
|
7493
|
+
progressNode.prepend(circleNotchIcon);
|
|
7494
|
+
}
|
|
7495
|
+
typeNode.replaceWith(progressNode);
|
|
7496
|
+
}
|
|
7497
|
+
else {
|
|
7498
|
+
const fileIcon = value.status === 'error' ? icons.get('warningCircle') : icons.get('file');
|
|
7499
|
+
if (fileIcon) {
|
|
7500
|
+
typeNode.append(fileIcon);
|
|
7501
|
+
}
|
|
7502
|
+
}
|
|
7503
|
+
fileNode.append(infoNode);
|
|
7504
|
+
});
|
|
7505
|
+
}
|
|
7506
|
+
const fileBox = {
|
|
7507
|
+
type: 'inline',
|
|
7508
|
+
name: 'file',
|
|
7509
|
+
render: box => {
|
|
7510
|
+
const editor = box.getEditor();
|
|
7511
|
+
if (!editor) {
|
|
7512
|
+
return;
|
|
7513
|
+
}
|
|
7514
|
+
const value = box.value;
|
|
7515
|
+
const container = box.getContainer();
|
|
7516
|
+
const fileNode = query('<div class="lake-file" />');
|
|
7517
|
+
fileNode.addClass(`lake-file-${value.status}`);
|
|
7518
|
+
if (editor.readonly) {
|
|
7519
|
+
fileNode.addClass('lake-file-readonly');
|
|
7520
|
+
}
|
|
7521
|
+
appendContent(fileNode, box);
|
|
7522
|
+
container.empty();
|
|
7523
|
+
container.append(fileNode);
|
|
7524
|
+
if (!editor.readonly) {
|
|
7525
|
+
fileNode.on('click', () => {
|
|
7526
|
+
editor.selectBox(box);
|
|
7527
|
+
});
|
|
7528
|
+
let toolbar = null;
|
|
7529
|
+
const scrollListener = () => {
|
|
7530
|
+
if (toolbar) {
|
|
7531
|
+
toolbar.updatePosition();
|
|
7532
|
+
}
|
|
7533
|
+
};
|
|
7534
|
+
box.event.on('focus', () => {
|
|
7535
|
+
const items = value.status === 'done' ? boxToolbarItems : boxToolbarItems.filter(item => item.name === 'remove');
|
|
7536
|
+
toolbar = new BoxToolbar({
|
|
7537
|
+
root: editor.popupContainer,
|
|
7538
|
+
editor,
|
|
7539
|
+
box,
|
|
7540
|
+
items,
|
|
7541
|
+
});
|
|
7542
|
+
toolbar.render();
|
|
7543
|
+
editor.root.on('scroll', scrollListener);
|
|
7544
|
+
});
|
|
7545
|
+
box.event.on('blur', () => {
|
|
7546
|
+
if (toolbar) {
|
|
7547
|
+
toolbar.unmount();
|
|
7548
|
+
toolbar = null;
|
|
7549
|
+
}
|
|
7550
|
+
editor.root.off('scroll', scrollListener);
|
|
7551
|
+
});
|
|
7552
|
+
}
|
|
7553
|
+
else {
|
|
7554
|
+
fileNode.on('click', () => {
|
|
7555
|
+
window.open(value.url);
|
|
7556
|
+
});
|
|
7557
|
+
}
|
|
7558
|
+
box.event.emit('render');
|
|
7559
|
+
},
|
|
7560
|
+
};
|
|
7561
|
+
|
|
7030
7562
|
const config = {
|
|
7031
7563
|
comment: '#57606a',
|
|
7032
7564
|
name: '#444d56',
|
|
@@ -7131,7 +7663,7 @@ const codeBlockBox = {
|
|
|
7131
7663
|
Please check if the "lake-codemirror" library is added to this page.
|
|
7132
7664
|
`.trim());
|
|
7133
7665
|
codeBlockNode.on('click', () => {
|
|
7134
|
-
editor.
|
|
7666
|
+
editor.selectBox(box);
|
|
7135
7667
|
});
|
|
7136
7668
|
return;
|
|
7137
7669
|
}
|
|
@@ -7219,10 +7751,7 @@ const codeBlockBox = {
|
|
|
7219
7751
|
};
|
|
7220
7752
|
|
|
7221
7753
|
var copy = (editor) => {
|
|
7222
|
-
|
|
7223
|
-
return;
|
|
7224
|
-
}
|
|
7225
|
-
editor.container.on('copy', event => {
|
|
7754
|
+
editor.event.on('copy', event => {
|
|
7226
7755
|
const range = editor.selection.range;
|
|
7227
7756
|
if (range.isInsideBox) {
|
|
7228
7757
|
return;
|
|
@@ -7239,7 +7768,7 @@ var copy = (editor) => {
|
|
|
7239
7768
|
if (!dataTransfer) {
|
|
7240
7769
|
return;
|
|
7241
7770
|
}
|
|
7242
|
-
const box =
|
|
7771
|
+
const box = getBox(boxNode);
|
|
7243
7772
|
const content = box.getHTML();
|
|
7244
7773
|
dataTransfer.setData('text/html', content);
|
|
7245
7774
|
});
|
|
@@ -7249,7 +7778,7 @@ var cut = (editor) => {
|
|
|
7249
7778
|
if (editor.readonly) {
|
|
7250
7779
|
return;
|
|
7251
7780
|
}
|
|
7252
|
-
editor.
|
|
7781
|
+
editor.event.on('cut', event => {
|
|
7253
7782
|
const range = editor.selection.range;
|
|
7254
7783
|
if (range.isInsideBox) {
|
|
7255
7784
|
return;
|
|
@@ -7266,7 +7795,7 @@ var cut = (editor) => {
|
|
|
7266
7795
|
if (!dataTransfer) {
|
|
7267
7796
|
return;
|
|
7268
7797
|
}
|
|
7269
|
-
const box =
|
|
7798
|
+
const box = getBox(boxNode);
|
|
7270
7799
|
const content = box.getHTML();
|
|
7271
7800
|
dataTransfer.setData('text/html', content);
|
|
7272
7801
|
editor.removeBox();
|
|
@@ -7332,7 +7861,7 @@ function insertFirstNode(editor, otherNode) {
|
|
|
7332
7861
|
const range = editor.selection.range;
|
|
7333
7862
|
const boxNode = range.startNode.closest('lake-box');
|
|
7334
7863
|
if (boxNode.length > 0) {
|
|
7335
|
-
const box =
|
|
7864
|
+
const box = getBox(boxNode);
|
|
7336
7865
|
if (box.type === 'inline') {
|
|
7337
7866
|
if (range.isBoxStart) {
|
|
7338
7867
|
range.setStartBefore(boxNode);
|
|
@@ -7363,7 +7892,7 @@ function insertFirstNode(editor, otherNode) {
|
|
|
7363
7892
|
}
|
|
7364
7893
|
const block = range.startNode.closestBlock();
|
|
7365
7894
|
if (otherNode.isBlockBox) {
|
|
7366
|
-
const box =
|
|
7895
|
+
const box = getBox(otherNode);
|
|
7367
7896
|
const value = otherNode.attr('value') !== '' ? box.value : undefined;
|
|
7368
7897
|
editor.insertBox(box.name, value);
|
|
7369
7898
|
otherNode.remove();
|
|
@@ -7375,7 +7904,7 @@ function insertFirstNode(editor, otherNode) {
|
|
|
7375
7904
|
if (block.isEmpty && block.name === 'p') {
|
|
7376
7905
|
block.replaceWith(otherNode);
|
|
7377
7906
|
otherNode.find('lake-box').each(node => {
|
|
7378
|
-
|
|
7907
|
+
getBox(node).render();
|
|
7379
7908
|
});
|
|
7380
7909
|
range.shrinkAfter(otherNode);
|
|
7381
7910
|
return;
|
|
@@ -7433,7 +7962,7 @@ var paste = (editor) => {
|
|
|
7433
7962
|
if (editor.readonly) {
|
|
7434
7963
|
return;
|
|
7435
7964
|
}
|
|
7436
|
-
editor.
|
|
7965
|
+
editor.event.on('paste', event => {
|
|
7437
7966
|
const { requestTypes } = editor.config.image;
|
|
7438
7967
|
const range = editor.selection.range;
|
|
7439
7968
|
if (range.isInsideBox) {
|
|
@@ -7449,9 +7978,11 @@ var paste = (editor) => {
|
|
|
7449
7978
|
if (dataTransfer.files.length > 0) {
|
|
7450
7979
|
for (const file of dataTransfer.files) {
|
|
7451
7980
|
if (requestTypes.indexOf(file.type) >= 0) {
|
|
7452
|
-
|
|
7981
|
+
uploadFile({
|
|
7453
7982
|
editor,
|
|
7983
|
+
name: file.type.indexOf('image/') === 0 ? 'image' : 'file',
|
|
7454
7984
|
file,
|
|
7985
|
+
onError: error => editor.config.onMessage('error', error),
|
|
7455
7986
|
});
|
|
7456
7987
|
}
|
|
7457
7988
|
}
|
|
@@ -7474,7 +8005,155 @@ var paste = (editor) => {
|
|
|
7474
8005
|
editor.event.emit('beforepaste', fragment);
|
|
7475
8006
|
fixClipboardData(fragment);
|
|
7476
8007
|
pasteFragment(editor, fragment);
|
|
7477
|
-
editor.box.renderAll(editor);
|
|
8008
|
+
editor.box.renderAll(editor.container);
|
|
8009
|
+
});
|
|
8010
|
+
};
|
|
8011
|
+
|
|
8012
|
+
var drop = (editor) => {
|
|
8013
|
+
if (editor.readonly) {
|
|
8014
|
+
return;
|
|
8015
|
+
}
|
|
8016
|
+
let draggedNode = null;
|
|
8017
|
+
let dropIndication = null;
|
|
8018
|
+
let targetBlock = null;
|
|
8019
|
+
let dropPosition = 'bottom';
|
|
8020
|
+
// The dragstart event is fired when the user starts dragging an element or text selection.
|
|
8021
|
+
editor.container.on('dragstart', event => {
|
|
8022
|
+
draggedNode = null;
|
|
8023
|
+
const dragEvent = event;
|
|
8024
|
+
const dataTransfer = dragEvent.dataTransfer;
|
|
8025
|
+
if (!dataTransfer) {
|
|
8026
|
+
return;
|
|
8027
|
+
}
|
|
8028
|
+
dataTransfer.effectAllowed = 'move';
|
|
8029
|
+
// set the dragged node
|
|
8030
|
+
const targetNode = query(dragEvent.target);
|
|
8031
|
+
const boxNode = targetNode.closest('lake-box');
|
|
8032
|
+
if (boxNode.length === 0) {
|
|
8033
|
+
dragEvent.preventDefault();
|
|
8034
|
+
return;
|
|
8035
|
+
}
|
|
8036
|
+
const box = getBox(boxNode);
|
|
8037
|
+
if (box.type === 'inline') {
|
|
8038
|
+
dragEvent.preventDefault();
|
|
8039
|
+
return;
|
|
8040
|
+
}
|
|
8041
|
+
draggedNode = boxNode;
|
|
8042
|
+
// prepare an indication rod
|
|
8043
|
+
dropIndication = query(safeTemplate `
|
|
8044
|
+
<div class="lake-drop-indication">
|
|
8045
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#000000" viewBox="0 0 256 256">
|
|
8046
|
+
<path d="M181.66,133.66l-80,80A8,8,0,0,1,88,208V48a8,8,0,0,1,13.66-5.66l80,80A8,8,0,0,1,181.66,133.66Z"></path>
|
|
8047
|
+
</svg>
|
|
8048
|
+
</div>
|
|
8049
|
+
`);
|
|
8050
|
+
editor.overlayContainer.append(dropIndication);
|
|
8051
|
+
});
|
|
8052
|
+
// The dragover event is fired when an element or text selection is being dragged over a valid drop target (every few hundred milliseconds).
|
|
8053
|
+
editor.container.on('dragover', event => {
|
|
8054
|
+
const dragEvent = event;
|
|
8055
|
+
dragEvent.preventDefault();
|
|
8056
|
+
const dataTransfer = dragEvent.dataTransfer;
|
|
8057
|
+
if (!dataTransfer) {
|
|
8058
|
+
return;
|
|
8059
|
+
}
|
|
8060
|
+
dataTransfer.dropEffect = 'move';
|
|
8061
|
+
if (!dropIndication) {
|
|
8062
|
+
return;
|
|
8063
|
+
}
|
|
8064
|
+
const targetNode = query(dragEvent.target);
|
|
8065
|
+
if (targetNode.isContainer) {
|
|
8066
|
+
return;
|
|
8067
|
+
}
|
|
8068
|
+
const targetBoxNode = targetNode.closest('lake-box');
|
|
8069
|
+
if (targetBoxNode.length > 0) {
|
|
8070
|
+
if (targetBoxNode.isBlockBox) {
|
|
8071
|
+
targetBlock = targetBoxNode;
|
|
8072
|
+
}
|
|
8073
|
+
else {
|
|
8074
|
+
targetBlock = targetBoxNode.closestBlock();
|
|
8075
|
+
}
|
|
8076
|
+
}
|
|
8077
|
+
else {
|
|
8078
|
+
targetBlock = targetNode.closestBlock();
|
|
8079
|
+
}
|
|
8080
|
+
const containerRect = editor.container.get(0).getBoundingClientRect();
|
|
8081
|
+
let targetBlcokRect = targetBlock.get(0).getBoundingClientRect();
|
|
8082
|
+
dropPosition = 'bottom';
|
|
8083
|
+
let left = targetBlcokRect.x - containerRect.x;
|
|
8084
|
+
let top = targetBlcokRect.y + targetBlcokRect.height - containerRect.y + (parseInt(targetBlock.computedCSS('margin-bottom'), 10) / 2);
|
|
8085
|
+
if (dragEvent.clientY < targetBlcokRect.y + (targetBlcokRect.height / 2)) {
|
|
8086
|
+
const prevBlock = targetBlock.prev();
|
|
8087
|
+
if (prevBlock.length > 0 && prevBlock.isBlock || prevBlock.isBlockBox) {
|
|
8088
|
+
targetBlock = prevBlock;
|
|
8089
|
+
targetBlcokRect = targetBlock.get(0).getBoundingClientRect();
|
|
8090
|
+
left = targetBlcokRect.x - containerRect.x;
|
|
8091
|
+
top = targetBlcokRect.y + targetBlcokRect.height - containerRect.y + (parseInt(targetBlock.computedCSS('margin-bottom'), 10) / 2);
|
|
8092
|
+
}
|
|
8093
|
+
else {
|
|
8094
|
+
dropPosition = 'top';
|
|
8095
|
+
top = targetBlcokRect.y - containerRect.y - (parseInt(editor.container.computedCSS('padding-top'), 10) / 2);
|
|
8096
|
+
}
|
|
8097
|
+
}
|
|
8098
|
+
dropIndication.css({
|
|
8099
|
+
top: `${top}px`,
|
|
8100
|
+
left: `${left}px`,
|
|
8101
|
+
width: `${targetBlcokRect.width}px`,
|
|
8102
|
+
display: 'block',
|
|
8103
|
+
});
|
|
8104
|
+
});
|
|
8105
|
+
// The dragend event is fired when a drag operation ends (by releasing a mouse button or hitting the escape key).
|
|
8106
|
+
editor.container.on('dragend', () => {
|
|
8107
|
+
if (!dropIndication) {
|
|
8108
|
+
return;
|
|
8109
|
+
}
|
|
8110
|
+
dropIndication.remove();
|
|
8111
|
+
dropIndication = null;
|
|
8112
|
+
});
|
|
8113
|
+
// The drop event is fired when an element or text selection is dropped on a valid drop target.
|
|
8114
|
+
editor.container.on('drop', event => {
|
|
8115
|
+
const dragEvent = event;
|
|
8116
|
+
const dataTransfer = dragEvent.dataTransfer;
|
|
8117
|
+
if (!dataTransfer) {
|
|
8118
|
+
return;
|
|
8119
|
+
}
|
|
8120
|
+
if (!dropIndication) {
|
|
8121
|
+
return;
|
|
8122
|
+
}
|
|
8123
|
+
dropIndication.remove();
|
|
8124
|
+
dropIndication = null;
|
|
8125
|
+
// drop a box
|
|
8126
|
+
if (draggedNode && targetBlock && draggedNode.isBox) {
|
|
8127
|
+
if (draggedNode.get(0) === targetBlock.get(0)) {
|
|
8128
|
+
return;
|
|
8129
|
+
}
|
|
8130
|
+
if (dropPosition === 'bottom' && draggedNode.get(0) === targetBlock.next().get(0)) {
|
|
8131
|
+
return;
|
|
8132
|
+
}
|
|
8133
|
+
dragEvent.preventDefault();
|
|
8134
|
+
const draggedBox = getBox(draggedNode);
|
|
8135
|
+
const range = editor.selection.range;
|
|
8136
|
+
if (targetBlock.isBox) {
|
|
8137
|
+
if (dropPosition === 'top') {
|
|
8138
|
+
range.selectBoxStart(targetBlock);
|
|
8139
|
+
}
|
|
8140
|
+
else {
|
|
8141
|
+
range.selectBoxEnd(targetBlock);
|
|
8142
|
+
}
|
|
8143
|
+
}
|
|
8144
|
+
else {
|
|
8145
|
+
range.selectNodeContents(targetBlock);
|
|
8146
|
+
if (dropPosition === 'top') {
|
|
8147
|
+
range.collapseToStart();
|
|
8148
|
+
}
|
|
8149
|
+
else {
|
|
8150
|
+
range.collapseToEnd();
|
|
8151
|
+
}
|
|
8152
|
+
}
|
|
8153
|
+
editor.insertBox(draggedBox.name, draggedBox.value);
|
|
8154
|
+
draggedNode.remove();
|
|
8155
|
+
editor.history.save();
|
|
8156
|
+
}
|
|
7478
8157
|
});
|
|
7479
8158
|
};
|
|
7480
8159
|
|
|
@@ -8194,15 +8873,17 @@ class LinkPopup {
|
|
|
8194
8873
|
if (!this.linkNode) {
|
|
8195
8874
|
return;
|
|
8196
8875
|
}
|
|
8876
|
+
const position = nodeAndView(this.linkNode);
|
|
8877
|
+
if (position.left < 0 || position.right < 0 || position.top < 0 || position.bottom < 0) {
|
|
8878
|
+
this.container.css('visibility', 'hidden');
|
|
8879
|
+
return;
|
|
8880
|
+
}
|
|
8881
|
+
this.container.css('visibility', '');
|
|
8197
8882
|
const linkNativeNode = this.linkNode.get(0);
|
|
8198
8883
|
// Returns a DOMRect object providing information about the size of an element and its position relative to the viewport.
|
|
8199
8884
|
const linkRect = linkNativeNode.getBoundingClientRect();
|
|
8200
8885
|
const linkX = linkRect.x + window.scrollX;
|
|
8201
8886
|
const linkY = linkRect.y + window.scrollY;
|
|
8202
|
-
if (linkX < 0 || linkY < 0) {
|
|
8203
|
-
this.hide();
|
|
8204
|
-
return;
|
|
8205
|
-
}
|
|
8206
8887
|
// link.x + popup.width > window.width
|
|
8207
8888
|
if (linkRect.x + this.container.width() > window.innerWidth) {
|
|
8208
8889
|
// link.x + window.scrollX - (popup.width - link.width)
|
|
@@ -8264,14 +8945,14 @@ var link = (editor) => {
|
|
|
8264
8945
|
const range = editor.selection.range;
|
|
8265
8946
|
range.setStartAfter(node);
|
|
8266
8947
|
range.collapseToStart();
|
|
8267
|
-
editor.selection.
|
|
8948
|
+
editor.selection.sync();
|
|
8268
8949
|
editor.history.save();
|
|
8269
8950
|
},
|
|
8270
8951
|
onRemove: node => {
|
|
8271
8952
|
const range = editor.selection.range;
|
|
8272
8953
|
range.setStartAfter(node);
|
|
8273
8954
|
range.collapseToStart();
|
|
8274
|
-
editor.selection.
|
|
8955
|
+
editor.selection.sync();
|
|
8275
8956
|
editor.history.save();
|
|
8276
8957
|
},
|
|
8277
8958
|
});
|
|
@@ -8318,7 +8999,7 @@ var hr = (editor) => {
|
|
|
8318
8999
|
const fragment = new Fragment(nativeFragment);
|
|
8319
9000
|
fragment.find('hr').each(nativeNode => {
|
|
8320
9001
|
const node = query(nativeNode);
|
|
8321
|
-
const box =
|
|
9002
|
+
const box = getBox('hr');
|
|
8322
9003
|
node.replaceWith(box.node);
|
|
8323
9004
|
});
|
|
8324
9005
|
});
|
|
@@ -8342,7 +9023,7 @@ var image = (editor) => {
|
|
|
8342
9023
|
const fragment = new Fragment(nativeFragment);
|
|
8343
9024
|
fragment.find('img').each(nativeNode => {
|
|
8344
9025
|
const node = query(nativeNode);
|
|
8345
|
-
const box =
|
|
9026
|
+
const box = getBox('image');
|
|
8346
9027
|
const value = node.attr('data-lake-value');
|
|
8347
9028
|
if (value === '') {
|
|
8348
9029
|
box.value = {
|
|
@@ -8364,6 +9045,39 @@ var image = (editor) => {
|
|
|
8364
9045
|
});
|
|
8365
9046
|
};
|
|
8366
9047
|
|
|
9048
|
+
var file = (editor) => {
|
|
9049
|
+
editor.setPluginConfig('file', {
|
|
9050
|
+
requestMethod: 'POST',
|
|
9051
|
+
requestTypes: [
|
|
9052
|
+
'application/zip',
|
|
9053
|
+
'application/x-zip-compressed',
|
|
9054
|
+
'application/vnd.rar',
|
|
9055
|
+
'image/gif',
|
|
9056
|
+
'image/jpeg',
|
|
9057
|
+
'image/png',
|
|
9058
|
+
'image/svg+xml',
|
|
9059
|
+
'text/plain',
|
|
9060
|
+
'text/html',
|
|
9061
|
+
'application/pdf',
|
|
9062
|
+
'application/msword',
|
|
9063
|
+
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
|
9064
|
+
'application/vnd.ms-excel',
|
|
9065
|
+
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
|
9066
|
+
'application/vnd.ms-powerpoint',
|
|
9067
|
+
'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
|
9068
|
+
],
|
|
9069
|
+
});
|
|
9070
|
+
if (editor.readonly) {
|
|
9071
|
+
return;
|
|
9072
|
+
}
|
|
9073
|
+
editor.command.add('file', {
|
|
9074
|
+
execute: (value) => {
|
|
9075
|
+
editor.insertBox('file', value);
|
|
9076
|
+
editor.history.save();
|
|
9077
|
+
},
|
|
9078
|
+
});
|
|
9079
|
+
};
|
|
9080
|
+
|
|
8367
9081
|
const langList = [
|
|
8368
9082
|
'text',
|
|
8369
9083
|
'c',
|
|
@@ -8740,12 +9454,10 @@ function splitBlock(editor, block) {
|
|
|
8740
9454
|
editor.selection.splitBlock();
|
|
8741
9455
|
block = range.getBlocks()[0];
|
|
8742
9456
|
if (!block) {
|
|
8743
|
-
editor.history.save();
|
|
8744
9457
|
return;
|
|
8745
9458
|
}
|
|
8746
9459
|
if (endText === '' && (block.isHeading || block.name === 'blockquote')) {
|
|
8747
9460
|
editor.selection.setBlocks('<p />');
|
|
8748
|
-
editor.history.save();
|
|
8749
9461
|
return;
|
|
8750
9462
|
}
|
|
8751
9463
|
if (block.isList && block.attr('type') === 'checklist') {
|
|
@@ -8990,8 +9702,7 @@ var backspaceKey = (editor) => {
|
|
|
8990
9702
|
const prevNode = range.getPrevNode();
|
|
8991
9703
|
if (prevNode.isBox) {
|
|
8992
9704
|
event.preventDefault();
|
|
8993
|
-
|
|
8994
|
-
editor.removeBox();
|
|
9705
|
+
editor.removeBox(prevNode);
|
|
8995
9706
|
editor.history.save();
|
|
8996
9707
|
return;
|
|
8997
9708
|
}
|
|
@@ -9110,8 +9821,7 @@ var deleteKey = (editor) => {
|
|
|
9110
9821
|
const nextNode = range.getNextNode();
|
|
9111
9822
|
if (nextNode.isBox) {
|
|
9112
9823
|
event.preventDefault();
|
|
9113
|
-
|
|
9114
|
-
editor.removeBox();
|
|
9824
|
+
editor.removeBox(nextNode);
|
|
9115
9825
|
editor.history.save();
|
|
9116
9826
|
return;
|
|
9117
9827
|
}
|
|
@@ -9292,7 +10002,7 @@ var escapeKey = (editor) => {
|
|
|
9292
10002
|
event.preventDefault();
|
|
9293
10003
|
const boxNode = range.commonAncestor.closest('lake-box');
|
|
9294
10004
|
range.selectBoxEnd(boxNode);
|
|
9295
|
-
selection.
|
|
10005
|
+
selection.sync();
|
|
9296
10006
|
return;
|
|
9297
10007
|
}
|
|
9298
10008
|
if (editor.hasFocus) {
|
|
@@ -9304,10 +10014,12 @@ var escapeKey = (editor) => {
|
|
|
9304
10014
|
|
|
9305
10015
|
Editor.box.add(hrBox);
|
|
9306
10016
|
Editor.box.add(imageBox);
|
|
10017
|
+
Editor.box.add(fileBox);
|
|
9307
10018
|
Editor.box.add(codeBlockBox);
|
|
9308
10019
|
Editor.plugin.add(copy);
|
|
9309
10020
|
Editor.plugin.add(cut);
|
|
9310
10021
|
Editor.plugin.add(paste);
|
|
10022
|
+
Editor.plugin.add(drop);
|
|
9311
10023
|
Editor.plugin.add(undo);
|
|
9312
10024
|
Editor.plugin.add(redo);
|
|
9313
10025
|
Editor.plugin.add(selectAll);
|
|
@@ -9332,6 +10044,7 @@ Editor.plugin.add(formatPainter);
|
|
|
9332
10044
|
Editor.plugin.add(link);
|
|
9333
10045
|
Editor.plugin.add(hr);
|
|
9334
10046
|
Editor.plugin.add(image);
|
|
10047
|
+
Editor.plugin.add(file);
|
|
9335
10048
|
Editor.plugin.add(codeBlock);
|
|
9336
10049
|
Editor.plugin.add(markdown);
|
|
9337
10050
|
Editor.plugin.add(enterKey);
|