reffy 14.4.0 → 14.5.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": "14.4.0",
3
+ "version": "14.5.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",
@@ -36,7 +36,7 @@
36
36
  "ajv-formats": "2.1.1",
37
37
  "commander": "11.1.0",
38
38
  "fetch-filecache-for-crawling": "5.1.1",
39
- "puppeteer": "21.5.2",
39
+ "puppeteer": "21.6.1",
40
40
  "semver": "^7.3.5",
41
41
  "web-specs": "2.75.1",
42
42
  "webidl2": "24.4.1"
@@ -46,8 +46,8 @@
46
46
  "mocha": "10.2.0",
47
47
  "respec": "34.2.2",
48
48
  "respec-hljs": "2.1.1",
49
- "rollup": "4.6.1",
50
- "undici": "^5.22.1"
49
+ "rollup": "4.9.1",
50
+ "undici": "^6.1.0"
51
51
  },
52
52
  "overrides": {
53
53
  "puppeteer": "$puppeteer"
@@ -63,6 +63,10 @@
63
63
  },
64
64
  "definedIn": {
65
65
  "type": "string"
66
+ },
67
+ "htmlProse": {
68
+ "type": "string",
69
+ "minLength": 1
66
70
  }
67
71
  }
68
72
  }
@@ -15,7 +15,7 @@
15
15
 
16
16
  "shortname": {
17
17
  "type": "string",
18
- "pattern": "^[\\w\\-]+((?<=-\\d+)\\.\\d+)?$",
18
+ "pattern": "^[\\w\\-]+((?<=-v?\\d+)\\.\\d+)?$",
19
19
  "$comment": "Same definition as in browser-specs"
20
20
  },
21
21
 
@@ -122,6 +122,57 @@ function isNotAlreadyExported(dfn, idx, list) {
122
122
  return first === dfn;
123
123
  }
124
124
 
125
+ // Extract the element's inner HTML content, removing any complex structure,
126
+ // so that the result can be injected elsewhere without creating problems.
127
+ function getHtmlProseDefinition(proseEl) {
128
+ // Apply modifications to a copy of the element
129
+ proseEl = proseEl.cloneNode(true);
130
+
131
+ // Drop asides that authoring tools add here and there
132
+ let el;
133
+ const asideSelector = [
134
+ 'aside', '.mdn-anno', '.wpt-tests-block', '.annotation',
135
+ '[id^=dfn-panel-]'
136
+ ].join(',');
137
+ while (el = proseEl.querySelector(asideSelector)) {
138
+ el.remove();
139
+ }
140
+
141
+ // Keep simple grouping content and text-level semantics elements
142
+ const keepSelector = [
143
+ 'blockquote', 'dd', 'div', 'dl', 'dt', 'figcaption', 'figure', 'hr', 'li',
144
+ 'ol', 'p', 'pre', 'ul',
145
+ 'a', 'abbr', 'b', 'bdi', 'bdo', 'br', 'cite', 'code', 'data', 'dfn', 'em',
146
+ 'i', 'kbd', 'mark', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'small', 'span',
147
+ 'strong', 'sub', 'sup', 'time', 'u', 'var', 'wbr'
148
+ ].join(',');
149
+ while (el = proseEl.querySelector(`:not(${keepSelector})`)) {
150
+ // The content is more complex than anticipated. It may be worth checking
151
+ // the definition to assess whether the extraction logic needs to become
152
+ // smarter. For lack of a better reporting mechanism for now, let's record
153
+ // a warning.
154
+ console.warn('[reffy]', `Unexpected element "${el.nodeName}" found in textual definition of "${proseEl.getAttribute('data-defines')}"`);
155
+ el.remove();
156
+ }
157
+
158
+ // Drop all attributes except "href", "dir", "lang" and "title"
159
+ // For "href", let's make sure that we have an absolute URL
160
+ [...proseEl.querySelectorAll('*')].forEach(el => {
161
+ el.getAttributeNames().forEach(attr => {
162
+ if (attr === 'href') {
163
+ const page = el.closest('[data-reffy-page]')?.getAttribute('data-reffy-page');
164
+ const url = new URL(el.getAttribute('href'), page ?? window.location.href);
165
+ el.setAttribute('href', url.toString());
166
+ }
167
+ else if (!['dir', 'lang', 'title'].includes(attr)) {
168
+ el.removeAttribute(attr);
169
+ }
170
+ });
171
+ });
172
+
173
+ return proseEl.innerHTML.trim();
174
+ }
175
+
125
176
  function definitionMapper(el, idToHeading, usesDfnDataModel) {
126
177
  let definedIn = 'prose';
127
178
  const enclosingEl = el.closest('dt,pre,table,h1,h2,h3,h4,h5,h6,.note,.example') || el;
@@ -157,7 +208,7 @@ function definitionMapper(el, idToHeading, usesDfnDataModel) {
157
208
  url.hash = '#' + encodeURIComponent(el.getAttribute('id'));
158
209
  const href = url.toString();
159
210
 
160
- return {
211
+ const dfn = {
161
212
  // ID is the id attribute
162
213
  // (ID may not be unique in a multi-page spec)
163
214
  id: el.getAttribute('id'),
@@ -211,6 +262,17 @@ function definitionMapper(el, idToHeading, usesDfnDataModel) {
211
262
  // indicates that definition appears in the main body of the specification)
212
263
  definedIn
213
264
  };
265
+
266
+ // Extract a prose definition in HTML for the term, if available
267
+ const proseEl = document.querySelector(`[data-defines="#${dfn.id}"]`);
268
+ if (proseEl) {
269
+ const htmlProse = getHtmlProseDefinition(proseEl);
270
+ if (htmlProse) {
271
+ dfn.htmlProse = htmlProse;
272
+ }
273
+ }
274
+
275
+ return dfn;
214
276
  }
215
277
 
216
278
  export default function (spec, idToHeading = {}) {