@ckeditor/ckeditor5-html-support 41.4.2 → 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/README.md +6 -0
- package/dist/index.js +525 -393
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1297,15 +1297,49 @@ var defaultConfig = {
|
|
|
1297
1297
|
]
|
|
1298
1298
|
};
|
|
1299
1299
|
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
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
|
-
|
|
1308
|
-
|
|
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
|
-
|
|
1318
|
-
|
|
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
|
-
|
|
1326
|
-
|
|
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
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
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
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
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
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
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
|
-
|
|
1376
|
-
|
|
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
|
-
|
|
1381
|
-
|
|
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
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
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
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1455
|
-
|
|
1552
|
+
* @inheritDoc
|
|
1553
|
+
*/ static get pluginName() {
|
|
1456
1554
|
return 'DataFilter';
|
|
1457
1555
|
}
|
|
1458
1556
|
/**
|
|
1459
|
-
|
|
1460
|
-
|
|
1557
|
+
* @inheritDoc
|
|
1558
|
+
*/ static get requires() {
|
|
1461
1559
|
return [
|
|
1462
1560
|
DataSchema,
|
|
1463
1561
|
Widget
|
|
1464
1562
|
];
|
|
1465
1563
|
}
|
|
1466
1564
|
/**
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
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
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
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
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
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
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
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
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
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
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
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
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
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
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
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
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
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
|
-
|
|
1607
|
-
|
|
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
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
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
|
-
|
|
1658
|
-
|
|
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
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
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
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
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
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
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
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
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
|
-
|
|
1840
|
-
|
|
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
|
-
|
|
1848
|
-
|
|
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
|
-
|
|
1896
|
-
|
|
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
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2161
|
-
|
|
2246
|
+
* @inheritDoc
|
|
2247
|
+
*/ static get requires() {
|
|
2162
2248
|
return [
|
|
2163
2249
|
DataFilter
|
|
2164
2250
|
];
|
|
2165
2251
|
}
|
|
2166
2252
|
/**
|
|
2167
|
-
|
|
2168
|
-
|
|
2253
|
+
* @inheritDoc
|
|
2254
|
+
*/ static get pluginName() {
|
|
2169
2255
|
return 'CodeBlockElementSupport';
|
|
2170
2256
|
}
|
|
2171
2257
|
/**
|
|
2172
|
-
|
|
2173
|
-
|
|
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
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
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
|
-
|
|
2262
|
-
|
|
2363
|
+
* @inheritDoc
|
|
2364
|
+
*/ static get pluginName() {
|
|
2263
2365
|
return 'DualContentModelElementSupport';
|
|
2264
2366
|
}
|
|
2265
2367
|
/**
|
|
2266
|
-
|
|
2267
|
-
|
|
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
|
-
|
|
2316
|
-
|
|
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
|
-
|
|
2331
|
-
|
|
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
|
-
|
|
2445
|
+
/**
|
|
2446
|
+
* Provides the General HTML Support integration with {@link module:heading/heading~Heading Heading} feature.
|
|
2447
|
+
*/ class HeadingElementSupport extends Plugin {
|
|
2344
2448
|
/**
|
|
2345
|
-
|
|
2346
|
-
|
|
2449
|
+
* @inheritDoc
|
|
2450
|
+
*/ static get requires() {
|
|
2347
2451
|
return [
|
|
2348
2452
|
DataSchema,
|
|
2349
2453
|
Enter
|
|
2350
2454
|
];
|
|
2351
2455
|
}
|
|
2352
2456
|
/**
|
|
2353
|
-
|
|
2354
|
-
|
|
2457
|
+
* @inheritDoc
|
|
2458
|
+
*/ static get pluginName() {
|
|
2355
2459
|
return 'HeadingElementSupport';
|
|
2356
2460
|
}
|
|
2357
2461
|
/**
|
|
2358
|
-
|
|
2359
|
-
|
|
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
|
-
|
|
2369
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2412
|
-
|
|
2517
|
+
* @inheritDoc
|
|
2518
|
+
*/ static get requires() {
|
|
2413
2519
|
return [
|
|
2414
2520
|
DataFilter
|
|
2415
2521
|
];
|
|
2416
2522
|
}
|
|
2417
2523
|
/**
|
|
2418
|
-
|
|
2419
|
-
|
|
2524
|
+
* @inheritDoc
|
|
2525
|
+
*/ static get pluginName() {
|
|
2420
2526
|
return 'ImageElementSupport';
|
|
2421
2527
|
}
|
|
2422
2528
|
/**
|
|
2423
|
-
|
|
2424
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2595
|
-
|
|
2702
|
+
* @inheritDoc
|
|
2703
|
+
*/ static get requires() {
|
|
2596
2704
|
return [
|
|
2597
2705
|
DataFilter
|
|
2598
2706
|
];
|
|
2599
2707
|
}
|
|
2600
2708
|
/**
|
|
2601
|
-
|
|
2602
|
-
|
|
2709
|
+
* @inheritDoc
|
|
2710
|
+
*/ static get pluginName() {
|
|
2603
2711
|
return 'MediaEmbedElementSupport';
|
|
2604
2712
|
}
|
|
2605
2713
|
/**
|
|
2606
|
-
|
|
2607
|
-
|
|
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
|
-
|
|
2807
|
+
/**
|
|
2808
|
+
* Provides the General HTML Support for `script` elements.
|
|
2809
|
+
*/ class ScriptElementSupport extends Plugin {
|
|
2700
2810
|
/**
|
|
2701
|
-
|
|
2702
|
-
|
|
2811
|
+
* @inheritDoc
|
|
2812
|
+
*/ static get requires() {
|
|
2703
2813
|
return [
|
|
2704
2814
|
DataFilter
|
|
2705
2815
|
];
|
|
2706
2816
|
}
|
|
2707
2817
|
/**
|
|
2708
|
-
|
|
2709
|
-
|
|
2818
|
+
* @inheritDoc
|
|
2819
|
+
*/ static get pluginName() {
|
|
2710
2820
|
return 'ScriptElementSupport';
|
|
2711
2821
|
}
|
|
2712
2822
|
/**
|
|
2713
|
-
|
|
2714
|
-
|
|
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
|
-
|
|
2858
|
+
/**
|
|
2859
|
+
* Provides the General HTML Support integration with {@link module:table/table~Table Table} feature.
|
|
2860
|
+
*/ class TableElementSupport extends Plugin {
|
|
2749
2861
|
/**
|
|
2750
|
-
|
|
2751
|
-
|
|
2862
|
+
* @inheritDoc
|
|
2863
|
+
*/ static get requires() {
|
|
2752
2864
|
return [
|
|
2753
2865
|
DataFilter
|
|
2754
2866
|
];
|
|
2755
2867
|
}
|
|
2756
2868
|
/**
|
|
2757
|
-
|
|
2758
|
-
|
|
2869
|
+
* @inheritDoc
|
|
2870
|
+
*/ static get pluginName() {
|
|
2759
2871
|
return 'TableElementSupport';
|
|
2760
2872
|
}
|
|
2761
2873
|
/**
|
|
2762
|
-
|
|
2763
|
-
|
|
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
|
-
|
|
3013
|
+
/**
|
|
3014
|
+
* Provides the General HTML Support for `style` elements.
|
|
3015
|
+
*/ class StyleElementSupport extends Plugin {
|
|
2902
3016
|
/**
|
|
2903
|
-
|
|
2904
|
-
|
|
3017
|
+
* @inheritDoc
|
|
3018
|
+
*/ static get requires() {
|
|
2905
3019
|
return [
|
|
2906
3020
|
DataFilter
|
|
2907
3021
|
];
|
|
2908
3022
|
}
|
|
2909
3023
|
/**
|
|
2910
|
-
|
|
2911
|
-
|
|
3024
|
+
* @inheritDoc
|
|
3025
|
+
*/ static get pluginName() {
|
|
2912
3026
|
return 'StyleElementSupport';
|
|
2913
3027
|
}
|
|
2914
3028
|
/**
|
|
2915
|
-
|
|
2916
|
-
|
|
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
|
-
|
|
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
|
-
|
|
2953
|
-
|
|
3068
|
+
* @inheritDoc
|
|
3069
|
+
*/ static get requires() {
|
|
2954
3070
|
return [
|
|
2955
3071
|
DataFilter
|
|
2956
3072
|
];
|
|
2957
3073
|
}
|
|
2958
3074
|
/**
|
|
2959
|
-
|
|
2960
|
-
|
|
3075
|
+
* @inheritDoc
|
|
3076
|
+
*/ static get pluginName() {
|
|
2961
3077
|
return 'ListElementSupport';
|
|
2962
3078
|
}
|
|
2963
3079
|
/**
|
|
2964
|
-
|
|
2965
|
-
|
|
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
|
-
|
|
3063
|
-
|
|
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
|
-
|
|
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
|
-
|
|
3125
|
-
|
|
3242
|
+
* @inheritDoc
|
|
3243
|
+
*/ static get requires() {
|
|
3126
3244
|
return [
|
|
3127
3245
|
DataFilter,
|
|
3128
3246
|
DataSchema
|
|
3129
3247
|
];
|
|
3130
3248
|
}
|
|
3131
3249
|
/**
|
|
3132
|
-
|
|
3133
|
-
|
|
3250
|
+
* @inheritDoc
|
|
3251
|
+
*/ static get pluginName() {
|
|
3134
3252
|
return 'CustomElementSupport';
|
|
3135
3253
|
}
|
|
3136
3254
|
/**
|
|
3137
|
-
|
|
3138
|
-
|
|
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
|
-
|
|
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
|
-
|
|
3279
|
-
|
|
3401
|
+
* @inheritDoc
|
|
3402
|
+
*/ static get pluginName() {
|
|
3280
3403
|
return 'GeneralHtmlSupport';
|
|
3281
3404
|
}
|
|
3282
3405
|
/**
|
|
3283
|
-
|
|
3284
|
-
|
|
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
|
-
|
|
3301
|
-
|
|
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
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
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
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
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
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
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
|
-
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
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
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
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
|
-
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
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
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
|
|
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
|
-
|
|
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
|
-
|
|
3479
|
-
|
|
3605
|
+
* @inheritDoc
|
|
3606
|
+
*/ static get pluginName() {
|
|
3480
3607
|
return 'HtmlComment';
|
|
3481
3608
|
}
|
|
3482
3609
|
/**
|
|
3483
|
-
|
|
3484
|
-
|
|
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
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
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
|
-
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
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
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
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
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
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
|
-
|
|
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
|
-
|
|
3681
|
-
|
|
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
|
-
|
|
3716
|
-
|
|
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
|
-
|
|
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
|
-
|
|
3737
|
-
|
|
3868
|
+
* @inheritDoc
|
|
3869
|
+
*/ static get pluginName() {
|
|
3738
3870
|
return 'FullPage';
|
|
3739
3871
|
}
|
|
3740
3872
|
/**
|
|
3741
|
-
|
|
3742
|
-
|
|
3873
|
+
* @inheritDoc
|
|
3874
|
+
*/ init() {
|
|
3743
3875
|
const editor = this.editor;
|
|
3744
3876
|
const properties = [
|
|
3745
3877
|
'$fullPageDocument',
|