reffy 20.0.13 → 20.0.14

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.
Files changed (78) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +151 -151
  3. package/index.js +29 -29
  4. package/package.json +3 -3
  5. package/reffy.js +324 -324
  6. package/schemas/browserlib/extract-algorithms.json +52 -52
  7. package/schemas/browserlib/extract-cssdfn.json +108 -108
  8. package/schemas/browserlib/extract-dfns.json +90 -90
  9. package/schemas/browserlib/extract-elements.json +17 -17
  10. package/schemas/browserlib/extract-events.json +31 -31
  11. package/schemas/browserlib/extract-headings.json +19 -19
  12. package/schemas/browserlib/extract-ids.json +7 -7
  13. package/schemas/browserlib/extract-links.json +12 -12
  14. package/schemas/browserlib/extract-refs.json +12 -12
  15. package/schemas/common.json +876 -876
  16. package/schemas/files/extracts/algorithms.json +12 -12
  17. package/schemas/files/extracts/css.json +16 -16
  18. package/schemas/files/extracts/dfns.json +12 -12
  19. package/schemas/files/extracts/elements.json +12 -12
  20. package/schemas/files/extracts/events.json +12 -12
  21. package/schemas/files/extracts/headings.json +12 -12
  22. package/schemas/files/extracts/ids.json +12 -12
  23. package/schemas/files/extracts/links.json +12 -12
  24. package/schemas/files/extracts/refs.json +12 -12
  25. package/schemas/files/index.json +59 -59
  26. package/schemas/postprocessing/events.json +50 -50
  27. package/schemas/postprocessing/idlnames-parsed.json +27 -27
  28. package/schemas/postprocessing/idlnames.json +17 -17
  29. package/schemas/postprocessing/idlparsed.json +67 -67
  30. package/src/browserlib/clone-and-clean.mjs +24 -24
  31. package/src/browserlib/create-outline.mjs +353 -353
  32. package/src/browserlib/extract-algorithms.mjs +723 -723
  33. package/src/browserlib/extract-cddl.mjs +125 -125
  34. package/src/browserlib/extract-dfns.mjs +1093 -1093
  35. package/src/browserlib/extract-headings.mjs +76 -76
  36. package/src/browserlib/extract-ids.mjs +28 -28
  37. package/src/browserlib/extract-links.mjs +45 -45
  38. package/src/browserlib/extract-references.mjs +308 -308
  39. package/src/browserlib/extract-webidl.mjs +89 -89
  40. package/src/browserlib/get-absolute-url.mjs +29 -29
  41. package/src/browserlib/get-code-elements.mjs +20 -20
  42. package/src/browserlib/get-generator.mjs +26 -26
  43. package/src/browserlib/get-lastmodified-date.mjs +13 -13
  44. package/src/browserlib/get-revision.mjs +12 -12
  45. package/src/browserlib/get-title.mjs +14 -14
  46. package/src/browserlib/informative-selector.mjs +24 -24
  47. package/src/browserlib/map-ids-to-headings.mjs +173 -173
  48. package/src/browserlib/reffy.json +85 -85
  49. package/src/browserlib/trim-spaces.mjs +35 -35
  50. package/src/cli/check-missing-dfns.js +587 -587
  51. package/src/cli/merge-crawl-results.js +132 -132
  52. package/src/cli/parse-webidl.js +447 -447
  53. package/src/lib/css-grammar-parse-tree.schema.json +109 -109
  54. package/src/lib/css-grammar-parser.js +440 -440
  55. package/src/lib/fetch.js +51 -51
  56. package/src/lib/markdown-report.js +360 -360
  57. package/src/lib/mock-server.js +218 -218
  58. package/src/lib/post-processor.js +322 -322
  59. package/src/lib/throttled-queue.js +129 -129
  60. package/src/postprocessing/annotate-links.js +41 -41
  61. package/src/postprocessing/csscomplete.js +48 -48
  62. package/src/postprocessing/idlnames.js +391 -391
  63. package/src/postprocessing/idlparsed.js +179 -179
  64. package/src/postprocessing/patch-dfns.js +51 -51
  65. package/src/specs/missing-css-rules.json +197 -197
  66. package/src/specs/spec-equivalents.json +149 -149
  67. package/src/browserlib/extract-editors.mjs~ +0 -14
  68. package/src/browserlib/extract-events.mjs~ +0 -3
  69. package/src/browserlib/generate-es-dfn-report.sh~ +0 -4
  70. package/src/browserlib/get-revision.mjs~ +0 -7
  71. package/src/cli/csstree-grammar-check.js +0 -28
  72. package/src/cli/csstree-grammar-check.js~ +0 -10
  73. package/src/cli/csstree-grammar-parser.js +0 -11
  74. package/src/cli/csstree-grammar-parser.js~ +0 -1
  75. package/src/cli/extract-editors.js~ +0 -38
  76. package/src/cli/process-specs.js~ +0 -28
  77. package/src/postprocessing/annotate-links.js~ +0 -8
  78. package/src/postprocessing/events.js~ +0 -245
