Add a zulip module to marked, which supports emoji and user mentions

This is partially inspired by https://github.com/chjj/marked/pull/238

(imported from commit 03b84cde88fc8c2fe31c1003a5ce852cc364733e)
This commit is contained in:
Leo Franchi
2014-01-03 17:16:40 -06:00
parent 87ce2bd0be
commit 0de824f73e
2 changed files with 63 additions and 12 deletions

View File

@@ -259,15 +259,15 @@ $(function () {
// We used GFM + tables, so replace the list start regex for that ruleset
// We remove the |[\d+]\. that matches the numbering in a numbered list
marked.Lexer.rules.tables.list = /^( *)((?:\*)) [\s\S]+?(?:\n+(?=(?: *[\-*_]){3,} *(?:\n+|$))|\n{2,}(?! )(?!\1(?:\*) )\n*|\s*$)/;
// marked.Lexer.rules.tables
// Disable headings
disable_markdown_regex(marked.Lexer.rules.tables, 'heading');
disable_markdown_regex(marked.Lexer.rules.tables, 'lheading');
// Disable __strong__, all <em>
marked.InlineLexer.rules.breaks.strong = /^\*\*([\s\S]+?)\*\*(?!\*)/;
disable_markdown_regex(marked.InlineLexer.rules.breaks, 'em');
disable_markdown_regex(marked.InlineLexer.rules.breaks, 'del');
marked.InlineLexer.rules.zulip.strong = /^\*\*([\s\S]+?)\*\*(?!\*)/;
disable_markdown_regex(marked.InlineLexer.rules.zulip, 'em');
disable_markdown_regex(marked.InlineLexer.rules.zulip, 'del');
marked.setOptions({
gfm: true,
@@ -277,6 +277,7 @@ $(function () {
sanitize: true,
smartLists: true,
smartypants: false,
zulip: true,
renderer: r
});

View File

@@ -453,6 +453,8 @@ var inline = {
code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,
br: /^ {2,}\n(?!\s*$)/,
del: noop,
emoji: noop,
usermention: noop,
text: /^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/
};
@@ -506,6 +508,14 @@ inline.breaks = merge({}, inline.gfm, {
text: replace(inline.gfm.text)('{2,}', '*')()
});
inline.zulip = merge({}, inline.breaks, {
emoji: /^:([A-Za-z0-9_\-\+]+?):/,
usermention: /^(@\*\*([^\*]+)?\*\*)/m,
text: replace(inline.text)
(']|', '@:]|')
()
});
/**
* Inline Lexer & Compiler
*/
@@ -521,14 +531,18 @@ function InlineLexer(links, options) {
Error('Tokens array requires a `links` property.');
}
if (this.options.gfm) {
if (this.options.breaks) {
this.rules = inline.breaks;
} else {
this.rules = inline.gfm;
if (this.options.zulip) {
this.rules = inline.zulip;
} else {
if (this.options.gfm) {
if (this.options.breaks) {
this.rules = inline.breaks;
} else {
this.rules = inline.gfm;
}
} else if (this.options.pedantic) {
this.rules = inline.pedantic;
}
} else if (this.options.pedantic) {
this.rules = inline.pedantic;
}
}
@@ -625,6 +639,13 @@ InlineLexer.prototype.output = function(src) {
continue;
}
// usermention (zulip)
if (cap = this.rules.usermention.exec(src)) {
src = src.substring(cap[0].length);
out += this.usermention(cap[2], cap[1]);
continue;
}
// strong
if (cap = this.rules.strong.exec(src)) {
src = src.substring(cap[0].length);
@@ -660,6 +681,13 @@ InlineLexer.prototype.output = function(src) {
continue;
}
// emoji (gfm)
if (cap = this.rules.emoji.exec(src)) {
src = src.substring(cap[0].length);
out += this.emoji(cap[1]);
continue;
}
// text
if (cap = this.rules.text.exec(src)) {
src = src.substring(cap[0].length);
@@ -691,6 +719,27 @@ InlineLexer.prototype.outputLink = function(cap, link) {
}
};
InlineLexer.prototype.emoji = function (name) {
if (typeof this.options.emojiHandler !== 'function')
return ':' + name + ':';
return this.options.emojiHandler(name);
};
InlineLexer.prototype.usermention = function (username, orig) {
if (typeof this.options.userMentionHandler !== 'function')
{
return orig;
}
var handled = this.options.userMentionHandler(username);
if (handled !== undefined) {
return handled;
}
return orig;
};
/**
* Smartypants Transformations
*/
@@ -1144,6 +1193,7 @@ marked.setOptions = function(opt) {
marked.defaults = {
gfm: true,
emoji: false,
tables: true,
breaks: false,
pedantic: false,