lakelib 0.3.3 → 0.3.4
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/README.md +28 -22
- package/dist/lake.min.css +1 -1
- package/dist/lake.min.js +22 -22
- package/dist/lake.min.js.map +1 -1
- package/lib/lake.css +4 -1
- package/lib/lake.d.ts +2148 -0
- package/lib/lake.js +1211 -602
- package/lib/lake.js.map +1 -1
- package/package.json +30 -33
- package/lib/config/element-rules.d.ts +0 -1
- package/lib/config/menu-items.d.ts +0 -9
- package/lib/config/tag-names.d.ts +0 -6
- package/lib/config/toolbar-items.d.ts +0 -2
- package/lib/css/index.d.ts +0 -17
- package/lib/editor.d.ts +0 -93
- package/lib/elements/bookmark.d.ts +0 -2
- package/lib/elements/box.d.ts +0 -2
- package/lib/i18n/en-US/index.d.ts +0 -169
- package/lib/i18n/index.d.ts +0 -2
- package/lib/i18n/ja/index.d.ts +0 -169
- package/lib/i18n/ko/index.d.ts +0 -169
- package/lib/i18n/types.d.ts +0 -1233
- package/lib/i18n/zh-CN/index.d.ts +0 -169
- package/lib/icons/index.d.ts +0 -1
- package/lib/index.d.ts +0 -35
- package/lib/managers/box-manager.d.ts +0 -6
- package/lib/managers/command.d.ts +0 -23
- package/lib/managers/history.d.ts +0 -32
- package/lib/managers/keystroke.d.ts +0 -11
- package/lib/managers/plugin.d.ts +0 -7
- package/lib/managers/selection.d.ts +0 -40
- package/lib/models/box.d.ts +0 -25
- package/lib/models/fragment.d.ts +0 -8
- package/lib/models/nodes.d.ts +0 -98
- package/lib/models/range.d.ts +0 -56
- package/lib/operations/add-mark.d.ts +0 -3
- package/lib/operations/delete-contents.d.ts +0 -2
- package/lib/operations/insert-block.d.ts +0 -3
- package/lib/operations/insert-bookmark.d.ts +0 -6
- package/lib/operations/insert-box.d.ts +0 -4
- package/lib/operations/insert-contents.d.ts +0 -4
- package/lib/operations/remove-box.d.ts +0 -3
- package/lib/operations/remove-mark.d.ts +0 -2
- package/lib/operations/set-blocks.d.ts +0 -3
- package/lib/operations/split-block.d.ts +0 -3
- package/lib/operations/split-marks.d.ts +0 -3
- package/lib/operations/to-bookmark.d.ts +0 -6
- package/lib/parsers/html-parser.d.ts +0 -13
- package/lib/parsers/text-parser.d.ts +0 -6
- package/lib/plugins/align.d.ts +0 -3
- package/lib/plugins/arrow-keys.d.ts +0 -3
- package/lib/plugins/backspace-key.d.ts +0 -3
- package/lib/plugins/block-quote.d.ts +0 -3
- package/lib/plugins/bold.d.ts +0 -3
- package/lib/plugins/code-block/code-block-box.d.ts +0 -4
- package/lib/plugins/code-block/index.d.ts +0 -5
- package/lib/plugins/code.d.ts +0 -3
- package/lib/plugins/copy.d.ts +0 -3
- package/lib/plugins/cut.d.ts +0 -3
- package/lib/plugins/delete-key.d.ts +0 -3
- package/lib/plugins/drop.d.ts +0 -3
- package/lib/plugins/emoji/emoji-box.d.ts +0 -4
- package/lib/plugins/emoji/index.d.ts +0 -5
- package/lib/plugins/enter-key.d.ts +0 -3
- package/lib/plugins/equation/equation-box.d.ts +0 -4
- package/lib/plugins/equation/index.d.ts +0 -5
- package/lib/plugins/escape-key.d.ts +0 -3
- package/lib/plugins/file/file-box.d.ts +0 -4
- package/lib/plugins/file/index.d.ts +0 -5
- package/lib/plugins/font-color.d.ts +0 -3
- package/lib/plugins/font-family.d.ts +0 -3
- package/lib/plugins/font-size.d.ts +0 -3
- package/lib/plugins/format-painter.d.ts +0 -3
- package/lib/plugins/heading.d.ts +0 -3
- package/lib/plugins/highlight.d.ts +0 -3
- package/lib/plugins/hr/hr-box.d.ts +0 -4
- package/lib/plugins/hr/index.d.ts +0 -5
- package/lib/plugins/image/image-box.d.ts +0 -5
- package/lib/plugins/image/index.d.ts +0 -5
- package/lib/plugins/indent.d.ts +0 -3
- package/lib/plugins/italic.d.ts +0 -3
- package/lib/plugins/link/index.d.ts +0 -3
- package/lib/plugins/link/insert-link.d.ts +0 -3
- package/lib/plugins/link/link-popup.d.ts +0 -32
- package/lib/plugins/list.d.ts +0 -3
- package/lib/plugins/markdown.d.ts +0 -3
- package/lib/plugins/mention/index.d.ts +0 -5
- package/lib/plugins/mention/mention-box.d.ts +0 -4
- package/lib/plugins/mention/mention-menu.d.ts +0 -15
- package/lib/plugins/mention/types.d.ts +0 -6
- package/lib/plugins/paste.d.ts +0 -3
- package/lib/plugins/redo.d.ts +0 -3
- package/lib/plugins/remove-format.d.ts +0 -3
- package/lib/plugins/select-all.d.ts +0 -3
- package/lib/plugins/shift-enter-key.d.ts +0 -3
- package/lib/plugins/slash/index.d.ts +0 -3
- package/lib/plugins/slash/slash-items.d.ts +0 -2
- package/lib/plugins/slash/slash-menu.d.ts +0 -19
- package/lib/plugins/slash/types.d.ts +0 -20
- package/lib/plugins/special-character.d.ts +0 -3
- package/lib/plugins/strikethrough.d.ts +0 -3
- package/lib/plugins/subscript.d.ts +0 -3
- package/lib/plugins/superscript.d.ts +0 -3
- package/lib/plugins/tab-key.d.ts +0 -3
- package/lib/plugins/table/delete-column.d.ts +0 -2
- package/lib/plugins/table/delete-row.d.ts +0 -2
- package/lib/plugins/table/delete-table.d.ts +0 -2
- package/lib/plugins/table/index.d.ts +0 -4
- package/lib/plugins/table/insert-column.d.ts +0 -4
- package/lib/plugins/table/insert-row.d.ts +0 -4
- package/lib/plugins/table/insert-table.d.ts +0 -3
- package/lib/plugins/table/merge-cells.d.ts +0 -3
- package/lib/plugins/table/split-cell.d.ts +0 -3
- package/lib/plugins/table/utils.d.ts +0 -6
- package/lib/plugins/underline.d.ts +0 -3
- package/lib/plugins/undo.d.ts +0 -3
- package/lib/plugins/unlink.d.ts +0 -3
- package/lib/plugins/video/index.d.ts +0 -5
- package/lib/plugins/video/video-box.d.ts +0 -4
- package/lib/storage/box-instances.d.ts +0 -2
- package/lib/storage/boxes.d.ts +0 -2
- package/lib/storage/editors.d.ts +0 -2
- package/lib/types/box.d.ts +0 -15
- package/lib/types/corner-toolbar.d.ts +0 -7
- package/lib/types/dropdown.d.ts +0 -23
- package/lib/types/native.d.ts +0 -2
- package/lib/types/node.d.ts +0 -13
- package/lib/types/object.d.ts +0 -3
- package/lib/types/plugin.d.ts +0 -3
- package/lib/types/request.d.ts +0 -20
- package/lib/types/selection.d.ts +0 -14
- package/lib/types/toolbar.d.ts +0 -29
- package/lib/ui/button.d.ts +0 -19
- package/lib/ui/corner-toolbar.d.ts +0 -18
- package/lib/ui/dropdown.d.ts +0 -36
- package/lib/ui/floating-toolbar.d.ts +0 -16
- package/lib/ui/menu.d.ts +0 -33
- package/lib/ui/resizer.d.ts +0 -17
- package/lib/ui/toolbar.d.ts +0 -29
- package/lib/utils/append-break.d.ts +0 -2
- package/lib/utils/camel-case.d.ts +0 -1
- package/lib/utils/change-tag-name.d.ts +0 -2
- package/lib/utils/debug.d.ts +0 -1
- package/lib/utils/denormalize-value.d.ts +0 -1
- package/lib/utils/encode.d.ts +0 -1
- package/lib/utils/file-size.d.ts +0 -1
- package/lib/utils/fix-numbered-list.d.ts +0 -2
- package/lib/utils/from-base64.d.ts +0 -1
- package/lib/utils/get-box.d.ts +0 -3
- package/lib/utils/get-css.d.ts +0 -1
- package/lib/utils/get-deep-element.d.ts +0 -2
- package/lib/utils/in-string.d.ts +0 -1
- package/lib/utils/indent-block.d.ts +0 -2
- package/lib/utils/merge-nodes.d.ts +0 -5
- package/lib/utils/modifier-text.d.ts +0 -1
- package/lib/utils/morph.d.ts +0 -56
- package/lib/utils/normalize-value.d.ts +0 -1
- package/lib/utils/parse-style.d.ts +0 -2
- package/lib/utils/query.d.ts +0 -2
- package/lib/utils/remove-break.d.ts +0 -2
- package/lib/utils/remove-empty-marks.d.ts +0 -2
- package/lib/utils/remove-zws.d.ts +0 -2
- package/lib/utils/request.d.ts +0 -27
- package/lib/utils/scroll-to-node.d.ts +0 -2
- package/lib/utils/split-nodes.d.ts +0 -5
- package/lib/utils/template.d.ts +0 -1
- package/lib/utils/to-base64.d.ts +0 -1
- package/lib/utils/to-hex.d.ts +0 -1
- package/lib/utils/to-node-list.d.ts +0 -1
- package/lib/utils/unsafe-template.d.ts +0 -1
- package/lib/utils/upload-file.d.ts +0 -11
- package/lib/utils/visible-info.d.ts +0 -10
- package/lib/utils/wrap-node-list.d.ts +0 -2
package/lib/lake.js
CHANGED
|
@@ -194,7 +194,7 @@ var danger = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"32\" height=\"32
|
|
|
194
194
|
//
|
|
195
195
|
// Phosphor Icons (https://phosphoricons.com/).
|
|
196
196
|
// - other icons
|
|
197
|
-
// eslint-disable-next-line
|
|
197
|
+
// eslint-disable-next-line ts/ban-ts-comment
|
|
198
198
|
// @ts-nocheck
|
|
199
199
|
// common
|
|
200
200
|
const icons = new Map([
|
|
@@ -397,19 +397,25 @@ function camelCase(value) {
|
|
|
397
397
|
return camelString;
|
|
398
398
|
}
|
|
399
399
|
|
|
400
|
-
|
|
400
|
+
/**
|
|
401
|
+
* Converts an alpha value to a hex value.
|
|
402
|
+
*/
|
|
401
403
|
function alphaToHex(value) {
|
|
402
404
|
const hexString = Math.round(Number.parseFloat(value) * 255).toString(16);
|
|
403
405
|
return hexString.length > 1 ? hexString : `0${hexString}`;
|
|
404
406
|
}
|
|
405
|
-
|
|
407
|
+
/**
|
|
408
|
+
* Converts a decimal to a hex value.
|
|
409
|
+
*/
|
|
406
410
|
function hex(value) {
|
|
407
411
|
const hexString = Number.parseInt(value, 10).toString(16).toLowerCase();
|
|
408
412
|
return hexString.length > 1 ? hexString : `0${hexString}`;
|
|
409
413
|
}
|
|
410
|
-
|
|
414
|
+
/**
|
|
415
|
+
* Converts a color in RGB or RGBA format to hex format.
|
|
416
|
+
*/
|
|
411
417
|
function toHex(value) {
|
|
412
|
-
return value.replace(/rgba?\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*([\d.]+)\s*)?\)/
|
|
418
|
+
return value.replace(/rgba?\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*([\d.]+)\s*)?\)/gi, (match, p1, p2, p3, p4) => {
|
|
413
419
|
if (p4 === undefined) {
|
|
414
420
|
return `#${hex(p1)}${hex(p2)}${hex(p3)}`;
|
|
415
421
|
}
|
|
@@ -433,14 +439,20 @@ function debug(...data) {
|
|
|
433
439
|
}
|
|
434
440
|
}
|
|
435
441
|
|
|
436
|
-
|
|
437
|
-
|
|
442
|
+
/**
|
|
443
|
+
* A key-value object for storing all events.
|
|
444
|
+
* The value is an array which include types and listeners.
|
|
445
|
+
*/
|
|
438
446
|
const eventData = {};
|
|
439
447
|
let lastNodeId = 0;
|
|
440
|
-
|
|
448
|
+
/**
|
|
449
|
+
* The Nodes interface represents a collection of the nodes.
|
|
450
|
+
* It is similar to jQuery, but its implementation is much simpler.
|
|
451
|
+
* Its methods can be considered aliases of native DOM interfaces, designed to simplify DOM manipulation.
|
|
452
|
+
*/
|
|
441
453
|
class Nodes {
|
|
442
454
|
constructor(node) {
|
|
443
|
-
node = node !== null && node !==
|
|
455
|
+
node = node !== null && node !== void 0 ? node : [];
|
|
444
456
|
this.nodeList = Array.isArray(node) ? node : [node];
|
|
445
457
|
for (let i = 0; i < this.nodeList.length; i++) {
|
|
446
458
|
// lakeId is an expando for preserving node ID.
|
|
@@ -451,12 +463,16 @@ class Nodes {
|
|
|
451
463
|
}
|
|
452
464
|
this.length = this.nodeList.length;
|
|
453
465
|
}
|
|
454
|
-
|
|
466
|
+
/**
|
|
467
|
+
* The unique ID of the first node.
|
|
468
|
+
*/
|
|
455
469
|
get id() {
|
|
456
470
|
const node = this.get(0);
|
|
457
471
|
return node.lakeId;
|
|
458
472
|
}
|
|
459
|
-
|
|
473
|
+
/**
|
|
474
|
+
* The name of the first node.
|
|
475
|
+
*/
|
|
460
476
|
get name() {
|
|
461
477
|
if (this.length === 0) {
|
|
462
478
|
return '';
|
|
@@ -464,7 +480,9 @@ class Nodes {
|
|
|
464
480
|
const node = this.get(0);
|
|
465
481
|
return node.nodeName.toLowerCase();
|
|
466
482
|
}
|
|
467
|
-
|
|
483
|
+
/**
|
|
484
|
+
* A boolean value indicating whether the first node is an element.
|
|
485
|
+
*/
|
|
468
486
|
get isElement() {
|
|
469
487
|
if (this.length === 0) {
|
|
470
488
|
return false;
|
|
@@ -472,7 +490,9 @@ class Nodes {
|
|
|
472
490
|
const node = this.get(0);
|
|
473
491
|
return node.nodeType === Node.ELEMENT_NODE;
|
|
474
492
|
}
|
|
475
|
-
|
|
493
|
+
/**
|
|
494
|
+
* A boolean value indicating whether the first node is a text.
|
|
495
|
+
*/
|
|
476
496
|
get isText() {
|
|
477
497
|
if (this.length === 0) {
|
|
478
498
|
return false;
|
|
@@ -480,65 +500,87 @@ class Nodes {
|
|
|
480
500
|
const node = this.get(0);
|
|
481
501
|
return node.nodeType === Node.TEXT_NODE;
|
|
482
502
|
}
|
|
483
|
-
|
|
503
|
+
/**
|
|
504
|
+
* A boolean value indicating whether the first node is a block.
|
|
505
|
+
*/
|
|
484
506
|
get isBlock() {
|
|
485
507
|
if (this.length === 0) {
|
|
486
508
|
return false;
|
|
487
509
|
}
|
|
488
510
|
return blockTagNames.has(this.name);
|
|
489
511
|
}
|
|
490
|
-
|
|
512
|
+
/**
|
|
513
|
+
* A boolean value indicating whether the first node is a mark.
|
|
514
|
+
*/
|
|
491
515
|
get isMark() {
|
|
492
516
|
if (this.length === 0) {
|
|
493
517
|
return false;
|
|
494
518
|
}
|
|
495
519
|
return markTagNames.has(this.name);
|
|
496
520
|
}
|
|
497
|
-
|
|
521
|
+
/**
|
|
522
|
+
* A boolean value indicating whether the first node is a void element that cannot have any child nodes.
|
|
523
|
+
*/
|
|
498
524
|
get isVoid() {
|
|
499
525
|
if (this.length === 0) {
|
|
500
526
|
return false;
|
|
501
527
|
}
|
|
502
528
|
return voidTagNames.has(this.name);
|
|
503
529
|
}
|
|
504
|
-
|
|
530
|
+
/**
|
|
531
|
+
* A boolean value indicating whether the first node is a heading.
|
|
532
|
+
*/
|
|
505
533
|
get isHeading() {
|
|
506
534
|
if (this.length === 0) {
|
|
507
535
|
return false;
|
|
508
536
|
}
|
|
509
537
|
return headingTagNames.has(this.name);
|
|
510
538
|
}
|
|
511
|
-
|
|
539
|
+
/**
|
|
540
|
+
* A boolean value indicating whether the first node is a list.
|
|
541
|
+
*/
|
|
512
542
|
get isList() {
|
|
513
543
|
if (this.length === 0) {
|
|
514
544
|
return false;
|
|
515
545
|
}
|
|
516
546
|
return listTagNames.has(this.name);
|
|
517
547
|
}
|
|
518
|
-
|
|
548
|
+
/**
|
|
549
|
+
* A boolean value indicating whether the first node is a table.
|
|
550
|
+
*/
|
|
519
551
|
get isTable() {
|
|
520
552
|
if (this.length === 0) {
|
|
521
553
|
return false;
|
|
522
554
|
}
|
|
523
555
|
return tableTagNames.has(this.name);
|
|
524
556
|
}
|
|
525
|
-
|
|
557
|
+
/**
|
|
558
|
+
* A boolean value indicating whether the first node is a bookmark element.
|
|
559
|
+
*/
|
|
526
560
|
get isBookmark() {
|
|
527
561
|
return this.name === 'lake-bookmark';
|
|
528
562
|
}
|
|
529
|
-
|
|
563
|
+
/**
|
|
564
|
+
* A boolean value indicating whether the first node is a box element.
|
|
565
|
+
*/
|
|
530
566
|
get isBox() {
|
|
531
567
|
return this.name === 'lake-box';
|
|
532
568
|
}
|
|
533
|
-
|
|
569
|
+
/**
|
|
570
|
+
* A boolean value indicating whether the first node is an inline box element.
|
|
571
|
+
*/
|
|
534
572
|
get isInlineBox() {
|
|
535
573
|
return this.isBox && this.attr('type') === 'inline';
|
|
536
574
|
}
|
|
537
|
-
|
|
575
|
+
/**
|
|
576
|
+
* A boolean value indicating whether the first node is a block box element.
|
|
577
|
+
*/
|
|
538
578
|
get isBlockBox() {
|
|
539
579
|
return this.isBox && this.attr('type') === 'block';
|
|
540
580
|
}
|
|
541
|
-
|
|
581
|
+
/**
|
|
582
|
+
* A boolean value indicating whether the first node is a contenteditable element where users can edit the content.
|
|
583
|
+
*/
|
|
542
584
|
get isContainer() {
|
|
543
585
|
if (this.length === 0) {
|
|
544
586
|
return false;
|
|
@@ -546,15 +588,21 @@ class Nodes {
|
|
|
546
588
|
const node = this.get(0);
|
|
547
589
|
return this.isElement && node.getAttribute('contenteditable') === 'true';
|
|
548
590
|
}
|
|
549
|
-
|
|
591
|
+
/**
|
|
592
|
+
* A boolean value indicating whether the first node does not have an ancestor element which contenteditable attribute is true.
|
|
593
|
+
*/
|
|
550
594
|
get isOutside() {
|
|
551
595
|
return this.closest('[contenteditable="true"]').length === 0;
|
|
552
596
|
}
|
|
553
|
-
|
|
597
|
+
/**
|
|
598
|
+
* A boolean value indicating whether the first node has an ancestor element which contenteditable attribute is true.
|
|
599
|
+
*/
|
|
554
600
|
get isInside() {
|
|
555
601
|
return !this.isOutside && !this.isContainer;
|
|
556
602
|
}
|
|
557
|
-
|
|
603
|
+
/**
|
|
604
|
+
* A boolean value indicating whether the first node's parent element is an element which contenteditable attribute is true.
|
|
605
|
+
*/
|
|
558
606
|
get isTopInside() {
|
|
559
607
|
if (this.length === 0) {
|
|
560
608
|
return false;
|
|
@@ -565,7 +613,9 @@ class Nodes {
|
|
|
565
613
|
}
|
|
566
614
|
return this.isInside && parentNode.isContainer;
|
|
567
615
|
}
|
|
568
|
-
|
|
616
|
+
/**
|
|
617
|
+
* A boolean value indicating whether the first node is editable.
|
|
618
|
+
*/
|
|
569
619
|
get isContentEditable() {
|
|
570
620
|
if (this.length === 0) {
|
|
571
621
|
return false;
|
|
@@ -583,11 +633,15 @@ class Nodes {
|
|
|
583
633
|
const element = this.get(0);
|
|
584
634
|
return element.isContentEditable;
|
|
585
635
|
}
|
|
586
|
-
|
|
636
|
+
/**
|
|
637
|
+
* A boolean value indicating whether the first node is indivisible.
|
|
638
|
+
*/
|
|
587
639
|
get isIndivisible() {
|
|
588
640
|
return this.isContainer || this.isTable;
|
|
589
641
|
}
|
|
590
|
-
|
|
642
|
+
/**
|
|
643
|
+
* A boolean value indicating whether the first node is empty.
|
|
644
|
+
*/
|
|
591
645
|
get isEmpty() {
|
|
592
646
|
if (this.isBox) {
|
|
593
647
|
return false;
|
|
@@ -607,20 +661,28 @@ class Nodes {
|
|
|
607
661
|
}
|
|
608
662
|
return true;
|
|
609
663
|
}
|
|
610
|
-
|
|
664
|
+
/**
|
|
665
|
+
* Returns a native node at the specified index.
|
|
666
|
+
*/
|
|
611
667
|
get(index) {
|
|
612
668
|
return this.nodeList[index];
|
|
613
669
|
}
|
|
614
|
-
|
|
670
|
+
/**
|
|
671
|
+
* Returns all native nodes.
|
|
672
|
+
*/
|
|
615
673
|
getAll() {
|
|
616
674
|
return this.nodeList;
|
|
617
675
|
}
|
|
618
|
-
|
|
676
|
+
/**
|
|
677
|
+
* Returns a new Nodes object that includes only the node at the specified index.
|
|
678
|
+
*/
|
|
619
679
|
eq(index) {
|
|
620
680
|
const node = this.get(index);
|
|
621
681
|
return new Nodes(node);
|
|
622
682
|
}
|
|
623
|
-
|
|
683
|
+
/**
|
|
684
|
+
* Executes a provided function once for each node.
|
|
685
|
+
*/
|
|
624
686
|
each(callback) {
|
|
625
687
|
const nodes = this.getAll();
|
|
626
688
|
for (let i = 0; i < nodes.length; i++) {
|
|
@@ -630,7 +692,9 @@ class Nodes {
|
|
|
630
692
|
}
|
|
631
693
|
return this;
|
|
632
694
|
}
|
|
633
|
-
|
|
695
|
+
/**
|
|
696
|
+
* Executes a provided function once for each element.
|
|
697
|
+
*/
|
|
634
698
|
eachElement(callback) {
|
|
635
699
|
const nodes = this.getAll();
|
|
636
700
|
for (let i = 0; i < nodes.length; i++) {
|
|
@@ -642,12 +706,16 @@ class Nodes {
|
|
|
642
706
|
}
|
|
643
707
|
return this;
|
|
644
708
|
}
|
|
645
|
-
|
|
709
|
+
/**
|
|
710
|
+
* Returns a new Nodes object with the nodes in reversed order.
|
|
711
|
+
*/
|
|
646
712
|
reverse() {
|
|
647
713
|
const nodes = this.getAll().reverse();
|
|
648
714
|
return new Nodes(nodes);
|
|
649
715
|
}
|
|
650
|
-
|
|
716
|
+
/**
|
|
717
|
+
* Tests whether the first node would be selected by the specified CSS selector.
|
|
718
|
+
*/
|
|
651
719
|
matches(selector) {
|
|
652
720
|
if (!this.isElement) {
|
|
653
721
|
return false;
|
|
@@ -655,13 +723,17 @@ class Nodes {
|
|
|
655
723
|
const element = this.get(0);
|
|
656
724
|
return element.matches(selector);
|
|
657
725
|
}
|
|
658
|
-
|
|
659
|
-
|
|
726
|
+
/**
|
|
727
|
+
* Returns a boolean value indicating whether the given node is a descendant of the first node,
|
|
728
|
+
* that is the node itself, one of its direct children (childNodes), one of the children's direct children, and so on.
|
|
729
|
+
*/
|
|
660
730
|
contains(otherNode) {
|
|
661
731
|
const element = this.get(0);
|
|
662
732
|
return element.contains(otherNode.get(0));
|
|
663
733
|
}
|
|
664
|
-
|
|
734
|
+
/**
|
|
735
|
+
* Returns a boolean value indicating whether the first node and a given node are siblings.
|
|
736
|
+
*/
|
|
665
737
|
isSibling(otherNode) {
|
|
666
738
|
if (this.length === 0) {
|
|
667
739
|
return false;
|
|
@@ -669,7 +741,9 @@ class Nodes {
|
|
|
669
741
|
const parent = this.get(0).parentNode;
|
|
670
742
|
return parent && parent === otherNode.parent().get(0);
|
|
671
743
|
}
|
|
672
|
-
|
|
744
|
+
/**
|
|
745
|
+
* Returns the descendants of the first node that match the specified CSS selector or node path.
|
|
746
|
+
*/
|
|
673
747
|
find(selector) {
|
|
674
748
|
if (typeof selector === 'string') {
|
|
675
749
|
const element = this.get(0);
|
|
@@ -685,7 +759,9 @@ class Nodes {
|
|
|
685
759
|
}
|
|
686
760
|
return node;
|
|
687
761
|
}
|
|
688
|
-
|
|
762
|
+
/**
|
|
763
|
+
* Traverses the first node and its parents (heading toward the document root) until it finds an element that matches the specified CSS selector.
|
|
764
|
+
*/
|
|
689
765
|
closest(selector) {
|
|
690
766
|
if (this.isText) {
|
|
691
767
|
const element = this.get(0).parentNode;
|
|
@@ -700,7 +776,9 @@ class Nodes {
|
|
|
700
776
|
const element = this.get(0);
|
|
701
777
|
return new Nodes(element.closest(selector));
|
|
702
778
|
}
|
|
703
|
-
|
|
779
|
+
/**
|
|
780
|
+
* Traverses the first node and its parents until it finds a block element.
|
|
781
|
+
*/
|
|
704
782
|
closestBlock() {
|
|
705
783
|
let node = this.eq(0);
|
|
706
784
|
while (node.length > 0) {
|
|
@@ -714,7 +792,9 @@ class Nodes {
|
|
|
714
792
|
}
|
|
715
793
|
return node;
|
|
716
794
|
}
|
|
717
|
-
|
|
795
|
+
/**
|
|
796
|
+
* Traverses the first node and its parents until it finds an operable block.
|
|
797
|
+
*/
|
|
718
798
|
closestOperableBlock() {
|
|
719
799
|
const boxNode = this.closest('lake-box');
|
|
720
800
|
const block = boxNode.length > 0 ? boxNode.closestBlock() : this.closestBlock();
|
|
@@ -730,11 +810,15 @@ class Nodes {
|
|
|
730
810
|
}
|
|
731
811
|
return block;
|
|
732
812
|
}
|
|
733
|
-
|
|
813
|
+
/**
|
|
814
|
+
* Traverses the first node and its parents until it finds a div element which contenteditable attribute is true.
|
|
815
|
+
*/
|
|
734
816
|
closestContainer() {
|
|
735
817
|
return this.closest('div[contenteditable="true"]');
|
|
736
818
|
}
|
|
737
|
-
|
|
819
|
+
/**
|
|
820
|
+
* Traverses the first node and its parents until it finds an element which can scroll.
|
|
821
|
+
*/
|
|
738
822
|
closestScroller() {
|
|
739
823
|
let parent = this.eq(0);
|
|
740
824
|
while (parent.length > 0) {
|
|
@@ -745,32 +829,44 @@ class Nodes {
|
|
|
745
829
|
}
|
|
746
830
|
return new Nodes();
|
|
747
831
|
}
|
|
748
|
-
|
|
832
|
+
/**
|
|
833
|
+
* Returns the parent of the first node.
|
|
834
|
+
*/
|
|
749
835
|
parent() {
|
|
750
836
|
const node = this.get(0);
|
|
751
837
|
return new Nodes(node.parentNode);
|
|
752
838
|
}
|
|
753
|
-
|
|
839
|
+
/**
|
|
840
|
+
* Returns the immediately preceding sibling of the first node.
|
|
841
|
+
*/
|
|
754
842
|
prev() {
|
|
755
843
|
const node = this.get(0);
|
|
756
844
|
return new Nodes(node.previousSibling);
|
|
757
845
|
}
|
|
758
|
-
|
|
846
|
+
/**
|
|
847
|
+
* Returns the immediately following sibling of the first node.
|
|
848
|
+
*/
|
|
759
849
|
next() {
|
|
760
850
|
const node = this.get(0);
|
|
761
851
|
return new Nodes(node.nextSibling);
|
|
762
852
|
}
|
|
763
|
-
|
|
853
|
+
/**
|
|
854
|
+
* Returns the first child of the first node.
|
|
855
|
+
*/
|
|
764
856
|
first() {
|
|
765
857
|
const element = this.get(0);
|
|
766
858
|
return new Nodes(element.firstChild);
|
|
767
859
|
}
|
|
768
|
-
|
|
860
|
+
/**
|
|
861
|
+
* Returns the last child of the first node.
|
|
862
|
+
*/
|
|
769
863
|
last() {
|
|
770
864
|
const element = this.get(0);
|
|
771
865
|
return new Nodes(element.lastChild);
|
|
772
866
|
}
|
|
773
|
-
|
|
867
|
+
/**
|
|
868
|
+
* Returns a number indicating the position of the first node relative to its sibling nodes.
|
|
869
|
+
*/
|
|
774
870
|
index() {
|
|
775
871
|
let i = -1;
|
|
776
872
|
let sibling = this.get(0);
|
|
@@ -780,7 +876,9 @@ class Nodes {
|
|
|
780
876
|
}
|
|
781
877
|
return i;
|
|
782
878
|
}
|
|
783
|
-
|
|
879
|
+
/**
|
|
880
|
+
* Returns the path of the first node.
|
|
881
|
+
*/
|
|
784
882
|
path() {
|
|
785
883
|
const path = [];
|
|
786
884
|
let node = this.eq(0);
|
|
@@ -800,7 +898,9 @@ class Nodes {
|
|
|
800
898
|
}
|
|
801
899
|
return path.reverse();
|
|
802
900
|
}
|
|
803
|
-
|
|
901
|
+
/**
|
|
902
|
+
* Returns a list which contains all of the child nodes of the first node.
|
|
903
|
+
*/
|
|
804
904
|
children() {
|
|
805
905
|
const childList = [];
|
|
806
906
|
let child = this.first();
|
|
@@ -810,7 +910,9 @@ class Nodes {
|
|
|
810
910
|
}
|
|
811
911
|
return childList;
|
|
812
912
|
}
|
|
813
|
-
|
|
913
|
+
/**
|
|
914
|
+
* Returns a generator that iterates over the descendants of the first node.
|
|
915
|
+
*/
|
|
814
916
|
*getWalker() {
|
|
815
917
|
function* iterate(node) {
|
|
816
918
|
if (node.isBox) {
|
|
@@ -828,7 +930,9 @@ class Nodes {
|
|
|
828
930
|
yield node;
|
|
829
931
|
}
|
|
830
932
|
}
|
|
831
|
-
|
|
933
|
+
/**
|
|
934
|
+
* Sets up an event listener for each element.
|
|
935
|
+
*/
|
|
832
936
|
on(type, listener) {
|
|
833
937
|
return this.eachElement(element => {
|
|
834
938
|
element.addEventListener(type, listener, false);
|
|
@@ -842,15 +946,17 @@ class Nodes {
|
|
|
842
946
|
});
|
|
843
947
|
});
|
|
844
948
|
}
|
|
845
|
-
|
|
949
|
+
/**
|
|
950
|
+
* Removes event listeners previously registered with on() method.
|
|
951
|
+
*/
|
|
846
952
|
off(type, listener) {
|
|
847
953
|
return this.eachElement(element => {
|
|
848
954
|
var _a;
|
|
849
955
|
const elementId = element.lakeId;
|
|
850
|
-
const eventItems = (_a = eventData[elementId]) !== null && _a !==
|
|
956
|
+
const eventItems = (_a = eventData[elementId]) !== null && _a !== void 0 ? _a : [];
|
|
851
957
|
for (let i = 0; i < eventItems.length; i++) {
|
|
852
958
|
const item = eventItems[i];
|
|
853
|
-
if (!type || type === item.type && (!listener || listener === item.listener)) {
|
|
959
|
+
if (!type || (type === item.type && (!listener || listener === item.listener))) {
|
|
854
960
|
element.removeEventListener(item.type, item.listener, false);
|
|
855
961
|
eventItems[i] = {
|
|
856
962
|
type: '',
|
|
@@ -861,41 +967,53 @@ class Nodes {
|
|
|
861
967
|
eventData[elementId] = eventItems.filter((item) => item.type !== '');
|
|
862
968
|
});
|
|
863
969
|
}
|
|
864
|
-
|
|
970
|
+
/**
|
|
971
|
+
* Executes all event listeners attached to all nodes for the given event type.
|
|
972
|
+
*/
|
|
865
973
|
emit(type, event) {
|
|
866
974
|
return this.eachElement(element => {
|
|
867
975
|
const elementId = element.lakeId;
|
|
868
976
|
const eventItems = eventData[elementId];
|
|
869
977
|
for (const item of eventItems) {
|
|
870
978
|
if (item.type === type) {
|
|
871
|
-
item.listener(event !== null && event !==
|
|
979
|
+
item.listener(event !== null && event !== void 0 ? event : new Event(type));
|
|
872
980
|
}
|
|
873
981
|
}
|
|
874
982
|
});
|
|
875
983
|
}
|
|
876
|
-
|
|
984
|
+
/**
|
|
985
|
+
* Returns all event listeners attached to the node at the specified index.
|
|
986
|
+
*/
|
|
877
987
|
getEventListeners(index) {
|
|
878
988
|
const elementId = this.get(index).lakeId;
|
|
879
989
|
return eventData[elementId];
|
|
880
990
|
}
|
|
881
|
-
|
|
991
|
+
/**
|
|
992
|
+
* Sets focus on the specified node, if it can be focused.
|
|
993
|
+
*/
|
|
882
994
|
focus() {
|
|
883
995
|
const element = this.get(0);
|
|
884
996
|
element.focus();
|
|
885
997
|
return this;
|
|
886
998
|
}
|
|
887
|
-
|
|
999
|
+
/**
|
|
1000
|
+
* Removes focus from the specified node.
|
|
1001
|
+
*/
|
|
888
1002
|
blur() {
|
|
889
1003
|
const element = this.get(0);
|
|
890
1004
|
element.blur();
|
|
891
1005
|
return this;
|
|
892
1006
|
}
|
|
893
|
-
|
|
1007
|
+
/**
|
|
1008
|
+
* Returns a copy of the first node. If deep is true, the copy also includes the node's descendants.
|
|
1009
|
+
*/
|
|
894
1010
|
clone(deep = false) {
|
|
895
1011
|
const node = this.get(0);
|
|
896
1012
|
return new Nodes(node.cloneNode(deep));
|
|
897
1013
|
}
|
|
898
|
-
|
|
1014
|
+
/**
|
|
1015
|
+
* Returns a boolean value indicating whether the first node has the specified attribute or not.
|
|
1016
|
+
*/
|
|
899
1017
|
hasAttr(attributeName) {
|
|
900
1018
|
const element = this.get(0);
|
|
901
1019
|
return element.hasAttribute(attributeName);
|
|
@@ -910,24 +1028,30 @@ class Nodes {
|
|
|
910
1028
|
}
|
|
911
1029
|
if (value === undefined) {
|
|
912
1030
|
const element = this.get(0);
|
|
913
|
-
return (_a = element.getAttribute(attributeName)) !== null && _a !==
|
|
1031
|
+
return (_a = element.getAttribute(attributeName)) !== null && _a !== void 0 ? _a : '';
|
|
914
1032
|
}
|
|
915
1033
|
return this.eachElement(element => {
|
|
916
1034
|
element.setAttribute(attributeName, value);
|
|
917
1035
|
});
|
|
918
1036
|
}
|
|
919
|
-
|
|
1037
|
+
/**
|
|
1038
|
+
* Removes the attribute with the specified name from every element.
|
|
1039
|
+
*/
|
|
920
1040
|
removeAttr(attributeName) {
|
|
921
1041
|
return this.eachElement(element => {
|
|
922
1042
|
element.removeAttribute(attributeName);
|
|
923
1043
|
});
|
|
924
1044
|
}
|
|
925
|
-
|
|
1045
|
+
/**
|
|
1046
|
+
* Returns a boolean value indicating whether the first node has the specified class or not.
|
|
1047
|
+
*/
|
|
926
1048
|
hasClass(className) {
|
|
927
1049
|
const element = this.get(0);
|
|
928
1050
|
return inString(element.className, className, ' ');
|
|
929
1051
|
}
|
|
930
|
-
|
|
1052
|
+
/**
|
|
1053
|
+
* Adds the given class to every element.
|
|
1054
|
+
*/
|
|
931
1055
|
addClass(className) {
|
|
932
1056
|
if (Array.isArray(className)) {
|
|
933
1057
|
for (const name of className) {
|
|
@@ -942,7 +1066,9 @@ class Nodes {
|
|
|
942
1066
|
element.classList.add(className);
|
|
943
1067
|
});
|
|
944
1068
|
}
|
|
945
|
-
|
|
1069
|
+
/**
|
|
1070
|
+
* Removes the given class from every element.
|
|
1071
|
+
*/
|
|
946
1072
|
removeClass(className) {
|
|
947
1073
|
if (Array.isArray(className)) {
|
|
948
1074
|
for (const name of className) {
|
|
@@ -960,8 +1086,10 @@ class Nodes {
|
|
|
960
1086
|
}
|
|
961
1087
|
});
|
|
962
1088
|
}
|
|
963
|
-
|
|
964
|
-
|
|
1089
|
+
/**
|
|
1090
|
+
* Returns the value of the given CSS property of the first node,
|
|
1091
|
+
* after applying active stylesheets and resolving any basic computation this value may contain.
|
|
1092
|
+
*/
|
|
965
1093
|
computedCSS(propertyName) {
|
|
966
1094
|
const element = this.get(0);
|
|
967
1095
|
return getCSS(element, propertyName);
|
|
@@ -984,28 +1112,38 @@ class Nodes {
|
|
|
984
1112
|
}
|
|
985
1113
|
});
|
|
986
1114
|
}
|
|
987
|
-
|
|
1115
|
+
/**
|
|
1116
|
+
* Returns the width of of the first node.
|
|
1117
|
+
*/
|
|
988
1118
|
width() {
|
|
989
1119
|
const element = this.get(0);
|
|
990
1120
|
return element.offsetWidth;
|
|
991
1121
|
}
|
|
992
|
-
|
|
1122
|
+
/**
|
|
1123
|
+
* Returns the interior width of the first node, which does not include padding.
|
|
1124
|
+
*/
|
|
993
1125
|
innerWidth() {
|
|
994
1126
|
const paddingLeft = Number.parseInt(this.computedCSS('padding-left'), 10) || 0;
|
|
995
1127
|
const paddingRight = Number.parseInt(this.computedCSS('padding-right'), 10) || 0;
|
|
996
1128
|
return this.width() - paddingLeft - paddingRight;
|
|
997
1129
|
}
|
|
998
|
-
|
|
1130
|
+
/**
|
|
1131
|
+
* Returns the height of of the first node.
|
|
1132
|
+
*/
|
|
999
1133
|
height() {
|
|
1000
1134
|
const element = this.get(0);
|
|
1001
1135
|
return element.offsetHeight;
|
|
1002
1136
|
}
|
|
1003
|
-
|
|
1137
|
+
/**
|
|
1138
|
+
* Displays all nodes.
|
|
1139
|
+
*/
|
|
1004
1140
|
show(displayType = 'block') {
|
|
1005
1141
|
this.css('display', displayType);
|
|
1006
1142
|
return this;
|
|
1007
1143
|
}
|
|
1008
|
-
|
|
1144
|
+
/**
|
|
1145
|
+
* Hides all nodes.
|
|
1146
|
+
*/
|
|
1009
1147
|
hide() {
|
|
1010
1148
|
this.css('display', 'none');
|
|
1011
1149
|
return this;
|
|
@@ -1024,7 +1162,7 @@ class Nodes {
|
|
|
1024
1162
|
if (value === undefined) {
|
|
1025
1163
|
const node = this.get(0);
|
|
1026
1164
|
if (this.isText) {
|
|
1027
|
-
return (_a = node.nodeValue) !== null && _a !==
|
|
1165
|
+
return (_a = node.nodeValue) !== null && _a !== void 0 ? _a : '';
|
|
1028
1166
|
}
|
|
1029
1167
|
const element = node;
|
|
1030
1168
|
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/innerText
|
|
@@ -1043,17 +1181,23 @@ class Nodes {
|
|
|
1043
1181
|
element.value = value;
|
|
1044
1182
|
});
|
|
1045
1183
|
}
|
|
1046
|
-
|
|
1184
|
+
/**
|
|
1185
|
+
* Returns the HTML string describing the first node including its descendants.
|
|
1186
|
+
*/
|
|
1047
1187
|
outerHTML() {
|
|
1048
1188
|
const element = this.get(0);
|
|
1049
1189
|
return element.outerHTML;
|
|
1050
1190
|
}
|
|
1051
|
-
|
|
1191
|
+
/**
|
|
1192
|
+
* Removes all child nodes for each element.
|
|
1193
|
+
*/
|
|
1052
1194
|
empty() {
|
|
1053
1195
|
this.html('');
|
|
1054
1196
|
return this;
|
|
1055
1197
|
}
|
|
1056
|
-
|
|
1198
|
+
/**
|
|
1199
|
+
* Inserts the specified content just inside the first node, before its first child.
|
|
1200
|
+
*/
|
|
1057
1201
|
prepend(content) {
|
|
1058
1202
|
const element = this.get(0);
|
|
1059
1203
|
if (typeof content === 'string') {
|
|
@@ -1079,7 +1223,9 @@ class Nodes {
|
|
|
1079
1223
|
}
|
|
1080
1224
|
return this;
|
|
1081
1225
|
}
|
|
1082
|
-
|
|
1226
|
+
/**
|
|
1227
|
+
* Inserts the specified content just inside the first node, after its last child.
|
|
1228
|
+
*/
|
|
1083
1229
|
append(content) {
|
|
1084
1230
|
const element = this.get(0);
|
|
1085
1231
|
if (typeof content === 'string') {
|
|
@@ -1095,7 +1241,9 @@ class Nodes {
|
|
|
1095
1241
|
element.appendChild(content);
|
|
1096
1242
|
return this;
|
|
1097
1243
|
}
|
|
1098
|
-
|
|
1244
|
+
/**
|
|
1245
|
+
* Inserts the specified content before the first node.
|
|
1246
|
+
*/
|
|
1099
1247
|
before(content) {
|
|
1100
1248
|
const node = this.get(0);
|
|
1101
1249
|
if (!node.parentNode) {
|
|
@@ -1114,7 +1262,9 @@ class Nodes {
|
|
|
1114
1262
|
node.parentNode.insertBefore(content, node);
|
|
1115
1263
|
return this;
|
|
1116
1264
|
}
|
|
1117
|
-
|
|
1265
|
+
/**
|
|
1266
|
+
* Inserts the specified content after the first node.
|
|
1267
|
+
*/
|
|
1118
1268
|
after(content) {
|
|
1119
1269
|
const node = this.get(0);
|
|
1120
1270
|
if (!node.parentNode) {
|
|
@@ -1143,7 +1293,9 @@ class Nodes {
|
|
|
1143
1293
|
}
|
|
1144
1294
|
return this;
|
|
1145
1295
|
}
|
|
1146
|
-
|
|
1296
|
+
/**
|
|
1297
|
+
* Replaces the first node with the given new content.
|
|
1298
|
+
*/
|
|
1147
1299
|
replaceWith(newContent) {
|
|
1148
1300
|
const node = this.get(0);
|
|
1149
1301
|
if (!node.parentNode) {
|
|
@@ -1159,7 +1311,9 @@ class Nodes {
|
|
|
1159
1311
|
node.parentNode.replaceChild(target, node);
|
|
1160
1312
|
return this;
|
|
1161
1313
|
}
|
|
1162
|
-
|
|
1314
|
+
/**
|
|
1315
|
+
* Removes all nodes from the DOM.
|
|
1316
|
+
*/
|
|
1163
1317
|
remove(keepChildren = false) {
|
|
1164
1318
|
this.each(node => {
|
|
1165
1319
|
if (!node.parentNode) {
|
|
@@ -1177,7 +1331,9 @@ class Nodes {
|
|
|
1177
1331
|
});
|
|
1178
1332
|
return this;
|
|
1179
1333
|
}
|
|
1180
|
-
|
|
1334
|
+
/**
|
|
1335
|
+
* Splits the first node, which must be a text node, into two nodes at the specified offset, keeping both as siblings in the tree.
|
|
1336
|
+
*/
|
|
1181
1337
|
splitText(offset) {
|
|
1182
1338
|
if (!this.isText) {
|
|
1183
1339
|
return new Nodes();
|
|
@@ -1186,7 +1342,9 @@ class Nodes {
|
|
|
1186
1342
|
const newNode = node.splitText(offset);
|
|
1187
1343
|
return new Nodes(newNode);
|
|
1188
1344
|
}
|
|
1189
|
-
|
|
1345
|
+
/**
|
|
1346
|
+
* Returns information about the first node, which is used for debugging.
|
|
1347
|
+
*/
|
|
1190
1348
|
toString() {
|
|
1191
1349
|
if (this.length === 0) {
|
|
1192
1350
|
return '';
|
|
@@ -1198,13 +1356,19 @@ class Nodes {
|
|
|
1198
1356
|
}
|
|
1199
1357
|
return `node (${node.lakeId}): ${nodeValue}`;
|
|
1200
1358
|
}
|
|
1201
|
-
|
|
1359
|
+
/**
|
|
1360
|
+
* Prints information about the first node, which is used for debugging.
|
|
1361
|
+
*/
|
|
1202
1362
|
info() {
|
|
1203
1363
|
debug(this.toString());
|
|
1204
1364
|
}
|
|
1205
1365
|
}
|
|
1206
1366
|
|
|
1207
|
-
|
|
1367
|
+
/**
|
|
1368
|
+
* Returns a Nodes object representing a collection of the nodes.
|
|
1369
|
+
* This function is similar to jQuery, but its implementation is very simple.
|
|
1370
|
+
* It is designed for simplifying DOM manipulation.
|
|
1371
|
+
*/
|
|
1208
1372
|
function query(content) {
|
|
1209
1373
|
if (content instanceof Nodes) {
|
|
1210
1374
|
return content;
|
|
@@ -1222,10 +1386,13 @@ const characterMap = new Map([
|
|
|
1222
1386
|
]);
|
|
1223
1387
|
// Converts all of the reserved characters in the specified string to HTML entities.
|
|
1224
1388
|
function encode(value) {
|
|
1225
|
-
return value.replace(/[&<>"\xA0]/g, match => { var _a; return (_a = characterMap.get(match)) !== null && _a !==
|
|
1389
|
+
return value.replace(/[&<>"\xA0]/g, match => { var _a; return (_a = characterMap.get(match)) !== null && _a !== void 0 ? _a : ''; });
|
|
1226
1390
|
}
|
|
1227
1391
|
|
|
1228
|
-
|
|
1392
|
+
/**
|
|
1393
|
+
* A tag function that converts all of the reserved characters in the specified string to HTML entities.
|
|
1394
|
+
* It also removes empty spaces at the beginning and end of lines.
|
|
1395
|
+
*/
|
|
1229
1396
|
function template(strings, ...keys) {
|
|
1230
1397
|
let content = strings[0];
|
|
1231
1398
|
for (let i = 0; i < keys.length; i++) {
|
|
@@ -1235,82 +1402,170 @@ function template(strings, ...keys) {
|
|
|
1235
1402
|
// Don't escape special characters in the template.
|
|
1236
1403
|
content += strings[i + 1];
|
|
1237
1404
|
}
|
|
1238
|
-
content = content
|
|
1239
|
-
replace(/^\s+/gm, '')
|
|
1240
|
-
replace(/\s+$/gm, '')
|
|
1241
|
-
replace(/[\r\n]/g, '');
|
|
1405
|
+
content = content
|
|
1406
|
+
.replace(/^\s+/gm, '')
|
|
1407
|
+
.replace(/\s+$/gm, '')
|
|
1408
|
+
.replace(/[\r\n]/g, '');
|
|
1242
1409
|
return content;
|
|
1243
1410
|
}
|
|
1244
1411
|
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1412
|
+
const boxInstances = new Map();
|
|
1413
|
+
function getInstanceMap(id) {
|
|
1414
|
+
let instanceMap = boxInstances.get(id);
|
|
1415
|
+
if (!instanceMap) {
|
|
1416
|
+
instanceMap = new Map();
|
|
1417
|
+
boxInstances.set(id, instanceMap);
|
|
1418
|
+
return instanceMap;
|
|
1249
1419
|
}
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1420
|
+
return instanceMap;
|
|
1421
|
+
}
|
|
1422
|
+
|
|
1423
|
+
const boxes = new Map();
|
|
1424
|
+
|
|
1425
|
+
const editors = new Map();
|
|
1426
|
+
|
|
1427
|
+
// Creates a Base64-encoded ASCII string from a string.
|
|
1428
|
+
function toBase64(value) {
|
|
1429
|
+
const encoder = new TextEncoder();
|
|
1430
|
+
const byteArray = encoder.encode(value);
|
|
1431
|
+
let binaryString = '';
|
|
1432
|
+
byteArray.forEach(byte => {
|
|
1433
|
+
binaryString += String.fromCharCode(byte);
|
|
1434
|
+
});
|
|
1435
|
+
return window.btoa(binaryString);
|
|
1436
|
+
}
|
|
1437
|
+
|
|
1438
|
+
// Decodes a string of data which has been encoded using Base64 encoding.
|
|
1439
|
+
function fromBase64(value) {
|
|
1440
|
+
const binaryString = window.atob(value);
|
|
1441
|
+
const byteArray = new Uint8Array(binaryString.length);
|
|
1442
|
+
for (let i = 0; i < binaryString.length; i++) {
|
|
1443
|
+
byteArray[i] = binaryString.charCodeAt(i);
|
|
1253
1444
|
}
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
});
|
|
1266
|
-
}
|
|
1267
|
-
child = child.next();
|
|
1268
|
-
}
|
|
1269
|
-
return new Nodes(nodeList);
|
|
1445
|
+
const decoder = new TextDecoder();
|
|
1446
|
+
return decoder.decode(byteArray);
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1449
|
+
function visibleInfo(target) {
|
|
1450
|
+
let rect;
|
|
1451
|
+
let viewport;
|
|
1452
|
+
if (target instanceof Nodes) {
|
|
1453
|
+
const nativeNode = target.get(0);
|
|
1454
|
+
rect = nativeNode.getBoundingClientRect();
|
|
1455
|
+
viewport = target.closestScroller();
|
|
1270
1456
|
}
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1457
|
+
else {
|
|
1458
|
+
rect = target.get().getBoundingClientRect();
|
|
1459
|
+
viewport = target.commonAncestor.closestScroller();
|
|
1460
|
+
}
|
|
1461
|
+
let left = rect.left;
|
|
1462
|
+
let right = rect.right;
|
|
1463
|
+
let top = rect.top;
|
|
1464
|
+
let bottom = rect.bottom;
|
|
1465
|
+
let viewportWidth = window.innerWidth;
|
|
1466
|
+
let viewportHeight = window.innerHeight;
|
|
1467
|
+
if (viewport.length > 0) {
|
|
1468
|
+
const nativeViewport = viewport.get(0);
|
|
1469
|
+
const viewportRect = nativeViewport.getBoundingClientRect();
|
|
1470
|
+
const offsetLeft = viewportRect.x;
|
|
1471
|
+
const offsetTop = viewportRect.y;
|
|
1472
|
+
left -= offsetLeft;
|
|
1473
|
+
right -= offsetLeft;
|
|
1474
|
+
top -= offsetTop;
|
|
1475
|
+
bottom -= offsetTop;
|
|
1476
|
+
viewportWidth = viewportRect.width;
|
|
1477
|
+
viewportHeight = viewportRect.height;
|
|
1478
|
+
}
|
|
1479
|
+
let leftEdge = 0;
|
|
1480
|
+
if (left < 0) {
|
|
1481
|
+
leftEdge = -1;
|
|
1482
|
+
}
|
|
1483
|
+
else if (viewportWidth - left < 0) {
|
|
1484
|
+
leftEdge = 1;
|
|
1485
|
+
}
|
|
1486
|
+
let rightEdge = 0;
|
|
1487
|
+
if (right < 0) {
|
|
1488
|
+
rightEdge = -1;
|
|
1276
1489
|
}
|
|
1490
|
+
else if (viewportWidth - right < 0) {
|
|
1491
|
+
rightEdge = 1;
|
|
1492
|
+
}
|
|
1493
|
+
let topEdge = 0;
|
|
1494
|
+
if (top < 0) {
|
|
1495
|
+
topEdge = -1;
|
|
1496
|
+
}
|
|
1497
|
+
else if (viewportHeight - top < 0) {
|
|
1498
|
+
topEdge = 1;
|
|
1499
|
+
}
|
|
1500
|
+
let bottomEdge = 0;
|
|
1501
|
+
if (bottom < 0) {
|
|
1502
|
+
bottomEdge = -1;
|
|
1503
|
+
}
|
|
1504
|
+
else if (viewportHeight - bottom < 0) {
|
|
1505
|
+
bottomEdge = 1;
|
|
1506
|
+
}
|
|
1507
|
+
return {
|
|
1508
|
+
left: leftEdge,
|
|
1509
|
+
right: rightEdge,
|
|
1510
|
+
top: topEdge,
|
|
1511
|
+
bottom: bottomEdge,
|
|
1512
|
+
};
|
|
1277
1513
|
}
|
|
1278
1514
|
|
|
1279
|
-
|
|
1515
|
+
/**
|
|
1516
|
+
* The Range interface represents a fragment of a document that can contain nodes and parts of text nodes.
|
|
1517
|
+
* Its interface is similar to the native Range, with some additional properties and methods specifically designed for more efficient manipulation.
|
|
1518
|
+
*/
|
|
1280
1519
|
class Range {
|
|
1281
1520
|
constructor(range) {
|
|
1282
|
-
this.range = range !== null && range !==
|
|
1521
|
+
this.range = range !== null && range !== void 0 ? range : document.createRange();
|
|
1283
1522
|
}
|
|
1284
|
-
|
|
1523
|
+
/**
|
|
1524
|
+
* A node within which the range starts.
|
|
1525
|
+
*/
|
|
1285
1526
|
get startNode() {
|
|
1286
1527
|
return new Nodes(this.range.startContainer);
|
|
1287
1528
|
}
|
|
1288
|
-
|
|
1529
|
+
/**
|
|
1530
|
+
* A number representing where in the startNode the range starts.
|
|
1531
|
+
*/
|
|
1289
1532
|
get startOffset() {
|
|
1290
1533
|
return this.range.startOffset;
|
|
1291
1534
|
}
|
|
1292
|
-
|
|
1535
|
+
/**
|
|
1536
|
+
* A node within which the range ends.
|
|
1537
|
+
*/
|
|
1293
1538
|
get endNode() {
|
|
1294
1539
|
return new Nodes(this.range.endContainer);
|
|
1295
1540
|
}
|
|
1296
|
-
|
|
1541
|
+
/**
|
|
1542
|
+
* A number representing where in the endNode the range ends.
|
|
1543
|
+
*/
|
|
1297
1544
|
get endOffset() {
|
|
1298
1545
|
return this.range.endOffset;
|
|
1299
1546
|
}
|
|
1300
|
-
|
|
1547
|
+
/**
|
|
1548
|
+
* The deepest — or furthest down the document tree — node that contains both boundary points of the range.
|
|
1549
|
+
*/
|
|
1301
1550
|
get commonAncestor() {
|
|
1302
1551
|
return new Nodes(this.range.commonAncestorContainer);
|
|
1303
1552
|
}
|
|
1304
|
-
|
|
1553
|
+
/**
|
|
1554
|
+
* A boolean value indicating whether the range's start and end points are at the same position.
|
|
1555
|
+
*/
|
|
1305
1556
|
get isCollapsed() {
|
|
1306
1557
|
return this.range.collapsed;
|
|
1307
1558
|
}
|
|
1308
|
-
|
|
1559
|
+
/**
|
|
1560
|
+
* A boolean value indicating whether the range's start point is in a box.
|
|
1561
|
+
*/
|
|
1309
1562
|
get isBox() {
|
|
1310
1563
|
const boxNode = this.commonAncestor.closest('lake-box');
|
|
1311
1564
|
return boxNode.length > 0;
|
|
1312
1565
|
}
|
|
1313
|
-
|
|
1566
|
+
/**
|
|
1567
|
+
* A boolean value indicating whether the commonAncestor is in the start position of a box.
|
|
1568
|
+
*/
|
|
1314
1569
|
// case 1: <lake-box><span class="lake-box-strip">|</span><div class="lake-box-container"></div> ...
|
|
1315
1570
|
// case 2: <lake-box><span class="lake-box-strip"></span>|<div class="lake-box-container"></div> ...
|
|
1316
1571
|
// case 3: <lake-box>|<span class="lake-box-strip"></span><div class="lake-box-container"></div> ...
|
|
@@ -1322,7 +1577,9 @@ class Range {
|
|
|
1322
1577
|
const boxContainer = boxNode.find('.lake-box-container');
|
|
1323
1578
|
return this.compareBeforeNode(boxContainer) >= 0;
|
|
1324
1579
|
}
|
|
1325
|
-
|
|
1580
|
+
/**
|
|
1581
|
+
* A boolean value indicating whether the commonAncestor is in the center position of a box.
|
|
1582
|
+
*/
|
|
1326
1583
|
// case 1: ... <div class="lake-box-container"><div>|</div></div> ...
|
|
1327
1584
|
// case 2: ... <div class="lake-box-container"><div></div>|</div> ...
|
|
1328
1585
|
get isBoxCenter() {
|
|
@@ -1335,7 +1592,9 @@ class Range {
|
|
|
1335
1592
|
// case: ... <div class="lake-box-container">|<div></div></div> ...
|
|
1336
1593
|
return this.isCollapsed && this.startNode.get(0) === boxContainer.get(0) && this.startOffset === 0;
|
|
1337
1594
|
}
|
|
1338
|
-
|
|
1595
|
+
/**
|
|
1596
|
+
* A boolean value indicating whether commonAncestor is in the end position of a box.
|
|
1597
|
+
*/
|
|
1339
1598
|
// case 1: ... <div class="lake-box-container"></div><span class="lake-box-strip">|</span></lake-box>
|
|
1340
1599
|
// case 2: ... <div class="lake-box-container"></div>|<span class="lake-box-strip"></span></lake-box>
|
|
1341
1600
|
// case 3: ... <div class="lake-box-container"></div><span class="lake-box-strip"></span>|</lake-box>
|
|
@@ -1347,7 +1606,9 @@ class Range {
|
|
|
1347
1606
|
const boxContainer = boxNode.find('.lake-box-container');
|
|
1348
1607
|
return this.compareAfterNode(boxContainer) <= 0;
|
|
1349
1608
|
}
|
|
1350
|
-
|
|
1609
|
+
/**
|
|
1610
|
+
* A boolean value indicating whether commonAncestor is inside the container of a box.
|
|
1611
|
+
*/
|
|
1351
1612
|
// case 1: ... <div class="lake-box-container"><div>|</div></div> ...
|
|
1352
1613
|
// case 2: ... <div class="lake-box-container"><div></div>|</div> ...
|
|
1353
1614
|
get isInsideBox() {
|
|
@@ -1358,32 +1619,38 @@ class Range {
|
|
|
1358
1619
|
const boxContainer = boxNode.find('.lake-box-container');
|
|
1359
1620
|
// Returns false when the box was selected.
|
|
1360
1621
|
// case: ... <div class="lake-box-container">|<div></div></div> ...
|
|
1361
|
-
if (this.isCollapsed
|
|
1362
|
-
this.startNode.get(0) === boxContainer.get(0)
|
|
1363
|
-
this.startOffset === 0) {
|
|
1622
|
+
if (this.isCollapsed
|
|
1623
|
+
&& this.startNode.get(0) === boxContainer.get(0)
|
|
1624
|
+
&& this.startOffset === 0) {
|
|
1364
1625
|
return false;
|
|
1365
1626
|
}
|
|
1366
1627
|
return this.compareBeforeNode(boxContainer) < 0 && this.compareAfterNode(boxContainer) > 0;
|
|
1367
1628
|
}
|
|
1368
|
-
|
|
1629
|
+
/**
|
|
1630
|
+
* A boolean value indicating whether the range is inoperative.
|
|
1631
|
+
*/
|
|
1369
1632
|
get isInoperative() {
|
|
1370
1633
|
if (this.commonAncestor.isOutside) {
|
|
1371
1634
|
return true;
|
|
1372
1635
|
}
|
|
1373
1636
|
const startBlock = this.startNode.closest('td');
|
|
1374
1637
|
const endBlock = this.endNode.closest('td');
|
|
1375
|
-
if (startBlock.length > 0
|
|
1376
|
-
endBlock.length > 0
|
|
1377
|
-
startBlock.get(0) !== endBlock.get(0)) {
|
|
1638
|
+
if (startBlock.length > 0
|
|
1639
|
+
&& endBlock.length > 0
|
|
1640
|
+
&& startBlock.get(0) !== endBlock.get(0)) {
|
|
1378
1641
|
return true;
|
|
1379
1642
|
}
|
|
1380
1643
|
return false;
|
|
1381
1644
|
}
|
|
1382
|
-
|
|
1645
|
+
/**
|
|
1646
|
+
* Returns a native Range object from the range.
|
|
1647
|
+
*/
|
|
1383
1648
|
get() {
|
|
1384
1649
|
return this.range;
|
|
1385
1650
|
}
|
|
1386
|
-
|
|
1651
|
+
/**
|
|
1652
|
+
* Returns the size and position of the range.
|
|
1653
|
+
*/
|
|
1387
1654
|
getRect() {
|
|
1388
1655
|
const range = this.clone();
|
|
1389
1656
|
let rect;
|
|
@@ -1436,13 +1703,17 @@ class Range {
|
|
|
1436
1703
|
height: height > 0 ? height : 1,
|
|
1437
1704
|
});
|
|
1438
1705
|
}
|
|
1439
|
-
|
|
1440
|
-
|
|
1706
|
+
/**
|
|
1707
|
+
* Returns -1, 0, or 1 depending on whether the specified node is before, the same as, or after the range.
|
|
1708
|
+
* −1 if the point is before the range. 0 if the point is in the range. 1 if the point is after the range.
|
|
1709
|
+
*/
|
|
1441
1710
|
comparePoint(node, offset) {
|
|
1442
1711
|
return this.range.comparePoint(node.get(0), offset);
|
|
1443
1712
|
}
|
|
1444
|
-
|
|
1445
|
-
|
|
1713
|
+
/**
|
|
1714
|
+
* Returns -1, 0, or 1 depending on whether the beginning of the specified node is before, the same as, or after the range.
|
|
1715
|
+
* −1 if the beginning of the node is before the range. 0 if the beginning of the node is in the range. 1 if the beginning of the node is after the range.
|
|
1716
|
+
*/
|
|
1446
1717
|
compareBeforeNode(node) {
|
|
1447
1718
|
const targetRange = new Range();
|
|
1448
1719
|
if (node.isText) {
|
|
@@ -1454,13 +1725,15 @@ class Range {
|
|
|
1454
1725
|
targetRange.collapseToStart();
|
|
1455
1726
|
return this.comparePoint(targetRange.startNode, targetRange.startOffset);
|
|
1456
1727
|
}
|
|
1457
|
-
|
|
1458
|
-
|
|
1728
|
+
/**
|
|
1729
|
+
* Returns -1, 0, or 1 depending on whether the end of the specified node is before, the same as, or after the range.
|
|
1730
|
+
* −1 if the end of the node is before the range. 0 if the end of the node is in the range. 1 if the end of the node is after the range.
|
|
1731
|
+
*/
|
|
1459
1732
|
compareAfterNode(node) {
|
|
1460
1733
|
var _a;
|
|
1461
1734
|
const targetRange = new Range();
|
|
1462
1735
|
if (node.isText) {
|
|
1463
|
-
const nodeValue = (_a = node.get(0).nodeValue) !== null && _a !==
|
|
1736
|
+
const nodeValue = (_a = node.get(0).nodeValue) !== null && _a !== void 0 ? _a : '';
|
|
1464
1737
|
targetRange.setStart(node, nodeValue.length);
|
|
1465
1738
|
}
|
|
1466
1739
|
else {
|
|
@@ -1469,51 +1742,75 @@ class Range {
|
|
|
1469
1742
|
targetRange.collapseToStart();
|
|
1470
1743
|
return this.comparePoint(targetRange.startNode, targetRange.startOffset);
|
|
1471
1744
|
}
|
|
1472
|
-
|
|
1745
|
+
/**
|
|
1746
|
+
* Returns a boolean value indicating whether the specified node is part of the range or intersects the range.
|
|
1747
|
+
*/
|
|
1473
1748
|
intersectsNode(node) {
|
|
1474
1749
|
return this.range.intersectsNode(node.get(0));
|
|
1475
1750
|
}
|
|
1476
|
-
|
|
1751
|
+
/**
|
|
1752
|
+
* Sets the start position of the range.
|
|
1753
|
+
*/
|
|
1477
1754
|
setStart(node, offset) {
|
|
1478
1755
|
this.range.setStart(node.get(0), offset);
|
|
1479
1756
|
}
|
|
1480
|
-
|
|
1757
|
+
/**
|
|
1758
|
+
* Sets the start position of the range to the beginning of the specified node.
|
|
1759
|
+
*/
|
|
1481
1760
|
setStartBefore(node) {
|
|
1482
1761
|
this.range.setStartBefore(node.get(0));
|
|
1483
1762
|
}
|
|
1484
|
-
|
|
1763
|
+
/**
|
|
1764
|
+
* Sets the start position of the range to the end of the specified node.
|
|
1765
|
+
*/
|
|
1485
1766
|
setStartAfter(node) {
|
|
1486
1767
|
this.range.setStartAfter(node.get(0));
|
|
1487
1768
|
}
|
|
1488
|
-
|
|
1769
|
+
/**
|
|
1770
|
+
* Sets the end position of the range.
|
|
1771
|
+
*/
|
|
1489
1772
|
setEnd(node, offset) {
|
|
1490
1773
|
this.range.setEnd(node.get(0), offset);
|
|
1491
1774
|
}
|
|
1492
|
-
|
|
1775
|
+
/**
|
|
1776
|
+
* Sets the end position of the range to the beginning of the specified node.
|
|
1777
|
+
*/
|
|
1493
1778
|
setEndBefore(node) {
|
|
1494
1779
|
this.range.setEndBefore(node.get(0));
|
|
1495
1780
|
}
|
|
1496
|
-
|
|
1781
|
+
/**
|
|
1782
|
+
* Sets the end position of the range to the end of the specified node.
|
|
1783
|
+
*/
|
|
1497
1784
|
setEndAfter(node) {
|
|
1498
1785
|
this.range.setEndAfter(node.get(0));
|
|
1499
1786
|
}
|
|
1500
|
-
|
|
1787
|
+
/**
|
|
1788
|
+
* Collapses the range to its start.
|
|
1789
|
+
*/
|
|
1501
1790
|
collapseToStart() {
|
|
1502
1791
|
this.range.collapse(true);
|
|
1503
1792
|
}
|
|
1504
|
-
|
|
1793
|
+
/**
|
|
1794
|
+
* Collapses the range to its end.
|
|
1795
|
+
*/
|
|
1505
1796
|
collapseToEnd() {
|
|
1506
1797
|
this.range.collapse(false);
|
|
1507
1798
|
}
|
|
1508
|
-
|
|
1799
|
+
/**
|
|
1800
|
+
* Sets the range to contain the specified node and its contents.
|
|
1801
|
+
*/
|
|
1509
1802
|
selectNode(node) {
|
|
1510
1803
|
this.range.selectNode(node.get(0));
|
|
1511
1804
|
}
|
|
1512
|
-
|
|
1805
|
+
/**
|
|
1806
|
+
* Sets the range to contain the contents of the specified node.
|
|
1807
|
+
*/
|
|
1513
1808
|
selectNodeContents(node) {
|
|
1514
1809
|
this.range.selectNodeContents(node.get(0));
|
|
1515
1810
|
}
|
|
1516
|
-
|
|
1811
|
+
/**
|
|
1812
|
+
* Collapses the range to the center position of the specified box.
|
|
1813
|
+
*/
|
|
1517
1814
|
selectBox(boxNode) {
|
|
1518
1815
|
const boxContainer = boxNode.find('.lake-box-container');
|
|
1519
1816
|
if (boxContainer.length === 0) {
|
|
@@ -1522,7 +1819,9 @@ class Range {
|
|
|
1522
1819
|
this.setStart(boxContainer, 0);
|
|
1523
1820
|
this.collapseToStart();
|
|
1524
1821
|
}
|
|
1525
|
-
|
|
1822
|
+
/**
|
|
1823
|
+
* Collapses the range to the start position of the specified box.
|
|
1824
|
+
*/
|
|
1526
1825
|
selectBoxStart(boxNode) {
|
|
1527
1826
|
const boxStrip = boxNode.find('.lake-box-strip');
|
|
1528
1827
|
if (boxStrip.length === 0) {
|
|
@@ -1531,7 +1830,9 @@ class Range {
|
|
|
1531
1830
|
this.selectNodeContents(boxStrip.eq(0));
|
|
1532
1831
|
this.collapseToStart();
|
|
1533
1832
|
}
|
|
1534
|
-
|
|
1833
|
+
/**
|
|
1834
|
+
* Collapses the range to the end position of the specified box.
|
|
1835
|
+
*/
|
|
1535
1836
|
selectBoxEnd(boxNode) {
|
|
1536
1837
|
const boxStrip = boxNode.find('.lake-box-strip');
|
|
1537
1838
|
if (boxStrip.length === 0) {
|
|
@@ -1540,7 +1841,9 @@ class Range {
|
|
|
1540
1841
|
this.selectNodeContents(boxStrip.eq(1));
|
|
1541
1842
|
this.collapseToStart();
|
|
1542
1843
|
}
|
|
1543
|
-
|
|
1844
|
+
/**
|
|
1845
|
+
* Collapses the range to the deepest point at the beginning of the contents of the specified node.
|
|
1846
|
+
*/
|
|
1544
1847
|
shrinkBefore(node) {
|
|
1545
1848
|
if (node.isBox) {
|
|
1546
1849
|
this.selectBoxStart(node);
|
|
@@ -1553,9 +1856,9 @@ class Range {
|
|
|
1553
1856
|
}
|
|
1554
1857
|
this.setStart(node, 0);
|
|
1555
1858
|
let child;
|
|
1556
|
-
while (this.startNode.isElement
|
|
1557
|
-
(child = this.startNode.children()[0])
|
|
1558
|
-
child.isElement && !child.isVoid) {
|
|
1859
|
+
while (this.startNode.isElement
|
|
1860
|
+
&& (child = this.startNode.children()[0])
|
|
1861
|
+
&& child.isElement && !child.isVoid) {
|
|
1559
1862
|
if (child.isBox) {
|
|
1560
1863
|
this.selectBoxStart(child);
|
|
1561
1864
|
return;
|
|
@@ -1564,7 +1867,9 @@ class Range {
|
|
|
1564
1867
|
}
|
|
1565
1868
|
this.collapseToStart();
|
|
1566
1869
|
}
|
|
1567
|
-
|
|
1870
|
+
/**
|
|
1871
|
+
* Collapses the range to the deepest point at the end of the contents of the specified node.
|
|
1872
|
+
*/
|
|
1568
1873
|
shrinkAfter(node) {
|
|
1569
1874
|
if (node.isBox) {
|
|
1570
1875
|
this.selectBoxEnd(node);
|
|
@@ -1577,10 +1882,10 @@ class Range {
|
|
|
1577
1882
|
}
|
|
1578
1883
|
this.setEnd(node, node.children().length);
|
|
1579
1884
|
let child;
|
|
1580
|
-
while (this.endNode.isElement
|
|
1581
|
-
this.endOffset > 0
|
|
1582
|
-
(child = this.endNode.children()[this.endOffset - 1])
|
|
1583
|
-
child.isElement && !child.isVoid) {
|
|
1885
|
+
while (this.endNode.isElement
|
|
1886
|
+
&& this.endOffset > 0
|
|
1887
|
+
&& (child = this.endNode.children()[this.endOffset - 1])
|
|
1888
|
+
&& child.isElement && !child.isVoid) {
|
|
1584
1889
|
if (child.isBox) {
|
|
1585
1890
|
this.selectBoxEnd(child);
|
|
1586
1891
|
return;
|
|
@@ -1590,30 +1895,34 @@ class Range {
|
|
|
1590
1895
|
this.collapseToEnd();
|
|
1591
1896
|
this.adjustBr();
|
|
1592
1897
|
}
|
|
1593
|
-
|
|
1898
|
+
/**
|
|
1899
|
+
* Sets the start and end positions of the range to the deepest start position and end position of the contents of the specified node.
|
|
1900
|
+
*/
|
|
1594
1901
|
// <div>[<p><strong>foo</strong></p>]</div>
|
|
1595
1902
|
// to
|
|
1596
1903
|
// <div><p><strong>[foo]</strong></p></div>
|
|
1597
1904
|
shrink() {
|
|
1598
1905
|
const isCollapsed = this.isCollapsed;
|
|
1599
1906
|
let child;
|
|
1600
|
-
while (this.startNode.isElement
|
|
1601
|
-
(child = this.startNode.children()[this.startOffset])
|
|
1602
|
-
child.isElement && !child.isVoid && !child.isBox) {
|
|
1907
|
+
while (this.startNode.isElement
|
|
1908
|
+
&& (child = this.startNode.children()[this.startOffset])
|
|
1909
|
+
&& child.isElement && !child.isVoid && !child.isBox) {
|
|
1603
1910
|
this.setStart(child, 0);
|
|
1604
1911
|
}
|
|
1605
1912
|
if (isCollapsed) {
|
|
1606
1913
|
this.collapseToStart();
|
|
1607
1914
|
return;
|
|
1608
1915
|
}
|
|
1609
|
-
while (this.endNode.isElement
|
|
1610
|
-
this.endOffset > 0
|
|
1611
|
-
(child = this.endNode.children()[this.endOffset - 1])
|
|
1612
|
-
child.isElement && !child.isVoid && !child.isBox) {
|
|
1916
|
+
while (this.endNode.isElement
|
|
1917
|
+
&& this.endOffset > 0
|
|
1918
|
+
&& (child = this.endNode.children()[this.endOffset - 1])
|
|
1919
|
+
&& child.isElement && !child.isVoid && !child.isBox) {
|
|
1613
1920
|
this.setEnd(child, child.children().length);
|
|
1614
1921
|
}
|
|
1615
1922
|
}
|
|
1616
|
-
|
|
1923
|
+
/**
|
|
1924
|
+
* Relocates the start and end positions of the range for boxes.
|
|
1925
|
+
*/
|
|
1617
1926
|
adjustBox() {
|
|
1618
1927
|
const startBoxNode = this.startNode.closest('lake-box');
|
|
1619
1928
|
if (startBoxNode.length > 0) {
|
|
@@ -1638,7 +1947,9 @@ class Range {
|
|
|
1638
1947
|
}
|
|
1639
1948
|
}
|
|
1640
1949
|
}
|
|
1641
|
-
|
|
1950
|
+
/**
|
|
1951
|
+
* Relocates the start and end positions of the range for tables.
|
|
1952
|
+
*/
|
|
1642
1953
|
adjustTable() {
|
|
1643
1954
|
const startTable = this.startNode.closest('table');
|
|
1644
1955
|
const endTable = this.endNode.closest('table');
|
|
@@ -1652,7 +1963,9 @@ class Range {
|
|
|
1652
1963
|
this.shrink();
|
|
1653
1964
|
}
|
|
1654
1965
|
}
|
|
1655
|
-
|
|
1966
|
+
/**
|
|
1967
|
+
* Relocates the start and end positions of the range for blocks.
|
|
1968
|
+
*/
|
|
1656
1969
|
// case 1:
|
|
1657
1970
|
// <p>foo</p>|<p>bar</p>
|
|
1658
1971
|
// to
|
|
@@ -1686,13 +1999,17 @@ class Range {
|
|
|
1686
1999
|
this.shrinkBefore(nextBlock);
|
|
1687
2000
|
}
|
|
1688
2001
|
}
|
|
1689
|
-
|
|
2002
|
+
/**
|
|
2003
|
+
* Relocates the start and end positions of the range for boxes, tables, and blocks.
|
|
2004
|
+
*/
|
|
1690
2005
|
adjust() {
|
|
1691
2006
|
this.adjustBox();
|
|
1692
2007
|
this.adjustTable();
|
|
1693
2008
|
this.adjustBlock();
|
|
1694
2009
|
}
|
|
1695
|
-
|
|
2010
|
+
/**
|
|
2011
|
+
* Relocates the start and end positions of the range for <br /> elements.
|
|
2012
|
+
*/
|
|
1696
2013
|
// In composition mode (e.g., when a user starts entering a Chinese character using a Pinyin IME),
|
|
1697
2014
|
// uncompleted text is inserted if the cursor is positioned behind a <br> tag.
|
|
1698
2015
|
// To fix this bug, the cursor needs to be moved to the front of the <br> tag.
|
|
@@ -1707,7 +2024,9 @@ class Range {
|
|
|
1707
2024
|
this.collapseToStart();
|
|
1708
2025
|
}
|
|
1709
2026
|
}
|
|
1710
|
-
|
|
2027
|
+
/**
|
|
2028
|
+
* Returns the node immediately preceding the start position of the range.
|
|
2029
|
+
*/
|
|
1711
2030
|
getPrevNode() {
|
|
1712
2031
|
let prevNode;
|
|
1713
2032
|
if (this.startNode.isText) {
|
|
@@ -1721,9 +2040,11 @@ class Range {
|
|
|
1721
2040
|
else {
|
|
1722
2041
|
prevNode = this.startNode.children()[this.startOffset - 1];
|
|
1723
2042
|
}
|
|
1724
|
-
return prevNode !== null && prevNode !==
|
|
2043
|
+
return prevNode !== null && prevNode !== void 0 ? prevNode : new Nodes();
|
|
1725
2044
|
}
|
|
1726
|
-
|
|
2045
|
+
/**
|
|
2046
|
+
* Returns the node immediately following the end position of the range.
|
|
2047
|
+
*/
|
|
1727
2048
|
getNextNode() {
|
|
1728
2049
|
let nextNode;
|
|
1729
2050
|
if (this.endNode.isText) {
|
|
@@ -1737,9 +2058,11 @@ class Range {
|
|
|
1737
2058
|
else {
|
|
1738
2059
|
nextNode = this.endNode.children()[this.endOffset];
|
|
1739
2060
|
}
|
|
1740
|
-
return nextNode !== null && nextNode !==
|
|
2061
|
+
return nextNode !== null && nextNode !== void 0 ? nextNode : new Nodes();
|
|
1741
2062
|
}
|
|
1742
|
-
|
|
2063
|
+
/**
|
|
2064
|
+
* Returns the boxes contained within or intersected by the range.
|
|
2065
|
+
*/
|
|
1743
2066
|
getBoxes() {
|
|
1744
2067
|
if (this.isCollapsed) {
|
|
1745
2068
|
const startBox = this.startNode.closest('lake-box');
|
|
@@ -1755,7 +2078,9 @@ class Range {
|
|
|
1755
2078
|
}
|
|
1756
2079
|
return nodeList;
|
|
1757
2080
|
}
|
|
1758
|
-
|
|
2081
|
+
/**
|
|
2082
|
+
* Returns the blocks contained within or intersected by the range.
|
|
2083
|
+
*/
|
|
1759
2084
|
getBlocks() {
|
|
1760
2085
|
if (this.isCollapsed) {
|
|
1761
2086
|
const startBlock = this.startNode.closestOperableBlock();
|
|
@@ -1766,19 +2091,19 @@ class Range {
|
|
|
1766
2091
|
}
|
|
1767
2092
|
const startBlock = this.startNode.closestOperableBlock();
|
|
1768
2093
|
const endBlock = this.endNode.closestOperableBlock();
|
|
1769
|
-
if (startBlock.isInside
|
|
1770
|
-
startBlock.get(0)
|
|
1771
|
-
startBlock.get(0) === endBlock.get(0)) {
|
|
2094
|
+
if (startBlock.isInside
|
|
2095
|
+
&& startBlock.get(0)
|
|
2096
|
+
&& startBlock.get(0) === endBlock.get(0)) {
|
|
1772
2097
|
return startBlock.isTable ? [] : [startBlock];
|
|
1773
2098
|
}
|
|
1774
2099
|
const blocks = [];
|
|
1775
2100
|
const clonedRange = this.clone();
|
|
1776
2101
|
clonedRange.collapseToEnd();
|
|
1777
2102
|
for (const child of this.commonAncestor.getWalker()) {
|
|
1778
|
-
if (child.isBlock && !child.isTable && child.isTopInside
|
|
1779
|
-
//
|
|
1780
|
-
clonedRange.comparePoint(child, 0) !== 0
|
|
1781
|
-
this.intersectsNode(child)) {
|
|
2103
|
+
if (child.isBlock && !child.isTable && child.isTopInside
|
|
2104
|
+
// The range doesn't end at the start of a block.
|
|
2105
|
+
&& clonedRange.comparePoint(child, 0) !== 0
|
|
2106
|
+
&& this.intersectsNode(child)) {
|
|
1782
2107
|
blocks.push(child);
|
|
1783
2108
|
}
|
|
1784
2109
|
}
|
|
@@ -1786,20 +2111,22 @@ class Range {
|
|
|
1786
2111
|
return blocks;
|
|
1787
2112
|
}
|
|
1788
2113
|
for (const child of this.commonAncestor.getWalker()) {
|
|
1789
|
-
if (child.isBlock && !child.isTable
|
|
1790
|
-
(startBlock.isSibling(child) || endBlock.isSibling(child))
|
|
1791
|
-
this.intersectsNode(child)) {
|
|
2114
|
+
if (child.isBlock && !child.isTable
|
|
2115
|
+
&& (startBlock.isSibling(child) || endBlock.isSibling(child))
|
|
2116
|
+
&& this.intersectsNode(child)) {
|
|
1792
2117
|
blocks.push(child);
|
|
1793
2118
|
}
|
|
1794
2119
|
}
|
|
1795
2120
|
return blocks;
|
|
1796
2121
|
}
|
|
1797
|
-
|
|
2122
|
+
/**
|
|
2123
|
+
* Returns the marks and text nodes contained within or intersected by the range.
|
|
2124
|
+
*/
|
|
1798
2125
|
getMarks(hasText = false) {
|
|
1799
2126
|
const marks = [];
|
|
1800
2127
|
if (this.commonAncestor.isText && hasText) {
|
|
1801
|
-
if (this.startOffset === 0
|
|
1802
|
-
this.endOffset === this.commonAncestor.text().length) {
|
|
2128
|
+
if (this.startOffset === 0
|
|
2129
|
+
&& this.endOffset === this.commonAncestor.text().length) {
|
|
1803
2130
|
marks.push(this.commonAncestor);
|
|
1804
2131
|
return marks;
|
|
1805
2132
|
}
|
|
@@ -1826,7 +2153,9 @@ class Range {
|
|
|
1826
2153
|
}
|
|
1827
2154
|
return marks;
|
|
1828
2155
|
}
|
|
1829
|
-
|
|
2156
|
+
/**
|
|
2157
|
+
* Returns the text from the start position of the closest block to the start position of the range.
|
|
2158
|
+
*/
|
|
1830
2159
|
// "<p>one<anchor />two<focus />three</p>" returns "one".
|
|
1831
2160
|
getStartText() {
|
|
1832
2161
|
const node = this.startNode;
|
|
@@ -1849,7 +2178,9 @@ class Range {
|
|
|
1849
2178
|
}
|
|
1850
2179
|
return text;
|
|
1851
2180
|
}
|
|
1852
|
-
|
|
2181
|
+
/**
|
|
2182
|
+
* Returns the text from the end position of the range to the end position of the closest block.
|
|
2183
|
+
*/
|
|
1853
2184
|
// "<p>one<anchor />two<focus />three</p>" returns "three".
|
|
1854
2185
|
getEndText() {
|
|
1855
2186
|
const node = this.endNode;
|
|
@@ -1872,9 +2203,11 @@ class Range {
|
|
|
1872
2203
|
}
|
|
1873
2204
|
return text;
|
|
1874
2205
|
}
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
2206
|
+
/**
|
|
2207
|
+
* Returns a new range from the specified character to the start position of the range.
|
|
2208
|
+
* The specified character must be preceded by a whitespace or be at the beginning of a paragraph,
|
|
2209
|
+
* without being adjacent to other characters. It will return null if not.
|
|
2210
|
+
*/
|
|
1878
2211
|
getCharacterRange(character) {
|
|
1879
2212
|
const newRange = this.clone();
|
|
1880
2213
|
newRange.shrink();
|
|
@@ -1911,15 +2244,21 @@ class Range {
|
|
|
1911
2244
|
}
|
|
1912
2245
|
return newRange;
|
|
1913
2246
|
}
|
|
1914
|
-
|
|
2247
|
+
/**
|
|
2248
|
+
* Returns a copy of the range.
|
|
2249
|
+
*/
|
|
1915
2250
|
clone() {
|
|
1916
2251
|
return new Range(this.range.cloneRange());
|
|
1917
2252
|
}
|
|
1918
|
-
|
|
2253
|
+
/**
|
|
2254
|
+
* Returns a DocumentFragment object copying the nodes included in the range.
|
|
2255
|
+
*/
|
|
1919
2256
|
cloneContents() {
|
|
1920
2257
|
return this.range.cloneContents();
|
|
1921
2258
|
}
|
|
1922
|
-
|
|
2259
|
+
/**
|
|
2260
|
+
* Prints information about the range, which is used for debugging.
|
|
2261
|
+
*/
|
|
1923
2262
|
info() {
|
|
1924
2263
|
debug('--- range information ---');
|
|
1925
2264
|
debug('start node:', this.startNode.toString(), ', offset:', this.startOffset);
|
|
@@ -1927,98 +2266,6 @@ class Range {
|
|
|
1927
2266
|
}
|
|
1928
2267
|
}
|
|
1929
2268
|
|
|
1930
|
-
const boxes = new Map();
|
|
1931
|
-
|
|
1932
|
-
const editors = new Map();
|
|
1933
|
-
|
|
1934
|
-
// Creates a Base64-encoded ASCII string from a string.
|
|
1935
|
-
function toBase64(value) {
|
|
1936
|
-
const encoder = new TextEncoder();
|
|
1937
|
-
const byteArray = encoder.encode(value);
|
|
1938
|
-
let binaryString = '';
|
|
1939
|
-
byteArray.forEach(byte => {
|
|
1940
|
-
binaryString += String.fromCharCode(byte);
|
|
1941
|
-
});
|
|
1942
|
-
return window.btoa(binaryString);
|
|
1943
|
-
}
|
|
1944
|
-
|
|
1945
|
-
// Decodes a string of data which has been encoded using Base64 encoding.
|
|
1946
|
-
function fromBase64(value) {
|
|
1947
|
-
const binaryString = window.atob(value);
|
|
1948
|
-
const byteArray = new Uint8Array(binaryString.length);
|
|
1949
|
-
for (let i = 0; i < binaryString.length; i++) {
|
|
1950
|
-
byteArray[i] = binaryString.charCodeAt(i);
|
|
1951
|
-
}
|
|
1952
|
-
const decoder = new TextDecoder();
|
|
1953
|
-
return decoder.decode(byteArray);
|
|
1954
|
-
}
|
|
1955
|
-
|
|
1956
|
-
function visibleInfo(target) {
|
|
1957
|
-
let rect;
|
|
1958
|
-
let viewport;
|
|
1959
|
-
if (target instanceof Nodes) {
|
|
1960
|
-
const nativeNode = target.get(0);
|
|
1961
|
-
rect = nativeNode.getBoundingClientRect();
|
|
1962
|
-
viewport = target.closestScroller();
|
|
1963
|
-
}
|
|
1964
|
-
else {
|
|
1965
|
-
rect = target.get().getBoundingClientRect();
|
|
1966
|
-
viewport = target.commonAncestor.closestScroller();
|
|
1967
|
-
}
|
|
1968
|
-
let left = rect.left;
|
|
1969
|
-
let right = rect.right;
|
|
1970
|
-
let top = rect.top;
|
|
1971
|
-
let bottom = rect.bottom;
|
|
1972
|
-
let viewportWidth = window.innerWidth;
|
|
1973
|
-
let viewportHeight = window.innerHeight;
|
|
1974
|
-
if (viewport.length > 0) {
|
|
1975
|
-
const nativeViewport = viewport.get(0);
|
|
1976
|
-
const viewportRect = nativeViewport.getBoundingClientRect();
|
|
1977
|
-
const offsetLeft = viewportRect.x;
|
|
1978
|
-
const offsetTop = viewportRect.y;
|
|
1979
|
-
left -= offsetLeft;
|
|
1980
|
-
right -= offsetLeft;
|
|
1981
|
-
top -= offsetTop;
|
|
1982
|
-
bottom -= offsetTop;
|
|
1983
|
-
viewportWidth = viewportRect.width;
|
|
1984
|
-
viewportHeight = viewportRect.height;
|
|
1985
|
-
}
|
|
1986
|
-
let leftEdge = 0;
|
|
1987
|
-
if (left < 0) {
|
|
1988
|
-
leftEdge = -1;
|
|
1989
|
-
}
|
|
1990
|
-
else if (viewportWidth - left < 0) {
|
|
1991
|
-
leftEdge = 1;
|
|
1992
|
-
}
|
|
1993
|
-
let rightEdge = 0;
|
|
1994
|
-
if (right < 0) {
|
|
1995
|
-
rightEdge = -1;
|
|
1996
|
-
}
|
|
1997
|
-
else if (viewportWidth - right < 0) {
|
|
1998
|
-
rightEdge = 1;
|
|
1999
|
-
}
|
|
2000
|
-
let topEdge = 0;
|
|
2001
|
-
if (top < 0) {
|
|
2002
|
-
topEdge = -1;
|
|
2003
|
-
}
|
|
2004
|
-
else if (viewportHeight - top < 0) {
|
|
2005
|
-
topEdge = 1;
|
|
2006
|
-
}
|
|
2007
|
-
let bottomEdge = 0;
|
|
2008
|
-
if (bottom < 0) {
|
|
2009
|
-
bottomEdge = -1;
|
|
2010
|
-
}
|
|
2011
|
-
else if (viewportHeight - bottom < 0) {
|
|
2012
|
-
bottomEdge = 1;
|
|
2013
|
-
}
|
|
2014
|
-
return {
|
|
2015
|
-
left: leftEdge,
|
|
2016
|
-
right: rightEdge,
|
|
2017
|
-
top: topEdge,
|
|
2018
|
-
bottom: bottomEdge,
|
|
2019
|
-
};
|
|
2020
|
-
}
|
|
2021
|
-
|
|
2022
2269
|
const headingMenuItems = [
|
|
2023
2270
|
{
|
|
2024
2271
|
value: 'h1',
|
|
@@ -2609,7 +2856,7 @@ const toolbarItems = [
|
|
|
2609
2856
|
const currentValues = [];
|
|
2610
2857
|
for (const item of activeItems) {
|
|
2611
2858
|
if (item.node.isMark) {
|
|
2612
|
-
const name = (_a = tagPluginNameMap.get(item.name)) !== null && _a !==
|
|
2859
|
+
const name = (_a = tagPluginNameMap.get(item.name)) !== null && _a !== void 0 ? _a : item.name;
|
|
2613
2860
|
currentValues.push(name);
|
|
2614
2861
|
}
|
|
2615
2862
|
}
|
|
@@ -2667,7 +2914,7 @@ const toolbarItems = [
|
|
|
2667
2914
|
},
|
|
2668
2915
|
];
|
|
2669
2916
|
|
|
2670
|
-
|
|
2917
|
+
/*
|
|
2671
2918
|
The MIT License (MIT)
|
|
2672
2919
|
|
|
2673
2920
|
Copyright (c) 2016-present react-component
|
|
@@ -2716,7 +2963,7 @@ function getBody(xhr) {
|
|
|
2716
2963
|
function request(option) {
|
|
2717
2964
|
const xhr = new XMLHttpRequest();
|
|
2718
2965
|
if (option.onProgress && xhr.upload) {
|
|
2719
|
-
xhr.upload.onprogress =
|
|
2966
|
+
xhr.upload.onprogress = e => {
|
|
2720
2967
|
if (e.total > 0) {
|
|
2721
2968
|
e.percent = (e.loaded / e.total) * 100;
|
|
2722
2969
|
}
|
|
@@ -2749,7 +2996,7 @@ function request(option) {
|
|
|
2749
2996
|
formData.append(filename, option.file);
|
|
2750
2997
|
}
|
|
2751
2998
|
}
|
|
2752
|
-
xhr.onerror =
|
|
2999
|
+
xhr.onerror = e => {
|
|
2753
3000
|
if (option.onError) {
|
|
2754
3001
|
option.onError(e);
|
|
2755
3002
|
}
|
|
@@ -2854,11 +3101,13 @@ function uploadFile(config) {
|
|
|
2854
3101
|
return box;
|
|
2855
3102
|
}
|
|
2856
3103
|
|
|
2857
|
-
|
|
3104
|
+
/**
|
|
3105
|
+
* The Button interface represents a clickable UI component. When a user clicks the button, a specified action is executed.
|
|
3106
|
+
*/
|
|
2858
3107
|
class Button {
|
|
2859
3108
|
constructor(config) {
|
|
2860
3109
|
this.config = config;
|
|
2861
|
-
this.root = config.root;
|
|
3110
|
+
this.root = query(config.root);
|
|
2862
3111
|
this.node = query(template `
|
|
2863
3112
|
<button type="button" name="${config.name}" class="lake-button" />
|
|
2864
3113
|
`);
|
|
@@ -2869,7 +3118,9 @@ class Button {
|
|
|
2869
3118
|
this.node.attr('tabindex', config.tabIndex.toString());
|
|
2870
3119
|
}
|
|
2871
3120
|
}
|
|
2872
|
-
|
|
3121
|
+
/**
|
|
3122
|
+
* Renders the button to the DOM.
|
|
3123
|
+
*/
|
|
2873
3124
|
render() {
|
|
2874
3125
|
const config = this.config;
|
|
2875
3126
|
const buttonNode = this.node;
|
|
@@ -2884,6 +3135,7 @@ class Button {
|
|
|
2884
3135
|
buttonNode.append(`<span>${config.text}</span>`);
|
|
2885
3136
|
}
|
|
2886
3137
|
this.root.append(buttonNode);
|
|
3138
|
+
this.root.get(0).appendChild(buttonNode.get(0));
|
|
2887
3139
|
buttonNode.on('mouseenter', () => {
|
|
2888
3140
|
if (buttonNode.attr('disabled')) {
|
|
2889
3141
|
return;
|
|
@@ -2914,10 +3166,10 @@ function unsafeTemplate(strings, ...keys) {
|
|
|
2914
3166
|
content += key;
|
|
2915
3167
|
content += strings[i + 1];
|
|
2916
3168
|
}
|
|
2917
|
-
content = content
|
|
2918
|
-
replace(/^\s+/gm, '')
|
|
2919
|
-
replace(/\s+$/gm, '')
|
|
2920
|
-
replace(/[\r\n]/g, '');
|
|
3169
|
+
content = content
|
|
3170
|
+
.replace(/^\s+/gm, '')
|
|
3171
|
+
.replace(/\s+$/gm, '')
|
|
3172
|
+
.replace(/[\r\n]/g, '');
|
|
2921
3173
|
return content;
|
|
2922
3174
|
}
|
|
2923
3175
|
|
|
@@ -2929,7 +3181,7 @@ function modifierText(value, userAgent) {
|
|
|
2929
3181
|
if (typeof window === 'undefined') {
|
|
2930
3182
|
return value;
|
|
2931
3183
|
}
|
|
2932
|
-
userAgent = userAgent !== null && userAgent !==
|
|
3184
|
+
userAgent = userAgent !== null && userAgent !== void 0 ? userAgent : navigator.userAgent;
|
|
2933
3185
|
const isMac = userAgent.indexOf('Mac OS X') >= 0;
|
|
2934
3186
|
const modText = isMac ? '⌘' : 'Ctrl';
|
|
2935
3187
|
return value.replace(/(^|\+|\s)mod(\+|\s|$)/g, `$1${modText}$2`);
|
|
@@ -3626,21 +3878,25 @@ const initFormatters = () => {
|
|
|
3626
3878
|
};
|
|
3627
3879
|
return formatters;
|
|
3628
3880
|
};
|
|
3629
|
-
|
|
3881
|
+
function loadFormatters(locale) {
|
|
3630
3882
|
loadedFormatters[locale] = initFormatters();
|
|
3631
|
-
}
|
|
3632
|
-
|
|
3883
|
+
}
|
|
3884
|
+
function loadLocale(locale) {
|
|
3633
3885
|
if (loadedLocales[locale]) {
|
|
3634
3886
|
return;
|
|
3635
3887
|
}
|
|
3636
3888
|
loadedLocales[locale] = localeTranslations[locale];
|
|
3637
3889
|
loadFormatters(locale);
|
|
3638
|
-
}
|
|
3890
|
+
}
|
|
3639
3891
|
const loadAllLocales = () => locales.forEach(loadLocale);
|
|
3640
|
-
|
|
3892
|
+
function i18nObject(locale) {
|
|
3893
|
+
return i18nObject$1(locale, loadedLocales[locale], loadedFormatters[locale]);
|
|
3894
|
+
}
|
|
3641
3895
|
loadAllLocales();
|
|
3642
3896
|
|
|
3643
|
-
|
|
3897
|
+
/**
|
|
3898
|
+
* The Dropdown component provides a user-friendly menu with selectable options. Use it to allow users to pick from a list of predefined choices.
|
|
3899
|
+
*/
|
|
3644
3900
|
class Dropdown {
|
|
3645
3901
|
constructor(config) {
|
|
3646
3902
|
this.clickListener = (event) => {
|
|
@@ -3654,7 +3910,7 @@ class Dropdown {
|
|
|
3654
3910
|
this.scrollListener = () => this.updatePosition();
|
|
3655
3911
|
this.resizeListener = () => this.updatePosition();
|
|
3656
3912
|
this.config = config;
|
|
3657
|
-
this.root = config.root;
|
|
3913
|
+
this.root = query(config.root);
|
|
3658
3914
|
this.locale = config.locale || i18nObject('en-US');
|
|
3659
3915
|
this.location = config.location || 'local';
|
|
3660
3916
|
this.direction = config.direction || 'auto';
|
|
@@ -3672,7 +3928,9 @@ class Dropdown {
|
|
|
3672
3928
|
titleNode.attr('tabindex', config.tabIndex.toString());
|
|
3673
3929
|
}
|
|
3674
3930
|
}
|
|
3675
|
-
|
|
3931
|
+
/**
|
|
3932
|
+
* Returns the value of the node.
|
|
3933
|
+
*/
|
|
3676
3934
|
static getValue(node) {
|
|
3677
3935
|
const value = node.attr('value');
|
|
3678
3936
|
if (value === '') {
|
|
@@ -3680,7 +3938,9 @@ class Dropdown {
|
|
|
3680
3938
|
}
|
|
3681
3939
|
return JSON.parse(fromBase64(value));
|
|
3682
3940
|
}
|
|
3683
|
-
|
|
3941
|
+
/**
|
|
3942
|
+
* Updates the value of the node.
|
|
3943
|
+
*/
|
|
3684
3944
|
static setValue(node, value) {
|
|
3685
3945
|
node.attr('value', toBase64(JSON.stringify(value)));
|
|
3686
3946
|
}
|
|
@@ -3865,11 +4125,13 @@ class Dropdown {
|
|
|
3865
4125
|
document.removeEventListener('click', this.clickListener);
|
|
3866
4126
|
window.removeEventListener('resize', this.resizeListener);
|
|
3867
4127
|
}
|
|
3868
|
-
|
|
4128
|
+
/**
|
|
4129
|
+
* Renders the dropdown to the DOM.
|
|
4130
|
+
*/
|
|
3869
4131
|
render() {
|
|
3870
4132
|
var _a, _b;
|
|
3871
4133
|
const config = this.config;
|
|
3872
|
-
const defaultValue = (_a = config.defaultValue) !== null && _a !==
|
|
4134
|
+
const defaultValue = (_a = config.defaultValue) !== null && _a !== void 0 ? _a : '';
|
|
3873
4135
|
const titleNode = this.node.find('.lake-dropdown-title');
|
|
3874
4136
|
if (!config.downIcon) {
|
|
3875
4137
|
titleNode.addClass('lake-dropdown-title-no-down');
|
|
@@ -3894,7 +4156,7 @@ class Dropdown {
|
|
|
3894
4156
|
Dropdown.setValue(this.node, [defaultValue]);
|
|
3895
4157
|
if (textNode.length > 0) {
|
|
3896
4158
|
const menuMap = Dropdown.getMenuMap(config.menuItems, this.locale);
|
|
3897
|
-
textNode.text((_b = menuMap.get(defaultValue)) !== null && _b !==
|
|
4159
|
+
textNode.text((_b = menuMap.get(defaultValue)) !== null && _b !== void 0 ? _b : defaultValue);
|
|
3898
4160
|
}
|
|
3899
4161
|
if (config.menuType === 'color') {
|
|
3900
4162
|
this.updateColorAccent(titleNode, defaultValue);
|
|
@@ -3948,7 +4210,9 @@ class Dropdown {
|
|
|
3948
4210
|
this.showMenu();
|
|
3949
4211
|
});
|
|
3950
4212
|
}
|
|
3951
|
-
|
|
4213
|
+
/**
|
|
4214
|
+
* Removes the dropdown from the DOM and cleans up resources.
|
|
4215
|
+
*/
|
|
3952
4216
|
unmount() {
|
|
3953
4217
|
this.hideMenu();
|
|
3954
4218
|
this.menuNode.remove();
|
|
@@ -3981,7 +4245,9 @@ const toolbarItemMap = new Map();
|
|
|
3981
4245
|
for (const item of toolbarItems) {
|
|
3982
4246
|
toolbarItemMap.set(item.name, item);
|
|
3983
4247
|
}
|
|
3984
|
-
|
|
4248
|
+
/**
|
|
4249
|
+
* The Toolbar interface provides properties and methods for rendering and manipulating the toolbar.
|
|
4250
|
+
*/
|
|
3985
4251
|
class Toolbar {
|
|
3986
4252
|
constructor(config) {
|
|
3987
4253
|
this.placement = 'top';
|
|
@@ -4087,7 +4353,9 @@ class Toolbar {
|
|
|
4087
4353
|
}
|
|
4088
4354
|
});
|
|
4089
4355
|
}
|
|
4090
|
-
|
|
4356
|
+
/**
|
|
4357
|
+
* Updates the state of each toolbar item, such as whether it is selected or disabled.
|
|
4358
|
+
*/
|
|
4091
4359
|
updateState(state = {
|
|
4092
4360
|
activeItems: [],
|
|
4093
4361
|
}) {
|
|
@@ -4148,13 +4416,15 @@ class Toolbar {
|
|
|
4148
4416
|
if (textNode.length > 0) {
|
|
4149
4417
|
const key = selectedValues[0] || item.defaultValue || '';
|
|
4150
4418
|
const menuMap = this.allMenuMap.get(item.name);
|
|
4151
|
-
const text = (_a = (menuMap && menuMap.get(key))) !== null && _a !==
|
|
4419
|
+
const text = (_a = (menuMap && menuMap.get(key))) !== null && _a !== void 0 ? _a : key;
|
|
4152
4420
|
textNode.text(text);
|
|
4153
4421
|
}
|
|
4154
4422
|
}
|
|
4155
4423
|
}
|
|
4156
4424
|
}
|
|
4157
|
-
|
|
4425
|
+
/**
|
|
4426
|
+
* Renders the toolbar for the specified editor.
|
|
4427
|
+
*/
|
|
4158
4428
|
render(editor) {
|
|
4159
4429
|
this.root.append(this.container);
|
|
4160
4430
|
for (const name of this.items) {
|
|
@@ -4187,7 +4457,9 @@ class Toolbar {
|
|
|
4187
4457
|
}
|
|
4188
4458
|
}
|
|
4189
4459
|
}
|
|
4190
|
-
|
|
4460
|
+
/**
|
|
4461
|
+
* Destroys the toolbar instance, removing it from the DOM.
|
|
4462
|
+
*/
|
|
4191
4463
|
unmount() {
|
|
4192
4464
|
for (const dropdown of this.dropdownList) {
|
|
4193
4465
|
dropdown.unmount();
|
|
@@ -4216,8 +4488,8 @@ class FloatingToolbar extends Toolbar {
|
|
|
4216
4488
|
}
|
|
4217
4489
|
updatePosition() {
|
|
4218
4490
|
const visible = visibleInfo(this.range);
|
|
4219
|
-
if ((visible.top === -1 && visible.bottom === -1)
|
|
4220
|
-
(visible.top === 1 && visible.bottom === 1)) {
|
|
4491
|
+
if ((visible.top === -1 && visible.bottom === -1)
|
|
4492
|
+
|| (visible.top === 1 && visible.bottom === 1)) {
|
|
4221
4493
|
this.container.css('visibility', 'hidden');
|
|
4222
4494
|
return;
|
|
4223
4495
|
}
|
|
@@ -4293,12 +4565,18 @@ class FloatingToolbar extends Toolbar {
|
|
|
4293
4565
|
}
|
|
4294
4566
|
}
|
|
4295
4567
|
|
|
4296
|
-
|
|
4568
|
+
/**
|
|
4569
|
+
* The Box interface represents an embedded content designed to enhance editing capability.
|
|
4570
|
+
*/
|
|
4297
4571
|
class Box {
|
|
4298
4572
|
constructor(node) {
|
|
4299
|
-
|
|
4573
|
+
/**
|
|
4574
|
+
* An EventEmitter object for handling events. See the Instance events for details.
|
|
4575
|
+
*/
|
|
4300
4576
|
this.event = new EventEmitter();
|
|
4301
|
-
|
|
4577
|
+
/**
|
|
4578
|
+
* A floating toolbar attached to the box.
|
|
4579
|
+
*/
|
|
4302
4580
|
this.toolbar = null;
|
|
4303
4581
|
if (typeof node === 'string') {
|
|
4304
4582
|
const component = boxes.get(node);
|
|
@@ -4339,9 +4617,9 @@ class Box {
|
|
|
4339
4617
|
container.off('click');
|
|
4340
4618
|
}
|
|
4341
4619
|
container.on('mouseenter', () => {
|
|
4342
|
-
if (container.hasClass('lake-box-selected')
|
|
4343
|
-
container.hasClass('lake-box-focused')
|
|
4344
|
-
container.hasClass('lake-box-activated')) {
|
|
4620
|
+
if (container.hasClass('lake-box-selected')
|
|
4621
|
+
|| container.hasClass('lake-box-focused')
|
|
4622
|
+
|| container.hasClass('lake-box-activated')) {
|
|
4345
4623
|
return;
|
|
4346
4624
|
}
|
|
4347
4625
|
container.addClass('lake-box-hovered');
|
|
@@ -4357,15 +4635,21 @@ class Box {
|
|
|
4357
4635
|
container.attr('draggable', 'true');
|
|
4358
4636
|
}
|
|
4359
4637
|
}
|
|
4360
|
-
|
|
4638
|
+
/**
|
|
4639
|
+
* Indicates the type of the box.
|
|
4640
|
+
*/
|
|
4361
4641
|
get type() {
|
|
4362
4642
|
return this.node.attr('type');
|
|
4363
4643
|
}
|
|
4364
|
-
|
|
4644
|
+
/**
|
|
4645
|
+
* Returns the name of the box.
|
|
4646
|
+
*/
|
|
4365
4647
|
get name() {
|
|
4366
4648
|
return this.node.attr('name');
|
|
4367
4649
|
}
|
|
4368
|
-
|
|
4650
|
+
/**
|
|
4651
|
+
* Gets or sets the value of the box.
|
|
4652
|
+
*/
|
|
4369
4653
|
get value() {
|
|
4370
4654
|
const value = this.node.attr('value');
|
|
4371
4655
|
if (value === '') {
|
|
@@ -4373,7 +4657,6 @@ class Box {
|
|
|
4373
4657
|
}
|
|
4374
4658
|
return JSON.parse(fromBase64(value));
|
|
4375
4659
|
}
|
|
4376
|
-
// Sets the value of the box.
|
|
4377
4660
|
set value(value) {
|
|
4378
4661
|
this.node.attr('value', toBase64(JSON.stringify(value)));
|
|
4379
4662
|
}
|
|
@@ -4389,7 +4672,9 @@ class Box {
|
|
|
4389
4672
|
}
|
|
4390
4673
|
this.value = value;
|
|
4391
4674
|
}
|
|
4392
|
-
|
|
4675
|
+
/**
|
|
4676
|
+
* Returns the Editor object that contains the box.
|
|
4677
|
+
*/
|
|
4393
4678
|
getEditor() {
|
|
4394
4679
|
const container = this.node.closest('div[contenteditable]');
|
|
4395
4680
|
const editor = container.length > 0 ? editors.get(container.id) : undefined;
|
|
@@ -4398,11 +4683,15 @@ class Box {
|
|
|
4398
4683
|
}
|
|
4399
4684
|
return editor;
|
|
4400
4685
|
}
|
|
4401
|
-
|
|
4686
|
+
/**
|
|
4687
|
+
* Returns the container element of the box.
|
|
4688
|
+
*/
|
|
4402
4689
|
getContainer() {
|
|
4403
4690
|
return this.node.find('.lake-box-container');
|
|
4404
4691
|
}
|
|
4405
|
-
|
|
4692
|
+
/**
|
|
4693
|
+
* Returns the HTML content inside the box.
|
|
4694
|
+
*/
|
|
4406
4695
|
getHTML() {
|
|
4407
4696
|
const component = boxes.get(this.name);
|
|
4408
4697
|
if (component === undefined) {
|
|
@@ -4413,7 +4702,9 @@ class Box {
|
|
|
4413
4702
|
}
|
|
4414
4703
|
return component.html(this);
|
|
4415
4704
|
}
|
|
4416
|
-
|
|
4705
|
+
/**
|
|
4706
|
+
* Adds a floating toolbar to the box.
|
|
4707
|
+
*/
|
|
4417
4708
|
setToolbar(items) {
|
|
4418
4709
|
const editor = this.getEditor();
|
|
4419
4710
|
this.event.on('focus', () => {
|
|
@@ -4438,7 +4729,9 @@ class Box {
|
|
|
4438
4729
|
}
|
|
4439
4730
|
});
|
|
4440
4731
|
}
|
|
4441
|
-
|
|
4732
|
+
/**
|
|
4733
|
+
* Renders the content inside the box.
|
|
4734
|
+
*/
|
|
4442
4735
|
render() {
|
|
4443
4736
|
const component = boxes.get(this.name);
|
|
4444
4737
|
if (component === undefined) {
|
|
@@ -4455,7 +4748,9 @@ class Box {
|
|
|
4455
4748
|
}
|
|
4456
4749
|
debug(`Box "${this.name}" (id: ${this.node.id}) rendered`);
|
|
4457
4750
|
}
|
|
4458
|
-
|
|
4751
|
+
/**
|
|
4752
|
+
* Destroys the box instance.
|
|
4753
|
+
*/
|
|
4459
4754
|
unmount() {
|
|
4460
4755
|
this.event.emit('blur');
|
|
4461
4756
|
this.event.emit('beforeunmount');
|
|
@@ -4465,9 +4760,94 @@ class Box {
|
|
|
4465
4760
|
}
|
|
4466
4761
|
}
|
|
4467
4762
|
|
|
4763
|
+
/**
|
|
4764
|
+
* Returns an existing Box instance associated with the provided boxNode or generates a new one if none exists.
|
|
4765
|
+
* The function handles the creation and storage of Box instances, storing them either in a temporary or
|
|
4766
|
+
* permanentmap based on whether the boxNode is contained within a container.
|
|
4767
|
+
*/
|
|
4768
|
+
function getBox(boxNode) {
|
|
4769
|
+
const tempInstanceMap = getInstanceMap(0);
|
|
4770
|
+
// boxNode is a name
|
|
4771
|
+
if (typeof boxNode === 'string') {
|
|
4772
|
+
const box = new Box(boxNode);
|
|
4773
|
+
tempInstanceMap.set(box.node.id, box);
|
|
4774
|
+
return box;
|
|
4775
|
+
}
|
|
4776
|
+
// boxNode is a node
|
|
4777
|
+
boxNode = query(boxNode);
|
|
4778
|
+
const container = boxNode.closestContainer();
|
|
4779
|
+
if (container.length === 0) {
|
|
4780
|
+
let box = tempInstanceMap.get(boxNode.id);
|
|
4781
|
+
if (box) {
|
|
4782
|
+
return box;
|
|
4783
|
+
}
|
|
4784
|
+
box = new Box(boxNode);
|
|
4785
|
+
tempInstanceMap.set(boxNode.id, box);
|
|
4786
|
+
return box;
|
|
4787
|
+
}
|
|
4788
|
+
const instanceMap = getInstanceMap(container.id);
|
|
4789
|
+
let box = tempInstanceMap.get(boxNode.id);
|
|
4790
|
+
if (box) {
|
|
4791
|
+
// move the box instance from temporary map to permanent map
|
|
4792
|
+
instanceMap.set(boxNode.id, box);
|
|
4793
|
+
tempInstanceMap.delete(boxNode.id);
|
|
4794
|
+
return box;
|
|
4795
|
+
}
|
|
4796
|
+
box = instanceMap.get(boxNode.id);
|
|
4797
|
+
if (box) {
|
|
4798
|
+
return box;
|
|
4799
|
+
}
|
|
4800
|
+
box = new Box(boxNode);
|
|
4801
|
+
instanceMap.set(boxNode.id, box);
|
|
4802
|
+
return box;
|
|
4803
|
+
}
|
|
4804
|
+
|
|
4805
|
+
/**
|
|
4806
|
+
* The Fragment interface represents a lightweight document object that has no parent.
|
|
4807
|
+
* It is designed for efficient manipulation of document structures without affecting the main DOM.
|
|
4808
|
+
*/
|
|
4809
|
+
class Fragment {
|
|
4810
|
+
constructor(fragment) {
|
|
4811
|
+
this.fragment = fragment !== null && fragment !== void 0 ? fragment : document.createDocumentFragment();
|
|
4812
|
+
}
|
|
4813
|
+
/**
|
|
4814
|
+
* Returns a native DocumentFragment object from the fragment.
|
|
4815
|
+
*/
|
|
4816
|
+
get() {
|
|
4817
|
+
return this.fragment;
|
|
4818
|
+
}
|
|
4819
|
+
/**
|
|
4820
|
+
* Finds and returns descendants of the fragment that match the specified CSS selector.
|
|
4821
|
+
*/
|
|
4822
|
+
find(selector) {
|
|
4823
|
+
const nodeList = [];
|
|
4824
|
+
let child = new Nodes(this.fragment.firstChild);
|
|
4825
|
+
while (child.length > 0) {
|
|
4826
|
+
if (child.matches(selector)) {
|
|
4827
|
+
nodeList.push(child.get(0));
|
|
4828
|
+
}
|
|
4829
|
+
else if (child.isElement) {
|
|
4830
|
+
child.find(selector).each(node => {
|
|
4831
|
+
nodeList.push(node);
|
|
4832
|
+
});
|
|
4833
|
+
}
|
|
4834
|
+
child = child.next();
|
|
4835
|
+
}
|
|
4836
|
+
return new Nodes(nodeList);
|
|
4837
|
+
}
|
|
4838
|
+
/**
|
|
4839
|
+
* Inserts the specified content just inside the fragment, after its last child.
|
|
4840
|
+
*/
|
|
4841
|
+
append(content) {
|
|
4842
|
+
query(content).each(nativeNode => {
|
|
4843
|
+
this.fragment.appendChild(nativeNode);
|
|
4844
|
+
});
|
|
4845
|
+
}
|
|
4846
|
+
}
|
|
4847
|
+
|
|
4468
4848
|
const blockAttributeRules = {
|
|
4469
4849
|
id: /^[\w-]+$/,
|
|
4470
|
-
class: /^[\w
|
|
4850
|
+
class: /^[\w\- ]+$/,
|
|
4471
4851
|
style: {
|
|
4472
4852
|
'text-align': ['left', 'center', 'right', 'justify', 'start', 'end'],
|
|
4473
4853
|
'margin-left': /^-?\d+px$/i,
|
|
@@ -4540,7 +4920,7 @@ function getElementRules() {
|
|
|
4540
4920
|
},
|
|
4541
4921
|
},
|
|
4542
4922
|
span: {
|
|
4543
|
-
class: /^[\w
|
|
4923
|
+
class: /^[\w\- ]+$/,
|
|
4544
4924
|
style: {
|
|
4545
4925
|
color: /^[^"]+$/,
|
|
4546
4926
|
'background-color': /^[^"]+$/,
|
|
@@ -4558,7 +4938,7 @@ function getElementRules() {
|
|
|
4558
4938
|
sup: {},
|
|
4559
4939
|
code: {},
|
|
4560
4940
|
a: {
|
|
4561
|
-
class: /^[\w
|
|
4941
|
+
class: /^[\w\- ]+$/,
|
|
4562
4942
|
name: /^[\w-]+$/,
|
|
4563
4943
|
href: /^[^"]+$/,
|
|
4564
4944
|
target: /^[\w-]+$/,
|
|
@@ -4573,9 +4953,9 @@ function getElementRules() {
|
|
|
4573
4953
|
|
|
4574
4954
|
// Converts a string from style property of element to a key-value object that contains a list of all styles properties.
|
|
4575
4955
|
function parseStyle(styleValue) {
|
|
4576
|
-
styleValue = styleValue.replace(/"/
|
|
4956
|
+
styleValue = styleValue.replace(/"/gi, '"');
|
|
4577
4957
|
const properties = {};
|
|
4578
|
-
const re = /\s*([\w-]+)\s*:([^;]*)(
|
|
4958
|
+
const re = /\s*([\w-]+)\s*:([^;]*)(?:;|$)/g;
|
|
4579
4959
|
let result;
|
|
4580
4960
|
while ((result = re.exec(styleValue)) !== null) {
|
|
4581
4961
|
const key = result[1].toLowerCase().trim();
|
|
@@ -4585,7 +4965,9 @@ function parseStyle(styleValue) {
|
|
|
4585
4965
|
return properties;
|
|
4586
4966
|
}
|
|
4587
4967
|
|
|
4588
|
-
|
|
4968
|
+
/**
|
|
4969
|
+
* The HTMLParser interface provides the ability to parse an HTML string according to specified rules.
|
|
4970
|
+
*/
|
|
4589
4971
|
class HTMLParser {
|
|
4590
4972
|
constructor(content, rules = getElementRules()) {
|
|
4591
4973
|
this.rules = rules;
|
|
@@ -4596,13 +4978,17 @@ class HTMLParser {
|
|
|
4596
4978
|
this.source = content;
|
|
4597
4979
|
}
|
|
4598
4980
|
}
|
|
4599
|
-
|
|
4981
|
+
/**
|
|
4982
|
+
* Parses the given HTML string and returns the body element from the result.
|
|
4983
|
+
*/
|
|
4600
4984
|
parseHTML(html) {
|
|
4601
4985
|
const parser = new DOMParser();
|
|
4602
4986
|
const doc = parser.parseFromString(html, 'text/html');
|
|
4603
4987
|
return new Nodes(doc.querySelector('body'));
|
|
4604
4988
|
}
|
|
4605
|
-
|
|
4989
|
+
/**
|
|
4990
|
+
* Returns a boolean value indicating whether the given value matches the given rule.
|
|
4991
|
+
*/
|
|
4606
4992
|
static matchRule(rule, value) {
|
|
4607
4993
|
if (typeof rule === 'string') {
|
|
4608
4994
|
return rule === value;
|
|
@@ -4615,7 +5001,9 @@ class HTMLParser {
|
|
|
4615
5001
|
}
|
|
4616
5002
|
return false;
|
|
4617
5003
|
}
|
|
4618
|
-
|
|
5004
|
+
/**
|
|
5005
|
+
* Returns an open tag string from the specified element.
|
|
5006
|
+
*/
|
|
4619
5007
|
static getOpenTagString(element, rules) {
|
|
4620
5008
|
let tagName = element.name;
|
|
4621
5009
|
let attributeRules = rules[tagName];
|
|
@@ -4667,7 +5055,9 @@ class HTMLParser {
|
|
|
4667
5055
|
}
|
|
4668
5056
|
return openTag;
|
|
4669
5057
|
}
|
|
4670
|
-
|
|
5058
|
+
/**
|
|
5059
|
+
* Returns a closed tag string from the specified element.
|
|
5060
|
+
*/
|
|
4671
5061
|
static getClosedTagString(element, rules) {
|
|
4672
5062
|
let tagName = element.name;
|
|
4673
5063
|
const attributeRules = rules[tagName];
|
|
@@ -4679,7 +5069,9 @@ class HTMLParser {
|
|
|
4679
5069
|
}
|
|
4680
5070
|
return tagName;
|
|
4681
5071
|
}
|
|
4682
|
-
|
|
5072
|
+
/**
|
|
5073
|
+
* Returns the value of the text node with trimming invisible whitespace.
|
|
5074
|
+
*/
|
|
4683
5075
|
// <p>foo</p>\n<p>bar</p>
|
|
4684
5076
|
// or
|
|
4685
5077
|
// <p>\nfoo\n</p>
|
|
@@ -4688,22 +5080,23 @@ class HTMLParser {
|
|
|
4688
5080
|
const prevSibling = textNode.prev();
|
|
4689
5081
|
const nextSibling = textNode.next();
|
|
4690
5082
|
let nodeValue = textNode.text();
|
|
4691
|
-
if ((prevSibling.isBlock || prevSibling.isBlockBox) &&
|
|
4692
|
-
(
|
|
4693
|
-
prevSibling.length === 0 && nextSibling.length === 0 && parentNode.isBlock) {
|
|
5083
|
+
if (((prevSibling.isBlock || prevSibling.isBlockBox) && (nextSibling.isBlock || nextSibling.isBlockBox))
|
|
5084
|
+
|| (prevSibling.length === 0 && nextSibling.length === 0 && parentNode.isBlock)) {
|
|
4694
5085
|
nodeValue = nodeValue.replace(/^[\u0020\t\r\n]+|[\u0020\t\r\n]+$/g, '');
|
|
4695
5086
|
}
|
|
4696
|
-
else if ((prevSibling.isBlock || prevSibling.isBlockBox)
|
|
4697
|
-
prevSibling.length === 0 && parentNode.isBlock) {
|
|
5087
|
+
else if ((prevSibling.isBlock || prevSibling.isBlockBox)
|
|
5088
|
+
|| (prevSibling.length === 0 && parentNode.isBlock)) {
|
|
4698
5089
|
nodeValue = nodeValue.replace(/^[\u0020\t\r\n]+/, '');
|
|
4699
5090
|
}
|
|
4700
|
-
else if ((nextSibling.isBlock || nextSibling.isBlockBox)
|
|
4701
|
-
nextSibling.length === 0 && parentNode.isBlock) {
|
|
5091
|
+
else if ((nextSibling.isBlock || nextSibling.isBlockBox)
|
|
5092
|
+
|| (nextSibling.length === 0 && parentNode.isBlock)) {
|
|
4702
5093
|
nodeValue = nodeValue.replace(/[\u0020\t\r\n]+$/, '');
|
|
4703
5094
|
}
|
|
4704
5095
|
return nodeValue;
|
|
4705
5096
|
}
|
|
4706
|
-
|
|
5097
|
+
/**
|
|
5098
|
+
* Returns the parsed HTML as a string.
|
|
5099
|
+
*/
|
|
4707
5100
|
getHTML() {
|
|
4708
5101
|
const rules = this.rules;
|
|
4709
5102
|
function* iterate(node) {
|
|
@@ -4741,7 +5134,9 @@ class HTMLParser {
|
|
|
4741
5134
|
}
|
|
4742
5135
|
return html.trim();
|
|
4743
5136
|
}
|
|
4744
|
-
|
|
5137
|
+
/**
|
|
5138
|
+
* Returns the parsed content as a DocumentFragment object.
|
|
5139
|
+
*/
|
|
4745
5140
|
getFragment() {
|
|
4746
5141
|
const html = this.getHTML();
|
|
4747
5142
|
const body = this.parseHTML(html);
|
|
@@ -4756,12 +5151,16 @@ class HTMLParser {
|
|
|
4756
5151
|
}
|
|
4757
5152
|
}
|
|
4758
5153
|
|
|
4759
|
-
|
|
5154
|
+
/**
|
|
5155
|
+
* The TextParser interface enables parsing of text into structured HTML.
|
|
5156
|
+
*/
|
|
4760
5157
|
class TextParser {
|
|
4761
5158
|
constructor(content) {
|
|
4762
5159
|
this.content = content;
|
|
4763
5160
|
}
|
|
4764
|
-
|
|
5161
|
+
/**
|
|
5162
|
+
* Converts the parsed text into an HTML string.
|
|
5163
|
+
*/
|
|
4765
5164
|
getHTML() {
|
|
4766
5165
|
let html = this.content;
|
|
4767
5166
|
html = html.replace(/ {2}/g, ' \xA0');
|
|
@@ -4773,7 +5172,9 @@ class TextParser {
|
|
|
4773
5172
|
html = html.replace(/[\r\n]/g, '</p><p>');
|
|
4774
5173
|
return html;
|
|
4775
5174
|
}
|
|
4776
|
-
|
|
5175
|
+
/**
|
|
5176
|
+
* Generates a DocumentFragment object that represents the parsed text.
|
|
5177
|
+
*/
|
|
4777
5178
|
getFragment() {
|
|
4778
5179
|
const htmlParser = new HTMLParser(this.getHTML());
|
|
4779
5180
|
return htmlParser.getFragment();
|
|
@@ -4787,7 +5188,9 @@ function insertNode(range, node) {
|
|
|
4787
5188
|
nativeRange.setEndAfter(nativeNode);
|
|
4788
5189
|
nativeRange.collapse(false);
|
|
4789
5190
|
}
|
|
4790
|
-
|
|
5191
|
+
/**
|
|
5192
|
+
* Inserts a bookmark at the cursor position or a pair of bookmarks at the beginning and end of the range.
|
|
5193
|
+
*/
|
|
4791
5194
|
// case 1: foo<lake-bookmark type="focus" />bar
|
|
4792
5195
|
// case 2: <lake-bookmark type="anchor" />foo<lake-bookmark type="focus" />
|
|
4793
5196
|
// case 3: foo<lake-box type="inline" name="image" focus="start"></lake-box>bar
|
|
@@ -4843,55 +5246,6 @@ function insertBookmark(range) {
|
|
|
4843
5246
|
};
|
|
4844
5247
|
}
|
|
4845
5248
|
|
|
4846
|
-
const boxInstances = new Map();
|
|
4847
|
-
function getInstanceMap(id) {
|
|
4848
|
-
let instanceMap = boxInstances.get(id);
|
|
4849
|
-
if (!instanceMap) {
|
|
4850
|
-
instanceMap = new Map();
|
|
4851
|
-
boxInstances.set(id, instanceMap);
|
|
4852
|
-
return instanceMap;
|
|
4853
|
-
}
|
|
4854
|
-
return instanceMap;
|
|
4855
|
-
}
|
|
4856
|
-
|
|
4857
|
-
// Returns an already generated box instance or generates a new instance if it does not exist.
|
|
4858
|
-
function getBox(boxNode) {
|
|
4859
|
-
const tempInstanceMap = getInstanceMap(0);
|
|
4860
|
-
// boxNode is a name
|
|
4861
|
-
if (typeof boxNode === 'string') {
|
|
4862
|
-
const box = new Box(boxNode);
|
|
4863
|
-
tempInstanceMap.set(box.node.id, box);
|
|
4864
|
-
return box;
|
|
4865
|
-
}
|
|
4866
|
-
// boxNode is node
|
|
4867
|
-
boxNode = query(boxNode);
|
|
4868
|
-
const container = boxNode.closestContainer();
|
|
4869
|
-
if (container.length === 0) {
|
|
4870
|
-
let box = tempInstanceMap.get(boxNode.id);
|
|
4871
|
-
if (box) {
|
|
4872
|
-
return box;
|
|
4873
|
-
}
|
|
4874
|
-
box = new Box(boxNode);
|
|
4875
|
-
tempInstanceMap.set(boxNode.id, box);
|
|
4876
|
-
return box;
|
|
4877
|
-
}
|
|
4878
|
-
const instanceMap = getInstanceMap(container.id);
|
|
4879
|
-
let box = tempInstanceMap.get(boxNode.id);
|
|
4880
|
-
if (box) {
|
|
4881
|
-
// move the box instance from temporary map to permanent map
|
|
4882
|
-
instanceMap.set(boxNode.id, box);
|
|
4883
|
-
tempInstanceMap.delete(boxNode.id);
|
|
4884
|
-
return box;
|
|
4885
|
-
}
|
|
4886
|
-
box = instanceMap.get(boxNode.id);
|
|
4887
|
-
if (box) {
|
|
4888
|
-
return box;
|
|
4889
|
-
}
|
|
4890
|
-
box = new Box(boxNode);
|
|
4891
|
-
instanceMap.set(boxNode.id, box);
|
|
4892
|
-
return box;
|
|
4893
|
-
}
|
|
4894
|
-
|
|
4895
5249
|
function removeAndNormalizeNode(node, range) {
|
|
4896
5250
|
const previousNode = node.prev();
|
|
4897
5251
|
const nextNode = node.next();
|
|
@@ -4913,7 +5267,9 @@ function removeAndNormalizeNode(node, range) {
|
|
|
4913
5267
|
node.remove();
|
|
4914
5268
|
}
|
|
4915
5269
|
}
|
|
4916
|
-
|
|
5270
|
+
/**
|
|
5271
|
+
* Changes the specified range to a range represented by the provided bookmark.
|
|
5272
|
+
*/
|
|
4917
5273
|
function toBookmark(range, bookmark) {
|
|
4918
5274
|
const anchor = bookmark.anchor;
|
|
4919
5275
|
const focus = bookmark.focus;
|
|
@@ -4984,8 +5340,8 @@ function removeBreak(block) {
|
|
|
4984
5340
|
}
|
|
4985
5341
|
child = nextNode;
|
|
4986
5342
|
}
|
|
4987
|
-
if (nodeList.length === 1 && nodeList[0].name === 'br'
|
|
4988
|
-
nodeList.length === 2 && nodeList[0].name === 'br' && nodeList[1].isBookmark) {
|
|
5343
|
+
if ((nodeList.length === 1 && nodeList[0].name === 'br')
|
|
5344
|
+
|| (nodeList.length === 2 && nodeList[0].name === 'br' && nodeList[1].isBookmark)) {
|
|
4989
5345
|
nodeList[0].remove();
|
|
4990
5346
|
}
|
|
4991
5347
|
if (nodeList.length === 2 && nodeList[0].isBookmark && nodeList[1].name === 'br') {
|
|
@@ -5071,11 +5427,11 @@ function mergeNodes(node, otherNode) {
|
|
|
5071
5427
|
child = next;
|
|
5072
5428
|
}
|
|
5073
5429
|
originalOtherNode.remove();
|
|
5074
|
-
if (nextNode.length > 0
|
|
5075
|
-
nextOtherNode.length > 0
|
|
5076
|
-
nextNode.isElement
|
|
5077
|
-
!nextNode.isBox
|
|
5078
|
-
nextNode.clone(false).get(0).isEqualNode(nextOtherNode.clone(false).get(0))) {
|
|
5430
|
+
if (nextNode.length > 0
|
|
5431
|
+
&& nextOtherNode.length > 0
|
|
5432
|
+
&& nextNode.isElement
|
|
5433
|
+
&& !nextNode.isBox
|
|
5434
|
+
&& nextNode.clone(false).get(0).isEqualNode(nextOtherNode.clone(false).get(0))) {
|
|
5079
5435
|
return mergeNodes(nextNode, nextOtherNode);
|
|
5080
5436
|
}
|
|
5081
5437
|
if (nextNode.length === 0) {
|
|
@@ -5136,7 +5492,9 @@ function fixNumberedList(blocks) {
|
|
|
5136
5492
|
}
|
|
5137
5493
|
}
|
|
5138
5494
|
|
|
5139
|
-
|
|
5495
|
+
/**
|
|
5496
|
+
* Removes the contents of the specified range.
|
|
5497
|
+
*/
|
|
5140
5498
|
function deleteContents(range) {
|
|
5141
5499
|
if (range.isCollapsed) {
|
|
5142
5500
|
return;
|
|
@@ -5175,7 +5533,9 @@ function deleteContents(range) {
|
|
|
5175
5533
|
toBookmark(range, bookmark);
|
|
5176
5534
|
}
|
|
5177
5535
|
|
|
5178
|
-
|
|
5536
|
+
/**
|
|
5537
|
+
* Inserts the specified contents into the range.
|
|
5538
|
+
*/
|
|
5179
5539
|
function insertContents(range, contents) {
|
|
5180
5540
|
if (range.commonAncestor.isOutside) {
|
|
5181
5541
|
return;
|
|
@@ -5223,7 +5583,7 @@ function getDeepElement(element) {
|
|
|
5223
5583
|
|
|
5224
5584
|
// Appends a list of nodes to the specified element.
|
|
5225
5585
|
function wrapNodeList(nodeList, wrapper) {
|
|
5226
|
-
wrapper = wrapper !== null && wrapper !==
|
|
5586
|
+
wrapper = wrapper !== null && wrapper !== void 0 ? wrapper : query('<p />');
|
|
5227
5587
|
if (nodeList.length === 0) {
|
|
5228
5588
|
return wrapper;
|
|
5229
5589
|
}
|
|
@@ -5261,7 +5621,9 @@ function getTopNonBlockNodes(range) {
|
|
|
5261
5621
|
}
|
|
5262
5622
|
return nodeList;
|
|
5263
5623
|
}
|
|
5264
|
-
|
|
5624
|
+
/**
|
|
5625
|
+
* Adds new blocks or changes the target blocks in the specified range.
|
|
5626
|
+
*/
|
|
5265
5627
|
function setBlocks(range, value) {
|
|
5266
5628
|
if (range.commonAncestor.isOutside) {
|
|
5267
5629
|
return;
|
|
@@ -5414,7 +5776,9 @@ function removeEmptyMarks(node) {
|
|
|
5414
5776
|
}
|
|
5415
5777
|
}
|
|
5416
5778
|
|
|
5417
|
-
|
|
5779
|
+
/**
|
|
5780
|
+
* Removes the contents of the specified range and then splits the block node at the point of the collapsed range.
|
|
5781
|
+
*/
|
|
5418
5782
|
// <p>one<anchor />two<focus />three</p>
|
|
5419
5783
|
// to
|
|
5420
5784
|
// <p>one</p>
|
|
@@ -5478,7 +5842,9 @@ function splitBlock$1(range) {
|
|
|
5478
5842
|
};
|
|
5479
5843
|
}
|
|
5480
5844
|
|
|
5481
|
-
|
|
5845
|
+
/**
|
|
5846
|
+
* Inserts a block into the specified range.
|
|
5847
|
+
*/
|
|
5482
5848
|
function insertBlock(range, value) {
|
|
5483
5849
|
if (range.commonAncestor.isOutside) {
|
|
5484
5850
|
return null;
|
|
@@ -5506,7 +5872,9 @@ function insertBlock(range, value) {
|
|
|
5506
5872
|
return block;
|
|
5507
5873
|
}
|
|
5508
5874
|
|
|
5509
|
-
|
|
5875
|
+
/**
|
|
5876
|
+
* Splits text nodes or mark nodes.
|
|
5877
|
+
*/
|
|
5510
5878
|
function splitMarksAtPoint(node, offset, removeEmptyMark) {
|
|
5511
5879
|
let start = null;
|
|
5512
5880
|
let end = null;
|
|
@@ -5586,7 +5954,9 @@ function splitMarks(range, removeEmptyMark = true) {
|
|
|
5586
5954
|
};
|
|
5587
5955
|
}
|
|
5588
5956
|
|
|
5589
|
-
|
|
5957
|
+
/**
|
|
5958
|
+
* Removes zero-width space at the beginning or end of the specified node.
|
|
5959
|
+
*/
|
|
5590
5960
|
function removePreviousOrNextZWS(node) {
|
|
5591
5961
|
const prevNode = node.prev();
|
|
5592
5962
|
if (prevNode.length > 0 && prevNode.isText && prevNode.isEmpty) {
|
|
@@ -5597,7 +5967,9 @@ function removePreviousOrNextZWS(node) {
|
|
|
5597
5967
|
nextNode.remove();
|
|
5598
5968
|
}
|
|
5599
5969
|
}
|
|
5600
|
-
|
|
5970
|
+
/**
|
|
5971
|
+
* Returns a nested mark copied from ancestors of the specified node.
|
|
5972
|
+
*/
|
|
5601
5973
|
function getNestedMark$1(node) {
|
|
5602
5974
|
let parent = node;
|
|
5603
5975
|
if (parent.isText) {
|
|
@@ -5620,22 +5992,26 @@ function getNestedMark$1(node) {
|
|
|
5620
5992
|
}
|
|
5621
5993
|
return mark;
|
|
5622
5994
|
}
|
|
5623
|
-
|
|
5995
|
+
/**
|
|
5996
|
+
* Returns the topmost mark element or the closest element with the same tag name as the specified node.
|
|
5997
|
+
*/
|
|
5624
5998
|
function getUpperMark(node, tagName) {
|
|
5625
5999
|
const nodeText = node.text();
|
|
5626
6000
|
let parent = node;
|
|
5627
6001
|
while (parent.length > 0) {
|
|
5628
6002
|
const nextParent = parent.parent();
|
|
5629
|
-
if (!nextParent.isMark
|
|
5630
|
-
nodeText !== nextParent.text()
|
|
5631
|
-
!parent.isText && parent.name === tagName && parent.attr('style') !== '') {
|
|
6003
|
+
if (!nextParent.isMark
|
|
6004
|
+
|| nodeText !== nextParent.text()
|
|
6005
|
+
|| (!parent.isText && parent.name === tagName && parent.attr('style') !== '')) {
|
|
5632
6006
|
break;
|
|
5633
6007
|
}
|
|
5634
6008
|
parent = nextParent;
|
|
5635
6009
|
}
|
|
5636
6010
|
return parent;
|
|
5637
6011
|
}
|
|
5638
|
-
|
|
6012
|
+
/**
|
|
6013
|
+
* Adds the specified mark to the texts of the range.
|
|
6014
|
+
*/
|
|
5639
6015
|
function addMark(range, value) {
|
|
5640
6016
|
if (range.commonAncestor.isOutside) {
|
|
5641
6017
|
return;
|
|
@@ -5730,7 +6106,9 @@ function removeZWS(node) {
|
|
|
5730
6106
|
}
|
|
5731
6107
|
}
|
|
5732
6108
|
|
|
5733
|
-
|
|
6109
|
+
/**
|
|
6110
|
+
* Returns a nested mark copied from each last child of the descendants of the specified node.
|
|
6111
|
+
*/
|
|
5734
6112
|
function getNestedMark(node, tagName) {
|
|
5735
6113
|
if (!node.isMark || !tagName) {
|
|
5736
6114
|
return null;
|
|
@@ -5757,7 +6135,9 @@ function getNestedMark(node, tagName) {
|
|
|
5757
6135
|
}
|
|
5758
6136
|
return mark;
|
|
5759
6137
|
}
|
|
5760
|
-
|
|
6138
|
+
/**
|
|
6139
|
+
* Removes the specified marks in the range.
|
|
6140
|
+
*/
|
|
5761
6141
|
function removeMark(range, value) {
|
|
5762
6142
|
if (range.commonAncestor.isOutside) {
|
|
5763
6143
|
return;
|
|
@@ -5819,7 +6199,9 @@ function removeMark(range, value) {
|
|
|
5819
6199
|
toBookmark(range, bookmark);
|
|
5820
6200
|
}
|
|
5821
6201
|
|
|
5822
|
-
|
|
6202
|
+
/**
|
|
6203
|
+
* Inserts a box into the specified range.
|
|
6204
|
+
*/
|
|
5823
6205
|
function insertBox(range, boxName, boxValue) {
|
|
5824
6206
|
if (range.commonAncestor.isOutside) {
|
|
5825
6207
|
return null;
|
|
@@ -5863,7 +6245,9 @@ function unmountBox(box) {
|
|
|
5863
6245
|
}
|
|
5864
6246
|
return box;
|
|
5865
6247
|
}
|
|
5866
|
-
|
|
6248
|
+
/**
|
|
6249
|
+
* Removes a box that contains the specified range.
|
|
6250
|
+
*/
|
|
5867
6251
|
function removeBox(range) {
|
|
5868
6252
|
if (range.commonAncestor.isOutside) {
|
|
5869
6253
|
return null;
|
|
@@ -5891,36 +6275,38 @@ function removeBox(range) {
|
|
|
5891
6275
|
return box;
|
|
5892
6276
|
}
|
|
5893
6277
|
|
|
5894
|
-
var version = "0.3.
|
|
6278
|
+
var version = "0.3.4";
|
|
5895
6279
|
|
|
5896
6280
|
// Converts the custom HTML tags to the special tags that can not be parsed by browser.
|
|
5897
6281
|
function denormalizeValue(value) {
|
|
5898
|
-
return value
|
|
5899
|
-
replace(/(<lake-box[^>]+>)[\s\S]*?(<\/lake-box>)/
|
|
5900
|
-
replace(/<lake-bookmark\s+type="anchor">\s*<\/lake-bookmark>/
|
|
5901
|
-
replace(/<lake-bookmark\s+type="focus">\s*<\/lake-bookmark>/
|
|
6282
|
+
return value
|
|
6283
|
+
.replace(/(<lake-box[^>]+>)[\s\S]*?(<\/lake-box>)/gi, '$1$2')
|
|
6284
|
+
.replace(/<lake-bookmark\s+type="anchor">\s*<\/lake-bookmark>/gi, '<anchor />')
|
|
6285
|
+
.replace(/<lake-bookmark\s+type="focus">\s*<\/lake-bookmark>/gi, '<focus />');
|
|
5902
6286
|
}
|
|
5903
6287
|
|
|
5904
6288
|
// Converts the special tags to ordinary HTML tags that can be parsed by browser.
|
|
5905
6289
|
function normalizeValue(value) {
|
|
5906
|
-
return value
|
|
5907
|
-
replace(/(<lake-box[^>]+>)[\s\S]*?(<\/lake-box>|$)/
|
|
5908
|
-
replace(/<anchor\s*\/>/
|
|
5909
|
-
replace(/<focus\s*\/>/
|
|
6290
|
+
return value
|
|
6291
|
+
.replace(/(<lake-box[^>]+>)[\s\S]*?(<\/lake-box>|$)/gi, '$1</lake-box>')
|
|
6292
|
+
.replace(/<anchor\s*\/>/gi, '<lake-bookmark type="anchor"></lake-bookmark>')
|
|
6293
|
+
.replace(/<focus\s*\/>/gi, '<lake-bookmark type="focus"></lake-bookmark>');
|
|
5910
6294
|
}
|
|
5911
6295
|
|
|
5912
6296
|
// If the specified node is not visible, scrolls the container that contains the node to its position to make it visible.
|
|
5913
6297
|
function scrollToNode(node, options) {
|
|
5914
6298
|
const visible = visibleInfo(node);
|
|
5915
|
-
if (visible.left !== 0
|
|
5916
|
-
visible.right !== 0
|
|
5917
|
-
visible.top !== 0
|
|
5918
|
-
visible.bottom !== 0) {
|
|
6299
|
+
if (visible.left !== 0
|
|
6300
|
+
|| visible.right !== 0
|
|
6301
|
+
|| visible.top !== 0
|
|
6302
|
+
|| visible.bottom !== 0) {
|
|
5919
6303
|
node.get(0).scrollIntoView(options);
|
|
5920
6304
|
}
|
|
5921
6305
|
}
|
|
5922
6306
|
|
|
5923
|
-
|
|
6307
|
+
/**
|
|
6308
|
+
* Returns a key-value object of all attributes of the specified element.
|
|
6309
|
+
*/
|
|
5924
6310
|
function getAttributes(element) {
|
|
5925
6311
|
const nativeElement = element.get(0);
|
|
5926
6312
|
const attributes = {};
|
|
@@ -5982,6 +6368,9 @@ function appendNextNestedNodes(activeItems, range) {
|
|
|
5982
6368
|
}
|
|
5983
6369
|
}
|
|
5984
6370
|
}
|
|
6371
|
+
/**
|
|
6372
|
+
* The Selection interface represents the range of content selected by the user or the current cursor position.
|
|
6373
|
+
*/
|
|
5985
6374
|
class Selection {
|
|
5986
6375
|
constructor(container) {
|
|
5987
6376
|
const selection = window.getSelection();
|
|
@@ -5994,7 +6383,9 @@ class Selection {
|
|
|
5994
6383
|
this.container = container;
|
|
5995
6384
|
this.range = this.getCurrentRange();
|
|
5996
6385
|
}
|
|
5997
|
-
|
|
6386
|
+
/**
|
|
6387
|
+
* Returns a Range object that is currently selected.
|
|
6388
|
+
*/
|
|
5998
6389
|
getCurrentRange() {
|
|
5999
6390
|
if (this.selection.rangeCount > 0) {
|
|
6000
6391
|
const range = this.selection.getRangeAt(0);
|
|
@@ -6002,7 +6393,9 @@ class Selection {
|
|
|
6002
6393
|
}
|
|
6003
6394
|
return new Range();
|
|
6004
6395
|
}
|
|
6005
|
-
|
|
6396
|
+
/**
|
|
6397
|
+
* Adds the selection.range to the native selection.
|
|
6398
|
+
*/
|
|
6006
6399
|
sync() {
|
|
6007
6400
|
if (!this.container.contains(this.range.commonAncestor)) {
|
|
6008
6401
|
return;
|
|
@@ -6010,21 +6403,25 @@ class Selection {
|
|
|
6010
6403
|
this.selection.removeAllRanges();
|
|
6011
6404
|
this.selection.addRange(this.range.get());
|
|
6012
6405
|
}
|
|
6013
|
-
|
|
6406
|
+
/**
|
|
6407
|
+
* Replaces the selection.range with the range of the native selection.
|
|
6408
|
+
*/
|
|
6014
6409
|
updateByRange() {
|
|
6015
6410
|
const newRange = this.getCurrentRange();
|
|
6016
6411
|
if (!this.container.contains(newRange.commonAncestor)) {
|
|
6017
6412
|
return;
|
|
6018
6413
|
}
|
|
6019
|
-
if (this.range.startNode.get(0) === newRange.startNode.get(0)
|
|
6020
|
-
this.range.startOffset === newRange.startOffset
|
|
6021
|
-
this.range.endNode.get(0) === newRange.endNode.get(0)
|
|
6022
|
-
this.range.endOffset === newRange.endOffset) {
|
|
6414
|
+
if (this.range.startNode.get(0) === newRange.startNode.get(0)
|
|
6415
|
+
&& this.range.startOffset === newRange.startOffset
|
|
6416
|
+
&& this.range.endNode.get(0) === newRange.endNode.get(0)
|
|
6417
|
+
&& this.range.endOffset === newRange.endOffset) {
|
|
6023
6418
|
return;
|
|
6024
6419
|
}
|
|
6025
6420
|
this.range = newRange;
|
|
6026
6421
|
}
|
|
6027
|
-
|
|
6422
|
+
/**
|
|
6423
|
+
* Replaces the selection.range with the range represented by the bookmark.
|
|
6424
|
+
*/
|
|
6028
6425
|
updateByBookmark() {
|
|
6029
6426
|
const range = this.range;
|
|
6030
6427
|
const container = this.container;
|
|
@@ -6045,43 +6442,78 @@ class Selection {
|
|
|
6045
6442
|
});
|
|
6046
6443
|
this.sync();
|
|
6047
6444
|
}
|
|
6445
|
+
/**
|
|
6446
|
+
* Returns a list of items related to the current selection.
|
|
6447
|
+
*/
|
|
6048
6448
|
getActiveItems() {
|
|
6049
6449
|
const activeItems = [];
|
|
6050
6450
|
appendAncestralNodes(activeItems, this.range);
|
|
6051
6451
|
appendNextNestedNodes(activeItems, this.range);
|
|
6052
6452
|
return activeItems;
|
|
6053
6453
|
}
|
|
6454
|
+
/**
|
|
6455
|
+
* Inserts a bookmark at the cursor position or a pair of bookmarks at the selection boundaries.
|
|
6456
|
+
*/
|
|
6054
6457
|
insertBookmark() {
|
|
6055
6458
|
return insertBookmark(this.range);
|
|
6056
6459
|
}
|
|
6460
|
+
/**
|
|
6461
|
+
* Changes selection.range to the range represented by the provided bookmark.
|
|
6462
|
+
*/
|
|
6057
6463
|
toBookmark(bookmark) {
|
|
6058
6464
|
return toBookmark(this.range, bookmark);
|
|
6059
6465
|
}
|
|
6466
|
+
/**
|
|
6467
|
+
* Inserts the specified content into the selection.
|
|
6468
|
+
*/
|
|
6060
6469
|
insertContents(contents) {
|
|
6061
6470
|
return insertContents(this.range, contents);
|
|
6062
6471
|
}
|
|
6472
|
+
/**
|
|
6473
|
+
* Removes the contents of the selection.
|
|
6474
|
+
*/
|
|
6063
6475
|
deleteContents() {
|
|
6064
6476
|
return deleteContents(this.range);
|
|
6065
6477
|
}
|
|
6478
|
+
/**
|
|
6479
|
+
* Adds new blocks or changes the target blocks in the selection.
|
|
6480
|
+
*/
|
|
6066
6481
|
setBlocks(value) {
|
|
6067
6482
|
return setBlocks(this.range, value);
|
|
6068
6483
|
}
|
|
6484
|
+
/**
|
|
6485
|
+
* Removes the contents of the selection and splits the block node at the cursor position.
|
|
6486
|
+
*/
|
|
6069
6487
|
splitBlock() {
|
|
6070
6488
|
return splitBlock$1(this.range);
|
|
6071
6489
|
}
|
|
6490
|
+
/**
|
|
6491
|
+
* Inserts a block into the selection.
|
|
6492
|
+
*/
|
|
6072
6493
|
insertBlock(value) {
|
|
6073
6494
|
return insertBlock(this.range, value);
|
|
6074
6495
|
}
|
|
6496
|
+
/**
|
|
6497
|
+
* Splits text nodes or mark nodes.
|
|
6498
|
+
*/
|
|
6075
6499
|
splitMarks(removeEmptyMark) {
|
|
6076
6500
|
return splitMarks(this.range, removeEmptyMark);
|
|
6077
6501
|
}
|
|
6502
|
+
/**
|
|
6503
|
+
* Adds the specified mark to the selected text.
|
|
6504
|
+
*/
|
|
6078
6505
|
addMark(value) {
|
|
6079
6506
|
return addMark(this.range, value);
|
|
6080
6507
|
}
|
|
6508
|
+
/**
|
|
6509
|
+
* Removes specified marks from the selection.
|
|
6510
|
+
*/
|
|
6081
6511
|
removeMark(value) {
|
|
6082
6512
|
return removeMark(this.range, value);
|
|
6083
6513
|
}
|
|
6084
|
-
|
|
6514
|
+
/**
|
|
6515
|
+
* Collapses the selection to the center position of the specified box.
|
|
6516
|
+
*/
|
|
6085
6517
|
selectBox(box) {
|
|
6086
6518
|
let boxNode = box;
|
|
6087
6519
|
if (box instanceof Box) {
|
|
@@ -6093,7 +6525,9 @@ class Selection {
|
|
|
6093
6525
|
this.range.selectBox(boxNode);
|
|
6094
6526
|
this.sync();
|
|
6095
6527
|
}
|
|
6096
|
-
|
|
6528
|
+
/**
|
|
6529
|
+
* Inserts a box into the selection.
|
|
6530
|
+
*/
|
|
6097
6531
|
insertBox(boxName, boxValue) {
|
|
6098
6532
|
const box = insertBox(this.range, boxName, boxValue);
|
|
6099
6533
|
if (!box) {
|
|
@@ -6101,7 +6535,9 @@ class Selection {
|
|
|
6101
6535
|
}
|
|
6102
6536
|
return box;
|
|
6103
6537
|
}
|
|
6104
|
-
|
|
6538
|
+
/**
|
|
6539
|
+
* Removes the specified box. If no parameter is given, the selected box is removed.
|
|
6540
|
+
*/
|
|
6105
6541
|
removeBox(box = null) {
|
|
6106
6542
|
if (box) {
|
|
6107
6543
|
this.selectBox(box);
|
|
@@ -6110,23 +6546,41 @@ class Selection {
|
|
|
6110
6546
|
}
|
|
6111
6547
|
}
|
|
6112
6548
|
|
|
6549
|
+
/**
|
|
6550
|
+
* The Command interface manages a collection of commands.
|
|
6551
|
+
*/
|
|
6113
6552
|
class Command {
|
|
6114
6553
|
constructor(selection) {
|
|
6115
6554
|
this.commandMap = new Map();
|
|
6116
6555
|
this.selection = selection;
|
|
6117
6556
|
}
|
|
6557
|
+
/**
|
|
6558
|
+
* Adds a new command to the collection.
|
|
6559
|
+
*/
|
|
6118
6560
|
add(name, commandItem) {
|
|
6119
6561
|
this.commandMap.set(name, commandItem);
|
|
6120
6562
|
}
|
|
6563
|
+
/**
|
|
6564
|
+
* Removes a command from the collection by its name.
|
|
6565
|
+
*/
|
|
6121
6566
|
delete(name) {
|
|
6122
6567
|
this.commandMap.delete(name);
|
|
6123
6568
|
}
|
|
6569
|
+
/**
|
|
6570
|
+
* Returns the names of all registered commands.
|
|
6571
|
+
*/
|
|
6124
6572
|
getNames() {
|
|
6125
6573
|
return Array.from(this.commandMap.keys());
|
|
6126
6574
|
}
|
|
6575
|
+
/**
|
|
6576
|
+
* Checks whether the specified command exists.
|
|
6577
|
+
*/
|
|
6127
6578
|
has(name) {
|
|
6128
6579
|
return this.commandMap.get(name) !== undefined;
|
|
6129
6580
|
}
|
|
6581
|
+
/**
|
|
6582
|
+
* Returns a command item by its name.
|
|
6583
|
+
*/
|
|
6130
6584
|
getItem(name) {
|
|
6131
6585
|
const commandItem = this.commandMap.get(name);
|
|
6132
6586
|
if (commandItem === undefined) {
|
|
@@ -6134,6 +6588,9 @@ class Command {
|
|
|
6134
6588
|
}
|
|
6135
6589
|
return commandItem;
|
|
6136
6590
|
}
|
|
6591
|
+
/**
|
|
6592
|
+
* Checks if the specified command is disabled.
|
|
6593
|
+
*/
|
|
6137
6594
|
isDisabled(name) {
|
|
6138
6595
|
const commandItem = this.getItem(name);
|
|
6139
6596
|
if (!commandItem.isDisabled) {
|
|
@@ -6142,6 +6599,9 @@ class Command {
|
|
|
6142
6599
|
const activeItems = this.selection.getActiveItems();
|
|
6143
6600
|
return commandItem.isDisabled(activeItems);
|
|
6144
6601
|
}
|
|
6602
|
+
/**
|
|
6603
|
+
* Checks if the specified command is selected.
|
|
6604
|
+
*/
|
|
6145
6605
|
isSelected(name) {
|
|
6146
6606
|
const commandItem = this.getItem(name);
|
|
6147
6607
|
if (!commandItem.isSelected) {
|
|
@@ -6150,6 +6610,9 @@ class Command {
|
|
|
6150
6610
|
const activeItems = this.selection.getActiveItems();
|
|
6151
6611
|
return commandItem.isSelected(activeItems);
|
|
6152
6612
|
}
|
|
6613
|
+
/**
|
|
6614
|
+
* Returns the selected values for the specified command.
|
|
6615
|
+
*/
|
|
6153
6616
|
selectedValues(name) {
|
|
6154
6617
|
const commandItem = this.getItem(name);
|
|
6155
6618
|
if (!commandItem.selectedValues) {
|
|
@@ -6158,6 +6621,9 @@ class Command {
|
|
|
6158
6621
|
const activeItems = this.selection.getActiveItems();
|
|
6159
6622
|
return commandItem.selectedValues(activeItems);
|
|
6160
6623
|
}
|
|
6624
|
+
/**
|
|
6625
|
+
* Executes the specified command.
|
|
6626
|
+
*/
|
|
6161
6627
|
execute(name, ...data) {
|
|
6162
6628
|
const container = this.selection.container;
|
|
6163
6629
|
const range = this.selection.range;
|
|
@@ -6170,7 +6636,7 @@ class Command {
|
|
|
6170
6636
|
}
|
|
6171
6637
|
}
|
|
6172
6638
|
|
|
6173
|
-
|
|
6639
|
+
/*
|
|
6174
6640
|
BSD 2-Clause License
|
|
6175
6641
|
|
|
6176
6642
|
Copyright (c) 2022, Big Sky Software
|
|
@@ -6270,7 +6736,7 @@ function getIdIntersectionCount(ctx, node1, node2) {
|
|
|
6270
6736
|
}
|
|
6271
6737
|
return matchCount;
|
|
6272
6738
|
}
|
|
6273
|
-
|
|
6739
|
+
/*
|
|
6274
6740
|
* A bottom up algorithm that finds all elements with ids inside of the node
|
|
6275
6741
|
* argument and populates id sets for those nodes and all their parents, generating
|
|
6276
6742
|
* a set of ids contained within all nodes for the entire hierarchy in the DOM
|
|
@@ -6298,7 +6764,7 @@ function populateIdMapForNode(node, idMap) {
|
|
|
6298
6764
|
}
|
|
6299
6765
|
}
|
|
6300
6766
|
}
|
|
6301
|
-
|
|
6767
|
+
/*
|
|
6302
6768
|
* This function computes a map of nodes to all ids contained within that node (inclusive of the
|
|
6303
6769
|
* node). This map can be used to ask if two nodes have intersecting sets of ids, which allows
|
|
6304
6770
|
* for a looser definition of "matching" than tradition id matching, and allows child nodes
|
|
@@ -6473,7 +6939,7 @@ function insertSiblings(previousSibling, morphedNode, nextSibling) {
|
|
|
6473
6939
|
const node = stack.pop();
|
|
6474
6940
|
added.push(node); // push added preceding siblings on in order and insert
|
|
6475
6941
|
if (node) {
|
|
6476
|
-
(_a = morphedNode.parentElement) === null || _a ===
|
|
6942
|
+
(_a = morphedNode.parentElement) === null || _a === void 0 ? void 0 : _a.insertBefore(node, morphedNode);
|
|
6477
6943
|
}
|
|
6478
6944
|
}
|
|
6479
6945
|
added.push(morphedNode);
|
|
@@ -6486,14 +6952,14 @@ function insertSiblings(previousSibling, morphedNode, nextSibling) {
|
|
|
6486
6952
|
while (stack.length > 0) {
|
|
6487
6953
|
const node = stack.pop();
|
|
6488
6954
|
if (node) {
|
|
6489
|
-
(_b = morphedNode.parentElement) === null || _b ===
|
|
6955
|
+
(_b = morphedNode.parentElement) === null || _b === void 0 ? void 0 : _b.insertBefore(node, morphedNode.nextSibling);
|
|
6490
6956
|
}
|
|
6491
6957
|
}
|
|
6492
6958
|
return added;
|
|
6493
6959
|
}
|
|
6494
6960
|
function scoreElement(node1, node2, ctx) {
|
|
6495
6961
|
if (isSoftMatch(node1, node2)) {
|
|
6496
|
-
return .5 + getIdIntersectionCount(ctx, node1, node2);
|
|
6962
|
+
return 0.5 + getIdIntersectionCount(ctx, node1, node2);
|
|
6497
6963
|
}
|
|
6498
6964
|
return 0;
|
|
6499
6965
|
}
|
|
@@ -6528,7 +6994,7 @@ function ignoreAttribute(attr, to, updateType, ctx) {
|
|
|
6528
6994
|
}
|
|
6529
6995
|
return ctx.callbacks.beforeAttributeUpdated(attr, to, updateType) === false;
|
|
6530
6996
|
}
|
|
6531
|
-
|
|
6997
|
+
/*
|
|
6532
6998
|
* @param possibleActiveElement
|
|
6533
6999
|
* @param ctx
|
|
6534
7000
|
* @returns {boolean}
|
|
@@ -6536,7 +7002,7 @@ function ignoreAttribute(attr, to, updateType, ctx) {
|
|
|
6536
7002
|
function ignoreValueOfActiveElement(possibleActiveElement, ctx) {
|
|
6537
7003
|
return ctx.ignoreActiveValue && possibleActiveElement === document.activeElement;
|
|
6538
7004
|
}
|
|
6539
|
-
|
|
7005
|
+
/*
|
|
6540
7006
|
* syncs a given node with another node, copying over all attributes and
|
|
6541
7007
|
* inner element state from the 'from' node to the 'to' node
|
|
6542
7008
|
*
|
|
@@ -6579,7 +7045,7 @@ function syncNodeFrom(from, to, ctx) {
|
|
|
6579
7045
|
}
|
|
6580
7046
|
}
|
|
6581
7047
|
}
|
|
6582
|
-
|
|
7048
|
+
/*
|
|
6583
7049
|
* @param oldNode root node to merge content into
|
|
6584
7050
|
* @param newContent new content to merge
|
|
6585
7051
|
* @param ctx the merge context
|
|
@@ -6600,7 +7066,7 @@ function morphOldNodeTo(oldNode, newContent, ctx) {
|
|
|
6600
7066
|
return oldNode;
|
|
6601
7067
|
if (ctx.callbacks.beforeNodeAdded(newContent) === false)
|
|
6602
7068
|
return oldNode;
|
|
6603
|
-
(_a = oldNode.parentElement) === null || _a ===
|
|
7069
|
+
(_a = oldNode.parentElement) === null || _a === void 0 ? void 0 : _a.replaceChild(newContent, oldNode);
|
|
6604
7070
|
ctx.callbacks.afterNodeAdded(newContent);
|
|
6605
7071
|
ctx.callbacks.afterNodeRemoved(oldNode);
|
|
6606
7072
|
return newContent;
|
|
@@ -6616,7 +7082,7 @@ function morphOldNodeTo(oldNode, newContent, ctx) {
|
|
|
6616
7082
|
return oldNode;
|
|
6617
7083
|
}
|
|
6618
7084
|
}
|
|
6619
|
-
|
|
7085
|
+
/*
|
|
6620
7086
|
* This is the core algorithm for matching up children. The idea is to use id sets to try to match up
|
|
6621
7087
|
* nodes as faithfully as possible. We greedily match, which allows us to keep the algorithm fast, but
|
|
6622
7088
|
* by using id sets, we are able to better match up with content deeper in the DOM.
|
|
@@ -6706,8 +7172,8 @@ function morphNormalizedContent(oldNode, normalizedNewContent, ctx) {
|
|
|
6706
7172
|
// into either side of the best match
|
|
6707
7173
|
const bestMatch = findBestNodeMatch(normalizedNewContent, oldNode, ctx);
|
|
6708
7174
|
// stash the siblings that will need to be inserted on either side of the best match
|
|
6709
|
-
const previousSibling = bestMatch === null || bestMatch ===
|
|
6710
|
-
const nextSibling = bestMatch === null || bestMatch ===
|
|
7175
|
+
const previousSibling = bestMatch === null || bestMatch === void 0 ? void 0 : bestMatch.previousSibling;
|
|
7176
|
+
const nextSibling = bestMatch === null || bestMatch === void 0 ? void 0 : bestMatch.nextSibling;
|
|
6711
7177
|
// morph it
|
|
6712
7178
|
const morphedNode = morphOldNodeTo(oldNode, bestMatch, ctx);
|
|
6713
7179
|
if (bestMatch) {
|
|
@@ -6729,7 +7195,10 @@ function morph(node, otherNode, config = {}) {
|
|
|
6729
7195
|
morphNormalizedContent(node.get(0), normalizedContent, ctx);
|
|
6730
7196
|
}
|
|
6731
7197
|
|
|
6732
|
-
|
|
7198
|
+
/**
|
|
7199
|
+
* The History interface manages undo and redo functionality for a container that holds some editable content.
|
|
7200
|
+
* It emits events when actions like save, undo, or redo are performed.
|
|
7201
|
+
*/
|
|
6733
7202
|
//
|
|
6734
7203
|
// Example:
|
|
6735
7204
|
//
|
|
@@ -6746,19 +7215,29 @@ function morph(node, otherNode, config = {}) {
|
|
|
6746
7215
|
class History {
|
|
6747
7216
|
constructor(selection) {
|
|
6748
7217
|
this.canSave = true;
|
|
6749
|
-
|
|
7218
|
+
/**
|
|
7219
|
+
* A list in which the current and previous contents are stored.
|
|
7220
|
+
*/
|
|
6750
7221
|
this.list = [];
|
|
6751
|
-
|
|
7222
|
+
/**
|
|
7223
|
+
* An index that always indicates the position at which new content is stored.
|
|
7224
|
+
*/
|
|
6752
7225
|
this.index = 0;
|
|
7226
|
+
/**
|
|
7227
|
+
* The maximum length of the history. Once this limit is reached, the earliest item in the list will be removed.
|
|
7228
|
+
*/
|
|
6753
7229
|
this.limit = 100;
|
|
7230
|
+
/**
|
|
7231
|
+
* An EventEmitter object used to set up events.
|
|
7232
|
+
*/
|
|
6754
7233
|
this.event = new EventEmitter();
|
|
6755
7234
|
this.selection = selection;
|
|
6756
7235
|
this.container = selection.container;
|
|
6757
7236
|
}
|
|
6758
7237
|
removeBookmark(value) {
|
|
6759
|
-
return value.replace(/(<lake-box[^>]+)\
|
|
6760
|
-
replace(/<lake-bookmark\s+type="anchor">\s*<\/lake-bookmark>/
|
|
6761
|
-
replace(/<lake-bookmark\s+type="focus">\s*<\/lake-bookmark>/
|
|
7238
|
+
return value.replace(/(<lake-box[^>]+)\sfocus="\w+"([^>]*>)/gi, '$1$2')
|
|
7239
|
+
.replace(/<lake-bookmark\s+type="anchor">\s*<\/lake-bookmark>/gi, '')
|
|
7240
|
+
.replace(/<lake-bookmark\s+type="focus">\s*<\/lake-bookmark>/gi, '');
|
|
6762
7241
|
}
|
|
6763
7242
|
getValue(container) {
|
|
6764
7243
|
return new HTMLParser(container).getHTML();
|
|
@@ -6802,12 +7281,22 @@ class History {
|
|
|
6802
7281
|
this.removeIdfromBoxes(container);
|
|
6803
7282
|
this.removeIdfromBoxes(otherContainer);
|
|
6804
7283
|
}
|
|
7284
|
+
/**
|
|
7285
|
+
* A boolean value indicating whether the history can be undone.
|
|
7286
|
+
*/
|
|
6805
7287
|
get canUndo() {
|
|
6806
7288
|
return this.index > 1 && !!this.list[this.index - 2];
|
|
6807
7289
|
}
|
|
7290
|
+
/**
|
|
7291
|
+
* A boolean value indicating whether the history can be redone.
|
|
7292
|
+
*/
|
|
6808
7293
|
get canRedo() {
|
|
6809
7294
|
return !!this.list[this.index];
|
|
6810
7295
|
}
|
|
7296
|
+
/**
|
|
7297
|
+
* Creates a deep clone of the current container with its content.
|
|
7298
|
+
* If there is a selection within the container, it ensures the selection is also preserved in the cloned container.
|
|
7299
|
+
*/
|
|
6811
7300
|
cloneContainer() {
|
|
6812
7301
|
const range = this.selection.range;
|
|
6813
7302
|
const newContainer = this.container.clone(true);
|
|
@@ -6837,6 +7326,9 @@ class History {
|
|
|
6837
7326
|
insertBookmark(newRange);
|
|
6838
7327
|
return newContainer;
|
|
6839
7328
|
}
|
|
7329
|
+
/**
|
|
7330
|
+
* Undoes to the previous saved content.
|
|
7331
|
+
*/
|
|
6840
7332
|
undo() {
|
|
6841
7333
|
if (!this.list[this.index - 2]) {
|
|
6842
7334
|
return;
|
|
@@ -6859,6 +7351,9 @@ class History {
|
|
|
6859
7351
|
this.selection.updateByBookmark();
|
|
6860
7352
|
debug(`History undone (index: ${this.index})`);
|
|
6861
7353
|
}
|
|
7354
|
+
/**
|
|
7355
|
+
* Redoes to the next saved content.
|
|
7356
|
+
*/
|
|
6862
7357
|
redo() {
|
|
6863
7358
|
if (!this.list[this.index]) {
|
|
6864
7359
|
return;
|
|
@@ -6881,24 +7376,36 @@ class History {
|
|
|
6881
7376
|
this.selection.updateByBookmark();
|
|
6882
7377
|
debug(`History redone (index: ${this.index})`);
|
|
6883
7378
|
}
|
|
7379
|
+
/**
|
|
7380
|
+
* Resumes the ability to save history.
|
|
7381
|
+
* This method re-enables saving after the pause method has been called.
|
|
7382
|
+
*/
|
|
6884
7383
|
continue() {
|
|
6885
7384
|
this.canSave = true;
|
|
6886
7385
|
}
|
|
7386
|
+
/**
|
|
7387
|
+
* Pauses the ability to save history.
|
|
7388
|
+
* This method temporarily disables saving history, which can be resumed later by calling the continue method.
|
|
7389
|
+
*/
|
|
6887
7390
|
pause() {
|
|
6888
7391
|
this.canSave = false;
|
|
6889
7392
|
}
|
|
7393
|
+
/**
|
|
7394
|
+
* Saves the current content to the history.
|
|
7395
|
+
* The content is saved only if it is different from the previous content.
|
|
7396
|
+
*/
|
|
6890
7397
|
save(options = {}) {
|
|
6891
7398
|
var _a, _b, _c;
|
|
6892
|
-
const inputType = (_a = options.inputType) !== null && _a !==
|
|
6893
|
-
const update = (_b = options.update) !== null && _b !==
|
|
6894
|
-
const emitEvent = (_c = options.emitEvent) !== null && _c !==
|
|
7399
|
+
const inputType = (_a = options.inputType) !== null && _a !== void 0 ? _a : '';
|
|
7400
|
+
const update = (_b = options.update) !== null && _b !== void 0 ? _b : false;
|
|
7401
|
+
const emitEvent = (_c = options.emitEvent) !== null && _c !== void 0 ? _c : true;
|
|
6895
7402
|
if (!this.canSave) {
|
|
6896
7403
|
return;
|
|
6897
7404
|
}
|
|
6898
7405
|
const item = this.cloneContainer();
|
|
6899
7406
|
const value = this.getValue(item);
|
|
6900
|
-
if (this.list[this.index - 1]
|
|
6901
|
-
this.removeBookmark(this.getValue(this.list[this.index - 1])) === this.removeBookmark(value)) {
|
|
7407
|
+
if (this.list[this.index - 1]
|
|
7408
|
+
&& this.removeBookmark(this.getValue(this.list[this.index - 1])) === this.removeBookmark(value)) {
|
|
6902
7409
|
return;
|
|
6903
7410
|
}
|
|
6904
7411
|
if (update) {
|
|
@@ -6923,6 +7430,10 @@ class History {
|
|
|
6923
7430
|
}
|
|
6924
7431
|
}
|
|
6925
7432
|
|
|
7433
|
+
/**
|
|
7434
|
+
* The Keystroke interface provides a way to handle keyboard events and define custom shortcuts for a given container.
|
|
7435
|
+
* It allows you to register hotkeys, bind specific actions to them, and handle their execution.
|
|
7436
|
+
*/
|
|
6926
7437
|
class Keystroke {
|
|
6927
7438
|
constructor(container) {
|
|
6928
7439
|
this.keydownEventList = [];
|
|
@@ -6961,21 +7472,29 @@ class Keystroke {
|
|
|
6961
7472
|
}
|
|
6962
7473
|
});
|
|
6963
7474
|
}
|
|
6964
|
-
|
|
7475
|
+
/**
|
|
7476
|
+
* Registers a keydown event listener for the specified key combination.
|
|
7477
|
+
* The listener will be triggered when the key combination is pressed.
|
|
7478
|
+
*/
|
|
6965
7479
|
setKeydown(type, listener) {
|
|
6966
7480
|
this.keydownEventList.push({
|
|
6967
7481
|
type,
|
|
6968
7482
|
listener,
|
|
6969
7483
|
});
|
|
6970
7484
|
}
|
|
6971
|
-
|
|
7485
|
+
/**
|
|
7486
|
+
* Registers a keyup event listener for the specified key combination.
|
|
7487
|
+
* The listener will be triggered when the key combination is released.
|
|
7488
|
+
*/
|
|
6972
7489
|
setKeyup(type, listener) {
|
|
6973
7490
|
this.keyupEventList.push({
|
|
6974
7491
|
type,
|
|
6975
7492
|
listener,
|
|
6976
7493
|
});
|
|
6977
7494
|
}
|
|
6978
|
-
|
|
7495
|
+
/**
|
|
7496
|
+
* Triggers all keydown event listeners associated with the specified key combination.
|
|
7497
|
+
*/
|
|
6979
7498
|
keydown(type) {
|
|
6980
7499
|
for (const item of this.keydownEventList) {
|
|
6981
7500
|
if (item.type === type) {
|
|
@@ -6985,7 +7504,9 @@ class Keystroke {
|
|
|
6985
7504
|
}
|
|
6986
7505
|
}
|
|
6987
7506
|
}
|
|
6988
|
-
|
|
7507
|
+
/**
|
|
7508
|
+
* Triggers all keyup event listeners associated with the specified key combination.
|
|
7509
|
+
*/
|
|
6989
7510
|
keyup(type) {
|
|
6990
7511
|
for (const item of this.keyupEventList) {
|
|
6991
7512
|
if (item.type === type) {
|
|
@@ -6997,25 +7518,48 @@ class Keystroke {
|
|
|
6997
7518
|
}
|
|
6998
7519
|
}
|
|
6999
7520
|
|
|
7521
|
+
/**
|
|
7522
|
+
* The BoxManager interface manages a collection of BoxComponent objects.
|
|
7523
|
+
* It allows you to add, remove, and retrieve the names of components.
|
|
7524
|
+
*/
|
|
7000
7525
|
class BoxManager {
|
|
7526
|
+
/**
|
|
7527
|
+
* Adds a BoxComponent to the collection.
|
|
7528
|
+
*/
|
|
7001
7529
|
add(component) {
|
|
7002
7530
|
boxes.set(component.name, component);
|
|
7003
7531
|
}
|
|
7532
|
+
/**
|
|
7533
|
+
* Removes a box component from the collection by its name.
|
|
7534
|
+
*/
|
|
7004
7535
|
remove(name) {
|
|
7005
7536
|
boxes.delete(name);
|
|
7006
7537
|
}
|
|
7538
|
+
/**
|
|
7539
|
+
* Returns a list of all box component names in the collection.
|
|
7540
|
+
*/
|
|
7007
7541
|
getNames() {
|
|
7008
7542
|
return Array.from(boxes.keys());
|
|
7009
7543
|
}
|
|
7010
7544
|
}
|
|
7011
7545
|
|
|
7546
|
+
/**
|
|
7547
|
+
* The Plugin interface manages a collection of plugins.
|
|
7548
|
+
* It allows plugins to be added and loaded into an Editor instance, and it handles the initialization and unmounting of those plugins.
|
|
7549
|
+
*/
|
|
7012
7550
|
class Plugin {
|
|
7013
7551
|
constructor() {
|
|
7014
7552
|
this.pluginMap = new Map();
|
|
7015
7553
|
}
|
|
7554
|
+
/**
|
|
7555
|
+
* Registers a plugin using a name as the key.
|
|
7556
|
+
*/
|
|
7016
7557
|
add(name, plugin) {
|
|
7017
7558
|
this.pluginMap.set(name, plugin);
|
|
7018
7559
|
}
|
|
7560
|
+
/**
|
|
7561
|
+
* Loads all registered plugins.
|
|
7562
|
+
*/
|
|
7019
7563
|
loadAll(editor) {
|
|
7020
7564
|
const unmountPluginMap = new Map();
|
|
7021
7565
|
for (const name of this.pluginMap.keys()) {
|
|
@@ -7048,41 +7592,53 @@ const defaultConfig = {
|
|
|
7048
7592
|
return;
|
|
7049
7593
|
}
|
|
7050
7594
|
if (type === 'warning') {
|
|
7051
|
-
// eslint-disable-next-line no-console
|
|
7052
7595
|
console.warn(message);
|
|
7053
7596
|
return;
|
|
7054
7597
|
}
|
|
7055
7598
|
if (type === 'error') {
|
|
7056
|
-
// eslint-disable-next-line no-console
|
|
7057
7599
|
console.error(message);
|
|
7058
7600
|
}
|
|
7059
7601
|
},
|
|
7060
7602
|
slash: false,
|
|
7061
7603
|
mention: false,
|
|
7062
7604
|
};
|
|
7063
|
-
|
|
7605
|
+
/**
|
|
7606
|
+
* The Editor interface provides properties and methods for rendering and manipulating the editor.
|
|
7607
|
+
*/
|
|
7064
7608
|
class Editor {
|
|
7065
7609
|
constructor(config) {
|
|
7066
|
-
|
|
7610
|
+
/**
|
|
7611
|
+
* A string that has not yet been saved to the history.
|
|
7612
|
+
*/
|
|
7067
7613
|
this.unsavedInputData = '';
|
|
7068
|
-
|
|
7614
|
+
/**
|
|
7615
|
+
* The number of input event calls before saving to the history.
|
|
7616
|
+
*/
|
|
7069
7617
|
this.unsavedInputCount = 0;
|
|
7070
|
-
|
|
7618
|
+
/**
|
|
7619
|
+
* The state of the current selection.
|
|
7620
|
+
*/
|
|
7071
7621
|
this.state = {
|
|
7072
7622
|
activeItems: [],
|
|
7073
7623
|
disabledNameMap: new Map(),
|
|
7074
7624
|
selectedNameMap: new Map(),
|
|
7075
7625
|
selectedValuesMap: new Map(),
|
|
7076
7626
|
};
|
|
7077
|
-
|
|
7627
|
+
/**
|
|
7628
|
+
* The functions for unmounting plugins.
|
|
7629
|
+
*/
|
|
7078
7630
|
this.unmountPluginMap = new Map();
|
|
7079
|
-
|
|
7631
|
+
/**
|
|
7632
|
+
* An EventEmitter object used to set up events.
|
|
7633
|
+
*/
|
|
7080
7634
|
this.event = new EventEmitter();
|
|
7081
|
-
|
|
7082
|
-
|
|
7083
|
-
|
|
7635
|
+
/**
|
|
7636
|
+
* A boolean value indicating whether a user is entering a character using a text composition system such as an Input Method Editor (IME).
|
|
7637
|
+
*/
|
|
7084
7638
|
this.isComposing = false;
|
|
7085
|
-
|
|
7639
|
+
/**
|
|
7640
|
+
* A pop-up component which is currently displayed, such as LinkPopup, MentionMenu, and SlashMenu.
|
|
7641
|
+
*/
|
|
7086
7642
|
this.popup = null;
|
|
7087
7643
|
this.copyListener = event => {
|
|
7088
7644
|
const range = this.selection.getCurrentRange();
|
|
@@ -7122,7 +7678,9 @@ class Editor {
|
|
|
7122
7678
|
}, 1, {
|
|
7123
7679
|
immediate: true,
|
|
7124
7680
|
});
|
|
7125
|
-
|
|
7681
|
+
/**
|
|
7682
|
+
* Updates the classes of all boxes when the current selection is changed.
|
|
7683
|
+
*/
|
|
7126
7684
|
this.updateBoxSelectionStyle = debounce(() => {
|
|
7127
7685
|
// The editor has been unmounted.
|
|
7128
7686
|
if (this.root.first().length === 0) {
|
|
@@ -7170,7 +7728,9 @@ class Editor {
|
|
|
7170
7728
|
}, 50, {
|
|
7171
7729
|
immediate: true,
|
|
7172
7730
|
});
|
|
7173
|
-
|
|
7731
|
+
/**
|
|
7732
|
+
* Triggers the statechange event when the current selection is changed.
|
|
7733
|
+
*/
|
|
7174
7734
|
this.emitStateChangeEvent = debounce(() => {
|
|
7175
7735
|
const commandNames = this.command.getNames();
|
|
7176
7736
|
let activeItems = this.selection.getActiveItems();
|
|
@@ -7243,7 +7803,9 @@ class Editor {
|
|
|
7243
7803
|
this.keystroke = new Keystroke(this.container);
|
|
7244
7804
|
editors.set(this.container.id, this);
|
|
7245
7805
|
}
|
|
7246
|
-
|
|
7806
|
+
/**
|
|
7807
|
+
* Adds or Removes a placeholder class.
|
|
7808
|
+
*/
|
|
7247
7809
|
togglePlaceholderClass(value) {
|
|
7248
7810
|
value = denormalizeValue(value);
|
|
7249
7811
|
const className = 'lake-placeholder';
|
|
@@ -7254,7 +7816,9 @@ class Editor {
|
|
|
7254
7816
|
this.container.removeClass(className);
|
|
7255
7817
|
}
|
|
7256
7818
|
}
|
|
7257
|
-
|
|
7819
|
+
/**
|
|
7820
|
+
* Moves the input text from box strip to normal position.
|
|
7821
|
+
*/
|
|
7258
7822
|
moveBoxStripText() {
|
|
7259
7823
|
const selection = this.selection;
|
|
7260
7824
|
const range = selection.range;
|
|
@@ -7286,12 +7850,16 @@ class Editor {
|
|
|
7286
7850
|
stripNode.html('<br />');
|
|
7287
7851
|
selection.insertContents(document.createTextNode(text));
|
|
7288
7852
|
}
|
|
7289
|
-
|
|
7853
|
+
/**
|
|
7854
|
+
* Resets the value of "unsavedInputData" property.
|
|
7855
|
+
*/
|
|
7290
7856
|
resetUnsavedInputData() {
|
|
7291
7857
|
this.unsavedInputData = '';
|
|
7292
7858
|
this.unsavedInputCount = 0;
|
|
7293
7859
|
}
|
|
7294
|
-
|
|
7860
|
+
/**
|
|
7861
|
+
* Handles input event.
|
|
7862
|
+
*/
|
|
7295
7863
|
handleInputEvent(event) {
|
|
7296
7864
|
var _a;
|
|
7297
7865
|
this.selection.updateByRange();
|
|
@@ -7306,7 +7874,7 @@ class Editor {
|
|
|
7306
7874
|
}
|
|
7307
7875
|
const inputType = event instanceof CompositionEvent ? 'insertText' : event.inputType;
|
|
7308
7876
|
if (inputType === 'insertText') {
|
|
7309
|
-
const inputData = (_a = event.data) !== null && _a !==
|
|
7877
|
+
const inputData = (_a = event.data) !== null && _a !== void 0 ? _a : '';
|
|
7310
7878
|
if (inputData.length > 1) {
|
|
7311
7879
|
this.history.save({
|
|
7312
7880
|
inputType: 'insertText',
|
|
@@ -7333,7 +7901,9 @@ class Editor {
|
|
|
7333
7901
|
}
|
|
7334
7902
|
this.history.save();
|
|
7335
7903
|
}
|
|
7336
|
-
|
|
7904
|
+
/**
|
|
7905
|
+
* Binds events for inputting text.
|
|
7906
|
+
*/
|
|
7337
7907
|
bindInputEvents() {
|
|
7338
7908
|
this.container.on('compositionstart', () => {
|
|
7339
7909
|
this.isComposing = true;
|
|
@@ -7352,7 +7922,9 @@ class Editor {
|
|
|
7352
7922
|
this.handleInputEvent(event);
|
|
7353
7923
|
});
|
|
7354
7924
|
}
|
|
7355
|
-
|
|
7925
|
+
/**
|
|
7926
|
+
* Removes all unused box instances.
|
|
7927
|
+
*/
|
|
7356
7928
|
removeBoxGarbage() {
|
|
7357
7929
|
const instanceMap = getInstanceMap(this.container.id);
|
|
7358
7930
|
for (const box of instanceMap.values()) {
|
|
@@ -7362,7 +7934,9 @@ class Editor {
|
|
|
7362
7934
|
}
|
|
7363
7935
|
}
|
|
7364
7936
|
}
|
|
7365
|
-
|
|
7937
|
+
/**
|
|
7938
|
+
* Binds events for history.
|
|
7939
|
+
*/
|
|
7366
7940
|
bindHistoryEvents() {
|
|
7367
7941
|
const executeCommonMethods = (value) => {
|
|
7368
7942
|
if (this.fixContent()) {
|
|
@@ -7396,11 +7970,15 @@ class Editor {
|
|
|
7396
7970
|
}
|
|
7397
7971
|
});
|
|
7398
7972
|
}
|
|
7399
|
-
|
|
7973
|
+
/**
|
|
7974
|
+
* Returns translation functions for the specified language.
|
|
7975
|
+
*/
|
|
7400
7976
|
get locale() {
|
|
7401
7977
|
return i18nObject(this.config.lang);
|
|
7402
7978
|
}
|
|
7403
|
-
|
|
7979
|
+
/**
|
|
7980
|
+
* Sets the default config for the specified plugin.
|
|
7981
|
+
*/
|
|
7404
7982
|
setPluginConfig(name, config) {
|
|
7405
7983
|
if (typeof this.config[name] !== 'object') {
|
|
7406
7984
|
this.config[name] = {};
|
|
@@ -7411,7 +7989,9 @@ class Editor {
|
|
|
7411
7989
|
}
|
|
7412
7990
|
}
|
|
7413
7991
|
}
|
|
7414
|
-
|
|
7992
|
+
/**
|
|
7993
|
+
* Fixes incorrect content, such as adding paragraphs for void elements or removing empty tags.
|
|
7994
|
+
*/
|
|
7415
7995
|
fixContent() {
|
|
7416
7996
|
const range = this.selection.range;
|
|
7417
7997
|
const cellNode = range.commonAncestor.closest('td');
|
|
@@ -7446,7 +8026,9 @@ class Editor {
|
|
|
7446
8026
|
range.adjustBr();
|
|
7447
8027
|
return changed;
|
|
7448
8028
|
}
|
|
7449
|
-
|
|
8029
|
+
/**
|
|
8030
|
+
* Renders all boxes that haven't been rendered yet.
|
|
8031
|
+
*/
|
|
7450
8032
|
renderBoxes() {
|
|
7451
8033
|
this.removeBoxGarbage();
|
|
7452
8034
|
const container = this.container;
|
|
@@ -7460,7 +8042,9 @@ class Editor {
|
|
|
7460
8042
|
box.render();
|
|
7461
8043
|
});
|
|
7462
8044
|
}
|
|
7463
|
-
|
|
8045
|
+
/**
|
|
8046
|
+
* Scrolls to the cursor.
|
|
8047
|
+
*/
|
|
7464
8048
|
scrollToCursor() {
|
|
7465
8049
|
const range = this.selection.range;
|
|
7466
8050
|
if (range.isBox) {
|
|
@@ -7493,7 +8077,9 @@ class Editor {
|
|
|
7493
8077
|
});
|
|
7494
8078
|
artificialCursor.remove();
|
|
7495
8079
|
}
|
|
7496
|
-
|
|
8080
|
+
/**
|
|
8081
|
+
* Checks whether the editor has focus.
|
|
8082
|
+
*/
|
|
7497
8083
|
hasFocus() {
|
|
7498
8084
|
const activeElement = document.activeElement;
|
|
7499
8085
|
if (!activeElement) {
|
|
@@ -7501,7 +8087,9 @@ class Editor {
|
|
|
7501
8087
|
}
|
|
7502
8088
|
return query(activeElement).closest('.lake-container').get(0) === this.container.get(0);
|
|
7503
8089
|
}
|
|
7504
|
-
|
|
8090
|
+
/**
|
|
8091
|
+
* Sets focus on the editor.
|
|
8092
|
+
*/
|
|
7505
8093
|
focus() {
|
|
7506
8094
|
const range = this.selection.range;
|
|
7507
8095
|
if (this.container.contains(range.commonAncestor) && range.isBox) {
|
|
@@ -7509,11 +8097,15 @@ class Editor {
|
|
|
7509
8097
|
}
|
|
7510
8098
|
this.container.focus();
|
|
7511
8099
|
}
|
|
7512
|
-
|
|
8100
|
+
/**
|
|
8101
|
+
* Removes focus from the editor.
|
|
8102
|
+
*/
|
|
7513
8103
|
blur() {
|
|
7514
8104
|
this.container.blur();
|
|
7515
8105
|
}
|
|
7516
|
-
|
|
8106
|
+
/**
|
|
8107
|
+
* Sets the specified content to the editor.
|
|
8108
|
+
*/
|
|
7517
8109
|
setValue(value) {
|
|
7518
8110
|
value = normalizeValue(value);
|
|
7519
8111
|
const htmlParser = new HTMLParser(value);
|
|
@@ -7524,14 +8116,18 @@ class Editor {
|
|
|
7524
8116
|
this.renderBoxes();
|
|
7525
8117
|
this.selection.updateByBookmark();
|
|
7526
8118
|
}
|
|
7527
|
-
|
|
8119
|
+
/**
|
|
8120
|
+
* Returns the editor's content.
|
|
8121
|
+
*/
|
|
7528
8122
|
getValue() {
|
|
7529
8123
|
const item = this.history.cloneContainer();
|
|
7530
8124
|
let value = new HTMLParser(item).getHTML();
|
|
7531
8125
|
value = denormalizeValue(value);
|
|
7532
8126
|
return value;
|
|
7533
8127
|
}
|
|
7534
|
-
|
|
8128
|
+
/**
|
|
8129
|
+
* Renders an editing area and sets default content to it.
|
|
8130
|
+
*/
|
|
7535
8131
|
render() {
|
|
7536
8132
|
const value = normalizeValue(this.config.value);
|
|
7537
8133
|
const htmlParser = new HTMLParser(value);
|
|
@@ -7563,7 +8159,9 @@ class Editor {
|
|
|
7563
8159
|
this.bindHistoryEvents();
|
|
7564
8160
|
}
|
|
7565
8161
|
}
|
|
7566
|
-
|
|
8162
|
+
/**
|
|
8163
|
+
* Destroys the editor.
|
|
8164
|
+
*/
|
|
7567
8165
|
unmount() {
|
|
7568
8166
|
// Executes delayed executions immediately.
|
|
7569
8167
|
this.updateSelectionRange.flush();
|
|
@@ -7598,11 +8196,17 @@ class Editor {
|
|
|
7598
8196
|
}
|
|
7599
8197
|
}
|
|
7600
8198
|
}
|
|
7601
|
-
|
|
8199
|
+
/**
|
|
8200
|
+
* The current version of Lake.
|
|
8201
|
+
*/
|
|
7602
8202
|
Editor.version = version;
|
|
7603
|
-
|
|
8203
|
+
/**
|
|
8204
|
+
* A BoxManager object that manages the box components.
|
|
8205
|
+
*/
|
|
7604
8206
|
Editor.box = new BoxManager();
|
|
7605
|
-
|
|
8207
|
+
/**
|
|
8208
|
+
* A Plugin object that manages a collection of plugins.
|
|
8209
|
+
*/
|
|
7606
8210
|
Editor.plugin = new Plugin();
|
|
7607
8211
|
|
|
7608
8212
|
var copy = (editor) => {
|
|
@@ -7975,18 +8579,18 @@ var drop = (editor) => {
|
|
|
7975
8579
|
let targetBlcokRect = targetBlock.get(0).getBoundingClientRect();
|
|
7976
8580
|
dropPosition = 'bottom';
|
|
7977
8581
|
let left = targetBlcokRect.x - containerRect.x;
|
|
7978
|
-
let top = targetBlcokRect.y + targetBlcokRect.height - containerRect.y + (parseInt(targetBlock.computedCSS('margin-bottom'), 10) / 2);
|
|
8582
|
+
let top = targetBlcokRect.y + targetBlcokRect.height - containerRect.y + (Number.parseInt(targetBlock.computedCSS('margin-bottom'), 10) / 2);
|
|
7979
8583
|
if (dragEvent.clientY < targetBlcokRect.y + (targetBlcokRect.height / 2)) {
|
|
7980
8584
|
const prevBlock = targetBlock.prev();
|
|
7981
|
-
if (prevBlock.length > 0 && prevBlock.isBlock || prevBlock.isBlockBox) {
|
|
8585
|
+
if ((prevBlock.length > 0 && prevBlock.isBlock) || prevBlock.isBlockBox) {
|
|
7982
8586
|
targetBlock = prevBlock;
|
|
7983
8587
|
targetBlcokRect = targetBlock.get(0).getBoundingClientRect();
|
|
7984
8588
|
left = targetBlcokRect.x - containerRect.x;
|
|
7985
|
-
top = targetBlcokRect.y + targetBlcokRect.height - containerRect.y + (parseInt(targetBlock.computedCSS('margin-bottom'), 10) / 2);
|
|
8589
|
+
top = targetBlcokRect.y + targetBlcokRect.height - containerRect.y + (Number.parseInt(targetBlock.computedCSS('margin-bottom'), 10) / 2);
|
|
7986
8590
|
}
|
|
7987
8591
|
else {
|
|
7988
8592
|
dropPosition = 'top';
|
|
7989
|
-
top = targetBlcokRect.y - containerRect.y - (parseInt(editor.container.computedCSS('padding-top'), 10) / 2);
|
|
8593
|
+
top = targetBlcokRect.y - containerRect.y - (Number.parseInt(editor.container.computedCSS('padding-top'), 10) / 2);
|
|
7990
8594
|
}
|
|
7991
8595
|
}
|
|
7992
8596
|
dropIndication.css({
|
|
@@ -8384,8 +8988,10 @@ function insertColumn(range, direction) {
|
|
|
8384
8988
|
if (direction === 'right') {
|
|
8385
8989
|
const currentRowCells = tableMap[currentRowIndex];
|
|
8386
8990
|
columnIndex++;
|
|
8387
|
-
|
|
8388
|
-
columnIndex
|
|
8991
|
+
if (currentRowCells) {
|
|
8992
|
+
while (currentCell === currentRowCells[columnIndex]) {
|
|
8993
|
+
columnIndex++;
|
|
8994
|
+
}
|
|
8389
8995
|
}
|
|
8390
8996
|
}
|
|
8391
8997
|
debug(`insertColumn: rows ${table.rows.length}, column ${columnIndex}, ${direction}`);
|
|
@@ -9470,7 +10076,7 @@ class LinkPopup {
|
|
|
9470
10076
|
}
|
|
9471
10077
|
// Writes the specified text to the system clipboard
|
|
9472
10078
|
writeClipboardText(text) {
|
|
9473
|
-
return __awaiter(this,
|
|
10079
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
9474
10080
|
let error = false;
|
|
9475
10081
|
try {
|
|
9476
10082
|
if (window.LAKE_TEST) {
|
|
@@ -9792,9 +10398,9 @@ var link = (editor) => {
|
|
|
9792
10398
|
return;
|
|
9793
10399
|
}
|
|
9794
10400
|
const linkNode = targetNode.closest('a');
|
|
9795
|
-
if (linkNode.length === 0
|
|
9796
|
-
!editor.container.contains(linkNode)
|
|
9797
|
-
linkNode.closest('lake-box').length > 0) {
|
|
10401
|
+
if (linkNode.length === 0
|
|
10402
|
+
|| !editor.container.contains(linkNode)
|
|
10403
|
+
|| linkNode.closest('lake-box').length > 0) {
|
|
9798
10404
|
if (!popup.visible) {
|
|
9799
10405
|
return;
|
|
9800
10406
|
}
|
|
@@ -9992,7 +10598,7 @@ var codeBlockBox = {
|
|
|
9992
10598
|
});
|
|
9993
10599
|
const codeEditor = new EditorView({
|
|
9994
10600
|
parent: codeBlockNativeNode,
|
|
9995
|
-
doc: (_a = boxValue.code) !== null && _a !==
|
|
10601
|
+
doc: (_a = boxValue.code) !== null && _a !== void 0 ? _a : '',
|
|
9996
10602
|
extensions: [
|
|
9997
10603
|
EditorState.readOnly.of(editor.readonly),
|
|
9998
10604
|
EditorView.editable.of(!editor.readonly),
|
|
@@ -10091,7 +10697,7 @@ class CornerToolbar {
|
|
|
10091
10697
|
constructor(config) {
|
|
10092
10698
|
this.config = config;
|
|
10093
10699
|
this.locale = this.config.locale || i18nObject('en-US');
|
|
10094
|
-
this.root = config.root;
|
|
10700
|
+
this.root = query(config.root);
|
|
10095
10701
|
this.container = query('<div class="lake-corner-toolbar" />');
|
|
10096
10702
|
}
|
|
10097
10703
|
appendButton(item) {
|
|
@@ -10125,8 +10731,8 @@ class CornerToolbar {
|
|
|
10125
10731
|
class Resizer {
|
|
10126
10732
|
constructor(config) {
|
|
10127
10733
|
this.config = config;
|
|
10128
|
-
this.root = config.root;
|
|
10129
|
-
this.target = config.target;
|
|
10734
|
+
this.root = query(config.root);
|
|
10735
|
+
this.target = query(config.target);
|
|
10130
10736
|
this.container = query(template `
|
|
10131
10737
|
<div class="lake-resizer">
|
|
10132
10738
|
<div class="lake-resizer-top-left"></div>
|
|
@@ -10344,7 +10950,7 @@ function renderFloatingToolbar(box) {
|
|
|
10344
10950
|
}
|
|
10345
10951
|
// Loads an image and get its width and height.
|
|
10346
10952
|
function getImageInfo(url) {
|
|
10347
|
-
return __awaiter(this,
|
|
10953
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
10348
10954
|
const node = query('<img />');
|
|
10349
10955
|
node.css({
|
|
10350
10956
|
position: 'absolute',
|
|
@@ -10534,7 +11140,7 @@ function renderCaption(box) {
|
|
|
10534
11140
|
}
|
|
10535
11141
|
// Displays error icon and filename.
|
|
10536
11142
|
function renderError$1(box) {
|
|
10537
|
-
return __awaiter(this,
|
|
11143
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
10538
11144
|
const editor = box.getEditor();
|
|
10539
11145
|
const boxContainer = box.getContainer();
|
|
10540
11146
|
const value = box.value;
|
|
@@ -10577,7 +11183,7 @@ function renderError$1(box) {
|
|
|
10577
11183
|
}
|
|
10578
11184
|
// Displays an image with uplaoding progress.
|
|
10579
11185
|
function renderUploading(box) {
|
|
10580
|
-
return __awaiter(this,
|
|
11186
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
10581
11187
|
const editor = box.getEditor();
|
|
10582
11188
|
const boxContainer = box.getContainer();
|
|
10583
11189
|
const value = box.value;
|
|
@@ -10647,7 +11253,7 @@ function renderUploading(box) {
|
|
|
10647
11253
|
}
|
|
10648
11254
|
// Displays an image that can be previewed or removed.
|
|
10649
11255
|
function renderDone(box) {
|
|
10650
|
-
return __awaiter(this,
|
|
11256
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
10651
11257
|
const editor = box.getEditor();
|
|
10652
11258
|
const boxContainer = box.getContainer();
|
|
10653
11259
|
const value = box.value;
|
|
@@ -10833,7 +11439,7 @@ var image = (editor) => {
|
|
|
10833
11439
|
};
|
|
10834
11440
|
|
|
10835
11441
|
function getVideoId(url) {
|
|
10836
|
-
const result = /\w
|
|
11442
|
+
const result = /\w+$/.exec(url || '');
|
|
10837
11443
|
return result ? result[0] : '';
|
|
10838
11444
|
}
|
|
10839
11445
|
function appendButtonGroup(box) {
|
|
@@ -11040,7 +11646,7 @@ function setFloatingToolbar(box) {
|
|
|
11040
11646
|
box.setToolbar(items);
|
|
11041
11647
|
}
|
|
11042
11648
|
function appendContent(rootNode, box) {
|
|
11043
|
-
return __awaiter(this,
|
|
11649
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
11044
11650
|
const value = box.value;
|
|
11045
11651
|
const infoNode = query(template `
|
|
11046
11652
|
<div class="lake-file-info">
|
|
@@ -11283,7 +11889,7 @@ var specialCharacter = (editor) => {
|
|
|
11283
11889
|
});
|
|
11284
11890
|
};
|
|
11285
11891
|
|
|
11286
|
-
|
|
11892
|
+
function emptyCallback$2() { }
|
|
11287
11893
|
// The Menu class represents a list of options for selecting an item.
|
|
11288
11894
|
class Menu {
|
|
11289
11895
|
constructor(config) {
|
|
@@ -11303,27 +11909,29 @@ class Menu {
|
|
|
11303
11909
|
if (!isDownKey && !isUpKey && !isEnterKey) {
|
|
11304
11910
|
return;
|
|
11305
11911
|
}
|
|
11912
|
+
const nativeContainer = this.container.get(0);
|
|
11306
11913
|
const selectedItemNode = this.container.find('.lake-menu-item-selected');
|
|
11307
11914
|
if (selectedItemNode.length === 0) {
|
|
11915
|
+
event.preventDefault();
|
|
11308
11916
|
const firstItem = this.container.find('.lake-menu-item').eq(0);
|
|
11309
|
-
scrollToNode(firstItem, {
|
|
11310
|
-
behavior: 'instant',
|
|
11311
|
-
block: 'start',
|
|
11312
|
-
});
|
|
11313
11917
|
firstItem.addClass('lake-menu-item-selected');
|
|
11918
|
+
nativeContainer.scrollTop = 0;
|
|
11314
11919
|
return;
|
|
11315
11920
|
}
|
|
11316
11921
|
this.noMouseEvent = true;
|
|
11922
|
+
const paddingTop = Number.parseInt(this.container.computedCSS('padding-top'), 10) || 0;
|
|
11923
|
+
const paddingBottom = Number.parseInt(this.container.computedCSS('padding-bottom'), 10) || 0;
|
|
11317
11924
|
if (isDownKey) {
|
|
11318
11925
|
event.preventDefault();
|
|
11319
11926
|
let nextItemNode = selectedItemNode.next();
|
|
11320
11927
|
if (nextItemNode.length === 0) {
|
|
11321
11928
|
nextItemNode = this.container.find('.lake-menu-item').eq(0);
|
|
11322
11929
|
}
|
|
11323
|
-
|
|
11324
|
-
|
|
11325
|
-
|
|
11326
|
-
|
|
11930
|
+
const nextItemNativeNode = nextItemNode.get(0);
|
|
11931
|
+
const visible = visibleInfo(nextItemNode);
|
|
11932
|
+
if (visible.top !== 0 || visible.bottom !== 0) {
|
|
11933
|
+
nativeContainer.scrollTop = nextItemNativeNode.offsetTop - this.container.height() + nextItemNode.height() + paddingBottom;
|
|
11934
|
+
}
|
|
11327
11935
|
this.container.find('.lake-menu-item').removeClass('lake-menu-item-selected');
|
|
11328
11936
|
nextItemNode.addClass('lake-menu-item-selected');
|
|
11329
11937
|
}
|
|
@@ -11334,10 +11942,11 @@ class Menu {
|
|
|
11334
11942
|
const itemNode = this.container.find('.lake-menu-item');
|
|
11335
11943
|
prevItemNode = itemNode.eq(itemNode.length - 1);
|
|
11336
11944
|
}
|
|
11337
|
-
|
|
11338
|
-
|
|
11339
|
-
|
|
11340
|
-
|
|
11945
|
+
const prevItemNativeNode = prevItemNode.get(0);
|
|
11946
|
+
const visible = visibleInfo(prevItemNode);
|
|
11947
|
+
if (visible.top !== 0 || visible.bottom !== 0) {
|
|
11948
|
+
nativeContainer.scrollTop = prevItemNativeNode.offsetTop - paddingTop;
|
|
11949
|
+
}
|
|
11341
11950
|
this.container.find('.lake-menu-item').removeClass('lake-menu-item-selected');
|
|
11342
11951
|
prevItemNode.addClass('lake-menu-item-selected');
|
|
11343
11952
|
}
|
|
@@ -11516,7 +12125,7 @@ class Menu {
|
|
|
11516
12125
|
}
|
|
11517
12126
|
}
|
|
11518
12127
|
|
|
11519
|
-
|
|
12128
|
+
function emptyCallback$1() { }
|
|
11520
12129
|
// The MentionMenu class, inheriting from the Menu class, represents a list of users for selecting a user.
|
|
11521
12130
|
class MentionMenu extends Menu {
|
|
11522
12131
|
constructor(config) {
|
|
@@ -11529,7 +12138,7 @@ class MentionMenu extends Menu {
|
|
|
11529
12138
|
const itemNode = query(template `
|
|
11530
12139
|
<li>
|
|
11531
12140
|
<div class="lake-mention-avatar"></div>
|
|
11532
|
-
<div class="lake-mention-nickname">${(_a = item.nickname) !== null && _a !==
|
|
12141
|
+
<div class="lake-mention-nickname">${(_a = item.nickname) !== null && _a !== void 0 ? _a : item.name}</div>
|
|
11533
12142
|
<div class="lake-mention-name">(${item.name})</div>
|
|
11534
12143
|
</li>
|
|
11535
12144
|
`);
|
|
@@ -11551,10 +12160,10 @@ class MentionMenu extends Menu {
|
|
|
11551
12160
|
keyword = keyword.toLowerCase();
|
|
11552
12161
|
const items = [];
|
|
11553
12162
|
for (const item of this.items) {
|
|
11554
|
-
const nickname = (_a = item.nickname) !== null && _a !==
|
|
11555
|
-
if (item.name.toLowerCase().indexOf(keyword) >= 0
|
|
11556
|
-
nickname.toLowerCase().indexOf(keyword) >= 0
|
|
11557
|
-
nickname.replace(/\s+/g, '').indexOf(keyword) >= 0) {
|
|
12163
|
+
const nickname = (_a = item.nickname) !== null && _a !== void 0 ? _a : item.name;
|
|
12164
|
+
if (item.name.toLowerCase().indexOf(keyword) >= 0
|
|
12165
|
+
|| nickname.toLowerCase().indexOf(keyword) >= 0
|
|
12166
|
+
|| nickname.replace(/\s+/g, '').indexOf(keyword) >= 0) {
|
|
11558
12167
|
items.push(item);
|
|
11559
12168
|
}
|
|
11560
12169
|
}
|
|
@@ -11573,7 +12182,7 @@ var mentionBox = {
|
|
|
11573
12182
|
const url = getProfileUrl ? getProfileUrl(value) : '#';
|
|
11574
12183
|
const boxContainer = box.getContainer();
|
|
11575
12184
|
const rootNode = query(template `
|
|
11576
|
-
<div class="lake-mention"><a href="${url}">@${(_a = value.nickname) !== null && _a !==
|
|
12185
|
+
<div class="lake-mention"><a href="${url}">@${(_a = value.nickname) !== null && _a !== void 0 ? _a : value.name}</a></div>
|
|
11577
12186
|
`);
|
|
11578
12187
|
boxContainer.empty();
|
|
11579
12188
|
boxContainer.append(rootNode);
|
|
@@ -11776,7 +12385,7 @@ const blockItemListForSpaceKey = [
|
|
|
11776
12385
|
var _a;
|
|
11777
12386
|
return [
|
|
11778
12387
|
'heading',
|
|
11779
|
-
(_a = headingTypeMap.get(results[0])) !== null && _a !==
|
|
12388
|
+
(_a = headingTypeMap.get(results[0])) !== null && _a !== void 0 ? _a : 'h6',
|
|
11780
12389
|
];
|
|
11781
12390
|
},
|
|
11782
12391
|
},
|
|
@@ -11851,7 +12460,7 @@ const blockItemListForEnterKey = [
|
|
|
11851
12460
|
return [
|
|
11852
12461
|
'codeBlock',
|
|
11853
12462
|
{
|
|
11854
|
-
lang: (_a = shortLangTypeMap.get(results[1])) !== null && _a !==
|
|
12463
|
+
lang: (_a = shortLangTypeMap.get(results[1])) !== null && _a !== void 0 ? _a : results[1],
|
|
11855
12464
|
},
|
|
11856
12465
|
];
|
|
11857
12466
|
},
|
|
@@ -12272,8 +12881,8 @@ var backspaceKey = (editor) => {
|
|
|
12272
12881
|
const boxNode = range.commonAncestor.closest('lake-box');
|
|
12273
12882
|
const box = getBox(boxNode);
|
|
12274
12883
|
const boxValue = box.value;
|
|
12275
|
-
if (range.isCollapsed && box.name === 'codeBlock'
|
|
12276
|
-
(boxValue.code === undefined || boxValue.code === '')) {
|
|
12884
|
+
if (range.isCollapsed && box.name === 'codeBlock'
|
|
12885
|
+
&& (boxValue.code === undefined || boxValue.code === '')) {
|
|
12277
12886
|
event.preventDefault();
|
|
12278
12887
|
editor.selection.removeBox(box);
|
|
12279
12888
|
editor.history.save();
|
|
@@ -12391,9 +13000,9 @@ var backspaceKey = (editor) => {
|
|
|
12391
13000
|
editor.selection.setBlocks('<p />');
|
|
12392
13001
|
block = range.getBlocks()[0];
|
|
12393
13002
|
}
|
|
12394
|
-
if (block.css('margin-left') !== ''
|
|
12395
|
-
block.css('text-indent') !== ''
|
|
12396
|
-
block.attr('indent') !== '') {
|
|
13003
|
+
if (block.css('margin-left') !== ''
|
|
13004
|
+
|| block.css('text-indent') !== ''
|
|
13005
|
+
|| block.attr('indent') !== '') {
|
|
12397
13006
|
indentBlock(block, 'decrease');
|
|
12398
13007
|
editor.history.save();
|
|
12399
13008
|
return;
|
|
@@ -12922,7 +13531,7 @@ const slashItems = [
|
|
|
12922
13531
|
},
|
|
12923
13532
|
];
|
|
12924
13533
|
|
|
12925
|
-
|
|
13534
|
+
function emptyCallback() { }
|
|
12926
13535
|
const slashItemMap = new Map();
|
|
12927
13536
|
for (const item of slashItems) {
|
|
12928
13537
|
slashItemMap.set(item.name, item);
|
|
@@ -12991,10 +13600,10 @@ class SlashMenu extends Menu {
|
|
|
12991
13600
|
itemTitle = itemTitle.toLowerCase();
|
|
12992
13601
|
let itemTitleEnglish = typeof item.title === 'string' ? item.title : item.title(localeEnglish);
|
|
12993
13602
|
itemTitleEnglish = itemTitleEnglish.toLowerCase();
|
|
12994
|
-
if (itemTitle.indexOf(keyword) >= 0
|
|
12995
|
-
itemTitle.replace(/\s+/g, '').indexOf(keyword) >= 0
|
|
12996
|
-
itemTitleEnglish.indexOf(keyword) >= 0
|
|
12997
|
-
itemTitleEnglish.replace(/\s+/g, '').indexOf(keyword) >= 0) {
|
|
13603
|
+
if (itemTitle.indexOf(keyword) >= 0
|
|
13604
|
+
|| itemTitle.replace(/\s+/g, '').indexOf(keyword) >= 0
|
|
13605
|
+
|| itemTitleEnglish.indexOf(keyword) >= 0
|
|
13606
|
+
|| itemTitleEnglish.replace(/\s+/g, '').indexOf(keyword) >= 0) {
|
|
12998
13607
|
items.push(typeof name === 'string' ? item.name : name);
|
|
12999
13608
|
}
|
|
13000
13609
|
}
|
|
@@ -13091,9 +13700,9 @@ var slash = (editor) => {
|
|
|
13091
13700
|
return;
|
|
13092
13701
|
}
|
|
13093
13702
|
const block = range.getBlocks()[0];
|
|
13094
|
-
if (!block
|
|
13095
|
-
block.find('lake-box').length > 0
|
|
13096
|
-
block.closest('table').length > 0) {
|
|
13703
|
+
if (!block
|
|
13704
|
+
|| block.find('lake-box').length > 0
|
|
13705
|
+
|| block.closest('table').length > 0) {
|
|
13097
13706
|
return;
|
|
13098
13707
|
}
|
|
13099
13708
|
const keyword = getKeyword(block);
|
|
@@ -13195,5 +13804,5 @@ Editor.plugin.add('arrowKeys', arrowKeys);
|
|
|
13195
13804
|
Editor.plugin.add('escapeKey', escapeKey);
|
|
13196
13805
|
Editor.plugin.add('slash', slash);
|
|
13197
13806
|
|
|
13198
|
-
export { Box, Button, Dropdown, Editor, Fragment, HTMLParser, Nodes, Range, TextParser, Toolbar, addMark, deleteContents, icons, insertBlock, insertBookmark, insertBox, insertContents, query, removeBox, removeMark, setBlocks, splitBlock$1 as splitBlock, splitMarks, template, toBookmark, toHex };
|
|
13807
|
+
export { Box, Button, Dropdown, Editor, Fragment, HTMLParser, Nodes, Range, TextParser, Toolbar, addMark, deleteContents, getBox, icons, insertBlock, insertBookmark, insertBox, insertContents, query, removeBox, removeMark, setBlocks, splitBlock$1 as splitBlock, splitMarks, template, toBookmark, toHex };
|
|
13199
13808
|
//# sourceMappingURL=lake.js.map
|