@@ -63,8 +63,6 @@ import kebabCase from 'lodash/kebabCase';
63
63
import { processMarkdownFile , processApiFile } from '@mui/internal-scripts/generate-llms-txt' ;
64
64
import { ComponentInfo , ProjectSettings } from '@mui-internal/api-docs-builder' ;
65
65
import { getHeaders } from '@mui/internal-markdown' ;
66
- import { fixPathname } from '@mui-internal/api-docs-builder/buildApiUtils' ;
67
- import replaceUrl from '@mui-internal/api-docs-builder/utils/replaceUrl' ;
68
66
import findComponents from '@mui-internal/api-docs-builder/utils/findComponents' ;
69
67
import findPagesMarkdown from '@mui-internal/api-docs-builder/utils/findPagesMarkdown' ;
70
68
@@ -153,21 +151,26 @@ async function findComponentsToProcess(
153
151
continue ;
154
152
}
155
153
156
- // Get the markdown file path from the first demo
157
- const firstDemo = demos [ 0 ] ;
158
- const markdownPath = firstDemo ? firstDemo . filePath : undefined ;
159
-
160
154
// Get API JSON path
161
155
const apiJsonPath = path . join (
162
156
componentInfo . apiPagesDirectory ,
163
157
`${ path . basename ( componentInfo . apiPathname ) } .json` ,
164
158
) ;
165
159
160
+ const primaryDemo = demos . find (
161
+ ( demo ) =>
162
+ demo . demoPathname . toLowerCase ( ) . includes ( `/${ kebabCase ( componentInfo . name ) } /` ) ||
163
+ demo . demoPathname . toLowerCase ( ) . includes ( `/react-${ kebabCase ( componentInfo . name ) } /` ) ,
164
+ ) ;
165
+
166
+ const demoToUse = primaryDemo || demos [ 0 ] ;
167
+ const markdownPathToUse = demoToUse ? demoToUse . filePath : undefined ;
168
+
166
169
components . push ( {
167
170
name : componentInfo . name ,
168
171
componentInfo,
169
- demos,
170
- markdownPath,
172
+ demos : primaryDemo ? [ primaryDemo ] : demos ,
173
+ markdownPath : markdownPathToUse ,
171
174
apiJsonPath : fs . existsSync ( apiJsonPath ) ? apiJsonPath : undefined ,
172
175
} ) ;
173
176
} catch ( error ) {
@@ -219,38 +222,46 @@ function extractMarkdownInfo(markdownPath: string): { title: string; description
219
222
* Find all non-component markdown files from specified folders
220
223
*/
221
224
function findNonComponentMarkdownFiles (
222
- folders : string [ ] ,
225
+ projectSettings : ProjectSettings ,
223
226
grep : RegExp | null ,
224
227
) : Array < { markdownPath : string ; outputPath : string } > {
228
+ if ( ! projectSettings . pagesManifestPath ) {
229
+ return [ ] ;
230
+ }
231
+ const pagesContent = fs . readFileSync ( projectSettings . pagesManifestPath , 'utf-8' ) ;
232
+
233
+ // Extract all pathname strings using regex
234
+ const pathnameRegex = / p a t h n a m e : \s * [ ' " ` ] ( [ ^ ' " ` ] + ) [ ' " ` ] / g;
235
+ const matches = Array . from ( pagesContent . matchAll ( pathnameRegex ) ) ;
236
+
225
237
// Get all markdown files using the existing findPagesMarkdown utility
226
238
const allMarkdownFiles = findPagesMarkdown ( ) ;
227
239
228
240
const files : Array < { markdownPath : string ; outputPath : string } > = [ ] ;
229
241
230
- for ( const page of allMarkdownFiles ) {
231
- // Check if the page belongs to one of the specified folders
232
- const belongsToFolder = folders . some ( ( folder ) => page . pathname . startsWith ( `/${ folder } ` ) ) ;
233
- if ( ! belongsToFolder ) {
234
- continue ;
235
- }
236
-
242
+ for ( const match of matches ) {
243
+ const pathname = match [ 1 ] ;
244
+ const parsedPathname = pathname
245
+ . replace ( '/material-ui/' , '/material/' )
246
+ . replace ( '/react-' , '/components/' ) ;
237
247
// Apply grep filter if specified
238
248
if ( grep ) {
239
- const fileName = path . basename ( page . filename ) ;
240
- if ( ! grep . test ( fileName ) && ! grep . test ( page . pathname ) ) {
249
+ const fileName = path . basename ( parsedPathname ) ;
250
+ if ( ! grep . test ( fileName ) && ! grep . test ( parsedPathname ) ) {
241
251
continue ;
242
252
}
243
253
}
244
-
245
- // Apply fixPathname first, then replaceUrl to get the proper output structure (like components)
246
- const afterFixPathname = fixPathname ( page . pathname ) ;
247
- const fixedPathname = replaceUrl ( afterFixPathname , '/material-ui/' ) ;
248
- const outputPath = `${ fixedPathname . replace ( / ^ \/ / , '' ) . replace ( / \/ $ / , '' ) } .md` ;
249
-
250
- files . push ( {
251
- markdownPath : page . filename ,
252
- outputPath,
253
- } ) ;
254
+ // Filter out external links and special patterns
255
+ if ( pathname . startsWith ( '/material-ui/' ) ) {
256
+ const page = allMarkdownFiles . find ( ( p ) => p . pathname === parsedPathname ) ;
257
+
258
+ if ( page ) {
259
+ files . push ( {
260
+ markdownPath : page . filename ,
261
+ outputPath : `${ pathname . startsWith ( '/' ) ? pathname . slice ( 1 ) : pathname } .md` ,
262
+ } ) ;
263
+ }
264
+ }
254
265
}
255
266
256
267
return files ;
@@ -427,15 +438,12 @@ async function buildLlmsDocs(argv: ArgumentsCamelCase<CommandOptions>): Promise<
427
438
// Found ${components.length} components to process
428
439
429
440
// Find non-component markdown files if specified in project settings
430
- let nonComponentFiles : Array < { markdownPath : string ; outputPath : string } > = [ ] ;
431
441
const nonComponentFolders = ( projectSettings as any ) . nonComponentFolders ;
432
- if ( nonComponentFolders && nonComponentFolders . length > 0 ) {
433
- nonComponentFiles = findNonComponentMarkdownFiles ( nonComponentFolders , grep ) ;
434
- // Found ${nonComponentFiles.length} non-component markdown files to process
435
- }
442
+ const nonComponentFiles = findNonComponentMarkdownFiles ( projectSettings , grep ) ;
436
443
437
444
// Track generated files for llms.txt
438
445
const generatedFiles : GeneratedFile [ ] = [ ] ;
446
+ const generatedComponentRecord : Record < string , boolean > = { } ;
439
447
440
448
// Process each component
441
449
let processedCount = 0 ;
@@ -478,6 +486,7 @@ async function buildLlmsDocs(argv: ArgumentsCamelCase<CommandOptions>): Promise<
478
486
originalMarkdownPath : component . markdownPath ,
479
487
category : 'components' ,
480
488
} ) ;
489
+ generatedComponentRecord [ outputFileName ] = true ;
481
490
}
482
491
}
483
492
} catch ( error ) {
@@ -488,6 +497,10 @@ async function buildLlmsDocs(argv: ArgumentsCamelCase<CommandOptions>): Promise<
488
497
// Process non-component markdown files
489
498
for ( const file of nonComponentFiles ) {
490
499
try {
500
+ if ( generatedComponentRecord [ file . outputPath ] ) {
501
+ // Skip files that have already been generated as component docs
502
+ continue ;
503
+ }
491
504
// Processing non-component file: ${path.relative(process.cwd(), file.markdownPath)}
492
505
493
506
// Process the markdown file with demo replacement
@@ -560,7 +573,9 @@ async function buildLlmsDocs(argv: ArgumentsCamelCase<CommandOptions>): Promise<
560
573
projectName = dirName . charAt ( 0 ) . toUpperCase ( ) + dirName . slice ( 1 ) ;
561
574
}
562
575
563
- const llmsContent = generateLlmsTxt ( files , projectName , dirName , ORIGIN ) ;
576
+ const llmsContent = generateLlmsTxt ( files , projectName , dirName , ORIGIN )
577
+ . replace ( / U i / g, 'UI' )
578
+ . replace ( / A p i / g, 'API' ) ;
564
579
const llmsPath = path . join ( outputDir , dirName , 'llms.txt' ) ;
565
580
566
581
// Ensure directory exists
0 commit comments