From 5729e7df6fe2c21cdb14d27dc77f8f67d0bbd0a3 Mon Sep 17 00:00:00 2001 From: Sam Date: Wed, 29 Oct 2014 15:24:51 +1100 Subject: [PATCH] PERF: use raw rendering for topic list rename my handlebars helper to "raw", create ember compat handlebars to handle rendering patch ember rails to use the correct precompiler --- .../helpers/{handlebars.js.es6 => raw.js.es6} | 6 +- .../discourse/lib/ember_compat_handlebars.js | 105 ++++++++++++++++++ .../templates/components/basic-topic-list.hbs | 2 +- .../templates/list/activity_column.raw.hbs | 2 +- .../templates/list/category_column.raw.hbs | 2 +- .../templates/list/posters_column.raw.hbs | 2 +- .../templates/list/topic_list_item.hbs | 6 +- .../mobile/components/basic-topic-list.hbs | 2 +- .../templates/mobile/list/topic_list_item.hbs | 2 +- app/assets/javascripts/main_include.js | 2 + .../ember_compat_handlebars.rb | 36 ++++++ 11 files changed, 153 insertions(+), 14 deletions(-) rename app/assets/javascripts/discourse/helpers/{handlebars.js.es6 => raw.js.es6} (66%) create mode 100644 app/assets/javascripts/discourse/lib/ember_compat_handlebars.js create mode 100644 lib/freedom_patches/ember_compat_handlebars.rb diff --git a/app/assets/javascripts/discourse/helpers/handlebars.js.es6 b/app/assets/javascripts/discourse/helpers/raw.js.es6 similarity index 66% rename from app/assets/javascripts/discourse/helpers/handlebars.js.es6 rename to app/assets/javascripts/discourse/helpers/raw.js.es6 index 18931346b..7c34fdfbf 100644 --- a/app/assets/javascripts/discourse/helpers/handlebars.js.es6 +++ b/app/assets/javascripts/discourse/helpers/raw.js.es6 @@ -1,4 +1,4 @@ -Handlebars.registerHelper('handlebars', function(property, options) { +Handlebars.registerHelper('raw', function(property, options) { var template = Em.TEMPLATES[property + ".raw"]; var params = options.hash; @@ -13,7 +13,3 @@ Handlebars.registerHelper('handlebars', function(property, options) { return new Handlebars.SafeString(template(params)); }); - -Handlebars.registerHelper('get', function(property) { - return Em.get(this, property); -}); diff --git a/app/assets/javascripts/discourse/lib/ember_compat_handlebars.js b/app/assets/javascripts/discourse/lib/ember_compat_handlebars.js new file mode 100644 index 000000000..587182552 --- /dev/null +++ b/app/assets/javascripts/discourse/lib/ember_compat_handlebars.js @@ -0,0 +1,105 @@ +// keep IIF for simpler testing + +// EmberCompatHandlebars is a mechanism for quickly rendering templates which is Ember aware +// templates are highly compatible with Ember so you don't need to worry about calling "get" +// and computed properties function, additionally it uses stringParams like Ember does + +(function(){ + + // compat with ie8 in case this gets picked up elsewhere + var objectCreate = Object.create || function(parent) { + function F() {} + F.prototype = parent; + return new F(); + }; + + + var RawHandlebars = objectCreate(Handlebars); + + RawHandlebars.helper = function() {}; + RawHandlebars.helpers = objectCreate(Handlebars.helpers); + + RawHandlebars.helpers.get = function(context, options){ + var firstContext = options.contexts[0]; + var val = firstContext[context]; + val = val === undefined ? Em.get(firstContext, context): val; + return val; + }; + + // adds compatability so this works with stringParams + var stringCompatHelper = function(fn){ + + var old = RawHandlebars.helpers[fn]; + RawHandlebars.helpers[fn] = function(context,options){ + return old.apply(this, [ + RawHandlebars.helpers.get(context,options), + options + ]); + }; + }; + + stringCompatHelper("each"); + stringCompatHelper("if"); + stringCompatHelper("unless"); + stringCompatHelper("with"); + + + RawHandlebars.Compiler = function() {}; + RawHandlebars.Compiler.prototype = objectCreate(Handlebars.Compiler.prototype); + RawHandlebars.Compiler.prototype.compiler = RawHandlebars.Compiler; + + RawHandlebars.JavaScriptCompiler = function() {}; + + RawHandlebars.JavaScriptCompiler.prototype = objectCreate(Handlebars.JavaScriptCompiler.prototype); + RawHandlebars.JavaScriptCompiler.prototype.compiler = RawHandlebars.JavaScriptCompiler; + RawHandlebars.JavaScriptCompiler.prototype.namespace = "Discourse.EmberCompatHandlebars"; + + + RawHandlebars.Compiler.prototype.mustache = function(mustache) { + if ( !(mustache.params.length || mustache.hash)) { + + var id = new Handlebars.AST.IdNode([{ part: 'get' }]); + + if (!mustache.escaped) { + mustache.hash = mustache.hash || new Handlebars.AST.HashNode([]); + mustache.hash.pairs.push(["unescaped", new Handlebars.AST.StringNode("true")]); + } + mustache = new Handlebars.AST.MustacheNode([id].concat([mustache.id]), mustache.hash, !mustache.escaped); + } + + return Handlebars.Compiler.prototype.mustache.call(this, mustache); + }; + + RawHandlebars.precompile = function(value, asObject) { + var ast = Handlebars.parse(value); + + var options = { + knownHelpers: { + get: true + }, + data: true, + stringParams: true + }; + + asObject = asObject === undefined ? true : asObject; + + var environment = new RawHandlebars.Compiler().compile(ast, options); + return new RawHandlebars.JavaScriptCompiler().compile(environment, options, undefined, asObject); + }; + + + RawHandlebars.compile = function(string) { + var ast = Handlebars.parse(string); + // this forces us to rewrite helpers + var options = { data: true, stringParams: true }; + var environment = new RawHandlebars.Compiler().compile(ast, options); + var templateSpec = new RawHandlebars.JavaScriptCompiler().compile(environment, options, undefined, true); + + var template = RawHandlebars.template(templateSpec); + + return template; + }; + + Discourse.EmberCompatHandlebars = RawHandlebars; + +})(); diff --git a/app/assets/javascripts/discourse/templates/components/basic-topic-list.hbs b/app/assets/javascripts/discourse/templates/components/basic-topic-list.hbs index 1cdf72cd3..ef4447b88 100644 --- a/app/assets/javascripts/discourse/templates/components/basic-topic-list.hbs +++ b/app/assets/javascripts/discourse/templates/components/basic-topic-list.hbs @@ -48,7 +48,7 @@ {{number topic.views numberKey="views_long"}} - {{handlebars "list/activity_column" topic=topic class="num" tagName="td"}} + {{raw "list/activity_column" topic=topic class="num" tagName="td"}} {{/grouped-each}} diff --git a/app/assets/javascripts/discourse/templates/list/activity_column.raw.hbs b/app/assets/javascripts/discourse/templates/list/activity_column.raw.hbs index 7f532c9b5..e74f1586f 100644 --- a/app/assets/javascripts/discourse/templates/list/activity_column.raw.hbs +++ b/app/assets/javascripts/discourse/templates/list/activity_column.raw.hbs @@ -1 +1 @@ -<{{this.tagName}} class="{{cold-age-class "topic.createdAt" startDate="topic.bumpedAt" class=this.class}} activity" title="{{get "topic.bumpedAtTitle"}}">{{format-date "topic.bumpedAt" format="tiny" noTitle=true}} +<{{this.tagName}} class="{{class}} {{cold-age-class topic.createdAt startDate=topic.bumpedAt class=""}} activity" title="{{topic.bumpedAtTitle}}">{{format-date topic.bumpedAt format="tiny" noTitle=true}} diff --git a/app/assets/javascripts/discourse/templates/list/category_column.raw.hbs b/app/assets/javascripts/discourse/templates/list/category_column.raw.hbs index 5978e08b4..0527596b0 100644 --- a/app/assets/javascripts/discourse/templates/list/category_column.raw.hbs +++ b/app/assets/javascripts/discourse/templates/list/category_column.raw.hbs @@ -1,3 +1,3 @@ {{#unless hideCategory}} -{{category-link "category" showParent=true}} +{{category-link category showParent=true}} {{/unless}} diff --git a/app/assets/javascripts/discourse/templates/list/posters_column.raw.hbs b/app/assets/javascripts/discourse/templates/list/posters_column.raw.hbs index b091db1aa..eae7670c3 100644 --- a/app/assets/javascripts/discourse/templates/list/posters_column.raw.hbs +++ b/app/assets/javascripts/discourse/templates/list/posters_column.raw.hbs @@ -1,5 +1,5 @@ {{#each posters}} -{{avatar this usernamePath="user.username" imageSize="small"}} +{{avatar this usernamePath="user.username" imageSize="small"}} {{/each}} diff --git a/app/assets/javascripts/discourse/templates/list/topic_list_item.hbs b/app/assets/javascripts/discourse/templates/list/topic_list_item.hbs index 3e108d328..87b1e9325 100644 --- a/app/assets/javascripts/discourse/templates/list/topic_list_item.hbs +++ b/app/assets/javascripts/discourse/templates/list/topic_list_item.hbs @@ -27,10 +27,10 @@ {{/if}} -{{handlebars "list/category_column" hideCategory=hideCategory category=category}} -{{handlebars "list/posters_column" posters=posters}} +{{raw "list/category_column" hideCategory=hideCategory category=category}} +{{raw "list/posters_column" posters=posters}} {{posts-count-column topic=model class="num" action="showTopicEntrance"}} {{number views numberKey="views_long"}} -{{handlebars "list/activity_column" topic=model class="num" tagName="td"}} +{{raw "list/activity_column" topic=model class="num" tagName="td"}} diff --git a/app/assets/javascripts/discourse/templates/mobile/components/basic-topic-list.hbs b/app/assets/javascripts/discourse/templates/mobile/components/basic-topic-list.hbs index 2b5f07508..57098274d 100644 --- a/app/assets/javascripts/discourse/templates/mobile/components/basic-topic-list.hbs +++ b/app/assets/javascripts/discourse/templates/mobile/components/basic-topic-list.hbs @@ -27,7 +27,7 @@
{{posts-count-column topic=topic tagName="div" class="num posts" action="clickedPosts"}} - {{handlebars "list/activity_column" topic=topic tagName="div" class="num activity last"}} + {{raw "list/activity_column" topic=topic tagName="div" class="num activity last"}}
{{#unless controller.hideCategory}}
diff --git a/app/assets/javascripts/discourse/templates/mobile/list/topic_list_item.hbs b/app/assets/javascripts/discourse/templates/mobile/list/topic_list_item.hbs index 7ba927d93..1d7908ccf 100644 --- a/app/assets/javascripts/discourse/templates/mobile/list/topic_list_item.hbs +++ b/app/assets/javascripts/discourse/templates/mobile/list/topic_list_item.hbs @@ -31,7 +31,7 @@ {{posts-count-column topic=this tagName="div" class="num posts" action="showTopicEntrance"}}
{{last_poster_username}} - {{handlebars "list/activity_column" topic=this tagName="span" class="age"}} + {{raw "list/activity_column" topic=this tagName="span" class="age"}}
diff --git a/app/assets/javascripts/main_include.js b/app/assets/javascripts/main_include.js index c6d4ef2d9..9cf9a5a39 100644 --- a/app/assets/javascripts/main_include.js +++ b/app/assets/javascripts/main_include.js @@ -8,8 +8,10 @@ // This is a BUG we should fix // it is only required here cause preview is not loading it using LAB //= require highlight.pack.js +// // Stuff we need to load first +//= require ./discourse/lib/ember_compat_handlebars //= require ./discourse/lib/computed //= require ./discourse/mixins/scrolling //= require_tree ./discourse/mixins diff --git a/lib/freedom_patches/ember_compat_handlebars.rb b/lib/freedom_patches/ember_compat_handlebars.rb new file mode 100644 index 000000000..978619472 --- /dev/null +++ b/lib/freedom_patches/ember_compat_handlebars.rb @@ -0,0 +1,36 @@ +# barber patches to re-route raw compilation via ember compat handlebars +# + +module Barber + class EmberCompatPrecompiler < Barber::Precompiler + + def self.call(template) + "Handlebars.template(#{compile(template)})" + end + + def sources + [handlebars, precompiler] + end + + def precompiler + @precompiler ||= StringIO.new <