diff options
| author | Hunternif | 2021-08-04 01:56:00 +0100 |
|---|---|---|
| committer | Hunternif | 2021-08-04 01:56:00 +0100 |
| commit | ca861cdc44ca476cec2949f237bbc7503862ad58 (patch) | |
| tree | 520f918a9a77432bf283b46b4296812eb4332ffe /client/js/util/markdown.js | |
| parent | dd03540398fcab11bfc2c3cebed2fb7a78592c16 (diff) | |
| parent | 59452711668b9f7a7aeea3c57301b22882987c2b (diff) | |
Merge remote-tracking branch 'origin/master' into hunternif
# Conflicts:
# client/css/post-content-control.styl
# client/css/post-list-view.styl
# client/html/post_edit_sidebar.tpl
# client/js/controllers/post_list_controller.js
# client/js/controllers/post_main_controller.js
# client/js/controllers/post_upload_controller.js
# client/js/controllers/tag_controller.js
# client/js/controllers/user_list_controller.js
# client/js/controls/expander_control.js
# client/js/controls/post_content_control.js
# client/js/controls/post_edit_sidebar_control.js
# client/js/controls/post_readonly_sidebar_control.js
# client/js/controls/tag_input_control.js
# client/js/main.js
# client/js/models/abstract_list.js
# client/js/models/post.js
# client/js/models/post_list.js
# client/js/models/settings.js
# client/js/models/tag.js
# client/js/models/tag_list.js
# client/js/tags.js
# client/js/util/search.js
# client/js/util/touch.js
# client/js/util/uri.js
# client/js/util/views.js
# client/js/views/post_main_view.js
# client/js/views/post_upload_view.js
# client/js/views/posts_header_view.js
# client/js/views/posts_page_view.js
# client/js/views/settings_view.js
# client/js/views/tag_view.js
# client/package-lock.json
# client/package.json
# server/config.yaml.dist
# server/szurubooru/api/__init__.py
# server/szurubooru/api/post_api.py
# server/szurubooru/api/tag_api.py
# server/szurubooru/func/posts.py
# server/szurubooru/func/tags.py
# server/szurubooru/model/__init__.py
# server/szurubooru/model/post.py
# server/szurubooru/model/tag.py
# server/szurubooru/search/configs/__init__.py
# server/szurubooru/search/configs/post_search_config.py
# server/szurubooru/search/executor.py
# server/szurubooru/tests/api/test_post_retrieving.py
# server/szurubooru/tests/api/test_post_updating.py
# server/szurubooru/tests/api/test_tag_updating.py
# server/szurubooru/tests/conftest.py
# server/szurubooru/tests/func/test_posts.py
# server/szurubooru/tests/func/test_tags.py
# server/szurubooru/tests/search/configs/test_post_search_config.py
Diffstat (limited to 'client/js/util/markdown.js')
| -rw-r--r-- | client/js/util/markdown.js | 94 |
1 files changed, 53 insertions, 41 deletions
diff --git a/client/js/util/markdown.js b/client/js/util/markdown.js index f326ebb..22cdae5 100644 --- a/client/js/util/markdown.js +++ b/client/js/util/markdown.js @@ -1,6 +1,7 @@ -'use strict'; +"use strict"; -const marked = require('marked'); +const marked = require("marked"); +const DOMPurify = require("dompurify"); class BaseMarkdownWrapper { preprocess(text) { @@ -20,62 +21,68 @@ class SjisWrapper extends BaseMarkdownWrapper { preprocess(text) { return text.replace( - /\[sjis\]((?:[^\[]|\[(?!\/?sjis\]))+)\[\/sjis\]/ig, + /\[sjis\]((?:[^\[]|\[(?!\/?sjis\]))+)\[\/sjis\]/gi, (match, capture) => { - var ret = '%%%SJIS' + this.buf.length; + var ret = "%%%SJIS" + this.buf.length; this.buf.push(capture); return ret; - }); + } + ); } postprocess(text) { return text.replace( /(?:<p>)?%%%SJIS(\d+)(?:<\/p>)?/, (match, capture) => { - return '<div class="sjis">' + this.buf[capture] + '</div>'; - }); + return '<div class="sjis">' + this.buf[capture] + "</div>"; + } + ); } } // fix \ before ~ being stripped away class TildeWrapper extends BaseMarkdownWrapper { preprocess(text) { - return text.replace(/\\~/g, '%%%T'); + return text.replace(/\\~/g, "%%%T"); } postprocess(text) { - return text.replace(/%%%T/g, '\\~'); + return text.replace(/%%%T/g, "\\~"); } } -//prevent ^#... from being treated as headers, due to tag permalinks +// prevent ^#... from being treated as headers, due to tag permalinks class TagPermalinkFixWrapper extends BaseMarkdownWrapper { preprocess(text) { - return text.replace(/^#/g, '%%%#'); + return text.replace(/^#/g, "%%%#"); } postprocess(text) { - return text.replace(/%%%#/g, '#'); + return text.replace(/%%%#/g, "#"); } } -//post, user and tags permalinks +// post, user and tags permalinks class EntityPermalinkWrapper extends BaseMarkdownWrapper { preprocess(text) { // URL-based permalinks + text = text.replace(new RegExp("\\b/post/(\\d+)/?\\b", "g"), "@$1"); text = text.replace( - new RegExp('\\b/post/(\\d+)/?\\b', 'g'), '@$1'); - text = text.replace( - new RegExp('\\b/tag/([a-zA-Z0-9_-]+?)/?', 'g'), '#$1'); + new RegExp("\\b/tag/([a-zA-Z0-9_-]+?)/?", "g"), + "#$1" + ); text = text.replace( - new RegExp('\\b/user/([a-zA-Z0-9_-]+?)/?', 'g'), '+$1'); + new RegExp("\\b/user/([a-zA-Z0-9_-]+?)/?", "g"), + "+$1" + ); 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)'); + "$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; } } @@ -83,51 +90,58 @@ class EntityPermalinkWrapper extends BaseMarkdownWrapper { class SearchPermalinkWrapper extends BaseMarkdownWrapper { postprocess(text) { return text.replace( - /\[search\]((?:[^\[]|\[(?!\/?search\]))+)\[\/search\]/ig, - '<a href="/posts/query=$1"><code>$1</code></a>'); + /\[search\]((?:[^\[]|\[(?!\/?search\]))+)\[\/search\]/gi, + '<a href="/posts/query=$1"><code>$1</code></a>' + ); } } class SpoilersWrapper extends BaseMarkdownWrapper { postprocess(text) { return text.replace( - /\[spoiler\]((?:[^\[]|\[(?!\/?spoiler\]))+)\[\/spoiler\]/ig, - '<span class="spoiler">$1</span>'); + /\[spoiler\]((?:[^\[]|\[(?!\/?spoiler\]))+)\[\/spoiler\]/gi, + '<span class="spoiler">$1</span>' + ); } } class SmallWrapper extends BaseMarkdownWrapper { postprocess(text) { return text.replace( - /\[small\]((?:[^\[]|\[(?!\/?small\]))+)\[\/small\]/ig, - '<small>$1</small>'); + /\[small\]((?:[^\[]|\[(?!\/?small\]))+)\[\/small\]/gi, + "<small>$1</small>" + ); } } class StrikeThroughWrapper extends BaseMarkdownWrapper { postprocess(text) { - text = text.replace(/(^|[^\\])(~~|~)([^~]+)\2/g, '$1<del>$3</del>'); - return text.replace(/\\~/g, '~'); + text = text.replace(/(^|[^\\])(~~|~)([^~]+)\2/g, "$1<del>$3</del>"); + return text.replace(/\\~/g, "~"); } } function createRenderer() { function sanitize(str) { - return str.replace(/&<"/g, m => { - if (m === '&') { - return '&'; + return str.replace(/&<"/g, (m) => { + if (m === "&") { + return "&"; } - if (m === '<') { - return '<'; + if (m === "<") { + return "<"; } - return '"'; + return """; }); } const renderer = new marked.Renderer(); renderer.image = (href, title, alt) => { - let [_, url, width, height] = - /^(.+?)(?:\s=\s*(\d*)\s*x\s*(\d*)\s*)?$/.exec(href); + let [ + _, + url, + width, + height, + ] = /^(.+?)(?:\s=\s*(\d*)\s*x\s*(\d*)\s*)?$/.exec(href); let res = '<img src="' + sanitize(url) + '" alt="' + sanitize(alt); if (width) { res += '" width="' + width; @@ -145,7 +159,6 @@ function formatMarkdown(text) { const options = { renderer: renderer, breaks: true, - sanitize: true, smartypants: true, }; let wrappers = [ @@ -166,7 +179,7 @@ function formatMarkdown(text) { for (let wrapper of wrappers) { text = wrapper.postprocess(text); } - return text; + return DOMPurify.sanitize(text); } function formatInlineMarkdown(text) { @@ -174,7 +187,6 @@ function formatInlineMarkdown(text) { const options = { renderer: renderer, breaks: true, - sanitize: true, smartypants: true, }; let wrappers = [ @@ -193,7 +205,7 @@ function formatInlineMarkdown(text) { for (let wrapper of wrappers) { text = wrapper.postprocess(text); } - return text; + return DOMPurify.sanitize(text); } module.exports = { |