REFACTOR: Split off raw handlebars helpers from compiler

This allows us to compile without Ember being present
This commit is contained in:
Robin Ward 2019-11-01 11:01:16 -04:00
parent 4e07f725c6
commit 785ebb674d
5 changed files with 73 additions and 87 deletions

View File

@ -1,4 +1,4 @@
import { rawGet } from "discourse-common/lib/raw-handlebars";
import { get } from "@ember/object";
export function htmlHelper(fn) {
return Ember.Helper.helper(function(...args) {
@ -10,6 +10,17 @@ export function htmlHelper(fn) {
const _helpers = {};
function rawGet(ctx, property, options) {
if (options.types && options.data.view) {
var view = options.data.view;
return view.getStream
? view.getStream(property).value()
: view.getAttr(property);
} else {
return get(ctx, property);
}
}
export function registerHelper(name, fn) {
_helpers[name] = Ember.Helper.helper(fn);
}

View File

@ -0,0 +1,44 @@
import { get } from "@ember/object";
export function registerRawHelpers(hbs, handlebarsClass) {
hbs.helper = function() {};
hbs.helpers = Object.create(handlebarsClass.helpers);
hbs.helpers["get"] = function(context, options) {
var firstContext = options.contexts[0];
var val = firstContext[context];
if (context.indexOf("controller.") === 0) {
context = context.slice(context.indexOf(".") + 1);
}
return val === undefined ? get(firstContext, context) : val;
};
// #each .. in support (as format is transformed to this)
hbs.registerHelper("each", function(
localName,
inKeyword,
contextName,
options
) {
var list = get(this, contextName);
var output = [];
var innerContext = Object.create(this);
for (var i = 0; i < list.length; i++) {
innerContext[localName] = list[i];
output.push(options.fn(innerContext));
}
return output.join("");
});
function stringCompatHelper(fn) {
const old = hbs.helpers[fn];
hbs.helpers[fn] = function(context, options) {
return old.apply(this, [hbs.helpers.get(context, options), options]);
};
}
stringCompatHelper("if");
stringCompatHelper("unless");
stringCompatHelper("with");
}

View File

@ -1,66 +1,9 @@
import { get } from "@ember/object";
// This 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
// compat with ie8 in case this gets picked up elsewhere
const objectCreate =
Object.create ||
function(parent) {
function F() {}
F.prototype = parent;
return new F();
};
const RawHandlebars = Handlebars.create();
RawHandlebars.helper = function() {};
RawHandlebars.helpers = objectCreate(Handlebars.helpers);
RawHandlebars.helpers["get"] = function(context, options) {
var firstContext = options.contexts[0];
var val = firstContext[context];
if (context.indexOf("controller.") === 0) {
context = context.slice(context.indexOf(".") + 1);
}
return val === undefined ? get(firstContext, context) : val;
};
// adds compatability so this works with stringParams
function stringCompatHelper(fn) {
const old = RawHandlebars.helpers[fn];
RawHandlebars.helpers[fn] = function(context, options) {
return old.apply(this, [
RawHandlebars.helpers.get(context, options),
options
]);
};
}
// #each .. in support (as format is transformed to this)
RawHandlebars.registerHelper("each", function(
localName,
inKeyword,
contextName,
options
) {
var list = get(this, contextName);
var output = [];
var innerContext = objectCreate(this);
for (var i = 0; i < list.length; i++) {
innerContext[localName] = list[i];
output.push(options.fn(innerContext));
}
return output.join("");
});
stringCompatHelper("if");
stringCompatHelper("unless");
stringCompatHelper("with");
function buildPath(blk, args) {
var result = {
type: "PathExpression",
@ -115,14 +58,14 @@ function replaceGet(ast) {
if (Handlebars.Compiler) {
RawHandlebars.Compiler = function() {};
RawHandlebars.Compiler.prototype = objectCreate(
RawHandlebars.Compiler.prototype = Object.create(
Handlebars.Compiler.prototype
);
RawHandlebars.Compiler.prototype.compiler = RawHandlebars.Compiler;
RawHandlebars.JavaScriptCompiler = function() {};
RawHandlebars.JavaScriptCompiler.prototype = objectCreate(
RawHandlebars.JavaScriptCompiler.prototype = Object.create(
Handlebars.JavaScriptCompiler.prototype
);
RawHandlebars.JavaScriptCompiler.prototype.compiler =
@ -173,17 +116,6 @@ if (Handlebars.Compiler) {
};
}
RawHandlebars.get = function(ctx, property, options) {
if (options.types && options.data.view) {
var view = options.data.view;
return view.getStream
? view.getStream(property).value()
: view.getAttr(property);
} else {
return get(ctx, property);
}
};
export function template() {
return RawHandlebars.template.apply(this, arguments);
}
@ -196,8 +128,4 @@ export function compile() {
return RawHandlebars.compile.apply(this, arguments);
}
export function rawGet() {
return RawHandlebars.get.apply(this, arguments);
}
export default RawHandlebars;

View File

@ -1,4 +1,6 @@
import { registerHelpers } from "discourse-common/lib/helpers";
import RawHandlebars from "discourse-common/lib/raw-handlebars";
import { registerRawHelpers } from "discourse-common/lib/raw-handlebars-helpers";
export function autoLoadModules(container, registry) {
Object.keys(requirejs.entries).forEach(entry => {
@ -10,6 +12,7 @@ export function autoLoadModules(container, registry) {
}
});
registerHelpers(registry);
registerRawHelpers(RawHandlebars, Handlebars);
}
export default {

View File

@ -18,19 +18,19 @@ class Barber::Precompiler
# very hacky but lets us use ES6. I'm ashamed of this code -RW
transpiled = transpiled[0...transpiled.index('export ')]
@precompiler = StringIO.new <<END
var __RawHandlebars;
(function() {
#{transpiled};
__RawHandlebars = RawHandlebars;
})();
@precompiler = StringIO.new <<~END
var __RawHandlebars;
(function() {
#{transpiled};
__RawHandlebars = RawHandlebars;
})();
Barber = {
precompile: function(string) {
return __RawHandlebars.precompile(string, false).toString();
}
};
END
Barber = {
precompile: function(string) {
return __RawHandlebars.precompile(string, false).toString();
}
};
END
end
@precompiler