mirror of
https://github.com/perfect-panel/ppanel-web.git
synced 2026-02-06 11:40:28 -05:00
88 lines
2.6 KiB
TypeScript
88 lines
2.6 KiB
TypeScript
const BASE_URL = 'https://cdn.jsdelivr.net/gh/perfect-panel/ppanel-tutorial';
|
|
|
|
async function getVersion() {
|
|
const response = await fetch(
|
|
'https://api.github.com/repos/perfect-panel/ppanel-tutorial/commits',
|
|
);
|
|
const json = await response.json();
|
|
return json[0].sha;
|
|
}
|
|
|
|
export async function getTutorial(path: string): Promise<string> {
|
|
const version = await getVersion();
|
|
try {
|
|
const url = `${BASE_URL}@${version}/${path}`;
|
|
const response = await fetch(url);
|
|
if (!response.ok) {
|
|
throw new Error(`HTTP error! status: ${response.status}`);
|
|
}
|
|
const text = await response.text();
|
|
const markdown = addPrefixToImageUrls(text, getUrlPrefix(url));
|
|
return markdown;
|
|
} catch (error) {
|
|
console.error('Error fetching the markdown file:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
type TutorialItem = {
|
|
title: string;
|
|
path: string;
|
|
subItems?: TutorialItem[];
|
|
};
|
|
|
|
export async function getTutorialList() {
|
|
return await getTutorial('SUMMARY.md').then((markdown) => {
|
|
const map = parseTutorialToMap(markdown);
|
|
map.forEach((value, key) => {
|
|
map.set(
|
|
key,
|
|
value.filter((item) => item.title !== 'README'),
|
|
);
|
|
});
|
|
return map;
|
|
});
|
|
}
|
|
|
|
function parseTutorialToMap(markdown: string): Map<string, TutorialItem[]> {
|
|
const map = new Map<string, TutorialItem[]>();
|
|
let currentSection = '';
|
|
const lines = markdown.split('\n');
|
|
|
|
for (const line of lines) {
|
|
if (line.startsWith('## ')) {
|
|
currentSection = line.replace('## ', '').trim();
|
|
map.set(currentSection, []);
|
|
} else if (line.startsWith('* ')) {
|
|
const [, text, link] = line.match(/\* \[(.*?)\]\((.*?)\)/) || [];
|
|
if (text && link) {
|
|
if (!map.has(currentSection)) {
|
|
map.set(currentSection, []);
|
|
}
|
|
map.get(currentSection)!.push({ title: text, path: link });
|
|
}
|
|
} else if (line.startsWith(' * ')) {
|
|
const [, text, link] = line.match(/\* \[(.*?)\]\((.*?)\)/) || [];
|
|
if (text && link) {
|
|
const lastItem = map.get(currentSection)?.slice(-1)[0];
|
|
if (lastItem) {
|
|
if (!lastItem.subItems) {
|
|
lastItem.subItems = [];
|
|
}
|
|
lastItem.subItems.push({ title: text, path: link });
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return map;
|
|
}
|
|
function getUrlPrefix(url: string): string {
|
|
return url.replace(/\/[^/]+\.md$/, '/');
|
|
}
|
|
function addPrefixToImageUrls(markdown: string, prefix: string): string {
|
|
return markdown.replace(/!\[(.*?)\]\((.*?)\)/g, (match, imgAlt, imgUrl) => {
|
|
return ` ? imgUrl : `${prefix}${imgUrl}`})`;
|
|
});
|
|
}
|