@ckeditor/ckeditor5-engine 31.0.0 → 33.0.0
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/LICENSE.md +2 -2
- package/package.json +25 -25
- package/src/controller/datacontroller.js +71 -80
- package/src/controller/editingcontroller.js +83 -6
- package/src/conversion/conversion.js +15 -14
- package/src/conversion/conversionhelpers.js +1 -1
- package/src/conversion/downcastdispatcher.js +298 -367
- package/src/conversion/downcasthelpers.js +771 -63
- package/src/conversion/mapper.js +105 -60
- package/src/conversion/modelconsumable.js +85 -35
- package/src/conversion/upcastdispatcher.js +3 -6
- package/src/conversion/upcasthelpers.js +4 -2
- package/src/conversion/viewconsumable.js +1 -1
- package/src/dataprocessor/basichtmlwriter.js +1 -1
- package/src/dataprocessor/dataprocessor.jsdoc +1 -1
- package/src/dataprocessor/htmldataprocessor.js +9 -31
- package/src/dataprocessor/htmlwriter.js +1 -1
- package/src/dataprocessor/xmldataprocessor.js +1 -1
- package/src/dev-utils/model.js +16 -14
- package/src/dev-utils/operationreplayer.js +1 -1
- package/src/dev-utils/utils.js +1 -1
- package/src/dev-utils/view.js +7 -7
- package/src/index.js +2 -1
- package/src/model/batch.js +77 -10
- package/src/model/differ.js +87 -59
- package/src/model/document.js +13 -4
- package/src/model/documentfragment.js +1 -1
- package/src/model/documentselection.js +1 -1
- package/src/model/element.js +1 -1
- package/src/model/history.js +1 -1
- package/src/model/item.jsdoc +1 -1
- package/src/model/liveposition.js +1 -1
- package/src/model/liverange.js +1 -1
- package/src/model/markercollection.js +29 -5
- package/src/model/model.js +18 -9
- package/src/model/node.js +1 -1
- package/src/model/nodelist.js +1 -1
- package/src/model/operation/attributeoperation.js +1 -1
- package/src/model/operation/detachoperation.js +1 -1
- package/src/model/operation/insertoperation.js +1 -1
- package/src/model/operation/markeroperation.js +1 -1
- package/src/model/operation/mergeoperation.js +1 -1
- package/src/model/operation/moveoperation.js +1 -1
- package/src/model/operation/nooperation.js +1 -1
- package/src/model/operation/operation.js +1 -1
- package/src/model/operation/operationfactory.js +1 -1
- package/src/model/operation/renameoperation.js +1 -1
- package/src/model/operation/rootattributeoperation.js +1 -1
- package/src/model/operation/splitoperation.js +1 -1
- package/src/model/operation/transform.js +1 -1
- package/src/model/operation/utils.js +1 -1
- package/src/model/position.js +1 -1
- package/src/model/range.js +1 -1
- package/src/model/rootelement.js +1 -1
- package/src/model/schema.js +1 -1
- package/src/model/selection.js +1 -1
- package/src/model/text.js +1 -1
- package/src/model/textproxy.js +1 -1
- package/src/model/treewalker.js +1 -1
- package/src/model/utils/autoparagraphing.js +1 -1
- package/src/model/utils/deletecontent.js +1 -1
- package/src/model/utils/getselectedcontent.js +1 -1
- package/src/model/utils/insertcontent.js +1 -1
- package/src/model/utils/modifyselection.js +15 -8
- package/src/model/utils/selection-post-fixer.js +37 -30
- package/src/model/writer.js +17 -27
- package/src/view/attributeelement.js +1 -1
- package/src/view/containerelement.js +1 -1
- package/src/view/document.js +3 -2
- package/src/view/documentfragment.js +1 -1
- package/src/view/documentselection.js +1 -1
- package/src/view/domconverter.js +169 -47
- package/src/view/downcastwriter.js +121 -5
- package/src/view/editableelement.js +1 -1
- package/src/view/element.js +29 -1
- package/src/view/elementdefinition.jsdoc +1 -1
- package/src/view/emptyelement.js +1 -1
- package/src/view/filler.js +1 -1
- package/src/view/item.jsdoc +1 -1
- package/src/view/matcher.js +15 -14
- package/src/view/node.js +1 -1
- package/src/view/observer/arrowkeysobserver.js +1 -1
- package/src/view/observer/bubblingemittermixin.js +1 -1
- package/src/view/observer/bubblingeventinfo.js +1 -1
- package/src/view/observer/clickobserver.js +1 -1
- package/src/view/observer/compositionobserver.js +1 -1
- package/src/view/observer/domeventdata.js +1 -1
- package/src/view/observer/domeventobserver.js +1 -1
- package/src/view/observer/fakeselectionobserver.js +1 -1
- package/src/view/observer/focusobserver.js +1 -1
- package/src/view/observer/inputobserver.js +1 -1
- package/src/view/observer/keyobserver.js +1 -1
- package/src/view/observer/mouseobserver.js +1 -1
- package/src/view/observer/mutationobserver.js +1 -1
- package/src/view/observer/observer.js +1 -1
- package/src/view/observer/selectionobserver.js +3 -3
- package/src/view/placeholder.js +1 -1
- package/src/view/position.js +1 -1
- package/src/view/range.js +1 -1
- package/src/view/rawelement.js +1 -1
- package/src/view/renderer.js +7 -17
- package/src/view/rooteditableelement.js +1 -1
- package/src/view/selection.js +1 -1
- package/src/view/styles/background.js +1 -1
- package/src/view/styles/border.js +1 -1
- package/src/view/styles/margin.js +1 -1
- package/src/view/styles/padding.js +1 -1
- package/src/view/styles/utils.js +1 -1
- package/src/view/stylesmap.js +1 -1
- package/src/view/text.js +1 -1
- package/src/view/textproxy.js +1 -1
- package/src/view/treewalker.js +1 -1
- package/src/view/uielement.js +1 -1
- package/src/view/upcastwriter.js +1 -1
- package/src/view/view.js +1 -1
- package/theme/placeholder.css +10 -1
- package/theme/renderer.css +2 -2
package/src/model/writer.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Copyright (c) 2003-
|
|
2
|
+
* @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
3
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
4
|
*/
|
|
5
5
|
|
|
@@ -27,7 +27,7 @@ import DocumentSelection from './documentselection';
|
|
|
27
27
|
|
|
28
28
|
import toMap from '@ckeditor/ckeditor5-utils/src/tomap';
|
|
29
29
|
|
|
30
|
-
import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
|
|
30
|
+
import CKEditorError, { logWarning } from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
33
|
* The model can only be modified by using the writer. It should be used whenever you want to create a node, modify
|
|
@@ -968,30 +968,8 @@ export default class Writer {
|
|
|
968
968
|
* As the first parameter you can set marker name or instance. If none of them is provided, new marker, with a unique
|
|
969
969
|
* name is created and returned.
|
|
970
970
|
*
|
|
971
|
-
*
|
|
972
|
-
* the
|
|
973
|
-
* the marker {@link module:engine/view/element~Element view element} without changing any marker data.
|
|
974
|
-
*
|
|
975
|
-
* let isCommentActive = false;
|
|
976
|
-
*
|
|
977
|
-
* model.conversion.markerToHighlight( {
|
|
978
|
-
* model: 'comment',
|
|
979
|
-
* view: data => {
|
|
980
|
-
* const classes = [ 'comment-marker' ];
|
|
981
|
-
*
|
|
982
|
-
* if ( isCommentActive ) {
|
|
983
|
-
* classes.push( 'comment-marker--active' );
|
|
984
|
-
* }
|
|
985
|
-
*
|
|
986
|
-
* return { classes };
|
|
987
|
-
* }
|
|
988
|
-
* } );
|
|
989
|
-
*
|
|
990
|
-
* // Change the property that indicates if marker is displayed as active or not.
|
|
991
|
-
* isCommentActive = true;
|
|
992
|
-
*
|
|
993
|
-
* // And refresh the marker to convert it with additional class.
|
|
994
|
-
* model.change( writer => writer.updateMarker( 'comment' ) );
|
|
971
|
+
* **Note**: If you want to change the {@link module:engine/view/element~Element view element} of the marker while its data in the model
|
|
972
|
+
* remains the same, use the dedicated {@link module:engine/controller/editingcontroller~EditingController#reconvertMarker} method.
|
|
995
973
|
*
|
|
996
974
|
* The `options.usingOperation` parameter lets you change if the marker should be managed by operations or not. See
|
|
997
975
|
* {@link module:engine/model/markercollection~Marker marker class description} to learn about the difference between
|
|
@@ -1037,7 +1015,7 @@ export default class Writer {
|
|
|
1037
1015
|
|
|
1038
1016
|
if ( !currentMarker ) {
|
|
1039
1017
|
/**
|
|
1040
|
-
* Marker with provided name does not
|
|
1018
|
+
* Marker with provided name does not exist and will not be updated.
|
|
1041
1019
|
*
|
|
1042
1020
|
* @error writer-updatemarker-marker-not-exists
|
|
1043
1021
|
*/
|
|
@@ -1045,6 +1023,18 @@ export default class Writer {
|
|
|
1045
1023
|
}
|
|
1046
1024
|
|
|
1047
1025
|
if ( !options ) {
|
|
1026
|
+
/**
|
|
1027
|
+
* The usage of `writer.updateMarker()` only to reconvert (refresh) a
|
|
1028
|
+
* {@link module:engine/model/markercollection~Marker model marker} was deprecated and may not work in the future.
|
|
1029
|
+
* Please update your code to use
|
|
1030
|
+
* {@link module:engine/controller/editingcontroller~EditingController#reconvertMarker `editor.editing.reconvertMarker()`}
|
|
1031
|
+
* instead.
|
|
1032
|
+
*
|
|
1033
|
+
* @error writer-updatemarker-reconvert-using-editingcontroller
|
|
1034
|
+
* @param {String} markerName The name of the updated marker.
|
|
1035
|
+
*/
|
|
1036
|
+
logWarning( 'writer-updatemarker-reconvert-using-editingcontroller', { markerName } );
|
|
1037
|
+
|
|
1048
1038
|
this.model.markers._refresh( currentMarker );
|
|
1049
1039
|
|
|
1050
1040
|
return;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Copyright (c) 2003-
|
|
2
|
+
* @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
3
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
4
|
*/
|
|
5
5
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Copyright (c) 2003-
|
|
2
|
+
* @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
3
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
4
|
*/
|
|
5
5
|
|
package/src/view/document.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Copyright (c) 2003-
|
|
2
|
+
* @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
3
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
4
|
*/
|
|
5
5
|
|
|
@@ -141,7 +141,8 @@ export default class Document {
|
|
|
141
141
|
*
|
|
142
142
|
* * adding or removing attribute from elements,
|
|
143
143
|
* * changes inside of {@link module:engine/view/uielement~UIElement UI elements},
|
|
144
|
-
* * {@link module:engine/
|
|
144
|
+
* * {@link module:engine/controller/editingcontroller~EditingController#reconvertItem marking some of the model elements to be
|
|
145
|
+
* re-converted}.
|
|
145
146
|
*
|
|
146
147
|
* Try to avoid changes which touch view structure:
|
|
147
148
|
*
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Copyright (c) 2003-
|
|
2
|
+
* @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
3
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
4
|
*/
|
|
5
5
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Copyright (c) 2003-
|
|
2
|
+
* @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
3
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
4
|
*/
|
|
5
5
|
|
package/src/view/domconverter.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Copyright (c) 2003-
|
|
2
|
+
* @license Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
|
|
3
3
|
* For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
|
|
4
4
|
*/
|
|
5
5
|
|
|
@@ -24,13 +24,18 @@ import {
|
|
|
24
24
|
} from './filler';
|
|
25
25
|
|
|
26
26
|
import global from '@ckeditor/ckeditor5-utils/src/dom/global';
|
|
27
|
+
import { logWarning } from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
|
|
27
28
|
import indexOf from '@ckeditor/ckeditor5-utils/src/dom/indexof';
|
|
28
29
|
import getAncestors from '@ckeditor/ckeditor5-utils/src/dom/getancestors';
|
|
29
30
|
import isText from '@ckeditor/ckeditor5-utils/src/dom/istext';
|
|
31
|
+
import isComment from '@ckeditor/ckeditor5-utils/src/dom/iscomment';
|
|
30
32
|
|
|
31
33
|
const BR_FILLER_REF = BR_FILLER( document ); // eslint-disable-line new-cap
|
|
32
34
|
const NBSP_FILLER_REF = NBSP_FILLER( document ); // eslint-disable-line new-cap
|
|
33
35
|
const MARKED_NBSP_FILLER_REF = MARKED_NBSP_FILLER( document ); // eslint-disable-line new-cap
|
|
36
|
+
const UNSAFE_ATTRIBUTE_NAME_PREFIX = 'data-ck-unsafe-attribute-';
|
|
37
|
+
const UNSAFE_ELEMENT_REPLACEMENT_ATTRIBUTE = 'data-ck-unsafe-element';
|
|
38
|
+
const UNSAFE_ELEMENTS = [ 'script', 'style' ];
|
|
34
39
|
|
|
35
40
|
/**
|
|
36
41
|
* `DomConverter` is a set of tools to do transformations between DOM nodes and view nodes. It also handles
|
|
@@ -72,14 +77,6 @@ export default class DomConverter {
|
|
|
72
77
|
*/
|
|
73
78
|
this.renderingMode = options.renderingMode || 'editing';
|
|
74
79
|
|
|
75
|
-
/**
|
|
76
|
-
* Main switch for new rendering approach in the editing view.
|
|
77
|
-
*
|
|
78
|
-
* @protected
|
|
79
|
-
* @member {Boolean}
|
|
80
|
-
*/
|
|
81
|
-
this.experimentalRenderingMode = false;
|
|
82
|
-
|
|
83
80
|
/**
|
|
84
81
|
* The mode of a block filler used by the DOM converter.
|
|
85
82
|
*
|
|
@@ -242,21 +239,47 @@ export default class DomConverter {
|
|
|
242
239
|
}
|
|
243
240
|
|
|
244
241
|
/**
|
|
245
|
-
* Decides whether given pair of attribute key and value should be passed further down the pipeline.
|
|
242
|
+
* Decides whether a given pair of attribute key and value should be passed further down the pipeline.
|
|
246
243
|
*
|
|
247
244
|
* @param {String} attributeKey
|
|
248
245
|
* @param {String} attributeValue
|
|
246
|
+
* @param {String} elementName Element name in lower case.
|
|
249
247
|
* @returns {Boolean}
|
|
250
248
|
*/
|
|
251
|
-
shouldRenderAttribute( attributeKey, attributeValue ) {
|
|
252
|
-
if (
|
|
249
|
+
shouldRenderAttribute( attributeKey, attributeValue, elementName ) {
|
|
250
|
+
if ( this.renderingMode === 'data' ) {
|
|
253
251
|
return true;
|
|
254
252
|
}
|
|
255
253
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
254
|
+
attributeKey = attributeKey.toLowerCase();
|
|
255
|
+
|
|
256
|
+
if ( attributeKey.startsWith( 'on' ) ) {
|
|
257
|
+
return false;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
if (
|
|
261
|
+
attributeKey === 'srcdoc' &&
|
|
262
|
+
attributeValue.match( /\bon\S+\s*=|javascript:|<\s*\/*script/i )
|
|
263
|
+
) {
|
|
264
|
+
return false;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
if (
|
|
268
|
+
elementName === 'img' &&
|
|
269
|
+
( attributeKey === 'src' || attributeKey === 'srcset' )
|
|
270
|
+
) {
|
|
271
|
+
return true;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
if ( elementName === 'source' && attributeKey === 'srcset' ) {
|
|
275
|
+
return true;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
if ( attributeValue.match( /^\s*(javascript:|data:(image\/svg|text\/x?html))/i ) ) {
|
|
279
|
+
return false;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
return true;
|
|
260
283
|
}
|
|
261
284
|
|
|
262
285
|
/**
|
|
@@ -267,7 +290,7 @@ export default class DomConverter {
|
|
|
267
290
|
*/
|
|
268
291
|
setContentOf( domElement, html ) {
|
|
269
292
|
// For data pipeline we pass the HTML as-is.
|
|
270
|
-
if (
|
|
293
|
+
if ( this.renderingMode === 'data' ) {
|
|
271
294
|
domElement.innerHTML = html;
|
|
272
295
|
|
|
273
296
|
return;
|
|
@@ -294,17 +317,15 @@ export default class DomConverter {
|
|
|
294
317
|
for ( const currentNode of nodes ) {
|
|
295
318
|
// Go through nodes to remove those that are prohibited in editing pipeline.
|
|
296
319
|
for ( const attributeName of currentNode.getAttributeNames() ) {
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
if ( !this.shouldRenderAttribute( attributeName, attributeValue ) ) {
|
|
300
|
-
currentNode.removeAttribute( attributeName );
|
|
301
|
-
}
|
|
320
|
+
this.setDomElementAttribute( currentNode, attributeName, currentNode.getAttribute( attributeName ) );
|
|
302
321
|
}
|
|
303
322
|
|
|
304
323
|
const elementName = currentNode.tagName.toLowerCase();
|
|
305
324
|
|
|
306
325
|
// There are certain nodes, that should be renamed to <span> in editing pipeline.
|
|
307
326
|
if ( this._shouldRenameElement( elementName ) ) {
|
|
327
|
+
_logUnsafeElement( elementName );
|
|
328
|
+
|
|
308
329
|
currentNode.replaceWith( this._createReplacementDomElement( elementName, currentNode ) );
|
|
309
330
|
}
|
|
310
331
|
}
|
|
@@ -364,6 +385,8 @@ export default class DomConverter {
|
|
|
364
385
|
} else {
|
|
365
386
|
// Create DOM element.
|
|
366
387
|
if ( this._shouldRenameElement( viewNode.name ) ) {
|
|
388
|
+
_logUnsafeElement( viewNode.name );
|
|
389
|
+
|
|
367
390
|
domElement = this._createReplacementDomElement( viewNode.name );
|
|
368
391
|
} else if ( viewNode.hasAttribute( 'xmlns' ) ) {
|
|
369
392
|
domElement = domDocument.createElementNS( viewNode.getAttribute( 'xmlns' ), viewNode.name );
|
|
@@ -383,13 +406,7 @@ export default class DomConverter {
|
|
|
383
406
|
|
|
384
407
|
// Copy element's attributes.
|
|
385
408
|
for ( const key of viewNode.getAttributeKeys() ) {
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
if ( !this.shouldRenderAttribute( key, value ) ) {
|
|
389
|
-
continue;
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
domElement.setAttribute( key, value );
|
|
409
|
+
this.setDomElementAttribute( domElement, key, viewNode.getAttribute( key ), viewNode );
|
|
393
410
|
}
|
|
394
411
|
}
|
|
395
412
|
|
|
@@ -403,6 +420,60 @@ export default class DomConverter {
|
|
|
403
420
|
}
|
|
404
421
|
}
|
|
405
422
|
|
|
423
|
+
/**
|
|
424
|
+
* Sets the attribute on a DOM element.
|
|
425
|
+
*
|
|
426
|
+
* **Note**: To remove the attribute, use {@link #removeDomElementAttribute}.
|
|
427
|
+
*
|
|
428
|
+
* @param {HTMLElement} domElement The DOM element the attribute should be set on.
|
|
429
|
+
* @param {String} key The name of the attribute.
|
|
430
|
+
* @param {String} value The value of the attribute.
|
|
431
|
+
* @param {module:engine/view/element~Element} [relatedViewElement] The view element related to the `domElement` (if there is any).
|
|
432
|
+
* It helps decide whether the attribute set is unsafe. For instance, view elements created via the
|
|
433
|
+
* {@link module:engine/view/downcastwriter~DowncastWriter} methods can allow certain attributes that would normally be filtered out.
|
|
434
|
+
*/
|
|
435
|
+
setDomElementAttribute( domElement, key, value, relatedViewElement = null ) {
|
|
436
|
+
const shouldRenderAttribute = this.shouldRenderAttribute( key, value, domElement.tagName.toLowerCase() ) ||
|
|
437
|
+
relatedViewElement && relatedViewElement.shouldRenderUnsafeAttribute( key );
|
|
438
|
+
|
|
439
|
+
if ( !shouldRenderAttribute ) {
|
|
440
|
+
logWarning( 'domconverter-unsafe-attribute-detected', { domElement, key, value } );
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
// The old value was safe but the new value is unsafe.
|
|
444
|
+
if ( domElement.hasAttribute( key ) && !shouldRenderAttribute ) {
|
|
445
|
+
domElement.removeAttribute( key );
|
|
446
|
+
}
|
|
447
|
+
// The old value was unsafe (but prefixed) but the new value will be safe (will be unprefixed).
|
|
448
|
+
else if ( domElement.hasAttribute( UNSAFE_ATTRIBUTE_NAME_PREFIX + key ) && shouldRenderAttribute ) {
|
|
449
|
+
domElement.removeAttribute( UNSAFE_ATTRIBUTE_NAME_PREFIX + key );
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
// If the attribute should not be rendered, rename it (instead of removing) to give developers some idea of what
|
|
453
|
+
// is going on (https://github.com/ckeditor/ckeditor5/issues/10801).
|
|
454
|
+
domElement.setAttribute( shouldRenderAttribute ? key : UNSAFE_ATTRIBUTE_NAME_PREFIX + key, value );
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
/**
|
|
458
|
+
* Removes an attribute from a DOM element.
|
|
459
|
+
*
|
|
460
|
+
* **Note**: To set the attribute, use {@link #setDomElementAttribute}.
|
|
461
|
+
*
|
|
462
|
+
* @param {HTMLElement} domElement The DOM element the attribute should be removed from.
|
|
463
|
+
* @param {String} key The name of the attribute.
|
|
464
|
+
*/
|
|
465
|
+
removeDomElementAttribute( domElement, key ) {
|
|
466
|
+
// See #_createReplacementDomElement() to learn what this is.
|
|
467
|
+
if ( key == UNSAFE_ELEMENT_REPLACEMENT_ATTRIBUTE ) {
|
|
468
|
+
return;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
domElement.removeAttribute( key );
|
|
472
|
+
|
|
473
|
+
// See setDomElementAttribute() to learn what this is.
|
|
474
|
+
domElement.removeAttribute( UNSAFE_ATTRIBUTE_NAME_PREFIX + key );
|
|
475
|
+
}
|
|
476
|
+
|
|
406
477
|
/**
|
|
407
478
|
* Converts children of the view element to DOM using the
|
|
408
479
|
* {@link module:engine/view/domconverter~DomConverter#viewToDom} method.
|
|
@@ -548,7 +619,7 @@ export default class DomConverter {
|
|
|
548
619
|
return hostElement;
|
|
549
620
|
}
|
|
550
621
|
|
|
551
|
-
if (
|
|
622
|
+
if ( isComment( domNode ) && options.skipComments ) {
|
|
552
623
|
return null;
|
|
553
624
|
}
|
|
554
625
|
|
|
@@ -593,8 +664,8 @@ export default class DomConverter {
|
|
|
593
664
|
|
|
594
665
|
// Treat this element's content as a raw data if it was registered as such.
|
|
595
666
|
// Comment node is also treated as an element with raw data.
|
|
596
|
-
if ( this._isViewElementWithRawContent( viewElement, options ) ||
|
|
597
|
-
const rawContent =
|
|
667
|
+
if ( this._isViewElementWithRawContent( viewElement, options ) || isComment( domNode ) ) {
|
|
668
|
+
const rawContent = isComment( domNode ) ? domNode.data : domNode.innerHTML;
|
|
598
669
|
|
|
599
670
|
viewElement._setCustomProperty( '$rawContent', rawContent );
|
|
600
671
|
|
|
@@ -963,16 +1034,6 @@ export default class DomConverter {
|
|
|
963
1034
|
return node && node.nodeType == Node.DOCUMENT_FRAGMENT_NODE;
|
|
964
1035
|
}
|
|
965
1036
|
|
|
966
|
-
/**
|
|
967
|
-
* Returns `true` when `node.nodeType` equals `Node.COMMENT_NODE`.
|
|
968
|
-
*
|
|
969
|
-
* @param {Node} node Node to check.
|
|
970
|
-
* @returns {Boolean}
|
|
971
|
-
*/
|
|
972
|
-
isComment( node ) {
|
|
973
|
-
return node && node.nodeType == Node.COMMENT_NODE;
|
|
974
|
-
}
|
|
975
|
-
|
|
976
1037
|
/**
|
|
977
1038
|
* Checks if the node is an instance of the block filler for this DOM converter.
|
|
978
1039
|
*
|
|
@@ -1457,7 +1518,7 @@ export default class DomConverter {
|
|
|
1457
1518
|
* @returns {Element}
|
|
1458
1519
|
*/
|
|
1459
1520
|
_createViewElement( node, options ) {
|
|
1460
|
-
if (
|
|
1521
|
+
if ( isComment( node ) ) {
|
|
1461
1522
|
return new ViewUIElement( this.document, '$comment' );
|
|
1462
1523
|
}
|
|
1463
1524
|
|
|
@@ -1479,18 +1540,20 @@ export default class DomConverter {
|
|
|
1479
1540
|
}
|
|
1480
1541
|
|
|
1481
1542
|
/**
|
|
1482
|
-
* Checks whether given element name should be renamed in a current rendering mode.
|
|
1543
|
+
* Checks whether a given element name should be renamed in a current rendering mode.
|
|
1483
1544
|
*
|
|
1484
1545
|
* @private
|
|
1485
1546
|
* @param {String} elementName The name of view element.
|
|
1486
1547
|
* @returns {Boolean}
|
|
1487
1548
|
*/
|
|
1488
1549
|
_shouldRenameElement( elementName ) {
|
|
1489
|
-
|
|
1550
|
+
const name = elementName.toLowerCase();
|
|
1551
|
+
|
|
1552
|
+
return this.renderingMode === 'editing' && UNSAFE_ELEMENTS.includes( name );
|
|
1490
1553
|
}
|
|
1491
1554
|
|
|
1492
1555
|
/**
|
|
1493
|
-
* Return a <span> element with special attribute holding the name of the original element.
|
|
1556
|
+
* Return a <span> element with a special attribute holding the name of the original element.
|
|
1494
1557
|
* Optionally, copy all the attributes of the original element if that element is provided.
|
|
1495
1558
|
*
|
|
1496
1559
|
* @private
|
|
@@ -1502,7 +1565,7 @@ export default class DomConverter {
|
|
|
1502
1565
|
const newDomElement = document.createElement( 'span' );
|
|
1503
1566
|
|
|
1504
1567
|
// Mark the span replacing a script as hidden.
|
|
1505
|
-
newDomElement.setAttribute(
|
|
1568
|
+
newDomElement.setAttribute( UNSAFE_ELEMENT_REPLACEMENT_ATTRIBUTE, elementName );
|
|
1506
1569
|
|
|
1507
1570
|
if ( originalDomElement ) {
|
|
1508
1571
|
while ( originalDomElement.firstChild ) {
|
|
@@ -1566,6 +1629,20 @@ function hasBlockParent( domNode, blockElements ) {
|
|
|
1566
1629
|
return parent && parent.tagName && blockElements.includes( parent.tagName.toLowerCase() );
|
|
1567
1630
|
}
|
|
1568
1631
|
|
|
1632
|
+
// Log to console the information about element that was replaced.
|
|
1633
|
+
// Check UNSAFE_ELEMENTS for all recognized unsafe elements.
|
|
1634
|
+
//
|
|
1635
|
+
// @param {String} elementName The name of the view element
|
|
1636
|
+
function _logUnsafeElement( elementName ) {
|
|
1637
|
+
if ( elementName === 'script' ) {
|
|
1638
|
+
logWarning( 'domconverter-unsafe-script-element-detected' );
|
|
1639
|
+
}
|
|
1640
|
+
|
|
1641
|
+
if ( elementName === 'style' ) {
|
|
1642
|
+
logWarning( 'domconverter-unsafe-style-element-detected' );
|
|
1643
|
+
}
|
|
1644
|
+
}
|
|
1645
|
+
|
|
1569
1646
|
/**
|
|
1570
1647
|
* Enum representing the type of the block filler.
|
|
1571
1648
|
*
|
|
@@ -1578,3 +1655,48 @@ function hasBlockParent( domNode, blockElements ) {
|
|
|
1578
1655
|
*
|
|
1579
1656
|
* @typedef {String} module:engine/view/filler~BlockFillerMode
|
|
1580
1657
|
*/
|
|
1658
|
+
|
|
1659
|
+
/**
|
|
1660
|
+
* While rendering the editor content, the {@link module:engine/view/domconverter~DomConverter} detected a `<script>` element that may
|
|
1661
|
+
* disrupt the editing experience. To avoid this, the `<script>` element was replaced with `<span data-ck-unsafe-element="script"></span>`.
|
|
1662
|
+
*
|
|
1663
|
+
* @error domconverter-unsafe-script-element-detected
|
|
1664
|
+
*/
|
|
1665
|
+
|
|
1666
|
+
/**
|
|
1667
|
+
* While rendering the editor content, the {@link module:engine/view/domconverter~DomConverter} detected a `<style>` element that may affect
|
|
1668
|
+
* the editing experience. To avoid this, the `<style>` element was replaced with `<span data-ck-unsafe-element="style"></span>`.
|
|
1669
|
+
*
|
|
1670
|
+
* @error domconverter-unsafe-style-element-detected
|
|
1671
|
+
*/
|
|
1672
|
+
|
|
1673
|
+
/**
|
|
1674
|
+
* The {@link module:engine/view/domconverter~DomConverter} detected an interactive attribute in the
|
|
1675
|
+
* {@glink framework/guides/architecture/editing-engine#editing-pipeline editing pipeline}. For the best
|
|
1676
|
+
* editing experience, the attribute was renamed to `data-ck-unsafe-attribute-[original attribute name]`.
|
|
1677
|
+
*
|
|
1678
|
+
* If you are the author of the plugin that generated this attribute and you want it to be preserved
|
|
1679
|
+
* in the editing pipeline, you can configure this when creating the element
|
|
1680
|
+
* using {@link module:engine/view/downcastwriter~DowncastWriter} during the
|
|
1681
|
+
* {@glink framework/guides/architecture/editing-engine#conversion model–view conversion}. Methods such as
|
|
1682
|
+
* {@link module:engine/view/downcastwriter~DowncastWriter#createContainerElement},
|
|
1683
|
+
* {@link module:engine/view/downcastwriter~DowncastWriter#createAttributeElement}, or
|
|
1684
|
+
* {@link module:engine/view/downcastwriter~DowncastWriter#createEmptyElement}
|
|
1685
|
+
* accept an option that will disable filtering of specific attributes:
|
|
1686
|
+
*
|
|
1687
|
+
* const paragraph = writer.createContainerElement( 'p',
|
|
1688
|
+
* {
|
|
1689
|
+
* class: 'clickable-paragraph',
|
|
1690
|
+
* onclick: 'alert( "Paragraph clicked!" )'
|
|
1691
|
+
* },
|
|
1692
|
+
* {
|
|
1693
|
+
* // Make sure the "onclick" attribute will pass through.
|
|
1694
|
+
* renderUnsafeAttributes: [ 'onclick' ]
|
|
1695
|
+
* }
|
|
1696
|
+
* );
|
|
1697
|
+
*
|
|
1698
|
+
* @error domconverter-unsafe-attribute-detected
|
|
1699
|
+
* @param {HTMLElement} domElement The DOM element the attribute was set on.
|
|
1700
|
+
* @param {String} key The original name of the attribute
|
|
1701
|
+
* @param {String} value The value of the original attribute
|
|
1702
|
+
*/
|