less 2.2.2 → 2.6.0

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 (441) hide show
  1. checksums.yaml +7 -0
  2. data/Changelog.md +17 -0
  3. data/Gemfile +7 -3
  4. data/README.md +29 -13
  5. data/bin/lessc +3 -1
  6. data/less.gemspec +2 -6
  7. data/lib/less/defaults.rb +3 -3
  8. data/lib/less/java_script/rhino_context.rb +17 -27
  9. data/lib/less/java_script/v8_context.rb +11 -11
  10. data/lib/less/js/.gitattributes +10 -0
  11. data/lib/less/js/.gitignore +24 -0
  12. data/lib/less/js/.jshintrc +11 -0
  13. data/lib/less/js/.npmignore +1 -0
  14. data/lib/less/js/.travis.yml +8 -0
  15. data/lib/less/js/CHANGELOG.md +299 -0
  16. data/lib/less/js/CONTRIBUTING.md +50 -0
  17. data/lib/less/js/Gruntfile.js +298 -0
  18. data/lib/less/js/README.md +43 -12
  19. data/lib/less/js/benchmark/benchmark.less +194 -194
  20. data/lib/less/js/benchmark/less-benchmark.js +9 -10
  21. data/lib/less/js/bin/lessc +310 -37
  22. data/lib/less/js/bower.json +18 -0
  23. data/lib/less/js/build/README.md +51 -0
  24. data/lib/less/js/build/amd.js +1 -1
  25. data/lib/less/js/build/browser-header.js +4 -0
  26. data/lib/less/js/build/build.yml +162 -0
  27. data/lib/less/js/build/require-rhino.js +7 -2
  28. data/lib/less/js/build/rhino-header.js +4 -0
  29. data/lib/less/js/build/rhino-modules.js +131 -0
  30. data/lib/less/js/build/tasks/.gitkeep +1 -0
  31. data/lib/less/js/build.gradle +347 -0
  32. data/lib/less/js/dist/less-1.3.1.js +4011 -0
  33. data/lib/less/js/dist/less-1.3.1.min.js +9 -0
  34. data/lib/less/js/dist/less-1.3.2.js +4401 -0
  35. data/lib/less/js/dist/less-1.3.2.min.js +9 -0
  36. data/lib/less/js/dist/less-1.3.3.js +4413 -0
  37. data/lib/less/js/dist/less-1.3.3.min.js +9 -0
  38. data/lib/less/js/dist/less-1.4.0-beta.js +5830 -0
  39. data/lib/less/js/dist/less-1.4.0-beta.min.js +11 -0
  40. data/lib/less/js/dist/less-1.4.0.js +5830 -0
  41. data/lib/less/js/dist/less-1.4.0.min.js +11 -0
  42. data/lib/less/js/dist/less-1.4.1.js +5837 -0
  43. data/lib/less/js/dist/less-1.4.1.min.js +11 -0
  44. data/lib/less/js/dist/less-1.4.2.js +5837 -0
  45. data/lib/less/js/dist/less-1.4.2.min.js +11 -0
  46. data/lib/less/js/dist/less-1.5.0.js +6914 -0
  47. data/lib/less/js/dist/less-1.5.0.min.js +13 -0
  48. data/lib/less/js/dist/less-1.5.1.js +6941 -0
  49. data/lib/less/js/dist/less-1.5.1.min.js +13 -0
  50. data/lib/less/js/dist/less-1.6.0.js +7485 -0
  51. data/lib/less/js/dist/less-1.6.0.min.js +16 -0
  52. data/lib/less/js/dist/less-1.6.1.js +7513 -0
  53. data/lib/less/js/dist/less-1.6.1.min.js +16 -0
  54. data/lib/less/js/dist/less-1.6.2.js +7624 -0
  55. data/lib/less/js/dist/less-1.6.2.min.js +16 -0
  56. data/lib/less/js/dist/less-1.6.3.js +7627 -0
  57. data/lib/less/js/dist/less-1.6.3.min.js +16 -0
  58. data/lib/less/js/dist/less-1.7.0.js +7921 -0
  59. data/lib/less/js/dist/less-1.7.0.min.js +16 -0
  60. data/lib/less/js/dist/less-rhino-1.3.1.js +3725 -0
  61. data/lib/less/js/dist/less-rhino-1.3.2.js +3990 -0
  62. data/lib/less/js/dist/less-rhino-1.3.3.js +4002 -0
  63. data/lib/less/js/dist/less-rhino-1.4.0.js +4273 -0
  64. data/lib/less/js/dist/less-rhino-1.5.1.js +6831 -0
  65. data/lib/less/js/dist/less-rhino-1.6.2.js +9017 -0
  66. data/lib/less/js/dist/less-rhino-1.6.3.js +9020 -0
  67. data/lib/less/js/dist/less-rhino-1.7.0.js +9301 -0
  68. data/lib/less/js/dist/lessc-rhino-1.6.2.js +449 -0
  69. data/lib/less/js/dist/lessc-rhino-1.6.3.js +449 -0
  70. data/lib/less/js/dist/lessc-rhino-1.7.0.js +449 -0
  71. data/lib/less/js/gradle/wrapper/gradle-wrapper.jar +0 -0
  72. data/lib/less/js/gradle/wrapper/gradle-wrapper.properties +6 -0
  73. data/lib/less/js/gradlew +164 -0
  74. data/lib/less/js/gradlew.bat +90 -0
  75. data/lib/less/js/lib/less/browser.js +547 -250
  76. data/lib/less/js/lib/less/encoder.js +4 -0
  77. data/lib/less/js/lib/less/env.js +136 -0
  78. data/lib/less/js/lib/less/extend-visitor.js +416 -0
  79. data/lib/less/js/lib/less/functions.js +576 -36
  80. data/lib/less/js/lib/less/import-visitor.js +142 -0
  81. data/lib/less/js/lib/less/index.js +187 -83
  82. data/lib/less/js/lib/less/join-selector-visitor.js +44 -0
  83. data/lib/less/js/lib/less/lessc_helper.js +82 -0
  84. data/lib/less/js/lib/less/parser.js +1286 -523
  85. data/lib/less/js/lib/less/rhino.js +415 -29
  86. data/lib/less/js/lib/less/source-map-output.js +141 -0
  87. data/lib/less/js/lib/less/to-css-visitor.js +240 -0
  88. data/lib/less/js/lib/less/tree/alpha.js +17 -5
  89. data/lib/less/js/lib/less/tree/anonymous.js +25 -4
  90. data/lib/less/js/lib/less/tree/assignment.js +17 -5
  91. data/lib/less/js/lib/less/tree/call.js +36 -13
  92. data/lib/less/js/lib/less/tree/color.js +119 -31
  93. data/lib/less/js/lib/less/tree/comment.js +18 -4
  94. data/lib/less/js/lib/less/tree/condition.js +35 -28
  95. data/lib/less/js/lib/less/tree/detached-ruleset.js +20 -0
  96. data/lib/less/js/lib/less/tree/dimension.js +291 -16
  97. data/lib/less/js/lib/less/tree/directive.js +56 -22
  98. data/lib/less/js/lib/less/tree/element.js +78 -17
  99. data/lib/less/js/lib/less/tree/expression.js +39 -8
  100. data/lib/less/js/lib/less/tree/extend.js +53 -0
  101. data/lib/less/js/lib/less/tree/import.js +81 -36
  102. data/lib/less/js/lib/less/tree/javascript.js +17 -10
  103. data/lib/less/js/lib/less/tree/keyword.js +8 -3
  104. data/lib/less/js/lib/less/tree/media.js +70 -27
  105. data/lib/less/js/lib/less/tree/mixin.js +250 -70
  106. data/lib/less/js/lib/less/tree/negative.js +24 -0
  107. data/lib/less/js/lib/less/tree/operation.js +38 -13
  108. data/lib/less/js/lib/less/tree/paren.js +9 -2
  109. data/lib/less/js/lib/less/tree/quoted.js +29 -10
  110. data/lib/less/js/lib/less/tree/rule.js +77 -29
  111. data/lib/less/js/lib/less/tree/ruleset-call.js +16 -0
  112. data/lib/less/js/lib/less/tree/ruleset.js +445 -107
  113. data/lib/less/js/lib/less/tree/selector.js +117 -30
  114. data/lib/less/js/lib/less/tree/unicode-descriptor.js +15 -0
  115. data/lib/less/js/lib/less/tree/url.js +43 -15
  116. data/lib/less/js/lib/less/tree/value.js +16 -6
  117. data/lib/less/js/lib/less/tree/variable.js +26 -8
  118. data/lib/less/js/lib/less/tree.js +82 -2
  119. data/lib/less/js/lib/less/visitor.js +146 -0
  120. data/lib/less/js/lib/source-map/source-map-0.1.31.js +1933 -0
  121. data/lib/less/js/lib/source-map/source-map-footer.js +4 -0
  122. data/lib/less/js/lib/source-map/source-map-header.js +3 -0
  123. data/lib/less/js/package.json +86 -11
  124. data/lib/less/js/test/browser/common.js +201 -0
  125. data/lib/less/js/test/browser/css/global-vars/simple.css +3 -0
  126. data/lib/less/js/test/browser/css/modify-vars/simple.css +8 -0
  127. data/lib/less/js/test/browser/css/postProcessor/postProcessor.css +4 -0
  128. data/lib/less/js/test/browser/css/relative-urls/urls.css +35 -0
  129. data/lib/less/js/test/browser/css/rootpath/urls.css +35 -0
  130. data/lib/less/js/test/browser/css/rootpath-relative/urls.css +35 -0
  131. data/lib/less/js/test/browser/css/urls.css +53 -0
  132. data/lib/less/js/test/browser/es5.js +27 -0
  133. data/lib/less/js/test/browser/jasmine-html.js +681 -0
  134. data/lib/less/js/test/browser/jasmine.css +82 -0
  135. data/lib/less/js/test/browser/jasmine.js +2600 -0
  136. data/lib/less/js/test/browser/less/console-errors/test-error.less +3 -0
  137. data/lib/less/js/test/browser/less/console-errors/test-error.txt +2 -0
  138. data/lib/less/js/test/browser/less/global-vars/simple.less +3 -0
  139. data/lib/less/js/test/browser/less/imports/urls.less +4 -0
  140. data/lib/less/js/test/browser/less/imports/urls2.less +4 -0
  141. data/lib/less/js/test/browser/less/modify-vars/imports/simple2.less +4 -0
  142. data/lib/less/js/test/browser/less/modify-vars/simple.less +8 -0
  143. data/lib/less/js/test/browser/less/postProcessor/postProcessor.less +4 -0
  144. data/lib/less/js/test/browser/less/relative-urls/urls.less +33 -0
  145. data/lib/less/js/test/browser/less/rootpath/urls.less +33 -0
  146. data/lib/less/js/test/browser/less/rootpath-relative/urls.less +33 -0
  147. data/lib/less/js/test/browser/less/urls.less +57 -0
  148. data/lib/less/js/test/browser/phantom-runner.js +150 -0
  149. data/lib/less/js/test/browser/runner-browser-options.js +42 -0
  150. data/lib/less/js/test/browser/runner-browser-spec.js +12 -0
  151. data/lib/less/js/test/browser/runner-console-errors.js +5 -0
  152. data/lib/less/js/test/browser/runner-errors-options.js +5 -0
  153. data/lib/less/js/test/browser/runner-errors-spec.js +4 -0
  154. data/lib/less/js/test/browser/runner-global-vars-options.js +4 -0
  155. data/lib/less/js/test/browser/runner-global-vars-spec.js +3 -0
  156. data/lib/less/js/test/browser/runner-legacy-options.js +4 -0
  157. data/lib/less/js/test/browser/runner-legacy-spec.js +3 -0
  158. data/lib/less/js/test/browser/runner-main-options.js +15 -0
  159. data/lib/less/js/test/browser/runner-main-spec.js +3 -0
  160. data/lib/less/js/test/browser/runner-modify-vars-options.js +2 -0
  161. data/lib/less/js/test/browser/runner-modify-vars-spec.js +43 -0
  162. data/lib/less/js/test/browser/runner-no-js-errors-options.js +4 -0
  163. data/lib/less/js/test/browser/runner-no-js-errors-spec.js +4 -0
  164. data/lib/less/js/test/browser/runner-postProcessor-options.js +4 -0
  165. data/lib/less/js/test/browser/runner-postProcessor.js +3 -0
  166. data/lib/less/js/test/browser/runner-production-options.js +3 -0
  167. data/lib/less/js/test/browser/runner-production-spec.js +5 -0
  168. data/lib/less/js/test/browser/runner-relative-urls-options.js +3 -0
  169. data/lib/less/js/test/browser/runner-relative-urls-spec.js +3 -0
  170. data/lib/less/js/test/browser/runner-rootpath-options.js +3 -0
  171. data/lib/less/js/test/browser/runner-rootpath-relative-options.js +4 -0
  172. data/lib/less/js/test/browser/runner-rootpath-relative-spec.js +3 -0
  173. data/lib/less/js/test/browser/runner-rootpath-spec.js +3 -0
  174. data/lib/less/js/test/browser/test-runner-template.tmpl +47 -0
  175. data/lib/less/js/test/css/charsets.css +1 -0
  176. data/lib/less/js/test/css/colors.css +29 -0
  177. data/lib/less/js/test/css/comments.css +15 -2
  178. data/lib/less/js/test/css/compression/compression.css +3 -0
  179. data/lib/less/js/test/css/css-3.css +73 -2
  180. data/lib/less/js/test/css/css-escapes.css +4 -0
  181. data/lib/less/js/test/css/css-guards.css +37 -0
  182. data/lib/less/js/test/css/css.css +20 -14
  183. data/lib/less/js/test/css/debug/linenumbers-all.css +49 -0
  184. data/lib/less/js/test/css/debug/linenumbers-comments.css +40 -0
  185. data/lib/less/js/test/css/debug/linenumbers-mediaquery.css +40 -0
  186. data/lib/less/js/test/css/detached-rulesets.css +71 -0
  187. data/lib/less/js/test/css/empty.css +0 -0
  188. data/lib/less/js/test/css/extend-chaining.css +81 -0
  189. data/lib/less/js/test/css/extend-clearfix.css +19 -0
  190. data/lib/less/js/test/css/extend-exact.css +37 -0
  191. data/lib/less/js/test/css/extend-media.css +24 -0
  192. data/lib/less/js/test/css/extend-nest.css +57 -0
  193. data/lib/less/js/test/css/extend-selector.css +80 -0
  194. data/lib/less/js/test/css/extend.css +76 -0
  195. data/lib/less/js/test/css/extract-and-length.css +133 -0
  196. data/lib/less/js/test/css/functions.css +117 -2
  197. data/lib/less/js/test/css/globalVars/extended.css +12 -0
  198. data/lib/less/js/test/css/globalVars/simple.css +6 -0
  199. data/lib/less/js/test/css/ie-filters.css +7 -3
  200. data/lib/less/js/test/css/import-inline.css +5 -0
  201. data/lib/less/js/test/css/import-interpolation.css +6 -0
  202. data/lib/less/js/test/css/import-once.css +15 -0
  203. data/lib/less/js/test/css/import-reference.css +68 -0
  204. data/lib/less/js/test/css/import.css +23 -10
  205. data/lib/less/js/test/css/javascript.css +3 -2
  206. data/lib/less/js/test/css/legacy/legacy.css +7 -0
  207. data/lib/less/js/test/css/media.css +141 -1
  208. data/lib/less/js/test/css/merge.css +34 -0
  209. data/lib/less/js/test/css/mixins-args.css +41 -4
  210. data/lib/less/js/test/css/mixins-guards-default-func.css +129 -0
  211. data/lib/less/js/test/css/mixins-guards.css +24 -0
  212. data/lib/less/js/test/css/mixins-important.css +28 -0
  213. data/lib/less/js/test/css/mixins-interpolated.css +39 -0
  214. data/lib/less/js/test/css/mixins-named-args.css +27 -0
  215. data/lib/less/js/test/css/mixins-pattern.css +4 -0
  216. data/lib/less/js/test/css/mixins.css +70 -0
  217. data/lib/less/js/test/css/modifyVars/extended.css +9 -0
  218. data/lib/less/js/test/css/no-output.css +0 -0
  219. data/lib/less/js/test/css/parens.css +21 -5
  220. data/lib/less/js/test/css/property-name-interp.css +20 -0
  221. data/lib/less/js/test/css/scope.css +23 -0
  222. data/lib/less/js/test/css/selectors.css +84 -0
  223. data/lib/less/js/test/css/static-urls/urls.css +45 -0
  224. data/lib/less/js/test/css/strings.css +5 -2
  225. data/lib/less/js/test/css/url-args/urls.css +56 -0
  226. data/lib/less/js/test/css/urls.css +71 -0
  227. data/lib/less/js/test/css/variables-in-at-rules.css +18 -0
  228. data/lib/less/js/test/css/variables.css +22 -4
  229. data/lib/less/js/test/css/whitespace.css +4 -0
  230. data/lib/less/js/test/data/data-uri-fail.png +0 -0
  231. data/lib/less/js/test/data/image.jpg +1 -0
  232. data/lib/less/js/test/data/page.html +1 -0
  233. data/lib/less/js/test/index.js +45 -0
  234. data/lib/less/js/test/less/charsets.less +3 -0
  235. data/lib/less/js/test/less/colors.less +37 -4
  236. data/lib/less/js/test/less/comments.less +21 -3
  237. data/lib/less/js/test/less/compression/compression.less +36 -0
  238. data/lib/less/js/test/less/css-3.less +70 -6
  239. data/lib/less/js/test/less/css-escapes.less +6 -1
  240. data/lib/less/js/test/less/css-guards.less +102 -0
  241. data/lib/less/js/test/less/css.less +23 -15
  242. data/lib/less/js/test/less/debug/import/test.less +25 -0
  243. data/lib/less/js/test/less/debug/linenumbers.less +33 -0
  244. data/lib/less/js/test/less/detached-rulesets.less +103 -0
  245. data/lib/less/js/test/less/empty.less +0 -0
  246. data/lib/less/js/test/less/errors/add-mixed-units.less +3 -0
  247. data/lib/less/js/test/less/errors/add-mixed-units.txt +4 -0
  248. data/lib/less/js/test/less/errors/add-mixed-units2.less +3 -0
  249. data/lib/less/js/test/less/errors/add-mixed-units2.txt +4 -0
  250. data/lib/less/js/test/less/errors/at-rules-undefined-var.less +4 -0
  251. data/lib/less/js/test/less/errors/at-rules-undefined-var.txt +4 -0
  252. data/lib/less/js/test/less/errors/bad-variable-declaration1.less +1 -0
  253. data/lib/less/js/test/less/errors/bad-variable-declaration1.txt +2 -0
  254. data/lib/less/js/test/less/errors/color-func-invalid-color.less +3 -0
  255. data/lib/less/js/test/less/errors/color-func-invalid-color.txt +4 -0
  256. data/lib/less/js/test/less/errors/comment-in-selector.less +1 -0
  257. data/lib/less/js/test/less/errors/comment-in-selector.txt +2 -0
  258. data/lib/less/js/test/less/errors/css-guard-default-func.less +4 -0
  259. data/lib/less/js/test/less/errors/css-guard-default-func.txt +4 -0
  260. data/lib/less/js/test/less/errors/detached-ruleset-1.less +6 -0
  261. data/lib/less/js/test/less/errors/detached-ruleset-1.txt +4 -0
  262. data/lib/less/js/test/less/errors/detached-ruleset-2.less +6 -0
  263. data/lib/less/js/test/less/errors/detached-ruleset-2.txt +4 -0
  264. data/lib/less/js/test/less/errors/detached-ruleset-3.less +4 -0
  265. data/lib/less/js/test/less/errors/detached-ruleset-3.txt +4 -0
  266. data/lib/less/js/test/less/errors/detached-ruleset-4.less +5 -0
  267. data/lib/less/js/test/less/errors/detached-ruleset-4.txt +3 -0
  268. data/lib/less/js/test/less/errors/detached-ruleset-5.less +4 -0
  269. data/lib/less/js/test/less/errors/detached-ruleset-5.txt +3 -0
  270. data/lib/less/js/test/less/errors/detached-ruleset-6.less +5 -0
  271. data/lib/less/js/test/less/errors/detached-ruleset-6.txt +4 -0
  272. data/lib/less/js/test/less/errors/divide-mixed-units.less +3 -0
  273. data/lib/less/js/test/less/errors/divide-mixed-units.txt +4 -0
  274. data/lib/less/js/test/less/errors/extend-no-selector.less +3 -0
  275. data/lib/less/js/test/less/errors/extend-no-selector.txt +3 -0
  276. data/lib/less/js/test/less/errors/extend-not-at-end.less +3 -0
  277. data/lib/less/js/test/less/errors/extend-not-at-end.txt +3 -0
  278. data/lib/less/js/test/less/errors/import-missing.less +6 -0
  279. data/lib/less/js/test/less/errors/import-missing.txt +3 -0
  280. data/lib/less/js/test/less/errors/import-no-semi.less +1 -0
  281. data/lib/less/js/test/less/errors/import-no-semi.txt +2 -0
  282. data/lib/less/js/test/less/errors/import-subfolder1.less +1 -0
  283. data/lib/less/js/test/less/errors/import-subfolder1.txt +3 -0
  284. data/lib/less/js/test/less/errors/import-subfolder2.less +1 -0
  285. data/lib/less/js/test/less/errors/import-subfolder2.txt +4 -0
  286. data/lib/less/js/test/less/errors/imports/import-subfolder1.less +1 -0
  287. data/lib/less/js/test/less/errors/imports/import-subfolder2.less +1 -0
  288. data/lib/less/js/test/less/errors/imports/import-test.less +4 -0
  289. data/lib/less/js/test/less/errors/imports/subfolder/mixin-not-defined.less +1 -0
  290. data/lib/less/js/test/less/errors/imports/subfolder/parse-error-curly-bracket.less +1 -0
  291. data/lib/less/js/test/less/errors/javascript-error.less +3 -0
  292. data/lib/less/js/test/less/errors/javascript-error.txt +4 -0
  293. data/lib/less/js/test/less/errors/javascript-undefined-var.less +3 -0
  294. data/lib/less/js/test/less/errors/javascript-undefined-var.txt +4 -0
  295. data/lib/less/js/test/less/errors/mixed-mixin-definition-args-1.less +6 -0
  296. data/lib/less/js/test/less/errors/mixed-mixin-definition-args-1.txt +4 -0
  297. data/lib/less/js/test/less/errors/mixed-mixin-definition-args-2.less +6 -0
  298. data/lib/less/js/test/less/errors/mixed-mixin-definition-args-2.txt +4 -0
  299. data/lib/less/js/test/less/errors/mixin-not-defined.less +11 -0
  300. data/lib/less/js/test/less/errors/mixin-not-defined.txt +3 -0
  301. data/lib/less/js/test/less/errors/mixin-not-matched.less +6 -0
  302. data/lib/less/js/test/less/errors/mixin-not-matched.txt +3 -0
  303. data/lib/less/js/test/less/errors/mixin-not-matched2.less +6 -0
  304. data/lib/less/js/test/less/errors/mixin-not-matched2.txt +3 -0
  305. data/lib/less/js/test/less/errors/mixin-not-visible-in-scope-1.less +9 -0
  306. data/lib/less/js/test/less/errors/mixin-not-visible-in-scope-1.txt +4 -0
  307. data/lib/less/js/test/less/errors/mixins-guards-default-func-1.less +9 -0
  308. data/lib/less/js/test/less/errors/mixins-guards-default-func-1.txt +4 -0
  309. data/lib/less/js/test/less/errors/mixins-guards-default-func-2.less +9 -0
  310. data/lib/less/js/test/less/errors/mixins-guards-default-func-2.txt +4 -0
  311. data/lib/less/js/test/less/errors/mixins-guards-default-func-3.less +9 -0
  312. data/lib/less/js/test/less/errors/mixins-guards-default-func-3.txt +4 -0
  313. data/lib/less/js/test/less/errors/multiple-guards-on-css-selectors.less +4 -0
  314. data/lib/less/js/test/less/errors/multiple-guards-on-css-selectors.txt +4 -0
  315. data/lib/less/js/test/less/errors/multiple-guards-on-css-selectors2.less +4 -0
  316. data/lib/less/js/test/less/errors/multiple-guards-on-css-selectors2.txt +4 -0
  317. data/lib/less/js/test/less/errors/multiply-mixed-units.less +7 -0
  318. data/lib/less/js/test/less/errors/multiply-mixed-units.txt +4 -0
  319. data/lib/less/js/test/less/errors/parens-error-1.less +3 -0
  320. data/lib/less/js/test/less/errors/parens-error-1.txt +4 -0
  321. data/lib/less/js/test/less/errors/parens-error-2.less +3 -0
  322. data/lib/less/js/test/less/errors/parens-error-2.txt +4 -0
  323. data/lib/less/js/test/less/errors/parens-error-3.less +3 -0
  324. data/lib/less/js/test/less/errors/parens-error-3.txt +4 -0
  325. data/lib/less/js/test/less/errors/parse-error-curly-bracket.less +4 -0
  326. data/lib/less/js/test/less/errors/parse-error-curly-bracket.txt +4 -0
  327. data/lib/less/js/test/less/errors/parse-error-extra-parens.less +5 -0
  328. data/lib/less/js/test/less/errors/parse-error-extra-parens.txt +3 -0
  329. data/lib/less/js/test/less/errors/parse-error-missing-bracket.less +2 -0
  330. data/lib/less/js/test/less/errors/parse-error-missing-bracket.txt +3 -0
  331. data/lib/less/js/test/less/errors/parse-error-missing-parens.less +5 -0
  332. data/lib/less/js/test/less/errors/parse-error-missing-parens.txt +3 -0
  333. data/lib/less/js/test/less/errors/parse-error-with-import.less +13 -0
  334. data/lib/less/js/test/less/errors/parse-error-with-import.txt +4 -0
  335. data/lib/less/js/test/less/errors/percentage-missing-space.less +3 -0
  336. data/lib/less/js/test/less/errors/percentage-missing-space.txt +4 -0
  337. data/lib/less/js/test/less/errors/property-asterisk-only-name.less +3 -0
  338. data/lib/less/js/test/less/errors/property-asterisk-only-name.txt +4 -0
  339. data/lib/less/js/test/less/errors/property-ie5-hack.less +3 -0
  340. data/lib/less/js/test/less/errors/property-ie5-hack.txt +4 -0
  341. data/lib/less/js/test/less/errors/property-in-root.less +4 -0
  342. data/lib/less/js/test/less/errors/property-in-root.txt +4 -0
  343. data/lib/less/js/test/less/errors/property-in-root2.less +1 -0
  344. data/lib/less/js/test/less/errors/property-in-root2.txt +4 -0
  345. data/lib/less/js/test/less/errors/property-in-root3.less +4 -0
  346. data/lib/less/js/test/less/errors/property-in-root3.txt +3 -0
  347. data/lib/less/js/test/less/errors/property-interp-not-defined.less +1 -0
  348. data/lib/less/js/test/less/errors/property-interp-not-defined.txt +2 -0
  349. data/lib/less/js/test/less/errors/recursive-variable.less +1 -0
  350. data/lib/less/js/test/less/errors/recursive-variable.txt +2 -0
  351. data/lib/less/js/test/less/errors/svg-gradient1.less +3 -0
  352. data/lib/less/js/test/less/errors/svg-gradient1.txt +4 -0
  353. data/lib/less/js/test/less/errors/svg-gradient2.less +3 -0
  354. data/lib/less/js/test/less/errors/svg-gradient2.txt +4 -0
  355. data/lib/less/js/test/less/errors/svg-gradient3.less +3 -0
  356. data/lib/less/js/test/less/errors/svg-gradient3.txt +4 -0
  357. data/lib/less/js/test/less/errors/unit-function.less +3 -0
  358. data/lib/less/js/test/less/errors/unit-function.txt +4 -0
  359. data/lib/less/js/test/less/extend-chaining.less +91 -0
  360. data/lib/less/js/test/less/extend-clearfix.less +19 -0
  361. data/lib/less/js/test/less/extend-exact.less +46 -0
  362. data/lib/less/js/test/less/extend-media.less +24 -0
  363. data/lib/less/js/test/less/extend-nest.less +65 -0
  364. data/lib/less/js/test/less/extend-selector.less +99 -0
  365. data/lib/less/js/test/less/extend.less +81 -0
  366. data/lib/less/js/test/less/extract-and-length.less +133 -0
  367. data/lib/less/js/test/less/functions.less +130 -6
  368. data/lib/less/js/test/less/globalVars/extended.json +5 -0
  369. data/lib/less/js/test/less/globalVars/extended.less +10 -0
  370. data/lib/less/js/test/less/globalVars/simple.json +3 -0
  371. data/lib/less/js/test/less/globalVars/simple.less +3 -0
  372. data/lib/less/js/test/less/ie-filters.less +7 -0
  373. data/lib/less/js/test/less/import/deeper/import-once-test-a.less +1 -0
  374. data/lib/less/js/test/less/import/import-and-relative-paths-test.less +17 -0
  375. data/lib/less/js/test/less/import/import-charset-test.less +1 -0
  376. data/lib/less/js/test/less/import/import-interpolation.less +1 -0
  377. data/lib/less/js/test/less/import/import-interpolation2.less +5 -0
  378. data/lib/less/js/test/less/import/import-once-test-c.less +6 -0
  379. data/lib/less/js/test/less/import/import-reference.less +51 -0
  380. data/lib/less/js/test/less/import/import-test-a.less +1 -0
  381. data/lib/less/js/test/less/import/import-test-c.less +0 -1
  382. data/lib/less/js/test/less/import/import-test-f.less +5 -0
  383. data/lib/less/js/test/less/import/imports/font.less +8 -0
  384. data/lib/less/js/test/less/import/imports/logo.less +5 -0
  385. data/lib/less/js/test/less/import/invalid-css.less +1 -0
  386. data/lib/less/js/test/less/import/urls.less +1 -0
  387. data/lib/less/js/test/less/import-inline.less +2 -0
  388. data/lib/less/js/test/less/import-interpolation.less +8 -0
  389. data/lib/less/js/test/less/import-once.less +6 -0
  390. data/lib/less/js/test/less/import-reference.less +21 -0
  391. data/lib/less/js/test/less/import.less +13 -3
  392. data/lib/less/js/test/less/javascript.less +5 -3
  393. data/lib/less/js/test/less/legacy/legacy.less +7 -0
  394. data/lib/less/js/test/less/media.less +158 -3
  395. data/lib/less/js/test/less/merge.less +78 -0
  396. data/lib/less/js/test/less/mixins-args.less +93 -15
  397. data/lib/less/js/test/less/mixins-guards-default-func.less +195 -0
  398. data/lib/less/js/test/less/mixins-guards.less +65 -0
  399. data/lib/less/js/test/less/mixins-important.less +8 -1
  400. data/lib/less/js/test/less/mixins-interpolated.less +69 -0
  401. data/lib/less/js/test/less/mixins-named-args.less +36 -0
  402. data/lib/less/js/test/less/mixins-nested.less +2 -2
  403. data/lib/less/js/test/less/mixins-pattern.less +4 -1
  404. data/lib/less/js/test/less/mixins.less +74 -0
  405. data/lib/less/js/test/less/modifyVars/extended.json +5 -0
  406. data/lib/less/js/test/less/modifyVars/extended.less +11 -0
  407. data/lib/less/js/test/less/no-js-errors/no-js-errors.less +3 -0
  408. data/lib/less/js/test/less/no-js-errors/no-js-errors.txt +4 -0
  409. data/lib/less/js/test/less/no-output.less +2 -0
  410. data/lib/less/js/test/less/operations.less +27 -27
  411. data/lib/less/js/test/less/parens.less +24 -5
  412. data/lib/less/js/test/less/property-name-interp.less +53 -0
  413. data/lib/less/js/test/less/scope.less +73 -1
  414. data/lib/less/js/test/less/selectors.less +101 -0
  415. data/lib/less/js/test/less/sourcemaps/basic.json +3 -0
  416. data/lib/less/js/test/less/sourcemaps/basic.less +27 -0
  417. data/lib/less/js/test/less/sourcemaps/imported.css +7 -0
  418. data/lib/less/js/test/less/static-urls/urls.less +33 -0
  419. data/lib/less/js/test/less/strings.less +7 -1
  420. data/lib/less/js/test/less/url-args/urls.less +63 -0
  421. data/lib/less/js/test/less/urls.less +72 -0
  422. data/lib/less/js/test/less/variables-in-at-rules.less +20 -0
  423. data/lib/less/js/test/less/variables.less +42 -13
  424. data/lib/less/js/test/less/whitespace.less +7 -0
  425. data/lib/less/js/test/less-test.js +251 -65
  426. data/lib/less/js/test/rhino/test-header.js +15 -0
  427. data/lib/less/js/test/sourcemaps/basic.json +1 -0
  428. data/lib/less/js/test/sourcemaps/index.html +17 -0
  429. data/lib/less/loader.rb +191 -27
  430. data/lib/less/parser.rb +47 -8
  431. data/lib/less/version.rb +2 -2
  432. data/spec/less/loader_spec.rb +45 -0
  433. data/spec/less/parser_spec.rb +43 -17
  434. data/spec/less/some/some.css +0 -0
  435. data/spec/less/some/some.less +4 -0
  436. metadata +352 -57
  437. data/lib/less/js/CHANGELOG +0 -41
  438. data/lib/less/js/Makefile +0 -75
  439. data/lib/less/js/build/ecma-5.js +0 -120
  440. data/lib/less/js/build/header.js +0 -7
  441. data/lib/less/js/lib/less/cssmin.js +0 -355
