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/dist/less.js CHANGED
@@ -1,8 +1,8 @@
1
1
  /*!
2
- * Less - Leaner CSS v2.1.1
2
+ * Less - Leaner CSS v2.3.1
3
3
  * http://lesscss.org
4
4
  *
5
- * Copyright (c) 2009-2014, Alexis Sellier <self@cloudhead.net>
5
+ * Copyright (c) 2009-2015, Alexis Sellier <self@cloudhead.net>
6
6
  * Licensed under the Apache v2 License.
7
7
  *
8
8
  */
@@ -20,7 +20,7 @@ module.exports = function(window, options) {
20
20
  addDataAttr(options, browser.currentScript(window));
21
21
 
22
22
  if (options.isFileProtocol === undefined) {
23
- options.isFileProtocol = /^(file|chrome(-extension)?|resource|qrc|app):/.test(window.location.protocol);
23
+ options.isFileProtocol = /^(file|(chrome|safari)(-extension)?|resource|qrc|app):/.test(window.location.protocol);
24
24
  }
25
25
 
26
26
  // Load styles asynchronously (default: false)
@@ -52,6 +52,10 @@ module.exports = function(window, options) {
52
52
  options.useFileCache = true;
53
53
  }
54
54
 
55
+ if (options.onReady === undefined) {
56
+ options.onReady = true;
57
+ }
58
+
55
59
  };
56
60
 
