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.
- package/LICENSE +21 -21
- package/README.md +158 -158
- package/index.js +11 -11
- package/package.json +53 -53
- package/reffy.js +248 -248
- package/src/browserlib/canonicalize-url.mjs +50 -50
- package/src/browserlib/create-outline.mjs +352 -352
- package/src/browserlib/extract-cssdfn.mjs +319 -319
- package/src/browserlib/extract-dfns.mjs +686 -686
- package/src/browserlib/extract-elements.mjs +205 -205
- package/src/browserlib/extract-headings.mjs +48 -48
- package/src/browserlib/extract-ids.mjs +28 -28
- package/src/browserlib/extract-links.mjs +28 -28
- package/src/browserlib/extract-references.mjs +203 -203
- package/src/browserlib/extract-webidl.mjs +134 -134
- package/src/browserlib/get-absolute-url.mjs +21 -21
- package/src/browserlib/get-generator.mjs +26 -26
- package/src/browserlib/get-lastmodified-date.mjs +13 -13
- package/src/browserlib/get-title.mjs +11 -11
- package/src/browserlib/informative-selector.mjs +16 -16
- package/src/browserlib/map-ids-to-headings.mjs +136 -136
- package/src/browserlib/reffy.json +53 -53
- package/src/cli/check-missing-dfns.js +609 -609
- package/src/cli/generate-idlnames.js +430 -430
- package/src/cli/generate-idlparsed.js +139 -139
- package/src/cli/merge-crawl-results.js +128 -128
- package/src/cli/parse-webidl.js +430 -430
- package/src/lib/css-grammar-parse-tree.schema.json +109 -109
- package/src/lib/css-grammar-parser.js +440 -440
- package/src/lib/fetch.js +55 -55
- package/src/lib/nock-server.js +119 -119
- package/src/lib/specs-crawler.js +605 -603
- package/src/lib/util.js +898 -898
- package/src/specs/missing-css-rules.json +197 -197
- package/src/specs/spec-equivalents.json +149 -149
- package/src/browserlib/extract-editors.mjs~ +0 -14
- package/src/browserlib/generate-es-dfn-report.sh~ +0 -4
- package/src/cli/csstree-grammar-check.js +0 -28
- package/src/cli/csstree-grammar-check.js~ +0 -10
- package/src/cli/csstree-grammar-parser.js +0 -11
- package/src/cli/csstree-grammar-parser.js~ +0 -1
- package/src/cli/extract-editors.js~ +0 -38
- 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
|
}
|