Created
November 12, 2014 17:33
-
-
Save Panya/6b5c40d0830552c22f03 to your computer and use it in GitHub Desktop.
@extend !optional
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/docs/extend.md b/docs/extend.md | |
index a0e037f..92b18c6 100644 | |
--- a/docs/extend.md | |
+++ b/docs/extend.md | |
@@ -185,3 +185,20 @@ Yielding: | |
} | |
Note that if the selector is not extended, it won't be in the resulting CSS, so it's a powerful way to create a library of extendable code. While you can insert code through mixins, they would insert the same code every time you use them, while extending placeholders would give you compact output. | |
+ | |
+## Optional extending | |
+ | |
+Sometimes it might be usefull to be able to extend something that might | |
+exists or not depending on the context. You can suffix any selector by `optional` to achieve this: | |
+ | |
+ $specialDesign | |
+ color: #FFF | |
+ | |
+ .btn | |
+ @extend .design !optional, $specialDesign !optional | |
+ | |
+Yielding: | |
+ | |
+ .btn { | |
+ color: #fff; | |
+ } | |
diff --git a/lib/nodes/selector.js b/lib/nodes/selector.js | |
index 46db498..14f697c 100644 | |
--- a/lib/nodes/selector.js | |
+++ b/lib/nodes/selector.js | |
@@ -23,6 +23,7 @@ var Selector = module.exports = function Selector(segs){ | |
Node.call(this); | |
this.inherits = true; | |
this.segments = segs; | |
+ this.optional = false; | |
}; | |
/** | |
@@ -66,6 +67,7 @@ Selector.prototype.clone = function(parent){ | |
clone.column = this.column; | |
clone.filename = this.filename; | |
clone.inherits = this.inherits; | |
+ clone.optional = this.optional; | |
clone.val = this.val; | |
clone.segments = this.segments.map(function(node){ return node.clone(parent, clone); }); | |
return clone; | |
@@ -82,6 +84,7 @@ Selector.prototype.toJSON = function(){ | |
return { | |
__type: 'Selector', | |
inherits: this.inherits, | |
+ optional: this.optional, | |
segments: this.segments, | |
val: this.val, | |
lineno: this.lineno, | |
diff --git a/lib/parser.js b/lib/parser.js | |
index efd024e..eb068e0 100644 | |
--- a/lib/parser.js | |
+++ b/lib/parser.js | |
@@ -1073,12 +1073,26 @@ Parser.prototype = { | |
extend: function(){ | |
var tok = this.expect('extend') | |
, selectors = [] | |
+ , sel | |
+ , tok | |
, node | |
, arr; | |
do { | |
arr = this.selectorParts(); | |
- if (arr.length) selectors.push(new nodes.Selector(arr)); | |
+ if (arr.length) { | |
+ sel = new nodes.Selector(arr); | |
+ | |
+ if ('!' == this.peek().type) { | |
+ tok = this.lookahead(2); | |
+ if ('ident' == tok.type && 'optional' == tok.val.name) { | |
+ this.skip(['!', 'ident']); | |
+ sel.optional = true; | |
+ } | |
+ } | |
+ | |
+ selectors.push(sel); | |
+ } | |
} while(this.accept(',')); | |
node = new nodes.Extend(selectors); | |
diff --git a/lib/visitor/evaluator.js b/lib/visitor/evaluator.js | |
index e2ea546..ee776fe 100644 | |
--- a/lib/visitor/evaluator.js | |
+++ b/lib/visitor/evaluator.js | |
@@ -835,6 +835,7 @@ Evaluator.prototype.visitExtend = function(extend){ | |
// Cloning the selector for when we are in a loop and don't want it to affect | |
// the selector nodes and cause the values to be different to expected | |
selector: this.interpolate(selector.clone()).trim(), | |
+ optional: selector.optional, | |
lineno: selector.lineno, | |
column: selector.column | |
}); | |
diff --git a/lib/visitor/normalizer.js b/lib/visitor/normalizer.js | |
index e81b8eb..9ed77d4 100644 | |
--- a/lib/visitor/normalizer.js | |
+++ b/lib/visitor/normalizer.js | |
@@ -378,6 +378,7 @@ Normalizer.prototype.extend = function(group, selectors){ | |
group.block.node.extends.forEach(function(extend){ | |
var groups = map[extend.selector]; | |
if (!groups) { | |
+ if (extend.optional) return; | |
var err = new Error('Failed to @extend "' + extend.selector + '"'); | |
err.lineno = extend.lineno; | |
err.column = extend.column; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment