Comparing version 0.13.25 to 0.13.26
@@ -914,2 +914,4 @@ define('dom-helper', ['exports', './htmlbars-runtime/morph', './morph-attr', './dom-helper/build-html-dom', './dom-helper/classes', './dom-helper/prop'], function (exports, Morph, AttrMorph, build_html_dom, classes, prop) { | ||
function UNDEFINED() {} | ||
// TODO should this be an o_create kind of thing? | ||
@@ -924,3 +926,8 @@ var propertyCaches = {};function normalizeProperty(element, attrName) { | ||
for (key in element) { | ||
cache[key.toLowerCase()] = key; | ||
key = key.toLowerCase(); | ||
if (isSettable(element, key)) { | ||
cache[key] = key; | ||
} else { | ||
cache[key] = UNDEFINED; | ||
} | ||
} | ||
@@ -931,5 +938,38 @@ propertyCaches[tagName] = cache; | ||
// presumes that the attrName has been lowercased. | ||
return cache[attrName]; | ||
var value = cache[attrName]; | ||
return value === UNDEFINED ? undefined : value; | ||
} | ||
// elements with a property that does not conform to the spec in certain | ||
// browsers. In these cases, we'll end up using setAttribute instead | ||
var badPairs = [{ | ||
// phantomjs < 2.0 lets you set it as a prop but won't reflect it | ||
// back to the attribute. button.getAttribute('type') === null | ||
tagName: 'BUTTON', | ||
propName: 'type' | ||
}, { | ||
// Some version of IE (like IE9) actually throw an exception | ||
// if you set input.type = 'something-unknown' | ||
tagName: 'INPUT', | ||
propName: 'type' | ||
}, { | ||
// Some versions of IE (IE8) throw an exception when setting | ||
// `input.list = 'somestring'`: | ||
// https://github.com/emberjs/ember.js/issues/10908 | ||
// https://github.com/emberjs/ember.js/issues/11364 | ||
tagName: 'INPUT', | ||
propName: 'list' | ||
}]; | ||
function isSettable(element, attrName) { | ||
for (var i = 0, l = badPairs.length; i < l; i++) { | ||
var pair = badPairs[i]; | ||
if (pair.tagName === element.tagName && pair.propName === attrName) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
exports.propertyCaches = propertyCaches; | ||
@@ -936,0 +976,0 @@ |
@@ -67,4 +67,9 @@ define('htmlbars-util', ['exports', './htmlbars-util/safe-string', './htmlbars-util/handlebars/utils', './htmlbars-util/namespaces', './htmlbars-util/morph-utils'], function (exports, SafeString, utils, namespaces, morph_utils) { | ||
var isArray = Array.isArray || function (array) { | ||
return Object.prototype.toString.call(array) === '[object Array]'; | ||
}; | ||
var indexOfArray = getIdx; | ||
exports.isArray = isArray; | ||
exports.indexOfArray = indexOfArray; | ||
@@ -444,3 +449,3 @@ | ||
}); | ||
define('htmlbars-util/template-utils', ['exports', '../htmlbars-util/morph-utils'], function (exports, morph_utils) { | ||
define('htmlbars-util/template-utils', ['exports', '../htmlbars-util/morph-utils', './array-utils'], function (exports, morph_utils, array_utils) { | ||
@@ -498,3 +503,3 @@ 'use strict'; | ||
} | ||
if (typeof blocks === 'function') { | ||
if (typeof blocks === "function") { | ||
env.hooks.bindBlock(env, shadowScope, blocks); | ||
@@ -539,3 +544,3 @@ } else { | ||
if (toClear) { | ||
if (Object.prototype.toString.call(toClear) === '[object Array]') { | ||
if (array_utils.isArray(toClear)) { | ||
for (var i = 0, l = toClear.length; i < l; i++) { | ||
@@ -542,0 +547,0 @@ clearMorph(toClear[i], env); |
@@ -914,2 +914,4 @@ define('dom-helper', ['exports', './htmlbars-runtime/morph', './morph-attr', './dom-helper/build-html-dom', './dom-helper/classes', './dom-helper/prop'], function (exports, Morph, AttrMorph, build_html_dom, classes, prop) { | ||
function UNDEFINED() {} | ||
// TODO should this be an o_create kind of thing? | ||
@@ -924,3 +926,8 @@ var propertyCaches = {};function normalizeProperty(element, attrName) { | ||
for (key in element) { | ||
cache[key.toLowerCase()] = key; | ||
key = key.toLowerCase(); | ||
if (isSettable(element, key)) { | ||
cache[key] = key; | ||
} else { | ||
cache[key] = UNDEFINED; | ||
} | ||
} | ||
@@ -931,5 +938,38 @@ propertyCaches[tagName] = cache; | ||
// presumes that the attrName has been lowercased. | ||
return cache[attrName]; | ||
var value = cache[attrName]; | ||
return value === UNDEFINED ? undefined : value; | ||
} | ||
// elements with a property that does not conform to the spec in certain | ||
// browsers. In these cases, we'll end up using setAttribute instead | ||
var badPairs = [{ | ||
// phantomjs < 2.0 lets you set it as a prop but won't reflect it | ||
// back to the attribute. button.getAttribute('type') === null | ||
tagName: 'BUTTON', | ||
propName: 'type' | ||
}, { | ||
// Some version of IE (like IE9) actually throw an exception | ||
// if you set input.type = 'something-unknown' | ||
tagName: 'INPUT', | ||
propName: 'type' | ||
}, { | ||
// Some versions of IE (IE8) throw an exception when setting | ||
// `input.list = 'somestring'`: | ||
// https://github.com/emberjs/ember.js/issues/10908 | ||
// https://github.com/emberjs/ember.js/issues/11364 | ||
tagName: 'INPUT', | ||
propName: 'list' | ||
}]; | ||
function isSettable(element, attrName) { | ||
for (var i = 0, l = badPairs.length; i < l; i++) { | ||
var pair = badPairs[i]; | ||
if (pair.tagName === element.tagName && pair.propName === attrName) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
exports.propertyCaches = propertyCaches; | ||
@@ -936,0 +976,0 @@ |
@@ -195,2 +195,29 @@ 'use strict'; | ||
test("#setProperty uses setAttribute for special non-compliant element props", function () { | ||
expect(6); | ||
var badPairs = [{ tagName: "button", key: "type", value: "submit", selfClosing: false }, { tagName: "input", key: "type", value: "x-not-supported", selfClosing: true }]; | ||
badPairs.forEach(function (pair) { | ||
var node = dom.createElement(pair.tagName); | ||
var setAttribute = node.setAttribute; | ||
node.setAttribute = function (attrName, value) { | ||
equal(attrName, pair.key, "setAttribute called with correct attrName"); | ||
equal(value, pair.value, "setAttribute called with correct value"); | ||
return setAttribute.call(this, attrName, value); | ||
}; | ||
dom.setProperty(node, pair.key, pair.value); | ||
// e.g. <button type="submit"></button> | ||
var expected = "<" + pair.tagName + " " + pair.key + "=\"" + pair.value + "\">"; | ||
if (pair.selfClosing === false) { | ||
expected += "</" + pair.tagName + ">"; | ||
} | ||
htmlbars_test_helpers.equalHTML(node, expected, "output html is correct"); | ||
}); | ||
}); | ||
test("#addClasses", function () { | ||
@@ -197,0 +224,0 @@ var node = dom.createElement("div"); |
@@ -10,2 +10,4 @@ 'use strict'; | ||
function UNDEFINED() {} | ||
// TODO should this be an o_create kind of thing? | ||
@@ -20,3 +22,8 @@ var propertyCaches = {};function normalizeProperty(element, attrName) { | ||
for (key in element) { | ||
cache[key.toLowerCase()] = key; | ||
key = key.toLowerCase(); | ||
if (isSettable(element, key)) { | ||
cache[key] = key; | ||
} else { | ||
cache[key] = UNDEFINED; | ||
} | ||
} | ||
@@ -27,5 +34,38 @@ propertyCaches[tagName] = cache; | ||
// presumes that the attrName has been lowercased. | ||
return cache[attrName]; | ||
var value = cache[attrName]; | ||
return value === UNDEFINED ? undefined : value; | ||
} | ||
// elements with a property that does not conform to the spec in certain | ||
// browsers. In these cases, we'll end up using setAttribute instead | ||
var badPairs = [{ | ||
// phantomjs < 2.0 lets you set it as a prop but won't reflect it | ||
// back to the attribute. button.getAttribute('type') === null | ||
tagName: 'BUTTON', | ||
propName: 'type' | ||
}, { | ||
// Some version of IE (like IE9) actually throw an exception | ||
// if you set input.type = 'something-unknown' | ||
tagName: 'INPUT', | ||
propName: 'type' | ||
}, { | ||
// Some versions of IE (IE8) throw an exception when setting | ||
// `input.list = 'somestring'`: | ||
// https://github.com/emberjs/ember.js/issues/10908 | ||
// https://github.com/emberjs/ember.js/issues/11364 | ||
tagName: 'INPUT', | ||
propName: 'list' | ||
}]; | ||
function isSettable(element, attrName) { | ||
for (var i = 0, l = badPairs.length; i < l; i++) { | ||
var pair = badPairs[i]; | ||
if (pair.tagName === element.tagName && pair.propName === attrName) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} | ||
exports.propertyCaches = propertyCaches; |
@@ -660,3 +660,4 @@ 'use strict'; | ||
yieldTo: contentBlock, | ||
self: { attrs: hash } }); | ||
self: { attrs: hash } | ||
}); | ||
@@ -663,0 +664,0 @@ var elementBlock = template_utils.blockFor(render['default'], elementTemplate, { |
@@ -7,3 +7,3 @@ 'use strict'; | ||
var base = { | ||
acceptExpression: function (node, morph, env, scope) { | ||
acceptExpression: function (node, env, scope) { | ||
var ret = { value: null }; | ||
@@ -23,7 +23,7 @@ | ||
case "get": | ||
ret.value = this.get(node, morph, env, scope);break; | ||
ret.value = this.get(node, env, scope);break; | ||
case "subexpr": | ||
ret.value = this.subexpr(node, morph, env, scope);break; | ||
ret.value = this.subexpr(node, env, scope);break; | ||
case "concat": | ||
ret.value = this.concat(node, morph, env, scope);break; | ||
ret.value = this.concat(node, env, scope);break; | ||
} | ||
@@ -34,19 +34,7 @@ | ||
acceptParamsAndHash: function (env, scope, morph, path, params, hash) { | ||
params = params && this.acceptParams(params, morph, env, scope); | ||
hash = hash && this.acceptHash(hash, morph, env, scope); | ||
morph_utils.linkParams(env, scope, morph, path, params, hash); | ||
return [params, hash]; | ||
}, | ||
acceptParams: function (nodes, morph, env, scope) { | ||
if (morph.linkedParams) { | ||
return morph.linkedParams.params; | ||
} | ||
acceptParams: function (nodes, env, scope) { | ||
var arr = new Array(nodes.length); | ||
for (var i = 0, l = nodes.length; i < l; i++) { | ||
arr[i] = this.acceptExpression(nodes[i], morph, env, scope, null, null).value; | ||
arr[i] = this.acceptExpression(nodes[i], env, scope).value; | ||
} | ||
@@ -57,11 +45,7 @@ | ||
acceptHash: function (pairs, morph, env, scope) { | ||
if (morph.linkedParams) { | ||
return morph.linkedParams.hash; | ||
} | ||
acceptHash: function (pairs, env, scope) { | ||
var object = {}; | ||
for (var i = 0, l = pairs.length; i < l; i += 2) { | ||
object[pairs[i]] = this.acceptExpression(pairs[i + 1], morph, env, scope, null, null).value; | ||
object[pairs[i]] = this.acceptExpression(pairs[i + 1], env, scope).value; | ||
} | ||
@@ -73,3 +57,3 @@ | ||
// [ 'get', path ] | ||
get: function (node, morph, env, scope) { | ||
get: function (node, env, scope) { | ||
return env.hooks.get(env, scope, node[1]); | ||
@@ -79,12 +63,25 @@ }, | ||
// [ 'subexpr', path, params, hash ] | ||
subexpr: function (node, morph, env, scope) { | ||
subexpr: function (node, env, scope) { | ||
var path = node[1], | ||
params = node[2], | ||
hash = node[3]; | ||
return env.hooks.subexpr(env, scope, path, this.acceptParams(params, morph, env, scope), this.acceptHash(hash, morph, env, scope)); | ||
return env.hooks.subexpr(env, scope, path, this.acceptParams(params, env, scope), this.acceptHash(hash, env, scope)); | ||
}, | ||
// [ 'concat', parts ] | ||
concat: function (node, morph, env, scope) { | ||
return env.hooks.concat(env, this.acceptParams(node[1], morph, env, scope)); | ||
concat: function (node, env, scope) { | ||
return env.hooks.concat(env, this.acceptParams(node[1], env, scope)); | ||
}, | ||
linkParamsAndHash: function (env, scope, morph, path, params, hash) { | ||
if (morph.linkedParams) { | ||
params = morph.linkedParams.params; | ||
hash = morph.linkedParams.hash; | ||
} else { | ||
params = params && this.acceptParams(params, env, scope); | ||
hash = hash && this.acceptHash(hash, env, scope); | ||
} | ||
morph_utils.linkParams(env, scope, morph, path, params, hash); | ||
return [params, hash]; | ||
} | ||
@@ -101,3 +98,3 @@ }; | ||
inverseId = node[5]; | ||
var paramsAndHash = this.acceptParamsAndHash(env, scope, morph, path, params, hash); | ||
var paramsAndHash = this.linkParamsAndHash(env, scope, morph, path, params, hash); | ||
@@ -113,3 +110,3 @@ morph.isDirty = morph.isSubtreeDirty = false; | ||
hash = node[3]; | ||
var paramsAndHash = this.acceptParamsAndHash(env, scope, morph, path, params, hash); | ||
var paramsAndHash = this.linkParamsAndHash(env, scope, morph, path, params, hash); | ||
@@ -128,2 +125,5 @@ morph.isDirty = morph.isSubtreeDirty = false; | ||
env.hooks.inline(morph, env, scope, path, [], {}, visitor); | ||
if (morph.linkedResult) { | ||
morph_utils.linkParams(env, scope, morph, "@content-helper", [morph.linkedResult], null); | ||
} | ||
return; | ||
@@ -148,3 +148,3 @@ } | ||
hash = node[3]; | ||
var paramsAndHash = this.acceptParamsAndHash(env, scope, morph, path, params, hash); | ||
var paramsAndHash = this.linkParamsAndHash(env, scope, morph, path, params, hash); | ||
@@ -159,3 +159,3 @@ morph.isDirty = morph.isSubtreeDirty = false; | ||
value = node[2]; | ||
var paramsAndHash = this.acceptParamsAndHash(env, scope, morph, "@attribute", [value], null); | ||
var paramsAndHash = this.linkParamsAndHash(env, scope, morph, "@attribute", [value], null); | ||
@@ -172,3 +172,3 @@ morph.isDirty = morph.isSubtreeDirty = false; | ||
inverseId = node[4]; | ||
var paramsAndHash = this.acceptParamsAndHash(env, scope, morph, path, [], attrs); | ||
var paramsAndHash = this.linkParamsAndHash(env, scope, morph, path, [], attrs); | ||
var templates = { | ||
@@ -175,0 +175,0 @@ default: template.templates[templateId], |
@@ -684,3 +684,3 @@ 'use strict'; | ||
if (result && "value" in result) { | ||
value = result.value; | ||
value = env.hooks.getValue(result.value); | ||
hasValue = true; | ||
@@ -875,3 +875,3 @@ } | ||
if (result && "value" in result) { | ||
return result.value; | ||
return env.hooks.getValue(result.value); | ||
} | ||
@@ -878,0 +878,0 @@ } |
@@ -18,3 +18,3 @@ 'use strict'; | ||
test("blocks", function () { | ||
test("programs", function () { | ||
var ast = htmlbars_syntax.parse("\n {{#if foo}}\n {{bar}}\n {{/if}}\n "); | ||
@@ -27,2 +27,55 @@ | ||
locEqual(ast.body[1].program, 2, 2, 4, 7, "nested program"); | ||
}); | ||
test("blocks", function () { | ||
var ast = htmlbars_syntax.parse("\n {{#if foo}}\n {{#if bar}}\n test\n {{else}}\n test\n {{/if }}\n {{/if\n }}\n "); | ||
locEqual(ast.body[1], 2, 2, 9, 8, "outer block"); | ||
locEqual(ast.body[1].program.body[0], 3, 4, 7, 13, "nested block"); | ||
}); | ||
test("mustache", function () { | ||
var ast = htmlbars_syntax.parse("\n {{foo}}\n {{#if foo}}\n bar: {{bar\n }}\n {{/if}}\n "); | ||
locEqual(ast.body[1], 2, 4, 2, 11, "outer mustache"); | ||
locEqual(ast.body[3].program.body[1], 4, 11, 5, 10, "inner mustache"); | ||
}); | ||
test("element modifier", function () { | ||
var ast = htmlbars_syntax.parse("\n <div {{bind-attr\n foo\n bar=wat}}></div>\n "); | ||
locEqual(ast.body[1].modifiers[0], 2, 9, 4, 15, "element modifier"); | ||
}); | ||
test("html elements", function () { | ||
var ast = htmlbars_syntax.parse("\n <section>\n <br>\n <div>\n <hr />\n </div>\n </section>\n "); | ||
var _ast$body = ast.body; | ||
var section = _ast$body[1]; | ||
var _section$children = section.children; | ||
var br = _section$children[1]; | ||
var div = _section$children[3]; | ||
var _div$children = div.children; | ||
var hr = _div$children[1]; | ||
locEqual(section, 2, 4, 7, 14, "section element"); | ||
locEqual(br, 3, 6, 3, 10, "br element"); | ||
locEqual(div, 4, 6, 6, 12, "div element"); | ||
locEqual(hr, 5, 8, 5, 14, "hr element"); | ||
}); | ||
test("components", function () { | ||
var ast = htmlbars_syntax.parse("\n <el-page>\n <el-header></el-header>\n <el-input />\n <el-footer>\n </el-footer>\n </el-page>\n "); | ||
var _ast$body2 = ast.body; | ||
var page = _ast$body2[1]; | ||
var _page$program$body = page.program.body; | ||
var header = _page$program$body[1]; | ||
var input = _page$program$body[3]; | ||
var footer = _page$program$body[5]; | ||
locEqual(page, 2, 4, 7, 14, "page component"); | ||
locEqual(header, 3, 6, 3, 29, "header component"); | ||
locEqual(input, 4, 6, 4, 18, "input component"); | ||
locEqual(footer, 5, 6, 6, 22, "footer component"); | ||
}); |
@@ -24,3 +24,3 @@ 'use strict'; | ||
function buildMustache(path, params, hash, raw) { | ||
function buildMustache(path, params, hash, raw, loc) { | ||
return { | ||
@@ -31,7 +31,8 @@ type: "MustacheStatement", | ||
hash: hash || buildHash([]), | ||
escaped: !raw | ||
escaped: !raw, | ||
loc: buildLoc(loc) | ||
}; | ||
} | ||
function buildBlock(path, params, hash, program, inverse) { | ||
function buildBlock(path, params, hash, program, inverse, loc) { | ||
return { | ||
@@ -43,7 +44,8 @@ type: "BlockStatement", | ||
program: program || null, | ||
inverse: inverse || null | ||
inverse: inverse || null, | ||
loc: buildLoc(loc) | ||
}; | ||
} | ||
function buildElementModifier(path, params, hash) { | ||
function buildElementModifier(path, params, hash, loc) { | ||
return { | ||
@@ -53,3 +55,4 @@ type: "ElementModifierStatement", | ||
params: params || [], | ||
hash: hash || buildHash([]) | ||
hash: hash || buildHash([]), | ||
loc: buildLoc(loc) | ||
}; | ||
@@ -94,3 +97,3 @@ } | ||
function buildComponent(tag, attributes, program) { | ||
function buildComponent(tag, attributes, program, loc) { | ||
return { | ||
@@ -100,3 +103,4 @@ type: "ComponentNode", | ||
attributes: attributes, | ||
program: program | ||
program: program, | ||
loc: buildLoc(loc) | ||
}; | ||
@@ -103,0 +107,0 @@ } |
'use strict'; | ||
var builders = require('./builders'); | ||
var b = require('./builders'); | ||
var array_utils = require('../htmlbars-util/array-utils'); | ||
@@ -11,3 +11,3 @@ var utils = require('./utils'); | ||
var body = []; | ||
var node = builders.buildProgram(body, program.blockParams, program.loc); | ||
var node = b.buildProgram(body, program.blockParams, program.loc); | ||
var i, | ||
@@ -54,3 +54,3 @@ l = program.body.length; | ||
var node = builders.buildBlock(block.path, block.params, block.hash, program, inverse); | ||
var node = b.buildBlock(block.path, block.params, block.hash, program, inverse, block.loc); | ||
var parentProgram = this.currentElement(); | ||
@@ -60,5 +60,11 @@ utils.appendChild(parentProgram, node); | ||
MustacheStatement: function (mustache) { | ||
delete mustache.strip; | ||
MustacheStatement: function (rawMustache) { | ||
var path = rawMustache.path; | ||
var params = rawMustache.params; | ||
var hash = rawMustache.hash; | ||
var escaped = rawMustache.escaped; | ||
var loc = rawMustache.loc; | ||
var mustache = b['default'].mustache(path, params, hash, !escaped, loc); | ||
if (this.tokenizer.state === "comment") { | ||
@@ -162,3 +168,3 @@ this.tokenizer.addChar("{{" + this.sourceForMustache(mustache) + "}}"); | ||
} else { | ||
node.hash = builders.buildHash(); | ||
node.hash = b.buildHash(); | ||
} | ||
@@ -165,0 +171,0 @@ |
@@ -23,2 +23,3 @@ 'use strict'; | ||
element.loc = { | ||
source: null, | ||
start: { line: tag.loc.start.line, column: tag.loc.start.column }, | ||
@@ -91,2 +92,5 @@ end: { line: null, column: null } | ||
element.loc.end.line = tag.loc.end.line; | ||
element.loc.end.column = tag.loc.end.column; | ||
if (disableComponentGeneration || element.tag.indexOf("-") === -1) { | ||
@@ -97,3 +101,3 @@ utils.appendChild(parent, element); | ||
utils.parseComponentBlockParams(element, program); | ||
var component = builders.buildComponent(element.tag, element.attributes, program); | ||
var component = builders.buildComponent(element.tag, element.attributes, program, element.loc); | ||
utils.appendChild(parent, component); | ||
@@ -100,0 +104,0 @@ } |
@@ -63,3 +63,8 @@ 'use strict'; | ||
var modifier = builders['default'].elementModifier(mustache.path, mustache.params, mustache.hash); | ||
var path = mustache.path; | ||
var params = mustache.params; | ||
var hash = mustache.hash; | ||
var loc = mustache.loc; | ||
var modifier = builders['default'].elementModifier(path, params, hash, loc); | ||
this.token.modifiers.push(modifier); | ||
@@ -66,0 +71,0 @@ }; |
@@ -51,4 +51,9 @@ 'use strict'; | ||
var isArray = Array.isArray || function (array) { | ||
return Object.prototype.toString.call(array) === '[object Array]'; | ||
}; | ||
var indexOfArray = getIdx; | ||
exports.isArray = isArray; | ||
exports.indexOfArray = indexOfArray; |
@@ -9,2 +9,3 @@ 'use strict'; | ||
var morph_utils = require('../htmlbars-util/morph-utils'); | ||
var array_utils = require('./array-utils'); | ||
@@ -57,3 +58,3 @@ | ||
} | ||
if (typeof blocks === 'function') { | ||
if (typeof blocks === "function") { | ||
env.hooks.bindBlock(env, shadowScope, blocks); | ||
@@ -98,3 +99,3 @@ } else { | ||
if (toClear) { | ||
if (Object.prototype.toString.call(toClear) === '[object Array]') { | ||
if (array_utils.isArray(toClear)) { | ||
for (var i = 0, l = toClear.length; i < l; i++) { | ||
@@ -101,0 +102,0 @@ clearMorph(toClear[i], env); |
@@ -12,3 +12,3 @@ 'use strict'; | ||
* See https://raw.githubusercontent.com/tildeio/htmlbars/master/LICENSE | ||
* @version 0.13.25.19f7e05a | ||
* @version 0.13.26.ecb10c7a | ||
*/ | ||
@@ -15,0 +15,0 @@ |
@@ -5,2 +5,4 @@ export function isAttrRemovalValue(value) { | ||
function UNDEFINED() {} | ||
// TODO should this be an o_create kind of thing? | ||
@@ -17,3 +19,8 @@ export var propertyCaches = {}; | ||
for (key in element) { | ||
cache[key.toLowerCase()] = key; | ||
key = key.toLowerCase(); | ||
if (isSettable(element, key)) { | ||
cache[key] = key; | ||
} else { | ||
cache[key] = UNDEFINED; | ||
} | ||
} | ||
@@ -24,3 +31,36 @@ propertyCaches[tagName] = cache; | ||
// presumes that the attrName has been lowercased. | ||
return cache[attrName]; | ||
var value = cache[attrName]; | ||
return value === UNDEFINED ? undefined : value; | ||
} | ||
// elements with a property that does not conform to the spec in certain | ||
// browsers. In these cases, we'll end up using setAttribute instead | ||
var badPairs = [{ | ||
// phantomjs < 2.0 lets you set it as a prop but won't reflect it | ||
// back to the attribute. button.getAttribute('type') === null | ||
tagName: 'BUTTON', | ||
propName: 'type' | ||
}, { | ||
// Some version of IE (like IE9) actually throw an exception | ||
// if you set input.type = 'something-unknown' | ||
tagName: 'INPUT', | ||
propName: 'type' | ||
}, { | ||
// Some versions of IE (IE8) throw an exception when setting | ||
// `input.list = 'somestring'`: | ||
// https://github.com/emberjs/ember.js/issues/10908 | ||
// https://github.com/emberjs/ember.js/issues/11364 | ||
tagName: 'INPUT', | ||
propName: 'list' | ||
}]; | ||
function isSettable(element, attrName) { | ||
for (let i = 0, l = badPairs.length; i < l; i++) { | ||
let pair = badPairs[i]; | ||
if (pair.tagName === element.tagName && pair.propName === attrName) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
} |
@@ -34,3 +34,3 @@ import { merge, createObject } from "../htmlbars-util/object-utils"; | ||
var base = { | ||
acceptExpression: function(node, morph, env, scope) { | ||
acceptExpression: function(node, env, scope) { | ||
var ret = { value: null }; | ||
@@ -48,5 +48,5 @@ | ||
case 'value': ret.value = node[1]; break; | ||
case 'get': ret.value = this.get(node, morph, env, scope); break; | ||
case 'subexpr': ret.value = this.subexpr(node, morph, env, scope); break; | ||
case 'concat': ret.value = this.concat(node, morph, env, scope); break; | ||
case 'get': ret.value = this.get(node, env, scope); break; | ||
case 'subexpr': ret.value = this.subexpr(node, env, scope); break; | ||
case 'concat': ret.value = this.concat(node, env, scope); break; | ||
} | ||
@@ -57,19 +57,7 @@ | ||
acceptParamsAndHash: function(env, scope, morph, path, params, hash) { | ||
params = params && this.acceptParams(params, morph, env, scope); | ||
hash = hash && this.acceptHash(hash, morph, env, scope); | ||
linkParams(env, scope, morph, path, params, hash); | ||
return [params, hash]; | ||
}, | ||
acceptParams: function(nodes, morph, env, scope) { | ||
if (morph.linkedParams) { | ||
return morph.linkedParams.params; | ||
} | ||
acceptParams: function(nodes, env, scope) { | ||
var arr = new Array(nodes.length); | ||
for (var i=0, l=nodes.length; i<l; i++) { | ||
arr[i] = this.acceptExpression(nodes[i], morph, env, scope, null, null).value; | ||
arr[i] = this.acceptExpression(nodes[i], env, scope).value; | ||
} | ||
@@ -80,11 +68,7 @@ | ||
acceptHash: function(pairs, morph, env, scope) { | ||
if (morph.linkedParams) { | ||
return morph.linkedParams.hash; | ||
} | ||
acceptHash: function(pairs, env, scope) { | ||
var object = {}; | ||
for (var i=0, l=pairs.length; i<l; i += 2) { | ||
object[pairs[i]] = this.acceptExpression(pairs[i+1], morph, env, scope, null, null).value; | ||
object[pairs[i]] = this.acceptExpression(pairs[i+1], env, scope).value; | ||
} | ||
@@ -96,3 +80,3 @@ | ||
// [ 'get', path ] | ||
get: function(node, morph, env, scope) { | ||
get: function(node, env, scope) { | ||
return env.hooks.get(env, scope, node[1]); | ||
@@ -102,12 +86,25 @@ }, | ||
// [ 'subexpr', path, params, hash ] | ||
subexpr: function(node, morph, env, scope) { | ||
subexpr: function(node, env, scope) { | ||
var path = node[1], params = node[2], hash = node[3]; | ||
return env.hooks.subexpr(env, scope, path, | ||
this.acceptParams(params, morph, env, scope), | ||
this.acceptHash(hash, morph, env, scope)); | ||
this.acceptParams(params, env, scope), | ||
this.acceptHash(hash, env, scope)); | ||
}, | ||
// [ 'concat', parts ] | ||
concat: function(node, morph, env, scope) { | ||
return env.hooks.concat(env, this.acceptParams(node[1], morph, env, scope)); | ||
concat: function(node, env, scope) { | ||
return env.hooks.concat(env, this.acceptParams(node[1], env, scope)); | ||
}, | ||
linkParamsAndHash: function(env, scope, morph, path, params, hash) { | ||
if (morph.linkedParams) { | ||
params = morph.linkedParams.params; | ||
hash = morph.linkedParams.hash; | ||
} else { | ||
params = params && this.acceptParams(params, env, scope); | ||
hash = hash && this.acceptHash(hash, env, scope); | ||
} | ||
linkParams(env, scope, morph, path, params, hash); | ||
return [params, hash]; | ||
} | ||
@@ -120,3 +117,3 @@ }; | ||
var path = node[1], params = node[2], hash = node[3], templateId = node[4], inverseId = node[5]; | ||
var paramsAndHash = this.acceptParamsAndHash(env, scope, morph, path, params, hash); | ||
var paramsAndHash = this.linkParamsAndHash(env, scope, morph, path, params, hash); | ||
@@ -133,3 +130,3 @@ morph.isDirty = morph.isSubtreeDirty = false; | ||
var path = node[1], params = node[2], hash = node[3]; | ||
var paramsAndHash = this.acceptParamsAndHash(env, scope, morph, path, params, hash); | ||
var paramsAndHash = this.linkParamsAndHash(env, scope, morph, path, params, hash); | ||
@@ -148,2 +145,5 @@ morph.isDirty = morph.isSubtreeDirty = false; | ||
env.hooks.inline(morph, env, scope, path, [], {}, visitor); | ||
if (morph.linkedResult) { | ||
linkParams(env, scope, morph, '@content-helper', [morph.linkedResult], null); | ||
} | ||
return; | ||
@@ -166,3 +166,3 @@ } | ||
var path = node[1], params = node[2], hash = node[3]; | ||
var paramsAndHash = this.acceptParamsAndHash(env, scope, morph, path, params, hash); | ||
var paramsAndHash = this.linkParamsAndHash(env, scope, morph, path, params, hash); | ||
@@ -176,3 +176,3 @@ morph.isDirty = morph.isSubtreeDirty = false; | ||
var name = node[1], value = node[2]; | ||
var paramsAndHash = this.acceptParamsAndHash(env, scope, morph, '@attribute', [value], null); | ||
var paramsAndHash = this.linkParamsAndHash(env, scope, morph, '@attribute', [value], null); | ||
@@ -186,3 +186,3 @@ morph.isDirty = morph.isSubtreeDirty = false; | ||
var path = node[1], attrs = node[2], templateId = node[3], inverseId = node[4]; | ||
var paramsAndHash = this.acceptParamsAndHash(env, scope, morph, path, [], attrs); | ||
var paramsAndHash = this.linkParamsAndHash(env, scope, morph, path, [], attrs); | ||
var templates = { | ||
@@ -189,0 +189,0 @@ default: template.templates[templateId], |
@@ -699,3 +699,3 @@ import render from "./render"; | ||
if (result && 'value' in result) { | ||
value = result.value; | ||
value = env.hooks.getValue(result.value); | ||
hasValue = true; | ||
@@ -916,3 +916,3 @@ } | ||
var result = env.hooks.invokeHelper(null, env, scope, null, params, hash, helper, {}); | ||
if (result && 'value' in result) { return result.value; } | ||
if (result && 'value' in result) { return env.hooks.getValue(result.value); } | ||
} | ||
@@ -919,0 +919,0 @@ |
// Statements | ||
export function buildMustache(path, params, hash, raw) { | ||
export function buildMustache(path, params, hash, raw, loc) { | ||
return { | ||
@@ -9,7 +9,8 @@ type: "MustacheStatement", | ||
hash: hash || buildHash([]), | ||
escaped: !raw | ||
escaped: !raw, | ||
loc: buildLoc(loc) | ||
}; | ||
} | ||
export function buildBlock(path, params, hash, program, inverse) { | ||
export function buildBlock(path, params, hash, program, inverse, loc) { | ||
return { | ||
@@ -21,7 +22,8 @@ type: "BlockStatement", | ||
program: program || null, | ||
inverse: inverse || null | ||
inverse: inverse || null, | ||
loc: buildLoc(loc) | ||
}; | ||
} | ||
export function buildElementModifier(path, params, hash) { | ||
export function buildElementModifier(path, params, hash, loc) { | ||
return { | ||
@@ -31,3 +33,4 @@ type: "ElementModifierStatement", | ||
params: params || [], | ||
hash: hash || buildHash([]) | ||
hash: hash || buildHash([]), | ||
loc: buildLoc(loc) | ||
}; | ||
@@ -72,3 +75,3 @@ } | ||
export function buildComponent(tag, attributes, program) { | ||
export function buildComponent(tag, attributes, program, loc) { | ||
return { | ||
@@ -78,3 +81,4 @@ type: "ComponentNode", | ||
attributes: attributes, | ||
program: program | ||
program: program, | ||
loc: buildLoc(loc) | ||
}; | ||
@@ -81,0 +85,0 @@ } |
@@ -0,1 +1,2 @@ | ||
import b from "./builders"; | ||
import { buildProgram, buildBlock, buildHash } from "./builders"; | ||
@@ -48,3 +49,3 @@ import { forEach } from "../htmlbars-util/array-utils"; | ||
var node = buildBlock(block.path, block.params, block.hash, program, inverse); | ||
var node = buildBlock(block.path, block.params, block.hash, program, inverse, block.loc); | ||
var parentProgram = this.currentElement(); | ||
@@ -54,4 +55,5 @@ appendChild(parentProgram, node); | ||
MustacheStatement: function(mustache) { | ||
delete mustache.strip; | ||
MustacheStatement: function(rawMustache) { | ||
let { path, params, hash, escaped, loc } = rawMustache; | ||
let mustache = b.mustache(path, params, hash, !escaped, loc); | ||
@@ -58,0 +60,0 @@ if (this.tokenizer.state === 'comment') { |
@@ -26,2 +26,3 @@ import { buildProgram, buildComponent, buildElement, buildComment, buildText } from "./builders"; | ||
element.loc = { | ||
source: null, | ||
start: { line: tag.loc.start.line, column: tag.loc.start.column}, | ||
@@ -94,2 +95,5 @@ end: { line: null, column: null} | ||
element.loc.end.line = tag.loc.end.line; | ||
element.loc.end.column = tag.loc.end.column; | ||
if (disableComponentGeneration || element.tag.indexOf("-") === -1) { | ||
@@ -100,3 +104,3 @@ appendChild(parent, element); | ||
parseComponentBlockParams(element, program); | ||
var component = buildComponent(element.tag, element.attributes, program); | ||
var component = buildComponent(element.tag, element.attributes, program, element.loc); | ||
appendChild(parent, component); | ||
@@ -103,0 +107,0 @@ } |
@@ -63,3 +63,4 @@ import { Tokenizer } from "../simple-html-tokenizer"; | ||
var modifier = builders.elementModifier(mustache.path, mustache.params, mustache.hash); | ||
let { path, params, hash, loc } = mustache; | ||
var modifier = builders.elementModifier(path, params, hash, loc); | ||
this.token.modifiers.push(modifier); | ||
@@ -66,0 +67,0 @@ }; |
@@ -46,2 +46,6 @@ export function forEach(array, callback, binding) { | ||
export var indexOfArray = getIdx; | ||
export var isArray = (Array.isArray || function(array) { | ||
return Object.prototype.toString.call(array) === '[object Array]'; | ||
}); | ||
export var indexOfArray = getIdx; |
import { visitChildren } from "../htmlbars-util/morph-utils"; | ||
import { isArray } from "./array-utils"; | ||
@@ -88,3 +89,3 @@ export function RenderState(renderNode) { | ||
if (toClear) { | ||
if (Object.prototype.toString.call(toClear) === '[object Array]') { | ||
if (isArray(toClear)) { | ||
for (var i=0, l=toClear.length; i<l; i++) { | ||
@@ -91,0 +92,0 @@ clearMorph(toClear[i], env); |
@@ -6,3 +6,3 @@ /* | ||
* See https://raw.githubusercontent.com/tildeio/htmlbars/master/LICENSE | ||
* @version 0.13.25.19f7e05a | ||
* @version 0.13.26.ecb10c7a | ||
*/ | ||
@@ -9,0 +9,0 @@ |
@@ -244,2 +244,29 @@ define('dom-helper-tests/dom-helper-node-test', ['../dom-helper'], function (DOMHelper) { | ||
test("#setProperty uses setAttribute for special non-compliant element props", function () { | ||
expect(6); | ||
var badPairs = [{ tagName: "button", key: "type", value: "submit", selfClosing: false }, { tagName: "input", key: "type", value: "x-not-supported", selfClosing: true }]; | ||
badPairs.forEach(function (pair) { | ||
var node = dom.createElement(pair.tagName); | ||
var setAttribute = node.setAttribute; | ||
node.setAttribute = function (attrName, value) { | ||
equal(attrName, pair.key, "setAttribute called with correct attrName"); | ||
equal(value, pair.value, "setAttribute called with correct value"); | ||
return setAttribute.call(this, attrName, value); | ||
}; | ||
dom.setProperty(node, pair.key, pair.value); | ||
// e.g. <button type="submit"></button> | ||
var expected = "<" + pair.tagName + " " + pair.key + "=\"" + pair.value + "\">"; | ||
if (pair.selfClosing === false) { | ||
expected += "</" + pair.tagName + ">"; | ||
} | ||
htmlbars_test_helpers.equalHTML(node, expected, "output html is correct"); | ||
}); | ||
}); | ||
test("#addClasses", function () { | ||
@@ -752,2 +779,40 @@ var node = dom.createElement("div"); | ||
}); | ||
define('dom-helper-tests/prop-test', ['dom-helper/prop'], function (prop) { | ||
'use strict'; | ||
QUnit.module('dom-helper prop'); | ||
test('returns `undefined` for special element properties that are non-compliant in certain browsers', function () { | ||
expect(3); | ||
var badPairs = [{ tagName: 'BUTTON', key: 'type' }, { tagName: 'INPUT', key: 'type' }, { tagName: 'INPUT', key: 'list' }]; | ||
badPairs.forEach(function (pair) { | ||
var element = { | ||
tagName: pair.tagName | ||
}; | ||
Object.defineProperty(element, pair.key, { | ||
set: function () { | ||
throw new Error('I am a bad browser!'); | ||
} | ||
}); | ||
var actual = prop.normalizeProperty(element, pair.key); | ||
equal(actual, undefined); | ||
}); | ||
}); | ||
}); | ||
define('dom-helper-tests/prop-test.jshint', function () { | ||
'use strict'; | ||
module('JSHint - dom-helper-tests'); | ||
test('dom-helper-tests/prop-test.js should pass jshint', function () { | ||
ok(true, 'dom-helper-tests/prop-test.js should pass jshint.'); | ||
}); | ||
}); | ||
define('htmlbars-test-helpers', ['exports', '../simple-html-tokenizer', '../htmlbars-util/array-utils'], function (exports, simple_html_tokenizer, array_utils) { | ||
@@ -1018,4 +1083,9 @@ | ||
var isArray = Array.isArray || function (array) { | ||
return Object.prototype.toString.call(array) === '[object Array]'; | ||
}; | ||
var indexOfArray = getIdx; | ||
exports.isArray = isArray; | ||
exports.indexOfArray = indexOfArray; | ||
@@ -1475,3 +1545,3 @@ | ||
}); | ||
define('htmlbars-util/template-utils', ['exports', '../htmlbars-util/morph-utils'], function (exports, morph_utils) { | ||
define('htmlbars-util/template-utils', ['exports', '../htmlbars-util/morph-utils', './array-utils'], function (exports, morph_utils, array_utils) { | ||
@@ -1529,3 +1599,3 @@ 'use strict'; | ||
} | ||
if (typeof blocks === 'function') { | ||
if (typeof blocks === "function") { | ||
env.hooks.bindBlock(env, shadowScope, blocks); | ||
@@ -1570,3 +1640,3 @@ } else { | ||
if (toClear) { | ||
if (Object.prototype.toString.call(toClear) === '[object Array]') { | ||
if (array_utils.isArray(toClear)) { | ||
for (var i = 0, l = toClear.length; i < l; i++) { | ||
@@ -1573,0 +1643,0 @@ clearMorph(toClear[i], env); |
@@ -98,3 +98,3 @@ define('htmlbars-syntax-tests/htmlbars-syntax.jshint', function () { | ||
test("blocks", function () { | ||
test("programs", function () { | ||
var ast = htmlbars_syntax.parse("\n {{#if foo}}\n {{bar}}\n {{/if}}\n "); | ||
@@ -109,2 +109,55 @@ | ||
test("blocks", function () { | ||
var ast = htmlbars_syntax.parse("\n {{#if foo}}\n {{#if bar}}\n test\n {{else}}\n test\n {{/if }}\n {{/if\n }}\n "); | ||
locEqual(ast.body[1], 2, 2, 9, 8, "outer block"); | ||
locEqual(ast.body[1].program.body[0], 3, 4, 7, 13, "nested block"); | ||
}); | ||
test("mustache", function () { | ||
var ast = htmlbars_syntax.parse("\n {{foo}}\n {{#if foo}}\n bar: {{bar\n }}\n {{/if}}\n "); | ||
locEqual(ast.body[1], 2, 4, 2, 11, "outer mustache"); | ||
locEqual(ast.body[3].program.body[1], 4, 11, 5, 10, "inner mustache"); | ||
}); | ||
test("element modifier", function () { | ||
var ast = htmlbars_syntax.parse("\n <div {{bind-attr\n foo\n bar=wat}}></div>\n "); | ||
locEqual(ast.body[1].modifiers[0], 2, 9, 4, 15, "element modifier"); | ||
}); | ||
test("html elements", function () { | ||
var ast = htmlbars_syntax.parse("\n <section>\n <br>\n <div>\n <hr />\n </div>\n </section>\n "); | ||
var _ast$body = ast.body; | ||
var section = _ast$body[1]; | ||
var _section$children = section.children; | ||
var br = _section$children[1]; | ||
var div = _section$children[3]; | ||
var _div$children = div.children; | ||
var hr = _div$children[1]; | ||
locEqual(section, 2, 4, 7, 14, "section element"); | ||
locEqual(br, 3, 6, 3, 10, "br element"); | ||
locEqual(div, 4, 6, 6, 12, "div element"); | ||
locEqual(hr, 5, 8, 5, 14, "hr element"); | ||
}); | ||
test("components", function () { | ||
var ast = htmlbars_syntax.parse("\n <el-page>\n <el-header></el-header>\n <el-input />\n <el-footer>\n </el-footer>\n </el-page>\n "); | ||
var _ast$body2 = ast.body; | ||
var page = _ast$body2[1]; | ||
var _page$program$body = page.program.body; | ||
var header = _page$program$body[1]; | ||
var input = _page$program$body[3]; | ||
var footer = _page$program$body[5]; | ||
locEqual(page, 2, 4, 7, 14, "page component"); | ||
locEqual(header, 3, 6, 3, 29, "header component"); | ||
locEqual(input, 4, 6, 4, 18, "input component"); | ||
locEqual(footer, 5, 6, 6, 22, "footer component"); | ||
}); | ||
}); | ||
@@ -111,0 +164,0 @@ define('htmlbars-syntax-tests/loc-node-test.jshint', function () { |
@@ -266,4 +266,9 @@ define('htmlbars-test-helpers', ['exports', '../simple-html-tokenizer', '../htmlbars-util/array-utils'], function (exports, simple_html_tokenizer, array_utils) { | ||
var isArray = Array.isArray || function (array) { | ||
return Object.prototype.toString.call(array) === '[object Array]'; | ||
}; | ||
var indexOfArray = getIdx; | ||
exports.isArray = isArray; | ||
exports.indexOfArray = indexOfArray; | ||
@@ -723,3 +728,3 @@ | ||
}); | ||
define('htmlbars-util/template-utils', ['exports', '../htmlbars-util/morph-utils'], function (exports, morph_utils) { | ||
define('htmlbars-util/template-utils', ['exports', '../htmlbars-util/morph-utils', './array-utils'], function (exports, morph_utils, array_utils) { | ||
@@ -777,3 +782,3 @@ 'use strict'; | ||
} | ||
if (typeof blocks === 'function') { | ||
if (typeof blocks === "function") { | ||
env.hooks.bindBlock(env, shadowScope, blocks); | ||
@@ -818,3 +823,3 @@ } else { | ||
if (toClear) { | ||
if (Object.prototype.toString.call(toClear) === '[object Array]') { | ||
if (array_utils.isArray(toClear)) { | ||
for (var i = 0, l = toClear.length; i < l; i++) { | ||
@@ -821,0 +826,0 @@ clearMorph(toClear[i], env); |
var packagesConfig = { | ||
"version": "0.13.25", | ||
"revision": "19f7e05a6712bf8c1a3fe57e23010e0f91f0471a", | ||
"version": "0.13.26", | ||
"revision": "ecb10c7a7b5101b6a465f148a1cc8e13753860b0", | ||
"vendored": {}, | ||
@@ -5,0 +5,0 @@ "dependencies": { |
{ | ||
"name": "htmlbars", | ||
"version": "0.13.25", | ||
"version": "0.13.26", | ||
"description": "HTMLBars compiles Handlebars templates into document fragments rather than string buffers", | ||
@@ -5,0 +5,0 @@ "main": "dist/cjs/htmlbars.js", |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
2115489
276
58928