| /** |
| * @license Handlebars hbs 0.4.0 - Alex Sexton, but Handlebars has it's own licensing junk |
| * |
| * Available via the MIT or new BSD license. |
| * see: http://github.com/jrburke/require-cs for details on the plugin this was based off of |
| */ |
| |
| /* Yes, deliciously evil. */ |
| /*jslint evil: true, strict: false, plusplus: false, regexp: false */ |
| /*global require: false, XMLHttpRequest: false, ActiveXObject: false, |
| define: false, process: false, window: false */ |
| define([ |
| //>>excludeStart('excludeHbs', pragmas.excludeHbs) |
| 'handlebars', 'underscore', 'i18nprecompile' |
| //>>excludeEnd('excludeHbs') |
| ], function( |
| //>>excludeStart('excludeHbs', pragmas.excludeHbs) |
| Handlebars, _, precompile |
| //>>excludeEnd('excludeHbs') |
| ) { |
| //>>excludeStart('excludeHbs', pragmas.excludeHbs) |
| var fs, getXhr, |
| progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'], |
| fetchText = function() { |
| throw new Error('Environment unsupported.'); |
| }, |
| buildMap = [], |
| filecode = "w+", |
| templateExtension = "hbs", |
| customNameExtension = "@hbs", |
| devStyleDirectory = "/styles/", |
| buildStyleDirectory = "/demo-build/styles/", |
| helperDirectory = "template/helpers/", |
| i18nDirectory = "template/i18n/", |
| buildCSSFileName = "screen.build.css"; |
| |
| Handlebars.registerHelper('$', function() { |
| //placeholder for translation helper |
| }); |
| |
| if (typeof window !== "undefined" && window.navigator && window.document && !window.navigator.userAgent.match(/Node.js/)) { |
| // Browser action |
| getXhr = function() { |
| //Would love to dump the ActiveX crap in here. Need IE 6 to die first. |
| var xhr, i, progId; |
| if (typeof XMLHttpRequest !== "undefined") { |
| return new XMLHttpRequest(); |
| } else { |
| for (i = 0; i < 3; i++) { |
| progId = progIds[i]; |
| try { |
| xhr = new ActiveXObject(progId); |
| } catch (e) {} |
| |
| if (xhr) { |
| progIds = [progId]; // so faster next time |
| break; |
| } |
| } |
| } |
| |
| if (!xhr) { |
| throw new Error("getXhr(): XMLHttpRequest not available"); |
| } |
| |
| return xhr; |
| }; |
| |
| fetchText = function(url, callback) { |
| var prependComment = "<!--START: " + url + "--> == <!--END: " + url + "-->"; |
| var xhr = getXhr(); |
| xhr.open('GET', url, true); |
| xhr.onreadystatechange = function(evt) { |
| //Do not explicitly handle errors, those should be |
| //visible via console output in the browser. |
| if (xhr.readyState === 4) { |
| callback(xhr.responseText); |
| //TODO FIXME Gautam:Not working with backbone-forms when it does this : $($.trim(this.template(_.result(this, 'templateData')))); |
| // callback(prependComment.replace('==',xhr.responseText)); |
| } |
| }; |
| xhr.send(null); |
| }; |
| |
| } else if (typeof process !== "undefined" && |
| process.versions && |
| !!process.versions.node) { |
| //Using special require.nodeRequire, something added by r.js. |
| fs = require.nodeRequire('fs'); |
| fetchText = function(path, callback) { |
| var body = fs.readFileSync(path, 'utf8') || ""; |
| // we need to remove BOM stuff from the file content |
| body = body.replace(/^\uFEFF/, ''); |
| callback(body); |
| }; |
| } else if (typeof java !== "undefined" && typeof java.io !== "undefined") { |
| fetchText = function(path, callback) { |
| var f = new java.io.File(path); |
| var is = new java.io.FileReader(f); |
| var reader = new java.io.BufferedReader(is); |
| var line; |
| var text = ""; |
| while ((line = reader.readLine()) !== null) { |
| text += new String(line) + "\n"; |
| } |
| reader.close(); |
| callback(text); |
| }; |
| } |
| |
| var cache = {}; |
| var fetchOrGetCached = function(path, callback) { |
| if (cache[path]) { |
| callback(cache[path]); |
| } else { |
| fetchText(path, function(data) { |
| cache[path] = data; |
| callback.call(this, data); |
| }); |
| } |
| }; |
| var styleList = [], |
| styleMap = {}; |
| //>>excludeEnd('excludeHbs') |
| |
| return { |
| |
| get: function() { |
| return Handlebars; |
| }, |
| |
| write: function(pluginName, name, write) { |
| |
| if ((name + customNameExtension) in buildMap) { |
| var text = buildMap[name + customNameExtension]; |
| write.asModule(pluginName + "!" + name, text); |
| } |
| }, |
| |
| version: '0.4.0', |
| |
| load: function(name, parentRequire, load, config) { |
| //>>excludeStart('excludeHbs', pragmas.excludeHbs) |
| |
| var compiledName = name + customNameExtension, |
| disableI18n = (config.hbs && config.hbs.disableI18n), |
| partialDeps = []; |
| |
| function recursiveNodeSearch(statements, res) { |
| _(statements).forEach(function(statement) { |
| if (statement && statement.type && statement.type === 'partial') { |
| res.push(statement.partialName.name); |
| } |
| if (statement && statement.program && statement.program.statements) { |
| recursiveNodeSearch(statement.program.statements, res); |
| } |
| if (statement && statement.program && statement.program.inverse && statement.program.inverse.statements) { |
| recursiveNodeSearch(statement.program.inverse.statements, res); |
| } |
| }); |
| return res; |
| } |
| |
| // TODO :: use the parser to do this! |
| function findPartialDeps(nodes) { |
| var res = []; |
| if (nodes && nodes.statements) { |
| res = recursiveNodeSearch(nodes.statements, []); |
| } |
| return _(res).unique(); |
| } |
| |
| // See if the first item is a comment that's json |
| function getMetaData(nodes) { |
| var statement, res, test; |
| if (nodes && nodes.statements) { |
| statement = nodes.statements[0]; |
| if (statement && statement.type === "comment") { |
| try { |
| res = (statement.comment).replace(new RegExp('^[\\s]+|[\\s]+$', 'g'), ''); |
| test = JSON.parse(res); |
| return res; |
| } catch (e) { |
| return "{}"; |
| } |
| } |
| } |
| return "{}"; |
| } |
| |
| function composeParts(parts) { |
| if (!parts) { |
| return []; |
| } |
| var res = [parts[0]], |
| cur = parts[0], |
| i; |
| |
| for (i = 1; i < parts.length; ++i) { |
| if (parts.hasOwnProperty(i)) { |
| cur += "." + parts[i]; |
| res.push(cur); |
| } |
| } |
| return res; |
| } |
| |
| function recursiveVarSearch(statements, res, prefix, helpersres) { |
| prefix = prefix ? prefix + "." : ""; |
| |
| var newprefix = "", |
| flag = false; |
| |
| // loop through each statement |
| _(statements).forEach(function(statement) { |
| var parts, part, sideways; |
| |
| // if it's a mustache block |
| if (statement && statement.type && statement.type === 'mustache') { |
| |
| // If it has params, the first part is a helper or something |
| if (!statement.params || !statement.params.length) { |
| parts = composeParts(statement.id.parts); |
| for (part in parts) { |
| if (parts[part]) { |
| newprefix = parts[part] || newprefix; |
| res.push(prefix + parts[part]); |
| } |
| } |
| res.push(prefix + statement.id.string); |
| } |
| |
| var paramsWithoutParts = ['this', '.', '..', './..', '../..', '../../..']; |
| |
| // grab the params |
| if (statement.params && typeof Handlebars.helpers[statement.id.string] === 'undefined') { |
| _(statement.params).forEach(function(param) { |
| if (_(paramsWithoutParts).contains(param.original) || param instanceof Handlebars.AST.StringNode || param instanceof Handlebars.AST.IntegerNode || param instanceof Handlebars.AST.BooleanNode) { |
| helpersres.push(statement.id.string); |
| } |
| |
| parts = composeParts(param.parts); |
| |
| for (var part in parts) { |
| if (parts[part]) { |
| newprefix = parts[part] || newprefix; |
| helpersres.push(statement.id.string); |
| res.push(prefix + parts[part]); |
| } |
| } |
| }); |
| } |
| } |
| |
| // If it's a meta block |
| if (statement && statement.mustache) { |
| recursiveVarSearch([statement.mustache], res, prefix + newprefix, helpersres); |
| } |
| |
| // if it's a whole new program |
| if (statement && statement.program && statement.program.statements) { |
| sideways = recursiveVarSearch([statement.mustache], [], "", helpersres)[0] || ""; |
| if (statement.program.inverse && statement.program.inverse.statements) { |
| recursiveVarSearch(statement.program.inverse.statements, res, prefix + newprefix + (sideways ? (prefix + newprefix) ? "." + sideways : sideways : ""), helpersres); |
| } |
| recursiveVarSearch(statement.program.statements, res, prefix + newprefix + (sideways ? (prefix + newprefix) ? "." + sideways : sideways : ""), helpersres); |
| } |
| }); |
| return res; |
| } |
| |
| // This finds the Helper dependencies since it's soooo similar |
| function getExternalDeps(nodes) { |
| var res = []; |
| var helpersres = []; |
| |
| if (nodes && nodes.statements) { |
| res = recursiveVarSearch(nodes.statements, [], undefined, helpersres); |
| } |
| |
| var defaultHelpers = ["helperMissing", "blockHelperMissing", "each", "if", "unless", "with"]; |
| |
| return { |
| vars: _(res).chain().unique().map(function(e) { |
| if (e === "") { |
| return '.'; |
| } |
| if (e.length && e[e.length - 1] === '.') { |
| return e.substr(0, e.length - 1) + '[]'; |
| } |
| return e; |
| }).value(), |
| helpers: _(helpersres).chain().unique().map(function(e) { |
| if (_(defaultHelpers).contains(e)) { |
| return undefined; |
| } |
| return e; |
| }).compact().value() |
| }; |
| } |
| |
| function fetchAndRegister(langMap) { |
| fetchText(path, function(text) { |
| // for some reason it doesn't include hbs _first_ when i don't add it here... |
| var nodes = Handlebars.parse(text), |
| deps = findPartialDeps(nodes), |
| meta = getMetaData(nodes), |
| extDeps = getExternalDeps(nodes), |
| vars = extDeps.vars, |
| helps = extDeps.helpers || [], |
| depStr = deps.join("', 'hbs!").replace(/_/g, '/'), |
| helpDepStr = config.hbs && config.hbs.disableHelpers ? |
| "" : (function() { |
| var i, paths = [], |
| pathGetter = config.hbs && config.hbs.helperPathCallback ? config.hbs.helperPathCallback : function(name) { |
| return (config.hbs && config.hbs.helperDirectory ? config.hbs.helperDirectory : helperDirectory) + name; |
| }; |
| |
| for (i = 0; i < helps.length; i++) { |
| paths[i] = "'" + pathGetter(helps[i], path) + "'" |
| } |
| return paths; |
| })().join(','), |
| debugOutputStart = "", |
| debugOutputEnd = "", |
| debugProperties = "", |
| metaObj, head, linkElem; |
| |
| if (depStr) { |
| depStr = ",'hbs!" + depStr + "'"; |
| } |
| if (helpDepStr) { |
| helpDepStr = "," + helpDepStr; |
| } |
| |
| if (meta !== "{}") { |
| try { |
| metaObj = JSON.parse(meta); |
| if (metaObj && metaObj.styles) { |
| styleList = _.union(styleList, metaObj.styles); |
| |
| // In dev mode in the browser |
| if (require.isBrowser && !config.isBuild) { |
| head = document.head || document.getElementsByTagName('head')[0]; |
| _(metaObj.styles).forEach(function(style) { |
| if (!styleMap[style]) { |
| linkElem = document.createElement('link'); |
| linkElem.href = config.baseUrl + devStyleDirectory + style + '.css'; |
| linkElem.media = 'all'; |
| linkElem.rel = 'stylesheet'; |
| linkElem.type = 'text/css'; |
| head.appendChild(linkElem); |
| styleMap[style] = linkElem; |
| } |
| }); |
| } else if (config.isBuild) { |
| (function() { |
| var fs = require.nodeRequire('fs'), |
| str = _(metaObj.styles).map(function(style) { |
| if (!styleMap[style]) { |
| styleMap[style] = true; |
| return "@import url(" + style + ".css);\n"; |
| } |
| return ""; |
| }).join("\n"); |
| |
| // I write out my import statements to a file in order to help me build stuff. |
| // Then I use a tool to inline my import statements afterwards. (you can run r.js on it too) |
| fs.open(__dirname + buildStyleDirectory + buildCSSFileName, filecode, '0666', function(e, id) { |
| fs.writeSync(id, str, null, encoding = 'utf8'); |
| fs.close(id); |
| }); |
| filecode = "a"; |
| })(); |
| } |
| } |
| } catch (e) { |
| console.log('error injecting styles'); |
| } |
| } |
| |
| if (!config.isBuild && !config.serverRender) { |
| debugOutputStart = "<!-- START - " + name + " -->"; |
| debugOutputEnd = "<!-- END - " + name + " -->"; |
| debugProperties = "t.meta = " + meta + ";\n" + |
| "t.helpers = " + JSON.stringify(helps) + ";\n" + |
| "t.deps = " + JSON.stringify(deps) + ";\n" + |
| "t.vars = " + JSON.stringify(vars) + ";\n"; |
| } |
| |
| var mapping = disableI18n ? false : _.extend(langMap, config.localeMapping), |
| configHbs = config.hbs || {}, |
| options = _.extend(configHbs.compileOptions || {}, { |
| originalKeyFallback: configHbs.originalKeyFallback |
| }), |
| prec = precompile(text, mapping, options); |
| |
| text = "/* START_TEMPLATE */\n" + |
| "define(['hbs','handlebars'" + depStr + helpDepStr + "], function( hbs, Handlebars ){ \n" + |
| "var t = Handlebars.template(" + prec + ");\n" + |
| "Handlebars.registerPartial('" + name.replace(/\//g, '_') + "', t);\n" + |
| debugProperties + |
| "return t;\n" + |
| "});\n" + |
| "/* END_TEMPLATE */\n"; |
| |
| //Hold on to the transformed text if a build. |
| if (config.isBuild) { |
| buildMap[compiledName] = text; |
| } |
| |
| //IE with conditional comments on cannot handle the |
| //sourceURL trick, so skip it if enabled. |
| /*@if (@_jscript) @else @*/ |
| if (!config.isBuild) { |
| text += "\r\n//@ sourceURL=" + path; |
| } |
| /*@end@*/ |
| |
| for (var i in deps) { |
| if (deps.hasOwnProperty(i)) { |
| deps[i] = 'hbs!' + deps[i].replace(/_/g, '/'); |
| } |
| } |
| |
| if (!config.isBuild) { |
| require(deps, function() { |
| load.fromText(text); |
| |
| //Give result to load. Need to wait until the module |
| //is fully parse, which will happen after this |
| //execution. |
| parentRequire([name], function(value) { |
| load(value); |
| }); |
| }); |
| } else { |
| load.fromText(name, text); |
| |
| //Give result to load. Need to wait until the module |
| //is fully parse, which will happen after this |
| //execution. |
| parentRequire([name], function(value) { |
| load(value); |
| }); |
| } |
| |
| if (config.removeCombined) { |
| fs.unlinkSync(path); |
| } |
| }); |
| } |
| |
| var path, |
| omitExtension = config.hbs && config.hbs.templateExtension === false; |
| if (omitExtension) { |
| path = parentRequire.toUrl(name); |
| } else { |
| path = parentRequire.toUrl(name + '.' + (config.hbs && config.hbs.templateExtension ? config.hbs.templateExtension : templateExtension)); |
| } |
| |
| if (disableI18n) { |
| fetchAndRegister(false); |
| } else { |
| // Workaround until jam is able to pass config info or we move i18n to a separate module. |
| // This logs a warning and disables i18n if there's an error loading the language file |
| var langMapPath = (config.hbs && config.hbs.i18nDirectory ? config.hbs.i18nDirectory : i18nDirectory) + (config.locale || "en_us") + '.json'; |
| try { |
| fetchOrGetCached(parentRequire.toUrl(langMapPath), function(langMap) { |
| fetchAndRegister(JSON.parse(langMap)); |
| }); |
| } catch (er) { |
| // if there's no configuration at all, log a warning and disable i18n for this and subsequent templates |
| if (!config.hbs) { |
| console.warn('hbs: Error reading ' + langMapPath + ', disabling i18n. Ignore this if you\'re using jam, otherwise check your i18n configuration.\n'); |
| config.hbs = { |
| disableI18n: true |
| }; |
| fetchAndRegister(false); |
| } else { |
| throw er; |
| |
| } |
| } |
| } |
| //>>excludeEnd('excludeHbs') |
| } |
| }; |
| }); |
| /* END_hbs_PLUGIN */ |