UNPKG

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