2
2
3
3
import { access , constants , readFile } from 'node:fs/promises' ;
4
4
import { resolve } from 'node:path' ;
5
+ import { fileURLToPath } from 'node:url' ;
6
+ import { parseArgs } from 'node:util' ;
5
7
6
8
import Ajv , { ValidateFunction } from 'ajv' ;
7
- import type { fromHtml as FromHtmlFunction } from 'hast-util-from-html' ;
8
- import type { HTML , Heading } from 'mdast' ;
9
- import type { fromMarkdown as FromMarkdownFunction } from 'mdast-util-from-markdown' ;
10
- import * as minimist from 'minimist' ;
11
- import type { Literal , Node } from 'unist' ;
12
- import type { visit as VisitFunction } from 'unist-util-visit' ;
9
+ import { fromHtml } from 'hast-util-from-html' ;
10
+ import { fromMarkdown } from 'mdast-util-from-markdown' ;
11
+ import { visit } from 'unist-util-visit' ;
13
12
import { URI } from 'vscode-uri' ;
14
13
import { parseDocument , visit as yamlVisit } from 'yaml' ;
15
14
16
- import { dynamicImport } from '../lib/helpers' ;
17
- import { DocsWorkspace } from '../lib/markdown' ;
15
+ import type { HTML , Heading } from 'mdast' ;
16
+ import type { Literal , Node } from 'unist' ;
17
+
18
+ import { DocsWorkspace } from '../lib/markdown.js' ;
18
19
19
20
// "<any char>: <match group>"
20
21
const possibleStringRegex = / ^ [ \S ] + ?: * ?( \S [ \S ] + ?) $ / gm;
@@ -35,19 +36,19 @@ interface ApiHistory {
35
36
36
37
interface Options {
37
38
// Check if the API history block is preceded by a heading
38
- checkPlacement : boolean ;
39
+ checkPlacement ? : boolean ;
39
40
// Check if the 'breaking-changes-header' heading id's in the API history block exist in the breaking changes file at this filepath
40
- breakingChangesFile : string ;
41
+ breakingChangesFile ? : string ;
41
42
// Check if the API history block contains strings that might cause issues when parsing the YAML
42
- checkStrings : boolean ;
43
+ checkStrings ? : boolean ;
43
44
// Check if the API history block contains descriptions that aren't surrounded by double quotation marks
44
- checkDescriptions: boolean ;
45
+ checkDescriptions ? : boolean ;
45
46
// Check if the API history block contains comments
46
- disallowComments: boolean ;
47
+ disallowComments ? : boolean ;
47
48
// Array of glob patterns to ignore when processing files
48
- ignoreGlobs: string [ ] ;
49
+ ignoreGlobs ? : string [ ] ;
49
50
// Check if the API history block's YAML adheres to the JSON schema at this filepath
50
- schema: string ;
51
+ schema ? : string ;
51
52
52
53
// TODO: Implement this when GH_TOKEN isn't needed to fetch PR release versions anymore
53
54
// checkPullRequestLinks: boolean;
@@ -65,12 +66,6 @@ function isHTML(node: Node): node is HTML {
65
66
export async function findPossibleApiHistoryBlocks (
66
67
content : string ,
67
68
) : Promise < PossibleHistoryBlock [ ] > {
68
- const { fromMarkdown } = ( await dynamicImport ( 'mdast-util-from-markdown' ) ) as {
69
- fromMarkdown : typeof FromMarkdownFunction ;
70
- } ;
71
- const { visit } = ( await dynamicImport ( 'unist-util-visit' ) ) as {
72
- visit : typeof VisitFunction ;
73
- } ;
74
69
const tree = fromMarkdown ( content ) ;
75
70
const codeBlocks : PossibleHistoryBlock [ ] = [ ] ;
76
71
@@ -119,13 +114,6 @@ async function main(
119
114
let warningCounter = 0 ;
120
115
121
116
try {
122
- const { fromHtml } = ( await dynamicImport ( 'hast-util-from-html' ) ) as {
123
- fromHtml : typeof FromHtmlFunction ;
124
- } ;
125
- const { fromMarkdown } = ( await dynamicImport ( 'mdast-util-from-markdown' ) ) as {
126
- fromMarkdown : typeof FromMarkdownFunction ;
127
- } ;
128
-
129
117
const workspace = new DocsWorkspace ( workspaceRoot , globs , ignoreGlobs ) ;
130
118
131
119
let validateAgainstSchema : ValidateFunction < ApiHistory > | null = null ;
@@ -407,47 +395,71 @@ async function main(
407
395
}
408
396
409
397
function parseCommandLine ( ) {
410
- const showUsage = ( arg ? : string ) : boolean => {
411
- if ( ! arg || arg . startsWith ( '-' ) ) {
412
- console . log (
413
- 'Usage: lint-roller-markdown-api-history [--root <dir>] <globs>' +
414
- ' [-h|--help]' +
415
- ' [--check-placement] [--breaking-changes-file <path>] [--check-strings] [--check-descriptions] [--disallow-comments]' +
416
- ' [--schema <path>]' +
417
- ' [--ignore <globs>] [--ignore-path <path>]' ,
418
- ) ;
419
- process . exit ( 1 ) ;
420
- }
421
-
422
- return true ;
398
+ const showUsage = ( ) : never => {
399
+ console . log (
400
+ 'Usage: lint-roller-markdown-api-history [--root <dir>] <globs>' +
401
+ ' [-h|--help]' +
402
+ ' [--check-placement] [--breaking-changes-file <path>] [--check-strings] [--check-descriptions] [--disallow-comments]' +
403
+ ' [--schema <path>]' +
404
+ ' [--ignore <globs>] [--ignore-path <path>]' ,
405
+ ) ;
406
+ process . exit ( 1 ) ;
423
407
} ;
424
408
425
- const opts = minimist ( process . argv . slice ( 2 ) , {
426
- boolean : [
427
- 'help' ,
428
- 'check-placement' ,
429
- 'check-strings' ,
430
- 'check-descriptions' ,
431
- 'disallow-comments' ,
432
- ] ,
433
- string : [ 'root' , 'ignore' , 'ignore-path' , 'schema' , 'breaking-changes-file' ] ,
434
- unknown : showUsage ,
435
- default : {
436
- 'check-placement' : true ,
437
- 'check-strings' : true ,
438
- 'check-descriptions' : true ,
439
- 'disallow-comments' : true ,
440
- } ,
441
- } ) ;
409
+ try {
410
+ const opts = parseArgs ( {
411
+ allowNegative : true ,
412
+ allowPositionals : true ,
413
+ options : {
414
+ 'check-placement' : {
415
+ type : 'boolean' ,
416
+ default : true ,
417
+ } ,
418
+ 'check-strings' : {
419
+ type : 'boolean' ,
420
+ default : true ,
421
+ } ,
422
+ 'check-descriptions' : {
423
+ type : 'boolean' ,
424
+ default : true ,
425
+ } ,
426
+ 'disallow-comments' : {
427
+ type : 'boolean' ,
428
+ default : true ,
429
+ } ,
430
+ root : {
431
+ type : 'string' ,
432
+ } ,
433
+ ignore : {
434
+ type : 'string' ,
435
+ multiple : true ,
436
+ } ,
437
+ 'ignore-path' : {
438
+ type : 'string' ,
439
+ } ,
440
+ schema : {
441
+ type : 'string' ,
442
+ } ,
443
+ 'breaking-changes-file' : {
444
+ type : 'string' ,
445
+ } ,
446
+ help : {
447
+ type : 'boolean' ,
448
+ } ,
449
+ } ,
450
+ } ) ;
442
451
443
- if ( opts . help || ! opts . _ . length ) showUsage ( ) ;
452
+ if ( opts . values . help || ! opts . positionals . length ) return showUsage ( ) ;
444
453
445
- return opts ;
454
+ return opts ;
455
+ } catch {
456
+ return showUsage ( ) ;
457
+ }
446
458
}
447
459
448
460
async function init ( ) {
449
461
try {
450
- const opts = parseCommandLine ( ) ;
462
+ const { values : opts , positionals } = parseCommandLine ( ) ;
451
463
452
464
if ( ! opts . root ) {
453
465
opts . root = '. ';
@@ -477,7 +489,7 @@ async function init() {
477
489
478
490
const { historyBlockCounter , documentCounter , errorCounter , warningCounter } = await main (
479
491
resolve ( process . cwd ( ) , opts . root ) ,
480
- opts . _ ,
492
+ positionals ,
481
493
{
482
494
checkPlacement : opts [ 'check-placement' ] ,
483
495
breakingChangesFile : opts [ 'breaking-changes-file' ] ,
@@ -500,7 +512,7 @@ async function init() {
500
512
}
501
513
}
502
514
503
- if ( require . main === module ) {
515
+ if ( process . argv [ 1 ] === fileURLToPath ( import . meta . url ) ) {
504
516
init ( ) . catch ( ( error ) => {
505
517
console . error ( error ) ;
506
518
process . exit ( 1 ) ;
0 commit comments