less 2.1.1 → 2.3.1

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 (333) hide show
  1. package/.idea/inspectionProfiles/Project_Default.xml +1 -0
  2. package/.idea/jsLinters/jscs.xml +4 -0
  3. package/.idea/jsLinters/jshint.xml +58 -4
  4. package/.idea/workspace.xml +451 -758
  5. package/.jscsrc +38 -0
  6. package/.jshintrc +0 -2
  7. package/.travis.yml +0 -1
  8. package/CHANGELOG.md +52 -0
  9. package/Gruntfile.js +37 -3
  10. package/bin/lessc +380 -316
  11. package/bower.json +1 -1
  12. package/dist/less.js +790 -479
  13. package/dist/less.min.js +7 -7
  14. package/lib/less/contexts.js +1 -1
  15. package/lib/less/data/unit-conversions.js +3 -3
  16. package/lib/less/environment/abstract-file-manager.js +4 -4
  17. package/lib/less/environment/environment.js +9 -0
  18. package/lib/less/functions/color-blending.js +3 -3
  19. package/lib/less/functions/color.js +8 -8
  20. package/lib/less/functions/data-uri.js +39 -31
  21. package/lib/less/functions/string.js +3 -1
  22. package/lib/less/functions/svg.js +12 -15
  23. package/lib/less/functions/types.js +15 -2
  24. package/lib/less/import-manager.js +10 -5
  25. package/lib/less/index.js +2 -1
  26. package/lib/less/parse-tree.js +8 -2
  27. package/lib/less/parse.js +65 -0
  28. package/lib/less/parser/parser-input.js +3 -2
  29. package/lib/less/parser/parser.js +24 -11
  30. package/lib/less/render.js +7 -36
  31. package/lib/less/source-map-output.js +3 -3
  32. package/lib/less/transform-tree.js +1 -1
  33. package/lib/less/tree/assignment.js +0 -1
  34. package/lib/less/tree/color.js +4 -4
  35. package/lib/less/tree/condition.js +1 -1
  36. package/lib/less/tree/debug-info.js +6 -2
  37. package/lib/less/tree/dimension.js +1 -1
  38. package/lib/less/tree/directive.js +25 -6
  39. package/lib/less/tree/expression.js +1 -1
  40. package/lib/less/tree/import.js +2 -2
  41. package/lib/less/tree/index.js +1 -0
  42. package/lib/less/tree/media.js +3 -2
  43. package/lib/less/tree/mixin-call.js +3 -4
  44. package/lib/less/tree/mixin-definition.js +4 -3
  45. package/lib/less/tree/quoted.js +1 -1
  46. package/lib/less/tree/rule.js +2 -3
  47. package/lib/less/tree/ruleset.js +263 -157
  48. package/lib/less/tree/selector.js +2 -1
  49. package/lib/less/tree/url.js +5 -2
  50. package/lib/less/tree/value.js +1 -1
  51. package/lib/less/tree/variable.js +1 -1
  52. package/lib/less/visitors/extend-visitor.js +60 -25
  53. package/lib/less/visitors/import-sequencer.js +20 -14
  54. package/lib/less/visitors/import-visitor.js +13 -10
  55. package/lib/less/visitors/to-css-visitor.js +37 -5
  56. package/lib/less-browser/add-default-options.js +5 -1
  57. package/lib/less-browser/bootstrap.js +10 -8
  58. package/lib/less-browser/cache.js +1 -1
  59. package/lib/less-browser/index.js +13 -12
  60. package/lib/less-browser/utils.js +9 -6
  61. package/lib/less-node/file-manager.js +51 -28
  62. package/lib/less-node/image-size.js +34 -0
  63. package/lib/less-node/index.js +3 -0
  64. package/lib/less-node/lessc-helper.js +3 -2
  65. package/lib/less-node/url-file-manager.js +2 -2
  66. package/lib/less-rhino/index.js +2 -4
  67. package/package.json +10 -7
  68. package/test/browser/common.js +13 -11
  69. package/test/browser/css/urls.css +6 -3
  70. package/test/browser/jasmine-jsreporter.js +2 -3
  71. package/test/browser/less/nested-gradient-with-svg-gradient/mixin-consumer.less +5 -0
  72. package/test/browser/less/nested-gradient-with-svg-gradient/svg-gradient-mixin.less +15 -0
  73. package/test/browser/less/urls.less +1 -0
  74. package/test/browser/less.js +15 -9424
  75. package/test/browser/runner-errors-options.js +0 -1
  76. package/test/browser/runner-errors-spec.js +0 -1
  77. package/test/browser/runner-legacy-options.js +0 -1
  78. package/test/browser/runner-no-js-errors-spec.js +0 -1
  79. package/test/browser/runner-production-options.js +0 -1
  80. package/test/browser/runner-relative-urls-options.js +0 -1
  81. package/test/browser/runner-rootpath-options.js +0 -1
  82. package/test/browser/runner-rootpath-relative-options.js +0 -1
  83. package/test/browser/runner-strict-units-options.js +0 -1
  84. package/test/copy-bom.js +72 -0
  85. package/test/css/comments.css +1 -0
  86. package/test/css/css-3.css +2 -0
  87. package/test/css/functions.css +2 -0
  88. package/test/css/import-interpolation.css +6 -0
  89. package/test/css/import-reference.css +25 -0
  90. package/test/css/include-path/include-path.css +6 -0
  91. package/test/css/mixins-important.css +6 -0
  92. package/test/css/selectors.css +10 -1
  93. package/test/css/url-args/urls.css +3 -3
  94. package/test/css/urls.css +12 -4
  95. package/test/css/variables.css +7 -1
  96. package/test/data/image.svg +3 -0
  97. package/test/index.js +14 -10
  98. package/test/less/comments.less +1 -0
  99. package/test/less/css-3.less +3 -0
  100. package/test/less/css-guards.less +2 -1
  101. package/test/less/errors/detached-ruleset-2.txt +1 -1
  102. package/test/less/errors/import-missing.txt +1 -1
  103. package/test/less/errors/parens-error-1.txt +1 -1
  104. package/test/less/errors/parens-error-2.txt +1 -1
  105. package/test/less/errors/parens-error-3.txt +1 -1
  106. package/test/less/errors/single-character.less +1 -0
  107. package/test/less/errors/single-character.txt +2 -0
  108. package/test/less/functions.less +5 -0
  109. package/test/less/import/import-interpolation.less +1 -0
  110. package/test/less/import/import-reference.less +38 -0
  111. package/test/less/import-reference.less +3 -1
  112. package/test/less/import.less +2 -0
  113. package/test/less/include-path/include-path.less +6 -0
  114. package/test/less/mixins-important.less +12 -0
  115. package/test/less/nested-gradient-with-svg-gradient/mixin-consumer.less +5 -0
  116. package/test/less/nested-gradient-with-svg-gradient/svg-gradient-mixin.less +15 -0
  117. package/test/less/selectors.less +19 -4
  118. package/test/less/urls.less +10 -1
  119. package/test/less/variables.less +17 -3
  120. package/test/less-bom/charsets.less +3 -0
  121. package/test/less-bom/colors.less +98 -0
  122. package/test/less-bom/comments.less +102 -0
  123. package/test/less-bom/comments2.less +20 -0
  124. package/test/less-bom/compression/compression.less +36 -0
  125. package/test/less-bom/css-3.less +154 -0
  126. package/test/less-bom/css-escapes.less +33 -0
  127. package/test/less-bom/css-guards.less +103 -0
  128. package/test/less-bom/css.less +108 -0
  129. package/test/less-bom/debug/import/test.less +25 -0
  130. package/test/less-bom/debug/linenumbers.less +33 -0
  131. package/test/less-bom/detached-rulesets.less +103 -0
  132. package/test/less-bom/empty.less +1 -0
  133. package/test/less-bom/errors/add-mixed-units.less +3 -0
  134. package/test/less-bom/errors/add-mixed-units.txt +4 -0
  135. package/test/less-bom/errors/add-mixed-units2.less +3 -0
  136. package/test/less-bom/errors/add-mixed-units2.txt +4 -0
  137. package/test/less-bom/errors/at-rules-undefined-var.less +4 -0
  138. package/test/less-bom/errors/at-rules-undefined-var.txt +4 -0
  139. package/test/less-bom/errors/bad-variable-declaration1.less +1 -0
  140. package/test/less-bom/errors/bad-variable-declaration1.txt +2 -0
  141. package/test/less-bom/errors/color-func-invalid-color.less +3 -0
  142. package/test/less-bom/errors/color-func-invalid-color.txt +4 -0
  143. package/test/less-bom/errors/color-invalid-hex-code.less +3 -0
  144. package/test/less-bom/errors/color-invalid-hex-code.txt +4 -0
  145. package/test/less-bom/errors/color-invalid-hex-code2.less +3 -0
  146. package/test/less-bom/errors/color-invalid-hex-code2.txt +4 -0
  147. package/test/less-bom/errors/css-guard-default-func.less +4 -0
  148. package/test/less-bom/errors/css-guard-default-func.txt +4 -0
  149. package/test/less-bom/errors/detached-ruleset-1.less +6 -0
  150. package/test/less-bom/errors/detached-ruleset-1.txt +4 -0
  151. package/test/less-bom/errors/detached-ruleset-2.less +6 -0
  152. package/test/less-bom/errors/detached-ruleset-2.txt +4 -0
  153. package/test/less-bom/errors/detached-ruleset-3.less +4 -0
  154. package/test/less-bom/errors/detached-ruleset-3.txt +4 -0
  155. package/test/less-bom/errors/detached-ruleset-4.less +5 -0
  156. package/test/less-bom/errors/detached-ruleset-4.txt +4 -0
  157. package/test/less-bom/errors/detached-ruleset-5.less +4 -0
  158. package/test/less-bom/errors/detached-ruleset-5.txt +3 -0
  159. package/test/less-bom/errors/detached-ruleset-6.less +5 -0
  160. package/test/less-bom/errors/detached-ruleset-6.txt +4 -0
  161. package/test/less-bom/errors/divide-mixed-units.less +3 -0
  162. package/test/less-bom/errors/divide-mixed-units.txt +4 -0
  163. package/test/less-bom/errors/extend-no-selector.less +3 -0
  164. package/test/less-bom/errors/extend-no-selector.txt +3 -0
  165. package/test/less-bom/errors/extend-not-at-end.less +3 -0
  166. package/test/less-bom/errors/extend-not-at-end.txt +3 -0
  167. package/test/less-bom/errors/import-malformed.less +1 -0
  168. package/test/less-bom/errors/import-malformed.txt +3 -0
  169. package/test/less-bom/errors/import-missing.less +6 -0
  170. package/test/less-bom/errors/import-missing.txt +3 -0
  171. package/test/less-bom/errors/import-no-semi.less +1 -0
  172. package/test/less-bom/errors/import-no-semi.txt +2 -0
  173. package/test/less-bom/errors/import-subfolder1.less +1 -0
  174. package/test/less-bom/errors/import-subfolder1.txt +3 -0
  175. package/test/less-bom/errors/import-subfolder2.less +1 -0
  176. package/test/less-bom/errors/import-subfolder2.txt +4 -0
  177. package/test/less-bom/errors/imports/import-subfolder1.less +1 -0
  178. package/test/less-bom/errors/imports/import-subfolder2.less +1 -0
  179. package/test/less-bom/errors/imports/import-test.less +4 -0
  180. package/test/less-bom/errors/imports/subfolder/mixin-not-defined.less +1 -0
  181. package/test/less-bom/errors/imports/subfolder/parse-error-curly-bracket.less +1 -0
  182. package/test/less-bom/errors/javascript-error.less +3 -0
  183. package/test/less-bom/errors/javascript-error.txt +4 -0
  184. package/test/less-bom/errors/javascript-undefined-var.less +3 -0
  185. package/test/less-bom/errors/javascript-undefined-var.txt +4 -0
  186. package/test/less-bom/errors/mixed-mixin-definition-args-1.less +6 -0
  187. package/test/less-bom/errors/mixed-mixin-definition-args-1.txt +4 -0
  188. package/test/less-bom/errors/mixed-mixin-definition-args-2.less +6 -0
  189. package/test/less-bom/errors/mixed-mixin-definition-args-2.txt +4 -0
  190. package/test/less-bom/errors/mixin-not-defined.less +11 -0
  191. package/test/less-bom/errors/mixin-not-defined.txt +3 -0
  192. package/test/less-bom/errors/mixin-not-matched.less +6 -0
  193. package/test/less-bom/errors/mixin-not-matched.txt +3 -0
  194. package/test/less-bom/errors/mixin-not-matched2.less +6 -0
  195. package/test/less-bom/errors/mixin-not-matched2.txt +3 -0
  196. package/test/less-bom/errors/mixin-not-visible-in-scope-1.less +9 -0
  197. package/test/less-bom/errors/mixin-not-visible-in-scope-1.txt +4 -0
  198. package/test/less-bom/errors/mixins-guards-default-func-1.less +9 -0
  199. package/test/less-bom/errors/mixins-guards-default-func-1.txt +4 -0
  200. package/test/less-bom/errors/mixins-guards-default-func-2.less +9 -0
  201. package/test/less-bom/errors/mixins-guards-default-func-2.txt +4 -0
  202. package/test/less-bom/errors/mixins-guards-default-func-3.less +9 -0
  203. package/test/less-bom/errors/mixins-guards-default-func-3.txt +4 -0
  204. package/test/less-bom/errors/multiple-guards-on-css-selectors.less +4 -0
  205. package/test/less-bom/errors/multiple-guards-on-css-selectors.txt +4 -0
  206. package/test/less-bom/errors/multiple-guards-on-css-selectors2.less +4 -0
  207. package/test/less-bom/errors/multiple-guards-on-css-selectors2.txt +4 -0
  208. package/test/less-bom/errors/multiply-mixed-units.less +7 -0
  209. package/test/less-bom/errors/multiply-mixed-units.txt +4 -0
  210. package/test/less-bom/errors/parens-error-1.less +3 -0
  211. package/test/less-bom/errors/parens-error-1.txt +4 -0
  212. package/test/less-bom/errors/parens-error-2.less +3 -0
  213. package/test/less-bom/errors/parens-error-2.txt +4 -0
  214. package/test/less-bom/errors/parens-error-3.less +3 -0
  215. package/test/less-bom/errors/parens-error-3.txt +4 -0
  216. package/test/less-bom/errors/parse-error-curly-bracket.less +4 -0
  217. package/test/less-bom/errors/parse-error-curly-bracket.txt +4 -0
  218. package/test/less-bom/errors/parse-error-extra-parens.less +5 -0
  219. package/test/less-bom/errors/parse-error-extra-parens.txt +3 -0
  220. package/test/less-bom/errors/parse-error-missing-bracket.less +2 -0
  221. package/test/less-bom/errors/parse-error-missing-bracket.txt +3 -0
  222. package/test/less-bom/errors/parse-error-missing-parens.less +5 -0
  223. package/test/less-bom/errors/parse-error-missing-parens.txt +3 -0
  224. package/test/less-bom/errors/parse-error-with-import.less +13 -0
  225. package/test/less-bom/errors/parse-error-with-import.txt +4 -0
  226. package/test/less-bom/errors/percentage-missing-space.less +3 -0
  227. package/test/less-bom/errors/percentage-missing-space.txt +4 -0
  228. package/test/less-bom/errors/property-asterisk-only-name.less +3 -0
  229. package/test/less-bom/errors/property-asterisk-only-name.txt +4 -0
  230. package/test/less-bom/errors/property-ie5-hack.less +3 -0
  231. package/test/less-bom/errors/property-ie5-hack.txt +3 -0
  232. package/test/less-bom/errors/property-in-root.less +4 -0
  233. package/test/less-bom/errors/property-in-root.txt +4 -0
  234. package/test/less-bom/errors/property-in-root2.less +1 -0
  235. package/test/less-bom/errors/property-in-root2.txt +4 -0
  236. package/test/less-bom/errors/property-in-root3.less +4 -0
  237. package/test/less-bom/errors/property-in-root3.txt +3 -0
  238. package/test/less-bom/errors/property-interp-not-defined.less +1 -0
  239. package/test/less-bom/errors/property-interp-not-defined.txt +2 -0
  240. package/test/less-bom/errors/recursive-variable.less +1 -0
  241. package/test/less-bom/errors/recursive-variable.txt +2 -0
  242. package/test/less-bom/errors/single-character.less +1 -0
  243. package/test/less-bom/errors/single-character.txt +2 -0
  244. package/test/less-bom/errors/svg-gradient1.less +3 -0
  245. package/test/less-bom/errors/svg-gradient1.txt +4 -0
  246. package/test/less-bom/errors/svg-gradient2.less +3 -0
  247. package/test/less-bom/errors/svg-gradient2.txt +4 -0
  248. package/test/less-bom/errors/svg-gradient3.less +3 -0
  249. package/test/less-bom/errors/svg-gradient3.txt +4 -0
  250. package/test/less-bom/errors/unit-function.less +3 -0
  251. package/test/less-bom/errors/unit-function.txt +4 -0
  252. package/test/less-bom/extend-chaining.less +91 -0
  253. package/test/less-bom/extend-clearfix.less +19 -0
  254. package/test/less-bom/extend-exact.less +46 -0
  255. package/test/less-bom/extend-media.less +24 -0
  256. package/test/less-bom/extend-nest.less +65 -0
  257. package/test/less-bom/extend-selector.less +99 -0
  258. package/test/less-bom/extend.less +81 -0
  259. package/test/less-bom/extract-and-length.less +133 -0
  260. package/test/less-bom/functions.less +201 -0
  261. package/test/less-bom/globalVars/extended.json +5 -0
  262. package/test/less-bom/globalVars/extended.less +10 -0
  263. package/test/less-bom/globalVars/simple.json +3 -0
  264. package/test/less-bom/globalVars/simple.less +3 -0
  265. package/test/less-bom/ie-filters.less +15 -0
  266. package/test/less-bom/import/deeper/deeper-2/url-import-2.less +3 -0
  267. package/test/less-bom/import/deeper/deeper-2/url-import.less +1 -0
  268. package/test/less-bom/import/deeper/import-once-test-a.less +1 -0
  269. package/test/less-bom/import/deeper/url-import.less +1 -0
  270. package/test/less-bom/import/import-and-relative-paths-test.less +17 -0
  271. package/test/less-bom/import/import-charset-test.less +1 -0
  272. package/test/less-bom/import/import-interpolation.less +2 -0
  273. package/test/less-bom/import/import-interpolation2.less +5 -0
  274. package/test/less-bom/import/import-once-test-c.less +6 -0
  275. package/test/less-bom/import/import-reference.less +89 -0
  276. package/test/less-bom/import/import-test-a.less +4 -0
  277. package/test/less-bom/import/import-test-b.less +8 -0
  278. package/test/less-bom/import/import-test-c.less +6 -0
  279. package/test/less-bom/import/import-test-d.css +1 -0
  280. package/test/less-bom/import/import-test-e.less +2 -0
  281. package/test/less-bom/import/import-test-f.less +5 -0
  282. package/test/less-bom/import/imports/font.less +8 -0
  283. package/test/less-bom/import/imports/logo.less +5 -0
  284. package/test/less-bom/import/interpolation-vars.less +6 -0
  285. package/test/less-bom/import/invalid-css.less +1 -0
  286. package/test/less-bom/import/urls.less +1 -0
  287. package/test/less-bom/import-inline.less +3 -0
  288. package/test/less-bom/import-interpolation.less +8 -0
  289. package/test/less-bom/import-once.less +6 -0
  290. package/test/less-bom/import-reference.less +23 -0
  291. package/test/less-bom/import.less +30 -0
  292. package/test/less-bom/include-path/include-path.less +6 -0
  293. package/test/less-bom/javascript.less +38 -0
  294. package/test/less-bom/lazy-eval.less +6 -0
  295. package/test/less-bom/legacy/legacy.less +7 -0
  296. package/test/less-bom/media.less +234 -0
  297. package/test/less-bom/merge.less +78 -0
  298. package/test/less-bom/mixins-args.less +215 -0
  299. package/test/less-bom/mixins-closure.less +26 -0
  300. package/test/less-bom/mixins-guards-default-func.less +195 -0
  301. package/test/less-bom/mixins-guards.less +271 -0
  302. package/test/less-bom/mixins-important.less +37 -0
  303. package/test/less-bom/mixins-interpolated.less +75 -0
  304. package/test/less-bom/mixins-named-args.less +36 -0
  305. package/test/less-bom/mixins-nested.less +22 -0
  306. package/test/less-bom/mixins-pattern.less +102 -0
  307. package/test/less-bom/mixins.less +145 -0
  308. package/test/less-bom/modifyVars/extended.json +5 -0
  309. package/test/less-bom/modifyVars/extended.less +11 -0
  310. package/test/less-bom/nested-gradient-with-svg-gradient/mixin-consumer.less +5 -0
  311. package/test/less-bom/nested-gradient-with-svg-gradient/svg-gradient-mixin.less +15 -0
  312. package/test/less-bom/no-js-errors/no-js-errors.less +3 -0
  313. package/test/less-bom/no-js-errors/no-js-errors.txt +4 -0
  314. package/test/less-bom/no-output.less +2 -0
  315. package/test/less-bom/operations.less +62 -0
  316. package/test/less-bom/parens.less +45 -0
  317. package/test/less-bom/property-name-interp.less +56 -0
  318. package/test/less-bom/rulesets.less +30 -0
  319. package/test/less-bom/scope.less +104 -0
  320. package/test/less-bom/selectors.less +174 -0
  321. package/test/less-bom/sourcemaps/basic.json +3 -0
  322. package/test/less-bom/sourcemaps/basic.less +27 -0
  323. package/test/less-bom/sourcemaps/imported.css +7 -0
  324. package/test/less-bom/static-urls/urls.less +33 -0
  325. package/test/less-bom/strict-units/strict-units.less +4 -0
  326. package/test/less-bom/strings.less +73 -0
  327. package/test/less-bom/url-args/urls.less +63 -0
  328. package/test/less-bom/urls.less +94 -0
  329. package/test/less-bom/variables-in-at-rules.less +20 -0
  330. package/test/less-bom/variables.less +119 -0
  331. package/test/less-bom/whitespace.less +44 -0
  332. package/test/less-test.js +127 -28
  333. package/test/modify-vars.js +6 -4
