FIX: Allow intra-word underscores.
This commit is contained in:
parent
89265c3a8b
commit
73489b652e
|
@ -10,23 +10,34 @@ Discourse.Dialect.on("register", function(event) {
|
||||||
var dialect = event.dialect,
|
var dialect = event.dialect,
|
||||||
MD = event.MD;
|
MD = event.MD;
|
||||||
|
|
||||||
/**
|
|
||||||
Handles simultaneous bold and italics
|
|
||||||
|
|
||||||
@method parseMentions
|
var inlineBuilder = function(symbol, tag, surround) {
|
||||||
@param {String} text the text match
|
return function(text, match, prev) {
|
||||||
@param {Array} match the match found
|
if (prev && (prev.length > 0)) {
|
||||||
@param {Array} prev the previous jsonML
|
var last = prev[prev.length - 1];
|
||||||
@return {Array} an array containing how many chars we've replaced and the jsonML content for it.
|
if (typeof last === "string" && (!last.match(/\W$/))) { return; }
|
||||||
@namespace Discourse.Dialect
|
}
|
||||||
**/
|
|
||||||
dialect.inline['***'] = function boldItalics(text, match, prev) {
|
|
||||||
var regExp = /^\*{3}([^\*]+)\*{3}/,
|
|
||||||
m = regExp.exec(text);
|
|
||||||
|
|
||||||
if (m) {
|
var regExp = new RegExp("^\\" + symbol + "([^\\" + symbol + "]+)" + "\\" + symbol, "igm"),
|
||||||
return [m[0].length, ['strong', ['em'].concat(this.processInline(m[1]))]];
|
m = regExp.exec(text);
|
||||||
}
|
|
||||||
|
if (m) {
|
||||||
|
|
||||||
|
var contents = [tag].concat(this.processInline(m[1]));
|
||||||
|
if (surround) {
|
||||||
|
contents = [surround, contents];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [m[0].length, contents];
|
||||||
|
}
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
dialect.inline['***'] = inlineBuilder('**', 'em', 'strong');
|
||||||
|
dialect.inline['**'] = inlineBuilder('**', 'strong');
|
||||||
|
dialect.inline['*'] = inlineBuilder('*', 'em');
|
||||||
|
dialect.inline['_'] = inlineBuilder('_', 'em');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,3 +1,18 @@
|
||||||
|
/*
|
||||||
|
This is a fork of markdown-js with a few changes to support discourse:
|
||||||
|
|
||||||
|
* We have replaced the strong/em handlers because we prefer them only to work on word
|
||||||
|
boundaries.
|
||||||
|
|
||||||
|
* We removed the maraku support as we don't use it.
|
||||||
|
|
||||||
|
* We don't escape the contents of HTML as we prefer to use a whitelist.
|
||||||
|
|
||||||
|
* Note the name BetterMarkdown doesn't mean it's *better* than markdown-js, it refers
|
||||||
|
to it being better than our previous markdown parser!
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
// Released under MIT license
|
// Released under MIT license
|
||||||
// Copyright (c) 2009-2010 Dominic Baggott
|
// Copyright (c) 2009-2010 Dominic Baggott
|
||||||
// Copyright (c) 2009-2010 Ash Berlin
|
// Copyright (c) 2009-2010 Ash Berlin
|
||||||
|
@ -1004,69 +1019,6 @@ Markdown.dialects.Gruber.inline = {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Meta Helper/generator method for em and strong handling
|
|
||||||
function strong_em( tag, md ) {
|
|
||||||
|
|
||||||
var state_slot = tag + "_state",
|
|
||||||
other_slot = tag == "strong" ? "em_state" : "strong_state";
|
|
||||||
|
|
||||||
function CloseTag(len) {
|
|
||||||
this.len_after = len;
|
|
||||||
this.name = "close_" + md;
|
|
||||||
}
|
|
||||||
|
|
||||||
return function ( text, orig_match ) {
|
|
||||||
|
|
||||||
if ( this[state_slot][0] == md ) {
|
|
||||||
// Most recent em is of this type
|
|
||||||
//D:this.debug("closing", md);
|
|
||||||
this[state_slot].shift();
|
|
||||||
|
|
||||||
// "Consume" everything to go back to the recrusion in the else-block below
|
|
||||||
return[ text.length, new CloseTag(text.length-md.length) ];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Store a clone of the em/strong states
|
|
||||||
var other = this[other_slot].slice(),
|
|
||||||
state = this[state_slot].slice();
|
|
||||||
|
|
||||||
this[state_slot].unshift(md);
|
|
||||||
|
|
||||||
//D:this.debug_indent += " ";
|
|
||||||
|
|
||||||
// Recurse
|
|
||||||
var res = this.processInline( text.substr( md.length ) );
|
|
||||||
//D:this.debug_indent = this.debug_indent.substr(2);
|
|
||||||
|
|
||||||
var last = res[res.length - 1];
|
|
||||||
|
|
||||||
//D:this.debug("processInline from", tag + ": ", uneval( res ) );
|
|
||||||
|
|
||||||
var check = this[state_slot].shift();
|
|
||||||
if ( last instanceof CloseTag ) {
|
|
||||||
res.pop();
|
|
||||||
// We matched! Huzzah.
|
|
||||||
var consumed = text.length - last.len_after;
|
|
||||||
return [ consumed, [ tag ].concat(res) ];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Restore the state of the other kind. We might have mistakenly closed it.
|
|
||||||
this[other_slot] = other;
|
|
||||||
this[state_slot] = state;
|
|
||||||
|
|
||||||
// We can't reuse the processed result as it could have wrong parsing contexts in it.
|
|
||||||
return [ md.length, md ];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}; // End returned function
|
|
||||||
}
|
|
||||||
|
|
||||||
Markdown.dialects.Gruber.inline["**"] = strong_em("strong", "**");
|
|
||||||
Markdown.dialects.Gruber.inline["__"] = strong_em("strong", "__");
|
|
||||||
Markdown.dialects.Gruber.inline["*"] = strong_em("em", "*");
|
|
||||||
Markdown.dialects.Gruber.inline["_"] = strong_em("em", "_");
|
|
||||||
|
|
||||||
|
|
||||||
// Build default order from insertion order.
|
// Build default order from insertion order.
|
||||||
Markdown.buildBlockOrder = function(d) {
|
Markdown.buildBlockOrder = function(d) {
|
||||||
var ord = [];
|
var ord = [];
|
|
@ -105,7 +105,7 @@ module PrettyText
|
||||||
ctx.eval("var I18n = {}; I18n.t = function(a,b){ return helpers.t(a,b); }");
|
ctx.eval("var I18n = {}; I18n.t = function(a,b){ return helpers.t(a,b); }");
|
||||||
|
|
||||||
ctx_load(ctx,
|
ctx_load(ctx,
|
||||||
"app/assets/javascripts/external/markdown.js",
|
"app/assets/javascripts/external/better_markdown.js",
|
||||||
"app/assets/javascripts/discourse/dialects/dialect.js",
|
"app/assets/javascripts/discourse/dialects/dialect.js",
|
||||||
"app/assets/javascripts/discourse/components/utilities.js",
|
"app/assets/javascripts/discourse/components/utilities.js",
|
||||||
"app/assets/javascripts/discourse/components/markdown.js")
|
"app/assets/javascripts/discourse/components/markdown.js")
|
||||||
|
|
|
@ -17,7 +17,13 @@ var cookedOptions = function(input, opts, expected, text) {
|
||||||
|
|
||||||
test("basic cooking", function() {
|
test("basic cooking", function() {
|
||||||
cooked("hello", "<p>hello</p>", "surrounds text with paragraphs");
|
cooked("hello", "<p>hello</p>", "surrounds text with paragraphs");
|
||||||
|
cooked("**evil**", "<p><strong>evil</strong></p>", "it bolds text.");
|
||||||
|
cooked("*trout*", "<p><em>trout</em></p>", "it italicizes text.");
|
||||||
|
cooked("_trout_", "<p><em>trout</em></p>", "it italicizes text.");
|
||||||
cooked("***hello***", "<p><strong><em>hello</em></strong></p>", "it can do bold and italics at once.");
|
cooked("***hello***", "<p><strong><em>hello</em></strong></p>", "it can do bold and italics at once.");
|
||||||
|
cooked("word_with_underscores", "<p>word_with_underscores</p>", "it doesn't do intraword italics");
|
||||||
|
cooked("hello \\*evil\\*", "<p>hello *evil*</p>", "it supports escaping of asterisks");
|
||||||
|
cooked("hello \\_evil\\_", "<p>hello _evil_</p>", "it supports escaping of italics");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Traditional Line Breaks", function() {
|
test("Traditional Line Breaks", function() {
|
||||||
|
|
Loading…
Reference in New Issue