@ckeditor/ckeditor5-html-support 33.0.0 → 34.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/README.md +2 -1
- package/build/html-support.js +1 -1
- package/build/html-support.js.map +1 -1
- package/build/translations/en-au.js +1 -0
- package/build/translations/hr.js +1 -0
- package/build/translations/jv.js +1 -0
- package/lang/translations/en-au.po +21 -0
- package/lang/translations/hr.po +21 -0
- package/lang/translations/jv.po +21 -0
- package/package.json +31 -31
- package/src/conversionutils.js +48 -5
- package/src/converters.js +18 -12
- package/src/datafilter.js +7 -1
- package/src/generalhtmlsupport.js +229 -1
- package/src/integrations/codeblock.js +5 -3
- package/src/integrations/documentlist.js +200 -0
- package/src/integrations/image.js +28 -17
- package/src/integrations/mediaembed.js +3 -2
- package/src/schemadefinitions.js +47 -66
- package/theme/datafilter.css +5 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
!function(n){const i=n["en-au"]=n["en-au"]||{};i.dictionary=Object.assign(i.dictionary||{},{"HTML object":"HTML object"})}(window.CKEDITOR_TRANSLATIONS||(window.CKEDITOR_TRANSLATIONS={}));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
!function(i){const n=i.hr=i.hr||{};n.dictionary=Object.assign(n.dictionary||{},{"HTML object":"HTML objekt"})}(window.CKEDITOR_TRANSLATIONS||(window.CKEDITOR_TRANSLATIONS={}));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
!function(i){const n=i.jv=i.jv||{};n.dictionary=Object.assign(n.dictionary||{},{"HTML object":"Obyek HTML"})}(window.CKEDITOR_TRANSLATIONS||(window.CKEDITOR_TRANSLATIONS={}));
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
|
|
2
|
+
#
|
|
3
|
+
# !!! IMPORTANT !!!
|
|
4
|
+
#
|
|
5
|
+
# Before you edit this file, please keep in mind that contributing to the project
|
|
6
|
+
# translations is possible ONLY via the Transifex online service.
|
|
7
|
+
#
|
|
8
|
+
# To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
|
|
9
|
+
#
|
|
10
|
+
# To learn more, check out the official contributor's guide:
|
|
11
|
+
# https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
|
|
12
|
+
#
|
|
13
|
+
msgid ""
|
|
14
|
+
msgstr ""
|
|
15
|
+
"Language-Team: English (Australia) (https://www.transifex.com/ckeditor/teams/11143/en_AU/)\n"
|
|
16
|
+
"Language: en_AU\n"
|
|
17
|
+
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
|
18
|
+
|
|
19
|
+
msgctxt "A label describing an HTML object widget."
|
|
20
|
+
msgid "HTML object"
|
|
21
|
+
msgstr "HTML object"
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
|
|
2
|
+
#
|
|
3
|
+
# !!! IMPORTANT !!!
|
|
4
|
+
#
|
|
5
|
+
# Before you edit this file, please keep in mind that contributing to the project
|
|
6
|
+
# translations is possible ONLY via the Transifex online service.
|
|
7
|
+
#
|
|
8
|
+
# To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
|
|
9
|
+
#
|
|
10
|
+
# To learn more, check out the official contributor's guide:
|
|
11
|
+
# https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
|
|
12
|
+
#
|
|
13
|
+
msgid ""
|
|
14
|
+
msgstr ""
|
|
15
|
+
"Language-Team: Croatian (https://www.transifex.com/ckeditor/teams/11143/hr/)\n"
|
|
16
|
+
"Language: hr\n"
|
|
17
|
+
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
|
|
18
|
+
|
|
19
|
+
msgctxt "A label describing an HTML object widget."
|
|
20
|
+
msgid "HTML object"
|
|
21
|
+
msgstr "HTML objekt"
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Copyright (c) 2003-2022, CKSource Holding sp. z o.o. All rights reserved.
|
|
2
|
+
#
|
|
3
|
+
# !!! IMPORTANT !!!
|
|
4
|
+
#
|
|
5
|
+
# Before you edit this file, please keep in mind that contributing to the project
|
|
6
|
+
# translations is possible ONLY via the Transifex online service.
|
|
7
|
+
#
|
|
8
|
+
# To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
|
|
9
|
+
#
|
|
10
|
+
# To learn more, check out the official contributor's guide:
|
|
11
|
+
# https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
|
|
12
|
+
#
|
|
13
|
+
msgid ""
|
|
14
|
+
msgstr ""
|
|
15
|
+
"Language-Team: Javanese (https://www.transifex.com/ckeditor/teams/11143/jv/)\n"
|
|
16
|
+
"Language: jv\n"
|
|
17
|
+
"Plural-Forms: nplurals=1; plural=0;\n"
|
|
18
|
+
|
|
19
|
+
msgctxt "A label describing an HTML object widget."
|
|
20
|
+
msgid "HTML object"
|
|
21
|
+
msgstr "Obyek HTML"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ckeditor/ckeditor5-html-support",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "34.0.0",
|
|
4
4
|
"description": "HTML Support feature for CKEditor 5.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ckeditor",
|
|
@@ -16,39 +16,39 @@
|
|
|
16
16
|
],
|
|
17
17
|
"main": "src/index.js",
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"ckeditor5": "^
|
|
19
|
+
"ckeditor5": "^34.0.0",
|
|
20
20
|
"lodash-es": "^4.17.15"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
|
-
"@ckeditor/ckeditor5-alignment": "^
|
|
24
|
-
"@ckeditor/ckeditor5-basic-styles": "^
|
|
25
|
-
"@ckeditor/ckeditor5-block-quote": "^
|
|
26
|
-
"@ckeditor/ckeditor5-cloud-services": "^
|
|
27
|
-
"@ckeditor/ckeditor5-code-block": "^
|
|
28
|
-
"@ckeditor/ckeditor5-core": "^
|
|
29
|
-
"@ckeditor/ckeditor5-dev-utils": "^
|
|
30
|
-
"@ckeditor/ckeditor5-easy-image": "^
|
|
31
|
-
"@ckeditor/ckeditor5-editor-classic": "^
|
|
32
|
-
"@ckeditor/ckeditor5-engine": "^
|
|
33
|
-
"@ckeditor/ckeditor5-enter": "^
|
|
34
|
-
"@ckeditor/ckeditor5-essentials": "^
|
|
35
|
-
"@ckeditor/ckeditor5-font": "^
|
|
36
|
-
"@ckeditor/ckeditor5-heading": "^
|
|
37
|
-
"@ckeditor/ckeditor5-highlight": "^
|
|
38
|
-
"@ckeditor/ckeditor5-horizontal-line": "^
|
|
39
|
-
"@ckeditor/ckeditor5-html-embed": "^
|
|
40
|
-
"@ckeditor/ckeditor5-image": "^
|
|
41
|
-
"@ckeditor/ckeditor5-indent": "^
|
|
42
|
-
"@ckeditor/ckeditor5-link": "^
|
|
43
|
-
"@ckeditor/ckeditor5-list": "^
|
|
44
|
-
"@ckeditor/ckeditor5-media-embed": "^
|
|
45
|
-
"@ckeditor/ckeditor5-page-break": "^
|
|
46
|
-
"@ckeditor/ckeditor5-paragraph": "^
|
|
47
|
-
"@ckeditor/ckeditor5-paste-from-office": "^
|
|
48
|
-
"@ckeditor/ckeditor5-source-editing": "^
|
|
49
|
-
"@ckeditor/ckeditor5-table": "^
|
|
50
|
-
"@ckeditor/ckeditor5-theme-lark": "^
|
|
51
|
-
"@ckeditor/ckeditor5-utils": "^
|
|
23
|
+
"@ckeditor/ckeditor5-alignment": "^34.0.0",
|
|
24
|
+
"@ckeditor/ckeditor5-basic-styles": "^34.0.0",
|
|
25
|
+
"@ckeditor/ckeditor5-block-quote": "^34.0.0",
|
|
26
|
+
"@ckeditor/ckeditor5-cloud-services": "^34.0.0",
|
|
27
|
+
"@ckeditor/ckeditor5-code-block": "^34.0.0",
|
|
28
|
+
"@ckeditor/ckeditor5-core": "^34.0.0",
|
|
29
|
+
"@ckeditor/ckeditor5-dev-utils": "^30.0.0",
|
|
30
|
+
"@ckeditor/ckeditor5-easy-image": "^34.0.0",
|
|
31
|
+
"@ckeditor/ckeditor5-editor-classic": "^34.0.0",
|
|
32
|
+
"@ckeditor/ckeditor5-engine": "^34.0.0",
|
|
33
|
+
"@ckeditor/ckeditor5-enter": "^34.0.0",
|
|
34
|
+
"@ckeditor/ckeditor5-essentials": "^34.0.0",
|
|
35
|
+
"@ckeditor/ckeditor5-font": "^34.0.0",
|
|
36
|
+
"@ckeditor/ckeditor5-heading": "^34.0.0",
|
|
37
|
+
"@ckeditor/ckeditor5-highlight": "^34.0.0",
|
|
38
|
+
"@ckeditor/ckeditor5-horizontal-line": "^34.0.0",
|
|
39
|
+
"@ckeditor/ckeditor5-html-embed": "^34.0.0",
|
|
40
|
+
"@ckeditor/ckeditor5-image": "^34.0.0",
|
|
41
|
+
"@ckeditor/ckeditor5-indent": "^34.0.0",
|
|
42
|
+
"@ckeditor/ckeditor5-link": "^34.0.0",
|
|
43
|
+
"@ckeditor/ckeditor5-list": "^34.0.0",
|
|
44
|
+
"@ckeditor/ckeditor5-media-embed": "^34.0.0",
|
|
45
|
+
"@ckeditor/ckeditor5-page-break": "^34.0.0",
|
|
46
|
+
"@ckeditor/ckeditor5-paragraph": "^34.0.0",
|
|
47
|
+
"@ckeditor/ckeditor5-paste-from-office": "^34.0.0",
|
|
48
|
+
"@ckeditor/ckeditor5-source-editing": "^34.0.0",
|
|
49
|
+
"@ckeditor/ckeditor5-table": "^34.0.0",
|
|
50
|
+
"@ckeditor/ckeditor5-theme-lark": "^34.0.0",
|
|
51
|
+
"@ckeditor/ckeditor5-utils": "^34.0.0",
|
|
52
52
|
"webpack": "^5.58.1",
|
|
53
53
|
"webpack-cli": "^4.9.0"
|
|
54
54
|
},
|
package/src/conversionutils.js
CHANGED
|
@@ -10,12 +10,30 @@
|
|
|
10
10
|
import { cloneDeep } from 'lodash-es';
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
-
* Helper function for downcast converter.
|
|
13
|
+
* Helper function for the downcast converter. Updates attributes on the given view element.
|
|
14
14
|
*
|
|
15
|
-
* @param {module:engine/view/downcastwriter~DowncastWriter} writer
|
|
16
|
-
* @param {Object}
|
|
17
|
-
* @param {
|
|
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.
|
|
18
19
|
*/
|
|
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
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Helper function for the downcast converter. Sets attributes on the given view element.
|
|
32
|
+
*
|
|
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.
|
|
36
|
+
*/
|
|
19
37
|
export function setViewAttributes( writer, viewAttributes, viewElement ) {
|
|
20
38
|
if ( viewAttributes.attributes ) {
|
|
21
39
|
for ( const [ key, value ] of Object.entries( viewAttributes.attributes ) ) {
|
|
@@ -32,6 +50,31 @@ export function setViewAttributes( writer, viewAttributes, viewElement ) {
|
|
|
32
50
|
}
|
|
33
51
|
}
|
|
34
52
|
|
|
53
|
+
/**
|
|
54
|
+
* Helper function for the downcast converter. Removes attributes on the given view element.
|
|
55
|
+
*
|
|
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.
|
|
59
|
+
*/
|
|
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
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
35
78
|
/**
|
|
36
79
|
* Merges view element attribute objects.
|
|
37
80
|
*
|
|
@@ -45,7 +88,7 @@ export function mergeViewElementAttributes( target, source ) {
|
|
|
45
88
|
for ( const key in source ) {
|
|
46
89
|
// Merge classes.
|
|
47
90
|
if ( Array.isArray( source[ key ] ) ) {
|
|
48
|
-
result[ key ] = Array.from( new Set( [ ...target[ key ], ...source[ key ] ] ) );
|
|
91
|
+
result[ key ] = Array.from( new Set( [ ...( target[ key ] || [] ), ...source[ key ] ] ) );
|
|
49
92
|
}
|
|
50
93
|
|
|
51
94
|
// Merge attributes or styles.
|
package/src/converters.js
CHANGED
|
@@ -8,7 +8,11 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { toWidget } from 'ckeditor5/src/widget';
|
|
11
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
setViewAttributes,
|
|
13
|
+
mergeViewElementAttributes,
|
|
14
|
+
updateViewAttributes
|
|
15
|
+
} from './conversionutils';
|
|
12
16
|
|
|
13
17
|
/**
|
|
14
18
|
* View-to-model conversion helper for object elements.
|
|
@@ -28,7 +32,7 @@ export function viewToModelObjectConverter( { model: modelName } ) {
|
|
|
28
32
|
}
|
|
29
33
|
|
|
30
34
|
/**
|
|
31
|
-
* Conversion helper converting object element to HTML object widget.
|
|
35
|
+
* Conversion helper converting an object element to an HTML object widget.
|
|
32
36
|
*
|
|
33
37
|
* @param {module:core/editor/editor~Editor} editor
|
|
34
38
|
* @param {module:html-support/dataschema~DataSchemaInlineElementDefinition} definition
|
|
@@ -37,14 +41,15 @@ export function viewToModelObjectConverter( { model: modelName } ) {
|
|
|
37
41
|
export function toObjectWidgetConverter( editor, { view: viewName, isInline } ) {
|
|
38
42
|
const t = editor.t;
|
|
39
43
|
|
|
40
|
-
return ( modelElement, { writer
|
|
44
|
+
return ( modelElement, { writer } ) => {
|
|
41
45
|
const widgetLabel = t( 'HTML object' );
|
|
42
46
|
|
|
43
47
|
const viewElement = createObjectView( viewName, modelElement, writer );
|
|
48
|
+
const viewAttributes = modelElement.getAttribute( 'htmlAttributes' );
|
|
49
|
+
|
|
44
50
|
writer.addClass( 'html-object-embed__content', viewElement );
|
|
45
51
|
|
|
46
|
-
|
|
47
|
-
if ( viewAttributes && consumable.consume( modelElement, `attribute:htmlAttributes:${ modelElement.name }` ) ) {
|
|
52
|
+
if ( viewAttributes ) {
|
|
48
53
|
setViewAttributes( writer, viewAttributes, viewElement );
|
|
49
54
|
}
|
|
50
55
|
|
|
@@ -55,10 +60,7 @@ export function toObjectWidgetConverter( editor, { view: viewName, isInline } )
|
|
|
55
60
|
class: 'html-object-embed',
|
|
56
61
|
'data-html-object-embed-label': widgetLabel
|
|
57
62
|
},
|
|
58
|
-
viewElement
|
|
59
|
-
{
|
|
60
|
-
isAllowedInsideAttributeElement: isInline
|
|
61
|
-
}
|
|
63
|
+
viewElement
|
|
62
64
|
);
|
|
63
65
|
|
|
64
66
|
return toWidget( viewContainer, writer, { widgetLabel } );
|
|
@@ -91,6 +93,11 @@ export function viewToAttributeInlineConverter( { view: viewName, model: attribu
|
|
|
91
93
|
dispatcher.on( `element:${ viewName }`, ( evt, data, conversionApi ) => {
|
|
92
94
|
const viewAttributes = dataFilter._consumeAllowedAttributes( data.viewItem, conversionApi );
|
|
93
95
|
|
|
96
|
+
// Do not apply the attribute if the element itself is already consumed and there is no view attributes to store.
|
|
97
|
+
if ( !viewAttributes && !conversionApi.consumable.test( data.viewItem, { name: true } ) ) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
|
|
94
101
|
// Since we are converting to attribute we need a range on which we will set the attribute.
|
|
95
102
|
// If the range is not created yet, we will create it.
|
|
96
103
|
if ( !data.modelRange ) {
|
|
@@ -168,16 +175,15 @@ export function viewToModelBlockAttributeConverter( { view: viewName }, dataFilt
|
|
|
168
175
|
export function modelToViewBlockAttributeConverter( { model: modelName } ) {
|
|
169
176
|
return dispatcher => {
|
|
170
177
|
dispatcher.on( `attribute:htmlAttributes:${ modelName }`, ( evt, data, conversionApi ) => {
|
|
171
|
-
const viewAttributes = data.attributeNewValue;
|
|
172
|
-
|
|
173
178
|
if ( !conversionApi.consumable.consume( data.item, evt.name ) ) {
|
|
174
179
|
return;
|
|
175
180
|
}
|
|
176
181
|
|
|
182
|
+
const { attributeOldValue, attributeNewValue } = data;
|
|
177
183
|
const viewWriter = conversionApi.writer;
|
|
178
184
|
const viewElement = conversionApi.mapper.toViewElement( data.item );
|
|
179
185
|
|
|
180
|
-
|
|
186
|
+
updateViewAttributes( viewWriter, attributeOldValue, attributeNewValue, viewElement );
|
|
181
187
|
} );
|
|
182
188
|
};
|
|
183
189
|
}
|
package/src/datafilter.js
CHANGED
|
@@ -312,6 +312,7 @@ export default class DataFilter extends Plugin {
|
|
|
312
312
|
|
|
313
313
|
schema.register( modelName, definition.modelSchema );
|
|
314
314
|
|
|
315
|
+
/* istanbul ignore next: paranoid check */
|
|
315
316
|
if ( !viewName ) {
|
|
316
317
|
return;
|
|
317
318
|
}
|
|
@@ -336,7 +337,12 @@ export default class DataFilter extends Plugin {
|
|
|
336
337
|
conversion.for( 'upcast' ).add( viewToModelBlockAttributeConverter( definition, this ) );
|
|
337
338
|
|
|
338
339
|
conversion.for( 'editingDowncast' ).elementToStructure( {
|
|
339
|
-
model:
|
|
340
|
+
model: {
|
|
341
|
+
name: modelName,
|
|
342
|
+
attributes: [
|
|
343
|
+
'htmlAttributes'
|
|
344
|
+
]
|
|
345
|
+
},
|
|
340
346
|
view: toObjectWidgetConverter( editor, definition )
|
|
341
347
|
} );
|
|
342
348
|
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { Plugin } from 'ckeditor5/src/core';
|
|
11
|
+
import { toArray } from 'ckeditor5/src/utils';
|
|
11
12
|
|
|
12
13
|
import DataFilter from './datafilter';
|
|
13
14
|
import CodeBlockElementSupport from './integrations/codeblock';
|
|
@@ -18,6 +19,7 @@ import MediaEmbedElementSupport from './integrations/mediaembed';
|
|
|
18
19
|
import ScriptElementSupport from './integrations/script';
|
|
19
20
|
import TableElementSupport from './integrations/table';
|
|
20
21
|
import StyleElementSupport from './integrations/style';
|
|
22
|
+
import DocumentListElementSupport from './integrations/documentlist';
|
|
21
23
|
|
|
22
24
|
/**
|
|
23
25
|
* The General HTML Support feature.
|
|
@@ -48,7 +50,8 @@ export default class GeneralHtmlSupport extends Plugin {
|
|
|
48
50
|
MediaEmbedElementSupport,
|
|
49
51
|
ScriptElementSupport,
|
|
50
52
|
TableElementSupport,
|
|
51
|
-
StyleElementSupport
|
|
53
|
+
StyleElementSupport,
|
|
54
|
+
DocumentListElementSupport
|
|
52
55
|
];
|
|
53
56
|
}
|
|
54
57
|
|
|
@@ -63,6 +66,231 @@ export default class GeneralHtmlSupport extends Plugin {
|
|
|
63
66
|
dataFilter.loadAllowedConfig( editor.config.get( 'htmlSupport.allow' ) || [] );
|
|
64
67
|
dataFilter.loadDisallowedConfig( editor.config.get( 'htmlSupport.disallow' ) || [] );
|
|
65
68
|
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Returns a GHS model attribute name related to a given view element name.
|
|
72
|
+
*
|
|
73
|
+
* @protected
|
|
74
|
+
* @param {String} viewElementName A view element name.
|
|
75
|
+
* @returns {String}
|
|
76
|
+
*/
|
|
77
|
+
getGhsAttributeNameForElement( viewElementName ) {
|
|
78
|
+
const dataSchema = this.editor.plugins.get( 'DataSchema' );
|
|
79
|
+
const definitions = Array.from( dataSchema.getDefinitionsForView( viewElementName, false ) );
|
|
80
|
+
|
|
81
|
+
if ( definitions && definitions.length && definitions[ 0 ].isInline && !definitions[ 0 ].isObject ) {
|
|
82
|
+
return definitions[ 0 ].model;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return 'htmlAttributes';
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Updates GHS model attribute for a specified view element name, so it includes a given class name.
|
|
90
|
+
*
|
|
91
|
+
* @protected
|
|
92
|
+
* @param {String} viewElementName A view element name.
|
|
93
|
+
* @param {String|Array.<String>} className The css class to add.
|
|
94
|
+
* @param {module:engine/model/selection~Selectable} selectable The selection or element to update.
|
|
95
|
+
*/
|
|
96
|
+
addModelHtmlClass( viewElementName, className, selectable ) {
|
|
97
|
+
const model = this.editor.model;
|
|
98
|
+
const ghsAttributeName = this.getGhsAttributeNameForElement( viewElementName );
|
|
99
|
+
|
|
100
|
+
model.change( writer => {
|
|
101
|
+
for ( const item of getItemsToUpdateGhsAttribute( model, selectable, ghsAttributeName ) ) {
|
|
102
|
+
modifyGhsAttribute( writer, item, ghsAttributeName, 'classes', classes => {
|
|
103
|
+
for ( const value of toArray( className ) ) {
|
|
104
|
+
classes.add( value );
|
|
105
|
+
}
|
|
106
|
+
} );
|
|
107
|
+
}
|
|
108
|
+
} );
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Updates GHS model attribute for a specified view element name, so it does not include a given class name.
|
|
113
|
+
*
|
|
114
|
+
* @protected
|
|
115
|
+
* @param {String} viewElementName A view element name.
|
|
116
|
+
* @param {String|Array.<String>} className The css class to remove.
|
|
117
|
+
* @param {module:engine/model/selection~Selectable} selectable The selection or element to update.
|
|
118
|
+
*/
|
|
119
|
+
removeModelHtmlClass( viewElementName, className, selectable ) {
|
|
120
|
+
const model = this.editor.model;
|
|
121
|
+
const ghsAttributeName = this.getGhsAttributeNameForElement( viewElementName );
|
|
122
|
+
|
|
123
|
+
model.change( writer => {
|
|
124
|
+
for ( const item of getItemsToUpdateGhsAttribute( model, selectable, ghsAttributeName ) ) {
|
|
125
|
+
modifyGhsAttribute( writer, item, ghsAttributeName, 'classes', classes => {
|
|
126
|
+
for ( const value of toArray( className ) ) {
|
|
127
|
+
classes.delete( value );
|
|
128
|
+
}
|
|
129
|
+
} );
|
|
130
|
+
}
|
|
131
|
+
} );
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Updates GHS model attribute for a specified view element name, so it includes a given attribute.
|
|
136
|
+
*
|
|
137
|
+
* @protected
|
|
138
|
+
* @param {String} viewElementName A view element name.
|
|
139
|
+
* @param {Object} attributes The object with attributes to set.
|
|
140
|
+
* @param {module:engine/model/selection~Selectable} selectable The selection or element to update.
|
|
141
|
+
*/
|
|
142
|
+
setModelHtmlAttributes( viewElementName, attributes, selectable ) {
|
|
143
|
+
const model = this.editor.model;
|
|
144
|
+
const ghsAttributeName = this.getGhsAttributeNameForElement( viewElementName );
|
|
145
|
+
|
|
146
|
+
model.change( writer => {
|
|
147
|
+
for ( const item of getItemsToUpdateGhsAttribute( model, selectable, ghsAttributeName ) ) {
|
|
148
|
+
modifyGhsAttribute( writer, item, ghsAttributeName, 'attributes', attributesMap => {
|
|
149
|
+
for ( const [ key, value ] of Object.entries( attributes ) ) {
|
|
150
|
+
attributesMap.set( key, value );
|
|
151
|
+
}
|
|
152
|
+
} );
|
|
153
|
+
}
|
|
154
|
+
} );
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Updates GHS model attribute for a specified view element name, so it does not include a given attribute.
|
|
159
|
+
*
|
|
160
|
+
* @protected
|
|
161
|
+
* @param {String} viewElementName A view element name.
|
|
162
|
+
* @param {String|Array.<String>} attributeName The attribute name (or names) to remove.
|
|
163
|
+
* @param {module:engine/model/selection~Selectable} selectable The selection or element to update.
|
|
164
|
+
*/
|
|
165
|
+
removeModelHtmlAttributes( viewElementName, attributeName, selectable ) {
|
|
166
|
+
const model = this.editor.model;
|
|
167
|
+
const ghsAttributeName = this.getGhsAttributeNameForElement( viewElementName );
|
|
168
|
+
|
|
169
|
+
model.change( writer => {
|
|
170
|
+
for ( const item of getItemsToUpdateGhsAttribute( model, selectable, ghsAttributeName ) ) {
|
|
171
|
+
modifyGhsAttribute( writer, item, ghsAttributeName, 'attributes', attributesMap => {
|
|
172
|
+
for ( const key of toArray( attributeName ) ) {
|
|
173
|
+
attributesMap.delete( key );
|
|
174
|
+
}
|
|
175
|
+
} );
|
|
176
|
+
}
|
|
177
|
+
} );
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Updates GHS model attribute for a specified view element name, so it includes a given style.
|
|
182
|
+
*
|
|
183
|
+
* @protected
|
|
184
|
+
* @param {String} viewElementName A view element name.
|
|
185
|
+
* @param {Object} styles The object with styles to set.
|
|
186
|
+
* @param {module:engine/model/selection~Selectable} selectable The selection or element to update.
|
|
187
|
+
*/
|
|
188
|
+
setModelHtmlStyles( viewElementName, styles, selectable ) {
|
|
189
|
+
const model = this.editor.model;
|
|
190
|
+
const ghsAttributeName = this.getGhsAttributeNameForElement( viewElementName );
|
|
191
|
+
|
|
192
|
+
model.change( writer => {
|
|
193
|
+
for ( const item of getItemsToUpdateGhsAttribute( model, selectable, ghsAttributeName ) ) {
|
|
194
|
+
modifyGhsAttribute( writer, item, ghsAttributeName, 'styles', stylesMap => {
|
|
195
|
+
for ( const [ key, value ] of Object.entries( styles ) ) {
|
|
196
|
+
stylesMap.set( key, value );
|
|
197
|
+
}
|
|
198
|
+
} );
|
|
199
|
+
}
|
|
200
|
+
} );
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Updates GHS model attribute for a specified view element name, so it does not include a given style.
|
|
205
|
+
*
|
|
206
|
+
* @protected
|
|
207
|
+
* @param {String} viewElementName A view element name.
|
|
208
|
+
* @param {String|Array.<String>} properties The style (or styles list) to remove.
|
|
209
|
+
* @param {module:engine/model/selection~Selectable} selectable The selection or element to update.
|
|
210
|
+
*/
|
|
211
|
+
removeModelHtmlStyles( viewElementName, properties, selectable ) {
|
|
212
|
+
const model = this.editor.model;
|
|
213
|
+
const ghsAttributeName = this.getGhsAttributeNameForElement( viewElementName );
|
|
214
|
+
|
|
215
|
+
model.change( writer => {
|
|
216
|
+
for ( const item of getItemsToUpdateGhsAttribute( model, selectable, ghsAttributeName ) ) {
|
|
217
|
+
modifyGhsAttribute( writer, item, ghsAttributeName, 'styles', stylesMap => {
|
|
218
|
+
for ( const key of toArray( properties ) ) {
|
|
219
|
+
stylesMap.delete( key );
|
|
220
|
+
}
|
|
221
|
+
} );
|
|
222
|
+
}
|
|
223
|
+
} );
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Returns an iterator over an items in the selectable that accept given GHS attribute.
|
|
228
|
+
function* getItemsToUpdateGhsAttribute( model, selectable, ghsAttributeName ) {
|
|
229
|
+
if ( selectable.is( 'documentSelection' ) && selectable.isCollapsed ) {
|
|
230
|
+
if ( model.schema.checkAttributeInSelection( selectable, ghsAttributeName ) ) {
|
|
231
|
+
yield selectable;
|
|
232
|
+
}
|
|
233
|
+
} else {
|
|
234
|
+
for ( const range of getValidRangesForSelectable( model, selectable, ghsAttributeName ) ) {
|
|
235
|
+
yield* range.getItems( { shallow: true } );
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Translates a given selectable to an iterable of ranges.
|
|
241
|
+
function getValidRangesForSelectable( model, selectable, ghsAttributeName ) {
|
|
242
|
+
if ( selectable.is( 'node' ) || selectable.is( '$text' ) || selectable.is( '$textProxy' ) ) {
|
|
243
|
+
if ( model.schema.checkAttribute( selectable, ghsAttributeName ) ) {
|
|
244
|
+
return [ model.createRangeOn( selectable ) ];
|
|
245
|
+
} else {
|
|
246
|
+
return [];
|
|
247
|
+
}
|
|
248
|
+
} else {
|
|
249
|
+
return model.schema.getValidRanges( model.createSelection( selectable ).getRanges(), ghsAttributeName );
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// Updates a GHS attribute on a specified item.
|
|
254
|
+
// @param {module:engine/model/writer~Writer} writer
|
|
255
|
+
// @param {module:engine/model/item~Item|module:engine/model/documentselection~DocumentSelection} item
|
|
256
|
+
// @param {String} ghsAttributeName
|
|
257
|
+
// @param {'classes'|'attributes'|'styles'} subject
|
|
258
|
+
// @param {Function} callback That receives a map or set as an argument and should modify it (add or remove entries).
|
|
259
|
+
function modifyGhsAttribute( writer, item, ghsAttributeName, subject, callback ) {
|
|
260
|
+
const oldValue = item.getAttribute( ghsAttributeName );
|
|
261
|
+
const newValue = {};
|
|
262
|
+
|
|
263
|
+
for ( const kind of [ 'attributes', 'styles', 'classes' ] ) {
|
|
264
|
+
if ( kind != subject ) {
|
|
265
|
+
if ( oldValue && oldValue[ kind ] ) {
|
|
266
|
+
newValue[ kind ] = oldValue[ kind ];
|
|
267
|
+
}
|
|
268
|
+
} else {
|
|
269
|
+
const values = kind == 'classes' ?
|
|
270
|
+
new Set( oldValue && oldValue[ kind ] || [] ) :
|
|
271
|
+
new Map( Object.entries( oldValue && oldValue[ kind ] || {} ) );
|
|
272
|
+
|
|
273
|
+
callback( values );
|
|
274
|
+
|
|
275
|
+
if ( values.size ) {
|
|
276
|
+
newValue[ kind ] = kind == 'classes' ? Array.from( values ) : Object.fromEntries( values );
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
if ( Object.keys( newValue ).length ) {
|
|
282
|
+
if ( item.is( 'documentSelection' ) ) {
|
|
283
|
+
writer.setSelectionAttribute( ghsAttributeName, newValue );
|
|
284
|
+
} else {
|
|
285
|
+
writer.setAttribute( ghsAttributeName, newValue, item );
|
|
286
|
+
}
|
|
287
|
+
} else if ( oldValue ) {
|
|
288
|
+
if ( item.is( 'documentSelection' ) ) {
|
|
289
|
+
writer.removeSelectionAttribute( ghsAttributeName );
|
|
290
|
+
} else {
|
|
291
|
+
writer.removeAttribute( ghsAttributeName, item );
|
|
292
|
+
}
|
|
293
|
+
}
|
|
66
294
|
}
|
|
67
295
|
|
|
68
296
|
/**
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { Plugin } from 'ckeditor5/src/core';
|
|
11
|
-
import {
|
|
11
|
+
import { updateViewAttributes } from '../conversionutils.js';
|
|
12
12
|
|
|
13
13
|
import DataFilter from '../datafilter';
|
|
14
14
|
|
|
@@ -101,10 +101,11 @@ function modelToViewCodeBlockAttributeConverter() {
|
|
|
101
101
|
return;
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
+
const { attributeOldValue, attributeNewValue } = data;
|
|
104
105
|
const viewCodeElement = conversionApi.mapper.toViewElement( data.item );
|
|
105
106
|
const viewPreElement = viewCodeElement.parent;
|
|
106
107
|
|
|
107
|
-
|
|
108
|
+
updateViewAttributes( conversionApi.writer, attributeOldValue, attributeNewValue, viewPreElement );
|
|
108
109
|
} );
|
|
109
110
|
|
|
110
111
|
dispatcher.on( 'attribute:htmlContentAttributes:codeBlock', ( evt, data, conversionApi ) => {
|
|
@@ -112,9 +113,10 @@ function modelToViewCodeBlockAttributeConverter() {
|
|
|
112
113
|
return;
|
|
113
114
|
}
|
|
114
115
|
|
|
116
|
+
const { attributeOldValue, attributeNewValue } = data;
|
|
115
117
|
const viewCodeElement = conversionApi.mapper.toViewElement( data.item );
|
|
116
118
|
|
|
117
|
-
|
|
119
|
+
updateViewAttributes( conversionApi.writer, attributeOldValue, attributeNewValue, viewCodeElement );
|
|
118
120
|
} );
|
|
119
121
|
};
|
|
120
122
|
}
|