diff options
author | Joram Wilander <jwawilander@gmail.com> | 2015-10-29 07:53:06 -0400 |
---|---|---|
committer | Joram Wilander <jwawilander@gmail.com> | 2015-10-29 07:53:06 -0400 |
commit | 82abf9063fe9ae9983a8aec6ecb49a8fe1a4ba98 (patch) | |
tree | 884de39c955526b240d9a1e8ca6a0aeeebbfd3cf /web/react/utils/markdown.jsx | |
parent | 64b617099db2b25555fe944ef6a0fe64dba2484d (diff) | |
parent | 0356130ca6d4e3457769946d7dbf383ffe291098 (diff) | |
download | chat-82abf9063fe9ae9983a8aec6ecb49a8fe1a4ba98.tar.gz chat-82abf9063fe9ae9983a8aec6ecb49a8fe1a4ba98.tar.bz2 chat-82abf9063fe9ae9983a8aec6ecb49a8fe1a4ba98.zip |
Merge pull request #1218 from hmhealey/underscores
PLT-631/PLT-764/PLT-204/PLT-521 Updating autolinking and handling of underscores by the markdown parser
Diffstat (limited to 'web/react/utils/markdown.jsx')
-rw-r--r-- | web/react/utils/markdown.jsx | 82 |
1 files changed, 67 insertions, 15 deletions
diff --git a/web/react/utils/markdown.jsx b/web/react/utils/markdown.jsx index 26587dd6e..e34f3d00a 100644 --- a/web/react/utils/markdown.jsx +++ b/web/react/utils/markdown.jsx @@ -6,7 +6,43 @@ const Utils = require('./utils.jsx'); const marked = require('marked'); -export class MattermostMarkdownRenderer extends marked.Renderer { +class MattermostInlineLexer extends marked.InlineLexer { + constructor(links, options) { + super(links, options); + + this.rules = Object.assign({}, this.rules); + + // modified version of the regex that doesn't break up words in snake_case, + // allows for links starting with www, and allows links succounded by parentheses + // the original is /^[\s\S]+?(?=[\\<!\[_*`~]|https?:\/\/| {2,}\n|$)/ + this.rules.text = /^[\s\S]+?(?=[^\w\/]_|[\\<!\[*`~]|https?:\/\/|www\.|\(| {2,}\n|$)/; + + // modified version of the regex that allows links starting with www and those surrounded + // by parentheses + // the original is /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/ + this.rules.url = /^(\(?(?:https?:\/\/|www\.)[^\s<.][^\s<]*[^<.,:;"'\]\s])/; + + // modified version of the regex that allows <links> starting with www. + // the original is /^<([^ >]+(@|:\/)[^ >]+)>/ + this.rules.autolink = /^<((?:[^ >]+(@|:\/)|www\.)[^ >]+)>/; + } +} + +class MattermostParser extends marked.Parser { + parse(src) { + this.inline = new MattermostInlineLexer(src.links, this.options, this.renderer); + this.tokens = src.reverse(); + + var out = ''; + while (this.next()) { + out += this.tok(); + } + + return out; + } +} + +class MattermostMarkdownRenderer extends marked.Renderer { constructor(options, formattingOptions = {}) { super(options); @@ -32,8 +68,20 @@ export class MattermostMarkdownRenderer extends marked.Renderer { link(href, title, text) { let outHref = href; + let outText = text; + let prefix = ''; + let suffix = ''; + + // some links like https://en.wikipedia.org/wiki/Rendering_(computer_graphics) contain brackets + // and we try our best to differentiate those from ones just wrapped in brackets when autolinking + if (outHref.startsWith('(') && outHref.endsWith(')') && text === outHref) { + prefix = '('; + suffix = ')'; + outText = text.substring(1, text.length - 1); + outHref = outHref.substring(1, outHref.length - 1); + } - if (!(/^(mailto|https?|ftp)/.test(outHref))) { + if (!(/[a-z+.-]+:/i).test(outHref)) { outHref = `http://${outHref}`; } @@ -48,26 +96,17 @@ export class MattermostMarkdownRenderer extends marked.Renderer { output += ' target="_blank">'; } - output += text + '</a>'; + output += outText + '</a>'; - return output; + return prefix + output + suffix; } paragraph(text) { - let outText = text; - - // required so markdown does not strip '_' from @user_names - outText = TextFormatting.doFormatMentions(text); - - if (!('emoticons' in this.options) || this.options.emoticon) { - outText = TextFormatting.doFormatEmoticons(outText); - } - if (this.formattingOptions.singleline) { - return `<p class="markdown__paragraph-inline">${outText}</p>`; + return `<p class="markdown__paragraph-inline">${text}</p>`; } - return super.paragraph(outText); + return super.paragraph(text); } table(header, body) { @@ -78,3 +117,16 @@ export class MattermostMarkdownRenderer extends marked.Renderer { return TextFormatting.doFormatText(txt, this.formattingOptions); } } + +export function format(text, options) { + const markdownOptions = { + renderer: new MattermostMarkdownRenderer(null, options), + sanitize: true, + gfm: true + }; + + const tokens = marked.lexer(text, markdownOptions); + + return new MattermostParser(markdownOptions).parse(tokens); +} + |