reffy 18.5.0 → 18.6.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 +2 -2
- package/schemas/files/index.json +19 -0
- package/src/lib/markdown-report.js +39 -22
- package/src/lib/post-processor.js +2 -2
- package/src/lib/specs-crawler.js +167 -89
- package/src/lib/util.js +17 -1
- package/src/postprocessing/idlnames.js +3 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "reffy",
|
|
3
|
-
"version": "18.
|
|
3
|
+
"version": "18.6.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",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"mocha": "11.1.0",
|
|
47
47
|
"respec": "35.3.0",
|
|
48
48
|
"respec-hljs": "2.1.1",
|
|
49
|
-
"rollup": "4.
|
|
49
|
+
"rollup": "4.40.0",
|
|
50
50
|
"undici": "^7.0.0"
|
|
51
51
|
},
|
|
52
52
|
"overrides": {
|
package/schemas/files/index.json
CHANGED
|
@@ -35,6 +35,25 @@
|
|
|
35
35
|
"items": {
|
|
36
36
|
"type": "object"
|
|
37
37
|
}
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
"post": {
|
|
41
|
+
"type": "array",
|
|
42
|
+
"items": {
|
|
43
|
+
"type": "object",
|
|
44
|
+
"properties": {
|
|
45
|
+
"mod": {
|
|
46
|
+
"type": "string"
|
|
47
|
+
},
|
|
48
|
+
"result": {
|
|
49
|
+
"oneOf": [
|
|
50
|
+
{ "type": "object" },
|
|
51
|
+
{ "type": "array" }
|
|
52
|
+
]
|
|
53
|
+
},
|
|
54
|
+
"additionalProperties": false
|
|
55
|
+
}
|
|
56
|
+
}
|
|
38
57
|
}
|
|
39
58
|
}
|
|
40
59
|
}
|
|
@@ -75,27 +75,39 @@ const moduleFunctions = {
|
|
|
75
75
|
.join('\n')
|
|
76
76
|
},
|
|
77
77
|
dfns: {
|
|
78
|
+
// For dfns, note we make a distinction between terms that are exported by
|
|
79
|
+
// default (such as CSS and Web IDL terms) and terms that editors choose to
|
|
80
|
+
// export explicitly. The former get reported in other details, the latter
|
|
81
|
+
// are the ones most likely to cause duplication issues.
|
|
78
82
|
isPresent: isArrayPresent,
|
|
79
|
-
summary: value =>
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
83
|
+
summary: value => [
|
|
84
|
+
{
|
|
85
|
+
access: 'explicitly exported',
|
|
86
|
+
dfns: value
|
|
87
|
+
.filter(dfn => dfn.access === 'public')
|
|
88
|
+
.filter(dfn => dfn.type === 'dfn' || dfn.type === 'cddl')
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
access: 'exported by default',
|
|
92
|
+
dfns: value
|
|
93
|
+
.filter(dfn => dfn.access === 'public')
|
|
94
|
+
.filter(dfn => dfn.type !== 'dfn' && dfn.type !== 'cddl')
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
access: 'private',
|
|
98
|
+
dfns: value
|
|
99
|
+
.filter(dfn => dfn.access !== 'public')
|
|
86
100
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
.filter(found => found)
|
|
92
|
-
.join(', ');
|
|
93
|
-
},
|
|
101
|
+
]
|
|
102
|
+
.map(t => t.dfns.length > 0 ? t.dfns.length + ' ' + t.access : null)
|
|
103
|
+
.filter(found => found)
|
|
104
|
+
.join(', '),
|
|
94
105
|
details: value => {
|
|
95
106
|
const details = value
|
|
96
107
|
.filter(dfn => dfn.access === 'public')
|
|
108
|
+
.filter(dfn => dfn.type === 'dfn' || dfn.type === 'cddl')
|
|
97
109
|
.map(dfn => '- ' + wrapTerm(dfn.linkingText[0], dfn.type, dfn.href) +
|
|
98
|
-
(dfn.for?.length > 0 ? ' for ' + wrapTerm(dfn.for[0], dfn.type)
|
|
110
|
+
(dfn.for?.length > 0 ? ' for ' + wrapTerm(dfn.for[0], dfn.type): '') +
|
|
99
111
|
`, type ${dfn.type}` +
|
|
100
112
|
` ([xref search](https://respec.org/xref/?term=${encodeURIComponent(dfn.linkingText[0])}))`
|
|
101
113
|
);
|
|
@@ -104,7 +116,7 @@ const moduleFunctions = {
|
|
|
104
116
|
}
|
|
105
117
|
const s = details.length > 1 ? 's' : '';
|
|
106
118
|
const report = ['<details>'];
|
|
107
|
-
report.push(`<summary>${details.length} exported term${s}</summary>`);
|
|
119
|
+
report.push(`<summary>${details.length} explicitly exported term${s}</summary>`);
|
|
108
120
|
report.push('');
|
|
109
121
|
report.push(...details);
|
|
110
122
|
report.push('</details>');
|
|
@@ -205,7 +217,9 @@ const moduleFunctions = {
|
|
|
205
217
|
summary: arrayInfo
|
|
206
218
|
},
|
|
207
219
|
links: {
|
|
208
|
-
isPresent:
|
|
220
|
+
isPresent: value =>
|
|
221
|
+
isArrayPresent(Object.keys(value?.rawlinks ?? {})) ||
|
|
222
|
+
isArrayPresent(Object.keys(value?.autolinks ?? {})),
|
|
209
223
|
summary: value => ['rawlinks', 'autolinks']
|
|
210
224
|
.map(prop => Object.keys(value[prop]).length > 0 ?
|
|
211
225
|
Object.keys(value[prop]).length + ' ' + prop :
|
|
@@ -243,13 +257,15 @@ function arrayInfo(value) {
|
|
|
243
257
|
}
|
|
244
258
|
|
|
245
259
|
function wrapTerm(term, type, href) {
|
|
246
|
-
let res = '';
|
|
247
260
|
if (type === 'abstract-op' || type === 'dfn') {
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
261
|
+
if (href) {
|
|
262
|
+
return `[${term}](${href})`;
|
|
263
|
+
}
|
|
264
|
+
else {
|
|
265
|
+
return `"${term}"`;
|
|
266
|
+
}
|
|
252
267
|
}
|
|
268
|
+
const res = '`' + term + '`';
|
|
253
269
|
if (href) {
|
|
254
270
|
return `[${res}](${href})`;
|
|
255
271
|
}
|
|
@@ -312,6 +328,7 @@ export async function generateSpecReport(specResult) {
|
|
|
312
328
|
}
|
|
313
329
|
}
|
|
314
330
|
if (extractsSummary.length > 0) {
|
|
331
|
+
extractsSummary.sort();
|
|
315
332
|
summary.push(`- Spec defines:`);
|
|
316
333
|
summary.push(...extractsSummary);
|
|
317
334
|
}
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
import fs from 'node:fs';
|
|
51
51
|
import path from 'node:path';
|
|
52
52
|
import { pathToFileURL } from 'node:url';
|
|
53
|
-
import { createFolderIfNeeded } from './util.js';
|
|
53
|
+
import { createFolderIfNeeded, shouldSaveToFile } from './util.js';
|
|
54
54
|
import csscomplete from '../postprocessing/csscomplete.js';
|
|
55
55
|
import events from '../postprocessing/events.js';
|
|
56
56
|
import idlnames from '../postprocessing/idlnames.js';
|
|
@@ -220,7 +220,7 @@ async function save(mod, processResult, options) {
|
|
|
220
220
|
}
|
|
221
221
|
}
|
|
222
222
|
|
|
223
|
-
if (!options
|
|
223
|
+
if (!shouldSaveToFile(options)) {
|
|
224
224
|
// Nothing to do if no output folder was given
|
|
225
225
|
return;
|
|
226
226
|
}
|
package/src/lib/specs-crawler.js
CHANGED
|
@@ -27,7 +27,8 @@ import {
|
|
|
27
27
|
setupBrowser,
|
|
28
28
|
teardownBrowser,
|
|
29
29
|
createFolderIfNeeded,
|
|
30
|
-
loadJSON
|
|
30
|
+
loadJSON,
|
|
31
|
+
shouldSaveToFile
|
|
31
32
|
} from './util.js';
|
|
32
33
|
|
|
33
34
|
import packageConfig from '../../package.json' with { type: 'json' };
|
|
@@ -188,7 +189,7 @@ async function crawlSpec(spec, crawlOptions) {
|
|
|
188
189
|
*/
|
|
189
190
|
async function saveSpecResults(spec, settings) {
|
|
190
191
|
settings = settings || {};
|
|
191
|
-
if (!settings
|
|
192
|
+
if (!shouldSaveToFile(settings)) {
|
|
192
193
|
return spec;
|
|
193
194
|
}
|
|
194
195
|
|
|
@@ -337,16 +338,78 @@ async function saveSpecResults(spec, settings) {
|
|
|
337
338
|
|
|
338
339
|
|
|
339
340
|
/**
|
|
340
|
-
*
|
|
341
|
-
*
|
|
341
|
+
* Helper function that takes a list of specs as inputs and expands them to an
|
|
342
|
+
* object suitable for crawling, with as much information as possible.
|
|
342
343
|
*
|
|
343
344
|
* @function
|
|
344
|
-
* @param {Array(String)}
|
|
345
|
+
* @param {Array(String|Object)} list A list of "specs", where each spec can be
|
|
346
|
+
* a string that represents a spec's shortname, series shortname or URL, or an
|
|
347
|
+
* object that already contains appropriate information.
|
|
348
|
+
* @return {Array(Object)} An array of spec objects. Note: When a spec was
|
|
349
|
+
* already described through an object, the function returns the object as-is
|
|
350
|
+
* and makes no attempt at validating it.
|
|
351
|
+
*/
|
|
352
|
+
function prepareListOfSpecs(list) {
|
|
353
|
+
return list.map(spec => {
|
|
354
|
+
if (typeof spec !== 'string') {
|
|
355
|
+
return spec;
|
|
356
|
+
}
|
|
357
|
+
let match = specs.find(s => s.url === spec || s.shortname === spec);
|
|
358
|
+
if (!match) {
|
|
359
|
+
match = specs.find(s => s.series &&
|
|
360
|
+
s.series.shortname === spec &&
|
|
361
|
+
s.series.currentSpecification === s.shortname);
|
|
362
|
+
}
|
|
363
|
+
if (match) {
|
|
364
|
+
return match;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
let url = null;
|
|
368
|
+
try {
|
|
369
|
+
url = (new URL(spec)).href;
|
|
370
|
+
}
|
|
371
|
+
catch {
|
|
372
|
+
if (spec.endsWith('.html')) {
|
|
373
|
+
url = (new URL(spec, `file://${process.cwd()}/`)).href;
|
|
374
|
+
}
|
|
375
|
+
else {
|
|
376
|
+
const msg = `Spec ID "${spec}" can neither be interpreted as a URL, a valid shortname or a relative path to an HTML file`;
|
|
377
|
+
throw new Error(msg);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
return {
|
|
381
|
+
url,
|
|
382
|
+
nightly: { url },
|
|
383
|
+
shortname: spec.replace(/[:\/\\\.]/g, ''),
|
|
384
|
+
series: {
|
|
385
|
+
shortname: spec.replace(/[:\/\\\.]/g, ''),
|
|
386
|
+
}
|
|
387
|
+
};
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Crawl the provided list of specifications and return an array with the crawl
|
|
394
|
+
* results.
|
|
395
|
+
*
|
|
396
|
+
* Crawl options may be specified as a second parameter. The function ignores
|
|
397
|
+
* options that affect the output such as `output`, `markdown` or `terse`. The
|
|
398
|
+
* function also does not run post-processing modules that apply at the "crawl"
|
|
399
|
+
* level.
|
|
400
|
+
*
|
|
401
|
+
* @function
|
|
402
|
+
* @param {Array(String|Object)} speclist List of specs to crawl, where each
|
|
403
|
+
* spec can be a string that represents a spec's shortname, series shortname or
|
|
404
|
+
* URL, or an object that already contains appropriate information.
|
|
345
405
|
* @param {Object} crawlOptions Crawl options
|
|
346
|
-
* @return {Promise<Array(Object)} The promise to get an array
|
|
347
|
-
*
|
|
406
|
+
* @return {Promise<Array(Object)} The promise to get an array with crawl
|
|
407
|
+
* results.
|
|
348
408
|
*/
|
|
349
409
|
async function crawlList(speclist, crawlOptions) {
|
|
410
|
+
// Expand the list of specs to spec objects suitable for crawling
|
|
411
|
+
speclist = prepareListOfSpecs(speclist);
|
|
412
|
+
|
|
350
413
|
// Make a shallow copy of crawl options object since we're going
|
|
351
414
|
// to modify properties in place
|
|
352
415
|
crawlOptions = Object.assign({speclist}, crawlOptions);
|
|
@@ -420,6 +483,25 @@ async function crawlList(speclist, crawlOptions) {
|
|
|
420
483
|
await teardownBrowser();
|
|
421
484
|
}
|
|
422
485
|
|
|
486
|
+
// Merge extracts per series when necessary (CSS/IDL extracts)
|
|
487
|
+
for (const mod of crawlOptions.modules) {
|
|
488
|
+
if (mod.extractsPerSeries) {
|
|
489
|
+
await adjustExtractsPerSeries(results, mod.property, crawlOptions);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
for (const mod of crawlOptions.post ?? []) {
|
|
493
|
+
if (postProcessor.extractsPerSeries(mod)) {
|
|
494
|
+
await adjustExtractsPerSeries(results, mod.property, crawlOptions);
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
// Attach a crawl summary in Markdown if so requested
|
|
499
|
+
if (crawlOptions.markdown || crawlOptions.summary) {
|
|
500
|
+
for (const res of results) {
|
|
501
|
+
res.crawlSummary = await generateSpecReport(res);
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
|
|
423
505
|
return results;
|
|
424
506
|
}
|
|
425
507
|
|
|
@@ -435,7 +517,7 @@ async function crawlList(speclist, crawlOptions) {
|
|
|
435
517
|
* @return {Promise(Array)} The promise to get an updated crawl results array
|
|
436
518
|
*/
|
|
437
519
|
async function adjustExtractsPerSeries(data, property, settings) {
|
|
438
|
-
if (!settings
|
|
520
|
+
if (!shouldSaveToFile(settings)) {
|
|
439
521
|
return data;
|
|
440
522
|
}
|
|
441
523
|
|
|
@@ -487,7 +569,7 @@ async function adjustExtractsPerSeries(data, property, settings) {
|
|
|
487
569
|
* @return {Promise<void>} The promise to have saved the data
|
|
488
570
|
*/
|
|
489
571
|
async function saveResults(contents, settings) {
|
|
490
|
-
if (!settings
|
|
572
|
+
if (!shouldSaveToFile(settings)) {
|
|
491
573
|
return;
|
|
492
574
|
}
|
|
493
575
|
const indexFilename = path.join(settings.output, 'index.json');
|
|
@@ -496,62 +578,38 @@ async function saveResults(contents, settings) {
|
|
|
496
578
|
|
|
497
579
|
|
|
498
580
|
/**
|
|
499
|
-
*
|
|
500
|
-
*
|
|
581
|
+
* Run a crawl given a set of options.
|
|
582
|
+
*
|
|
583
|
+
* The set of options matches those defined in the CLI. The function crawls all
|
|
584
|
+
* specs by default in particular.
|
|
585
|
+
*
|
|
586
|
+
* If the `output` option is not set, the function outputs a JSON dump of the
|
|
587
|
+
* crawl results to the console (or a report in Markdown if the `markdown`
|
|
588
|
+
* option is set) and does not return anything to the caller.
|
|
589
|
+
*
|
|
590
|
+
* If the `output` option is set to the magic value `{return}`, the function
|
|
591
|
+
* outputs nothing but returns an object that represents the crawl results,
|
|
592
|
+
* with the actual results per spec stored in a `results` property.
|
|
593
|
+
*
|
|
594
|
+
* If the `output` option is set to any other value, the function interprets it
|
|
595
|
+
* as a folder, creates subfolders and files with crawl results in that folder,
|
|
596
|
+
* with a root `index.json` entry point, and does not return anything.
|
|
501
597
|
*
|
|
502
598
|
* @function
|
|
503
|
-
* @param {Object} options Crawl options. Possible options
|
|
599
|
+
* @param {Object} options Crawl options. Possible options include:
|
|
504
600
|
* publishedVersion, debug, output, terse, modules and specs.
|
|
505
601
|
* See CLI help (node reffy.js --help) for details.
|
|
506
|
-
* @return {Promise<void>} The promise that the crawl will have been
|
|
602
|
+
* @return {Promise<void|Object>} The promise that the crawl will have been
|
|
603
|
+
* made along with the index of crawl results if the `output` option was set
|
|
604
|
+
* to the specific value `{return}`.
|
|
507
605
|
*/
|
|
508
606
|
async function crawlSpecs(options) {
|
|
509
|
-
function prepareListOfSpecs(list) {
|
|
510
|
-
return list.map(spec => {
|
|
511
|
-
if (typeof spec !== 'string') {
|
|
512
|
-
return spec;
|
|
513
|
-
}
|
|
514
|
-
let match = specs.find(s => s.url === spec || s.shortname === spec);
|
|
515
|
-
if (!match) {
|
|
516
|
-
match = specs.find(s => s.series &&
|
|
517
|
-
s.series.shortname === spec &&
|
|
518
|
-
s.series.currentSpecification === s.shortname);
|
|
519
|
-
}
|
|
520
|
-
if (match) {
|
|
521
|
-
return match;
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
let url = null;
|
|
525
|
-
try {
|
|
526
|
-
url = (new URL(spec)).href;
|
|
527
|
-
}
|
|
528
|
-
catch {
|
|
529
|
-
if (spec.endsWith('.html')) {
|
|
530
|
-
url = (new URL(spec, `file://${process.cwd()}/`)).href;
|
|
531
|
-
}
|
|
532
|
-
else {
|
|
533
|
-
const msg = `Spec ID "${spec}" can neither be interpreted as a URL, a valid shortname or a relative path to an HTML file`;
|
|
534
|
-
throw new Error(msg);
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
return {
|
|
538
|
-
url,
|
|
539
|
-
nightly: { url },
|
|
540
|
-
shortname: spec.replace(/[:\/\\\.]/g, ''),
|
|
541
|
-
series: {
|
|
542
|
-
shortname: spec.replace(/[:\/\\\.]/g, ''),
|
|
543
|
-
}
|
|
544
|
-
};
|
|
545
|
-
});
|
|
546
|
-
}
|
|
547
|
-
|
|
548
607
|
const crawlIndex = options?.useCrawl ?
|
|
549
608
|
await loadJSON(path.join(options.useCrawl, 'index.json')) :
|
|
550
609
|
null;
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
options?.specs
|
|
554
|
-
specs;
|
|
610
|
+
const requestedList = crawlIndex ?
|
|
611
|
+
crawlIndex.results :
|
|
612
|
+
(options?.specs ?? specs);
|
|
555
613
|
|
|
556
614
|
// Make a shallow copy of passed options parameter and expand modules
|
|
557
615
|
// in place.
|
|
@@ -559,20 +617,6 @@ async function crawlSpecs(options) {
|
|
|
559
617
|
options.modules = expandBrowserModules(options.modules);
|
|
560
618
|
|
|
561
619
|
return crawlList(requestedList, options)
|
|
562
|
-
.then(async results => {
|
|
563
|
-
// Merge extracts per series when necessary (CSS/IDL extracts)
|
|
564
|
-
for (const mod of options.modules) {
|
|
565
|
-
if (mod.extractsPerSeries) {
|
|
566
|
-
await adjustExtractsPerSeries(results, mod.property, options);
|
|
567
|
-
}
|
|
568
|
-
}
|
|
569
|
-
for (const mod of options.post ?? []) {
|
|
570
|
-
if (postProcessor.extractsPerSeries(mod)) {
|
|
571
|
-
await adjustExtractsPerSeries(results, mod.property, options);
|
|
572
|
-
}
|
|
573
|
-
}
|
|
574
|
-
return results;
|
|
575
|
-
})
|
|
576
620
|
.then(async results => {
|
|
577
621
|
// Create and return a crawl index out of the results, to allow
|
|
578
622
|
// post-processing modules to run.
|
|
@@ -592,13 +636,6 @@ async function crawlSpecs(options) {
|
|
|
592
636
|
errors: results.filter(spec => !!spec.error).length
|
|
593
637
|
};
|
|
594
638
|
|
|
595
|
-
// Attach a crawl summary in Markdown if so requested
|
|
596
|
-
if (options.markdown || options.summary) {
|
|
597
|
-
for (const res of results) {
|
|
598
|
-
res.crawlSummary = await generateSpecReport(res);
|
|
599
|
-
}
|
|
600
|
-
}
|
|
601
|
-
|
|
602
639
|
// Return results to the console or save crawl results to an
|
|
603
640
|
// index.json file
|
|
604
641
|
if (options.terse) {
|
|
@@ -625,7 +662,7 @@ async function crawlSpecs(options) {
|
|
|
625
662
|
else if (!options.output) {
|
|
626
663
|
console.log(JSON.stringify(results, null, 2));
|
|
627
664
|
}
|
|
628
|
-
else {
|
|
665
|
+
else if (shouldSaveToFile(options)) {
|
|
629
666
|
await saveResults(index, options);
|
|
630
667
|
}
|
|
631
668
|
return index;
|
|
@@ -636,7 +673,7 @@ async function crawlSpecs(options) {
|
|
|
636
673
|
if (!postProcessor.appliesAtLevel(mod, 'crawl')) {
|
|
637
674
|
continue;
|
|
638
675
|
}
|
|
639
|
-
const crawlResults = options
|
|
676
|
+
const crawlResults = shouldSaveToFile(options) ?
|
|
640
677
|
await expandCrawlResult(
|
|
641
678
|
crawlIndex, options.output, postProcessor.dependsOn(mod)) :
|
|
642
679
|
crawlIndex;
|
|
@@ -647,25 +684,66 @@ async function crawlSpecs(options) {
|
|
|
647
684
|
console.log();
|
|
648
685
|
console.log(JSON.stringify(result, null, 2));
|
|
649
686
|
}
|
|
687
|
+
else if (!shouldSaveToFile(options)) {
|
|
688
|
+
// Attach the post-processing result to the index of the
|
|
689
|
+
// crawl results.
|
|
690
|
+
crawlIndex.post = crawlIndex.post ?? [];
|
|
691
|
+
crawlIndex.post.push({
|
|
692
|
+
mod: postProcessor.getProperty(mod),
|
|
693
|
+
result
|
|
694
|
+
});
|
|
695
|
+
}
|
|
650
696
|
}
|
|
697
|
+
|
|
698
|
+
// Function does not return anything if it already reported the
|
|
699
|
+
// results to the console or files. It returns the index of the
|
|
700
|
+
// crawl results otherwise.
|
|
701
|
+
if (!options.output || shouldSaveToFile(options)) {
|
|
702
|
+
return;
|
|
703
|
+
}
|
|
704
|
+
return crawlIndex;
|
|
651
705
|
});
|
|
652
706
|
}
|
|
653
707
|
|
|
654
708
|
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
709
|
+
/**
|
|
710
|
+
* Crawl a set of specs according to the given set of crawl options.
|
|
711
|
+
*
|
|
712
|
+
* The function behaves differently depending on the parameters it receives.
|
|
713
|
+
*
|
|
714
|
+
* If it receives no parameter, the function behaves as it were called with a
|
|
715
|
+
* single empty object as parameter.
|
|
716
|
+
*
|
|
717
|
+
* If it receives a single object as parameter, this object sets crawl options
|
|
718
|
+
* (essentially matching CLI options). What the function outputs or returns
|
|
719
|
+
* depends on the `output` option. If `output` is not set, the function outputs
|
|
720
|
+
* a JSON dump of the index of the crawl results to the console and returns
|
|
721
|
+
* nothing to the caller. If `output` is set to the "magic" value `{return}`,
|
|
722
|
+
* the function does not output anything but returns the index of the crawl
|
|
723
|
+
* results which a caller may then process in any way they wish. If `output` is
|
|
724
|
+
* set to any other value, it defines a folder, the function saves crawl
|
|
725
|
+
* results as folders and files in that folder and returns nothing.
|
|
726
|
+
*
|
|
727
|
+
* If it receives an array as first parameter, the array defines the set of
|
|
728
|
+
* specs that are to be crawled (each spec may be a string representing the
|
|
729
|
+
* spec's shortname, series shortname, or URL; or a spec object). The second
|
|
730
|
+
* parameter, if present, defines additional crawl options (same as above,
|
|
731
|
+
* except the `specs` option should not be set). The function returns an
|
|
732
|
+
* array of crawl results to the caller.
|
|
733
|
+
*
|
|
734
|
+
* Note the function does not apply post-processing modules that run at the
|
|
735
|
+
* "crawl" level when it receives an array as first parameter. It will also
|
|
736
|
+
* ignore crawl options that control the output such as `output`, `markdown`
|
|
737
|
+
* and `terse`.
|
|
738
|
+
*/
|
|
665
739
|
function crawl(...args) {
|
|
666
740
|
return Array.isArray(args[0]) ?
|
|
667
741
|
crawlList.apply(this, args) :
|
|
668
742
|
crawlSpecs.apply(this, args);
|
|
669
743
|
}
|
|
670
744
|
|
|
745
|
+
|
|
746
|
+
/**************************************************
|
|
747
|
+
Export crawl method for use as module
|
|
748
|
+
**************************************************/
|
|
671
749
|
export { crawl as crawlSpecs };
|
package/src/lib/util.js
CHANGED
|
@@ -1137,6 +1137,21 @@ async function getSchemaValidationFunction(schemaName) {
|
|
|
1137
1137
|
};
|
|
1138
1138
|
}
|
|
1139
1139
|
|
|
1140
|
+
|
|
1141
|
+
/**
|
|
1142
|
+
* Return true if the crawler should save results to files given the crawl
|
|
1143
|
+
* options.
|
|
1144
|
+
*
|
|
1145
|
+
* @function
|
|
1146
|
+
* @param {Object} crawlOptions Crawl options (optional)
|
|
1147
|
+
* @return {Boolean} true when the crawler should save the results to files,
|
|
1148
|
+
* false otherwise.
|
|
1149
|
+
*/
|
|
1150
|
+
function shouldSaveToFile(crawlOptions) {
|
|
1151
|
+
return crawlOptions?.output && crawlOptions.output !== '{return}';
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1154
|
+
|
|
1140
1155
|
export {
|
|
1141
1156
|
fetch,
|
|
1142
1157
|
expandBrowserModules,
|
|
@@ -1151,5 +1166,6 @@ export {
|
|
|
1151
1166
|
createFolderIfNeeded,
|
|
1152
1167
|
getInterfaceTreeInfo,
|
|
1153
1168
|
getSchemaValidationFunction,
|
|
1154
|
-
loadJSON
|
|
1169
|
+
loadJSON,
|
|
1170
|
+
shouldSaveToFile
|
|
1155
1171
|
};
|
|
@@ -14,7 +14,8 @@ import {
|
|
|
14
14
|
getExpectedDfnFromIdlDesc } from '../cli/check-missing-dfns.js';
|
|
15
15
|
import {
|
|
16
16
|
isLatestLevelThatPasses,
|
|
17
|
-
createFolderIfNeeded
|
|
17
|
+
createFolderIfNeeded,
|
|
18
|
+
shouldSaveToFile } from '../lib/util.js';
|
|
18
19
|
|
|
19
20
|
|
|
20
21
|
/**
|
|
@@ -379,7 +380,7 @@ async function generateIdlNames(crawl, options) {
|
|
|
379
380
|
* @param {Object} options Crawl options ("output" will be used)
|
|
380
381
|
*/
|
|
381
382
|
async function saveIdlNames(names, options) {
|
|
382
|
-
if (!options
|
|
383
|
+
if (!shouldSaveToFile(options)) {
|
|
383
384
|
return;
|
|
384
385
|
}
|
|
385
386
|
|