@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
|
@@ -39,9 +39,6 @@ import { getShorthandValues, getBoxSidesValueReducer, getBoxSidesValues, isLengt
|
|
|
39
39
|
* }
|
|
40
40
|
* };
|
|
41
41
|
*
|
|
42
|
-
* The `border` value is reduced to a 4 values for each box edge (even if they could be further reduces to a single
|
|
43
|
-
* `border:<width> <style> <color>` style.
|
|
44
|
-
*
|
|
45
42
|
* @param {module:engine/view/stylesmap~StylesProcessor} stylesProcessor
|
|
46
43
|
*/
|
|
47
44
|
export function addBorderRules( stylesProcessor ) {
|
|
@@ -102,7 +99,7 @@ export function addBorderRules( stylesProcessor ) {
|
|
|
102
99
|
stylesProcessor.setReducer( 'border-right', getBorderPositionReducer( 'right' ) );
|
|
103
100
|
stylesProcessor.setReducer( 'border-bottom', getBorderPositionReducer( 'bottom' ) );
|
|
104
101
|
stylesProcessor.setReducer( 'border-left', getBorderPositionReducer( 'left' ) );
|
|
105
|
-
stylesProcessor.setReducer( 'border',
|
|
102
|
+
stylesProcessor.setReducer( 'border', getBorderReducer() );
|
|
106
103
|
|
|
107
104
|
stylesProcessor.setStyleRelation( 'border', [
|
|
108
105
|
'border-color', 'border-style', 'border-width',
|
|
@@ -238,39 +235,128 @@ function normalizeBorderShorthand( string ) {
|
|
|
238
235
|
return result;
|
|
239
236
|
}
|
|
240
237
|
|
|
241
|
-
|
|
242
|
-
|
|
238
|
+
// The border reducer factory.
|
|
239
|
+
//
|
|
240
|
+
// It tries to produce the most optimal output for the specified styles.
|
|
241
|
+
//
|
|
242
|
+
// For a border style:
|
|
243
|
+
//
|
|
244
|
+
// style: {top: "solid", bottom: "solid", right: "solid", left: "solid"}
|
|
245
|
+
//
|
|
246
|
+
// It will produce: `border-style: solid`.
|
|
247
|
+
// For a border style and color:
|
|
248
|
+
//
|
|
249
|
+
// color: {top: "#ff0", bottom: "#ff0", right: "#ff0", left: "#ff0"}
|
|
250
|
+
// style: {top: "solid", bottom: "solid", right: "solid", left: "solid"}
|
|
251
|
+
//
|
|
252
|
+
// It will produce: `border-color: #ff0; border-style: solid`.
|
|
253
|
+
// If all border parameters are specified:
|
|
254
|
+
//
|
|
255
|
+
// color: {top: "#ff0", bottom: "#ff0", right: "#ff0", left: "#ff0"}
|
|
256
|
+
// style: {top: "solid", bottom: "solid", right: "solid", left: "solid"}
|
|
257
|
+
// width: {top: "2px", bottom: "2px", right: "2px", left: "2px"}
|
|
258
|
+
//
|
|
259
|
+
// It will combine everything into a single property: `border: 2px solid #ff0`.
|
|
260
|
+
//
|
|
261
|
+
// The definitions are merged only if all border selectors have the same values.
|
|
262
|
+
//
|
|
263
|
+
// @returns {Function}
|
|
264
|
+
function getBorderReducer() {
|
|
265
|
+
return value => {
|
|
266
|
+
const topStyles = extractBorderPosition( value, 'top' );
|
|
267
|
+
const rightStyles = extractBorderPosition( value, 'right' );
|
|
268
|
+
const bottomStyles = extractBorderPosition( value, 'bottom' );
|
|
269
|
+
const leftStyles = extractBorderPosition( value, 'left' );
|
|
270
|
+
|
|
271
|
+
const borderStyles = [ topStyles, rightStyles, bottomStyles, leftStyles ];
|
|
272
|
+
|
|
273
|
+
const borderStylesByType = {
|
|
274
|
+
width: getReducedStyleValueForType( borderStyles, 'width' ),
|
|
275
|
+
style: getReducedStyleValueForType( borderStyles, 'style' ),
|
|
276
|
+
color: getReducedStyleValueForType( borderStyles, 'color' )
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
// Try reducing to a single `border:` property.
|
|
280
|
+
const reducedBorderStyle = reduceBorderPosition( borderStylesByType, 'all' );
|
|
281
|
+
|
|
282
|
+
if ( reducedBorderStyle.length ) {
|
|
283
|
+
return reducedBorderStyle;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// Try reducing to `border-style:`, `border-width:`, `border-color:` properties.
|
|
287
|
+
const reducedStyleTypes = Object.entries( borderStylesByType ).reduce( ( reducedStyleTypes, [ type, value ] ) => {
|
|
288
|
+
if ( value ) {
|
|
289
|
+
reducedStyleTypes.push( [ `border-${ type }`, value ] );
|
|
290
|
+
|
|
291
|
+
// Remove it from the full set to not include it in the most specific properties later.
|
|
292
|
+
borderStyles.forEach( style => ( style[ type ] = null ) );
|
|
293
|
+
}
|
|
243
294
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
295
|
+
return reducedStyleTypes;
|
|
296
|
+
}, [] );
|
|
297
|
+
|
|
298
|
+
// The reduced properties (by type) and all that remains that could not be reduced.
|
|
299
|
+
return [
|
|
300
|
+
...reducedStyleTypes,
|
|
301
|
+
...reduceBorderPosition( topStyles, 'top' ),
|
|
302
|
+
...reduceBorderPosition( rightStyles, 'right' ),
|
|
303
|
+
...reduceBorderPosition( bottomStyles, 'bottom' ),
|
|
304
|
+
...reduceBorderPosition( leftStyles, 'left' )
|
|
305
|
+
];
|
|
306
|
+
};
|
|
248
307
|
|
|
249
|
-
|
|
308
|
+
// @param {Array.<Object>} styles The array of objects with `style`, `color`, `width` properties.
|
|
309
|
+
// @param {'width'|'style'|'color'} type
|
|
310
|
+
function getReducedStyleValueForType( styles, type ) {
|
|
311
|
+
return styles
|
|
312
|
+
.map( style => style[ type ] )
|
|
313
|
+
.reduce( ( result, style ) => result == style ? result : null );
|
|
314
|
+
}
|
|
250
315
|
}
|
|
251
316
|
|
|
252
317
|
function getBorderPositionReducer( which ) {
|
|
253
318
|
return value => reduceBorderPosition( value, which );
|
|
254
319
|
}
|
|
255
320
|
|
|
321
|
+
// Returns an array with reduced border styles depending on the specified values.
|
|
322
|
+
//
|
|
323
|
+
// If all border properties (width, style, color) are specified, the returned selector will be
|
|
324
|
+
// merged into a group: `border-*: [width] [style] [color]`.
|
|
325
|
+
//
|
|
326
|
+
// Otherwise, the specific definitions will be returned: `border-(width|style|color)-*: [value]`.
|
|
327
|
+
//
|
|
328
|
+
// @param {Object|null} value Styles if defined.
|
|
329
|
+
// @param {'top'|'right'|'bottom'|'left'|'all'} which The border position.
|
|
330
|
+
// @returns {Array}
|
|
256
331
|
function reduceBorderPosition( value, which ) {
|
|
257
|
-
const
|
|
332
|
+
const borderTypes = [];
|
|
333
|
+
|
|
334
|
+
if ( value && value.width ) {
|
|
335
|
+
borderTypes.push( 'width' );
|
|
336
|
+
}
|
|
258
337
|
|
|
259
|
-
if ( value && value.
|
|
260
|
-
|
|
338
|
+
if ( value && value.style ) {
|
|
339
|
+
borderTypes.push( 'style' );
|
|
261
340
|
}
|
|
262
341
|
|
|
263
|
-
if ( value && value.
|
|
264
|
-
|
|
342
|
+
if ( value && value.color ) {
|
|
343
|
+
borderTypes.push( 'color' );
|
|
265
344
|
}
|
|
266
345
|
|
|
267
|
-
if (
|
|
268
|
-
|
|
346
|
+
if ( borderTypes.length == 3 ) {
|
|
347
|
+
const borderValue = borderTypes.map( item => value[ item ] ).join( ' ' );
|
|
348
|
+
|
|
349
|
+
return [
|
|
350
|
+
which == 'all' ? [ 'border', borderValue ] : [ `border-${ which }`, borderValue ]
|
|
351
|
+
];
|
|
269
352
|
}
|
|
270
353
|
|
|
271
|
-
|
|
272
|
-
|
|
354
|
+
// We are unable to reduce to a single `border:` property.
|
|
355
|
+
if ( which == 'all' ) {
|
|
356
|
+
return [];
|
|
273
357
|
}
|
|
274
358
|
|
|
275
|
-
return
|
|
359
|
+
return borderTypes.map( type => {
|
|
360
|
+
return [ `border-${ which }-${ type }`, value[ type ] ];
|
|
361
|
+
} );
|
|
276
362
|
}
|
package/src/view/styles/utils.js
CHANGED
|
@@ -220,7 +220,7 @@ export function getBoxSidesValueReducer( styleShorthand ) {
|
|
|
220
220
|
* // will return '1px 1px 2px'
|
|
221
221
|
*
|
|
222
222
|
* @param {module:engine/view/stylesmap~BoxSides} styleShorthand
|
|
223
|
-
* @returns {
|
|
223
|
+
* @returns {String}
|
|
224
224
|
*/
|
|
225
225
|
export function getBoxSidesShorthandValue( { top, right, bottom, left } ) {
|
|
226
226
|
const out = [];
|
package/src/view/stylesmap.js
CHANGED
|
@@ -25,7 +25,7 @@ export default class StylesMap {
|
|
|
25
25
|
* Keeps an internal representation of styles map. Normalized styles are kept as object tree to allow unified modification and
|
|
26
26
|
* value access model using lodash's get, set, unset, etc methods.
|
|
27
27
|
*
|
|
28
|
-
* When no style processor rules are defined
|
|
28
|
+
* When no style processor rules are defined it acts as simple key-value storage.
|
|
29
29
|
*
|
|
30
30
|
* @private
|
|
31
31
|
* @type {Object}
|
|
@@ -44,7 +44,7 @@ export default class StylesMap {
|
|
|
44
44
|
/**
|
|
45
45
|
* Returns true if style map has no styles set.
|
|
46
46
|
*
|
|
47
|
-
* @
|
|
47
|
+
* @type {Boolean}
|
|
48
48
|
*/
|
|
49
49
|
get isEmpty() {
|
|
50
50
|
const entries = Object.entries( this._styles );
|
|
@@ -350,15 +350,28 @@ export default class StylesMap {
|
|
|
350
350
|
}
|
|
351
351
|
|
|
352
352
|
/**
|
|
353
|
-
* Returns style
|
|
353
|
+
* Returns all style properties names as they would appear when using {@link #toString `#toString()`}.
|
|
354
|
+
*
|
|
355
|
+
* When `expand` is set to true and there's a shorthand style property set, it will also return all equivalent styles:
|
|
356
|
+
*
|
|
357
|
+
* stylesMap.setTo( 'margin: 1em' )
|
|
358
|
+
*
|
|
359
|
+
* will be expanded to:
|
|
360
|
+
*
|
|
361
|
+
* [ 'margin', 'margin-top', 'margin-right', 'margin-bottom', 'margin-left' ]
|
|
354
362
|
*
|
|
363
|
+
* @param {Boolean} [expand=false] Expand shorthand style properties and all return equivalent style representations.
|
|
355
364
|
* @returns {Array.<String>}
|
|
356
365
|
*/
|
|
357
|
-
getStyleNames() {
|
|
366
|
+
getStyleNames( expand = false ) {
|
|
358
367
|
if ( this.isEmpty ) {
|
|
359
368
|
return [];
|
|
360
369
|
}
|
|
361
370
|
|
|
371
|
+
if ( expand ) {
|
|
372
|
+
return this._styleProcessor.getStyleNames( this._styles );
|
|
373
|
+
}
|
|
374
|
+
|
|
362
375
|
const entries = this._getStylesEntries();
|
|
363
376
|
|
|
364
377
|
return entries.map( ( [ key ] ) => key );
|
|
@@ -540,7 +553,6 @@ export class StylesProcessor {
|
|
|
540
553
|
*
|
|
541
554
|
* **Note**: To define reducer callbacks use {@link #setReducer}.
|
|
542
555
|
*
|
|
543
|
-
* @param {String} name
|
|
544
556
|
* @param {String} name Name of style property.
|
|
545
557
|
* @param {Object} styles Object holding normalized styles.
|
|
546
558
|
* @returns {Array.<module:engine/view/stylesmap~PropertyDescriptor>}
|
|
@@ -562,6 +574,34 @@ export class StylesProcessor {
|
|
|
562
574
|
return [ [ name, normalizedValue ] ];
|
|
563
575
|
}
|
|
564
576
|
|
|
577
|
+
/**
|
|
578
|
+
* Return all style properties. Also expand shorthand properties (e.g. `margin`, `background`) if respective extractor is available.
|
|
579
|
+
*
|
|
580
|
+
* @param {Object} styles Object holding normalized styles.
|
|
581
|
+
* @returns {Array.<String>}
|
|
582
|
+
*/
|
|
583
|
+
getStyleNames( styles ) {
|
|
584
|
+
// Find all extractable styles that have a value.
|
|
585
|
+
const expandedStyleNames = Array.from( this._consumables.keys() ).filter( name => {
|
|
586
|
+
const style = this.getNormalized( name, styles );
|
|
587
|
+
|
|
588
|
+
if ( style && typeof style == 'object' ) {
|
|
589
|
+
return Object.keys( style ).length;
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
return style;
|
|
593
|
+
} );
|
|
594
|
+
|
|
595
|
+
// For simple styles (for example `color`) we don't have a map of those styles
|
|
596
|
+
// but they are 1 to 1 with normalized object keys.
|
|
597
|
+
const styleNamesKeysSet = new Set( [
|
|
598
|
+
...expandedStyleNames,
|
|
599
|
+
...Object.keys( styles )
|
|
600
|
+
] );
|
|
601
|
+
|
|
602
|
+
return Array.from( styleNamesKeysSet.values() );
|
|
603
|
+
}
|
|
604
|
+
|
|
565
605
|
/**
|
|
566
606
|
* Returns related style names.
|
|
567
607
|
*
|
package/src/view/upcastwriter.js
CHANGED
|
@@ -222,7 +222,7 @@ export default class UpcastWriter {
|
|
|
222
222
|
/**
|
|
223
223
|
* Adds or overwrites element's attribute with a specified key and value.
|
|
224
224
|
*
|
|
225
|
-
* writer.setAttribute(
|
|
225
|
+
* writer.setAttribute( 'href', 'http://ckeditor.com', linkElement );
|
|
226
226
|
*
|
|
227
227
|
* @see module:engine/view/element~Element#_setAttribute
|
|
228
228
|
* @param {String} key Attribute key.
|
|
@@ -236,7 +236,7 @@ export default class UpcastWriter {
|
|
|
236
236
|
/**
|
|
237
237
|
* Removes attribute from the element.
|
|
238
238
|
*
|
|
239
|
-
* writer.removeAttribute(
|
|
239
|
+
* writer.removeAttribute( 'href', linkElement );
|
|
240
240
|
*
|
|
241
241
|
* @see module:engine/view/element~Element#_removeAttribute
|
|
242
242
|
* @param {String} key Attribute key.
|
|
@@ -249,8 +249,8 @@ export default class UpcastWriter {
|
|
|
249
249
|
/**
|
|
250
250
|
* Adds specified class to the element.
|
|
251
251
|
*
|
|
252
|
-
* writer.addClass(
|
|
253
|
-
* writer.addClass(
|
|
252
|
+
* writer.addClass( 'foo', linkElement );
|
|
253
|
+
* writer.addClass( [ 'foo', 'bar' ], linkElement );
|
|
254
254
|
*
|
|
255
255
|
* @see module:engine/view/element~Element#_addClass
|
|
256
256
|
* @param {Array.<String>|String} className Single class name or array of class names which will be added.
|
|
@@ -263,8 +263,8 @@ export default class UpcastWriter {
|
|
|
263
263
|
/**
|
|
264
264
|
* Removes specified class from the element.
|
|
265
265
|
*
|
|
266
|
-
* writer.removeClass(
|
|
267
|
-
* writer.removeClass(
|
|
266
|
+
* writer.removeClass( 'foo', linkElement );
|
|
267
|
+
* writer.removeClass( [ 'foo', 'bar' ], linkElement );
|
|
268
268
|
*
|
|
269
269
|
* @see module:engine/view/element~Element#_removeClass
|
|
270
270
|
* @param {Array.<String>|String} className Single class name or array of class names which will be removed.
|
|
@@ -277,11 +277,11 @@ export default class UpcastWriter {
|
|
|
277
277
|
/**
|
|
278
278
|
* Adds style to the element.
|
|
279
279
|
*
|
|
280
|
-
* writer.setStyle(
|
|
281
|
-
* writer.setStyle(
|
|
280
|
+
* writer.setStyle( 'color', 'red', element );
|
|
281
|
+
* writer.setStyle( {
|
|
282
282
|
* color: 'red',
|
|
283
283
|
* position: 'fixed'
|
|
284
|
-
* } );
|
|
284
|
+
* }, element );
|
|
285
285
|
*
|
|
286
286
|
* **Note**: This method can work with normalized style names if
|
|
287
287
|
* {@link module:engine/controller/datacontroller~DataController#addStyleProcessorRules a particular style processor rule is enabled}.
|
|
@@ -302,8 +302,8 @@ export default class UpcastWriter {
|
|
|
302
302
|
/**
|
|
303
303
|
* Removes specified style from the element.
|
|
304
304
|
*
|
|
305
|
-
* writer.removeStyle(
|
|
306
|
-
* writer.removeStyle(
|
|
305
|
+
* writer.removeStyle( 'color', element ); // Removes 'color' style.
|
|
306
|
+
* writer.removeStyle( [ 'color', 'border-top' ], element ); // Removes both 'color' and 'border-top' styles.
|
|
307
307
|
*
|
|
308
308
|
* **Note**: This method can work with normalized style names if
|
|
309
309
|
* {@link module:engine/controller/datacontroller~DataController#addStyleProcessorRules a particular style processor rule is enabled}.
|
|
@@ -358,6 +358,7 @@ export default class UpcastWriter {
|
|
|
358
358
|
* @param {module:engine/view/item~Item|module:engine/model/position~Position} itemOrPosition
|
|
359
359
|
* @param {Number|'end'|'before'|'after'} [offset] Offset or one of the flags. Used only when
|
|
360
360
|
* first parameter is a {@link module:engine/view/item~Item view item}.
|
|
361
|
+
* @returns {module:engine/view/position~Position}
|
|
361
362
|
*/
|
|
362
363
|
createPositionAt( itemOrPosition, offset ) {
|
|
363
364
|
return Position._createAt( itemOrPosition, offset );
|
package/src/view/view.js
CHANGED
|
@@ -210,6 +210,11 @@ export default class View {
|
|
|
210
210
|
this.listenTo( this.document.selection, 'change', () => {
|
|
211
211
|
this._hasChangedSinceTheLastRendering = true;
|
|
212
212
|
} );
|
|
213
|
+
|
|
214
|
+
// Trigger re-render if only the focus changed.
|
|
215
|
+
this.listenTo( this.document, 'change:isFocused', () => {
|
|
216
|
+
this._hasChangedSinceTheLastRendering = true;
|
|
217
|
+
} );
|
|
213
218
|
}
|
|
214
219
|
|
|
215
220
|
/**
|