@ckeditor/ckeditor5-html-support 45.2.1 → 46.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/build/html-support.js +2 -2
  2. package/dist/index.js +110 -54
  3. package/dist/index.js.map +1 -1
  4. package/package.json +13 -12
  5. package/src/converters.d.ts +21 -11
  6. package/src/converters.js +10 -0
  7. package/src/datafilter.d.ts +6 -6
  8. package/src/datafilter.js +7 -5
  9. package/src/dataschema.d.ts +14 -14
  10. package/src/dataschema.js +2 -2
  11. package/src/emptyblock.d.ts +1 -1
  12. package/src/emptyblock.js +1 -1
  13. package/src/fullpage.d.ts +1 -1
  14. package/src/fullpage.js +4 -4
  15. package/src/generalhtmlsupport.d.ts +20 -16
  16. package/src/generalhtmlsupport.js +21 -14
  17. package/src/generalhtmlsupportconfig.d.ts +5 -5
  18. package/src/htmlcomment.d.ts +6 -6
  19. package/src/htmlcomment.js +1 -1
  20. package/src/htmlpagedataprocessor.d.ts +1 -1
  21. package/src/htmlpagedataprocessor.js +3 -3
  22. package/src/index.d.ts +23 -19
  23. package/src/index.js +11 -7
  24. package/src/integrations/codeblock.d.ts +2 -2
  25. package/src/integrations/codeblock.js +2 -2
  26. package/src/integrations/customelement.d.ts +3 -3
  27. package/src/integrations/customelement.js +7 -6
  28. package/src/integrations/dualcontent.d.ts +6 -5
  29. package/src/integrations/dualcontent.js +6 -5
  30. package/src/integrations/heading.d.ts +2 -2
  31. package/src/integrations/heading.js +2 -2
  32. package/src/integrations/horizontalline.d.ts +2 -2
  33. package/src/integrations/horizontalline.js +2 -2
  34. package/src/integrations/image.d.ts +2 -2
  35. package/src/integrations/image.js +2 -2
  36. package/src/integrations/integrationutils.d.ts +2 -2
  37. package/src/integrations/list.d.ts +2 -2
  38. package/src/integrations/list.js +2 -2
  39. package/src/integrations/mediaembed.d.ts +2 -2
  40. package/src/integrations/mediaembed.js +3 -3
  41. package/src/integrations/script.d.ts +2 -2
  42. package/src/integrations/script.js +4 -3
  43. package/src/integrations/style.d.ts +2 -2
  44. package/src/integrations/style.js +4 -3
  45. package/src/integrations/table.d.ts +2 -2
  46. package/src/integrations/table.js +2 -2
  47. package/src/schemadefinitions.d.ts +49 -5
  48. package/src/schemadefinitions.js +50 -43
  49. package/src/utils.d.ts +26 -7
  50. package/src/utils.js +30 -0
package/dist/index.js CHANGED
@@ -4,9 +4,9 @@
4
4
  */
5
5
  import { Plugin } from '@ckeditor/ckeditor5-core/dist/index.js';
6
6
  import { toArray, priorities, CKEditorError, isValidAttributeName, uid, logWarning, global } from '@ckeditor/ckeditor5-utils/dist/index.js';
7
- import { Matcher, StylesMap, UpcastWriter, HtmlDataProcessor } from '@ckeditor/ckeditor5-engine/dist/index.js';
7
+ import { Matcher, StylesMap, ViewUpcastWriter, HtmlDataProcessor } from '@ckeditor/ckeditor5-engine/dist/index.js';
8
8
  import { toWidget, Widget } from '@ckeditor/ckeditor5-widget/dist/index.js';
9
- import { startCase, cloneDeep, mergeWith, isPlainObject, isEqual } from 'es-toolkit/compat';
9
+ import { cloneDeep, startCase, mergeWith, isPlainObject, isEqual } from 'es-toolkit/compat';
10
10
  import { Enter } from '@ckeditor/ckeditor5-enter/dist/index.js';
11
11
 
