suneditor 2.46.1 → 2.46.3

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/example.md ADDED
@@ -0,0 +1,587 @@
1
+ # Example usage in the framework
2
+ This is just a simple example and is not a complete answer.
3
+ If there are any examples or errors in other frameworks, please participate and correct them.
4
+ - [React](#react-component)
5
+ - [React class](#react-class)
6
+ - [Vue](#vue-component)
7
+
8
+
9
+ ## React Component
10
+
11
+ ### React class
12
+
13
+ ### 1. Editor.tsx
14
+ ```typescript
15
+ import React, { Component, createRef } from "react";
16
+ import suneditor from "suneditor";
17
+ import { en } from "suneditor/src/lang";
18
+ import plugins from "suneditor/src/plugins";
19
+ import CodeMirror from "codemirror";
20
+ import katex from "katex";
21
+ import "suneditor/dist/css/suneditor.min.css";
22
+ import "codemirror/mode/htmlmixed/htmlmixed";
23
+ import "codemirror/lib/codemirror.css";
24
+ import "katex/dist/katex.min.css";
25
+ import "./Editor.scss"
26
+
27
+
28
+ interface Props {
29
+ contents?: string;
30
+ onBlur?: Function;
31
+ onSave: Function;
32
+ }
33
+
34
+ interface State {
35
+ imageList: any[];
36
+ selectedImages: any[];
37
+ imageSize: string;
38
+ }
39
+
40
+ class Editor extends Component<Props, State> {
41
+ txtArea: any;
42
+ editor: any;
43
+
44
+ constructor(props: any) {
45
+ super(props);
46
+ this.txtArea = createRef();
47
+ this.state = {
48
+ imageList: [],
49
+ selectedImages: [],
50
+ imageSize: "0KB",
51
+ };
52
+ }
53
+
54
+ componentDidMount() {
55
+ const editor: any = this.editor = suneditor.create(this.txtArea.current, {
56
+ plugins: plugins,
57
+ lang: en,
58
+ callBackSave: (contents: string) => this.props.onSave(contents),
59
+ codeMirror: CodeMirror,
60
+ stickyToolbar: 0,
61
+ katex: katex,
62
+ width: '100%',
63
+ height: 'auto',
64
+ minHeight: '400px',
65
+ value: this.props.contents,
66
+ // imageUploadUrl: `url`,
67
+ imageMultipleFile: true,
68
+ previewTemplate: `
69
+ <div style="width:auto; max-width:1136px; min-height:400px; margin:auto;">
70
+ {{contents}}
71
+ </div>
72
+ `,
73
+ buttonList: [
74
+ // default
75
+ ['undo', 'redo'],
76
+ ['font', 'fontSize', 'formatBlock'],
77
+ ['paragraphStyle', 'blockquote'],
78
+ ['bold', 'underline', 'italic', 'strike', 'subscript', 'superscript'],
79
+ ['fontColor', 'hiliteColor', 'textStyle'],
80
+ ['removeFormat'],
81
+ ['outdent', 'indent'],
82
+ ['align', 'horizontalRule', 'list', 'lineHeight'],
83
+ ['table', 'link', 'image', 'video'],
84
+ ['fullScreen', 'showBlocks', 'codeView'],
85
+ ['preview'],
86
+ ['save'],
87
+ // responsive
88
+ ['%1161', [
89
+ ['undo', 'redo'],
90
+ [':p-Formats-default.more_paragraph', 'font', 'fontSize', 'formatBlock', 'paragraphStyle', 'blockquote'],
91
+ ['bold', 'underline', 'italic', 'strike', 'subscript', 'superscript'],
92
+ ['fontColor', 'hiliteColor', 'textStyle'],
93
+ ['removeFormat'],
94
+ ['outdent', 'indent'],
95
+ ['align', 'horizontalRule', 'list', 'lineHeight'],
96
+ ['-right', 'save'],
97
+ ['-right', ':i-Etc-default.more_vertical', 'fullScreen', 'showBlocks', 'codeView', 'preview'],
98
+ ['-right', ':r-Table&Media-default.more_plus', 'table', 'link', 'image', 'video'],
99
+ ]],
100
+ ['%893', [
101
+ ['undo', 'redo'],
102
+ [':p-Formats-default.more_paragraph', 'font', 'fontSize', 'formatBlock', 'paragraphStyle', 'blockquote'],
103
+ ['bold', 'underline', 'italic', 'strike'],
104
+ [':t-Fonts-default.more_text', 'subscript', 'superscript', 'fontColor', 'hiliteColor', 'textStyle'],
105
+ ['removeFormat'],
106
+ ['outdent', 'indent'],
107
+ ['align', 'horizontalRule', 'list', 'lineHeight'],
108
+ ['-right', 'save'],
109
+ ['-right', ':i-Etc-default.more_vertical', 'fullScreen', 'showBlocks', 'codeView', 'preview'],
110
+ ['-right', ':r-Table&Media-default.more_plus', 'table', 'link', 'image', 'video'],
111
+ ]],
112
+ ['%855', [
113
+ ['undo', 'redo'],
114
+ [':p-Formats-default.more_paragraph', 'font', 'fontSize', 'formatBlock', 'paragraphStyle', 'blockquote'],
115
+ [':t-Fonts-default.more_text', 'bold', 'underline', 'italic', 'strike', 'subscript', 'superscript', 'fontColor', 'hiliteColor', 'textStyle'],
116
+ ['removeFormat'],
117
+ ['outdent', 'indent'],
118
+ ['align', 'horizontalRule', 'list', 'lineHeight'],
119
+ [':r-Table&Media-default.more_plus', 'table', 'link', 'image', 'video'],
120
+ ['-right', 'save'],
121
+ ['-right', ':i-Etc-default.more_vertical', 'fullScreen', 'showBlocks', 'codeView', 'preview'],
122
+ ]],
123
+ ['%563', [
124
+ ['undo', 'redo'],
125
+ [':p-Formats-default.more_paragraph', 'font', 'fontSize', 'formatBlock', 'paragraphStyle', 'blockquote'],
126
+ [':t-Fonts-default.more_text', 'bold', 'underline', 'italic', 'strike', 'subscript', 'superscript', 'fontColor', 'hiliteColor', 'textStyle'],
127
+ ['removeFormat'],
128
+ ['outdent', 'indent'],
129
+ [':e-List&Line-default.more_horizontal', 'align', 'horizontalRule', 'list', 'lineHeight'],
130
+ [':r-Table&Media-default.more_plus', 'table', 'link', 'image', 'video'],
131
+ ['-right', 'save'],
132
+ ['-right', ':i-Etc-default.more_vertical', 'fullScreen', 'showBlocks', 'codeView', 'preview'],
133
+ ]],
134
+ ['%458', [
135
+ ['undo', 'redo'],
136
+ [':p-Formats-default.more_paragraph', 'font', 'fontSize', 'formatBlock', 'paragraphStyle', 'blockquote'],
137
+ [':t-Fonts-default.more_text', 'bold', 'underline', 'italic', 'strike', 'subscript', 'superscript', 'fontColor', 'hiliteColor', 'textStyle', 'removeFormat'],
138
+ [':e-List&Line-default.more_horizontal', 'outdent', 'indent', 'align', 'horizontalRule', 'list', 'lineHeight'],
139
+ [':r-Table&Media-default.more_plus', 'table', 'link', 'image', 'video'],
140
+ ['-right', 'save'],
141
+ ['-right', ':i-Etc-default.more_vertical', 'fullScreen', 'showBlocks', 'codeView', 'preview'],
142
+ ]]
143
+ ]
144
+ });
145
+
146
+ editor.onBlur = () => {
147
+ if (typeof this.props.onBlur === 'function') this.props.onBlur()
148
+ }
149
+
150
+ editor.onImageUpload = this.imageUpload.bind(this);
151
+ // editor.onVideoUpload = videoUpload;
152
+ }
153
+
154
+ componentDidUpdate(prevProps: any) {
155
+ if (this.props.contents !== prevProps.contents) {
156
+ this.editor.setContents(this.props.contents);
157
+ this.editor.core.history.reset(true);
158
+ }
159
+ }
160
+
161
+ componentWillUnmount() {
162
+ if (this.editor) this.editor.destroy();
163
+ }
164
+
165
+ // image, video
166
+ findIndex(arr: any[], index: number) {
167
+ let idx = -1;
168
+
169
+ arr.some(function (a, i) {
170
+ if ((typeof a === 'number' ? a : a.index) === index) {
171
+ idx = i;
172
+ return true;
173
+ }
174
+ return false;
175
+ })
176
+
177
+ return idx;
178
+ }
179
+
180
+ imageUpload(targetElement: Element, index: number, state: string, imageInfo: Record<string, string>, remainingFilesCount: number) {
181
+ if (state === 'delete') {
182
+ this.state.imageList.splice(this.findIndex(this.state.imageList, index), 1)
183
+ this.setState({
184
+ imageList: this.state.imageList
185
+ })
186
+ } else {
187
+ if (state === 'create') {
188
+ const imageList = this.state.imageList;
189
+ imageList.push(imageInfo)
190
+ this.setState({
191
+ imageList: imageList
192
+ })
193
+ } else { // update
194
+ //
195
+ }
196
+ }
197
+
198
+ if (remainingFilesCount === 0) {
199
+ this.setImageList()
200
+ }
201
+ }
202
+
203
+ setImageList() {
204
+ const imageList = this.state.imageList;
205
+ let size = 0;
206
+
207
+ for (let i = 0; i < imageList.length; i++) {
208
+ size += Number((imageList[i].size / 1000).toFixed(1));
209
+ }
210
+
211
+ this.setState({
212
+ imageSize: size.toFixed(1) + 'KB'
213
+ })
214
+ }
215
+
216
+ selectImage(evt: any, type: string, index: number) {
217
+ evt.preventDefault();
218
+ evt.stopPropagation();
219
+ this.state.imageList[this.findIndex(this.state.imageList, index)][type]();
220
+ }
221
+
222
+ checkImage(index: number) {
223
+ const selectedImages = this.state.selectedImages;
224
+ const currentImageIdx = this.findIndex(selectedImages, index)
225
+
226
+ if (currentImageIdx > -1) {
227
+ selectedImages.splice(currentImageIdx, 1)
228
+ } else {
229
+ selectedImages.push(index)
230
+ }
231
+
232
+ this.setState({
233
+ selectedImages: selectedImages
234
+ })
235
+ }
236
+
237
+ deleteCheckedImages() {
238
+ const iamgesInfo = this.editor.getImagesInfo();
239
+
240
+ for (let i = 0; i < iamgesInfo.length; i++) {
241
+ if (this.state.selectedImages.indexOf(iamgesInfo[i].index as number) > -1) {
242
+ iamgesInfo[i].delete();
243
+ i--;
244
+ }
245
+ }
246
+
247
+ this.setState({
248
+ selectedImages: [],
249
+ })
250
+ }
251
+
252
+ fileUploadToEditor(e: any) {
253
+ if (e.target.files) {
254
+ this.editor.insertImage(e.target.files)
255
+ e.target.value = ''
256
+ }
257
+ }
258
+
259
+ render() {
260
+ return <div>
261
+ <textarea ref={this.txtArea} />
262
+ <div className="component-list">
263
+ <div className="file-list-info">
264
+ <span>Attach files</span>
265
+ <span className="xefu-btn">
266
+ <span className="files-text">Images</span>
267
+ </span>
268
+ <input type="file" id="files_upload" accept=".jpg, .jpeg, .png, .ico, .tif, .tiff, .gif, .bmp, .raw" multiple className="files-text files-input" onChange={(e: any) => this.fileUploadToEditor(e)} />
269
+ <span id="image_size" className="total-size text-small-2">{this.state.imageSize}</span>
270
+ <button className="btn btn-md btn-danger" id="image_remove" disabled={this.state.selectedImages.length === 0} onClick={() => this.deleteCheckedImages()}>삭제</button>
271
+ </div>
272
+ <div className="file-list">
273
+ <ul id="image_list">
274
+ {
275
+ this.state.imageList.map((v, i) => {
276
+ return <li key={i} onClick={() => this.checkImage(v.index)} className={this.state.selectedImages.includes(v.index) ? "checked" : ""}>
277
+ <div>
278
+ <div className="image-wrapper"><img src={v.src} /></div>
279
+ </div>
280
+ <a onClick={(evt: any) => this.selectImage(evt, "select", v.index)} className="image-size">{(v.size / 1000).toFixed(1)}KB</a>
281
+ <div className="image-check"><svg aria-hidden="true" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" data-fa-i2svg=""><path fill="currentColor" d="M173.898 439.404l-166.4-166.4c-9.997-9.997-9.997-26.206 0-36.204l36.203-36.204c9.997-9.998 26.207-9.998 36.204 0L192 312.69 432.095 72.596c9.997-9.997 26.207-9.997 36.204 0l36.203 36.204c9.997 9.997 9.997 26.206 0 36.204l-294.4 294.401c-9.998 9.997-26.207 9.997-36.204-.001z"></path></svg></div>
282
+ </li>
283
+ })
284
+ }
285
+ </ul>
286
+ </div>
287
+ </div>
288
+ </div>;
289
+ }
290
+ }
291
+
292
+ export default Editor;
293
+ ```
294
+
295
+ ### 2 PostEdit.tsx
296
+ ```typescript
297
+ import React, { Component, createRef } from "react";
298
+ import Editor from "./Editor";
299
+
300
+ interface Props {}
301
+
302
+ interface State {
303
+ content: string;
304
+ }
305
+
306
+ class PostEdit extends Component<Props, State> {
307
+ editorRef: any = createRef();
308
+
309
+ constructor(props: Props) {
310
+ super(props);
311
+ this.state = {
312
+ content: "Test",
313
+ };
314
+ }
315
+
316
+ save() {
317
+ const contents = this.editorRef.current.editor.getContents();
318
+ console.log("save", contents);
319
+ }
320
+
321
+ render() {
322
+ return (
323
+ <div>
324
+ <Editor ref={this.editorRef} contents={this.state.content} onSave={this.save.bind(this)}></Editor>
325
+
326
+ <button onClick={() => this.save()}>
327
+ <span>Save</span>
328
+ </button>
329
+ </div>
330
+ );
331
+ }
332
+ }
333
+
334
+ export default PostEdit;
335
+
336
+ ```
337
+
338
+ ### 3. Editor file component Scss
339
+ ```scss
340
+ .sun-editor .se-dialog .se-dialog-inner .se-dialog-content {
341
+ margin: 100px auto !important;
342
+ }
343
+ .sun-editor .se-wrapper .se-wrapper-wysiwyg {
344
+ padding-bottom: 200px !important;
345
+ }
346
+
347
+ .sun-editor-editable .se-component.__se__float-left {
348
+ margin: 0 0 10px 0;
349
+ }
350
+ .sun-editor-editable .se-component.__se__float-right {
351
+ margin: 0 0 10px 0;
352
+ }
353
+
354
+ .sun-editor-editable a {
355
+ color: #004cff !important;
356
+ text-decoration: none !important;
357
+ }
358
+
359
+ // image list
360
+ /** image list */
361
+ .component-list {
362
+ display: flex;
363
+ box-sizing: border-box;
364
+ position: relative;
365
+ width: 100%;
366
+ margin: 10px 0 10px 0;
367
+ padding: 4px;
368
+ background: #fff;
369
+ }
370
+
371
+ .xefu-btn {
372
+ display: inline-block;
373
+ *display: inline;
374
+ margin: 0;
375
+ padding: 0 12px !important;
376
+ height: 24px !important;
377
+ overflow: visible;
378
+ border: 1px solid #bbb;
379
+ border-radius: 2px;
380
+ text-decoration: none !important;
381
+ text-align: center;
382
+ vertical-align: top;
383
+ line-height: 24px !important;
384
+ font-family: inherit;
385
+ font-size: 12px;
386
+ color: #333;
387
+ *zoom: 1;
388
+ cursor: pointer;
389
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
390
+ background-color: #f5f5f5;
391
+ *background-color: #e6e6e6;
392
+ background-image: -moz-linear-gradient(top, #ffffff, #e6e6e6);
393
+ background-image: -webkit-linear-gradient(top, #ffffff, #e6e6e6);
394
+ background-image: -webkit-gradient(top, #ffffff, #e6e6e6);
395
+ background-image: -o-linear-gradient(top, #ffffff, #e6e6e6);
396
+ background-image: linear-gradient(top, #ffffff, #e6e6e6);
397
+ background-repeat: repeat-x;
398
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff',endColorstr='#e6e6e6',GradientType=0);
399
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
400
+ }
401
+
402
+ .component-list .files-text {
403
+ display: inline-block;
404
+ margin: 0 -12px !important;
405
+ padding: 0 12px !important;
406
+ overflow: visible;
407
+ width: auto;
408
+ height: 24px;
409
+ border: 0;
410
+ vertical-align: top;
411
+ text-decoration: none !important;
412
+ line-height: 24px;
413
+ font-family: inherit;
414
+ font-size: 12px;
415
+ color: #333;
416
+ cursor: pointer;
417
+ background: 0 0;
418
+ }
419
+
420
+ .component-list .files-input {
421
+ position: absolute;
422
+ width: 86px;
423
+ left: 26px;
424
+ top: 27px;
425
+ opacity: 0;
426
+ -ms-filter: "alpha(opacity=0)";
427
+ font-size: 8px !important;
428
+ direction: ltr;
429
+ cursor: pointer;
430
+ }
431
+
432
+ .component-list * {
433
+ box-sizing: border-box;
434
+ }
435
+
436
+ .component-list button {
437
+ margin: 0 !important;
438
+ }
439
+
440
+ .component-list .file-list-info {
441
+ float: left;
442
+ white-space: nowrap;
443
+ padding: 10px;
444
+ background: #f5f5f5;
445
+ border: 1px solid #ccc;
446
+ }
447
+
448
+ .component-list .file-list-info span {
449
+ display: block;
450
+ width: 100%;
451
+ margin: 12px 0;
452
+ }
453
+
454
+ .component-list .file-list-info .total-size {
455
+ color: #333;
456
+ }
457
+
458
+ .component-list .file-list {
459
+ padding: 0 0 0 0;
460
+ margin: 0 0 0 10px;
461
+ border: none;
462
+ }
463
+
464
+ .component-list .file-list ul {
465
+ margin: 0;
466
+ padding: 0;
467
+ height: auto;
468
+ width: 100%;
469
+ background-color: #f5f5f5;
470
+ border: 1px solid #ccc;
471
+ }
472
+
473
+ .component-list .file-list ul li {
474
+ position: relative;
475
+ display: inline-block;
476
+ margin: 3px;
477
+ width: auto;
478
+ height: auto;
479
+ border: 3px solid #fff;
480
+ }
481
+
482
+ .component-list .file-list ul li .image-wrapper {
483
+ width: 54px;
484
+ height: auto;
485
+ }
486
+
487
+ .component-list .file-list ul li .file-wrapper {
488
+ cursor: default;
489
+ width: 70px;
490
+ height: 21px;
491
+ font-size: 11px;
492
+ overflow: hidden;
493
+ text-overflow: ellipsis;
494
+ white-space: pre;
495
+ word-break: break-all;
496
+ padding-top: 4px;
497
+ }
498
+ .component-list .file-list ul li .file-wrapper svg {
499
+ vertical-align: sub;
500
+ }
501
+
502
+ .component-list .file-list ul li.checked {
503
+ border: 3px solid #dc3545;
504
+ }
505
+
506
+ .component-list .file-list ul li img {
507
+ width: 100%;
508
+ height: auto;
509
+ }
510
+
511
+ .component-list .file-list ul li .image-size {
512
+ color: #666;
513
+ font-size: 10px;
514
+ }
515
+
516
+ .component-list .file-list ul li .image-check {
517
+ position: absolute;
518
+ height: 12px;
519
+ width: 12px;
520
+ top: 0;
521
+ left: auto;
522
+ right: 0;
523
+ margin: 0;
524
+ padding: 1px 0 1px 2px;
525
+ border: 0;
526
+ border-radius: 0 0 0 5px;
527
+ outline: none;
528
+ background-color: #dc3545;
529
+ }
530
+
531
+ .component-list .file-list ul li.checked .image-check {
532
+ display: block;
533
+ }
534
+
535
+ .component-list .file-list ul li:not(.checked) .image-check {
536
+ display: none;
537
+ }
538
+
539
+ .component-list .file-list ul li .image-check svg {
540
+ display: inline-block;
541
+ font-size: 10px;
542
+ height: 1em;
543
+ width: 1em;
544
+ overflow: visible;
545
+ vertical-align: 0.875em;
546
+ margin: 0;
547
+ padding: 0;
548
+ color: #fff;
549
+ }
550
+
551
+ /** video */
552
+ .component-list .component-file-list {
553
+ width: 100%;
554
+ padding: 0 0 0 0;
555
+ margin: 0 0 0 10px;
556
+ border: none;
557
+ }
558
+ .component-list .component-file-list ul {
559
+ margin: 0;
560
+ padding: 0;
561
+ height: auto;
562
+ width: 100%;
563
+ background-color: #f5f5f5;
564
+ border: 1px solid #ccc;
565
+ }
566
+ .component-list .component-file-list ul li {
567
+ position: relative;
568
+ display: inline-block;
569
+ width: 100%;
570
+ height: 24px;
571
+ margin: 0;
572
+ border: 0;
573
+ overflow: hidden;
574
+ }
575
+ .component-list .component-file-list ul li button {
576
+ width: 30px;
577
+ height: 24px;
578
+ padding: 0;
579
+ }
580
+ .component-list .component-file-list ul li a {
581
+ color: #333;
582
+ }
583
+
584
+ ```
585
+
586
+
587
+ ## Vue Component
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "suneditor",
3
- "version": "2.46.1",
3
+ "version": "2.46.3",
4
4
  "description": "Vanilla javascript based WYSIWYG web editor, with no dependencies",
5
5
  "author": "JiHong.Lee",
6
6
  "license": "MIT",
@@ -29,31 +29,30 @@
29
29
  "bower_components"
30
30
  ],
31
31
  "devDependencies": {
32
- "@babel/core": "^7.21.3",
33
- "@octokit/rest": "^20.1.0",
34
- "@webpack-cli/init": "^1.1.3",
35
- "babel-loader": "^8.1.0",
36
- "clean-webpack-plugin": "^0.1.19",
37
- "codemirror": "^5.61.0",
38
- "css-loader": "^1.0.1",
39
- "csstype": "^2.6.13",
40
- "dotenv": "^16.4.5",
41
- "file-loader": "^2.0.0",
42
- "html-webpack-plugin": "^3.2.0",
43
- "jasmine": "^2.99.0",
44
- "jasmine-core": "^2.99.1",
45
- "jshint": "^2.13.4",
46
- "karma": "^6.3.19",
47
- "karma-chrome-launcher": "^2.2.0",
48
- "karma-jasmine": "^1.1.2",
49
- "katex": "^0.16.10",
50
- "mini-css-extract-plugin": "^0.4.5",
51
- "optimize-css-assets-webpack-plugin": "^5.0.4",
52
- "url-loader": "^1.1.2",
53
- "webpack": "^4.44.1",
54
- "webpack-cli": "^3.3.12",
55
- "webpack-dev-server": "^3.11.0",
56
- "webpack-merge": "^4.2.2"
32
+ "@babel/core": "~7.21.3",
33
+ "@octokit/rest": "~20.1.0",
34
+ "@webpack-cli/init": "~1.1.3",
35
+ "babel-loader": "~8.1.0",
36
+ "clean-webpack-plugin": "~0.1.19",
37
+ "codemirror": "~5.61.0",
38
+ "css-loader": "~1.0.1",
39
+ "csstype": "~2.6.13",
40
+ "file-loader": "~2.0.0",
41
+ "html-webpack-plugin": "~3.2.0",
42
+ "jasmine": "~2.99.0",
43
+ "jasmine-core": "~2.99.1",
44
+ "jshint": "~2.13.4",
45
+ "karma": "~6.3.19",
46
+ "karma-chrome-launcher": "~2.2.0",
47
+ "karma-jasmine": "~1.1.2",
48
+ "katex": "~0.16.10",
49
+ "mini-css-extract-plugin": "~0.4.5",
50
+ "optimize-css-assets-webpack-plugin": "~5.0.4",
51
+ "url-loader": "~1.1.2",
52
+ "webpack": "~4.44.1",
53
+ "webpack-cli": "~3.3.12",
54
+ "webpack-dev-server": "~3.11.0",
55
+ "webpack-merge": "~4.2.2"
57
56
  },
58
57
  "keywords": [
59
58
  "wysiwyg",
package/src/lib/core.js CHANGED
@@ -477,7 +477,7 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
477
477
  _cleanStyleRegExp: {
478
478
  div: new _w.RegExp('\\s*[^-a-zA-Z](.+)\\s*:[^;]+(?!;)*', 'ig'),
479
479
  span: new _w.RegExp('\\s*[^-a-zA-Z](font-family|font-size|color|background-color)\\s*:[^;]+(?!;)*', 'ig'),
480
- format: new _w.RegExp('\\s*[^-a-zA-Z](text-align|margin-left|margin-right|width|height)\\s*:[^;]+(?!;)*', 'ig'),
480
+ format: new _w.RegExp('\\s*[^-a-zA-Z](text-align|margin-left|margin-right|width|height|line-height)\\s*:[^;]+(?!;)*', 'ig'),
481
481
  fontSizeUnit: new _w.RegExp('\\d+' + options.fontSizeUnit + '$', 'i'),
482
482
  },
483
483
 
@@ -6256,12 +6256,14 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
6256
6256
  this._editorRange();
6257
6257
  }
6258
6258
 
6259
- if (util.isBreak(format.nextSibling)) util.removeItem(format.nextSibling);
6260
- if (util.isBreak(format.previousSibling)) util.removeItem(format.previousSibling);
6261
- if (util.isBreak(focusNode)) {
6262
- const zeroWidth = util.createTextNode(util.zeroWidthSpace);
6263
- focusNode.parentNode.insertBefore(zeroWidth, focusNode);
6264
- focusNode = zeroWidth;
6259
+ if (format) {
6260
+ if (util.isBreak(format.nextSibling)) util.removeItem(format.nextSibling);
6261
+ if (util.isBreak(format.previousSibling)) util.removeItem(format.previousSibling);
6262
+ if (util.isBreak(focusNode)) {
6263
+ const zeroWidth = util.createTextNode(util.zeroWidthSpace);
6264
+ focusNode.parentNode.insertBefore(zeroWidth, focusNode);
6265
+ focusNode = zeroWidth;
6266
+ }
6265
6267
  }
6266
6268
 
6267
6269
  this.effectNode = null;