@@ -3,63 +3,70 @@ import * as path from 'path';
33import matter from 'gray-matter' ;
44
55const rootDir = path . join ( process . cwd ( ) , 'pages' ) ;
6- const errors : string [ ] = [ ] ;
6+ const warnings : string [ ] = [ ] ;
77
8- interface PageInfo {
9- title : string ;
10- url : string ;
11- }
8+ // ANSI color codes
9+ const YELLOW = '\x1b[33m' ;
10+ const RESET = '\x1b[0m' ;
11+ const BOLD = '\x1b[1m' ;
1212
13- async function getReferencedPages ( breadcrumbContent : string ) : Promise < string [ ] > {
14- // Extract URLs from Card components in the breadcrumb file
15- const cardRegex = / < C a r d [ ^ > ] * h r e f = " ( [ ^ " ] + ) " [ ^ > ] * > / g;
16- const urls : string [ ] = [ ] ;
17- let match ;
18-
19- while ( ( match = cardRegex . exec ( breadcrumbContent ) ) !== null ) {
20- urls . push ( match [ 1 ] ) ;
13+ // Pages to exclude from checks
14+ const excludedPages = [
15+ '400.mdx' ,
16+ '500.mdx' ,
17+ 'index.mdx' ,
18+ '404.mdx'
19+ ] ;
20+
21+ async function getReferencedPagesFromBreadcrumb ( breadcrumbPath : string ) : Promise < string [ ] > {
22+ try {
23+ const content = await fs . readFile ( breadcrumbPath , 'utf-8' ) ;
24+ const cardMatches = content . match ( / < C a r d [ ^ > ] * h r e f = " ( [ ^ " ] + ) " [ ^ > ] * > / g) || [ ] ;
25+ return cardMatches . map ( match => {
26+ const hrefMatch = match . match ( / h r e f = " ( [ ^ " ] + ) " / ) ;
27+ return hrefMatch ? hrefMatch [ 1 ] : '' ;
28+ } ) . filter ( Boolean ) ;
29+ } catch ( error ) {
30+ return [ ] ;
2131 }
22-
23- return urls ;
2432}
2533
2634async function checkDirectory ( dirPath : string ) : Promise < void > {
2735 const entries = await fs . readdir ( dirPath , { withFileTypes : true } ) ;
36+ const currentDir = path . basename ( dirPath ) ;
2837
29- // First, find the breadcrumb file for this directory
30- const dirName = path . basename ( dirPath ) ;
31- const breadcrumbFile = path . join ( dirPath , `${ dirName } .mdx` ) ;
32- let referencedPages : string [ ] = [ ] ;
33-
34- try {
35- const breadcrumbContent = await fs . readFile ( breadcrumbFile , 'utf-8' ) ;
36- referencedPages = await getReferencedPages ( breadcrumbContent ) ;
37- } catch ( error ) {
38- // Only check for missing references if not in root directory
39- if ( dirPath !== rootDir ) {
40- errors . push ( `Missing breadcrumb file for directory: ${ path . relative ( rootDir , dirPath ) } ` ) ;
41- return ;
38+ // Skip the root directory check
39+ if ( dirPath !== rootDir ) {
40+ const breadcrumbPath = path . join ( dirPath , `${ currentDir } .mdx` ) ;
41+ const referencedPages = await getReferencedPagesFromBreadcrumb ( breadcrumbPath ) ;
42+
43+ // Check all .mdx and .md files in the current directory
44+ for ( const entry of entries ) {
45+ if ( entry . isFile ( ) &&
46+ ( entry . name . endsWith ( '.mdx' ) || entry . name . endsWith ( '.md' ) ) &&
47+ ! excludedPages . includes ( entry . name ) &&
48+ entry . name !== `${ currentDir } .mdx` ) {
49+
50+ const pageName = entry . name . replace ( / \. ( m d | m d x ) $ / , '' ) ;
51+ const relativePath = `/stack/${ path . relative ( rootDir , dirPath ) } /${ pageName } ` . replace ( / \\ / g, '/' ) ;
52+
53+ if ( ! referencedPages . includes ( relativePath ) ) {
54+ const humanReadableName = pageName . split ( '-' )
55+ . map ( word => word . charAt ( 0 ) . toUpperCase ( ) + word . slice ( 1 ) )
56+ . join ( ' ' ) ;
57+
58+ warnings . push (
59+ `Page "${ humanReadableName } " at path "${ relativePath } " is not listed in the breadcrumb navigation of ${ currentDir } .mdx`
60+ ) ;
61+ }
62+ }
4263 }
4364 }
4465
45- // Check each entry in the directory
66+ // Process subdirectories
4667 for ( const entry of entries ) {
47- if ( entry . name . startsWith ( '_' ) || entry . name . startsWith ( '.' ) ) continue ;
48-
49- const fullPath = path . join ( dirPath , entry . name ) ;
50-
51- if ( entry . isDirectory ( ) ) {
52- // Recursively check subdirectories
53- await checkDirectory ( fullPath ) ;
54- } else if ( ( entry . name . endsWith ( '.md' ) || entry . name . endsWith ( '.mdx' ) ) &&
55- entry . name !== `${ dirName } .mdx` ) {
56- // Check if this page is referenced in the breadcrumb
57- const relativePath = '/' + path . relative ( rootDir , fullPath )
58- . replace ( / \. ( m d | m d x ) $ / , '' ) ;
59-
60- if ( ! referencedPages . includes ( relativePath ) ) {
61- errors . push ( `Page not referenced in breadcrumb: ${ relativePath } ` ) ;
62- }
68+ if ( entry . isDirectory ( ) && ! entry . name . startsWith ( '_' ) && ! entry . name . startsWith ( '.' ) ) {
69+ await checkDirectory ( path . join ( dirPath , entry . name ) ) ;
6370 }
6471 }
6572}
@@ -68,15 +75,15 @@ async function main() {
6875 try {
6976 await checkDirectory ( rootDir ) ;
7077
71- if ( errors . length > 0 ) {
72- console . error ( 'Breadcrumb check failed:' ) ;
73- errors . forEach ( error => console . error ( ` - ${ error } `) ) ;
78+ if ( warnings . length > 0 ) {
79+ console . log ( ` ${ YELLOW } ${ BOLD } Missing pages in breadcrumb navigation: ${ RESET } ` ) ;
80+ warnings . forEach ( warning => console . log ( ` ${ YELLOW } - ${ warning } ${ RESET } `) ) ;
7481 process . exit ( 1 ) ;
7582 } else {
76- console . log ( 'All pages are properly referenced in breadcrumb navigation.' ) ;
83+ console . log ( 'All pages are properly listed in their respective breadcrumb navigation files .' ) ;
7784 }
7885 } catch ( error ) {
79- console . error ( ' Error checking breadcrumbs:' , error ) ;
86+ console . log ( ` ${ YELLOW } ${ BOLD } Error checking breadcrumbs:${ RESET } ` , error ) ;
8087 process . exit ( 1 ) ;
8188 }
8289}
0 commit comments