diff --git a/scripts/generate-llms-txt.js b/scripts/generate-llms-txt.js index f7488671a82..f98000e2da9 100644 --- a/scripts/generate-llms-txt.js +++ b/scripts/generate-llms-txt.js @@ -10,6 +10,29 @@ const DESCRIPTION = 'React Native is a framework for building native apps using React. It lets you create mobile apps using only JavaScript and React.'; const URL_PREFIX = 'https://reactnative.dev'; +const INPUT_FILE_PATHS = [ + { + name: 'sidebars.ts', + docPath: '../docs/', + prefix: '/docs', + }, + { + name: 'sidebarsArchitecture.ts', + docPath: './architecture/', + prefix: '/architecture', + }, + { + name: 'sidebarsCommunity.ts', + docPath: './community/', + prefix: '/community', + }, + { + name: 'sidebarsContributing.ts', + docPath: './contributing/', + prefix: '/contributing', + }, +]; + const SLUG_TO_URL = { 'architecture-overview': 'overview', 'architecture-glossary': 'glossary', @@ -108,7 +131,6 @@ function checkUrl(urlString) { resolve({ url: urlString, status: res.statusCode, - is404: res.statusCode === 404, }); }); @@ -116,7 +138,6 @@ function checkUrl(urlString) { resolve({ url: urlString, status: 'Error', - is404: false, error: error.message, }); }); @@ -126,7 +147,6 @@ function checkUrl(urlString) { resolve({ url: urlString, status: 'Timeout', - is404: false, }); }); @@ -140,11 +160,7 @@ async function processUrls(urls) { for (const urlToCheck of urls) { const result = await checkUrl(urlToCheck); - if ( - result.is404 || - result.status === 'Error' || - result.status === 'Timeout' - ) { + if (result.status !== 200) { unavailableUrls.push({ url: urlToCheck, status: result.status, @@ -176,18 +192,14 @@ function extractMetadataFromMarkdown(filePath) { slug: slugMatch ? slugMatch[1].trim().replace(/^\//, '') : null, }; } - // If no frontmatter found, use the filename - return { - title: filePath.split('/').pop().replace('.md', ''), - slug: null, - }; } catch (error) { console.error(`Error reading file ${filePath}:`, error); - return { - title: filePath.split('/').pop().replace('.md', ''), - slug: null, - }; } + // If no frontmatter found, on an error occurred use the filename + return { + title: filePath.split('/').pop().replace('.md', ''), + slug: null, + }; } // Function to map special cases for file names that don't match the sidebar @@ -283,38 +295,15 @@ function generateMarkdown(sidebarConfig, docPath, prefix, unavailableUrls) { return markdown.replace(/(#+ .*)\n/g, '\n$1\n').replace(/\n(\n)+/g, '\n\n'); } -const inputFilePaths = [ - { - name: 'sidebars.ts', - docPath: '../docs/', - prefix: '/docs', - }, - { - name: 'sidebarsArchitecture.ts', - docPath: './architecture/', - prefix: '/architecture', - }, - { - name: 'sidebarsCommunity.ts', - docPath: './community/', - prefix: '/community', - }, - { - name: 'sidebarsContributing.ts', - docPath: './contributing/', - prefix: '/contributing', - }, -]; - -let output = `# ${TITLE}\n\n`; -output += `> ${DESCRIPTION}\n\n`; -output += `This documentation covers all aspects of using React Native, from installation to advanced usage.\n\n`; - async function generateOutput() { const results = []; const promises = []; - for (const {name, docPath, prefix} of inputFilePaths) { + let output = `# ${TITLE}\n\n`; + output += `> ${DESCRIPTION}\n\n`; + output += `This documentation covers all aspects of using React Native, from installation to advanced usage.\n\n`; + + for (const {name, docPath, prefix} of INPUT_FILE_PATHS) { const sidebarConfig = await convertSidebarConfigToJson(name); if (sidebarConfig) { @@ -324,8 +313,10 @@ async function generateOutput() { .then(result => { if (result.unavailableUrls.length > 0) { console.error( - 'Skipping new pages not existing in production deployment yet:', - result.unavailableUrls.map(entry => entry.url) + 'Skipping new pages not existing in the latest version docs yet:', + result.unavailableUrls.map(entry => + entry.url.replace('/docs', '/docs/next') + ) ); } const markdown = generateMarkdown( @@ -375,7 +366,7 @@ async function generateOutput() { } function isEntryUnavailable(unavailableUrls, docPath) { - return !unavailableUrls.find(entry => + return !!unavailableUrls.find(entry => entry.url.endsWith(docPath.substring(1)) ); }