lib/render-md.js - git - Webernet Explorer _X
git 🏠 Home 👤 Sign up Self hosted git, retro shell
★ otgit, code hosting from the year 2000 ★
📄 octuna / lib / render-md.js
83 lines · 2.2 KB · Raw
1const { escape } = require('./render');
2 
3function safeUrl(url) {
4 if (/^https?:\/\//i.test(url)) return url;
5 if (/^\//.test(url)) return url;
6 return '';
7}
8 
9function inline(s) {
10 s = escape(s);
11 s = s.replace(/`([^`]+)`/g, (_, c) => `<code>${c}</code>`);
12 s = s.replace(/\*\*([^*]+)\*\*/g, (_, c) => `<strong>${c}</strong>`);
13 s = s.replace(/\*([^*\s][^*]*)\*/g, (_, c) => `<em>${c}</em>`);
14 s = s.replace(/\[([^\]]+)\]\(([^)]+)\)/g, (_, text, url) => {
15 const safe = safeUrl(url);
16 return safe ? `<a href="${escape(safe)}" rel="noopener noreferrer">${text}</a>` : text;
17 });
18 return s;
19}
20 
21function render(md) {
22 const lines = (md || '').split('\n');
23 const out = [];
24 let inCode = false;
25 let codeBuf = [];
26 let inList = false;
27 let listType = '';
28 
29 function flushList() {
30 if (!inList) return;
31 out.push(`</${listType}>`);
32 inList = false; listType = '';
33 }
34 
35 for (const line of lines) {
36 if (line.startsWith('```')) {
37 if (inCode) {
38 out.push(`<pre><code>${escape(codeBuf.join('\n'))}</code></pre>`);
39 codeBuf = []; inCode = false;
40 } else {
41 flushList();
42 inCode = true;
43 }
44 continue;
45 }
46 if (inCode) { codeBuf.push(line); continue; }
47 
48 const hm = line.match(/^(#{1,6})\s+(.+)$/);
49 if (hm) {
50 flushList();
51 const n = hm[1].length;
52 out.push(`<h${n}>${inline(hm[2])}</h${n}>`);
53 continue;
54 }
55 if (/^[-*_]{3,}\s*$/.test(line)) {
56 flushList(); out.push('<hr>'); continue;
57 }
58 const ulm = line.match(/^[-*+]\s+(.+)$/);
59 if (ulm) {
60 if (!inList || listType !== 'ul') { flushList(); out.push('<ul>'); inList = true; listType = 'ul'; }
61 out.push(`<li>${inline(ulm[1])}</li>`);
62 continue;
63 }
64 const olm = line.match(/^\d+\.\s+(.+)$/);
65 if (olm) {
66 if (!inList || listType !== 'ol') { flushList(); out.push('<ol>'); inList = true; listType = 'ol'; }
67 out.push(`<li>${inline(olm[1])}</li>`);
68 continue;
69 }
70 if (line.trim() === '') {
71 flushList(); out.push(''); continue;
72 }
73 flushList();
74 out.push(`<p>${inline(line)}</p>`);
75 }
76 
77 if (inCode) out.push(`<pre><code>${escape(codeBuf.join('\n'))}</code></pre>`);
78 flushList();
79 return out.join('\n');
80}
81 
82module.exports = { render };
83 
Done 🔒 Internet