lakelib 0.3.9 → 0.3.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lake.min.css +5 -5
- package/dist/lake.min.js +36 -41
- package/dist/lake.min.js.map +1 -1
- package/lib/lake.css +112 -73
- package/lib/lake.d.ts +106 -1
- package/lib/lake.js +469 -281
- package/lib/lake.js.map +1 -1
- package/package.json +3 -3
package/lib/lake.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import EventEmitter from 'eventemitter3';
|
|
2
2
|
import { i18nObject as i18nObject$1 } from 'typesafe-i18n';
|
|
3
|
+
import { isKeyHotkey } from 'is-hotkey';
|
|
3
4
|
import debounce from 'debounce';
|
|
4
5
|
import isEqual from 'fast-deep-equal/es6';
|
|
5
|
-
import { isKeyHotkey } from 'is-hotkey';
|
|
6
6
|
import 'photoswipe/style.css';
|
|
7
7
|
import PhotoSwipeLightbox from 'photoswipe/lightbox';
|
|
8
8
|
import PhotoSwipe from 'photoswipe';
|
|
@@ -149,6 +149,8 @@ var specialCharacter$1 = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"32\"
|
|
|
149
149
|
|
|
150
150
|
var equation$1 = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"32\" height=\"32\" fill=\"#000000\" viewBox=\"0 0 256 256\"><path d=\"M184,72V56H80.65l53.6,67a8,8,0,0,1,0,10l-53.6,67H184V184a8,8,0,0,1,16,0v24a8,8,0,0,1-8,8H64a8,8,0,0,1-6.25-13l60-75-60-75A8,8,0,0,1,64,40H192a8,8,0,0,1,8,8V72a8,8,0,0,1-16,0Z\"></path></svg>";
|
|
151
151
|
|
|
152
|
+
var twitter$1 = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"32\" height=\"32\" fill=\"#000000\" viewBox=\"0 0 256 256\"><path d=\"M214.75,211.71l-62.6-98.38,61.77-67.95a8,8,0,0,0-11.84-10.76L143.24,99.34,102.75,35.71A8,8,0,0,0,96,32H48a8,8,0,0,0-6.75,12.3l62.6,98.37-61.77,68a8,8,0,1,0,11.84,10.76l58.84-64.72,40.49,63.63A8,8,0,0,0,160,224h48a8,8,0,0,0,6.75-12.29ZM164.39,208,62.57,48h29L193.43,208Z\"></path></svg>";
|
|
153
|
+
|
|
152
154
|
var table$1 = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"32\" height=\"32\" fill=\"#000000\" viewBox=\"0 0 256 256\"><path d=\"M216,48H40A16,16,0,0,0,24,64V192a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V64A16,16,0,0,0,216,48ZM104,144V112h48v32Zm48,16v32H104V160ZM40,112H88v32H40Zm64-16V64h48V96Zm64,16h48v32H168Zm48-16H168V64h48ZM88,64V96H40V64ZM40,160H88v32H40Zm176,32H168V160h48v32Z\"></path></svg>";
|
|
153
155
|
|
|
154
156
|
var unlink = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"32\" height=\"32\" fill=\"#000000\" viewBox=\"0 0 256 256\"><path d=\"M190.63,65.37a32,32,0,0,0-45.19-.06L133.79,77.52a8,8,0,0,1-11.58-11l11.72-12.29a1.59,1.59,0,0,1,.13-.13,48,48,0,0,1,67.88,67.88,1.59,1.59,0,0,1-.13.13l-12.29,11.72a8,8,0,0,1-11-11.58l12.21-11.65A32,32,0,0,0,190.63,65.37ZM122.21,178.48l-11.65,12.21a32,32,0,0,1-45.25-45.25l12.21-11.65a8,8,0,0,0-11-11.58L54.19,133.93a1.59,1.59,0,0,0-.13.13,48,48,0,0,0,67.88,67.88,1.59,1.59,0,0,0,.13-.13l11.72-12.29a8,8,0,1,0-11.58-11ZM208,152H184a8,8,0,0,0,0,16h24a8,8,0,0,0,0-16ZM48,104H72a8,8,0,0,0,0-16H48a8,8,0,0,0,0,16Zm112,72a8,8,0,0,0-8,8v24a8,8,0,0,0,16,0V184A8,8,0,0,0,160,176ZM96,80a8,8,0,0,0,8-8V48a8,8,0,0,0-16,0V72A8,8,0,0,0,96,80Z\"></path></svg>";
|
|
@@ -263,6 +265,7 @@ const icons = new Map([
|
|
|
263
265
|
['emoji', emoji$1],
|
|
264
266
|
['specialCharacter', specialCharacter$1],
|
|
265
267
|
['equation', equation$1],
|
|
268
|
+
['twitter', twitter$1],
|
|
266
269
|
['table', table$1],
|
|
267
270
|
// link
|
|
268
271
|
['unlink', unlink],
|
|
@@ -2864,6 +2867,15 @@ const toolbarItems = [
|
|
|
2864
2867
|
editor.command.execute(value);
|
|
2865
2868
|
},
|
|
2866
2869
|
},
|
|
2870
|
+
{
|
|
2871
|
+
name: 'twitter',
|
|
2872
|
+
type: 'button',
|
|
2873
|
+
icon: icons.get('twitter'),
|
|
2874
|
+
tooltip: locale => locale.toolbar.twitter(),
|
|
2875
|
+
onClick: (editor, value) => {
|
|
2876
|
+
editor.command.execute(value);
|
|
2877
|
+
},
|
|
2878
|
+
},
|
|
2867
2879
|
{
|
|
2868
2880
|
name: 'heading',
|
|
2869
2881
|
type: 'dropdown',
|
|
@@ -3318,7 +3330,7 @@ var enUS = {
|
|
|
3318
3330
|
formatPainter: 'Format painter',
|
|
3319
3331
|
link: 'Link',
|
|
3320
3332
|
hr: 'Horizontal line',
|
|
3321
|
-
video: '
|
|
3333
|
+
video: 'YouTube',
|
|
3322
3334
|
codeBlock: 'Code block',
|
|
3323
3335
|
heading: 'Heading',
|
|
3324
3336
|
heading1: 'Heading 1',
|
|
@@ -3340,6 +3352,7 @@ var enUS = {
|
|
|
3340
3352
|
file: 'File',
|
|
3341
3353
|
emoji: 'Emoji',
|
|
3342
3354
|
equation: 'Mathematical formula',
|
|
3355
|
+
twitter: 'X (Tweet)',
|
|
3343
3356
|
removeColor: 'Remove color',
|
|
3344
3357
|
},
|
|
3345
3358
|
slash: {
|
|
@@ -3379,10 +3392,12 @@ var enUS = {
|
|
|
3379
3392
|
hrDesc: 'Insert a horizontal line',
|
|
3380
3393
|
codeBlock: 'Code block',
|
|
3381
3394
|
codeBlockDesc: 'Insert a code block',
|
|
3382
|
-
video: '
|
|
3383
|
-
videoDesc: 'Insert a video
|
|
3395
|
+
video: 'YouTube',
|
|
3396
|
+
videoDesc: 'Insert a YouTube video',
|
|
3384
3397
|
equation: 'Mathematical formula',
|
|
3385
3398
|
equationDesc: 'Insert a TeX expression',
|
|
3399
|
+
twitter: 'Tweet',
|
|
3400
|
+
twitterDesc: 'Insert an X (Tweet)',
|
|
3386
3401
|
image: 'Image',
|
|
3387
3402
|
imageDesc: 'Upload an image',
|
|
3388
3403
|
file: 'File',
|
|
@@ -3446,7 +3461,7 @@ var enUS = {
|
|
|
3446
3461
|
video: {
|
|
3447
3462
|
embed: 'Embed video',
|
|
3448
3463
|
remove: 'Delete',
|
|
3449
|
-
description: 'Paste a link to embed
|
|
3464
|
+
description: 'Paste a YouTube link to embed the video.',
|
|
3450
3465
|
url: 'Link',
|
|
3451
3466
|
urlError: 'Please enter a valid link.',
|
|
3452
3467
|
},
|
|
@@ -3458,6 +3473,13 @@ var enUS = {
|
|
|
3458
3473
|
help: 'Supported functions',
|
|
3459
3474
|
placeholder: 'Type a TeX expression...',
|
|
3460
3475
|
},
|
|
3476
|
+
twitter: {
|
|
3477
|
+
embed: 'Embed Tweet',
|
|
3478
|
+
remove: 'Delete',
|
|
3479
|
+
description: 'Paste an X (Twitter) link to embed the post.',
|
|
3480
|
+
url: 'Link',
|
|
3481
|
+
urlError: 'Please enter a valid link.',
|
|
3482
|
+
},
|
|
3461
3483
|
};
|
|
3462
3484
|
|
|
3463
3485
|
var zhCN = {
|
|
@@ -3487,7 +3509,7 @@ var zhCN = {
|
|
|
3487
3509
|
formatPainter: '格式刷',
|
|
3488
3510
|
link: '链接',
|
|
3489
3511
|
hr: '分割线',
|
|
3490
|
-
video: '
|
|
3512
|
+
video: 'YouTube',
|
|
3491
3513
|
codeBlock: '代码块',
|
|
3492
3514
|
heading: '标题',
|
|
3493
3515
|
heading1: '标题 1',
|
|
@@ -3509,6 +3531,7 @@ var zhCN = {
|
|
|
3509
3531
|
file: '文件',
|
|
3510
3532
|
emoji: '表情',
|
|
3511
3533
|
equation: '数学公式',
|
|
3534
|
+
twitter: 'X (Tweet)',
|
|
3512
3535
|
removeColor: '默认',
|
|
3513
3536
|
},
|
|
3514
3537
|
slash: {
|
|
@@ -3548,10 +3571,12 @@ var zhCN = {
|
|
|
3548
3571
|
hrDesc: '插入分割线',
|
|
3549
3572
|
codeBlock: '代码块',
|
|
3550
3573
|
codeBlockDesc: '插入代码块',
|
|
3551
|
-
video: '
|
|
3574
|
+
video: 'YouTube',
|
|
3552
3575
|
videoDesc: '插入 YouTube 视频',
|
|
3553
3576
|
equation: '数学公式',
|
|
3554
3577
|
equationDesc: '支持 TeX 语法',
|
|
3578
|
+
twitter: 'Tweet',
|
|
3579
|
+
twitterDesc: '插入 Tweet',
|
|
3555
3580
|
image: '图片',
|
|
3556
3581
|
imageDesc: '上传图片',
|
|
3557
3582
|
file: '文件',
|
|
@@ -3627,6 +3652,13 @@ var zhCN = {
|
|
|
3627
3652
|
help: '支持的功能',
|
|
3628
3653
|
placeholder: '请输入 TeX 表达式',
|
|
3629
3654
|
},
|
|
3655
|
+
twitter: {
|
|
3656
|
+
embed: '嵌入 Tweet',
|
|
3657
|
+
remove: '删除',
|
|
3658
|
+
description: '在下面的输入框里,粘贴 X (Twitter) 链接。',
|
|
3659
|
+
url: '链接',
|
|
3660
|
+
urlError: '请输入有效的链接。',
|
|
3661
|
+
},
|
|
3630
3662
|
};
|
|
3631
3663
|
|
|
3632
3664
|
var ja = {
|
|
@@ -3656,7 +3688,7 @@ var ja = {
|
|
|
3656
3688
|
formatPainter: '形式ペインタ',
|
|
3657
3689
|
link: 'リンク',
|
|
3658
3690
|
hr: '区切り線',
|
|
3659
|
-
video: '
|
|
3691
|
+
video: 'YouTube',
|
|
3660
3692
|
codeBlock: 'コードブロック',
|
|
3661
3693
|
heading: '見出し',
|
|
3662
3694
|
heading1: '見出し 1',
|
|
@@ -3678,6 +3710,7 @@ var ja = {
|
|
|
3678
3710
|
file: 'ファイル',
|
|
3679
3711
|
emoji: '絵文字',
|
|
3680
3712
|
equation: '数式',
|
|
3713
|
+
twitter: 'ツイート',
|
|
3681
3714
|
removeColor: 'デフォルト',
|
|
3682
3715
|
},
|
|
3683
3716
|
slash: {
|
|
@@ -3717,10 +3750,12 @@ var ja = {
|
|
|
3717
3750
|
hrDesc: '水平線を挿入',
|
|
3718
3751
|
codeBlock: 'コードブロック',
|
|
3719
3752
|
codeBlockDesc: 'コードブロックを挿入',
|
|
3720
|
-
video: '
|
|
3753
|
+
video: 'YouTube',
|
|
3721
3754
|
videoDesc: 'YouTube から動画を挿入',
|
|
3722
3755
|
equation: '数式',
|
|
3723
3756
|
equationDesc: 'TeX 数式を挿入',
|
|
3757
|
+
twitter: 'ツイート',
|
|
3758
|
+
twitterDesc: 'ツイートを挿入',
|
|
3724
3759
|
image: '画像',
|
|
3725
3760
|
imageDesc: '画像をアップロード',
|
|
3726
3761
|
file: 'ファイル',
|
|
@@ -3796,6 +3831,13 @@ var ja = {
|
|
|
3796
3831
|
help: 'サポートされている機能',
|
|
3797
3832
|
placeholder: 'TeX 数式を入力してください',
|
|
3798
3833
|
},
|
|
3834
|
+
twitter: {
|
|
3835
|
+
embed: 'ツイートを埋め込む',
|
|
3836
|
+
remove: '削除',
|
|
3837
|
+
description: '下の入力欄に X (Twitter) リンクを貼り付けてください。',
|
|
3838
|
+
url: 'リンク',
|
|
3839
|
+
urlError: '有効なリンクを入力してください。',
|
|
3840
|
+
},
|
|
3799
3841
|
};
|
|
3800
3842
|
|
|
3801
3843
|
var ko = {
|
|
@@ -3825,7 +3867,7 @@ var ko = {
|
|
|
3825
3867
|
formatPainter: '형식 복사기',
|
|
3826
3868
|
link: '링크',
|
|
3827
3869
|
hr: '구분선',
|
|
3828
|
-
video: '
|
|
3870
|
+
video: '유튜브',
|
|
3829
3871
|
codeBlock: '코드 블록',
|
|
3830
3872
|
heading: '제목',
|
|
3831
3873
|
heading1: '제목 1',
|
|
@@ -3847,6 +3889,7 @@ var ko = {
|
|
|
3847
3889
|
file: '파일',
|
|
3848
3890
|
emoji: '이모지',
|
|
3849
3891
|
equation: '수학 공식',
|
|
3892
|
+
twitter: '트윗',
|
|
3850
3893
|
removeColor: '기본 색상',
|
|
3851
3894
|
},
|
|
3852
3895
|
slash: {
|
|
@@ -3873,7 +3916,7 @@ var ko = {
|
|
|
3873
3916
|
checklist: '체크리스트',
|
|
3874
3917
|
checklistDesc: '체크리스트를 작성',
|
|
3875
3918
|
table: '표',
|
|
3876
|
-
tableDesc: '표를
|
|
3919
|
+
tableDesc: '표를 추가',
|
|
3877
3920
|
infoAlert: '정보 블록',
|
|
3878
3921
|
infoAlertDesc: '정보 블록을 작성',
|
|
3879
3922
|
tipAlert: '팁 블록',
|
|
@@ -3883,13 +3926,15 @@ var ko = {
|
|
|
3883
3926
|
dangerAlert: '위험 블록',
|
|
3884
3927
|
dangerAlertDesc: '위험 블록을 작성',
|
|
3885
3928
|
hr: '구분선',
|
|
3886
|
-
hrDesc: '구분선을
|
|
3929
|
+
hrDesc: '구분선을 추가',
|
|
3887
3930
|
codeBlock: '코드 블록',
|
|
3888
|
-
codeBlockDesc: '코드 블록을
|
|
3889
|
-
video: '
|
|
3890
|
-
videoDesc: '유튜브 동영상을
|
|
3931
|
+
codeBlockDesc: '코드 블록을 추가',
|
|
3932
|
+
video: '유튜브',
|
|
3933
|
+
videoDesc: '유튜브 동영상을 추가',
|
|
3891
3934
|
equation: '수학 공식',
|
|
3892
|
-
equationDesc: 'TeX 수식을
|
|
3935
|
+
equationDesc: 'TeX 수식을 추가',
|
|
3936
|
+
twitter: '트윗',
|
|
3937
|
+
twitterDesc: '트윗을 추가',
|
|
3893
3938
|
image: '이미지',
|
|
3894
3939
|
imageDesc: '이미지를 업로드',
|
|
3895
3940
|
file: '파일',
|
|
@@ -3908,12 +3953,12 @@ var ko = {
|
|
|
3908
3953
|
fitTable: '페이지 너비에 맞게 조정',
|
|
3909
3954
|
cellBackground: '셀 배경 색상',
|
|
3910
3955
|
column: '열',
|
|
3911
|
-
insertColumnLeft: '왼쪽에 열을
|
|
3912
|
-
insertColumnRight: '오른쪽에 열을
|
|
3956
|
+
insertColumnLeft: '왼쪽에 열을 추가',
|
|
3957
|
+
insertColumnRight: '오른쪽에 열을 추가',
|
|
3913
3958
|
deleteColumn: '열을 삭제',
|
|
3914
3959
|
row: '행',
|
|
3915
|
-
insertRowAbove: '위에 행을
|
|
3916
|
-
insertRowBelow: '아래에 행을
|
|
3960
|
+
insertRowAbove: '위에 행을 추가',
|
|
3961
|
+
insertRowBelow: '아래에 행을 추가',
|
|
3917
3962
|
deleteRow: '행을 삭제',
|
|
3918
3963
|
merge: '셀을 병합',
|
|
3919
3964
|
mergeUp: '위쪽으로 셀을 병합',
|
|
@@ -3951,9 +3996,9 @@ var ko = {
|
|
|
3951
3996
|
remove: '삭제',
|
|
3952
3997
|
},
|
|
3953
3998
|
video: {
|
|
3954
|
-
embed: '
|
|
3999
|
+
embed: '동영상을 추가',
|
|
3955
4000
|
remove: '삭제',
|
|
3956
|
-
description: '아래 입력란에
|
|
4001
|
+
description: '아래 입력란에 유튜브 링크를 붙여넣으세요.',
|
|
3957
4002
|
url: '링크',
|
|
3958
4003
|
urlError: '유효한 링크를 입력하세요.',
|
|
3959
4004
|
},
|
|
@@ -3965,6 +4010,13 @@ var ko = {
|
|
|
3965
4010
|
help: '지원되는 기능',
|
|
3966
4011
|
placeholder: 'TeX 수식을 입력하세요',
|
|
3967
4012
|
},
|
|
4013
|
+
twitter: {
|
|
4014
|
+
embed: '트윗을 추가',
|
|
4015
|
+
remove: '삭제',
|
|
4016
|
+
description: '아래 입력란에 X (Twitter) 링크를 붙여넣으세요.',
|
|
4017
|
+
url: '링크',
|
|
4018
|
+
urlError: '유효한 링크를 입력하세요.',
|
|
4019
|
+
},
|
|
3968
4020
|
};
|
|
3969
4021
|
|
|
3970
4022
|
const localeTranslations = {
|
|
@@ -4687,9 +4739,7 @@ class Box {
|
|
|
4687
4739
|
if (component === undefined) {
|
|
4688
4740
|
throw new Error(`Box "${node}" has not been defined yet.`);
|
|
4689
4741
|
}
|
|
4690
|
-
|
|
4691
|
-
const name = encode(component.name);
|
|
4692
|
-
this.node = query(template `<lake-box type="${type}" name="${name}"></lake-box>`);
|
|
4742
|
+
this.node = query(template `<lake-box type="${component.type}" name="${component.name}"></lake-box>`);
|
|
4693
4743
|
if (component.value) {
|
|
4694
4744
|
this.value = component.value;
|
|
4695
4745
|
}
|
|
@@ -4906,6 +4956,281 @@ function getBox(boxNode) {
|
|
|
4906
4956
|
return box;
|
|
4907
4957
|
}
|
|
4908
4958
|
|
|
4959
|
+
// The CornerToolbar class represents a button group located in the top-right corner of a box.
|
|
4960
|
+
class CornerToolbar {
|
|
4961
|
+
constructor(config) {
|
|
4962
|
+
this.config = config;
|
|
4963
|
+
this.locale = this.config.locale || i18nObject('en-US');
|
|
4964
|
+
this.root = query(config.root);
|
|
4965
|
+
this.container = query('<div class="lake-corner-toolbar" />');
|
|
4966
|
+
}
|
|
4967
|
+
appendButton(item) {
|
|
4968
|
+
const buttonNode = query(template `
|
|
4969
|
+
<button type="button" name="${item.name}" tabindex="-1" />
|
|
4970
|
+
`);
|
|
4971
|
+
const tooltip = typeof item.tooltip === 'string' ? item.tooltip : item.tooltip(this.locale);
|
|
4972
|
+
buttonNode.attr('title', tooltip);
|
|
4973
|
+
if (item.icon) {
|
|
4974
|
+
buttonNode.append(item.icon);
|
|
4975
|
+
}
|
|
4976
|
+
this.container.append(buttonNode);
|
|
4977
|
+
buttonNode.on('click', event => {
|
|
4978
|
+
event.preventDefault();
|
|
4979
|
+
item.onClick(event);
|
|
4980
|
+
});
|
|
4981
|
+
}
|
|
4982
|
+
render() {
|
|
4983
|
+
const { items } = this.config;
|
|
4984
|
+
if (items.length === 0) {
|
|
4985
|
+
return;
|
|
4986
|
+
}
|
|
4987
|
+
this.root.append(this.container);
|
|
4988
|
+
for (const item of items) {
|
|
4989
|
+
this.appendButton(item);
|
|
4990
|
+
}
|
|
4991
|
+
}
|
|
4992
|
+
}
|
|
4993
|
+
|
|
4994
|
+
// The Resizer class represents a UI component used to resize images or videos.
|
|
4995
|
+
class Resizer {
|
|
4996
|
+
constructor(config) {
|
|
4997
|
+
this.config = config;
|
|
4998
|
+
this.root = query(config.root);
|
|
4999
|
+
this.target = query(config.target);
|
|
5000
|
+
this.container = query(template `
|
|
5001
|
+
<div class="lake-resizer">
|
|
5002
|
+
<div class="lake-resizer-top-left"></div>
|
|
5003
|
+
<div class="lake-resizer-top-right"></div>
|
|
5004
|
+
<div class="lake-resizer-bottom-left"></div>
|
|
5005
|
+
<div class="lake-resizer-bottom-right"></div>
|
|
5006
|
+
<div class="lake-resizer-info"></div>
|
|
5007
|
+
</div>
|
|
5008
|
+
`);
|
|
5009
|
+
}
|
|
5010
|
+
bindEvents(pointerNode) {
|
|
5011
|
+
const target = this.target;
|
|
5012
|
+
const infoNode = this.container.find('.lake-resizer-info');
|
|
5013
|
+
const isPlus = pointerNode.attr('class').indexOf('-right') >= 0;
|
|
5014
|
+
const initialWidth = target.width();
|
|
5015
|
+
const initialHeight = target.height();
|
|
5016
|
+
const rate = initialHeight / initialWidth;
|
|
5017
|
+
let clientX = 0;
|
|
5018
|
+
let width = 0;
|
|
5019
|
+
// resizing box
|
|
5020
|
+
const pointermoveListener = (event) => {
|
|
5021
|
+
const pointerEvent = event;
|
|
5022
|
+
const diffX = pointerEvent.clientX - clientX;
|
|
5023
|
+
const newWidth = Math.round(isPlus ? width + diffX : width - diffX);
|
|
5024
|
+
const newHeight = Math.round(rate * newWidth);
|
|
5025
|
+
infoNode.text(`${newWidth} x ${newHeight}`);
|
|
5026
|
+
target.css({
|
|
5027
|
+
width: `${newWidth}px`,
|
|
5028
|
+
height: `${newHeight}px`,
|
|
5029
|
+
});
|
|
5030
|
+
if (this.config.onResize) {
|
|
5031
|
+
this.config.onResize(newWidth, newHeight);
|
|
5032
|
+
}
|
|
5033
|
+
};
|
|
5034
|
+
// start resizing
|
|
5035
|
+
const pointerdownListener = (event) => {
|
|
5036
|
+
const pointerEvent = event;
|
|
5037
|
+
const pointerNativeNode = pointerNode.get(0);
|
|
5038
|
+
// The capture will be implicitly released after a pointerup or pointercancel event.
|
|
5039
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/Element/setPointerCapture
|
|
5040
|
+
try {
|
|
5041
|
+
// Test case throws an exception on Firefox.
|
|
5042
|
+
pointerNativeNode.setPointerCapture(pointerEvent.pointerId);
|
|
5043
|
+
}
|
|
5044
|
+
catch ( /* empty */_a) { /* empty */ }
|
|
5045
|
+
clientX = pointerEvent.clientX;
|
|
5046
|
+
width = target.width();
|
|
5047
|
+
infoNode.text(`${initialWidth} x ${initialHeight}`);
|
|
5048
|
+
infoNode.show();
|
|
5049
|
+
pointerNode.on('pointermove', pointermoveListener);
|
|
5050
|
+
};
|
|
5051
|
+
// stop resizing
|
|
5052
|
+
const pointerupListner = () => {
|
|
5053
|
+
pointerNode.off('pointermove');
|
|
5054
|
+
infoNode.hide();
|
|
5055
|
+
width = target.width();
|
|
5056
|
+
const height = Math.round(rate * width);
|
|
5057
|
+
this.config.onStop(width, height);
|
|
5058
|
+
};
|
|
5059
|
+
// cancel resizing
|
|
5060
|
+
const pointercancelListner = () => {
|
|
5061
|
+
pointerNode.off('pointermove');
|
|
5062
|
+
infoNode.hide();
|
|
5063
|
+
};
|
|
5064
|
+
pointerNode.on('pointerdown', pointerdownListener);
|
|
5065
|
+
pointerNode.on('pointerup', pointerupListner);
|
|
5066
|
+
pointerNode.on('pointercancel', pointercancelListner);
|
|
5067
|
+
}
|
|
5068
|
+
render() {
|
|
5069
|
+
this.bindEvents(this.container.find('.lake-resizer-top-left'));
|
|
5070
|
+
this.bindEvents(this.container.find('.lake-resizer-top-right'));
|
|
5071
|
+
this.bindEvents(this.container.find('.lake-resizer-bottom-left'));
|
|
5072
|
+
this.bindEvents(this.container.find('.lake-resizer-bottom-right'));
|
|
5073
|
+
this.root.append(this.container);
|
|
5074
|
+
}
|
|
5075
|
+
}
|
|
5076
|
+
|
|
5077
|
+
/**
|
|
5078
|
+
* Returns the localized string.
|
|
5079
|
+
*/
|
|
5080
|
+
function getLocaleString(locale, value) {
|
|
5081
|
+
return typeof value === 'string' ? value : value(locale);
|
|
5082
|
+
}
|
|
5083
|
+
/**
|
|
5084
|
+
* Appends a corner toolbar to the iframe box.
|
|
5085
|
+
*/
|
|
5086
|
+
function appendCornerToolbar(config, box) {
|
|
5087
|
+
const editor = box.getEditor();
|
|
5088
|
+
const boxContainer = box.getContainer();
|
|
5089
|
+
const rootNode = boxContainer.find('.lake-iframe');
|
|
5090
|
+
if (rootNode.find('.lake-corner-toolbar').length > 0) {
|
|
5091
|
+
return;
|
|
5092
|
+
}
|
|
5093
|
+
new CornerToolbar({
|
|
5094
|
+
locale: editor.locale,
|
|
5095
|
+
root: rootNode,
|
|
5096
|
+
items: [
|
|
5097
|
+
{
|
|
5098
|
+
name: 'remove',
|
|
5099
|
+
icon: icons.get('remove'),
|
|
5100
|
+
tooltip: config.deleteButtonText,
|
|
5101
|
+
onClick: event => {
|
|
5102
|
+
event.stopPropagation();
|
|
5103
|
+
editor.selection.removeBox(box);
|
|
5104
|
+
editor.history.save();
|
|
5105
|
+
},
|
|
5106
|
+
},
|
|
5107
|
+
],
|
|
5108
|
+
}).render();
|
|
5109
|
+
}
|
|
5110
|
+
/**
|
|
5111
|
+
* Shows the iframe in the box.
|
|
5112
|
+
*/
|
|
5113
|
+
function showIframe(config, box) {
|
|
5114
|
+
const editor = box.getEditor();
|
|
5115
|
+
const boxContainer = box.getContainer();
|
|
5116
|
+
const value = box.value;
|
|
5117
|
+
const width = value.width || config.width;
|
|
5118
|
+
const height = value.height || config.height;
|
|
5119
|
+
const iframeNode = query('<iframe></iframe>');
|
|
5120
|
+
iframeNode.css({
|
|
5121
|
+
width,
|
|
5122
|
+
height,
|
|
5123
|
+
});
|
|
5124
|
+
const iframeAttributes = config.iframeAttributes(value.url);
|
|
5125
|
+
for (const key of Object.keys(iframeAttributes)) {
|
|
5126
|
+
iframeNode.attr(key, iframeAttributes[key]);
|
|
5127
|
+
}
|
|
5128
|
+
const placeholderNode = query('<div class="lake-iframe-placeholder" />');
|
|
5129
|
+
placeholderNode.css({
|
|
5130
|
+
width,
|
|
5131
|
+
height,
|
|
5132
|
+
});
|
|
5133
|
+
if (config.iframePlaceholder) {
|
|
5134
|
+
placeholderNode.append(config.iframePlaceholder);
|
|
5135
|
+
}
|
|
5136
|
+
const rootNode = boxContainer.find('.lake-iframe');
|
|
5137
|
+
iframeNode.on('load', () => {
|
|
5138
|
+
placeholderNode.remove();
|
|
5139
|
+
if (editor.readonly) {
|
|
5140
|
+
return;
|
|
5141
|
+
}
|
|
5142
|
+
if (config.resize === true && rootNode.find('.lake-resizer').length === 0) {
|
|
5143
|
+
new Resizer({
|
|
5144
|
+
root: rootNode,
|
|
5145
|
+
target: iframeNode,
|
|
5146
|
+
onStop: (newWidth, newHeight) => {
|
|
5147
|
+
box.updateValue({
|
|
5148
|
+
width: `${newWidth}px`,
|
|
5149
|
+
height: `${newHeight}px`,
|
|
5150
|
+
});
|
|
5151
|
+
editor.selection.selectBox(box);
|
|
5152
|
+
editor.history.save();
|
|
5153
|
+
},
|
|
5154
|
+
}).render();
|
|
5155
|
+
}
|
|
5156
|
+
});
|
|
5157
|
+
if (config.validUrl(value.url)) {
|
|
5158
|
+
rootNode.prepend(iframeNode);
|
|
5159
|
+
}
|
|
5160
|
+
else {
|
|
5161
|
+
placeholderNode.css('position', 'static');
|
|
5162
|
+
}
|
|
5163
|
+
rootNode.prepend(placeholderNode);
|
|
5164
|
+
if (config.beforeIframeLoad) {
|
|
5165
|
+
config.beforeIframeLoad(box);
|
|
5166
|
+
}
|
|
5167
|
+
}
|
|
5168
|
+
/**
|
|
5169
|
+
* Creates an iframe box component with configurable properties.
|
|
5170
|
+
* This component supports rendering an iframe with customizable attributes, resizing, and toolbar functionalities.
|
|
5171
|
+
*/
|
|
5172
|
+
function createIframeBox(config) {
|
|
5173
|
+
return {
|
|
5174
|
+
type: config.type,
|
|
5175
|
+
name: config.name,
|
|
5176
|
+
render: box => {
|
|
5177
|
+
const editor = box.getEditor();
|
|
5178
|
+
const locale = editor.locale;
|
|
5179
|
+
const value = box.value;
|
|
5180
|
+
const boxContainer = box.getContainer();
|
|
5181
|
+
const rootNode = query('<div class="lake-iframe" />');
|
|
5182
|
+
boxContainer.empty();
|
|
5183
|
+
boxContainer.append(rootNode);
|
|
5184
|
+
if (value.url === undefined) {
|
|
5185
|
+
if (editor.readonly) {
|
|
5186
|
+
box.node.hide();
|
|
5187
|
+
return;
|
|
5188
|
+
}
|
|
5189
|
+
const formNode = query(template `
|
|
5190
|
+
<div class="lake-iframe-form">
|
|
5191
|
+
<div class="lake-description">${getLocaleString(locale, config.formDescription)}</div>
|
|
5192
|
+
<div class="lake-input-label">${getLocaleString(locale, config.urlLabel || '')}</div>
|
|
5193
|
+
<div class="lake-input-field">
|
|
5194
|
+
<input type="text" name="url" placeholder="${config.urlPlaceholder}" />
|
|
5195
|
+
</div>
|
|
5196
|
+
</div>
|
|
5197
|
+
`);
|
|
5198
|
+
const button = new Button({
|
|
5199
|
+
root: formNode.find('.lake-input-field'),
|
|
5200
|
+
name: 'embed',
|
|
5201
|
+
type: 'primary',
|
|
5202
|
+
text: getLocaleString(locale, config.embedButtonText),
|
|
5203
|
+
onClick: () => {
|
|
5204
|
+
const url = formNode.find('input[name="url"]').value();
|
|
5205
|
+
if (!config.validUrl(url)) {
|
|
5206
|
+
editor.config.onMessage('error', getLocaleString(locale, config.urlError));
|
|
5207
|
+
return;
|
|
5208
|
+
}
|
|
5209
|
+
box.updateValue('url', url);
|
|
5210
|
+
editor.history.save();
|
|
5211
|
+
formNode.remove();
|
|
5212
|
+
showIframe(config, box);
|
|
5213
|
+
},
|
|
5214
|
+
});
|
|
5215
|
+
formNode.find('input[name="url"]').on('keydown', event => {
|
|
5216
|
+
if (isKeyHotkey('enter', event)) {
|
|
5217
|
+
event.preventDefault();
|
|
5218
|
+
button.node.emit('click');
|
|
5219
|
+
}
|
|
5220
|
+
});
|
|
5221
|
+
button.render();
|
|
5222
|
+
rootNode.append(formNode);
|
|
5223
|
+
}
|
|
5224
|
+
else {
|
|
5225
|
+
showIframe(config, box);
|
|
5226
|
+
}
|
|
5227
|
+
if (!editor.readonly) {
|
|
5228
|
+
appendCornerToolbar(config, box);
|
|
5229
|
+
}
|
|
5230
|
+
},
|
|
5231
|
+
};
|
|
5232
|
+
}
|
|
5233
|
+
|
|
4909
5234
|
/**
|
|
4910
5235
|
* The Fragment interface represents a lightweight document object that has no parent.
|
|
4911
5236
|
* It is designed for efficient manipulation of document structures without affecting the main DOM.
|
|
@@ -6273,7 +6598,7 @@ function removeBox(range) {
|
|
|
6273
6598
|
return box;
|
|
6274
6599
|
}
|
|
6275
6600
|
|
|
6276
|
-
var version = "0.3.
|
|
6601
|
+
var version = "0.3.10";
|
|
6277
6602
|
|
|
6278
6603
|
// Converts the custom HTML tags to the special tags that can not be parsed by browser.
|
|
6279
6604
|
function denormalizeValue(value) {
|
|
@@ -10682,124 +11007,6 @@ var codeBlock = (editor) => {
|
|
|
10682
11007
|
});
|
|
10683
11008
|
};
|
|
10684
11009
|
|
|
10685
|
-
// The CornerToolbar class represents a button group located in the top-right corner of a box.
|
|
10686
|
-
class CornerToolbar {
|
|
10687
|
-
constructor(config) {
|
|
10688
|
-
this.config = config;
|
|
10689
|
-
this.locale = this.config.locale || i18nObject('en-US');
|
|
10690
|
-
this.root = query(config.root);
|
|
10691
|
-
this.container = query('<div class="lake-corner-toolbar" />');
|
|
10692
|
-
}
|
|
10693
|
-
appendButton(item) {
|
|
10694
|
-
const buttonNode = query(template `
|
|
10695
|
-
<button type="button" name="${item.name}" tabindex="-1" />
|
|
10696
|
-
`);
|
|
10697
|
-
const tooltip = typeof item.tooltip === 'string' ? item.tooltip : item.tooltip(this.locale);
|
|
10698
|
-
buttonNode.attr('title', tooltip);
|
|
10699
|
-
if (item.icon) {
|
|
10700
|
-
buttonNode.append(item.icon);
|
|
10701
|
-
}
|
|
10702
|
-
this.container.append(buttonNode);
|
|
10703
|
-
buttonNode.on('click', event => {
|
|
10704
|
-
event.preventDefault();
|
|
10705
|
-
item.onClick(event);
|
|
10706
|
-
});
|
|
10707
|
-
}
|
|
10708
|
-
render() {
|
|
10709
|
-
const { items } = this.config;
|
|
10710
|
-
if (items.length === 0) {
|
|
10711
|
-
return;
|
|
10712
|
-
}
|
|
10713
|
-
this.root.append(this.container);
|
|
10714
|
-
for (const item of items) {
|
|
10715
|
-
this.appendButton(item);
|
|
10716
|
-
}
|
|
10717
|
-
}
|
|
10718
|
-
}
|
|
10719
|
-
|
|
10720
|
-
// The Resizer class represents a UI component used to resize images or videos.
|
|
10721
|
-
class Resizer {
|
|
10722
|
-
constructor(config) {
|
|
10723
|
-
this.config = config;
|
|
10724
|
-
this.root = query(config.root);
|
|
10725
|
-
this.target = query(config.target);
|
|
10726
|
-
this.container = query(template `
|
|
10727
|
-
<div class="lake-resizer">
|
|
10728
|
-
<div class="lake-resizer-top-left"></div>
|
|
10729
|
-
<div class="lake-resizer-top-right"></div>
|
|
10730
|
-
<div class="lake-resizer-bottom-left"></div>
|
|
10731
|
-
<div class="lake-resizer-bottom-right"></div>
|
|
10732
|
-
<div class="lake-resizer-info"></div>
|
|
10733
|
-
</div>
|
|
10734
|
-
`);
|
|
10735
|
-
}
|
|
10736
|
-
bindEvents(pointerNode) {
|
|
10737
|
-
const target = this.target;
|
|
10738
|
-
const infoNode = this.container.find('.lake-resizer-info');
|
|
10739
|
-
const isPlus = pointerNode.attr('class').indexOf('-right') >= 0;
|
|
10740
|
-
const initialWidth = target.width();
|
|
10741
|
-
const initialHeight = target.height();
|
|
10742
|
-
const rate = initialHeight / initialWidth;
|
|
10743
|
-
let clientX = 0;
|
|
10744
|
-
let width = 0;
|
|
10745
|
-
// resizing box
|
|
10746
|
-
const pointermoveListener = (event) => {
|
|
10747
|
-
const pointerEvent = event;
|
|
10748
|
-
const diffX = pointerEvent.clientX - clientX;
|
|
10749
|
-
const newWidth = Math.round(isPlus ? width + diffX : width - diffX);
|
|
10750
|
-
const newHeight = Math.round(rate * newWidth);
|
|
10751
|
-
infoNode.text(`${newWidth} x ${newHeight}`);
|
|
10752
|
-
target.css({
|
|
10753
|
-
width: `${newWidth}px`,
|
|
10754
|
-
height: `${newHeight}px`,
|
|
10755
|
-
});
|
|
10756
|
-
if (this.config.onResize) {
|
|
10757
|
-
this.config.onResize(newWidth, newHeight);
|
|
10758
|
-
}
|
|
10759
|
-
};
|
|
10760
|
-
// start resizing
|
|
10761
|
-
const pointerdownListener = (event) => {
|
|
10762
|
-
const pointerEvent = event;
|
|
10763
|
-
const pointerNativeNode = pointerNode.get(0);
|
|
10764
|
-
// The capture will be implicitly released after a pointerup or pointercancel event.
|
|
10765
|
-
// https://developer.mozilla.org/en-US/docs/Web/API/Element/setPointerCapture
|
|
10766
|
-
try {
|
|
10767
|
-
// Test case throws an exception on Firefox.
|
|
10768
|
-
pointerNativeNode.setPointerCapture(pointerEvent.pointerId);
|
|
10769
|
-
}
|
|
10770
|
-
catch ( /* empty */_a) { /* empty */ }
|
|
10771
|
-
clientX = pointerEvent.clientX;
|
|
10772
|
-
width = target.width();
|
|
10773
|
-
infoNode.text(`${initialWidth} x ${initialHeight}`);
|
|
10774
|
-
infoNode.show();
|
|
10775
|
-
pointerNode.on('pointermove', pointermoveListener);
|
|
10776
|
-
};
|
|
10777
|
-
// stop resizing
|
|
10778
|
-
const pointerupListner = () => {
|
|
10779
|
-
pointerNode.off('pointermove');
|
|
10780
|
-
infoNode.hide();
|
|
10781
|
-
width = target.width();
|
|
10782
|
-
const height = Math.round(rate * width);
|
|
10783
|
-
this.config.onStop(width, height);
|
|
10784
|
-
};
|
|
10785
|
-
// cancel resizing
|
|
10786
|
-
const pointercancelListner = () => {
|
|
10787
|
-
pointerNode.off('pointermove');
|
|
10788
|
-
infoNode.hide();
|
|
10789
|
-
};
|
|
10790
|
-
pointerNode.on('pointerdown', pointerdownListener);
|
|
10791
|
-
pointerNode.on('pointerup', pointerupListner);
|
|
10792
|
-
pointerNode.on('pointercancel', pointercancelListner);
|
|
10793
|
-
}
|
|
10794
|
-
render() {
|
|
10795
|
-
this.bindEvents(this.container.find('.lake-resizer-top-left'));
|
|
10796
|
-
this.bindEvents(this.container.find('.lake-resizer-top-right'));
|
|
10797
|
-
this.bindEvents(this.container.find('.lake-resizer-bottom-left'));
|
|
10798
|
-
this.bindEvents(this.container.find('.lake-resizer-bottom-right'));
|
|
10799
|
-
this.root.append(this.container);
|
|
10800
|
-
}
|
|
10801
|
-
}
|
|
10802
|
-
|
|
10803
11010
|
const alignValueMap = {
|
|
10804
11011
|
start: 'left',
|
|
10805
11012
|
end: 'right',
|
|
@@ -11428,145 +11635,36 @@ var image = (editor) => {
|
|
|
11428
11635
|
});
|
|
11429
11636
|
};
|
|
11430
11637
|
|
|
11431
|
-
|
|
11432
|
-
|
|
11638
|
+
/**
|
|
11639
|
+
* Extracts ID from the specified URL.
|
|
11640
|
+
*/
|
|
11641
|
+
function getId$1(url) {
|
|
11642
|
+
const result = /[\w\-]+$/.exec(url || '');
|
|
11433
11643
|
return result ? result[0] : '';
|
|
11434
11644
|
}
|
|
11435
|
-
|
|
11436
|
-
const editor = box.getEditor();
|
|
11437
|
-
const boxContainer = box.getContainer();
|
|
11438
|
-
const rootNode = boxContainer.find('.lake-video');
|
|
11439
|
-
if (rootNode.find('.lake-corner-toolbar').length > 0) {
|
|
11440
|
-
return;
|
|
11441
|
-
}
|
|
11442
|
-
new CornerToolbar({
|
|
11443
|
-
locale: editor.locale,
|
|
11444
|
-
root: rootNode,
|
|
11445
|
-
items: [
|
|
11446
|
-
{
|
|
11447
|
-
name: 'remove',
|
|
11448
|
-
icon: icons.get('remove'),
|
|
11449
|
-
tooltip: editor.locale.video.remove(),
|
|
11450
|
-
onClick: event => {
|
|
11451
|
-
event.stopPropagation();
|
|
11452
|
-
editor.selection.removeBox(box);
|
|
11453
|
-
editor.history.save();
|
|
11454
|
-
},
|
|
11455
|
-
},
|
|
11456
|
-
],
|
|
11457
|
-
}).render();
|
|
11458
|
-
}
|
|
11459
|
-
function showVideo(box) {
|
|
11460
|
-
const editor = box.getEditor();
|
|
11461
|
-
const boxContainer = box.getContainer();
|
|
11462
|
-
const value = box.value;
|
|
11463
|
-
const width = value.width || 560;
|
|
11464
|
-
const height = value.height || 315;
|
|
11465
|
-
boxContainer.css({
|
|
11466
|
-
width: `${width}px`,
|
|
11467
|
-
height: `${height}px`,
|
|
11468
|
-
});
|
|
11469
|
-
const videoId = getVideoId(value.url);
|
|
11470
|
-
if (videoId === '') {
|
|
11471
|
-
throw new Error(`Invalid link: ${value.url}`);
|
|
11472
|
-
}
|
|
11473
|
-
// YouTube URL: https://www.youtube.com/watch?v=5sMBhDv4sik
|
|
11474
|
-
// The script for embedding YouTube:
|
|
11475
|
-
// <iframe width="560" height="315" src="https://www.youtube.com/embed/5sMBhDv4sik" title="YouTube video player"
|
|
11476
|
-
// frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
|
|
11477
|
-
// referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
|
|
11478
|
-
const iframeNode = query(template `
|
|
11479
|
-
<iframe width="100%" height="${height}" src="https://www.youtube.com/embed/${videoId}" title="YouTube video player"
|
|
11480
|
-
frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
|
|
11481
|
-
referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
|
|
11482
|
-
`);
|
|
11483
|
-
const rootNode = boxContainer.find('.lake-video');
|
|
11484
|
-
if (!editor.readonly) {
|
|
11485
|
-
iframeNode.on('load', () => {
|
|
11486
|
-
appendButtonGroup(box);
|
|
11487
|
-
new Resizer({
|
|
11488
|
-
root: rootNode,
|
|
11489
|
-
target: boxContainer,
|
|
11490
|
-
onResize: (newWidth, newHeight) => {
|
|
11491
|
-
iframeNode.attr({
|
|
11492
|
-
height: newHeight.toString(),
|
|
11493
|
-
});
|
|
11494
|
-
},
|
|
11495
|
-
onStop: (newWidth, newHeight) => {
|
|
11496
|
-
box.updateValue({
|
|
11497
|
-
width: newWidth,
|
|
11498
|
-
height: newHeight,
|
|
11499
|
-
});
|
|
11500
|
-
editor.history.save();
|
|
11501
|
-
},
|
|
11502
|
-
}).render();
|
|
11503
|
-
});
|
|
11504
|
-
}
|
|
11505
|
-
rootNode.prepend(iframeNode);
|
|
11506
|
-
}
|
|
11507
|
-
var videoBox = {
|
|
11645
|
+
const videoBox = createIframeBox({
|
|
11508
11646
|
type: 'inline',
|
|
11509
11647
|
name: 'video',
|
|
11510
|
-
|
|
11511
|
-
|
|
11512
|
-
|
|
11513
|
-
|
|
11514
|
-
|
|
11515
|
-
|
|
11516
|
-
|
|
11517
|
-
|
|
11518
|
-
|
|
11519
|
-
|
|
11520
|
-
|
|
11521
|
-
|
|
11522
|
-
|
|
11523
|
-
|
|
11524
|
-
|
|
11525
|
-
|
|
11526
|
-
|
|
11527
|
-
|
|
11528
|
-
|
|
11529
|
-
|
|
11530
|
-
<div class="lake-row">${locale.video.url()}</div>
|
|
11531
|
-
<div class="lake-row">
|
|
11532
|
-
<input type="text" name="url" placeholder="https://www.youtube.com/watch?v=..." />
|
|
11533
|
-
</div>
|
|
11534
|
-
<div class="lake-row lake-button-row"></div>
|
|
11535
|
-
</div>
|
|
11536
|
-
`);
|
|
11537
|
-
const button = new Button({
|
|
11538
|
-
root: formNode.find('.lake-button-row'),
|
|
11539
|
-
name: 'embed',
|
|
11540
|
-
type: 'primary',
|
|
11541
|
-
text: locale.video.embed(),
|
|
11542
|
-
onClick: () => {
|
|
11543
|
-
const url = formNode.find('input[name="url"]').value();
|
|
11544
|
-
if (url.indexOf('https://www.youtube.com/') < 0 || getVideoId(url) === '') {
|
|
11545
|
-
editor.config.onMessage('error', locale.video.urlError());
|
|
11546
|
-
return;
|
|
11547
|
-
}
|
|
11548
|
-
box.updateValue('url', url);
|
|
11549
|
-
editor.history.save();
|
|
11550
|
-
formNode.remove();
|
|
11551
|
-
showVideo(box);
|
|
11552
|
-
},
|
|
11553
|
-
});
|
|
11554
|
-
formNode.find('input[name="url"]').on('keydown', event => {
|
|
11555
|
-
if (isKeyHotkey('enter', event)) {
|
|
11556
|
-
event.preventDefault();
|
|
11557
|
-
button.node.emit('click');
|
|
11558
|
-
}
|
|
11559
|
-
});
|
|
11560
|
-
button.render();
|
|
11561
|
-
rootNode.append(formNode);
|
|
11562
|
-
appendButtonGroup(box);
|
|
11563
|
-
}
|
|
11564
|
-
else {
|
|
11565
|
-
showVideo(box);
|
|
11566
|
-
}
|
|
11567
|
-
},
|
|
11568
|
-
};
|
|
11569
|
-
|
|
11648
|
+
width: '560px',
|
|
11649
|
+
height: '315px',
|
|
11650
|
+
formDescription: locale => locale.video.description(),
|
|
11651
|
+
urlLabel: locale => locale.video.url(),
|
|
11652
|
+
urlPlaceholder: 'https://www.youtube.com/watch?v=...',
|
|
11653
|
+
embedButtonText: locale => locale.video.embed(),
|
|
11654
|
+
deleteButtonText: locale => locale.video.remove(),
|
|
11655
|
+
validUrl: url => url.indexOf('https://www.youtube.com/') === 0 && getId$1(url) !== '',
|
|
11656
|
+
urlError: locale => locale.video.urlError(),
|
|
11657
|
+
iframePlaceholder: icons.get('video'),
|
|
11658
|
+
iframeAttributes: url => ({
|
|
11659
|
+
src: `https://www.youtube.com/embed/${getId$1(url)}`,
|
|
11660
|
+
title: 'YouTube video player',
|
|
11661
|
+
frameborder: '0',
|
|
11662
|
+
allow: 'accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share',
|
|
11663
|
+
referrerpolicy: 'strict-origin-when-cross-origin',
|
|
11664
|
+
allowfullscreen: 'true',
|
|
11665
|
+
}),
|
|
11666
|
+
resize: true,
|
|
11667
|
+
});
|
|
11570
11668
|
var video = (editor) => {
|
|
11571
11669
|
if (editor.readonly) {
|
|
11572
11670
|
return;
|
|
@@ -11576,7 +11674,10 @@ var video = (editor) => {
|
|
|
11576
11674
|
const box = editor.selection.insertBox('video', value);
|
|
11577
11675
|
editor.history.save();
|
|
11578
11676
|
if (box) {
|
|
11579
|
-
box.getContainer().find('input[name="url"]')
|
|
11677
|
+
const urlInput = box.getContainer().find('input[name="url"]');
|
|
11678
|
+
if (urlInput.length > 0) {
|
|
11679
|
+
urlInput.focus();
|
|
11680
|
+
}
|
|
11580
11681
|
}
|
|
11581
11682
|
},
|
|
11582
11683
|
});
|
|
@@ -12297,6 +12398,81 @@ var mention = (editor) => {
|
|
|
12297
12398
|
};
|
|
12298
12399
|
};
|
|
12299
12400
|
|
|
12401
|
+
/**
|
|
12402
|
+
* Extracts ID from the specified URL.
|
|
12403
|
+
*/
|
|
12404
|
+
function getId(url) {
|
|
12405
|
+
const result = /\d+$/.exec(url || '');
|
|
12406
|
+
return result ? result[0] : '';
|
|
12407
|
+
}
|
|
12408
|
+
/**
|
|
12409
|
+
* Returns the current theme.
|
|
12410
|
+
*/
|
|
12411
|
+
function getTheme() {
|
|
12412
|
+
return document.documentElement.classList.contains('lake-dark') ? 'dark' : 'light';
|
|
12413
|
+
}
|
|
12414
|
+
const twitterBox = createIframeBox({
|
|
12415
|
+
type: 'inline',
|
|
12416
|
+
name: 'twitter',
|
|
12417
|
+
width: '550px',
|
|
12418
|
+
height: '300px',
|
|
12419
|
+
formDescription: locale => locale.twitter.description(),
|
|
12420
|
+
urlLabel: locale => locale.twitter.url(),
|
|
12421
|
+
urlPlaceholder: 'https://x.com/username/status/...',
|
|
12422
|
+
embedButtonText: locale => locale.twitter.embed(),
|
|
12423
|
+
deleteButtonText: locale => locale.twitter.remove(),
|
|
12424
|
+
validUrl: url => (url.indexOf('https://x.com/') === 0 || url.indexOf('https://twitter.com/') === 0) && getId(url) !== '',
|
|
12425
|
+
urlError: locale => locale.twitter.urlError(),
|
|
12426
|
+
iframePlaceholder: icons.get('twitter'),
|
|
12427
|
+
iframeAttributes: url => {
|
|
12428
|
+
return {
|
|
12429
|
+
src: `https://platform.twitter.com/embed/Tweet.html?id=${getId(url)}&theme=${getTheme()}`,
|
|
12430
|
+
title: 'Twitter tweet',
|
|
12431
|
+
scrolling: 'no',
|
|
12432
|
+
frameborder: '0',
|
|
12433
|
+
allowtransparency: 'true',
|
|
12434
|
+
allowfullscreen: 'true',
|
|
12435
|
+
};
|
|
12436
|
+
},
|
|
12437
|
+
beforeIframeLoad: box => {
|
|
12438
|
+
const boxContainer = box.getContainer();
|
|
12439
|
+
const placeholder = boxContainer.find('.lake-iframe-placeholder');
|
|
12440
|
+
const iframe = boxContainer.find('iframe');
|
|
12441
|
+
if (getTheme() === 'dark') {
|
|
12442
|
+
iframe.css('border-radius', '13px');
|
|
12443
|
+
}
|
|
12444
|
+
const messageListener = (event) => {
|
|
12445
|
+
if (event.origin === 'https://platform.twitter.com') {
|
|
12446
|
+
const params = event.data['twttr.embed'].params;
|
|
12447
|
+
const height = params[0].height;
|
|
12448
|
+
if (height > 0) {
|
|
12449
|
+
placeholder.css('height', `${height}px`);
|
|
12450
|
+
iframe.css('height', `${height}px`);
|
|
12451
|
+
window.removeEventListener('message', messageListener);
|
|
12452
|
+
}
|
|
12453
|
+
}
|
|
12454
|
+
};
|
|
12455
|
+
window.addEventListener('message', messageListener);
|
|
12456
|
+
},
|
|
12457
|
+
});
|
|
12458
|
+
var twitter = (editor) => {
|
|
12459
|
+
if (editor.readonly) {
|
|
12460
|
+
return;
|
|
12461
|
+
}
|
|
12462
|
+
editor.command.add('twitter', {
|
|
12463
|
+
execute: (value) => {
|
|
12464
|
+
const box = editor.selection.insertBox('twitter', value);
|
|
12465
|
+
editor.history.save();
|
|
12466
|
+
if (box) {
|
|
12467
|
+
const urlInput = box.getContainer().find('input[name="url"]');
|
|
12468
|
+
if (urlInput.length > 0) {
|
|
12469
|
+
urlInput.focus();
|
|
12470
|
+
}
|
|
12471
|
+
}
|
|
12472
|
+
},
|
|
12473
|
+
});
|
|
12474
|
+
};
|
|
12475
|
+
|
|
12300
12476
|
const headingTypeMap = new Map([
|
|
12301
12477
|
['#', 'h1'],
|
|
12302
12478
|
['##', 'h2'],
|
|
@@ -13489,6 +13665,16 @@ const slashItems = [
|
|
|
13489
13665
|
editor.command.execute(value);
|
|
13490
13666
|
},
|
|
13491
13667
|
},
|
|
13668
|
+
{
|
|
13669
|
+
name: 'twitter',
|
|
13670
|
+
type: 'button',
|
|
13671
|
+
icon: icons.get('twitter'),
|
|
13672
|
+
title: locale => locale.slash.twitter(),
|
|
13673
|
+
description: locale => locale.slash.twitterDesc(),
|
|
13674
|
+
onClick: (editor, value) => {
|
|
13675
|
+
editor.command.execute(value);
|
|
13676
|
+
},
|
|
13677
|
+
},
|
|
13492
13678
|
{
|
|
13493
13679
|
name: 'image',
|
|
13494
13680
|
type: 'upload',
|
|
@@ -13736,6 +13922,7 @@ Editor.box.add(imageBox);
|
|
|
13736
13922
|
Editor.box.add(videoBox);
|
|
13737
13923
|
Editor.box.add(fileBox);
|
|
13738
13924
|
Editor.box.add(mentionBox);
|
|
13925
|
+
Editor.box.add(twitterBox);
|
|
13739
13926
|
Editor.plugin.add('copy', copy);
|
|
13740
13927
|
Editor.plugin.add('cut', cut);
|
|
13741
13928
|
Editor.plugin.add('paste', paste);
|
|
@@ -13772,6 +13959,7 @@ Editor.plugin.add('emoji', emoji);
|
|
|
13772
13959
|
Editor.plugin.add('equation', equation);
|
|
13773
13960
|
Editor.plugin.add('specialCharacter', specialCharacter);
|
|
13774
13961
|
Editor.plugin.add('mention', mention);
|
|
13962
|
+
Editor.plugin.add('twitter', twitter);
|
|
13775
13963
|
Editor.plugin.add('markdown', markdown);
|
|
13776
13964
|
Editor.plugin.add('enterKey', enterKey);
|
|
13777
13965
|
Editor.plugin.add('shiftEnterKey', shiftEnterKey);
|
|
@@ -13782,5 +13970,5 @@ Editor.plugin.add('arrowKeys', arrowKeys);
|
|
|
13782
13970
|
Editor.plugin.add('escapeKey', escapeKey);
|
|
13783
13971
|
Editor.plugin.add('slash', slash);
|
|
13784
13972
|
|
|
13785
|
-
export { Box, Button, Dropdown, Editor, Fragment, HTMLParser, Nodes, Range, TextParser, Toolbar, addMark, deleteContents, getBox, getContentRules, icons, insertBlock, insertBookmark, insertBox, insertContents, query, removeBox, removeMark, setBlocks, splitBlock$1 as splitBlock, splitMarks, template, toBookmark, toHex };
|
|
13973
|
+
export { Box, Button, Dropdown, Editor, Fragment, HTMLParser, Nodes, Range, TextParser, Toolbar, addMark, createIframeBox, deleteContents, getBox, getContentRules, icons, insertBlock, insertBookmark, insertBox, insertContents, query, removeBox, removeMark, setBlocks, splitBlock$1 as splitBlock, splitMarks, template, toBookmark, toHex };
|
|
13786
13974
|
//# sourceMappingURL=lake.js.map
|