@ckeditor/ckeditor5-html-support 36.0.1 → 37.0.0-alpha.1

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.
Files changed (50) hide show
  1. package/README.md +2 -2
  2. package/build/html-support.js +1 -1
  3. package/ckeditor5-metadata.json +2 -2
  4. package/package.json +42 -36
  5. package/src/augmentation.d.ts +33 -0
  6. package/src/augmentation.js +5 -0
  7. package/src/conversionutils.d.ts +42 -0
  8. package/src/conversionutils.js +57 -77
  9. package/src/converters.d.ts +56 -0
  10. package/src/converters.js +104 -156
  11. package/src/datafilter.d.ts +250 -0
  12. package/src/datafilter.js +566 -782
  13. package/src/dataschema.d.ts +169 -0
  14. package/src/dataschema.js +143 -229
  15. package/src/fullpage.d.ts +21 -0
  16. package/src/fullpage.js +65 -86
  17. package/src/generalhtmlsupport.d.ts +88 -0
  18. package/src/generalhtmlsupport.js +244 -327
  19. package/src/generalhtmlsupportconfig.d.ts +67 -0
  20. package/src/generalhtmlsupportconfig.js +5 -0
  21. package/src/htmlcomment.d.ts +72 -0
  22. package/src/htmlcomment.js +175 -239
  23. package/src/htmlpagedataprocessor.d.ts +22 -0
  24. package/src/htmlpagedataprocessor.js +53 -76
  25. package/src/index.d.ts +25 -0
  26. package/src/index.js +1 -2
  27. package/src/integrations/codeblock.d.ts +22 -0
  28. package/src/integrations/codeblock.js +87 -115
  29. package/src/integrations/customelement.d.ts +25 -0
  30. package/src/integrations/customelement.js +127 -160
  31. package/src/integrations/documentlist.d.ts +26 -0
  32. package/src/integrations/documentlist.js +154 -191
  33. package/src/integrations/dualcontent.d.ts +44 -0
  34. package/src/integrations/dualcontent.js +92 -128
  35. package/src/integrations/heading.d.ts +25 -0
  36. package/src/integrations/heading.js +41 -54
  37. package/src/integrations/image.d.ts +25 -0
  38. package/src/integrations/image.js +154 -212
  39. package/src/integrations/integrationutils.d.ts +15 -0
  40. package/src/integrations/integrationutils.js +21 -0
  41. package/src/integrations/mediaembed.d.ts +25 -0
  42. package/src/integrations/mediaembed.js +101 -147
  43. package/src/integrations/script.d.ts +25 -0
  44. package/src/integrations/script.js +45 -67
  45. package/src/integrations/style.d.ts +25 -0
  46. package/src/integrations/style.js +45 -67
  47. package/src/integrations/table.d.ts +22 -0
  48. package/src/integrations/table.js +113 -160
  49. package/src/schemadefinitions.d.ts +13 -0
  50. package/src/schemadefinitions.js +846 -835
@@ -2,100 +2,80 @@
2
2
  * @license Copyright (c) 2003-2023, 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
-
6
- /**
7
- * @module html-support/conversionutils
8
- */
9
-
10
5
  import { cloneDeep } from 'lodash-es';
11
-
12
6
  /**
13
7
  * Helper function for the downcast converter. Updates attributes on the given view element.
14
8
  *
15
- * @param {module:engine/view/downcastwriter~DowncastWriter} writer The view writer.
16
- * @param {Object} oldViewAttributes The previous GHS attribute value.
17
- * @param {Object} newViewAttributes The current GHS attribute value.
18
- * @param {module:engine/view/element~Element} viewElement The view element to update.
9
+ * @param writer The view writer.
10
+ * @param oldViewAttributes The previous GHS attribute value.
11
+ * @param newViewAttributes The current GHS attribute value.
12
+ * @param viewElement The view element to update.
19
13
  */
