reffy 6.2.0 → 6.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +158 -158
  3. package/index.js +11 -11
  4. package/package.json +53 -53
  5. package/reffy.js +248 -248
  6. package/src/browserlib/canonicalize-url.mjs +50 -50
  7. package/src/browserlib/create-outline.mjs +352 -352
  8. package/src/browserlib/extract-cssdfn.mjs +319 -319
  9. package/src/browserlib/extract-dfns.mjs +686 -686
  10. package/src/browserlib/extract-elements.mjs +205 -205
  11. package/src/browserlib/extract-headings.mjs +48 -48
  12. package/src/browserlib/extract-ids.mjs +28 -28
  13. package/src/browserlib/extract-links.mjs +28 -28
  14. package/src/browserlib/extract-references.mjs +203 -203
  15. package/src/browserlib/extract-webidl.mjs +134 -134
  16. package/src/browserlib/get-absolute-url.mjs +21 -21
  17. package/src/browserlib/get-generator.mjs +26 -26
  18. package/src/browserlib/get-lastmodified-date.mjs +13 -13
  19. package/src/browserlib/get-title.mjs +11 -11
  20. package/src/browserlib/informative-selector.mjs +16 -16
  21. package/src/browserlib/map-ids-to-headings.mjs +136 -136
  22. package/src/browserlib/reffy.json +53 -53
  23. package/src/cli/check-missing-dfns.js +609 -609
  24. package/src/cli/generate-idlnames.js +430 -430
  25. package/src/cli/generate-idlparsed.js +139 -139
  26. package/src/cli/merge-crawl-results.js +128 -128
  27. package/src/cli/parse-webidl.js +430 -430
  28. package/src/lib/css-grammar-parse-tree.schema.json +109 -109
  29. package/src/lib/css-grammar-parser.js +440 -440
  30. package/src/lib/fetch.js +55 -55
  31. package/src/lib/nock-server.js +119 -119
  32. package/src/lib/specs-crawler.js +605 -603
  33. package/src/lib/util.js +898 -898
  34. package/src/specs/missing-css-rules.json +197 -197
  35. package/src/specs/spec-equivalents.json +149 -149
  36. package/src/browserlib/extract-editors.mjs~ +0 -14
  37. package/src/browserlib/generate-es-dfn-report.sh~ +0 -4
  38. package/src/cli/csstree-grammar-check.js +0 -28
  39. package/src/cli/csstree-grammar-check.js~ +0 -10
  40. package/src/cli/csstree-grammar-parser.js +0 -11
  41. package/src/cli/csstree-grammar-parser.js~ +0 -1
  42. package/src/cli/extract-editors.js~ +0 -38
  43. package/src/cli/process-specs.js~ +0 -28
