Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 39 additions & 48 deletions scripts/generate-llms-txt.js
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -108,15 +131,13 @@ function checkUrl(urlString) {
resolve({
url: urlString,
status: res.statusCode,
is404: res.statusCode === 404,
});
});

req.on('error', error => {
resolve({
url: urlString,
status: 'Error',
is404: false,
error: error.message,
});
});
Expand All @@ -126,7 +147,6 @@ function checkUrl(urlString) {
resolve({
url: urlString,
status: 'Timeout',
is404: false,
});
});

Expand All @@ -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,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand All @@ -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(
Expand Down Expand Up @@ -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))
);
}
Expand Down