20
- export function updateViewAttributes( writer, oldViewAttributes, newViewAttributes, viewElement ) {
21
- if ( oldViewAttributes ) {
22
- removeViewAttributes( writer, oldViewAttributes, viewElement );
23
- }
24
-
25
- if ( newViewAttributes ) {
26
- setViewAttributes( writer, newViewAttributes, viewElement );
27
- }
14
+ export function updateViewAttributes(writer, oldViewAttributes, newViewAttributes, viewElement) {
15
+ if (oldViewAttributes) {
16
+ removeViewAttributes(writer, oldViewAttributes, viewElement);
17
+ }
18
+ if (newViewAttributes) {
19
+ setViewAttributes(writer, newViewAttributes, viewElement);
20
+ }
28
21
  }
29
-
30
22
  /**
31
23
  * Helper function for the downcast converter. Sets attributes on the given view element.
32
24
  *
33
- * @param {module:engine/view/downcastwriter~DowncastWriter} writer The view writer.
34
- * @param {Object} viewAttributes The GHS attribute value.
35
- * @param {module:engine/view/element~Element} viewElement The view element to update.
25
+ * @param writer The view writer.
26
+ * @param viewAttributes The GHS attribute value.
27
+ * @param viewElement The view element to update.
36
28
  */
37
- export function setViewAttributes( writer, viewAttributes, viewElement ) {
38
- if ( viewAttributes.attributes ) {
39
- for ( const [ key, value ] of Object.entries( viewAttributes.attributes ) ) {
40
- writer.setAttribute( key, value, viewElement );
41
- }
42
- }
43
-
44
- if ( viewAttributes.styles ) {
45
- writer.setStyle( viewAttributes.styles, viewElement );
46
- }
47
-
48
- if ( viewAttributes.classes ) {
49
- writer.addClass( viewAttributes.classes, viewElement );
50
- }
29
+ export function setViewAttributes(writer, viewAttributes, viewElement) {
30
+ if (viewAttributes.attributes) {
31
+ for (const [key, value] of Object.entries(viewAttributes.attributes)) {
32
+ writer.setAttribute(key, value, viewElement);
33
+ }
34
+ }
35
+ if (viewAttributes.styles) {
36
+ writer.setStyle(viewAttributes.styles, viewElement);
37
+ }
38
+ if (viewAttributes.classes) {
39
+ writer.addClass(viewAttributes.classes, viewElement);
40
+ }
51
41
  }
52
-
53
42
  /**
54
43
  * Helper function for the downcast converter. Removes attributes on the given view element.
55
44
  *
56
- * @param {module:engine/view/downcastwriter~DowncastWriter} writer The view writer.
57
- * @param {Object} viewAttributes The GHS attribute value.
58
- * @param {module:engine/view/element~Element} viewElement The view element to update.
45
+ * @param writer The view writer.
46
+ * @param viewAttributes The GHS attribute value.
47
+ * @param viewElement The view element to update.
59
48
  */
60
- export function removeViewAttributes( writer, viewAttributes, viewElement ) {
61
- if ( viewAttributes.attributes ) {
62
- for ( const [ key ] of Object.entries( viewAttributes.attributes ) ) {
63
- writer.removeAttribute( key, viewElement );
64
- }
65
- }
66
-
67
- if ( viewAttributes.styles ) {
68
- for ( const style of Object.keys( viewAttributes.styles ) ) {
69
- writer.removeStyle( style, viewElement );
70
- }
71
- }
72
-
73
- if ( viewAttributes.classes ) {
74
- writer.removeClass( viewAttributes.classes, viewElement );
75
- }
49
+ export function removeViewAttributes(writer, viewAttributes, viewElement) {
50
+ if (viewAttributes.attributes) {
51
+ for (const [key] of Object.entries(viewAttributes.attributes)) {
52
+ writer.removeAttribute(key, viewElement);
53
+ }
54
+ }
55
+ if (viewAttributes.styles) {
56
+ for (const style of Object.keys(viewAttributes.styles)) {
57
+ writer.removeStyle(style, viewElement);
58
+ }
59
+ }
60
+ if (viewAttributes.classes) {
61
+ writer.removeClass(viewAttributes.classes, viewElement);
62
+ }
76
63
  }
77
-
78
64
  /**
79
65
  * Merges view element attribute objects.
80
- *
81
- * @param {Object} target
82
- * @param {Object} source
83
- * @returns {Object}
84
66
  */
85
- export function mergeViewElementAttributes( target, source ) {
86
- const result = cloneDeep( target );
87
-
88
- for ( const key in source ) {
89
- // Merge classes.
90
- if ( Array.isArray( source[ key ] ) ) {
91
- result[ key ] = Array.from( new Set( [ ...( target[ key ] || [] ), ...source[ key ] ] ) );
92
- }
93
-
94
- // Merge attributes or styles.
95
- else {
96
- result[ key ] = { ...target[ key ], ...source[ key ] };
97
- }
98
- }
99
-
100
- return result;
67
+ export function mergeViewElementAttributes(target, source) {
68
+ const result = cloneDeep(target);
69
+ let key = 'attributes';
70
+ for (key in source) {
71
+ // Merge classes.
72
+ if (key == 'classes') {
73
+ result[key] = Array.from(new Set([...(target[key] || []), ...source[key]]));
74
+ }
75
+ // Merge attributes or styles.
76
+ else {
77
+ result[key] = { ...target[key], ...source[key] };
78
+ }
79
+ }
80
+ return result;
101
81
  }
@@ -0,0 +1,56 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ /**
6
+ * @module html-support/converters
7
+ */
8
+ import type { Editor } from 'ckeditor5/src/core';
9
+ import type { AttributeElement, DowncastConversionApi, DowncastDispatcher, DowncastWriter, Element, ElementCreatorFunction, UpcastConversionApi, UpcastDispatcher, ViewElement } from 'ckeditor5/src/engine';
10
+ import type DataFilter from './datafilter';
11
+ import type { DataSchemaBlockElementDefinition, DataSchemaDefinition, DataSchemaInlineElementDefinition } from './dataschema';
12
+ /**
13
+ * View-to-model conversion helper for object elements.
14
+ *
15
+ * Preserves object element content in `htmlContent` attribute.
16
+ *
17
+ * @returns Returns a conversion callback.
18
+ */
19
+ export declare function viewToModelObjectConverter({ model: modelName }: DataSchemaDefinition): (viewElement: ViewElement, conversionApi: UpcastConversionApi) => Element;
20
+ /**
21
+ * Conversion helper converting an object element to an HTML object widget.
22
+ *
23
+ * @returns Returns a conversion callback.
24
+ */
25
+ export declare function toObjectWidgetConverter(editor: Editor, { view: viewName, isInline }: DataSchemaInlineElementDefinition): ElementCreatorFunction;
26
+ /**
27
+ * Creates object view element from the given model element.
28
+ */
29
+ export declare function createObjectView(viewName: string, modelElement: Element, writer: DowncastWriter): ViewElement;
30
+ /**
31
+ * View-to-attribute conversion helper preserving inline element attributes on `$text`.
32
+ *
33
+ * @returns Returns a conversion callback.
34
+ */
35
+ export declare function viewToAttributeInlineConverter({ view: viewName, model: attributeKey }: DataSchemaInlineElementDefinition, dataFilter: DataFilter): (dispatcher: UpcastDispatcher) => void;
36
+ /**
37
+ * Attribute-to-view conversion helper applying attributes to view element preserved on `$text`.
38
+ *
39
+ * @returns Returns a conversion callback.
40
+ */
41
+ export declare function attributeToViewInlineConverter({ priority, view: viewName }: DataSchemaInlineElementDefinition): (attributeValue: any, conversionApi: DowncastConversionApi) => AttributeElement | undefined;
42
+ /**
43
+ * View-to-model conversion helper preserving allowed attributes on block element.
44
+ *
45
+ * All matched attributes will be preserved on `htmlAttributes` attribute.
46
+ *
47
+ * @returns Returns a conversion callback.
48
+ */
49
+ export declare function viewToModelBlockAttributeConverter({ view: viewName }: DataSchemaBlockElementDefinition, dataFilter: DataFilter): (dispatcher: UpcastDispatcher) => void;
50
+ /**
51
+ * Model-to-view conversion helper applying attributes preserved in `htmlAttributes` attribute
52
+ * for block elements.
53
+ *
54
+ * @returns Returns a conversion callback.
55
+ */
56
+ export declare function modelToViewBlockAttributeConverter({ model: modelName }: DataSchemaBlockElementDefinition): (dispatcher: DowncastDispatcher) => void;
package/src/converters.js CHANGED
@@ -2,199 +2,147 @@
2
2
  * @license Copyright (c) 2003-2023, 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
-
6
- /**
7
- * @module html-support/converters
8
- */
9
-
10
5
  import { toWidget } from 'ckeditor5/src/widget';
11
- import {
12
- setViewAttributes,
13
- mergeViewElementAttributes,
14
- updateViewAttributes
15
- } from './conversionutils';
16
-
6
+ import { setViewAttributes, mergeViewElementAttributes, updateViewAttributes } from './conversionutils';
17
7
  /**
18
8
  * View-to-model conversion helper for object elements.
19
9
  *
20
10
  * Preserves object element content in `htmlContent` attribute.
21
11
  *
22
- * @param {module:html-support/dataschema~DataSchemaDefinition} definition
23
- * @returns {Function} Returns a conversion callback.
12
+ * @returns Returns a conversion callback.
24
13
  */
25
- export function viewToModelObjectConverter( { model: modelName } ) {
26
- return ( viewElement, conversionApi ) => {
27
- // Let's keep element HTML and its attributes, so we can rebuild element in downcast conversions.
28
- return conversionApi.writer.createElement( modelName, {
29
- htmlContent: viewElement.getCustomProperty( '$rawContent' )
30
- } );
31
- };
14
+ export function viewToModelObjectConverter({ model: modelName }) {
15
+ return (viewElement, conversionApi) => {
16
+ // Let's keep element HTML and its attributes, so we can rebuild element in downcast conversions.
17
+ return conversionApi.writer.createElement(modelName, {
18
+ htmlContent: viewElement.getCustomProperty('$rawContent')
19
+ });
20
+ };
32
21
  }
33
-
34
22
  /**
35
23
  * Conversion helper converting an object element to an HTML object widget.
36
24
  *
37
- * @param {module:core/editor/editor~Editor} editor
38
- * @param {module:html-support/dataschema~DataSchemaInlineElementDefinition} definition
39
- * @returns {Function} Returns a conversion callback.
25
+ * @returns Returns a conversion callback.
40
26
  */
41
- export function toObjectWidgetConverter( editor, { view: viewName, isInline } ) {
42
- const t = editor.t;
43
-
44
- return ( modelElement, { writer } ) => {
45
- const widgetLabel = t( 'HTML object' );
46
-
47
- const viewElement = createObjectView( viewName, modelElement, writer );
48
- const viewAttributes = modelElement.getAttribute( 'htmlAttributes' );
49
-
50
- writer.addClass( 'html-object-embed__content', viewElement );
51
-
52
- if ( viewAttributes ) {
53
- setViewAttributes( writer, viewAttributes, viewElement );
54
- }
55
-
56
- // Widget cannot be a raw element because the widget system would not be able
57
- // to add its UI to it. Thus, we need separate view container.
58
- const viewContainer = writer.createContainerElement( isInline ? 'span' : 'div',
59
- {
60
- class: 'html-object-embed',
61
- 'data-html-object-embed-label': widgetLabel
62
- },
63
- viewElement
64
- );
65
-
66
- return toWidget( viewContainer, writer, { widgetLabel } );
67
- };
27
+ export function toObjectWidgetConverter(editor, { view: viewName, isInline }) {
28
+ const t = editor.t;
29
+ return (modelElement, { writer }) => {
30
+ const widgetLabel = t('HTML object');
31
+ const viewElement = createObjectView(viewName, modelElement, writer);
32
+ const viewAttributes = modelElement.getAttribute('htmlAttributes');
33
+ writer.addClass('html-object-embed__content', viewElement);
34
+ if (viewAttributes) {
35
+ setViewAttributes(writer, viewAttributes, viewElement);
36
+ }
37
+ // Widget cannot be a raw element because the widget system would not be able
38
+ // to add its UI to it. Thus, we need separate view container.
39
+ const viewContainer = writer.createContainerElement(isInline ? 'span' : 'div', {
40
+ class: 'html-object-embed',
41
+ 'data-html-object-embed-label': widgetLabel
42
+ }, viewElement);
43
+ return toWidget(viewContainer, writer, { label: widgetLabel });
44
+ };
68
45
  }
69
-
70
46
  /**
71
47
  * Creates object view element from the given model element.
72
- *
73
- * @param {String} viewName
74
- * @param {module:engine/model/element~Element} modelElement
75
- * @param {module:engine/view/downcastwriter~DowncastWriter} writer
76
- * @returns {module:engine/view/element~Element}
77
48
  */
78
- export function createObjectView( viewName, modelElement, writer ) {
79
- return writer.createRawElement( viewName, null, ( domElement, domConverter ) => {
80
- domConverter.setContentOf( domElement, modelElement.getAttribute( 'htmlContent' ) );
81
- } );
49
+ export function createObjectView(viewName, modelElement, writer) {
50
+ return writer.createRawElement(viewName, null, (domElement, domConverter) => {
51
+ domConverter.setContentOf(domElement, modelElement.getAttribute('htmlContent'));
52
+ });
82
53
  }
83
-
84
54
  /**
85
55
  * View-to-attribute conversion helper preserving inline element attributes on `$text`.
86
56
  *
87
- * @param {module:html-support/dataschema~DataSchemaInlineElementDefinition} definition
88
- * @param {module:html-support/datafilter~DataFilter} dataFilter
89
- * @returns {Function} Returns a conversion callback.
57
+ * @returns Returns a conversion callback.
90
58
  */
91
- export function viewToAttributeInlineConverter( { view: viewName, model: attributeKey }, dataFilter ) {
92
- return dispatcher => {
93
- dispatcher.on( `element:${ viewName }`, ( evt, data, conversionApi ) => {
94
- let viewAttributes = dataFilter.processViewAttributes( data.viewItem, conversionApi );
95
-
96
- // Do not apply the attribute if the element itself is already consumed and there are no view attributes to store.
97
- if ( !viewAttributes && !conversionApi.consumable.test( data.viewItem, { name: true } ) ) {
98
- return;
99
- }
100
-
101
- // Otherwise, we might need to convert it to an empty object just to preserve element itself,
102
- // for example `<cite>` => <$text htmlCite="{}">.
103
- viewAttributes = viewAttributes || {};
104
-
105
- // Consume the element itself if it wasn't consumed by any other converter.
106
- conversionApi.consumable.consume( data.viewItem, { name: true } );
107
-
108
- // Since we are converting to attribute we need a range on which we will set the attribute.
109
- // If the range is not created yet, we will create it.
110
- if ( !data.modelRange ) {
111
- data = Object.assign( data, conversionApi.convertChildren( data.viewItem, data.modelCursor ) );
112
- }
113
-
114
- // Set attribute on each item in range according to the schema.
115
- for ( const node of data.modelRange.getItems() ) {
116
- if ( conversionApi.schema.checkAttribute( node, attributeKey ) ) {
117
- // Node's children are converted recursively, so node can already include model attribute.
118
- // We want to extend it, not replace.
119
- const nodeAttributes = node.getAttribute( attributeKey );
120
- const attributesToAdd = mergeViewElementAttributes( viewAttributes, nodeAttributes || {} );
121
-
122
- conversionApi.writer.setAttribute( attributeKey, attributesToAdd, node );
123
- }
124
- }
125
- }, { priority: 'low' } );
126
- };
59
+ export function viewToAttributeInlineConverter({ view: viewName, model: attributeKey }, dataFilter) {
60
+ return (dispatcher) => {
61
+ dispatcher.on(`element:${viewName}`, (evt, data, conversionApi) => {
62
+ let viewAttributes = dataFilter.processViewAttributes(data.viewItem, conversionApi);
63
+ // Do not apply the attribute if the element itself is already consumed and there are no view attributes to store.
64
+ if (!viewAttributes && !conversionApi.consumable.test(data.viewItem, { name: true })) {
65
+ return;
66
+ }
67
+ // Otherwise, we might need to convert it to an empty object just to preserve element itself,
68
+ // for example `<cite>` => <$text htmlCite="{}">.
69
+ viewAttributes = viewAttributes || {};
70
+ // Consume the element itself if it wasn't consumed by any other converter.
71
+ conversionApi.consumable.consume(data.viewItem, { name: true });
72
+ // Since we are converting to attribute we need a range on which we will set the attribute.
73
+ // If the range is not created yet, we will create it.
74
+ if (!data.modelRange) {
75
+ data = Object.assign(data, conversionApi.convertChildren(data.viewItem, data.modelCursor));
76
+ }
77
+ // Set attribute on each item in range according to the schema.
78
+ for (const node of data.modelRange.getItems()) {
79
+ if (conversionApi.schema.checkAttribute(node, attributeKey)) {
80
+ // Node's children are converted recursively, so node can already include model attribute.
81
+ // We want to extend it, not replace.
82
+ const nodeAttributes = node.getAttribute(attributeKey);
83
+ const attributesToAdd = mergeViewElementAttributes(viewAttributes, nodeAttributes || {});
84
+ conversionApi.writer.setAttribute(attributeKey, attributesToAdd, node);
85
+ }
86
+ }
87
+ }, { priority: 'low' });
88
+ };
127
89
  }
128
-
129
90
  /**
130
91
  * Attribute-to-view conversion helper applying attributes to view element preserved on `$text`.
131
92
  *
132
- * @param {module:html-support/dataschema~DataSchemaInlineElementDefinition} definition
133
- * @returns {Function} Returns a conversion callback.
93
+ * @returns Returns a conversion callback.
134
94
  */
135
- export function attributeToViewInlineConverter( { priority, view: viewName } ) {
136
- return ( attributeValue, conversionApi ) => {
137
- if ( !attributeValue ) {
138
- return;
139
- }
140
-
141
- const { writer } = conversionApi;
142
- const viewElement = writer.createAttributeElement( viewName, null, { priority } );
143
-
144
- setViewAttributes( writer, attributeValue, viewElement );
145
-
146
- return viewElement;
147
- };
95
+ export function attributeToViewInlineConverter({ priority, view: viewName }) {
96
+ return (attributeValue, conversionApi) => {
97
+ if (!attributeValue) {
98
+ return;
99
+ }
100
+ const { writer } = conversionApi;
101
+ const viewElement = writer.createAttributeElement(viewName, null, { priority });
102
+ setViewAttributes(writer, attributeValue, viewElement);
103
+ return viewElement;
104
+ };
148
105
  }
149
-
150
106
  /**
151
107
  * View-to-model conversion helper preserving allowed attributes on block element.
152
108
  *
153
109
  * All matched attributes will be preserved on `htmlAttributes` attribute.
154
110
  *
155
- * @param {module:html-support/dataschema~DataSchemaBlockElementDefinition} definition
156
- * @param {module:html-support/datafilter~DataFilter} dataFilter
157
- * @returns {Function} Returns a conversion callback.
111
+ * @returns Returns a conversion callback.
158
112
  */
159
- export function viewToModelBlockAttributeConverter( { view: viewName }, dataFilter ) {
160
- return dispatcher => {
161
- dispatcher.on( `element:${ viewName }`, ( evt, data, conversionApi ) => {
162
- // Converting an attribute of an element that has not been converted to anything does not make sense
163
- // because there will be nowhere to set that attribute on. At this stage, the element should've already
164
- // been converted. A collapsed range can show up in to-do lists (<input>) or complex widgets (e.g. table).
165
- // (https://github.com/ckeditor/ckeditor5/issues/11000).
166
- if ( !data.modelRange || data.modelRange.isCollapsed ) {
167
- return;
168
- }
169
-
170
- const viewAttributes = dataFilter.processViewAttributes( data.viewItem, conversionApi );
171
-
172
- if ( viewAttributes ) {
173
- conversionApi.writer.setAttribute( 'htmlAttributes', viewAttributes, data.modelRange );
174
- }
175
- }, { priority: 'low' } );
176
- };
113
+ export function viewToModelBlockAttributeConverter({ view: viewName }, dataFilter) {
114
+ return (dispatcher) => {
115
+ dispatcher.on(`element:${viewName}`, (evt, data, conversionApi) => {
116
+ // Converting an attribute of an element that has not been converted to anything does not make sense
117
+ // because there will be nowhere to set that attribute on. At this stage, the element should've already
118
+ // been converted. A collapsed range can show up in to-do lists (<input>) or complex widgets (e.g. table).
119
+ // (https://github.com/ckeditor/ckeditor5/issues/11000).
120
+ if (!data.modelRange || data.modelRange.isCollapsed) {
121
+ return;
122
+ }
123
+ const viewAttributes = dataFilter.processViewAttributes(data.viewItem, conversionApi);
124
+ if (viewAttributes) {
125
+ conversionApi.writer.setAttribute('htmlAttributes', viewAttributes, data.modelRange);
126
+ }
127
+ }, { priority: 'low' });
128
+ };
177
129
  }
178
-
179
130
  /**
180
131
  * Model-to-view conversion helper applying attributes preserved in `htmlAttributes` attribute
181
132
  * for block elements.
182
133
  *
183
- * @param {module:html-support/dataschema~DataSchemaBlockElementDefinition} definition
184
- * @returns {Function} Returns a conversion callback.
134
+ * @returns Returns a conversion callback.
185
135
  */
186
- export function modelToViewBlockAttributeConverter( { model: modelName } ) {
187
- return dispatcher => {
188
- dispatcher.on( `attribute:htmlAttributes:${ modelName }`, ( evt, data, conversionApi ) => {
189
- if ( !conversionApi.consumable.consume( data.item, evt.name ) ) {
190
- return;
191
- }
192
-
193
- const { attributeOldValue, attributeNewValue } = data;
194
- const viewWriter = conversionApi.writer;
195
- const viewElement = conversionApi.mapper.toViewElement( data.item );
196
-
197
- updateViewAttributes( viewWriter, attributeOldValue, attributeNewValue, viewElement );
198
- } );
199
- };
136
+ export function modelToViewBlockAttributeConverter({ model: modelName }) {
137
+ return (dispatcher) => {
138
+ dispatcher.on(`attribute:htmlAttributes:${modelName}`, (evt, data, conversionApi) => {
139
+ if (!conversionApi.consumable.consume(data.item, evt.name)) {
140
+ return;
141
+ }
142
+ const { attributeOldValue, attributeNewValue } = data;
143
+ const viewWriter = conversionApi.writer;
144
+ const viewElement = conversionApi.mapper.toViewElement(data.item);
145
+ updateViewAttributes(viewWriter, attributeOldValue, attributeNewValue, viewElement);
146
+ });
147
+ };
200
148
  }