@@ -0,0 +1,4 @@
1
+ // base64 encoder implementation for node
2
+ exports.encodeBase64 = function(str) {
3
+ return new Buffer(str).toString('base64');
4
+ };
@@ -0,0 +1,136 @@
1
+ (function (tree) {
2
+
3
+ var parseCopyProperties = [
4
+ 'paths', // option - unmodified - paths to search for imports on
5
+ 'optimization', // option - optimization level (for the chunker)
6
+ 'files', // list of files that have been imported, used for import-once
7
+ 'contents', // map - filename to contents of all the files
8
+ 'contentsIgnoredChars', // map - filename to lines at the begining of each file to ignore
9
+ 'relativeUrls', // option - whether to adjust URL's to be relative
10
+ 'rootpath', // option - rootpath to append to URL's
11
+ 'strictImports', // option -
12
+ 'insecure', // option - whether to allow imports from insecure ssl hosts
13
+ 'dumpLineNumbers', // option - whether to dump line numbers
14
+ 'compress', // option - whether to compress
15
+ 'processImports', // option - whether to process imports. if false then imports will not be imported
16
+ 'syncImport', // option - whether to import synchronously
17
+ 'javascriptEnabled',// option - whether JavaScript is enabled. if undefined, defaults to true
18
+ 'mime', // browser only - mime type for sheet import
19
+ 'useFileCache', // browser only - whether to use the per file session cache
20
+ 'currentFileInfo' // information about the current file - for error reporting and importing and making urls relative etc.
21
+ ];
22
+
23
+ //currentFileInfo = {
24
+ // 'relativeUrls' - option - whether to adjust URL's to be relative
25
+ // 'filename' - full resolved filename of current file
26
+ // 'rootpath' - path to append to normal URLs for this node
27
+ // 'currentDirectory' - path to the current file, absolute
28
+ // 'rootFilename' - filename of the base file
29
+ // 'entryPath' - absolute path to the entry file
30
+ // 'reference' - whether the file should not be output and only output parts that are referenced
31
+
32
+ tree.parseEnv = function(options) {
33
+ copyFromOriginal(options, this, parseCopyProperties);
34
+
35
+ if (!this.contents) { this.contents = {}; }
36
+ if (!this.contentsIgnoredChars) { this.contentsIgnoredChars = {}; }
37
+ if (!this.files) { this.files = {}; }
38
+
39
+ if (!this.currentFileInfo) {
40
+ var filename = (options && options.filename) || "input";
41
+ var entryPath = filename.replace(/[^\/\\]*$/, "");
42
+ if (options) {
43
+ options.filename = null;
44
+ }
45
+ this.currentFileInfo = {
46
+ filename: filename,
47
+ relativeUrls: this.relativeUrls,
48
+ rootpath: (options && options.rootpath) || "",
49
+ currentDirectory: entryPath,
50
+ entryPath: entryPath,
51
+ rootFilename: filename
52
+ };
53
+ }
54
+ };
55
+
56
+ var evalCopyProperties = [
57
+ 'silent', // whether to swallow errors and warnings
58
+ 'verbose', // whether to log more activity
59
+ 'compress', // whether to compress
60
+ 'yuicompress', // whether to compress with the outside tool yui compressor
61
+ 'ieCompat', // whether to enforce IE compatibility (IE8 data-uri)
62
+ 'strictMath', // whether math has to be within parenthesis
63
+ 'strictUnits', // whether units need to evaluate correctly
64
+ 'cleancss', // whether to compress with clean-css
65
+ 'sourceMap', // whether to output a source map
66
+ 'importMultiple', // whether we are currently importing multiple copies
67
+ 'urlArgs' // whether to add args into url tokens
68
+ ];
69
+
70
+ tree.evalEnv = function(options, frames) {
71
+ copyFromOriginal(options, this, evalCopyProperties);
72
+
73
+ this.frames = frames || [];
74
+ };
75
+
76
+ tree.evalEnv.prototype.inParenthesis = function () {
77
+ if (!this.parensStack) {
78
+ this.parensStack = [];
79
+ }
80
+ this.parensStack.push(true);
81
+ };
82
+
83
+ tree.evalEnv.prototype.outOfParenthesis = function () {
84
+ this.parensStack.pop();
85
+ };
86
+
87
+ tree.evalEnv.prototype.isMathOn = function () {
88
+ return this.strictMath ? (this.parensStack && this.parensStack.length) : true;
89
+ };
90
+
91
+ tree.evalEnv.prototype.isPathRelative = function (path) {
92
+ return !/^(?:[a-z-]+:|\/)/.test(path);
93
+ };
94
+
95
+ tree.evalEnv.prototype.normalizePath = function( path ) {
96
+ var
97
+ segments = path.split("/").reverse(),
98
+ segment;
99
+
100
+ path = [];
101
+ while (segments.length !== 0 ) {
102
+ segment = segments.pop();
103
+ switch( segment ) {
104
+ case ".":
105
+ break;
106
+ case "..":
107
+ if ((path.length === 0) || (path[path.length - 1] === "..")) {
108
+ path.push( segment );
109
+ } else {
110
+ path.pop();
111
+ }
112
+ break;
113
+ default:
114
+ path.push( segment );
115
+ break;
116
+ }
117
+ }
118
+
119
+ return path.join("/");
120
+ };
121
+
122
+ //todo - do the same for the toCSS env
123
+ //tree.toCSSEnv = function (options) {
124
+ //};
125
+
126
+ var copyFromOriginal = function(original, destination, propertiesToCopy) {
127
+ if (!original) { return; }
128
+
129
+ for(var i = 0; i < propertiesToCopy.length; i++) {
130
+ if (original.hasOwnProperty(propertiesToCopy[i])) {
131
+ destination[propertiesToCopy[i]] = original[propertiesToCopy[i]];
132
+ }
133
+ }
134
+ };
135
+
136
+ })(require('./tree'));
@@ -0,0 +1,416 @@
1
+ (function (tree) {
2
+ /*jshint loopfunc:true */
3
+
4
+ tree.extendFinderVisitor = function() {
5
+ this._visitor = new tree.visitor(this);
6
+ this.contexts = [];
7
+ this.allExtendsStack = [[]];
8
+ };
9
+
10
+ tree.extendFinderVisitor.prototype = {
11
+ run: function (root) {
12
+ root = this._visitor.visit(root);
13
+ root.allExtends = this.allExtendsStack[0];
14
+ return root;
15
+ },
16
+ visitRule: function (ruleNode, visitArgs) {
17
+ visitArgs.visitDeeper = false;
18
+ },
19
+ visitMixinDefinition: function (mixinDefinitionNode, visitArgs) {
20
+ visitArgs.visitDeeper = false;
21
+ },
22
+ visitRuleset: function (rulesetNode, visitArgs) {
23
+ if (rulesetNode.root) {
24
+ return;
25
+ }
26
+
27
+ var i, j, extend, allSelectorsExtendList = [], extendList;
28
+
29
+ // get &:extend(.a); rules which apply to all selectors in this ruleset
30
+ var rules = rulesetNode.rules, ruleCnt = rules ? rules.length : 0;
31
+ for(i = 0; i < ruleCnt; i++) {
32
+ if (rulesetNode.rules[i] instanceof tree.Extend) {
33
+ allSelectorsExtendList.push(rules[i]);
34
+ rulesetNode.extendOnEveryPath = true;
35
+ }
36
+ }
37
+
38
+ // now find every selector and apply the extends that apply to all extends
39
+ // and the ones which apply to an individual extend
40
+ var paths = rulesetNode.paths;
41
+ for(i = 0; i < paths.length; i++) {
42
+ var selectorPath = paths[i],
43
+ selector = selectorPath[selectorPath.length - 1],
44
+ selExtendList = selector.extendList;
45
+
46
+ extendList = selExtendList ? selExtendList.slice(0).concat(allSelectorsExtendList)
47
+ : allSelectorsExtendList;
48
+
49
+ if (extendList) {
50
+ extendList = extendList.map(function(allSelectorsExtend) {
51
+ return allSelectorsExtend.clone();
52
+ });
53
+ }
54
+
55
+ for(j = 0; j < extendList.length; j++) {
56
+ this.foundExtends = true;
57
+ extend = extendList[j];
58
+ extend.findSelfSelectors(selectorPath);
59
+ extend.ruleset = rulesetNode;
60
+ if (j === 0) { extend.firstExtendOnThisSelectorPath = true; }
61
+ this.allExtendsStack[this.allExtendsStack.length-1].push(extend);
62
+ }
63
+ }
64
+
65
+ this.contexts.push(rulesetNode.selectors);
66
+ },
67
+ visitRulesetOut: function (rulesetNode) {
68
+ if (!rulesetNode.root) {
69
+ this.contexts.length = this.contexts.length - 1;
70
+ }
71
+ },
72
+ visitMedia: function (mediaNode, visitArgs) {
73
+ mediaNode.allExtends = [];
74
+ this.allExtendsStack.push(mediaNode.allExtends);
75
+ },
76
+ visitMediaOut: function (mediaNode) {
77
+ this.allExtendsStack.length = this.allExtendsStack.length - 1;
78
+ },
79
+ visitDirective: function (directiveNode, visitArgs) {
80
+ directiveNode.allExtends = [];
81
+ this.allExtendsStack.push(directiveNode.allExtends);
82
+ },
83
+ visitDirectiveOut: function (directiveNode) {
84
+ this.allExtendsStack.length = this.allExtendsStack.length - 1;
85
+ }
86
+ };
87
+
88
+ tree.processExtendsVisitor = function() {
89
+ this._visitor = new tree.visitor(this);
90
+ };
91
+
92
+ tree.processExtendsVisitor.prototype = {
93
+ run: function(root) {
94
+ var extendFinder = new tree.extendFinderVisitor();
95
+ extendFinder.run(root);
96
+ if (!extendFinder.foundExtends) { return root; }
97
+ root.allExtends = root.allExtends.concat(this.doExtendChaining(root.allExtends, root.allExtends));
98
+ this.allExtendsStack = [root.allExtends];
99
+ return this._visitor.visit(root);
100
+ },
101
+ doExtendChaining: function (extendsList, extendsListTarget, iterationCount) {
102
+ //
103
+ // chaining is different from normal extension.. if we extend an extend then we are not just copying, altering and pasting
104
+ // the selector we would do normally, but we are also adding an extend with the same target selector
105
+ // this means this new extend can then go and alter other extends
106
+ //
107
+ // this method deals with all the chaining work - without it, extend is flat and doesn't work on other extend selectors
108
+ // this is also the most expensive.. and a match on one selector can cause an extension of a selector we had already processed if
109
+ // we look at each selector at a time, as is done in visitRuleset
110
+
111
+ var extendIndex, targetExtendIndex, matches, extendsToAdd = [], newSelector, extendVisitor = this, selectorPath, extend, targetExtend, newExtend;
112
+
113
+ iterationCount = iterationCount || 0;
114
+
115
+ //loop through comparing every extend with every target extend.
116
+ // a target extend is the one on the ruleset we are looking at copy/edit/pasting in place
117
+ // e.g. .a:extend(.b) {} and .b:extend(.c) {} then the first extend extends the second one
118
+ // and the second is the target.
119
+ // the seperation into two lists allows us to process a subset of chains with a bigger set, as is the
120
+ // case when processing media queries
121
+ for(extendIndex = 0; extendIndex < extendsList.length; extendIndex++){
122
+ for(targetExtendIndex = 0; targetExtendIndex < extendsListTarget.length; targetExtendIndex++){
123
+
124
+ extend = extendsList[extendIndex];
125
+ targetExtend = extendsListTarget[targetExtendIndex];
126
+
127
+ // look for circular references
128
+ if( extend.parent_ids.indexOf( targetExtend.object_id ) >= 0 ){ continue; }
129
+
130
+ // find a match in the target extends self selector (the bit before :extend)
131
+ selectorPath = [targetExtend.selfSelectors[0]];
132
+ matches = extendVisitor.findMatch(extend, selectorPath);
133
+
134
+ if (matches.length) {
135
+
136
+ // we found a match, so for each self selector..
137
+ extend.selfSelectors.forEach(function(selfSelector) {
138
+
139
+ // process the extend as usual
140
+ newSelector = extendVisitor.extendSelector(matches, selectorPath, selfSelector);
141
+
142
+ // but now we create a new extend from it
143
+ newExtend = new(tree.Extend)(targetExtend.selector, targetExtend.option, 0);
144
+ newExtend.selfSelectors = newSelector;
145
+
146
+ // add the extend onto the list of extends for that selector
147
+ newSelector[newSelector.length-1].extendList = [newExtend];
148
+
149
+ // record that we need to add it.
150
+ extendsToAdd.push(newExtend);
151
+ newExtend.ruleset = targetExtend.ruleset;
152
+
153
+ //remember its parents for circular references
154
+ newExtend.parent_ids = newExtend.parent_ids.concat(targetExtend.parent_ids, extend.parent_ids);
155
+
156
+ // only process the selector once.. if we have :extend(.a,.b) then multiple
157
+ // extends will look at the same selector path, so when extending
158
+ // we know that any others will be duplicates in terms of what is added to the css
159
+ if (targetExtend.firstExtendOnThisSelectorPath) {
160
+ newExtend.firstExtendOnThisSelectorPath = true;
161
+ targetExtend.ruleset.paths.push(newSelector);
162
+ }
163
+ });
164
+ }
165
+ }
166
+ }
167
+
168
+ if (extendsToAdd.length) {
169
+ // try to detect circular references to stop a stack overflow.
170
+ // may no longer be needed.
171
+ this.extendChainCount++;
172
+ if (iterationCount > 100) {
173
+ var selectorOne = "{unable to calculate}";
174
+ var selectorTwo = "{unable to calculate}";
175
+ try
176
+ {
177
+ selectorOne = extendsToAdd[0].selfSelectors[0].toCSS();
178
+ selectorTwo = extendsToAdd[0].selector.toCSS();
179
+ }
180
+ catch(e) {}
181
+ throw {message: "extend circular reference detected. One of the circular extends is currently:"+selectorOne+":extend(" + selectorTwo+")"};
182
+ }
183
+
184
+ // now process the new extends on the existing rules so that we can handle a extending b extending c ectending d extending e...
185
+ return extendsToAdd.concat(extendVisitor.doExtendChaining(extendsToAdd, extendsListTarget, iterationCount+1));
186
+ } else {
187
+ return extendsToAdd;
188
+ }
189
+ },
190
+ visitRule: function (ruleNode, visitArgs) {
191
+ visitArgs.visitDeeper = false;
192
+ },
193
+ visitMixinDefinition: function (mixinDefinitionNode, visitArgs) {
194
+ visitArgs.visitDeeper = false;
195
+ },
196
+ visitSelector: function (selectorNode, visitArgs) {
197
+ visitArgs.visitDeeper = false;
198
+ },
199
+ visitRuleset: function (rulesetNode, visitArgs) {
200
+ if (rulesetNode.root) {
201
+ return;
202
+ }
203
+ var matches, pathIndex, extendIndex, allExtends = this.allExtendsStack[this.allExtendsStack.length-1], selectorsToAdd = [], extendVisitor = this, selectorPath;
204
+
205
+ // look at each selector path in the ruleset, find any extend matches and then copy, find and replace
206
+
207
+ for(extendIndex = 0; extendIndex < allExtends.length; extendIndex++) {
208
+ for(pathIndex = 0; pathIndex < rulesetNode.paths.length; pathIndex++) {
209
+ selectorPath = rulesetNode.paths[pathIndex];
210
+
211
+ // extending extends happens initially, before the main pass
212
+ if (rulesetNode.extendOnEveryPath) { continue; }
213
+ var extendList = selectorPath[selectorPath.length-1].extendList;
214
+ if (extendList && extendList.length) { continue; }
215
+
216
+ matches = this.findMatch(allExtends[extendIndex], selectorPath);
217
+
218
+ if (matches.length) {
219
+
220
+ allExtends[extendIndex].selfSelectors.forEach(function(selfSelector) {
221
+ selectorsToAdd.push(extendVisitor.extendSelector(matches, selectorPath, selfSelector));
222
+ });
223
+ }
224
+ }
225
+ }
226
+ rulesetNode.paths = rulesetNode.paths.concat(selectorsToAdd);
227
+ },
228
+ findMatch: function (extend, haystackSelectorPath) {
229
+ //
230
+ // look through the haystack selector path to try and find the needle - extend.selector
231
+ // returns an array of selector matches that can then be replaced
232
+ //
233
+ var haystackSelectorIndex, hackstackSelector, hackstackElementIndex, haystackElement,
234
+ targetCombinator, i,
235
+ extendVisitor = this,
236
+ needleElements = extend.selector.elements,
237
+ potentialMatches = [], potentialMatch, matches = [];
238
+
239
+ // loop through the haystack elements
240
+ for(haystackSelectorIndex = 0; haystackSelectorIndex < haystackSelectorPath.length; haystackSelectorIndex++) {
241
+ hackstackSelector = haystackSelectorPath[haystackSelectorIndex];
242
+
243
+ for(hackstackElementIndex = 0; hackstackElementIndex < hackstackSelector.elements.length; hackstackElementIndex++) {
244
+
245
+ haystackElement = hackstackSelector.elements[hackstackElementIndex];
246
+
247
+ // if we allow elements before our match we can add a potential match every time. otherwise only at the first element.
248
+ if (extend.allowBefore || (haystackSelectorIndex === 0 && hackstackElementIndex === 0)) {
249
+ potentialMatches.push({pathIndex: haystackSelectorIndex, index: hackstackElementIndex, matched: 0, initialCombinator: haystackElement.combinator});
250
+ }
251
+
252
+ for(i = 0; i < potentialMatches.length; i++) {
253
+ potentialMatch = potentialMatches[i];
254
+
255
+ // selectors add " " onto the first element. When we use & it joins the selectors together, but if we don't
256
+ // then each selector in haystackSelectorPath has a space before it added in the toCSS phase. so we need to work out
257
+ // what the resulting combinator will be
258
+ targetCombinator = haystackElement.combinator.value;
259
+ if (targetCombinator === '' && hackstackElementIndex === 0) {
260
+ targetCombinator = ' ';
261
+ }
262
+
263
+ // if we don't match, null our match to indicate failure
264
+ if (!extendVisitor.isElementValuesEqual(needleElements[potentialMatch.matched].value, haystackElement.value) ||
265
+ (potentialMatch.matched > 0 && needleElements[potentialMatch.matched].combinator.value !== targetCombinator)) {
266
+ potentialMatch = null;
267
+ } else {
268
+ potentialMatch.matched++;
269
+ }
270
+
271
+ // if we are still valid and have finished, test whether we have elements after and whether these are allowed
272
+ if (potentialMatch) {
273
+ potentialMatch.finished = potentialMatch.matched === needleElements.length;
274
+ if (potentialMatch.finished &&
275
+ (!extend.allowAfter && (hackstackElementIndex+1 < hackstackSelector.elements.length || haystackSelectorIndex+1 < haystackSelectorPath.length))) {
276
+ potentialMatch = null;
277
+ }
278
+ }
279
+ // if null we remove, if not, we are still valid, so either push as a valid match or continue
280
+ if (potentialMatch) {
281
+ if (potentialMatch.finished) {
282
+ potentialMatch.length = needleElements.length;
283
+ potentialMatch.endPathIndex = haystackSelectorIndex;
284
+ potentialMatch.endPathElementIndex = hackstackElementIndex + 1; // index after end of match
285
+ potentialMatches.length = 0; // we don't allow matches to overlap, so start matching again
286
+ matches.push(potentialMatch);
287
+ }
288
+ } else {
289
+ potentialMatches.splice(i, 1);
290
+ i--;
291
+ }
292
+ }
293
+ }
294
+ }
295
+ return matches;
296
+ },
297
+ isElementValuesEqual: function(elementValue1, elementValue2) {
298
+ if (typeof elementValue1 === "string" || typeof elementValue2 === "string") {
299
+ return elementValue1 === elementValue2;
300
+ }
301
+ if (elementValue1 instanceof tree.Attribute) {
302
+ if (elementValue1.op !== elementValue2.op || elementValue1.key !== elementValue2.key) {
303
+ return false;
304
+ }
305
+ if (!elementValue1.value || !elementValue2.value) {
306
+ if (elementValue1.value || elementValue2.value) {
307
+ return false;
308
+ }
309
+ return true;
310
+ }
311
+ elementValue1 = elementValue1.value.value || elementValue1.value;
312
+ elementValue2 = elementValue2.value.value || elementValue2.value;
313
+ return elementValue1 === elementValue2;
314
+ }
315
+ elementValue1 = elementValue1.value;
316
+ elementValue2 = elementValue2.value;
317
+ if (elementValue1 instanceof tree.Selector) {
318
+ if (!(elementValue2 instanceof tree.Selector) || elementValue1.elements.length !== elementValue2.elements.length) {
319
+ return false;
320
+ }
321
+ for(var i = 0; i <elementValue1.elements.length; i++) {
322
+ if (elementValue1.elements[i].combinator.value !== elementValue2.elements[i].combinator.value) {
323
+ if (i !== 0 || (elementValue1.elements[i].combinator.value || ' ') !== (elementValue2.elements[i].combinator.value || ' ')) {
324
+ return false;
325
+ }
326
+ }
327
+ if (!this.isElementValuesEqual(elementValue1.elements[i].value, elementValue2.elements[i].value)) {
328
+ return false;
329
+ }
330
+ }
331
+ return true;
332
+ }
333
+ return false;
334
+ },
335
+ extendSelector:function (matches, selectorPath, replacementSelector) {
336
+
337
+ //for a set of matches, replace each match with the replacement selector
338
+
339
+ var currentSelectorPathIndex = 0,
340
+ currentSelectorPathElementIndex = 0,
341
+ path = [],
342
+ matchIndex,
343
+ selector,
344
+ firstElement,
345
+ match,
346
+ newElements;
347
+
348
+ for (matchIndex = 0; matchIndex < matches.length; matchIndex++) {
349
+ match = matches[matchIndex];
350
+ selector = selectorPath[match.pathIndex];
351
+ firstElement = new tree.Element(
352
+ match.initialCombinator,
353
+ replacementSelector.elements[0].value,
354
+ replacementSelector.elements[0].index,
355
+ replacementSelector.elements[0].currentFileInfo
356
+ );
357
+
358
+ if (match.pathIndex > currentSelectorPathIndex && currentSelectorPathElementIndex > 0) {
359
+ path[path.length - 1].elements = path[path.length - 1].elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex));
360
+ currentSelectorPathElementIndex = 0;
361
+ currentSelectorPathIndex++;
362
+ }
363
+
364
+ newElements = selector.elements
365
+ .slice(currentSelectorPathElementIndex, match.index)
366
+ .concat([firstElement])
367
+ .concat(replacementSelector.elements.slice(1));
368
+
369
+ if (currentSelectorPathIndex === match.pathIndex && matchIndex > 0) {
370
+ path[path.length - 1].elements =
371
+ path[path.length - 1].elements.concat(newElements);
372
+ } else {
373
+ path = path.concat(selectorPath.slice(currentSelectorPathIndex, match.pathIndex));
374
+
375
+ path.push(new tree.Selector(
376
+ newElements
377
+ ));
378
+ }
379
+ currentSelectorPathIndex = match.endPathIndex;
380
+ currentSelectorPathElementIndex = match.endPathElementIndex;
381
+ if (currentSelectorPathElementIndex >= selectorPath[currentSelectorPathIndex].elements.length) {
382
+ currentSelectorPathElementIndex = 0;
383
+ currentSelectorPathIndex++;
384
+ }
385
+ }
386
+
387
+ if (currentSelectorPathIndex < selectorPath.length && currentSelectorPathElementIndex > 0) {
388
+ path[path.length - 1].elements = path[path.length - 1].elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex));
389
+ currentSelectorPathIndex++;
390
+ }
391
+
392
+ path = path.concat(selectorPath.slice(currentSelectorPathIndex, selectorPath.length));
393
+
394
+ return path;
395
+ },
396
+ visitRulesetOut: function (rulesetNode) {
397
+ },
398
+ visitMedia: function (mediaNode, visitArgs) {
399
+ var newAllExtends = mediaNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]);
400
+ newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, mediaNode.allExtends));
401
+ this.allExtendsStack.push(newAllExtends);
402
+ },
403
+ visitMediaOut: function (mediaNode) {
404
+ this.allExtendsStack.length = this.allExtendsStack.length - 1;
405
+ },
406
+ visitDirective: function (directiveNode, visitArgs) {
407
+ var newAllExtends = directiveNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]);
408
+ newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, directiveNode.allExtends));
409
+ this.allExtendsStack.push(newAllExtends);
410
+ },
411
+ visitDirectiveOut: function (directiveNode) {
412
+ this.allExtendsStack.length = this.allExtendsStack.length - 1;
413
+ }
414
+ };
415
+
416
+ })(require('./tree'));