@@ -1,203 +1,203 @@
1
- import getGenerator from './get-generator.mjs';
2
-
3
-
4
- /**
5
- * Extract the list of references from the "References" appendix of the
6
- * current document.
7
- *
8
- * Notes:
9
- * - By definition, this function does not return the specifications that
10
- * the current document references in the prose but failed to add to the
11
- * "References" appendix.
12
- * - The function throws when no references could be found
13
- *
14
- * @function
15
- * @public
16
- * @return {Object} An object with a "normative" and/or an "informative"
17
- * property that list references as they appear in the "References".
18
- */
19
- export default function () {
20
- const generator = getGenerator();
21
- const extractionRules = getExtractionRules(generator);
22
- const references = extractReferences(extractionRules);
23
- if (references?.normative.length || references?.informative.length) {
24
- return references;
25
- }
26
- else {
27
- return null;
28
- }
29
- }
30
-
31
-
32
-
33
- /**
34
- * Given the name of the generator used to create the document,
35
- * return the rules to use to extract references.
36
- *
37
- * @function
38
- * @private
39
- * @param {String} generator The well-known generator used to create the doc,
40
- * null if unknown
41
- * @return {Object} Relevant extraction rules (or null if no rules seem to apply).
42
- */
43
- function getExtractionRules(generator) {
44
- const extractionRules = {
45
- bikeshed: {
46
- generator: "Bikeshed",
47
- listSelector: {
48
- normative: "#normative + dl",
49
- informative: "#informative + dl"
50
- }
51
- },
52
- respec: {
53
- generator: "ReSpec",
54
- listSelector: {
55
- normative: "#normative-references > dl",
56
- informative: "#informative-references > dl"
57
- }
58
- }
59
- };
60
-
61
- return (generator ? extractionRules[generator] : null);
62
- }
63
-
64
-
65
- /**
66
- * Skip next siblings until another tag with the given name is found
67
- *
68
- * @function
69
- * @private
70
- * @param {Node} node The DOM node to use as starting point
71
- * @param {String} name The sibling name to find
72
- * @return {Node} The next sibling with the given name, null if not found
73
- */
74
- function nextTag(node, name) {
75
- let nextEl = node.nextElementSibling;
76
- while(nextEl && nextEl.tagName !== name.toUpperCase()) {
77
- nextEl = nextEl.nextElementSibling;
78
- }
79
- return nextEl;
80
- }
81
-
82
-
83
- /**
84
- * Given a markup definition list, parse and return the list of references
85
- *
86
- * @function
87
- * @param {Node} referenceList The "dl" to parse
88
- * @param {Object} options Parsing options, set "filterInformative" to put
89
- * references flagged as "non-normative" to a separate returned list
90
- * @return {Array} An array whose first item is the list of references and the
91
- * second item the list of "non-normative" references (the second item is only
92
- * set when "filterInformative" is set)
93
- */
94
- function parseReferences(referenceList, options) {
95
- var defaultRef = [], informativeRef = [];
96
- options = options || {};
97
- [].forEach.call(referenceList.querySelectorAll("dt"), function (dt) {
98
- var ref = {};
99
- ref.name = dt.textContent.replace(/[\[\] \n]/g, '');
100
- var desc = nextTag(dt, "dd");
101
- if (!desc || !ref.name) {
102
- return;
103
- }
104
- ref.url = desc.querySelector('a[href^="http"]')?.href ?? "";
105
- if (options.filterInformative &&
106
- desc.textContent.match(/non-normative/i)) {
107
- return informativeRef.push(ref);
108
- }
109
- defaultRef.push(ref);
110
- });
111
- return [defaultRef, informativeRef];
112
- };
113
-
114
- const textMatch = re => n => n.textContent.match(re);
115
-
116
- /**
117
- * Extract references from generic documents that we could not associate with
118
- * any particular set of extraction rules.
119
- *
120
- * @function
121
- * @private
122
- * @return {Object} A list of references.
123
- */
124
- function extractReferencesWithoutRules() {
125
- const references = {
126
- normative: [],
127
- informative: []
128
- };
129
- const anchors = [...document.querySelectorAll("h1, h2, h3")];
130
- const referenceHeadings = anchors.filter(textMatch(/references/i));
131
- if (!referenceHeadings.length) {
132
- return references;
133
- }
134
- if (referenceHeadings.length > 1) {
135
- const normative = referenceHeadings.find(textMatch(/normative/i));
136
- if (normative) {
137
- const nList = nextTag(normative, "dl");
138
- if (nList) {
139
- references.normative = parseReferences(nList)[0];
140
- }
141
- }
142
- const informative = referenceHeadings.find(textMatch(/informative/i));
143
- if (informative) {
144
- const iList = nextTag(informative, "dl");
145
- if (iList) {
146
- references.informative = parseReferences(iList)[0];
147
- }
148
- }
149
- if (informative || normative) {
150
- return references;
151
- }
152
- }
153
-
154
- // If there are still multiple reference headings,
155
- // keep only the last one
156
- const referenceHeading = referenceHeadings.pop();
157
- const list = nextTag(referenceHeading, "dl");
158
- if (list) {
159
- const refs = parseReferences(list, { filterInformative: true });
160
- references.normative = refs[0];
161
- references.informative = refs[1];
162
- }
163
- return references;
164
- }
165
-
166
-
167
- /**
168
- * Extract references from the given document
169
- *
170
- * @function
171
- * @private
172
- * @param {Object} rules Extraction rules to use
173
- * @return {Object} A list of references.
174
- */
175
- function extractReferences(rules) {
176
- if (!rules) {
177
- return extractReferencesWithoutRules();
178
- }
179
- if (!rules.listSelector ||
180
- !rules.listSelector.normative) {
181
- throw new Error("Extraction rules for the list of references are incorrect");
182
- }
183
- const generator = rules.generator || "an unknown generator";
184
-
185
- const references = {
186
- normative: [],
187
- informative: []
188
- };
189
- ["normative", "informative"].forEach(function (referenceType) {
190
- const referenceList = document.querySelector(rules.listSelector[referenceType]);
191
- if (referenceList) {
192
- const refs = parseReferences(referenceList, {
193
- filterInformative: (referenceType === "normative")
194
- });
195
- references[referenceType] = references[referenceType].concat(refs[0]);
196
- if (referenceType === "normative") {
197
- references.informative = references.informative.concat(refs[1]);
198
- }
199
- }
200
- });
201
-
202
- return references;
203
- }
1
+ import getGenerator from './get-generator.mjs';
2
+
3
+
4
+ /**
5
+ * Extract the list of references from the "References" appendix of the
6
+ * current document.
7
+ *
8
+ * Notes:
9
+ * - By definition, this function does not return the specifications that
10
+ * the current document references in the prose but failed to add to the
11
+ * "References" appendix.
12
+ * - The function throws when no references could be found
13
+ *
14
+ * @function
15
+ * @public
16
+ * @return {Object} An object with a "normative" and/or an "informative"
17
+ * property that list references as they appear in the "References".
18
+ */
19
+ export default function () {
20
+ const generator = getGenerator();
21
+ const extractionRules = getExtractionRules(generator);
22
+ const references = extractReferences(extractionRules);
23
+ if (references?.normative.length || references?.informative.length) {
24
+ return references;
25
+ }
26
+ else {
27
+ return null;
28
+ }
29
+ }
30
+
31
+
32
+
33
+ /**
34
+ * Given the name of the generator used to create the document,
35
+ * return the rules to use to extract references.
36
+ *
37
+ * @function
38
+ * @private
39
+ * @param {String} generator The well-known generator used to create the doc,
40
+ * null if unknown
41
+ * @return {Object} Relevant extraction rules (or null if no rules seem to apply).
42
+ */
43
+ function getExtractionRules(generator) {
44
+ const extractionRules = {
45
+ bikeshed: {
46
+ generator: "Bikeshed",
47
+ listSelector: {
48
+ normative: "#normative + dl",
49
+ informative: "#informative + dl"
50
+ }
51
+ },
52
+ respec: {
53
+ generator: "ReSpec",
54
+ listSelector: {
55
+ normative: "#normative-references > dl",
56
+ informative: "#informative-references > dl"
57
+ }
58
+ }
59
+ };
60
+
61
+ return (generator ? extractionRules[generator] : null);
62
+ }
63
+
64
+
65
+ /**
66
+ * Skip next siblings until another tag with the given name is found
67
+ *
68
+ * @function
69
+ * @private
70
+ * @param {Node} node The DOM node to use as starting point
71
+ * @param {String} name The sibling name to find
72
+ * @return {Node} The next sibling with the given name, null if not found
73
+ */
74
+ function nextTag(node, name) {
75
+ let nextEl = node.nextElementSibling;
76
+ while(nextEl && nextEl.tagName !== name.toUpperCase()) {
77
+ nextEl = nextEl.nextElementSibling;
78
+ }
79
+ return nextEl;
80
+ }
81
+
82
+
83
+ /**
84
+ * Given a markup definition list, parse and return the list of references
85
+ *
86
+ * @function
87
+ * @param {Node} referenceList The "dl" to parse
88
+ * @param {Object} options Parsing options, set "filterInformative" to put
89
+ * references flagged as "non-normative" to a separate returned list
90
+ * @return {Array} An array whose first item is the list of references and the
91
+ * second item the list of "non-normative" references (the second item is only
92
+ * set when "filterInformative" is set)
93
+ */
94
+ function parseReferences(referenceList, options) {
95
+ var defaultRef = [], informativeRef = [];
96
+ options = options || {};
97
+ [].forEach.call(referenceList.querySelectorAll("dt"), function (dt) {
98
+ var ref = {};
99
+ ref.name = dt.textContent.replace(/[\[\] \n]/g, '');
100
+ var desc = nextTag(dt, "dd");
101
+ if (!desc || !ref.name) {
102
+ return;
103
+ }
104
+ ref.url = desc.querySelector('a[href^="http"]')?.href ?? "";
105
+ if (options.filterInformative &&
106
+ desc.textContent.match(/non-normative/i)) {
107
+ return informativeRef.push(ref);
108
+ }
109
+ defaultRef.push(ref);
110
+ });
111
+ return [defaultRef, informativeRef];
112
+ };
113
+
114
+ const textMatch = re => n => n.textContent.match(re);
115
+
116
+ /**
117
+ * Extract references from generic documents that we could not associate with
118
+ * any particular set of extraction rules.
119
+ *
120
+ * @function
121
+ * @private
122
+ * @return {Object} A list of references.
123
+ */
124
+ function extractReferencesWithoutRules() {
125
+ const references = {
126
+ normative: [],
127
+ informative: []
128
+ };
129
+ const anchors = [...document.querySelectorAll("h1, h2, h3")];
130
+ const referenceHeadings = anchors.filter(textMatch(/references/i));
131
+ if (!referenceHeadings.length) {
132
+ return references;
133
+ }
134
+ if (referenceHeadings.length > 1) {
135
+ const normative = referenceHeadings.find(textMatch(/normative/i));
136
+ if (normative) {
137
+ const nList = nextTag(normative, "dl");
138
+ if (nList) {
139
+ references.normative = parseReferences(nList)[0];
140
+ }
141
+ }
142
+ const informative = referenceHeadings.find(textMatch(/informative/i));
143
+ if (informative) {
144
+ const iList = nextTag(informative, "dl");
145
+ if (iList) {
146
+ references.informative = parseReferences(iList)[0];
147
+ }
148
+ }
149
+ if (informative || normative) {
150
+ return references;
151
+ }
152
+ }
153
+
154
+ // If there are still multiple reference headings,
155
+ // keep only the last one
156
+ const referenceHeading = referenceHeadings.pop();
157
+ const list = nextTag(referenceHeading, "dl");
158
+ if (list) {
159
+ const refs = parseReferences(list, { filterInformative: true });
160
+ references.normative = refs[0];
161
+ references.informative = refs[1];
162
+ }
163
+ return references;
164
+ }
165
+
166
+
167
+ /**
168
+ * Extract references from the given document
169
+ *
170
+ * @function
171
+ * @private
172
+ * @param {Object} rules Extraction rules to use
173
+ * @return {Object} A list of references.
174
+ */
175
+ function extractReferences(rules) {
176
+ if (!rules) {
177
+ return extractReferencesWithoutRules();
178
+ }
179
+ if (!rules.listSelector ||
180
+ !rules.listSelector.normative) {
181
+ throw new Error("Extraction rules for the list of references are incorrect");
182
+ }
183
+ const generator = rules.generator || "an unknown generator";
184
+
185
+ const references = {
186
+ normative: [],
187
+ informative: []
188
+ };
189
+ ["normative", "informative"].forEach(function (referenceType) {
190
+ const referenceList = document.querySelector(rules.listSelector[referenceType]);
191
+ if (referenceList) {
192
+ const refs = parseReferences(referenceList, {
193
+ filterInformative: (referenceType === "normative")
194
+ });
195
+ references[referenceType] = references[referenceType].concat(refs[0]);
196
+ if (referenceType === "normative") {
197
+ references.informative = references.informative.concat(refs[1]);
198
+ }
199
+ }
200
+ });
201
+
202
+ return references;
203
+ }
@@ -1,135 +1,135 @@
1
- import getGenerator from './get-generator.mjs';
2
- import informativeSelector from './informative-selector.mjs';
3
-
4
- /**
5
- * Extract the list of WebIDL definitions in the current spec
6
- *
7
- * @function
8
- * @public
9
- * @return {Promise} The promise to get a dump of the IDL definitions, or
10
- * an empty string if the spec does not contain any IDL.
11
- */
12
- export default function () {
13
- const generator = getGenerator();
14
- let idl = '';
15
- if (generator === 'bikeshed') {
16
- idl = extractBikeshedIdl();
17
- }
18
- else if (document.title.startsWith('Web IDL')) {
19
- // IDL content in the Web IDL spec are... examples,
20
- // not real definitions
21
- }
22
- else {
23
- // Most non-ReSpec specs still follow the ReSpec conventions
24
- // for IDL definitions
25
- idl = extractRespecIdl();
26
- }
27
-
28
- if (idl) {
29
- // Remove trailing spaces and use spaces throughout
30
- idl = idl
31
- .replace(/\s+$/gm, '\n')
32
- .replace(/\t/g, ' ')
33
- .trim();
34
- }
35
- return idl;
36
- }
37
-
38
-
39
- /**
40
- * Extract IDL definitions from a Bikeshed spec
41
- *
42
- * Note Bikeshed summarizes IDL definitions in an appendix. This is
43
- * what the code uses.
44
- */
45
- function extractBikeshedIdl() {
46
- const idlHeading = document.getElementById('idl-index');
47
- if (idlHeading) {
48
- const nextEl = idlHeading.nextElementSibling;
49
- if (nextEl) {
50
- return nextEl.textContent;
51
- }
52
- else {
53
- throw new Error('Could not find IDL in IDL index');
54
- }
55
- }
56
- else {
57
- // the document may have been generated with "omit idl-index"
58
- // in which case, we try the simple way
59
- return extractRespecIdl();
60
- }
61
- }
62
-
63
-
64
- /**
65
- * Extract IDL definitions from a ReSpec spec, and in practice from
66
- * most other specs as well.
67
- *
68
- * The function tries all known patterns used to define IDL content, making
69
- * sure that it only extracts elements once.
70
- */
71
- function extractRespecIdl() {
72
- // Helper function that trims individual lines in an IDL block,
73
- // removing as much space as possible from the beginning of the page
74
- // while preserving indentation. Rules followed:
75
- // - Always trim the first line
76
- // - Remove whitespaces from the end of each line
77
- // - Replace lines that contain spaces with empty lines
78
- // - Drop same number of leading whitespaces from all other lines
79
- const trimIdlSpaces = idl => {
80
- const lines = idl.trim().split('\n');
81
- const toRemove = lines
82
- .slice(1)
83
- .filter(line => line.search(/\S/) > -1)
84
- .reduce(
85
- (min, line) => Math.min(min, line.search(/\S/)),
86
- Number.MAX_VALUE);
87
- return lines
88
- .map(line => {
89
- let firstRealChat = line.search(/\S/);
90
- if (firstRealChat === -1) {
91
- return '';
92
- }
93
- else if (firstRealChat === 0) {
94
- return line.replace(/\s+$/, '');
95
- }
96
- else {
97
- return line.substring(toRemove).replace(/\s+$/, '');
98
- }
99
- })
100
- .join('\n');
101
- };
102
-
103
- // Detect the IDL index appendix if there's one (to exclude it)
104
- const idlEl = document.querySelector('#idl-index pre') ||
105
- document.querySelector('.chapter-idl pre'); // SVG 2 draft
106
-
107
- let idl = [
108
- 'pre.idl:not(.exclude):not(.extract):not(#actual-idl-index)',
109
- 'pre:not(.exclude):not(.extract) > code.idl-code:not(.exclude):not(.extract)',
110
- 'pre:not(.exclude):not(.extract) > code.idl:not(.exclude):not(.extract)',
111
- 'div.idl-code:not(.exclude):not(.extract) > pre:not(.exclude):not(.extract)',
112
- 'pre.widl:not(.exclude):not(.extract)'
113
- ]
114
- .map(sel => [...document.querySelectorAll(sel)])
115
- .reduce((res, elements) => res.concat(elements), [])
116
- .filter(el => el !== idlEl)
117
- .filter((el, idx, self) => self.indexOf(el) === idx)
118
- .filter(el => !el.closest(informativeSelector))
119
- .map(el => el.cloneNode(true))
120
- .map(el => {
121
- const header = el.querySelector('.idlHeader');
122
- if (header) {
123
- header.remove();
124
- }
125
- const tests = el.querySelector('details.respec-tests-details');
126
- if (tests) {
127
- tests.remove();
128
- }
129
- return el;
130
- })
131
- .map(el => trimIdlSpaces(el.textContent))
132
- .join('\n\n');
133
-
134
- return idl;
1
+ import getGenerator from './get-generator.mjs';
2
+ import informativeSelector from './informative-selector.mjs';
3
+
4
+ /**
5
+ * Extract the list of WebIDL definitions in the current spec
6
+ *
7
+ * @function
8
+ * @public
9
+ * @return {Promise} The promise to get a dump of the IDL definitions, or
10
+ * an empty string if the spec does not contain any IDL.
11
+ */
12
+ export default function () {
13
+ const generator = getGenerator();
14
+ let idl = '';
15
+ if (generator === 'bikeshed') {
16
+ idl = extractBikeshedIdl();
17
+ }
18
+ else if (document.title.startsWith('Web IDL')) {
19
+ // IDL content in the Web IDL spec are... examples,
20
+ // not real definitions
21
+ }
22
+ else {
23
+ // Most non-ReSpec specs still follow the ReSpec conventions
24
+ // for IDL definitions
25
+ idl = extractRespecIdl();
26
+ }
27
+
28
+ if (idl) {
29
+ // Remove trailing spaces and use spaces throughout
30
+ idl = idl
31
+ .replace(/\s+$/gm, '\n')
32
+ .replace(/\t/g, ' ')
33
+ .trim();
34
+ }
35
+ return idl;
36
+ }
37
+
38
+
39
+ /**
40
+ * Extract IDL definitions from a Bikeshed spec
41
+ *
42
+ * Note Bikeshed summarizes IDL definitions in an appendix. This is
43
+ * what the code uses.
44
+ */
45
+ function extractBikeshedIdl() {
46
+ const idlHeading = document.getElementById('idl-index');
47
+ if (idlHeading) {
48
+ const nextEl = idlHeading.nextElementSibling;
49
+ if (nextEl) {
50
+ return nextEl.textContent;
51
+ }
52
+ else {
53
+ throw new Error('Could not find IDL in IDL index');
54
+ }
55
+ }
56
+ else {
57
+ // the document may have been generated with "omit idl-index"
58
+ // in which case, we try the simple way
59
+ return extractRespecIdl();
60
+ }
61
+ }
62
+
63
+
64
+ /**
65
+ * Extract IDL definitions from a ReSpec spec, and in practice from
66
+ * most other specs as well.
67
+ *
68
+ * The function tries all known patterns used to define IDL content, making
69
+ * sure that it only extracts elements once.
70
+ */
71
+ function extractRespecIdl() {
72
+ // Helper function that trims individual lines in an IDL block,
73
+ // removing as much space as possible from the beginning of the page
74
+ // while preserving indentation. Rules followed:
75
+ // - Always trim the first line
76
+ // - Remove whitespaces from the end of each line
77
+ // - Replace lines that contain spaces with empty lines
78
+ // - Drop same number of leading whitespaces from all other lines
79
+ const trimIdlSpaces = idl => {
80
+ const lines = idl.trim().split('\n');
81
+ const toRemove = lines
82
+ .slice(1)
83
+ .filter(line => line.search(/\S/) > -1)
84
+ .reduce(
85
+ (min, line) => Math.min(min, line.search(/\S/)),
86
+ Number.MAX_VALUE);
87
+ return lines
88
+ .map(line => {
89
+ let firstRealChat = line.search(/\S/);
90
+ if (firstRealChat === -1) {
91
+ return '';
92
+ }
93
+ else if (firstRealChat === 0) {
94
+ return line.replace(/\s+$/, '');
95
+ }
96
+ else {
97
+ return line.substring(toRemove).replace(/\s+$/, '');
98
+ }
99
+ })
100
+ .join('\n');
101
+ };
102
+
103
+ // Detect the IDL index appendix if there's one (to exclude it)
104
+ const idlEl = document.querySelector('#idl-index pre') ||
105
+ document.querySelector('.chapter-idl pre'); // SVG 2 draft
106
+
107
+ let idl = [
108
+ 'pre.idl:not(.exclude):not(.extract):not(#actual-idl-index)',
109
+ 'pre:not(.exclude):not(.extract) > code.idl-code:not(.exclude):not(.extract)',
110
+ 'pre:not(.exclude):not(.extract) > code.idl:not(.exclude):not(.extract)',
111
+ 'div.idl-code:not(.exclude):not(.extract) > pre:not(.exclude):not(.extract)',
112
+ 'pre.widl:not(.exclude):not(.extract)'
113
+ ]
114
+ .map(sel => [...document.querySelectorAll(sel)])
115
+ .reduce((res, elements) => res.concat(elements), [])
116
+ .filter(el => el !== idlEl)
117
+ .filter((el, idx, self) => self.indexOf(el) === idx)
118
+ .filter(el => !el.closest(informativeSelector))
119
+ .map(el => el.cloneNode(true))
120
+ .map(el => {
121
+ const header = el.querySelector('.idlHeader');
122
+ if (header) {
123
+ header.remove();
124
+ }
125
+ const tests = el.querySelector('details.respec-tests-details');
126
+ if (tests) {
127
+ tests.remove();
128
+ }
129
+ return el;
130
+ })
131
+ .map(el => trimIdlSpaces(el.textContent))
132
+ .join('\n\n');
133
+
134
+ return idl;
135
135
  }