reffy 14.6.2 → 14.7.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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "reffy",
|
|
3
|
-
"version": "14.
|
|
3
|
+
"version": "14.7.0",
|
|
4
4
|
"description": "W3C/WHATWG spec dependencies exploration companion. Features a short set of tools to study spec references as well as WebIDL term definitions and references found in W3C specifications.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -36,17 +36,17 @@
|
|
|
36
36
|
"ajv-formats": "2.1.1",
|
|
37
37
|
"commander": "12.0.0",
|
|
38
38
|
"fetch-filecache-for-crawling": "5.1.1",
|
|
39
|
-
"puppeteer": "22.
|
|
39
|
+
"puppeteer": "22.1.0",
|
|
40
40
|
"semver": "^7.3.5",
|
|
41
|
-
"web-specs": "
|
|
41
|
+
"web-specs": "3.3.0",
|
|
42
42
|
"webidl2": "24.4.1"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"chai": "4.3.10",
|
|
46
|
-
"mocha": "10.
|
|
46
|
+
"mocha": "10.3.0",
|
|
47
47
|
"respec": "34.4.0",
|
|
48
48
|
"respec-hljs": "2.1.1",
|
|
49
|
-
"rollup": "4.
|
|
49
|
+
"rollup": "4.12.0",
|
|
50
50
|
"undici": "^6.1.0"
|
|
51
51
|
},
|
|
52
52
|
"overrides": {
|
|
@@ -32,7 +32,8 @@
|
|
|
32
32
|
"required": ["fragment", "type"],
|
|
33
33
|
"properties": {
|
|
34
34
|
"fragment": { "type": "string" },
|
|
35
|
-
"type": { "$ref": "../common.json#/$defs/interfacetype" }
|
|
35
|
+
"type": { "$ref": "../common.json#/$defs/interfacetype" },
|
|
36
|
+
"href": { "$ref": "../common.json#/$defs/url" }
|
|
36
37
|
}
|
|
37
38
|
}
|
|
38
39
|
},
|
|
@@ -47,7 +48,8 @@
|
|
|
47
48
|
"required": ["fragment", "type"],
|
|
48
49
|
"properties": {
|
|
49
50
|
"fragment": { "type": "string" },
|
|
50
|
-
"type": { "$ref": "../common.json#/$defs/extensiontype" }
|
|
51
|
+
"type": { "$ref": "../common.json#/$defs/extensiontype" },
|
|
52
|
+
"href": { "$ref": "../common.json#/$defs/url" }
|
|
51
53
|
}
|
|
52
54
|
}
|
|
53
55
|
}
|
package/src/lib/specs-crawler.js
CHANGED
|
@@ -88,6 +88,11 @@ async function crawlSpec(spec, crawlOptions) {
|
|
|
88
88
|
if (crawlOptions.useCrawl) {
|
|
89
89
|
result = await expandSpecResult(spec, crawlOptions.useCrawl);
|
|
90
90
|
}
|
|
91
|
+
else if (!urlToCrawl) {
|
|
92
|
+
// No nightly URL? That means the spec is not public (typical
|
|
93
|
+
// example here is ISO specs). Nothing to crawl in such cases.
|
|
94
|
+
result = {};
|
|
95
|
+
}
|
|
91
96
|
else {
|
|
92
97
|
result = await processSpecification(
|
|
93
98
|
urlToCrawl,
|
|
@@ -120,7 +125,9 @@ async function crawlSpec(spec, crawlOptions) {
|
|
|
120
125
|
}
|
|
121
126
|
|
|
122
127
|
// Copy results back into initial spec object
|
|
123
|
-
|
|
128
|
+
if (result.crawled) {
|
|
129
|
+
spec.crawled = result.crawled;
|
|
130
|
+
}
|
|
124
131
|
if (result.crawlCacheInfo) {
|
|
125
132
|
spec.crawlCacheInfo = result.crawlCacheInfo;
|
|
126
133
|
}
|
|
@@ -8,17 +8,165 @@
|
|
|
8
8
|
const webidlParser = require('../cli/parse-webidl');
|
|
9
9
|
|
|
10
10
|
module.exports = {
|
|
11
|
-
dependsOn: ['idl'],
|
|
11
|
+
dependsOn: ['dfns', 'idl'],
|
|
12
12
|
input: 'spec',
|
|
13
13
|
property: 'idlparsed',
|
|
14
14
|
|
|
15
15
|
run: async function(spec, options) {
|
|
16
|
+
function getHref(idl, member) {
|
|
17
|
+
let dfnType;
|
|
18
|
+
let dfnFor;
|
|
19
|
+
let dfnOverload = 0;
|
|
20
|
+
let dfnName;
|
|
21
|
+
if (member) {
|
|
22
|
+
if (['iterable', 'maplike', 'setlike'].includes(member.type) ||
|
|
23
|
+
['getter', 'setter', 'stringifier', 'deleter'].includes(member.special)) {
|
|
24
|
+
// No dfns of these types in any spec as of Feb 2024, or at least no
|
|
25
|
+
// no dfns that we can easily map to (for example, the HTML spec
|
|
26
|
+
// tends to use generic "dfn" for these).
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
if (member.type === 'operation') {
|
|
30
|
+
dfnType = 'method';
|
|
31
|
+
dfnOverload = idl.members
|
|
32
|
+
.filter(m => m.type === member.type && m.name === member.name)
|
|
33
|
+
.findIndex(m => m === member);
|
|
34
|
+
}
|
|
35
|
+
else if (member.type === 'field') {
|
|
36
|
+
dfnType = 'dict-member';
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
dfnType = member.type;
|
|
40
|
+
}
|
|
41
|
+
dfnName = member.name ?? member.value;
|
|
42
|
+
if (member.type === 'constructor') {
|
|
43
|
+
dfnName = 'constructor';
|
|
44
|
+
}
|
|
45
|
+
dfnFor = idl.name;
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
// The type of the dfn to look for is the same as the IDL type, except
|
|
49
|
+
// that composed IDL types ("interface mixin", "callback interface")
|
|
50
|
+
// only have the basic type in definitions.
|
|
51
|
+
dfnType = idl.type.split(' ')[0];
|
|
52
|
+
dfnName = idl.name;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (!['attribute', 'callback', 'const', 'constructor',
|
|
56
|
+
'dict-member', 'dictionary', 'enum', 'enum-value',
|
|
57
|
+
'interface', 'method', 'namespace', 'typedef'
|
|
58
|
+
].includes(dfnType)) {
|
|
59
|
+
console.error(`[error] Found unexpected IDL type "${dfnType}" in ${spec.shortname}`);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const dfnNames = [];
|
|
63
|
+
if (dfnType === 'enum-value') {
|
|
64
|
+
// Bikeshed keeps wrapping quotes in the dfn linking text, not ReSpec.
|
|
65
|
+
dfnNames.push(dfnName);
|
|
66
|
+
dfnNames.push(`"${dfnName}"`);
|
|
67
|
+
}
|
|
68
|
+
else if (dfnType === 'method' || dfnType === 'constructor') {
|
|
69
|
+
// Spec authoring tools use different naming conventions in dfns:
|
|
70
|
+
// - For variadic arguments, Bikeshed adds "...", not ReSpec.
|
|
71
|
+
// - For overloads, Bikeshed relies on argument names, ReSpec adds
|
|
72
|
+
// "!overload-x" to the name of the second, third, etc. overloads.
|
|
73
|
+
// - The HTML spec sometimes excludes argument names from method dfns.
|
|
74
|
+
// We'll give these different variants a try, roughly starting from the
|
|
75
|
+
// most specific ones, in other words starting by looking at a specific
|
|
76
|
+
// overload dfn.
|
|
77
|
+
// When a method has overloads but the spec only has one dfn for the
|
|
78
|
+
// first variant, this approach will link the other overloads to that
|
|
79
|
+
// first dfn. That's slightly incorrect but a good enough approximation
|
|
80
|
+
// in practice.
|
|
81
|
+
const argsVariadic = member.arguments.map(arg => (arg.variadic ? '...' : '') + arg.name);
|
|
82
|
+
const args = member.arguments.map(arg => arg.name);
|
|
83
|
+
dfnNames.push(`${dfnName}!overload-${dfnOverload}(${args.join(', ')})`);
|
|
84
|
+
dfnNames.push(`${dfnName}(${argsVariadic.join(', ')})`);
|
|
85
|
+
dfnNames.push(`${dfnName}(${args.join(', ')})`);
|
|
86
|
+
dfnNames.push(`${dfnName}()`);
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
dfnNames.push(dfnName);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Look for definitions that look like good initial candidates
|
|
93
|
+
const candidateDfns = spec.dfns.filter(dfn =>
|
|
94
|
+
dfn.type === dfnType && (dfnFor ? dfn.for.includes(dfnFor) : true));
|
|
95
|
+
|
|
96
|
+
// Look for names in turn in that list of candidates.
|
|
97
|
+
for (const name of dfnNames) {
|
|
98
|
+
const dfns = candidateDfns.filter(dfn => dfn.linkingText.includes(name));
|
|
99
|
+
if (dfns.length > 0) {
|
|
100
|
+
if (dfns.length > 1) {
|
|
101
|
+
const forLabel = dfnFor ? ` for \`${dfnFor}\`` : '';
|
|
102
|
+
console.warn(`[warn] More than one dfn for ${dfnType} \`${dfnName}\`${forLabel} in [${spec.shortname}](${spec.crawled}).`);
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
return dfns[0].href;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
|
|
16
114
|
if (!spec?.idl) {
|
|
17
115
|
return spec;
|
|
18
116
|
}
|
|
19
117
|
try {
|
|
20
118
|
spec.idlparsed = await webidlParser.parse(spec.idl);
|
|
21
119
|
spec.idlparsed.hasObsoleteIdl = webidlParser.hasObsoleteIdl(spec.idl);
|
|
120
|
+
|
|
121
|
+
if (spec.dfns) {
|
|
122
|
+
for (const idl of Object.values(spec.idlparsed.idlNames)) {
|
|
123
|
+
const href = getHref(idl);
|
|
124
|
+
if (href) {
|
|
125
|
+
idl.href = href;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (idl.values) {
|
|
129
|
+
for (const value of idl.values) {
|
|
130
|
+
const href = getHref(idl, value);
|
|
131
|
+
if (href) {
|
|
132
|
+
value.href = href;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (idl.members) {
|
|
138
|
+
for (const member of idl.members) {
|
|
139
|
+
const href = getHref(idl, member);
|
|
140
|
+
if (href) {
|
|
141
|
+
member.href = href;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
for (const extendedIdl of Object.values(spec.idlparsed.idlExtendedNames)) {
|
|
148
|
+
for (const idl of extendedIdl) {
|
|
149
|
+
// No dfn for the extension, we can only link specific members
|
|
150
|
+
if (idl.values) {
|
|
151
|
+
for (const value of idl.values) {
|
|
152
|
+
const href = getHref(idl, value);
|
|
153
|
+
if (href) {
|
|
154
|
+
value.href = href;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if (idl.members) {
|
|
160
|
+
for (const member of idl.members) {
|
|
161
|
+
const href = getHref(idl, member);
|
|
162
|
+
if (href) {
|
|
163
|
+
member.href = href;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
22
170
|
}
|
|
23
171
|
catch (err) {
|
|
24
172
|
// IDL content is invalid and cannot be parsed.
|