diff --git a/.travis.yml b/.travis.yml index 1457ce05b..b71e6844e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,11 @@ node_js: - "4.0.0" - "0.12" - "0.10" +before_install: + - mkdir travis-phantomjs + - wget https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-2.1.1-linux-x86_64.tar.bz2 -O $PWD/travis-phantomjs/phantomjs-2.1.1-linux-x86_64.tar.bz2 + - tar -xvf $PWD/travis-phantomjs/phantomjs-2.1.1-linux-x86_64.tar.bz2 -C $PWD/travis-phantomjs + - export PATH=$PWD/travis-phantomjs/phantomjs-2.1.1-linux-x86_64/bin:$PATH install: - npm install -g grunt-cli - npm install diff --git a/lib/less/parser/parser.js b/lib/less/parser/parser.js index 008db4a8d..b66fc5f3f 100644 --- a/lib/less/parser/parser.js +++ b/lib/less/parser/parser.js @@ -261,7 +261,7 @@ var Parser = function Parser(context, imports, fileInfo) { } node = mixin.definition() || this.rule() || this.ruleset() || - mixin.call() || this.rulesetCall() || this.directive(); + mixin.call() || this.rulesetCall() || this.entities.call() || this.directive(); if (node) { root.push(node); } else { @@ -370,19 +370,51 @@ var Parser = function Parser(context, imports, fileInfo) { return new(tree.Call)(name, args, index, fileInfo); }, arguments: function () { - var args = [], arg; + var argsSemiColon = [], argsComma = [], + expressions = [], + isSemiColonSeparated, value, arg; + + parserInput.save(); while (true) { - arg = this.assignment() || parsers.expression(); + + arg = parsers.detachedRuleset() || this.assignment() || parsers.expression(); + if (!arg) { break; } - args.push(arg); - if (! parserInput.$char(',')) { - break; + + value = arg; + + if (arg.value && arg.value.length == 1) { + value = arg.value[0]; + } + + if (value) { + expressions.push(value); + } + + argsComma.push(value); + + if (parserInput.$char(',')) { + continue; + } + + if (parserInput.$char(';') || isSemiColonSeparated) { + + isSemiColonSeparated = true; + + if (expressions.length > 1) { + value = new(tree.Value)(expressions); + } + argsSemiColon.push(value); + + expressions = []; } } - return args; + + parserInput.forget(); + return isSemiColonSeparated ? argsSemiColon : argsComma; }, literal: function () { return this.dimension() || diff --git a/lib/less/tree/anonymous.js b/lib/less/tree/anonymous.js index d3da585ad..ec4f31304 100644 --- a/lib/less/tree/anonymous.js +++ b/lib/less/tree/anonymous.js @@ -6,7 +6,7 @@ var Anonymous = function (value, index, currentFileInfo, mapLines, rulesetLike, this.mapLines = mapLines; this.currentFileInfo = currentFileInfo; this.rulesetLike = (typeof rulesetLike === 'undefined') ? false : rulesetLike; - + this.allowRoot = true; this.copyVisibilityInfo(visibilityInfo); }; Anonymous.prototype = new Node(); diff --git a/lib/less/tree/call.js b/lib/less/tree/call.js index 279b6fa52..12e183747 100644 --- a/lib/less/tree/call.js +++ b/lib/less/tree/call.js @@ -31,18 +31,21 @@ Call.prototype.eval = function (context) { var args = this.args.map(function (a) { return a.eval(context); }), result, funcCaller = new FunctionCaller(this.name, context, this.index, this.currentFileInfo); - if (funcCaller.isValid()) { // 1. + if (funcCaller.isValid()) { try { result = funcCaller.call(args); - if (result != null) { - return result; - } } catch (e) { throw { type: e.type || "Runtime", message: "error evaluating function `" + this.name + "`" + (e.message ? ': ' + e.message : ''), index: this.index, filename: this.currentFileInfo.filename }; } + + if (result != null) { + result.index = this.index; + result.currentFileInfo = this.currentFileInfo; + return result; + } } return new Call(this.name, args, this.index, this.currentFileInfo); diff --git a/lib/less/tree/comment.js b/lib/less/tree/comment.js index 6983c6300..6566950c9 100644 --- a/lib/less/tree/comment.js +++ b/lib/less/tree/comment.js @@ -5,6 +5,7 @@ var Comment = function (value, isLineComment, index, currentFileInfo) { this.value = value; this.isLineComment = isLineComment; this.currentFileInfo = currentFileInfo; + this.allowRoot = true; }; Comment.prototype = new Node(); Comment.prototype.type = "Comment"; diff --git a/lib/less/tree/directive.js b/lib/less/tree/directive.js index 3e754d435..70be82c73 100644 --- a/lib/less/tree/directive.js +++ b/lib/less/tree/directive.js @@ -23,6 +23,7 @@ var Directive = function (name, value, rules, index, currentFileInfo, debugInfo, this.debugInfo = debugInfo; this.isRooted = isRooted || false; this.copyVisibilityInfo(visibilityInfo); + this.allowRoot = true; }; Directive.prototype = new Node(); diff --git a/lib/less/tree/extend.js b/lib/less/tree/extend.js index e51604243..e91fbf77d 100644 --- a/lib/less/tree/extend.js +++ b/lib/less/tree/extend.js @@ -9,6 +9,7 @@ var Extend = function Extend(selector, option, index, currentFileInfo, visibilit this.parent_ids = [this.object_id]; this.currentFileInfo = currentFileInfo || {}; this.copyVisibilityInfo(visibilityInfo); + this.allowRoot = true; switch(option) { case "all": diff --git a/lib/less/tree/import.js b/lib/less/tree/import.js index 57be4a75f..3787b052b 100644 --- a/lib/less/tree/import.js +++ b/lib/less/tree/import.js @@ -23,6 +23,7 @@ var Import = function (path, features, options, index, currentFileInfo, visibili this.path = path; this.features = features; this.currentFileInfo = currentFileInfo; + this.allowRoot = true; if (this.options.less !== undefined || this.options.inline) { this.css = !this.options.less || this.options.inline; diff --git a/lib/less/tree/media.js b/lib/less/tree/media.js index 436f6f14f..0bbd23a65 100644 --- a/lib/less/tree/media.js +++ b/lib/less/tree/media.js @@ -15,6 +15,7 @@ var Media = function (value, features, index, currentFileInfo, visibilityInfo) { this.rules = [new Ruleset(selectors, value)]; this.rules[0].allowImports = true; this.copyVisibilityInfo(visibilityInfo); + this.allowRoot = true; }; Media.prototype = new Directive(); Media.prototype.type = "Media"; diff --git a/lib/less/tree/mixin-call.js b/lib/less/tree/mixin-call.js index 254514524..5864a0c36 100644 --- a/lib/less/tree/mixin-call.js +++ b/lib/less/tree/mixin-call.js @@ -9,6 +9,7 @@ var MixinCall = function (elements, args, index, currentFileInfo, important) { this.index = index; this.currentFileInfo = currentFileInfo; this.important = important; + this.allowRoot = true; }; MixinCall.prototype = new Node(); MixinCall.prototype.type = "MixinCall"; diff --git a/lib/less/tree/mixin-definition.js b/lib/less/tree/mixin-definition.js index e02768c10..b2e3413d0 100644 --- a/lib/less/tree/mixin-definition.js +++ b/lib/less/tree/mixin-definition.js @@ -27,6 +27,7 @@ var Definition = function (name, params, rules, condition, variadic, frames, vis this.optionalParameters = optionalParameters; this.frames = frames; this.copyVisibilityInfo(visibilityInfo); + this.allowRoot = true; }; Definition.prototype = new Ruleset(); Definition.prototype.type = "MixinDefinition"; diff --git a/lib/less/tree/rule.js b/lib/less/tree/rule.js index c4318a964..99d168cff 100644 --- a/lib/less/tree/rule.js +++ b/lib/less/tree/rule.js @@ -12,6 +12,7 @@ var Rule = function (name, value, important, merge, index, currentFileInfo, inli this.inline = inline || false; this.variable = (variable !== undefined) ? variable : (name.charAt && (name.charAt(0) === '@')); + this.allowRoot = true; }; function evalName(context, name) { diff --git a/lib/less/tree/ruleset-call.js b/lib/less/tree/ruleset-call.js index 7a62c14dd..d271c8ddd 100644 --- a/lib/less/tree/ruleset-call.js +++ b/lib/less/tree/ruleset-call.js @@ -3,6 +3,7 @@ var Node = require("./node"), var RulesetCall = function (variable) { this.variable = variable; + this.allowRoot = true; }; RulesetCall.prototype = new Node(); RulesetCall.prototype.type = "RulesetCall"; diff --git a/lib/less/tree/ruleset.js b/lib/less/tree/ruleset.js index 9f1917666..dcf8ae843 100644 --- a/lib/less/tree/ruleset.js +++ b/lib/less/tree/ruleset.js @@ -14,6 +14,7 @@ var Ruleset = function (selectors, rules, strictImports, visibilityInfo) { this._lookups = {}; this.strictImports = strictImports; this.copyVisibilityInfo(visibilityInfo); + this.allowRoot = true; }; Ruleset.prototype = new Node(); Ruleset.prototype.type = "Ruleset"; diff --git a/lib/less/visitors/to-css-visitor.js b/lib/less/visitors/to-css-visitor.js index cc90cdd88..9dc755f98 100644 --- a/lib/less/visitors/to-css-visitor.js +++ b/lib/less/visitors/to-css-visitor.js @@ -199,13 +199,24 @@ ToCSSVisitor.prototype = { return directiveNode; }, - checkPropertiesInRoot: function(rules) { - var ruleNode; + checkValidNodes: function(rules, isRoot) { + if (!rules) { + return; + } + for (var i = 0; i < rules.length; i++) { - ruleNode = rules[i]; - if (ruleNode instanceof tree.Rule && !ruleNode.variable) { - throw { message: "properties must be inside selector blocks, they cannot be in the root.", - index: ruleNode.index, filename: ruleNode.currentFileInfo ? ruleNode.currentFileInfo.filename : null}; + var ruleNode = rules[i]; + if (isRoot && ruleNode instanceof tree.Rule && !ruleNode.variable) { + throw { message: "Properties must be inside selector blocks. They cannot be in the root", + index: ruleNode.index, filename: ruleNode.currentFileInfo && ruleNode.currentFileInfo.filename}; + } + if (ruleNode instanceof tree.Call) { + throw { message: "Function '" + ruleNode.name + "' is undefined", + index: ruleNode.index, filename: ruleNode.currentFileInfo && ruleNode.currentFileInfo.filename}; + } + if (!ruleNode.allowRoot) { + throw { message: ruleNode.type + " node returned by a function is not valid here", + index: ruleNode.index, filename: ruleNode.currentFileInfo && ruleNode.currentFileInfo.filename}; } } }, @@ -213,9 +224,9 @@ ToCSSVisitor.prototype = { visitRuleset: function (rulesetNode, visitArgs) { //at this point rulesets are nested into each other var rule, rulesets = []; - if (rulesetNode.firstRoot) { - this.checkPropertiesInRoot(rulesetNode.rules); - } + + this.checkValidNodes(rulesetNode.rules, rulesetNode.firstRoot); + if (! rulesetNode.root) { //remove invisible paths this._compileRulesetPaths(rulesetNode); diff --git a/test/css/plugin.css b/test/css/plugin.css index b837dc63e..0b6910754 100644 --- a/test/css/plugin.css +++ b/test/css/plugin.css @@ -1,3 +1,4 @@ +@charset "utf-8"; .other { trans: transitive; } @@ -42,3 +43,7 @@ result: local; } } +.root { + prop: value; +} +@arbitrary value after (); diff --git a/test/less/errors/detached-ruleset-3.txt b/test/less/errors/detached-ruleset-3.txt index 15d281fa3..ad43ab46a 100644 --- a/test/less/errors/detached-ruleset-3.txt +++ b/test/less/errors/detached-ruleset-3.txt @@ -1,4 +1,4 @@ -SyntaxError: properties must be inside selector blocks, they cannot be in the root. in {path}detached-ruleset-3.less on line 2, column 3: +SyntaxError: Properties must be inside selector blocks. They cannot be in the root in {path}detached-ruleset-3.less on line 2, column 3: 1 @a: { 2 b: 1; 3 }; diff --git a/test/less/errors/functions-1.less b/test/less/errors/functions-1.less new file mode 100644 index 000000000..f502aa276 --- /dev/null +++ b/test/less/errors/functions-1.less @@ -0,0 +1,2 @@ +@plugin "../plugin/plugin-tree-nodes"; +test-undefined(); \ No newline at end of file diff --git a/test/less/errors/functions-1.txt b/test/less/errors/functions-1.txt new file mode 100644 index 000000000..abeb4bda5 --- /dev/null +++ b/test/less/errors/functions-1.txt @@ -0,0 +1,3 @@ +SyntaxError: Function 'test-undefined' is undefined in {path}functions-1.less on line 2, column 1: +1 @plugin "../plugin/plugin-tree-nodes"; +2 test-undefined(); diff --git a/test/less/errors/functions-10-keyword.less b/test/less/errors/functions-10-keyword.less new file mode 100644 index 000000000..16d0b9858 --- /dev/null +++ b/test/less/errors/functions-10-keyword.less @@ -0,0 +1,2 @@ +@plugin "../plugin/plugin-tree-nodes"; +test-keyword(); \ No newline at end of file diff --git a/test/less/errors/functions-10-keyword.txt b/test/less/errors/functions-10-keyword.txt new file mode 100644 index 000000000..dabe839d6 --- /dev/null +++ b/test/less/errors/functions-10-keyword.txt @@ -0,0 +1,3 @@ +SyntaxError: Keyword node returned by a function is not valid here in {path}functions-10-keyword.less on line 2, column 1: +1 @plugin "../plugin/plugin-tree-nodes"; +2 test-keyword(); diff --git a/test/less/errors/functions-11-operation.less b/test/less/errors/functions-11-operation.less new file mode 100644 index 000000000..5695bdb91 --- /dev/null +++ b/test/less/errors/functions-11-operation.less @@ -0,0 +1,2 @@ +@plugin "../plugin/plugin-tree-nodes"; +test-operation(); \ No newline at end of file diff --git a/test/less/errors/functions-11-operation.txt b/test/less/errors/functions-11-operation.txt new file mode 100644 index 000000000..27287179c --- /dev/null +++ b/test/less/errors/functions-11-operation.txt @@ -0,0 +1,3 @@ +SyntaxError: Operation node returned by a function is not valid here in {path}functions-11-operation.less on line 2, column 1: +1 @plugin "../plugin/plugin-tree-nodes"; +2 test-operation(); diff --git a/test/less/errors/functions-12-quoted.less b/test/less/errors/functions-12-quoted.less new file mode 100644 index 000000000..d35be8710 --- /dev/null +++ b/test/less/errors/functions-12-quoted.less @@ -0,0 +1,2 @@ +@plugin "../plugin/plugin-tree-nodes"; +test-quoted(); \ No newline at end of file diff --git a/test/less/errors/functions-12-quoted.txt b/test/less/errors/functions-12-quoted.txt new file mode 100644 index 000000000..45c62ea64 --- /dev/null +++ b/test/less/errors/functions-12-quoted.txt @@ -0,0 +1,3 @@ +SyntaxError: Quoted node returned by a function is not valid here in {path}functions-12-quoted.less on line 2, column 1: +1 @plugin "../plugin/plugin-tree-nodes"; +2 test-quoted(); diff --git a/test/less/errors/functions-13-selector.less b/test/less/errors/functions-13-selector.less new file mode 100644 index 000000000..2fd879c60 --- /dev/null +++ b/test/less/errors/functions-13-selector.less @@ -0,0 +1,2 @@ +@plugin "../plugin/plugin-tree-nodes"; +test-selector(); \ No newline at end of file diff --git a/test/less/errors/functions-13-selector.txt b/test/less/errors/functions-13-selector.txt new file mode 100644 index 000000000..2f4b097f2 --- /dev/null +++ b/test/less/errors/functions-13-selector.txt @@ -0,0 +1,3 @@ +SyntaxError: Selector node returned by a function is not valid here in {path}functions-13-selector.less on line 2, column 1: +1 @plugin "../plugin/plugin-tree-nodes"; +2 test-selector(); diff --git a/test/less/errors/functions-14-url.less b/test/less/errors/functions-14-url.less new file mode 100644 index 000000000..bed6dabff --- /dev/null +++ b/test/less/errors/functions-14-url.less @@ -0,0 +1,2 @@ +@plugin "../plugin/plugin-tree-nodes"; +test-url(); \ No newline at end of file diff --git a/test/less/errors/functions-14-url.txt b/test/less/errors/functions-14-url.txt new file mode 100644 index 000000000..aeb275cab --- /dev/null +++ b/test/less/errors/functions-14-url.txt @@ -0,0 +1,3 @@ +SyntaxError: Url node returned by a function is not valid here in {path}functions-14-url.less on line 2, column 1: +1 @plugin "../plugin/plugin-tree-nodes"; +2 test-url(); diff --git a/test/less/errors/functions-15-value.less b/test/less/errors/functions-15-value.less new file mode 100644 index 000000000..189ce1967 --- /dev/null +++ b/test/less/errors/functions-15-value.less @@ -0,0 +1,2 @@ +@plugin "../plugin/plugin-tree-nodes"; +test-value(); \ No newline at end of file diff --git a/test/less/errors/functions-15-value.txt b/test/less/errors/functions-15-value.txt new file mode 100644 index 000000000..41f6e6a17 --- /dev/null +++ b/test/less/errors/functions-15-value.txt @@ -0,0 +1,3 @@ +SyntaxError: Value node returned by a function is not valid here in {path}functions-15-value.less on line 2, column 1: +1 @plugin "../plugin/plugin-tree-nodes"; +2 test-value(); diff --git a/test/less/errors/functions-2-alpha.less b/test/less/errors/functions-2-alpha.less new file mode 100644 index 000000000..f00da0788 --- /dev/null +++ b/test/less/errors/functions-2-alpha.less @@ -0,0 +1,2 @@ +@plugin "../plugin/plugin-tree-nodes"; +test-alpha(); \ No newline at end of file diff --git a/test/less/errors/functions-2-alpha.txt b/test/less/errors/functions-2-alpha.txt new file mode 100644 index 000000000..38a172731 --- /dev/null +++ b/test/less/errors/functions-2-alpha.txt @@ -0,0 +1,3 @@ +SyntaxError: Alpha node returned by a function is not valid here in {path}functions-2-alpha.less on line 2, column 1: +1 @plugin "../plugin/plugin-tree-nodes"; +2 test-alpha(); diff --git a/test/less/errors/functions-3-assignment.less b/test/less/errors/functions-3-assignment.less new file mode 100644 index 000000000..fe7f5ade4 --- /dev/null +++ b/test/less/errors/functions-3-assignment.less @@ -0,0 +1,2 @@ +@plugin "../plugin/plugin-tree-nodes"; +test-assignment(); \ No newline at end of file diff --git a/test/less/errors/functions-3-assignment.txt b/test/less/errors/functions-3-assignment.txt new file mode 100644 index 000000000..35c199265 --- /dev/null +++ b/test/less/errors/functions-3-assignment.txt @@ -0,0 +1,3 @@ +SyntaxError: Assignment node returned by a function is not valid here in {path}functions-3-assignment.less on line 2, column 1: +1 @plugin "../plugin/plugin-tree-nodes"; +2 test-assignment(); diff --git a/test/less/errors/functions-4-call.less b/test/less/errors/functions-4-call.less new file mode 100644 index 000000000..6b55c88a7 --- /dev/null +++ b/test/less/errors/functions-4-call.less @@ -0,0 +1,2 @@ +@plugin "../plugin/plugin-tree-nodes"; +test-call(); \ No newline at end of file diff --git a/test/less/errors/functions-4-call.txt b/test/less/errors/functions-4-call.txt new file mode 100644 index 000000000..338582d7c --- /dev/null +++ b/test/less/errors/functions-4-call.txt @@ -0,0 +1,3 @@ +SyntaxError: Function 'foo' is undefined in {path}functions-4-call.less on line 2, column 1: +1 @plugin "../plugin/plugin-tree-nodes"; +2 test-call(); diff --git a/test/less/errors/functions-5-color-2.less b/test/less/errors/functions-5-color-2.less new file mode 100644 index 000000000..4839416b0 --- /dev/null +++ b/test/less/errors/functions-5-color-2.less @@ -0,0 +1 @@ +rgba(0,0,0,0); \ No newline at end of file diff --git a/test/less/errors/functions-5-color-2.txt b/test/less/errors/functions-5-color-2.txt new file mode 100644 index 000000000..8b36fd985 --- /dev/null +++ b/test/less/errors/functions-5-color-2.txt @@ -0,0 +1,2 @@ +SyntaxError: Color node returned by a function is not valid here in {path}functions-5-color-2.less on line 1, column 1: +1 rgba(0,0,0,0); diff --git a/test/less/errors/functions-5-color.less b/test/less/errors/functions-5-color.less new file mode 100644 index 000000000..700ec5b92 --- /dev/null +++ b/test/less/errors/functions-5-color.less @@ -0,0 +1,2 @@ +@plugin "../plugin/plugin-tree-nodes"; +test-color(); \ No newline at end of file diff --git a/test/less/errors/functions-5-color.txt b/test/less/errors/functions-5-color.txt new file mode 100644 index 000000000..fdcd1a08a --- /dev/null +++ b/test/less/errors/functions-5-color.txt @@ -0,0 +1,3 @@ +SyntaxError: Color node returned by a function is not valid here in {path}functions-5-color.less on line 2, column 1: +1 @plugin "../plugin/plugin-tree-nodes"; +2 test-color(); diff --git a/test/less/errors/functions-6-condition.less b/test/less/errors/functions-6-condition.less new file mode 100644 index 000000000..db1000b83 --- /dev/null +++ b/test/less/errors/functions-6-condition.less @@ -0,0 +1,2 @@ +@plugin "../plugin/plugin-tree-nodes"; +test-condition(); \ No newline at end of file diff --git a/test/less/errors/functions-6-condition.txt b/test/less/errors/functions-6-condition.txt new file mode 100644 index 000000000..421bba5f5 --- /dev/null +++ b/test/less/errors/functions-6-condition.txt @@ -0,0 +1,3 @@ +SyntaxError: Condition node returned by a function is not valid here in {path}functions-6-condition.less on line 2, column 1: +1 @plugin "../plugin/plugin-tree-nodes"; +2 test-condition(); diff --git a/test/less/errors/functions-7-dimension.less b/test/less/errors/functions-7-dimension.less new file mode 100644 index 000000000..c399d33e2 --- /dev/null +++ b/test/less/errors/functions-7-dimension.less @@ -0,0 +1,2 @@ +@plugin "../plugin/plugin-tree-nodes"; +test-dimension(); \ No newline at end of file diff --git a/test/less/errors/functions-7-dimension.txt b/test/less/errors/functions-7-dimension.txt new file mode 100644 index 000000000..3b1b7026c --- /dev/null +++ b/test/less/errors/functions-7-dimension.txt @@ -0,0 +1,3 @@ +SyntaxError: Dimension node returned by a function is not valid here in {path}functions-7-dimension.less on line 2, column 1: +1 @plugin "../plugin/plugin-tree-nodes"; +2 test-dimension(); diff --git a/test/less/errors/functions-8-element.less b/test/less/errors/functions-8-element.less new file mode 100644 index 000000000..c762aad81 --- /dev/null +++ b/test/less/errors/functions-8-element.less @@ -0,0 +1,2 @@ +@plugin "../plugin/plugin-tree-nodes"; +test-element(); \ No newline at end of file diff --git a/test/less/errors/functions-8-element.txt b/test/less/errors/functions-8-element.txt new file mode 100644 index 000000000..b505d9543 --- /dev/null +++ b/test/less/errors/functions-8-element.txt @@ -0,0 +1,3 @@ +SyntaxError: Element node returned by a function is not valid here in {path}functions-8-element.less on line 2, column 1: +1 @plugin "../plugin/plugin-tree-nodes"; +2 test-element(); diff --git a/test/less/errors/functions-9-expression.less b/test/less/errors/functions-9-expression.less new file mode 100644 index 000000000..5f0bf46c4 --- /dev/null +++ b/test/less/errors/functions-9-expression.less @@ -0,0 +1,2 @@ +@plugin "../plugin/plugin-tree-nodes"; +test-expression(); \ No newline at end of file diff --git a/test/less/errors/functions-9-expression.txt b/test/less/errors/functions-9-expression.txt new file mode 100644 index 000000000..224db785e --- /dev/null +++ b/test/less/errors/functions-9-expression.txt @@ -0,0 +1,3 @@ +SyntaxError: Expression node returned by a function is not valid here in {path}functions-9-expression.less on line 2, column 1: +1 @plugin "../plugin/plugin-tree-nodes"; +2 test-expression(); diff --git a/test/less/errors/property-in-root.txt b/test/less/errors/property-in-root.txt index 04b277660..10c985344 100644 --- a/test/less/errors/property-in-root.txt +++ b/test/less/errors/property-in-root.txt @@ -1,4 +1,4 @@ -SyntaxError: properties must be inside selector blocks, they cannot be in the root. in {path}property-in-root.less on line 2, column 3: +SyntaxError: Properties must be inside selector blocks. They cannot be in the root in {path}property-in-root.less on line 2, column 3: 1 .a() { 2 prop:1; 3 } diff --git a/test/less/errors/property-in-root2.txt b/test/less/errors/property-in-root2.txt index 04b277660..10c985344 100644 --- a/test/less/errors/property-in-root2.txt +++ b/test/less/errors/property-in-root2.txt @@ -1,4 +1,4 @@ -SyntaxError: properties must be inside selector blocks, they cannot be in the root. in {path}property-in-root.less on line 2, column 3: +SyntaxError: Properties must be inside selector blocks. They cannot be in the root in {path}property-in-root.less on line 2, column 3: 1 .a() { 2 prop:1; 3 } diff --git a/test/less/errors/property-in-root3.txt b/test/less/errors/property-in-root3.txt index 68ef9454d..13a49052e 100644 --- a/test/less/errors/property-in-root3.txt +++ b/test/less/errors/property-in-root3.txt @@ -1,3 +1,3 @@ -SyntaxError: properties must be inside selector blocks, they cannot be in the root. in {path}property-in-root3.less on line 1, column 1: +SyntaxError: Properties must be inside selector blocks. They cannot be in the root in {path}property-in-root3.less on line 1, column 1: 1 prop:1; 2 .a { diff --git a/test/less/errors/root-func-undefined-1.less b/test/less/errors/root-func-undefined-1.less new file mode 100644 index 000000000..e5bacda6b --- /dev/null +++ b/test/less/errors/root-func-undefined-1.less @@ -0,0 +1 @@ +func(); \ No newline at end of file diff --git a/test/less/errors/root-func-undefined-1.txt b/test/less/errors/root-func-undefined-1.txt new file mode 100644 index 000000000..a07480e61 --- /dev/null +++ b/test/less/errors/root-func-undefined-1.txt @@ -0,0 +1,2 @@ +SyntaxError: Function 'func' is undefined in {path}root-func-undefined-1.less on line 1, column 1: +1 func(); diff --git a/test/less/errors/root-func-undefined-2.less b/test/less/errors/root-func-undefined-2.less new file mode 100644 index 000000000..ee34616e1 --- /dev/null +++ b/test/less/errors/root-func-undefined-2.less @@ -0,0 +1,2 @@ +@plugin "../plugin/plugin-tree-nodes.js"; +test-undefined(); \ No newline at end of file diff --git a/test/less/errors/root-func-undefined-2.txt b/test/less/errors/root-func-undefined-2.txt new file mode 100644 index 000000000..031385d01 --- /dev/null +++ b/test/less/errors/root-func-undefined-2.txt @@ -0,0 +1,3 @@ +SyntaxError: Function 'test-undefined' is undefined in {path}root-func-undefined-2.less on line 2, column 1: +1 @plugin "../plugin/plugin-tree-nodes.js"; +2 test-undefined(); diff --git a/test/less/plugin.less b/test/less/plugin.less index 17524a400..66775ea9f 100644 --- a/test/less/plugin.less +++ b/test/less/plugin.less @@ -81,5 +81,13 @@ } } +@plugin "./plugin/plugin-tree-nodes"; +@ruleset2: test-detached-ruleset(); +.root { + @ruleset2(); +} + +test-directive("@charset"; '"utf-8"'); +test-directive("@arbitrary"; "value after ()"); diff --git a/test/less/plugin/plugin-tree-nodes.js b/test/less/plugin/plugin-tree-nodes.js new file mode 100644 index 000000000..442352d7f --- /dev/null +++ b/test/less/plugin/plugin-tree-nodes.js @@ -0,0 +1,80 @@ +functions.addMultiple({ + + "test-comment": function() { + return new tree.Combinator(' '); + }, + "test-directive": function(arg1, arg2) { + return new tree.Directive(arg1.value, new tree.Anonymous(arg2.value)); + }, + "test-extend": function() { + //TODO + }, + "test-import": function() { + //TODO + }, + "test-media": function() { + //TODO + }, + "test-mixin-call": function() { + //TODO + }, + "test-mixin-definition": function() { + //TODO + }, + "test-ruleset-call": function() { + return new tree.Combinator(' '); + }, + // Functions must return something. Must 'return true' if they produce no output. + "test-undefined": function() { }, + + // These cause root errors + "test-alpha": function() { + return new tree.Alpha(30); + }, + "test-assignment": function() { + return new tree.Assignment("bird", "robin"); + }, + "test-attribute": function() { + return new tree.Attribute("foo", "=", "bar"); + }, + "test-call": function() { + return new tree.Call("foo"); + }, + "test-color": function() { + return new tree.Color([50, 50, 50]); + }, + "test-condition": function() { + return new tree.Condition('<', new tree.Value([0]), new tree.Value([1])); + }, + "test-detached-ruleset" : function() { + var rule = new tree.Rule('prop', new tree.Anonymous('value')); + return new tree.DetachedRuleset(new tree.Ruleset("", [ rule ])); + }, + "test-dimension": function() { + return new tree.Dimension(1, 'px'); + }, + "test-element": function() { + return new tree.Element('+', 'a'); + }, + "test-expression": function() { + return new tree.Expression([1, 2, 3]); + }, + "test-keyword": function() { + return new tree.Keyword('foo'); + }, + "test-operation": function() { + return new tree.Operation('+', [1, 2]); + }, + "test-quoted": function() { + return new tree.Quoted('"', 'foo'); + }, + "test-selector": function() { + return new tree.Selector([new tree.Element('a')]); + }, + "test-url": function() { + return new tree.URL('http://google.com'); + }, + "test-value": function() { + return new tree.Value([1]); + } +}); \ No newline at end of file