diff --git a/client/js/util/misc.js b/client/js/util/misc.js index d445412..56c2043 100644 --- a/client/js/util/misc.js +++ b/client/js/util/misc.js @@ -1,5 +1,7 @@ 'use strict'; +const marked = require('marked'); + function* range(start=0, end=null, step=1) { if (end == null) { end = start; @@ -81,6 +83,72 @@ function formatRelativeTime(timeString) { return future ? 'in ' + text : text + ' ago'; } +function formatMarkdown(text) { + const renderer = new marked.Renderer(); + + const options = { + renderer: renderer, + breaks: true, + sanitize: true, + smartypants: true, + }; + + const sjis = []; + + const preDecorator = text => { + text = text.replace( + /\[sjis\]((?:[^\[]|\[(?!\/?sjis\]))+)\[\/sjis\]/ig, + (match, capture) => { + var ret = '%%%SJIS' + sjis.length; + sjis.push(capture); + return ret; + }); + //prevent ^#... from being treated as headers, due to tag permalinks + text = text.replace(/^#/g, '%%%#'); + //fix \ before ~ being stripped away + text = text.replace(/\\~/g, '%%%T'); + //post, user and tags premalinks + text = text.replace( + /(^|^\(|(?:[^\]])\(|[\s<>\[\]\)])([+#@][a-zA-Z0-9_-]+)/g, + '$1[$2]($2)'); + text = text.replace(/\]\(@(\d+)\)/g, '](#/post/$1)'); + text = text.replace(/\]\(\+([a-zA-Z0-9_-]+)\)/g, '](#/user/$1)'); + text = text.replace(/\]\(#([a-zA-Z0-9_-]+)\)/g, '](#/posts/query=$1)'); + return text; + }; + + const postDecorator = text => { + //restore fixes + text = text.replace(/%%%T/g, '\\~'); + text = text.replace(/%%%#/g, '#'); + + text = text.replace( + /%%%SJIS(\d+)/, + (match, capture) => { + return '
$1
');
+ //spoilers
+ text = text.replace(
+ /\[spoiler\]((?:[^\[]|\[(?!\/?spoiler\]))+)\[\/spoiler\]/ig,
+ '$1');
+ //[small]
+ text = text.replace(
+ /\[small\]((?:[^\[]|\[(?!\/?small\]))+)\[\/small\]/ig,
+ '$1');
+ //strike-through
+ text = text.replace(/(^|[^\\])(~~|~)([^~]+)\2/g, '$1