reffy 7.2.8 → 8.0.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/README.md +2 -9
- package/index.js +3 -5
- package/package.json +5 -5
- package/reffy.js +61 -15
- package/src/browserlib/extract-events.mjs +20 -20
- package/src/browserlib/reffy.json +1 -1
- package/src/lib/post-processor.js +269 -0
- package/src/lib/specs-crawler.js +93 -127
- package/src/lib/util.js +81 -8
- package/src/postprocessing/csscomplete.js +50 -0
- package/src/postprocessing/events.js +195 -0
- package/src/{cli/generate-idlnames.js → postprocessing/idlnames.js} +102 -143
- package/src/postprocessing/idlparsed.js +31 -0
- package/src/cli/generate-idlparsed.js +0 -139
package/src/lib/specs-crawler.js
CHANGED
|
@@ -14,16 +14,15 @@ const fs = require('fs');
|
|
|
14
14
|
const path = require('path');
|
|
15
15
|
const specs = require('web-specs');
|
|
16
16
|
const cssDfnParser = require('./css-grammar-parser');
|
|
17
|
-
const
|
|
18
|
-
const { generateIdlNames, saveIdlNames } = require('../cli/generate-idlnames');
|
|
17
|
+
const postProcessor = require('./post-processor');
|
|
19
18
|
const {
|
|
20
19
|
completeWithAlternativeUrls,
|
|
21
20
|
expandBrowserModules,
|
|
22
21
|
expandCrawlResult,
|
|
23
22
|
expandSpecResult,
|
|
24
|
-
getGeneratedIDLNamesByCSSProperty,
|
|
25
23
|
isLatestLevelThatPasses,
|
|
26
24
|
processSpecification,
|
|
25
|
+
requireFromWorkingDirectory,
|
|
27
26
|
setupBrowser,
|
|
28
27
|
teardownBrowser,
|
|
29
28
|
createFolderIfNeeded
|
|
@@ -72,111 +71,52 @@ async function specOrFallback(spec, fallbackFolder, fallbackData) {
|
|
|
72
71
|
*/
|
|
73
72
|
async function crawlSpec(spec, crawlOptions) {
|
|
74
73
|
crawlOptions = crawlOptions || {};
|
|
75
|
-
|
|
74
|
+
|
|
75
|
+
const urlToCrawl = crawlOptions.publishedVersion ?
|
|
76
76
|
(spec.release ? spec.release : spec.nightly) :
|
|
77
77
|
spec.nightly;
|
|
78
78
|
const fallbackFolder = crawlOptions.fallback ?
|
|
79
79
|
path.dirname(crawlOptions.fallback) : '';
|
|
80
80
|
|
|
81
|
-
if (spec.error) {
|
|
82
|
-
return specOrFallback(spec, fallbackFolder, crawlOptions.fallbackData?.results);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
81
|
try {
|
|
86
82
|
const fallback = crawlOptions.fallbackData?.results?.find(s => s.url === spec.url);
|
|
87
83
|
let cacheInfo = {};
|
|
88
84
|
if (crawlOptions.fallbackData?.crawler === `reffy-${reffyVersion}`) {
|
|
89
85
|
cacheInfo = Object.assign({}, fallback?.crawlCacheInfo);
|
|
90
86
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
(spec,
|
|
94
|
-
const idToHeading = modules.find(m => m.needsIdToHeadingMap) ?
|
|
95
|
-
window.reffy.mapIdsToHeadings() : null;
|
|
96
|
-
const res = {
|
|
97
|
-
crawled: window.location.toString()
|
|
98
|
-
};
|
|
99
|
-
modules.forEach(mod => {
|
|
100
|
-
res[mod.property] = window.reffy[mod.name](spec, idToHeading);
|
|
101
|
-
});
|
|
102
|
-
return res;
|
|
103
|
-
},
|
|
104
|
-
[spec, crawlOptions.modules],
|
|
105
|
-
{ quiet: crawlOptions.quiet,
|
|
106
|
-
forceLocalFetch: crawlOptions.forceLocalFetch,
|
|
107
|
-
...cacheInfo}
|
|
108
|
-
);
|
|
109
|
-
if (result.status === "notmodified" && fallback) {
|
|
110
|
-
crawlOptions.quiet ?? console.warn(`skipping ${spec.url}, no change`);
|
|
111
|
-
const copy = Object.assign({}, fallback);
|
|
112
|
-
return expandSpecResult(copy, fallbackFolder);
|
|
87
|
+
let result = null;
|
|
88
|
+
if (crawlOptions.useCrawl) {
|
|
89
|
+
result = await expandSpecResult(spec, crawlOptions.useCrawl);
|
|
113
90
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
.forEach(propDfn => {
|
|
126
|
-
propDfn.linkingText.forEach(lt => {
|
|
127
|
-
if (!result.css.properties.hasOwnProperty(lt)) {
|
|
128
|
-
result.css.properties[lt] = {
|
|
129
|
-
name: lt
|
|
130
|
-
};
|
|
131
|
-
}
|
|
132
|
-
});
|
|
91
|
+
else {
|
|
92
|
+
result = await processSpecification(
|
|
93
|
+
urlToCrawl,
|
|
94
|
+
(spec, modules) => {
|
|
95
|
+
const idToHeading = modules.find(m => m.needsIdToHeadingMap) ?
|
|
96
|
+
window.reffy.mapIdsToHeadings() : null;
|
|
97
|
+
const res = {
|
|
98
|
+
crawled: window.location.toString()
|
|
99
|
+
};
|
|
100
|
+
modules.forEach(mod => {
|
|
101
|
+
res[mod.property] = window.reffy[mod.name](spec, idToHeading);
|
|
133
102
|
});
|
|
103
|
+
return res;
|
|
104
|
+
},
|
|
105
|
+
[spec, crawlOptions.modules],
|
|
106
|
+
{ quiet: crawlOptions.quiet,
|
|
107
|
+
forceLocalFetch: crawlOptions.forceLocalFetch,
|
|
108
|
+
...cacheInfo}
|
|
109
|
+
);
|
|
110
|
+
if (result.status === "notmodified" && fallback) {
|
|
111
|
+
crawlOptions.quiet ?? console.warn(`skipping ${spec.url}, no change`);
|
|
112
|
+
const copy = Object.assign({}, fallback);
|
|
113
|
+
return expandSpecResult(copy, fallbackFolder);
|
|
134
114
|
}
|
|
115
|
+
}
|
|
135
116
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
// real CSS properties. In practice, they are. Let's remove them from
|
|
140
|
-
// the extract.
|
|
141
|
-
['property-name', '--*'].forEach(prop => {
|
|
142
|
-
if ((result.css.properties || {})[prop]) {
|
|
143
|
-
delete result.css.properties[prop];
|
|
144
|
-
}
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
// Specific rule for CSS extracts:
|
|
148
|
-
// Parse extracted CSS definitions and add generated IDL attribute names
|
|
149
|
-
Object.entries(result.css.properties || {}).forEach(([prop, dfn]) => {
|
|
150
|
-
if (dfn.value || dfn.newValues) {
|
|
151
|
-
try {
|
|
152
|
-
dfn.parsedValue = cssDfnParser.parsePropDefValue(
|
|
153
|
-
dfn.value || dfn.newValues);
|
|
154
|
-
} catch (e) {
|
|
155
|
-
dfn.valueParseError = e.message;
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
dfn.styleDeclaration = getGeneratedIDLNamesByCSSProperty(prop);
|
|
159
|
-
});
|
|
160
|
-
Object.entries(result.css.descriptors || {}).forEach(([desc, dfn]) => {
|
|
161
|
-
if (dfn.value) {
|
|
162
|
-
try {
|
|
163
|
-
dfn.parsedValue = cssDfnParser.parsePropDefValue(
|
|
164
|
-
dfn.value);
|
|
165
|
-
} catch (e) {
|
|
166
|
-
dfn.valueParseError = e.message;
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
});
|
|
170
|
-
Object.entries(result.css.valuespaces || {}).forEach(([vs, dfn]) => {
|
|
171
|
-
if (dfn.value) {
|
|
172
|
-
try {
|
|
173
|
-
dfn.parsedValue = cssDfnParser.parsePropDefValue(
|
|
174
|
-
dfn.value);
|
|
175
|
-
} catch (e) {
|
|
176
|
-
dfn.valueParseError = e.message;
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
});
|
|
117
|
+
// Run post-processing modules at the spec level
|
|
118
|
+
for (const mod of (crawlOptions.post ?? [])) {
|
|
119
|
+
await postProcessor.run(mod, result, crawlOptions);
|
|
180
120
|
}
|
|
181
121
|
|
|
182
122
|
// Copy results back into initial spec object
|
|
@@ -187,9 +127,12 @@ async function crawlSpec(spec, crawlOptions) {
|
|
|
187
127
|
crawlOptions.modules.forEach(mod => {
|
|
188
128
|
if (result[mod.property]) {
|
|
189
129
|
spec[mod.property] = result[mod.property];
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
crawlOptions.post?.forEach(mod => {
|
|
133
|
+
const prop = mod.property ?? mod.name;
|
|
134
|
+
if (postProcessor.appliesAtLevel(mod, 'spec') && result[prop]) {
|
|
135
|
+
spec[prop] = result[prop];
|
|
193
136
|
}
|
|
194
137
|
});
|
|
195
138
|
}
|
|
@@ -236,12 +179,6 @@ async function saveSpecResults(spec, settings) {
|
|
|
236
179
|
continue;
|
|
237
180
|
}
|
|
238
181
|
folders[mod.property] = await getSubfolder(mod.property);
|
|
239
|
-
|
|
240
|
-
// Specific rule for IDL:
|
|
241
|
-
// Raw IDL goes to "idl" subfolder, parsed IDL goes to "idlparsed"
|
|
242
|
-
if (mod.property === 'idl') {
|
|
243
|
-
folders.idlparsed = await getSubfolder('idlparsed');
|
|
244
|
-
}
|
|
245
182
|
}
|
|
246
183
|
|
|
247
184
|
function getBaseJSON(spec) {
|
|
@@ -301,9 +238,6 @@ async function saveSpecResults(spec, settings) {
|
|
|
301
238
|
if (spec.idl) {
|
|
302
239
|
spec.idl = await saveIdl(spec);
|
|
303
240
|
}
|
|
304
|
-
if (spec.idlparsed) {
|
|
305
|
-
spec.idlparsed = await saveIdlParsed(spec, settings.output);
|
|
306
|
-
}
|
|
307
241
|
|
|
308
242
|
// Save CSS dumps
|
|
309
243
|
function defineCSSContent(spec) {
|
|
@@ -331,14 +265,16 @@ async function saveSpecResults(spec, settings) {
|
|
|
331
265
|
(typeof thing == 'object') && (Object.keys(thing).length === 0);
|
|
332
266
|
}
|
|
333
267
|
|
|
334
|
-
// Save all other extracts
|
|
268
|
+
// Save all other extracts from crawling modules
|
|
335
269
|
const remainingModules = modules.filter(mod =>
|
|
336
270
|
!mod.metadata && mod.property !== 'css' && mod.property !== 'idl');
|
|
337
271
|
for (const mod of remainingModules) {
|
|
338
272
|
await saveExtract(spec, mod.property, spec => !isEmpty(spec[mod.property]));
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// Save extracts from post-processing modules that run at the spec level
|
|
276
|
+
for (const mod of (settings.post ?? [])) {
|
|
277
|
+
await postProcessor.save(mod, spec, settings);
|
|
342
278
|
}
|
|
343
279
|
|
|
344
280
|
return spec;
|
|
@@ -372,10 +308,17 @@ async function crawlList(speclist, crawlOptions) {
|
|
|
372
308
|
}
|
|
373
309
|
}
|
|
374
310
|
|
|
375
|
-
// Prepare Puppeteer instance
|
|
376
|
-
|
|
311
|
+
// Prepare Puppeteer instance unless we already have crawl results and
|
|
312
|
+
// we're only interested in post-processing
|
|
313
|
+
let list = null;
|
|
314
|
+
if (crawlOptions.useCrawl) {
|
|
315
|
+
list = speclist;
|
|
316
|
+
}
|
|
317
|
+
else {
|
|
318
|
+
await setupBrowser(crawlOptions.modules);
|
|
319
|
+
list = speclist.map(completeWithAlternativeUrls);
|
|
320
|
+
}
|
|
377
321
|
|
|
378
|
-
const list = speclist.map(completeWithAlternativeUrls);
|
|
379
322
|
const listAndPromise = list.map(spec => {
|
|
380
323
|
let resolve = null;
|
|
381
324
|
let reject = null;
|
|
@@ -418,7 +361,9 @@ async function crawlList(speclist, crawlOptions) {
|
|
|
418
361
|
const results = await Promise.all(listAndPromise.map(crawlSpecAndPromise));
|
|
419
362
|
|
|
420
363
|
// Close Puppeteer instance
|
|
421
|
-
|
|
364
|
+
if (!crawlOptions.useCrawl) {
|
|
365
|
+
teardownBrowser();
|
|
366
|
+
}
|
|
422
367
|
|
|
423
368
|
return results;
|
|
424
369
|
}
|
|
@@ -564,8 +509,12 @@ function crawlSpecs(options) {
|
|
|
564
509
|
});
|
|
565
510
|
}
|
|
566
511
|
|
|
567
|
-
const
|
|
568
|
-
|
|
512
|
+
const crawlIndex = options?.useCrawl ?
|
|
513
|
+
requireFromWorkingDirectory(options.useCrawl) :
|
|
514
|
+
null;
|
|
515
|
+
|
|
516
|
+
const requestedList = crawlIndex ? crawlIndex.results :
|
|
517
|
+
options?.specs ? prepareListOfSpecs(options.specs) :
|
|
569
518
|
specs;
|
|
570
519
|
|
|
571
520
|
// Make a shallow copy of passed options parameter and expand modules
|
|
@@ -579,9 +528,11 @@ function crawlSpecs(options) {
|
|
|
579
528
|
for (const mod of options.modules) {
|
|
580
529
|
if (mod.extractsPerSeries) {
|
|
581
530
|
await adjustExtractsPerSeries(results, mod.property, options);
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
for (const mod of options.post ?? []) {
|
|
534
|
+
if (postProcessor.extractsPerSeries(mod)) {
|
|
535
|
+
await adjustExtractsPerSeries(results, mod.property, options);
|
|
585
536
|
}
|
|
586
537
|
}
|
|
587
538
|
return results;
|
|
@@ -612,14 +563,21 @@ function crawlSpecs(options) {
|
|
|
612
563
|
}
|
|
613
564
|
})
|
|
614
565
|
.then(async crawlIndex => {
|
|
615
|
-
//
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
566
|
+
// Run post-processing modules at the crawl level
|
|
567
|
+
for (const mod of (options.post ?? [])) {
|
|
568
|
+
if (!postProcessor.appliesAtLevel(mod, 'crawl')) {
|
|
569
|
+
continue;
|
|
570
|
+
}
|
|
571
|
+
const crawlResults = await expandCrawlResult(
|
|
572
|
+
crawlIndex, options.output, postProcessor.dependsOn(mod));
|
|
573
|
+
const result = await postProcessor.run(mod, crawlResults, options);
|
|
574
|
+
await postProcessor.save(mod, result, options);
|
|
575
|
+
|
|
576
|
+
if (!options.output) {
|
|
577
|
+
console.log();
|
|
578
|
+
console.log(JSON.stringify(result, null, 2));
|
|
579
|
+
}
|
|
619
580
|
}
|
|
620
|
-
const crawlResults = await expandCrawlResult(crawlIndex, options.output, ['idlparsed', 'dfns']);
|
|
621
|
-
const idlNames = generateIdlNames(crawlResults.results, options);
|
|
622
|
-
await saveIdlNames(idlNames, options.output);
|
|
623
581
|
});
|
|
624
582
|
}
|
|
625
583
|
|
|
@@ -627,5 +585,13 @@ function crawlSpecs(options) {
|
|
|
627
585
|
/**************************************************
|
|
628
586
|
Export methods for use as module
|
|
629
587
|
**************************************************/
|
|
630
|
-
|
|
631
|
-
|
|
588
|
+
// TODO: consider more alignment between the two crawl functions or
|
|
589
|
+
// find more explicit names to distinguish between them:
|
|
590
|
+
// - "crawlList" takes an explicit list of specs as input, does not run the
|
|
591
|
+
// post-processor, and returns the results without saving them to files.
|
|
592
|
+
// - "crawlSpecs" takes options as input, runs all steps and saves results
|
|
593
|
+
// to files (or outputs the results to the console). It does not return
|
|
594
|
+
// anything.
|
|
595
|
+
module.exports.crawlSpecs = (...args) => Array.isArray(args[0]) ?
|
|
596
|
+
crawlList.apply(this, args) :
|
|
597
|
+
crawlSpecs.apply(this, args);
|
package/src/lib/util.js
CHANGED
|
@@ -605,7 +605,7 @@ async function processSpecification(spec, processFunction, args, options) {
|
|
|
605
605
|
window.document.head.querySelector("script[src*='respec']");
|
|
606
606
|
|
|
607
607
|
function sleep(ms) {
|
|
608
|
-
return new Promise(resolve => setTimeout(resolve, ms));
|
|
608
|
+
return new Promise(resolve => setTimeout(resolve, ms, 'slept'));
|
|
609
609
|
}
|
|
610
610
|
|
|
611
611
|
async function isReady(counter) {
|
|
@@ -614,7 +614,10 @@ async function processSpecification(spec, processFunction, args, options) {
|
|
|
614
614
|
throw new Error('Respec generation took too long');
|
|
615
615
|
}
|
|
616
616
|
if (window.document.respec?.ready) {
|
|
617
|
-
await window.document.respec.ready;
|
|
617
|
+
const res = await Promise.race([window.document.respec.ready, sleep(60000)]);
|
|
618
|
+
if (res === 'slept') {
|
|
619
|
+
throw new Error('Respec generation took too long');
|
|
620
|
+
}
|
|
618
621
|
}
|
|
619
622
|
else if (usesRespec) {
|
|
620
623
|
await sleep(1000);
|
|
@@ -741,10 +744,10 @@ function isLatestLevelThatPasses(spec, list, predicate) {
|
|
|
741
744
|
return true;
|
|
742
745
|
}
|
|
743
746
|
while (spec.seriesNext) {
|
|
747
|
+
spec = list.find(s => s.shortname === spec.seriesNext);
|
|
744
748
|
if (!spec) {
|
|
745
749
|
break;
|
|
746
750
|
}
|
|
747
|
-
spec = list.find(s => s.shortname === spec.seriesNext);
|
|
748
751
|
if ((spec.seriesComposition === 'full') && predicate(spec)) {
|
|
749
752
|
return false;
|
|
750
753
|
}
|
|
@@ -813,10 +816,19 @@ async function expandSpecResult(spec, baseFolder, properties) {
|
|
|
813
816
|
// Also drop header that may have been added when extract was
|
|
814
817
|
// serialized.
|
|
815
818
|
if (contents.startsWith('// GENERATED CONTENT - DO NOT EDIT')) {
|
|
816
|
-
const
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
819
|
+
const hasWindowsEndings = contents.indexOf('\r\n');
|
|
820
|
+
if (hasWindowsEndings) {
|
|
821
|
+
const endOfHeader = contents.indexOf('\r\n\r\n');
|
|
822
|
+
contents = contents.substring(endOfHeader + 4)
|
|
823
|
+
// remove trailing newline added in saveIdl
|
|
824
|
+
.slice(0, -2);
|
|
825
|
+
}
|
|
826
|
+
else {
|
|
827
|
+
const endOfHeader = contents.indexOf('\n\n');
|
|
828
|
+
contents = contents.substring(endOfHeader + 2)
|
|
829
|
+
// remove trailing newline added in saveIdl
|
|
830
|
+
.slice(0, -1);
|
|
831
|
+
}
|
|
820
832
|
}
|
|
821
833
|
spec.idl = contents;
|
|
822
834
|
}
|
|
@@ -927,6 +939,66 @@ async function createFolderIfNeeded(folder) {
|
|
|
927
939
|
}
|
|
928
940
|
|
|
929
941
|
|
|
942
|
+
/**
|
|
943
|
+
* Tree hierarchies on which events may bubble
|
|
944
|
+
*
|
|
945
|
+
* First interface is the tree root, further interfaces are deeper levels in
|
|
946
|
+
* the tree.
|
|
947
|
+
*/
|
|
948
|
+
const trees = {
|
|
949
|
+
// DOM tree:
|
|
950
|
+
// https://dom.spec.whatwg.org/#node-trees
|
|
951
|
+
'dom': ['Window', 'Document', 'Element', 'Node'],
|
|
952
|
+
|
|
953
|
+
// IndexedDB tree (defined through "get the parent" algorithms)
|
|
954
|
+
// https://www.w3.org/TR/IndexedDB/#ref-for-get-the-parent%E2%91%A0
|
|
955
|
+
// https://www.w3.org/TR/IndexedDB/#ref-for-get-the-parent%E2%91%A1
|
|
956
|
+
'IndexedDB': ['IDBDatabase', 'IDBTransaction', 'IDBRequest'],
|
|
957
|
+
|
|
958
|
+
// Web Bluetooth tree
|
|
959
|
+
// https://webbluetoothcg.github.io/web-bluetooth/#bluetooth-tree-bluetooth-tree
|
|
960
|
+
'web-bluetooth': [
|
|
961
|
+
'Bluetooth', 'BluetoothDevice', 'BluetoothRemoteGATTService',
|
|
962
|
+
'BluetoothRemoteGATTCharacteristic', 'BluetoothRemoteGATTDescriptor'],
|
|
963
|
+
|
|
964
|
+
// Serial tree
|
|
965
|
+
// https://wicg.github.io/serial/#serialport-interface
|
|
966
|
+
'serial': ['Serial', 'SerialPort']
|
|
967
|
+
};
|
|
968
|
+
|
|
969
|
+
|
|
970
|
+
/**
|
|
971
|
+
* Return information about the tree hierarchy the IDL interface is linked to.
|
|
972
|
+
*
|
|
973
|
+
* @function
|
|
974
|
+
* @param {String} iface Name of the IDL interface to link to a tree
|
|
975
|
+
* @param {Array(Object)} interfaces A list of all known IDL interfaces with
|
|
976
|
+
* inheritance information in an "inheritance" property.
|
|
977
|
+
* @return {Object} An object with a "tree" property set to the shortname of the
|
|
978
|
+
* spec that defines the tree hierarchy, an "interface" property set to the
|
|
979
|
+
* interface name of the closest interface in the inheritance chain of the
|
|
980
|
+
* given interface that belongs to the tree, and a "depth" property that gives
|
|
981
|
+
* the depth of that interface in the tree hierarchy (where 0 is the tree
|
|
982
|
+
* root). The object is null if the interface cannot be associated with a
|
|
983
|
+
* tree.
|
|
984
|
+
*/
|
|
985
|
+
function getInterfaceTreeInfo(iface, interfaces) {
|
|
986
|
+
while (iface) {
|
|
987
|
+
for (const [tree, nodes] of Object.entries(trees)) {
|
|
988
|
+
if (nodes.includes(iface)) {
|
|
989
|
+
return {
|
|
990
|
+
tree,
|
|
991
|
+
interface: iface,
|
|
992
|
+
depth: nodes.findIndex(i => i === iface)
|
|
993
|
+
};
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
iface = interfaces.find(i => i.name === iface)?.inheritance;
|
|
997
|
+
}
|
|
998
|
+
return null;
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
|
|
930
1002
|
module.exports = {
|
|
931
1003
|
fetch,
|
|
932
1004
|
requireFromWorkingDirectory,
|
|
@@ -939,5 +1011,6 @@ module.exports = {
|
|
|
939
1011
|
expandCrawlResult,
|
|
940
1012
|
expandSpecResult,
|
|
941
1013
|
getGeneratedIDLNamesByCSSProperty,
|
|
942
|
-
createFolderIfNeeded
|
|
1014
|
+
createFolderIfNeeded,
|
|
1015
|
+
getInterfaceTreeInfo
|
|
943
1016
|
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Post-processing module that adds CSS property definitions found in prose
|
|
3
|
+
* from the dfns extract, clean up property definitions that should never have
|
|
4
|
+
* been extracted, and adds the generated IDL attribute names in a
|
|
5
|
+
* styleDeclaration sub-property.
|
|
6
|
+
*
|
|
7
|
+
* Module runs at the spec level. It does not create a distinct property but
|
|
8
|
+
* rather completes the `css` property with additional info.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const { getGeneratedIDLNamesByCSSProperty } = require('../lib/util');
|
|
12
|
+
|
|
13
|
+
module.exports = {
|
|
14
|
+
dependsOn: ['css', 'dfns'],
|
|
15
|
+
input: 'spec',
|
|
16
|
+
|
|
17
|
+
run: async function(spec, options) {
|
|
18
|
+
if (spec.dfns && spec.css) {
|
|
19
|
+
spec.dfns
|
|
20
|
+
.filter(dfn => dfn.type == "property" && !dfn.informative)
|
|
21
|
+
.forEach(propDfn => {
|
|
22
|
+
propDfn.linkingText.forEach(lt => {
|
|
23
|
+
if (!spec.css.properties.hasOwnProperty(lt)) {
|
|
24
|
+
spec.css.properties[lt] = {
|
|
25
|
+
name: lt
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (spec.css) {
|
|
33
|
+
// Add generated IDL attribute names
|
|
34
|
+
Object.entries(spec.css.properties || {}).forEach(([prop, dfn]) => {
|
|
35
|
+
dfn.styleDeclaration = getGeneratedIDLNamesByCSSProperty(prop);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// Drop the sample definition (property-name) in CSS2 and the custom
|
|
39
|
+
// property definition (--*) in CSS Variables that specs incorrectly flag
|
|
40
|
+
// as real CSS properties.
|
|
41
|
+
['property-name', '--*'].forEach(prop => {
|
|
42
|
+
if ((spec.css.properties || {})[prop]) {
|
|
43
|
+
delete spec.css.properties[prop];
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return spec;
|
|
49
|
+
}
|
|
50
|
+
};
|