Add safe markdown renderer for operator-authored landing copy
This commit is contained in:
@@ -0,0 +1,41 @@
|
|||||||
|
/* md.js — tiny, safe markdown subset for user-authored copy.
|
||||||
|
* Supports: # headings, **bold**, *italic*, [links](url), - lists, blank-line paragraphs.
|
||||||
|
* Everything is HTML-escaped FIRST, so authored text can never inject markup.
|
||||||
|
*/
|
||||||
|
const esc = (s) => String(s)
|
||||||
|
.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')
|
||||||
|
.replace(/"/g, '"').replace(/'/g, ''');
|
||||||
|
|
||||||
|
export function renderMarkdown(src) {
|
||||||
|
const lines = esc(src || '').split(/\r?\n/);
|
||||||
|
const out = [];
|
||||||
|
let para = [], list = null;
|
||||||
|
|
||||||
|
const flushPara = () => { if (para.length) { out.push(`<p>${inline(para.join(' '))}</p>`); para = []; } };
|
||||||
|
const flushList = () => { if (list) { out.push(`<ul>${list.join('')}</ul>`); list = null; } };
|
||||||
|
|
||||||
|
for (const raw of lines) {
|
||||||
|
const line = raw.trim();
|
||||||
|
if (!line) { flushPara(); flushList(); continue; }
|
||||||
|
|
||||||
|
const h = line.match(/^(#{1,3})\s+(.*)$/);
|
||||||
|
if (h) { flushPara(); flushList(); const n = h[1].length + 1; out.push(`<h${n}>${inline(h[2])}</h${n}>`); continue; }
|
||||||
|
|
||||||
|
const li = line.match(/^[-*]\s+(.*)$/);
|
||||||
|
if (li) { flushPara(); (list ||= []).push(`<li>${inline(li[1])}</li>`); continue; }
|
||||||
|
|
||||||
|
flushList();
|
||||||
|
para.push(line);
|
||||||
|
}
|
||||||
|
flushPara(); flushList();
|
||||||
|
return out.join('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
function inline(t) {
|
||||||
|
return t
|
||||||
|
.replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>')
|
||||||
|
.replace(/\*([^*]+)\*/g, '<em>$1</em>')
|
||||||
|
// links: only http(s) and site-relative, so no javascript: URLs
|
||||||
|
.replace(/\[([^\]]+)\]\((https?:\/\/[^\s)]+|\/[^\s)]*)\)/g,
|
||||||
|
'<a href="$2" target="_blank" rel="noopener noreferrer">$1</a>');
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user