156 lines
4.9 KiB
TypeScript
156 lines
4.9 KiB
TypeScript
|
import * as plugins from './plugins.js';
|
||
|
import * as paths from './paths.js';
|
||
|
|
||
|
// Function to generate nav links from a folder
|
||
|
export async function generateNavLinks(projectName: string) {
|
||
|
const folderPath = plugins.path.join(paths.docsDir, projectName);
|
||
|
try {
|
||
|
let files = await plugins.fs.readdir(folderPath);
|
||
|
files = files.filter((file) => file.endsWith('.md')); // Only include Markdown files
|
||
|
const navLinks: {
|
||
|
text: string;
|
||
|
link: string;
|
||
|
}[] = [];
|
||
|
for (const file of files) {
|
||
|
const name = plugins.path.basename(file, '.md');
|
||
|
const fileContent = await plugins.fs.readFile(plugins.path.join(folderPath, file), 'utf8');
|
||
|
const smartfmInstance = new plugins.smartfm.Smartfm({
|
||
|
fmType: 'yaml'
|
||
|
});
|
||
|
const frontmatter = smartfmInstance.parse(fileContent);
|
||
|
let title = name;
|
||
|
if (frontmatter.data.title) {
|
||
|
title = frontmatter.data.title;
|
||
|
}
|
||
|
navLinks.push({
|
||
|
text: title,
|
||
|
link: `/${projectName}/${name}`,
|
||
|
});
|
||
|
}
|
||
|
return navLinks;
|
||
|
} catch (error) {
|
||
|
console.error(`Error reading folder ${folderPath}:`, error);
|
||
|
return [];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Downloads README files from all repositories within a specified Gitea organization.
|
||
|
*
|
||
|
* @param domain - The domain of the Gitea instance (e.g., "https://gitea.example.com").
|
||
|
* @param org - The name of the organization whose repositories will be processed.
|
||
|
* @param outputDir - The directory where README files will be saved. Defaults to "./readmes".
|
||
|
* @param authToken - (Optional) Personal access token for authenticated requests.
|
||
|
*/
|
||
|
export async function downloadReadmes(
|
||
|
domain: string,
|
||
|
org: string,
|
||
|
outputDir: string = './readmes',
|
||
|
authToken?: string
|
||
|
): Promise<void> {
|
||
|
// Ensure the output directory exists
|
||
|
await plugins.fs.mkdir(outputDir, { recursive: true });
|
||
|
|
||
|
// Helper function to construct headers
|
||
|
const getHeaders = (additionalHeaders: Record<string, string> = {}) => {
|
||
|
const headers: Record<string, string> = {
|
||
|
'Content-Type': 'application/json',
|
||
|
...additionalHeaders,
|
||
|
};
|
||
|
if (authToken) {
|
||
|
headers['Authorization'] = `token ${authToken}`;
|
||
|
}
|
||
|
return headers;
|
||
|
};
|
||
|
|
||
|
try {
|
||
|
let page = 1;
|
||
|
const perPage = 50; // Adjust as needed
|
||
|
let hasMore = true;
|
||
|
const repos: any[] = [];
|
||
|
|
||
|
console.log(`Fetching repositories for organization: ${org}`);
|
||
|
|
||
|
// Fetch all repositories with pagination
|
||
|
while (hasMore) {
|
||
|
const reposUrl = new URL(`/api/v1/orgs/${encodeURIComponent(org)}/repos`, domain);
|
||
|
reposUrl.searchParams.append('page', page.toString());
|
||
|
reposUrl.searchParams.append('limit', perPage.toString());
|
||
|
|
||
|
const reposResponse = await fetch(reposUrl.toString(), {
|
||
|
method: 'GET',
|
||
|
headers: getHeaders(),
|
||
|
});
|
||
|
|
||
|
if (!reposResponse.ok) {
|
||
|
throw new Error(
|
||
|
`Failed to fetch repositories: ${reposResponse.status} ${reposResponse.statusText}`
|
||
|
);
|
||
|
}
|
||
|
|
||
|
const fetchedRepos = await reposResponse.json();
|
||
|
repos.push(...fetchedRepos);
|
||
|
|
||
|
if (fetchedRepos.length < perPage) {
|
||
|
hasMore = false;
|
||
|
} else {
|
||
|
page += 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
console.log(`Total repositories found: ${repos.length}`);
|
||
|
|
||
|
for (const repo of repos) {
|
||
|
const repoName: string = repo.name;
|
||
|
console.log(`Processing repository: ${repoName}`);
|
||
|
|
||
|
try {
|
||
|
const readmeUrl = new URL(
|
||
|
`/api/v1/repos/${encodeURIComponent(org)}/${encodeURIComponent(
|
||
|
repoName
|
||
|
)}/contents/readme.md`,
|
||
|
domain
|
||
|
);
|
||
|
|
||
|
console.log(readmeUrl.toString());
|
||
|
|
||
|
const readmeResponse = await fetch(readmeUrl.toString(), {
|
||
|
method: 'GET',
|
||
|
headers: getHeaders({
|
||
|
Accept: 'application/vnd.gitea.raw',
|
||
|
}),
|
||
|
});
|
||
|
|
||
|
if (readmeResponse.status === 404) {
|
||
|
console.warn(`README not found for repository: ${repoName}`);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (!readmeResponse.ok) {
|
||
|
throw new Error(
|
||
|
`Failed to fetch README: ${readmeResponse.status} ${readmeResponse.statusText}`
|
||
|
);
|
||
|
}
|
||
|
|
||
|
const readmeContentResponseObject: any = JSON.parse(await readmeResponse.text());
|
||
|
let readmeContent = atob(readmeContentResponseObject.content);
|
||
|
readmeContent = `---
|
||
|
title: "@${org}/${repo.name}"
|
||
|
---
|
||
|
${readmeContent}`;
|
||
|
const sanitizedRepoName = repoName.replace(/[^a-z0-9_\-]/gi, '_'); // Sanitize filename
|
||
|
const readmePath = plugins.path.join(outputDir, `${sanitizedRepoName}_readme.md`);
|
||
|
|
||
|
await plugins.fs.writeFile(readmePath, readmeContent, 'utf8');
|
||
|
console.log(`Saved README for ${repoName} to ${readmePath}`);
|
||
|
} catch (readmeError: any) {
|
||
|
console.error(`Error fetching README for repository: ${repoName}`, readmeError.message);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
console.log('All READMEs have been processed.');
|
||
|
} catch (error: any) {
|
||
|
console.error('An error occurred while fetching repositories:', error.message);
|
||
|
}
|
||
|
}
|