AnP/Public/ecma/Utils/MarkDown.ecma.js
2026-06-08 08:07:37 +02:00

101 lines
3.2 KiB
JavaScript

"use strict";
export const MarkDown = (function(){
const MarkDown = function(anp){};
MarkDown.Item = function(pattern, replace, block = false){
this.pattern = pattern;
this.replace = replace;
this.block = block;
this.match = null;
this.length = 0;
this.more = true;
this.index = -1;
};
MarkDown.Header = () => new MarkDown.Item(/^(#{1,6})\s*(.+)$/m, (match, hashes, content) => `<h${hashes.length}>${MarkDown.to_html(content, false)}</h${hashes.length}>`, true);
MarkDown.Block = () => new MarkDown.Item(/^```([a-z]*)\r?\n([\s\S]*?)\r?\n```/, (match, lang, content) => `<fieldset><legend>${lang}</legend><pre><code class="${lang}">${content}</code></pre></fieldset>`, true);
MarkDown.BlockQuote = () => new MarkDown.Item(/^>\s?(.+)$/m, (match, content) => `<blockquote>${MarkDown.to_html(content, false)}</blockquote>`, true);
MarkDown.Paragraph = () => new MarkDown.Item(/^((?:[^\r\n]+(?:\r\n|[\r\n])?)+)/m, (match, content) => `<p>${MarkDown.to_html(content, false)}</p>\n\n`, true);
MarkDown.Link = () => new MarkDown.Item(/\[([^\]]+)\]\(([^)]+)\)|([a-z]{2,12}:\/{2}[^ "']+)/, (match, text, url, link) => `<a href="${url || link}" target="_blank" title="${text || link}">${text || link}</a>`);
MarkDown.Bold = () => new MarkDown.Item(/\*{2}((?:(?!(?:\*{2})).)+)\*{2}/, (match, content) => `<b>${MarkDown.to_html(content, false)}</b>`);
MarkDown.Italic = () => new MarkDown.Item(/\*((?:(?!(?:\*)).|\*{2})+)\*(?!\*)/, (match, content) => `<i>${MarkDown.to_html(content, false)}</i>`);
MarkDown.to_html = (string, blocks = true) => {
let html = ``;
const matches = [
MarkDown.Header(),
MarkDown.Block(),
MarkDown.BlockQuote(),
MarkDown.Paragraph(),
MarkDown.Link(),
MarkDown.Bold(),
MarkDown.Italic()
];
do{
let index = 1 << 28,
i = null;
[...matches].forEach((item, j) => {
if(!item.more)
return;
if(item.block && !blocks){
item.more = false;
return;
};
if(item.index < 0){
const submatches = string.match(item.pattern);
if(!submatches){
item.more = false;
return;
};
item.match = submatches;
item.length = submatches[0].length;
item.index = submatches.index;
};
if(index > item.index){
index = item.index;
i = j;
};
});
if(i === null)
break;
const item = matches[i],
total = index + item.length;
html += string.substring(0, index) + item.replace(...item.match);
string = string.substring(total);
matches.forEach(item => {
item.index -= total;
});
}while(matches.length)
html += string;
return html;
}
return MarkDown;
})();