less 2.4.0 → 2.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (405) hide show
  1. package/.idea/jsLibraryMappings.xml +7 -7
  2. package/.idea/less.js.iml +9 -16
  3. package/.idea/libraries/less_js_node_modules.xml +14 -0
  4. package/.idea/misc.xml +14 -5
  5. package/.idea/modules.xml +8 -9
  6. package/.idea/vcs.xml +6 -7
  7. package/.idea/workspace.xml +592 -806
  8. package/.jscsrc +72 -72
  9. package/.travis.yml +1 -0
  10. package/CHANGELOG.md +54 -8
  11. package/Gruntfile.js +40 -13
  12. package/README.md +2 -0
  13. package/appveyor.yml +0 -6
  14. package/bin/lessc +22 -24
  15. package/bower.json +1 -2
  16. package/dist/less-rolledup.js +8572 -0
  17. package/dist/less.js +807 -401
  18. package/dist/less.min.js +9 -8
  19. package/lib/less/contexts.js +2 -0
  20. package/lib/less/environment/abstract-file-manager.js +5 -1
  21. package/lib/less/functions/color.js +46 -12
  22. package/lib/less/functions/function-caller.js +31 -2
  23. package/lib/less/functions/function-registry.js +28 -17
  24. package/lib/less/functions/math-helper.js +16 -0
  25. package/lib/less/functions/math.js +4 -16
  26. package/lib/less/functions/number.js +7 -2
  27. package/lib/less/functions/string.js +5 -3
  28. package/lib/less/functions/svg.js +19 -11
  29. package/lib/less/functions/types.js +1 -6
  30. package/lib/less/import-manager.js +8 -3
  31. package/lib/less/index.js +1 -1
  32. package/lib/less/parser/parser-input.js +55 -54
  33. package/lib/less/parser/parser.js +168 -52
  34. package/lib/less/plugins/function-importer.js +35 -0
  35. package/lib/less/source-map-output.js +1 -2
  36. package/lib/less/tree/anonymous.js +10 -2
  37. package/lib/less/tree/color.js +4 -1
  38. package/lib/less/tree/comment.js +0 -3
  39. package/lib/less/tree/dimension.js +5 -3
  40. package/lib/less/tree/directive.js +40 -15
  41. package/lib/less/tree/expression.js +5 -0
  42. package/lib/less/tree/import.js +22 -10
  43. package/lib/less/tree/media.js +3 -23
  44. package/lib/less/tree/mixin-call.js +17 -7
  45. package/lib/less/tree/mixin-definition.js +20 -6
  46. package/lib/less/tree/rule.js +19 -1
  47. package/lib/less/tree/ruleset.js +40 -27
  48. package/lib/less/tree/selector.js +8 -1
  49. package/lib/less/visitors/extend-visitor.js +1 -4
  50. package/lib/less/visitors/import-visitor.js +17 -2
  51. package/lib/less/visitors/join-selector-visitor.js +6 -0
  52. package/lib/less/visitors/to-css-visitor.js +48 -14
  53. package/lib/less-browser/bootstrap.js +5 -6
  54. package/lib/less-browser/index.js +20 -12
  55. package/lib/less-node/image-size.js +54 -31
  56. package/lib/less-node/index.js +1 -1
  57. package/lib/less-node/lessc-helper.js +2 -2
  58. package/lib/less-rhino/index.js +12 -8
  59. package/package.json +9 -13
  60. package/test/browser/less/urls.less +7 -1
  61. package/test/browser/less.js +30 -0
  62. package/test/browser/runner-VisitorPlugin-options.js +3 -0
  63. package/test/browser/runner-VisitorPlugin.js +3 -0
  64. package/test/browser/runner-filemanagerPlugin-options.js +4 -0
  65. package/test/browser/runner-filemanagerPlugin.js +3 -0
  66. package/test/browser/runner-global-vars-options.js +2 -1
  67. package/test/browser/runner-main-options.js +11 -11
  68. package/test/browser/runner-postProcessor.js +1 -1
  69. package/test/browser/runner-postProcessorPlugin-options.js +3 -0
  70. package/test/browser/runner-postProcessorPlugin.js +3 -0
  71. package/test/browser/runner-preProcessorPlugin-options.js +3 -0
  72. package/test/browser/runner-preProcessorPlugin.js +3 -0
  73. package/test/css/comments2.css +1 -1
  74. package/test/css/compression/compression.css +1 -1
  75. package/test/css/detached-rulesets.css +5 -0
  76. package/test/css/directives-bubling.css +119 -0
  77. package/test/css/extract-and-length.css +1 -1
  78. package/test/css/filemanagerPlugin/filemanager.css +3 -0
  79. package/test/css/functions.css +17 -1
  80. package/test/css/import-reference.css +5 -1
  81. package/test/css/import.css +4 -0
  82. package/test/css/include-path/include-path.css +4 -1
  83. package/test/css/include-path-string/include-path-string.css +3 -0
  84. package/test/css/legacy/legacy.css +14 -0
  85. package/test/css/media.css +0 -1
  86. package/test/css/mixins-args.css +51 -1
  87. package/test/css/plugin.css +44 -0
  88. package/test/css/postProcessorPlugin/postProcessor.css +4 -0
  89. package/test/css/preProcessorPlugin/preProcessor.css +3 -0
  90. package/test/css/scope.css +1 -1
  91. package/test/css/strings.css +1 -1
  92. package/test/css/url-args/urls.css +5 -5
  93. package/test/css/urls.css +8 -8
  94. package/test/css/variables.css +5 -5
  95. package/test/css/visitorPlugin/visitor.css +3 -0
  96. package/test/data/image.jpg +0 -0
  97. package/test/data/image.svg +2 -1
  98. package/test/data/page.html +1 -1
  99. package/test/index.js +5 -0
  100. package/test/less/detached-rulesets.less +9 -0
  101. package/test/less/directives-bubling.less +142 -0
  102. package/test/less/errors/at-rules-undefined-var.txt +4 -4
  103. package/test/less/errors/css-guard-default-func.txt +4 -4
  104. package/test/less/errors/javascript-undefined-var.txt +4 -4
  105. package/test/less/errors/mixins-guards-default-func-1.txt +4 -4
  106. package/test/less/errors/mixins-guards-default-func-2.txt +4 -4
  107. package/test/less/errors/mixins-guards-default-func-3.txt +4 -4
  108. package/test/less/errors/{parse-error-extra-parens.less → parse-error-media-no-block-1.less} +0 -0
  109. package/test/less/errors/parse-error-media-no-block-1.txt +3 -0
  110. package/test/less/errors/parse-error-media-no-block-2.less +1 -0
  111. package/test/less/errors/parse-error-media-no-block-2.txt +2 -0
  112. package/test/less/errors/parse-error-media-no-block-3.less +4 -0
  113. package/test/less/errors/parse-error-media-no-block-3.txt +3 -0
  114. package/test/less/errors/percentage-non-number-argument.less +3 -0
  115. package/test/less/errors/percentage-non-number-argument.txt +4 -0
  116. package/test/less/errors/property-interp-not-defined.txt +2 -2
  117. package/test/less/errors/svg-gradient2.txt +1 -1
  118. package/test/less/errors/svg-gradient3.txt +1 -1
  119. package/test/less/errors/svg-gradient4.less +4 -0
  120. package/test/less/errors/svg-gradient4.txt +4 -0
  121. package/test/less/errors/svg-gradient5.less +4 -0
  122. package/test/less/errors/svg-gradient5.txt +4 -0
  123. package/test/less/errors/svg-gradient6.less +4 -0
  124. package/test/less/errors/svg-gradient6.txt +4 -0
  125. package/test/less/filemanagerPlugin/colors.test +1 -0
  126. package/test/less/filemanagerPlugin/filemanager.less +4 -0
  127. package/test/less/functions.less +20 -2
  128. package/test/less/import/css-import.less +1 -0
  129. package/test/less/import/import-inline-invalid-css.less +1 -0
  130. package/test/less/import/import-reference.less +10 -1
  131. package/test/less/import/import-test-a.less +1 -0
  132. package/test/less/import-reference.less +4 -1
  133. package/test/less/import.less +1 -0
  134. package/test/less/include-path/include-path.less +3 -1
  135. package/test/less/include-path-string/include-path-string.less +3 -0
  136. package/test/less/legacy/legacy.less +14 -0
  137. package/test/less/mixins-args.less +48 -0
  138. package/test/less/mixins-guards.less +9 -0
  139. package/test/less/no-output.less +1 -1
  140. package/test/less/plugin/plugin-global.js +9 -0
  141. package/test/less/plugin/plugin-local.js +8 -0
  142. package/test/less/plugin/plugin-transitive.js +5 -0
  143. package/test/less/plugin/plugin-transitive.less +5 -0
  144. package/test/less/plugin.less +85 -0
  145. package/test/less/postProcessorPlugin/postProcessor.less +4 -0
  146. package/test/less/preProcessorPlugin/preProcessor.less +3 -0
  147. package/test/less/sourcemaps/imported.css +6 -6
  148. package/test/less/visitorPlugin/visitor.less +4 -0
  149. package/test/less-bom/charsets.less +3 -0
  150. package/test/less-bom/colors.less +98 -0
  151. package/test/less-bom/comments.less +102 -0
  152. package/test/less-bom/comments2.less +20 -0
  153. package/test/less-bom/compression/compression.less +36 -0
  154. package/test/less-bom/css-3.less +154 -0
  155. package/test/less-bom/css-escapes.less +33 -0
  156. package/test/less-bom/css-guards.less +103 -0
  157. package/test/less-bom/css.less +108 -0
  158. package/test/less-bom/debug/import/test.less +25 -0
  159. package/test/less-bom/debug/linenumbers.less +33 -0
  160. package/test/less-bom/detached-rulesets.less +112 -0
  161. package/test/less-bom/directives-bubling.less +142 -0
  162. package/test/less-bom/empty.less +1 -0
  163. package/test/less-bom/errors/add-mixed-units.less +3 -0
  164. package/test/less-bom/errors/add-mixed-units.txt +4 -0
  165. package/test/less-bom/errors/add-mixed-units2.less +3 -0
  166. package/test/less-bom/errors/add-mixed-units2.txt +4 -0
  167. package/test/less-bom/errors/at-rules-undefined-var.less +4 -0
  168. package/test/less-bom/errors/at-rules-undefined-var.txt +4 -0
  169. package/test/less-bom/errors/bad-variable-declaration1.less +1 -0
  170. package/test/less-bom/errors/bad-variable-declaration1.txt +2 -0
  171. package/test/less-bom/errors/color-func-invalid-color.less +3 -0
  172. package/test/less-bom/errors/color-func-invalid-color.txt +4 -0
  173. package/test/less-bom/errors/color-invalid-hex-code.less +3 -0
  174. package/test/less-bom/errors/color-invalid-hex-code.txt +4 -0
  175. package/test/less-bom/errors/color-invalid-hex-code2.less +3 -0
  176. package/test/less-bom/errors/color-invalid-hex-code2.txt +4 -0
  177. package/test/less-bom/errors/css-guard-default-func.less +4 -0
  178. package/test/less-bom/errors/css-guard-default-func.txt +4 -0
  179. package/test/less-bom/errors/detached-ruleset-1.less +6 -0
  180. package/test/less-bom/errors/detached-ruleset-1.txt +4 -0
  181. package/test/less-bom/errors/detached-ruleset-2.less +6 -0
  182. package/test/less-bom/errors/detached-ruleset-2.txt +4 -0
  183. package/test/less-bom/errors/detached-ruleset-3.less +4 -0
  184. package/test/less-bom/errors/detached-ruleset-3.txt +4 -0
  185. package/test/less-bom/errors/detached-ruleset-5.less +4 -0
  186. package/test/less-bom/errors/detached-ruleset-5.txt +3 -0
  187. package/test/less-bom/errors/detached-ruleset-6.less +5 -0
  188. package/test/less-bom/errors/detached-ruleset-6.txt +4 -0
  189. package/test/less-bom/errors/divide-mixed-units.less +3 -0
  190. package/test/less-bom/errors/divide-mixed-units.txt +4 -0
  191. package/test/less-bom/errors/extend-no-selector.less +3 -0
  192. package/test/less-bom/errors/extend-no-selector.txt +3 -0
  193. package/test/less-bom/errors/extend-not-at-end.less +3 -0
  194. package/test/less-bom/errors/extend-not-at-end.txt +3 -0
  195. package/test/less-bom/errors/import-malformed.less +1 -0
  196. package/test/less-bom/errors/import-malformed.txt +3 -0
  197. package/test/less-bom/errors/import-missing.less +6 -0
  198. package/test/less-bom/errors/import-missing.txt +3 -0
  199. package/test/less-bom/errors/import-no-semi.less +1 -0
  200. package/test/less-bom/errors/import-no-semi.txt +2 -0
  201. package/test/less-bom/errors/import-subfolder1.less +1 -0
  202. package/test/less-bom/errors/import-subfolder1.txt +3 -0
  203. package/test/less-bom/errors/import-subfolder2.less +1 -0
  204. package/test/less-bom/errors/import-subfolder2.txt +4 -0
  205. package/test/less-bom/errors/imports/import-subfolder1.less +1 -0
  206. package/test/less-bom/errors/imports/import-subfolder2.less +1 -0
  207. package/test/less-bom/errors/imports/import-test.less +4 -0
  208. package/test/less-bom/errors/imports/subfolder/mixin-not-defined.less +1 -0
  209. package/test/less-bom/errors/imports/subfolder/parse-error-curly-bracket.less +1 -0
  210. package/test/less-bom/errors/javascript-error.less +3 -0
  211. package/test/less-bom/errors/javascript-error.txt +4 -0
  212. package/test/less-bom/errors/javascript-undefined-var.less +3 -0
  213. package/test/less-bom/errors/javascript-undefined-var.txt +4 -0
  214. package/test/less-bom/errors/mixed-mixin-definition-args-1.less +6 -0
  215. package/test/less-bom/errors/mixed-mixin-definition-args-1.txt +4 -0
  216. package/test/less-bom/errors/mixed-mixin-definition-args-2.less +6 -0
  217. package/test/less-bom/errors/mixed-mixin-definition-args-2.txt +4 -0
  218. package/test/less-bom/errors/mixin-not-defined.less +11 -0
  219. package/test/less-bom/errors/mixin-not-defined.txt +3 -0
  220. package/test/less-bom/errors/mixin-not-matched.less +6 -0
  221. package/test/less-bom/errors/mixin-not-matched.txt +3 -0
  222. package/test/less-bom/errors/mixin-not-matched2.less +6 -0
  223. package/test/less-bom/errors/mixin-not-matched2.txt +3 -0
  224. package/test/less-bom/errors/mixin-not-visible-in-scope-1.less +9 -0
  225. package/test/less-bom/errors/mixin-not-visible-in-scope-1.txt +4 -0
  226. package/test/less-bom/errors/mixins-guards-default-func-1.less +9 -0
  227. package/test/less-bom/errors/mixins-guards-default-func-1.txt +4 -0
  228. package/test/less-bom/errors/mixins-guards-default-func-2.less +9 -0
  229. package/test/less-bom/errors/mixins-guards-default-func-2.txt +4 -0
  230. package/test/less-bom/errors/mixins-guards-default-func-3.less +9 -0
  231. package/test/less-bom/errors/mixins-guards-default-func-3.txt +4 -0
  232. package/test/less-bom/errors/multiple-guards-on-css-selectors.less +4 -0
  233. package/test/less-bom/errors/multiple-guards-on-css-selectors.txt +4 -0
  234. package/test/less-bom/errors/multiple-guards-on-css-selectors2.less +4 -0
  235. package/test/less-bom/errors/multiple-guards-on-css-selectors2.txt +4 -0
  236. package/test/less-bom/errors/multiply-mixed-units.less +7 -0
  237. package/test/less-bom/errors/multiply-mixed-units.txt +4 -0
  238. package/test/less-bom/errors/parens-error-1.less +3 -0
  239. package/test/less-bom/errors/parens-error-1.txt +4 -0
  240. package/test/less-bom/errors/parens-error-2.less +3 -0
  241. package/test/less-bom/errors/parens-error-2.txt +4 -0
  242. package/test/less-bom/errors/parens-error-3.less +3 -0
  243. package/test/less-bom/errors/parens-error-3.txt +4 -0
  244. package/test/less-bom/errors/parse-error-curly-bracket.less +4 -0
  245. package/test/less-bom/errors/parse-error-curly-bracket.txt +4 -0
  246. package/test/less-bom/errors/parse-error-media-no-block-1.less +5 -0
  247. package/test/less-bom/errors/parse-error-media-no-block-1.txt +3 -0
  248. package/test/less-bom/errors/parse-error-media-no-block-2.less +1 -0
  249. package/test/less-bom/errors/parse-error-media-no-block-2.txt +2 -0
  250. package/test/less-bom/errors/parse-error-media-no-block-3.less +4 -0
  251. package/test/less-bom/errors/parse-error-media-no-block-3.txt +3 -0
  252. package/test/less-bom/errors/parse-error-missing-bracket.less +2 -0
  253. package/test/less-bom/errors/parse-error-missing-bracket.txt +3 -0
  254. package/test/less-bom/errors/parse-error-missing-parens.less +5 -0
  255. package/test/less-bom/errors/parse-error-missing-parens.txt +3 -0
  256. package/test/less-bom/errors/parse-error-with-import.less +13 -0
  257. package/test/less-bom/errors/parse-error-with-import.txt +4 -0
  258. package/test/less-bom/errors/percentage-missing-space.less +3 -0
  259. package/test/less-bom/errors/percentage-missing-space.txt +4 -0
  260. package/test/less-bom/errors/percentage-non-number-argument.less +3 -0
  261. package/test/less-bom/errors/percentage-non-number-argument.txt +4 -0
  262. package/test/less-bom/errors/property-asterisk-only-name.less +3 -0
  263. package/test/less-bom/errors/property-asterisk-only-name.txt +4 -0
  264. package/test/less-bom/errors/property-ie5-hack.less +3 -0
  265. package/test/less-bom/errors/property-ie5-hack.txt +3 -0
  266. package/test/less-bom/errors/property-in-root.less +4 -0
  267. package/test/less-bom/errors/property-in-root.txt +4 -0
  268. package/test/less-bom/errors/property-in-root2.less +1 -0
  269. package/test/less-bom/errors/property-in-root2.txt +4 -0
  270. package/test/less-bom/errors/property-in-root3.less +4 -0
  271. package/test/less-bom/errors/property-in-root3.txt +3 -0
  272. package/test/less-bom/errors/property-interp-not-defined.less +1 -0
  273. package/test/less-bom/errors/property-interp-not-defined.txt +2 -0
  274. package/test/less-bom/errors/recursive-variable.less +1 -0
  275. package/test/less-bom/errors/recursive-variable.txt +2 -0
  276. package/test/less-bom/errors/single-character.less +1 -0
  277. package/test/less-bom/errors/single-character.txt +2 -0
  278. package/test/less-bom/errors/svg-gradient1.less +3 -0
  279. package/test/less-bom/errors/svg-gradient1.txt +4 -0
  280. package/test/less-bom/errors/svg-gradient2.less +3 -0
  281. package/test/less-bom/errors/svg-gradient2.txt +4 -0
  282. package/test/less-bom/errors/svg-gradient3.less +3 -0
  283. package/test/less-bom/errors/svg-gradient3.txt +4 -0
  284. package/test/less-bom/errors/svg-gradient4.less +4 -0
  285. package/test/less-bom/errors/svg-gradient4.txt +4 -0
  286. package/test/less-bom/errors/svg-gradient5.less +4 -0
  287. package/test/less-bom/errors/svg-gradient5.txt +4 -0
  288. package/test/less-bom/errors/svg-gradient6.less +4 -0
  289. package/test/less-bom/errors/svg-gradient6.txt +4 -0
  290. package/test/less-bom/errors/unit-function.less +3 -0
  291. package/test/less-bom/errors/unit-function.txt +4 -0
  292. package/test/less-bom/extend-chaining.less +91 -0
  293. package/test/less-bom/extend-clearfix.less +19 -0
  294. package/test/less-bom/extend-exact.less +46 -0
  295. package/test/less-bom/extend-media.less +24 -0
  296. package/test/less-bom/extend-nest.less +65 -0
  297. package/test/less-bom/extend-selector.less +99 -0
  298. package/test/less-bom/extend.less +81 -0
  299. package/test/less-bom/extract-and-length.less +133 -0
  300. package/test/less-bom/filemanagerPlugin/colors.test +1 -0
  301. package/test/less-bom/filemanagerPlugin/filemanager.less +4 -0
  302. package/test/less-bom/functions.less +232 -0
  303. package/test/less-bom/globalVars/extended.json +5 -0
  304. package/test/less-bom/globalVars/extended.less +10 -0
  305. package/test/less-bom/globalVars/simple.json +3 -0
  306. package/test/less-bom/globalVars/simple.less +3 -0
  307. package/test/less-bom/ie-filters.less +15 -0
  308. package/test/less-bom/import/css-import.less +1 -0
  309. package/test/less-bom/import/deeper/deeper-2/url-import-2.less +3 -0
  310. package/test/less-bom/import/deeper/deeper-2/url-import.less +1 -0
  311. package/test/less-bom/import/deeper/import-once-test-a.less +1 -0
  312. package/test/less-bom/import/deeper/url-import.less +1 -0
  313. package/test/less-bom/import/import-and-relative-paths-test.less +17 -0
  314. package/test/less-bom/import/import-charset-test.less +1 -0
  315. package/test/less-bom/import/import-inline-invalid-css.less +1 -0
  316. package/test/less-bom/import/import-interpolation.less +2 -0
  317. package/test/less-bom/import/import-interpolation2.less +5 -0
  318. package/test/less-bom/import/import-once-test-c.less +6 -0
  319. package/test/less-bom/import/import-reference.less +98 -0
  320. package/test/less-bom/import/import-test-a.less +5 -0
  321. package/test/less-bom/import/import-test-b.less +8 -0
  322. package/test/less-bom/import/import-test-c.less +6 -0
  323. package/test/less-bom/import/import-test-d.css +1 -0
  324. package/test/less-bom/import/import-test-e.less +2 -0
  325. package/test/less-bom/import/import-test-f.less +5 -0
  326. package/test/less-bom/import/imports/font.less +8 -0
  327. package/test/less-bom/import/imports/logo.less +6 -0
  328. package/test/less-bom/import/interpolation-vars.less +6 -0
  329. package/test/less-bom/import/invalid-css.less +1 -0
  330. package/test/less-bom/import/urls.less +1 -0
  331. package/test/less-bom/import-inline.less +3 -0
  332. package/test/less-bom/import-interpolation.less +8 -0
  333. package/test/less-bom/import-once.less +6 -0
  334. package/test/less-bom/import-reference.less +26 -0
  335. package/test/less-bom/import.less +31 -0
  336. package/test/less-bom/include-path/include-path.less +8 -0
  337. package/test/less-bom/include-path-string/include-path-string.less +3 -0
  338. package/test/less-bom/javascript.less +38 -0
  339. package/test/less-bom/lazy-eval.less +6 -0
  340. package/test/less-bom/legacy/legacy.less +21 -0
  341. package/test/less-bom/media.less +234 -0
  342. package/test/less-bom/merge.less +78 -0
  343. package/test/less-bom/mixins-args.less +263 -0
  344. package/test/less-bom/mixins-closure.less +26 -0
  345. package/test/less-bom/mixins-guards-default-func.less +195 -0
  346. package/test/less-bom/mixins-guards.less +280 -0
  347. package/test/less-bom/mixins-important.less +53 -0
  348. package/test/less-bom/mixins-interpolated.less +75 -0
  349. package/test/less-bom/mixins-named-args.less +36 -0
  350. package/test/less-bom/mixins-nested.less +22 -0
  351. package/test/less-bom/mixins-pattern.less +102 -0
  352. package/test/less-bom/mixins.less +145 -0
  353. package/test/less-bom/modifyVars/extended.json +5 -0
  354. package/test/less-bom/modifyVars/extended.less +11 -0
  355. package/test/less-bom/nested-gradient-with-svg-gradient/mixin-consumer.less +5 -0
  356. package/test/less-bom/nested-gradient-with-svg-gradient/svg-gradient-mixin.less +15 -0
  357. package/test/less-bom/no-js-errors/no-js-errors.less +3 -0
  358. package/test/less-bom/no-js-errors/no-js-errors.txt +4 -0
  359. package/test/less-bom/no-output.less +2 -0
  360. package/test/less-bom/operations.less +62 -0
  361. package/test/less-bom/parens.less +45 -0
  362. package/test/less-bom/plugin/plugin-global.js +9 -0
  363. package/test/less-bom/plugin/plugin-local.js +8 -0
  364. package/test/less-bom/plugin/plugin-transitive.js +5 -0
  365. package/test/less-bom/plugin/plugin-transitive.less +5 -0
  366. package/test/less-bom/plugin.less +85 -0
  367. package/test/less-bom/postProcessorPlugin/postProcessor.less +4 -0
  368. package/test/less-bom/preProcessorPlugin/preProcessor.less +3 -0
  369. package/test/less-bom/property-name-interp.less +56 -0
  370. package/test/less-bom/rulesets.less +30 -0
  371. package/test/less-bom/scope.less +104 -0
  372. package/test/less-bom/selectors.less +184 -0
  373. package/test/less-bom/sourcemaps/basic.json +3 -0
  374. package/test/less-bom/sourcemaps/basic.less +27 -0
  375. package/test/less-bom/sourcemaps/imported.css +7 -0
  376. package/test/less-bom/sourcemaps-empty/empty.less +1 -0
  377. package/test/less-bom/sourcemaps-empty/var-defs.less +1 -0
  378. package/test/less-bom/static-urls/urls.less +33 -0
  379. package/test/less-bom/strict-units/strict-units.less +4 -0
  380. package/test/less-bom/strings.less +73 -0
  381. package/test/less-bom/url-args/urls.less +63 -0
  382. package/test/less-bom/urls.less +94 -0
  383. package/test/less-bom/variables-in-at-rules.less +20 -0
  384. package/test/less-bom/variables.less +119 -0
  385. package/test/less-bom/visitorPlugin/visitor.less +4 -0
  386. package/test/less-bom/whitespace.less +44 -0
  387. package/test/less-test.js +9 -5
  388. package/test/plugins/filemanager/index.js +19 -0
  389. package/test/plugins/postprocess/index.js +14 -0
  390. package/test/plugins/preprocess/index.js +19 -0
  391. package/test/plugins/visitor/index.js +24 -0
  392. package/test.less +1 -0
  393. package/.idea/codeStyleSettings.xml +0 -13
  394. package/.idea/encodings.xml +0 -5
  395. package/.idea/inspectionProfiles/Project_Default.xml +0 -8
  396. package/.idea/inspectionProfiles/profiles_settings.xml +0 -7
  397. package/.idea/jsLinters/jscs.xml +0 -4
  398. package/.idea/jsLinters/jshint.xml +0 -70
  399. package/.idea/libraries/sass_stdlib.xml +0 -8
  400. package/.idea/scopes/scope_settings.xml +0 -5
  401. package/projectFilesBackup/.idea/libraries/sass_stdlib.xml +0 -8
  402. package/test/less/errors/detached-ruleset-4.less +0 -5
  403. package/test/less/errors/detached-ruleset-4.txt +0 -4
  404. package/test/less/errors/parse-error-extra-parens.txt +0 -3
  405. package/test/sourcemaps/maps/import-map.map +0 -1
