Skip to content

Commit

Permalink
Create an ember-htmlbars package and bring in all the deps. Again.
Browse files Browse the repository at this point in the history
  • Loading branch information
ebryn authored and mixonic committed Nov 9, 2014
1 parent 3e63200 commit bcd5c40
Show file tree
Hide file tree
Showing 5 changed files with 184 additions and 11 deletions.
35 changes: 24 additions & 11 deletions Brocfile.js
Expand Up @@ -86,7 +86,11 @@ function defeatureifyConfig(opts) {
/*
Returns a tree picked from `packages/#{packageName}/lib` and then move `main.js` to `/#{packageName}.js`.
*/
function vendoredPackage(packageName) {
function vendoredPackage(packageName, options) {
if (!options) { options = {}; }

var libPath = options.libPath || 'packages/' + packageName + '/lib';
var mainFile = options.mainFile || 'main.js';
/*
For example:
Given the following dir:
Expand All @@ -97,8 +101,8 @@ function vendoredPackage(packageName) {
/metamorph
└── main.js
*/
var libTree = pickFiles('packages/' + packageName + '/lib', {
files: ['main.js'],
var libTree = pickFiles(libPath, {
files: [ mainFile ],
srcDir: '/',
destDir: '/' + packageName
});
Expand All @@ -113,7 +117,7 @@ function vendoredPackage(packageName) {
└── metamorph.js
*/
var sourceTree = moveFile(libTree, {
srcFile: packageName + '/main.js',
srcFile: packageName + '/' + mainFile,
destFile: '/' + packageName + '.js'
});

Expand Down Expand Up @@ -337,14 +341,23 @@ var iifeStop = writeFile('iife-stop', '})();');
'ember-metal': {trees: null, vendorRequirements: ['backburner']}
```
*/
var handlebarsConfig = {
libPath: 'node_modules/handlebars/dist',
mainFile: 'handlebars.amd.js'
};

var vendoredPackages = {
'loader': vendoredPackage('loader'),
'rsvp': vendoredEs6Package('rsvp'),
'backburner': vendoredEs6Package('backburner'),
'router': vendoredEs6Package('router.js'),
'route-recognizer': vendoredEs6Package('route-recognizer'),
'dag-map': vendoredEs6Package('dag-map'),
'morph': htmlbarsPackage('morph')
'loader': vendoredPackage('loader'),
'rsvp': vendoredEs6Package('rsvp'),
'backburner': vendoredEs6Package('backburner'),
'router': vendoredEs6Package('router.js'),
'route-recognizer': vendoredEs6Package('route-recognizer'),
'dag-map': vendoredEs6Package('dag-map'),
'morph': htmlbarsPackage('morph'),
'htmlbars': htmlbarsPackage('htmlbars-runtime'),
'htmlbars-compiler': htmlbarsPackage('htmlbars-compiler'),
'simple-html-tokenizer': vendoredEs6Package('simple-html-tokenizer'),
'handlebars': vendoredPackage('handlebars', handlebarsConfig)
};

var emberHandlebarsCompiler = pickFiles('packages/ember-handlebars-compiler/lib', {
Expand Down
1 change: 1 addition & 0 deletions lib/packages.js
Expand Up @@ -9,6 +9,7 @@ module.exports = {
'ember-testing': {trees: null, requirements: ['ember-application', 'ember-routing'], developmentOnly: true},
'ember-handlebars-compiler': {trees: null, requirements: ['ember-views']},
'ember-handlebars': {trees: null, requirements: ['ember-views', 'ember-handlebars-compiler']},
'ember-htmlbars': {trees: null, vendorRequirements: ['htmlbars', 'handlebars', 'simple-html-tokenizer', 'htmlbars-compiler'], requirements: ['ember-metal-views']},
'ember-routing': {trees: null, vendorRequirements: ['router', 'route-recognizer'],
requirements: ['ember-runtime', 'ember-views']},
'ember-routing-handlebars': {trees: null, requirements: ['ember-routing', 'ember-handlebars']},
Expand Down
112 changes: 112 additions & 0 deletions packages/ember-htmlbars/lib/hooks.js
@@ -0,0 +1,112 @@
import Stream from "ember-metal/streams/stream";
import {readArray} from "ember-metal/streams/read";

function streamifyArgs(context, params, options, env) {
var hooks = env.hooks;

// TODO: Revisit keyword rewriting approach
if (params.length === 3 && params[1] === "in") {
params.splice(0, 3, {isKeyword: true, from: params[2], to: params[0]});
options.types.splice(0, 3, 'keyword');
}

if (params.length === 3 && params[1] === "as") {
params.splice(0, 3, {isKeyword: true, from: params[0], to: params[2]});
options.types.splice(0, 3, 'keyword');
}

// Convert ID params to streams
for (var i = 0, l = params.length; i < l; i++) {
if (options.types[i] === 'id') {
params[i] = hooks.streamFor(context, params[i]);
} else if (options.types[i] === 'keyword') {
params[i].lazyValue = hooks.streamFor(context, params[i].from);
}
}

// Convert hash ID values to streams
var hash = options.hash,
hashTypes = options.hashTypes;
for (var key in hash) {
if (hashTypes[key] === 'id') {
hash[key] = hooks.streamFor(context, hash[key]);
}
}
}

export function content(morph, path, context, params, options, env) {
var hooks = env.hooks;

// TODO: just set escaped on the morph in HTMLBars
morph.escaped = options.escaped;
var lazyValue;
var helper = hooks.lookupHelper(path, env);
if (helper) {
streamifyArgs(context, params, options, env);
lazyValue = helper(params, options, env);
} else {
lazyValue = hooks.streamFor(context, path);
}
if (lazyValue) {
lazyValue.subscribe(function(sender) {
morph.update(sender.value());
});

morph.update(lazyValue.value());
}
}

export function element(element, path, context, params, options, env) { //jshint ignore:line
var hooks = env.hooks;
var helper = hooks.lookupHelper(path, env);

if (helper) {
streamifyArgs(context, params, options, env);
return helper(element, params, options, env);
} else {
return hooks.streamFor(context, path);
}
}

export function subexpr(path, context, params, options, env) {
var hooks = env.hooks;
var helper = hooks.lookupHelper(path, env);

if (helper) {
streamifyArgs(context, params, options, env);
return helper(params, options, env);
} else {
return hooks.streamFor(context, path);
}
}

export function lookupHelper(name, env) {
if (name === 'concat') { return concat; }
if (name === 'attribute') { return attribute; }
return env.helpers[name];
}

function attribute(element, params, options) {
var name = params[0],
value = params[1];

value.subscribe(function(lazyValue) {
element.setAttribute(name, lazyValue.value());
});

element.setAttribute(name, value.value());
}

function concat(params, options) {
var stream = new Stream(function() {
return readArray(params).join('');
});

params.forEach(function(param) {
if (param && param.isStream) {
param.subscribe(stream.notifyAll, stream);
}
});

return stream;
}
24 changes: 24 additions & 0 deletions packages/ember-htmlbars/lib/main.js
@@ -0,0 +1,24 @@
import { content, element, subexpr, lookupHelper } from "ember-htmlbars/hooks";
import { DOMHelper } from "morph";
import Stream from "ember-metal/streams/stream";

export var defaultEnv = {
dom: new DOMHelper(),

hooks: {
content: content,
element: element,
subexpr: subexpr,
lookupHelper: lookupHelper,

streamFor: function(context, path) {
return new Stream(function() {
return context[path];
});
}
},

helpers: {

}
};
23 changes: 23 additions & 0 deletions packages/ember-htmlbars/tests/htmlbars_test.js
@@ -0,0 +1,23 @@
import { compile } from "htmlbars-compiler/compiler";
import { defaultEnv } from "ember-htmlbars";

function fragmentHTML(fragment) {
var html = '', node;
for (var i = 0, l = fragment.childNodes.length; i < l; i++) {
node = fragment.childNodes[i];
if (node.nodeType === 3) {
html += node.nodeValue;
} else {
html += node.outerHTML;
}
}
return html;
}

QUnit.module("ember-htmlbars");

test("hello world", function() {
var template = compile("ohai {{name}}");
var output = template({name: 'erik'}, defaultEnv, document.body);
equal(fragmentHTML(output), "ohai erik");
});

0 comments on commit bcd5c40

Please sign in to comment.