@@ -1,179 +1,179 @@
1
- /**
2
- * Post-processing module that creates a parsed IDL structure out of the IDL
3
- * extract.
4
- *
5
- * The module runs at the spec level and generates an `idlparsed` property.
6
- */
7
-
8
- import webidlParser from '../cli/parse-webidl.js';
9
-
10
- export default {
11
- dependsOn: ['dfns', 'idl'],
12
- input: 'spec',
13
- property: 'idlparsed',
14
-
15
- run: async function(spec, options) {
16
- function getHref(idl, member) {
17
- let dfnType;
18
- let dfnFor;
19
- let dfnOverload = 0;
20
- let dfnName;
21
- if (member) {
22
- if (['async_iterable', 'iterable', 'maplike', 'setlike'].includes(member.type) ||
23
- ['getter', 'setter', 'stringifier', 'deleter'].includes(member.special)) {
24
- // No dfns of these types in any spec as of Feb 2024, or at least no
25
- // no dfns that we can easily map to (for example, the HTML spec
26
- // tends to use generic "dfn" for these).
27
- return null;
28
- }
29
- if (member.type === 'operation') {
30
- dfnType = 'method';
31
- dfnOverload = idl.members
32
- .filter(m => m.type === member.type && m.name === member.name)
33
- .findIndex(m => m === member);
34
- }
35
- else if (member.type === 'field') {
36
- dfnType = 'dict-member';
37
- }
38
- else {
39
- dfnType = member.type;
40
- }
41
- dfnName = member.name ?? member.value;
42
- if (member.type === 'constructor') {
43
- dfnName = 'constructor';
44
- }
45
- dfnFor = idl.name;
46
- }
47
- else {
48
- // The type of the dfn to look for is the same as the IDL type, except
49
- // that composed IDL types ("interface mixin", "callback interface")
50
- // only have the basic type in definitions.
51
- dfnType = idl.type.split(' ')[0];
52
- dfnName = idl.name;
53
- }
54
-
55
- if (!['attribute', 'callback', 'const', 'constructor',
56
- 'dict-member', 'dictionary', 'enum', 'enum-value',
57
- 'interface', 'method', 'namespace', 'typedef'
58
- ].includes(dfnType)) {
59
- console.error(`[error] Found unexpected IDL type "${dfnType}" in ${spec.shortname}`);
60
- }
61
-
62
- const dfnNames = [];
63
- if (dfnType === 'enum-value') {
64
- // Bikeshed keeps wrapping quotes in the dfn linking text, not ReSpec.
65
- dfnNames.push(dfnName);
66
- dfnNames.push(`"${dfnName}"`);
67
- }
68
- else if (dfnType === 'method' || dfnType === 'constructor') {
69
- // Spec authoring tools use different naming conventions in dfns:
70
- // - For variadic arguments, Bikeshed adds "...", not ReSpec.
71
- // - For overloads, Bikeshed relies on argument names, ReSpec adds
72
- // "!overload-x" to the name of the second, third, etc. overloads.
73
- // - The HTML spec sometimes excludes argument names from method dfns.
74
- // We'll give these different variants a try, roughly starting from the
75
- // most specific ones, in other words starting by looking at a specific
76
- // overload dfn.
77
- // When a method has overloads but the spec only has one dfn for the
78
- // first variant, this approach will link the other overloads to that
79
- // first dfn. That's slightly incorrect but a good enough approximation
80
- // in practice.
81
- const argsVariadic = member.arguments.map(arg => (arg.variadic ? '...' : '') + arg.name);
82
- const args = member.arguments.map(arg => arg.name);
83
- dfnNames.push(`${dfnName}!overload-${dfnOverload}(${args.join(', ')})`);
84
- dfnNames.push(`${dfnName}(${argsVariadic.join(', ')})`);
85
- dfnNames.push(`${dfnName}(${args.join(', ')})`);
86
- dfnNames.push(`${dfnName}()`);
87
- }
88
- else {
89
- dfnNames.push(dfnName);
90
- }
91
-
92
- // Look for definitions that look like good initial candidates
93
- const candidateDfns = spec.dfns.filter(dfn =>
94
- dfn.type === dfnType && (dfnFor ? dfn.for.includes(dfnFor) : true));
95
-
96
- // Look for names in turn in that list of candidates.
97
- for (const name of dfnNames) {
98
- const dfns = candidateDfns.filter(dfn => dfn.linkingText.includes(name));
99
- if (dfns.length > 0) {
100
- if (dfns.length > 1) {
101
- const forLabel = dfnFor ? ` for \`${dfnFor}\`` : '';
102
- console.warn(`[warn] More than one dfn for ${dfnType} \`${dfnName}\`${forLabel} in [${spec.shortname}](${spec.crawled}).`);
103
- return null;
104
- }
105
- else {
106
- return dfns[0].href;
107
- }
108
- }
109
- }
110
-
111
- return null;
112
- }
113
-
114
- if (!spec?.idl) {
115
- return spec;
116
- }
117
- try {
118
- spec.idlparsed = await webidlParser.parse(spec.idl);
119
- spec.idlparsed.hasObsoleteIdl = webidlParser.hasObsoleteIdl(spec.idl);
120
-
121
- if (spec.dfns) {
122
- for (const idl of Object.values(spec.idlparsed.idlNames)) {
123
- const href = getHref(idl);
124
- if (href) {
125
- idl.href = href;
126
- }
127
-
128
- if (idl.values) {
129
- for (const value of idl.values) {
130
- const href = getHref(idl, value);
131
- if (href) {
132
- value.href = href;
133
- }
134
- }
135
- }
136
-
137
- if (idl.members) {
138
- for (const member of idl.members) {
139
- const href = getHref(idl, member);
140
- if (href) {
141
- member.href = href;
142
- }
143
- }
144
- }
145
- }
146
-
147
- for (const extendedIdl of Object.values(spec.idlparsed.idlExtendedNames)) {
148
- for (const idl of extendedIdl) {
149
- // No dfn for the extension, we can only link specific members
150
- if (idl.values) {
151
- for (const value of idl.values) {
152
- const href = getHref(idl, value);
153
- if (href) {
154
- value.href = href;
155
- }
156
- }
157
- }
158
-
159
- if (idl.members) {
160
- for (const member of idl.members) {
161
- const href = getHref(idl, member);
162
- if (href) {
163
- member.href = href;
164
- }
165
- }
166
- }
167
- }
168
- }
169
- }
170
- }
171
- catch (err) {
172
- // IDL content is invalid and cannot be parsed.
173
- // Let's return the error, along with the raw IDL
174
- // content so that it may be saved to a file.
175
- spec.idlparsed = err.toString();
176
- }
177
- return spec;
178
- }
179
- };
1
+ /**
2
+ * Post-processing module that creates a parsed IDL structure out of the IDL
3
+ * extract.
4
+ *
5
+ * The module runs at the spec level and generates an `idlparsed` property.
6
+ */
7
+
8
+ import webidlParser from '../cli/parse-webidl.js';
9
+
10
+ export default {
11
+ dependsOn: ['dfns', 'idl'],
12
+ input: 'spec',
13
+ property: 'idlparsed',
14
+
15
+ run: async function(spec, options) {
16
+ function getHref(idl, member) {
17
+ let dfnType;
18
+ let dfnFor;
19
+ let dfnOverload = 0;
20
+ let dfnName;
21
+ if (member) {
22
+ if (['async_iterable', 'iterable', 'maplike', 'setlike'].includes(member.type) ||
23
+ ['getter', 'setter', 'stringifier', 'deleter'].includes(member.special)) {
24
+ // No dfns of these types in any spec as of Feb 2024, or at least no
25
+ // no dfns that we can easily map to (for example, the HTML spec
26
+ // tends to use generic "dfn" for these).
27
+ return null;
28
+ }
29
+ if (member.type === 'operation') {
30
+ dfnType = 'method';
31
+ dfnOverload = idl.members
32
+ .filter(m => m.type === member.type && m.name === member.name)
33
+ .findIndex(m => m === member);
34
+ }
35
+ else if (member.type === 'field') {
36
+ dfnType = 'dict-member';
37
+ }
38
+ else {
39
+ dfnType = member.type;
40
+ }
41
+ dfnName = member.name ?? member.value;
42
+ if (member.type === 'constructor') {
43
+ dfnName = 'constructor';
44
+ }
45
+ dfnFor = idl.name;
46
+ }
47
+ else {
48
+ // The type of the dfn to look for is the same as the IDL type, except
49
+ // that composed IDL types ("interface mixin", "callback interface")
50
+ // only have the basic type in definitions.
51
+ dfnType = idl.type.split(' ')[0];
52
+ dfnName = idl.name;
53
+ }
54
+
55
+ if (!['attribute', 'callback', 'const', 'constructor',
56
+ 'dict-member', 'dictionary', 'enum', 'enum-value',
57
+ 'interface', 'method', 'namespace', 'typedef'
58
+ ].includes(dfnType)) {
59
+ console.error(`[error] Found unexpected IDL type "${dfnType}" in ${spec.shortname}`);
60
+ }
61
+
62
+ const dfnNames = [];
63
+ if (dfnType === 'enum-value') {
64
+ // Bikeshed keeps wrapping quotes in the dfn linking text, not ReSpec.
65
+ dfnNames.push(dfnName);
66
+ dfnNames.push(`"${dfnName}"`);
67
+ }
68
+ else if (dfnType === 'method' || dfnType === 'constructor') {
69
+ // Spec authoring tools use different naming conventions in dfns:
70
+ // - For variadic arguments, Bikeshed adds "...", not ReSpec.
71
+ // - For overloads, Bikeshed relies on argument names, ReSpec adds
72
+ // "!overload-x" to the name of the second, third, etc. overloads.
73
+ // - The HTML spec sometimes excludes argument names from method dfns.
74
+ // We'll give these different variants a try, roughly starting from the
75
+ // most specific ones, in other words starting by looking at a specific
76
+ // overload dfn.
77
+ // When a method has overloads but the spec only has one dfn for the
78
+ // first variant, this approach will link the other overloads to that
79
+ // first dfn. That's slightly incorrect but a good enough approximation
80
+ // in practice.
81
+ const argsVariadic = member.arguments.map(arg => (arg.variadic ? '...' : '') + arg.name);
82
+ const args = member.arguments.map(arg => arg.name);
83
+ dfnNames.push(`${dfnName}!overload-${dfnOverload}(${args.join(', ')})`);
84
+ dfnNames.push(`${dfnName}(${argsVariadic.join(', ')})`);
85
+ dfnNames.push(`${dfnName}(${args.join(', ')})`);
86
+ dfnNames.push(`${dfnName}()`);
87
+ }
88
+ else {
89
+ dfnNames.push(dfnName);
90
+ }
91
+
92
+ // Look for definitions that look like good initial candidates
93
+ const candidateDfns = spec.dfns.filter(dfn =>
94
+ dfn.type === dfnType && (dfnFor ? dfn.for.includes(dfnFor) : true));
95
+
96
+ // Look for names in turn in that list of candidates.
97
+ for (const name of dfnNames) {
98
+ const dfns = candidateDfns.filter(dfn => dfn.linkingText.includes(name));
99
+ if (dfns.length > 0) {
100
+ if (dfns.length > 1) {
101
+ const forLabel = dfnFor ? ` for \`${dfnFor}\`` : '';
102
+ console.warn(`[warn] More than one dfn for ${dfnType} \`${dfnName}\`${forLabel} in [${spec.shortname}](${spec.crawled}).`);
103
+ return null;
104
+ }
105
+ else {
106
+ return dfns[0].href;
107
+ }
108
+ }
109
+ }
110
+
111
+ return null;
112
+ }
113
+
114
+ if (!spec?.idl) {
115
+ return spec;
116
+ }
117
+ try {
118
+ spec.idlparsed = await webidlParser.parse(spec.idl);
119
+ spec.idlparsed.hasObsoleteIdl = webidlParser.hasObsoleteIdl(spec.idl);
120
+
121
+ if (spec.dfns) {
122
+ for (const idl of Object.values(spec.idlparsed.idlNames)) {
123
+ const href = getHref(idl);
124
+ if (href) {
125
+ idl.href = href;
126
+ }
127
+
128
+ if (idl.values) {
129
+ for (const value of idl.values) {
130
+ const href = getHref(idl, value);
131
+ if (href) {
132
+ value.href = href;
133
+ }
134
+ }
135
+ }
136
+
137
+ if (idl.members) {
138
+ for (const member of idl.members) {
139
+ const href = getHref(idl, member);
140
+ if (href) {
141
+ member.href = href;
142
+ }
143
+ }
144
+ }
145
+ }
146
+
147
+ for (const extendedIdl of Object.values(spec.idlparsed.idlExtendedNames)) {
148
+ for (const idl of extendedIdl) {
149
+ // No dfn for the extension, we can only link specific members
150
+ if (idl.values) {
151
+ for (const value of idl.values) {
152
+ const href = getHref(idl, value);
153
+ if (href) {
154
+ value.href = href;
155
+ }
156
+ }
157
+ }
158
+
159
+ if (idl.members) {
160
+ for (const member of idl.members) {
161
+ const href = getHref(idl, member);
162
+ if (href) {
163
+ member.href = href;
164
+ }
165
+ }
166
+ }
167
+ }
168
+ }
169
+ }
170
+ }
171
+ catch (err) {
172
+ // IDL content is invalid and cannot be parsed.
173
+ // Let's return the error, along with the raw IDL
174
+ // content so that it may be saved to a file.
175
+ spec.idlparsed = err.toString();
176
+ }
177
+ return spec;
178
+ }
179
+ };
@@ -1,51 +1,51 @@
1
- /**
2
- * Post-processing module that can be used to patch definition extracts,
3
- * typically to drop problematic duplicate definitions they may contain.
4
- *
5
- * This post-processing module should only be considered as last resort because
6
- * it requires manual maintenance over time. Goal is to hardcode things here
7
- * only when duplicate terms create actual referencing issues, not to resolve
8
- * all duplicate definitions conflicts.
9
- *
10
- * The module runs at the spec level.
11
- */
12
-
13
- export default {
14
- dependsOn: ['dfns'],
15
- input: 'spec',
16
-
17
- run: async function (spec, options) {
18
- // Note the spec object passed to post-processing modules does not contain
19
- // any specific detail on the spec other than the crawled URL, so no direct
20
- // way to match spec on its shortname
21
- if (spec.crawled && spec.dfns) {
22
- // https://github.com/w3c/webref/blob/main/ed/idlpatches/orientation-event.idl.patch
23
- if (spec.crawled.includes('/deviceorientation/') ||
24
- spec.crawled.includes('/TR/orientation-event/')) {
25
- spec.dfns = spec.dfns.filter(dfn =>
26
- !dfn.linkingText.includes('PermissionState') &&
27
- !dfn.for.includes('PermissionState'));
28
- }
29
-
30
- // https://github.com/w3c/webref/blob/main/ed/idlpatches/portals.idl.patch
31
- else if (spec.crawled.includes('/portals/')) {
32
- spec.dfns = spec.dfns.filter(dfn =>
33
- dfn.linkingText[0] !== 'MessageEventSource');
34
- }
35
-
36
- // The /TR versions of WebCrypto API, Publication Manifest and Audiobooks
37
- // do not follow the usual dfn data model. Definitions get extracted as
38
- // "exported" as a result. This creates collisions. The nightly versions
39
- // of the specs respect the dfn data model and these specs don't export
40
- // terms in practice. Also see discussion in:
41
- // https://github.com/w3c/reffy/issues/1250
42
- else if (spec.crawled.includes('/TR/WebCryptoAPI/') ||
43
- spec.crawled.includes('/TR/pub-manifest/') ||
44
- spec.crawled.includes('/TR/audiobooks/')) {
45
- spec.dfns.forEach(dfn => dfn.access = 'private');
46
- }
47
- }
48
-
49
- return spec;
50
- }
51
- };
1
+ /**
2
+ * Post-processing module that can be used to patch definition extracts,
3
+ * typically to drop problematic duplicate definitions they may contain.
4
+ *
5
+ * This post-processing module should only be considered as last resort because
6
+ * it requires manual maintenance over time. Goal is to hardcode things here
7
+ * only when duplicate terms create actual referencing issues, not to resolve
8
+ * all duplicate definitions conflicts.
9
+ *
10
+ * The module runs at the spec level.
11
+ */
12
+
13
+ export default {
14
+ dependsOn: ['dfns'],
15
+ input: 'spec',
16
+
17
+ run: async function (spec, options) {
18
+ // Note the spec object passed to post-processing modules does not contain
19
+ // any specific detail on the spec other than the crawled URL, so no direct
20
+ // way to match spec on its shortname
21
+ if (spec.crawled && spec.dfns) {
22
+ // https://github.com/w3c/webref/blob/main/ed/idlpatches/orientation-event.idl.patch
23
+ if (spec.crawled.includes('/deviceorientation/') ||
24
+ spec.crawled.includes('/TR/orientation-event/')) {
25
+ spec.dfns = spec.dfns.filter(dfn =>
26
+ !dfn.linkingText.includes('PermissionState') &&
27
+ !dfn.for.includes('PermissionState'));
28
+ }
29
+
30
+ // https://github.com/w3c/webref/blob/main/ed/idlpatches/portals.idl.patch
31
+ else if (spec.crawled.includes('/portals/')) {
32
+ spec.dfns = spec.dfns.filter(dfn =>
33
+ dfn.linkingText[0] !== 'MessageEventSource');
34
+ }
35
+
36
+ // The /TR versions of WebCrypto API, Publication Manifest and Audiobooks
37
+ // do not follow the usual dfn data model. Definitions get extracted as
38
+ // "exported" as a result. This creates collisions. The nightly versions
39
+ // of the specs respect the dfn data model and these specs don't export
40
+ // terms in practice. Also see discussion in:
41
+ // https://github.com/w3c/reffy/issues/1250
42
+ else if (spec.crawled.includes('/TR/WebCryptoAPI/') ||
43
+ spec.crawled.includes('/TR/pub-manifest/') ||
44
+ spec.crawled.includes('/TR/audiobooks/')) {
45
+ spec.dfns.forEach(dfn => dfn.access = 'private');
46
+ }
47
+ }
48
+
49
+ return spec;
50
+ }
51
+ };