@ckeditor/ckeditor5-html-support 34.0.0 → 35.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.
Files changed (73) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/LICENSE.md +6 -2
  3. package/build/html-support.js +1 -1
  4. package/build/translations/ar.js +1 -0
  5. package/build/translations/bg.js +1 -0
  6. package/build/translations/bn.js +1 -0
  7. package/build/translations/ca.js +1 -0
  8. package/build/translations/da.js +1 -0
  9. package/build/translations/et.js +1 -0
  10. package/build/translations/fi.js +1 -0
  11. package/build/translations/fr.js +1 -0
  12. package/build/translations/he.js +1 -0
  13. package/build/translations/hi.js +1 -0
  14. package/build/translations/ja.js +1 -0
  15. package/build/translations/ko.js +1 -0
  16. package/build/translations/lt.js +1 -0
  17. package/build/translations/lv.js +1 -0
  18. package/build/translations/ms.js +1 -0
  19. package/build/translations/no.js +1 -0
  20. package/build/translations/pt.js +1 -0
  21. package/build/translations/ro.js +1 -0
  22. package/build/translations/sv.js +1 -0
  23. package/build/translations/th.js +1 -0
  24. package/build/translations/tr.js +1 -0
  25. package/build/translations/uk.js +1 -0
  26. package/build/translations/ur.js +1 -0
  27. package/build/translations/vi.js +1 -0
  28. package/build/translations/zh-cn.js +1 -0
  29. package/lang/translations/ar.po +21 -0
  30. package/lang/translations/bg.po +21 -0
  31. package/lang/translations/bn.po +21 -0
  32. package/lang/translations/ca.po +21 -0
  33. package/lang/translations/da.po +21 -0
  34. package/lang/translations/es.po +1 -1
  35. package/lang/translations/et.po +21 -0
  36. package/lang/translations/fi.po +21 -0
  37. package/lang/translations/fr.po +21 -0
  38. package/lang/translations/he.po +21 -0
  39. package/lang/translations/hi.po +21 -0
  40. package/lang/translations/it.po +1 -1
  41. package/lang/translations/ja.po +21 -0
  42. package/lang/translations/ko.po +21 -0
  43. package/lang/translations/lt.po +21 -0
  44. package/lang/translations/lv.po +21 -0
  45. package/lang/translations/ms.po +21 -0
  46. package/lang/translations/no.po +21 -0
  47. package/lang/translations/pt-br.po +1 -1
  48. package/lang/translations/pt.po +21 -0
  49. package/lang/translations/ro.po +21 -0
  50. package/lang/translations/sv.po +21 -0
  51. package/lang/translations/th.po +21 -0
  52. package/lang/translations/tr.po +21 -0
  53. package/lang/translations/uk.po +21 -0
  54. package/lang/translations/ur.po +21 -0
  55. package/lang/translations/vi.po +21 -0
  56. package/lang/translations/zh-cn.po +21 -0
  57. package/package.json +32 -31
  58. package/src/converters.js +16 -5
  59. package/src/datafilter.js +149 -13
  60. package/src/dataschema.js +3 -0
  61. package/src/generalhtmlsupport.js +7 -5
  62. package/src/integrations/codeblock.js +8 -1
  63. package/src/integrations/customelement.js +179 -0
  64. package/src/integrations/documentlist.js +10 -3
  65. package/src/integrations/dualcontent.js +19 -3
  66. package/src/integrations/heading.js +7 -0
  67. package/src/integrations/image.js +36 -10
  68. package/src/integrations/mediaembed.js +42 -6
  69. package/src/integrations/script.js +7 -0
  70. package/src/integrations/style.js +7 -0
  71. package/src/integrations/table.js +36 -7
  72. package/src/schemadefinitions.js +19 -0
  73. package/build/html-support.js.map +0 -1
@@ -28,6 +28,13 @@ export default class ImageElementSupport extends Plugin {
28
28
  return [ DataFilter ];
29
29
  }
