From aeba089de19610b0b6590ca786dcc0cabeb25e51 Mon Sep 17 00:00:00 2001 From: Philip Guerrant Date: Mon, 2 Dec 2013 15:23:16 -0700 Subject: [PATCH] Add support for default variables using "?" --- lib/less/parser.js | 28 +++++++++++++++++++++++----- lib/less/tree/rule.js | 5 +++-- lib/less/tree/ruleset.js | 4 +++- 3 files changed, 29 insertions(+), 8 deletions(-) diff --git a/lib/less/parser.js b/lib/less/parser.js index 32197d668..c1619d560 100644 --- a/lib/less/parser.js +++ b/lib/less/parser.js @@ -886,6 +886,19 @@ less.Parser = function Parser(env) { if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1]; } }, + // + // The name portion of a default variable definition. Used in the `rule` parser + // + // ?fink: + // + defaultVariable: function () { + var name; + + if (input.charAt(i) === '?' && (name = $(/^(\?[\w-]+)\s*:/))) { + return name[1].replace('?', '@'); + } + }, + // // extend syntax - used to extend selectors // @@ -1319,19 +1332,24 @@ less.Parser = function Parser(env) { } }, rule: function (tryAnonymous) { - var name, value, c = input.charAt(i), important, merge = false; + var name, value, c = input.charAt(i), important, isDefault, isVar, merge = false; save(); if (c === '.' || c === '#' || c === '&') { return; } - if (name = $(this.variable) || $(this.ruleProperty)) { + name = $(this.defaultVariable); + isDefault = !!name; + name = name || $(this.variable); + isVar = !!name; + name = name || $(this.ruleProperty); + + if (name) { // prefer to try to parse first if its a variable or we are compressing // but always fallback on the other one - value = !tryAnonymous && (env.compress || (name.charAt(0) === '@')) ? + value = !tryAnonymous && (env.compress || isVar) ? ($(this.value) || $(this.anonymousValue)) : ($(this.anonymousValue) || $(this.value)); - important = $(this.important); if (name[name.length-1] === "+") { merge = true; @@ -1339,7 +1357,7 @@ less.Parser = function Parser(env) { } if (value && $(this.end)) { - return new (tree.Rule)(name, value, important, merge, memo, env.currentFileInfo); + return new (tree.Rule)(name, value, important, merge, memo, env.currentFileInfo, null, isDefault); } else { furthest = i; restore(); diff --git a/lib/less/tree/rule.js b/lib/less/tree/rule.js index 20562094d..1a6404041 100644 --- a/lib/less/tree/rule.js +++ b/lib/less/tree/rule.js @@ -1,6 +1,6 @@ (function (tree) { -tree.Rule = function (name, value, important, merge, index, currentFileInfo, inline) { +tree.Rule = function (name, value, important, merge, index, currentFileInfo, inline, isDefault) { this.name = name; this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); this.important = important ? ' ' + important.trim() : ''; @@ -9,6 +9,7 @@ tree.Rule = function (name, value, important, merge, index, currentFileInfo, inl this.currentFileInfo = currentFileInfo; this.inline = inline || false; this.variable = (name.charAt(0) === '@'); + this.isDefault = isDefault; }; tree.Rule.prototype = { @@ -40,7 +41,7 @@ tree.Rule.prototype = { this.value.eval(env), this.important, this.merge, - this.index, this.currentFileInfo, this.inline); + this.index, this.currentFileInfo, this.inline, this.isDefault); } finally { if (strictMathBypass) { diff --git a/lib/less/tree/ruleset.js b/lib/less/tree/ruleset.js index a89dfb001..69fd42dac 100644 --- a/lib/less/tree/ruleset.js +++ b/lib/less/tree/ruleset.js @@ -145,7 +145,9 @@ tree.Ruleset.prototype = { else { return this._variables = this.rules.reduce(function (hash, r) { if (r instanceof tree.Rule && r.variable === true) { - hash[r.name] = r; + if (!r.isDefault || !hash[r.name]) { + hash[r.name] = r; + } } return hash; }, {});