57
61
  },{"./browser":3,"./utils":9}],2:[function(require,module,exports){
@@ -70,16 +74,17 @@ require("./add-default-options")(window, options);
70
74
 
71
75
  var less = module.exports = require("./index")(window, options);
72
76
 
73
- if (/!watch/.test(window.location.hash)) {
74
- less.watch();
75
- }
76
-
77
- less.pageLoadFinished = less.registerStylesheets().then(
78
- function () {
79
- return less.refresh(less.env === 'development');
77
+ if (options.onReady) {
78
+ if (/!watch/.test(window.location.hash)) {
79
+ less.watch();
80
80
  }
81
- );
82
81
 
82
+ less.pageLoadFinished = less.registerStylesheets().then(
83
+ function () {
84
+ return less.refresh(less.env === 'development');
85
+ }
86
+ );
87
+ }
83
88
  },{"./add-default-options":1,"./index":7,"promise/polyfill.js":undefined}],3:[function(require,module,exports){
84
89
  var utils = require("./utils");
85
90
  module.exports = {
@@ -165,7 +170,7 @@ module.exports = function(window, options, logger) {
165
170
  cache.setItem(path + ':timestamp', lastModified);
166
171
  } catch(e) {
167
172
  //TODO - could do with adding more robust error handling
168
- logger.error('failed to save');
173
+ logger.error('failed to save "' + path + '" to local storage for caching.');
169
174
  }
170
175
  }
171
176
  },
@@ -591,12 +596,13 @@ function loadStyleSheet(sheet, callback, reload, remaining, modifyVars) {
591
596
  if (webInfo) {
592
597
  webInfo.remaining = remaining;
593
598
 
594
- var css = cache.getCSS(path, webInfo);
595
- if (!reload && css) {
596
- browser.createCSS(window.document, css, sheet);
597
- webInfo.local = true;
598
- callback(null, null, data, sheet, webInfo, path);
599
- return;
599
+ if (!instanceOptions.modifyVars) {
600
+ var css = cache.getCSS(path, webInfo);
601
+ if (!reload && css) {
602
+ webInfo.local = true;
603
+ callback(null, css, data, sheet, webInfo, path);
604
+ return;
605
+ }
600
606
  }
601
607
  }
602
608
 
@@ -609,6 +615,10 @@ function loadStyleSheet(sheet, callback, reload, remaining, modifyVars) {
609
615
  e.href = path;
610
616
  callback(e);
611
617
  } else {
618
+ result.css = postProcessCSS(result.css);
619
+ if (!instanceOptions.modifyVars) {
620
+ cache.setCSS(sheet.href, webInfo.lastModified, result.css);
621
+ }
612
622
  callback(null, result.css, data, sheet, webInfo, path);
613
623
  }
614
624
  });
@@ -634,13 +644,11 @@ function initRunningMode(){
634
644
  less.watchTimer = setInterval(function () {
635
645
  if (less.watchMode) {
636
646
  fileManager.clearFileCache();
637
- loadStyleSheets(function (e, css, _, sheet, context) {
647
+ loadStyleSheets(function (e, css, _, sheet, webInfo) {
638
648
  if (e) {
639
649
  errors.add(e, e.href || sheet.href);
640
650
  } else if (css) {
641
- css = postProcessCSS(css);
642
651
  browser.createCSS(window.document, css, sheet);
643
- cache.setCSS(sheet.href, context.lastModified, css);
644
652
  }
645
653
  });
646
654
  }
@@ -707,10 +715,8 @@ less.refresh = function (reload, modifyVars, clearFileCache) {
707
715
  less.logger.info("loading " + sheet.href + " from cache.");
708
716
  } else {
709
717
  less.logger.info("rendered " + sheet.href + " successfully.");
710
- css = postProcessCSS(css);
711
- browser.createCSS(window.document, css, sheet);
712
- cache.setCSS(sheet.href, webInfo.lastModified, css);
713
718
  }
719
+ browser.createCSS(window.document, css, sheet);
714
720
  less.logger.info("css for " + sheet.href + " generated in " + (new Date() - endTime) + 'ms');
715
721
  if (webInfo.remaining === 0) {
716
722
  totalMilliseconds = new Date() - startTime;
@@ -782,11 +788,11 @@ module.exports = function(less, options) {
782
788
  module.exports = {
783
789
  extractId: function(href) {
784
790
  return href.replace(/^[a-z-]+:\/+?[^\/]+/, '' ) // Remove protocol & domain
785
- .replace(/[\?\&]livereload=\w+/,'' ) // Remove LiveReload cachebuster
786
- .replace(/^\//, '' ) // Remove root /
787
- .replace(/\.[a-zA-Z]+$/, '' ) // Remove simple extension
788
- .replace(/[^\.\w-]+/g, '-') // Replace illegal characters
789
- .replace(/\./g, ':'); // Replace dots with colons(for valid id)
791
+ .replace(/[\?\&]livereload=\w+/, '' ) // Remove LiveReload cachebuster
792
+ .replace(/^\//, '' ) // Remove root /
793
+ .replace(/\.[a-zA-Z]+$/, '' ) // Remove simple extension
794
+ .replace(/[^\.\w-]+/g, '-') // Replace illegal characters
795
+ .replace(/\./g, ':'); // Replace dots with colons(for valid id)
790
796
  },
791
797
  addDataAttr: function(options, tag) {
792
798
  for (var opt in tag.dataset) {
@@ -794,7 +800,10 @@ module.exports = {
794
800
  if (opt === "env" || opt === "dumpLineNumbers" || opt === "rootpath" || opt === "errorReporting") {
795
801
  options[opt] = tag.dataset[opt];
796
802
  } else {
797
- options[opt] = JSON.parse(tag.dataset[opt]);
803
+ try {
804
+ options[opt] = JSON.parse(tag.dataset[opt]);
805
+ }
806
+ catch(_) {}
798
807
  }
799
808
  }
800
809
  }
@@ -845,6 +854,7 @@ contexts.Parse = function(options) {
845
854
  };
846
855
 
847
856
  var evalCopyProperties = [
857
+ 'paths', // additional include paths
848
858
  'compress', // whether to compress
849
859
  'ieCompat', // whether to enforce IE compatibility (IE8 data-uri)
850
860
  'strictMath', // whether math has to be within parenthesis
@@ -912,7 +922,6 @@ contexts.Eval.prototype.normalizePath = function( path ) {
912
922
 
913
923
  //todo - do the same for the toCSS ?
914
924
 
915
-
916
925
  },{}],11:[function(require,module,exports){
917
926
  module.exports = {
918
927
  'aliceblue':'#f0f8ff',
@@ -1086,9 +1095,9 @@ module.exports = {
1086
1095
  'ms': 0.001
1087
1096
  },
1088
1097
  angle: {
1089
- 'rad': 1/(2*Math.PI),
1090
- 'deg': 1/360,
1091
- 'grad': 1/400,
1098
+ 'rad': 1 / (2 * Math.PI),
1099
+ 'deg': 1 / 360,
1100
+ 'grad': 1 / 400,
1092
1101
  'turn': 1
1093
1102
  }
1094
1103
  };
@@ -1148,10 +1157,10 @@ abstractFileManager.prototype.pathDiff = function pathDiff(url, baseUrl) {
1148
1157
  }
1149
1158
  baseUrlDirectories = baseUrlParts.directories.slice(i);
1150
1159
  urlDirectories = urlParts.directories.slice(i);
1151
- for(i = 0; i < baseUrlDirectories.length-1; i++) {
1160
+ for(i = 0; i < baseUrlDirectories.length - 1; i++) {
1152
1161
  diff += "../";
1153
1162
  }
1154
- for(i = 0; i < urlDirectories.length-1; i++) {
1163
+ for(i = 0; i < urlDirectories.length - 1; i++) {
1155
1164
  diff += urlDirectories[i] + "/";
1156
1165
  }
1157
1166
  return diff;
@@ -1176,7 +1185,7 @@ abstractFileManager.prototype.extractUrlParts = function extractUrlParts(url, ba
1176
1185
  if (baseUrl && (!urlParts[1] || urlParts[2])) {
1177
1186
  baseUrlParts = baseUrl.match(urlPartsRegex);
1178
1187
  if (!baseUrlParts) {
1179
- throw new Error("Could not parse page url - '"+baseUrl+"'");
1188
+ throw new Error("Could not parse page url - '" + baseUrl + "'");
1180
1189
  }
1181
1190
  urlParts[1] = urlParts[1] || baseUrlParts[1] || "";
1182
1191
  if (!urlParts[2]) {
@@ -1197,7 +1206,7 @@ abstractFileManager.prototype.extractUrlParts = function extractUrlParts(url, ba
1197
1206
 
1198
1207
  for(i = 0; i < directories.length; i++) {
1199
1208
  if (directories[i] === ".." && i > 0) {
1200
- directories.splice(i-1, 2);
1209
+ directories.splice(i - 1, 2);
1201
1210
  i -= 2;
1202
1211
  }
1203
1212
  }
@@ -1214,6 +1223,7 @@ abstractFileManager.prototype.extractUrlParts = function extractUrlParts(url, ba
1214
1223
  module.exports = abstractFileManager;
1215
1224
 
1216
1225
  },{}],15:[function(require,module,exports){
1226
+ var logger = require("../logger");
1217
1227
  var environment = function(externalEnvironment, fileManagers) {
1218
1228
  this.fileManagers = fileManagers || [];
1219
1229
  externalEnvironment = externalEnvironment || {};
@@ -1234,6 +1244,14 @@ var environment = function(externalEnvironment, fileManagers) {
1234
1244
  };
1235
1245
 
1236
1246
  environment.prototype.getFileManager = function (filename, currentDirectory, options, environment, isSync) {
1247
+
1248
+ if (!filename) {
1249
+ logger.warn("getFileManager called with no filename.. Please report this issue. continuing.");
1250
+ }
1251
+ if (currentDirectory == null) {
1252
+ logger.warn("getFileManager called with null directory.. Please report this issue. continuing.");
1253
+ }
1254
+
1237
1255
  var fileManagers = this.fileManagers;
1238
1256
  if (options.pluginManager) {
1239
1257
  fileManagers = [].concat(fileManagers).concat(options.pluginManager.getFileManagers());
@@ -1257,7 +1275,7 @@ environment.prototype.clearFileManagers = function () {
1257
1275
 
1258
1276
  module.exports = environment;
1259
1277
 
1260
- },{}],16:[function(require,module,exports){
1278
+ },{"../logger":31}],16:[function(require,module,exports){
1261
1279
  var Color = require("../tree/color"),
1262
1280
  functionRegistry = require("./function-registry");
1263
1281
 
@@ -1293,9 +1311,9 @@ var colorBlendModeFunctions = {
1293
1311
  },
1294
1312
  overlay: function(cb, cs) {
1295
1313
  cb *= 2;
1296
- return (cb <= 1)
1297
- ? colorBlendModeFunctions.multiply(cb, cs)
1298
- : colorBlendModeFunctions.screen(cb - 1, cs);
1314
+ return (cb <= 1) ?
1315
+ colorBlendModeFunctions.multiply(cb, cs) :
1316
+ colorBlendModeFunctions.screen(cb - 1, cs);
1299
1317
  },
1300
1318
  softlight: function(cb, cs) {
1301
1319
  var d = 1, e = cb;
@@ -1333,7 +1351,7 @@ for (var f in colorBlendModeFunctions) {
1333
1351
 
1334
1352
  functionRegistry.addMultiple(colorBlend);
1335
1353
 
1336
- },{"../tree/color":46,"./function-registry":21}],17:[function(require,module,exports){
1354
+ },{"../tree/color":47,"./function-registry":21}],17:[function(require,module,exports){
1337
1355
  var Dimension = require("../tree/dimension"),
1338
1356
  Color = require("../tree/color"),
1339
1357
  Quoted = require("../tree/quoted"),
@@ -1383,7 +1401,7 @@ colorFunctions = {
1383
1401
  h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h);
1384
1402
  if (h * 6 < 1) { return m1 + (m2 - m1) * h * 6; }
1385
1403
  else if (h * 2 < 1) { return m2; }
1386
- else if (h * 3 < 2) { return m1 + (m2 - m1) * (2/3 - h) * 6; }
1404
+ else if (h * 3 < 2) { return m1 + (m2 - m1) * (2 / 3 - h) * 6; }
1387
1405
  else { return m1; }
1388
1406
  }
1389
1407
 
@@ -1393,9 +1411,9 @@ colorFunctions = {
1393
1411
  var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s;
1394
1412
  var m1 = l * 2 - m2;
1395
1413
 
1396
- return colorFunctions.rgba(hue(h + 1/3) * 255,
1414
+ return colorFunctions.rgba(hue(h + 1 / 3) * 255,
1397
1415
  hue(h) * 255,
1398
- hue(h - 1/3) * 255,
1416
+ hue(h - 1 / 3) * 255,
1399
1417
  a);
1400
1418
  },
1401
1419
 
@@ -1463,9 +1481,9 @@ colorFunctions = {
1463
1481
  },
1464
1482
  luminance: function (color) {
1465
1483
  var luminance =
1466
- (0.2126 * color.rgb[0] / 255)
1467
- + (0.7152 * color.rgb[1] / 255)
1468
- + (0.0722 * color.rgb[2] / 255);
1484
+ (0.2126 * color.rgb[0] / 255) +
1485
+ (0.7152 * color.rgb[1] / 255) +
1486
+ (0.0722 * color.rgb[2] / 255);
1469
1487
 
1470
1488
  return new Dimension(luminance * color.alpha * 100, '%');
1471
1489
  },
@@ -1595,7 +1613,7 @@ colorFunctions = {
1595
1613
  return new Color(c.value.slice(1));
1596
1614
  }
1597
1615
  if ((c instanceof Color) || (c = Color.fromKeyword(c.value))) {
1598
- c.keyword = undefined;
1616
+ c.value = undefined;
1599
1617
  return c;
1600
1618
  }
1601
1619
  throw {
@@ -1604,7 +1622,7 @@ colorFunctions = {
1604
1622
  };
1605
1623
  },
1606
1624
  tint: function(color, amount) {
1607
- return colorFunctions.mix(colorFunctions.rgb(255,255,255), color, amount);
1625
+ return colorFunctions.mix(colorFunctions.rgb(255, 255, 255), color, amount);
1608
1626
  },
1609
1627
  shade: function(color, amount) {
1610
1628
  return colorFunctions.mix(colorFunctions.rgb(0, 0, 0), color, amount);
@@ -1612,9 +1630,9 @@ colorFunctions = {
1612
1630
  };
1613
1631
  functionRegistry.addMultiple(colorFunctions);
1614
1632
 
1615
- },{"../tree/anonymous":42,"../tree/color":46,"../tree/dimension":52,"../tree/quoted":69,"./function-registry":21}],18:[function(require,module,exports){
1633
+ },{"../tree/anonymous":43,"../tree/color":47,"../tree/dimension":53,"../tree/quoted":70,"./function-registry":21}],18:[function(require,module,exports){
1616
1634
  module.exports = function(environment) {
1617
- var Anonymous = require("../tree/anonymous"),
1635
+ var Quoted = require("../tree/quoted"),
1618
1636
  URL = require("../tree/url"),
1619
1637
  functionRegistry = require("./function-registry"),
1620
1638
  fallback = function(functionThis, node) {
@@ -1624,39 +1642,44 @@ module.exports = function(environment) {
1624
1642
 
1625
1643
  functionRegistry.add("data-uri", function(mimetypeNode, filePathNode) {
1626
1644
 
1627
- var mimetype = mimetypeNode.value;
1628
- var filePath = (filePathNode && filePathNode.value);
1629
-
1630
- var fileManager = environment.getFileManager(filePath, this.context.currentFileInfo, this.context, environment, true);
1631
-
1632
- if (!fileManager) {
1633
- return fallback(this, filePathNode || mimetypeNode);
1645
+ if (!filePathNode) {
1646
+ filePathNode = mimetypeNode;
1647
+ mimetypeNode = null;
1634
1648
  }
1635
1649
 
1636
- var useBase64 = false;
1637
-
1638
- if (arguments.length < 2) {
1639
- filePath = mimetype;
1640
- }
1650
+ var mimetype = mimetypeNode && mimetypeNode.value;
1651
+ var filePath = filePathNode.value;
1652
+ var currentFileInfo = this.currentFileInfo;
1653
+ var currentDirectory = currentFileInfo.relativeUrls ?
1654
+ currentFileInfo.currentDirectory : currentFileInfo.entryPath;
1641
1655
 
1642
1656
  var fragmentStart = filePath.indexOf('#');
1643
1657
  var fragment = '';
1644
- if (fragmentStart!==-1) {
1658
+ if (fragmentStart !== -1) {
1645
1659
  fragment = filePath.slice(fragmentStart);
1646
1660
  filePath = filePath.slice(0, fragmentStart);
1647
1661
  }
1648
1662
 
1649
- var currentDirectory = this.currentFileInfo.relativeUrls ?
1650
- this.currentFileInfo.currentDirectory : this.currentFileInfo.entryPath;
1663
+ var fileManager = environment.getFileManager(filePath, currentDirectory, this.context, environment, true);
1664
+
1665
+ if (!fileManager) {
1666
+ return fallback(this, filePathNode);
1667
+ }
1668
+
1669
+ var useBase64 = false;
1651
1670
 
1652
1671
  // detect the mimetype if not given
1653
- if (arguments.length < 2) {
1672
+ if (!mimetypeNode) {
1654
1673
 
1655
1674
  mimetype = environment.mimeLookup(filePath);
1656
1675
 
1657
- // use base 64 unless it's an ASCII or UTF-8 format
1658
- var charset = environment.charsetLookup(mimetype);
1659
- useBase64 = ['US-ASCII', 'UTF-8'].indexOf(charset) < 0;
1676
+ if (mimetype === "image/svg+xml") {
1677
+ useBase64 = false;
1678
+ } else {
1679
+ // use base 64 unless it's an ASCII or UTF-8 format
1680
+ var charset = environment.charsetLookup(mimetype);
1681
+ useBase64 = ['US-ASCII', 'UTF-8'].indexOf(charset) < 0;
1682
+ }
1660
1683
  if (useBase64) { mimetype += ';base64'; }
1661
1684
  }
1662
1685
  else {
@@ -1665,33 +1688,36 @@ module.exports = function(environment) {
1665
1688
 
1666
1689
  var fileSync = fileManager.loadFileSync(filePath, currentDirectory, this.context, environment);
1667
1690
  if (!fileSync.contents) {
1668
- logger.warn("Skipped data-uri embedding because file not found");
1691
+ logger.warn("Skipped data-uri embedding of " + filePath + " because file not found");
1669
1692
  return fallback(this, filePathNode || mimetypeNode);
1670
1693
  }
1671
1694
  var buf = fileSync.contents;
1695
+ if (useBase64 && !environment.encodeBase64) {
1696
+ return fallback(this, filePathNode);
1697
+ }
1698
+
1699
+ buf = useBase64 ? environment.encodeBase64(buf) : encodeURIComponent(buf);
1672
1700
 
1673
- // IE8 cannot handle a data-uri larger than 32KB. If this is exceeded
1701
+ var uri = "data:" + mimetype + ',' + buf + fragment;
1702
+
1703
+ // IE8 cannot handle a data-uri larger than 32,768 characters. If this is exceeded
1674
1704
  // and the --ieCompat flag is enabled, return a normal url() instead.
1675
- var DATA_URI_MAX_KB = 32,
1676
- fileSizeInKB = parseInt((buf.length / 1024), 10);
1677
- if (fileSizeInKB >= DATA_URI_MAX_KB) {
1705
+ var DATA_URI_MAX = 32768;
1706
+ if (uri.length >= DATA_URI_MAX) {
1678
1707
 
1679
1708
  if (this.context.ieCompat !== false) {
1680
- logger.warn("Skipped data-uri embedding of %s because its size (%dKB) exceeds IE8-safe %dKB!", filePath, fileSizeInKB, DATA_URI_MAX_KB);
1709
+ logger.warn("Skipped data-uri embedding of " + filePath + " because its size (" + uri.length +
1710
+ " characters) exceeds IE8-safe " + DATA_URI_MAX + " characters!");
1681
1711
 
1682
1712
  return fallback(this, filePathNode || mimetypeNode);
1683
1713
  }
1684
1714
  }
1685
1715
 
1686
- buf = useBase64 ? buf.toString('base64')
1687
- : encodeURIComponent(buf);
1688
-
1689
- var uri = "\"data:" + mimetype + ',' + buf + fragment + "\"";
1690
- return new URL(new Anonymous(uri), this.index, this.currentFileInfo);
1716
+ return new URL(new Quoted('"' + uri + '"', uri, false, this.index, this.currentFileInfo), this.index, this.currentFileInfo);
1691
1717
  });
1692
1718
  };
1693
1719
 
1694
- },{"../logger":31,"../tree/anonymous":42,"../tree/url":76,"./function-registry":21}],19:[function(require,module,exports){
1720
+ },{"../logger":31,"../tree/quoted":70,"../tree/url":77,"./function-registry":21}],19:[function(require,module,exports){
1695
1721
  var Keyword = require("../tree/keyword"),
1696
1722
  functionRegistry = require("./function-registry");
1697
1723
 
@@ -1720,7 +1746,7 @@ functionRegistry.add("default", defaultFunc.eval.bind(defaultFunc));
1720
1746
 
1721
1747
  module.exports = defaultFunc;
1722
1748
 
1723
- },{"../tree/keyword":61,"./function-registry":21}],20:[function(require,module,exports){
1749
+ },{"../tree/keyword":62,"./function-registry":21}],20:[function(require,module,exports){
1724
1750
  var functionRegistry = require("./function-registry");
1725
1751
 
1726
1752
  var functionCaller = function(name, context, index, currentFileInfo) {
@@ -1823,7 +1849,7 @@ mathFunctions.round = function (n, f) {
1823
1849
 
1824
1850
  functionRegistry.addMultiple(mathFunctions);
1825
1851
 
1826
- },{"../tree/dimension":52,"./function-registry":21}],24:[function(require,module,exports){
1852
+ },{"../tree/dimension":53,"./function-registry":21}],24:[function(require,module,exports){
1827
1853
  var Dimension = require("../tree/dimension"),
1828
1854
  Anonymous = require("../tree/anonymous"),
1829
1855
  functionRegistry = require("./function-registry");
@@ -1901,7 +1927,7 @@ functionRegistry.addMultiple({
1901
1927
  }
1902
1928
  });
1903
1929
 
1904
- },{"../tree/anonymous":42,"../tree/dimension":52,"./function-registry":21}],25:[function(require,module,exports){
1930
+ },{"../tree/anonymous":43,"../tree/dimension":53,"./function-registry":21}],25:[function(require,module,exports){
1905
1931
  var Quoted = require("../tree/quoted"),
1906
1932
  Anonymous = require("../tree/anonymous"),
1907
1933
  JavaScript = require("../tree/javascript"),
@@ -1912,7 +1938,9 @@ functionRegistry.addMultiple({
1912
1938
  return new Anonymous(str instanceof JavaScript ? str.evaluated : str.value);
1913
1939
  },
1914
1940
  escape: function (str) {
1915
- return new Anonymous(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29"));
1941
+ return new Anonymous(
1942
+ encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B")
1943
+ .replace(/\(/g, "%28").replace(/\)/g, "%29"));
1916
1944
  },
1917
1945
  replace: function (string, pattern, replacement, flags) {
1918
1946
  var result = string.value;
@@ -1936,18 +1964,21 @@ functionRegistry.addMultiple({
1936
1964
  }
1937
1965
  });
1938
1966
 
1939
- },{"../tree/anonymous":42,"../tree/javascript":59,"../tree/quoted":69,"./function-registry":21}],26:[function(require,module,exports){
1967
+ },{"../tree/anonymous":43,"../tree/javascript":60,"../tree/quoted":70,"./function-registry":21}],26:[function(require,module,exports){
1940
1968
  module.exports = function(environment) {
1941
1969
  var Dimension = require("../tree/dimension"),
1942
1970
  Color = require("../tree/color"),
1943
- Anonymous = require("../tree/anonymous"),
1971
+ Expression = require("../tree/expression"),
1972
+ Quoted = require("../tree/quoted"),
1944
1973
  URL = require("../tree/url"),
1945
1974
  functionRegistry = require("./function-registry");
1946
1975
 
1947
1976
  functionRegistry.add("svg-gradient", function(direction) {
1948
1977
 
1949
1978
  function throwArgumentDescriptor() {
1950
- throw { type: "Argument", message: "svg-gradient expects direction, start_color [start_position], [color position,]..., end_color [end_position]" };
1979
+ throw { type: "Argument",
1980
+ message: "svg-gradient expects direction, start_color [start_position], [color position,]...," +
1981
+ " end_color [end_position]" };
1951
1982
  }
1952
1983
 
1953
1984
  if (arguments.length < 3) {
@@ -1957,7 +1988,6 @@ module.exports = function(environment) {
1957
1988
  gradientDirectionSvg,
1958
1989
  gradientType = "linear",
1959
1990
  rectangleDimension = 'x="0" y="0" width="1" height="1"',
1960
- useBase64 = true,
1961
1991
  renderEnv = {compress: false},
1962
1992
  returner,
1963
1993
  directionValue = direction.toCSS(renderEnv),
@@ -1983,14 +2013,15 @@ module.exports = function(environment) {
1983
2013
  rectangleDimension = 'x="-50" y="-50" width="101" height="101"';
1984
2014
  break;
1985
2015
  default:
1986
- throw { type: "Argument", message: "svg-gradient direction must be 'to bottom', 'to right', 'to bottom right', 'to top right' or 'ellipse at center'" };
2016
+ throw { type: "Argument", message: "svg-gradient direction must be 'to bottom', 'to right'," +
2017
+ " 'to bottom right', 'to top right' or 'ellipse at center'" };
1987
2018
  }
1988
2019
  returner = '<?xml version="1.0" ?>' +
1989
2020
  '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100%" height="100%" viewBox="0 0 1 1" preserveAspectRatio="none">' +
1990
2021
  '<' + gradientType + 'Gradient id="gradient" gradientUnits="userSpaceOnUse" ' + gradientDirectionSvg + '>';
1991
2022
 
1992
2023
  for (i = 0; i < stops.length; i+= 1) {
1993
- if (stops[i].value) {
2024
+ if (stops[i] instanceof Expression) {
1994
2025
  color = stops[i].value[0];
1995
2026
  position = stops[i].value[1];
1996
2027
  } else {
@@ -1998,7 +2029,7 @@ module.exports = function(environment) {
1998
2029
  position = undefined;
1999
2030
  }
2000
2031
 
2001
- if (!(color instanceof Color) || (!((i === 0 || i+1 === stops.length) && position === undefined) && !(position instanceof Dimension))) {
2032
+ if (!(color instanceof Color) || (!((i === 0 || i + 1 === stops.length) && position === undefined) && !(position instanceof Dimension))) {
2002
2033
  throwArgumentDescriptor();
2003
2034
  }
2004
2035
  positionValue = position ? position.toCSS(renderEnv) : i === 0 ? "0%" : "100%";
@@ -2008,21 +2039,16 @@ module.exports = function(environment) {
2008
2039
  returner += '</' + gradientType + 'Gradient>' +
2009
2040
  '<rect ' + rectangleDimension + ' fill="url(#gradient)" /></svg>';
2010
2041
 
2011
- if (useBase64) {
2012
- try {
2013
- returner = environment.encodeBase64(returner);
2014
- } catch(e) {
2015
- useBase64 = false;
2016
- }
2017
- }
2042
+ returner = encodeURIComponent(returner);
2018
2043
 
2019
- returner = "'data:image/svg+xml" + (useBase64 ? ";base64" : "") + "," + returner + "'";
2020
- return new URL(new Anonymous(returner), this.index, this.currentFileInfo);
2044
+ returner = "data:image/svg+xml," + returner;
2045
+ return new URL(new Quoted("'" + returner + "'", returner, false, this.index, this.currentFileInfo), this.index, this.currentFileInfo);
2021
2046
  });
2022
2047
  };
2023
2048
 
2024
- },{"../tree/anonymous":42,"../tree/color":46,"../tree/dimension":52,"../tree/url":76,"./function-registry":21}],27:[function(require,module,exports){
2049
+ },{"../tree/color":47,"../tree/dimension":53,"../tree/expression":56,"../tree/quoted":70,"../tree/url":77,"./function-registry":21}],27:[function(require,module,exports){
2025
2050
  var Keyword = require("../tree/keyword"),
2051
+ DetachedRuleset = require("../tree/detached-ruleset"),
2026
2052
  Dimension = require("../tree/dimension"),
2027
2053
  Color = require("../tree/color"),
2028
2054
  Quoted = require("../tree/quoted"),
@@ -2035,9 +2061,19 @@ var isa = function (n, Type) {
2035
2061
  return (n instanceof Type) ? Keyword.True : Keyword.False;
2036
2062
  },
2037
2063
  isunit = function (n, unit) {
2038
- return (n instanceof Dimension) && n.unit.is(unit.value || unit) ? Keyword.True : Keyword.False;
2064
+ if (unit === undefined) {
2065
+ throw { type: "Argument", message: "missing the required second argument to isunit." };
2066
+ }
2067
+ unit = typeof unit.value === "string" ? unit.value : unit;
2068
+ if (typeof unit !== "string") {
2069
+ throw { type: "Argument", message: "Second argument to isunit should be a unit or a string." };
2070
+ }
2071
+ return (n instanceof Dimension) && n.unit.is(unit) ? Keyword.True : Keyword.False;
2039
2072
  };
2040
2073
  functionRegistry.addMultiple({
2074
+ isruleset: function (n) {
2075
+ return isa(n, DetachedRuleset);
2076
+ },
2041
2077
  iscolor: function (n) {
2042
2078
  return isa(n, Color);
2043
2079
  },
@@ -2065,7 +2101,9 @@ functionRegistry.addMultiple({
2065
2101
  isunit: isunit,
2066
2102
  unit: function (val, unit) {
2067
2103
  if(!(val instanceof Dimension)) {
2068
- throw { type: "Argument", message: "the first argument to unit must be a number" + (val instanceof Operation ? ". Have you forgotten parenthesis?" : "") };
2104
+ throw { type: "Argument",
2105
+ message: "the first argument to unit must be a number" +
2106
+ (val instanceof Operation ? ". Have you forgotten parenthesis?" : "") };
2069
2107
  }
2070
2108
  if (unit) {
2071
2109
  if (unit instanceof Keyword) {
@@ -2094,7 +2132,7 @@ functionRegistry.addMultiple({
2094
2132
  }
2095
2133
  });
2096
2134
 
2097
- },{"../tree/anonymous":42,"../tree/color":46,"../tree/dimension":52,"../tree/keyword":61,"../tree/operation":67,"../tree/quoted":69,"../tree/url":76,"./function-registry":21}],28:[function(require,module,exports){
2135
+ },{"../tree/anonymous":43,"../tree/color":47,"../tree/detached-ruleset":52,"../tree/dimension":53,"../tree/keyword":62,"../tree/operation":68,"../tree/quoted":70,"../tree/url":77,"./function-registry":21}],28:[function(require,module,exports){
2098
2136
  var contexts = require("./contexts"),
2099
2137
  Parser = require('./parser/parser');
2100
2138
 
@@ -2137,12 +2175,14 @@ module.exports = function(environment) {
2137
2175
  importManager.queue.splice(importManager.queue.indexOf(path), 1); // Remove the path from the queue
2138
2176
 
2139
2177
  var importedEqualsRoot = fullPath === importManager.rootFilename;
2140
-
2178
+ if (importOptions.optional && e) {
2179
+ callback(null, {rules:[]}, false, null);
2180
+ }
2181
+ else {
2141
2182
  importManager.files[fullPath] = root;
2142
-
2143
2183
  if (e && !importManager.error) { importManager.error = e; }
2144
-
2145
2184
  callback(e, root, importedEqualsRoot, fullPath);
2185
+ }
2146
2186
  };
2147
2187
 
2148
2188
  var newFileInfo = {
@@ -2165,7 +2205,7 @@ module.exports = function(environment) {
2165
2205
 
2166
2206
  var loadFileCallback = function(loadedFile) {
2167
2207
  var resolvedFilename = loadedFile.filename,
2168
- contents = loadedFile.contents;
2208
+ contents = loadedFile.contents.replace(/^\uFEFF/, '');
2169
2209
 
2170
2210
  // Pass on an updated rootpath if path of imported file is relative and file
2171
2211
  // is in a (sub|sup) directory
@@ -2177,7 +2217,10 @@ module.exports = function(environment) {
2177
2217
  // then rootpath should become 'less/../'
2178
2218
  newFileInfo.currentDirectory = fileManager.getPath(resolvedFilename);
2179
2219
  if(newFileInfo.relativeUrls) {
2180
- newFileInfo.rootpath = fileManager.join((importManager.context.rootpath || ""), fileManager.pathDiff(newFileInfo.currentDirectory, newFileInfo.entryPath));
2220
+ newFileInfo.rootpath = fileManager.join(
2221
+ (importManager.context.rootpath || ""),
2222
+ fileManager.pathDiff(newFileInfo.currentDirectory, newFileInfo.entryPath));
2223
+
2181
2224
  if (!fileManager.isPathAbsolute(newFileInfo.rootpath) && fileManager.alwaysMakePathsAbsolute()) {
2182
2225
  newFileInfo.rootpath = fileManager.join(newFileInfo.entryPath, newFileInfo.rootpath);
2183
2226
  }
@@ -2217,12 +2260,12 @@ module.exports = function(environment) {
2217
2260
  return ImportManager;
2218
2261
  };
2219
2262
 
2220
- },{"./contexts":10,"./parser/parser":35}],29:[function(require,module,exports){
2263
+ },{"./contexts":10,"./parser/parser":36}],29:[function(require,module,exports){
2221
2264
  module.exports = function(environment, fileManagers) {
2222
2265
  var SourceMapOutput, SourceMapBuilder, ParseTree, ImportManager, Environment;
2223
2266
 
2224
2267
  var less = {
2225
- version: [2, 1, 1],
2268
+ version: [2, 3, 1],
2226
2269
  data: require('./data'),
2227
2270
  tree: require('./tree'),
2228
2271
  Environment: (Environment = require("./environment/environment")),
@@ -2237,6 +2280,7 @@ module.exports = function(environment, fileManagers) {
2237
2280
  ParseTree: (ParseTree = require('./parse-tree')(SourceMapBuilder)),
2238
2281
  ImportManager: (ImportManager = require('./import-manager')(environment)),
2239
2282
  render: require("./render")(environment, ParseTree, ImportManager),
2283
+ parse: require("./parse")(environment, ParseTree, ImportManager),
2240
2284
  LessError: require('./less-error'),
2241
2285
  transformTree: require('./transform-tree'),
2242
2286
  utils: require('./utils'),
@@ -2247,7 +2291,7 @@ module.exports = function(environment, fileManagers) {
2247
2291
  return less;
2248
2292
  };
2249
2293
 
2250
- },{"./contexts":10,"./data":12,"./environment/abstract-file-manager":14,"./environment/environment":15,"./functions":22,"./import-manager":28,"./less-error":30,"./logger":31,"./parse-tree":32,"./parser/parser":35,"./plugin-manager":36,"./render":37,"./source-map-builder":38,"./source-map-output":39,"./transform-tree":40,"./tree":58,"./utils":79,"./visitors":83}],30:[function(require,module,exports){
2294
+ },{"./contexts":10,"./data":12,"./environment/abstract-file-manager":14,"./environment/environment":15,"./functions":22,"./import-manager":28,"./less-error":30,"./logger":31,"./parse":33,"./parse-tree":32,"./parser/parser":36,"./plugin-manager":37,"./render":38,"./source-map-builder":39,"./source-map-output":40,"./transform-tree":41,"./tree":59,"./utils":80,"./visitors":84}],30:[function(require,module,exports){
2251
2295
  var utils = require("./utils");
2252
2296
 
2253
2297
  var LessError = module.exports = function LessError(e, importManager, currentFilename) {
@@ -2291,7 +2335,7 @@ if (typeof Object.create === 'undefined') {
2291
2335
 
2292
2336
  LessError.prototype.constructor = LessError;
2293
2337
 
2294
- },{"./utils":79}],31:[function(require,module,exports){
2338
+ },{"./utils":80}],31:[function(require,module,exports){
2295
2339
  module.exports = {
2296
2340
  error: function(msg) {
2297
2341
  this._fireEvent("error", msg);
@@ -2329,7 +2373,8 @@ module.exports = {
2329
2373
 
2330
2374
  },{}],32:[function(require,module,exports){
2331
2375
  var LessError = require('./less-error'),
2332
- transformTree = require("./transform-tree");
2376
+ transformTree = require("./transform-tree"),
2377
+ logger = require("./logger");
2333
2378
 
2334
2379
  module.exports = function(SourceMapBuilder) {
2335
2380
  var ParseTree = function(root, imports) {
@@ -2346,8 +2391,13 @@ ParseTree.prototype.toCSS = function(options) {
2346
2391
  }
2347
2392
 
2348
2393
  try {
2394
+ var compress = Boolean(options.compress);
2395
+ if (compress) {
2396
+ logger.warn("The compress option has been deprecated. We recommend you use a dedicated css minifier, for instance see less-plugin-clean-css.");
2397
+ }
2398
+
2349
2399
  var toCSSOptions = {
2350
- compress: Boolean(options.compress),
2400
+ compress: compress,
2351
2401
  dumpLineNumbers: options.dumpLineNumbers,
2352
2402
  strictUnits: Boolean(options.strictUnits),
2353
2403
  numPrecision: 8};
@@ -2383,7 +2433,74 @@ ParseTree.prototype.toCSS = function(options) {
2383
2433
  return ParseTree;
2384
2434
  };
2385
2435
 
2386
- },{"./less-error":30,"./transform-tree":40}],33:[function(require,module,exports){
2436
+ },{"./less-error":30,"./logger":31,"./transform-tree":41}],33:[function(require,module,exports){
2437
+ var PromiseConstructor = typeof Promise === 'undefined' ? require('promise') : Promise,
2438
+ contexts = require("./contexts"),
2439
+ Parser = require('./parser/parser'),
2440
+ PluginManager = require('./plugin-manager');
2441
+
2442
+ module.exports = function(environment, ParseTree, ImportManager) {
2443
+ var parse = function (input, options, callback) {
2444
+ options = options || {};
2445
+
2446
+ if (typeof(options) === 'function') {
2447
+ callback = options;
2448
+ options = {};
2449
+ }
2450
+
2451
+ if (!callback) {
2452
+ var self = this;
2453
+ return new PromiseConstructor(function (resolve, reject) {
2454
+ parse.call(self, input, options, function(err, output) {
2455
+ if (err) {
2456
+ reject(err);
2457
+ } else {
2458
+ resolve(output);
2459
+ }
2460
+ });
2461
+ });
2462
+ } else {
2463
+ var context,
2464
+ rootFileInfo,
2465
+ pluginManager = new PluginManager(this);
2466
+
2467
+ pluginManager.addPlugins(options.plugins);
2468
+ options.pluginManager = pluginManager;
2469
+
2470
+ context = new contexts.Parse(options);
2471
+
2472
+ if (options.rootFileInfo) {
2473
+ rootFileInfo = options.rootFileInfo;
2474
+ } else {
2475
+ var filename = options.filename || "input";
2476
+ var entryPath = filename.replace(/[^\/\\]*$/, "");
2477
+ rootFileInfo = {
2478
+ filename: filename,
2479
+ relativeUrls: context.relativeUrls,
2480
+ rootpath: context.rootpath || "",
2481
+ currentDirectory: entryPath,
2482
+ entryPath: entryPath,
2483
+ rootFilename: filename
2484
+ };
2485
+ // add in a missing trailing slash
2486
+ if (rootFileInfo.rootpath && rootFileInfo.rootpath.slice(-1) !== "/") {
2487
+ rootFileInfo.rootpath += "/";
2488
+ }
2489
+ }
2490
+
2491
+ var imports = new ImportManager(context, rootFileInfo);
2492
+
2493
+ new Parser(context, imports, rootFileInfo)
2494
+ .parse(input, function (e, root) {
2495
+ if (e) { return callback(e); }
2496
+ callback(null, root, imports, options);
2497
+ }, options);
2498
+ }
2499
+ };
2500
+ return parse;
2501
+ };
2502
+
2503
+ },{"./contexts":10,"./parser/parser":36,"./plugin-manager":37,"promise":undefined}],34:[function(require,module,exports){
2387
2504
  // Split the input into chunks.
2388
2505
  module.exports = function (input, fail) {
2389
2506
  var len = input.length, level = 0, parenLevel = 0,
@@ -2497,7 +2614,7 @@ module.exports = function (input, fail) {
2497
2614
  return chunks;
2498
2615
  };
2499
2616
 
2500
- },{}],34:[function(require,module,exports){
2617
+ },{}],35:[function(require,module,exports){
2501
2618
  var chunker = require('./chunker');
2502
2619
 
2503
2620
  module.exports = function() {
@@ -2516,7 +2633,8 @@ module.exports = function() {
2516
2633
  saveStack.push( { current: current, i: parserInput.i, j: j });
2517
2634
  };
2518
2635
  parserInput.restore = function(possibleErrorMessage) {
2519
- if (parserInput.i > furthest) {
2636
+
2637
+ if (parserInput.i > furthest || (parserInput.i === furthest && possibleErrorMessage && !furthestPossibleErrorMessage)) {
2520
2638
  furthest = parserInput.i;
2521
2639
  furthestPossibleErrorMessage = possibleErrorMessage;
2522
2640
  }
@@ -2738,7 +2856,7 @@ module.exports = function() {
2738
2856
 
2739
2857
  parserInput.end = function() {
2740
2858
  var message,
2741
- isFinished = parserInput.i >= input.length - 1;
2859
+ isFinished = parserInput.i >= input.length;
2742
2860
 
2743
2861
  if (parserInput.i < furthest) {
2744
2862
  message = furthestPossibleErrorMessage;
@@ -2756,7 +2874,7 @@ module.exports = function() {
2756
2874
  return parserInput;
2757
2875
  };
2758
2876
 
2759
- },{"./chunker":33}],35:[function(require,module,exports){
2877
+ },{"./chunker":34}],36:[function(require,module,exports){
2760
2878
  var LessError = require('../less-error'),
2761
2879
  tree = require("../tree"),
2762
2880
  visitors = require("../visitors"),
@@ -2963,7 +3081,7 @@ var Parser = function Parser(context, imports, fileInfo) {
2963
3081
  // Ruleset (Selector '.class', [
2964
3082
  // Rule ("color", Value ([Expression [Color #fff]]))
2965
3083
  // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]]))
2966
- // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]]))
3084
+ // Rule ("width", Value ([Expression [Operation " + " [Variable "@w"][Dimension 4px]]]))
2967
3085
  // Ruleset (Selector [Element '>', '.child'], [...])
2968
3086
  // ])
2969
3087
  //
@@ -2990,13 +3108,17 @@ var Parser = function Parser(context, imports, fileInfo) {
2990
3108
  primary: function () {
2991
3109
  var mixin = this.mixin, root = [], node;
2992
3110
 
2993
- while (!parserInput.finished)
3111
+ while (true)
2994
3112
  {
2995
3113
  while(true) {
2996
3114
  node = this.comment();
2997
3115
  if (!node) { break; }
2998
3116
  root.push(node);
2999
3117
  }
3118
+ // always process comments before deciding if finished
3119
+ if (parserInput.finished) {
3120
+ break;
3121
+ }
3000
3122
  if (parserInput.peek('}')) {
3001
3123
  break;
3002
3124
  }
@@ -3209,7 +3331,9 @@ var Parser = function Parser(context, imports, fileInfo) {
3209
3331
  var rgb;
3210
3332
 
3211
3333
  if (parserInput.currentChar() === '#' && (rgb = parserInput.$re(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/))) {
3212
- var colorCandidateString = rgb.input.match(/^#([\w]+).*/); // strip colons, brackets, whitespaces and other characters that should not definitely be part of color string
3334
+ // strip colons, brackets, whitespaces and other characters that should not
3335
+ // definitely be part of color string
3336
+ var colorCandidateString = rgb.input.match(/^#([\w]+).*/);
3213
3337
  colorCandidateString = colorCandidateString[1];
3214
3338
  if (!colorCandidateString.match(/^[A-Fa-f0-9]+$/)) { // verify if candidate consists only of allowed HEX characters
3215
3339
  error("Invalid HEX color code");
@@ -3305,8 +3429,9 @@ var Parser = function Parser(context, imports, fileInfo) {
3305
3429
  }
3306
3430
 
3307
3431
  option = option && option[1];
3308
- if (!elements)
3432
+ if (!elements) {
3309
3433
  error("Missing target selector for :extend().");
3434
+ }
3310
3435
  extend = new(tree.Extend)(new(tree.Selector)(elements), option, index);
3311
3436
  if (extendList) { extendList.push(extend); } else { extendList = [ extend ]; }
3312
3437
 
@@ -3616,8 +3741,10 @@ var Parser = function Parser(context, imports, fileInfo) {
3616
3741
 
3617
3742
  c = this.combinator();
3618
3743
 
3619
- e = parserInput.$re(/^(?:\d+\.\d+|\d+)%/) || parserInput.$re(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/) ||
3620
- parserInput.$char('*') || parserInput.$char('&') || this.attribute() || parserInput.$re(/^\([^()@]+\)/) || parserInput.$re(/^[\.#](?=@)/) ||
3744
+ e = parserInput.$re(/^(?:\d+\.\d+|\d+)%/) ||
3745
+ parserInput.$re(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/) ||
3746
+ parserInput.$char('*') || parserInput.$char('&') || this.attribute() ||
3747
+ parserInput.$re(/^\([^&()@]+\)/) || parserInput.$re(/^[\.#:](?=@)/) ||
3621
3748
  this.entities.variableCurly();
3622
3749
 
3623
3750
  if (! e) {
@@ -3928,7 +4055,7 @@ var Parser = function Parser(context, imports, fileInfo) {
3928
4055
  },
3929
4056
 
3930
4057
  importOption: function() {
3931
- var opt = parserInput.$re(/^(less|css|multiple|once|inline|reference)/);
4058
+ var opt = parserInput.$re(/^(less|css|multiple|once|inline|reference|optional)/);
3932
4059
  if (opt) {
3933
4060
  return opt[1];
3934
4061
  }
@@ -4142,15 +4269,19 @@ var Parser = function Parser(context, imports, fileInfo) {
4142
4269
  sub: function () {
4143
4270
  var a, e;
4144
4271
 
4272
+ parserInput.save();
4145
4273
  if (parserInput.$char('(')) {
4146
4274
  a = this.addition();
4147
- if (a) {
4275
+ if (a && parserInput.$char(')')) {
4276
+ parserInput.forget();
4148
4277
  e = new(tree.Expression)([a]);
4149
- expectChar(')');
4150
4278
  e.parens = true;
4151
4279
  return e;
4152
4280
  }
4281
+ parserInput.restore("Expected ')'");
4282
+ return;
4153
4283
  }
4284
+ parserInput.restore();
4154
4285
  },
4155
4286
  multiplication: function () {
4156
4287
  var m, a, op, operation, isSpaced;
@@ -4357,8 +4488,8 @@ Parser.serializeVars = function(vars) {
4357
4488
  for (var name in vars) {
4358
4489
  if (Object.hasOwnProperty.call(vars, name)) {
4359
4490
  var value = vars[name];
4360
- s += ((name[0] === '@') ? '' : '@') + name +': '+ value +
4361
- ((('' + value).slice(-1) === ';') ? '' : ';');
4491
+ s += ((name[0] === '@') ? '' : '@') + name + ': ' + value +
4492
+ ((String(value).slice(-1) === ';') ? '' : ';');
4362
4493
  }
4363
4494
  }
4364
4495
 
@@ -4367,7 +4498,7 @@ Parser.serializeVars = function(vars) {
4367
4498
 
4368
4499
  module.exports = Parser;
4369
4500
 
4370
- },{"../less-error":30,"../tree":58,"../utils":79,"../visitors":83,"./parser-input":34}],36:[function(require,module,exports){
4501
+ },{"../less-error":30,"../tree":59,"../utils":80,"../visitors":84,"./parser-input":35}],37:[function(require,module,exports){
4371
4502
  /**
4372
4503
  * Plugin Manager
4373
4504
  */
@@ -4456,16 +4587,11 @@ PluginManager.prototype.getFileManagers = function() {
4456
4587
  };
4457
4588
  module.exports = PluginManager;
4458
4589
 
4459
- },{}],37:[function(require,module,exports){
4460
- var PromiseConstructor = typeof Promise === 'undefined' ? require('promise') : Promise,
4461
- contexts = require("./contexts"),
4462
- Parser = require('./parser/parser'),
4463
- PluginManager = require('./plugin-manager');
4590
+ },{}],38:[function(require,module,exports){
4591
+ var PromiseConstructor = typeof Promise === 'undefined' ? require('promise') : Promise;
4464
4592
 
4465
4593
  module.exports = function(environment, ParseTree, ImportManager) {
4466
4594
  var render = function (input, options, callback) {
4467
- options = options || {};
4468
-
4469
4595
  if (typeof(options) === 'function') {
4470
4596
  callback = options;
4471
4597
  options = {};
@@ -4483,49 +4609,25 @@ module.exports = function(environment, ParseTree, ImportManager) {
4483
4609
  });
4484
4610
  });
4485
4611
  } else {
4486
- var context,
4487
- rootFileInfo,
4488
- pluginManager = new PluginManager(this);
4489
-
4490
- pluginManager.addPlugins(options.plugins);
4491
- options.pluginManager = pluginManager;
4492
-
4493
- context = new contexts.Parse(options);
4494
-
4495
- if (options.rootFileInfo) {
4496
- rootFileInfo = options.rootFileInfo;
4497
- } else {
4498
- var filename = options.filename || "input";
4499
- var entryPath = filename.replace(/[^\/\\]*$/, "");
4500
- rootFileInfo = {
4501
- filename: filename,
4502
- relativeUrls: context.relativeUrls,
4503
- rootpath: context.rootpath || "",
4504
- currentDirectory: entryPath,
4505
- entryPath: entryPath,
4506
- rootFilename: filename
4507
- };
4508
- }
4509
-
4510
- var imports = new ImportManager(context, rootFileInfo);
4612
+ this.parse(input, options, function(err, root, imports, options) {
4613
+ if (err) { return callback(err); }
4511
4614
 
4512
- new Parser(context, imports, rootFileInfo)
4513
- .parse(input, function (e, root) {
4514
- if (e) { return callback(e); }
4515
4615
  var result;
4516
4616
  try {
4517
4617
  var parseTree = new ParseTree(root, imports);
4518
4618
  result = parseTree.toCSS(options);
4519
4619
  }
4520
- catch (err) { return callback( err); }
4620
+ catch (err) { return callback(err); }
4621
+
4521
4622
  callback(null, result);
4522
- }, options);
4623
+ });
4523
4624
  }
4524
4625
  };
4626
+
4525
4627
  return render;
4526
4628
  };
4527
4629
 
4528
- },{"./contexts":10,"./parser/parser":35,"./plugin-manager":36,"promise":undefined}],38:[function(require,module,exports){
4630
+ },{"promise":undefined}],39:[function(require,module,exports){
4529
4631
  module.exports = function (SourceMapOutput, environment) {
4530
4632
 
4531
4633
  var SourceMapBuilder = function (options) {
@@ -4592,7 +4694,7 @@ module.exports = function (SourceMapOutput, environment) {
4592
4694
  return SourceMapBuilder;
4593
4695
  };
4594
4696
 
4595
- },{}],39:[function(require,module,exports){
4697
+ },{}],40:[function(require,module,exports){
4596
4698
  module.exports = function (environment) {
4597
4699
 
4598
4700
  var SourceMapOutput = function (options) {
@@ -4610,7 +4712,7 @@ module.exports = function (environment) {
4610
4712
  }
4611
4713
  if (options.sourceMapRootpath) {
4612
4714
  this._sourceMapRootpath = options.sourceMapRootpath.replace(/\\/g, '/');
4613
- if (this._sourceMapRootpath.charAt(this._sourceMapRootpath.length-1) !== '/') {
4715
+ if (this._sourceMapRootpath.charAt(this._sourceMapRootpath.length - 1) !== '/') {
4614
4716
  this._sourceMapRootpath += '/';
4615
4717
  }
4616
4718
  } else {
@@ -4661,11 +4763,11 @@ module.exports = function (environment) {
4661
4763
  }
4662
4764
  inputSource = inputSource.substring(0, index);
4663
4765
  sourceLines = inputSource.split("\n");
4664
- sourceColumns = sourceLines[sourceLines.length-1];
4766
+ sourceColumns = sourceLines[sourceLines.length - 1];
4665
4767
  }
4666
4768
 
4667
4769
  lines = chunk.split("\n");
4668
- columns = lines[lines.length-1];
4770
+ columns = lines[lines.length - 1];
4669
4771
 
4670
4772
  if (fileInfo) {
4671
4773
  if (!mapLines) {
@@ -4733,7 +4835,7 @@ module.exports = function (environment) {
4733
4835
  return SourceMapOutput;
4734
4836
  };
4735
4837
 
4736
- },{}],40:[function(require,module,exports){
4838
+ },{}],41:[function(require,module,exports){
4737
4839
  var contexts = require("./contexts"),
4738
4840
  visitor = require("./visitors"),
4739
4841
  tree = require("./tree");
@@ -4781,7 +4883,7 @@ module.exports = function(root, options) {
4781
4883
 
4782
4884
  if (options.pluginManager) {
4783
4885
  var pluginVisitors = options.pluginManager.getVisitors();
4784
- for(i =0; i < pluginVisitors.length; i++) {
4886
+ for(i = 0; i < pluginVisitors.length; i++) {
4785
4887
  var pluginVisitor = pluginVisitors[i];
4786
4888
  if (pluginVisitor.isPreEvalVisitor) {
4787
4889
  preEvalVisitors.push(pluginVisitor);
@@ -4808,7 +4910,7 @@ module.exports = function(root, options) {
4808
4910
  return evaldRoot;
4809
4911
  };
4810
4912
 
4811
- },{"./contexts":10,"./tree":58,"./visitors":83}],41:[function(require,module,exports){
4913
+ },{"./contexts":10,"./tree":59,"./visitors":84}],42:[function(require,module,exports){
4812
4914
  var Node = require("./node");
4813
4915
 
4814
4916
  var Alpha = function (val) {
@@ -4838,7 +4940,7 @@ Alpha.prototype.genCSS = function (context, output) {
4838
4940
 
4839
4941
  module.exports = Alpha;
4840
4942
 
4841
- },{"./node":66}],42:[function(require,module,exports){
4943
+ },{"./node":67}],43:[function(require,module,exports){
4842
4944
  var Node = require("./node");
4843
4945
 
4844
4946
  var Anonymous = function (value, index, currentFileInfo, mapLines, rulesetLike) {
@@ -4864,7 +4966,7 @@ Anonymous.prototype.genCSS = function (context, output) {
4864
4966
  };
4865
4967
  module.exports = Anonymous;
4866
4968
 
4867
- },{"./node":66}],43:[function(require,module,exports){
4969
+ },{"./node":67}],44:[function(require,module,exports){
4868
4970
  var Node = require("./node");
4869
4971
 
4870
4972
  var Assignment = function (key, val) {
@@ -4893,8 +4995,7 @@ Assignment.prototype.genCSS = function (context, output) {
4893
4995
  };
4894
4996
  module.exports = Assignment;
4895
4997
 
4896
-
4897
- },{"./node":66}],44:[function(require,module,exports){
4998
+ },{"./node":67}],45:[function(require,module,exports){
4898
4999
  var Node = require("./node");
4899
5000
 
4900
5001
  var Attribute = function (key, op, value) {
@@ -4923,7 +5024,7 @@ Attribute.prototype.toCSS = function (context) {
4923
5024
  };
4924
5025
  module.exports = Attribute;
4925
5026
 
4926
- },{"./node":66}],45:[function(require,module,exports){
5027
+ },{"./node":67}],46:[function(require,module,exports){
4927
5028
  var Node = require("./node"),
4928
5029
  FunctionCaller = require("../functions/function-caller");
4929
5030
  //
@@ -4987,7 +5088,7 @@ Call.prototype.genCSS = function (context, output) {
4987
5088
  };
4988
5089
  module.exports = Call;
4989
5090
 
4990
- },{"../functions/function-caller":20,"./node":66}],46:[function(require,module,exports){
5091
+ },{"../functions/function-caller":20,"./node":67}],47:[function(require,module,exports){
4991
5092
  var Node = require("./node"),
4992
5093
  colors = require("../data/colors");
4993
5094
 
@@ -5046,11 +5147,11 @@ Color.prototype.genCSS = function (context, output) {
5046
5147
  Color.prototype.toCSS = function (context, doNotCompress) {
5047
5148
  var compress = context && context.compress && !doNotCompress, color, alpha;
5048
5149
 
5049
- // `keyword` is set if this color was originally
5150
+ // `value` is set if this color was originally
5050
5151
  // converted from a named color string so we need
5051
5152
  // to respect this and try to output named color too.
5052
- if (this.keyword) {
5053
- return this.keyword;
5153
+ if (this.value) {
5154
+ return this.value;
5054
5155
  }
5055
5156
 
5056
5157
  // If we have some transparency, the only way to represent it
@@ -5169,13 +5270,13 @@ Color.fromKeyword = function(keyword) {
5169
5270
  }
5170
5271
 
5171
5272
  if (c) {
5172
- c.keyword = keyword;
5273
+ c.value = keyword;
5173
5274
  return c;
5174
5275
  }
5175
5276
  };
5176
5277
  module.exports = Color;
5177
5278
 
5178
- },{"../data/colors":11,"./node":66}],47:[function(require,module,exports){
5279
+ },{"../data/colors":11,"./node":67}],48:[function(require,module,exports){
5179
5280
  var Node = require("./node");
5180
5281
 
5181
5282
  var Combinator = function (value) {
@@ -5200,7 +5301,7 @@ Combinator.prototype.genCSS = function (context, output) {
5200
5301
  };
5201
5302
  module.exports = Combinator;
5202
5303
 
5203
- },{"./node":66}],48:[function(require,module,exports){
5304
+ },{"./node":67}],49:[function(require,module,exports){
5204
5305
  var Node = require("./node"),
5205
5306
  getDebugInfo = require("./debug-info");
5206
5307
 
@@ -5230,7 +5331,7 @@ Comment.prototype.isRulesetLike = function(root) {
5230
5331
  };
5231
5332
  module.exports = Comment;
5232
5333
 
5233
- },{"./debug-info":50,"./node":66}],49:[function(require,module,exports){
5334
+ },{"./debug-info":51,"./node":67}],50:[function(require,module,exports){
5234
5335
  var Node = require("./node");
5235
5336
 
5236
5337
  var Condition = function (op, l, r, i, negate) {
@@ -5259,15 +5360,15 @@ Condition.prototype.eval = function (context) {
5259
5360
  default: return false;
5260
5361
  }
5261
5362
  }
5262
- }) (this.op, this.lvalue.eval(context), this.rvalue.eval(context));
5363
+ })(this.op, this.lvalue.eval(context), this.rvalue.eval(context));
5263
5364
 
5264
5365
  return this.negate ? !result : result;
5265
5366
  };
5266
5367
  module.exports = Condition;
5267
5368
 
5268
- },{"./node":66}],50:[function(require,module,exports){
5369
+ },{"./node":67}],51:[function(require,module,exports){
5269
5370
  var debugInfo = function(context, ctx, lineSeparator) {
5270
- var result="";
5371
+ var result = "";
5271
5372
  if (context.dumpLineNumbers && !context.compress) {
5272
5373
  switch(context.dumpLineNumbers) {
5273
5374
  case 'comments':
@@ -5289,8 +5390,12 @@ debugInfo.asComment = function(ctx) {
5289
5390
  };
5290
5391
 
5291
5392
  debugInfo.asMediaQuery = function(ctx) {
5393
+ var filenameWithProtocol = ctx.debugInfo.fileName;
5394
+ if (!/^[a-z]+:\/\//i.test(filenameWithProtocol)) {
5395
+ filenameWithProtocol = 'file://' + filenameWithProtocol;
5396
+ }
5292
5397
  return '@media -sass-debug-info{filename{font-family:' +
5293
- ('file://' + ctx.debugInfo.fileName).replace(/([.:\/\\])/g, function (a) {
5398
+ filenameWithProtocol.replace(/([.:\/\\])/g, function (a) {
5294
5399
  if (a == '\\') {
5295
5400
  a = '\/';
5296
5401
  }
@@ -5301,7 +5406,7 @@ debugInfo.asMediaQuery = function(ctx) {
5301
5406
 
5302
5407
  module.exports = debugInfo;
5303
5408
 
5304
- },{}],51:[function(require,module,exports){
5409
+ },{}],52:[function(require,module,exports){
5305
5410
  var Node = require("./node"),
5306
5411
  contexts = require("../contexts");
5307
5412
 
@@ -5324,7 +5429,7 @@ DetachedRuleset.prototype.callEval = function (context) {
5324
5429
  };
5325
5430
  module.exports = DetachedRuleset;
5326
5431
 
5327
- },{"../contexts":10,"./node":66}],52:[function(require,module,exports){
5432
+ },{"../contexts":10,"./node":67}],53:[function(require,module,exports){
5328
5433
  var Node = require("./node"),
5329
5434
  unitConversions = require("../data/unit-conversions"),
5330
5435
  Unit = require("./unit"),
@@ -5352,7 +5457,7 @@ Dimension.prototype.toColor = function () {
5352
5457
  };
5353
5458
  Dimension.prototype.genCSS = function (context, output) {
5354
5459
  if ((context && context.strictUnits) && !this.unit.isSingular()) {
5355
- throw new Error("Multiple units in dimension. Correct the units or use the unit function. Bad unit: "+this.unit.toString());
5460
+ throw new Error("Multiple units in dimension. Correct the units or use the unit function. Bad unit: " + this.unit.toString());
5356
5461
  }
5357
5462
 
5358
5463
  var value = this.fround(context, this.value),
@@ -5481,11 +5586,11 @@ Dimension.prototype.convertTo = function (conversions) {
5481
5586
  };
5482
5587
  module.exports = Dimension;
5483
5588
 
5484
- },{"../data/unit-conversions":13,"./color":46,"./node":66,"./unit":75}],53:[function(require,module,exports){
5589
+ },{"../data/unit-conversions":13,"./color":47,"./node":67,"./unit":76}],54:[function(require,module,exports){
5485
5590
  var Node = require("./node"),
5486
5591
  Ruleset = require("./ruleset");
5487
5592
 
5488
- var Directive = function (name, value, rules, index, currentFileInfo, debugInfo) {
5593
+ var Directive = function (name, value, rules, index, currentFileInfo, debugInfo, isReferenced) {
5489
5594
  this.name = name;
5490
5595
  this.value = value;
5491
5596
  if (rules) {
@@ -5495,6 +5600,7 @@ var Directive = function (name, value, rules, index, currentFileInfo, debugInfo)
5495
5600
  this.index = index;
5496
5601
  this.currentFileInfo = currentFileInfo;
5497
5602
  this.debugInfo = debugInfo;
5603
+ this.isReferenced = isReferenced;
5498
5604
  };
5499
5605
 
5500
5606
  Directive.prototype = new Node();
@@ -5522,7 +5628,10 @@ Directive.prototype.genCSS = function (context, output) {
5522
5628
  value.genCSS(context, output);
5523
5629
  }
5524
5630
  if (rules) {
5525
- this.outputRuleset(context, output, [rules]);
5631
+ if (rules.type === "Ruleset") {
5632
+ rules = [rules];
5633
+ }
5634
+ this.outputRuleset(context, output, rules);
5526
5635
  } else {
5527
5636
  output.add(';');
5528
5637
  }
@@ -5537,11 +5646,23 @@ Directive.prototype.eval = function (context) {
5537
5646
  rules.root = true;
5538
5647
  }
5539
5648
  return new Directive(this.name, value, rules,
5540
- this.index, this.currentFileInfo, this.debugInfo);
5649
+ this.index, this.currentFileInfo, this.debugInfo, this.isReferenced);
5650
+ };
5651
+ Directive.prototype.variable = function (name) {
5652
+ if (this.rules) {
5653
+ return Ruleset.prototype.variable.call(this.rules, name);
5654
+ }
5655
+ };
5656
+ Directive.prototype.find = function () {
5657
+ if (this.rules) {
5658
+ return Ruleset.prototype.find.apply(this.rules, arguments);
5659
+ }
5660
+ };
5661
+ Directive.prototype.rulesets = function () {
5662
+ if (this.rules) {
5663
+ return Ruleset.prototype.rulesets.apply(this.rules);
5664
+ }
5541
5665
  };
5542
- Directive.prototype.variable = function (name) { if (this.rules) return Ruleset.prototype.variable.call(this.rules, name); };
5543
- Directive.prototype.find = function () { if (this.rules) return Ruleset.prototype.find.apply(this.rules, arguments); };
5544
- Directive.prototype.rulesets = function () { if (this.rules) return Ruleset.prototype.rulesets.apply(this.rules); };
5545
5666
  Directive.prototype.markReferenced = function () {
5546
5667
  var i, rules;
5547
5668
  this.isReferenced = true;
@@ -5554,6 +5675,9 @@ Directive.prototype.markReferenced = function () {
5554
5675
  }
5555
5676
  }
5556
5677
  };
5678
+ Directive.prototype.getIsReferenced = function () {
5679
+ return !this.currentFileInfo || !this.currentFileInfo.reference || this.isReferenced;
5680
+ };
5557
5681
  Directive.prototype.outputRuleset = function (context, output, rules) {
5558
5682
  var ruleCnt = rules.length, i;
5559
5683
  context.tabLevel = (context.tabLevel | 0) + 1;
@@ -5587,7 +5711,7 @@ Directive.prototype.outputRuleset = function (context, output, rules) {
5587
5711
  };
5588
5712
  module.exports = Directive;
5589
5713
 
5590
- },{"./node":66,"./ruleset":72}],54:[function(require,module,exports){
5714
+ },{"./node":67,"./ruleset":73}],55:[function(require,module,exports){
5591
5715
  var Node = require("./node"),
5592
5716
  Paren = require("./paren"),
5593
5717
  Combinator = require("./combinator");
@@ -5642,7 +5766,7 @@ Element.prototype.toCSS = function (context) {
5642
5766
  };
5643
5767
  module.exports = Element;
5644
5768
 
5645
- },{"./combinator":47,"./node":66,"./paren":68}],55:[function(require,module,exports){
5769
+ },{"./combinator":48,"./node":67,"./paren":69}],56:[function(require,module,exports){
5646
5770
  var Node = require("./node"),
5647
5771
  Paren = require("./paren"),
5648
5772
  Comment = require("./comment");
@@ -5650,7 +5774,7 @@ var Node = require("./node"),
5650
5774
  var Expression = function (value) {
5651
5775
  this.value = value;
5652
5776
  if (!value) {
5653
- throw new Error("Expression requires a array parameter");
5777
+ throw new Error("Expression requires an array parameter");
5654
5778
  }
5655
5779
  };
5656
5780
  Expression.prototype = new Node();
@@ -5700,7 +5824,7 @@ Expression.prototype.throwAwayComments = function () {
5700
5824
  };
5701
5825
  module.exports = Expression;
5702
5826
 
5703
- },{"./comment":48,"./node":66,"./paren":68}],56:[function(require,module,exports){
5827
+ },{"./comment":49,"./node":67,"./paren":69}],57:[function(require,module,exports){
5704
5828
  var Node = require("./node");
5705
5829
 
5706
5830
  var Extend = function Extend(selector, option, index) {
@@ -5753,7 +5877,7 @@ Extend.prototype.findSelfSelectors = function (selectors) {
5753
5877
  };
5754
5878
  module.exports = Extend;
5755
5879
 
5756
- },{"./node":66}],57:[function(require,module,exports){
5880
+ },{"./node":67}],58:[function(require,module,exports){
5757
5881
  var Node = require("./node"),
5758
5882
  Media = require("./media"),
5759
5883
  URL = require("./url"),
@@ -5784,7 +5908,7 @@ var Import = function (path, features, options, index, currentFileInfo) {
5784
5908
  this.css = !this.options.less || this.options.inline;
5785
5909
  } else {
5786
5910
  var pathValue = this.getPath();
5787
- if (pathValue && /css([\?;].*)?$/.test(pathValue)) {
5911
+ if (pathValue && /[#\.\&\?\/]css([\?;].*)?$/.test(pathValue)) {
5788
5912
  this.css = true;
5789
5913
  }
5790
5914
  }
@@ -5856,7 +5980,7 @@ Import.prototype.evalPath = function (context) {
5856
5980
  var pathValue = path.value;
5857
5981
  // Add the base path if the import is relative
5858
5982
  if (pathValue && context.isPathRelative(pathValue)) {
5859
- path.value = rootpath +pathValue;
5983
+ path.value = rootpath + pathValue;
5860
5984
  }
5861
5985
  }
5862
5986
  path.value = context.normalizePath(path.value);
@@ -5895,9 +6019,10 @@ Import.prototype.eval = function (context) {
5895
6019
  };
5896
6020
  module.exports = Import;
5897
6021
 
5898
- },{"./anonymous":42,"./media":62,"./node":66,"./quoted":69,"./ruleset":72,"./url":76}],58:[function(require,module,exports){
6022
+ },{"./anonymous":43,"./media":63,"./node":67,"./quoted":70,"./ruleset":73,"./url":77}],59:[function(require,module,exports){
5899
6023
  var tree = {};
5900
6024
 
6025
+ tree.Node = require('./node');
5901
6026
  tree.Alpha = require('./alpha');
5902
6027
  tree.Color = require('./color');
5903
6028
  tree.Directive = require('./directive');
@@ -5937,7 +6062,7 @@ tree.RulesetCall = require('./ruleset-call');
5937
6062
 
5938
6063
  module.exports = tree;
5939
6064
 
5940
- },{"./alpha":41,"./anonymous":42,"./assignment":43,"./attribute":44,"./call":45,"./color":46,"./combinator":47,"./comment":48,"./condition":49,"./detached-ruleset":51,"./dimension":52,"./directive":53,"./element":54,"./expression":55,"./extend":56,"./import":57,"./javascript":59,"./keyword":61,"./media":62,"./mixin-call":63,"./mixin-definition":64,"./negative":65,"./operation":67,"./paren":68,"./quoted":69,"./rule":70,"./ruleset":72,"./ruleset-call":71,"./selector":73,"./unicode-descriptor":74,"./unit":75,"./url":76,"./value":77,"./variable":78}],59:[function(require,module,exports){
6065
+ },{"./alpha":42,"./anonymous":43,"./assignment":44,"./attribute":45,"./call":46,"./color":47,"./combinator":48,"./comment":49,"./condition":50,"./detached-ruleset":52,"./dimension":53,"./directive":54,"./element":55,"./expression":56,"./extend":57,"./import":58,"./javascript":60,"./keyword":62,"./media":63,"./mixin-call":64,"./mixin-definition":65,"./negative":66,"./node":67,"./operation":68,"./paren":69,"./quoted":70,"./rule":71,"./ruleset":73,"./ruleset-call":72,"./selector":74,"./unicode-descriptor":75,"./unit":76,"./url":77,"./value":78,"./variable":79}],60:[function(require,module,exports){
5941
6066
  var JsEvalNode = require("./js-eval-node"),
5942
6067
  Dimension = require("./dimension"),
5943
6068
  Quoted = require("./quoted"),
@@ -5967,7 +6092,7 @@ JavaScript.prototype.eval = function(context) {
5967
6092
 
5968
6093
  module.exports = JavaScript;
5969
6094
 
5970
- },{"./anonymous":42,"./dimension":52,"./js-eval-node":60,"./quoted":69}],60:[function(require,module,exports){
6095
+ },{"./anonymous":43,"./dimension":53,"./js-eval-node":61,"./quoted":70}],61:[function(require,module,exports){
5971
6096
  var Node = require("./node"),
5972
6097
  Variable = require("./variable");
5973
6098
 
@@ -6030,7 +6155,7 @@ JsEvalNode.prototype.jsify = function (obj) {
6030
6155
 
6031
6156
  module.exports = JsEvalNode;
6032
6157
 
6033
- },{"./node":66,"./variable":78}],61:[function(require,module,exports){
6158
+ },{"./node":67,"./variable":79}],62:[function(require,module,exports){
6034
6159
  var Node = require("./node");
6035
6160
 
6036
6161
  var Keyword = function (value) { this.value = value; };
@@ -6046,7 +6171,7 @@ Keyword.False = new Keyword('false');
6046
6171
 
6047
6172
  module.exports = Keyword;
6048
6173
 
6049
- },{"./node":66}],62:[function(require,module,exports){
6174
+ },{"./node":67}],63:[function(require,module,exports){
6050
6175
  var Ruleset = require("./ruleset"),
6051
6176
  Value = require("./value"),
6052
6177
  Element = require("./element"),
@@ -6203,13 +6328,14 @@ Media.prototype.permute = function (arr) {
6203
6328
  }
6204
6329
  };
6205
6330
  Media.prototype.bubbleSelectors = function (selectors) {
6206
- if (!selectors)
6207
- return;
6331
+ if (!selectors) {
6332
+ return;
6333
+ }
6208
6334
  this.rules = [new Ruleset(selectors.slice(0), [this.rules[0]])];
6209
6335
  };
6210
6336
  module.exports = Media;
6211
6337
 
6212
- },{"./anonymous":42,"./directive":53,"./element":54,"./expression":55,"./ruleset":72,"./selector":73,"./value":77}],63:[function(require,module,exports){
6338
+ },{"./anonymous":43,"./directive":54,"./element":55,"./expression":56,"./ruleset":73,"./selector":74,"./value":78}],64:[function(require,module,exports){
6213
6339
  var Node = require("./node"),
6214
6340
  Selector = require("./selector"),
6215
6341
  MixinDefinition = require("./mixin-definition"),
@@ -6234,7 +6360,7 @@ MixinCall.prototype.accept = function (visitor) {
6234
6360
  };
6235
6361
  MixinCall.prototype.eval = function (context) {
6236
6362
  var mixins, mixin, mixinPath, args, rules = [], match = false, i, m, f, isRecursive, isOneFound, rule,
6237
- candidates = [], candidate, conditionResult = [], defaultResult, defFalseEitherCase=-1,
6363
+ candidates = [], candidate, conditionResult = [], defaultResult, defFalseEitherCase = -1,
6238
6364
  defNone = 0, defTrue = 1, defFalse = 2, count, originalRuleset, noArgumentsFilter;
6239
6365
 
6240
6366
  function calcDefGroup(mixin, mixinPath) {
@@ -6296,7 +6422,7 @@ MixinCall.prototype.eval = function (context) {
6296
6422
  if (mixin.matchArgs(args, context)) {
6297
6423
  candidate = {mixin: mixin, group: calcDefGroup(mixin, mixinPath)};
6298
6424
 
6299
- if (candidate.group!==defFalseEitherCase) {
6425
+ if (candidate.group !== defFalseEitherCase) {
6300
6426
  candidates.push(candidate);
6301
6427
  }
6302
6428
 
@@ -6317,8 +6443,7 @@ MixinCall.prototype.eval = function (context) {
6317
6443
  defaultResult = defTrue;
6318
6444
  if ((count[defTrue] + count[defFalse]) > 1) {
6319
6445
  throw { type: 'Runtime',
6320
- message: 'Ambiguous use of `default()` found when matching for `'
6321
- + this.format(args) + '`',
6446
+ message: 'Ambiguous use of `default()` found when matching for `' + this.format(args) + '`',
6322
6447
  index: this.index, filename: this.currentFileInfo.filename };
6323
6448
  }
6324
6449
  }
@@ -6381,7 +6506,7 @@ MixinCall.prototype.format = function (args) {
6381
6506
  };
6382
6507
  module.exports = MixinCall;
6383
6508
 
6384
- },{"../functions/default":19,"./mixin-definition":64,"./node":66,"./selector":73}],64:[function(require,module,exports){
6509
+ },{"../functions/default":19,"./mixin-definition":65,"./node":67,"./selector":74}],65:[function(require,module,exports){
6385
6510
  var Selector = require("./selector"),
6386
6511
  Element = require("./element"),
6387
6512
  Ruleset = require("./ruleset"),
@@ -6516,9 +6641,10 @@ Definition.prototype.evalCall = function (context, args, important) {
6516
6641
  Definition.prototype.matchCondition = function (args, context) {
6517
6642
  if (this.condition && !this.condition.eval(
6518
6643
  new contexts.Eval(context,
6519
- [this.evalParams(context, new contexts.Eval(context, this.frames ? this.frames.concat(context.frames) : context.frames), args, [])] // the parameter variables
6520
- .concat(this.frames) // the parent namespace/mixin frames
6521
- .concat(context.frames)))) { // the current environment frames
6644
+ [this.evalParams(context, /* the parameter variables*/
6645
+ new contexts.Eval(context, this.frames ? this.frames.concat(context.frames) : context.frames), args, [])]
6646
+ .concat(this.frames) // the parent namespace/mixin frames
6647
+ .concat(context.frames)))) { // the current environment frames
6522
6648
  return false;
6523
6649
  }
6524
6650
  return true;
@@ -6546,7 +6672,7 @@ Definition.prototype.matchArgs = function (args, context) {
6546
6672
  };
6547
6673
  module.exports = Definition;
6548
6674
 
6549
- },{"../contexts":10,"./element":54,"./expression":55,"./rule":70,"./ruleset":72,"./selector":73}],65:[function(require,module,exports){
6675
+ },{"../contexts":10,"./element":55,"./expression":56,"./rule":71,"./ruleset":73,"./selector":74}],66:[function(require,module,exports){
6550
6676
  var Node = require("./node"),
6551
6677
  Operation = require("./operation"),
6552
6678
  Dimension = require("./dimension");
@@ -6568,7 +6694,7 @@ Negative.prototype.eval = function (context) {
6568
6694
  };
6569
6695
  module.exports = Negative;
6570
6696
 
6571
- },{"./dimension":52,"./node":66,"./operation":67}],66:[function(require,module,exports){
6697
+ },{"./dimension":53,"./node":67,"./operation":68}],67:[function(require,module,exports){
6572
6698
  var Node = function() {
6573
6699
  };
6574
6700
  Node.prototype.toCSS = function (context) {
@@ -6644,7 +6770,7 @@ Node.numericCompare = function (a, b) {
6644
6770
  };
6645
6771
  module.exports = Node;
6646
6772
 
6647
- },{}],67:[function(require,module,exports){
6773
+ },{}],68:[function(require,module,exports){
6648
6774
  var Node = require("./node"),
6649
6775
  Color = require("./color"),
6650
6776
  Dimension = require("./dimension");
@@ -6694,7 +6820,7 @@ Operation.prototype.genCSS = function (context, output) {
6694
6820
 
6695
6821
  module.exports = Operation;
6696
6822
 
6697
- },{"./color":46,"./dimension":52,"./node":66}],68:[function(require,module,exports){
6823
+ },{"./color":47,"./dimension":53,"./node":67}],69:[function(require,module,exports){
6698
6824
  var Node = require("./node");
6699
6825
 
6700
6826
  var Paren = function (node) {
@@ -6712,7 +6838,7 @@ Paren.prototype.eval = function (context) {
6712
6838
  };
6713
6839
  module.exports = Paren;
6714
6840
 
6715
- },{"./node":66}],69:[function(require,module,exports){
6841
+ },{"./node":67}],70:[function(require,module,exports){
6716
6842
  var Node = require("./node"),
6717
6843
  JsEvalNode = require("./js-eval-node"),
6718
6844
  Variable = require("./variable");
@@ -6752,7 +6878,7 @@ Quoted.prototype.eval = function (context) {
6752
6878
  do {
6753
6879
  value = evaluatedValue;
6754
6880
  evaluatedValue = value.replace(regexp, replacementFnc);
6755
- } while (value!==evaluatedValue);
6881
+ } while (value !== evaluatedValue);
6756
6882
  return evaluatedValue;
6757
6883
  }
6758
6884
  value = iterativeReplace(value, /`([^`]+)`/g, javascriptReplacement);
@@ -6769,7 +6895,7 @@ Quoted.prototype.compare = function (other) {
6769
6895
  };
6770
6896
  module.exports = Quoted;
6771
6897
 
6772
- },{"./js-eval-node":60,"./node":66,"./variable":78}],70:[function(require,module,exports){
6898
+ },{"./js-eval-node":61,"./node":67,"./variable":79}],71:[function(require,module,exports){
6773
6899
  var Node = require("./node"),
6774
6900
  Value = require("./value"),
6775
6901
  Keyword = require("./keyword");
@@ -6814,9 +6940,8 @@ Rule.prototype.eval = function (context) {
6814
6940
  if (typeof name !== "string") {
6815
6941
  // expand 'primitive' name directly to get
6816
6942
  // things faster (~10% for benchmark.less):
6817
- name = (name.length === 1)
6818
- && (name[0] instanceof Keyword)
6819
- ? name[0].value : evalName(context, name);
6943
+ name = (name.length === 1) && (name[0] instanceof Keyword) ?
6944
+ name[0].value : evalName(context, name);
6820
6945
  variable = false; // never treat expanded interpolation as new variable name
6821
6946
  }
6822
6947
  if (name === "font" && !context.strictMath) {
@@ -6867,7 +6992,7 @@ Rule.prototype.makeImportant = function () {
6867
6992
 
6868
6993
  module.exports = Rule;
6869
6994
 
6870
- },{"./keyword":61,"./node":66,"./value":77}],71:[function(require,module,exports){
6995
+ },{"./keyword":62,"./node":67,"./value":78}],72:[function(require,module,exports){
6871
6996
  var Node = require("./node"),
6872
6997
  Variable = require("./variable");
6873
6998
 
@@ -6882,11 +7007,12 @@ RulesetCall.prototype.eval = function (context) {
6882
7007
  };
6883
7008
  module.exports = RulesetCall;
6884
7009
 
6885
- },{"./node":66,"./variable":78}],72:[function(require,module,exports){
7010
+ },{"./node":67,"./variable":79}],73:[function(require,module,exports){
6886
7011
  var Node = require("./node"),
6887
7012
  Rule = require("./rule"),
6888
7013
  Selector = require("./selector"),
6889
7014
  Element = require("./element"),
7015
+ Paren = require("./paren"),
6890
7016
  contexts = require("../contexts"),
6891
7017
  defaultFunc = require("../functions/default"),
6892
7018
  getDebugInfo = require("./debug-info");
@@ -6992,7 +7118,7 @@ Ruleset.prototype.eval = function (context) {
6992
7118
  });
6993
7119
  rsRules.splice.apply(rsRules, [i, 1].concat(rules));
6994
7120
  rsRuleCnt += rules.length - 1;
6995
- i += rules.length-1;
7121
+ i += rules.length - 1;
6996
7122
  ruleset.resetCache();
6997
7123
  } else if (rsRules[i].type === "RulesetCall") {
6998
7124
  /*jshint loopfunc:true */
@@ -7005,7 +7131,7 @@ Ruleset.prototype.eval = function (context) {
7005
7131
  });
7006
7132
  rsRules.splice.apply(rsRules, [i, 1].concat(rules));
7007
7133
  rsRuleCnt += rules.length - 1;
7008
- i += rules.length-1;
7134
+ i += rules.length - 1;
7009
7135
  ruleset.resetCache();
7010
7136
  }
7011
7137
  }
@@ -7058,7 +7184,7 @@ Ruleset.prototype.evalImports = function(context) {
7058
7184
  importRules = rules[i].eval(context);
7059
7185
  if (importRules && importRules.length) {
7060
7186
  rules.splice.apply(rules, [i, 1].concat(importRules));
7061
- i+= importRules.length-1;
7187
+ i+= importRules.length - 1;
7062
7188
  } else {
7063
7189
  rules.splice(i, 1, importRules);
7064
7190
  }
@@ -7067,20 +7193,20 @@ Ruleset.prototype.evalImports = function(context) {
7067
7193
  }
7068
7194
  };
7069
7195
  Ruleset.prototype.makeImportant = function() {
7070
- return new Ruleset(this.selectors, this.rules.map(function (r) {
7071
- if (r.makeImportant) {
7072
- return r.makeImportant();
7073
- } else {
7074
- return r;
7075
- }
7076
- }), this.strictImports);
7077
- };
7078
- Ruleset.prototype.matchArgs = function (args) {
7196
+ this.rules = this.rules.map(function (r) {
7197
+ if (r.makeImportant) {
7198
+ return r.makeImportant();
7199
+ } else {
7200
+ return r;
7201
+ }
7202
+ });
7203
+ return this;
7204
+ };Ruleset.prototype.matchArgs = function (args) {
7079
7205
  return !args || args.length === 0;
7080
7206
  };
7081
7207
  // lets you call a css selector with a guard
7082
7208
  Ruleset.prototype.matchCondition = function (args, context) {
7083
- var lastSelector = this.selectors[this.selectors.length-1];
7209
+ var lastSelector = this.selectors[this.selectors.length - 1];
7084
7210
  if (!lastSelector.evaldCondition) {
7085
7211
  return false;
7086
7212
  }
@@ -7105,7 +7231,8 @@ Ruleset.prototype.variables = function () {
7105
7231
  }
7106
7232
  // when evaluating variables in an import statement, imports have not been eval'd
7107
7233
  // so we need to go inside import statements.
7108
- if (r.type === "Import" && r.root) {
7234
+ // guard against root being a string (in the case of inlined less)
7235
+ if (r.type === "Import" && r.root && r.root.variables) {
7109
7236
  var vars = r.root.variables();
7110
7237
  for(var name in vars) {
7111
7238
  if (vars.hasOwnProperty(name)) {
@@ -7298,194 +7425,298 @@ Ruleset.prototype.genCSS = function (context, output) {
7298
7425
  }
7299
7426
  };
7300
7427
  Ruleset.prototype.markReferenced = function () {
7301
- if (!this.selectors) {
7302
- return;
7428
+ var s;
7429
+ if (this.selectors) {
7430
+ for (s = 0; s < this.selectors.length; s++) {
7431
+ this.selectors[s].markReferenced();
7432
+ }
7303
7433
  }
7304
- for (var s = 0; s < this.selectors.length; s++) {
7305
- this.selectors[s].markReferenced();
7434
+
7435
+ if (this.rules) {
7436
+ for (s = 0; s < this.rules.length; s++) {
7437
+ if (this.rules[s].markReferenced) {
7438
+ this.rules[s].markReferenced();
7439
+ }
7440
+ }
7306
7441
  }
7307
7442
  };
7443
+ Ruleset.prototype.getIsReferenced = function() {
7444
+ var i, j, path, selector;
7445
+
7446
+ if (this.paths) {
7447
+ for (i = 0; i < this.paths.length; i++) {
7448
+ path = this.paths[i];
7449
+ for (j = 0; j < path.length; j++) {
7450
+ if (path[j].getIsReferenced && path[j].getIsReferenced()) {
7451
+ return true;
7452
+ }
7453
+ }
7454
+ }
7455
+ }
7456
+
7457
+ if (this.selectors) {
7458
+ for (i = 0; i < this.selectors.length; i++) {
7459
+ selector = this.selectors[i];
7460
+ if (selector.getIsReferenced && selector.getIsReferenced()) {
7461
+ return true;
7462
+ }
7463
+ }
7464
+ }
7465
+ return false;
7466
+ };
7467
+
7308
7468
  Ruleset.prototype.joinSelectors = function (paths, context, selectors) {
7309
7469
  for (var s = 0; s < selectors.length; s++) {
7310
7470
  this.joinSelector(paths, context, selectors[s]);
7311
7471
  }
7312
7472
  };
7313
- Ruleset.prototype.joinSelector = function (paths, context, selector) {
7314
7473
 
7315
- var i, j, k,
7316
- hasParentSelector, newSelectors, el, sel, parentSel,
7317
- newSelectorPath, afterParentJoin, newJoinedSelector,
7318
- newJoinedSelectorEmpty, lastSelector, currentElements,
7319
- selectorsMultiplied;
7474
+ Ruleset.prototype.joinSelector = function (paths, context, selector) {
7320
7475
 
7321
- for (i = 0; i < selector.elements.length; i++) {
7322
- el = selector.elements[i];
7323
- if (el.value === '&') {
7324
- hasParentSelector = true;
7325
- }
7326
- }
7476
+ function createParenthesis(elementsToPak, originalElement) {
7477
+ var replacementParen, j;
7478
+ if (elementsToPak.length === 0) {
7479
+ replacementParen = new Paren(elementsToPak[0]);
7480
+ } else {
7481
+ var insideParent = [];
7482
+ for (j = 0; j < elementsToPak.length; j++) {
7483
+ insideParent.push(new Element(null, elementsToPak[j], originalElement.index, originalElement.currentFileInfo));
7484
+ }
7485
+ replacementParen = new Paren(new Selector(insideParent));
7486
+ }
7487
+ return replacementParen;
7488
+ }
7489
+
7490
+ function createSelector(containedElement, originalElement) {
7491
+ var element, selector;
7492
+ element = new Element(null, containedElement, originalElement.index, originalElement.currentFileInfo);
7493
+ selector = new Selector([element]);
7494
+ return selector;
7495
+ }
7496
+
7497
+ // replace all parent selectors inside `inSelector` by content of `context` array
7498
+ // resulting selectors are returned inside `paths` array
7499
+ // returns true if `inSelector` contained at least one parent selector
7500
+ function replaceParentSelector(paths, context, inSelector) {
7501
+ // The paths are [[Selector]]
7502
+ // The first list is a list of comma separated selectors
7503
+ // The inner list is a list of inheritance separated selectors
7504
+ // e.g.
7505
+ // .a, .b {
7506
+ // .c {
7507
+ // }
7508
+ // }
7509
+ // == [[.a] [.c]] [[.b] [.c]]
7510
+ //
7511
+ var i, j, k, currentElements, newSelectors, selectorsMultiplied, sel, el, hadParentSelector = false;
7512
+ function findNestedSelector(element) {
7513
+ var maybeSelector;
7514
+ if (element.value.type !== 'Paren') {
7515
+ return null;
7516
+ }
7327
7517
 
7328
- if (!hasParentSelector) {
7329
- if (context.length > 0) {
7330
- for (i = 0; i < context.length; i++) {
7331
- paths.push(context[i].concat(selector));
7518
+ maybeSelector = element.value.value;
7519
+ if (maybeSelector.type !== 'Selector') {
7520
+ return null;
7332
7521
  }
7522
+
7523
+ return maybeSelector;
7333
7524
  }
7334
- else {
7335
- paths.push([selector]);
7336
- }
7337
- return;
7338
- }
7339
7525
 
7340
- // The paths are [[Selector]]
7341
- // The first list is a list of comma separated selectors
7342
- // The inner list is a list of inheritance separated selectors
7343
- // e.g.
7344
- // .a, .b {
7345
- // .c {
7346
- // }
7347
- // }
7348
- // == [[.a] [.c]] [[.b] [.c]]
7349
- //
7526
+ // the elements from the current selector so far
7527
+ currentElements = [];
7528
+ // the current list of new selectors to add to the path.
7529
+ // We will build it up. We initiate it with one empty selector as we "multiply" the new selectors
7530
+ // by the parents
7531
+ newSelectors = [
7532
+ []
7533
+ ];
7350
7534
 
7351
- // the elements from the current selector so far
7352
- currentElements = [];
7353
- // the current list of new selectors to add to the path.
7354
- // We will build it up. We initiate it with one empty selector as we "multiply" the new selectors
7355
- // by the parents
7356
- newSelectors = [[]];
7357
-
7358
- for (i = 0; i < selector.elements.length; i++) {
7359
- el = selector.elements[i];
7360
- // non parent reference elements just get added
7361
- if (el.value !== "&") {
7362
- currentElements.push(el);
7363
- } else {
7364
- // the new list of selectors to add
7365
- selectorsMultiplied = [];
7366
-
7367
- // merge the current list of non parent selector elements
7368
- // on to the current list of selectors to add
7369
- if (currentElements.length > 0) {
7370
- this.mergeElementsOnToSelectors(currentElements, newSelectors);
7371
- }
7372
-
7373
- // loop through our current selectors
7374
- for (j = 0; j < newSelectors.length; j++) {
7375
- sel = newSelectors[j];
7376
- // if we don't have any parent paths, the & might be in a mixin so that it can be used
7377
- // whether there are parents or not
7378
- if (context.length === 0) {
7379
- // the combinator used on el should now be applied to the next element instead so that
7380
- // it is not lost
7381
- if (sel.length > 0) {
7382
- sel[0].elements = sel[0].elements.slice(0);
7383
- sel[0].elements.push(new Element(el.combinator, '', el.index, el.currentFileInfo));
7535
+ for (i = 0; i < inSelector.elements.length; i++) {
7536
+ el = inSelector.elements[i];
7537
+ // non parent reference elements just get added
7538
+ if (el.value !== "&") {
7539
+ var nestedSelector = findNestedSelector(el);
7540
+ if (nestedSelector != null) {
7541
+ // merge the current list of non parent selector elements
7542
+ // on to the current list of selectors to add
7543
+ mergeElementsOnToSelectors(currentElements, newSelectors);
7544
+
7545
+ var nestedPaths = [], replaced, replacedNewSelectors = [];
7546
+ replaced = replaceParentSelector(nestedPaths, context, nestedSelector);
7547
+ hadParentSelector = hadParentSelector || replaced;
7548
+ //the nestedPaths array should have only one member - replaceParentSelector does not multiply selectors
7549
+ for (k = 0; k < nestedPaths.length; k++) {
7550
+ var replacementSelector = createSelector(createParenthesis(nestedPaths[k], el), el);
7551
+ addAllReplacementsIntoPath(newSelectors, [replacementSelector], el, inSelector, replacedNewSelectors);
7384
7552
  }
7385
- selectorsMultiplied.push(sel);
7553
+ newSelectors = replacedNewSelectors;
7554
+ currentElements = [];
7555
+
7556
+ } else {
7557
+ currentElements.push(el);
7386
7558
  }
7387
- else {
7388
- // and the parent selectors
7389
- for (k = 0; k < context.length; k++) {
7390
- parentSel = context[k];
7391
- // We need to put the current selectors
7392
- // then join the last selector's elements on to the parents selectors
7393
-
7394
- // our new selector path
7395
- newSelectorPath = [];
7396
- // selectors from the parent after the join
7397
- afterParentJoin = [];
7398
- newJoinedSelectorEmpty = true;
7399
-
7400
- //construct the joined selector - if & is the first thing this will be empty,
7401
- // if not newJoinedSelector will be the last set of elements in the selector
7559
+
7560
+ } else {
7561
+ hadParentSelector = true;
7562
+ // the new list of selectors to add
7563
+ selectorsMultiplied = [];
7564
+
7565
+ // merge the current list of non parent selector elements
7566
+ // on to the current list of selectors to add
7567
+ mergeElementsOnToSelectors(currentElements, newSelectors);
7568
+
7569
+ // loop through our current selectors
7570
+ for (j = 0; j < newSelectors.length; j++) {
7571
+ sel = newSelectors[j];
7572
+ // if we don't have any parent paths, the & might be in a mixin so that it can be used
7573
+ // whether there are parents or not
7574
+ if (context.length === 0) {
7575
+ // the combinator used on el should now be applied to the next element instead so that
7576
+ // it is not lost
7402
7577
  if (sel.length > 0) {
7403
- newSelectorPath = sel.slice(0);
7404
- lastSelector = newSelectorPath.pop();
7405
- newJoinedSelector = selector.createDerived(lastSelector.elements.slice(0));
7406
- newJoinedSelectorEmpty = false;
7578
+ sel[0].elements.push(new Element(el.combinator, '', el.index, el.currentFileInfo));
7407
7579
  }
7408
- else {
7409
- newJoinedSelector = selector.createDerived([]);
7580
+ selectorsMultiplied.push(sel);
7581
+ }
7582
+ else {
7583
+ // and the parent selectors
7584
+ for (k = 0; k < context.length; k++) {
7585
+ // We need to put the current selectors
7586
+ // then join the last selector's elements on to the parents selectors
7587
+ var newSelectorPath = addReplacementIntoPath(sel, context[k], el, inSelector);
7588
+ // add that to our new set of selectors
7589
+ selectorsMultiplied.push(newSelectorPath);
7410
7590
  }
7591
+ }
7592
+ }
7411
7593
 
7412
- //put together the parent selectors after the join
7413
- if (parentSel.length > 1) {
7414
- afterParentJoin = afterParentJoin.concat(parentSel.slice(1));
7415
- }
7594
+ // our new selectors has been multiplied, so reset the state
7595
+ newSelectors = selectorsMultiplied;
7596
+ currentElements = [];
7597
+ }
7598
+ }
7416
7599
 
7417
- if (parentSel.length > 0) {
7418
- newJoinedSelectorEmpty = false;
7419
-
7420
- // /deep/ is a combinator that is valid without anything in front of it
7421
- // so if the & does not have a combinator that is "" or " " then
7422
- // and there is a combinator on the parent, then grab that.
7423
- // this also allows + a { & .b { .a & { ... though not sure why you would want to do that
7424
- var combinator = el.combinator,
7425
- parentEl = parentSel[0].elements[0];
7426
- if (combinator.emptyOrWhitespace && !parentEl.combinator.emptyOrWhitespace) {
7427
- combinator = parentEl.combinator;
7428
- }
7429
- // join the elements so far with the first part of the parent
7430
- newJoinedSelector.elements.push(new Element(combinator, parentEl.value, el.index, el.currentFileInfo));
7431
- newJoinedSelector.elements = newJoinedSelector.elements.concat(parentSel[0].elements.slice(1));
7432
- }
7600
+ // if we have any elements left over (e.g. .a& .b == .b)
7601
+ // add them on to all the current selectors
7602
+ mergeElementsOnToSelectors(currentElements, newSelectors);
7433
7603
 
7434
- if (!newJoinedSelectorEmpty) {
7435
- // now add the joined selector
7436
- newSelectorPath.push(newJoinedSelector);
7437
- }
7604
+ for (i = 0; i < newSelectors.length; i++) {
7605
+ if (newSelectors[i].length > 0) {
7606
+ paths.push(newSelectors[i]);
7607
+ }
7608
+ }
7438
7609
 
7439
- // and the rest of the parent
7440
- newSelectorPath = newSelectorPath.concat(afterParentJoin);
7610
+ return hadParentSelector;
7611
+ }
7441
7612
 
7442
- // add that to our new set of selectors
7443
- selectorsMultiplied.push(newSelectorPath);
7444
- }
7445
- }
7613
+ // joins selector path from `beginningPath` with selector path in `addPath`
7614
+ // `replacedElement` contains element that is being replaced by `addPath`
7615
+ // returns concatenated path
7616
+ function addReplacementIntoPath(beginningPath, addPath, replacedElement, originalSelector) {
7617
+ var newSelectorPath, lastSelector, newJoinedSelector;
7618
+ // our new selector path
7619
+ newSelectorPath = [];
7620
+
7621
+ //construct the joined selector - if & is the first thing this will be empty,
7622
+ // if not newJoinedSelector will be the last set of elements in the selector
7623
+ if (beginningPath.length > 0) {
7624
+ newSelectorPath = beginningPath.slice(0);
7625
+ lastSelector = newSelectorPath.pop();
7626
+ newJoinedSelector = originalSelector.createDerived(lastSelector.elements.slice(0));
7627
+ }
7628
+ else {
7629
+ newJoinedSelector = originalSelector.createDerived([]);
7630
+ }
7631
+
7632
+ if (addPath.length > 0) {
7633
+ // /deep/ is a combinator that is valid without anything in front of it
7634
+ // so if the & does not have a combinator that is "" or " " then
7635
+ // and there is a combinator on the parent, then grab that.
7636
+ // this also allows + a { & .b { .a & { ... though not sure why you would want to do that
7637
+ var combinator = replacedElement.combinator, parentEl = addPath[0].elements[0];
7638
+ if (combinator.emptyOrWhitespace && !parentEl.combinator.emptyOrWhitespace) {
7639
+ combinator = parentEl.combinator;
7446
7640
  }
7641
+ // join the elements so far with the first part of the parent
7642
+ newJoinedSelector.elements.push(new Element(combinator, parentEl.value, replacedElement.index, replacedElement.currentFileInfo));
7643
+ newJoinedSelector.elements = newJoinedSelector.elements.concat(addPath[0].elements.slice(1));
7644
+ }
7447
7645
 
7448
- // our new selectors has been multiplied, so reset the state
7449
- newSelectors = selectorsMultiplied;
7450
- currentElements = [];
7646
+ // now add the joined selector - but only if it is not empty
7647
+ if (newJoinedSelector.elements.length !== 0) {
7648
+ newSelectorPath.push(newJoinedSelector);
7451
7649
  }
7452
- }
7453
7650
 
7454
- // if we have any elements left over (e.g. .a& .b == .b)
7455
- // add them on to all the current selectors
7456
- if (currentElements.length > 0) {
7457
- this.mergeElementsOnToSelectors(currentElements, newSelectors);
7651
+ //put together the parent selectors after the join (e.g. the rest of the parent)
7652
+ if (addPath.length > 1) {
7653
+ newSelectorPath = newSelectorPath.concat(addPath.slice(1));
7654
+ }
7655
+ return newSelectorPath;
7458
7656
  }
7459
7657
 
7460
- for (i = 0; i < newSelectors.length; i++) {
7461
- if (newSelectors[i].length > 0) {
7462
- paths.push(newSelectors[i]);
7658
+ // joins selector path from `beginningPath` with every selector path in `addPaths` array
7659
+ // `replacedElement` contains element that is being replaced by `addPath`
7660
+ // returns array with all concatenated paths
7661
+ function addAllReplacementsIntoPath( beginningPath, addPaths, replacedElement, originalSelector, result) {
7662
+ var j;
7663
+ for (j = 0; j < beginningPath.length; j++) {
7664
+ var newSelectorPath = addReplacementIntoPath(beginningPath[j], addPaths, replacedElement, originalSelector);
7665
+ result.push(newSelectorPath);
7463
7666
  }
7667
+ return result;
7464
7668
  }
7465
- };
7466
- Ruleset.prototype.mergeElementsOnToSelectors = function(elements, selectors) {
7467
- var i, sel;
7468
7669
 
7469
- if (selectors.length === 0) {
7470
- selectors.push([ new Selector(elements) ]);
7471
- return;
7670
+ function mergeElementsOnToSelectors(elements, selectors) {
7671
+ var i, sel;
7672
+
7673
+ if (elements.length === 0) {
7674
+ return ;
7675
+ }
7676
+ if (selectors.length === 0) {
7677
+ selectors.push([ new Selector(elements) ]);
7678
+ return;
7679
+ }
7680
+
7681
+ for (i = 0; i < selectors.length; i++) {
7682
+ sel = selectors[i];
7683
+
7684
+ // if the previous thing in sel is a parent this needs to join on to it
7685
+ if (sel.length > 0) {
7686
+ sel[sel.length - 1] = sel[sel.length - 1].createDerived(sel[sel.length - 1].elements.concat(elements));
7687
+ }
7688
+ else {
7689
+ sel.push(new Selector(elements));
7690
+ }
7691
+ }
7472
7692
  }
7473
7693
 
7474
- for (i = 0; i < selectors.length; i++) {
7475
- sel = selectors[i];
7694
+ // joinSelector code follows
7695
+ var i, newPaths, hadParentSelector;
7476
7696
 
7477
- // if the previous thing in sel is a parent this needs to join on to it
7478
- if (sel.length > 0) {
7479
- sel[sel.length - 1] = sel[sel.length - 1].createDerived(sel[sel.length - 1].elements.concat(elements));
7697
+ newPaths = [];
7698
+ hadParentSelector = replaceParentSelector(newPaths, context, selector);
7699
+
7700
+ if (!hadParentSelector) {
7701
+ if (context.length > 0) {
7702
+ newPaths = [];
7703
+ for (i = 0; i < context.length; i++) {
7704
+ newPaths.push(context[i].concat(selector));
7705
+ }
7480
7706
  }
7481
7707
  else {
7482
- sel.push(new Selector(elements));
7708
+ newPaths = [[selector]];
7483
7709
  }
7484
7710
  }
7711
+
7712
+ for (i = 0; i < newPaths.length; i++) {
7713
+ paths.push(newPaths[i]);
7714
+ }
7715
+
7485
7716
  };
7486
7717
  module.exports = Ruleset;
7487
7718
 
7488
- },{"../contexts":10,"../functions/default":19,"./debug-info":50,"./element":54,"./node":66,"./rule":70,"./selector":73}],73:[function(require,module,exports){
7719
+ },{"../contexts":10,"../functions/default":19,"./debug-info":51,"./element":55,"./node":67,"./paren":69,"./rule":71,"./selector":74}],74:[function(require,module,exports){
7489
7720
  var Node = require("./node");
7490
7721
 
7491
7722
  var Selector = function (elements, extendList, condition, index, currentFileInfo, isReferenced) {
@@ -7539,8 +7770,9 @@ Selector.prototype.match = function (other) {
7539
7770
  return olen; // return number of matched elements
7540
7771
  };
7541
7772
  Selector.prototype.CacheElements = function() {
7542
- if (this._elements)
7773
+ if (this._elements) {
7543
7774
  return;
7775
+ }
7544
7776
 
7545
7777
  var elements = this.elements.map( function(v) {
7546
7778
  return v.combinator.value + (v.value.value || v.value);
@@ -7595,7 +7827,7 @@ Selector.prototype.getIsOutput = function() {
7595
7827
  };
7596
7828
  module.exports = Selector;
7597
7829
 
7598
- },{"./node":66}],74:[function(require,module,exports){
7830
+ },{"./node":67}],75:[function(require,module,exports){
7599
7831
  var Node = require("./node");
7600
7832
 
7601
7833
  var UnicodeDescriptor = function (value) {
@@ -7606,7 +7838,7 @@ UnicodeDescriptor.prototype.type = "UnicodeDescriptor";
7606
7838
 
7607
7839
  module.exports = UnicodeDescriptor;
7608
7840
 
7609
- },{"./node":66}],75:[function(require,module,exports){
7841
+ },{"./node":67}],76:[function(require,module,exports){
7610
7842
  var Node = require("./node"),
7611
7843
  unitConversions = require("../data/unit-conversions");
7612
7844
 
@@ -7726,7 +7958,7 @@ Unit.prototype.cancel = function () {
7726
7958
  };
7727
7959
  module.exports = Unit;
7728
7960
 
7729
- },{"../data/unit-conversions":13,"./node":66}],76:[function(require,module,exports){
7961
+ },{"../data/unit-conversions":13,"./node":67}],77:[function(require,module,exports){
7730
7962
  var Node = require("./node");
7731
7963
 
7732
7964
  var URL = function (val, index, currentFileInfo, isEvald) {
@@ -7752,9 +7984,12 @@ URL.prototype.eval = function (context) {
7752
7984
  if (!this.isEvald) {
7753
7985
  // Add the base path if the URL is relative
7754
7986
  rootpath = this.currentFileInfo && this.currentFileInfo.rootpath;
7755
- if (rootpath && typeof val.value === "string" && context.isPathRelative(val.value)) {
7987
+ if (rootpath &&
7988
+ typeof val.value === "string" &&
7989
+ context.isPathRelative(val.value)) {
7990
+
7756
7991
  if (!val.quote) {
7757
- rootpath = rootpath.replace(/[\(\)'"\s]/g, function(match) { return "\\"+match; });
7992
+ rootpath = rootpath.replace(/[\(\)'"\s]/g, function(match) { return "\\" + match; });
7758
7993
  }
7759
7994
  val.value = rootpath + val.value;
7760
7995
  }
@@ -7779,7 +8014,7 @@ URL.prototype.eval = function (context) {
7779
8014
  };
7780
8015
  module.exports = URL;
7781
8016
 
7782
- },{"./node":66}],77:[function(require,module,exports){
8017
+ },{"./node":67}],78:[function(require,module,exports){
7783
8018
  var Node = require("./node");
7784
8019
 
7785
8020
  var Value = function (value) {
@@ -7808,14 +8043,14 @@ Value.prototype.genCSS = function (context, output) {
7808
8043
  var i;
7809
8044
  for(i = 0; i < this.value.length; i++) {
7810
8045
  this.value[i].genCSS(context, output);
7811
- if (i+1 < this.value.length) {
8046
+ if (i + 1 < this.value.length) {
7812
8047
  output.add((context && context.compress) ? ',' : ', ');
7813
8048
  }
7814
8049
  }
7815
8050
  };
7816
8051
  module.exports = Value;
7817
8052
 
7818
- },{"./node":66}],78:[function(require,module,exports){
8053
+ },{"./node":67}],79:[function(require,module,exports){
7819
8054
  var Node = require("./node");
7820
8055
 
7821
8056
  var Variable = function (name, index, currentFileInfo) {
@@ -7845,7 +8080,7 @@ Variable.prototype.eval = function (context) {
7845
8080
  var v = frame.variable(name);
7846
8081
  if (v) {
7847
8082
  if (v.important) {
7848
- var importantScope = context.importantScope[context.importantScope.length-1];
8083
+ var importantScope = context.importantScope[context.importantScope.length - 1];
7849
8084
  importantScope.important = v.important;
7850
8085
  }
7851
8086
  return v.value.eval(context);
@@ -7870,7 +8105,7 @@ Variable.prototype.find = function (obj, fun) {
7870
8105
  };
7871
8106
  module.exports = Variable;
7872
8107
 
7873
- },{"./node":66}],79:[function(require,module,exports){
8108
+ },{"./node":67}],80:[function(require,module,exports){
7874
8109
  module.exports = {
7875
8110
  getLocation: function(index, inputStream) {
7876
8111
  var n = index + 1,
@@ -7892,9 +8127,10 @@ module.exports = {
7892
8127
  }
7893
8128
  };
7894
8129
 
7895
- },{}],80:[function(require,module,exports){
8130
+ },{}],81:[function(require,module,exports){
7896
8131
  var tree = require("../tree"),
7897
- Visitor = require("./visitor");
8132
+ Visitor = require("./visitor"),
8133
+ logger = require("../logger");
7898
8134
 
7899
8135
  /*jshint loopfunc:true */
7900
8136
 
@@ -7955,7 +8191,7 @@ ExtendFinderVisitor.prototype = {
7955
8191
  extend.findSelfSelectors(selectorPath);
7956
8192
  extend.ruleset = rulesetNode;
7957
8193
  if (j === 0) { extend.firstExtendOnThisSelectorPath = true; }
7958
- this.allExtendsStack[this.allExtendsStack.length-1].push(extend);
8194
+ this.allExtendsStack[this.allExtendsStack.length - 1].push(extend);
7959
8195
  }
7960
8196
  }
7961
8197
 
@@ -7989,23 +8225,43 @@ var ProcessExtendsVisitor = function() {
7989
8225
  ProcessExtendsVisitor.prototype = {
7990
8226
  run: function(root) {
7991
8227
  var extendFinder = new ExtendFinderVisitor();
8228
+ this.extendIndicies = {};
7992
8229
  extendFinder.run(root);
7993
8230
  if (!extendFinder.foundExtends) { return root; }
7994
8231
  root.allExtends = root.allExtends.concat(this.doExtendChaining(root.allExtends, root.allExtends));
7995
8232
  this.allExtendsStack = [root.allExtends];
7996
- return this._visitor.visit(root);
8233
+ var newRoot = this._visitor.visit(root);
8234
+ this.checkExtendsForNonMatched(root.allExtends);
8235
+ return newRoot;
8236
+ },
8237
+ checkExtendsForNonMatched: function(extendList) {
8238
+ var indicies = this.extendIndicies;
8239
+ extendList.filter(function(extend) {
8240
+ return !extend.hasFoundMatches && extend.parent_ids.length == 1;
8241
+ }).forEach(function(extend) {
8242
+ var selector = "_unknown_";
8243
+ try {
8244
+ selector = extend.selector.toCSS({});
8245
+ }catch(_){}
8246
+
8247
+ if(!indicies[extend.index + ' ' + selector]) {
8248
+ indicies[extend.index + ' ' + selector] = true;
8249
+ logger.warn("extend '" + selector + "' has no matches");
8250
+ }
8251
+ });
7997
8252
  },
7998
8253
  doExtendChaining: function (extendsList, extendsListTarget, iterationCount) {
7999
8254
  //
8000
- // chaining is different from normal extension.. if we extend an extend then we are not just copying, altering and pasting
8001
- // the selector we would do normally, but we are also adding an extend with the same target selector
8255
+ // chaining is different from normal extension.. if we extend an extend then we are not just copying, altering
8256
+ // and pasting the selector we would do normally, but we are also adding an extend with the same target selector
8002
8257
  // this means this new extend can then go and alter other extends
8003
8258
  //
8004
8259
  // this method deals with all the chaining work - without it, extend is flat and doesn't work on other extend selectors
8005
- // this is also the most expensive.. and a match on one selector can cause an extension of a selector we had already processed if
8006
- // we look at each selector at a time, as is done in visitRuleset
8260
+ // this is also the most expensive.. and a match on one selector can cause an extension of a selector we had already
8261
+ // processed if we look at each selector at a time, as is done in visitRuleset
8007
8262
 
8008
- var extendIndex, targetExtendIndex, matches, extendsToAdd = [], newSelector, extendVisitor = this, selectorPath, extend, targetExtend, newExtend;
8263
+ var extendIndex, targetExtendIndex, matches, extendsToAdd = [], newSelector, extendVisitor = this, selectorPath,
8264
+ extend, targetExtend, newExtend;
8009
8265
 
8010
8266
  iterationCount = iterationCount || 0;
8011
8267
 
@@ -8030,6 +8286,8 @@ ProcessExtendsVisitor.prototype = {
8030
8286
 
8031
8287
  if (matches.length) {
8032
8288
 
8289
+ extend.hasFoundMatches = true;
8290
+
8033
8291
  // we found a match, so for each self selector..
8034
8292
  extend.selfSelectors.forEach(function(selfSelector) {
8035
8293
 
@@ -8041,7 +8299,7 @@ ProcessExtendsVisitor.prototype = {
8041
8299
  newExtend.selfSelectors = newSelector;
8042
8300
 
8043
8301
  // add the extend onto the list of extends for that selector
8044
- newSelector[newSelector.length-1].extendList = [newExtend];
8302
+ newSelector[newSelector.length - 1].extendList = [newExtend];
8045
8303
 
8046
8304
  // record that we need to add it.
8047
8305
  extendsToAdd.push(newExtend);
@@ -8075,11 +8333,13 @@ ProcessExtendsVisitor.prototype = {
8075
8333
  selectorTwo = extendsToAdd[0].selector.toCSS();
8076
8334
  }
8077
8335
  catch(e) {}
8078
- throw {message: "extend circular reference detected. One of the circular extends is currently:"+selectorOne+":extend(" + selectorTwo+")"};
8336
+ throw { message: "extend circular reference detected. One of the circular extends is currently:" +
8337
+ selectorOne + ":extend(" + selectorTwo + ")"};
8079
8338
  }
8080
8339
 
8081
- // now process the new extends on the existing rules so that we can handle a extending b extending c ectending d extending e...
8082
- return extendsToAdd.concat(extendVisitor.doExtendChaining(extendsToAdd, extendsListTarget, iterationCount+1));
8340
+ // now process the new extends on the existing rules so that we can handle a extending b extending c extending
8341
+ // d extending e...
8342
+ return extendsToAdd.concat(extendVisitor.doExtendChaining(extendsToAdd, extendsListTarget, iterationCount + 1));
8083
8343
  } else {
8084
8344
  return extendsToAdd;
8085
8345
  }
@@ -8097,7 +8357,8 @@ ProcessExtendsVisitor.prototype = {
8097
8357
  if (rulesetNode.root) {
8098
8358
  return;
8099
8359
  }
8100
- var matches, pathIndex, extendIndex, allExtends = this.allExtendsStack[this.allExtendsStack.length-1], selectorsToAdd = [], extendVisitor = this, selectorPath;
8360
+ var matches, pathIndex, extendIndex, allExtends = this.allExtendsStack[this.allExtendsStack.length - 1],
8361
+ selectorsToAdd = [], extendVisitor = this, selectorPath;
8101
8362
 
8102
8363
  // look at each selector path in the ruleset, find any extend matches and then copy, find and replace
8103
8364
 
@@ -8107,12 +8368,13 @@ ProcessExtendsVisitor.prototype = {
8107
8368
 
8108
8369
  // extending extends happens initially, before the main pass
8109
8370
  if (rulesetNode.extendOnEveryPath) { continue; }
8110
- var extendList = selectorPath[selectorPath.length-1].extendList;
8371
+ var extendList = selectorPath[selectorPath.length - 1].extendList;
8111
8372
  if (extendList && extendList.length) { continue; }
8112
8373
 
8113
8374
  matches = this.findMatch(allExtends[extendIndex], selectorPath);
8114
8375
 
8115
8376
  if (matches.length) {
8377
+ allExtends[extendIndex].hasFoundMatches = true;
8116
8378
 
8117
8379
  allExtends[extendIndex].selfSelectors.forEach(function(selfSelector) {
8118
8380
  selectorsToAdd.push(extendVisitor.extendSelector(matches, selectorPath, selfSelector));
@@ -8143,15 +8405,16 @@ ProcessExtendsVisitor.prototype = {
8143
8405
 
8144
8406
  // if we allow elements before our match we can add a potential match every time. otherwise only at the first element.
8145
8407
  if (extend.allowBefore || (haystackSelectorIndex === 0 && hackstackElementIndex === 0)) {
8146
- potentialMatches.push({pathIndex: haystackSelectorIndex, index: hackstackElementIndex, matched: 0, initialCombinator: haystackElement.combinator});
8408
+ potentialMatches.push({pathIndex: haystackSelectorIndex, index: hackstackElementIndex, matched: 0,
8409
+ initialCombinator: haystackElement.combinator});
8147
8410
  }
8148
8411
 
8149
8412
  for(i = 0; i < potentialMatches.length; i++) {
8150
8413
  potentialMatch = potentialMatches[i];
8151
8414
 
8152
8415
  // selectors add " " onto the first element. When we use & it joins the selectors together, but if we don't
8153
- // then each selector in haystackSelectorPath has a space before it added in the toCSS phase. so we need to work out
8154
- // what the resulting combinator will be
8416
+ // then each selector in haystackSelectorPath has a space before it added in the toCSS phase. so we need to
8417
+ // work out what the resulting combinator will be
8155
8418
  targetCombinator = haystackElement.combinator.value;
8156
8419
  if (targetCombinator === '' && hackstackElementIndex === 0) {
8157
8420
  targetCombinator = ' ';
@@ -8169,7 +8432,8 @@ ProcessExtendsVisitor.prototype = {
8169
8432
  if (potentialMatch) {
8170
8433
  potentialMatch.finished = potentialMatch.matched === needleElements.length;
8171
8434
  if (potentialMatch.finished &&
8172
- (!extend.allowAfter && (hackstackElementIndex+1 < hackstackSelector.elements.length || haystackSelectorIndex+1 < haystackSelectorPath.length))) {
8435
+ (!extend.allowAfter &&
8436
+ (hackstackElementIndex + 1 < hackstackSelector.elements.length || haystackSelectorIndex + 1 < haystackSelectorPath.length))) {
8173
8437
  potentialMatch = null;
8174
8438
  }
8175
8439
  }
@@ -8215,7 +8479,7 @@ ProcessExtendsVisitor.prototype = {
8215
8479
  if (!(elementValue2 instanceof tree.Selector) || elementValue1.elements.length !== elementValue2.elements.length) {
8216
8480
  return false;
8217
8481
  }
8218
- for(var i = 0; i <elementValue1.elements.length; i++) {
8482
+ for(var i = 0; i < elementValue1.elements.length; i++) {
8219
8483
  if (elementValue1.elements[i].combinator.value !== elementValue2.elements[i].combinator.value) {
8220
8484
  if (i !== 0 || (elementValue1.elements[i].combinator.value || ' ') !== (elementValue2.elements[i].combinator.value || ' ')) {
8221
8485
  return false;
@@ -8253,7 +8517,8 @@ ProcessExtendsVisitor.prototype = {
8253
8517
  );
8254
8518
 
8255
8519
  if (match.pathIndex > currentSelectorPathIndex && currentSelectorPathElementIndex > 0) {
8256
- path[path.length - 1].elements = path[path.length - 1].elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex));
8520
+ path[path.length - 1].elements = path[path.length - 1]
8521
+ .elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex));
8257
8522
  currentSelectorPathElementIndex = 0;
8258
8523
  currentSelectorPathIndex++;
8259
8524
  }
@@ -8282,7 +8547,8 @@ ProcessExtendsVisitor.prototype = {
8282
8547
  }
8283
8548
 
8284
8549
  if (currentSelectorPathIndex < selectorPath.length && currentSelectorPathElementIndex > 0) {
8285
- path[path.length - 1].elements = path[path.length - 1].elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex));
8550
+ path[path.length - 1].elements = path[path.length - 1]
8551
+ .elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex));
8286
8552
  currentSelectorPathIndex++;
8287
8553
  }
8288
8554
 
@@ -8293,30 +8559,35 @@ ProcessExtendsVisitor.prototype = {
8293
8559
  visitRulesetOut: function (rulesetNode) {
8294
8560
  },
8295
8561
  visitMedia: function (mediaNode, visitArgs) {
8296
- var newAllExtends = mediaNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]);
8562
+ var newAllExtends = mediaNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length - 1]);
8297
8563
  newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, mediaNode.allExtends));
8298
8564
  this.allExtendsStack.push(newAllExtends);
8299
8565
  },
8300
8566
  visitMediaOut: function (mediaNode) {
8301
- this.allExtendsStack.length = this.allExtendsStack.length - 1;
8567
+ var lastIndex = this.allExtendsStack.length - 1;
8568
+ this.checkExtendsForNonMatched(this.allExtendsStack[lastIndex]);
8569
+ this.allExtendsStack.length = lastIndex;
8302
8570
  },
8303
8571
  visitDirective: function (directiveNode, visitArgs) {
8304
- var newAllExtends = directiveNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]);
8572
+ var newAllExtends = directiveNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length - 1]);
8305
8573
  newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, directiveNode.allExtends));
8306
8574
  this.allExtendsStack.push(newAllExtends);
8307
8575
  },
8308
8576
  visitDirectiveOut: function (directiveNode) {
8309
- this.allExtendsStack.length = this.allExtendsStack.length - 1;
8577
+ var lastIndex = this.allExtendsStack.length - 1;
8578
+ this.checkExtendsForNonMatched(this.allExtendsStack[lastIndex]);
8579
+ this.allExtendsStack.length = lastIndex;
8310
8580
  }
8311
8581
  };
8312
8582
 
8313
8583
  module.exports = ProcessExtendsVisitor;
8314
8584
 
8315
- },{"../tree":58,"./visitor":86}],81:[function(require,module,exports){
8585
+ },{"../logger":31,"../tree":59,"./visitor":87}],82:[function(require,module,exports){
8316
8586
  function ImportSequencer(onSequencerEmpty) {
8317
8587
  this.imports = [];
8318
8588
  this.variableImports = [];
8319
8589
  this._onSequencerEmpty = onSequencerEmpty;
8590
+ this._currentDepth = 0;
8320
8591
  }
8321
8592
 
8322
8593
  ImportSequencer.prototype.addImport = function(callback) {
@@ -8339,30 +8610,35 @@ ImportSequencer.prototype.addVariableImport = function(callback) {
8339
8610
  };
8340
8611
 
8341
8612
  ImportSequencer.prototype.tryRun = function() {
8342
- while(true) {
8343
- while(this.imports.length > 0) {
8344
- var importItem = this.imports[0];
8345
- if (!importItem.isReady) {
8346
- return;
8613
+ this._currentDepth++;
8614
+ try {
8615
+ while(true) {
8616
+ while(this.imports.length > 0) {
8617
+ var importItem = this.imports[0];
8618
+ if (!importItem.isReady) {
8619
+ return;
8620
+ }
8621
+ this.imports = this.imports.slice(1);
8622
+ importItem.callback.apply(null, importItem.args);
8347
8623
  }
8348
- this.imports = this.imports.slice(1);
8349
- importItem.callback.apply(null, importItem.args);
8350
- }
8351
- if (this.variableImports.length === 0) {
8352
- break;
8624
+ if (this.variableImports.length === 0) {
8625
+ break;
8626
+ }
8627
+ var variableImport = this.variableImports[0];
8628
+ this.variableImports = this.variableImports.slice(1);
8629
+ variableImport();
8353
8630
  }
8354
- var variableImport = this.variableImports[0];
8355
- this.variableImports = this.variableImports.slice(1);
8356
- variableImport();
8631
+ } finally {
8632
+ this._currentDepth--;
8357
8633
  }
8358
- if (this._onSequencerEmpty) {
8634
+ if (this._currentDepth === 0 && this._onSequencerEmpty) {
8359
8635
  this._onSequencerEmpty();
8360
8636
  }
8361
8637
  };
8362
8638
 
8363
8639
  module.exports = ImportSequencer;
8364
8640
 
8365
- },{}],82:[function(require,module,exports){
8641
+ },{}],83:[function(require,module,exports){
8366
8642
  var contexts = require("../contexts"),
8367
8643
  Visitor = require("./visitor"),
8368
8644
  ImportSequencer = require("./import-sequencer");
@@ -8376,26 +8652,28 @@ var ImportVisitor = function(importer, finish) {
8376
8652
  this.importCount = 0;
8377
8653
  this.onceFileDetectionMap = {};
8378
8654
  this.recursionDetector = {};
8379
- this._sequencer = new ImportSequencer();
8655
+ this._sequencer = new ImportSequencer(this._onSequencerEmpty.bind(this));
8380
8656
  };
8381
8657
 
8382
8658
  ImportVisitor.prototype = {
8383
8659
  isReplacing: false,
8384
8660
  run: function (root) {
8385
- var error;
8386
8661
  try {
8387
8662
  // process the contents
8388
8663
  this._visitor.visit(root);
8389
8664
  }
8390
8665
  catch(e) {
8391
- error = e;
8666
+ this.error = e;
8392
8667
  }
8393
8668
 
8394
8669
  this.isFinished = true;
8395
8670
  this._sequencer.tryRun();
8396
- if (this.importCount === 0) {
8397
- this._finish(error || this.error);
8671
+ },
8672
+ _onSequencerEmpty: function() {
8673
+ if (!this.isFinished) {
8674
+ return;
8398
8675
  }
8676
+ this._finish(this.error);
8399
8677
  },
8400
8678
  visitImport: function (importNode, visitArgs) {
8401
8679
  var inlineCSS = importNode.options.inline;
@@ -8447,9 +8725,13 @@ ImportVisitor.prototype = {
8447
8725
  var onImported = this.onImported.bind(this, evaldImportNode, context),
8448
8726
  sequencedOnImported = this._sequencer.addImport(onImported);
8449
8727
 
8450
- this._importer.push(evaldImportNode.getPath(), tryAppendLessExtension, evaldImportNode.currentFileInfo, evaldImportNode.options, sequencedOnImported);
8728
+ this._importer.push(evaldImportNode.getPath(), tryAppendLessExtension, evaldImportNode.currentFileInfo,
8729
+ evaldImportNode.options, sequencedOnImported);
8451
8730
  } else {
8452
8731
  this.importCount--;
8732
+ if (this.isFinished) {
8733
+ this._sequencer.tryRun();
8734
+ }
8453
8735
  }
8454
8736
  },
8455
8737
  onImported: function (importNode, context, e, root, importedAtRoot, fullPath) {
@@ -8499,10 +8781,7 @@ ImportVisitor.prototype = {
8499
8781
  importVisitor.importCount--;
8500
8782
 
8501
8783
  if (importVisitor.isFinished) {
8502
- this._sequencer.tryRun();
8503
- if (importVisitor.importCount === 0) {
8504
- importVisitor._finish(importVisitor.error);
8505
- }
8784
+ importVisitor._sequencer.tryRun();
8506
8785
  }
8507
8786
  },
8508
8787
  visitRule: function (ruleNode, visitArgs) {
@@ -8535,7 +8814,7 @@ ImportVisitor.prototype = {
8535
8814
  };
8536
8815
  module.exports = ImportVisitor;
8537
8816
 
8538
- },{"../contexts":10,"./import-sequencer":81,"./visitor":86}],83:[function(require,module,exports){
8817
+ },{"../contexts":10,"./import-sequencer":82,"./visitor":87}],84:[function(require,module,exports){
8539
8818
  var visitors = {
8540
8819
  Visitor: require("./visitor"),
8541
8820
  ImportVisitor: require('./import-visitor'),
@@ -8546,7 +8825,7 @@ var visitors = {
8546
8825
 
8547
8826
  module.exports = visitors;
8548
8827
 
8549
- },{"./extend-visitor":80,"./import-visitor":82,"./join-selector-visitor":84,"./to-css-visitor":85,"./visitor":86}],84:[function(require,module,exports){
8828
+ },{"./extend-visitor":81,"./import-visitor":83,"./join-selector-visitor":85,"./to-css-visitor":86,"./visitor":87}],85:[function(require,module,exports){
8550
8829
  var Visitor = require("./visitor");
8551
8830
 
8552
8831
  var JoinSelectorVisitor = function() {
@@ -8593,7 +8872,7 @@ JoinSelectorVisitor.prototype = {
8593
8872
 
8594
8873
  module.exports = JoinSelectorVisitor;
8595
8874
 
8596
- },{"./visitor":86}],85:[function(require,module,exports){
8875
+ },{"./visitor":87}],86:[function(require,module,exports){
8597
8876
  var tree = require("../tree"),
8598
8877
  Visitor = require("./visitor");
8599
8878
 
@@ -8642,16 +8921,16 @@ ToCSSVisitor.prototype = {
8642
8921
  },
8643
8922
 
8644
8923
  visitDirective: function(directiveNode, visitArgs) {
8645
- if (directiveNode.currentFileInfo.reference && !directiveNode.isReferenced) {
8646
- return;
8647
- }
8648
8924
  if (directiveNode.name === "@charset") {
8925
+ if (!directiveNode.getIsReferenced()) {
8926
+ return;
8927
+ }
8649
8928
  // Only output the debug info together with subsequent @charset definitions
8650
8929
  // a comment (or @media statement) before the actual @charset directive would
8651
8930
  // be considered illegal css as it has to be on the first line
8652
8931
  if (this.charset) {
8653
8932
  if (directiveNode.debugInfo) {
8654
- var comment = new tree.Comment("/* " + directiveNode.toCSS(this._context).replace(/\n/g, "")+" */\n");
8933
+ var comment = new tree.Comment("/* " + directiveNode.toCSS(this._context).replace(/\n/g, "") + " */\n");
8655
8934
  comment.debugInfo = directiveNode.debugInfo;
8656
8935
  return this._visitor.visit(comment);
8657
8936
  }
@@ -8661,6 +8940,38 @@ ToCSSVisitor.prototype = {
8661
8940
  }
8662
8941
  if (directiveNode.rules && directiveNode.rules.rules) {
8663
8942
  this._mergeRules(directiveNode.rules.rules);
8943
+ //process childs
8944
+ directiveNode.accept(this._visitor);
8945
+ visitArgs.visitDeeper = false;
8946
+
8947
+ // the directive was directly referenced and therefore needs to be shown in the output
8948
+ if (directiveNode.getIsReferenced()) {
8949
+ return directiveNode;
8950
+ }
8951
+
8952
+ if (!directiveNode.rules.rules) {
8953
+ return ;
8954
+ }
8955
+
8956
+ //the directive was not directly referenced
8957
+ for (var r = 0; r < directiveNode.rules.rules.length; r++) {
8958
+ var rule = directiveNode.rules.rules[r];
8959
+ if (rule.getIsReferenced && rule.getIsReferenced()) {
8960
+ //the directive contains something that was referenced (likely by extend)
8961
+ //therefore it needs to be shown in output too
8962
+
8963
+ //marking as referenced in case the directive is stored inside another directive
8964
+ directiveNode.markReferenced();
8965
+ return directiveNode;
8966
+ }
8967
+ }
8968
+ //The directive was not directly referenced and does not contain anything that
8969
+ //was referenced. Therefore it must not be shown in output.
8970
+ return ;
8971
+ } else {
8972
+ if (!directiveNode.getIsReferenced()) {
8973
+ return;
8974
+ }
8664
8975
  }
8665
8976
  return directiveNode;
8666
8977
  },
@@ -8821,7 +9132,7 @@ ToCSSVisitor.prototype = {
8821
9132
  var spacedGroups = [];
8822
9133
  var lastSpacedGroup = [];
8823
9134
  parts.map(function (p) {
8824
- if (p.merge==="+") {
9135
+ if (p.merge === "+") {
8825
9136
  if (lastSpacedGroup.length > 0) {
8826
9137
  spacedGroups.push(toExpression(lastSpacedGroup));
8827
9138
  }
@@ -8838,7 +9149,7 @@ ToCSSVisitor.prototype = {
8838
9149
 
8839
9150
  module.exports = ToCSSVisitor;
8840
9151
 
8841
- },{"../tree":58,"./visitor":86}],86:[function(require,module,exports){
9152
+ },{"../tree":59,"./visitor":87}],87:[function(require,module,exports){
8842
9153
  var tree = require("../tree");
8843
9154
 
8844
9155
  var _visitArgs = { visitDeeper: true },
@@ -8992,7 +9303,7 @@ Visitor.prototype = {
8992
9303
  };
8993
9304
  module.exports = Visitor;
8994
9305
 
8995
- },{"../tree":58}],87:[function(require,module,exports){
9306
+ },{"../tree":59}],88:[function(require,module,exports){
8996
9307
  // shim for using process in browser
8997
9308
 
8998
9309
  var process = module.exports = {};
@@ -9080,7 +9391,7 @@ process.chdir = function (dir) {
9080
9391
  throw new Error('process.chdir is not supported');
9081
9392
  };
9082
9393
 
9083
- },{}],88:[function(require,module,exports){
9394
+ },{}],89:[function(require,module,exports){
9084
9395
  'use strict';
9085
9396
 
9086
9397
  var asap = require('asap')
@@ -9187,7 +9498,7 @@ function doResolve(fn, onFulfilled, onRejected) {
9187
9498
  }
9188
9499
  }
9189
9500
 
9190
- },{"asap":90}],89:[function(require,module,exports){
9501
+ },{"asap":91}],90:[function(require,module,exports){
9191
9502
  'use strict';
9192
9503
 
9193
9504
  //This file contains the ES6 extensions to the core Promises/A+ API
@@ -9297,7 +9608,7 @@ Promise.prototype['catch'] = function (onRejected) {
9297
9608
  return this.then(null, onRejected);
9298
9609
  }
9299
9610
 
9300
- },{"./core.js":88,"asap":90}],90:[function(require,module,exports){
9611
+ },{"./core.js":89,"asap":91}],91:[function(require,module,exports){
9301
9612
  (function (process){
9302
9613
 
9303
9614
  // Use the fastest possible means to execute a task in a future turn
@@ -9414,7 +9725,7 @@ module.exports = asap;
9414
9725
 
9415
9726
 
9416
9727
  }).call(this,require('_process'))
9417
- },{"_process":87}],91:[function(require,module,exports){
9728
+ },{"_process":88}],92:[function(require,module,exports){
9418
9729
  // should work in any browser without browserify
9419
9730
 
9420
9731
  if (typeof Promise.prototype.done !== 'function') {
@@ -9439,5 +9750,5 @@ if (typeof Promise === 'undefined') {
9439
9750
 
9440
9751
  require('./polyfill-done.js');
9441
9752
 
9442
- },{"./lib/core.js":88,"./lib/es6-extensions.js":89,"./polyfill-done.js":91,"asap":90}]},{},[2])(2)
9753
+ },{"./lib/core.js":89,"./lib/es6-extensions.js":90,"./polyfill-done.js":92,"asap":91}]},{},[2])(2)
9443
9754
  });