@@ -63,8 +63,6 @@ import kebabCase from 'lodash/kebabCase';
6363import { processMarkdownFile , processApiFile } from '@mui/internal-scripts/generate-llms-txt' ;
6464import { ComponentInfo , ProjectSettings } from '@mui-internal/api-docs-builder' ;
6565import { 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' ;
6866import findComponents from '@mui-internal/api-docs-builder/utils/findComponents' ;
6967import findPagesMarkdown from '@mui-internal/api-docs-builder/utils/findPagesMarkdown' ;
7068
@@ -153,21 +151,26 @@ async function findComponentsToProcess(
153151 continue ;
154152 }
155153
156- // Get the markdown file path from the first demo
157- const firstDemo = demos [ 0 ] ;
158- const markdownPath = firstDemo ? firstDemo . filePath : undefined ;
159-
160154 // Get API JSON path
161155 const apiJsonPath = path . join (
162156 componentInfo . apiPagesDirectory ,
163157 `${ path . basename ( componentInfo . apiPathname ) } .json` ,
164158 ) ;
165159
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+
166169 components . push ( {
167170 name : componentInfo . name ,
168171 componentInfo,
169- demos,
170- markdownPath,
172+ demos : primaryDemo ? [ primaryDemo ] : demos ,
173+ markdownPath : markdownPathToUse ,
171174 apiJsonPath : fs . existsSync ( apiJsonPath ) ? apiJsonPath : undefined ,
172175 } ) ;
173176 } catch ( error ) {
@@ -219,38 +222,46 @@ function extractMarkdownInfo(markdownPath: string): { title: string; description
219222 * Find all non-component markdown files from specified folders
220223 */
221224function findNonComponentMarkdownFiles (
222- folders : string [ ] ,
225+ projectSettings : ProjectSettings ,
223226 grep : RegExp | null ,
224227) : 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+
225237 // Get all markdown files using the existing findPagesMarkdown utility
226238 const allMarkdownFiles = findPagesMarkdown ( ) ;
227239
228240 const files : Array < { markdownPath : string ; outputPath : string } > = [ ] ;
229241
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/' ) ;
237247 // Apply grep filter if specified
238248 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 ) ) {
241251 continue ;
242252 }
243253 }
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+ }
254265 }
255266
256267 return files ;
@@ -427,15 +438,12 @@ async function buildLlmsDocs(argv: ArgumentsCamelCase<CommandOptions>): Promise<
427438 // Found ${components.length} components to process
428439
429440 // Find non-component markdown files if specified in project settings
430- let nonComponentFiles : Array < { markdownPath : string ; outputPath : string } > = [ ] ;
431441 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 ) ;
436443
437444 // Track generated files for llms.txt
438445 const generatedFiles : GeneratedFile [ ] = [ ] ;
446+ const generatedComponentRecord : Record < string , boolean > = { } ;
439447
440448 // Process each component
441449 let processedCount = 0 ;
@@ -478,6 +486,7 @@ async function buildLlmsDocs(argv: ArgumentsCamelCase<CommandOptions>): Promise<
478486 originalMarkdownPath : component . markdownPath ,
479487 category : 'components' ,
480488 } ) ;
489+ generatedComponentRecord [ outputFileName ] = true ;
481490 }
482491 }
483492 } catch ( error ) {
@@ -488,6 +497,10 @@ async function buildLlmsDocs(argv: ArgumentsCamelCase<CommandOptions>): Promise<
488497 // Process non-component markdown files
489498 for ( const file of nonComponentFiles ) {
490499 try {
500+ if ( generatedComponentRecord [ file . outputPath ] ) {
501+ // Skip files that have already been generated as component docs
502+ continue ;
503+ }
491504 // Processing non-component file: ${path.relative(process.cwd(), file.markdownPath)}
492505
493506 // Process the markdown file with demo replacement
@@ -560,7 +573,9 @@ async function buildLlmsDocs(argv: ArgumentsCamelCase<CommandOptions>): Promise<
560573 projectName = dirName . charAt ( 0 ) . toUpperCase ( ) + dirName . slice ( 1 ) ;
561574 }
562575
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' ) ;
564579 const llmsPath = path . join ( outputDir , dirName , 'llms.txt' ) ;
565580
566581 // Ensure directory exists
0 commit comments