computer-scienceangular-roadmapbackend-roadmapblockchain-roadmapdba-roadmapdeveloper-roadmapdevops-roadmapfrontend-roadmapgo-roadmaphactoberfestjava-roadmapjavascript-roadmapnodejs-roadmappython-roadmapqa-roadmapreact-roadmaproadmapstudy-planvue-roadmapweb3-roadmap
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
119 lines
3.0 KiB
119 lines
3.0 KiB
1 year ago
|
import type { MarkdownFileType } from './file';
|
||
|
import slugify from 'slugify';
|
||
|
|
||
|
interface RawQuestionGroupFrontmatter {
|
||
|
order: number;
|
||
|
briefTitle: string;
|
||
|
briefDescription: string;
|
||
|
title: string;
|
||
|
description: string;
|
||
|
isNew: boolean;
|
||
|
seo: {
|
||
|
title: string;
|
||
|
description: string;
|
||
|
ogImageUrl?: string;
|
||
|
keywords: string[];
|
||
|
};
|
||
|
sitemap: {
|
||
|
priority: number;
|
||
|
changefreq: string;
|
||
|
};
|
||
|
questions: {
|
||
|
question: string;
|
||
|
answer: string;
|
||
|
topics: string[];
|
||
|
}[];
|
||
|
}
|
||
|
|
||
|
type RawQuestionGroupFileType =
|
||
|
MarkdownFileType<RawQuestionGroupFrontmatter> & {
|
||
|
id: string;
|
||
|
};
|
||
|
|
||
|
export type QuestionType = {
|
||
|
id: string;
|
||
|
question: string;
|
||
|
answer: string;
|
||
|
isLongAnswer: boolean;
|
||
|
topics?: string[];
|
||
|
};
|
||
|
|
||
|
export type QuestionGroupType = RawQuestionGroupFileType & {
|
||
|
questions: QuestionType[];
|
||
|
allTopics: string[];
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Gets all the best practice files
|
||
|
*
|
||
|
* @returns Promisified BestPracticeFileType[]
|
||
|
*/
|
||
|
export async function getAllQuestionGroups(): Promise<QuestionGroupType[]> {
|
||
|
const questionGroupFilesMap =
|
||
|
await import.meta.glob<RawQuestionGroupFileType>(
|
||
|
`/src/data/question-groups/*/*.md`,
|
||
|
{
|
||
|
eager: true,
|
||
|
}
|
||
|
);
|
||
|
|
||
|
const answerFilesMap = await import.meta.glob<string>(
|
||
|
// get the files inside /src/data/question-groups/[ignore]/content/*.md
|
||
|
`/src/data/question-groups/*/content/*.md`,
|
||
|
{
|
||
|
eager: true,
|
||
|
as: 'raw',
|
||
|
}
|
||
|
);
|
||
|
|
||
|
return Object.values(questionGroupFilesMap)
|
||
|
.map((questionGroupFile) => {
|
||
|
const fileParts = questionGroupFile?.file?.split('/');
|
||
|
const [questionGroupDir, questionGroupFileName] = fileParts?.slice(-2);
|
||
|
|
||
|
const questionGroupFileId = questionGroupFileName?.replace('.md', '');
|
||
|
const formattedAnswers: QuestionType[] =
|
||
|
questionGroupFile.frontmatter.questions.map((qa) => {
|
||
|
const questionText = qa.question;
|
||
|
let answerText = qa.answer;
|
||
|
let isLongAnswer = false;
|
||
|
|
||
|
if (answerText.endsWith('.md')) {
|
||
|
const answerFilePath = `/src/data/question-groups/${questionGroupDir}/content/${answerText}`;
|
||
|
answerText =
|
||
|
answerFilesMap[answerFilePath] ||
|
||
|
`File missing: ${answerFilePath}`;
|
||
|
|
||
|
isLongAnswer = true;
|
||
|
}
|
||
|
|
||
|
return {
|
||
|
id: slugify(questionText, { lower: true }),
|
||
|
question: questionText,
|
||
|
answer: answerText,
|
||
|
topics: qa.topics,
|
||
|
isLongAnswer,
|
||
|
};
|
||
|
});
|
||
|
|
||
|
const uniqueTopics = formattedAnswers
|
||
|
.flatMap((answer) => answer.topics || [])
|
||
|
.filter((topic) => topic)
|
||
|
.reduce((acc, topic) => {
|
||
|
if (!acc.includes(topic)) {
|
||
|
acc.push(topic);
|
||
|
}
|
||
|
|
||
|
return acc;
|
||
|
}, [] as string[]);
|
||
|
|
||
|
return {
|
||
|
...questionGroupFile,
|
||
|
id: questionGroupFileId,
|
||
|
questions: formattedAnswers,
|
||
|
allTopics: uniqueTopics,
|
||
|
};
|
||
|
})
|
||
|
.sort((a, b) => a.frontmatter.order - b.frontmatter.order);
|
||
|
}
|