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
@@ -2,6 +2,7 @@ var Node = require("./node"),
2
2
  Rule = require("./rule"),
3
3
  Selector = require("./selector"),
4
4
  Element = require("./element"),
5
+ Paren = require("./paren"),
5
6
  contexts = require("../contexts"),
6
7
  defaultFunc = require("../functions/default"),
7
8
  getDebugInfo = require("./debug-info");
@@ -107,7 +108,7 @@ Ruleset.prototype.eval = function (context) {
107
108
  });
108
109
  rsRules.splice.apply(rsRules, [i, 1].concat(rules));
109
110
  rsRuleCnt += rules.length - 1;
110
- i += rules.length-1;
111
+ i += rules.length - 1;
111
112
  ruleset.resetCache();
112
113
  } else if (rsRules[i].type === "RulesetCall") {
113
114
  /*jshint loopfunc:true */
@@ -120,7 +121,7 @@ Ruleset.prototype.eval = function (context) {
120
121
  });
121
122
  rsRules.splice.apply(rsRules, [i, 1].concat(rules));
122
123
  rsRuleCnt += rules.length - 1;
123
- i += rules.length-1;
124
+ i += rules.length - 1;
124
125
  ruleset.resetCache();
125
126
  }
126
127
  }
@@ -173,7 +174,7 @@ Ruleset.prototype.evalImports = function(context) {
173
174
  importRules = rules[i].eval(context);
174
175
  if (importRules && importRules.length) {
175
176
  rules.splice.apply(rules, [i, 1].concat(importRules));
176
- i+= importRules.length-1;
177
+ i+= importRules.length - 1;
177
178
  } else {
178
179
  rules.splice(i, 1, importRules);
179
180
  }
@@ -182,20 +183,20 @@ Ruleset.prototype.evalImports = function(context) {
182
183
  }
183
184
  };
184
185
  Ruleset.prototype.makeImportant = function() {
185
- return new Ruleset(this.selectors, this.rules.map(function (r) {
186
- if (r.makeImportant) {
187
- return r.makeImportant();
188
- } else {
189
- return r;
190
- }
191
- }), this.strictImports);
192
- };
193
- Ruleset.prototype.matchArgs = function (args) {
186
+ this.rules = this.rules.map(function (r) {
187
+ if (r.makeImportant) {
188
+ return r.makeImportant();
189
+ } else {
190
+ return r;
191
+ }
192
+ });
193
+ return this;
194
+ };Ruleset.prototype.matchArgs = function (args) {
194
195
  return !args || args.length === 0;
195
196
  };
196
197
  // lets you call a css selector with a guard
