Skip to content

Commit fb5e89b

Browse files
committed
[Events] Extract events defined in a definition table
The Pointer Events and UI Events specs have started to use tables to define events. For example: https://w3c.github.io/pointerevents/#dfn-auxclick This update adjusts the extraction logic to gather the information we need from the table.
1 parent c6647d7 commit fb5e89b

File tree

2 files changed

+141
-1
lines changed

2 files changed

+141
-1
lines changed

src/browserlib/extract-events.mjs

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,14 @@ export default function (spec) {
3333
return acc;
3434
}, {});
3535

36+
// Return true if the second event object describes the same event as the
37+
// first one. Note event types defined in event tables typically complete
38+
// event definitions for which we don't have any target information.
3639
function isSameEvent(e1, e2) {
3740
const res = e1.type === e2.type &&
3841
((e1.href && e1.href === e2.href ) ||
39-
(e1.targets?.sort()?.join("|") === e2.targets?.sort()?.join("|")));
42+
(e1.targets?.sort()?.join("|") === e2.targets?.sort()?.join("|")) ||
43+
(e2.src.format === 'event table'));
4044
if (res && e1.cancelable !== undefined && e2.cancelable !== undefined && e1.cancelable !== e2.cancelable) {
4145
console.error(`[reffy] Found two occurrences of same event with different "cancelable" properties in ${spec.title}: type=${e1.type} targets=${e1.targets.join(', ')} href=${e1.href}`);
4246
}
@@ -67,6 +71,46 @@ export default function (spec) {
6771

6872

6973
let events = [];
74+
75+
// Look for definitions in event-definition tables
76+
// (used in Pointer Events and UI Events)
77+
[...document.querySelectorAll('table.event-definition')].forEach(table => {
78+
const properties = [...table.querySelectorAll('tr')]
79+
.map(line => {
80+
const nameEl = line.querySelector('th');
81+
const valueEl = line.querySelector('td');
82+
if (!nameEl || !valueEl) {
83+
return null;
84+
}
85+
let name = nameEl.textContent.trim().toLowerCase();
86+
let value = valueEl.textContent.trim();
87+
if (name === 'trusted targets') {
88+
name = 'targets';
89+
value = value.split(',').map(v => v.trim());
90+
}
91+
if (['type', 'interface', 'targets'].includes(name)) {
92+
return { name, value };
93+
}
94+
else if (['bubbles', 'cancelable'].includes(name)) {
95+
return { name, value: value.toLowerCase() === 'yes' ? true : false };
96+
}
97+
else {
98+
return null;
99+
}
100+
})
101+
.filter(prop => !!prop);
102+
const event = {};
103+
for (const prop of properties) {
104+
event[prop.name] = prop.value;
105+
}
106+
event.src = {
107+
format: 'event table',
108+
href: href(table.closest('*[id]'))
109+
},
110+
events.push(event);
111+
});
112+
113+
70114
// Look for event summary tables
71115
// ignore DOM spec which uses a matching table format
72116
// to map to legacy event types
@@ -419,6 +463,7 @@ export default function (spec) {
419463
}
420464
}
421465
});
466+
422467
return events
423468
.map(e => {
424469
// Drop null properties (mandated by the schema for event extracts)

test/extract-events.js

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,101 @@ ${defaultIdl}`,
199199
given <var>name</var>.
200200
</p>`,
201201
res: []
202+
},
203+
{
204+
title: "extracts an event from an event-definition table",
205+
html: `<section id="events">
206+
<table class="event-definition">
207+
<tbody>
208+
<tr>
209+
<th>Type</th>
210+
<td><strong><code>auxclick</code></strong></td>
211+
</tr>
212+
<tr>
213+
<th>Interface</th>
214+
<td><code>PointerEvent</code></td>
215+
</tr>
216+
<tr>
217+
<th>Bubbles</th>
218+
<td>Yes</td>
219+
</tr>
220+
<tr>
221+
<th>Trusted Targets</th>
222+
<td><code>Element</code> </td>
223+
</tr>
224+
<tr>
225+
<th>Cancelable</th>
226+
<td>Yes</td>
227+
</tr>
228+
</tbody>
229+
</table>
230+
</section>`,
231+
res: [
232+
{
233+
interface: "PointerEvent",
234+
src: {
235+
format: "event table",
236+
href: "about:blank#events"
237+
},
238+
type: "auxclick",
239+
targets: [
240+
"Element"
241+
],
242+
bubbles: true,
243+
cancelable: true
244+
}
245+
]
246+
},
247+
{
248+
title: "extracts an event from an event-definition table and links it to dfn",
249+
html: `<section id="events">
250+
<div class="header-wrapper">
251+
<h4 id="x4-4-1-auxclick">
252+
<bdi class="secno">4.4.1<!---0.614927%--> </bdi>
253+
<dfn class="export" data-dfn-type="event" data-export="" id="dfn-auxclick">auxclick</dfn>
254+
</h4>
255+
</div>
256+
<table class="event-definition">
257+
<tbody>
258+
<tr>
259+
<th>Type</th>
260+
<td><strong><code>auxclick</code></strong></td>
261+
</tr>
262+
<tr>
263+
<th>Interface</th>
264+
<td><code>PointerEvent</code></td>
265+
</tr>
266+
<tr>
267+
<th>Bubbles</th>
268+
<td>Yes</td>
269+
</tr>
270+
<tr>
271+
<th>Trusted Targets</th>
272+
<td><code>Element</code> </td>
273+
</tr>
274+
<tr>
275+
<th>Cancelable</th>
276+
<td>Yes</td>
277+
</tr>
278+
</tbody>
279+
</table>
280+
</section>`,
281+
res: [
282+
{
283+
href: "about:blank#dfn-auxclick",
284+
interface: "PointerEvent",
285+
src: {
286+
format: "event table",
287+
href: "about:blank#events"
288+
},
289+
type: "auxclick",
290+
targets: [
291+
"Element"
292+
],
293+
bubbles: true,
294+
cancelable: true
295+
}
296+
]
202297
}
203298
];
204299

0 commit comments

Comments
 (0)