reffy 19.0.0 → 19.1.0

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": "19.0.0",
3
+ "version": "19.1.0",
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.1",
40
+ "puppeteer": "24.12.1",
41
41
  "semver": "^7.3.5",
42
- "web-specs": "3.53.0",
42
+ "web-specs": "3.56.0",
43
43
  "webidl2": "24.4.1"
44
44
  },
45
45
  "devDependencies": {
46
- "respec": "35.4.1",
46
+ "respec": "35.4.2",
47
47
  "respec-hljs": "2.1.1",
48
- "rollup": "4.43.0",
48
+ "rollup": "4.44.2",
49
49
  "undici": "^7.0.0"
50
50
  },
51
51
  "overrides": {
@@ -2,6 +2,21 @@
2
2
  "$schema": "http://json-schema.org/schema#",
3
3
  "$id": "https://github.com/w3c/reffy/blob/main/schemas/browserlib/extract-dfns.json",
4
4
 
5
+ "$defs": {
6
+ "heading": {
7
+ "type": "object",
8
+ "additionalProperties": false,
9
+ "required": ["href", "title"],
10
+ "properties": {
11
+ "id": { "$ref": "../common.json#/$defs/id" },
12
+ "href": { "$ref": "../common.json#/$defs/url" },
13
+ "title": { "type": "string" },
14
+ "number": { "$ref": "../common.json#/$defs/headingNumber" },
15
+ "alternateIds": { "type": "array", "items": { "$ref": "../common.json#/$defs/id"} }
16
+ }
17
+ }
18
+ },
19
+
5
20
  "type": "array",
6
21
  "items": {
7
22
  "type": "object",
@@ -24,19 +39,14 @@
24
39
  "enum": [
25
40
  "property", "descriptor", "value", "type",
26
41
  "at-rule", "function", "selector",
27
-
28
42
  "namespace", "interface", "constructor", "method", "argument",
29
43
  "attribute", "callback", "dictionary", "dict-member", "enum",
30
44
  "enum-value", "exception", "const", "typedef", "stringifier",
31
45
  "serializer", "iterator", "maplike", "setlike", "extended-attribute",
32
46
  "event", "permission",
33
-
34
47
  "element", "element-state", "element-attr", "attr-value",
35
-
36
48
  "cddl-module", "cddl-type", "cddl-parameter", "cddl-key", "cddl-value",
37
-
38
49
  "scheme", "http-header",
39
-
40
50
  "grammar", "abstract-op", "dfn"
41
51
  ],
42
52
  "$comment": "Types taken from src/browserlib/extract-dfns.mjs"
@@ -52,21 +62,25 @@
52
62
  "informative": {
53
63
  "type": "boolean"
54
64
  },
55
- "heading": {
56
- "type": "object",
57
- "additionalProperties": false,
58
- "required": ["href", "title"],
59
- "properties": {
60
- "id": { "$ref": "../common.json#/$defs/id" },
61
- "href": { "$ref": "../common.json#/$defs/url" },
62
- "title": { "type": "string" },
63
- "number": { "$ref": "../common.json#/$defs/headingNumber" },
64
- "alternateIds": { "type": "array", "items": { "$ref": "../common.json#/$defs/id"} }
65
- }
66
- },
65
+ "heading": { "$ref": "#/$defs/heading" },
67
66
  "definedIn": {
68
67
  "type": "string"
69
68
  },
69
+ "links": {
70
+ "type": "array",
71
+ "items": {
72
+ "type": "object",
73
+ "additionalProperties": false,
74
+ "required": ["type", "id", "href", "name"],
75
+ "properties": {
76
+ "type": { "type": "string", "enum": ["dev"] },
77
+ "id": { "$ref": "../common.json#/$defs/id" },
78
+ "name": { "type": "string" },
79
+ "href": { "$ref": "../common.json#/$defs/url" },
80
+ "heading": { "$ref": "#/$defs/heading" }
81
+ }
82
+ }
83
+ },
70
84
  "htmlProse": {
71
85
  "type": "string",
72
86
  "minLength": 1
@@ -100,7 +100,7 @@
100
100
  "required": ["name", "type"],
101
101
  "additionalProperties": false,
102
102
  "properties": {
103
- "name": { "type": "string", "pattern": "^[a-zA-Z0-9-\\(\\)\\[\\]\\{\\}]+$" },
103
+ "name": { "type": "string", "pattern": "^[a-zA-Z0-9-\\+\\(\\)\\[\\]\\{\\}]+$" },
104
104
  "for": { "$ref": "#/$defs/scopes" },
105
105
  "href": { "$ref": "../common.json#/$defs/url" },
106
106
  "type": { "type": "string", "enum": ["type"] },
@@ -1,5 +1,6 @@
1
1
  import extractWebIdl from './extract-webidl.mjs';
2
2
  import informativeSelector from './informative-selector.mjs';
3
+ import getAbsoluteUrl from './get-absolute-url.mjs';
3
4
  import {parse} from "../../node_modules/webidl2/index.js";
4
5
  /**
5
6
  * Extract definitions in the spec that follow the "Definitions data model":
@@ -276,7 +277,11 @@ function definitionMapper(el, idToHeading, usesDfnDataModel) {
276
277
  // Enclosing element under which the definition appears. Value can be one of
277
278
  // "dt", "pre", "table", "heading", "note", "example", or "prose" (last one
278
279
  // indicates that definition appears in the main body of the specification)
279
- definedIn
280
+ definedIn,
281
+
282
+ // Important links that complement the definition
283
+ // (typically: anchors in "for web developers" sections)
284
+ links: []
280
285
  };
281
286
 
282
287
  // Extract a prose definition in HTML for the term, if available
@@ -322,14 +327,14 @@ export default function (spec, idToHeading = {}) {
322
327
  break;
323
328
  }
324
329
 
325
- const definitions = [...document.querySelectorAll(definitionsSelector)];
326
- const usesDfnDataModel = definitions.some(dfn =>
330
+ const dfnEls = [...document.querySelectorAll(definitionsSelector)];
331
+ const usesDfnDataModel = dfnEls.some(dfn =>
327
332
  dfn.hasAttribute('data-dfn-type') ||
328
333
  dfn.hasAttribute('data-dfn-for') ||
329
334
  dfn.hasAttribute('data-export') ||
330
335
  dfn.hasAttribute('data-noexport'));
331
336
 
332
- return definitions
337
+ const definitions = dfnEls
333
338
  .map(node => {
334
339
  // 2021-06-21: Temporary preprocessing of invalid "idl" dfn type (used for
335
340
  // internal slots) while fix for https://github.com/w3c/respec/issues/3644
@@ -365,6 +370,45 @@ export default function (spec, idToHeading = {}) {
365
370
  })
366
371
  .map(node => definitionMapper(node, idToHeading, usesDfnDataModel))
367
372
  .filter(isNotAlreadyExported);
373
+
374
+ // Some specs have informative "For web developers" sections targeted at
375
+ // presenting concepts to web developers. These sections contain anchors
376
+ // that are useful for documentation purpose. The anchors themselves are
377
+ // references to terms defined elsewhere in the spec. We will capture them in
378
+ // a `links` property attached to the underlying definition.
379
+ // Note: Ideally, `.domintro` would be added to the informative selector list
380
+ // but some specs use `.domintro` for lists that define IDL terms. We'll get
381
+ // rid of them by skipping lists that have `dfn`.
382
+ const devSelector = '.domintro dt:not(dt:has(dfn)) a[id]';
383
+ for (const node of [...document.querySelectorAll(devSelector)]) {
384
+ const dfnHref = getAbsoluteUrl(node, { attribute: 'href' });
385
+ const dfn = definitions.find(d => d.href === dfnHref);
386
+ if (dfn) {
387
+ const href = getAbsoluteUrl(node);
388
+ const page = node.closest('[data-reffy-page]')?.getAttribute('data-reffy-page');
389
+ dfn.links.push({
390
+ type: 'dev',
391
+ id: node.getAttribute('id'),
392
+ name: normalize(node.closest('dt').textContent),
393
+ href,
394
+ heading: idToHeading[href] ?? {
395
+ href: (new URL(page ?? window.location.href)).toString(),
396
+ title: document.title
397
+ }
398
+ });
399
+ }
400
+ else {
401
+ // When an interface inherits from another, the reference may target
402
+ // a base dfn in another spec. For example:
403
+ // https://encoding.spec.whatwg.org/#ref-for-dom-generictransformstream-readable
404
+ // ... targets the Streams spec. There aren't many occurrences of this
405
+ // pattern and the occurrences do not look super interesting to link to
406
+ // from a documentation perspective. Let's skip them.
407
+ console.warn('[reffy]', `Dev dfn ${node.textContent} (${node.id}) targets unknown/external dfn at ${node.href}`);
408
+ }
409
+ }
410
+
411
+ return definitions;
368
412
  }
369
413
 
370
414
  function preProcessEcmascript() {
@@ -661,6 +705,21 @@ function preProcessEcmascript() {
661
705
  }
662
706
  });
663
707
 
708
+ // Extract production rules
709
+ [...document.querySelectorAll("emu-grammar[type=definition] emu-production")]
710
+ .forEach(el => {
711
+ const dfn = wrapWithDfn(el);
712
+ dfn.id = el.id;
713
+ dfn.dataset.lt = el.getAttribute("name");
714
+ dfn.dataset.dfnType = "grammar";
715
+ dfn.dataset.noexport = "";
716
+ if (el.closest('[data-reffy-page$="additional-ecmascript-features-for-web-browsers.html"]')) {
717
+ // Production rules in Annex B replace some of the production rules
718
+ // defined in other sections for web browser hosts.
719
+ dfn.dataset.dfnFor = "Web browsers";
720
+ }
721
+ });
722
+
664
723
  [...document.querySelectorAll("dfn")]
665
724
  .filter(legacySectionFilter)
666
725
  .forEach(el => {
@@ -18,7 +18,12 @@ export default function (node, { singlePage, attribute } =
18
18
  const url = new URL(page ?? window.location.href);
19
19
  const hashid = node.getAttribute(attribute);
20
20
  if (hashid) {
21
- url.hash = '#' + encodeURIComponent(hashid);
21
+ let fragment = hashid;
22
+ if (hashid.match(/^#/) && attribute === 'href') {
23
+ // Function is called to turn a fragment ref into an absolute URL
24
+ fragment = hashid.substring(1);
25
+ }
26
+ url.hash = '#' + encodeURIComponent(fragment);
22
27
  }
23
28
  return url.toString();
24
29
  }