reffy 18.8.2 → 19.0.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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "reffy",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "19.0.1",
|
|
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",
|
|
@@ -37,15 +37,15 @@
|
|
|
37
37
|
"ajv-formats": "3.0.1",
|
|
38
38
|
"commander": "14.0.0",
|
|
39
39
|
"fetch-filecache-for-crawling": "5.1.1",
|
|
40
|
-
"puppeteer": "24.10.
|
|
40
|
+
"puppeteer": "24.10.1",
|
|
41
41
|
"semver": "^7.3.5",
|
|
42
42
|
"web-specs": "3.53.0",
|
|
43
43
|
"webidl2": "24.4.1"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
|
-
"respec": "35.4.
|
|
46
|
+
"respec": "35.4.1",
|
|
47
47
|
"respec-hljs": "2.1.1",
|
|
48
|
-
"rollup": "4.
|
|
48
|
+
"rollup": "4.43.0",
|
|
49
49
|
"undici": "^7.0.0"
|
|
50
50
|
},
|
|
51
51
|
"overrides": {
|
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
"$schema": "http://json-schema.org/schema#",
|
|
3
3
|
"$id": "https://github.com/w3c/reffy/blob/main/schemas/postprocessing/css.json",
|
|
4
4
|
|
|
5
|
+
"$defs": {
|
|
6
|
+
"scopes": {
|
|
7
|
+
"type": "array",
|
|
8
|
+
"items": {
|
|
9
|
+
"type": "string"
|
|
10
|
+
},
|
|
11
|
+
"minItems": 1
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
|
|
5
15
|
"type": "object",
|
|
6
16
|
"additionalProperties": false,
|
|
7
17
|
"required": ["atrules", "functions", "properties", "selectors", "types"],
|
|
@@ -15,7 +25,7 @@
|
|
|
15
25
|
"properties": {
|
|
16
26
|
"name": { "type": "string", "pattern": "^@" },
|
|
17
27
|
"href": { "$ref": "../common.json#/$defs/url" },
|
|
18
|
-
"
|
|
28
|
+
"syntax": { "$ref": "../common.json#/$defs/cssValue" },
|
|
19
29
|
"prose": { "type": "string" },
|
|
20
30
|
"descriptors": {
|
|
21
31
|
"type": "array",
|
|
@@ -27,7 +37,7 @@
|
|
|
27
37
|
"name": { "type": "string" },
|
|
28
38
|
"for": { "type": "string" },
|
|
29
39
|
"href": { "$ref": "../common.json#/$defs/url" },
|
|
30
|
-
"
|
|
40
|
+
"syntax": { "$ref": "../common.json#/$defs/cssValue" }
|
|
31
41
|
}
|
|
32
42
|
}
|
|
33
43
|
}
|
|
@@ -41,12 +51,12 @@
|
|
|
41
51
|
"required": ["name", "type"],
|
|
42
52
|
"additionalProperties": false,
|
|
43
53
|
"properties": {
|
|
44
|
-
"name": { "type": "string", "pattern": "
|
|
45
|
-
"for": { "
|
|
54
|
+
"name": { "type": "string", "pattern": "^.*()$" },
|
|
55
|
+
"for": { "$ref": "#/$defs/scopes" },
|
|
46
56
|
"href": { "$ref": "../common.json#/$defs/url" },
|
|
47
57
|
"type": { "type": "string", "enum": ["function"] },
|
|
48
58
|
"prose": { "type": "string" },
|
|
49
|
-
"
|
|
59
|
+
"syntax": { "$ref": "../common.json#/$defs/cssValue" }
|
|
50
60
|
}
|
|
51
61
|
}
|
|
52
62
|
},
|
|
@@ -59,7 +69,7 @@
|
|
|
59
69
|
"properties": {
|
|
60
70
|
"name": { "$ref": "../common.json#/$defs/cssPropertyName" },
|
|
61
71
|
"href": { "$ref": "../common.json#/$defs/url" },
|
|
62
|
-
"
|
|
72
|
+
"syntax": { "$ref": "../common.json#/$defs/cssValue" },
|
|
63
73
|
"legacyAliasOf": { "$ref": "../common.json#/$defs/cssPropertyName" },
|
|
64
74
|
"styleDeclaration": {
|
|
65
75
|
"type": "array",
|
|
@@ -79,7 +89,7 @@
|
|
|
79
89
|
"name": { "$ref": "../common.json#/$defs/cssPropertyName" },
|
|
80
90
|
"href": { "$ref": "../common.json#/$defs/url" },
|
|
81
91
|
"prose": { "type": "string" },
|
|
82
|
-
"
|
|
92
|
+
"syntax": { "$ref": "../common.json#/$defs/cssValue" }
|
|
83
93
|
}
|
|
84
94
|
}
|
|
85
95
|
},
|
|
@@ -90,12 +100,12 @@
|
|
|
90
100
|
"required": ["name", "type"],
|
|
91
101
|
"additionalProperties": false,
|
|
92
102
|
"properties": {
|
|
93
|
-
"name": { "type": "string", "pattern": "
|
|
94
|
-
"for": { "
|
|
103
|
+
"name": { "type": "string", "pattern": "^[a-zA-Z0-9-\\+\\(\\)\\[\\]\\{\\}]+$" },
|
|
104
|
+
"for": { "$ref": "#/$defs/scopes" },
|
|
95
105
|
"href": { "$ref": "../common.json#/$defs/url" },
|
|
96
106
|
"type": { "type": "string", "enum": ["type"] },
|
|
97
107
|
"prose": { "type": "string" },
|
|
98
|
-
"
|
|
108
|
+
"syntax": { "$ref": "../common.json#/$defs/cssValue" }
|
|
99
109
|
}
|
|
100
110
|
}
|
|
101
111
|
}
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* In CSS extracts, functions and types that are defined for another construct
|
|
14
14
|
* appear under the `values` key of that construct entry. In the resulting
|
|
15
15
|
* construct, they get copied to the root lists under `functions` or `types`,
|
|
16
|
-
* and get a `for` key that contains the
|
|
16
|
+
* and get a `for` key that contains the list of constructs that they are
|
|
17
17
|
* defined for.
|
|
18
18
|
*
|
|
19
19
|
* CSS properties that are defined in one spec and extended in other specs get
|
|
@@ -51,12 +51,10 @@
|
|
|
51
51
|
* - This code uses arrays for lists, MDN data uses indexed objects.
|
|
52
52
|
* - This code lists scoped definitions with a `for` key. MDN data only has
|
|
53
53
|
* unscoped definitions.
|
|
54
|
-
* - This code stores syntaxes in a `value` key, MDN data uses a `syntax` key.
|
|
55
54
|
* - This code stores syntaxes of functions and types directly in the
|
|
56
55
|
* `functions` and `types` lists. MDN data stores them in a separate `syntaxes`
|
|
57
56
|
* category. The `syntaxes` view can be built by merging the `functions` and
|
|
58
57
|
* `types` lists.
|
|
59
|
-
* - This code keeps the surrounding `<>` for type names, MDN data does not.
|
|
60
58
|
*
|
|
61
59
|
* Module runs at the crawl level to create a `css.json` file.
|
|
62
60
|
*/
|
|
@@ -158,14 +156,27 @@ export default {
|
|
|
158
156
|
// ... and since we're looping through features, let's get rid
|
|
159
157
|
// of inner value definitions, which we no longer need
|
|
160
158
|
// (interesting ones were already copied to the root level)
|
|
159
|
+
// Let's also turn `value` keys into `syntax` keys because that's
|
|
160
|
+
// a better name and that matches what MDN data uses, and drop
|
|
161
|
+
// enclosing `<` and `>` for type names (type names that look like
|
|
162
|
+
// functions should be .
|
|
161
163
|
if (feature.values) {
|
|
162
164
|
delete feature.values;
|
|
163
165
|
}
|
|
166
|
+
if (feature.value) {
|
|
167
|
+
feature.syntax = feature.value;
|
|
168
|
+
delete feature.value;
|
|
169
|
+
}
|
|
164
170
|
for (const descriptor of feature.descriptors ?? []) {
|
|
165
171
|
if (descriptor.values) {
|
|
166
172
|
delete descriptor.values;
|
|
167
173
|
}
|
|
174
|
+
if (descriptor.value) {
|
|
175
|
+
descriptor.syntax = descriptor.value;
|
|
176
|
+
delete descriptor.value;
|
|
177
|
+
}
|
|
168
178
|
}
|
|
179
|
+
feature.name = unwrapName(feature.name);
|
|
169
180
|
|
|
170
181
|
const featureId = getFeatureId(feature);
|
|
171
182
|
if (!featureDfns[featureId]) {
|
|
@@ -178,10 +189,10 @@ export default {
|
|
|
178
189
|
// (that has some known syntax) in the most recent level. Move that base
|
|
179
190
|
// definition to the beginning of the array and get rid of other base
|
|
180
191
|
// definitions.
|
|
181
|
-
// (Note: the code
|
|
182
|
-
// unrelated specs still exist)
|
|
192
|
+
// (Note: the code chooses one definition if duplicates of base
|
|
193
|
+
// definitions in unrelated specs still exist)
|
|
183
194
|
for (const [name, dfns] of Object.entries(featureDfns)) {
|
|
184
|
-
let actualDfns = dfns.filter(dfn => dfn.
|
|
195
|
+
let actualDfns = dfns.filter(dfn => dfn.syntax);
|
|
185
196
|
if (actualDfns.length === 0) {
|
|
186
197
|
actualDfns = dfns.filter(dfn => !dfn.newValues);
|
|
187
198
|
}
|
|
@@ -214,7 +225,7 @@ export default {
|
|
|
214
225
|
if (dfn === baseDfn) {
|
|
215
226
|
continue;
|
|
216
227
|
}
|
|
217
|
-
if (baseDfn.
|
|
228
|
+
if (baseDfn.syntax && dfn.newValues) {
|
|
218
229
|
const newerDfn = dfns.find(d =>
|
|
219
230
|
d !== dfn &&
|
|
220
231
|
d.newValues === dfn.newValues &&
|
|
@@ -224,7 +235,7 @@ export default {
|
|
|
224
235
|
// the older one
|
|
225
236
|
continue;
|
|
226
237
|
}
|
|
227
|
-
baseDfn.
|
|
238
|
+
baseDfn.syntax += ' | ' + dfn.newValues;
|
|
228
239
|
}
|
|
229
240
|
if (baseDfn.descriptors && dfn.descriptors?.length > 0) {
|
|
230
241
|
baseDfn.descriptors.push(...dfn.descriptors.filter(desc => {
|
|
@@ -253,28 +264,28 @@ export default {
|
|
|
253
264
|
if (unscoped) {
|
|
254
265
|
// Only keep the scoped feature if it has a known syntax that
|
|
255
266
|
// differs from the unscoped feature
|
|
256
|
-
return feature.
|
|
267
|
+
return feature.syntax && feature.syntax !== unscoped.syntax;
|
|
257
268
|
}
|
|
258
269
|
}
|
|
259
270
|
return true;
|
|
260
271
|
})
|
|
261
272
|
.map(feature => {
|
|
262
273
|
if (feature.descriptors?.length > 0 &&
|
|
263
|
-
feature.
|
|
274
|
+
feature.syntax?.match(/{ <declaration-(rule-)?list> }/)) {
|
|
264
275
|
// Note: More advanced logic would allow to get rid of enclosing
|
|
265
276
|
// grouping constructs when there's no ambiguity. We'll stick to
|
|
266
277
|
// simple logic for now.
|
|
267
278
|
const syntax = feature.descriptors
|
|
268
279
|
.map(desc => {
|
|
269
280
|
if (desc.name.startsWith('@')) {
|
|
270
|
-
return `[ ${desc.
|
|
281
|
+
return `[ ${desc.syntax} ]`;
|
|
271
282
|
}
|
|
272
283
|
else {
|
|
273
|
-
return `[ ${desc.name}: [ ${desc.
|
|
284
|
+
return `[ ${desc.name}: [ ${desc.syntax} ]; ]`;
|
|
274
285
|
}
|
|
275
286
|
})
|
|
276
287
|
.join(' ||\n ');
|
|
277
|
-
feature.
|
|
288
|
+
feature.syntax = feature.syntax.replace(
|
|
278
289
|
/{ <declaration-(rule-)?list> }/,
|
|
279
290
|
'{\n ' + syntax + '\n}');
|
|
280
291
|
}
|
|
@@ -286,16 +297,42 @@ export default {
|
|
|
286
297
|
// Various CSS properties are "legacy aliases of" another property. Use the
|
|
287
298
|
// syntax of the other property for these.
|
|
288
299
|
for (const feature of categorized[category]) {
|
|
289
|
-
if (feature.legacyAliasOf && !feature.
|
|
300
|
+
if (feature.legacyAliasOf && !feature.syntax) {
|
|
290
301
|
const target = categorized[category].find(f =>
|
|
291
302
|
f.name === feature.legacyAliasOf && !f.for);
|
|
292
303
|
if (!target) {
|
|
293
304
|
throw new Error(`${feature.name} is a legacy alias of unknown ${f.legacyAliasOf}`);
|
|
294
305
|
}
|
|
295
|
-
feature.
|
|
306
|
+
feature.syntax = target.syntax;
|
|
296
307
|
}
|
|
297
308
|
}
|
|
298
309
|
|
|
310
|
+
// The same feature may be defined for multiple scopes.
|
|
311
|
+
// To ease indexing and lookup by feature name, let's merge the scopes
|
|
312
|
+
// when possible, turning the `for` key into an array. This will not get
|
|
313
|
+
// rid of all scoping duplicates, but should still make the feature name
|
|
314
|
+
// unique for all but a handful of them.
|
|
315
|
+
categorized[category] = categorized[category]
|
|
316
|
+
.map((feature, idx, list) => {
|
|
317
|
+
const first = list.find(f => f.href === feature.href);
|
|
318
|
+
if (first === feature) {
|
|
319
|
+
if (feature.for) {
|
|
320
|
+
feature.for = [feature.for];
|
|
321
|
+
}
|
|
322
|
+
return feature;
|
|
323
|
+
}
|
|
324
|
+
// Not the first time we see this feature, let's merge scopes.
|
|
325
|
+
// Both scopes should be defined as there is no way to author a
|
|
326
|
+
// single dfn that defines a feature both as scoped and unscoped.
|
|
327
|
+
if (!first.for || !feature.for) {
|
|
328
|
+
throw new Error(`Feature ${feature.name} defined both as unscoped and scoped within the same dfn, see ${feature.href}`);
|
|
329
|
+
}
|
|
330
|
+
first.for.push(feature.for);
|
|
331
|
+
first.for.sort();
|
|
332
|
+
return null;
|
|
333
|
+
})
|
|
334
|
+
.filter(feature => !!feature);
|
|
335
|
+
|
|
299
336
|
// Let's sort lists before we return to ease human-readability and
|
|
300
337
|
// avoid non-substantive diff
|
|
301
338
|
for (const feature of categorized[category]) {
|
|
@@ -313,13 +350,14 @@ export default {
|
|
|
313
350
|
|
|
314
351
|
|
|
315
352
|
/**
|
|
316
|
-
* Return the identifier of a feature, taking scoping construct into account
|
|
353
|
+
* Return the identifier of a feature, taking scoping construct(s) into account
|
|
317
354
|
* when needed.
|
|
318
355
|
*/
|
|
319
356
|
function getFeatureId(feature) {
|
|
320
357
|
let featureId = feature.name;
|
|
321
358
|
if (feature.for) {
|
|
322
|
-
featureId += ' for ' +
|
|
359
|
+
featureId += ' for ' +
|
|
360
|
+
(Array.isArray(feature.for) ? feature.for.join(',') : feature.for);
|
|
323
361
|
}
|
|
324
362
|
return featureId;
|
|
325
363
|
}
|
|
@@ -338,3 +376,18 @@ function decorateFeaturesWithSpec(data, spec) {
|
|
|
338
376
|
}
|
|
339
377
|
}
|
|
340
378
|
}
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* Unwrap (type) name
|
|
383
|
+
*
|
|
384
|
+
* Note: names that appear in other categories are never enclosed in `<`
|
|
385
|
+
* and `>`
|
|
386
|
+
*/
|
|
387
|
+
function unwrapName(name) {
|
|
388
|
+
const typeMatch = name.match(/^<([^>]+)>$/);
|
|
389
|
+
if (typeMatch) {
|
|
390
|
+
return typeMatch[1];
|
|
391
|
+
}
|
|
392
|
+
return name;
|
|
393
|
+
}
|