@tanstack/markdown
Version:
A tiny, fast, deterministic Markdown renderer for blogs and documentation.
79 lines (78 loc) • 2.29 kB
JavaScript
const htmlEscapes = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": ''',
};
export function normalizeInput(value) {
return value.replace(/^\uFEFF/, '').replace(/\r\n?/g, '\n');
}
export function escapeHtml(value) {
return value.replace(/[&<>"']/g, char => htmlEscapes[char]);
}
export function escapeAttr(value) {
return escapeHtml(value).replace(/`/g, '`');
}
export function isBlank(value) {
return /^\s*$/.test(value);
}
export function stripIndent(value, size) {
let index = 0;
while (index < value.length && index < size && value[index] === ' ')
index++;
return value.slice(index);
}
export function plainText(nodes) {
let value = '';
for (const node of nodes) {
if (node.type === 'text' || node.type === 'inlineCode')
value += node.value;
else if ('children' in node)
value += plainText(node.children);
else if (node.type === 'image')
value += node.alt;
}
return value;
}
export function createSlugger() {
const seen = new Map();
return (value) => {
const base = value
.toLowerCase()
.normalize('NFKD')
.replace(/[\u0300-\u036f]/g, '')
.replace(/&[a-z0-9#]+;/gi, '')
.replace(/[^a-z0-9]+/g, '-')
.replace(/^-+|-+$/g, '') || 'section';
const count = seen.get(base) ?? 0;
seen.set(base, count + 1);
return count === 0 ? base : `${base}-${count + 1}`;
};
}
export function sanitizeUrl(value) {
const trimmed = value.trim().replace(/[\u0000-\u001F\u007F\s]+/g, '');
if (!trimmed)
return '';
if (/^(#|\/|\.\/|\.\.\/)/.test(trimmed))
return trimmed;
if (/^(https?:|mailto:|tel:)/i.test(trimmed))
return trimmed;
if (/^[a-z][a-z0-9+.-]*:/i.test(trimmed))
return '';
return trimmed;
}
export function normalizeReferenceLabel(value) {
return value.trim().toLowerCase();
}
export function footnoteId(label) {
return normalizeReferenceLabel(label)
.replace(/[^a-z0-9_-]+/g, '-')
.replace(/^-+|-+$/g, '');
}
export function splitLines(value) {
const lines = value.split('\n');
if (lines.at(-1) === '')
lines.pop();
return lines;
}