Fixes #220 - Support expansion of CSS selector shorthand for tag names

This commit is contained in:
Patrick Steele-Idem 2016-02-16 21:39:58 -07:00
parent 92dccd4978
commit 9c2c99a707
23 changed files with 104 additions and 2 deletions

View File

@ -18,7 +18,6 @@ function isIEConditionalComment(comment) {
}
function replacePlaceholderEscapeFuncs(node, context) {
var walker = context.createWalker({
exit: function(node, parent) {
if (node.type === 'FunctionCall' &&
@ -36,6 +35,39 @@ function replacePlaceholderEscapeFuncs(node, context) {
return walker.walk(node);
}
function mergeShorthandClassNames(el, shorthandClassNames, context) {
var builder = context.builder;
let classNames = shorthandClassNames.map((className) => {
return builder.parseExpression(className.value);
});
var classAttr = el.getAttributeValue('class');
if (classAttr) {
classNames.push(classAttr);
}
let prevClassName;
var finalClassNames = [];
for (var i=0; i<classNames.length; i++) {
let className = classNames[i];
if (prevClassName && className.type === 'Literal' && prevClassName.type === 'Literal') {
prevClassName.value += ' ' + className.value;
} else {
finalClassNames.push(className);
}
prevClassName = className;
}
if (finalClassNames.length === 1) {
el.setAttributeValue('class', finalClassNames[0]);
} else {
var classListVar = context.addStaticVar('__classList', '__helpers.cl');
el.setAttributeValue('class', builder.functionCall(classListVar, finalClassNames));
}
}
class Parser {
constructor(parserImpl) {
ok(parserImpl, '"parserImpl" is required');
@ -160,6 +192,17 @@ class Parser {
var node = this.context.createNodeForEl(elDef);
if (el.shorthandClassNames) {
mergeShorthandClassNames(node, el.shorthandClassNames, context);
}
if (el.shorthandId) {
if (node.hasAttribute('id')) {
context.addError(node, 'A shorthand ID cannot be used in conjunction with the "id" attribute');
} else {
node.setAttributeValue('id', builder.parseExpression(el.shorthandId.value));
}
}
this.parentNode.appendChild(node);

View File

@ -252,7 +252,7 @@ module.exports = {
},
/**
* Merges
* Merges object properties
* @param {[type]} object [description]
* @param {[type]} source [description]
* @return {[type]} [description]
@ -264,5 +264,24 @@ module.exports = {
}
}
return into;
},
/**
* classList(a, b, c, ...)
* Joines a list of class names with spaces. Empty class names are omitted.
*
* classList('a', undefined, 'b') --> 'a b'
*
*/
cl: function() {
var args = arguments;
var classNames = [];
for (var i=0, len=args.length; i<len; i++) {
var cur = args[i];
if (cur) {
classNames.push(cur);
}
}
return classNames.join(' ');
}
};

View File

@ -0,0 +1 @@
<div class="foo bar"></div>

View File

@ -0,0 +1 @@
div.foo class="bar"

View File

@ -0,0 +1,3 @@
exports.templateData = {
name: 'Frank'
};

View File

@ -0,0 +1 @@
<div class="foo baz"></div>

View File

@ -0,0 +1 @@
div.foo.${data.missing} class="baz"

View File

@ -0,0 +1,3 @@
exports.templateData = {
name: 'Frank'
};

View File

@ -0,0 +1 @@
<div style="color: red;" id="foo-Frank">Hello Frank!</div>

View File

@ -0,0 +1,2 @@
div#foo-${data.name} style="color: red;"
- Hello ${data.name}!

View File

@ -0,0 +1,3 @@
exports.templateData = {
name: 'Frank'
};

View File

@ -0,0 +1 @@
<div style="color: red;" id="foo">Hello Frank!</div>

View File

@ -0,0 +1,2 @@
div#foo style="color: red;"
- Hello ${data.name}!

View File

@ -0,0 +1,3 @@
exports.templateData = {
name: 'Frank'
};

View File

@ -0,0 +1 @@
<div style="color: red;" class="foo">Hello Frank!</div>

View File

@ -0,0 +1,2 @@
div.foo style="color: red;"
- Hello ${data.name}!

View File

@ -0,0 +1,3 @@
exports.templateData = {
name: 'Frank'
};

View File

@ -0,0 +1 @@
<div class="bar baz" id="foo"></div>

View File

@ -0,0 +1 @@
#foo.bar.baz

View File

@ -0,0 +1,3 @@
exports.templateData = {
name: 'Frank'
};

View File

@ -0,0 +1 @@
<div class="bar baz" id="foo">Hello Frank!</div>

View File

@ -0,0 +1,3 @@
<#foo.bar.baz>
Hello ${data.name}!
</>

View File

@ -0,0 +1,3 @@
exports.templateData = {
name: 'Frank'
};