feat: release version 1.0.5
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
import { marked, Renderer } from 'marked';
|
||||
|
||||
function escapeHtml(value: string): string {
|
||||
return value
|
||||
.replaceAll('&', '&')
|
||||
.replaceAll('<', '<')
|
||||
.replaceAll('>', '>')
|
||||
.replaceAll('"', '"')
|
||||
.replaceAll("'", ''');
|
||||
}
|
||||
|
||||
function safeUrl(value: string): string | null {
|
||||
const trimmed = value.trim();
|
||||
if (trimmed.startsWith('#') || trimmed.startsWith('/')) return trimmed;
|
||||
|
||||
try {
|
||||
const url = new URL(trimmed);
|
||||
return ['http:', 'https:'].includes(url.protocol) ? url.href : null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
const renderer = new Renderer();
|
||||
|
||||
renderer.html = ({ text }) => escapeHtml(text);
|
||||
renderer.link = function ({ href, title, tokens }) {
|
||||
const label = this.parser.parseInline(tokens);
|
||||
const url = safeUrl(href);
|
||||
if (!url) return label;
|
||||
const titleAttribute = title ? ` title="${escapeHtml(title)}"` : '';
|
||||
return `<a href="${escapeHtml(url)}"${titleAttribute} target="_blank" rel="noreferrer">${label}</a>`;
|
||||
};
|
||||
renderer.image = ({ href, title, text }) => {
|
||||
const url = safeUrl(href);
|
||||
if (!url) return escapeHtml(text);
|
||||
const titleAttribute = title ? ` title="${escapeHtml(title)}"` : '';
|
||||
return `<img src="${escapeHtml(url)}" alt="${escapeHtml(text)}"${titleAttribute} loading="lazy">`;
|
||||
};
|
||||
|
||||
export function renderReleaseMarkdown(markdown: string): string {
|
||||
return marked.parse(markdown, {
|
||||
async: false,
|
||||
breaks: true,
|
||||
gfm: true,
|
||||
renderer
|
||||
}) as string;
|
||||
}
|
||||
Reference in New Issue
Block a user