mirror of
https://github.com/morten-olsen/morten-olsen.github.io.git
synced 2026-02-08 01:46:28 +01:00
92 lines
2.3 KiB
TypeScript
92 lines
2.3 KiB
TypeScript
import { decode } from 'html-entities';
|
|
import { existsSync } from 'fs';
|
|
import { resolve } from 'path';
|
|
|
|
const latexTypes = ['', 'section', 'subsection', 'paragraph', 'subparagraph'];
|
|
|
|
const sanitize = (text?: string) => {
|
|
if (!text) {
|
|
return '';
|
|
}
|
|
return decode(text)
|
|
.replace('&', '\\&')
|
|
.replace('_', '\\_')
|
|
.replace(/([^\\])\}/g, '$1\\}')
|
|
.replace(/([^\\])\{/g, '$1\\{')
|
|
.replace(/[^\\]\[/g, '\\[')
|
|
.replace(/#/g, '\\#');
|
|
};
|
|
|
|
type Renderer = (depth: number) => {
|
|
heading?: (text: string, depth: number) => string;
|
|
code?: (input: string) => string;
|
|
text?: (input: string) => string;
|
|
paragraph?: (input: string) => string;
|
|
list?: (input: string) => string;
|
|
listitem?: (input: string) => string;
|
|
link?: (href: string, text: string) => string;
|
|
strong?: (text: string) => string;
|
|
em?: (text: string) => string;
|
|
codespan?: (code: string) => string;
|
|
image?: (link: string) => string;
|
|
};
|
|
|
|
const renderer = (outerDepth: number, cwd: string) => ({
|
|
heading: (text: string, depth: number) => {
|
|
return `\\${latexTypes[outerDepth + depth]}{${sanitize(text)}}\n\n`;
|
|
},
|
|
code: (input: string) => {
|
|
return `
|
|
\\begin{lstlisting}
|
|
${input}
|
|
\\end{lstlisting}
|
|
`;
|
|
},
|
|
text: (input: string) => {
|
|
return sanitize(input);
|
|
},
|
|
blockquote: (input: string) => {
|
|
return sanitize(input);
|
|
},
|
|
paragraph: (input: string) => {
|
|
return `${input}\n\n`;
|
|
},
|
|
list: (input: string) => {
|
|
return `
|
|
\\begin{itemize}
|
|
${input}
|
|
\\end{itemize}
|
|
`;
|
|
},
|
|
listitem: (input: string) => {
|
|
return `\\item{${input}}`;
|
|
},
|
|
link: (href: string, text: string) => {
|
|
if (!text || text === href) {
|
|
return `\\url{${sanitize(href)}}`;
|
|
}
|
|
return `${sanitize(text)} (\\url{${sanitize(href)}})`;
|
|
},
|
|
strong: (text: string) => {
|
|
return `\\textbf{${sanitize(text)}}`;
|
|
},
|
|
em: (text: string) => {
|
|
return `\\textbf{${sanitize(text)}}`;
|
|
},
|
|
codespan: (code: string) => {
|
|
return `\\texttt{${sanitize(code)}}`;
|
|
},
|
|
image: (link: string) => {
|
|
const path = resolve(cwd, link);
|
|
if (!existsSync(path)) {
|
|
return `Online image not supported ${path}`;
|
|
}
|
|
return `
|
|
\\noindent\\includegraphics[width=\\linewidth]{${path}}
|
|
`;
|
|
},
|
|
});
|
|
|
|
export type { Renderer };
|
|
export { sanitize, renderer };
|