Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 46 additions & 1 deletion src/browserlib/extract-events.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,14 @@ export default function (spec) {
return acc;
}, {});

// Return true if the second event object describes the same event as the
// first one. Note event types defined in event tables typically complete
// event definitions for which we don't have any target information.
function isSameEvent(e1, e2) {
const res = e1.type === e2.type &&
((e1.href && e1.href === e2.href ) ||
(e1.targets?.sort()?.join("|") === e2.targets?.sort()?.join("|")));
(e1.targets?.sort()?.join("|") === e2.targets?.sort()?.join("|")) ||
(e2.src.format === 'event table'));
if (res && e1.cancelable !== undefined && e2.cancelable !== undefined && e1.cancelable !== e2.cancelable) {
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}`);
}
Expand Down Expand Up @@ -67,6 +71,46 @@ export default function (spec) {


let events = [];

// Look for definitions in event-definition tables
// (used in Pointer Events and UI Events)
[...document.querySelectorAll('table.event-definition')].forEach(table => {
const properties = [...table.querySelectorAll('tr')]
.map(line => {
const nameEl = line.querySelector('th');
const valueEl = line.querySelector('td');
if (!nameEl || !valueEl) {
return null;
}
let name = nameEl.textContent.trim().toLowerCase();
let value = valueEl.textContent.trim();
if (name === 'trusted targets') {
name = 'targets';
value = value.split(',').map(v => v.trim());
}
if (['type', 'interface', 'targets'].includes(name)) {
return { name, value };
}
else if (['bubbles', 'cancelable'].includes(name)) {
return { name, value: value.toLowerCase() === 'yes' ? true : false };
}
else {
return null;
}
})
.filter(prop => !!prop);
const event = {};
for (const prop of properties) {
event[prop.name] = prop.value;
}
event.src = {
format: 'event table',
href: href(table.closest('*[id]'))
},
events.push(event);
});


// Look for event summary tables
// ignore DOM spec which uses a matching table format
// to map to legacy event types
Expand Down Expand Up @@ -419,6 +463,7 @@ export default function (spec) {
}
}
});

return events
.map(e => {
// Drop null properties (mandated by the schema for event extracts)
Expand Down
95 changes: 95 additions & 0 deletions test/extract-events.js
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,101 @@ ${defaultIdl}`,
given <var>name</var>.
</p>`,
res: []
},
{
title: "extracts an event from an event-definition table",
html: `<section id="events">
<table class="event-definition">
<tbody>
<tr>
<th>Type</th>
<td><strong><code>auxclick</code></strong></td>
</tr>
<tr>
<th>Interface</th>
<td><code>PointerEvent</code></td>
</tr>
<tr>
<th>Bubbles</th>
<td>Yes</td>
</tr>
<tr>
<th>Trusted Targets</th>
<td><code>Element</code> </td>
</tr>
<tr>
<th>Cancelable</th>
<td>Yes</td>
</tr>
</tbody>
</table>
</section>`,
res: [
{
interface: "PointerEvent",
src: {
format: "event table",
href: "about:blank#events"
},
type: "auxclick",
targets: [
"Element"
],
bubbles: true,
cancelable: true
}
]
},
{
title: "extracts an event from an event-definition table and links it to dfn",
html: `<section id="events">
<div class="header-wrapper">
<h4 id="x4-4-1-auxclick">
<bdi class="secno">4.4.1<!---0.614927%--> </bdi>
<dfn class="export" data-dfn-type="event" data-export="" id="dfn-auxclick">auxclick</dfn>
</h4>
</div>
<table class="event-definition">
<tbody>
<tr>
<th>Type</th>
<td><strong><code>auxclick</code></strong></td>
</tr>
<tr>
<th>Interface</th>
<td><code>PointerEvent</code></td>
</tr>
<tr>
<th>Bubbles</th>
<td>Yes</td>
</tr>
<tr>
<th>Trusted Targets</th>
<td><code>Element</code> </td>
</tr>
<tr>
<th>Cancelable</th>
<td>Yes</td>
</tr>
</tbody>
</table>
</section>`,
res: [
{
href: "about:blank#dfn-auxclick",
interface: "PointerEvent",
src: {
format: "event table",
href: "about:blank#events"
},
type: "auxclick",
targets: [
"Element"
],
bubbles: true,
cancelable: true
}
]
}
];

Expand Down