reffy 8.0.0 → 8.0.3
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 +4 -4
- package/reffy.js +1 -1
- package/src/browserlib/extract-cssdfn.mjs +15 -3
- package/src/lib/util.js +7 -3
- package/src/postprocessing/events.js +52 -34
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "reffy",
|
|
3
|
-
"version": "8.0.
|
|
3
|
+
"version": "8.0.3",
|
|
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",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"abortcontroller-polyfill": "1.7.3",
|
|
35
35
|
"commander": "9.4.0",
|
|
36
36
|
"fetch-filecache-for-crawling": "4.1.0",
|
|
37
|
-
"puppeteer": "15.4.
|
|
37
|
+
"puppeteer": "15.4.1",
|
|
38
38
|
"semver": "^7.3.5",
|
|
39
39
|
"web-specs": "2.17.0",
|
|
40
40
|
"webidl2": "24.2.2"
|
|
@@ -42,8 +42,8 @@
|
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"chai": "4.3.6",
|
|
44
44
|
"mocha": "10.0.0",
|
|
45
|
-
"nock": "13.2.
|
|
46
|
-
"respec": "32.
|
|
45
|
+
"nock": "13.2.9",
|
|
46
|
+
"respec": "32.2.0",
|
|
47
47
|
"respec-hljs": "2.1.1",
|
|
48
48
|
"rollup": "2.77.0"
|
|
49
49
|
},
|
package/reffy.js
CHANGED
|
@@ -257,10 +257,22 @@ const extractValueSpaces = doc => {
|
|
|
257
257
|
// https://drafts.csswg.org/css-easing-2/#typedef-step-easing-function
|
|
258
258
|
const prod = text.split(reSplitRules)
|
|
259
259
|
.find(p => p.trim().startsWith(dfn.textContent.trim()));
|
|
260
|
-
if (
|
|
261
|
-
|
|
260
|
+
if (prod) {
|
|
261
|
+
parseProductionRule(prod, { pureSyntax: true });
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
// "=" may appear in another formula in the body of the text, as in:
|
|
265
|
+
// https://drafts.csswg.org/css-speech-1/#typedef-voice-volume-decibel
|
|
266
|
+
// It may be worth checking but not an error per se.
|
|
267
|
+
console.warn('[reffy]', `Found "=" next to definition of ${dfn.textContent.trim()} but no production rule. Did I miss something?`);
|
|
268
|
+
const name = (dfn.getAttribute('data-lt') ?? dfn.textContent)
|
|
269
|
+
.trim().replace(/^<?(.*?)>?$/, '<$1>');
|
|
270
|
+
if (!(name in res)) {
|
|
271
|
+
res[name] = {
|
|
272
|
+
prose: parent.textContent.trim().replace(/\s+/g, ' ')
|
|
273
|
+
};
|
|
274
|
+
}
|
|
262
275
|
}
|
|
263
|
-
parseProductionRule(prod, { pureSyntax: true });
|
|
264
276
|
}
|
|
265
277
|
else if (dfn.textContent.trim().match(/^[a-zA-Z_][a-zA-Z0-9_\-]+\([^\)]+\)$/)) {
|
|
266
278
|
// Definition is "prod(foo bar)", create a "prod() = prod(foo bar)" entry
|
package/src/lib/util.js
CHANGED
|
@@ -816,7 +816,7 @@ async function expandSpecResult(spec, baseFolder, properties) {
|
|
|
816
816
|
// Also drop header that may have been added when extract was
|
|
817
817
|
// serialized.
|
|
818
818
|
if (contents.startsWith('// GENERATED CONTENT - DO NOT EDIT')) {
|
|
819
|
-
const hasWindowsEndings = contents.
|
|
819
|
+
const hasWindowsEndings = contents.includes('\r\n\r\n');
|
|
820
820
|
if (hasWindowsEndings) {
|
|
821
821
|
const endOfHeader = contents.indexOf('\r\n\r\n');
|
|
822
822
|
contents = contents.substring(endOfHeader + 4)
|
|
@@ -946,9 +946,13 @@ async function createFolderIfNeeded(folder) {
|
|
|
946
946
|
* the tree.
|
|
947
947
|
*/
|
|
948
948
|
const trees = {
|
|
949
|
-
// DOM tree:
|
|
949
|
+
// The DOM tree is defined through "get the parent" algorithms:
|
|
950
950
|
// https://dom.spec.whatwg.org/#node-trees
|
|
951
|
-
|
|
951
|
+
// https://dom.spec.whatwg.org/#get-the-parent
|
|
952
|
+
// - Node -> Node
|
|
953
|
+
// - Document -> Window
|
|
954
|
+
// - ShadowRoot -> Element (both derive from Node, so covered by Node -> Node)
|
|
955
|
+
'dom': ['Window', 'Document', 'Node'],
|
|
952
956
|
|
|
953
957
|
// IndexedDB tree (defined through "get the parent" algorithms)
|
|
954
958
|
// https://www.w3.org/TR/IndexedDB/#ref-for-get-the-parent%E2%91%A0
|
|
@@ -46,7 +46,6 @@ module.exports = {
|
|
|
46
46
|
for (const event of events) {
|
|
47
47
|
expandMixinTargets(event, mixins);
|
|
48
48
|
setBubblingPerTarget(event, parsedInterfaces);
|
|
49
|
-
cleanTargetInTrees(event, parsedInterfaces);
|
|
50
49
|
}
|
|
51
50
|
|
|
52
51
|
// Consolidate events extended in other specs
|
|
@@ -55,11 +54,13 @@ module.exports = {
|
|
|
55
54
|
.map(event => {
|
|
56
55
|
const err = extendEvent(event, events);
|
|
57
56
|
if (err) {
|
|
57
|
+
// Event could not be extended, let's keep extension event
|
|
58
58
|
console.warn(err);
|
|
59
|
-
return
|
|
59
|
+
return null;
|
|
60
60
|
}
|
|
61
61
|
else {
|
|
62
|
-
|
|
62
|
+
// Event successfully extended, extension can be dropped
|
|
63
|
+
return event;
|
|
63
64
|
}
|
|
64
65
|
})
|
|
65
66
|
.filter(event => !!event);
|
|
@@ -67,6 +68,7 @@ module.exports = {
|
|
|
67
68
|
return events
|
|
68
69
|
.filter(event => !eventsToDrop.includes(event))
|
|
69
70
|
.map(event => {
|
|
71
|
+
cleanTargetInterfaces(event, parsedInterfaces);
|
|
70
72
|
delete event.spec;
|
|
71
73
|
return event;
|
|
72
74
|
});
|
|
@@ -133,41 +135,57 @@ function setBubblingPerTarget(event, parsedInterfaces) {
|
|
|
133
135
|
}
|
|
134
136
|
|
|
135
137
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
138
|
+
/**
|
|
139
|
+
* Filter the list of target interfaces to remove those that don't need to
|
|
140
|
+
* appear explicitly because they are de facto already covered by another entry
|
|
141
|
+
* in the list.
|
|
142
|
+
*
|
|
143
|
+
* Two reasons to drop a target interface t from the list:
|
|
144
|
+
* 1. There exists another target interface o with similar bubbling properties
|
|
145
|
+
* for the event and t inherits from o. If event fires at o, it can de facto
|
|
146
|
+
* fire at t.
|
|
147
|
+
* 2. There exists another target interface o such that t and o belong to the
|
|
148
|
+
* same bubbling tree, o is at a deeper level than t in the bubbling tree, and
|
|
149
|
+
* event bubbles when it fires at o. Event will de facto fire at t through
|
|
150
|
+
* bubbling when that happens.
|
|
151
|
+
*/
|
|
152
|
+
function cleanTargetInterfaces(event, parsedInterfaces) {
|
|
153
|
+
// Helper function that returns true if the iface interface inherits from the
|
|
154
|
+
// base interface
|
|
155
|
+
function inheritsFrom(iface, base) {
|
|
156
|
+
while (iface) {
|
|
157
|
+
if (iface === base) {
|
|
158
|
+
return true;
|
|
159
|
+
}
|
|
160
|
+
iface = parsedInterfaces.find(i => i.name === iface)?.inheritance;
|
|
144
161
|
}
|
|
162
|
+
return false;
|
|
145
163
|
}
|
|
146
|
-
return false;
|
|
147
|
-
}
|
|
148
164
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
let deepestInTrees = {};
|
|
152
|
-
let filteredTargets = [];
|
|
153
|
-
for (let {target, bubbles} of targets) {
|
|
154
|
-
const treeInfo = getInterfaceTreeInfo(target, parsedInterfaces);
|
|
155
|
-
if (!treeInfo) { // Not in a tree, we keep it in
|
|
156
|
-
filteredTargets.push({target});
|
|
157
|
-
continue;
|
|
158
|
-
}
|
|
159
|
-
const { tree, depth } = treeInfo;
|
|
160
|
-
const currentDeepest = deepestInTrees[tree]?.target;
|
|
161
|
-
if (currentDeepest) {
|
|
162
|
-
const { depth: currentDeepestDepth } = getInterfaceTreeInfo(currentDeepest, parsedInterfaces);
|
|
163
|
-
if (depth > currentDeepestDepth) {
|
|
164
|
-
deepestInTrees[tree] = {target, bubbles};
|
|
165
|
-
}
|
|
166
|
-
} else {
|
|
167
|
-
deepestInTrees[tree] = {target, bubbles};
|
|
168
|
-
}
|
|
165
|
+
if (!event.targets) {
|
|
166
|
+
return;
|
|
169
167
|
}
|
|
170
|
-
|
|
168
|
+
|
|
169
|
+
event.targets = event.targets
|
|
170
|
+
.filter(({ target, bubbles }) =>
|
|
171
|
+
// Drop if an ancestor in the inheritance chain is already there
|
|
172
|
+
!event.targets.find(({ target: other, bubbles: otherBubbles}) =>
|
|
173
|
+
target !== other &&
|
|
174
|
+
bubbles === otherBubbles &&
|
|
175
|
+
inheritsFrom(target, other)))
|
|
176
|
+
.filter(({ target, bubbles }) => {
|
|
177
|
+
// Drop if a deeper bubbling target interface in the tree is already there
|
|
178
|
+
const targetTreeInfo = getInterfaceTreeInfo(target, parsedInterfaces);
|
|
179
|
+
return !targetTreeInfo ||
|
|
180
|
+
!event.targets.find(({ target: other, bubbles: otherBubbles }) => {
|
|
181
|
+
if (other === target) {
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
const otherTreeInfo = getInterfaceTreeInfo(other, parsedInterfaces);
|
|
185
|
+
return otherTreeInfo?.tree === targetTreeInfo.tree &&
|
|
186
|
+
otherBubbles && otherTreeInfo.depth > targetTreeInfo.depth;
|
|
187
|
+
});
|
|
188
|
+
});
|
|
171
189
|
}
|
|
172
190
|
|
|
173
191
|
|