12
12
  /**
@@ -16,6 +16,7 @@ import { Enter } from '@ckeditor/ckeditor5-enter/dist/index.js';
16
16
  * @param oldViewAttributes The previous GHS attribute value.
17
17
  * @param newViewAttributes The current GHS attribute value.
18
18
  * @param viewElement The view element to update.
19
+ * @internal
19
20
  */ function updateViewAttributes(writer, oldViewAttributes, newViewAttributes, viewElement) {
20
21
  if (oldViewAttributes) {
21
22
  removeViewAttributes(writer, oldViewAttributes, viewElement);
@@ -30,6 +31,7 @@ import { Enter } from '@ckeditor/ckeditor5-enter/dist/index.js';
30
31
  * @param writer The view writer.
31
32
  * @param viewAttributes The GHS attribute value.
32
33
  * @param viewElement The view element to update.
34
+ * @internal
33
35
  */ function setViewAttributes(writer, viewAttributes, viewElement) {
34
36
  if (viewAttributes.attributes) {
35
37
  for (const [key, value] of Object.entries(viewAttributes.attributes)){
@@ -49,6 +51,7 @@ import { Enter } from '@ckeditor/ckeditor5-enter/dist/index.js';
49
51
  * @param writer The view writer.
50
52
  * @param viewAttributes The GHS attribute value.
51
53
  * @param viewElement The view element to update.
54
+ * @internal
52
55
  */ function removeViewAttributes(writer, viewAttributes, viewElement) {
53
56
  if (viewAttributes.attributes) {
54
57
  for (const [key] of Object.entries(viewAttributes.attributes)){
@@ -66,6 +69,8 @@ import { Enter } from '@ckeditor/ckeditor5-enter/dist/index.js';
66
69
  }
67
70
  /**
68
71
  * Merges view element attribute objects.
72
+ *
73
+ * @internal
69
74
  */ function mergeViewElementAttributes(target, source) {
70
75
  const result = cloneDeep(target);
71
76
  let key = 'attributes';
@@ -129,16 +134,43 @@ function modifyGhsAttribute(writer, item, ghsAttributeName, subject, callback) {
129
134
  }
130
135
  }
131
136
  }
137
+ /**
138
+ * Strips the `styles`, and `classes` keys from the GHS attribute value on the given item.
139
+ *
140
+ * @internal
141
+ */ function removeFormatting(ghsAttributeName, itemRange, writer) {
142
+ for (const item of itemRange.getItems({
143
+ shallow: true
144
+ })){
145
+ const value = item.getAttribute(ghsAttributeName);
146
+ // Copy only attributes to the new attribute value.
147
+ if (value && value.attributes && Object.keys(value.attributes).length) {
148
+ // But reset the GHS attribute only when there is anything more than just attributes.
149
+ if (Object.keys(value).length > 1) {
150
+ writer.setAttribute(ghsAttributeName, {
151
+ attributes: value.attributes
152
+ }, item);
153
+ }
154
+ } else {
155
+ // There are no attributes, so remove the GHS attribute completely.
156
+ writer.removeAttribute(ghsAttributeName, item);
157
+ }
158
+ }
159
+ }
132
160
  /**
133
161
  * Transforms passed string to PascalCase format. Examples:
134
162
  * * `div` => `Div`
135
163
  * * `h1` => `H1`
136
164
  * * `table` => `Table`
165
+ *
166
+ * @internal
137
167
  */ function toPascalCase(data) {
138
168
  return startCase(data).replace(/ /g, '');
139
169
  }
140
170
  /**
141
171
  * Returns the attribute name of the model element that holds raw HTML attributes.
172
+ *
173
+ * @internal
142
174
  */ function getHtmlAttributeName(viewElementName) {
143
175
  return `html${toPascalCase(viewElementName)}Attributes`;
144
176
  }
@@ -149,6 +181,7 @@ function modifyGhsAttribute(writer, item, ghsAttributeName, subject, callback) {
149
181
  * Preserves object element content in `htmlContent` attribute.
150
182
  *
151
183
  * @returns Returns a conversion callback.
184
+ * @internal
152
185
  */ function viewToModelObjectConverter({ model: modelName }) {
153
186
  return (viewElement, conversionApi)=>{
154
187
  // Let's keep element HTML and its attributes, so we can rebuild element in downcast conversions.
@@ -161,6 +194,7 @@ function modifyGhsAttribute(writer, item, ghsAttributeName, subject, callback) {
161
194
  * Conversion helper converting an object element to an HTML object widget.
162
195
  *
163
196
  * @returns Returns a conversion callback.
197
+ * @internal
164
198
  */ function toObjectWidgetConverter(editor, { view: viewName, isInline }) {
165
199
  const t = editor.t;
166
200
  return (modelElement, { writer })=>{
@@ -184,6 +218,8 @@ function modifyGhsAttribute(writer, item, ghsAttributeName, subject, callback) {
184
218
  }
185
219
  /**
186
220
  * Creates object view element from the given model element.
221
+ *
222
+ * @internal
187
223
  */ function createObjectView(viewName, modelElement, writer) {
188
224
  return writer.createRawElement(viewName, null, (domElement, domConverter)=>{
189
225
  domConverter.setContentOf(domElement, modelElement.getAttribute('htmlContent'));
@@ -193,6 +229,7 @@ function modifyGhsAttribute(writer, item, ghsAttributeName, subject, callback) {
193
229
  * View-to-attribute conversion helper preserving inline element attributes on `$text`.
194
230
  *
195
231
  * @returns Returns a conversion callback.
232
+ * @internal
196
233
  */ function viewToAttributeInlineConverter({ view: viewName, model: attributeKey, allowEmpty }, dataFilter) {
197
234
  return (dispatcher)=>{
198
235
  dispatcher.on(`element:${viewName}`, (evt, data, conversionApi)=>{
@@ -247,6 +284,8 @@ function modifyGhsAttribute(writer, item, ghsAttributeName, subject, callback) {
247
284
  }
248
285
  /**
249
286
  * Conversion helper converting an empty inline model element to an HTML element or widget.
287
+ *
288
+ * @internal
250
289
  */ function emptyInlineModelElementToViewConverter({ model: attributeKey, view: viewName }, asWidget) {
251
290
  return (item, { writer, consumable })=>{
252
291
  if (!item.hasAttribute(attributeKey)) {
@@ -264,6 +303,7 @@ function modifyGhsAttribute(writer, item, ghsAttributeName, subject, callback) {
264
303
  * Attribute-to-view conversion helper applying attributes to view element preserved on `$text`.
265
304
  *
266
305
  * @returns Returns a conversion callback.
306
+ * @internal
267
307
  */ function attributeToViewInlineConverter({ priority, view: viewName }) {
268
308
  return (attributeValue, conversionApi)=>{
269
309
  if (!attributeValue) {
@@ -283,6 +323,7 @@ function modifyGhsAttribute(writer, item, ghsAttributeName, subject, callback) {
283
323
  * All matched attributes will be preserved on `html*Attributes` attribute.
284
324
  *
285
325
  * @returns Returns a conversion callback.
326
+ * @internal
286
327
  */ function viewToModelBlockAttributeConverter({ view: viewName }, dataFilter) {
287
328
  return (dispatcher)=>{
288
329
  dispatcher.on(`element:${viewName}`, (evt, data, conversionApi)=>{
@@ -308,6 +349,7 @@ function modifyGhsAttribute(writer, item, ghsAttributeName, subject, callback) {
308
349
  * for block elements.
309
350
  *
310
351
  * @returns Returns a conversion callback.
352
+ * @internal
311
353
  */ function modelToViewBlockAttributeConverter({ view: viewName, model: modelName }) {
312
354
  return (dispatcher)=>{
313
355
  dispatcher.on(`attribute:${getHtmlAttributeName(viewName)}:${modelName}`, (evt, data, conversionApi)=>{
@@ -327,48 +369,51 @@ function modifyGhsAttribute(writer, item, ghsAttributeName, subject, callback) {
327
369
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
328
370
  */ /**
329
371
  * @module html-support/schemadefinitions
330
- */ // Skipped elements due to HTML deprecation:
331
- // * noframes (not sure if we should provide support for this element. CKE4 is not supporting frameset and frame,
332
- // but it will unpack <frameset><noframes>foobar</noframes></frameset> to <noframes>foobar</noframes>, so there
333
- // may be some content loss. Although using noframes as a standalone element seems invalid)
334
- // * keygen (this one is also empty)
335
- // * applet (support is limited mostly to old IE)
336
- // * basefont (this one is also empty)
337
- // * isindex (basically no support for modern browsers at all)
338
- //
339
- // Skipped elements due to lack empty element support:
340
- // * hr
341
- // * area
342
- // * br
343
- // * command
344
- // * map
345
- // * wbr
346
- // * colgroup -> col
347
- //
348
- // Skipped elements due to complexity:
349
- // * datalist with option elements used as a data source for input[list] element
350
- //
351
- // Skipped elements as they are handled as an object content:
352
- // * track
353
- // * source
354
- // * option
355
- // * param
356
- // * optgroup
357
- //
358
- // Skipped full page HTML elements:
359
- // * body
360
- // * html
361
- // * title
362
- // * head
363
- // * meta
364
- // * link
365
- // * etc...
366
- //
367
- // Skipped hidden elements:
368
- // noscript
369
- //
370
- // When adding elements to this list, update the feature guide listing, too.
371
- var defaultConfig = {
372
+ */ /**
373
+ * Skipped elements due to HTML deprecation:
374
+ * * noframes (not sure if we should provide support for this element. CKE4 is not supporting frameset and frame,
375
+ * but it will unpack <frameset><noframes>foobar</noframes></frameset> to <noframes>foobar</noframes>, so there
376
+ * may be some content loss. Although using noframes as a standalone element seems invalid)
377
+ * * keygen (this one is also empty)
378
+ * * applet (support is limited mostly to old IE)
379
+ * * basefont (this one is also empty)
380
+ * * isindex (basically no support for modern browsers at all)
381
+ *
382
+ * Skipped elements due to lack empty element support:
383
+ * * hr
384
+ * * area
385
+ * * br
386
+ * * command
387
+ * * map
388
+ * * wbr
389
+ * * colgroup -> col
390
+ *
391
+ * Skipped elements due to complexity:
392
+ * * datalist with option elements used as a data source for input[list] element
393
+ *
394
+ * Skipped elements as they are handled as an object content:
395
+ * * track
396
+ * * source
397
+ * * option
398
+ * * param
399
+ * * optgroup
400
+ *
401
+ * Skipped full page HTML elements:
402
+ * * body
403
+ * * html
404
+ * * title
405
+ * * head
406
+ * * meta
407
+ * * link
408
+ * * etc...
409
+ *
410
+ * Skipped hidden elements:
411
+ * noscript
412
+ *
413
+ * When adding elements to this list, update the feature guide listing, too.
414
+ *
415
+ * @internal
416
+ */ const defaultConfig = {
372
417
  block: [
373
418
  // Existing features.
374
419
  {
@@ -1029,7 +1074,10 @@ var defaultConfig = {
1029
1074
  model: 'htmlA',
1030
1075
  view: 'a',
1031
1076
  priority: 5,
1032
- coupledAttribute: 'linkHref'
1077
+ coupledAttribute: 'linkHref',
1078
+ attributeProperties: {
1079
+ isFormatting: true
1080
+ }
1033
1081
  },
1034
1082
  {
1035
1083
  model: 'htmlStrong',
@@ -2075,7 +2123,7 @@ var defaultConfig = {
2075
2123
  const schema = editor.model.schema;
2076
2124
  const conversion = editor.conversion;
2077
2125
  const attributeKey = definition.model;
2078
- // This element is stored in the model as an attribute on a block element, for example DocumentLists.
2126
+ // This element is stored in the model as an attribute on a block element, for example Lists.
2079
2127
  if (definition.appliesToBlock) {
2080
2128
  return;
2081
2129
  }
@@ -2431,9 +2479,10 @@ var defaultConfig = {
2431
2479
  * * model element HTML is semantically correct and easier to work with.
2432
2480
  *
2433
2481
  * If element contains any block element, it will be treated as a sectioning element and registered using
2434
- * {@link module:html-support/dataschema~DataSchemaDefinition#model} and
2435
- * {@link module:html-support/dataschema~DataSchemaDefinition#modelSchema} in editor schema.
2436
- * Otherwise, it will be registered under {@link module:html-support/dataschema~DataSchemaBlockElementDefinition#paragraphLikeModel} model
2482
+ * {@link module:html-support/dataschema~HtmlSupportDataSchemaDefinition#model} and
2483
+ * {@link module:html-support/dataschema~HtmlSupportDataSchemaDefinition#modelSchema} in editor schema.
2484
+ * Otherwise, it will be registered under
2485
+ * {@link module:html-support/dataschema~HtmlSupportDataSchemaBlockElementDefinition#paragraphLikeModel} model
2437
2486
  * name with model schema accepting only inline content (inheriting from `$block`).
2438
2487
  */ class DualContentModelElementSupport extends Plugin {
2439
2488
  /**
@@ -3567,8 +3616,9 @@ const STYLE_ATTRIBUTES_TO_PROPAGATE = [
3567
3616
  if (viewElement.is('element', 'template') && viewElement.getCustomProperty('$rawContent')) {
3568
3617
  htmlContent = viewElement.getCustomProperty('$rawContent');
3569
3618
  } else {
3570
- // Store the whole element in the attribute so that DomConverter will be able to use the pre like element context.
3571
- const viewWriter = new UpcastWriter(viewElement.document);
3619
+ // Store the whole element in the attribute so that ViewDomConverter
3620
+ // will be able to use the pre like element context.
3621
+ const viewWriter = new ViewUpcastWriter(viewElement.document);
3572
3622
  const documentFragment = viewWriter.createDocumentFragment(viewElement);
3573
3623
  const domFragment = editor.data.htmlProcessor.domConverter.viewToDom(documentFragment);
3574
3624
  const domElement = domFragment.firstChild;
@@ -3690,6 +3740,12 @@ const STYLE_ATTRIBUTES_TO_PROPAGATE = [
3690
3740
  dataFilter.loadAllowedConfig(editor.config.get('htmlSupport.allow') || []);
3691
3741
  dataFilter.loadDisallowedConfig(editor.config.get('htmlSupport.disallow') || []);
3692
3742
  }
3743
+ /**
3744
+ * @inheritDoc
3745
+ */ afterInit() {
3746
+ const removeFormatCommand = this.editor.commands.get('removeFormat');
3747
+ removeFormatCommand?.registerCustomAttribute((attributeName)=>attributeName.startsWith('html') && attributeName.endsWith('Attributes'), removeFormatting);
3748
+ }
3693
3749
  /**
3694
3750
  * Returns a GHS model attribute name related to a given view element name.
3695
3751
  *
@@ -4095,7 +4151,7 @@ const STYLE_ATTRIBUTES_TO_PROPAGATE = [
4095
4151
  const viewFragment = this.domConverter.domToView(domFragment, {
4096
4152
  skipComments: this.skipComments
4097
4153
  });
4098
- const writer = new UpcastWriter(viewFragment.document);
4154
+ const writer = new ViewUpcastWriter(viewFragment.document);
4099
4155
  // Using the DOM document with body content extracted as a skeleton of the page.
4100
4156
  writer.setCustomProperty('$fullPageDocument', domFragment.ownerDocument.documentElement.outerHTML, viewFragment);
4101
4157
  // List of `<style>` elements extracted from document's `<head>` element.
@@ -4206,7 +4262,7 @@ const STYLE_ATTRIBUTES_TO_PROPAGATE = [
4206
4262
  if (!root.hasAttribute('$fullPageDocument')) {
4207
4263
  return;
4208
4264
  }
4209
- const writer = new UpcastWriter(viewFragment.document);
4265
+ const writer = new ViewUpcastWriter(viewFragment.document);
4210
4266
  for (const name of properties){
4211
4267
  const value = root.getAttribute(name);
4212
4268
  if (value) {
@@ -4439,5 +4495,5 @@ const EMPTY_BLOCK_MODEL_ATTRIBUTE = 'htmlEmptyBlock';
4439
4495
  };
4440
4496
  }
4441
4497
 
4442
- export { DataFilter, DataSchema, EmptyBlock, FullPage, GeneralHtmlSupport, HtmlComment, HtmlPageDataProcessor };
4498
+ export { DataFilter, DataSchema, EmptyBlock, FullPage, GeneralHtmlSupport, HtmlComment, HtmlPageDataProcessor, defaultConfig as _HTML_SUPPORT_SCHEMA_DEFINITIONS, attributeToViewInlineConverter as _attributeToInlineHtmlSupportConverter, createObjectView as _createObjectHtmlSupportView, emptyInlineModelElementToViewConverter as _emptyInlineModelElementToViewHtmlSupportConverter, getHtmlAttributeName as _getHtmlSupportAttributeName, getDescendantElement as _getHtmlSupportDescendantElement, mergeViewElementAttributes as _mergeHtmlSupportViewElementAttributes, modelToViewBlockAttributeConverter as _modelToViewBlockAttributeHtmlSupportConverter, modifyGhsAttribute as _modifyHtmlSupportGhsAttribute, removeViewAttributes as _removeHtmlSupportViewAttributes, setViewAttributes as _setHtmlSupportViewAttributes, toPascalCase as _toHtmlSupportPascalCase, toObjectWidgetConverter as _toObjectWidgetHtmlSupportConverter, updateViewAttributes as _updateHtmlSupportViewAttributes, viewToAttributeInlineConverter as _viewToAttributeInlineHtmlSupportConverter, viewToModelBlockAttributeConverter as _viewToModelBlockAttributeHtmlSupportConverter, viewToModelObjectConverter as _viewToModelObjectContentHtmlSupportConverter };
4443
4499
  //# sourceMappingURL=index.js.map