You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

150 lines
4.9 KiB

4 years ago
  1. 'use strict';
  2. exports.type = 'perItem';
  3. exports.active = true;
  4. exports.description = 'removes unknown elements content and attributes, removes attrs with default values';
  5. exports.params = {
  6. unknownContent: true,
  7. unknownAttrs: true,
  8. defaultAttrs: true,
  9. uselessOverrides: true,
  10. keepDataAttrs: true,
  11. keepAriaAttrs: true,
  12. keepRoleAttr: false
  13. };
  14. var collections = require('./_collections'),
  15. elems = collections.elems,
  16. attrsGroups = collections.attrsGroups,
  17. elemsGroups = collections.elemsGroups,
  18. attrsGroupsDefaults = collections.attrsGroupsDefaults,
  19. attrsInheritable = collections.inheritableAttrs,
  20. applyGroups = collections.presentationNonInheritableGroupAttrs;
  21. // collect and extend all references
  22. for (var elem in elems) {
  23. elem = elems[elem];
  24. if (elem.attrsGroups) {
  25. elem.attrs = elem.attrs || [];
  26. elem.attrsGroups.forEach(function(attrsGroupName) {
  27. elem.attrs = elem.attrs.concat(attrsGroups[attrsGroupName]);
  28. var groupDefaults = attrsGroupsDefaults[attrsGroupName];
  29. if (groupDefaults) {
  30. elem.defaults = elem.defaults || {};
  31. for (var attrName in groupDefaults) {
  32. elem.defaults[attrName] = groupDefaults[attrName];
  33. }
  34. }
  35. });
  36. }
  37. if (elem.contentGroups) {
  38. elem.content = elem.content || [];
  39. elem.contentGroups.forEach(function(contentGroupName) {
  40. elem.content = elem.content.concat(elemsGroups[contentGroupName]);
  41. });
  42. }
  43. }
  44. /**
  45. * Remove unknown elements content and attributes,
  46. * remove attributes with default values.
  47. *
  48. * @param {Object} item current iteration item
  49. * @param {Object} params plugin params
  50. * @return {Boolean} if false, item will be filtered out
  51. *
  52. * @author Kir Belevich
  53. */
  54. exports.fn = function(item, params) {
  55. // elems w/o namespace prefix
  56. if (item.isElem() && !item.prefix) {
  57. var elem = item.elem;
  58. // remove unknown element's content
  59. if (
  60. params.unknownContent &&
  61. !item.isEmpty() &&
  62. elems[elem] && // make sure we know of this element before checking its children
  63. elem !== 'foreignObject' // Don't check foreignObject
  64. ) {
  65. item.content.forEach(function(content, i) {
  66. if (
  67. content.isElem() &&
  68. !content.prefix &&
  69. (
  70. (
  71. elems[elem].content && // Do we have a record of its permitted content?
  72. elems[elem].content.indexOf(content.elem) === -1
  73. ) ||
  74. (
  75. !elems[elem].content && // we dont know about its permitted content
  76. !elems[content.elem] // check that we know about the element at all
  77. )
  78. )
  79. ) {
  80. item.content.splice(i, 1);
  81. }
  82. });
  83. }
  84. // remove element's unknown attrs and attrs with default values
  85. if (elems[elem] && elems[elem].attrs) {
  86. item.eachAttr(function(attr) {
  87. if (
  88. attr.name !== 'xmlns' &&
  89. (attr.prefix === 'xml' || !attr.prefix) &&
  90. (!params.keepDataAttrs || attr.name.indexOf('data-') != 0) &&
  91. (!params.keepAriaAttrs || attr.name.indexOf('aria-') != 0) &&
  92. (!params.keepRoleAttr || attr.name != 'role')
  93. ) {
  94. if (
  95. // unknown attrs
  96. (
  97. params.unknownAttrs &&
  98. elems[elem].attrs.indexOf(attr.name) === -1
  99. ) ||
  100. // attrs with default values
  101. (
  102. params.defaultAttrs &&
  103. !item.hasAttr('id') &&
  104. elems[elem].defaults &&
  105. elems[elem].defaults[attr.name] === attr.value && (
  106. attrsInheritable.indexOf(attr.name) < 0 ||
  107. !item.parentNode.computedAttr(attr.name)
  108. )
  109. ) ||
  110. // useless overrides
  111. (
  112. params.uselessOverrides &&
  113. !item.hasAttr('id') &&
  114. applyGroups.indexOf(attr.name) < 0 &&
  115. attrsInheritable.indexOf(attr.name) > -1 &&
  116. item.parentNode.computedAttr(attr.name, attr.value)
  117. )
  118. ) {
  119. item.removeAttr(attr.name);
  120. }
  121. }
  122. });
  123. }
  124. }
  125. };