@ckeditor/ckeditor5-html-support 41.4.1 → 42.0.0-alpha.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/dist/index.js CHANGED
@@ -1297,15 +1297,49 @@ var defaultConfig = {
1297
1297
  ]
1298
1298
  };
1299
1299
 
1300
- class DataSchema extends Plugin {
1301
- /**
1302
- * @inheritDoc
1303
- */ static get pluginName() {
1300
+ /**
1301
+ * Holds representation of the extended HTML document type definitions to be used by the
1302
+ * editor in HTML support.
1303
+ *
1304
+ * Data schema is represented by data schema definitions.
1305
+ *
1306
+ * To add new definition for block element,
1307
+ * use {@link module:html-support/dataschema~DataSchema#registerBlockElement} method:
1308
+ *
1309
+ * ```ts
1310
+ * dataSchema.registerBlockElement( {
1311
+ * view: 'section',
1312
+ * model: 'my-section',
1313
+ * modelSchema: {
1314
+ * inheritAllFrom: '$block'
1315
+ * }
1316
+ * } );
1317
+ * ```
1318
+ *
1319
+ * To add new definition for inline element,
1320
+ * use {@link module:html-support/dataschema~DataSchema#registerInlineElement} method:
1321
+ *
1322
+ * ```
1323
+ * dataSchema.registerInlineElement( {
1324
+ * view: 'span',
1325
+ * model: 'my-span',
1326
+ * attributeProperties: {
1327
+ * copyOnEnter: true
1328
+ * }
1329
+ * } );
1330
+ * ```
1331
+ */ class DataSchema extends Plugin {
1332
+ /**
1333
+ * A map of registered data schema definitions.
1334
+ */ _definitions = [];
1335
+ /**
1336
+ * @inheritDoc
1337
+ */ static get pluginName() {
1304
1338
  return 'DataSchema';
1305
1339
  }
1306
1340
  /**
1307
- * @inheritDoc
1308
- */ init() {
1341
+ * @inheritDoc
1342
+ */ init() {
1309
1343
  for (const definition of defaultConfig.block){
1310
1344
  this.registerBlockElement(definition);
1311
1345
  }
@@ -1314,52 +1348,52 @@ class DataSchema extends Plugin {
1314
1348
  }
1315
1349
  }
1316
1350
  /**
1317
- * Add new data schema definition describing block element.
1318
- */ registerBlockElement(definition) {
1351
+ * Add new data schema definition describing block element.
1352
+ */ registerBlockElement(definition) {
1319
1353
  this._definitions.push({
1320
1354
  ...definition,
1321
1355
  isBlock: true
1322
1356
  });
1323
1357
  }
1324
1358
  /**
1325
- * Add new data schema definition describing inline element.
1326
- */ registerInlineElement(definition) {
1359
+ * Add new data schema definition describing inline element.
1360
+ */ registerInlineElement(definition) {
1327
1361
  this._definitions.push({
1328
1362
  ...definition,
1329
1363
  isInline: true
1330
1364
  });
1331
1365
  }
1332
1366
  /**
1333
- * Updates schema definition describing block element with new properties.
1334
- *
1335
- * Creates new scheme if it doesn't exist.
1336
- * Array properties are concatenated with original values.
1337
- *
1338
- * @param definition Definition update.
1339
- */ extendBlockElement(definition) {
1367
+ * Updates schema definition describing block element with new properties.
1368
+ *
1369
+ * Creates new scheme if it doesn't exist.
1370
+ * Array properties are concatenated with original values.
1371
+ *
1372
+ * @param definition Definition update.
1373
+ */ extendBlockElement(definition) {
1340
1374
  this._extendDefinition({
1341
1375
  ...definition,
1342
1376
  isBlock: true
1343
1377
  });
1344
1378
  }
1345
1379
  /**
1346
- * Updates schema definition describing inline element with new properties.
1347
- *
1348
- * Creates new scheme if it doesn't exist.
1349
- * Array properties are concatenated with original values.
1350
- *
1351
- * @param definition Definition update.
1352
- */ extendInlineElement(definition) {
1380
+ * Updates schema definition describing inline element with new properties.
1381
+ *
1382
+ * Creates new scheme if it doesn't exist.
1383
+ * Array properties are concatenated with original values.
1384
+ *
1385
+ * @param definition Definition update.
1386
+ */ extendInlineElement(definition) {
1353
1387
  this._extendDefinition({
1354
1388
  ...definition,
1355
1389
  isInline: true
1356
1390
  });
1357
1391
  }
1358
1392
  /**
1359
- * Returns all definitions matching the given view name.
1360
- *
1361
- * @param includeReferences Indicates if this method should also include definitions of referenced models.
1362
- */ getDefinitionsForView(viewName, includeReferences = false) {
1393
+ * Returns all definitions matching the given view name.
1394
+ *
1395
+ * @param includeReferences Indicates if this method should also include definitions of referenced models.
1396
+ */ getDefinitionsForView(viewName, includeReferences = false) {
1363
1397
  const definitions = new Set();
1364
1398
  for (const definition of this._getMatchingViewDefinitions(viewName)){
1365
1399
  if (includeReferences) {
@@ -1372,20 +1406,20 @@ class DataSchema extends Plugin {
1372
1406
  return definitions;
1373
1407
  }
1374
1408
  /**
1375
- * Returns definitions matching the given model name.
1376
- */ getDefinitionsForModel(modelName) {
1409
+ * Returns definitions matching the given model name.
1410
+ */ getDefinitionsForModel(modelName) {
1377
1411
  return this._definitions.filter((definition)=>definition.model == modelName);
1378
1412
  }
1379
1413
  /**
1380
- * Returns definitions matching the given view name.
1381
- */ _getMatchingViewDefinitions(viewName) {
1414
+ * Returns definitions matching the given view name.
1415
+ */ _getMatchingViewDefinitions(viewName) {
1382
1416
  return this._definitions.filter((def)=>def.view && testViewName(viewName, def.view));
1383
1417
  }
1384
1418
  /**
1385
- * Resolves all definition references registered for the given data schema definition.
1386
- *
1387
- * @param modelName Data schema model name.
1388
- */ *_getReferences(modelName) {
1419
+ * Resolves all definition references registered for the given data schema definition.
1420
+ *
1421
+ * @param modelName Data schema model name.
1422
+ */ *_getReferences(modelName) {
1389
1423
  const inheritProperties = [
1390
1424
  'inheritAllFrom',
1391
1425
  'inheritTypesFrom',
@@ -1412,13 +1446,13 @@ class DataSchema extends Plugin {
1412
1446
  }
1413
1447
  }
1414
1448
  /**
1415
- * Updates schema definition with new properties.
1416
- *
1417
- * Creates new scheme if it doesn't exist.
1418
- * Array properties are concatenated with original values.
1419
- *
1420
- * @param definition Definition update.
1421
- */ _extendDefinition(definition) {
1449
+ * Updates schema definition with new properties.
1450
+ *
1451
+ * Creates new scheme if it doesn't exist.
1452
+ * Array properties are concatenated with original values.
1453
+ *
1454
+ * @param definition Definition update.
1455
+ */ _extendDefinition(definition) {
1422
1456
  const currentDefinitions = Array.from(this._definitions.entries()).filter(([, currentDefinition])=>currentDefinition.model == definition.model);
1423
1457
  if (currentDefinitions.length == 0) {
1424
1458
  this._definitions.push(definition);
@@ -1430,12 +1464,6 @@ class DataSchema extends Plugin {
1430
1464
  });
1431
1465
  }
1432
1466
  }
1433
- constructor(){
1434
- super(...arguments);
1435
- /**
1436
- * A map of registered data schema definitions.
1437
- */ this._definitions = [];
1438
- }
1439
1467
  }
1440
1468
  /**
1441
1469
  * Test view name against the given pattern.
@@ -1449,27 +1477,97 @@ class DataSchema extends Plugin {
1449
1477
  return false;
1450
1478
  }
1451
1479
 
1452
- class DataFilter extends Plugin {
1480
+ /**
1481
+ * Allows to validate elements and element attributes registered by {@link module:html-support/dataschema~DataSchema}.
1482
+ *
1483
+ * To enable registered element in the editor, use {@link module:html-support/datafilter~DataFilter#allowElement} method:
1484
+ *
1485
+ * ```ts
1486
+ * dataFilter.allowElement( 'section' );
1487
+ * ```
1488
+ *
1489
+ * You can also allow or disallow specific element attributes:
1490
+ *
1491
+ * ```ts
1492
+ * // Allow `data-foo` attribute on `section` element.
1493
+ * dataFilter.allowAttributes( {
1494
+ * name: 'section',
1495
+ * attributes: {
1496
+ * 'data-foo': true
1497
+ * }
1498
+ * } );
1499
+ *
1500
+ * // Disallow `color` style attribute on 'section' element.
1501
+ * dataFilter.disallowAttributes( {
1502
+ * name: 'section',
1503
+ * styles: {
1504
+ * color: /[\s\S]+/
1505
+ * }
1506
+ * } );
1507
+ * ```
1508
+ *
1509
+ * To apply the information about allowed and disallowed attributes in custom integration plugin,
1510
+ * use the {@link module:html-support/datafilter~DataFilter#processViewAttributes `processViewAttributes()`} method.
1511
+ */ class DataFilter extends Plugin {
1512
+ /**
1513
+ * An instance of the {@link module:html-support/dataschema~DataSchema}.
1514
+ */ _dataSchema;
1515
+ /**
1516
+ * {@link module:engine/view/matcher~Matcher Matcher} instance describing rules upon which
1517
+ * content attributes should be allowed.
1518
+ */ _allowedAttributes;
1519
+ /**
1520
+ * {@link module:engine/view/matcher~Matcher Matcher} instance describing rules upon which
1521
+ * content attributes should be disallowed.
1522
+ */ _disallowedAttributes;
1523
+ /**
1524
+ * Allowed element definitions by {@link module:html-support/datafilter~DataFilter#allowElement} method.
1525
+ */ _allowedElements;
1526
+ /**
1527
+ * Disallowed element names by {@link module:html-support/datafilter~DataFilter#disallowElement} method.
1528
+ */ _disallowedElements;
1529
+ /**
1530
+ * Indicates if {@link module:engine/controller/datacontroller~DataController editor's data controller}
1531
+ * data has been already initialized.
1532
+ */ _dataInitialized;
1533
+ /**
1534
+ * Cached map of coupled attributes. Keys are the feature attributes names
1535
+ * and values are arrays with coupled GHS attributes names.
1536
+ */ _coupledAttributes;
1537
+ constructor(editor){
1538
+ super(editor);
1539
+ this._dataSchema = editor.plugins.get('DataSchema');
1540
+ this._allowedAttributes = new Matcher();
1541
+ this._disallowedAttributes = new Matcher();
1542
+ this._allowedElements = new Set();
1543
+ this._disallowedElements = new Set();
1544
+ this._dataInitialized = false;
1545
+ this._coupledAttributes = null;
1546
+ this._registerElementsAfterInit();
1547
+ this._registerElementHandlers();
1548
+ this._registerCoupledAttributesPostFixer();
1549
+ this._registerAssociatedHtmlAttributesPostFixer();
1550
+ }
1453
1551
  /**
1454
- * @inheritDoc
1455
- */ static get pluginName() {
1552
+ * @inheritDoc
1553
+ */ static get pluginName() {
1456
1554
  return 'DataFilter';
1457
1555
  }
1458
1556
  /**
1459
- * @inheritDoc
1460
- */ static get requires() {
1557
+ * @inheritDoc
1558
+ */ static get requires() {
1461
1559
  return [
1462
1560
  DataSchema,
1463
1561
  Widget
1464
1562
  ];
1465
1563
  }
1466
1564
  /**
1467
- * Load a configuration of one or many elements, where their attributes should be allowed.
1468
- *
1469
- * **Note**: Rules will be applied just before next data pipeline data init or set.
1470
- *
1471
- * @param config Configuration of elements that should have their attributes accepted in the editor.
1472
- */ loadAllowedConfig(config) {
1565
+ * Load a configuration of one or many elements, where their attributes should be allowed.
1566
+ *
1567
+ * **Note**: Rules will be applied just before next data pipeline data init or set.
1568
+ *
1569
+ * @param config Configuration of elements that should have their attributes accepted in the editor.
1570
+ */ loadAllowedConfig(config) {
1473
1571
  for (const pattern of config){
1474
1572
  // MatcherPattern allows omitting `name` to widen the search of elements.
1475
1573
  // Let's keep it consistent and match every element if a `name` has not been provided.
@@ -1480,12 +1578,12 @@ class DataFilter extends Plugin {
1480
1578
  }
1481
1579
  }
1482
1580
  /**
1483
- * Load a configuration of one or many elements, where their attributes should be disallowed.
1484
- *
1485
- * **Note**: Rules will be applied just before next data pipeline data init or set.
1486
- *
1487
- * @param config Configuration of elements that should have their attributes rejected from the editor.
1488
- */ loadDisallowedConfig(config) {
1581
+ * Load a configuration of one or many elements, where their attributes should be disallowed.
1582
+ *
1583
+ * **Note**: Rules will be applied just before next data pipeline data init or set.
1584
+ *
1585
+ * @param config Configuration of elements that should have their attributes rejected from the editor.
1586
+ */ loadDisallowedConfig(config) {
1489
1587
  for (const pattern of config){
1490
1588
  // MatcherPattern allows omitting `name` to widen the search of elements.
1491
1589
  // Let's keep it consistent and match every element if a `name` has not been provided.
@@ -1500,26 +1598,26 @@ class DataFilter extends Plugin {
1500
1598
  }
1501
1599
  }
1502
1600
  /**
1503
- * Load a configuration of one or many elements, where when empty should be allowed.
1504
- *
1505
- * **Note**: It modifies DataSchema so must be loaded before registering filtering rules.
1506
- *
1507
- * @param config Configuration of elements that should be preserved even if empty.
1508
- */ loadAllowedEmptyElementsConfig(config) {
1601
+ * Load a configuration of one or many elements, where when empty should be allowed.
1602
+ *
1603
+ * **Note**: It modifies DataSchema so must be loaded before registering filtering rules.
1604
+ *
1605
+ * @param config Configuration of elements that should be preserved even if empty.
1606
+ */ loadAllowedEmptyElementsConfig(config) {
1509
1607
  for (const elementName of config){
1510
1608
  this.allowEmptyElement(elementName);
1511
1609
  }
1512
1610
  }
1513
1611
  /**
1514
- * Allow the given element in the editor context.
1515
- *
1516
- * This method will only allow elements described by the {@link module:html-support/dataschema~DataSchema} used
1517
- * to create data filter.
1518
- *
1519
- * **Note**: Rules will be applied just before next data pipeline data init or set.
1520
- *
1521
- * @param viewName String or regular expression matching view name.
1522
- */ allowElement(viewName) {
1612
+ * Allow the given element in the editor context.
1613
+ *
1614
+ * This method will only allow elements described by the {@link module:html-support/dataschema~DataSchema} used
1615
+ * to create data filter.
1616
+ *
1617
+ * **Note**: Rules will be applied just before next data pipeline data init or set.
1618
+ *
1619
+ * @param viewName String or regular expression matching view name.
1620
+ */ allowElement(viewName) {
1523
1621
  for (const definition of this._dataSchema.getDefinitionsForView(viewName, true)){
1524
1622
  this._addAllowedElement(definition);
1525
1623
  // Reset cached map to recalculate it on the next usage.
@@ -1527,27 +1625,27 @@ class DataFilter extends Plugin {
1527
1625
  }
1528
1626
  }
1529
1627
  /**
1530
- * Disallow the given element in the editor context.
1531
- *
1532
- * This method will only disallow elements described by the {@link module:html-support/dataschema~DataSchema} used
1533
- * to create data filter.
1534
- *
1535
- * @param viewName String or regular expression matching view name.
1536
- */ disallowElement(viewName) {
1628
+ * Disallow the given element in the editor context.
1629
+ *
1630
+ * This method will only disallow elements described by the {@link module:html-support/dataschema~DataSchema} used
1631
+ * to create data filter.
1632
+ *
1633
+ * @param viewName String or regular expression matching view name.
1634
+ */ disallowElement(viewName) {
1537
1635
  for (const definition of this._dataSchema.getDefinitionsForView(viewName, false)){
1538
1636
  this._disallowedElements.add(definition.view);
1539
1637
  }
1540
1638
  }
1541
1639
  /**
1542
- * Allow the given empty element in the editor context.
1543
- *
1544
- * This method will only allow elements described by the {@link module:html-support/dataschema~DataSchema} used
1545
- * to create data filter.
1546
- *
1547
- * **Note**: It modifies DataSchema so must be called before registering filtering rules.
1548
- *
1549
- * @param viewName String or regular expression matching view name.
1550
- */ allowEmptyElement(viewName) {
1640
+ * Allow the given empty element in the editor context.
1641
+ *
1642
+ * This method will only allow elements described by the {@link module:html-support/dataschema~DataSchema} used
1643
+ * to create data filter.
1644
+ *
1645
+ * **Note**: It modifies DataSchema so must be called before registering filtering rules.
1646
+ *
1647
+ * @param viewName String or regular expression matching view name.
1648
+ */ allowEmptyElement(viewName) {
1551
1649
  for (const definition of this._dataSchema.getDefinitionsForView(viewName, true)){
1552
1650
  if (definition.isInline) {
1553
1651
  this._dataSchema.extendInlineElement({
@@ -1558,44 +1656,44 @@ class DataFilter extends Plugin {
1558
1656
  }
1559
1657
  }
1560
1658
  /**
1561
- * Allow the given attributes for view element allowed by {@link #allowElement} method.
1562
- *
1563
- * @param config Pattern matching all attributes which should be allowed.
1564
- */ allowAttributes(config) {
1659
+ * Allow the given attributes for view element allowed by {@link #allowElement} method.
1660
+ *
1661
+ * @param config Pattern matching all attributes which should be allowed.
1662
+ */ allowAttributes(config) {
1565
1663
  this._allowedAttributes.add(config);
1566
1664
  }
1567
1665
  /**
1568
- * Disallow the given attributes for view element allowed by {@link #allowElement} method.
1569
- *
1570
- * @param config Pattern matching all attributes which should be disallowed.
1571
- */ disallowAttributes(config) {
1666
+ * Disallow the given attributes for view element allowed by {@link #allowElement} method.
1667
+ *
1668
+ * @param config Pattern matching all attributes which should be disallowed.
1669
+ */ disallowAttributes(config) {
1572
1670
  this._disallowedAttributes.add(config);
1573
1671
  }
1574
1672
  /**
1575
- * Processes all allowed and disallowed attributes on the view element by consuming them and returning the allowed ones.
1576
- *
1577
- * This method applies the configuration set up by {@link #allowAttributes `allowAttributes()`}
1578
- * and {@link #disallowAttributes `disallowAttributes()`} over the given view element by consuming relevant attributes.
1579
- * It returns the allowed attributes that were found on the given view element for further processing by integration code.
1580
- *
1581
- * ```ts
1582
- * dispatcher.on( 'element:myElement', ( evt, data, conversionApi ) => {
1583
- * // Get rid of disallowed and extract all allowed attributes from a viewElement.
1584
- * const viewAttributes = dataFilter.processViewAttributes( data.viewItem, conversionApi );
1585
- * // Do something with them, i.e. store inside a model as a dictionary.
1586
- * if ( viewAttributes ) {
1587
- * conversionApi.writer.setAttribute( 'htmlAttributesOfMyElement', viewAttributes, data.modelRange );
1588
- * }
1589
- * } );
1590
- * ```
1591
- *
1592
- * @see module:engine/conversion/viewconsumable~ViewConsumable#consume
1593
- *
1594
- * @returns Object with following properties:
1595
- * - attributes Set with matched attribute names.
1596
- * - styles Set with matched style names.
1597
- * - classes Set with matched class names.
1598
- */ processViewAttributes(viewElement, conversionApi) {
1673
+ * Processes all allowed and disallowed attributes on the view element by consuming them and returning the allowed ones.
1674
+ *
1675
+ * This method applies the configuration set up by {@link #allowAttributes `allowAttributes()`}
1676
+ * and {@link #disallowAttributes `disallowAttributes()`} over the given view element by consuming relevant attributes.
1677
+ * It returns the allowed attributes that were found on the given view element for further processing by integration code.
1678
+ *
1679
+ * ```ts
1680
+ * dispatcher.on( 'element:myElement', ( evt, data, conversionApi ) => {
1681
+ * // Get rid of disallowed and extract all allowed attributes from a viewElement.
1682
+ * const viewAttributes = dataFilter.processViewAttributes( data.viewItem, conversionApi );
1683
+ * // Do something with them, i.e. store inside a model as a dictionary.
1684
+ * if ( viewAttributes ) {
1685
+ * conversionApi.writer.setAttribute( 'htmlAttributesOfMyElement', viewAttributes, data.modelRange );
1686
+ * }
1687
+ * } );
1688
+ * ```
1689
+ *
1690
+ * @see module:engine/conversion/viewconsumable~ViewConsumable#consume
1691
+ *
1692
+ * @returns Object with following properties:
1693
+ * - attributes Set with matched attribute names.
1694
+ * - styles Set with matched style names.
1695
+ * - classes Set with matched class names.
1696
+ */ processViewAttributes(viewElement, conversionApi) {
1599
1697
  const { consumable } = conversionApi;
1600
1698
  // Make sure that the disabled attributes are handled before the allowed attributes are called.
1601
1699
  // For example, for block images the <figure> converter triggers conversion for <img> first and then for other elements, i.e. <a>.
@@ -1603,8 +1701,8 @@ class DataFilter extends Plugin {
1603
1701
  return prepareGHSAttribute(viewElement, matchAndConsumeAttributes(viewElement, this._allowedAttributes, consumable));
1604
1702
  }
1605
1703
  /**
1606
- * Adds allowed element definition and fires registration event.
1607
- */ _addAllowedElement(definition) {
1704
+ * Adds allowed element definition and fires registration event.
1705
+ */ _addAllowedElement(definition) {
1608
1706
  if (this._allowedElements.has(definition)) {
1609
1707
  return;
1610
1708
  }
@@ -1634,9 +1732,9 @@ class DataFilter extends Plugin {
1634
1732
  }
1635
1733
  }
1636
1734
  /**
1637
- * Registers elements allowed by {@link module:html-support/datafilter~DataFilter#allowElement} method
1638
- * once {@link module:engine/controller/datacontroller~DataController editor's data controller} is initialized.
1639
- */ _registerElementsAfterInit() {
1735
+ * Registers elements allowed by {@link module:html-support/datafilter~DataFilter#allowElement} method
1736
+ * once {@link module:engine/controller/datacontroller~DataController editor's data controller} is initialized.
1737
+ */ _registerElementsAfterInit() {
1640
1738
  this.editor.data.on('init', ()=>{
1641
1739
  this._dataInitialized = true;
1642
1740
  for (const definition of this._allowedElements){
@@ -1654,8 +1752,8 @@ class DataFilter extends Plugin {
1654
1752
  });
1655
1753
  }
1656
1754
  /**
1657
- * Registers default element handlers.
1658
- */ _registerElementHandlers() {
1755
+ * Registers default element handlers.
1756
+ */ _registerElementHandlers() {
1659
1757
  this.on('register', (evt, definition)=>{
1660
1758
  const schema = this.editor.model.schema;
1661
1759
  // Object element should be only registered for new features.
@@ -1669,12 +1767,12 @@ class DataFilter extends Plugin {
1669
1767
  this._registerInlineElement(definition);
1670
1768
  } else {
1671
1769
  /**
1672
- * The definition cannot be handled by the data filter.
1673
- *
1674
- * Make sure that the registered definition is correct.
1675
- *
1676
- * @error data-filter-invalid-definition
1677
- */ throw new CKEditorError('data-filter-invalid-definition', null, definition);
1770
+ * The definition cannot be handled by the data filter.
1771
+ *
1772
+ * Make sure that the registered definition is correct.
1773
+ *
1774
+ * @error data-filter-invalid-definition
1775
+ */ throw new CKEditorError('data-filter-invalid-definition', null, definition);
1678
1776
  }
1679
1777
  evt.stop();
1680
1778
  }, {
@@ -1682,30 +1780,30 @@ class DataFilter extends Plugin {
1682
1780
  });
1683
1781
  }
1684
1782
  /**
1685
- * Registers a model post-fixer that is removing coupled GHS attributes of inline elements. Those attributes
1686
- * are removed if a coupled feature attribute is removed.
1687
- *
1688
- * For example, consider following HTML:
1689
- *
1690
- * ```html
1691
- * <a href="foo.html" id="myId">bar</a>
1692
- * ```
1693
- *
1694
- * Which would be upcasted to following text node in the model:
1695
- *
1696
- * ```html
1697
- * <$text linkHref="foo.html" htmlA="{ attributes: { id: 'myId' } }">bar</$text>
1698
- * ```
1699
- *
1700
- * When the user removes the link from that text (using UI), only `linkHref` attribute would be removed:
1701
- *
1702
- * ```html
1703
- * <$text htmlA="{ attributes: { id: 'myId' } }">bar</$text>
1704
- * ```
1705
- *
1706
- * The `htmlA` attribute would stay in the model and would cause GHS to generate an `<a>` element.
1707
- * This is incorrect from UX point of view, as the user wanted to remove the whole link (not only `href`).
1708
- */ _registerCoupledAttributesPostFixer() {
1783
+ * Registers a model post-fixer that is removing coupled GHS attributes of inline elements. Those attributes
1784
+ * are removed if a coupled feature attribute is removed.
1785
+ *
1786
+ * For example, consider following HTML:
1787
+ *
1788
+ * ```html
1789
+ * <a href="foo.html" id="myId">bar</a>
1790
+ * ```
1791
+ *
1792
+ * Which would be upcasted to following text node in the model:
1793
+ *
1794
+ * ```html
1795
+ * <$text linkHref="foo.html" htmlA="{ attributes: { id: 'myId' } }">bar</$text>
1796
+ * ```
1797
+ *
1798
+ * When the user removes the link from that text (using UI), only `linkHref` attribute would be removed:
1799
+ *
1800
+ * ```html
1801
+ * <$text htmlA="{ attributes: { id: 'myId' } }">bar</$text>
1802
+ * ```
1803
+ *
1804
+ * The `htmlA` attribute would stay in the model and would cause GHS to generate an `<a>` element.
1805
+ * This is incorrect from UX point of view, as the user wanted to remove the whole link (not only `href`).
1806
+ */ _registerCoupledAttributesPostFixer() {
1709
1807
  const model = this.editor.model;
1710
1808
  const selection = model.document.selection;
1711
1809
  model.document.registerPostFixer((writer)=>{
@@ -1764,34 +1862,34 @@ class DataFilter extends Plugin {
1764
1862
  });
1765
1863
  }
1766
1864
  /**
1767
- * Removes `html*Attributes` attributes from incompatible elements.
1768
- *
1769
- * For example, consider the following HTML:
1770
- *
1771
- * ```html
1772
- * <heading2 htmlH2Attributes="...">foobar[]</heading2>
1773
- * ```
1774
- *
1775
- * Pressing `enter` creates a new `paragraph` element that inherits
1776
- * the `htmlH2Attributes` attribute from `heading2`.
1777
- *
1778
- * ```html
1779
- * <heading2 htmlH2Attributes="...">foobar</heading2>
1780
- * <paragraph htmlH2Attributes="...">[]</paragraph>
1781
- * ```
1782
- *
1783
- * This postfixer ensures that this doesn't happen, and that elements can
1784
- * only have `html*Attributes` associated with them,
1785
- * e.g.: `htmlPAttributes` for `<p>`, `htmlDivAttributes` for `<div>`, etc.
1786
- *
1787
- * With it enabled, pressing `enter` at the end of `<heading2>` will create
1788
- * a new paragraph without the `htmlH2Attributes` attribute.
1789
- *
1790
- * ```html
1791
- * <heading2 htmlH2Attributes="...">foobar</heading2>
1792
- * <paragraph>[]</paragraph>
1793
- * ```
1794
- */ _registerAssociatedHtmlAttributesPostFixer() {
1865
+ * Removes `html*Attributes` attributes from incompatible elements.
1866
+ *
1867
+ * For example, consider the following HTML:
1868
+ *
1869
+ * ```html
1870
+ * <heading2 htmlH2Attributes="...">foobar[]</heading2>
1871
+ * ```
1872
+ *
1873
+ * Pressing `enter` creates a new `paragraph` element that inherits
1874
+ * the `htmlH2Attributes` attribute from `heading2`.
1875
+ *
1876
+ * ```html
1877
+ * <heading2 htmlH2Attributes="...">foobar</heading2>
1878
+ * <paragraph htmlH2Attributes="...">[]</paragraph>
1879
+ * ```
1880
+ *
1881
+ * This postfixer ensures that this doesn't happen, and that elements can
1882
+ * only have `html*Attributes` associated with them,
1883
+ * e.g.: `htmlPAttributes` for `<p>`, `htmlDivAttributes` for `<div>`, etc.
1884
+ *
1885
+ * With it enabled, pressing `enter` at the end of `<heading2>` will create
1886
+ * a new paragraph without the `htmlH2Attributes` attribute.
1887
+ *
1888
+ * ```html
1889
+ * <heading2 htmlH2Attributes="...">foobar</heading2>
1890
+ * <paragraph>[]</paragraph>
1891
+ * ```
1892
+ */ _registerAssociatedHtmlAttributesPostFixer() {
1795
1893
  const model = this.editor.model;
1796
1894
  model.document.registerPostFixer((writer)=>{
1797
1895
  const changes = model.document.differ.getChanges();
@@ -1814,9 +1912,9 @@ class DataFilter extends Plugin {
1814
1912
  });
1815
1913
  }
1816
1914
  /**
1817
- * Collects the map of coupled attributes. The returned map is keyed by the feature attribute name
1818
- * and coupled GHS attribute names are stored in the value array.
1819
- */ _getCoupledAttributesMap() {
1915
+ * Collects the map of coupled attributes. The returned map is keyed by the feature attribute name
1916
+ * and coupled GHS attribute names are stored in the value array.
1917
+ */ _getCoupledAttributesMap() {
1820
1918
  if (this._coupledAttributes) {
1821
1919
  return this._coupledAttributes;
1822
1920
  }
@@ -1836,16 +1934,16 @@ class DataFilter extends Plugin {
1836
1934
  return this._coupledAttributes;
1837
1935
  }
1838
1936
  /**
1839
- * Fires `register` event for the given element definition.
1840
- */ _fireRegisterEvent(definition) {
1937
+ * Fires `register` event for the given element definition.
1938
+ */ _fireRegisterEvent(definition) {
1841
1939
  if (definition.view && this._disallowedElements.has(definition.view)) {
1842
1940
  return;
1843
1941
  }
1844
1942
  this.fire(definition.view ? `register:${definition.view}` : 'register', definition);
1845
1943
  }
1846
1944
  /**
1847
- * Registers object element and attribute converters for the given data schema definition.
1848
- */ _registerObjectElement(definition) {
1945
+ * Registers object element and attribute converters for the given data schema definition.
1946
+ */ _registerObjectElement(definition) {
1849
1947
  const editor = this.editor;
1850
1948
  const schema = editor.model.schema;
1851
1949
  const conversion = editor.conversion;
@@ -1892,8 +1990,8 @@ class DataFilter extends Plugin {
1892
1990
  conversion.for('dataDowncast').add(modelToViewBlockAttributeConverter(definition));
1893
1991
  }
1894
1992
  /**
1895
- * Registers block element and attribute converters for the given data schema definition.
1896
- */ _registerBlockElement(definition) {
1993
+ * Registers block element and attribute converters for the given data schema definition.
1994
+ */ _registerBlockElement(definition) {
1897
1995
  const editor = this.editor;
1898
1996
  const schema = editor.model.schema;
1899
1997
  const conversion = editor.conversion;
@@ -1926,10 +2024,10 @@ class DataFilter extends Plugin {
1926
2024
  conversion.for('downcast').add(modelToViewBlockAttributeConverter(definition));
1927
2025
  }
1928
2026
  /**
1929
- * Registers inline element and attribute converters for the given data schema definition.
1930
- *
1931
- * Extends `$text` model schema to allow the given definition model attribute and its properties.
1932
- */ _registerInlineElement(definition) {
2027
+ * Registers inline element and attribute converters for the given data schema definition.
2028
+ *
2029
+ * Extends `$text` model schema to allow the given definition model attribute and its properties.
2030
+ */ _registerInlineElement(definition) {
1933
2031
  const editor = this.editor;
1934
2032
  const schema = editor.model.schema;
1935
2033
  const conversion = editor.conversion;
@@ -1978,20 +2076,6 @@ class DataFilter extends Plugin {
1978
2076
  view: emptyInlineModelElementToViewConverter(definition)
1979
2077
  });
1980
2078
  }
1981
- constructor(editor){
1982
- super(editor);
1983
- this._dataSchema = editor.plugins.get('DataSchema');
1984
- this._allowedAttributes = new Matcher();
1985
- this._disallowedAttributes = new Matcher();
1986
- this._allowedElements = new Set();
1987
- this._disallowedElements = new Set();
1988
- this._dataInitialized = false;
1989
- this._coupledAttributes = null;
1990
- this._registerElementsAfterInit();
1991
- this._registerElementHandlers();
1992
- this._registerCoupledAttributesPostFixer();
1993
- this._registerAssociatedHtmlAttributesPostFixer();
1994
- }
1995
2079
  }
1996
2080
  /**
1997
2081
  * Matches and consumes matched attributes.
@@ -2155,22 +2239,24 @@ class DataFilter extends Plugin {
2155
2239
  return splitRules;
2156
2240
  }
2157
2241
 
2158
- class CodeBlockElementSupport extends Plugin {
2242
+ /**
2243
+ * Provides the General HTML Support integration with {@link module:code-block/codeblock~CodeBlock Code Block} feature.
2244
+ */ class CodeBlockElementSupport extends Plugin {
2159
2245
  /**
2160
- * @inheritDoc
2161
- */ static get requires() {
2246
+ * @inheritDoc
2247
+ */ static get requires() {
2162
2248
  return [
2163
2249
  DataFilter
2164
2250
  ];
2165
2251
  }
2166
2252
  /**
2167
- * @inheritDoc
2168
- */ static get pluginName() {
2253
+ * @inheritDoc
2254
+ */ static get pluginName() {
2169
2255
  return 'CodeBlockElementSupport';
2170
2256
  }
2171
2257
  /**
2172
- * @inheritDoc
2173
- */ init() {
2258
+ * @inheritDoc
2259
+ */ init() {
2174
2260
  if (!this.editor.plugins.has('CodeBlockEditing')) {
2175
2261
  return;
2176
2262
  }
@@ -2249,22 +2335,38 @@ class CodeBlockElementSupport extends Plugin {
2249
2335
  };
2250
2336
  }
2251
2337
 
2252
- class DualContentModelElementSupport extends Plugin {
2253
- /**
2254
- * @inheritDoc
2255
- */ static get requires() {
2338
+ /**
2339
+ * Provides the General HTML Support integration for elements which can behave like sectioning element (e.g. article) or
2340
+ * element accepting only inline content (e.g. paragraph).
2341
+ *
2342
+ * The distinction between this two content models is important for choosing correct schema model and proper content conversion.
2343
+ * As an example, it ensures that:
2344
+ *
2345
+ * * children elements paragraphing is enabled for sectioning elements only,
2346
+ * * element and its content can be correctly handled by editing view (splitting and merging elements),
2347
+ * * model element HTML is semantically correct and easier to work with.
2348
+ *
2349
+ * If element contains any block element, it will be treated as a sectioning element and registered using
2350
+ * {@link module:html-support/dataschema~DataSchemaDefinition#model} and
2351
+ * {@link module:html-support/dataschema~DataSchemaDefinition#modelSchema} in editor schema.
2352
+ * Otherwise, it will be registered under {@link module:html-support/dataschema~DataSchemaBlockElementDefinition#paragraphLikeModel} model
2353
+ * name with model schema accepting only inline content (inheriting from `$block`).
2354
+ */ class DualContentModelElementSupport extends Plugin {
2355
+ /**
2356
+ * @inheritDoc
2357
+ */ static get requires() {
2256
2358
  return [
2257
2359
  DataFilter
2258
2360
  ];
2259
2361
  }
2260
2362
  /**
2261
- * @inheritDoc
2262
- */ static get pluginName() {
2363
+ * @inheritDoc
2364
+ */ static get pluginName() {
2263
2365
  return 'DualContentModelElementSupport';
2264
2366
  }
2265
2367
  /**
2266
- * @inheritDoc
2267
- */ init() {
2368
+ * @inheritDoc
2369
+ */ init() {
2268
2370
  const dataFilter = this.editor.plugins.get(DataFilter);
2269
2371
  dataFilter.on('register', (evt, definition)=>{
2270
2372
  const blockDefinition = definition;
@@ -2312,8 +2414,8 @@ class DualContentModelElementSupport extends Plugin {
2312
2414
  });
2313
2415
  }
2314
2416
  /**
2315
- * Checks whether the given view element includes any other block element.
2316
- */ _hasBlockContent(viewElement) {
2417
+ * Checks whether the given view element includes any other block element.
2418
+ */ _hasBlockContent(viewElement) {
2317
2419
  const view = this.editor.editing.view;
2318
2420
  const blockElements = view.domConverter.blockElements;
2319
2421
  // Traversing the viewElement subtree looking for block elements.
@@ -2327,8 +2429,8 @@ class DualContentModelElementSupport extends Plugin {
2327
2429
  return false;
2328
2430
  }
2329
2431
  /**
2330
- * Adds attribute filtering conversion for the given data schema.
2331
- */ _addAttributeConversion(definition) {
2432
+ * Adds attribute filtering conversion for the given data schema.
2433
+ */ _addAttributeConversion(definition) {
2332
2434
  const editor = this.editor;
2333
2435
  const conversion = editor.conversion;
2334
2436
  const dataFilter = editor.plugins.get(DataFilter);
@@ -2340,23 +2442,25 @@ class DualContentModelElementSupport extends Plugin {
2340
2442
  }
2341
2443
  }
2342
2444
 
2343
- class HeadingElementSupport extends Plugin {
2445
+ /**
2446
+ * Provides the General HTML Support integration with {@link module:heading/heading~Heading Heading} feature.
2447
+ */ class HeadingElementSupport extends Plugin {
2344
2448
  /**
2345
- * @inheritDoc
2346
- */ static get requires() {
2449
+ * @inheritDoc
2450
+ */ static get requires() {
2347
2451
  return [
2348
2452
  DataSchema,
2349
2453
  Enter
2350
2454
  ];
2351
2455
  }
2352
2456
  /**
2353
- * @inheritDoc
2354
- */ static get pluginName() {
2457
+ * @inheritDoc
2458
+ */ static get pluginName() {
2355
2459
  return 'HeadingElementSupport';
2356
2460
  }
2357
2461
  /**
2358
- * @inheritDoc
2359
- */ init() {
2462
+ * @inheritDoc
2463
+ */ init() {
2360
2464
  const editor = this.editor;
2361
2465
  if (!editor.plugins.has('HeadingEditing')) {
2362
2466
  return;
@@ -2365,8 +2469,8 @@ class HeadingElementSupport extends Plugin {
2365
2469
  this.registerHeadingElements(editor, options);
2366
2470
  }
2367
2471
  /**
2368
- * Registers all elements supported by HeadingEditing to enable custom attributes for those elements.
2369
- */ registerHeadingElements(editor, options) {
2472
+ * Registers all elements supported by HeadingEditing to enable custom attributes for those elements.
2473
+ */ registerHeadingElements(editor, options) {
2370
2474
  const dataSchema = editor.plugins.get(DataSchema);
2371
2475
  const headerModels = [];
2372
2476
  for (const option of options){
@@ -2406,22 +2510,24 @@ class HeadingElementSupport extends Plugin {
2406
2510
  }
2407
2511
  }
2408
2512
 
2409
- class ImageElementSupport extends Plugin {
2513
+ /**
2514
+ * Provides the General HTML Support integration with the {@link module:image/image~Image Image} feature.
2515
+ */ class ImageElementSupport extends Plugin {
2410
2516
  /**
2411
- * @inheritDoc
2412
- */ static get requires() {
2517
+ * @inheritDoc
2518
+ */ static get requires() {
2413
2519
  return [
2414
2520
  DataFilter
2415
2521
  ];
2416
2522
  }
2417
2523
  /**
2418
- * @inheritDoc
2419
- */ static get pluginName() {
2524
+ * @inheritDoc
2525
+ */ static get pluginName() {
2420
2526
  return 'ImageElementSupport';
2421
2527
  }
2422
2528
  /**
2423
- * @inheritDoc
2424
- */ init() {
2529
+ * @inheritDoc
2530
+ */ init() {
2425
2531
  const editor = this.editor;
2426
2532
  // At least one image plugin should be loaded for the integration to work properly.
2427
2533
  if (!editor.plugins.has('ImageInlineEditing') && !editor.plugins.has('ImageBlockEditing')) {
@@ -2589,22 +2695,24 @@ class ImageElementSupport extends Plugin {
2589
2695
  };
2590
2696
  }
2591
2697
 
2592
- class MediaEmbedElementSupport extends Plugin {
2698
+ /**
2699
+ * Provides the General HTML Support integration with {@link module:media-embed/mediaembed~MediaEmbed Media Embed} feature.
2700
+ */ class MediaEmbedElementSupport extends Plugin {
2593
2701
  /**
2594
- * @inheritDoc
2595
- */ static get requires() {
2702
+ * @inheritDoc
2703
+ */ static get requires() {
2596
2704
  return [
2597
2705
  DataFilter
2598
2706
  ];
2599
2707
  }
2600
2708
  /**
2601
- * @inheritDoc
2602
- */ static get pluginName() {
2709
+ * @inheritDoc
2710
+ */ static get pluginName() {
2603
2711
  return 'MediaEmbedElementSupport';
2604
2712
  }
2605
2713
  /**
2606
- * @inheritDoc
2607
- */ init() {
2714
+ * @inheritDoc
2715
+ */ init() {
2608
2716
  const editor = this.editor;
2609
2717
  // Stop here if MediaEmbed plugin is not provided or the integrator wants to output markup with previews as
2610
2718
  // we do not support filtering previews.
@@ -2696,22 +2804,24 @@ function modelToViewMediaAttributeConverter(mediaElementName) {
2696
2804
  };
2697
2805
  }
2698
2806
 
2699
- class ScriptElementSupport extends Plugin {
2807
+ /**
2808
+ * Provides the General HTML Support for `script` elements.
2809
+ */ class ScriptElementSupport extends Plugin {
2700
2810
  /**
2701
- * @inheritDoc
2702
- */ static get requires() {
2811
+ * @inheritDoc
2812
+ */ static get requires() {
2703
2813
  return [
2704
2814
  DataFilter
2705
2815
  ];
2706
2816
  }
2707
2817
  /**
2708
- * @inheritDoc
2709
- */ static get pluginName() {
2818
+ * @inheritDoc
2819
+ */ static get pluginName() {
2710
2820
  return 'ScriptElementSupport';
2711
2821
  }
2712
2822
  /**
2713
- * @inheritDoc
2714
- */ init() {
2823
+ * @inheritDoc
2824
+ */ init() {
2715
2825
  const dataFilter = this.editor.plugins.get(DataFilter);
2716
2826
  dataFilter.on('register:script', (evt, definition)=>{
2717
2827
  const editor = this.editor;
@@ -2745,22 +2855,24 @@ class ScriptElementSupport extends Plugin {
2745
2855
  }
2746
2856
  }
2747
2857
 
2748
- class TableElementSupport extends Plugin {
2858
+ /**
2859
+ * Provides the General HTML Support integration with {@link module:table/table~Table Table} feature.
2860
+ */ class TableElementSupport extends Plugin {
2749
2861
  /**
2750
- * @inheritDoc
2751
- */ static get requires() {
2862
+ * @inheritDoc
2863
+ */ static get requires() {
2752
2864
  return [
2753
2865
  DataFilter
2754
2866
  ];
2755
2867
  }
2756
2868
  /**
2757
- * @inheritDoc
2758
- */ static get pluginName() {
2869
+ * @inheritDoc
2870
+ */ static get pluginName() {
2759
2871
  return 'TableElementSupport';
2760
2872
  }
2761
2873
  /**
2762
- * @inheritDoc
2763
- */ init() {
2874
+ * @inheritDoc
2875
+ */ init() {
2764
2876
  const editor = this.editor;
2765
2877
  if (!editor.plugins.has('TableEditing')) {
2766
2878
  return;
@@ -2898,22 +3010,24 @@ class TableElementSupport extends Plugin {
2898
3010
  };
2899
3011
  }
2900
3012
 
2901
- class StyleElementSupport extends Plugin {
3013
+ /**
3014
+ * Provides the General HTML Support for `style` elements.
3015
+ */ class StyleElementSupport extends Plugin {
2902
3016
  /**
2903
- * @inheritDoc
2904
- */ static get requires() {
3017
+ * @inheritDoc
3018
+ */ static get requires() {
2905
3019
  return [
2906
3020
  DataFilter
2907
3021
  ];
2908
3022
  }
2909
3023
  /**
2910
- * @inheritDoc
2911
- */ static get pluginName() {
3024
+ * @inheritDoc
3025
+ */ static get pluginName() {
2912
3026
  return 'StyleElementSupport';
2913
3027
  }
2914
3028
  /**
2915
- * @inheritDoc
2916
- */ init() {
3029
+ * @inheritDoc
3030
+ */ init() {
2917
3031
  const dataFilter = this.editor.plugins.get(DataFilter);
2918
3032
  dataFilter.on('register:style', (evt, definition)=>{
2919
3033
  const editor = this.editor;
@@ -2947,22 +3061,24 @@ class StyleElementSupport extends Plugin {
2947
3061
  }
2948
3062
  }
2949
3063
 
2950
- class ListElementSupport extends Plugin {
3064
+ /**
3065
+ * Provides the General HTML Support integration with the {@link module:list/list~List List} feature.
3066
+ */ class ListElementSupport extends Plugin {
2951
3067
  /**
2952
- * @inheritDoc
2953
- */ static get requires() {
3068
+ * @inheritDoc
3069
+ */ static get requires() {
2954
3070
  return [
2955
3071
  DataFilter
2956
3072
  ];
2957
3073
  }
2958
3074
  /**
2959
- * @inheritDoc
2960
- */ static get pluginName() {
3075
+ * @inheritDoc
3076
+ */ static get pluginName() {
2961
3077
  return 'ListElementSupport';
2962
3078
  }
2963
3079
  /**
2964
- * @inheritDoc
2965
- */ init() {
3080
+ * @inheritDoc
3081
+ */ init() {
2966
3082
  const editor = this.editor;
2967
3083
  if (!editor.plugins.has('ListEditing')) {
2968
3084
  return;
@@ -3059,8 +3175,8 @@ class ListElementSupport extends Plugin {
3059
3175
  });
3060
3176
  }
3061
3177
  /**
3062
- * @inheritDoc
3063
- */ afterInit() {
3178
+ * @inheritDoc
3179
+ */ afterInit() {
3064
3180
  const editor = this.editor;
3065
3181
  if (!editor.commands.get('indentList')) {
3066
3182
  return;
@@ -3119,23 +3235,25 @@ class ListElementSupport extends Plugin {
3119
3235
  return listType === 'numbered' || listType == 'customNumbered' ? 'htmlOlAttributes' : 'htmlUlAttributes';
3120
3236
  }
3121
3237
 
3122
- class CustomElementSupport extends Plugin {
3238
+ /**
3239
+ * Provides the General HTML Support for custom elements (not registered in the {@link module:html-support/dataschema~DataSchema}).
3240
+ */ class CustomElementSupport extends Plugin {
3123
3241
  /**
3124
- * @inheritDoc
3125
- */ static get requires() {
3242
+ * @inheritDoc
3243
+ */ static get requires() {
3126
3244
  return [
3127
3245
  DataFilter,
3128
3246
  DataSchema
3129
3247
  ];
3130
3248
  }
3131
3249
  /**
3132
- * @inheritDoc
3133
- */ static get pluginName() {
3250
+ * @inheritDoc
3251
+ */ static get pluginName() {
3134
3252
  return 'CustomElementSupport';
3135
3253
  }
3136
3254
  /**
3137
- * @inheritDoc
3138
- */ init() {
3255
+ * @inheritDoc
3256
+ */ init() {
3139
3257
  const dataFilter = this.editor.plugins.get(DataFilter);
3140
3258
  const dataSchema = this.editor.plugins.get(DataSchema);
3141
3259
  dataFilter.on('register:$customElement', (evt, definition)=>{
@@ -3273,15 +3391,20 @@ class CustomElementSupport extends Plugin {
3273
3391
  return true;
3274
3392
  }
3275
3393
 
3276
- class GeneralHtmlSupport extends Plugin {
3394
+ /**
3395
+ * The General HTML Support feature.
3396
+ *
3397
+ * This is a "glue" plugin which initializes the {@link module:html-support/datafilter~DataFilter data filter} configuration
3398
+ * and features integration with the General HTML Support.
3399
+ */ class GeneralHtmlSupport extends Plugin {
3277
3400
  /**
3278
- * @inheritDoc
3279
- */ static get pluginName() {
3401
+ * @inheritDoc
3402
+ */ static get pluginName() {
3280
3403
  return 'GeneralHtmlSupport';
3281
3404
  }
3282
3405
  /**
3283
- * @inheritDoc
3284
- */ static get requires() {
3406
+ * @inheritDoc
3407
+ */ static get requires() {
3285
3408
  return [
3286
3409
  DataFilter,
3287
3410
  CodeBlockElementSupport,
@@ -3297,8 +3420,8 @@ class GeneralHtmlSupport extends Plugin {
3297
3420
  ];
3298
3421
  }
3299
3422
  /**
3300
- * @inheritDoc
3301
- */ init() {
3423
+ * @inheritDoc
3424
+ */ init() {
3302
3425
  const editor = this.editor;
3303
3426
  const dataFilter = editor.plugins.get(DataFilter);
3304
3427
  // Load the allowed empty inline elements' configuration.
@@ -3309,11 +3432,11 @@ class GeneralHtmlSupport extends Plugin {
3309
3432
  dataFilter.loadDisallowedConfig(editor.config.get('htmlSupport.disallow') || []);
3310
3433
  }
3311
3434
  /**
3312
- * Returns a GHS model attribute name related to a given view element name.
3313
- *
3314
- * @internal
3315
- * @param viewElementName A view element name.
3316
- */ getGhsAttributeNameForElement(viewElementName) {
3435
+ * Returns a GHS model attribute name related to a given view element name.
3436
+ *
3437
+ * @internal
3438
+ * @param viewElementName A view element name.
3439
+ */ getGhsAttributeNameForElement(viewElementName) {
3317
3440
  const dataSchema = this.editor.plugins.get('DataSchema');
3318
3441
  const definitions = Array.from(dataSchema.getDefinitionsForView(viewElementName, false));
3319
3442
  const inlineDefinition = definitions.find((definition)=>definition.isInline && !definitions[0].isObject);
@@ -3323,13 +3446,13 @@ class GeneralHtmlSupport extends Plugin {
3323
3446
  return getHtmlAttributeName(viewElementName);
3324
3447
  }
3325
3448
  /**
3326
- * Updates GHS model attribute for a specified view element name, so it includes the given class name.
3327
- *
3328
- * @internal
3329
- * @param viewElementName A view element name.
3330
- * @param className The css class to add.
3331
- * @param selectable The selection or element to update.
3332
- */ addModelHtmlClass(viewElementName, className, selectable) {
3449
+ * Updates GHS model attribute for a specified view element name, so it includes the given class name.
3450
+ *
3451
+ * @internal
3452
+ * @param viewElementName A view element name.
3453
+ * @param className The css class to add.
3454
+ * @param selectable The selection or element to update.
3455
+ */ addModelHtmlClass(viewElementName, className, selectable) {
3333
3456
  const model = this.editor.model;
3334
3457
  const ghsAttributeName = this.getGhsAttributeNameForElement(viewElementName);
3335
3458
  model.change((writer)=>{
@@ -3343,13 +3466,13 @@ class GeneralHtmlSupport extends Plugin {
3343
3466
  });
3344
3467
  }
3345
3468
  /**
3346
- * Updates GHS model attribute for a specified view element name, so it does not include the given class name.
3347
- *
3348
- * @internal
3349
- * @param viewElementName A view element name.
3350
- * @param className The css class to remove.
3351
- * @param selectable The selection or element to update.
3352
- */ removeModelHtmlClass(viewElementName, className, selectable) {
3469
+ * Updates GHS model attribute for a specified view element name, so it does not include the given class name.
3470
+ *
3471
+ * @internal
3472
+ * @param viewElementName A view element name.
3473
+ * @param className The css class to remove.
3474
+ * @param selectable The selection or element to update.
3475
+ */ removeModelHtmlClass(viewElementName, className, selectable) {
3353
3476
  const model = this.editor.model;
3354
3477
  const ghsAttributeName = this.getGhsAttributeNameForElement(viewElementName);
3355
3478
  model.change((writer)=>{
@@ -3363,12 +3486,12 @@ class GeneralHtmlSupport extends Plugin {
3363
3486
  });
3364
3487
  }
3365
3488
  /**
3366
- * Updates GHS model attribute for a specified view element name, so it includes the given attribute.
3367
- *
3368
- * @param viewElementName A view element name.
3369
- * @param attributes The object with attributes to set.
3370
- * @param selectable The selection or element to update.
3371
- */ setModelHtmlAttributes(viewElementName, attributes, selectable) {
3489
+ * Updates GHS model attribute for a specified view element name, so it includes the given attribute.
3490
+ *
3491
+ * @param viewElementName A view element name.
3492
+ * @param attributes The object with attributes to set.
3493
+ * @param selectable The selection or element to update.
3494
+ */ setModelHtmlAttributes(viewElementName, attributes, selectable) {
3372
3495
  const model = this.editor.model;
3373
3496
  const ghsAttributeName = this.getGhsAttributeNameForElement(viewElementName);
3374
3497
  model.change((writer)=>{
@@ -3382,12 +3505,12 @@ class GeneralHtmlSupport extends Plugin {
3382
3505
  });
3383
3506
  }
3384
3507
  /**
3385
- * Updates GHS model attribute for a specified view element name, so it does not include the given attribute.
3386
- *
3387
- * @param viewElementName A view element name.
3388
- * @param attributeName The attribute name (or names) to remove.
3389
- * @param selectable The selection or element to update.
3390
- */ removeModelHtmlAttributes(viewElementName, attributeName, selectable) {
3508
+ * Updates GHS model attribute for a specified view element name, so it does not include the given attribute.
3509
+ *
3510
+ * @param viewElementName A view element name.
3511
+ * @param attributeName The attribute name (or names) to remove.
3512
+ * @param selectable The selection or element to update.
3513
+ */ removeModelHtmlAttributes(viewElementName, attributeName, selectable) {
3391
3514
  const model = this.editor.model;
3392
3515
  const ghsAttributeName = this.getGhsAttributeNameForElement(viewElementName);
3393
3516
  model.change((writer)=>{
@@ -3401,12 +3524,12 @@ class GeneralHtmlSupport extends Plugin {
3401
3524
  });
3402
3525
  }
3403
3526
  /**
3404
- * Updates GHS model attribute for a specified view element name, so it includes a given style.
3405
- *
3406
- * @param viewElementName A view element name.
3407
- * @param styles The object with styles to set.
3408
- * @param selectable The selection or element to update.
3409
- */ setModelHtmlStyles(viewElementName, styles, selectable) {
3527
+ * Updates GHS model attribute for a specified view element name, so it includes a given style.
3528
+ *
3529
+ * @param viewElementName A view element name.
3530
+ * @param styles The object with styles to set.
3531
+ * @param selectable The selection or element to update.
3532
+ */ setModelHtmlStyles(viewElementName, styles, selectable) {
3410
3533
  const model = this.editor.model;
3411
3534
  const ghsAttributeName = this.getGhsAttributeNameForElement(viewElementName);
3412
3535
  model.change((writer)=>{
@@ -3420,12 +3543,12 @@ class GeneralHtmlSupport extends Plugin {
3420
3543
  });
3421
3544
  }
3422
3545
  /**
3423
- * Updates GHS model attribute for a specified view element name, so it does not include a given style.
3424
- *
3425
- * @param viewElementName A view element name.
3426
- * @param properties The style (or styles list) to remove.
3427
- * @param selectable The selection or element to update.
3428
- */ removeModelHtmlStyles(viewElementName, properties, selectable) {
3546
+ * Updates GHS model attribute for a specified view element name, so it does not include a given style.
3547
+ *
3548
+ * @param viewElementName A view element name.
3549
+ * @param properties The style (or styles list) to remove.
3550
+ * @param selectable The selection or element to update.
3551
+ */ removeModelHtmlStyles(viewElementName, properties, selectable) {
3429
3552
  const model = this.editor.model;
3430
3553
  const ghsAttributeName = this.getGhsAttributeNameForElement(viewElementName);
3431
3554
  model.change((writer)=>{
@@ -3473,15 +3596,19 @@ class GeneralHtmlSupport extends Plugin {
3473
3596
  }
3474
3597
  }
3475
3598
 
3476
- class HtmlComment extends Plugin {
3599
+ /**
3600
+ * The HTML comment feature. It preserves the HTML comments (`<!-- -->`) in the editor data.
3601
+ *
3602
+ * For a detailed overview, check the {@glink features/html/html-comments HTML comment feature documentation}.
3603
+ */ class HtmlComment extends Plugin {
3477
3604
  /**
3478
- * @inheritDoc
3479
- */ static get pluginName() {
3605
+ * @inheritDoc
3606
+ */ static get pluginName() {
3480
3607
  return 'HtmlComment';
3481
3608
  }
3482
3609
  /**
3483
- * @inheritDoc
3484
- */ init() {
3610
+ * @inheritDoc
3611
+ */ init() {
3485
3612
  const editor = this.editor;
3486
3613
  const loadedCommentsContent = new Map();
3487
3614
  editor.data.processor.skipComments = false;
@@ -3591,12 +3718,12 @@ class HtmlComment extends Plugin {
3591
3718
  });
3592
3719
  }
3593
3720
  /**
3594
- * Creates an HTML comment on the specified position and returns its ID.
3595
- *
3596
- * *Note*: If two comments are created at the same position, the second comment will be inserted before the first one.
3597
- *
3598
- * @returns Comment ID. This ID can be later used to e.g. remove the comment from the content.
3599
- */ createHtmlComment(position, content) {
3721
+ * Creates an HTML comment on the specified position and returns its ID.
3722
+ *
3723
+ * *Note*: If two comments are created at the same position, the second comment will be inserted before the first one.
3724
+ *
3725
+ * @returns Comment ID. This ID can be later used to e.g. remove the comment from the content.
3726
+ */ createHtmlComment(position, content) {
3600
3727
  const id = uid();
3601
3728
  const editor = this.editor;
3602
3729
  const model = editor.model;
@@ -3614,16 +3741,16 @@ class HtmlComment extends Plugin {
3614
3741
  });
3615
3742
  }
3616
3743
  /**
3617
- * Removes an HTML comment with the given comment ID.
3618
- *
3619
- * It does nothing and returns `false` if the comment with the given ID does not exist.
3620
- * Otherwise it removes the comment and returns `true`.
3621
- *
3622
- * Note that a comment can be removed also by removing the content around the comment.
3623
- *
3624
- * @param commentID The ID of the comment to be removed.
3625
- * @returns `true` when the comment with the given ID was removed, `false` otherwise.
3626
- */ removeHtmlComment(commentID) {
3744
+ * Removes an HTML comment with the given comment ID.
3745
+ *
3746
+ * It does nothing and returns `false` if the comment with the given ID does not exist.
3747
+ * Otherwise it removes the comment and returns `true`.
3748
+ *
3749
+ * Note that a comment can be removed also by removing the content around the comment.
3750
+ *
3751
+ * @param commentID The ID of the comment to be removed.
3752
+ * @returns `true` when the comment with the given ID was removed, `false` otherwise.
3753
+ */ removeHtmlComment(commentID) {
3627
3754
  const editor = this.editor;
3628
3755
  const marker = editor.model.markers.get(commentID);
3629
3756
  if (!marker) {
@@ -3635,10 +3762,10 @@ class HtmlComment extends Plugin {
3635
3762
  return true;
3636
3763
  }
3637
3764
  /**
3638
- * Gets the HTML comment data for the comment with a given ID.
3639
- *
3640
- * Returns `null` if the comment does not exist.
3641
- */ getHtmlCommentData(commentID) {
3765
+ * Gets the HTML comment data for the comment with a given ID.
3766
+ *
3767
+ * Returns `null` if the comment does not exist.
3768
+ */ getHtmlCommentData(commentID) {
3642
3769
  const editor = this.editor;
3643
3770
  const marker = editor.model.markers.get(commentID);
3644
3771
  if (!marker) {
@@ -3657,14 +3784,14 @@ class HtmlComment extends Plugin {
3657
3784
  };
3658
3785
  }
3659
3786
  /**
3660
- * Gets all HTML comments in the given range.
3661
- *
3662
- * By default, it includes comments at the range boundaries.
3663
- *
3664
- * @param range
3665
- * @param options.skipBoundaries When set to `true` the range boundaries will be skipped.
3666
- * @returns HTML comment IDs
3667
- */ getHtmlCommentsInRange(range, { skipBoundaries = false } = {}) {
3787
+ * Gets all HTML comments in the given range.
3788
+ *
3789
+ * By default, it includes comments at the range boundaries.
3790
+ *
3791
+ * @param range
3792
+ * @param options.skipBoundaries When set to `true` the range boundaries will be skipped.
3793
+ * @returns HTML comment IDs
3794
+ */ getHtmlCommentsInRange(range, { skipBoundaries = false } = {}) {
3668
3795
  const includeBoundaries = !skipBoundaries;
3669
3796
  // Unfortunately, MarkerCollection#getMarkersAtPosition() filters out collapsed markers.
3670
3797
  return Array.from(this.editor.model.markers.getMarkersGroup('$comment')).filter((marker)=>isCommentMarkerInRange(marker, range)).map((marker)=>marker.name);
@@ -3675,10 +3802,13 @@ class HtmlComment extends Plugin {
3675
3802
  }
3676
3803
  }
3677
3804
 
3678
- class HtmlPageDataProcessor extends HtmlDataProcessor {
3805
+ /**
3806
+ * The full page HTML data processor class.
3807
+ * This data processor implementation uses HTML as input and output data.
3808
+ */ class HtmlPageDataProcessor extends HtmlDataProcessor {
3679
3809
  /**
3680
- * @inheritDoc
3681
- */ toView(data) {
3810
+ * @inheritDoc
3811
+ */ toView(data) {
3682
3812
  // Ignore content that is not a full page source.
3683
3813
  if (!data.match(/<(?:html|body|head|meta)(?:\s[^>]*)?>/i)) {
3684
3814
  return super.toView(data);
@@ -3712,8 +3842,8 @@ class HtmlPageDataProcessor extends HtmlDataProcessor {
3712
3842
  return viewFragment;
3713
3843
  }
3714
3844
  /**
3715
- * @inheritDoc
3716
- */ toData(viewFragment) {
3845
+ * @inheritDoc
3846
+ */ toData(viewFragment) {
3717
3847
  let data = super.toData(viewFragment);
3718
3848
  const page = viewFragment.getCustomProperty('$fullPageDocument');
3719
3849
  const docType = viewFragment.getCustomProperty('$fullPageDocType');
@@ -3731,15 +3861,17 @@ class HtmlPageDataProcessor extends HtmlDataProcessor {
3731
3861
  }
3732
3862
  }
3733
3863
 
3734
- class FullPage extends Plugin {
3864
+ /**
3865
+ * The full page editing feature. It preserves the whole HTML page in the editor data.
3866
+ */ class FullPage extends Plugin {
3735
3867
  /**
3736
- * @inheritDoc
3737
- */ static get pluginName() {
3868
+ * @inheritDoc
3869
+ */ static get pluginName() {
3738
3870
  return 'FullPage';
3739
3871
  }
3740
3872
  /**
3741
- * @inheritDoc
3742
- */ init() {
3873
+ * @inheritDoc
3874
+ */ init() {
3743
3875
  const editor = this.editor;
3744
3876
  const properties = [
3745
3877
  '$fullPageDocument',