@ckeditor/ckeditor5-engine 27.1.0 → 29.2.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 +1 -1
- package/README.md +3 -3
- package/package.json +22 -21
- package/src/controller/datacontroller.js +28 -7
- package/src/controller/editingcontroller.js +1 -1
- package/src/conversion/conversion.js +4 -4
- package/src/conversion/downcastdispatcher.js +6 -2
- package/src/conversion/downcasthelpers.js +48 -39
- package/src/conversion/mapper.js +1 -0
- package/src/conversion/modelconsumable.js +10 -5
- package/src/conversion/upcastdispatcher.js +6 -6
- package/src/conversion/upcasthelpers.js +34 -30
- package/src/dataprocessor/dataprocessor.jsdoc +5 -5
- package/src/dataprocessor/htmldataprocessor.js +38 -9
- package/src/dataprocessor/xmldataprocessor.js +5 -5
- package/src/index.js +1 -0
- package/src/model/element.js +3 -3
- package/src/model/liveposition.js +1 -1
- package/src/model/model.js +5 -5
- package/src/model/node.js +3 -3
- package/src/model/range.js +5 -3
- package/src/model/schema.js +103 -39
- package/src/model/selection.js +1 -1
- package/src/model/treewalker.js +3 -4
- package/src/model/utils/deletecontent.js +17 -4
- package/src/model/utils/insertcontent.js +15 -15
- package/src/model/utils/selection-post-fixer.js +1 -1
- package/src/view/documentselection.js +2 -2
- package/src/view/domconverter.js +150 -72
- package/src/view/downcastwriter.js +2 -1
- package/src/view/element.js +3 -2
- package/src/view/filler.js +4 -4
- package/src/view/matcher.js +419 -93
- package/src/view/observer/focusobserver.js +7 -3
- package/src/view/observer/mouseobserver.js +1 -1
- package/src/view/renderer.js +9 -1
- package/src/view/selection.js +2 -2
- package/src/view/styles/background.js +2 -0
- package/src/view/styles/border.js +107 -21
- package/src/view/styles/utils.js +1 -1
- package/src/view/stylesmap.js +45 -5
- package/src/view/upcastwriter.js +12 -11
- package/src/view/view.js +5 -0
package/src/view/domconverter.js
CHANGED
|
@@ -7,10 +7,11 @@
|
|
|
7
7
|
* @module engine/view/domconverter
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
/* globals document, Node,
|
|
10
|
+
/* globals document, Node, Text */
|
|
11
11
|
|
|
12
12
|
import ViewText from './text';
|
|
13
13
|
import ViewElement from './element';
|
|
14
|
+
import ViewUIElement from './uielement';
|
|
14
15
|
import ViewPosition from './position';
|
|
15
16
|
import ViewRange from './range';
|
|
16
17
|
import ViewSelection from './selection';
|
|
@@ -25,9 +26,7 @@ import {
|
|
|
25
26
|
import global from '@ckeditor/ckeditor5-utils/src/dom/global';
|
|
26
27
|
import indexOf from '@ckeditor/ckeditor5-utils/src/dom/indexof';
|
|
27
28
|
import getAncestors from '@ckeditor/ckeditor5-utils/src/dom/getancestors';
|
|
28
|
-
import getCommonAncestor from '@ckeditor/ckeditor5-utils/src/dom/getcommonancestor';
|
|
29
29
|
import isText from '@ckeditor/ckeditor5-utils/src/dom/istext';
|
|
30
|
-
import { isElement } from 'lodash-es';
|
|
31
30
|
|
|
32
31
|
const BR_FILLER_REF = BR_FILLER( document ); // eslint-disable-line new-cap
|
|
33
32
|
const NBSP_FILLER_REF = NBSP_FILLER( document ); // eslint-disable-line new-cap
|
|
@@ -87,7 +86,29 @@ export default class DomConverter {
|
|
|
87
86
|
* @readonly
|
|
88
87
|
* @member {Array.<String>} module:engine/view/domconverter~DomConverter#blockElements
|
|
89
88
|
*/
|
|
90
|
-
this.blockElements = [
|
|
89
|
+
this.blockElements = [
|
|
90
|
+
'address', 'article', 'aside', 'blockquote', 'caption', 'center', 'dd', 'details', 'dir', 'div',
|
|
91
|
+
'dl', 'dt', 'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header',
|
|
92
|
+
'hgroup', 'legend', 'li', 'main', 'menu', 'nav', 'ol', 'p', 'pre', 'section', 'summary', 'table', 'tbody',
|
|
93
|
+
'td', 'tfoot', 'th', 'thead', 'tr', 'ul'
|
|
94
|
+
];
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* A list of elements that exist inline (in text) but their inner structure cannot be edited because
|
|
98
|
+
* of the way they are rendered by the browser. They are mostly HTML form elements but there are other
|
|
99
|
+
* elements such as `<img>` or `<iframe>` that also have non-editable children or no children whatsoever.
|
|
100
|
+
*
|
|
101
|
+
* Whether an element is considered an inline object has an impact on white space rendering (trimming)
|
|
102
|
+
* around (and inside of it). In short, white spaces in text nodes next to inline objects are not trimmed.
|
|
103
|
+
*
|
|
104
|
+
* You can extend this array if you introduce support for inline object elements which are not yet recognized here.
|
|
105
|
+
*
|
|
106
|
+
* @readonly
|
|
107
|
+
* @member {Array.<String>} module:engine/view/domconverter~DomConverter#inlineObjectElements
|
|
108
|
+
*/
|
|
109
|
+
this.inlineObjectElements = [
|
|
110
|
+
'object', 'iframe', 'input', 'button', 'textarea', 'select', 'option', 'video', 'embed', 'audio', 'img', 'canvas'
|
|
111
|
+
];
|
|
91
112
|
|
|
92
113
|
/**
|
|
93
114
|
* The DOM-to-view mapping.
|
|
@@ -232,8 +253,12 @@ export default class DomConverter {
|
|
|
232
253
|
this.bindDocumentFragments( domElement, viewNode );
|
|
233
254
|
}
|
|
234
255
|
} else if ( viewNode.is( 'uiElement' ) ) {
|
|
235
|
-
|
|
236
|
-
|
|
256
|
+
if ( viewNode.name === '$comment' ) {
|
|
257
|
+
domElement = domDocument.createComment( viewNode.getCustomProperty( '$rawContent' ) );
|
|
258
|
+
} else {
|
|
259
|
+
// UIElement has its own render() method (see #799).
|
|
260
|
+
domElement = viewNode.render( domDocument );
|
|
261
|
+
}
|
|
237
262
|
|
|
238
263
|
if ( options.bind ) {
|
|
239
264
|
this.bindElements( domElement, viewNode );
|
|
@@ -401,7 +426,9 @@ export default class DomConverter {
|
|
|
401
426
|
* @param {Object} [options] Conversion options.
|
|
402
427
|
* @param {Boolean} [options.bind=false] Determines whether new elements will be bound.
|
|
403
428
|
* @param {Boolean} [options.withChildren=true] If `true`, node's and document fragment's children will be converted too.
|
|
404
|
-
* @param {Boolean} [options.keepOriginalCase=false] If `false`, node's tag name will be
|
|
429
|
+
* @param {Boolean} [options.keepOriginalCase=false] If `false`, node's tag name will be converted to lower case.
|
|
430
|
+
* @param {Boolean} [options.skipComments=false] If `false`, comment nodes will be converted to `$comment`
|
|
431
|
+
* {@link module:engine/view/uielement~UIElement view UI elements}.
|
|
405
432
|
* @returns {module:engine/view/node~Node|module:engine/view/documentfragment~DocumentFragment|null} Converted node or document fragment
|
|
406
433
|
* or `null` if DOM node is a {@link module:engine/view/filler filler} or the given node is an empty text node.
|
|
407
434
|
*/
|
|
@@ -417,6 +444,10 @@ export default class DomConverter {
|
|
|
417
444
|
return hostElement;
|
|
418
445
|
}
|
|
419
446
|
|
|
447
|
+
if ( this.isComment( domNode ) && options.skipComments ) {
|
|
448
|
+
return null;
|
|
449
|
+
}
|
|
450
|
+
|
|
420
451
|
if ( isText( domNode ) ) {
|
|
421
452
|
if ( isInlineFiller( domNode ) ) {
|
|
422
453
|
return null;
|
|
@@ -425,8 +456,6 @@ export default class DomConverter {
|
|
|
425
456
|
|
|
426
457
|
return textData === '' ? null : new ViewText( this.document, textData );
|
|
427
458
|
}
|
|
428
|
-
} else if ( this.isComment( domNode ) ) {
|
|
429
|
-
return null;
|
|
430
459
|
} else {
|
|
431
460
|
if ( this.mapDomToView( domNode ) ) {
|
|
432
461
|
return this.mapDomToView( domNode );
|
|
@@ -443,8 +472,7 @@ export default class DomConverter {
|
|
|
443
472
|
}
|
|
444
473
|
} else {
|
|
445
474
|
// Create view element.
|
|
446
|
-
|
|
447
|
-
viewElement = new ViewElement( this.document, viewName );
|
|
475
|
+
viewElement = this._createViewElement( domNode, options );
|
|
448
476
|
|
|
449
477
|
if ( options.bind ) {
|
|
450
478
|
this.bindElements( domNode, viewElement );
|
|
@@ -453,13 +481,18 @@ export default class DomConverter {
|
|
|
453
481
|
// Copy element's attributes.
|
|
454
482
|
const attrs = domNode.attributes;
|
|
455
483
|
|
|
456
|
-
|
|
457
|
-
|
|
484
|
+
if ( attrs ) {
|
|
485
|
+
for ( let i = attrs.length - 1; i >= 0; i-- ) {
|
|
486
|
+
viewElement._setAttribute( attrs[ i ].name, attrs[ i ].value );
|
|
487
|
+
}
|
|
458
488
|
}
|
|
459
489
|
|
|
460
490
|
// Treat this element's content as a raw data if it was registered as such.
|
|
461
|
-
|
|
462
|
-
|
|
491
|
+
// Comment node is also treated as an element with raw data.
|
|
492
|
+
if ( this._isViewElementWithRawContent( viewElement, options ) || this.isComment( domNode ) ) {
|
|
493
|
+
const rawContent = this.isComment( domNode ) ? domNode.data : domNode.innerHTML;
|
|
494
|
+
|
|
495
|
+
viewElement._setCustomProperty( '$rawContent', rawContent );
|
|
463
496
|
|
|
464
497
|
// Store a DOM node to prevent left trimming of the following text node.
|
|
465
498
|
this._encounteredRawContentDomNodes.add( domNode );
|
|
@@ -950,7 +983,7 @@ export default class DomConverter {
|
|
|
950
983
|
}
|
|
951
984
|
|
|
952
985
|
/**
|
|
953
|
-
* Returns block {@link module:engine/view/filler filler} node based on current {@link #blockFillerMode} setting.
|
|
986
|
+
* Returns the block {@link module:engine/view/filler filler} node based on the current {@link #blockFillerMode} setting.
|
|
954
987
|
*
|
|
955
988
|
* @private
|
|
956
989
|
* @params {Document} domDocument
|
|
@@ -1029,8 +1062,8 @@ export default class DomConverter {
|
|
|
1029
1062
|
// 1. Replace the first space with a nbsp if the previous node ends with a space or there is no previous node
|
|
1030
1063
|
// (container element boundary).
|
|
1031
1064
|
if ( data.charAt( 0 ) == ' ' ) {
|
|
1032
|
-
const prevNode = this.
|
|
1033
|
-
const prevEndsWithSpace = prevNode && this._nodeEndsWithSpace( prevNode );
|
|
1065
|
+
const prevNode = this._getTouchingInlineViewNode( node, false );
|
|
1066
|
+
const prevEndsWithSpace = prevNode && prevNode.is( '$textProxy' ) && this._nodeEndsWithSpace( prevNode );
|
|
1034
1067
|
|
|
1035
1068
|
if ( prevEndsWithSpace || !prevNode ) {
|
|
1036
1069
|
data = '\u00A0' + data.substr( 1 );
|
|
@@ -1047,9 +1080,10 @@ export default class DomConverter {
|
|
|
1047
1080
|
//
|
|
1048
1081
|
// More here: https://github.com/ckeditor/ckeditor5-engine/issues/1747.
|
|
1049
1082
|
if ( data.charAt( data.length - 1 ) == ' ' ) {
|
|
1050
|
-
const nextNode = this.
|
|
1083
|
+
const nextNode = this._getTouchingInlineViewNode( node, true );
|
|
1084
|
+
const nextStartsWithSpace = nextNode && nextNode.is( '$textProxy' ) && nextNode.data.charAt( 0 ) == ' ';
|
|
1051
1085
|
|
|
1052
|
-
if ( data.charAt( data.length - 2 ) == ' ' || !nextNode ||
|
|
1086
|
+
if ( data.charAt( data.length - 2 ) == ' ' || !nextNode || nextStartsWithSpace ) {
|
|
1053
1087
|
data = data.substr( 0, data.length - 1 ) + '\u00A0';
|
|
1054
1088
|
}
|
|
1055
1089
|
}
|
|
@@ -1136,14 +1170,17 @@ export default class DomConverter {
|
|
|
1136
1170
|
// ` \u00A0` to ensure proper rendering. Since here we convert back, we recognize those pairs and change them back to ` `.
|
|
1137
1171
|
data = data.replace( / \u00A0/g, ' ' );
|
|
1138
1172
|
|
|
1173
|
+
const isNextNodeInlineObjectElement = nextNode && this.isElement( nextNode ) && nextNode.tagName != 'BR';
|
|
1174
|
+
const isNextNodeStartingWithSpace = nextNode && isText( nextNode ) && nextNode.data.charAt( 0 ) == ' ';
|
|
1175
|
+
|
|
1139
1176
|
// Then, let's change the last nbsp to a space.
|
|
1140
|
-
if ( /( |\u00A0)\u00A0$/.test( data ) || !nextNode ||
|
|
1177
|
+
if ( /( |\u00A0)\u00A0$/.test( data ) || !nextNode || isNextNodeInlineObjectElement || isNextNodeStartingWithSpace ) {
|
|
1141
1178
|
data = data.replace( /\u00A0$/, ' ' );
|
|
1142
1179
|
}
|
|
1143
1180
|
|
|
1144
1181
|
// Then, change character that is at the beginning of the text node to space character.
|
|
1145
1182
|
// We do that replacement only if this is the first node or the previous node ends on whitespace character.
|
|
1146
|
-
if ( shouldLeftTrim ) {
|
|
1183
|
+
if ( shouldLeftTrim || prevNode && this.isElement( prevNode ) && prevNode.tagName != 'BR' ) {
|
|
1147
1184
|
data = data.replace( /^\u00A0/, ' ' );
|
|
1148
1185
|
}
|
|
1149
1186
|
|
|
@@ -1158,15 +1195,15 @@ export default class DomConverter {
|
|
|
1158
1195
|
*
|
|
1159
1196
|
* @private
|
|
1160
1197
|
* @param {Node} node
|
|
1161
|
-
* @param {Node} prevNode
|
|
1198
|
+
* @param {Node} prevNode Either DOM text or `<br>` or one of `#inlineObjectElements`.
|
|
1162
1199
|
*/
|
|
1163
1200
|
_checkShouldLeftTrimDomText( node, prevNode ) {
|
|
1164
1201
|
if ( !prevNode ) {
|
|
1165
1202
|
return true;
|
|
1166
1203
|
}
|
|
1167
1204
|
|
|
1168
|
-
if ( isElement( prevNode ) ) {
|
|
1169
|
-
return
|
|
1205
|
+
if ( this.isElement( prevNode ) ) {
|
|
1206
|
+
return prevNode.tagName === 'BR';
|
|
1170
1207
|
}
|
|
1171
1208
|
|
|
1172
1209
|
// Shouldn't left trim if previous node is a node that was encountered as a raw content node.
|
|
@@ -1183,7 +1220,7 @@ export default class DomConverter {
|
|
|
1183
1220
|
*
|
|
1184
1221
|
* @private
|
|
1185
1222
|
* @param {Node} node
|
|
1186
|
-
* @param {Node} nextNode
|
|
1223
|
+
* @param {Node} nextNode Either DOM text or `<br>` or one of `#inlineObjectElements`.
|
|
1187
1224
|
*/
|
|
1188
1225
|
_checkShouldRightTrimDomText( node, nextNode ) {
|
|
1189
1226
|
if ( nextNode ) {
|
|
@@ -1200,18 +1237,23 @@ export default class DomConverter {
|
|
|
1200
1237
|
* @private
|
|
1201
1238
|
* @param {module:engine/view/text~Text} node Reference node.
|
|
1202
1239
|
* @param {Boolean} getNext
|
|
1203
|
-
* @returns {module:engine/view/text~Text|null} Touching text node
|
|
1240
|
+
* @returns {module:engine/view/text~Text|module:engine/view/element~Element|null} Touching text node, an inline object
|
|
1241
|
+
* or `null` if there is no next or previous touching text node.
|
|
1204
1242
|
*/
|
|
1205
|
-
|
|
1243
|
+
_getTouchingInlineViewNode( node, getNext ) {
|
|
1206
1244
|
const treeWalker = new ViewTreeWalker( {
|
|
1207
1245
|
startPosition: getNext ? ViewPosition._createAfter( node ) : ViewPosition._createBefore( node ),
|
|
1208
1246
|
direction: getNext ? 'forward' : 'backward'
|
|
1209
1247
|
} );
|
|
1210
1248
|
|
|
1211
1249
|
for ( const value of treeWalker ) {
|
|
1250
|
+
// Found an inline object (for example an image).
|
|
1251
|
+
if ( value.item.is( 'element' ) && this.inlineObjectElements.includes( value.item.name ) ) {
|
|
1252
|
+
return value.item;
|
|
1253
|
+
}
|
|
1212
1254
|
// ViewContainerElement is found on a way to next ViewText node, so given `node` was first/last
|
|
1213
1255
|
// text node in its container element.
|
|
1214
|
-
if ( value.item.is( 'containerElement' ) ) {
|
|
1256
|
+
else if ( value.item.is( 'containerElement' ) ) {
|
|
1215
1257
|
return null;
|
|
1216
1258
|
}
|
|
1217
1259
|
// <br> found – it works like a block boundary, so do not scan further.
|
|
@@ -1229,10 +1271,11 @@ export default class DomConverter {
|
|
|
1229
1271
|
|
|
1230
1272
|
/**
|
|
1231
1273
|
* Helper function. For the given text node, it finds the closest touching node which is either
|
|
1232
|
-
* a text
|
|
1233
|
-
* wasn't found so far, `null` is returned.
|
|
1274
|
+
* a text, `<br>` or an {@link #inlineObjectElements inline object}.
|
|
1234
1275
|
*
|
|
1235
|
-
*
|
|
1276
|
+
* If no such node is found, `null` is returned.
|
|
1277
|
+
*
|
|
1278
|
+
* For instance, in the following DOM structure:
|
|
1236
1279
|
*
|
|
1237
1280
|
* <p>foo<b>bar</b><br>bom</p>
|
|
1238
1281
|
*
|
|
@@ -1253,45 +1296,82 @@ export default class DomConverter {
|
|
|
1253
1296
|
return null;
|
|
1254
1297
|
}
|
|
1255
1298
|
|
|
1256
|
-
const
|
|
1257
|
-
const
|
|
1258
|
-
const topmostParent = getAncestors( node )[ 0 ];
|
|
1299
|
+
const stepInto = getNext ? 'firstChild' : 'lastChild';
|
|
1300
|
+
const stepOver = getNext ? 'nextSibling' : 'previousSibling';
|
|
1259
1301
|
|
|
1260
|
-
|
|
1261
|
-
acceptNode( node ) {
|
|
1262
|
-
if ( isText( node ) ) {
|
|
1263
|
-
return NodeFilter.FILTER_ACCEPT;
|
|
1264
|
-
}
|
|
1302
|
+
let skipChildren = true;
|
|
1265
1303
|
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1304
|
+
do {
|
|
1305
|
+
if ( !skipChildren && node[ stepInto ] ) {
|
|
1306
|
+
node = node[ stepInto ];
|
|
1307
|
+
} else if ( node[ stepOver ] ) {
|
|
1308
|
+
node = node[ stepOver ];
|
|
1309
|
+
skipChildren = false;
|
|
1310
|
+
} else {
|
|
1311
|
+
node = node.parentNode;
|
|
1312
|
+
skipChildren = true;
|
|
1313
|
+
}
|
|
1269
1314
|
|
|
1270
|
-
|
|
1315
|
+
if ( !node || this._isBlockElement( node ) ) {
|
|
1316
|
+
return null;
|
|
1271
1317
|
}
|
|
1272
|
-
}
|
|
1318
|
+
} while (
|
|
1319
|
+
!( isText( node ) || node.tagName == 'BR' || this._isInlineObjectElement( node ) )
|
|
1320
|
+
);
|
|
1273
1321
|
|
|
1274
|
-
|
|
1322
|
+
return node;
|
|
1323
|
+
}
|
|
1275
1324
|
|
|
1276
|
-
|
|
1325
|
+
/**
|
|
1326
|
+
* Returns `true` if a DOM node belongs to {@link #blockElements}. `false` otherwise.
|
|
1327
|
+
*
|
|
1328
|
+
* @private
|
|
1329
|
+
* @param {Node} node
|
|
1330
|
+
* @returns {Boolean}
|
|
1331
|
+
*/
|
|
1332
|
+
_isBlockElement( node ) {
|
|
1333
|
+
return this.isElement( node ) && this.blockElements.includes( node.tagName.toLowerCase() );
|
|
1334
|
+
}
|
|
1277
1335
|
|
|
1278
|
-
|
|
1279
|
-
|
|
1336
|
+
/**
|
|
1337
|
+
* Returns `true` if a DOM node belongs to {@link #inlineObjectElements}. `false` otherwise.
|
|
1338
|
+
*
|
|
1339
|
+
* @private
|
|
1340
|
+
* @param {Node} node
|
|
1341
|
+
* @returns {Boolean}
|
|
1342
|
+
*/
|
|
1343
|
+
_isInlineObjectElement( node ) {
|
|
1344
|
+
return this.isElement( node ) && this.inlineObjectElements.includes( node.tagName.toLowerCase() );
|
|
1345
|
+
}
|
|
1280
1346
|
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1347
|
+
/**
|
|
1348
|
+
* Creates view element basing on the node type.
|
|
1349
|
+
*
|
|
1350
|
+
* @private
|
|
1351
|
+
* @param {Node} node DOM node to check.
|
|
1352
|
+
* @param {Object} options Conversion options. See {@link module:engine/view/domconverter~DomConverter#domToView} options parameter.
|
|
1353
|
+
* @returns {Element}
|
|
1354
|
+
*/
|
|
1355
|
+
_createViewElement( node, options ) {
|
|
1356
|
+
if ( this.isComment( node ) ) {
|
|
1357
|
+
return new ViewUIElement( this.document, '$comment' );
|
|
1292
1358
|
}
|
|
1293
1359
|
|
|
1294
|
-
|
|
1360
|
+
const viewName = options.keepOriginalCase ? node.tagName : node.tagName.toLowerCase();
|
|
1361
|
+
|
|
1362
|
+
return new ViewElement( this.document, viewName );
|
|
1363
|
+
}
|
|
1364
|
+
|
|
1365
|
+
/**
|
|
1366
|
+
* Checks if view element's content should be treated as a raw data.
|
|
1367
|
+
*
|
|
1368
|
+
* @private
|
|
1369
|
+
* @param {Element} viewElement View element to check.
|
|
1370
|
+
* @param {Object} options Conversion options. See {@link module:engine/view/domconverter~DomConverter#domToView} options parameter.
|
|
1371
|
+
* @returns {Boolean}
|
|
1372
|
+
*/
|
|
1373
|
+
_isViewElementWithRawContent( viewElement, options ) {
|
|
1374
|
+
return options.withChildren !== false && this._rawContentElementMatcher.match( viewElement );
|
|
1295
1375
|
}
|
|
1296
1376
|
}
|
|
1297
1377
|
|
|
@@ -1300,14 +1380,9 @@ export default class DomConverter {
|
|
|
1300
1380
|
//
|
|
1301
1381
|
// @param {Node} node
|
|
1302
1382
|
// @param {Array.<String>} types
|
|
1303
|
-
// @param {Boolean} [boundaryParent] Can be given if parents should be checked up to a given element (excluding that element).
|
|
1304
1383
|
// @returns {Boolean} `true` if such parent exists or `false` if it does not.
|
|
1305
|
-
function _hasDomParentOfType( node, types
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
if ( boundaryParent ) {
|
|
1309
|
-
parents = parents.slice( parents.indexOf( boundaryParent ) + 1 );
|
|
1310
|
-
}
|
|
1384
|
+
function _hasDomParentOfType( node, types ) {
|
|
1385
|
+
const parents = getAncestors( node );
|
|
1311
1386
|
|
|
1312
1387
|
return parents.some( parent => parent.tagName && types.includes( parent.tagName.toLowerCase() ) );
|
|
1313
1388
|
}
|
|
@@ -1329,6 +1404,7 @@ function forEachDomNodeAncestor( node, callback ) {
|
|
|
1329
1404
|
// A is a block filler only if it is a single child of a block element.
|
|
1330
1405
|
//
|
|
1331
1406
|
// @param {Node} domNode DOM node.
|
|
1407
|
+
// @param {Array.<String>} blockElements
|
|
1332
1408
|
// @returns {Boolean}
|
|
1333
1409
|
function isNbspBlockFiller( domNode, blockElements ) {
|
|
1334
1410
|
const isNBSP = domNode.isEqualNode( NBSP_FILLER_REF );
|
|
@@ -1339,6 +1415,7 @@ function isNbspBlockFiller( domNode, blockElements ) {
|
|
|
1339
1415
|
// Checks if domNode has block parent.
|
|
1340
1416
|
//
|
|
1341
1417
|
// @param {Node} domNode DOM node.
|
|
1418
|
+
// @param {Array.<String>} blockElements
|
|
1342
1419
|
// @returns {Boolean}
|
|
1343
1420
|
function hasBlockParent( domNode, blockElements ) {
|
|
1344
1421
|
const parent = domNode.parentNode;
|
|
@@ -1347,13 +1424,14 @@ function hasBlockParent( domNode, blockElements ) {
|
|
|
1347
1424
|
}
|
|
1348
1425
|
|
|
1349
1426
|
/**
|
|
1350
|
-
* Enum representing type of the block filler.
|
|
1427
|
+
* Enum representing the type of the block filler.
|
|
1351
1428
|
*
|
|
1352
1429
|
* Possible values:
|
|
1353
1430
|
*
|
|
1354
|
-
* * `br`
|
|
1355
|
-
* * `nbsp`
|
|
1356
|
-
* * `markedNbsp`
|
|
1431
|
+
* * `br` – For the `<br data-cke-filler="true">` block filler used in the editing view.
|
|
1432
|
+
* * `nbsp` – For the ` ` block fillers used in the data.
|
|
1433
|
+
* * `markedNbsp` – For the ` ` block fillers wrapped in `<span>` elements: `<span data-cke-filler="true"> </span>`
|
|
1434
|
+
* used in the data.
|
|
1357
1435
|
*
|
|
1358
1436
|
* @typedef {String} module:engine/view/filler~BlockFillerMode
|
|
1359
1437
|
*/
|
|
@@ -191,7 +191,7 @@ export default class DowncastWriter {
|
|
|
191
191
|
createAttributeElement( name, attributes, options = {} ) {
|
|
192
192
|
const attributeElement = new AttributeElement( this.document, name, attributes );
|
|
193
193
|
|
|
194
|
-
if ( options.priority ) {
|
|
194
|
+
if ( typeof options.priority === 'number' ) {
|
|
195
195
|
attributeElement._priority = options.priority;
|
|
196
196
|
}
|
|
197
197
|
|
|
@@ -1075,6 +1075,7 @@ export default class DowncastWriter {
|
|
|
1075
1075
|
* @param {module:engine/view/item~Item|module:engine/model/position~Position} itemOrPosition
|
|
1076
1076
|
* @param {Number|'end'|'before'|'after'} [offset] Offset or one of the flags. Used only when
|
|
1077
1077
|
* first parameter is a {@link module:engine/view/item~Item view item}.
|
|
1078
|
+
* @returns {module:engine/view/position~Position}
|
|
1078
1079
|
*/
|
|
1079
1080
|
createPositionAt( itemOrPosition, offset ) {
|
|
1080
1081
|
return Position._createAt( itemOrPosition, offset );
|
package/src/view/element.js
CHANGED
|
@@ -468,10 +468,11 @@ export default class Element extends Node {
|
|
|
468
468
|
/**
|
|
469
469
|
* Returns iterator that contains all style names.
|
|
470
470
|
*
|
|
471
|
+
* @param {Boolean} [expand=false] Expand shorthand style properties and return all equivalent style representations.
|
|
471
472
|
* @returns {Iterable.<String>}
|
|
472
473
|
*/
|
|
473
|
-
getStyleNames() {
|
|
474
|
-
return this._styles.getStyleNames();
|
|
474
|
+
getStyleNames( expand = false ) {
|
|
475
|
+
return this._styles.getStyleNames( expand );
|
|
475
476
|
}
|
|
476
477
|
|
|
477
478
|
/**
|
package/src/view/filler.js
CHANGED
|
@@ -7,7 +7,7 @@ import { keyCodes } from '@ckeditor/ckeditor5-utils/src/keyboard';
|
|
|
7
7
|
import isText from '@ckeditor/ckeditor5-utils/src/dom/istext';
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
* Set of
|
|
10
|
+
* Set of utilities related to handling block and inline fillers.
|
|
11
11
|
*
|
|
12
12
|
* Browsers do not allow to put caret in elements which does not have height. Because of it, we need to fill all
|
|
13
13
|
* empty elements which should be selectable with elements or characters called "fillers". Unfortunately there is no one
|
|
@@ -36,7 +36,7 @@ import isText from '@ckeditor/ckeditor5-utils/src/dom/istext';
|
|
|
36
36
|
*/
|
|
37
37
|
|
|
38
38
|
/**
|
|
39
|
-
* Non-breaking space filler creator. This
|
|
39
|
+
* Non-breaking space filler creator. This function creates the ` ` text node.
|
|
40
40
|
* It defines how the filler is created.
|
|
41
41
|
*
|
|
42
42
|
* @see module:engine/view/filler~MARKED_NBSP_FILLER
|
|
@@ -46,7 +46,7 @@ import isText from '@ckeditor/ckeditor5-utils/src/dom/istext';
|
|
|
46
46
|
export const NBSP_FILLER = domDocument => domDocument.createTextNode( '\u00A0' );
|
|
47
47
|
|
|
48
48
|
/**
|
|
49
|
-
* Marked non-breaking space filler creator. This
|
|
49
|
+
* Marked non-breaking space filler creator. This function creates the `<span data-cke-filler="true"> </span>` element.
|
|
50
50
|
* It defines how the filler is created.
|
|
51
51
|
*
|
|
52
52
|
* @see module:engine/view/filler~NBSP_FILLER
|
|
@@ -62,7 +62,7 @@ export const MARKED_NBSP_FILLER = domDocument => {
|
|
|
62
62
|
};
|
|
63
63
|
|
|
64
64
|
/**
|
|
65
|
-
* `<br>` filler creator. This
|
|
65
|
+
* `<br>` filler creator. This function creates the `<br data-cke-filler="true">` element.
|
|
66
66
|
* It defines how the filler is created.
|
|
67
67
|
*
|
|
68
68
|
* @see module:engine/view/filler~NBSP_FILLER
|