From 127c3d0e21bf524aaf80e53b2fa24e2b86940b6d Mon Sep 17 00:00:00 2001 From: Robin Ward Date: Fri, 8 Nov 2013 11:42:26 -0500 Subject: [PATCH] FIX: Performance regression on Markdown renderer. --- .../javascripts/discourse/dialects/dialect.js | 24 +++++-- .../assets/javascripts/discourse_emoji.js | 71 ++++++++++++++----- 2 files changed, 70 insertions(+), 25 deletions(-) diff --git a/app/assets/javascripts/discourse/dialects/dialect.js b/app/assets/javascripts/discourse/dialects/dialect.js index 71ab8a27d..3edc4e641 100644 --- a/app/assets/javascripts/discourse/dialects/dialect.js +++ b/app/assets/javascripts/discourse/dialects/dialect.js @@ -156,6 +156,18 @@ Discourse.Dialect = { return html; }, + /** + Registers an inline replacer function + + @method registerInline + @param {String} start The token the replacement begins with + @param {Function} fn The replacing function + **/ + registerInline: function(start, fn) { + dialect.inline[start] = fn; + }, + + /** The simplest kind of replacement possible. Replace a stirng token with JsonML. @@ -173,9 +185,9 @@ Discourse.Dialect = { @param {Function} emitter A function that emits the JsonML for the replacement. **/ inlineReplace: function(token, emitter) { - dialect.inline[token] = function(text, match, prev) { + this.registerInline(token, function(text, match, prev) { return [token.length, emitter.call(this, token)]; - }; + }); }, /** @@ -205,7 +217,7 @@ Discourse.Dialect = { @param {Boolean} [opts.spaceBoundary] If true, the match must be on a sppace boundary **/ inlineRegexp: function(args) { - dialect.inline[args.start] = function(text, match, prev) { + this.registerInline(args.start, function(text, match, prev) { if (invalidBoundary(args, prev)) { return; } args.matcher.lastIndex = 0; @@ -216,7 +228,7 @@ Discourse.Dialect = { return [m[0].length, result]; } } - }; + }); }, /** @@ -252,7 +264,7 @@ Discourse.Dialect = { stop = args.stop || args.between, startLength = start.length; - dialect.inline[start] = function(text, match, prev) { + this.registerInline(start, function(text, match, prev) { if (invalidBoundary(args, prev)) { return; } var endPos = text.indexOf(stop, startLength); @@ -269,7 +281,7 @@ Discourse.Dialect = { if (contents) { return [endPos+stop.length, contents]; } - }; + }); }, /** diff --git a/vendor/gems/discourse_emoji/vendor/assets/javascripts/discourse_emoji.js b/vendor/gems/discourse_emoji/vendor/assets/javascripts/discourse_emoji.js index c2a2cfac7..58118a072 100644 --- a/vendor/gems/discourse_emoji/vendor/assets/javascripts/discourse_emoji.js +++ b/vendor/gems/discourse_emoji/vendor/assets/javascripts/discourse_emoji.js @@ -37,17 +37,50 @@ ":-$" : 'blush' }; - emoji.forEach(function (e) { - Discourse.Dialect.inlineReplace(":" + e + ":", function(code) { - return imageFor(e); - }); + var translationsWithColon = {}; + Object.keys(translations).forEach(function (t) { + if (t[0] === ':') { + translationsWithColon[t] = translations[t]; + } else { + var replacement = translations[t]; + Discourse.Dialect.inlineReplace(t, function () { + return imageFor(replacement); + }); + } }); - Object.keys(translations).forEach(function (code) { - var replacement = translations[code]; - Discourse.Dialect.inlineReplace(code, function (code) { - return imageFor(replacement); - }); + function escapeRegExp(s) { + return s.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&') + } + + var translationColonRegexp = new RegExp("^" + + Object.keys(translationsWithColon).map(function (t) { + return "(" + escapeRegExp(t) + ")"; + }).join("|") + ); + + Discourse.Dialect.registerInline(':', function(text, match, prev) { + var endPos = text.indexOf(':', 1), + contents; + + // If there is no trailing colon, check our translations that begin with colons + if (endPos === -1) { + translationColonRegexp.lastIndex = 0; + var match = translationColonRegexp.exec(text); + if (match && match[0]) { + contents = imageFor(translationsWithColon[match[0]]); + if (contents) { + return [match[0].length, contents]; + } + } + } + + // Simple find and replace from our array + var between = text.slice(1, endPos); + contents = imageFor(between); + if (contents) { + return [endPos+1, contents]; + } }); if (Discourse && Discourse.ComposerView) { @@ -56,16 +89,16 @@ var baseUrl = Discourse.getURL("/"); template = Handlebars.compile("
" + - "" + - "
"); + "" + + ""); $('#wmd-input').autocomplete({ template: template,