@ckeditor/ckeditor5-engine 32.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/package.json +22 -22
- package/src/controller/datacontroller.js +58 -66
- package/src/controller/editingcontroller.js +82 -5
- package/src/conversion/conversion.js +14 -13
- package/src/conversion/downcastdispatcher.js +297 -366
- package/src/conversion/downcasthelpers.js +770 -62
- package/src/conversion/mapper.js +104 -59
- package/src/conversion/modelconsumable.js +84 -34
- package/src/conversion/upcastdispatcher.js +2 -5
- package/src/conversion/upcasthelpers.js +3 -1
- package/src/dataprocessor/htmldataprocessor.js +1 -1
- package/src/dev-utils/model.js +13 -11
- package/src/index.js +1 -0
- package/src/model/batch.js +12 -12
- package/src/model/differ.js +86 -58
- package/src/model/document.js +12 -3
- package/src/model/markercollection.js +28 -4
- package/src/model/model.js +2 -1
- package/src/model/utils/modifyselection.js +14 -7
- package/src/model/writer.js +16 -26
- package/src/view/document.js +2 -1
- package/src/view/domconverter.js +31 -10
- package/src/view/downcastwriter.js +88 -3
- package/theme/placeholder.css +9 -0
package/src/view/domconverter.js
CHANGED
|
@@ -35,6 +35,7 @@ const NBSP_FILLER_REF = NBSP_FILLER( document ); // eslint-disable-line new-cap
|
|
|
35
35
|
const MARKED_NBSP_FILLER_REF = MARKED_NBSP_FILLER( document ); // eslint-disable-line new-cap
|
|
36
36
|
const UNSAFE_ATTRIBUTE_NAME_PREFIX = 'data-ck-unsafe-attribute-';
|
|
37
37
|
const UNSAFE_ELEMENT_REPLACEMENT_ATTRIBUTE = 'data-ck-unsafe-element';
|
|
38
|
+
const UNSAFE_ELEMENTS = [ 'script', 'style' ];
|
|
38
39
|
|
|
39
40
|
/**
|
|
40
41
|
* `DomConverter` is a set of tools to do transformations between DOM nodes and view nodes. It also handles
|
|
@@ -323,7 +324,7 @@ export default class DomConverter {
|
|
|
323
324
|
|
|
324
325
|
// There are certain nodes, that should be renamed to <span> in editing pipeline.
|
|
325
326
|
if ( this._shouldRenameElement( elementName ) ) {
|
|
326
|
-
|
|
327
|
+
_logUnsafeElement( elementName );
|
|
327
328
|
|
|
328
329
|
currentNode.replaceWith( this._createReplacementDomElement( elementName, currentNode ) );
|
|
329
330
|
}
|
|
@@ -384,7 +385,7 @@ export default class DomConverter {
|
|
|
384
385
|
} else {
|
|
385
386
|
// Create DOM element.
|
|
386
387
|
if ( this._shouldRenameElement( viewNode.name ) ) {
|
|
387
|
-
|
|
388
|
+
_logUnsafeElement( viewNode.name );
|
|
388
389
|
|
|
389
390
|
domElement = this._createReplacementDomElement( viewNode.name );
|
|
390
391
|
} else if ( viewNode.hasAttribute( 'xmlns' ) ) {
|
|
@@ -428,7 +429,7 @@ export default class DomConverter {
|
|
|
428
429
|
* @param {String} key The name of the attribute.
|
|
429
430
|
* @param {String} value The value of the attribute.
|
|
430
431
|
* @param {module:engine/view/element~Element} [relatedViewElement] The view element related to the `domElement` (if there is any).
|
|
431
|
-
* It helps decide whether the attribute set is unsafe. For instance, view elements created via
|
|
432
|
+
* It helps decide whether the attribute set is unsafe. For instance, view elements created via the
|
|
432
433
|
* {@link module:engine/view/downcastwriter~DowncastWriter} methods can allow certain attributes that would normally be filtered out.
|
|
433
434
|
*/
|
|
434
435
|
setDomElementAttribute( domElement, key, value, relatedViewElement = null ) {
|
|
@@ -1546,7 +1547,9 @@ export default class DomConverter {
|
|
|
1546
1547
|
* @returns {Boolean}
|
|
1547
1548
|
*/
|
|
1548
1549
|
_shouldRenameElement( elementName ) {
|
|
1549
|
-
|
|
1550
|
+
const name = elementName.toLowerCase();
|
|
1551
|
+
|
|
1552
|
+
return this.renderingMode === 'editing' && UNSAFE_ELEMENTS.includes( name );
|
|
1550
1553
|
}
|
|
1551
1554
|
|
|
1552
1555
|
/**
|
|
@@ -1626,6 +1629,20 @@ function hasBlockParent( domNode, blockElements ) {
|
|
|
1626
1629
|
return parent && parent.tagName && blockElements.includes( parent.tagName.toLowerCase() );
|
|
1627
1630
|
}
|
|
1628
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
|
+
|
|
1629
1646
|
/**
|
|
1630
1647
|
* Enum representing the type of the block filler.
|
|
1631
1648
|
*
|
|
@@ -1640,13 +1657,17 @@ function hasBlockParent( domNode, blockElements ) {
|
|
|
1640
1657
|
*/
|
|
1641
1658
|
|
|
1642
1659
|
/**
|
|
1643
|
-
*
|
|
1644
|
-
*
|
|
1645
|
-
*
|
|
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>`.
|
|
1646
1669
|
*
|
|
1647
|
-
* @error domconverter-unsafe-element-detected
|
|
1648
|
-
* @param {module:engine/model/element~Element|HTMLElement} unsafeElement The editing view or DOM element
|
|
1649
|
-
* that was renamed.
|
|
1670
|
+
* @error domconverter-unsafe-style-element-detected
|
|
1650
1671
|
*/
|
|
1651
1672
|
|
|
1652
1673
|
/**
|
|
@@ -58,6 +58,14 @@ export default class DowncastWriter {
|
|
|
58
58
|
* @type {Map.<String,Set>}
|
|
59
59
|
*/
|
|
60
60
|
this._cloneGroups = new Map();
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* The slot factory used by the `elementToStructure` downcast helper.
|
|
64
|
+
*
|
|
65
|
+
* @private
|
|
66
|
+
* @type {Function|null}
|
|
67
|
+
*/
|
|
68
|
+
this._slotFactory = null;
|
|
61
69
|
}
|
|
62
70
|
|
|
63
71
|
/**
|
|
@@ -222,8 +230,20 @@ export default class DowncastWriter {
|
|
|
222
230
|
* // Create element with custom classes.
|
|
223
231
|
* writer.createContainerElement( 'p', { class: 'foo bar baz' } );
|
|
224
232
|
*
|
|
233
|
+
* // Create element with children.
|
|
234
|
+
* writer.createContainerElement( 'figure', { class: 'image' }, [
|
|
235
|
+
* writer.createEmptyElement( 'img' ),
|
|
236
|
+
* writer.createContainerElement( 'figcaption' )
|
|
237
|
+
* ] );
|
|
238
|
+
*
|
|
239
|
+
* // Create element with specific options.
|
|
240
|
+
* writer.createContainerElement( 'span', { class: 'placeholder' }, { isAllowedInsideAttributeElement: true } );
|
|
241
|
+
*
|
|
225
242
|
* @param {String} name Name of the element.
|
|
226
243
|
* @param {Object} [attributes] Elements attributes.
|
|
244
|
+
* @param {module:engine/view/node~Node|Iterable.<module:engine/view/node~Node>|Object} [childrenOrOptions]
|
|
245
|
+
* A node or a list of nodes to be inserted into the created element. If no children were specified, element's `options`
|
|
246
|
+
* can be passed in this argument.
|
|
227
247
|
* @param {Object} [options] Element's options.
|
|
228
248
|
* @param {Boolean} [options.isAllowedInsideAttributeElement=false] Whether an element is
|
|
229
249
|
* {@link module:engine/view/element~Element#isAllowedInsideAttributeElement allowed inside an AttributeElement} and can be wrapped
|
|
@@ -232,8 +252,16 @@ export default class DowncastWriter {
|
|
|
232
252
|
* pipeline even though they would normally be filtered out by unsafe attribute detection mechanisms.
|
|
233
253
|
* @returns {module:engine/view/containerelement~ContainerElement} Created element.
|
|
234
254
|
*/
|
|
235
|
-
createContainerElement( name, attributes, options = {} ) {
|
|
236
|
-
|
|
255
|
+
createContainerElement( name, attributes, childrenOrOptions = {}, options = {} ) {
|
|
256
|
+
let children = null;
|
|
257
|
+
|
|
258
|
+
if ( isPlainObject( childrenOrOptions ) ) {
|
|
259
|
+
options = childrenOrOptions;
|
|
260
|
+
} else {
|
|
261
|
+
children = childrenOrOptions;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
const containerElement = new ContainerElement( this.document, name, attributes, children );
|
|
237
265
|
|
|
238
266
|
if ( options.isAllowedInsideAttributeElement !== undefined ) {
|
|
239
267
|
containerElement._isAllowedInsideAttributeElement = options.isAllowedInsideAttributeElement;
|
|
@@ -1167,7 +1195,7 @@ export default class DowncastWriter {
|
|
|
1167
1195
|
}
|
|
1168
1196
|
|
|
1169
1197
|
/**
|
|
1170
|
-
Creates new {@link module:engine/view/selection~Selection} instance.
|
|
1198
|
+
* Creates new {@link module:engine/view/selection~Selection} instance.
|
|
1171
1199
|
*
|
|
1172
1200
|
* // Creates empty selection without ranges.
|
|
1173
1201
|
* const selection = writer.createSelection();
|
|
@@ -1230,6 +1258,63 @@ export default class DowncastWriter {
|
|
|
1230
1258
|
return new Selection( selectable, placeOrOffset, options );
|
|
1231
1259
|
}
|
|
1232
1260
|
|
|
1261
|
+
/**
|
|
1262
|
+
* Creates placeholders for child elements of the {@link module:engine/conversion/downcasthelpers~DowncastHelpers#elementToStructure
|
|
1263
|
+
* `elementToStructure()`} conversion helper.
|
|
1264
|
+
*
|
|
1265
|
+
* const viewSlot = conversionApi.writer.createSlot();
|
|
1266
|
+
* const viewPosition = conversionApi.writer.createPositionAt( viewElement, 0 );
|
|
1267
|
+
*
|
|
1268
|
+
* conversionApi.writer.insert( viewPosition, viewSlot );
|
|
1269
|
+
*
|
|
1270
|
+
* It could be filtered down to a specific subset of children (only `<foo>` model elements in this case):
|
|
1271
|
+
*
|
|
1272
|
+
* const viewSlot = conversionApi.writer.createSlot( node => node.is( 'element', 'foo' ) );
|
|
1273
|
+
* const viewPosition = conversionApi.writer.createPositionAt( viewElement, 0 );
|
|
1274
|
+
*
|
|
1275
|
+
* conversionApi.writer.insert( viewPosition, viewSlot );
|
|
1276
|
+
*
|
|
1277
|
+
* While providing a filtered slot, make sure to provide slots for all child nodes. A single node can not be downcasted into
|
|
1278
|
+
* multiple slots.
|
|
1279
|
+
*
|
|
1280
|
+
* **Note**: You should not change the order of nodes. View elements should be in the same order as model nodes.
|
|
1281
|
+
*
|
|
1282
|
+
* @param {'children'|module:engine/conversion/downcasthelpers~SlotFilter} [modeOrFilter='children'] The filter for child nodes.
|
|
1283
|
+
* @returns {module:engine/view/element~Element} The slot element to be placed in to the view structure while processing
|
|
1284
|
+
* {@link module:engine/conversion/downcasthelpers~DowncastHelpers#elementToStructure `elementToStructure()`}.
|
|
1285
|
+
*/
|
|
1286
|
+
createSlot( modeOrFilter ) {
|
|
1287
|
+
if ( !this._slotFactory ) {
|
|
1288
|
+
/**
|
|
1289
|
+
* The `createSlot()` method is only allowed inside the `elementToStructure` downcast helper callback.
|
|
1290
|
+
*
|
|
1291
|
+
* @error view-writer-invalid-create-slot-context
|
|
1292
|
+
*/
|
|
1293
|
+
throw new CKEditorError( 'view-writer-invalid-create-slot-context', this.document );
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1296
|
+
return this._slotFactory( this, modeOrFilter );
|
|
1297
|
+
}
|
|
1298
|
+
|
|
1299
|
+
/**
|
|
1300
|
+
* Registers a slot factory.
|
|
1301
|
+
*
|
|
1302
|
+
* @protected
|
|
1303
|
+
* @param {Function} slotFactory The slot factory.
|
|
1304
|
+
*/
|
|
1305
|
+
_registerSlotFactory( slotFactory ) {
|
|
1306
|
+
this._slotFactory = slotFactory;
|
|
1307
|
+
}
|
|
1308
|
+
|
|
1309
|
+
/**
|
|
1310
|
+
* Clears the registered slot factory.
|
|
1311
|
+
*
|
|
1312
|
+
* @protected
|
|
1313
|
+
*/
|
|
1314
|
+
_clearSlotFactory() {
|
|
1315
|
+
this._slotFactory = null;
|
|
1316
|
+
}
|
|
1317
|
+
|
|
1233
1318
|
/**
|
|
1234
1319
|
* Inserts a node or nodes at the specified position. Takes care of breaking attributes before insertion
|
|
1235
1320
|
* and merging them afterwards if requested by the breakAttributes param.
|
package/theme/placeholder.css
CHANGED
|
@@ -25,3 +25,12 @@
|
|
|
25
25
|
display: none;
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
|
+
|
|
29
|
+
/*
|
|
30
|
+
* Rules for the `ck-placeholder` are loaded before the rules for `ck-reset_all` in the base CKEditor 5 DLL build.
|
|
31
|
+
* This fix overwrites the incorrectly set `position: static` from `ck-reset_all`.
|
|
32
|
+
* See https://github.com/ckeditor/ckeditor5/issues/11418.
|
|
33
|
+
*/
|
|
34
|
+
.ck.ck-reset_all .ck-placeholder {
|
|
35
|
+
position: relative;
|
|
36
|
+
}
|