@@ -43,7 +43,7 @@ var Parser = function Parser(context, imports, fileInfo) {
43
43
 
44
44
  function expect(arg, msg, index) {
45
45
  // some older browsers return typeof 'function' for RegExp
46
- var result = (Object.prototype.toString.call(arg) === '[object Function]') ? arg.call(parsers) : parserInput.$(arg);
46
+ var result = (Object.prototype.toString.call(arg) === '[object Function]') ? arg.call(parsers) : parserInput.$re(arg);
47
47
  if (result) {
48
48
  return result;
49
49
  }
@@ -122,7 +122,7 @@ var Parser = function Parser(context, imports, fileInfo) {
122
122
  // output. The callback is called when the input is parsed.
123
123
  try {
124
124
  parserInput.start(str, context.chunkInput, function fail(msg, index) {
125
- throw LessError({
125
+ throw new LessError({
126
126
  index: index,
127
127
  type: 'Parse',
128
128
  message: msg,
@@ -217,7 +217,7 @@ var Parser = function Parser(context, imports, fileInfo) {
217
217
  // Ruleset (Selector [Element '>', '.child'], [...])
218
218
  // ])
219
219
  //
220
- // In general, most rules will try to parse a token with the `$()` function, and if the return
220
+ // In general, most rules will try to parse a token with the `$re()` function, and if the return
221
221
  // value is truly, will return a new node, of the relevant type. Sometimes, we need to check
222
222
  // first, before parsing, that's when we use `peek()`.
223
223
  //
@@ -240,8 +240,7 @@ var Parser = function Parser(context, imports, fileInfo) {
240
240
  primary: function () {
241
241
  var mixin = this.mixin, root = [], node;
242
242
 
243
- while (true)
244
- {
243
+ while (true) {
245
244
  while (true) {
246
245
  node = this.comment();
247
246
  if (!node) { break; }
@@ -266,7 +265,11 @@ var Parser = function Parser(context, imports, fileInfo) {
266
265
  if (node) {
267
266
  root.push(node);
268
267
  } else {
269
- if (!(parserInput.$re(/^[\s\n]+/) || parserInput.$re(/^;+/))) {
268
+ var foundSemiColon = false;
269
+ while (parserInput.$char(";")) {
270
+ foundSemiColon = true;
271
+ }
272
+ if (!foundSemiColon) {
270
273
  break;
271
274
  }
272
275
  }
@@ -294,12 +297,20 @@ var Parser = function Parser(context, imports, fileInfo) {
294
297
  // "milky way" 'he\'s the one!'
295
298
  //
296
299
  quoted: function () {
297
- var str, index = parserInput.i;
300
+ var str, index = parserInput.i, isEscaped = false;
298
301
 
299
- str = parserInput.$re(/^(~)?("((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)')/);
300
- if (str) {
301
- return new(tree.Quoted)(str[2], str[3] || str[4], Boolean(str[1]), index, fileInfo);
302
+ parserInput.save();
303
+ if (parserInput.$char("~")) {
304
+ isEscaped = true;
305
+ }
306
+ str = parserInput.$quoted();
307
+ if (!str) {
308
+ parserInput.restore();
309
+ return;
302
310
  }
311
+ parserInput.forget();
312
+
313
+ return new(tree.Quoted)(str.charAt(0), str.substr(1, str.length - 2), isEscaped, index, fileInfo);
303
314
  },
304
315
 
305
316
  //
@@ -308,7 +319,7 @@ var Parser = function Parser(context, imports, fileInfo) {
308
319
  // black border-collapse
309
320
  //
310
321
  keyword: function () {
311
- var k = parserInput.$re(/^%|^[_A-Za-z-][_A-Za-z0-9-]*/);
322
+ var k = parserInput.$char("%") || parserInput.$re(/^[_A-Za-z-][_A-Za-z0-9-]*/);
312
323
  if (k) {
313
324
  return tree.Color.fromKeyword(k) || new(tree.Keyword)(k);
314
325
  }
@@ -327,6 +338,7 @@ var Parser = function Parser(context, imports, fileInfo) {
327
338
  call: function () {
328
339
  var name, nameLC, args, alpha, index = parserInput.i;
329
340
 
341
+ // http://jsperf.com/case-insensitive-regex-vs-strtolower-then-regex/18
330
342
  if (parserInput.peek(/^url\(/i)) {
331
343
  return;
332
344
  }
@@ -342,6 +354,7 @@ var Parser = function Parser(context, imports, fileInfo) {
342
354
  if (nameLC === 'alpha') {
343
355
  alpha = parsers.alpha();
344
356
  if (alpha) {
357
+ parserInput.forget();
345
358
  return alpha;
346
359
  }
347
360
  }
@@ -386,16 +399,22 @@ var Parser = function Parser(context, imports, fileInfo) {
386
399
 
387
400
  assignment: function () {
388
401
  var key, value;
402
+ parserInput.save();
389
403
  key = parserInput.$re(/^\w+(?=\s?=)/i);
390
404
  if (!key) {
405
+ parserInput.restore();
391
406
  return;
392
407
  }
393
408
  if (!parserInput.$char('=')) {
409
+ parserInput.restore();
394
410
  return;
395
411
  }
396
412
  value = parsers.entity();
397
413
  if (value) {
414
+ parserInput.forget();
398
415
  return new(tree.Assignment)(key, value);
416
+ } else {
417
+ parserInput.restore();
399
418
  }
400
419
  },
401
420
 
@@ -411,7 +430,7 @@ var Parser = function Parser(context, imports, fileInfo) {
411
430
 
412
431
  parserInput.autoCommentAbsorb = false;
413
432
 
414
- if (parserInput.currentChar() !== 'u' || !parserInput.$re(/^url\(/)) {
433
+ if (!parserInput.$str("url(")) {
415
434
  parserInput.autoCommentAbsorb = true;
416
435
  return;
417
436
  }
@@ -470,7 +489,7 @@ var Parser = function Parser(context, imports, fileInfo) {
470
489
  if (!colorCandidateString.match(/^[A-Fa-f0-9]+$/)) { // verify if candidate consists only of allowed HEX characters
471
490
  error("Invalid HEX color code");
472
491
  }
473
- return new(tree.Color)(rgb[1]);
492
+ return new(tree.Color)(rgb[1], undefined, '#' + colorCandidateString);
474
493
  }
475
494
  },
476
495
 
@@ -512,10 +531,22 @@ var Parser = function Parser(context, imports, fileInfo) {
512
531
  javascript: function () {
513
532
  var js, index = parserInput.i;
514
533
 
515
- js = parserInput.$re(/^(~)?`([^`]*)`/);
534
+ parserInput.save();
535
+
536
+ var escape = parserInput.$char("~");
537
+ var jsQuote = parserInput.$char("`");
538
+
539
+ if (!jsQuote) {
540
+ parserInput.restore();
541
+ return;
542
+ }
543
+
544
+ js = parserInput.$re(/^[^`]*`/);
516
545
  if (js) {
517
- return new(tree.JavaScript)(js[2], Boolean(js[1]), index, fileInfo);
546
+ parserInput.forget();
547
+ return new(tree.JavaScript)(js.substr(0, js.length - 1), Boolean(escape), index, fileInfo);
518
548
  }
549
+ parserInput.restore("invalid javascript definition");
519
550
  }
520
551
  },
521
552
 
@@ -549,7 +580,9 @@ var Parser = function Parser(context, imports, fileInfo) {
549
580
  extend: function(isRule) {
550
581
  var elements, e, index = parserInput.i, option, extendList, extend;
551
582
 
552
- if (!(isRule ? parserInput.$re(/^&:extend\(/) : parserInput.$re(/^:extend\(/))) { return; }
583
+ if (!parserInput.$str(isRule ? "&:extend(" : ":extend(")) {
584
+ return;
585
+ }
553
586
 
554
587
  do {
555
588
  option = null;
@@ -654,7 +687,8 @@ var Parser = function Parser(context, imports, fileInfo) {
654
687
  var entities = parsers.entities,
655
688
  returner = { args:null, variadic: false },
656
689
  expressions = [], argsSemiColon = [], argsComma = [],
657
- isSemiColonSeparated, expressionContainsNamed, name, nameLoop, value, arg;
690
+ isSemiColonSeparated, expressionContainsNamed, name, nameLoop,
691
+ value, arg, expand;
658
692
 
659
693
  parserInput.save();
660
694
 
@@ -663,7 +697,7 @@ var Parser = function Parser(context, imports, fileInfo) {
663
697
  arg = parsers.detachedRuleset() || parsers.expression();
664
698
  } else {
665
699
  parserInput.commentStore.length = 0;
666
- if (parserInput.currentChar() === '.' && parserInput.$re(/^\.{3}/)) {
700
+ if (parserInput.$str("...")) {
667
701
  returner.variadic = true;
668
702
  if (parserInput.$char(";") && !isSemiColonSeparated) {
669
703
  isSemiColonSeparated = true;
@@ -704,10 +738,7 @@ var Parser = function Parser(context, imports, fileInfo) {
704
738
  expressionContainsNamed = true;
705
739
  }
706
740
 
707
- // we do not support setting a ruleset as a default variable - it doesn't make sense
708
- // However if we do want to add it, there is nothing blocking it, just don't error
709
- // and remove isCall dependency below
710
- value = (isCall && parsers.detachedRuleset()) || parsers.expression();
741
+ value = parsers.detachedRuleset() || parsers.expression();
711
742
 
712
743
  if (!value) {
713
744
  if (isCall) {
@@ -719,14 +750,18 @@ var Parser = function Parser(context, imports, fileInfo) {
719
750
  }
720
751
  }
721
752
  nameLoop = (name = val.name);
722
- } else if (!isCall && parserInput.$re(/^\.{3}/)) {
723
- returner.variadic = true;
724
- if (parserInput.$char(";") && !isSemiColonSeparated) {
725
- isSemiColonSeparated = true;
753
+ } else if (parserInput.$str("...")) {
754
+ if (!isCall) {
755
+ returner.variadic = true;
756
+ if (parserInput.$char(";") && !isSemiColonSeparated) {
757
+ isSemiColonSeparated = true;
758
+ }
759
+ (isSemiColonSeparated ? argsSemiColon : argsComma)
760
+ .push({ name: arg.name, variadic: true });
761
+ break;
762
+ } else {
763
+ expand = true;
726
764
  }
727
- (isSemiColonSeparated ? argsSemiColon : argsComma)
728
- .push({ name: arg.name, variadic: true });
729
- break;
730
765
  } else if (!isCall) {
731
766
  name = nameLoop = val.name;
732
767
  value = null;
@@ -737,7 +772,7 @@ var Parser = function Parser(context, imports, fileInfo) {
737
772
  expressions.push(value);
738
773
  }
739
774
 
740
- argsComma.push({ name:nameLoop, value:value });
775
+ argsComma.push({ name:nameLoop, value:value, expand:expand });
741
776
 
742
777
  if (parserInput.$char(',')) {
743
778
  continue;
@@ -754,7 +789,7 @@ var Parser = function Parser(context, imports, fileInfo) {
754
789
  if (expressions.length > 1) {
755
790
  value = new(tree.Value)(expressions);
756
791
  }
757
- argsSemiColon.push({ name:name, value:value });
792
+ argsSemiColon.push({ name:name, value:value, expand:expand });
758
793
 
759
794
  name = null;
760
795
  expressions = [];
@@ -814,7 +849,7 @@ var Parser = function Parser(context, imports, fileInfo) {
814
849
 
815
850
  parserInput.commentStore.length = 0;
816
851
 
817
- if (parserInput.$re(/^when/)) { // Guard
852
+ if (parserInput.$str("when")) { // Guard
818
853
  cond = expect(parsers.conditions, 'expected condition');
819
854
  }
820
855
 
@@ -860,6 +895,7 @@ var Parser = function Parser(context, imports, fileInfo) {
860
895
  alpha: function () {
861
896
  var value;
862
897
 
898
+ // http://jsperf.com/case-insensitive-regex-vs-strtolower-then-regex/18
863
899
  if (! parserInput.$re(/^opacity=/i)) { return; }
864
900
  value = parserInput.$re(/^\d+/);
865
901
  if (!value) {
@@ -963,7 +999,7 @@ var Parser = function Parser(context, imports, fileInfo) {
963
999
  selector: function (isLess) {
964
1000
  var index = parserInput.i, elements, extendList, c, e, allExtends, when, condition;
965
1001
 
966
- while ((isLess && (extendList = this.extend())) || (isLess && (when = parserInput.$re(/^when/))) || (e = this.element())) {
1002
+ while ((isLess && (extendList = this.extend())) || (isLess && (when = parserInput.$str("when"))) || (e = this.element())) {
967
1003
  if (when) {
968
1004
  condition = expect(this.conditions, 'expected condition');
969
1005
  } else if (condition) {
@@ -1086,7 +1122,7 @@ var Parser = function Parser(context, imports, fileInfo) {
1086
1122
  rule: function (tryAnonymous) {
1087
1123
  var name, value, startOfRule = parserInput.i, c = parserInput.currentChar(), important, merge, isVariable;
1088
1124
 
1089
- if (c === '.' || c === '#' || c === '&') { return; }
1125
+ if (c === '.' || c === '#' || c === '&' || c === ':') { return; }
1090
1126
 
1091
1127
  parserInput.save();
1092
1128
 
@@ -1103,7 +1139,7 @@ var Parser = function Parser(context, imports, fileInfo) {
1103
1139
  // a name returned by this.ruleProperty() is always an array of the form:
1104
1140
  // [string-1, ..., string-n, ""] or [string-1, ..., string-n, "+"]
1105
1141
  // where each item is a tree.Keyword or tree.Variable
1106
- merge = !isVariable && name.pop().value;
1142
+ merge = !isVariable && name.length > 1 && name.pop().value;
1107
1143
 
1108
1144
  // prefer to try to parse first if its a variable or we are compressing
1109
1145
  // but always fallback on the other one
@@ -1116,7 +1152,7 @@ var Parser = function Parser(context, imports, fileInfo) {
1116
1152
  value = this.anonymousValue();
1117
1153
  if (value) {
1118
1154
  parserInput.forget();
1119
- // anonymous values absorb the end ';' which is reequired for them to work
1155
+ // anonymous values absorb the end ';' which is required for them to work
1120
1156
  return new (tree.Rule)(name, value, false, merge, startOfRule, fileInfo);
1121
1157
  }
1122
1158
  }
@@ -1168,15 +1204,14 @@ var Parser = function Parser(context, imports, fileInfo) {
1168
1204
  if ((path = this.entities.quoted() || this.entities.url())) {
1169
1205
  features = this.mediaFeatures();
1170
1206
 
1171
- if (!parserInput.$(';')) {
1207
+ if (!parserInput.$char(';')) {
1172
1208
  parserInput.i = index;
1173
1209
  error("missing semi-colon or unrecognised media features on import");
1174
1210
  }
1175
1211
  features = features && new(tree.Value)(features);
1176
1212
  return new(tree.Import)(path, features, options, index, fileInfo);
1177
1213
  }
1178
- else
1179
- {
1214
+ else {
1180
1215
  parserInput.i = index;
1181
1216
  error("malformed import statement");
1182
1217
  }
@@ -1276,16 +1311,61 @@ var Parser = function Parser(context, imports, fileInfo) {
1276
1311
  debugInfo = getDebugInfo(parserInput.i);
1277
1312
  }
1278
1313
 
1279
- if (parserInput.$re(/^@media/)) {
1314
+ parserInput.save();
1315
+
1316
+ if (parserInput.$str("@media")) {
1280
1317
  features = this.mediaFeatures();
1281
1318
 
1282
1319
  rules = this.block();
1283
- if (rules) {
1284
- media = new(tree.Media)(rules, features, parserInput.i, fileInfo);
1285
- if (context.dumpLineNumbers) {
1286
- media.debugInfo = debugInfo;
1320
+
1321
+ if (!rules) {
1322
+ parserInput.restore("media definitions require block statements after any features");
1323
+ return;
1324
+ }
1325
+
1326
+ parserInput.forget();
1327
+
1328
+ media = new(tree.Media)(rules, features, parserInput.i, fileInfo);
1329
+ if (context.dumpLineNumbers) {
1330
+ media.debugInfo = debugInfo;
1331
+ }
1332
+
1333
+ return media;
1334
+ }
1335
+
1336
+ parserInput.restore();
1337
+ },
1338
+
1339
+ //
1340
+ // A @plugin directive, used to import compiler extensions dynamically.
1341
+ //
1342
+ // @plugin "lib";
1343
+ //
1344
+ // Depending on our environment, importing is done differently:
1345
+ // In the browser, it's an XHR request, in Node, it would be a
1346
+ // file-system operation. The function used for importing is
1347
+ // stored in `import`, which we pass to the Import constructor.
1348
+ //
1349
+ plugin: function () {
1350
+ var path,
1351
+ index = parserInput.i,
1352
+ dir = parserInput.$re(/^@plugin?\s+/);
1353
+
1354
+ if (dir) {
1355
+ var options = { plugin : true };
1356
+
1357
+ if ((path = this.entities.quoted() || this.entities.url())) {
1358
+
1359
+ if (!parserInput.$char(';')) {
1360
+ parserInput.i = index;
1361
+ error("missing semi-colon on plugin");
1287
1362
  }
1288
- return media;
1363
+
1364
+ return new(tree.Import)(path, null, options, index, fileInfo);
1365
+ }
1366
+ else {
1367
+ parserInput.i = index;
1368
+ error("malformed plugin statement");
1289
1369
  }
1290
1370
  }
1291
1371
  },
@@ -1297,11 +1377,11 @@ var Parser = function Parser(context, imports, fileInfo) {
1297
1377
  //
1298
1378
  directive: function () {
1299
1379
  var index = parserInput.i, name, value, rules, nonVendorSpecificName,
1300
- hasIdentifier, hasExpression, hasUnknown, hasBlock = true;
1380
+ hasIdentifier, hasExpression, hasUnknown, hasBlock = true, isRooted = true;
1301
1381
 
1302
1382
  if (parserInput.currentChar() !== '@') { return; }
1303
1383
 
1304
- value = this['import']() || this.media();
1384
+ value = this['import']() || this.plugin() || this.media();
1305
1385
  if (value) {
1306
1386
  return value;
1307
1387
  }
@@ -1338,6 +1418,7 @@ var Parser = function Parser(context, imports, fileInfo) {
1338
1418
  case "@right-middle":
1339
1419
  case "@right-bottom":
1340
1420
  hasBlock = true;
1421
+ isRooted = true;
1341
1422
  break;
1342
1423
  */
1343
1424
  case "@counter-style":
@@ -1357,9 +1438,12 @@ var Parser = function Parser(context, imports, fileInfo) {
1357
1438
  break;
1358
1439
  case "@host":
1359
1440
  case "@page":
1441
+ hasUnknown = true;
1442
+ break;
1360
1443
  case "@document":
1361
1444
  case "@supports":
1362
1445
  hasUnknown = true;
1446
+ isRooted = false;
1363
1447
  break;
1364
1448
  }
1365
1449
 
@@ -1388,8 +1472,11 @@ var Parser = function Parser(context, imports, fileInfo) {
1388
1472
 
1389
1473
  if (rules || (!hasBlock && value && parserInput.$char(';'))) {
1390
1474
  parserInput.forget();
1391
- return new(tree.Directive)(name, value, rules, index, fileInfo,
1392
- context.dumpLineNumbers ? getDebugInfo(index) : null);
1475
+ return new (tree.Directive)(name, value, rules, index, fileInfo,
1476
+ context.dumpLineNumbers ? getDebugInfo(index) : null,
1477
+ false,
1478
+ isRooted
1479
+ );
1393
1480
  }
1394
1481
 
1395
1482
  parserInput.restore("directive options not recognised");
@@ -1514,11 +1601,33 @@ var Parser = function Parser(context, imports, fileInfo) {
1514
1601
  var entities = this.entities, index = parserInput.i, negate = false,
1515
1602
  a, b, c, op;
1516
1603
 
1517
- if (parserInput.$re(/^not/)) { negate = true; }
1604
+ if (parserInput.$str("not")) { negate = true; }
1518
1605
  expectChar('(');
1519
1606
  a = this.addition() || entities.keyword() || entities.quoted();
1520
1607
  if (a) {
1521
- op = parserInput.$re(/^(?:>=|<=|=<|[<=>])/);
1608
+ if (parserInput.$char('>')) {
1609
+ if (parserInput.$char('=')) {
1610
+ op = ">=";
1611
+ } else {
1612
+ op = '>';
1613
+ }
1614
+ } else
1615
+ if (parserInput.$char('<')) {
1616
+ if (parserInput.$char('=')) {
1617
+ op = "<=";
1618
+ } else {
1619
+ op = '<';
1620
+ }
1621
+ } else
1622
+ if (parserInput.$char('=')) {
1623
+ if (parserInput.$char('>')) {
1624
+ op = "=>";
1625
+ } else if (parserInput.$char('<')) {
1626
+ op = '=<';
1627
+ } else {
1628
+ op = '=';
1629
+ }
1630
+ }
1522
1631
  if (op) {
1523
1632
  b = this.addition() || entities.keyword() || entities.quoted();
1524
1633
  if (b) {
@@ -1530,7 +1639,7 @@ var Parser = function Parser(context, imports, fileInfo) {
1530
1639
  c = new(tree.Condition)('=', a, new(tree.Keyword)('true'), index, negate);
1531
1640
  }
1532
1641
  expectChar(')');
1533
- return parserInput.$re(/^and/) ? new(tree.Condition)('and', c, this.condition()) : c;
1642
+ return parserInput.$str("and") ? new(tree.Condition)('and', c, this.condition()) : c;
1534
1643
  }
1535
1644
  },
1536
1645
 
@@ -1600,6 +1709,13 @@ var Parser = function Parser(context, imports, fileInfo) {
1600
1709
 
1601
1710
  parserInput.save();
1602
1711
 
1712
+ var simpleProperty = parserInput.$re(/^([_a-zA-Z0-9-]+)\s*:/);
1713
+ if (simpleProperty) {
1714
+ name = [new(tree.Keyword)(simpleProperty[1])];
1715
+ parserInput.forget();
1716
+ return name;
1717
+ }
1718
+
1603
1719
  function match(re) {
1604
1720
  var i = parserInput.i,
1605
1721
  chunk = parserInput.$re(re);
@@ -0,0 +1,35 @@
1
+ var LessError = require('../less-error'),
2
+ tree = require("../tree");
3
+
4
+ var FunctionImporter = module.exports = function FunctionImporter(context, fileInfo) {
5
+ this.fileInfo = fileInfo;
6
+ };
7
+
8
+ FunctionImporter.prototype.eval = function(contents, callback) {
9
+ var loaded = {},
10
+ loader,
11
+ registry;
12
+
13
+ registry = {
14
+ add: function(name, func) {
15
+ loaded[name] = func;
16
+ },
17
+ addMultiple: function(functions) {
18
+ Object.keys(functions).forEach(function(name) {
19
+ loaded[name] = functions[name];
20
+ });
21
+ }
22
+ };
23
+
24
+ try {
25
+ loader = new Function("functions", "tree", "fileInfo", contents);
26
+ loader(registry, tree, this.fileInfo);
27
+ } catch(e) {
28
+ callback(new LessError({
29
+ message: "Plugin evaluation error: '" + e.name + ': ' + e.message.replace(/["]/g, "'") + "'" ,
30
+ filename: this.fileInfo.filename
31
+ }), null );
32
+ }
33
+
34
+ callback(null, { functions: loaded });
35
+ };
@@ -105,8 +105,7 @@ module.exports = function (environment) {
105
105
 
106
106
  if (this._outputSourceFiles) {
107
107
  for (var filename in this._contentsMap) {
108
- if (this._contentsMap.hasOwnProperty(filename))
109
- {
108
+ if (this._contentsMap.hasOwnProperty(filename)) {
110
109
  var source = this._contentsMap[filename];
111
110
  if (this._contentsIgnoredCharsMap[filename]) {
112
111
  source = source.slice(this._contentsIgnoredCharsMap[filename]);
@@ -1,16 +1,17 @@
1
1
  var Node = require("./node");
2
2
 
3
- var Anonymous = function (value, index, currentFileInfo, mapLines, rulesetLike) {
3
+ var Anonymous = function (value, index, currentFileInfo, mapLines, rulesetLike, referenced) {
4
4
  this.value = value;
5
5
  this.index = index;
6
6
  this.mapLines = mapLines;
7
7
  this.currentFileInfo = currentFileInfo;
8
8
  this.rulesetLike = (typeof rulesetLike === 'undefined') ? false : rulesetLike;
9
+ this.isReferenced = referenced || false;
9
10
  };
10
11
  Anonymous.prototype = new Node();
11
12
  Anonymous.prototype.type = "Anonymous";
12
13
  Anonymous.prototype.eval = function () {
13
- return new Anonymous(this.value, this.index, this.currentFileInfo, this.mapLines, this.rulesetLike);
14
+ return new Anonymous(this.value, this.index, this.currentFileInfo, this.mapLines, this.rulesetLike, this.isReferenced);
14
15
  };
15
16
  Anonymous.prototype.compare = function (other) {
16
17
  return other.toCSS && this.toCSS() === other.toCSS() ? 0 : undefined;
@@ -21,4 +22,11 @@ Anonymous.prototype.isRulesetLike = function() {
21
22
  Anonymous.prototype.genCSS = function (context, output) {
22
23
  output.add(this.value, this.currentFileInfo, this.index, this.mapLines);
23
24
  };
25
+ Anonymous.prototype.markReferenced = function () {
26
+ this.isReferenced = true;
27
+ };
28
+ Anonymous.prototype.getIsReferenced = function () {
29
+ return !this.currentFileInfo || !this.currentFileInfo.reference || this.isReferenced;
30
+ };
31
+
24
32
  module.exports = Anonymous;
@@ -4,7 +4,7 @@ var Node = require("./node"),
4
4
  //
5
5
  // RGB Colors - #ff0014, #eee
6
6
  //
7
- var Color = function (rgb, a) {
7
+ var Color = function (rgb, a, originalForm) {
8
8
  //
9
9
  // The end goal here, is to parse the arguments
10
10
  // into an integer triplet, such as `128, 255, 0`
@@ -23,6 +23,9 @@ var Color = function (rgb, a) {
23
23
  });
24
24
  }
25
25
  this.alpha = typeof a === 'number' ? a : 1;
26
+ if (typeof originalForm !== 'undefined') {
27
+ this.value = originalForm;
28
+ }
26
29
  };
27
30
 
28
31
  Color.prototype = new Node();
@@ -22,7 +22,4 @@ Comment.prototype.isSilent = function(context) {
22
22
  Comment.prototype.markReferenced = function () {
23
23
  this.isReferenced = true;
24
24
  };
25
- Comment.prototype.isRulesetLike = function(root) {
26
- return Boolean(root);
27
- };
28
25
  module.exports = Comment;
@@ -63,8 +63,10 @@ Dimension.prototype.operate = function (context, op, other) {
63
63
 
64
64
  if (op === '+' || op === '-') {
65
65
  if (unit.numerator.length === 0 && unit.denominator.length === 0) {
66
- unit.numerator = other.unit.numerator.slice(0);
67
- unit.denominator = other.unit.denominator.slice(0);
66
+ unit = other.unit.clone();
67
+ if (this.unit.backupUnit) {
68
+ unit.backupUnit = this.unit.backupUnit;
69
+ }
68
70
  } else if (other.unit.numerator.length === 0 && unit.denominator.length === 0) {
69
71
  // do nothing
70
72
  } else {
@@ -125,7 +127,7 @@ Dimension.prototype.convertTo = function (conversions) {
125
127
  conversions = derivedConversions;
126
128
  }
127
129
  applyUnit = function (atomicUnit, denominator) {
128
- /*jshint loopfunc:true */
130
+ /* jshint loopfunc:true */
129
131
  if (group.hasOwnProperty(atomicUnit)) {
130
132
  if (denominator) {
131
133
  value = value / (group[atomicUnit] / group[targetUnit]);