diff --git a/lib/less/parser.js b/lib/less/parser.js index 94669292a..edb73f36a 100644 --- a/lib/less/parser.js +++ b/lib/less/parser.js @@ -1684,8 +1684,6 @@ less.Parser = function Parser(env) { switch(nonVendorSpecificName) { case "@font-face": - hasBlock = true; - break; case "@viewport": case "@top-left": case "@top-left-corner": @@ -1719,21 +1717,23 @@ less.Parser = function Parser(env) { } if (hasIdentifier) { - identifier = ($re(/^[^{]+/) || '').trim(); - if (identifier) { - name += " " + identifier; + // identifier may be split over chunks because of @{var}s + // so we need to ensure we'll stop at '{' here: + identifier = ''; + while (input.charAt(i) !== '{') { + identifier += ($re(/^(?:@{|[^{])+/) || '').trim(); } } if (hasBlock) { rules = this.block(); if (rules) { - return new(tree.Directive)(name, rules, index, env.currentFileInfo); + return new(tree.Directive)(name, identifier, rules, index, env.currentFileInfo); } } else { value = hasExpression ? this.expression() : this.entity(); if (value && $char(';')) { - var directive = new(tree.Directive)(name, value, index, env.currentFileInfo); + var directive = new(tree.Directive)(name, identifier, value, index, env.currentFileInfo); if (env.dumpLineNumbers) { directive.debugInfo = getDebugInfo(i, input, env); } diff --git a/lib/less/tree/directive.js b/lib/less/tree/directive.js index a4404bd72..4a507208a 100644 --- a/lib/less/tree/directive.js +++ b/lib/less/tree/directive.js @@ -1,7 +1,9 @@ (function (tree) { -tree.Directive = function (name, value, index, currentFileInfo) { +tree.Directive = function (name, identifier, value, index, currentFileInfo) { this.name = name; + // note: identifier is actually anything between name and '{': + this.identifier = identifier; if (Array.isArray(value)) { this.rules = [new(tree.Ruleset)(null, value)]; @@ -35,10 +37,22 @@ tree.Directive.prototype = { }, toCSS: tree.toCSS, eval: function (env) { - var evaldDirective = this; + var evaldDirective = this, name= this.name, + identifier = this.identifier, index; + + function evalVar(_, name, offset) { + return new(tree.Variable)('@' + name, index + offset).eval(env).toCSS(env); + } + if (this.rules) { env.frames.unshift(this); - evaldDirective = new(tree.Directive)(this.name, null, this.index, this.currentFileInfo); + if (identifier) { + index = this.index + name.length + 1; + name += " " + identifier + .replace(/@\{([\w-]+)\}/g, evalVar) + .replace(/@(@?[\w-]+)(?![^\(]*:)/g, evalVar); + } + evaldDirective = new(tree.Directive)(name, null, null, this.index, this.currentFileInfo); evaldDirective.rules = [this.rules[0].eval(env)]; evaldDirective.rules[0].root = true; env.frames.shift(); diff --git a/test/css/at-rules-interpolation.css b/test/css/at-rules-interpolation.css new file mode 100644 index 000000000..510e6130c --- /dev/null +++ b/test/css/at-rules-interpolation.css @@ -0,0 +1,29 @@ +@supports (display: flexbox) and (width: 25%) or (height: 25%) { + div { + width: 100px; + } +} +@keyframes enlarger { + from { + font-size: 12px; + } + to { + font-size: 15px; + } +} +@-webkit-keyframes reducer { + from { + font-size: 13px; + } + to { + font-size: 10px; + } +} +@page :left, toc, index { + margin: 2cm; +} +@document url(http://www.w4.org/), domain(lesscss.org) { + body { + color: purple; + } +} diff --git a/test/css/debug/linenumbers-all.css b/test/css/debug/linenumbers-all.css index 25b103225..bf156312f 100644 --- a/test/css/debug/linenumbers-all.css +++ b/test/css/debug/linenumbers-all.css @@ -41,7 +41,7 @@ .tst2 { color: white; } -/* line 27, c:\git\less.js\test\less\debug\linenumbers.less */ +/* line 27, {path}linenumbers.less */ @media -sass-debug-info{filename{font-family:file\:\/\/{pathesc}linenumbers\.less}line{font-family:\0000327}} .test { color: red; diff --git a/test/less/at-rules-interpolation.less b/test/less/at-rules-interpolation.less new file mode 100644 index 000000000..13afa342b --- /dev/null +++ b/test/less/at-rules-interpolation.less @@ -0,0 +1,41 @@ + +@a: display; +@b: flexbox; +@c: 25%; +@d: c; + +@supports (@{a}: @b) and (width: @{c}) or (height: @@d) { + div { + width: 100px; + } +} + +@name: enlarger; +@keyframes @name { + from {font-size: 12px;} + to {font-size: 15px;} +} + +.m(reducer); +.m(@name) { + @-webkit-keyframes @name { + from {font-size: 13px;} + to {font-size: 10px;} + } +} + +@types: toc, index; +@dir: :left; + +@page @dir, @types { + margin: 2cm; +} + +@url: url(http://www.w4.org/); +@prefix: less; + +@document @url, domain(@{prefix}css.org) { + body { + color: purple; + } +} diff --git a/test/less/errors/at-rules-undefined-var.less b/test/less/errors/at-rules-undefined-var.less new file mode 100644 index 000000000..a1473805d --- /dev/null +++ b/test/less/errors/at-rules-undefined-var.less @@ -0,0 +1,4 @@ + +@keyframes @name { + 50% {width: 20px;} +} diff --git a/test/less/errors/at-rules-undefined-var.txt b/test/less/errors/at-rules-undefined-var.txt new file mode 100644 index 000000000..48ca57c4b --- /dev/null +++ b/test/less/errors/at-rules-undefined-var.txt @@ -0,0 +1,4 @@ +NameError: variable @name is undefined in {path}at-rules-undefined-var.less on line 2, column 12: +1 +2 @keyframes @name { +3 50% {width: 20px;}