30
30
 
31
+ /**
32
+ * @inheritDoc
33
+ */
34
+ static get pluginName() {
35
+ return 'ImageElementSupport';
36
+ }
37
+
31
38
  /**
32
39
  * @inheritDoc
33
40
  */
@@ -43,6 +50,10 @@ export default class ImageElementSupport extends Plugin {
43
50
  const conversion = editor.conversion;
44
51
  const dataFilter = editor.plugins.get( DataFilter );
45
52
 
53
+ dataFilter.on( 'register:figure', () => {
54
+ conversion.for( 'upcast' ).add( viewToModelFigureAttributeConverter( dataFilter ) );
55
+ } );
56
+
46
57
  dataFilter.on( 'register:img', ( evt, definition ) => {
47
58
  if ( definition.model !== 'imageBlock' && definition.model !== 'imageInline' ) {
48
59
  return;
@@ -96,31 +107,46 @@ function viewToModelImageAttributeConverter( dataFilter ) {
96
107
 
97
108
  preserveElementAttributes( viewImageElement, 'htmlAttributes' );
98
109
 
99
- if ( viewContainerElement.is( 'element', 'figure' ) ) {
100
- preserveElementAttributes( viewContainerElement, 'htmlFigureAttributes' );
101
- } else if ( viewContainerElement.is( 'element', 'a' ) ) {
110
+ if ( viewContainerElement.is( 'element', 'a' ) ) {
102
111
  preserveLinkAttributes( viewContainerElement );
103
112
  }
104
113
 
105
114
  function preserveElementAttributes( viewElement, attributeName ) {
106
- const viewAttributes = dataFilter._consumeAllowedAttributes( viewElement, conversionApi );
115
+ const viewAttributes = dataFilter.processViewAttributes( viewElement, conversionApi );
107
116
 
108
117
  if ( viewAttributes ) {
109
118
  conversionApi.writer.setAttribute( attributeName, viewAttributes, data.modelRange );
110
119
  }
111
120
  }
112
121
 
113
- // For a block image, we want to preserve the attributes on our own.
114
- // The inline image attributes will be handled by the GHS automatically.
115
122
  function preserveLinkAttributes( viewContainerElement ) {
116
123
  if ( data.modelRange && data.modelRange.getContainedElement().is( 'element', 'imageBlock' ) ) {
117
124
  preserveElementAttributes( viewContainerElement, 'htmlLinkAttributes' );
118
125
  }
126
+ }
127
+ }, { priority: 'low' } );
128
+ };
129
+ }
119
130
 
120
- // If we're in a link, then the `<figure>` element should be one level higher.
121
- if ( viewContainerElement.parent.is( 'element', 'figure' ) ) {
122
- preserveElementAttributes( viewContainerElement.parent, 'htmlFigureAttributes' );
123
- }
131
+ // View-to-model conversion helper preserving allowed attributes on {@link module:image/image~Image Image}
132
+ // feature model element from figure view element.
133
+ //
134
+ // @private
135
+ // @param {module:html-support/datafilter~DataFilter} dataFilter
136
+ // @returns {Function} Returns a conversion callback.
137
+ function viewToModelFigureAttributeConverter( dataFilter ) {
138
+ return dispatcher => {
139
+ dispatcher.on( 'element:figure', ( evt, data, conversionApi ) => {
140
+ const viewFigureElement = data.viewItem;
141
+
142
+ if ( !data.modelRange || !viewFigureElement.hasClass( 'image' ) ) {
143
+ return;
144
+ }
145
+
146
+ const viewAttributes = dataFilter.processViewAttributes( viewFigureElement, conversionApi );
147
+
148
+ if ( viewAttributes ) {
149
+ conversionApi.writer.setAttribute( 'htmlFigureAttributes', viewAttributes, data.modelRange );
124
150
  }
125
151
  }, { priority: 'low' } );
126
152
  };
@@ -19,10 +19,23 @@ import { updateViewAttributes } from '../conversionutils.js';
19
19
  * @extends module:core/plugin~Plugin
20
20
  */
21
21
  export default class MediaEmbedElementSupport extends Plugin {
22
+ /**
23
+ * @inheritDoc
24
+ */
22
25
  static get requires() {
23
26
  return [ DataFilter ];
24
27
  }
25
28
 
29
+ /**
30
+ * @inheritDoc
31
+ */
32
+ static get pluginName() {
33
+ return 'MediaEmbedElementSupport';
34
+ }
35
+
36
+ /**
37
+ * @inheritDoc
38
+ */
26
39
  init() {
27
40
  const editor = this.editor;
28
41
 
@@ -44,6 +57,10 @@ export default class MediaEmbedElementSupport extends Plugin {
44
57
  view: mediaElementName
45
58
  } );
46
59
 
60
+ dataFilter.on( 'register:figure', ( ) => {
61
+ conversion.for( 'upcast' ).add( viewToModelFigureAttributesConverter( dataFilter ) );
62
+ } );
63
+
47
64
  dataFilter.on( `register:${ mediaElementName }`, ( evt, definition ) => {
48
65
  if ( definition.model !== 'media' ) {
49
66
  return;
@@ -71,16 +88,11 @@ function viewToModelMediaAttributesConverter( dataFilter, mediaElementName ) {
71
88
 
72
89
  function upcastMedia( evt, data, conversionApi ) {
73
90
  const viewMediaElement = data.viewItem;
74
- const viewParent = viewMediaElement.parent;
75
91
 
76
92
  preserveElementAttributes( viewMediaElement, 'htmlAttributes' );
77
93
 
78
- if ( viewParent.is( 'element', 'figure' ) && viewParent.hasClass( 'media' ) ) {
79
- preserveElementAttributes( viewParent, 'htmlFigureAttributes' );
80
- }
81
-
82
94
  function preserveElementAttributes( viewElement, attributeName ) {
83
- const viewAttributes = dataFilter._consumeAllowedAttributes( viewElement, conversionApi );
95
+ const viewAttributes = dataFilter.processViewAttributes( viewElement, conversionApi );
84
96
 
85
97
  if ( viewAttributes ) {
86
98
  conversionApi.writer.setAttribute( attributeName, viewAttributes, data.modelRange );
@@ -89,6 +101,30 @@ function viewToModelMediaAttributesConverter( dataFilter, mediaElementName ) {
89
101
  }
90
102
  }
91
103
 
104
+ // View-to-model conversion helper preserving allowed attributes on {@link module:media-embed/mediaembed~MediaEmbed MediaEmbed}
105
+ // feature model element from figure view element.
106
+ //
107
+ // @private
108
+ // @param {module:html-support/datafilter~DataFilter} dataFilter
109
+ // @returns {Function} Returns a conversion callback.
110
+ function viewToModelFigureAttributesConverter( dataFilter ) {
111
+ return dispatcher => {
112
+ dispatcher.on( 'element:figure', ( evt, data, conversionApi ) => {
113
+ const viewFigureElement = data.viewItem;
114
+
115
+ if ( !data.modelRange || !viewFigureElement.hasClass( 'media' ) ) {
116
+ return;
117
+ }
118
+
119
+ const viewAttributes = dataFilter.processViewAttributes( viewFigureElement, conversionApi );
120
+
121
+ if ( viewAttributes ) {
122
+ conversionApi.writer.setAttribute( 'htmlFigureAttributes', viewAttributes, data.modelRange );
123
+ }
124
+ }, { priority: 'low' } );
125
+ };
126
+ }
127
+
92
128
  function modelToViewMediaAttributeConverter( mediaElementName ) {
93
129
  return dispatcher => {
94
130
  addAttributeConversionDispatcherHandler( mediaElementName, 'htmlAttributes' );
@@ -30,6 +30,13 @@ export default class ScriptElementSupport extends Plugin {
30
30
  return [ DataFilter ];
31
31
  }
32
32
 
33
+ /**
34
+ * @inheritDoc
35
+ */
36
+ static get pluginName() {
37
+ return 'ScriptElementSupport';
38
+ }
39
+
33
40
  /**
34
41
  * @inheritDoc
35
42
  */
@@ -30,6 +30,13 @@ export default class StyleElementSupport extends Plugin {
30
30
  return [ DataFilter ];
31
31
  }
32
32
 
33
+ /**
34
+ * @inheritDoc
35
+ */
36
+ static get pluginName() {
37
+ return 'StyleElementSupport';
38
+ }
39
+
33
40
  /**
34
41
  * @inheritDoc
35
42
  */
@@ -9,7 +9,6 @@
9
9
 
10
10
  import { Plugin } from 'ckeditor5/src/core';
11
11
  import { setViewAttributes } from '../conversionutils.js';
12
-
13
12
  import DataFilter from '../datafilter';
14
13
 
15
14
  /**
@@ -25,6 +24,13 @@ export default class TableElementSupport extends Plugin {
25
24
  return [ DataFilter ];
26
25
  }
27
26
 
27
+ /**
28
+ * @inheritDoc
29
+ */
30
+ static get pluginName() {
31
+ return 'TableElementSupport';
32
+ }
33
+
28
34
  /**
29
35
  * @inheritDoc
30
36
  */
@@ -39,6 +45,10 @@ export default class TableElementSupport extends Plugin {
39
45
  const conversion = editor.conversion;
40
46
  const dataFilter = editor.plugins.get( DataFilter );
41
47
 
48
+ dataFilter.on( 'register:figure', ( ) => {
49
+ conversion.for( 'upcast' ).add( viewToModelFigureAttributeConverter( dataFilter ) );
50
+ } );
51
+
42
52
  dataFilter.on( 'register:table', ( evt, definition ) => {
43
53
  if ( definition.model !== 'table' ) {
44
54
  return;
@@ -74,11 +84,6 @@ function viewToModelTableAttributeConverter( dataFilter ) {
74
84
 
75
85
  preserveElementAttributes( viewTableElement, 'htmlAttributes' );
76
86
 
77
- const viewFigureElement = viewTableElement.parent;
78
- if ( viewFigureElement.is( 'element', 'figure' ) ) {
79
- preserveElementAttributes( viewFigureElement, 'htmlFigureAttributes' );
80
- }
81
-
82
87
  for ( const childNode of viewTableElement.getChildren() ) {
83
88
  if ( childNode.is( 'element', 'thead' ) ) {
84
89
  preserveElementAttributes( childNode, 'htmlTheadAttributes' );
@@ -90,12 +95,36 @@ function viewToModelTableAttributeConverter( dataFilter ) {
90
95
  }
91
96
 
92
97
  function preserveElementAttributes( viewElement, attributeName ) {
93
- const viewAttributes = dataFilter._consumeAllowedAttributes( viewElement, conversionApi );
98
+ const viewAttributes = dataFilter.processViewAttributes( viewElement, conversionApi );
94
99
 
95
100
  if ( viewAttributes ) {
96
101
  conversionApi.writer.setAttribute( attributeName, viewAttributes, data.modelRange );
97
102
  }
98
103
  }
104
+ } );
105
+ };
106
+ }
107
+
108
+ // View-to-model conversion helper preserving allowed attributes on {@link module:table/table~Table Table}
109
+ // feature model element from figure view element.
110
+ //
111
+ // @private
112
+ // @param {module:html-support/datafilter~DataFilter} dataFilter
113
+ // @returns {Function} Returns a conversion callback.
114
+ function viewToModelFigureAttributeConverter( dataFilter ) {
115
+ return dispatcher => {
116
+ dispatcher.on( 'element:figure', ( evt, data, conversionApi ) => {
117
+ const viewFigureElement = data.viewItem;
118
+
119
+ if ( !data.modelRange || !viewFigureElement.hasClass( 'table' ) ) {
120
+ return;
121
+ }
122
+
123
+ const viewAttributes = dataFilter.processViewAttributes( viewFigureElement, conversionApi );
124
+
125
+ if ( viewAttributes ) {
126
+ conversionApi.writer.setAttribute( 'htmlFigureAttributes', viewAttributes, data.modelRange );
127
+ }
99
128
  }, { priority: 'low' } );
100
129
  };
101
130
  }
@@ -577,6 +577,7 @@ export default {
577
577
  model: 'htmlA',
578
578
  view: 'a',
579
579
  priority: 5,
580
+ coupledAttribute: 'linkHref',
580
581
  attributeProperties: {
581
582
  copyOnEnter: true
582
583
  }
@@ -584,6 +585,7 @@ export default {
584
585
  {
585
586
  model: 'htmlStrong',
586
587
  view: 'strong',
588
+ coupledAttribute: 'bold',
587
589
  attributeProperties: {
588
590
  copyOnEnter: true
589
591
  }
@@ -591,6 +593,7 @@ export default {
591
593
  {
592
594
  model: 'htmlB',
593
595
  view: 'b',
596
+ coupledAttribute: 'bold',
594
597
  attributeProperties: {
595
598
  copyOnEnter: true
596
599
  }
@@ -598,6 +601,7 @@ export default {
598
601
  {
599
602
  model: 'htmlI',
600
603
  view: 'i',
604
+ coupledAttribute: 'italic',
601
605
  attributeProperties: {
602
606
  copyOnEnter: true
603
607
  }
@@ -605,6 +609,7 @@ export default {
605
609
  {
606
610
  model: 'htmlEm',
607
611
  view: 'em',
612
+ coupledAttribute: 'italic',
608
613
  attributeProperties: {
609
614
  copyOnEnter: true
610
615
  }
@@ -612,6 +617,7 @@ export default {
612
617
  {
613
618
  model: 'htmlS',
614
619
  view: 's',
620
+ coupledAttribute: 'strikethrough',
615
621
  attributeProperties: {
616
622
  copyOnEnter: true
617
623
  }
@@ -620,6 +626,7 @@ export default {
620
626
  {
621
627
  model: 'htmlDel',
622
628
  view: 'del',
629
+ coupledAttribute: 'strikethrough',
623
630
  attributeProperties: {
624
631
  copyOnEnter: true
625
632
  }
@@ -635,6 +642,7 @@ export default {
635
642
  {
636
643
  model: 'htmlU',
637
644
  view: 'u',
645
+ coupledAttribute: 'underline',
638
646
  attributeProperties: {
639
647
  copyOnEnter: true
640
648
  }
@@ -642,6 +650,7 @@ export default {
642
650
  {
643
651
  model: 'htmlSub',
644
652
  view: 'sub',
653
+ coupledAttribute: 'subscript',
645
654
  attributeProperties: {
646
655
  copyOnEnter: true
647
656
  }
@@ -649,6 +658,7 @@ export default {
649
658
  {
650
659
  model: 'htmlSup',
651
660
  view: 'sup',
661
+ coupledAttribute: 'superscript',
652
662
  attributeProperties: {
653
663
  copyOnEnter: true
654
664
  }
@@ -656,6 +666,7 @@ export default {
656
666
  {
657
667
  model: 'htmlCode',
658
668
  view: 'code',
669
+ coupledAttribute: 'code',
659
670
  attributeProperties: {
660
671
  copyOnEnter: true
661
672
  }
@@ -828,6 +839,14 @@ export default {
828
839
  allowWhere: [ '$text', '$block' ],
829
840
  isInline: true
830
841
  }
842
+ },
843
+ {
844
+ model: 'htmlCustomElement',
845
+ view: '$customElement',
846
+ modelSchema: {
847
+ allowWhere: [ '$text', '$block' ],
848
+ isInline: true
849
+ }
831
850
  }
832
851
  ]
833
852
  };