197
198
  Ruleset.prototype.matchCondition = function (args, context) {
198
- var lastSelector = this.selectors[this.selectors.length-1];
199
+ var lastSelector = this.selectors[this.selectors.length - 1];
199
200
  if (!lastSelector.evaldCondition) {
200
201
  return false;
201
202
  }
@@ -220,7 +221,8 @@ Ruleset.prototype.variables = function () {
220
221
  }
221
222
  // when evaluating variables in an import statement, imports have not been eval'd
222
223
  // so we need to go inside import statements.
223
- if (r.type === "Import" && r.root) {
224
+ // guard against root being a string (in the case of inlined less)
225
+ if (r.type === "Import" && r.root && r.root.variables) {
224
226
  var vars = r.root.variables();
225
227
  for(var name in vars) {
226
228
  if (vars.hasOwnProperty(name)) {
@@ -413,189 +415,293 @@ Ruleset.prototype.genCSS = function (context, output) {
413
415
  }
414
416
  };
415
417
  Ruleset.prototype.markReferenced = function () {
416
- if (!this.selectors) {
417
- return;
418
+ var s;
419
+ if (this.selectors) {
420
+ for (s = 0; s < this.selectors.length; s++) {
421
+ this.selectors[s].markReferenced();
422
+ }
418
423
  }
419
- for (var s = 0; s < this.selectors.length; s++) {
420
- this.selectors[s].markReferenced();
424
+
425
+ if (this.rules) {
426
+ for (s = 0; s < this.rules.length; s++) {
427
+ if (this.rules[s].markReferenced) {
428
+ this.rules[s].markReferenced();
429
+ }
430
+ }
421
431
  }
422
432
  };
433
+ Ruleset.prototype.getIsReferenced = function() {
434
+ var i, j, path, selector;
435
+
436
+ if (this.paths) {
437
+ for (i = 0; i < this.paths.length; i++) {
438
+ path = this.paths[i];
439
+ for (j = 0; j < path.length; j++) {
440
+ if (path[j].getIsReferenced && path[j].getIsReferenced()) {
441
+ return true;
442
+ }
443
+ }
444
+ }
445
+ }
446
+
447
+ if (this.selectors) {
448
+ for (i = 0; i < this.selectors.length; i++) {
449
+ selector = this.selectors[i];
450
+ if (selector.getIsReferenced && selector.getIsReferenced()) {
451
+ return true;
452
+ }
453
+ }
454
+ }
455
+ return false;
456
+ };
457
+
423
458
  Ruleset.prototype.joinSelectors = function (paths, context, selectors) {
424
459
  for (var s = 0; s < selectors.length; s++) {
425
460
  this.joinSelector(paths, context, selectors[s]);
426
461
  }
427
462
  };
428
- Ruleset.prototype.joinSelector = function (paths, context, selector) {
429
-
430
- var i, j, k,
431
- hasParentSelector, newSelectors, el, sel, parentSel,
432
- newSelectorPath, afterParentJoin, newJoinedSelector,
433
- newJoinedSelectorEmpty, lastSelector, currentElements,
434
- selectorsMultiplied;
435
463
 
436
- for (i = 0; i < selector.elements.length; i++) {
437
- el = selector.elements[i];
438
- if (el.value === '&') {
439
- hasParentSelector = true;
440
- }
441
- }
464
+ Ruleset.prototype.joinSelector = function (paths, context, selector) {
442
465
 
443
- if (!hasParentSelector) {
444
- if (context.length > 0) {
445
- for (i = 0; i < context.length; i++) {
446
- paths.push(context[i].concat(selector));
466
+ function createParenthesis(elementsToPak, originalElement) {
467
+ var replacementParen, j;
468
+ if (elementsToPak.length === 0) {
469
+ replacementParen = new Paren(elementsToPak[0]);
470
+ } else {
471
+ var insideParent = [];
472
+ for (j = 0; j < elementsToPak.length; j++) {
473
+ insideParent.push(new Element(null, elementsToPak[j], originalElement.index, originalElement.currentFileInfo));
447
474
  }
475
+ replacementParen = new Paren(new Selector(insideParent));
448
476
  }
449
- else {
450
- paths.push([selector]);
451
- }
452
- return;
453
- }
454
-
455
- // The paths are [[Selector]]
456
- // The first list is a list of comma separated selectors
457
- // The inner list is a list of inheritance separated selectors
458
- // e.g.
459
- // .a, .b {
460
- // .c {
461
- // }
462
- // }
463
- // == [[.a] [.c]] [[.b] [.c]]
464
- //
465
-
466
- // the elements from the current selector so far
467
- currentElements = [];
468
- // the current list of new selectors to add to the path.
469
- // We will build it up. We initiate it with one empty selector as we "multiply" the new selectors
470
- // by the parents
471
- newSelectors = [[]];
472
-
473
- for (i = 0; i < selector.elements.length; i++) {
474
- el = selector.elements[i];
475
- // non parent reference elements just get added
476
- if (el.value !== "&") {
477
- currentElements.push(el);
478
- } else {
479
- // the new list of selectors to add
480
- selectorsMultiplied = [];
477
+ return replacementParen;
478
+ }
479
+
480
+ function createSelector(containedElement, originalElement) {
481
+ var element, selector;
482
+ element = new Element(null, containedElement, originalElement.index, originalElement.currentFileInfo);
483
+ selector = new Selector([element]);
484
+ return selector;
485
+ }
486
+
487
+ // replace all parent selectors inside `inSelector` by content of `context` array
488
+ // resulting selectors are returned inside `paths` array
489
+ // returns true if `inSelector` contained at least one parent selector
490
+ function replaceParentSelector(paths, context, inSelector) {
491
+ // The paths are [[Selector]]
492
+ // The first list is a list of comma separated selectors
493
+ // The inner list is a list of inheritance separated selectors
494
+ // e.g.
495
+ // .a, .b {
496
+ // .c {
497
+ // }
498
+ // }
499
+ // == [[.a] [.c]] [[.b] [.c]]
500
+ //
501
+ var i, j, k, currentElements, newSelectors, selectorsMultiplied, sel, el, hadParentSelector = false;
502
+ function findNestedSelector(element) {
503
+ var maybeSelector;
504
+ if (element.value.type !== 'Paren') {
505
+ return null;
506
+ }
481
507
 
482
- // merge the current list of non parent selector elements
483
- // on to the current list of selectors to add
484
- if (currentElements.length > 0) {
485
- this.mergeElementsOnToSelectors(currentElements, newSelectors);
508
+ maybeSelector = element.value.value;
509
+ if (maybeSelector.type !== 'Selector') {
510
+ return null;
486
511
  }
487
512
 
488
- // loop through our current selectors
489
- for (j = 0; j < newSelectors.length; j++) {
490
- sel = newSelectors[j];
491
- // if we don't have any parent paths, the & might be in a mixin so that it can be used
492
- // whether there are parents or not
493
- if (context.length === 0) {
494
- // the combinator used on el should now be applied to the next element instead so that
495
- // it is not lost
496
- if (sel.length > 0) {
497
- sel[0].elements = sel[0].elements.slice(0);
498
- sel[0].elements.push(new Element(el.combinator, '', el.index, el.currentFileInfo));
513
+ return maybeSelector;
514
+ }
515
+
516
+ // the elements from the current selector so far
517
+ currentElements = [];
518
+ // the current list of new selectors to add to the path.
519
+ // We will build it up. We initiate it with one empty selector as we "multiply" the new selectors
520
+ // by the parents
521
+ newSelectors = [
522
+ []
523
+ ];
524
+
525
+ for (i = 0; i < inSelector.elements.length; i++) {
526
+ el = inSelector.elements[i];
527
+ // non parent reference elements just get added
528
+ if (el.value !== "&") {
529
+ var nestedSelector = findNestedSelector(el);
530
+ if (nestedSelector != null) {
531
+ // merge the current list of non parent selector elements
532
+ // on to the current list of selectors to add
533
+ mergeElementsOnToSelectors(currentElements, newSelectors);
534
+
535
+ var nestedPaths = [], replaced, replacedNewSelectors = [];
536
+ replaced = replaceParentSelector(nestedPaths, context, nestedSelector);
537
+ hadParentSelector = hadParentSelector || replaced;
538
+ //the nestedPaths array should have only one member - replaceParentSelector does not multiply selectors
539
+ for (k = 0; k < nestedPaths.length; k++) {
540
+ var replacementSelector = createSelector(createParenthesis(nestedPaths[k], el), el);
541
+ addAllReplacementsIntoPath(newSelectors, [replacementSelector], el, inSelector, replacedNewSelectors);
499
542
  }
500
- selectorsMultiplied.push(sel);
543
+ newSelectors = replacedNewSelectors;
544
+ currentElements = [];
545
+
546
+ } else {
547
+ currentElements.push(el);
501
548
  }
502
- else {
503
- // and the parent selectors
504
- for (k = 0; k < context.length; k++) {
505
- parentSel = context[k];
506
- // We need to put the current selectors
507
- // then join the last selector's elements on to the parents selectors
508
-
509
- // our new selector path
510
- newSelectorPath = [];
511
- // selectors from the parent after the join
512
- afterParentJoin = [];
513
- newJoinedSelectorEmpty = true;
514
-
515
- //construct the joined selector - if & is the first thing this will be empty,
516
- // if not newJoinedSelector will be the last set of elements in the selector
549
+
550
+ } else {
551
+ hadParentSelector = true;
552
+ // the new list of selectors to add
553
+ selectorsMultiplied = [];
554
+
555
+ // merge the current list of non parent selector elements
556
+ // on to the current list of selectors to add
557
+ mergeElementsOnToSelectors(currentElements, newSelectors);
558
+
559
+ // loop through our current selectors
560
+ for (j = 0; j < newSelectors.length; j++) {
561
+ sel = newSelectors[j];
562
+ // if we don't have any parent paths, the & might be in a mixin so that it can be used
563
+ // whether there are parents or not
564
+ if (context.length === 0) {
565
+ // the combinator used on el should now be applied to the next element instead so that
566
+ // it is not lost
517
567
  if (sel.length > 0) {
518
- newSelectorPath = sel.slice(0);
519
- lastSelector = newSelectorPath.pop();
520
- newJoinedSelector = selector.createDerived(lastSelector.elements.slice(0));
521
- newJoinedSelectorEmpty = false;
568
+ sel[0].elements.push(new Element(el.combinator, '', el.index, el.currentFileInfo));
522
569
  }
523
- else {
524
- newJoinedSelector = selector.createDerived([]);
570
+ selectorsMultiplied.push(sel);
571
+ }
572
+ else {
573
+ // and the parent selectors
574
+ for (k = 0; k < context.length; k++) {
575
+ // We need to put the current selectors
576
+ // then join the last selector's elements on to the parents selectors
577
+ var newSelectorPath = addReplacementIntoPath(sel, context[k], el, inSelector);
578
+ // add that to our new set of selectors
579
+ selectorsMultiplied.push(newSelectorPath);
525
580
  }
581
+ }
582
+ }
526
583
 
527
- //put together the parent selectors after the join
528
- if (parentSel.length > 1) {
529
- afterParentJoin = afterParentJoin.concat(parentSel.slice(1));
530
- }
584
+ // our new selectors has been multiplied, so reset the state
585
+ newSelectors = selectorsMultiplied;
586
+ currentElements = [];
587
+ }
588
+ }
531
589
 
532
- if (parentSel.length > 0) {
533
- newJoinedSelectorEmpty = false;
534
-
535
- // /deep/ is a combinator that is valid without anything in front of it
536
- // so if the & does not have a combinator that is "" or " " then
537
- // and there is a combinator on the parent, then grab that.
538
- // this also allows + a { & .b { .a & { ... though not sure why you would want to do that
539
- var combinator = el.combinator,
540
- parentEl = parentSel[0].elements[0];
541
- if (combinator.emptyOrWhitespace && !parentEl.combinator.emptyOrWhitespace) {
542
- combinator = parentEl.combinator;
543
- }
544
- // join the elements so far with the first part of the parent
545
- newJoinedSelector.elements.push(new Element(combinator, parentEl.value, el.index, el.currentFileInfo));
546
- newJoinedSelector.elements = newJoinedSelector.elements.concat(parentSel[0].elements.slice(1));
547
- }
590
+ // if we have any elements left over (e.g. .a& .b == .b)
591
+ // add them on to all the current selectors
592
+ mergeElementsOnToSelectors(currentElements, newSelectors);
548
593
 
549
- if (!newJoinedSelectorEmpty) {
550
- // now add the joined selector
551
- newSelectorPath.push(newJoinedSelector);
552
- }
594
+ for (i = 0; i < newSelectors.length; i++) {
595
+ if (newSelectors[i].length > 0) {
596
+ paths.push(newSelectors[i]);
597
+ }
598
+ }
553
599
 
554
- // and the rest of the parent
555
- newSelectorPath = newSelectorPath.concat(afterParentJoin);
600
+ return hadParentSelector;
601
+ }
556
602
 
557
- // add that to our new set of selectors
558
- selectorsMultiplied.push(newSelectorPath);
559
- }
560
- }
603
+ // joins selector path from `beginningPath` with selector path in `addPath`
604
+ // `replacedElement` contains element that is being replaced by `addPath`
605
+ // returns concatenated path
606
+ function addReplacementIntoPath(beginningPath, addPath, replacedElement, originalSelector) {
607
+ var newSelectorPath, lastSelector, newJoinedSelector;
608
+ // our new selector path
609
+ newSelectorPath = [];
610
+
611
+ //construct the joined selector - if & is the first thing this will be empty,
612
+ // if not newJoinedSelector will be the last set of elements in the selector
613
+ if (beginningPath.length > 0) {
614
+ newSelectorPath = beginningPath.slice(0);
615
+ lastSelector = newSelectorPath.pop();
616
+ newJoinedSelector = originalSelector.createDerived(lastSelector.elements.slice(0));
617
+ }
618
+ else {
619
+ newJoinedSelector = originalSelector.createDerived([]);
620
+ }
621
+
622
+ if (addPath.length > 0) {
623
+ // /deep/ is a combinator that is valid without anything in front of it
624
+ // so if the & does not have a combinator that is "" or " " then
625
+ // and there is a combinator on the parent, then grab that.
626
+ // this also allows + a { & .b { .a & { ... though not sure why you would want to do that
627
+ var combinator = replacedElement.combinator, parentEl = addPath[0].elements[0];
628
+ if (combinator.emptyOrWhitespace && !parentEl.combinator.emptyOrWhitespace) {
629
+ combinator = parentEl.combinator;
561
630
  }
631
+ // join the elements so far with the first part of the parent
632
+ newJoinedSelector.elements.push(new Element(combinator, parentEl.value, replacedElement.index, replacedElement.currentFileInfo));
633
+ newJoinedSelector.elements = newJoinedSelector.elements.concat(addPath[0].elements.slice(1));
634
+ }
562
635
 
563
- // our new selectors has been multiplied, so reset the state
564
- newSelectors = selectorsMultiplied;
565
- currentElements = [];
636
+ // now add the joined selector - but only if it is not empty
637
+ if (newJoinedSelector.elements.length !== 0) {
638
+ newSelectorPath.push(newJoinedSelector);
566
639
  }
567
- }
568
640
 
569
- // if we have any elements left over (e.g. .a& .b == .b)
570
- // add them on to all the current selectors
571
- if (currentElements.length > 0) {
572
- this.mergeElementsOnToSelectors(currentElements, newSelectors);
641
+ //put together the parent selectors after the join (e.g. the rest of the parent)
642
+ if (addPath.length > 1) {
643
+ newSelectorPath = newSelectorPath.concat(addPath.slice(1));
644
+ }
645
+ return newSelectorPath;
573
646
  }
574
647
 
575
- for (i = 0; i < newSelectors.length; i++) {
576
- if (newSelectors[i].length > 0) {
577
- paths.push(newSelectors[i]);
648
+ // joins selector path from `beginningPath` with every selector path in `addPaths` array
649
+ // `replacedElement` contains element that is being replaced by `addPath`
650
+ // returns array with all concatenated paths
651
+ function addAllReplacementsIntoPath( beginningPath, addPaths, replacedElement, originalSelector, result) {
652
+ var j;
653
+ for (j = 0; j < beginningPath.length; j++) {
654
+ var newSelectorPath = addReplacementIntoPath(beginningPath[j], addPaths, replacedElement, originalSelector);
655
+ result.push(newSelectorPath);
578
656
  }
657
+ return result;
579
658
  }
580
- };
581
- Ruleset.prototype.mergeElementsOnToSelectors = function(elements, selectors) {
582
- var i, sel;
583
659
 
584
- if (selectors.length === 0) {
585
- selectors.push([ new Selector(elements) ]);
586
- return;
660
+ function mergeElementsOnToSelectors(elements, selectors) {
661
+ var i, sel;
662
+
663
+ if (elements.length === 0) {
664
+ return ;
665
+ }
666
+ if (selectors.length === 0) {
667
+ selectors.push([ new Selector(elements) ]);
668
+ return;
669
+ }
670
+
671
+ for (i = 0; i < selectors.length; i++) {
672
+ sel = selectors[i];
673
+
674
+ // if the previous thing in sel is a parent this needs to join on to it
675
+ if (sel.length > 0) {
676
+ sel[sel.length - 1] = sel[sel.length - 1].createDerived(sel[sel.length - 1].elements.concat(elements));
677
+ }
678
+ else {
679
+ sel.push(new Selector(elements));
680
+ }
681
+ }
587
682
  }
588
683
 
589
- for (i = 0; i < selectors.length; i++) {
590
- sel = selectors[i];
684
+ // joinSelector code follows
685
+ var i, newPaths, hadParentSelector;
686
+
687
+ newPaths = [];
688
+ hadParentSelector = replaceParentSelector(newPaths, context, selector);
591
689
 
592
- // if the previous thing in sel is a parent this needs to join on to it
593
- if (sel.length > 0) {
594
- sel[sel.length - 1] = sel[sel.length - 1].createDerived(sel[sel.length - 1].elements.concat(elements));
690
+ if (!hadParentSelector) {
691
+ if (context.length > 0) {
692
+ newPaths = [];
693
+ for (i = 0; i < context.length; i++) {
694
+ newPaths.push(context[i].concat(selector));
695
+ }
595
696
  }
596
697
  else {
597
- sel.push(new Selector(elements));
698
+ newPaths = [[selector]];
598
699
  }
599
700
  }
701
+
702
+ for (i = 0; i < newPaths.length; i++) {
703
+ paths.push(newPaths[i]);
704
+ }
705
+
600
706
  };
601
707
  module.exports = Ruleset;
@@ -51,8 +51,9 @@ Selector.prototype.match = function (other) {
51
51
  return olen; // return number of matched elements
52
52
  };
53
53
  Selector.prototype.CacheElements = function() {
54
- if (this._elements)
54
+ if (this._elements) {
55
55
  return;
56
+ }
56
57
 
57
58
  var elements = this.elements.map( function(v) {
58
59
  return v.combinator.value + (v.value.value || v.value);
@@ -23,9 +23,12 @@ URL.prototype.eval = function (context) {
23
23
  if (!this.isEvald) {
24
24
  // Add the base path if the URL is relative
25
25
  rootpath = this.currentFileInfo && this.currentFileInfo.rootpath;
26
- if (rootpath && typeof val.value === "string" && context.isPathRelative(val.value)) {
26
+ if (rootpath &&
27
+ typeof val.value === "string" &&
28
+ context.isPathRelative(val.value)) {
29
+
27
30
  if (!val.quote) {
28
- rootpath = rootpath.replace(/[\(\)'"\s]/g, function(match) { return "\\"+match; });
31
+ rootpath = rootpath.replace(/[\(\)'"\s]/g, function(match) { return "\\" + match; });
29
32
  }
30
33
  val.value = rootpath + val.value;
31
34
  }
@@ -26,7 +26,7 @@ Value.prototype.genCSS = function (context, output) {
26
26
  var i;
27
27
  for(i = 0; i < this.value.length; i++) {
28
28
  this.value[i].genCSS(context, output);
29
- if (i+1 < this.value.length) {
29
+ if (i + 1 < this.value.length) {
30
30
  output.add((context && context.compress) ? ',' : ', ');
31
31
  }
32
32
  }
@@ -27,7 +27,7 @@ Variable.prototype.eval = function (context) {
27
27
  var v = frame.variable(name);
28
28
  if (v) {
29
29
  if (v.important) {
30
- var importantScope = context.importantScope[context.importantScope.length-1];
30
+ var importantScope = context.importantScope[context.importantScope.length - 1];
31
31
  importantScope.important = v.important;
32
32
  }
33
33
  return v.value.eval(context);