in packages/docusaurus-utils/src/markdownUtils.ts [54:130]
export function createExcerpt(fileString: string): string | undefined {
const fileLines = fileString
.trimStart()
// Remove Markdown alternate title
.replace(/^[^\n]*\n[=]+/g, '')
.split('\n');
let inCode = false;
let inImport = false;
let lastCodeFence = '';
for (const fileLine of fileLines) {
if (fileLine === '' && inImport) {
inImport = false;
}
// Skip empty line.
if (!fileLine.trim()) {
continue;
}
// Skip import/export declaration.
if ((/^(?:import|export)\s.*/.test(fileLine) || inImport) && !inCode) {
inImport = true;
continue;
}
// Skip code block line.
if (fileLine.trim().startsWith('```')) {
const codeFence = fileLine.trim().match(/^`+/)![0]!;
if (!inCode) {
inCode = true;
lastCodeFence = codeFence;
// If we are in a ````-fenced block, all ``` would be plain text instead
// of fences
} else if (codeFence.length >= lastCodeFence.length) {
inCode = false;
}
continue;
} else if (inCode) {
continue;
}
const cleanedLine = fileLine
// Remove HTML tags.
.replace(/<[^>]*>/g, '')
// Remove Title headers
.replace(/^#[^#]+#?/gm, '')
// Remove Markdown + ATX-style headers
.replace(/^#{1,6}\s*(?<text>[^#]*)\s*#{0,6}/gm, '$1')
// Remove emphasis.
.replace(/(?<opening>[*_]{1,3})(?<text>.*?)\1/g, '$2')
// Remove strikethroughs.
.replace(/~~(?<text>\S.*\S)~~/g, '$1')
// Remove images.
.replace(/!\[(?<alt>.*?)\][[(].*?[\])]/g, '$1')
// Remove footnotes.
.replace(/\[\^.+?\](?:: .*$)?/g, '')
// Remove inline links.
.replace(/\[(?<alt>.*?)\][[(].*?[\])]/g, '$1')
// Remove inline code.
.replace(/`(?<text>.+?)`/g, '$1')
// Remove blockquotes.
.replace(/^\s{0,3}>\s?/g, '')
// Remove admonition definition.
.replace(/:::.*/, '')
// Remove Emoji names within colons include preceding whitespace.
.replace(/\s?:(?:::|[^:\n])+:/g, '')
// Remove custom Markdown heading id.
.replace(/\{#*[\w-]+\}/, '')
.trim();
if (cleanedLine) {
return cleanedLine;
}
}
return undefined;
}