package/bin/lessc CHANGED
@@ -3,8 +3,15 @@
3
3
  var path = require('path'),
4
4
  fs = require('../lib/less-node/fs'),
5
5
  os = require('os'),
6
+ errno,
6
7
  mkdirp;
7
8
 
9
+ try {
10
+ errno = require('errno');
11
+ } catch (err) {
12
+ errno = null;
13
+ }
14
+
8
15
  var less = require('../lib/less-node'),
9
16
  pluginLoader = new less.PluginLoader(less),
10
17
  plugin,
@@ -27,8 +34,8 @@ var silent = false,
27
34
  ieCompat: true,
28
35
  strictMath: false,
29
36
  strictUnits: false,
30
- globalVariables: '',
31
- modifyVariables: '',
37
+ globalVars: null,
38
+ modifyVars: null,
32
39
  urlArgs: '',
33
40
  plugins: plugins
34
41
  };
@@ -52,16 +59,16 @@ var checkArgFunc = function(arg, option) {
52
59
  var checkBooleanArg = function(arg) {
53
60
  var onOff = /^((on|t|true|y|yes)|(off|f|false|n|no))$/i.exec(arg);
54
61
  if (!onOff) {
55
- console.log(" unable to parse "+arg+" as a boolean. use one of on/t/true/y/yes/off/f/false/n/no");
62
+ console.log(" unable to parse " + arg + " as a boolean. use one of on/t/true/y/yes/off/f/false/n/no");
56
63
  continueProcessing = false;
57
64
  return false;
58
65
  }
59
66
  return Boolean(onOff[2]);
60
67
  };
61
68
 
62
- var parseVariableOption = function(option) {
69
+ var parseVariableOption = function(option, variables) {
63
70
  var parts = option.split('=', 2);
64
- return '@' + parts[0] + ': ' + parts[1] + ';\n';
71
+ variables[parts[0]] = parts[1];
65
72
  };
66
73
 
67
74
  var warningMessages = "";
@@ -73,351 +80,408 @@ function printUsage() {
73
80
  continueProcessing = false;
74
81
  }
75
82
 
76
- args = args.filter(function (arg) {
77
- var match;
83
+ // self executing function so we can return
84
+ (function() {
85
+ args = args.filter(function (arg) {
86
+ var match;
78
87
 
79
- match = arg.match(/^-I(.+)$/);
80
- if (match) {
81
- options.paths.push(match[1]);
82
- return false;
83
- }
88
+ match = arg.match(/^-I(.+)$/);
89
+ if (match) {
90
+ options.paths.push(match[1]);
91
+ return false;
92
+ }
84
93
 
85
- match = arg.match(/^--?([a-z][0-9a-z-]*)(?:=(.*))?$/i);
86
- if (match) { arg = match[1]; }
87
- else { return arg; }
88
-
89
- switch (arg) {
90
- case 'v':
91
- case 'version':
92
- console.log("lessc " + less.version.join('.') + " (Less Compiler) [JavaScript]");
93
- continueProcessing = false;
94
- break;
95
- case 'verbose':
96
- verbose = true;
97
- break;
98
- case 's':
99
- case 'silent':
100
- silent = true;
101
- break;
102
- case 'l':
103
- case 'lint':
104
- options.lint = true;
105
- break;
106
- case 'strict-imports':
107
- options.strictImports = true;
108
- break;
109
- case 'h':
110
- case 'help':
111
- printUsage();
112
- break;
113
- case 'x':
114
- case 'compress':
115
- options.compress = true;
116
- break;
117
- case 'insecure':
118
- options.insecure = true;
119
- break;
120
- case 'M':
121
- case 'depends':
122
- options.depends = true;
123
- break;
124
- case 'max-line-len':
125
- if (checkArgFunc(arg, match[2])) {
126
- options.maxLineLen = parseInt(match[2], 10);
127
- if (options.maxLineLen <= 0) {
128
- options.maxLineLen = -1;
129
- }
130
- }
131
- break;
132
- case 'no-color':
133
- options.color = false;
134
- break;
135
- case 'no-ie-compat':
136
- options.ieCompat = false;
137
- break;
138
- case 'no-js':
139
- options.javascriptEnabled = false;
140
- break;
141
- case 'include-path':
142
- if (checkArgFunc(arg, match[2])) {
143
- options.paths = match[2].split(os.type().match(/Windows/) ? ';' : ':')
144
- .map(function(p) {
145
- if (p) {
146
- return path.resolve(process.cwd(), p);
147
- }
148
- });
149
- }
150
- break;
151
- case 'line-numbers':
152
- if (checkArgFunc(arg, match[2])) {
153
- options.dumpLineNumbers = match[2];
154
- }
155
- break;
156
- case 'source-map':
157
- options.sourceMap = true;
158
- if (match[2]) {
159
- sourceMapOptions.sourceMapFullFilename = match[2];
160
- }
161
- break;
162
- case 'source-map-rootpath':
163
- if (checkArgFunc(arg, match[2])) {
164
- sourceMapOptions.sourceMapRootpath = match[2];
165
- }
166
- break;
167
- case 'source-map-basepath':
168
- if (checkArgFunc(arg, match[2])) {
169
- sourceMapOptions.sourceMapBasepath = match[2];
170
- }
171
- break;
172
- case 'source-map-map-inline':
173
- sourceMapFileInline = true;
174
- options.sourceMap = true;
175
- break;
176
- case 'source-map-less-inline':
177
- sourceMapOptions.outputSourceFiles = true;
178
- break;
179
- case 'source-map-url':
180
- if (checkArgFunc(arg, match[2])) {
181
- sourceMapOptions.sourceMapURL = match[2];
182
- }
183
- break;
184
- case 'rp':
185
- case 'rootpath':
186
- if (checkArgFunc(arg, match[2])) {
187
- options.rootpath = match[2].replace(/\\/g, '/');
188
- }
189
- break;
190
- case "ru":
191
- case "relative-urls":
192
- options.relativeUrls = true;
193
- break;
194
- case "sm":
195
- case "strict-math":
196
- if (checkArgFunc(arg, match[2])) {
197
- options.strictMath = checkBooleanArg(match[2]);
198
- }
199
- break;
200
- case "su":
201
- case "strict-units":
202
- if (checkArgFunc(arg, match[2])) {
203
- options.strictUnits = checkBooleanArg(match[2]);
204
- }
205
- break;
206
- case "global-var":
207
- if (checkArgFunc(arg, match[2])) {
208
- options.globalVariables += parseVariableOption(match[2]);
209
- }
210
- break;
211
- case "modify-var":
212
- if (checkArgFunc(arg, match[2])) {
213
- options.modifyVariables += parseVariableOption(match[2]);
214
- }
215
- break;
216
- case 'url-args':
217
- if (checkArgFunc(arg, match[2])) {
218
- options.urlArgs = match[2];
219
- }
220
- break;
221
- case 'plugin':
222
- var splitupArg = match[2].match(/^([^=]+)(=(.*))?/),
223
- name = splitupArg[1],
224
- pluginOptions = splitupArg[3];
225
-
226
- plugin = pluginLoader.tryLoadPlugin(name, pluginOptions);
227
- if (plugin) {
228
- plugins.push(plugin);
229
- } else {
230
- console.log("Unable to load plugin " + name + " please make sure that it is installed under or at the same level as less");
231
- console.log();
232
- printUsage();
233
- currentErrorcode = 1;
234
- }
235
- break;
236
- default:
237
- plugin = pluginLoader.tryLoadPlugin("less-plugin-" + arg, match[2]);
238
- if (plugin) {
239
- plugins.push(plugin);
240
- } else {
241
- console.log("Unable to interpret argument " + arg + " - if it is a plugin (less-plugin-" + arg + "), make sure that it is installed under or at the same level as less");
242
- console.log();
94
+ match = arg.match(/^--?([a-z][0-9a-z-]*)(?:=(.*))?$/i);
95
+ if (match) { arg = match[1]; }
96
+ else { return arg; }
97
+
98
+ switch (arg) {
99
+ case 'v':
100
+ case 'version':
101
+ console.log("lessc " + less.version.join('.') + " (Less Compiler) [JavaScript]");
102
+ continueProcessing = false;
103
+ break;
104
+ case 'verbose':
105
+ verbose = true;
106
+ break;
107
+ case 's':
108
+ case 'silent':
109
+ silent = true;
110
+ break;
111
+ case 'l':
112
+ case 'lint':
113
+ options.lint = true;
114
+ break;
115
+ case 'strict-imports':
116
+ options.strictImports = true;
117
+ break;
118
+ case 'h':
119
+ case 'help':
243
120
  printUsage();
244
- currentErrorcode = 1;
245
- }
246
- break;
247
- }
248
- });
121
+ break;
122
+ case 'x':
123
+ case 'compress':
124
+ options.compress = true;
125
+ break;
126
+ case 'insecure':
127
+ options.insecure = true;
128
+ break;
129
+ case 'M':
130
+ case 'depends':
131
+ options.depends = true;
132
+ break;
133
+ case 'max-line-len':
134
+ if (checkArgFunc(arg, match[2])) {
135
+ options.maxLineLen = parseInt(match[2], 10);
136
+ if (options.maxLineLen <= 0) {
137
+ options.maxLineLen = -1;
138
+ }
139
+ }
140
+ break;
141
+ case 'no-color':
142
+ options.color = false;
143
+ break;
144
+ case 'no-ie-compat':
145
+ options.ieCompat = false;
146
+ break;
147
+ case 'no-js':
148
+ options.javascriptEnabled = false;
149
+ break;
150
+ case 'include-path':
151
+ if (checkArgFunc(arg, match[2])) {
152
+ options.paths = match[2].split(os.type().match(/Windows/) ? ';' : ':')
153
+ .map(function(p) {
154
+ if (p) {
155
+ return path.resolve(process.cwd(), p);
156
+ }
157
+ });
158
+ }
159
+ break;
160
+ case 'line-numbers':
161
+ if (checkArgFunc(arg, match[2])) {
162
+ options.dumpLineNumbers = match[2];
163
+ }
164
+ break;
165
+ case 'source-map':
166
+ options.sourceMap = true;
167
+ if (match[2]) {
168
+ sourceMapOptions.sourceMapFullFilename = match[2];
169
+ }
170
+ break;
171
+ case 'source-map-rootpath':
172
+ if (checkArgFunc(arg, match[2])) {
173
+ sourceMapOptions.sourceMapRootpath = match[2];
174
+ }
175
+ break;
176
+ case 'source-map-basepath':
177
+ if (checkArgFunc(arg, match[2])) {
178
+ sourceMapOptions.sourceMapBasepath = match[2];
179
+ }
180
+ break;
181
+ case 'source-map-map-inline':
182
+ sourceMapFileInline = true;
183
+ options.sourceMap = true;
184
+ break;
185
+ case 'source-map-less-inline':
186
+ sourceMapOptions.outputSourceFiles = true;
187
+ break;
188
+ case 'source-map-url':
189
+ if (checkArgFunc(arg, match[2])) {
190
+ sourceMapOptions.sourceMapURL = match[2];
191
+ }
192
+ break;
193
+ case 'rp':
194
+ case 'rootpath':
195
+ if (checkArgFunc(arg, match[2])) {
196
+ options.rootpath = match[2].replace(/\\/g, '/');
197
+ }
198
+ break;
199
+ case "ru":
200
+ case "relative-urls":
201
+ options.relativeUrls = true;
202
+ break;
203
+ case "sm":
204
+ case "strict-math":
205
+ if (checkArgFunc(arg, match[2])) {
206
+ options.strictMath = checkBooleanArg(match[2]);
207
+ }
208
+ break;
209
+ case "su":
210
+ case "strict-units":
211
+ if (checkArgFunc(arg, match[2])) {
212
+ options.strictUnits = checkBooleanArg(match[2]);
213
+ }
214
+ break;
215
+ case "global-var":
216
+ if (checkArgFunc(arg, match[2])) {
217
+ if (!options.globalVars) {
218
+ options.globalVars = {};
219
+ }
220
+ parseVariableOption(match[2], options.globalVars);
221
+ }
222
+ break;
223
+ case "modify-var":
224
+ if (checkArgFunc(arg, match[2])) {
225
+ if (!options.modifyVars) {
226
+ options.modifyVars = {};
227
+ }
249
228
 
250
- if (!continueProcessing) {
251
- return;
252
- }
229
+ parseVariableOption(match[2], options.modifyVars);
230
+ }
231
+ break;
232
+ case 'url-args':
233
+ if (checkArgFunc(arg, match[2])) {
234
+ options.urlArgs = match[2];
235
+ }
236
+ break;
237
+ case 'plugin':
238
+ var splitupArg = match[2].match(/^([^=]+)(=(.*))?/),
239
+ name = splitupArg[1],
240
+ pluginOptions = splitupArg[3];
241
+
242
+ plugin = pluginLoader.tryLoadPlugin(name, pluginOptions);
243
+ if (plugin) {
244
+ plugins.push(plugin);
245
+ } else {
246
+ console.log("Unable to load plugin " + name +
247
+ " please make sure that it is installed under or at the same level as less");
248
+ console.log();
249
+ printUsage();
250
+ currentErrorcode = 1;
251
+ }
252
+ break;
253
+ default:
254
+ plugin = pluginLoader.tryLoadPlugin("less-plugin-" + arg, match[2]);
255
+ if (plugin) {
256
+ plugins.push(plugin);
257
+ } else {
258
+ console.log("Unable to interpret argument " + arg +
259
+ " - if it is a plugin (less-plugin-" + arg + "), make sure that it is installed under or at" +
260
+ " the same level as less");
261
+ console.log();
262
+ printUsage();
263
+ currentErrorcode = 1;
264
+ }
265
+ break;
266
+ }
267
+ });
253
268
 
254
- var input = args[1];
255
- if (input && input != '-') {
256
- input = path.resolve(process.cwd(), input);
257
- }
258
- var output = args[2];
259
- var outputbase = args[2];
260
- if (output) {
261
- output = path.resolve(process.cwd(), output);
262
- if (warningMessages) {
263
- console.log(warningMessages);
269
+ if (!continueProcessing) {
270
+ return;
264
271
  }
265
- }
266
-
267
- if (options.sourceMap) {
268
272
 
269
- sourceMapOptions.sourceMapInputFilename = input;
270
- if (!sourceMapOptions.sourceMapFullFilename) {
271
- if (!output && !sourceMapFileInline) {
272
- console.log("the sourcemap option only has an optional filename if the css filename is given");
273
- console.log("consider adding --source-map-map-inline which embeds the sourcemap into the css");
274
- return;
273
+ var input = args[1];
274
+ if (input && input != '-') {
275
+ input = path.resolve(process.cwd(), input);
276
+ }
277
+ var output = args[2];
278
+ var outputbase = args[2];
279
+ if (output) {
280
+ output = path.resolve(process.cwd(), output);
281
+ if (warningMessages) {
282
+ console.log(warningMessages);
275
283
  }
276
- // its in the same directory, so always just the basename
277
- sourceMapOptions.sourceMapOutputFilename = path.basename(output);
278
- sourceMapOptions.sourceMapFullFilename = output + ".map";
279
- // its in the same directory, so always just the basename
280
- sourceMapOptions.sourceMapFilename = path.basename(sourceMapOptions.sourceMapFullFilename);
281
- } else if (options.sourceMap && !sourceMapFileInline) {
282
- var mapFilename = path.resolve(process.cwd(), sourceMapOptions.sourceMapFullFilename),
283
- mapDir = path.dirname(mapFilename),
284
- outputDir = path.dirname(output);
285
- // find the path from the map to the output file
286
- sourceMapOptions.sourceMapOutputFilename = path.join(
287
- path.relative(mapDir, outputDir), path.basename(output));
288
-
289
- // make the sourcemap filename point to the sourcemap relative to the css file output directory
290
- sourceMapOptions.sourceMapFilename = path.join(
291
- path.relative(outputDir, mapDir), path.basename(sourceMapOptions.sourceMapFullFilename));
292
284
  }
293
- }
294
-
295
- if (sourceMapOptions.sourceMapBasepath === undefined) {
296
- sourceMapOptions.sourceMapBasepath = input ? path.dirname(input) : process.cwd();
297
- }
298
-
299
- if (sourceMapOptions.sourceMapRootpath === undefined) {
300
- var pathToMap = path.dirname(sourceMapFileInline ? output : sourceMapOptions.sourceMapFullFilename),
301
- pathToInput = path.dirname(sourceMapOptions.sourceMapInputFilename);
302
- sourceMapOptions.sourceMapRootpath = path.relative(pathToMap, pathToInput);
303
- }
304
285
 
286
+ if (options.sourceMap) {
305
287
 
306
- if (! input) {
307
- console.log("lessc: no input files");
308
- console.log("");
309
- printUsage();
310
- currentErrorcode = 1;
311
- return;
312
- }
313
-
314
- var ensureDirectory = function (filepath) {
315
- var dir = path.dirname(filepath),
316
- cmd,
317
- existsSync = fs.existsSync || path.existsSync;
318
- if (!existsSync(dir)) {
319
- if (mkdirp === undefined) {
320
- try {mkdirp = require('mkdirp');}
321
- catch(e) { mkdirp = null; }
288
+ sourceMapOptions.sourceMapInputFilename = input;
289
+ if (!sourceMapOptions.sourceMapFullFilename) {
290
+ if (!output && !sourceMapFileInline) {
291
+ console.log("the sourcemap option only has an optional filename if the css filename is given");
292
+ console.log("consider adding --source-map-map-inline which embeds the sourcemap into the css");
293
+ return;
294
+ }
295
+ // its in the same directory, so always just the basename
296
+ sourceMapOptions.sourceMapOutputFilename = path.basename(output);
297
+ sourceMapOptions.sourceMapFullFilename = output + ".map";
298
+ // its in the same directory, so always just the basename
299
+ sourceMapOptions.sourceMapFilename = path.basename(sourceMapOptions.sourceMapFullFilename);
300
+ } else if (options.sourceMap && !sourceMapFileInline) {
301
+ var mapFilename = path.resolve(process.cwd(), sourceMapOptions.sourceMapFullFilename),
302
+ mapDir = path.dirname(mapFilename),
303
+ outputDir = path.dirname(output);
304
+ // find the path from the map to the output file
305
+ sourceMapOptions.sourceMapOutputFilename = path.join(
306
+ path.relative(mapDir, outputDir), path.basename(output));
307
+
308
+ // make the sourcemap filename point to the sourcemap relative to the css file output directory
309
+ sourceMapOptions.sourceMapFilename = path.join(
310
+ path.relative(outputDir, mapDir), path.basename(sourceMapOptions.sourceMapFullFilename));
322
311
  }
323
- cmd = mkdirp && mkdirp.sync || fs.mkdirSync;
324
- cmd(dir);
325
312
  }
326
- };
327
313
 
328
- if (options.depends) {
329
- if (!outputbase) {
330
- console.log("option --depends requires an output path to be specified");
331
- return;
314
+ if (sourceMapOptions.sourceMapBasepath === undefined) {
315
+ sourceMapOptions.sourceMapBasepath = input ? path.dirname(input) : process.cwd();
332
316
  }
333
- process.stdout.write(outputbase + ": ");
334
- }
335
317
 
336
- if (!sourceMapFileInline) {
337
- var writeSourceMap = function(output) {
338
- var filename = sourceMapOptions.sourceMapFullFilename;
339
- ensureDirectory(filename);
340
- fs.writeFileSync(filename, output, 'utf8');
341
- };
342
- }
318
+ if (sourceMapOptions.sourceMapRootpath === undefined) {
319
+ var pathToMap = path.dirname(sourceMapFileInline ? output : sourceMapOptions.sourceMapFullFilename),
320
+ pathToInput = path.dirname(sourceMapOptions.sourceMapInputFilename);
321
+ sourceMapOptions.sourceMapRootpath = path.relative(pathToMap, pathToInput);
322
+ }
343
323
 
344
- var parseLessFile = function (e, data) {
345
- if (e) {
346
- console.log("lessc: " + e.message);
324
+ if (! input) {
325
+ console.log("lessc: no input files");
326
+ console.log("");
327
+ printUsage();
347
328
  currentErrorcode = 1;
348
329
  return;
349
330
  }
350
331
 
351
- data = options.globalVariables + data + '\n' + options.modifyVariables;
352
-
353
- options.paths = [path.dirname(input)].concat(options.paths);
354
- options.filename = input;
332
+ var ensureDirectory = function (filepath) {
333
+ var dir = path.dirname(filepath),
334
+ cmd,
335
+ existsSync = fs.existsSync || path.existsSync;
336
+ if (!existsSync(dir)) {
337
+ if (mkdirp === undefined) {
338
+ try {mkdirp = require('mkdirp');}
339
+ catch(e) { mkdirp = null; }
340
+ }
341
+ cmd = mkdirp && mkdirp.sync || fs.mkdirSync;
342
+ cmd(dir);
343
+ }
344
+ };
355
345
 
356
- if (options.lint) {
357
- options.sourceMap = false;
346
+ if (options.depends) {
347
+ if (!outputbase) {
348
+ console.log("option --depends requires an output path to be specified");
349
+ return;
350
+ }
351
+ process.stdout.write(outputbase + ": ");
358
352
  }
359
- sourceMapOptions.sourceMapFileInline = sourceMapFileInline;
360
353
 
361
- if (options.sourceMap) {
362
- options.sourceMap = sourceMapOptions;
354
+ if (!sourceMapFileInline) {
355
+ var writeSourceMap = function(output, onDone) {
356
+ var filename = sourceMapOptions.sourceMapFullFilename;
357
+ ensureDirectory(filename);
358
+ fs.writeFile(filename, output, 'utf8', function (err) {
359
+ if (err) {
360
+ var description = "Error: ";
361
+ if (errno && errno.errno[err.errno]) {
362
+ description += errno.errno[err.errno].description;
363
+ } else {
364
+ description += err.code + " " + err.message;
365
+ }
366
+ less.logger.error('lessc: failed to create file ' + filename);
367
+ less.logger.error(description);
368
+ } else {
369
+ less.logger.info('lessc: wrote ' + filename);
370
+ }
371
+ onDone();
372
+ });
373
+ };
363
374
  }
364
375
 
365
- less.logger.addListener({
366
- info: function(msg) {
367
- if (verbose) {
368
- console.log(msg);
369
- }
370
- },
371
- warn: function(msg) {
372
- if (!silent) {
373
- console.warn(msg);
374
- }
375
- },
376
- error: function(msg) {
377
- console.log(msg);
376
+ var writeSourceMapIfNeeded = function(output, onDone) {
377
+ if (options.sourceMap && !sourceMapFileInline) {
378
+ writeSourceMap(output, onDone);
379
+ } else {
380
+ onDone();
378
381
  }
379
- });
382
+ };
380
383
 
381
- less.render(data, options)
382
- .then(function(result) {
383
- if(!options.lint) {
384
- if (output) {
385
- ensureDirectory(output);
386
- fs.writeFileSync(output, result.css, 'utf8');
384
+ var writeOutput = function(output, result, onSuccess) {
385
+ if (output) {
386
+ ensureDirectory(output);
387
+ fs.writeFile(output, result.css, {encoding: 'utf8'}, function (err) {
388
+ if (err) {
389
+ var description = "Error: ";
390
+ if (errno && errno.errno[err.errno]) {
391
+ description += errno.errno[err.errno].description;
392
+ } else {
393
+ description += err.code + " " + err.message;
394
+ }
395
+ less.logger.error('lessc: failed to create file ' + output);
396
+ less.logger.error(description);
397
+ } else {
387
398
  less.logger.info('lessc: wrote ' + output);
388
- } else if (!options.depends) {
389
- process.stdout.write(result.css);
399
+ onSuccess();
390
400
  }
391
- if (options.sourceMap && !sourceMapFileInline) {
392
- writeSourceMap(result.map);
401
+ });
402
+ } else if (!options.depends) {
403
+ process.stdout.write(result.css);
404
+ onSuccess();
405
+ }
406
+ };
407
+
408
+ var logDependencies = function(options, result) {
409
+ if (options.depends) {
410
+ var depends = "";
411
+ for(var i = 0; i < result.imports.length; i++) {
412
+ depends += result.imports[i] + " ";
413
+ }
414
+ console.log(depends);
415
+ }
416
+ };
417
+
418
+ var parseLessFile = function (e, data) {
419
+ if (e) {
420
+ console.log("lessc: " + e.message);
421
+ currentErrorcode = 1;
422
+ return;
423
+ }
424
+
425
+ data = data.replace(/^\uFEFF/, '');
426
+
427
+ options.paths = [path.dirname(input)].concat(options.paths);
428
+ options.filename = input;
429
+
430
+ if (options.lint) {
431
+ options.sourceMap = false;
432
+ }
433
+ sourceMapOptions.sourceMapFileInline = sourceMapFileInline;
434
+
435
+ if (options.sourceMap) {
436
+ options.sourceMap = sourceMapOptions;
437
+ }
438
+
439
+ less.logger.addListener({
440
+ info: function(msg) {
441
+ if (verbose) {
442
+ console.log(msg);
393
443
  }
394
- if (options.depends) {
395
- var depends = "";
396
- for(var i = 0; i < result.imports.length; i++) {
397
- depends += result.imports[i] + " ";
398
- }
399
- console.log(depends);
444
+ },
445
+ warn: function(msg) {
446
+ // do not show warning if outputting css to the console or the silent option is used
447
+ if (!silent && output) {
448
+ console.warn(msg);
400
449
  }
450
+ },
451
+ error: function(msg) {
452
+ console.log(msg);
401
453
  }
402
- },
403
- function(err) {
404
- less.writeError(err, options);
405
- currentErrorcode = 1;
406
454
  });
407
- };
408
455
 
409
- if (input != '-') {
410
- fs.readFile(input, 'utf8', parseLessFile);
411
- } else {
412
- process.stdin.resume();
413
- process.stdin.setEncoding('utf8');
456
+ less.render(data, options)
457
+ .then(function(result) {
458
+ if(!options.lint) {
459
+ writeOutput(output, result, function() {
460
+ writeSourceMapIfNeeded(result.map, function() {
461
+ logDependencies(options, result);
462
+ });
463
+ });
464
+ }
465
+ },
466
+ function(err) {
467
+ less.writeError(err, options);
468
+ currentErrorcode = 1;
469
+ });
470
+ };
471
+
472
+ if (input != '-') {
473
+ fs.readFile(input, 'utf8', parseLessFile);
474
+ } else {
475
+ process.stdin.resume();
476
+ process.stdin.setEncoding('utf8');
414
477
 
415
- var buffer = '';
416
- process.stdin.on('data', function(data) {
417
- buffer += data;
418
- });
478
+ var buffer = '';
479
+ process.stdin.on('data', function(data) {
480
+ buffer += data;
481
+ });
419
482
 
420
- process.stdin.on('end', function() {
421
- parseLessFile(false, buffer);
422
- });
423
- }
483
+ process.stdin.on('end', function() {
484
+ parseLessFile(false, buffer);
485
+ });
486
+ }
487
+ })();