diff --git a/install-reddit.sh b/install-reddit.sh index 382490dbe..4264b9889 100755 --- a/install-reddit.sh +++ b/install-reddit.sh @@ -146,6 +146,7 @@ python-kazoo python-stripe nodejs +node-less gettext make optipng diff --git a/r2/Makefile b/r2/Makefile index 22c1e740b..cbe44f923 100644 --- a/r2/Makefile +++ b/r2/Makefile @@ -135,7 +135,7 @@ endef $(foreach plugin,$(PLUGINS),$(eval $(call PLUGIN_STATIC_TEMPLATE,$(plugin)))) #### Stylesheets -LESSC := r2/lib/contrib/less.js/bin/lessc +LESSC := lessc CSS_COMPRESS := $(PYTHON) r2/lib/contrib/rcssmin.py CSS_SOURCE_DIR := $(STATIC_BUILD_DIR)/css diff --git a/r2/r2/lib/contrib/less.js/CHANGELOG b/r2/r2/lib/contrib/less.js/CHANGELOG deleted file mode 100644 index b72af3357..000000000 --- a/r2/r2/lib/contrib/less.js/CHANGELOG +++ /dev/null @@ -1,41 +0,0 @@ -1.3.0 - -@media bubbling -Support arbitrary entities as selectors -Variadic argument support, see: https://gist.github.com/1933613 -Behaviour of zero-arity mixins has changed, see link above. -Allow '@import' directives in any selector -Media-query features can now be a variable -Automatic merging of media-query conditions -Fix global variable leaks -Fix error message on wrong-arity call -Fix an '@arguments' behaviour bug -Fix '::' selector output -Fix a bug when using @media with mixins - -1.2.1 - -Fix imports on browser -Improve error reporting on browser -Fix Runtime error reports from imported files -Fix 'File not found' import error reporting - -1.2.0 - -Mixin guards -New function `percentage` -New `color` function to parse hex color strings -New type-checking stylesheet functions -Fix Rhino support -Fix bug in string arguments to mixin call -Fix error reporting when index is 0 -Fix browser support in webkit and IE -Fix string interpolation bug when var is empty -Support '!important' after mixin calls -Support vanilla @keyframes directive -Support variables in certain css selectors, like 'nth-child' -Support @media and @import features properly -Improve @import support with media features -Improve error reports from imported files -Improve function call error reporting -Improve error-reporting diff --git a/r2/r2/lib/contrib/less.js/LICENSE b/r2/r2/lib/contrib/less.js/LICENSE deleted file mode 100644 index 40f3b781b..000000000 --- a/r2/r2/lib/contrib/less.js/LICENSE +++ /dev/null @@ -1,179 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -Copyright (c) 2009-2010 Alexis Sellier diff --git a/r2/r2/lib/contrib/less.js/Makefile b/r2/r2/lib/contrib/less.js/Makefile deleted file mode 100644 index 32d7cc044..000000000 --- a/r2/r2/lib/contrib/less.js/Makefile +++ /dev/null @@ -1,75 +0,0 @@ -# -# Run all tests -# -test: - node test/less-test.js - -# -# Run benchmark -# -benchmark: - node benchmark/less-benchmark.js - -# -# Build less.js -# -SRC = lib/less -HEADER = build/header.js -VERSION = `cat package.json | grep version \ - | grep -o '[0-9]\.[0-9]\.[0-9]\+'` -DIST = dist/less-${VERSION}.js -RHINO = dist/less-rhino-${VERSION}.js -DIST_MIN = dist/less-${VERSION}.min.js - -less: - @@mkdir -p dist - @@touch ${DIST} - @@cat ${HEADER} | sed s/@VERSION/${VERSION}/ > ${DIST} - @@echo "(function (window, undefined) {" >> ${DIST} - @@cat build/require.js\ - build/amd.js\ - build/ecma-5.js\ - ${SRC}/parser.js\ - ${SRC}/functions.js\ - ${SRC}/colors.js\ - ${SRC}/tree/*.js\ - ${SRC}/tree.js\ - ${SRC}/browser.js >> ${DIST} - @@echo "})(window);" >> ${DIST} - @@echo ${DIST} built. - -rhino: - @@mkdir -p dist - @@touch ${RHINO} - @@cat build/require-rhino.js\ - build/ecma-5.js\ - ${SRC}/parser.js\ - ${SRC}/functions.js\ - ${SRC}/tree/*.js\ - ${SRC}/tree.js\ - ${SRC}/rhino.js > ${RHINO} - @@echo ${RHINO} built. - -min: less - @@echo minifying... - @@uglifyjs ${DIST} > ${DIST_MIN} - @@echo ${DIST_MIN} built. - -server: less - cp dist/less-${VERSION}.js test/html/ - cd test/html && python -m SimpleHTTPServer - -clean: - git rm dist/* - -dist: clean min - git add dist/* - git commit -a -m "(dist) build ${VERSION}" - git archive master --prefix=less/ -o less-${VERSION}.tar.gz - npm publish less-${VERSION}.tar.gz - -stable: - npm tag less ${VERSION} stable - - -.PHONY: test benchmark diff --git a/r2/r2/lib/contrib/less.js/README.md b/r2/r2/lib/contrib/less.js/README.md deleted file mode 100644 index 726d6910f..000000000 --- a/r2/r2/lib/contrib/less.js/README.md +++ /dev/null @@ -1,20 +0,0 @@ -less.js -======= - -The **dynamic** stylesheet language. - - - -about ------ - -This is the JavaScript, and now official, stable version of LESS. - -For more information, visit . - -license -------- - -See `LICENSE` file. - -> Copyright (c) 2009-2011 Alexis Sellier diff --git a/r2/r2/lib/contrib/less.js/benchmark/benchmark.less b/r2/r2/lib/contrib/less.js/benchmark/benchmark.less deleted file mode 100644 index bf7fef73a..000000000 --- a/r2/r2/lib/contrib/less.js/benchmark/benchmark.less +++ /dev/null @@ -1,3979 +0,0 @@ -@bg: #f01; -@white: #fff; -@grey: #eee; -@black: #000; -@blue: #000; -@accent_colour: #000; -@light_grey: #eee; -@dark_grey: #eee; -@yellow: #422; -@red: #ff0000; -@colour_positive: #ff0000; -@colour_negative: #ff0000; - -.box_shadow (...) { -} -.text_shadow (...) { -} -.border_radius (...) { -} -.border_radius_top_left (...) { -} -.border_radius_top_right (...) { -} -.border_radius_bottom_right (...) { -} -.border_radius_bottom_left (...) { -} -.border_radius_top (...) { -} -.border_radius_right (...) { -} -.border_radius_bottom (...) { -} -.border_radius_left (...) { -} -div.browse { - margin: 0 0 20px; - &.class { - padding: 0; - } - div.header { - padding: 10px 10px 9px; text-align: left; background: @bg url('/images/panel_header_bg.png') repeat-x top left; - border-bottom: 1px solid (@bg * 0.66 + @black * 0.33); line-height: 1; height: 18px; - .border_radius_top(3); color: @light_grey; - h3 { font-size: 16px; margin: 0; color: @white; .text_shadow(1, 1, 0, @bg * 0.66 + @black * 0.33); } - span.filter { - float: left; display: block; overflow: hidden; position: relative; z-index: 5; - a { - margin: 0 1px 0 0; display: block; float: left; padding: 0 8px; height: 18px; font-weight: bold; font-size: 10px; line-height: 18px; - text-transform: uppercase; background: url('/images/transparent_backgrounds/black_50.png'); color: @light_grey; text-decoration: none; position: relative; z-index: 3; - .active { - background: @white; color: @black; z-index: 4; - :hover { color: @black; } - } - :hover { color: @white; } - :first-child { .border_radius_left(2); } - :last-child { .border_radius_right(2); margin-right: 0; } - } - } - - span.filter.dropdown { - margin: 0; position: relative; overflow: visible; - a { - .border_radius(2); background: @white; color: @black; margin: 0; position: relative; padding-right: 25px; - img { float: left; margin: 4px 5px 0 0; } - b.arrow { - float: right; display: block; height: 0; width: 0; border: 5px solid transparent; border-top: 5px solid @black; border-bottom: none; - position: absolute; top: 6px; right: 10px; - } - :hover { - background: @accent_colour; color: @white; - b.arrow { border-top: 5px solid @white; } - } - } - ul { - position: absolute; top: 100%; left: 0; margin: 1px 0 0; padding: 0; background: @white; .border_radius(2); - .box_shadow(0, 1, 1, @black); - li { - list-style: none; display: block; padding: 0; margin: 0; - a { - display: block; height: 18px; line-height: 18px; color: @black; font-size: 10px; text-transform: uppercase; background: transparent; - border-bottom: 1px solid (@light_grey * 0.66 + @white * 0.33); float: none; margin: 0; .border_radius(0); white-space: nowrap; - :hover { background: url('/images/transparent_backgrounds/accent_colour_25.png'); color: @black; } - } - :last-child { - a { border: none; } - } - } - } - } - span.filter.dropdown.sort { float: left; margin: 0 0 0 10px; } - span.filter.dropdown.localisation { float: left; margin: 0 0 0 10px; } - a.more { - float: right; color: @white; .text_shadow(1, 1, 0, @bg * 0.66 + @black * 0.33); font-size: 14px; font-weight: bold; - position: relative; top: 2px; - :hover { text-decoration: none; } - } - } - > ul { - margin: 0; background: @white; padding: 10px 0 0 10px; .border_radius(3); position: relative; - li { - display: block; float: left; list-style: none; margin: 0 10px 10px 0; padding: 5px; position: relative; - background: @white; width: 130px; border: 1px solid (@light_grey * 0.33 + @white * 0.66); .border_radius(2); - a.remove { - position: absolute; height: 16px; width: 16px; padding: 3px; background: @accent_colour; - .border_radius(99); display: none; z-index: 3; top: -8px; right: -8px; - img { vertical-align: middle; } - } - div.thumbnail { - .border_radius_top(3); position: relative; z-index: 3; - .marker { - position: absolute; padding: 2px; .border_radius(2); z-index: 3; - background: url('/images/transparent_backgrounds/white_75.png'); height: 12px; width: 12px; - } - .marker.coupon { - height: auto; width: auto; top: 10px; right: -3px; padding: 0; background: transparent; overflow: hidden; position: absolute; - b { - display: block; height: 0; width: 0; float: left; border: 14px solid transparent; border-top: 14px solid @accent_colour; - border-bottom: none; border-right: none; float: left; - } - span { - color: @white; font-size: 10px; font-weight: bold; text-transform: uppercase; height: 14px; line-height: 14px; display: block; - padding: 0 4px 0 2px; background: @accent_colour; .text_shadow(1, 1, 0px, (@accent_colour * 0.75 + @black * 0.25)); margin: 0 0 0 14px; - } - } - .marker.video { - position: absolute; left: 50%; top: 50%; background: @white; width: 10px; height: 10px; - b { display: block; width: 0; height: 0; border: 5px solid transparent; border-left: 10px solid @black; border-right: none; } - } - .marker.endorsed_by_me { background: none; padding: 0; right: 0; bottom: -32px; .border_radius(2); background: @white; } - a.thumbnail { - display: block; overflow: hidden; position: relative; text-align: center; - img { position: relative; display: block; margin: auto; } - } - } - div.text { - margin: 3px 0 0; display: block; - a { text-decoration: none; } - a.title { - display: block; text-decoration: none; font-weight: bold; font-size: 12px; line-height: 16px; - white-space: nowrap; height: 16px; overflow: hidden; - :before { - display: block; height: 32px; width: 20px; content: " "; float: right; right: -15px; top: -8px; - background: @white; position: relative; z-index: 1; .box_shadow(-5, 0, 10, @white); - } - } - small { - font-size: 11px; line-height: 13px; color: @grey; display: block; height: 13px; overflow: hidden; white-space: nowrap; - a { font-weight: bold; } - :before { - display: block; height: 32px; width: 20px; content: " "; float: right; right: -15px; top: -8px; - background: @white; position: relative; z-index: 1; .box_shadow(-5, 0, 10, @white); - } - } - } - :hover { - background: @accent_colour; - a.remove { display: block; } - div.thumbnail { - a.marker.remove, a.marker.video { - b { display: inline-block; } - } - a.marker.video { .box_shadow(0, 0, 2, @black); } - } - div.text { - a { color: @white; } - a.title:before { background: @accent_colour; .box_shadow(-5, 0, 10, @accent_colour); } - small { - color: @white * 0.75 + @accent_colour * 0.25; - :before { background: @accent_colour; .box_shadow(-5, 0, 10, @accent_colour); } - } - } - div.footer a { color: @white; } - } - } - > li.ad div.thumbnail a.thumbnail { - width: 130px; height: 97px; - img { width: 100%; height: 100%; } - } - > li.brand div.thumbnail a.thumbnail { - width: 120px; height: 87px; padding: 5px; background: @white; .border_radius(2); - img { max-width: 120px; max-height: 87px; } - } - li.paginate { - margin-bottom: 0; - a { - display: block; position: relative; text-decoration: none; height: 131px; - div.arrow { - background: #81c153 url('/images/button_bg.png') repeat-x left top; border: 1px solid (@accent_colour * 0.75 + @black * 0.25); - height: 44px; .border_radius(99); width: 44px; margin: 0 auto; position: relative; top: 32px; - b { text-indent: -9000px; display: block; border: 10px solid transparent; width: 0; height: 0; position: relative; top: 12px; } - } - div.label { - position: absolute; bottom: 5px; left: 0; right: 0; line-height: 13px; - color: @accent_colour * 0.85 + @black * 0.15; text-decoration: none; - font-weight: bold; font-size: 12px; text-align: center; - } - :hover { - div.arrow { background: #abd56e url('/images/button_bg.png') repeat-x left -44px; } - } - } - :hover { background: transparent; } - } - li.paginate.previous a div b { border-right: 15px solid @white; border-left: none; left: 12px; } - li.paginate.next a div b { border-left: 15px solid @white; border-right: none; left: 16px; } - } - > div.footer { - padding: 9px 10px 10px; background: @light_grey * 0.75 + @white * 0.25; overflow: hidden; - border-top: 1px solid @light_grey; .border_radius_bottom(3); - div.info { - float: left; color: @grey; - strong { color: @black; font-weight: normal; } - } - div.pagination { - float: right; - > * { - display: inline-block; line-height: 1; padding: 0 6px; line-height: 18px; height: 18px; background: @white; - .border_radius(3); text-decoration: none; font-weight: bold; - font-size: 10px; text-transform: uppercase; - } - a { color: @grey; } - a:hover { color: @black; } - span.disabled { color: @light_grey; } - span.current { color: @white; background: @bg; border: none; } - span.current:hover { color: @white; } - } - } -} -div.browse.with_categories { margin: 0 0 0 160px; } -div.browse.with_options > ul { .border_radius_top(0); } -div.browse.with_footer > ul { .border_radius_bottom(0); } -/* Browse List */ -div.browse.list { -> ul { - margin: 0; min-height: 320px; - padding: 10px 0 0 10px; overflow: hidden; - > li { - display: block; list-style: none; margin: 0 10px 10px 0; padding: 5px; - .border_radius(3); position: relative; line-height: normal; - .marker { - position: absolute; padding: 2px; .border_radius(2); - background: url('/images/transparent_backgrounds/white_75.png'); - img { height: 12px; width: 12px; } - } - img.marker { height: 12px; width: 12px; } - span.marker.new { - color: black; left: -5px; top: -5px; background: none; background-color: @white * 0.1 + @yellow * 0.6 + @red * 0.3; line-height: 1; padding: 2px 5px; - font-weight: bold; - } - a.marker.media_type { - display: inline-block; text-decoration: none; top: 39px; left: 8px; - font-size: 10px; - b { font-weight: normal; margin: 0 0 0 2px; line-height: 1; display: none; } - img { vertical-align: middle; } - } - a.thumbnail { - float: left; - width: 68px; display: block; overflow: hidden; - border: 1px solid @light_grey; - :hover { border-color: @accent_colour; } - } - span.title_brand { - display: block; margin: 0 0 2px 75px; - a { margin: 0; display: inline; } - a.brand_name { font-weight: normal; font-size: 12px; } - } - a.ad_title { - font-weight: bold; font-size: 14px; margin: 0 0 0 75px; display: block; - } - a.brand_name { - font-weight: bold; font-size: 14px; margin: 0 0 0 75px; display: block; - } - small { - display: block; color: @grey; margin: 0 0 0 75px; font-size: 12px; - } - small.brand_name { display: inline; margin: 0; } - ul.chart { - margin: 0 0 0 80px; - height: 39px; - } - ul.networks { - margin: 3px 0 0 75px; padding: 0; overflow: hidden; - li { display: block; float: left; margin: 0 5px 0 0; line-height: 1; } - } - div.points { - display: none; - font-size: 12px; text-align: right; - label { color: @grey; } - } - a.remove { bottom: -3px; right: -3px; } - } - li.ad { - a.thumbnail { height: 51px; } - span.title_brand { - small.brand_name { - display: block; - } - } - } - li.brand { - a.thumbnail { height: 68px; } - } - } -} -div.browse.list.with_options ul { .border_radius_top(0); } -div.browse.list.with_footer ul { .border_radius_bottom(0); } -div.browse.list.cols_2 { - > ul { - > li { - width: 285px; float: left; - :hover { - background: @white; - } - } - } -} -div.browse.ads.list { - > ul { - > li { - height: 53px; - a.thumbnail { - height: 51px; - } - } - } -} -div.browse.brands.list { - > ul { - > li { - height: 68px; - a.thumbnail { - height: 66px; - } - } - } -} - -/* Categories List */ -#categories { - margin: 40px 0 0; width: 160px; float: left; position: relative; z-index: 1; - ul { - margin: 0; padding: 10px 0 0; - li { - list-style: none; margin: 0; padding: 0; font-size: 14px; - a { color: @grey; display: block; padding: 5px 10px 5px 15px; text-decoration: none; .border_radius_left(3); } - a:hover { color: @black; background: @light_grey * 0.15 + @white * 0.85; } - } - .all a { font-weight: bold; } - .current a { - background: @white; color: @black; border: 1px solid (@light_grey * 0.25 + @white * 0.75); border-right: none; border-left: 5px solid @bg; - padding-left: 10px; - } - } -} - -/* Ads > Show */ -#ad { - div.header { - overflow: hidden; - h3 { font-size: 16px; margin: 0 0 3px; } - small { - a.category { font-weight: bold; color: @accent_colour; } - span.networks img { position: relative; top: 3px; } - } - span.brand { - float: right; color: @white; - a.brand_name { font-weight: bold; color: @accent_colour; } - } - } - div.content { - padding: 0; position: relative; - a.toggle_size { - display: block; .border_radius(3); background-color: @black; padding: 0 5px 0 26px; - background-position: 5px center; background-repeat: no-repeat; text-decoration: none; margin: 5px 5px 0 0; - position: absolute; top: 0; right: 0; line-height: 25px; z-index: 45; - } - img.creative { margin: 0 auto; max-width: 540px; display: block; } - object { position: relative; z-index: 44; } - object.video { line-height: 0; font-size: 0; } - object embed { position: relative; z-index: 45; line-height: 0; font-size: 0; } - } - div.content.not_video { - padding: 40px; text-align: center; - * { margin-left: auto; margin-right: auto; } - object.flash { margin-bottom: 0; } - } - div.footer { - padding: 0; - div.vote_views { - padding: 5px 10px; overflow: hidden; - div.share { float: right; margin: 2px 0 0 0; } - #login_register_msg, #encourage_vote_msg { line-height: 22px; font-weight: bold; color: @black; } - } - } -} -#sidebar { - #meta { - table { - margin: 0; - tr:last-child td { padding-bottom: 0; } - td { - padding: 0 0 5px; - ul.networks { - margin: 0; padding: 0; - li { - list-style: none; display: inline; - } - li { - } - } - } - td.label { color: @grey; white-space: nowrap; width: 1%; text-align: right; padding-right: 5px; } - } - } -} - -/* Voting */ -div.voted { - font-size: 12px; line-height: 22px; color: @black; display: inline-block; font-weight: bold; - img { float: left; margin-right: 5px; padding: 3px; .border_radius(3); } -} -#voted_up { - img { background: @colour_positive * 0.66 + @bg * 0.15; } -} -#voted_down { - img { background: @colour_negative * 0.66 + @bg * 0.15; } -} -#encourage_comment { - display: inline-block; line-height: 22px; font-weight: bold; -} -#vote { - overflow: hidden; font-size: 12px; line-height: 22px; color: @black; float: left; - a { - color: @white; font-weight: bold; overflow: hidden; display: block; - width: 16px; text-decoration: none; text-align: center; font-size: 10px; padding: 3px; text-transform: uppercase; - } - a.up { - float: left; background: @colour_positive * 0.66 + @bg * 0.15; .border_radius_left(3); - :hover { background: @colour_positive * 0.85 + @bg * 0.15; } - } - a.down { - float: left; background: @colour_negative * 0.66 + @bg * 0.15; .border_radius_right(3); - margin: 0 5px 0 1px; - :hover { background: @colour_negative * 0.85 + @bg * 0.15; } - } -} -#vote.disabled { - a.up { - background: (@colour_positive * 0.66 + @bg * 0.15) * 0.15 + @grey * 0.85; - :hover { background: (@colour_positive * 0.85 + @bg * 0.15) * 0.25 + @grey * 0.75; } - } - a.down { - background: (@colour_negative * 0.66 + @bg * 0.15) * 0.15 + @grey * 0.85; - :hover { background: (@colour_negative * 0.85 + @bg * 0.15) * 0.25 + @grey * 0.75; } - } -} - -/* Panels */ -div.panel { - margin: 0 0 20px; position: relative; .box_shadow(0, 0, 3, @light_grey * 0.66 + @white * 0.33); .border_radius(3); - > div.header { - background: @bg url('/images/panel_header_bg.png') repeat-x top left; border-bottom: 1px solid (@bg * 0.66 + @black * 0.33); - padding: 5px 10px 4px; .border_radius_top(3); min-height: 18px; - h2 { font-size: 16px; margin: 0; color: @white; .text_shadow(1, 1, 0, @bg * 0.66 + @black * 0.33); } - h3 { color: @white; font-size: 14px; margin: 0; line-height: 18px; .text_shadow(1, 1, 0, @bg * 0.66 + @black * 0.33); } - small { display: block; font-size: 12px; color: @light_grey * 0.25 + @white * 0.75; } - span.filter { - float: left; display: block; overflow: hidden; position: relative; z-index: 5; - a { - margin: 0 1px 0 0; display: block; float: left; padding: 0 8px; height: 18px; font-weight: bold; font-size: 10px; line-height: 18px; - text-transform: uppercase; background: url('/images/transparent_backgrounds/black_50.png'); color: @light_grey; text-decoration: none; position: relative; z-index: 3; - } - a:first-child { .border_radius_left(2); } - a:last-child { .border_radius_right(2); margin-right: 0; } - a.active { background: @white; color: @black; z-index: 4; } - a:hover { color: @white; } - a.active:hover { color: @black; } - } - - span.filter.dropdown { - margin: 0; position: relative; overflow: visible; - a { - .border_radius(2); background: @white; color: @black; margin: 0; position: relative; padding-right: 25px; - img { float: left; margin: 4px 5px 0 0; } - b.arrow { - float: right; display: block; height: 0; width: 0; border: 5px solid transparent; border-top: 5px solid @black; border-bottom: none; - position: absolute; top: 6px; right: 10px; - } - :hover { - background: @accent_colour; color: @white; - b.arrow { border-top: 5px solid @white; } - } - } - - ul { - position: absolute; top: 100%; left: 0; margin: 1px 0 0; padding: 0; background: @white; .border_radius(2); - .box_shadow(0, 1, 1, @black); - li { - list-style: none; display: block; padding: 0; margin: 0; - a { - display: block; height: 18px; line-height: 18px; color: @black; font-size: 10px; text-transform: uppercase; background: transparent; - border-bottom: 1px solid (@light_grey * 0.66 + @white * 0.33); float: none; margin: 0; .border_radius(0); white-space: nowrap; - :hover { background: url('/images/transparent_backgrounds/accent_colour_25.png'); color: @black; } - } - } - li:last-child { - a { border: none; } - } - } - } - span.filter.dropdown.sort { float: left; margin: 0 0 0 10px; } - span.filter.dropdown.localisation { float: left; margin: 0 0 0 10px; } - - a.more { - float: right; color: @white; .text_shadow(1, 1, 0, @bg * 0.66 + @black * 0.33); font-size: 14px; font-weight: bold; - position: relative; top: 2px; - :hover { text-decoration: none; } - } - } - > div.content { - background: @white; padding: 10px; - .no_padding { padding: 0; } - } - > div.footer { - background: @light_grey * 0.33 + @white * 0.66; border-top: 1px solid (@light_grey * 0.5 + @white * 0.5); - padding: 4px 10px 5px; .border_radius_bottom(3); - } -} -div.panel.no_footer div.content { .border_radius_bottom(3); } -div.panel.no_header div.content { .border_radius_top(3); } -div.panel.collapsable { - div.header { - cursor: pointer; - b.toggle { float: right; border: 5px solid transparent; border-bottom: 5px solid @white; border-top: none; display: block; width: 0; height: 0; margin: 6px 0 0 0; } - } - div.header:hover { - background-color: @bg * 0.75 + @white * 0.25; - } -} -div.panel.collapsed { - div.header { - border-bottom: none; .border_radius(3); - b.toggle { border-bottom: none; border-top: 5px solid @white; } - } - div.blank { border-bottom: none; .border_radius_bottom(3); } - div.content, div.footer { display: none; } -} - - -/* Sidebar Actions */ -#sidebar { - #actions { - .box_shadow(0, 0, 0, transparent); - div.content { - background: url('/images/transparent_backgrounds/accent_colour_10.png'); text-align: center; - p.endorsement { - margin: 0 0 10px; font-size: 14px; font-weight: bold; - small { font-weight: normal; line-height: inherit; margin: 10px 0 0; } - :last-child { margin: 0; } - } - div.share { margin: 5px 0 0; } - a.button { - font-size: 16px; line-height: normal; height: auto; padding: 5px 10px 5px 35px; font-weight: bold; margin: 0; position: relative; - img { position: absolute; top: 3px; left: 6px; } - } - div.flash.notice { - margin: 10px 0 0; font-size: 22px; - small { font-weight: normal; margin: 0 0 10px; } - } - div.flash.notice.done { margin: 0; } - small { - display: block; margin: 10px 0 0; font-size: 11px; color: #808080; line-height: 12px; - img.favicon { vertical-align: middle; } - } - div.blank { - border: none; background: none; padding: 10px 0 0; border-top: 1px solid (@accent_colour * 0.5 + @white * 0.5); - margin: 10px 0 0; - } - } - } -} - -/* People Lists */ -ul.people { - margin: 0; padding: 10px 0 0 10px; background: @white; - > li { - display: block; margin: 0 10px 10px 0; float: left; padding: 2px; width: 57px; position: relative; - .border_radius(2); background: @white; list-style: none; border: 1px solid (@light_grey * 0.33 + @white * 0.66); - a.avatar { - display: block; width: 59px; height: 59px; overflow: hidden; - img { width: 100%; height: 100%; } - } - a.name { display: block; font-size: 10px; text-align: center; } - :hover { - background: @accent_colour; - a.name { color: @white; } - } - } -} -ul.people.list { - padding: 0; - > li { - margin: 0 0 10px; padding: 0 0 10px; overflow: hidden; float: none; width: auto; .border_radius(0); - border: none; border-bottom: 1px solid (@light_grey * 0.33 + @white * 0.66); - span.points { - float: right; display: block; padding: 5px; background: @light_grey * 0.15 + @white * 0.85; line-height: 1; - text-align: center; width: 50px; height: 30px; .border_radius(3); margin: 0 0 0 10px; - strong { display: block; color: @black; font-size: 16px; margin: 2px 0 0; } - label { color: @grey; text-transform: uppercase; font-size: 10px; } - label.long { display: block; } - label.short { display: none; } - } - a.avatar { float: left; width: 40px; height: 40px; } - a.name { font-size: 14px; font-weight: bold; margin: 0 0 0 50px; text-align: left; } - a.name.long { display: inline; } - a.name.short { display: none; } - span.networks { - display: block; margin: 0 0 0 50px; - img.favicon { vertical-align: middle; } - } - :hover { - background: transparent; - a.name { color: @accent_colour * 0.85 + @black * 0.15; } - } - :last-child { padding-bottom: 0; border-bottom: none; margin-bottom: 0; } - } -} -ul.people.list.small { - > li { - span.points { - padding: 3px 6px; height: 18px; font-size: 9px; line-height: 17px; width: 60px; - strong { font-size: 12px; margin: 0; display: inline; } - label { font-size: 9px; } - label.long { display: none; } - label.short { display: inline; } - } - a.avatar { width: 24px; height: 24px; } - a.name { display: inline; line-height: 24px; margin: 0 0 0 5px; font-size: 12px; height: 24px; } - a.name.long { display: none; } - a.name.short { display: inline; } - span.networks { display: inline; margin: 0; } - :last-child { padding-bottom: 0; border-bottom: none; margin-bottom: 0; } - } -} -ul.people.tiled { - > li { - width: 28px; padding: 2px; - a.avatar { width: 24px; height: 24px; background: @white; padding: 2px; } - a.name, small, span.networks, span.points { display: none; } - } -} - -/* Comments */ -#comments { - ul { - margin: 0 0 20px; padding: 0; - li { - display: block; list-style: none; padding: 0; margin: 0 0 10px; - span.meta { - margin: 0; overflow: hidden; display: block; - small { font-size: 12px; color: @light_grey; float: right; line-height: 16px; display: inline-block; } - a.avatar { - display: inline-block; height: 16px; width: 16px; position: relative; top: 3px; - img { height: 100%; width: 100%; } - } - a.name { font-weight: bold; line-height: 16px; display: inline-block; } - span.inactive { color: @grey; font-weight: bold; line-height: 16px; display: inline-block; } - } - b.tail { - display: block; width: 0; height: 0; margin: 3px 0 0 10px; border: 5px solid transparent; border-top: none; - border-bottom: 5px solid @white; position: relative; z-index: 2; - } - blockquote { - margin: 0; padding: 10px; .border_radius(3); font-style: normal; background: @white; - color: @dark_grey; .box_shadow(0, 0, 3, @light_grey * 0.66 + @white * 0.33); - } - } - } - form { - margin: 0; - textarea { width: 500px; } - } -} - -/* Sidebar Categories */ -#sidebar { - #categories { - margin: 0 0 20px; - width: auto; - p { margin: 0; } - } -} - -#sidebar { - #ads > ul li, #recommendations > ul li { - width: 81px; - div.thumbnail { - a.thumbnail { height: 60px; width: 81px; } - } - div.text { - a.title { font-size: 11px; height: 14px; line-height: 14px; } - small { display: none; } - } - } - #brands > ul li { - width: 55px; - div.thumbnail { - a.thumbnail { - height: 45px; width: 45px; - img { max-height: 45px; max-width: 45px; } - } - } - div.text { display: none; } - } -} - -/* My Account */ -#accounts_controller { - #top { - #page_title { - #page_options { - a.button.public_profile { - float: right; font-size: 16px; line-height: 1; height: auto; padding: 8px 35px 8px 15px; position: relative; - b.arrow { display: block; height: 0; width: 0; position: absolute; top: 10px; right: 15px; border: 6px solid transparent; border-right: none; border-left: 6px solid @white; margin: 0; } - } - a.button.goto_dashboard { - float: right; font-size: 16px; line-height: 1; height: auto; padding: 8px 15px 8px 35px; margin-right: 5px; position: relative; - b.arrow { display: block; height: 0; width: 0; position: absolute; top: 10px; left: 15px; border: 6px solid transparent; border-left: none; border-right: 6px solid @white; margin: 0; } - } - } - } - } - #account_nav { - float: left; width: 200px; margin: 0 20px 0 0; - ul.nav { - margin: 0; padding: 0; - li { - margin: 0 0 5px; display: block; list-style: none; padding: 0; - a { - display: block; height: 30px; text-decoration: none; color: @white; - b { - border: 15px solid transparent; border-right: none; border-left: 10px solid transparent; width: 0; - height: 0; float: right; display: none; - } - span { - .border_radius(3); background: @bg; display: block; - line-height: 30px; padding: 0 10px; font-size: 14px; font-weight: bold; margin: 0 10px 0 0; - } - } - :hover { - a { - color: @white; - b { border-left-color: @bg; display: block; } - span { background: @bg; .border_radius_right(0); } - } - } - } - li.current a { - b { border-left-color: @accent_colour; display: block; } - span { background: @accent_colour; color: @white; .border_radius_right(0); } - } - } - } - #main { - > div { - margin: 0 0 20px; - form { margin: 0; } - } - #profile { - a.avatar { - float: left; display: block; - width: 70px; overflow: hidden; position: relative; text-decoration: none; - img { width: 100%; } - span { - display: block; line-height: 1; padding: 3px; margin: 5px 0 0; color: @white; background: @accent_colour; - .border_radius(3); .text_shadow(1, 1, 0, @grey); - text-align: center; font-size: 10px; font-weight: bold; text-transform: uppercase; - } - } - form { - margin: 0 0 0 90px; - h4 { margin: 10px 0 20px; border-bottom: 1px solid (@light_grey * 0.5 + @white * 0.5); padding: 0; color: @bg; font-size: 16px; } - ul.choices { - li { width: 30%; } - } - div.extra { margin-top: 20px; } - } - } - - #networks { - ul { margin: 0 -10px -10px 0; padding: 0; overflow: hidden; - li:hover - { - background: @light_grey; display: block; float: left; width: 180px; - padding: 10px; margin: 0 10px 10px 0; list-style: none; .border_radius(3); - position: relative; - * { line-height: normal; } - img { vertical-align: middle; float: left; } - .name { font-weight: bold; font-size: 14px; display: block; margin: -2px 0 0 42px; } - small { - font-size: 12px; color: @grey; display: block; margin-left: 42px; - strong { color: @black; font-weight: normal; } - } - :hover { - } - } - li.installed { - background: @white; - border: 2px solid @accent_colour; padding: 8px; - } - li.unavailable { - .name { color: @black; } - :hover { - background: @light_grey; - } - } - li:hover { - background: @light_grey * 0.5 + @white * 0.5; - } - } - } - } -} - -/* Shopping Style Panel */ -#shopping_style { - div.header a.button.small { float: right; } - div.content { - p { - margin: 0 0 10px; - label { text-transform: uppercase; font-size: 11px; display: block; color: @bg; font-weight: bold; } - span { color: @black; } - span.toggle { white-space: nowrap; color: @grey; } - :last-child { margin: 0; } - } - p.more { text-align: left; font-weight: normal; } - p.less { display: none; margin: 0; } - } -} - -/* People Controller */ -#people_controller.index { - #main { - div.panel { - float: left; width: 300px; margin: 0 20px 0 0; - :last-child { margin-right: 0; } - } - } -} -#people_controller.show { - #person_overview, #shopping_style { - a.button.small { - } - } - #content { - #shopping_style { - float: left; width: 240px; margin: 0 20px 0 0; - } - #main { width: 360px; } - } -} - -/* Search Results */ -#search_results { - margin: 0 0 20px; - li { - :hover { - small { color: @white * 0.75 + @accent_colour * 0.25; } - } - } -} -#search { - div.content { - padding: 20px; - form { - margin: 0; float: none; - span.submit_and_options { - display: block; - } - } - p { margin: 0 0 15px; } - h4 { font-weight: normal; margin: 0 0 5px; } - } -} - -/* Recommendations */ -#recommendations { - div.browse { - margin: 0; padding: 0; background: none; - ul { min-height: 0; .border_radius(0); } - } -} - -/* Blank States */ -div.blank { - padding: 20px; background: @bg * 0.05 + @blue * 0.05 + @white * 0.9; position: relative; - border: 1px solid (@bg * 0.1 + @blue * 0.1 + @white * 0.8); z-index: 1; - h4 { font-size: 18px; margin: 0 0 10px; } - h4:last-child { margin: 0; } - p { font-size: 16px; margin: 0 0 10px; } - p:last-child { margin: 0; } - p.with_list_number.large { - span { margin-left: 48px; display: block; color: @white; } - } - p.earn span { font-size: 22px; color: @white; line-height: 48px; font-weight: bold; } - a { white-space: nowrap; } - a.hide { - position: absolute; top: -5px; right: -5px; display: block; height: 16px; width: 16px; padding: 3px; background: #E7E9F6; .border_radius(99); - } -} - -div.blank.small { - padding: 10px 20px; - h4 { font-weight: normal; font-size: 16px; } - p { margin: 0; } -} -div.blank.tiny { - padding: 10px 20px; - h4 { font-weight: normal; font-size: 14px; } - p { margin: 0; font-size: 12px; } -} -div.blank.rounded { - .border_radius(3); margin: 0 0 20px; -} -div.blank.rounded.bottom { .border_radius_top(0); } -div.blank.with_border_bottom { border-bottom: 1px solid (@bg * 0.1 + @blue * 0.1 + @white * 0.8); } -div.blank.no_border_top { border-top: none; } -div.blank.no_border_bottom { border-bottom: none; } -div.blank.no_side_borders { border-right: none; border-left: none; } -div.panel { - div.blank { - padding: 10px 20px; overflow: hidden; margin: 0; - h4 { font-weight: normal; font-size: 14px; } - p, ul { margin: 0 0 10px; font-size: 12px; } - p:last-child, ul:last-child { margin: 0; } - } -} - -/* Sidebar Browse */ -#sidebar { - div.panel { - div.content.browse { - padding: 0; margin: 0; - > ul { - min-height: 0; .border_radius(0); - > li { - div.thumbnail { - a.thumbnail { padding: 5px; } - img.marker.media_type { top: 48px; left: 8px; } - } - div.footer { - a.title, a.name { font-size: 11px; font-weight: normal; } - } - } - } - } - - div.content.browse.ads > ul > li { - width: 93px; - > div.thumbnail a.thumbnail { width: 83px; height: 62px; } - } - div.content.browse.brands { - .border_radius(3); - > ul { - background: none; - > li { - width: 52px; - > div.thumbnail { - padding: 3px; - a.thumbnail { width: 42px; height: 42px; padding: 2px; } - } - li.active { background: @accent_colour; } - } - } - } - div.footer { - div.info { float: none; } - div.pagination { float: none; margin: 3px 0 0; } - } - } -} - -/* List Numbers */ -label.list_number { - float: left; background: url('/images/transparent_backgrounds/black_15.png'); padding: 2px; width: 24px; height: 24px; display: block; - .border_radius(99); - b { - display: block; font-weight: bold; font-size: 14px; color: @white; background: @accent_colour; height: 20px; width: 20px; line-height: 20px; - text-align: center; .border_radius(99); .text_shadow(1, 1, 0px, (@accent_colour * 0.75 + @black * 0.25)); - border: 2px solid @white; - } -} -label.list_number.large { - padding: 4px; width: 48px; height: 48px; .border_radius(99); position: relative; left: -10px; - b { - font-size: 28px; height: 40px; width: 40px; .border_radius(99); line-height: 40px; - .text_shadow(2, 2, 0px, (@accent_colour * 0.75 + @black * 0.25)); border-width: 4px; - } -} - -/* Dashboard */ -#dashboard_controller { - #ads { - span.filter.state { float: right; } - } - #sidebar { - #shopping_style div.content { - p.less { display: block; } - p.more { display: none; } - } - #influences { - div.header { - padding-bottom: 0; - ul.tabs { - position: relative; top: 1px; z-index: 3; - li { - margin: 0 5px 0 0; - a { - border: none; background: url('/images/transparent_backgrounds/white_75.png'); - :hover { color: @black; } - } - } - li.active { - a { - background: @white; border: none; - :hover { color: @black; } - } - } - } - } - - div.tab_content { - overflow: hidden; padding: 0; - > ul { - padding: 10px 10px 0; max-height: 280px; min-height: 120px; overflow-y: scroll; .border_radius_bottom(3px); - } - } - div.footer { - form { - p { - margin: 0 0 5px; - img.marker { float: right; margin: 5px 0 0 0; } - span.invitee { - line-height: 26px; padding: 3px 3px 0; font-size: 14px; - small { color: @grey; font-size: 12px; } - } - } - p.indent { margin-left: 36px; } - p.submit { margin-top: 10px; } - } - } - } - } - - div.panel.full { - > div.content { - margin: 0; padding: 0; background: none; - ul { - li { - width: 148px; - div.thumbnail { - img.marker.media_type { top: 90px; } - a.thumbnail { width: 138px; height: 104px; } - } - } - } - } - } - #people { - form { - padding: 0 0 5px; - input { width: 225px; float: left; margin: 0 5px 0 0; } - a.button { height: 23px; line-height: 23px; width: 60px; padding: 0; text-align: center; } - } - } -} - -/* Remove Pages Titles when Browsing */ -#ads_controller, #brands_controller { - #page_title { display: none; } -} - -/* Brands > Show */ -#brands_controller.show { - #ads { - div.filters { - h3 { font-size: 16px; margin: 0; } - span.show { float: right; } - span.filter.dropdown.localisation { float: right; margin: 0 0 0 10px; } - span.filter.state { float: right; margin: 0 0 0 10px; } - } - } -} - -/* FAQ */ -#pages_controller.faq { - #answers { - h3 { margin-top: 20px; padding-top: 20px; border-top: 1px solid (@light_grey * 0.75 + @white * 0.25); } - h3.first { margin-top: 0; padding-top: 0; border: none; } - } - #questions { - div.content { - padding: 20px; - ul { - margin: 0; padding: 0; - li { - margin: 0 0 10px; list-style: none; display: block; padding: 0; - a { font-size: 14px; } - } - li:last-child { - margin: 0; - } - } - } - } -} - -/* Person Overview */ -#person_overview { - padding: 20px 10px; position: relative; z-index: 25; - #person { - float: left; width: 620px; - a.avatar { - display: block; float: left; width: 60px; height: 60px; - img { height: 100%; width: 100%; } - } - > div { - margin: 0 0 0 75px; color: @white; font-size: 14px; .text_shadow(1, 1, 0, @bg * 0.66 + @black * 0.33); - } - div.name { - h2 { - margin: 0 0 5px; display: inline; - a { - font-size: 20px; font-weight: bold; .text_shadow(1, 1, 0, @bg * 0.66 + @black * 0.33); - line-height: 1; color: @white; text-decoration: none; - :hover { text-decoration: underline; } - } - a.button.small { - font-size: 10px; - :hover { text-decoration: none; } - } - } - - span.points { - float: right; display: block; padding: 5px 10px; .border_radius(2); text-align: center; background: @white; position: relative; - min-width: 45px; - strong { color: @black; font-weight: bold; font-size: 24px; line-height: 1; display: block; .text_shadow(0, 0, 0, transparent); } - label { font-size: 9px; text-transform: uppercase; color: @grey; display: block; .text_shadow(0, 0, 0, transparent); font-weight: bold; } - } - span.points.with_redeem { - .border_radius_bottom(0); - a.button { - display: block; text-align: center; .border_radius_top(0); font-size: 10px; font-weight: bold; padding: 0; - position: absolute; height: 18px; left: 0; right: 0; bottom: -19px; line-height: 18px; text-transform: uppercase; border: none; - } - } - div.options { margin: 0; } - } - div.meta { - color: @white * 0.66 + @bg * 0.33; - span { color: @white; } - label { color: @white * 0.66 + @bg * 0.33; } - ul.networks { - display: inline; margin: 0; padding: 0; - li { - display: inline; line-height: 1; - img { position: relative; vertical-align: middle; top: -1px; } - } - } - } - - div.extra { - font-size: 12px; margin-top: 20px; margin-bottom: 20px; - span.toggle { - .text_shadow(1, 1, 0, @bg * 0.66 + @black * 0.33); - a { font-size: 10px; font-weight: bold; text-transform: uppercase; text-decoration: none; color: @accent_colour; } - b.arrow { display: inline-block; width: 0; height: 0; border: 5px solid transparent; position: relative; top: -2px; } - } - #less_info { - span.toggle { - b.arrow { border-top: 5px solid @accent_colour; border-bottom: 0; } - } - } - #more_info { - span.toggle { - float: right; - b.arrow { border-bottom: 5px solid @accent_colour; border-top: 0; } - } - h4 { - color: @white; margin: 0 0 10px 0; border-bottom: 1px solid (@white * 0.25 + @bg * 0.75); .text_shadow(1, 1, 0, @bg * 0.66 + @black * 0.33); - span { font-size: 12px; } - } - p { - margin: 0 0 5px; - label { display: block; float: left; width: 120px; color: @white * 0.66 + @bg * 0.33; } - span { display: block; margin: 0 0 0 130px; } - } - p:last-child { margin: 0; } - - } - } - div.login { - margin: 0 0 0 75px; - a.button { font-weight: bold; } - } - } -} - -/* Dashboard Nav */ -#dashboard_nav { - position: absolute; bottom: 0; left: 10px; margin: 0; padding: 0; overflow: hidden; - li { - display: block; float: left; margin: 0 5px 0 0; - a { - display: block; height: 28px; padding: 0 10px; line-height: 28px; .border_radius_top(2); - text-decoration: none; color: @white; background: url('/images/transparent_backgrounds/accent_colour_30.png'); font-size: 14px; - font-weight: bold; - :hover { background: url('/images/transparent_backgrounds/accent_colour_45.png'); } - } - } - li.active { - a { - background: @white; color: @black; - :hover { color: @black; } - } - } -} - -/* Dwellometer */ -#dwellometer { - z-index: 45; float: right; .box_shadow(0, 0, 0, transparent); margin: 0; - div.content { - text-align: center; position: relative; - object, object embed { position: relative; z-index: 46; line-height: 0; } - div.title { - position: absolute; bottom: 10px; left: 0; right: 0; z-index: 50; - img { width: 120px; display: block; margin: 0 auto; position: relative; left: -5px; } - } - } -} - -/* Activity Stream */ -#activity { - div.content { - ul.events { - padding: 0; margin: 0 0 -10px; - li { - margin: 0; padding: 10px 0; border-bottom: 1px solid (@light_grey * 0.33 + @white * 0.66); - list-style: none; overflow: hidden; - small.meta { - font-size: 12px; color: @light_grey; float: right; - } - a.button { float: right; margin: 0 0 10px 10px; } - a.avatar, a.logo, a.thumbnail { - height: 32px; display: block; float: left; - img { width: 100%; height: 100%; } - } - a.avatar, a.logo, a.icon { width: 32px; } - a.thumbnail { width: 42px; } - div.symbols { - float: left; overflow: hidden; - b { - display: block; float: left; margin: 10px 5px 0; - img { height: 12px; width: 12px; } - } - b.voted { margin: 10px 3px 0; padding: 2px; .border_radius(2); } - b.voted.for { background: @colour_positive * 0.33 + @white * 0.66; } - b.voted.against { background: @colour_negative * 0.33 + @white * 0.66; } - } - /* Temporarily removed avatar and symbol */ -/* div.symbols a.agent, b { display: none; }*/ - div.description { - font-size: 12px; color: @grey; - a.agent { font-weight: bold; } - } - div.comment { - margin-top: 2px; - b.tail { - display: block; margin: 0 0 0 10px; width: 0; height: 0; border: 5px solid transparent; - border-top: none; border-bottom: 5px solid (@light_grey * 0.25 + @white * 0.75); - } - blockquote { - margin: 0; font-style: normal; color: @dark_grey; - .border_radius(3); background: @light_grey * 0.25 + @white * 0.75; padding: 5px 10px; - span.view_comment { - color: @grey; - } - } - } - div.content { - overflow: hidden; - } - } - li.new_comment.ad, li.endorsed.ad, li.voted { - div.description, div.content { margin-left: 106px; } -/* div.description, div.content { margin-left: 53px; }*/ - } - li.new_comment.brand, li.replied_to, li.endorsed.brand, li.connected, li.sn_setup { - div.description, div.content { margin-left: 96px; } -/* div.description, div.content { margin-left: 43px; }*/ - } - li.replied_to { - div.content { - a.thumbnail, a.logo { margin-top: 7px; } - } - } - li.replied_to.ad { - div.content { - div.comment { margin-left: 52px; } - } - } - li.replied_to.brand { - div.content { - div.comment { margin-left: 42px; } - } - } - li.voted div.description span.action { .border_radius(2); color: @dark_grey; padding: 0 3px; white-space: nowrap; } - li.voted.for div.description span.action { background: @colour_positive * 0.15 + @white * 0.85; } - li.voted.against div.description span.action { background: @colour_negative * 0.15 + @white * 0.85; } - li:first-child { padding-top: 0; } - li:last-child { border-bottom: none; } - li:hover div.content div.comment blockquote span.view_comment { - } - } - } -} - -/* Login/Register Modal */ -#login_register { - div.location_select, - div.location_search { margin-left: 130px; } - h3 { - small { font-size: 14px; font-weight: normal; display: block; color: @grey; text-align: left; margin: 0; display: block; } - } -} - -/* Contact Form in Pages */ -#pages_controller { - #sidebar { - #contact { - margin: 15px 0 0; - form { - label { text-align: left; float: none; width: auto; font-size: 12px; font-weight: bold; line-height: 1; margin: 0 0 5px; } - p.submit.indent { - margin: 0; - span.with_cancel { display: none; } - } - } - } - } -} - -/* Exclusive Offers */ -#offers { - div.content { - a.gift { - display: block; text-align: center; - img { height: 100px; } - } - } -} - -div.browse { - margin: 0 0 20px; - &.class { - padding: 0; - } - div.header { - padding: 10px 10px 9px; text-align: left; background: @bg url('/images/panel_header_bg.png') repeat-x top left; - border-bottom: 1px solid (@bg * 0.66 + @black * 0.33); line-height: 1; height: 18px; - .border_radius_top(3); color: @light_grey; - h3 { font-size: 16px; margin: 0; color: @white; .text_shadow(1, 1, 0, @bg * 0.66 + @black * 0.33); } - span.filter { - float: left; display: block; overflow: hidden; position: relative; z-index: 5; - a { - margin: 0 1px 0 0; display: block; float: left; padding: 0 8px; height: 18px; font-weight: bold; font-size: 10px; line-height: 18px; - text-transform: uppercase; background: url('/images/transparent_backgrounds/black_50.png'); color: @light_grey; text-decoration: none; position: relative; z-index: 3; - .active { - background: @white; color: @black; z-index: 4; - :hover { color: @black; } - } - :hover { color: @white; } - :first-child { .border_radius_left(2); } - :last-child { .border_radius_right(2); margin-right: 0; } - } - } - - span.filter.dropdown { - margin: 0; position: relative; overflow: visible; - a { - .border_radius(2); background: @white; color: @black; margin: 0; position: relative; padding-right: 25px; - img { float: left; margin: 4px 5px 0 0; } - b.arrow { - float: right; display: block; height: 0; width: 0; border: 5px solid transparent; border-top: 5px solid @black; border-bottom: none; - position: absolute; top: 6px; right: 10px; - } - :hover { - background: @accent_colour; color: @white; - b.arrow { border-top: 5px solid @white; } - } - } - ul { - position: absolute; top: 100%; left: 0; margin: 1px 0 0; padding: 0; background: @white; .border_radius(2); - .box_shadow(0, 1, 1, @black); - li { - list-style: none; display: block; padding: 0; margin: 0; - a { - display: block; height: 18px; line-height: 18px; color: @black; font-size: 10px; text-transform: uppercase; background: transparent; - border-bottom: 1px solid (@light_grey * 0.66 + @white * 0.33); float: none; margin: 0; .border_radius(0); white-space: nowrap; - :hover { background: url('/images/transparent_backgrounds/accent_colour_25.png'); color: @black; } - } - :last-child { - a { border: none; } - } - } - } - } - span.filter.dropdown.sort { float: left; margin: 0 0 0 10px; } - span.filter.dropdown.localisation { float: left; margin: 0 0 0 10px; } - a.more { - float: right; color: @white; .text_shadow(1, 1, 0, @bg * 0.66 + @black * 0.33); font-size: 14px; font-weight: bold; - position: relative; top: 2px; - :hover { text-decoration: none; } - } - } - > ul { - margin: 0; background: @white; padding: 10px 0 0 10px; .border_radius(3); position: relative; - li { - display: block; float: left; list-style: none; margin: 0 10px 10px 0; padding: 5px; position: relative; - background: @white; width: 130px; border: 1px solid (@light_grey * 0.33 + @white * 0.66); .border_radius(2); - a.remove { - position: absolute; height: 16px; width: 16px; padding: 3px; background: @accent_colour; - .border_radius(99); display: none; z-index: 3; top: -8px; right: -8px; - img { vertical-align: middle; } - } - div.thumbnail { - .border_radius_top(3); position: relative; z-index: 3; - .marker { - position: absolute; padding: 2px; .border_radius(2); z-index: 3; - background: url('/images/transparent_backgrounds/white_75.png'); height: 12px; width: 12px; - } - .marker.coupon { - height: auto; width: auto; top: 10px; right: -3px; padding: 0; background: transparent; overflow: hidden; position: absolute; - b { - display: block; height: 0; width: 0; float: left; border: 14px solid transparent; border-top: 14px solid @accent_colour; - border-bottom: none; border-right: none; float: left; - } - span { - color: @white; font-size: 10px; font-weight: bold; text-transform: uppercase; height: 14px; line-height: 14px; display: block; - padding: 0 4px 0 2px; background: @accent_colour; .text_shadow(1, 1, 0px, (@accent_colour * 0.75 + @black * 0.25)); margin: 0 0 0 14px; - } - } - .marker.video { - position: absolute; left: 50%; top: 50%; background: @white; width: 10px; height: 10px; - b { display: block; width: 0; height: 0; border: 5px solid transparent; border-left: 10px solid @black; border-right: none; } - } - .marker.endorsed_by_me { background: none; padding: 0; right: 0; bottom: -32px; .border_radius(2); background: @white; } - a.thumbnail { - display: block; overflow: hidden; position: relative; text-align: center; - img { position: relative; display: block; margin: auto; } - } - } - div.text { - margin: 3px 0 0; display: block; - a { text-decoration: none; } - a.title { - display: block; text-decoration: none; font-weight: bold; font-size: 12px; line-height: 16px; - white-space: nowrap; height: 16px; overflow: hidden; - :before { - display: block; height: 32px; width: 20px; content: " "; float: right; right: -15px; top: -8px; - background: @white; position: relative; z-index: 1; .box_shadow(-5, 0, 10, @white); - } - } - small { - font-size: 11px; line-height: 13px; color: @grey; display: block; height: 13px; overflow: hidden; white-space: nowrap; - a { font-weight: bold; } - :before { - display: block; height: 32px; width: 20px; content: " "; float: right; right: -15px; top: -8px; - background: @white; position: relative; z-index: 1; .box_shadow(-5, 0, 10, @white); - } - } - } - :hover { - background: @accent_colour; - a.remove { display: block; } - div.thumbnail { - a.marker.remove, a.marker.video { - b { display: inline-block; } - } - a.marker.video { .box_shadow(0, 0, 2, @black); } - } - div.text { - a { color: @white; } - a.title:before { background: @accent_colour; .box_shadow(-5, 0, 10, @accent_colour); } - small { - color: @white * 0.75 + @accent_colour * 0.25; - :before { background: @accent_colour; .box_shadow(-5, 0, 10, @accent_colour); } - } - } - div.footer a { color: @white; } - } - } - > li.ad div.thumbnail a.thumbnail { - width: 130px; height: 97px; - img { width: 100%; height: 100%; } - } - > li.brand div.thumbnail a.thumbnail { - width: 120px; height: 87px; padding: 5px; background: @white; .border_radius(2); - img { max-width: 120px; max-height: 87px; } - } - li.paginate { - margin-bottom: 0; - a { - display: block; position: relative; text-decoration: none; height: 131px; - div.arrow { - background: #81c153 url('/images/button_bg.png') repeat-x left top; border: 1px solid (@accent_colour * 0.75 + @black * 0.25); - height: 44px; .border_radius(99); width: 44px; margin: 0 auto; position: relative; top: 32px; - b { text-indent: -9000px; display: block; border: 10px solid transparent; width: 0; height: 0; position: relative; top: 12px; } - } - div.label { - position: absolute; bottom: 5px; left: 0; right: 0; line-height: 13px; - color: @accent_colour * 0.85 + @black * 0.15; text-decoration: none; - font-weight: bold; font-size: 12px; text-align: center; - } - :hover { - div.arrow { background: #abd56e url('/images/button_bg.png') repeat-x left -44px; } - } - } - :hover { background: transparent; } - } - li.paginate.previous a div b { border-right: 15px solid @white; border-left: none; left: 12px; } - li.paginate.next a div b { border-left: 15px solid @white; border-right: none; left: 16px; } - } - > div.footer { - padding: 9px 10px 10px; background: @light_grey * 0.75 + @white * 0.25; overflow: hidden; - border-top: 1px solid @light_grey; .border_radius_bottom(3); - div.info { - float: left; color: @grey; - strong { color: @black; font-weight: normal; } - } - div.pagination { - float: right; - > * { - display: inline-block; line-height: 1; padding: 0 6px; line-height: 18px; height: 18px; background: @white; - .border_radius(3); text-decoration: none; font-weight: bold; - font-size: 10px; text-transform: uppercase; - } - a { color: @grey; } - a:hover { color: @black; } - span.disabled { color: @light_grey; } - span.current { color: @white; background: @bg; border: none; } - span.current:hover { color: @white; } - } - } -} -div.browse.with_categories { margin: 0 0 0 160px; } -div.browse.with_options > ul { .border_radius_top(0); } -div.browse.with_footer > ul { .border_radius_bottom(0); } -/* Browse List */ -div.browse.list { -> ul { - margin: 0; min-height: 320px; - padding: 10px 0 0 10px; overflow: hidden; - > li { - display: block; list-style: none; margin: 0 10px 10px 0; padding: 5px; - .border_radius(3); position: relative; line-height: normal; - .marker { - position: absolute; padding: 2px; .border_radius(2); - background: url('/images/transparent_backgrounds/white_75.png'); - img { height: 12px; width: 12px; } - } - img.marker { height: 12px; width: 12px; } - span.marker.new { - color: black; left: -5px; top: -5px; background: none; background-color: @white * 0.1 + @yellow * 0.6 + @red * 0.3; line-height: 1; padding: 2px 5px; - font-weight: bold; - } - a.marker.media_type { - display: inline-block; text-decoration: none; top: 39px; left: 8px; - font-size: 10px; - b { font-weight: normal; margin: 0 0 0 2px; line-height: 1; display: none; } - img { vertical-align: middle; } - } - a.thumbnail { - float: left; - width: 68px; display: block; overflow: hidden; - border: 1px solid @light_grey; - :hover { border-color: @accent_colour; } - } - span.title_brand { - display: block; margin: 0 0 2px 75px; - a { margin: 0; display: inline; } - a.brand_name { font-weight: normal; font-size: 12px; } - } - a.ad_title { - font-weight: bold; font-size: 14px; margin: 0 0 0 75px; display: block; - } - a.brand_name { - font-weight: bold; font-size: 14px; margin: 0 0 0 75px; display: block; - } - small { - display: block; color: @grey; margin: 0 0 0 75px; font-size: 12px; - } - small.brand_name { display: inline; margin: 0; } - ul.chart { - margin: 0 0 0 80px; - height: 39px; - } - ul.networks { - margin: 3px 0 0 75px; padding: 0; overflow: hidden; - li { display: block; float: left; margin: 0 5px 0 0; line-height: 1; } - } - div.points { - display: none; - font-size: 12px; text-align: right; - label { color: @grey; } - } - a.remove { bottom: -3px; right: -3px; } - } - li.ad { - a.thumbnail { height: 51px; } - span.title_brand { - small.brand_name { - display: block; - } - } - } - li.brand { - a.thumbnail { height: 68px; } - } - } -} -div.browse.list.with_options ul { .border_radius_top(0); } -div.browse.list.with_footer ul { .border_radius_bottom(0); } -div.browse.list.cols_2 { - > ul { - > li { - width: 285px; float: left; - :hover { - background: @white; - } - } - } -} -div.browse.ads.list { - > ul { - > li { - height: 53px; - a.thumbnail { - height: 51px; - } - } - } -} -div.browse.brands.list { - > ul { - > li { - height: 68px; - a.thumbnail { - height: 66px; - } - } - } -} - -/* Categories List */ -#categories { - margin: 40px 0 0; width: 160px; float: left; position: relative; z-index: 1; - ul { - margin: 0; padding: 10px 0 0; - li { - list-style: none; margin: 0; padding: 0; font-size: 14px; - a { color: @grey; display: block; padding: 5px 10px 5px 15px; text-decoration: none; .border_radius_left(3); } - a:hover { color: @black; background: @light_grey * 0.15 + @white * 0.85; } - } - .all a { font-weight: bold; } - .current a { - background: @white; color: @black; border: 1px solid (@light_grey * 0.25 + @white * 0.75); border-right: none; border-left: 5px solid @bg; - padding-left: 10px; - } - } -} - -/* Ads > Show */ -#ad { - div.header { - overflow: hidden; - h3 { font-size: 16px; margin: 0 0 3px; } - small { - a.category { font-weight: bold; color: @accent_colour; } - span.networks img { position: relative; top: 3px; } - } - span.brand { - float: right; color: @white; - a.brand_name { font-weight: bold; color: @accent_colour; } - } - } - div.content { - padding: 0; position: relative; - a.toggle_size { - display: block; .border_radius(3); background-color: @black; padding: 0 5px 0 26px; - background-position: 5px center; background-repeat: no-repeat; text-decoration: none; margin: 5px 5px 0 0; - position: absolute; top: 0; right: 0; line-height: 25px; z-index: 45; - } - img.creative { margin: 0 auto; max-width: 540px; display: block; } - object { position: relative; z-index: 44; } - object.video { line-height: 0; font-size: 0; } - object embed { position: relative; z-index: 45; line-height: 0; font-size: 0; } - } - div.content.not_video { - padding: 40px; text-align: center; - * { margin-left: auto; margin-right: auto; } - object.flash { margin-bottom: 0; } - } - div.footer { - padding: 0; - div.vote_views { - padding: 5px 10px; overflow: hidden; - div.share { float: right; margin: 2px 0 0 0; } - #login_register_msg, #encourage_vote_msg { line-height: 22px; font-weight: bold; color: @black; } - } - } -} -#sidebar { - #meta { - table { - margin: 0; - tr:last-child td { padding-bottom: 0; } - td { - padding: 0 0 5px; - ul.networks { - margin: 0; padding: 0; - li { - list-style: none; display: inline; - } - li { - } - } - } - td.label { color: @grey; white-space: nowrap; width: 1%; text-align: right; padding-right: 5px; } - } - } -} - -/* Voting */ -div.voted { - font-size: 12px; line-height: 22px; color: @black; display: inline-block; font-weight: bold; - img { float: left; margin-right: 5px; padding: 3px; .border_radius(3); } -} -#voted_up { - img { background: @colour_positive * 0.66 + @bg * 0.15; } -} -#voted_down { - img { background: @colour_negative * 0.66 + @bg * 0.15; } -} -#encourage_comment { - display: inline-block; line-height: 22px; font-weight: bold; -} -#vote { - overflow: hidden; font-size: 12px; line-height: 22px; color: @black; float: left; - a { - color: @white; font-weight: bold; overflow: hidden; display: block; - width: 16px; text-decoration: none; text-align: center; font-size: 10px; padding: 3px; text-transform: uppercase; - } - a.up { - float: left; background: @colour_positive * 0.66 + @bg * 0.15; .border_radius_left(3); - :hover { background: @colour_positive * 0.85 + @bg * 0.15; } - } - a.down { - float: left; background: @colour_negative * 0.66 + @bg * 0.15; .border_radius_right(3); - margin: 0 5px 0 1px; - :hover { background: @colour_negative * 0.85 + @bg * 0.15; } - } -} -#vote.disabled { - a.up { - background: (@colour_positive * 0.66 + @bg * 0.15) * 0.15 + @grey * 0.85; - :hover { background: (@colour_positive * 0.85 + @bg * 0.15) * 0.25 + @grey * 0.75; } - } - a.down { - background: (@colour_negative * 0.66 + @bg * 0.15) * 0.15 + @grey * 0.85; - :hover { background: (@colour_negative * 0.85 + @bg * 0.15) * 0.25 + @grey * 0.75; } - } -} -#sidebar { - #ads > ul li, #recommendations > ul li { - width: 81px; - div.thumbnail { - a.thumbnail { height: 60px; width: 81px; } - } - div.text { - a.title { font-size: 11px; height: 14px; line-height: 14px; } - small { display: none; } - } - } - #brands > ul li { - width: 55px; - div.thumbnail { - a.thumbnail { - height: 45px; width: 45px; - img { max-height: 45px; max-width: 45px; } - } - } - div.text { display: none; } - } -} - -/* My Account */ -#accounts_controller { - #top { - #page_title { - #page_options { - a.button.public_profile { - float: right; font-size: 16px; line-height: 1; height: auto; padding: 8px 35px 8px 15px; position: relative; - b.arrow { display: block; height: 0; width: 0; position: absolute; top: 10px; right: 15px; border: 6px solid transparent; border-right: none; border-left: 6px solid @white; margin: 0; } - } - a.button.goto_dashboard { - float: right; font-size: 16px; line-height: 1; height: auto; padding: 8px 15px 8px 35px; margin-right: 5px; position: relative; - b.arrow { display: block; height: 0; width: 0; position: absolute; top: 10px; left: 15px; border: 6px solid transparent; border-left: none; border-right: 6px solid @white; margin: 0; } - } - } - } - } - #account_nav { - float: left; width: 200px; margin: 0 20px 0 0; - ul.nav { - margin: 0; padding: 0; - li { - margin: 0 0 5px; display: block; list-style: none; padding: 0; - a { - display: block; height: 30px; text-decoration: none; color: @white; - b { - border: 15px solid transparent; border-right: none; border-left: 10px solid transparent; width: 0; - height: 0; float: right; display: none; - } - span { - .border_radius(3); background: @bg; display: block; - line-height: 30px; padding: 0 10px; font-size: 14px; font-weight: bold; margin: 0 10px 0 0; - } - } - :hover { - a { - color: @white; - b { border-left-color: @bg; display: block; } - span { background: @bg; .border_radius_right(0); } - } - } - } - li.current a { - b { border-left-color: @accent_colour; display: block; } - span { background: @accent_colour; color: @white; .border_radius_right(0); } - } - } - } - #main { - > div { - margin: 0 0 20px; - form { margin: 0; } - } - #profile { - a.avatar { - float: left; display: block; - width: 70px; overflow: hidden; position: relative; text-decoration: none; - img { width: 100%; } - span { - display: block; line-height: 1; padding: 3px; margin: 5px 0 0; color: @white; background: @accent_colour; - .border_radius(3); .text_shadow(1, 1, 0, @grey); - text-align: center; font-size: 10px; font-weight: bold; text-transform: uppercase; - } - } - form { - margin: 0 0 0 90px; - h4 { margin: 10px 0 20px; border-bottom: 1px solid (@light_grey * 0.5 + @white * 0.5); padding: 0; color: @bg; font-size: 16px; } - ul.choices { - li { width: 30%; } - } - div.extra { margin-top: 20px; } - } - } - - #networks { - ul { margin: 0 -10px -10px 0; padding: 0; overflow: hidden; - li:hover - { - background: @light_grey; display: block; float: left; width: 180px; - padding: 10px; margin: 0 10px 10px 0; list-style: none; .border_radius(3); - position: relative; - * { line-height: normal; } - img { vertical-align: middle; float: left; } - .name { font-weight: bold; font-size: 14px; display: block; margin: -2px 0 0 42px; } - small { - font-size: 12px; color: @grey; display: block; margin-left: 42px; - strong { color: @black; font-weight: normal; } - } - :hover { - } - } - li.installed { - background: @white; - border: 2px solid @accent_colour; padding: 8px; - } - li.unavailable { - .name { color: @black; } - :hover { - background: @light_grey; - } - } - li:hover { - background: @light_grey * 0.5 + @white * 0.5; - } - } - } - } -} - -/* Shopping Style Panel */ -#shopping_style { - div.header a.button.small { float: right; } - div.content { - p { - margin: 0 0 10px; - label { text-transform: uppercase; font-size: 11px; display: block; color: @bg; font-weight: bold; } - span { color: @black; } - span.toggle { white-space: nowrap; color: @grey; } - :last-child { margin: 0; } - } - p.more { text-align: left; font-weight: normal; } - p.less { display: none; margin: 0; } - } -} - -/* People Controller */ -#people_controller.index { - #main { - div.panel { - float: left; width: 300px; margin: 0 20px 0 0; - :last-child { margin-right: 0; } - } - } -} -#people_controller.show { - #person_overview, #shopping_style { - a.button.small { - } - } - #content { - #shopping_style { - float: left; width: 240px; margin: 0 20px 0 0; - } - #main { width: 360px; } - } -} - -/* Search Results */ -#search_results { - margin: 0 0 20px; - li { - :hover { - small { color: @white * 0.75 + @accent_colour * 0.25; } - } - } -} -#search { - div.content { - padding: 20px; - form { - margin: 0; float: none; - span.submit_and_options { - display: block; - } - } - p { margin: 0 0 15px; } - h4 { font-weight: normal; margin: 0 0 5px; } - } -} - -/* Recommendations */ -#recommendations { - div.browse { - margin: 0; padding: 0; background: none; - ul { min-height: 0; .border_radius(0); } - } -} - -/* Blank States */ -div.blank { - padding: 20px; background: @bg * 0.05 + @blue * 0.05 + @white * 0.9; position: relative; - border: 1px solid (@bg * 0.1 + @blue * 0.1 + @white * 0.8); z-index: 1; - h4 { font-size: 18px; margin: 0 0 10px; } - h4:last-child { margin: 0; } - p { font-size: 16px; margin: 0 0 10px; } - p:last-child { margin: 0; } - p.with_list_number.large { - span { margin-left: 48px; display: block; color: @white; } - } - p.earn span { font-size: 22px; color: @white; line-height: 48px; font-weight: bold; } - a { white-space: nowrap; } - a.hide { - position: absolute; top: -5px; right: -5px; display: block; height: 16px; width: 16px; padding: 3px; background: #E7E9F6; .border_radius(99); - } -} - -div.blank.small { - padding: 10px 20px; - h4 { font-weight: normal; font-size: 16px; } - p { margin: 0; } -} -div.blank.tiny { - padding: 10px 20px; - h4 { font-weight: normal; font-size: 14px; } - p { margin: 0; font-size: 12px; } -} -div.blank.rounded { - .border_radius(3); margin: 0 0 20px; -} -div.blank.rounded.bottom { .border_radius_top(0); } -div.blank.with_border_bottom { border-bottom: 1px solid (@bg * 0.1 + @blue * 0.1 + @white * 0.8); } -div.blank.no_border_top { border-top: none; } -div.blank.no_border_bottom { border-bottom: none; } -div.blank.no_side_borders { border-right: none; border-left: none; } -div.panel { - div.blank { - padding: 10px 20px; overflow: hidden; margin: 0; - h4 { font-weight: normal; font-size: 14px; } - p, ul { margin: 0 0 10px; font-size: 12px; } - p:last-child, ul:last-child { margin: 0; } - } -} - -#yelow { - #short { - color: #fea; - } - #long { - color: #ffeeaa; - } - #rgba { - color: rgba(255, 238, 170, 0.1); - } -} - -#blue { - #short { - color: #00f; - } - #long { - color: #0000ff; - } - #rgba { - color: rgba(0, 0, 255, 0.1); - } -} - -#overflow { - .a { color: #111111 - #444444; } // #000000 - .b { color: #eee + #fff; } // #ffffff - .c { color: #aaa * 3; } // #ffffff - .d { color: #00ee00 + #009900; } // #00ff00 -} - -#grey { - color: rgb(200, 200, 200); -} - -#808080 { - color: hsl(50, 0%, 50%); -} - -#00ff00 { - color: hsl(120, 100%, 50%); -} -/******************\ -* * -* Comment Header * -* * -\******************/ - -/* - - Comment - -*/ - -/* - * Comment Test - * - * - cloudhead (http://cloudhead.net) - * - */ - -//////////////// -@var: "content"; -//////////////// - -/* Colors - * ------ - * #EDF8FC (background blue) - * #166C89 (darkest blue) - * - * Text: - * #333 (standard text) // A comment within a comment! - * #1F9EC9 (standard link) - * - */ - -/* @group Variables -------------------- */ -#comments /* boo */ { - /**/ // An empty comment - color: red; /* A C-style comment */ - background-color: orange; // A little comment - font-size: 12px; - - /* lost comment */ content: @var; - - border: 1px solid black; - - // padding & margin // - padding: 0; - margin: 2em; -} // - -/* commented out - #more-comments { - color: grey; - } -*/ - -#last { color: blue } -// -.comma-delimited { - background: url(bg.jpg) no-repeat, url(bg.png) repeat-x top left, url(bg); - text-shadow: -1px -1px 1px red, 6px 5px 5px yellow; - -moz-box-shadow: 0pt 0pt 2px rgba(255, 255, 255, 0.4) inset, - 0pt 4px 6px rgba(255, 255, 255, 0.4) inset; -} -@font-face { - font-family: Headline; - src: local(Futura-Medium), - url(fonts.svg#MyGeometricModern) format("svg"); -} -.other { - -moz-transform: translate(0, 11em) rotate(-90deg); -} -p:not([class*="lead"]) { - color: black; -} - -input[type="text"].class#id[attr=32]:not(1) { - color: white; -} - -div#id.class[a=1][b=2].class:not(1) { - color: white; -} - -ul.comma > li:not(:only-child)::after { - color: white; -} - -ol.comma > li:nth-last-child(2)::after { - color: white; -} - -li:nth-child(4n+1), -li:nth-child(-5n), -li:nth-child(-n+2) { - color: white; -} - -a[href^="http://"] { - color: black; -} - -a[href$="http://"] { - color: black; -} - -form[data-disabled] { - color: black; -} - -p::before { - color: black; -} -@charset "utf-8"; -div { color: black; } -div { width: 99%; } - -* { - min-width: 45em; -} - -h1, h2 > a > p, h3 { - color: none; -} - -div.class { - color: blue; -} - -div#id { - color: green; -} - -.class#id { - color: purple; -} - -.one.two.three { - color: grey; -} - -@media print { - font-size: 3em; -} - -@media screen { - font-size: 10px; -} - -@font-face { - font-family: 'Garamond Pro'; - src: url("/fonts/garamond-pro.ttf"); -} - -a:hover, a:link { - color: #999; -} - -p, p:first-child { - text-transform: none; -} - -q:lang(no) { - quotes: none; -} - -p + h1 { - font-size: 2.2em; -} - -#shorthands { - border: 1px solid #000; - font: 12px/16px Arial; - margin: 1px 0; - padding: 0 auto; - background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px; -} - -#more-shorthands { - margin: 0; - padding: 1px 0 2px 0; - font: normal small/20px 'Trebuchet MS', Verdana, sans-serif; -} - -.misc { - -moz-border-radius: 2px; - display: -moz-inline-stack; - width: .1em; - background-color: #009998; - background-image: url(images/image.jpg); - background: -webkit-gradient(linear, left top, left bottom, from(red), to(blue)); - margin: ; -} - -#important { - color: red !important; - width: 100%!important; - height: 20px ! important; -} - -#functions { - @var: 10; - color: color("evil red"); // #660000 - width: increment(15); - height: undefined("self"); - border-width: add(2, 3); - variable: increment(@var); -} - -#built-in { - @r: 32; - escaped: e("-Some::weird(#thing, y)"); - lighten: lighten(#ff0000, 50%); - darken: darken(#ff0000, 50%); - saturate: saturate(#29332f, 20%); - desaturate: desaturate(#203c31, 20%); - greyscale: greyscale(#203c31); - format: %("rgb(%d, %d, %d)", @r, 128, 64); - format-string: %("hello %s", "world"); - eformat: e(%("rgb(%d, %d, %d)", @r, 128, 64)); -} - -@var: @a; -@a: 100%; - -.lazy-eval { - width: @var; -} -.mixin (@a: 1px, @b: 50%) { - width: @a * 5; - height: @b - 1%; -} - -.mixina (@style, @width, @color: black) { - border: @width @style @color; -} - -.mixiny -(@a: 0, @b: 0) { - margin: @a; - padding: @b; -} - -.hidden() { - color: transparent; -} - -.two-args { - color: blue; - .mixin(2px, 100%); - .mixina(dotted, 2px); -} - -.one-arg { - .mixin(3px); -} - -.no-parens { - .mixin; -} - -.no-args { - .mixin(); -} - -.var-args { - @var: 9; - .mixin(@var, @var * 2); -} - -.multi-mix { - .mixin(2px, 30%); - .mixiny(4, 5); -} - -.maxa(@arg1: 10, @arg2: #f00) { - padding: @arg1 * 2px; - color: @arg2; -} - -body { - .maxa(15); -} - -@glob: 5; -.global-mixin(@a:2) { - width: @glob + @a; -} - -.scope-mix { - .global-mixin(3); -} - -.nested-ruleset (@width: 200px) { - width: @width; - .column { margin: @width; } -} -.content { - .nested-ruleset(600px); -} - -// - -.same-var-name2(@radius) { - radius: @radius; -} -.same-var-name(@radius) { - .same-var-name2(@radius); -} -#same-var-name { - .same-var-name(5px); -} - -// - -.var-inside () { - @var: 10px; - width: @var; -} -#var-inside { .var-inside; } -.mix-inner (@var) { - border-width: @var; -} - -.mix (@a: 10) { - .inner { - height: @a * 10; - - .innest { - width: @a; - .mix-inner(@a * 2); - } - } -} - -.class { - .mix(30); -} -.mixin () { - zero: 0; -} -.mixin (@a: 1px) { - one: 1; -} -.mixin (@a) { - one-req: 1; -} -.mixin (@a: 1px, @b: 2px) { - two: 2; -} - -.mixin (@a, @b, @c) { - three-req: 3; -} - -.mixin (@a: 1px, @b: 2px, @c: 3px) { - three: 3; -} - -.zero { - .mixin(); -} - -.one { - .mixin(1); -} - -.two { - .mixin(1, 2); -} - -.three { - .mixin(1, 2, 3); -} - -// - -.mixout ('left') { - left: 1; -} - -.mixout ('right') { - right: 1; -} - -.left { - .mixout('left'); -} -.right { - .mixout('right'); -} - -// - -.border (@side, @width) { - color: black; - .border-side(@side, @width); -} -.border-side (left, @w) { - border-left: @w; -} -.border-side (right, @w) { - border-right: @w; -} - -.border-right { - .border(right, 4px); -} -.border-left { - .border(left, 4px); -} - -// - - -.border-radius (@r) { - both: @r * 10; -} -.border-radius (@r, left) { - left: @r; -} -.border-radius (@r, right) { - right: @r; -} - -.only-right { - .border-radius(33, right); -} -.only-left { - .border-radius(33, left); -} -.left-right { - .border-radius(33); -} -.mixin { border: 1px solid black; } -.mixout { border-color: orange; } -.borders { border-style: dashed; } - -#namespace { - .borders { - border-style: dotted; - } - .biohazard { - content: "death"; - .man { - color: transparent; - } - } -} -#theme { - > .mixin { - background-color: grey; - } -} -#container { - color: black; - .mixin; - .mixout; - #theme > .mixin; -} - -#header { - .milk { - color: white; - .mixin; - #theme > .mixin; - } - #cookie { - .chips { - #namespace .borders; - .calories { - #container; - } - } - .borders; - } -} -.secure-zone { #namespace .biohazard .man; } -.direct { - #namespace > .borders; -} -#operations { - color: #110000 + #000011 + #001100; // #111111 - height: 10px / 2px + 6px - 1px * 2; // 9px - width: 2 * 4 - 5em; // 3em - .spacing { - height: 10px / 2px+6px-1px*2; - width: 2 * 4-5em; - } - substraction: 20 - 10 - 5 - 5; // 0 - division: 20 / 5 / 4; // 1 -} - -@x: 4; -@y: 12em; - -.with-variables { - height: @x + @y; // 16em - width: 12 + @y; // 24em - size: 5cm - @x; // 1cm -} - -@z: -2; - -.negative { - height: 2px + @z; // 0px - width: 2px - @z; // 4px -} - -.shorthands { - padding: -1px 2px 0 -4px; // -} - -.colors { - color: #123; // #112233 - border-color: #234 + #111111; // #334455 - background-color: #222222 - #fff; // #000000 - .other { - color: 2 * #111; // #222222 - border-color: #333333 / 3 + #111; // #222222 - } -} -.parens { - @var: 1px; - border: (@var * 2) solid black; - margin: (@var * 1) (@var + 2) (4 * 4) 3; - width: (6 * 6); - padding: 2px (6px * 6px); -} - -.more-parens { - @var: (2 * 2); - padding: (2 * @var) 4 4 (@var * 1px); - width: (@var * @var) * 6; - height: (7 * 7) + (8 * 8); - margin: 4 * (5 + 5) / 2 - (@var * 2); - //margin: (6 * 6)px; -} - -.nested-parens { - width: 2 * (4 * (2 + (1 + 6))) - 1; - height: ((2+3)*(2+3) / (9-4)) + 1; -} - -.mixed-units { - margin: 2px 4em 1 5pc; - padding: (2px + 4px) 1em 2px 2; -} -#first > .one { - > #second .two > #deux { - width: 50%; - #third { - &:focus { - color: black; - #fifth { - > #sixth { - .seventh #eighth { - + #ninth { - color: purple; - } - } - } - } - } - height: 100%; - } - #fourth, #five, #six { - color: #110000; - .seven, .eight > #nine { - border: 1px solid black; - } - #ten { - color: red; - } - } - } - font-size: 2em; -} -@x: blue; -@z: transparent; -@mix: none; - -.mixin { - @mix: #989; -} - -.tiny-scope { - color: @mix; // #989 - .mixin; -} - -.scope1 { - @y: orange; - @z: black; - color: @x; // blue - border-color: @z; // black - .hidden { - @x: #131313; - } - .scope2 { - @y: red; - color: @x; // blue - .scope3 { - @local: white; - color: @y; // red - border-color: @z; // black - background-color: @local; // white - } - } -}h1, h2, h3 { - a, p { - &:hover { - color: red; - } - } -} - -#all { color: blue; } -#the { color: blue; } -#same { color: blue; } - -ul, li, div, q, blockquote, textarea { - margin: 0; -} - -td { - margin: 0; - padding: 0; -} - -td, input { - line-height: 1em; -} -#strings { - background-image: url("http://son-of-a-banana.com"); - quotes: "~" "~"; - content: "#*%:&^,)!.(~*})"; - empty: ""; - brackets: "{" "}"; -} -#comments { - content: "/* hello */ // not-so-secret"; -} -#single-quote { - quotes: "'" "'"; - content: '""#!&""'; - empty: ''; -} -@a: 2; -@x: @a * @a; -@y: @x + 1; -@z: @x * 2 + @y; - -.variables { - width: @z + 1cm; // 14cm -} - -@b: @a * 10; -@c: #888; - -@fonts: "Trebuchet MS", Verdana, sans-serif; -@f: @fonts; - -@quotes: "~" "~"; -@q: @quotes; - -.variables { - height: @b + @x + 0px; // 24px - color: @c; - font-family: @f; - quotes: @q; -} - -.redefinition { - @var: 4; - @var: 2; - @var: 3; - three: @var; -} - -.values { - @a: 'Trebuchet'; - font-family: @a, @a, @a; -} - - -.whitespace - { color: white; } - -.whitespace -{ - color: white; -} - .whitespace -{ color: white; } - -.whitespace{color:white;} -.whitespace { color : white ; } - -.white, -.space, -.mania -{ color: white; } - -.no-semi-column { color: white } -.no-semi-column { - color: white; - white-space: pre -} -.no-semi-column {border: 2px solid white} -.newlines { - background: the, - great, - wall; - border: 2px - solid - black; -} -.empty { - -} -#yelow { - #short { - color: #fea; - } - #long { - color: #ffeeaa; - } - #rgba { - color: rgba(255, 238, 170, 0.1); - } -} - -#blue { - #short { - color: #00f; - } - #long { - color: #0000ff; - } - #rgba { - color: rgba(0, 0, 255, 0.1); - } -} - -#overflow { - .a { color: #111111 - #444444; } // #000000 - .b { color: #eee + #fff; } // #ffffff - .c { color: #aaa * 3; } // #ffffff - .d { color: #00ee00 + #009900; } // #00ff00 -} - -#grey { - color: rgb(200, 200, 200); -} - -#808080 { - color: hsl(50, 0%, 50%); -} - -#00ff00 { - color: hsl(120, 100%, 50%); -} -/******************\ -* * -* Comment Header * -* * -\******************/ - -/* - - Comment - -*/ - -/* - * Comment Test - * - * - cloudhead (http://cloudhead.net) - * - */ - -//////////////// -@var: "content"; -//////////////// - -/* Colors - * ------ - * #EDF8FC (background blue) - * #166C89 (darkest blue) - * - * Text: - * #333 (standard text) // A comment within a comment! - * #1F9EC9 (standard link) - * - */ - -/* @group Variables -------------------- */ -#comments /* boo */ { - /**/ // An empty comment - color: red; /* A C-style comment */ - background-color: orange; // A little comment - font-size: 12px; - - /* lost comment */ content: @var; - - border: 1px solid black; - - // padding & margin // - padding: 0; - margin: 2em; -} // - -/* commented out - #more-comments { - color: grey; - } -*/ - -#last { color: blue } -// -.comma-delimited { - background: url(bg.jpg) no-repeat, url(bg.png) repeat-x top left, url(bg); - text-shadow: -1px -1px 1px red, 6px 5px 5px yellow; - -moz-box-shadow: 0pt 0pt 2px rgba(255, 255, 255, 0.4) inset, - 0pt 4px 6px rgba(255, 255, 255, 0.4) inset; -} -@font-face { - font-family: Headline; - src: local(Futura-Medium), - url(fonts.svg#MyGeometricModern) format("svg"); -} -.other { - -moz-transform: translate(0, 11em) rotate(-90deg); -} -p:not([class*="lead"]) { - color: black; -} - -input[type="text"].class#id[attr=32]:not(1) { - color: white; -} - -div#id.class[a=1][b=2].class:not(1) { - color: white; -} - -ul.comma > li:not(:only-child)::after { - color: white; -} - -ol.comma > li:nth-last-child(2)::after { - color: white; -} - -li:nth-child(4n+1), -li:nth-child(-5n), -li:nth-child(-n+2) { - color: white; -} - -a[href^="http://"] { - color: black; -} - -a[href$="http://"] { - color: black; -} - -form[data-disabled] { - color: black; -} - -p::before { - color: black; -} -@charset "utf-8"; -div { color: black; } -div { width: 99%; } - -* { - min-width: 45em; -} - -h1, h2 > a > p, h3 { - color: none; -} - -div.class { - color: blue; -} - -div#id { - color: green; -} - -.class#id { - color: purple; -} - -.one.two.three { - color: grey; -} - -@media print { - font-size: 3em; -} - -@media screen { - font-size: 10px; -} - -@font-face { - font-family: 'Garamond Pro'; - src: url("/fonts/garamond-pro.ttf"); -} - -a:hover, a:link { - color: #999; -} - -p, p:first-child { - text-transform: none; -} - -q:lang(no) { - quotes: none; -} - -p + h1 { - font-size: 2.2em; -} - -#shorthands { - border: 1px solid #000; - font: 12px/16px Arial; - margin: 1px 0; - padding: 0 auto; - background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px; -} - -#more-shorthands { - margin: 0; - padding: 1px 0 2px 0; - font: normal small/20px 'Trebuchet MS', Verdana, sans-serif; -} - -.misc { - -moz-border-radius: 2px; - display: -moz-inline-stack; - width: .1em; - background-color: #009998; - background-image: url(images/image.jpg); - background: -webkit-gradient(linear, left top, left bottom, from(red), to(blue)); - margin: ; -} - -#important { - color: red !important; - width: 100%!important; - height: 20px ! important; -} - -#functions { - @var: 10; - color: color("evil red"); // #660000 - width: increment(15); - height: undefined("self"); - border-width: add(2, 3); - variable: increment(@var); -} - -#built-in { - @r: 32; - escaped: e("-Some::weird(#thing, y)"); - lighten: lighten(#ff0000, 50%); - darken: darken(#ff0000, 50%); - saturate: saturate(#29332f, 20%); - desaturate: desaturate(#203c31, 20%); - greyscale: greyscale(#203c31); - format: %("rgb(%d, %d, %d)", @r, 128, 64); - format-string: %("hello %s", "world"); - eformat: e(%("rgb(%d, %d, %d)", @r, 128, 64)); -} - -@var: @a; -@a: 100%; - -.lazy-eval { - width: @var; -} -.mixin (@a: 1px, @b: 50%) { - width: @a * 5; - height: @b - 1%; -} - -.mixina (@style, @width, @color: black) { - border: @width @style @color; -} - -.mixiny -(@a: 0, @b: 0) { - margin: @a; - padding: @b; -} - -.hidden() { - color: transparent; -} - -.two-args { - color: blue; - .mixin(2px, 100%); - .mixina(dotted, 2px); -} - -.one-arg { - .mixin(3px); -} - -.no-parens { - .mixin; -} - -.no-args { - .mixin(); -} - -.var-args { - @var: 9; - .mixin(@var, @var * 2); -} - -.multi-mix { - .mixin(2px, 30%); - .mixiny(4, 5); -} - -.maxa(@arg1: 10, @arg2: #f00) { - padding: @arg1 * 2px; - color: @arg2; -} - -body { - .maxa(15); -} - -@glob: 5; -.global-mixin(@a:2) { - width: @glob + @a; -} - -.scope-mix { - .global-mixin(3); -} - -.nested-ruleset (@width: 200px) { - width: @width; - .column { margin: @width; } -} -.content { - .nested-ruleset(600px); -} - -// - -.same-var-name2(@radius) { - radius: @radius; -} -.same-var-name(@radius) { - .same-var-name2(@radius); -} -#same-var-name { - .same-var-name(5px); -} - -// - -.var-inside () { - @var: 10px; - width: @var; -} -#var-inside { .var-inside; } -.mix-inner (@var) { - border-width: @var; -} - -.mix (@a: 10) { - .inner { - height: @a * 10; - - .innest { - width: @a; - .mix-inner(@a * 2); - } - } -} - -.class { - .mix(30); -} -.mixin () { - zero: 0; -} -.mixin (@a: 1px) { - one: 1; -} -.mixin (@a) { - one-req: 1; -} -.mixin (@a: 1px, @b: 2px) { - two: 2; -} - -.mixin (@a, @b, @c) { - three-req: 3; -} - -.mixin (@a: 1px, @b: 2px, @c: 3px) { - three: 3; -} - -.zero { - .mixin(); -} - -.one { - .mixin(1); -} - -.two { - .mixin(1, 2); -} - -.three { - .mixin(1, 2, 3); -} - -// - -.mixout ('left') { - left: 1; -} - -.mixout ('right') { - right: 1; -} - -.left { - .mixout('left'); -} -.right { - .mixout('right'); -} - -// - -.border (@side, @width) { - color: black; - .border-side(@side, @width); -} -.border-side (left, @w) { - border-left: @w; -} -.border-side (right, @w) { - border-right: @w; -} - -.border-right { - .border(right, 4px); -} -.border-left { - .border(left, 4px); -} - -// - - -.border-radius (@r) { - both: @r * 10; -} -.border-radius (@r, left) { - left: @r; -} -.border-radius (@r, right) { - right: @r; -} - -.only-right { - .border-radius(33, right); -} -.only-left { - .border-radius(33, left); -} -.left-right { - .border-radius(33); -} -.mixin { border: 1px solid black; } -.mixout { border-color: orange; } -.borders { border-style: dashed; } - -#namespace { - .borders { - border-style: dotted; - } - .biohazard { - content: "death"; - .man { - color: transparent; - } - } -} -#theme { - > .mixin { - background-color: grey; - } -} -#container { - color: black; - .mixin; - .mixout; - #theme > .mixin; -} - -#header { - .milk { - color: white; - .mixin; - #theme > .mixin; - } - #cookie { - .chips { - #namespace .borders; - .calories { - #container; - } - } - .borders; - } -} -.secure-zone { #namespace .biohazard .man; } -.direct { - #namespace > .borders; -} -#operations { - color: #110000 + #000011 + #001100; // #111111 - height: 10px / 2px + 6px - 1px * 2; // 9px - width: 2 * 4 - 5em; // 3em - .spacing { - height: 10px / 2px+6px-1px*2; - width: 2 * 4-5em; - } - substraction: 20 - 10 - 5 - 5; // 0 - division: 20 / 5 / 4; // 1 -} - -@x: 4; -@y: 12em; - -.with-variables { - height: @x + @y; // 16em - width: 12 + @y; // 24em - size: 5cm - @x; // 1cm -} - -@z: -2; - -.negative { - height: 2px + @z; // 0px - width: 2px - @z; // 4px -} - -.shorthands { - padding: -1px 2px 0 -4px; // -} - -.colors { - color: #123; // #112233 - border-color: #234 + #111111; // #334455 - background-color: #222222 - #fff; // #000000 - .other { - color: 2 * #111; // #222222 - border-color: #333333 / 3 + #111; // #222222 - } -} -.parens { - @var: 1px; - border: (@var * 2) solid black; - margin: (@var * 1) (@var + 2) (4 * 4) 3; - width: (6 * 6); - padding: 2px (6px * 6px); -} - -.more-parens { - @var: (2 * 2); - padding: (2 * @var) 4 4 (@var * 1px); - width: (@var * @var) * 6; - height: (7 * 7) + (8 * 8); - margin: 4 * (5 + 5) / 2 - (@var * 2); - //margin: (6 * 6)px; -} - -.nested-parens { - width: 2 * (4 * (2 + (1 + 6))) - 1; - height: ((2+3)*(2+3) / (9-4)) + 1; -} - -.mixed-units { - margin: 2px 4em 1 5pc; - padding: (2px + 4px) 1em 2px 2; -} -#first > .one { - > #second .two > #deux { - width: 50%; - #third { - &:focus { - color: black; - #fifth { - > #sixth { - .seventh #eighth { - + #ninth { - color: purple; - } - } - } - } - } - height: 100%; - } - #fourth, #five, #six { - color: #110000; - .seven, .eight > #nine { - border: 1px solid black; - } - #ten { - color: red; - } - } - } - font-size: 2em; -} -@x: blue; -@z: transparent; -@mix: none; - -.mixin { - @mix: #989; -} - -.tiny-scope { - color: @mix; // #989 - .mixin; -} - -.scope1 { - @y: orange; - @z: black; - color: @x; // blue - border-color: @z; // black - .hidden { - @x: #131313; - } - .scope2 { - @y: red; - color: @x; // blue - .scope3 { - @local: white; - color: @y; // red - border-color: @z; // black - background-color: @local; // white - } - } -}h1, h2, h3 { - a, p { - &:hover { - color: red; - } - } -} - -#all { color: blue; } -#the { color: blue; } -#same { color: blue; } - -ul, li, div, q, blockquote, textarea { - margin: 0; -} - -td { - margin: 0; - padding: 0; -} - -td, input { - line-height: 1em; -} -#strings { - background-image: url("http://son-of-a-banana.com"); - quotes: "~" "~"; - content: "#*%:&^,)!.(~*})"; - empty: ""; - brackets: "{" "}"; -} -#comments { - content: "/* hello */ // not-so-secret"; -} -#single-quote { - quotes: "'" "'"; - content: '""#!&""'; - empty: ''; -} -@a: 2; -@x: @a * @a; -@y: @x + 1; -@z: @x * 2 + @y; - -.variables { - width: @z + 1cm; // 14cm -} - -@b: @a * 10; -@c: #888; - -@fonts: "Trebuchet MS", Verdana, sans-serif; -@f: @fonts; - -@quotes: "~" "~"; -@q: @quotes; - -.variables { - height: @b + @x + 0px; // 24px - color: @c; - font-family: @f; - quotes: @q; -} - -.redefinition { - @var: 4; - @var: 2; - @var: 3; - three: @var; -} - -.values { - @a: 'Trebuchet'; - font-family: @a, @a, @a; -} - - -.whitespace - { color: white; } - -.whitespace -{ - color: white; -} - .whitespace -{ color: white; } - -.whitespace{color:white;} -.whitespace { color : white ; } - -.white, -.space, -.mania -{ color: white; } - -.no-semi-column { color: white } -.no-semi-column { - color: white; - white-space: pre -} -.no-semi-column {border: 2px solid white} -.newlines { - background: the, - great, - wall; - border: 2px - solid - black; -} -.empty { - -} -#yelow { - #short { - color: #fea; - } - #long { - color: #ffeeaa; - } - #rgba { - color: rgba(255, 238, 170, 0.1); - } -} - -#blue { - #short { - color: #00f; - } - #long { - color: #0000ff; - } - #rgba { - color: rgba(0, 0, 255, 0.1); - } -} - -#overflow { - .a { color: #111111 - #444444; } // #000000 - .b { color: #eee + #fff; } // #ffffff - .c { color: #aaa * 3; } // #ffffff - .d { color: #00ee00 + #009900; } // #00ff00 -} - -#grey { - color: rgb(200, 200, 200); -} - -#808080 { - color: hsl(50, 0%, 50%); -} - -#00ff00 { - color: hsl(120, 100%, 50%); -} -/******************\ -* * -* Comment Header * -* * -\******************/ - -/* - - Comment - -*/ - -/* - * Comment Test - * - * - cloudhead (http://cloudhead.net) - * - */ - -//////////////// -@var: "content"; -//////////////// - -/* Colors - * ------ - * #EDF8FC (background blue) - * #166C89 (darkest blue) - * - * Text: - * #333 (standard text) // A comment within a comment! - * #1F9EC9 (standard link) - * - */ - -/* @group Variables -------------------- */ -#comments /* boo */ { - /**/ // An empty comment - color: red; /* A C-style comment */ - background-color: orange; // A little comment - font-size: 12px; - - /* lost comment */ content: @var; - - border: 1px solid black; - - // padding & margin // - padding: 0; - margin: 2em; -} // - -/* commented out - #more-comments { - color: grey; - } -*/ - -#last { color: blue } -// -.comma-delimited { - background: url(bg.jpg) no-repeat, url(bg.png) repeat-x top left, url(bg); - text-shadow: -1px -1px 1px red, 6px 5px 5px yellow; - -moz-box-shadow: 0pt 0pt 2px rgba(255, 255, 255, 0.4) inset, - 0pt 4px 6px rgba(255, 255, 255, 0.4) inset; -} -@font-face { - font-family: Headline; - src: local(Futura-Medium), - url(fonts.svg#MyGeometricModern) format("svg"); -} -.other { - -moz-transform: translate(0, 11em) rotate(-90deg); -} -p:not([class*="lead"]) { - color: black; -} - -input[type="text"].class#id[attr=32]:not(1) { - color: white; -} - -div#id.class[a=1][b=2].class:not(1) { - color: white; -} - -ul.comma > li:not(:only-child)::after { - color: white; -} - -ol.comma > li:nth-last-child(2)::after { - color: white; -} - -li:nth-child(4n+1), -li:nth-child(-5n), -li:nth-child(-n+2) { - color: white; -} - -a[href^="http://"] { - color: black; -} - -a[href$="http://"] { - color: black; -} - -form[data-disabled] { - color: black; -} - -p::before { - color: black; -} -@charset "utf-8"; -div { color: black; } -div { width: 99%; } - -* { - min-width: 45em; -} - -h1, h2 > a > p, h3 { - color: none; -} - -div.class { - color: blue; -} - -div#id { - color: green; -} - -.class#id { - color: purple; -} - -.one.two.three { - color: grey; -} - -@media print { - font-size: 3em; -} - -@media screen { - font-size: 10px; -} - -@font-face { - font-family: 'Garamond Pro'; - src: url("/fonts/garamond-pro.ttf"); -} - -a:hover, a:link { - color: #999; -} - -p, p:first-child { - text-transform: none; -} - -q:lang(no) { - quotes: none; -} - -p + h1 { - font-size: 2.2em; -} - -#shorthands { - border: 1px solid #000; - font: 12px/16px Arial; - margin: 1px 0; - padding: 0 auto; - background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px; -} - -#more-shorthands { - margin: 0; - padding: 1px 0 2px 0; - font: normal small/20px 'Trebuchet MS', Verdana, sans-serif; -} - -.misc { - -moz-border-radius: 2px; - display: -moz-inline-stack; - width: .1em; - background-color: #009998; - background-image: url(images/image.jpg); - background: -webkit-gradient(linear, left top, left bottom, from(red), to(blue)); - margin: ; -} - -#important { - color: red !important; - width: 100%!important; - height: 20px ! important; -} - -#functions { - @var: 10; - color: color("evil red"); // #660000 - width: increment(15); - height: undefined("self"); - border-width: add(2, 3); - variable: increment(@var); -} - -#built-in { - @r: 32; - escaped: e("-Some::weird(#thing, y)"); - lighten: lighten(#ff0000, 50%); - darken: darken(#ff0000, 50%); - saturate: saturate(#29332f, 20%); - desaturate: desaturate(#203c31, 20%); - greyscale: greyscale(#203c31); - format: %("rgb(%d, %d, %d)", @r, 128, 64); - format-string: %("hello %s", "world"); - eformat: e(%("rgb(%d, %d, %d)", @r, 128, 64)); -} - -@var: @a; -@a: 100%; - -.lazy-eval { - width: @var; -} -.mixin (@a: 1px, @b: 50%) { - width: @a * 5; - height: @b - 1%; -} - -.mixina (@style, @width, @color: black) { - border: @width @style @color; -} - -.mixiny -(@a: 0, @b: 0) { - margin: @a; - padding: @b; -} - -.hidden() { - color: transparent; -} - -.two-args { - color: blue; - .mixin(2px, 100%); - .mixina(dotted, 2px); -} - -.one-arg { - .mixin(3px); -} - -.no-parens { - .mixin; -} - -.no-args { - .mixin(); -} - -.var-args { - @var: 9; - .mixin(@var, @var * 2); -} - -.multi-mix { - .mixin(2px, 30%); - .mixiny(4, 5); -} - -.maxa(@arg1: 10, @arg2: #f00) { - padding: @arg1 * 2px; - color: @arg2; -} - -body { - .maxa(15); -} - -@glob: 5; -.global-mixin(@a:2) { - width: @glob + @a; -} - -.scope-mix { - .global-mixin(3); -} - -.nested-ruleset (@width: 200px) { - width: @width; - .column { margin: @width; } -} -.content { - .nested-ruleset(600px); -} - -// - -.same-var-name2(@radius) { - radius: @radius; -} -.same-var-name(@radius) { - .same-var-name2(@radius); -} -#same-var-name { - .same-var-name(5px); -} - -// - -.var-inside () { - @var: 10px; - width: @var; -} -#var-inside { .var-inside; } -.mix-inner (@var) { - border-width: @var; -} - -.mix (@a: 10) { - .inner { - height: @a * 10; - - .innest { - width: @a; - .mix-inner(@a * 2); - } - } -} - -.class { - .mix(30); -} -.mixin () { - zero: 0; -} -.mixin (@a: 1px) { - one: 1; -} -.mixin (@a) { - one-req: 1; -} -.mixin (@a: 1px, @b: 2px) { - two: 2; -} - -.mixin (@a, @b, @c) { - three-req: 3; -} - -.mixin (@a: 1px, @b: 2px, @c: 3px) { - three: 3; -} - -.zero { - .mixin(); -} - -.one { - .mixin(1); -} - -.two { - .mixin(1, 2); -} - -.three { - .mixin(1, 2, 3); -} - -// - -.mixout ('left') { - left: 1; -} diff --git a/r2/r2/lib/contrib/less.js/benchmark/less-benchmark.js b/r2/r2/lib/contrib/less.js/benchmark/less-benchmark.js deleted file mode 100644 index 68fe1ad4c..000000000 --- a/r2/r2/lib/contrib/less.js/benchmark/less-benchmark.js +++ /dev/null @@ -1,47 +0,0 @@ -var path = require('path'), - fs = require('fs'), - sys = require('util'); - -var less = require('../lib/less'); -var file = path.join(__dirname, 'benchmark.less'); - -if (process.argv[2]) { file = path.join(process.cwd(), process.argv[2]) } - -fs.readFile(file, 'utf8', function (e, data) { - var tree, css, start, end, total; - - sys.puts("Benchmarking...\n", path.basename(file) + " (" + - parseInt(data.length / 1024) + " KB)", ""); - - start = new(Date); - - new(less.Parser)({ optimization: 2 }).parse(data, function (err, tree) { - end = new(Date); - - total = end - start; - - sys.puts("Parsing: " + - total + " ms (" + - parseInt(1000 / total * - data.length / 1024) + " KB\/s)"); - - start = new(Date); - css = tree.toCSS(); - end = new(Date); - - sys.puts("Generation: " + (end - start) + " ms (" + - parseInt(1000 / (end - start) * - data.length / 1024) + " KB\/s)"); - - total += end - start; - - sys.puts("Total: " + total + "ms (" + - parseInt(1000 / total * data.length / 1024) + " KB/s)"); - - if (err) { - less.writeError(err); - process.exit(3); - } - }); -}); - diff --git a/r2/r2/lib/contrib/less.js/bin/lessc b/r2/r2/lib/contrib/less.js/bin/lessc deleted file mode 100755 index 9855e851a..000000000 --- a/r2/r2/lib/contrib/less.js/bin/lessc +++ /dev/null @@ -1,143 +0,0 @@ -#!/usr/bin/env node -// Note: modified slightly to hobble along on Ubuntu Natty's ancient Node. - -var path = require('path'), - fs = require('fs'), - sys = require('util'); - -try { - var os = require('os'); -} catch (e) {} - -var less = require('../lib/less'); -var args = process.argv.slice(1); -var options = { - compress: false, - yuicompress: false, - optimization: 1, - silent: false, - paths: [], - color: true, - strictImports: false -}; - -args = args.filter(function (arg) { - var match; - - if (match = arg.match(/^-I(.+)$/)) { - options.paths.push(match[1]); - return false; - } - - if (match = arg.match(/^--?([a-z][0-9a-z-]*)(?:=([^\s]+))?$/i)) { arg = match[1] } - else { return arg } - - switch (arg) { - case 'v': - case 'version': - sys.puts("lessc " + less.version.join('.') + " (LESS Compiler) [JavaScript]"); - process.exit(0); - case 'verbose': - options.verbose = true; - break; - case 's': - case 'silent': - options.silent = true; - break; - case 'strict-imports': - options.strictImports = true; - break; - case 'h': - case 'help': - sys.puts("usage: lessc source [destination]"); - process.exit(0); - case 'x': - case 'compress': - options.compress = true; - break; - case 'yui-compress': - options.yuicompress = true; - break; - case 'no-color': - options.color = false; - break; - case 'include-path': - options.paths = match[2].split(os.type().match(/Windows/) ? ';' : ':') - .map(function(p) { - if (p) { - return path.resolve(process.cwd(), p); - } - }); - break; - case 'O0': options.optimization = 0; break; - case 'O1': options.optimization = 1; break; - case 'O2': options.optimization = 2; break; - } -}); - -var input = args[1]; -if (input && input != '-' && path.resolve) { - input = path.resolve(process.cwd(), input); -} -var output = args[2]; -if (output && path.resolve) { - output = path.resolve(process.cwd(), output); -} - -var css, fd, tree; - -if (! input) { - sys.puts("lessc: no input files"); - process.exit(1); -} - -var parseLessFile = function (e, data) { - if (e) { - sys.puts("lessc: " + e.message); - process.exit(1); - } - - new(less.Parser)({ - paths: [path.dirname(input)].concat(options.paths), - optimization: options.optimization, - filename: input, - strictImports: options.strictImports - }).parse(data, function (err, tree) { - if (err) { - less.writeError(err, options); - process.exit(1); - } else { - try { - css = tree.toCSS({ - compress: options.compress, - yuicompress: options.yuicompress - }); - if (output) { - fd = fs.openSync(output, "w"); - fs.writeSync(fd, css, 0, "utf8"); - } else { - sys.print(css); - } - } catch (e) { - less.writeError(e, options); - process.exit(2); - } - } - }); -}; - -if (input != '-') { - fs.readFile(input, 'utf-8', parseLessFile); -} else { - process.stdin.resume(); - process.stdin.setEncoding('utf8'); - - var buffer = ''; - process.stdin.on('data', function(data) { - buffer += data; - }); - - process.stdin.on('end', function() { - parseLessFile(false, buffer); - }); -} diff --git a/r2/r2/lib/contrib/less.js/lib/less/browser.js b/r2/r2/lib/contrib/less.js/lib/less/browser.js deleted file mode 100644 index cab913be0..000000000 --- a/r2/r2/lib/contrib/less.js/lib/less/browser.js +++ /dev/null @@ -1,380 +0,0 @@ -// -// browser.js - client-side engine -// - -var isFileProtocol = (location.protocol === 'file:' || - location.protocol === 'chrome:' || - location.protocol === 'chrome-extension:' || - location.protocol === 'resource:'); - -less.env = less.env || (location.hostname == '127.0.0.1' || - location.hostname == '0.0.0.0' || - location.hostname == 'localhost' || - location.port.length > 0 || - isFileProtocol ? 'development' - : 'production'); - -// Load styles asynchronously (default: false) -// -// This is set to `false` by default, so that the body -// doesn't start loading before the stylesheets are parsed. -// Setting this to `true` can result in flickering. -// -less.async = false; - -// Interval between watch polls -less.poll = less.poll || (isFileProtocol ? 1000 : 1500); - -// -// Watch mode -// -less.watch = function () { return this.watchMode = true }; -less.unwatch = function () { return this.watchMode = false }; - -if (less.env === 'development') { - less.optimization = 0; - - if (/!watch/.test(location.hash)) { - less.watch(); - } - less.watchTimer = setInterval(function () { - if (less.watchMode) { - loadStyleSheets(function (e, root, _, sheet, env) { - if (root) { - createCSS(root.toCSS(), sheet, env.lastModified); - } - }); - } - }, less.poll); -} else { - less.optimization = 3; -} - -var cache; - -try { - cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; -} catch (_) { - cache = null; -} - -// -// Get all tags with the 'rel' attribute set to "stylesheet/less" -// -var links = document.getElementsByTagName('link'); -var typePattern = /^text\/(x-)?less$/; - -less.sheets = []; - -for (var i = 0; i < links.length; i++) { - if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && - (links[i].type.match(typePattern)))) { - less.sheets.push(links[i]); - } -} - - -less.refresh = function (reload) { - var startTime, endTime; - startTime = endTime = new(Date); - - loadStyleSheets(function (e, root, _, sheet, env) { - if (env.local) { - log("loading " + sheet.href + " from cache."); - } else { - log("parsed " + sheet.href + " successfully."); - createCSS(root.toCSS(), sheet, env.lastModified); - } - log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms'); - (env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms'); - endTime = new(Date); - }, reload); - - loadStyles(); -}; -less.refreshStyles = loadStyles; - -less.refresh(less.env === 'development'); - -function loadStyles() { - var styles = document.getElementsByTagName('style'); - for (var i = 0; i < styles.length; i++) { - if (styles[i].type.match(typePattern)) { - new(less.Parser)().parse(styles[i].innerHTML || '', function (e, tree) { - var css = tree.toCSS(); - var style = styles[i]; - style.type = 'text/css'; - if (style.styleSheet) { - style.styleSheet.cssText = css; - } else { - style.innerHTML = css; - } - }); - } - } -} - -function loadStyleSheets(callback, reload) { - for (var i = 0; i < less.sheets.length; i++) { - loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1)); - } -} - -function loadStyleSheet(sheet, callback, reload, remaining) { - var url = window.location.href.replace(/[#?].*$/, ''); - var href = sheet.href.replace(/\?.*$/, ''); - var css = cache && cache.getItem(href); - var timestamp = cache && cache.getItem(href + ':timestamp'); - var styles = { css: css, timestamp: timestamp }; - - // Stylesheets in IE don't always return the full path - if (! /^(https?|file):/.test(href)) { - if (href.charAt(0) == "/") { - href = window.location.protocol + "//" + window.location.host + href; - } else { - href = url.slice(0, url.lastIndexOf('/') + 1) + href; - } - } - var filename = href.match(/([^\/]+)$/)[1]; - - xhr(sheet.href, sheet.type, function (data, lastModified) { - if (!reload && styles && lastModified && - (new(Date)(lastModified).valueOf() === - new(Date)(styles.timestamp).valueOf())) { - // Use local copy - createCSS(styles.css, sheet); - callback(null, null, data, sheet, { local: true, remaining: remaining }); - } else { - // Use remote copy (re-parse) - try { - new(less.Parser)({ - optimization: less.optimization, - paths: [href.replace(/[\w\.-]+$/, '')], - mime: sheet.type, - filename: filename - }).parse(data, function (e, root) { - if (e) { return error(e, href) } - try { - callback(e, root, data, sheet, { local: false, lastModified: lastModified, remaining: remaining }); - removeNode(document.getElementById('less-error-message:' + extractId(href))); - } catch (e) { - error(e, href); - } - }); - } catch (e) { - error(e, href); - } - } - }, function (status, url) { - throw new(Error)("Couldn't load " + url + " (" + status + ")"); - }); -} - -function extractId(href) { - return href.replace(/^[a-z]+:\/\/?[^\/]+/, '' ) // Remove protocol & domain - .replace(/^\//, '' ) // Remove root / - .replace(/\?.*$/, '' ) // Remove query - .replace(/\.[^\.\/]+$/, '' ) // Remove file extension - .replace(/[^\.\w-]+/g, '-') // Replace illegal characters - .replace(/\./g, ':'); // Replace dots with colons(for valid id) -} - -function createCSS(styles, sheet, lastModified) { - var css; - - // Strip the query-string - var href = sheet.href ? sheet.href.replace(/\?.*$/, '') : ''; - - // If there is no title set, use the filename, minus the extension - var id = 'less:' + (sheet.title || extractId(href)); - - // If the stylesheet doesn't exist, create a new node - if ((css = document.getElementById(id)) === null) { - css = document.createElement('style'); - css.type = 'text/css'; - css.media = sheet.media || 'screen'; - css.id = id; - document.getElementsByTagName('head')[0].appendChild(css); - } - - if (css.styleSheet) { // IE - try { - css.styleSheet.cssText = styles; - } catch (e) { - throw new(Error)("Couldn't reassign styleSheet.cssText."); - } - } else { - (function (node) { - if (css.childNodes.length > 0) { - if (css.firstChild.nodeValue !== node.nodeValue) { - css.replaceChild(node, css.firstChild); - } - } else { - css.appendChild(node); - } - })(document.createTextNode(styles)); - } - - // Don't update the local store if the file wasn't modified - if (lastModified && cache) { - log('saving ' + href + ' to cache.'); - cache.setItem(href, styles); - cache.setItem(href + ':timestamp', lastModified); - } -} - -function xhr(url, type, callback, errback) { - var xhr = getXMLHttpRequest(); - var async = isFileProtocol ? false : less.async; - - if (typeof(xhr.overrideMimeType) === 'function') { - xhr.overrideMimeType('text/css'); - } - xhr.open('GET', url, async); - xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); - xhr.send(null); - - if (isFileProtocol) { - if (xhr.status === 0 || (xhr.status >= 200 && xhr.status < 300)) { - callback(xhr.responseText); - } else { - errback(xhr.status, url); - } - } else if (async) { - xhr.onreadystatechange = function () { - if (xhr.readyState == 4) { - handleResponse(xhr, callback, errback); - } - }; - } else { - handleResponse(xhr, callback, errback); - } - - function handleResponse(xhr, callback, errback) { - if (xhr.status >= 200 && xhr.status < 300) { - callback(xhr.responseText, - xhr.getResponseHeader("Last-Modified")); - } else if (typeof(errback) === 'function') { - errback(xhr.status, url); - } - } -} - -function getXMLHttpRequest() { - if (window.XMLHttpRequest) { - return new(XMLHttpRequest); - } else { - try { - return new(ActiveXObject)("MSXML2.XMLHTTP.3.0"); - } catch (e) { - log("browser doesn't support AJAX."); - return null; - } - } -} - -function removeNode(node) { - return node && node.parentNode.removeChild(node); -} - -function log(str) { - if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) } -} - -function error(e, href) { - var id = 'less-error-message:' + extractId(href); - var template = '
  • {content}
  • '; - var elem = document.createElement('div'), timer, content, error = []; - var filename = e.filename || href; - - elem.id = id; - elem.className = "less-error-message"; - - content = '

    ' + (e.message || 'There is an error in your .less file') + - '

    ' + '

    in ' + filename + " "; - - var errorline = function (e, i, classname) { - if (e.extract[i]) { - error.push(template.replace(/\{line\}/, parseInt(e.line) + (i - 1)) - .replace(/\{class\}/, classname) - .replace(/\{content\}/, e.extract[i])); - } - }; - - if (e.stack) { - content += '
    ' + e.stack.split('\n').slice(1).join('
    '); - } else if (e.extract) { - errorline(e, 0, ''); - errorline(e, 1, 'line'); - errorline(e, 2, ''); - content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

    ' + - ''; - } - elem.innerHTML = content; - - // CSS for error messages - createCSS([ - '.less-error-message ul, .less-error-message li {', - 'list-style-type: none;', - 'margin-right: 15px;', - 'padding: 4px 0;', - 'margin: 0;', - '}', - '.less-error-message label {', - 'font-size: 12px;', - 'margin-right: 15px;', - 'padding: 4px 0;', - 'color: #cc7777;', - '}', - '.less-error-message pre {', - 'color: #dd6666;', - 'padding: 4px 0;', - 'margin: 0;', - 'display: inline-block;', - '}', - '.less-error-message pre.line {', - 'color: #ff0000;', - '}', - '.less-error-message h3 {', - 'font-size: 20px;', - 'font-weight: bold;', - 'padding: 15px 0 5px 0;', - 'margin: 0;', - '}', - '.less-error-message a {', - 'color: #10a', - '}', - '.less-error-message .error {', - 'color: red;', - 'font-weight: bold;', - 'padding-bottom: 2px;', - 'border-bottom: 1px dashed red;', - '}' - ].join('\n'), { title: 'error-message' }); - - elem.style.cssText = [ - "font-family: Arial, sans-serif", - "border: 1px solid #e00", - "background-color: #eee", - "border-radius: 5px", - "-webkit-border-radius: 5px", - "-moz-border-radius: 5px", - "color: #e00", - "padding: 15px", - "margin-bottom: 15px" - ].join(';'); - - if (less.env == 'development') { - timer = setInterval(function () { - if (document.body) { - if (document.getElementById(id)) { - document.body.replaceChild(elem, document.getElementById(id)); - } else { - document.body.insertBefore(elem, document.body.firstChild); - } - clearInterval(timer); - } - }, 10); - } -} - diff --git a/r2/r2/lib/contrib/less.js/lib/less/colors.js b/r2/r2/lib/contrib/less.js/lib/less/colors.js deleted file mode 100644 index ed4c2838b..000000000 --- a/r2/r2/lib/contrib/less.js/lib/less/colors.js +++ /dev/null @@ -1,152 +0,0 @@ -(function (tree) { - tree.colors = { - 'aliceblue':'#f0f8ff', - 'antiquewhite':'#faebd7', - 'aqua':'#00ffff', - 'aquamarine':'#7fffd4', - 'azure':'#f0ffff', - 'beige':'#f5f5dc', - 'bisque':'#ffe4c4', - 'black':'#000000', - 'blanchedalmond':'#ffebcd', - 'blue':'#0000ff', - 'blueviolet':'#8a2be2', - 'brown':'#a52a2a', - 'burlywood':'#deb887', - 'cadetblue':'#5f9ea0', - 'chartreuse':'#7fff00', - 'chocolate':'#d2691e', - 'coral':'#ff7f50', - 'cornflowerblue':'#6495ed', - 'cornsilk':'#fff8dc', - 'crimson':'#dc143c', - 'cyan':'#00ffff', - 'darkblue':'#00008b', - 'darkcyan':'#008b8b', - 'darkgoldenrod':'#b8860b', - 'darkgray':'#a9a9a9', - 'darkgrey':'#a9a9a9', - 'darkgreen':'#006400', - 'darkkhaki':'#bdb76b', - 'darkmagenta':'#8b008b', - 'darkolivegreen':'#556b2f', - 'darkorange':'#ff8c00', - 'darkorchid':'#9932cc', - 'darkred':'#8b0000', - 'darksalmon':'#e9967a', - 'darkseagreen':'#8fbc8f', - 'darkslateblue':'#483d8b', - 'darkslategray':'#2f4f4f', - 'darkslategrey':'#2f4f4f', - 'darkturquoise':'#00ced1', - 'darkviolet':'#9400d3', - 'deeppink':'#ff1493', - 'deepskyblue':'#00bfff', - 'dimgray':'#696969', - 'dimgrey':'#696969', - 'dodgerblue':'#1e90ff', - 'firebrick':'#b22222', - 'floralwhite':'#fffaf0', - 'forestgreen':'#228b22', - 'fuchsia':'#ff00ff', - 'gainsboro':'#dcdcdc', - 'ghostwhite':'#f8f8ff', - 'gold':'#ffd700', - 'goldenrod':'#daa520', - 'gray':'#808080', - 'grey':'#808080', - 'green':'#008000', - 'greenyellow':'#adff2f', - 'honeydew':'#f0fff0', - 'hotpink':'#ff69b4', - 'indianred':'#cd5c5c', - 'indigo':'#4b0082', - 'ivory':'#fffff0', - 'khaki':'#f0e68c', - 'lavender':'#e6e6fa', - 'lavenderblush':'#fff0f5', - 'lawngreen':'#7cfc00', - 'lemonchiffon':'#fffacd', - 'lightblue':'#add8e6', - 'lightcoral':'#f08080', - 'lightcyan':'#e0ffff', - 'lightgoldenrodyellow':'#fafad2', - 'lightgray':'#d3d3d3', - 'lightgrey':'#d3d3d3', - 'lightgreen':'#90ee90', - 'lightpink':'#ffb6c1', - 'lightsalmon':'#ffa07a', - 'lightseagreen':'#20b2aa', - 'lightskyblue':'#87cefa', - 'lightslategray':'#778899', - 'lightslategrey':'#778899', - 'lightsteelblue':'#b0c4de', - 'lightyellow':'#ffffe0', - 'lime':'#00ff00', - 'limegreen':'#32cd32', - 'linen':'#faf0e6', - 'magenta':'#ff00ff', - 'maroon':'#800000', - 'mediumaquamarine':'#66cdaa', - 'mediumblue':'#0000cd', - 'mediumorchid':'#ba55d3', - 'mediumpurple':'#9370d8', - 'mediumseagreen':'#3cb371', - 'mediumslateblue':'#7b68ee', - 'mediumspringgreen':'#00fa9a', - 'mediumturquoise':'#48d1cc', - 'mediumvioletred':'#c71585', - 'midnightblue':'#191970', - 'mintcream':'#f5fffa', - 'mistyrose':'#ffe4e1', - 'moccasin':'#ffe4b5', - 'navajowhite':'#ffdead', - 'navy':'#000080', - 'oldlace':'#fdf5e6', - 'olive':'#808000', - 'olivedrab':'#6b8e23', - 'orange':'#ffa500', - 'orangered':'#ff4500', - 'orchid':'#da70d6', - 'palegoldenrod':'#eee8aa', - 'palegreen':'#98fb98', - 'paleturquoise':'#afeeee', - 'palevioletred':'#d87093', - 'papayawhip':'#ffefd5', - 'peachpuff':'#ffdab9', - 'peru':'#cd853f', - 'pink':'#ffc0cb', - 'plum':'#dda0dd', - 'powderblue':'#b0e0e6', - 'purple':'#800080', - 'red':'#ff0000', - 'rosybrown':'#bc8f8f', - 'royalblue':'#4169e1', - 'saddlebrown':'#8b4513', - 'salmon':'#fa8072', - 'sandybrown':'#f4a460', - 'seagreen':'#2e8b57', - 'seashell':'#fff5ee', - 'sienna':'#a0522d', - 'silver':'#c0c0c0', - 'skyblue':'#87ceeb', - 'slateblue':'#6a5acd', - 'slategray':'#708090', - 'slategrey':'#708090', - 'snow':'#fffafa', - 'springgreen':'#00ff7f', - 'steelblue':'#4682b4', - 'tan':'#d2b48c', - 'teal':'#008080', - 'thistle':'#d8bfd8', - 'tomato':'#ff6347', - 'transparent':'rgba(0,0,0,0)', - 'turquoise':'#40e0d0', - 'violet':'#ee82ee', - 'wheat':'#f5deb3', - 'white':'#ffffff', - 'whitesmoke':'#f5f5f5', - 'yellow':'#ffff00', - 'yellowgreen':'#9acd32' - }; -})(require('./tree')); diff --git a/r2/r2/lib/contrib/less.js/lib/less/cssmin.js b/r2/r2/lib/contrib/less.js/lib/less/cssmin.js deleted file mode 100644 index 427de71c0..000000000 --- a/r2/r2/lib/contrib/less.js/lib/less/cssmin.js +++ /dev/null @@ -1,355 +0,0 @@ -/** - * cssmin.js - * Author: Stoyan Stefanov - http://phpied.com/ - * This is a JavaScript port of the CSS minification tool - * distributed with YUICompressor, itself a port - * of the cssmin utility by Isaac Schlueter - http://foohack.com/ - * Permission is hereby granted to use the JavaScript version under the same - * conditions as the YUICompressor (original YUICompressor note below). - */ - -/* -* YUI Compressor -* http://developer.yahoo.com/yui/compressor/ -* Author: Julien Lecomte - http://www.julienlecomte.net/ -* Copyright (c) 2011 Yahoo! Inc. All rights reserved. -* The copyrights embodied in the content of this file are licensed -* by Yahoo! Inc. under the BSD (revised) open source license. -*/ -var YAHOO = YAHOO || {}; -YAHOO.compressor = YAHOO.compressor || {}; - -/** - * Utility method to replace all data urls with tokens before we start - * compressing, to avoid performance issues running some of the subsequent - * regexes against large strings chunks. - * - * @private - * @method _extractDataUrls - * @param {String} css The input css - * @param {Array} The global array of tokens to preserve - * @returns String The processed css - */ -YAHOO.compressor._extractDataUrls = function (css, preservedTokens) { - - // Leave data urls alone to increase parse performance. - var maxIndex = css.length - 1, - appendIndex = 0, - startIndex, - endIndex, - terminator, - foundTerminator, - sb = [], - m, - preserver, - token, - pattern = /url\(\s*(["']?)data\:/g; - - // Since we need to account for non-base64 data urls, we need to handle - // ' and ) being part of the data string. Hence switching to indexOf, - // to determine whether or not we have matching string terminators and - // handling sb appends directly, instead of using matcher.append* methods. - - while ((m = pattern.exec(css)) !== null) { - - startIndex = m.index + 4; // "url(".length() - terminator = m[1]; // ', " or empty (not quoted) - - if (terminator.length === 0) { - terminator = ")"; - } - - foundTerminator = false; - - endIndex = pattern.lastIndex - 1; - - while(foundTerminator === false && endIndex+1 <= maxIndex) { - endIndex = css.indexOf(terminator, endIndex + 1); - - // endIndex == 0 doesn't really apply here - if ((endIndex > 0) && (css.charAt(endIndex - 1) !== '\\')) { - foundTerminator = true; - if (")" != terminator) { - endIndex = css.indexOf(")", endIndex); - } - } - } - - // Enough searching, start moving stuff over to the buffer - sb.push(css.substring(appendIndex, m.index)); - - if (foundTerminator) { - token = css.substring(startIndex, endIndex); - token = token.replace(/\s+/g, ""); - preservedTokens.push(token); - - preserver = "url(___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___)"; - sb.push(preserver); - - appendIndex = endIndex + 1; - } else { - // No end terminator found, re-add the whole match. Should we throw/warn here? - sb.push(css.substring(m.index, pattern.lastIndex)); - appendIndex = pattern.lastIndex; - } - } - - sb.push(css.substring(appendIndex)); - - return sb.join(""); -}; - -/** - * Utility method to compress hex color values of the form #AABBCC to #ABC. - * - * DOES NOT compress CSS ID selectors which match the above pattern (which would break things). - * e.g. #AddressForm { ... } - * - * DOES NOT compress IE filters, which have hex color values (which would break things). - * e.g. filter: chroma(color="#FFFFFF"); - * - * DOES NOT compress invalid hex values. - * e.g. background-color: #aabbccdd - * - * @private - * @method _compressHexColors - * @param {String} css The input css - * @returns String The processed css - */ -YAHOO.compressor._compressHexColors = function(css) { - - // Look for hex colors inside { ... } (to avoid IDs) and which don't have a =, or a " in front of them (to avoid filters) - var pattern = /(\=\s*?["']?)?#([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])(\}|[^0-9a-f{][^{]*?\})/gi, - m, - index = 0, - isFilter, - sb = []; - - while ((m = pattern.exec(css)) !== null) { - - sb.push(css.substring(index, m.index)); - - isFilter = m[1]; - - if (isFilter) { - // Restore, maintain case, otherwise filter will break - sb.push(m[1] + "#" + (m[2] + m[3] + m[4] + m[5] + m[6] + m[7])); - } else { - if (m[2].toLowerCase() == m[3].toLowerCase() && - m[4].toLowerCase() == m[5].toLowerCase() && - m[6].toLowerCase() == m[7].toLowerCase()) { - - // Compress. - sb.push("#" + (m[3] + m[5] + m[7]).toLowerCase()); - } else { - // Non compressible color, restore but lower case. - sb.push("#" + (m[2] + m[3] + m[4] + m[5] + m[6] + m[7]).toLowerCase()); - } - } - - index = pattern.lastIndex = pattern.lastIndex - m[8].length; - } - - sb.push(css.substring(index)); - - return sb.join(""); -}; - -YAHOO.compressor.cssmin = function (css, linebreakpos) { - - var startIndex = 0, - endIndex = 0, - i = 0, max = 0, - preservedTokens = [], - comments = [], - token = '', - totallen = css.length, - placeholder = ''; - - css = this._extractDataUrls(css, preservedTokens); - - // collect all comment blocks... - while ((startIndex = css.indexOf("/*", startIndex)) >= 0) { - endIndex = css.indexOf("*/", startIndex + 2); - if (endIndex < 0) { - endIndex = totallen; - } - token = css.slice(startIndex + 2, endIndex); - comments.push(token); - css = css.slice(0, startIndex + 2) + "___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_" + (comments.length - 1) + "___" + css.slice(endIndex); - startIndex += 2; - } - - // preserve strings so their content doesn't get accidentally minified - css = css.replace(/("([^\\"]|\\.|\\)*")|('([^\\']|\\.|\\)*')/g, function (match) { - var i, max, quote = match.substring(0, 1); - - match = match.slice(1, -1); - - // maybe the string contains a comment-like substring? - // one, maybe more? put'em back then - if (match.indexOf("___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_") >= 0) { - for (i = 0, max = comments.length; i < max; i = i + 1) { - match = match.replace("___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_" + i + "___", comments[i]); - } - } - - // minify alpha opacity in filter strings - match = match.replace(/progid:DXImageTransform\.Microsoft\.Alpha\(Opacity=/gi, "alpha(opacity="); - - preservedTokens.push(match); - return quote + "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___" + quote; - }); - - // strings are safe, now wrestle the comments - for (i = 0, max = comments.length; i < max; i = i + 1) { - - token = comments[i]; - placeholder = "___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_" + i + "___"; - - // ! in the first position of the comment means preserve - // so push to the preserved tokens keeping the ! - if (token.charAt(0) === "!") { - preservedTokens.push(token); - css = css.replace(placeholder, "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___"); - continue; - } - - // \ in the last position looks like hack for Mac/IE5 - // shorten that to /*\*/ and the next one to /**/ - if (token.charAt(token.length - 1) === "\\") { - preservedTokens.push("\\"); - css = css.replace(placeholder, "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___"); - i = i + 1; // attn: advancing the loop - preservedTokens.push(""); - css = css.replace("___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_" + i + "___", "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___"); - continue; - } - - // keep empty comments after child selectors (IE7 hack) - // e.g. html >/**/ body - if (token.length === 0) { - startIndex = css.indexOf(placeholder); - if (startIndex > 2) { - if (css.charAt(startIndex - 3) === '>') { - preservedTokens.push(""); - css = css.replace(placeholder, "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___"); - } - } - } - - // in all other cases kill the comment - css = css.replace("/*" + placeholder + "*/", ""); - } - - - // Normalize all whitespace strings to single spaces. Easier to work with that way. - css = css.replace(/\s+/g, " "); - - // Remove the spaces before the things that should not have spaces before them. - // But, be careful not to turn "p :link {...}" into "p:link{...}" - // Swap out any pseudo-class colons with the token, and then swap back. - css = css.replace(/(^|\})(([^\{:])+:)+([^\{]*\{)/g, function (m) { - return m.replace(":", "___YUICSSMIN_PSEUDOCLASSCOLON___"); - }); - css = css.replace(/\s+([!{};:>+\(\)\],])/g, '$1'); - css = css.replace(/___YUICSSMIN_PSEUDOCLASSCOLON___/g, ":"); - - // retain space for special IE6 cases - css = css.replace(/:first-(line|letter)(\{|,)/g, ":first-$1 $2"); - - // no space after the end of a preserved comment - css = css.replace(/\*\/ /g, '*/'); - - - // If there is a @charset, then only allow one, and push to the top of the file. - css = css.replace(/^(.*)(@charset "[^"]*";)/gi, '$2$1'); - css = css.replace(/^(\s*@charset [^;]+;\s*)+/gi, '$1'); - - // Put the space back in some cases, to support stuff like - // @media screen and (-webkit-min-device-pixel-ratio:0){ - css = css.replace(/\band\(/gi, "and ("); - - - // Remove the spaces after the things that should not have spaces after them. - css = css.replace(/([!{}:;>+\(\[,])\s+/g, '$1'); - - // remove unnecessary semicolons - css = css.replace(/;+\}/g, "}"); - - // Replace 0(px,em,%) with 0. - css = css.replace(/([\s:])(0)(px|em|%|in|cm|mm|pc|pt|ex)/gi, "$1$2"); - - // Replace 0 0 0 0; with 0. - css = css.replace(/:0 0 0 0(;|\})/g, ":0$1"); - css = css.replace(/:0 0 0(;|\})/g, ":0$1"); - css = css.replace(/:0 0(;|\})/g, ":0$1"); - - // Replace background-position:0; with background-position:0 0; - // same for transform-origin - css = css.replace(/(background-position|transform-origin|webkit-transform-origin|moz-transform-origin|o-transform-origin|ms-transform-origin):0(;|\})/gi, function(all, prop, tail) { - return prop.toLowerCase() + ":0 0" + tail; - }); - - // Replace 0.6 to .6, but only when preceded by : or a white-space - css = css.replace(/(:|\s)0+\.(\d+)/g, "$1.$2"); - - // Shorten colors from rgb(51,102,153) to #336699 - // This makes it more likely that it'll get further compressed in the next step. - css = css.replace(/rgb\s*\(\s*([0-9,\s]+)\s*\)/gi, function () { - var i, rgbcolors = arguments[1].split(','); - for (i = 0; i < rgbcolors.length; i = i + 1) { - rgbcolors[i] = parseInt(rgbcolors[i], 10).toString(16); - if (rgbcolors[i].length === 1) { - rgbcolors[i] = '0' + rgbcolors[i]; - } - } - return '#' + rgbcolors.join(''); - }); - - // Shorten colors from #AABBCC to #ABC. - css = this._compressHexColors(css); - - // border: none -> border:0 - css = css.replace(/(border|border-top|border-right|border-bottom|border-right|outline|background):none(;|\})/gi, function(all, prop, tail) { - return prop.toLowerCase() + ":0" + tail; - }); - - // shorter opacity IE filter - css = css.replace(/progid:DXImageTransform\.Microsoft\.Alpha\(Opacity=/gi, "alpha(opacity="); - - // Remove empty rules. - css = css.replace(/[^\};\{\/]+\{\}/g, ""); - - if (linebreakpos >= 0) { - // Some source control tools don't like it when files containing lines longer - // than, say 8000 characters, are checked in. The linebreak option is used in - // that case to split long lines after a specific column. - startIndex = 0; - i = 0; - while (i < css.length) { - i = i + 1; - if (css[i - 1] === '}' && i - startIndex > linebreakpos) { - css = css.slice(0, i) + '\n' + css.slice(i); - startIndex = i; - } - } - } - - // Replace multiple semi-colons in a row by a single one - // See SF bug #1980989 - css = css.replace(/;;+/g, ";"); - - // restore preserved comments and strings - for (i = 0, max = preservedTokens.length; i < max; i = i + 1) { - css = css.replace("___YUICSSMIN_PRESERVED_TOKEN_" + i + "___", preservedTokens[i]); - } - - // Trim the final string (for any leading or trailing white spaces) - css = css.replace(/^\s+|\s+$/g, ""); - - return css; - -}; - -exports.compressor = YAHOO.compressor; diff --git a/r2/r2/lib/contrib/less.js/lib/less/functions.js b/r2/r2/lib/contrib/less.js/lib/less/functions.js deleted file mode 100644 index 6eb34bac8..000000000 --- a/r2/r2/lib/contrib/less.js/lib/less/functions.js +++ /dev/null @@ -1,228 +0,0 @@ -(function (tree) { - -tree.functions = { - rgb: function (r, g, b) { - return this.rgba(r, g, b, 1.0); - }, - rgba: function (r, g, b, a) { - var rgb = [r, g, b].map(function (c) { return number(c) }), - a = number(a); - return new(tree.Color)(rgb, a); - }, - hsl: function (h, s, l) { - return this.hsla(h, s, l, 1.0); - }, - hsla: function (h, s, l, a) { - h = (number(h) % 360) / 360; - s = number(s); l = number(l); a = number(a); - - var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; - var m1 = l * 2 - m2; - - return this.rgba(hue(h + 1/3) * 255, - hue(h) * 255, - hue(h - 1/3) * 255, - a); - - function hue(h) { - h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); - if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; - else if (h * 2 < 1) return m2; - else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; - else return m1; - } - }, - hue: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().h)); - }, - saturation: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); - }, - lightness: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); - }, - alpha: function (color) { - return new(tree.Dimension)(color.toHSL().a); - }, - saturate: function (color, amount) { - var hsl = color.toHSL(); - - hsl.s += amount.value / 100; - hsl.s = clamp(hsl.s); - return hsla(hsl); - }, - desaturate: function (color, amount) { - var hsl = color.toHSL(); - - hsl.s -= amount.value / 100; - hsl.s = clamp(hsl.s); - return hsla(hsl); - }, - lighten: function (color, amount) { - var hsl = color.toHSL(); - - hsl.l += amount.value / 100; - hsl.l = clamp(hsl.l); - return hsla(hsl); - }, - darken: function (color, amount) { - var hsl = color.toHSL(); - - hsl.l -= amount.value / 100; - hsl.l = clamp(hsl.l); - return hsla(hsl); - }, - fadein: function (color, amount) { - var hsl = color.toHSL(); - - hsl.a += amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - fadeout: function (color, amount) { - var hsl = color.toHSL(); - - hsl.a -= amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - fade: function (color, amount) { - var hsl = color.toHSL(); - - hsl.a = amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - spin: function (color, amount) { - var hsl = color.toHSL(); - var hue = (hsl.h + amount.value) % 360; - - hsl.h = hue < 0 ? 360 + hue : hue; - - return hsla(hsl); - }, - // - // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein - // http://sass-lang.com - // - mix: function (color1, color2, weight) { - var p = weight.value / 100.0; - var w = p * 2 - 1; - var a = color1.toHSL().a - color2.toHSL().a; - - var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; - var w2 = 1 - w1; - - var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, - color1.rgb[1] * w1 + color2.rgb[1] * w2, - color1.rgb[2] * w1 + color2.rgb[2] * w2]; - - var alpha = color1.alpha * p + color2.alpha * (1 - p); - - return new(tree.Color)(rgb, alpha); - }, - greyscale: function (color) { - return this.desaturate(color, new(tree.Dimension)(100)); - }, - e: function (str) { - return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); - }, - escape: function (str) { - return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); - }, - '%': function (quoted /* arg, arg, ...*/) { - var args = Array.prototype.slice.call(arguments, 1), - str = quoted.value; - - for (var i = 0; i < args.length; i++) { - str = str.replace(/%[sda]/i, function(token) { - var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); - return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; - }); - } - str = str.replace(/%%/g, '%'); - return new(tree.Quoted)('"' + str + '"', str); - }, - round: function (n) { - return this._math('round', n); - }, - ceil: function (n) { - return this._math('ceil', n); - }, - floor: function (n) { - return this._math('floor', n); - }, - _math: function (fn, n) { - if (n instanceof tree.Dimension) { - return new(tree.Dimension)(Math[fn](number(n)), n.unit); - } else if (typeof(n) === 'number') { - return Math[fn](n); - } else { - throw { type: "Argument", message: "argument must be a number" }; - } - }, - argb: function (color) { - return new(tree.Anonymous)(color.toARGB()); - - }, - percentage: function (n) { - return new(tree.Dimension)(n.value * 100, '%'); - }, - color: function (n) { - if (n instanceof tree.Quoted) { - return new(tree.Color)(n.value.slice(1)); - } else { - throw { type: "Argument", message: "argument must be a string" }; - } - }, - iscolor: function (n) { - return this._isa(n, tree.Color); - }, - isnumber: function (n) { - return this._isa(n, tree.Dimension); - }, - isstring: function (n) { - return this._isa(n, tree.Quoted); - }, - iskeyword: function (n) { - return this._isa(n, tree.Keyword); - }, - isurl: function (n) { - return this._isa(n, tree.URL); - }, - ispixel: function (n) { - return (n instanceof tree.Dimension) && n.unit === 'px' ? tree.True : tree.False; - }, - ispercentage: function (n) { - return (n instanceof tree.Dimension) && n.unit === '%' ? tree.True : tree.False; - }, - isem: function (n) { - return (n instanceof tree.Dimension) && n.unit === 'em' ? tree.True : tree.False; - }, - _isa: function (n, Type) { - return (n instanceof Type) ? tree.True : tree.False; - } -}; - -function hsla(hsla) { - return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); -} - -function number(n) { - if (n instanceof tree.Dimension) { - return parseFloat(n.unit == '%' ? n.value / 100 : n.value); - } else if (typeof(n) === 'number') { - return n; - } else { - throw { - error: "RuntimeError", - message: "color functions take numbers as parameters" - }; - } -} - -function clamp(val) { - return Math.min(1, Math.max(0, val)); -} - -})(require('./tree')); diff --git a/r2/r2/lib/contrib/less.js/lib/less/index.js b/r2/r2/lib/contrib/less.js/lib/less/index.js deleted file mode 100644 index a11fa998d..000000000 --- a/r2/r2/lib/contrib/less.js/lib/less/index.js +++ /dev/null @@ -1,148 +0,0 @@ -var path = require('path'), - sys = require('util'), - fs = require('fs'); - -var less = { - version: [1, 3, 0], - Parser: require('./parser').Parser, - importer: require('./parser').importer, - tree: require('./tree'), - render: function (input, options, callback) { - options = options || {}; - - if (typeof(options) === 'function') { - callback = options, options = {}; - } - - var parser = new(less.Parser)(options), - ee; - - if (callback) { - parser.parse(input, function (e, root) { - callback(e, root && root.toCSS && root.toCSS(options)); - }); - } else { - ee = new(require('events').EventEmitter); - - process.nextTick(function () { - parser.parse(input, function (e, root) { - if (e) { ee.emit('error', e) } - else { ee.emit('success', root.toCSS(options)) } - }); - }); - return ee; - } - }, - writeError: function (ctx, options) { - options = options || {}; - - var message = ""; - var extract = ctx.extract; - var error = []; - var stylize = options.color ? less.stylize : function (str) { return str }; - - if (options.silent) { return } - - if (ctx.stack) { return sys.error(stylize(ctx.stack, 'red')) } - - if (!ctx.hasOwnProperty('index')) { - return sys.error(ctx.stack || ctx.message); - } - - if (typeof(extract[0]) === 'string') { - error.push(stylize((ctx.line - 1) + ' ' + extract[0], 'grey')); - } - - if (extract[1]) { - error.push(ctx.line + ' ' + extract[1].slice(0, ctx.column) - + stylize(stylize(stylize(extract[1][ctx.column], 'bold') - + extract[1].slice(ctx.column + 1), 'red'), 'inverse')); - } - - if (typeof(extract[2]) === 'string') { - error.push(stylize((ctx.line + 1) + ' ' + extract[2], 'grey')); - } - error = error.join('\n') + '\033[0m\n'; - - message += stylize(ctx.type + 'Error: ' + ctx.message, 'red'); - ctx.filename && (message += stylize(' in ', 'red') + ctx.filename + - stylize(':' + ctx.line + ':' + ctx.column, 'grey')); - - sys.error(message, error); - - if (ctx.callLine) { - sys.error(stylize('from ', 'red') + (ctx.filename || '')); - sys.error(stylize(ctx.callLine, 'grey') + ' ' + ctx.callExtract); - } - } -}; - -['color', 'directive', 'operation', 'dimension', - 'keyword', 'variable', 'ruleset', 'element', - 'selector', 'quoted', 'expression', 'rule', - 'call', 'url', 'alpha', 'import', - 'mixin', 'comment', 'anonymous', 'value', - 'javascript', 'assignment', 'condition', 'paren', - 'media' -].forEach(function (n) { - require('./tree/' + n); -}); - -less.Parser.importer = function (file, paths, callback, env) { - var pathname; - - // TODO: Undo this at some point, - // or use different approach. - paths.unshift('.'); - - for (var i = 0; i < paths.length; i++) { - try { - pathname = path.join(paths[i], file); - fs.statSync(pathname); - break; - } catch (e) { - pathname = null; - } - } - - if (pathname) { - fs.readFile(pathname, 'utf-8', function(e, data) { - if (e) return callback(e); - - new(less.Parser)({ - paths: [path.dirname(pathname)].concat(paths), - filename: pathname - }).parse(data, function (e, root) { - callback(e, root, data); - }); - }); - } else { - if (typeof(env.errback) === "function") { - env.errback(file, paths, callback); - } else { - callback({ type: 'File', message: "'" + file + "' wasn't found.\n" }); - } - } -} - -require('./functions'); -require('./colors'); - -for (var k in less) { exports[k] = less[k] } - -// Stylize a string -function stylize(str, style) { - var styles = { - 'bold' : [1, 22], - 'inverse' : [7, 27], - 'underline' : [4, 24], - 'yellow' : [33, 39], - 'green' : [32, 39], - 'red' : [31, 39], - 'grey' : [90, 39] - }; - return '\033[' + styles[style][0] + 'm' + str + - '\033[' + styles[style][1] + 'm'; -} -less.stylize = stylize; - diff --git a/r2/r2/lib/contrib/less.js/lib/less/parser.js b/r2/r2/lib/contrib/less.js/lib/less/parser.js deleted file mode 100644 index d732e1b15..000000000 --- a/r2/r2/lib/contrib/less.js/lib/less/parser.js +++ /dev/null @@ -1,1334 +0,0 @@ -var less, tree; - -if (typeof environment === "object" && ({}).toString.call(environment) === "[object Environment]") { - // Rhino - // Details on how to detect Rhino: https://github.com/ringo/ringojs/issues/88 - if (typeof(window) === 'undefined') { less = {} } - else { less = window.less = {} } - tree = less.tree = {}; - less.mode = 'rhino'; -} else if (typeof(window) === 'undefined') { - // Node.js - less = exports, - tree = require('./tree'); - less.mode = 'node'; -} else { - // Browser - if (typeof(window.less) === 'undefined') { window.less = {} } - less = window.less, - tree = window.less.tree = {}; - less.mode = 'browser'; -} -// -// less.js - parser -// -// A relatively straight-forward predictive parser. -// There is no tokenization/lexing stage, the input is parsed -// in one sweep. -// -// To make the parser fast enough to run in the browser, several -// optimization had to be made: -// -// - Matching and slicing on a huge input is often cause of slowdowns. -// The solution is to chunkify the input into smaller strings. -// The chunks are stored in the `chunks` var, -// `j` holds the current chunk index, and `current` holds -// the index of the current chunk in relation to `input`. -// This gives us an almost 4x speed-up. -// -// - In many cases, we don't need to match individual tokens; -// for example, if a value doesn't hold any variables, operations -// or dynamic references, the parser can effectively 'skip' it, -// treating it as a literal. -// An example would be '1px solid #000' - which evaluates to itself, -// we don't need to know what the individual components are. -// The drawback, of course is that you don't get the benefits of -// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, -// and a smaller speed-up in the code-gen. -// -// -// Token matching is done with the `$` function, which either takes -// a terminal string or regexp, or a non-terminal function to call. -// It also takes care of moving all the indices forwards. -// -// -less.Parser = function Parser(env) { - var input, // LeSS input string - i, // current index in `input` - j, // current chunk - temp, // temporarily holds a chunk's state, for backtracking - memo, // temporarily holds `i`, when backtracking - furthest, // furthest index the parser has gone to - chunks, // chunkified input - current, // index of current chunk, in `input` - parser; - - var that = this; - - // This function is called after all files - // have been imported through `@import`. - var finish = function () {}; - - var imports = this.imports = { - paths: env && env.paths || [], // Search paths, when importing - queue: [], // Files which haven't been imported yet - files: {}, // Holds the imported parse trees - contents: {}, // Holds the imported file contents - mime: env && env.mime, // MIME type of .less files - error: null, // Error in parsing/evaluating an import - push: function (path, callback) { - var that = this; - this.queue.push(path); - - // - // Import a file asynchronously - // - less.Parser.importer(path, this.paths, function (e, root, contents) { - that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue - - var imported = path in that.files; - - that.files[path] = root; // Store the root - that.contents[path] = contents; - - if (e && !that.error) { that.error = e } - - callback(e, root, imported); - - if (that.queue.length === 0) { finish() } // Call `finish` if we're done importing - }, env); - } - }; - - function save() { temp = chunks[j], memo = i, current = i } - function restore() { chunks[j] = temp, i = memo, current = i } - - function sync() { - if (i > current) { - chunks[j] = chunks[j].slice(i - current); - current = i; - } - } - // - // Parse from a token, regexp or string, and move forward if match - // - function $(tok) { - var match, args, length, c, index, endIndex, k, mem; - - // - // Non-terminal - // - if (tok instanceof Function) { - return tok.call(parser.parsers); - // - // Terminal - // - // Either match a single character in the input, - // or match a regexp in the current chunk (chunk[j]). - // - } else if (typeof(tok) === 'string') { - match = input.charAt(i) === tok ? tok : null; - length = 1; - sync (); - } else { - sync (); - - if (match = tok.exec(chunks[j])) { - length = match[0].length; - } else { - return null; - } - } - - // The match is confirmed, add the match length to `i`, - // and consume any extra white-space characters (' ' || '\n') - // which come after that. The reason for this is that LeSS's - // grammar is mostly white-space insensitive. - // - if (match) { - mem = i += length; - endIndex = i + chunks[j].length - length; - - while (i < endIndex) { - c = input.charCodeAt(i); - if (! (c === 32 || c === 10 || c === 9)) { break } - i++; - } - chunks[j] = chunks[j].slice(length + (i - mem)); - current = i; - - if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } - - if(typeof(match) === 'string') { - return match; - } else { - return match.length === 1 ? match[0] : match; - } - } - } - - function expect(arg, msg) { - var result = $(arg); - if (! result) { - error(msg || (typeof(arg) === 'string' ? "expected '" + arg + "' got '" + input.charAt(i) + "'" - : "unexpected token")); - } else { - return result; - } - } - - function error(msg, type) { - throw { index: i, type: type || 'Syntax', message: msg }; - } - - // Same as $(), but don't change the state of the parser, - // just return the match. - function peek(tok) { - if (typeof(tok) === 'string') { - return input.charAt(i) === tok; - } else { - if (tok.test(chunks[j])) { - return true; - } else { - return false; - } - } - } - - function basename(pathname) { - if (less.mode === 'node') { - return require('path').basename(pathname); - } else { - return pathname.match(/[^\/]+$/)[0]; - } - } - - function getInput(e, env) { - if (e.filename && env.filename && (e.filename !== env.filename)) { - return parser.imports.contents[basename(e.filename)]; - } else { - return input; - } - } - - function getLocation(index, input) { - for (var n = index, column = -1; - n >= 0 && input.charAt(n) !== '\n'; - n--) { column++ } - - return { line: typeof(index) === 'number' ? (input.slice(0, index).match(/\n/g) || "").length : null, - column: column }; - } - - function LessError(e, env) { - var input = getInput(e, env), - loc = getLocation(e.index, input), - line = loc.line, - col = loc.column, - lines = input.split('\n'); - - this.type = e.type || 'Syntax'; - this.message = e.message; - this.filename = e.filename || env.filename; - this.index = e.index; - this.line = typeof(line) === 'number' ? line + 1 : null; - this.callLine = e.call && (getLocation(e.call, input).line + 1); - this.callExtract = lines[getLocation(e.call, input).line]; - this.stack = e.stack; - this.column = col; - this.extract = [ - lines[line - 1], - lines[line], - lines[line + 1] - ]; - } - - this.env = env = env || {}; - - // The optimization level dictates the thoroughness of the parser, - // the lower the number, the less nodes it will create in the tree. - // This could matter for debugging, or if you want to access - // the individual nodes in the tree. - this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; - - this.env.filename = this.env.filename || null; - - // - // The Parser - // - return parser = { - - imports: imports, - // - // Parse an input string into an abstract syntax tree, - // call `callback` when done. - // - parse: function (str, callback) { - var root, start, end, zone, line, lines, buff = [], c, error = null; - - i = j = current = furthest = 0; - input = str.replace(/\r\n/g, '\n'); - - // Split the input into chunks. - chunks = (function (chunks) { - var j = 0, - skip = /[^"'`\{\}\/\(\)\\]+/g, - comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, - string = /"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`\\\r\n]|\\.)*)`/g, - level = 0, - match, - chunk = chunks[0], - inParam; - - for (var i = 0, c, cc; i < input.length; i++) { - skip.lastIndex = i; - if (match = skip.exec(input)) { - if (match.index === i) { - i += match[0].length; - chunk.push(match[0]); - } - } - c = input.charAt(i); - comment.lastIndex = string.lastIndex = i; - - if (match = string.exec(input)) { - if (match.index === i) { - i += match[0].length; - chunk.push(match[0]); - c = input.charAt(i); - } - } - - if (!inParam && c === '/') { - cc = input.charAt(i + 1); - if (cc === '/' || cc === '*') { - if (match = comment.exec(input)) { - if (match.index === i) { - i += match[0].length; - chunk.push(match[0]); - c = input.charAt(i); - } - } - } - } - - switch (c) { - case '{': if (! inParam) { level ++; chunk.push(c); break } - case '}': if (! inParam) { level --; chunk.push(c); chunks[++j] = chunk = []; break } - case '(': if (! inParam) { inParam = true; chunk.push(c); break } - case ')': if ( inParam) { inParam = false; chunk.push(c); break } - default: chunk.push(c); - } - } - if (level > 0) { - error = new(LessError)({ - index: i, - type: 'Parse', - message: "missing closing `}`", - filename: env.filename - }, env); - } - - return chunks.map(function (c) { return c.join('') });; - })([[]]); - - if (error) { - return callback(error); - } - - // Start with the primary rule. - // The whole syntax tree is held under a Ruleset node, - // with the `root` property set to true, so no `{}` are - // output. The callback is called when the input is parsed. - try { - root = new(tree.Ruleset)([], $(this.parsers.primary)); - root.root = true; - } catch (e) { - return callback(new(LessError)(e, env)); - } - - root.toCSS = (function (evaluate) { - var line, lines, column; - - return function (options, variables) { - var frames = [], importError; - - options = options || {}; - // - // Allows setting variables with a hash, so: - // - // `{ color: new(tree.Color)('#f01') }` will become: - // - // new(tree.Rule)('@color', - // new(tree.Value)([ - // new(tree.Expression)([ - // new(tree.Color)('#f01') - // ]) - // ]) - // ) - // - if (typeof(variables) === 'object' && !Array.isArray(variables)) { - variables = Object.keys(variables).map(function (k) { - var value = variables[k]; - - if (! (value instanceof tree.Value)) { - if (! (value instanceof tree.Expression)) { - value = new(tree.Expression)([value]); - } - value = new(tree.Value)([value]); - } - return new(tree.Rule)('@' + k, value, false, 0); - }); - frames = [new(tree.Ruleset)(null, variables)]; - } - - try { - var css = evaluate.call(this, { frames: frames }) - .toCSS([], { compress: options.compress || false }); - } catch (e) { - throw new(LessError)(e, env); - } - - if ((importError = parser.imports.error)) { // Check if there was an error during importing - if (importError instanceof LessError) throw importError; - else throw new(LessError)(importError, env); - } - - if (options.yuicompress && less.mode === 'node') { - return require('./cssmin').compressor.cssmin(css); - } else if (options.compress) { - return css.replace(/(\s)+/g, "$1"); - } else { - return css; - } - }; - })(root.eval); - - // If `i` is smaller than the `input.length - 1`, - // it means the parser wasn't able to parse the whole - // string, so we've got a parsing error. - // - // We try to extract a \n delimited string, - // showing the line where the parse error occured. - // We split it up into two parts (the part which parsed, - // and the part which didn't), so we can color them differently. - if (i < input.length - 1) { - i = furthest; - lines = input.split('\n'); - line = (input.slice(0, i).match(/\n/g) || "").length + 1; - - for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } - - error = { - type: "Parse", - message: "Syntax Error on line " + line, - index: i, - filename: env.filename, - line: line, - column: column, - extract: [ - lines[line - 2], - lines[line - 1], - lines[line] - ] - }; - } - - if (this.imports.queue.length > 0) { - finish = function () { callback(error, root) }; - } else { - callback(error, root); - } - }, - - // - // Here in, the parsing rules/functions - // - // The basic structure of the syntax tree generated is as follows: - // - // Ruleset -> Rule -> Value -> Expression -> Entity - // - // Here's some LESS code: - // - // .class { - // color: #fff; - // border: 1px solid #000; - // width: @w + 4px; - // > .child {...} - // } - // - // And here's what the parse tree might look like: - // - // Ruleset (Selector '.class', [ - // Rule ("color", Value ([Expression [Color #fff]])) - // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) - // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) - // Ruleset (Selector [Element '>', '.child'], [...]) - // ]) - // - // In general, most rules will try to parse a token with the `$()` function, and if the return - // value is truly, will return a new node, of the relevant type. Sometimes, we need to check - // first, before parsing, that's when we use `peek()`. - // - parsers: { - // - // The `primary` rule is the *entry* and *exit* point of the parser. - // The rules here can appear at any level of the parse tree. - // - // The recursive nature of the grammar is an interplay between the `block` - // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, - // as represented by this simplified grammar: - // - // primary → (ruleset | rule)+ - // ruleset → selector+ block - // block → '{' primary '}' - // - // Only at one point is the primary rule not called from the - // block rule: at the root level. - // - primary: function () { - var node, root = []; - - while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || - $(this.mixin.call) || $(this.comment) || $(this.directive)) - || $(/^[\s\n]+/)) { - node && root.push(node); - } - return root; - }, - - // We create a Comment node for CSS comments `/* */`, - // but keep the LeSS comments `//` silent, by just skipping - // over them. - comment: function () { - var comment; - - if (input.charAt(i) !== '/') return; - - if (input.charAt(i + 1) === '/') { - return new(tree.Comment)($(/^\/\/.*/), true); - } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { - return new(tree.Comment)(comment); - } - }, - - // - // Entities are tokens which can be found inside an Expression - // - entities: { - // - // A string, which supports escaping " and ' - // - // "milky way" 'he\'s the one!' - // - quoted: function () { - var str, j = i, e; - - if (input.charAt(j) === '~') { j++, e = true } // Escaped strings - if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; - - e && $('~'); - - if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { - return new(tree.Quoted)(str[0], str[1] || str[2], e); - } - }, - - // - // A catch-all word, such as: - // - // black border-collapse - // - keyword: function () { - var k; - - if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) { - if (tree.colors.hasOwnProperty(k)) { - // detect named color - return new(tree.Color)(tree.colors[k].slice(1)); - } else { - return new(tree.Keyword)(k); - } - } - }, - - // - // A function call - // - // rgb(255, 0, 255) - // - // We also try to catch IE's `alpha()`, but let the `alpha` parser - // deal with the details. - // - // The arguments are parsed with the `entities.arguments` parser. - // - call: function () { - var name, args, index = i; - - if (! (name = /^([\w-]+|%|progid:[\w\.]+)\(/.exec(chunks[j]))) return; - - name = name[1].toLowerCase(); - - if (name === 'url') { return null } - else { i += name.length } - - if (name === 'alpha') { return $(this.alpha) } - - $('('); // Parse the '(' and consume whitespace. - - args = $(this.entities.arguments); - - if (! $(')')) return; - - if (name) { return new(tree.Call)(name, args, index, env.filename) } - }, - arguments: function () { - var args = [], arg; - - while (arg = $(this.entities.assignment) || $(this.expression)) { - args.push(arg); - if (! $(',')) { break } - } - return args; - }, - literal: function () { - return $(this.entities.dimension) || - $(this.entities.color) || - $(this.entities.quoted); - }, - - // Assignments are argument entities for calls. - // They are present in ie filter properties as shown below. - // - // filter: progid:DXImageTransform.Microsoft.Alpha( *opacity=50* ) - // - - assignment: function () { - var key, value; - if ((key = $(/^\w+(?=\s?=)/i)) && $('=') && (value = $(this.entity))) { - return new(tree.Assignment)(key, value); - } - }, - - // - // Parse url() tokens - // - // We use a specific rule for urls, because they don't really behave like - // standard function calls. The difference is that the argument doesn't have - // to be enclosed within a string, so it can't be parsed as an Expression. - // - url: function () { - var value; - - if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; - value = $(this.entities.quoted) || $(this.entities.variable) || - $(this.entities.dataURI) || $(/^[-\w%@$\/.&=:;#+?~]+/) || ""; - - expect(')'); - - return new(tree.URL)((value.value || value.data || value instanceof tree.Variable) - ? value : new(tree.Anonymous)(value), imports.paths); - }, - - dataURI: function () { - var obj; - - if ($(/^data:/)) { - obj = {}; - obj.mime = $(/^[^\/]+\/[^,;)]+/) || ''; - obj.charset = $(/^;\s*charset=[^,;)]+/) || ''; - obj.base64 = $(/^;\s*base64/) || ''; - obj.data = $(/^,\s*[^)]+/); - - if (obj.data) { return obj } - } - }, - - // - // A Variable entity, such as `@fink`, in - // - // width: @fink + 2px - // - // We use a different parser for variable definitions, - // see `parsers.variable`. - // - variable: function () { - var name, index = i; - - if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { - return new(tree.Variable)(name, index, env.filename); - } - }, - - // - // A Hexadecimal color - // - // #4F3C2F - // - // `rgb` and `hsl` colors are parsed through the `entities.call` parser. - // - color: function () { - var rgb; - - if (input.charAt(i) === '#' && (rgb = $(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/))) { - return new(tree.Color)(rgb[1]); - } - }, - - // - // A Dimension, that is, a number and a unit - // - // 0.5em 95% - // - dimension: function () { - var value, c = input.charCodeAt(i); - if ((c > 57 || c < 45) || c === 47) return; - - if (value = $(/^(-?\d*\.?\d+)(px|%|em|rem|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn|dpi)?/)) { - return new(tree.Dimension)(value[1], value[2]); - } - }, - - // - // JavaScript code to be evaluated - // - // `window.location.href` - // - javascript: function () { - var str, j = i, e; - - if (input.charAt(j) === '~') { j++, e = true } // Escaped strings - if (input.charAt(j) !== '`') { return } - - e && $('~'); - - if (str = $(/^`([^`]*)`/)) { - return new(tree.JavaScript)(str[1], i, e); - } - } - }, - - // - // The variable part of a variable definition. Used in the `rule` parser - // - // @fink: - // - variable: function () { - var name; - - if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } - }, - - // - // A font size/line-height shorthand - // - // small/12px - // - // We need to peek first, or we'll match on keywords and dimensions - // - shorthand: function () { - var a, b; - - if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; - - if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { - return new(tree.Shorthand)(a, b); - } - }, - - // - // Mixins - // - mixin: { - // - // A Mixin call, with an optional argument list - // - // #mixins > .square(#fff); - // .rounded(4px, black); - // .button; - // - // The `while` loop is there because mixins can be - // namespaced, but we only support the child and descendant - // selector for now. - // - call: function () { - var elements = [], e, c, args = [], arg, index = i, s = input.charAt(i), name, value, important = false; - - if (s !== '.' && s !== '#') { return } - - while (e = $(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)) { - elements.push(new(tree.Element)(c, e, i)); - c = $('>'); - } - if ($('(')) { - while (arg = $(this.expression)) { - value = arg; - name = null; - - // Variable - if (arg.value.length == 1) { - var val = arg.value[0]; - if (val instanceof tree.Variable) { - if ($(':')) { - if (value = $(this.expression)) { - name = val.name; - } else { - throw new(Error)("Expected value"); - } - } - } - } - - args.push({ name: name, value: value }); - - if (! $(',')) { break } - } - if (! $(')')) throw new(Error)("Expected )"); - } - - if ($(this.important)) { - important = true; - } - - if (elements.length > 0 && ($(';') || peek('}'))) { - return new(tree.mixin.Call)(elements, args, index, env.filename, important); - } - }, - - // - // A Mixin definition, with a list of parameters - // - // .rounded (@radius: 2px, @color) { - // ... - // } - // - // Until we have a finer grained state-machine, we have to - // do a look-ahead, to make sure we don't have a mixin call. - // See the `rule` function for more information. - // - // We start by matching `.rounded (`, and then proceed on to - // the argument list, which has optional default values. - // We store the parameters in `params`, with a `value` key, - // if there is a value, such as in the case of `@radius`. - // - // Once we've got our params list, and a closing `)`, we parse - // the `{...}` block. - // - definition: function () { - var name, params = [], match, ruleset, param, value, cond, variadic = false; - if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || - peek(/^[^{]*(;|})/)) return; - - save(); - - if (match = $(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)) { - name = match[1]; - - do { - if (input.charAt(i) === '.' && $(/^\.{3}/)) { - variadic = true; - break; - } else if (param = $(this.entities.variable) || $(this.entities.literal) - || $(this.entities.keyword)) { - // Variable - if (param instanceof tree.Variable) { - if ($(':')) { - value = expect(this.expression, 'expected expression'); - params.push({ name: param.name, value: value }); - } else if ($(/^\.{3}/)) { - params.push({ name: param.name, variadic: true }); - variadic = true; - break; - } else { - params.push({ name: param.name }); - } - } else { - params.push({ value: param }); - } - } else { - break; - } - } while ($(',')) - - expect(')'); - - if ($(/^when/)) { // Guard - cond = expect(this.conditions, 'expected condition'); - } - - ruleset = $(this.block); - - if (ruleset) { - return new(tree.mixin.Definition)(name, params, ruleset, cond, variadic); - } else { - restore(); - } - } - } - }, - - // - // Entities are the smallest recognized token, - // and can be found inside a rule's value. - // - entity: function () { - return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || - $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || - $(this.comment); - }, - - // - // A Rule terminator. Note that we use `peek()` to check for '}', - // because the `block` rule will be expecting it, but we still need to make sure - // it's there, if ';' was ommitted. - // - end: function () { - return $(';') || peek('}'); - }, - - // - // IE's alpha function - // - // alpha(opacity=88) - // - alpha: function () { - var value; - - if (! $(/^\(opacity=/i)) return; - if (value = $(/^\d+/) || $(this.entities.variable)) { - expect(')'); - return new(tree.Alpha)(value); - } - }, - - // - // A Selector Element - // - // div - // + h1 - // #socks - // input[type="text"] - // - // Elements are the building blocks for Selectors, - // they are made out of a `Combinator` (see combinator rule), - // and an element name, such as a tag a class, or `*`. - // - element: function () { - var e, t, c, v; - - c = $(this.combinator); - e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/) || - $('*') || $(this.attribute) || $(/^\([^)@]+\)/); - - if (! e) { - $('(') && (v = $(this.entities.variable)) && $(')') && (e = new(tree.Paren)(v)); - } - - if (e) { return new(tree.Element)(c, e, i) } - - if (c.value && c.value.charAt(0) === '&') { - return new(tree.Element)(c, null, i); - } - }, - - // - // Combinators combine elements together, in a Selector. - // - // Because our parser isn't white-space sensitive, special care - // has to be taken, when parsing the descendant combinator, ` `, - // as it's an empty space. We have to check the previous character - // in the input, to see if it's a ` ` character. More info on how - // we deal with this in *combinator.js*. - // - combinator: function () { - var match, c = input.charAt(i); - - if (c === '>' || c === '+' || c === '~') { - i++; - while (input.charAt(i) === ' ') { i++ } - return new(tree.Combinator)(c); - } else if (c === '&') { - match = '&'; - i++; - if(input.charAt(i) === ' ') { - match = '& '; - } - while (input.charAt(i) === ' ') { i++ } - return new(tree.Combinator)(match); - } else if (input.charAt(i - 1) === ' ') { - return new(tree.Combinator)(" "); - } else { - return new(tree.Combinator)(null); - } - }, - - // - // A CSS Selector - // - // .class > div + h1 - // li a:hover - // - // Selectors are made out of one or more Elements, see above. - // - selector: function () { - var sel, e, elements = [], c, match; - - if ($('(')) { - sel = $(this.entity); - expect(')'); - return new(tree.Selector)([new(tree.Element)('', sel, i)]); - } - - while (e = $(this.element)) { - c = input.charAt(i); - elements.push(e) - if (c === '{' || c === '}' || c === ';' || c === ',') { break } - } - - if (elements.length > 0) { return new(tree.Selector)(elements) } - }, - tag: function () { - return $(/^[a-zA-Z][a-zA-Z-]*[0-9]?/) || $('*'); - }, - attribute: function () { - var attr = '', key, val, op; - - if (! $('[')) return; - - if (key = $(/^[a-zA-Z-]+/) || $(this.entities.quoted)) { - if ((op = $(/^[|~*$^]?=/)) && - (val = $(this.entities.quoted) || $(/^[\w-]+/))) { - attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); - } else { attr = key } - } - - if (! $(']')) return; - - if (attr) { return "[" + attr + "]" } - }, - - // - // The `block` rule is used by `ruleset` and `mixin.definition`. - // It's a wrapper around the `primary` rule, with added `{}`. - // - block: function () { - var content; - - if ($('{') && (content = $(this.primary)) && $('}')) { - return content; - } - }, - - // - // div, .class, body > p {...} - // - ruleset: function () { - var selectors = [], s, rules, match; - save(); - - while (s = $(this.selector)) { - selectors.push(s); - $(this.comment); - if (! $(',')) { break } - $(this.comment); - } - - if (selectors.length > 0 && (rules = $(this.block))) { - return new(tree.Ruleset)(selectors, rules, env.strictImports); - } else { - // Backtrack - furthest = i; - restore(); - } - }, - rule: function () { - var name, value, c = input.charAt(i), important, match; - save(); - - if (c === '.' || c === '#' || c === '&') { return } - - if (name = $(this.variable) || $(this.property)) { - if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { - i += match[0].length - 1; - value = new(tree.Anonymous)(match[1]); - } else if (name === "font") { - value = $(this.font); - } else { - value = $(this.value); - } - important = $(this.important); - - if (value && $(this.end)) { - return new(tree.Rule)(name, value, important, memo); - } else { - furthest = i; - restore(); - } - } - }, - - // - // An @import directive - // - // @import "lib"; - // - // Depending on our environemnt, importing is done differently: - // In the browser, it's an XHR request, in Node, it would be a - // file-system operation. The function used for importing is - // stored in `import`, which we pass to the Import constructor. - // - "import": function () { - var path, features, index = i; - var dir = $(/^@import(?:-(once))?\s+/); - - if (dir && (path = $(this.entities.quoted) || $(this.entities.url))) { - features = $(this.mediaFeatures); - if ($(';')) { - return new(tree.Import)(path, imports, features, (dir[1] === 'once'), index); - } - } - }, - - mediaFeature: function () { - var e, p, nodes = []; - - do { - if (e = $(this.entities.keyword)) { - nodes.push(e); - } else if ($('(')) { - p = $(this.property); - e = $(this.entity); - if ($(')')) { - if (p && e) { - nodes.push(new(tree.Paren)(new(tree.Rule)(p, e, null, i, true))); - } else if (e) { - nodes.push(new(tree.Paren)(e)); - } else { - return null; - } - } else { return null } - } - } while (e); - - if (nodes.length > 0) { - return new(tree.Expression)(nodes); - } - }, - - mediaFeatures: function () { - var e, features = []; - - do { - if (e = $(this.mediaFeature)) { - features.push(e); - if (! $(',')) { break } - } else if (e = $(this.entities.variable)) { - features.push(e); - if (! $(',')) { break } - } - } while (e); - - return features.length > 0 ? features : null; - }, - - media: function () { - var features, rules; - - if ($(/^@media/)) { - features = $(this.mediaFeatures); - - if (rules = $(this.block)) { - return new(tree.Media)(rules, features); - } - } - }, - - // - // A CSS Directive - // - // @charset "utf-8"; - // - directive: function () { - var name, value, rules, types, e, nodes; - - if (input.charAt(i) !== '@') return; - - if (value = $(this['import']) || $(this.media)) { - return value; - } else if (name = $(/^@page|@keyframes/) || $(/^@(?:-webkit-|-moz-|-o-|-ms-)[a-z0-9-]+/)) { - types = ($(/^[^{]+/) || '').trim(); - if (rules = $(this.block)) { - return new(tree.Directive)(name + " " + types, rules); - } - } else if (name = $(/^@[-a-z]+/)) { - if (name === '@font-face') { - if (rules = $(this.block)) { - return new(tree.Directive)(name, rules); - } - } else if ((value = $(this.entity)) && $(';')) { - return new(tree.Directive)(name, value); - } - } - }, - font: function () { - var value = [], expression = [], weight, shorthand, font, e; - - while (e = $(this.shorthand) || $(this.entity)) { - expression.push(e); - } - value.push(new(tree.Expression)(expression)); - - if ($(',')) { - while (e = $(this.expression)) { - value.push(e); - if (! $(',')) { break } - } - } - return new(tree.Value)(value); - }, - - // - // A Value is a comma-delimited list of Expressions - // - // font-family: Baskerville, Georgia, serif; - // - // In a Rule, a Value represents everything after the `:`, - // and before the `;`. - // - value: function () { - var e, expressions = [], important; - - while (e = $(this.expression)) { - expressions.push(e); - if (! $(',')) { break } - } - - if (expressions.length > 0) { - return new(tree.Value)(expressions); - } - }, - important: function () { - if (input.charAt(i) === '!') { - return $(/^! *important/); - } - }, - sub: function () { - var e; - - if ($('(') && (e = $(this.expression)) && $(')')) { - return e; - } - }, - multiplication: function () { - var m, a, op, operation; - if (m = $(this.operand)) { - while (!peek(/^\/\*/) && (op = ($('/') || $('*'))) && (a = $(this.operand))) { - operation = new(tree.Operation)(op, [operation || m, a]); - } - return operation || m; - } - }, - addition: function () { - var m, a, op, operation; - if (m = $(this.multiplication)) { - while ((op = $(/^[-+]\s+/) || (input.charAt(i - 1) != ' ' && ($('+') || $('-')))) && - (a = $(this.multiplication))) { - operation = new(tree.Operation)(op, [operation || m, a]); - } - return operation || m; - } - }, - conditions: function () { - var a, b, index = i, condition; - - if (a = $(this.condition)) { - while ($(',') && (b = $(this.condition))) { - condition = new(tree.Condition)('or', condition || a, b, index); - } - return condition || a; - } - }, - condition: function () { - var a, b, c, op, index = i, negate = false; - - if ($(/^not/)) { negate = true } - expect('('); - if (a = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { - if (op = $(/^(?:>=|=<|[<=>])/)) { - if (b = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { - c = new(tree.Condition)(op, a, b, index, negate); - } else { - error('expected expression'); - } - } else { - c = new(tree.Condition)('=', a, new(tree.Keyword)('true'), index, negate); - } - expect(')'); - return $(/^and/) ? new(tree.Condition)('and', c, $(this.condition)) : c; - } - }, - - // - // An operand is anything that can be part of an operation, - // such as a Color, or a Variable - // - operand: function () { - var negate, p = input.charAt(i + 1); - - if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } - var o = $(this.sub) || $(this.entities.dimension) || - $(this.entities.color) || $(this.entities.variable) || - $(this.entities.call); - return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) - : o; - }, - - // - // Expressions either represent mathematical operations, - // or white-space delimited Entities. - // - // 1px solid black - // @var * 2 - // - expression: function () { - var e, delim, entities = [], d; - - while (e = $(this.addition) || $(this.entity)) { - entities.push(e); - } - if (entities.length > 0) { - return new(tree.Expression)(entities); - } - }, - property: function () { - var name; - - if (name = $(/^(\*?-?[-a-z_0-9]+)\s*:/)) { - return name[1]; - } - } - } - }; -}; - -if (less.mode === 'browser' || less.mode === 'rhino') { - // - // Used by `@import` directives - // - less.Parser.importer = function (path, paths, callback, env) { - if (!/^([a-z]+:)?\//.test(path) && paths.length > 0) { - path = paths[0] + path; - } - // We pass `true` as 3rd argument, to force the reload of the import. - // This is so we can get the syntax tree as opposed to just the CSS output, - // as we need this to evaluate the current stylesheet. - loadStyleSheet({ href: path, title: path, type: env.mime }, function (e) { - if (e && typeof(env.errback) === "function") { - env.errback.call(null, path, paths, callback, env); - } else { - callback.apply(null, arguments); - } - }, true); - }; -} - diff --git a/r2/r2/lib/contrib/less.js/lib/less/rhino.js b/r2/r2/lib/contrib/less.js/lib/less/rhino.js deleted file mode 100644 index a2c5662fd..000000000 --- a/r2/r2/lib/contrib/less.js/lib/less/rhino.js +++ /dev/null @@ -1,62 +0,0 @@ -var name; - -function loadStyleSheet(sheet, callback, reload, remaining) { - var sheetName = name.slice(0, name.lastIndexOf('/') + 1) + sheet.href; - var input = readFile(sheetName); - var parser = new less.Parser({ - paths: [sheet.href.replace(/[\w\.-]+$/, '')] - }); - parser.parse(input, function (e, root) { - if (e) { - print("Error: " + e); - quit(1); - } - callback(root, sheet, { local: false, lastModified: 0, remaining: remaining }); - }); - - // callback({}, sheet, { local: true, remaining: remaining }); -} - -function writeFile(filename, content) { - var fstream = new java.io.FileWriter(filename); - var out = new java.io.BufferedWriter(fstream); - out.write(content); - out.close(); -} - -// Command line integration via Rhino -(function (args) { - name = args[0]; - var output = args[1]; - - if (!name) { - print('No files present in the fileset; Check your pattern match in build.xml'); - quit(1); - } - path = name.split("/");path.pop();path=path.join("/") - - var input = readFile(name); - - if (!input) { - print('lesscss: couldn\'t open file ' + name); - quit(1); - } - - var result; - var parser = new less.Parser(); - parser.parse(input, function (e, root) { - if (e) { - quit(1); - } else { - result = root.toCSS(); - if (output) { - writeFile(output, result); - print("Written to " + output); - } else { - print(result); - } - quit(0); - } - }); - print("done"); -}(arguments)); diff --git a/r2/r2/lib/contrib/less.js/lib/less/tree.js b/r2/r2/lib/contrib/less.js/lib/less/tree.js deleted file mode 100644 index 24ecd7120..000000000 --- a/r2/r2/lib/contrib/less.js/lib/less/tree.js +++ /dev/null @@ -1,17 +0,0 @@ -(function (tree) { - -tree.find = function (obj, fun) { - for (var i = 0, r; i < obj.length; i++) { - if (r = fun.call(obj, obj[i])) { return r } - } - return null; -}; -tree.jsify = function (obj) { - if (Array.isArray(obj.value) && (obj.value.length > 1)) { - return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; - } else { - return obj.toCSS(false); - } -}; - -})(require('./tree')); diff --git a/r2/r2/lib/contrib/less.js/lib/less/tree/alpha.js b/r2/r2/lib/contrib/less.js/lib/less/tree/alpha.js deleted file mode 100644 index 139ae9204..000000000 --- a/r2/r2/lib/contrib/less.js/lib/less/tree/alpha.js +++ /dev/null @@ -1,17 +0,0 @@ -(function (tree) { - -tree.Alpha = function (val) { - this.value = val; -}; -tree.Alpha.prototype = { - toCSS: function () { - return "alpha(opacity=" + - (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; - }, - eval: function (env) { - if (this.value.eval) { this.value = this.value.eval(env) } - return this; - } -}; - -})(require('../tree')); diff --git a/r2/r2/lib/contrib/less.js/lib/less/tree/anonymous.js b/r2/r2/lib/contrib/less.js/lib/less/tree/anonymous.js deleted file mode 100644 index 460c9ec78..000000000 --- a/r2/r2/lib/contrib/less.js/lib/less/tree/anonymous.js +++ /dev/null @@ -1,13 +0,0 @@ -(function (tree) { - -tree.Anonymous = function (string) { - this.value = string.value || string; -}; -tree.Anonymous.prototype = { - toCSS: function () { - return this.value; - }, - eval: function () { return this } -}; - -})(require('../tree')); diff --git a/r2/r2/lib/contrib/less.js/lib/less/tree/assignment.js b/r2/r2/lib/contrib/less.js/lib/less/tree/assignment.js deleted file mode 100644 index 70ce6e2f0..000000000 --- a/r2/r2/lib/contrib/less.js/lib/less/tree/assignment.js +++ /dev/null @@ -1,17 +0,0 @@ -(function (tree) { - -tree.Assignment = function (key, val) { - this.key = key; - this.value = val; -}; -tree.Assignment.prototype = { - toCSS: function () { - return this.key + '=' + (this.value.toCSS ? this.value.toCSS() : this.value); - }, - eval: function (env) { - if (this.value.eval) { this.value = this.value.eval(env) } - return this; - } -}; - -})(require('../tree')); \ No newline at end of file diff --git a/r2/r2/lib/contrib/less.js/lib/less/tree/call.js b/r2/r2/lib/contrib/less.js/lib/less/tree/call.js deleted file mode 100644 index c1465dd47..000000000 --- a/r2/r2/lib/contrib/less.js/lib/less/tree/call.js +++ /dev/null @@ -1,48 +0,0 @@ -(function (tree) { - -// -// A function call node. -// -tree.Call = function (name, args, index, filename) { - this.name = name; - this.args = args; - this.index = index; - this.filename = filename; -}; -tree.Call.prototype = { - // - // When evaluating a function call, - // we either find the function in `tree.functions` [1], - // in which case we call it, passing the evaluated arguments, - // or we simply print it out as it appeared originally [2]. - // - // The *functions.js* file contains the built-in functions. - // - // The reason why we evaluate the arguments, is in the case where - // we try to pass a variable to a function, like: `saturate(@color)`. - // The function should receive the value, not the variable. - // - eval: function (env) { - var args = this.args.map(function (a) { return a.eval(env) }); - - if (this.name in tree.functions) { // 1. - try { - return tree.functions[this.name].apply(tree.functions, args); - } catch (e) { - throw { type: e.type || "Runtime", - message: "error evaluating function `" + this.name + "`" + - (e.message ? ': ' + e.message : ''), - index: this.index, filename: this.filename }; - } - } else { // 2. - return new(tree.Anonymous)(this.name + - "(" + args.map(function (a) { return a.toCSS() }).join(', ') + ")"); - } - }, - - toCSS: function (env) { - return this.eval(env).toCSS(); - } -}; - -})(require('../tree')); diff --git a/r2/r2/lib/contrib/less.js/lib/less/tree/color.js b/r2/r2/lib/contrib/less.js/lib/less/tree/color.js deleted file mode 100644 index 37ce1781d..000000000 --- a/r2/r2/lib/contrib/less.js/lib/less/tree/color.js +++ /dev/null @@ -1,101 +0,0 @@ -(function (tree) { -// -// RGB Colors - #ff0014, #eee -// -tree.Color = function (rgb, a) { - // - // The end goal here, is to parse the arguments - // into an integer triplet, such as `128, 255, 0` - // - // This facilitates operations and conversions. - // - if (Array.isArray(rgb)) { - this.rgb = rgb; - } else if (rgb.length == 6) { - this.rgb = rgb.match(/.{2}/g).map(function (c) { - return parseInt(c, 16); - }); - } else { - this.rgb = rgb.split('').map(function (c) { - return parseInt(c + c, 16); - }); - } - this.alpha = typeof(a) === 'number' ? a : 1; -}; -tree.Color.prototype = { - eval: function () { return this }, - - // - // If we have some transparency, the only way to represent it - // is via `rgba`. Otherwise, we use the hex representation, - // which has better compatibility with older browsers. - // Values are capped between `0` and `255`, rounded and zero-padded. - // - toCSS: function () { - if (this.alpha < 1.0) { - return "rgba(" + this.rgb.map(function (c) { - return Math.round(c); - }).concat(this.alpha).join(', ') + ")"; - } else { - return '#' + this.rgb.map(function (i) { - i = Math.round(i); - i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); - return i.length === 1 ? '0' + i : i; - }).join(''); - } - }, - - // - // Operations have to be done per-channel, if not, - // channels will spill onto each other. Once we have - // our result, in the form of an integer triplet, - // we create a new Color node to hold the result. - // - operate: function (op, other) { - var result = []; - - if (! (other instanceof tree.Color)) { - other = other.toColor(); - } - - for (var c = 0; c < 3; c++) { - result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); - } - return new(tree.Color)(result, this.alpha + other.alpha); - }, - - toHSL: function () { - var r = this.rgb[0] / 255, - g = this.rgb[1] / 255, - b = this.rgb[2] / 255, - a = this.alpha; - - var max = Math.max(r, g, b), min = Math.min(r, g, b); - var h, s, l = (max + min) / 2, d = max - min; - - if (max === min) { - h = s = 0; - } else { - s = l > 0.5 ? d / (2 - max - min) : d / (max + min); - - switch (max) { - case r: h = (g - b) / d + (g < b ? 6 : 0); break; - case g: h = (b - r) / d + 2; break; - case b: h = (r - g) / d + 4; break; - } - h /= 6; - } - return { h: h * 360, s: s, l: l, a: a }; - }, - toARGB: function () { - var argb = [Math.round(this.alpha * 255)].concat(this.rgb); - return '#' + argb.map(function (i) { - i = Math.round(i); - i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); - return i.length === 1 ? '0' + i : i; - }).join(''); - } -}; - - -})(require('../tree')); diff --git a/r2/r2/lib/contrib/less.js/lib/less/tree/comment.js b/r2/r2/lib/contrib/less.js/lib/less/tree/comment.js deleted file mode 100644 index f4a33840d..000000000 --- a/r2/r2/lib/contrib/less.js/lib/less/tree/comment.js +++ /dev/null @@ -1,14 +0,0 @@ -(function (tree) { - -tree.Comment = function (value, silent) { - this.value = value; - this.silent = !!silent; -}; -tree.Comment.prototype = { - toCSS: function (env) { - return env.compress ? '' : this.value; - }, - eval: function () { return this } -}; - -})(require('../tree')); diff --git a/r2/r2/lib/contrib/less.js/lib/less/tree/condition.js b/r2/r2/lib/contrib/less.js/lib/less/tree/condition.js deleted file mode 100644 index 6b79dc960..000000000 --- a/r2/r2/lib/contrib/less.js/lib/less/tree/condition.js +++ /dev/null @@ -1,42 +0,0 @@ -(function (tree) { - -tree.Condition = function (op, l, r, i, negate) { - this.op = op.trim(); - this.lvalue = l; - this.rvalue = r; - this.index = i; - this.negate = negate; -}; -tree.Condition.prototype.eval = function (env) { - var a = this.lvalue.eval(env), - b = this.rvalue.eval(env); - - var i = this.index, result; - - var result = (function (op) { - switch (op) { - case 'and': - return a && b; - case 'or': - return a || b; - default: - if (a.compare) { - result = a.compare(b); - } else if (b.compare) { - result = b.compare(a); - } else { - throw { type: "Type", - message: "Unable to perform comparison", - index: i }; - } - switch (result) { - case -1: return op === '<' || op === '=<'; - case 0: return op === '=' || op === '>=' || op === '=<'; - case 1: return op === '>' || op === '>='; - } - } - })(this.op); - return this.negate ? !result : result; -}; - -})(require('../tree')); diff --git a/r2/r2/lib/contrib/less.js/lib/less/tree/dimension.js b/r2/r2/lib/contrib/less.js/lib/less/tree/dimension.js deleted file mode 100644 index 9a6fce3dd..000000000 --- a/r2/r2/lib/contrib/less.js/lib/less/tree/dimension.js +++ /dev/null @@ -1,49 +0,0 @@ -(function (tree) { - -// -// A number with a unit -// -tree.Dimension = function (value, unit) { - this.value = parseFloat(value); - this.unit = unit || null; -}; - -tree.Dimension.prototype = { - eval: function () { return this }, - toColor: function () { - return new(tree.Color)([this.value, this.value, this.value]); - }, - toCSS: function () { - var css = this.value + this.unit; - return css; - }, - - // In an operation between two Dimensions, - // we default to the first Dimension's unit, - // so `1px + 2em` will yield `3px`. - // In the future, we could implement some unit - // conversions such that `100cm + 10mm` would yield - // `101cm`. - operate: function (op, other) { - return new(tree.Dimension) - (tree.operate(op, this.value, other.value), - this.unit || other.unit); - }, - - // TODO: Perform unit conversion before comparing - compare: function (other) { - if (other instanceof tree.Dimension) { - if (other.value > this.value) { - return -1; - } else if (other.value < this.value) { - return 1; - } else { - return 0; - } - } else { - return -1; - } - } -}; - -})(require('../tree')); diff --git a/r2/r2/lib/contrib/less.js/lib/less/tree/directive.js b/r2/r2/lib/contrib/less.js/lib/less/tree/directive.js deleted file mode 100644 index 27538332a..000000000 --- a/r2/r2/lib/contrib/less.js/lib/less/tree/directive.js +++ /dev/null @@ -1,35 +0,0 @@ -(function (tree) { - -tree.Directive = function (name, value, features) { - this.name = name; - - if (Array.isArray(value)) { - this.ruleset = new(tree.Ruleset)([], value); - this.ruleset.allowImports = true; - } else { - this.value = value; - } -}; -tree.Directive.prototype = { - toCSS: function (ctx, env) { - if (this.ruleset) { - this.ruleset.root = true; - return this.name + (env.compress ? '{' : ' {\n ') + - this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + - (env.compress ? '}': '\n}\n'); - } else { - return this.name + ' ' + this.value.toCSS() + ';\n'; - } - }, - eval: function (env) { - env.frames.unshift(this); - this.ruleset = this.ruleset && this.ruleset.eval(env); - env.frames.shift(); - return this; - }, - variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, - find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, - rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } -}; - -})(require('../tree')); diff --git a/r2/r2/lib/contrib/less.js/lib/less/tree/element.js b/r2/r2/lib/contrib/less.js/lib/less/tree/element.js deleted file mode 100644 index 14b08d2ea..000000000 --- a/r2/r2/lib/contrib/less.js/lib/less/tree/element.js +++ /dev/null @@ -1,52 +0,0 @@ -(function (tree) { - -tree.Element = function (combinator, value, index) { - this.combinator = combinator instanceof tree.Combinator ? - combinator : new(tree.Combinator)(combinator); - - if (typeof(value) === 'string') { - this.value = value.trim(); - } else if (value) { - this.value = value; - } else { - this.value = ""; - } - this.index = index; -}; -tree.Element.prototype.eval = function (env) { - return new(tree.Element)(this.combinator, - this.value.eval ? this.value.eval(env) : this.value, - this.index); -}; -tree.Element.prototype.toCSS = function (env) { - var value = (this.value.toCSS ? this.value.toCSS(env) : this.value); - if (value == '' && this.combinator.value.charAt(0) == '&') { - return ''; - } else { - return this.combinator.toCSS(env || {}) + value; - } -}; - -tree.Combinator = function (value) { - if (value === ' ') { - this.value = ' '; - } else if (value === '& ') { - this.value = '& '; - } else { - this.value = value ? value.trim() : ""; - } -}; -tree.Combinator.prototype.toCSS = function (env) { - return { - '' : '', - ' ' : ' ', - '&' : '', - '& ' : ' ', - ':' : ' :', - '+' : env.compress ? '+' : ' + ', - '~' : env.compress ? '~' : ' ~ ', - '>' : env.compress ? '>' : ' > ' - }[this.value]; -}; - -})(require('../tree')); diff --git a/r2/r2/lib/contrib/less.js/lib/less/tree/expression.js b/r2/r2/lib/contrib/less.js/lib/less/tree/expression.js deleted file mode 100644 index fbfa9c5b7..000000000 --- a/r2/r2/lib/contrib/less.js/lib/less/tree/expression.js +++ /dev/null @@ -1,23 +0,0 @@ -(function (tree) { - -tree.Expression = function (value) { this.value = value }; -tree.Expression.prototype = { - eval: function (env) { - if (this.value.length > 1) { - return new(tree.Expression)(this.value.map(function (e) { - return e.eval(env); - })); - } else if (this.value.length === 1) { - return this.value[0].eval(env); - } else { - return this; - } - }, - toCSS: function (env) { - return this.value.map(function (e) { - return e.toCSS ? e.toCSS(env) : ''; - }).join(' '); - } -}; - -})(require('../tree')); diff --git a/r2/r2/lib/contrib/less.js/lib/less/tree/import.js b/r2/r2/lib/contrib/less.js/lib/less/tree/import.js deleted file mode 100644 index 7a977def2..000000000 --- a/r2/r2/lib/contrib/less.js/lib/less/tree/import.js +++ /dev/null @@ -1,83 +0,0 @@ -(function (tree) { -// -// CSS @import node -// -// The general strategy here is that we don't want to wait -// for the parsing to be completed, before we start importing -// the file. That's because in the context of a browser, -// most of the time will be spent waiting for the server to respond. -// -// On creation, we push the import path to our import queue, though -// `import,push`, we also pass it a callback, which it'll call once -// the file has been fetched, and parsed. -// -tree.Import = function (path, imports, features, once, index) { - var that = this; - - this.once = once; - this.index = index; - this._path = path; - this.features = features && new(tree.Value)(features); - - // The '.less' extension is optional - if (path instanceof tree.Quoted) { - this.path = /\.(le?|c)ss(\?.*)?$/.test(path.value) ? path.value : path.value + '.less'; - } else { - this.path = path.value.value || path.value; - } - - this.css = /css(\?.*)?$/.test(this.path); - - // Only pre-compile .less files - if (! this.css) { - imports.push(this.path, function (e, root, imported) { - if (e) { e.index = index } - if (imported && that.once) that.skip = imported; - that.root = root || new(tree.Ruleset)([], []); - }); - } -}; - -// -// The actual import node doesn't return anything, when converted to CSS. -// The reason is that it's used at the evaluation stage, so that the rules -// it imports can be treated like any other rules. -// -// In `eval`, we make sure all Import nodes get evaluated, recursively, so -// we end up with a flat structure, which can easily be imported in the parent -// ruleset. -// -tree.Import.prototype = { - toCSS: function (env) { - var features = this.features ? ' ' + this.features.toCSS(env) : ''; - - if (this.css) { - return "@import " + this._path.toCSS() + features + ';\n'; - } else { - return ""; - } - }, - eval: function (env) { - var ruleset, features = this.features && this.features.eval(env); - - if (this.skip) return []; - - if (this.css) { - return this; - } else { - ruleset = new(tree.Ruleset)([], this.root.rules.slice(0)); - - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.Import) { - Array.prototype - .splice - .apply(ruleset.rules, - [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - return this.features ? new(tree.Media)(ruleset.rules, this.features.value) : ruleset.rules; - } - } -}; - -})(require('../tree')); diff --git a/r2/r2/lib/contrib/less.js/lib/less/tree/javascript.js b/r2/r2/lib/contrib/less.js/lib/less/tree/javascript.js deleted file mode 100644 index 772a31ddd..000000000 --- a/r2/r2/lib/contrib/less.js/lib/less/tree/javascript.js +++ /dev/null @@ -1,51 +0,0 @@ -(function (tree) { - -tree.JavaScript = function (string, index, escaped) { - this.escaped = escaped; - this.expression = string; - this.index = index; -}; -tree.JavaScript.prototype = { - eval: function (env) { - var result, - that = this, - context = {}; - - var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { - return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); - }); - - try { - expression = new(Function)('return (' + expression + ')'); - } catch (e) { - throw { message: "JavaScript evaluation error: `" + expression + "`" , - index: this.index }; - } - - for (var k in env.frames[0].variables()) { - context[k.slice(1)] = { - value: env.frames[0].variables()[k].value, - toJS: function () { - return this.value.eval(env).toCSS(); - } - }; - } - - try { - result = expression.call(context); - } catch (e) { - throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , - index: this.index }; - } - if (typeof(result) === 'string') { - return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); - } else if (Array.isArray(result)) { - return new(tree.Anonymous)(result.join(', ')); - } else { - return new(tree.Anonymous)(result); - } - } -}; - -})(require('../tree')); - diff --git a/r2/r2/lib/contrib/less.js/lib/less/tree/keyword.js b/r2/r2/lib/contrib/less.js/lib/less/tree/keyword.js deleted file mode 100644 index 701b79e57..000000000 --- a/r2/r2/lib/contrib/less.js/lib/less/tree/keyword.js +++ /dev/null @@ -1,19 +0,0 @@ -(function (tree) { - -tree.Keyword = function (value) { this.value = value }; -tree.Keyword.prototype = { - eval: function () { return this }, - toCSS: function () { return this.value }, - compare: function (other) { - if (other instanceof tree.Keyword) { - return other.value === this.value ? 0 : 1; - } else { - return -1; - } - } -}; - -tree.True = new(tree.Keyword)('true'); -tree.False = new(tree.Keyword)('false'); - -})(require('../tree')); diff --git a/r2/r2/lib/contrib/less.js/lib/less/tree/media.js b/r2/r2/lib/contrib/less.js/lib/less/tree/media.js deleted file mode 100644 index 2b7b26e58..000000000 --- a/r2/r2/lib/contrib/less.js/lib/less/tree/media.js +++ /dev/null @@ -1,114 +0,0 @@ -(function (tree) { - -tree.Media = function (value, features) { - var el = new(tree.Element)('&', null, 0), - selectors = [new(tree.Selector)([el])]; - - this.features = new(tree.Value)(features); - this.ruleset = new(tree.Ruleset)(selectors, value); - this.ruleset.allowImports = true; -}; -tree.Media.prototype = { - toCSS: function (ctx, env) { - var features = this.features.toCSS(env); - - this.ruleset.root = (ctx.length === 0 || ctx[0].multiMedia); - return '@media ' + features + (env.compress ? '{' : ' {\n ') + - this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + - (env.compress ? '}': '\n}\n'); - }, - eval: function (env) { - if (!env.mediaBlocks) { - env.mediaBlocks = []; - env.mediaPath = []; - } - - var blockIndex = env.mediaBlocks.length; - env.mediaPath.push(this); - env.mediaBlocks.push(this); - - var media = new(tree.Media)([], []); - media.features = this.features.eval(env); - - env.frames.unshift(this.ruleset); - media.ruleset = this.ruleset.eval(env); - env.frames.shift(); - - env.mediaBlocks[blockIndex] = media; - env.mediaPath.pop(); - - return env.mediaPath.length === 0 ? media.evalTop(env) : - media.evalNested(env) - }, - variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, - find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, - rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) }, - - evalTop: function (env) { - var result = this; - - // Render all dependent Media blocks. - if (env.mediaBlocks.length > 1) { - var el = new(tree.Element)('&', null, 0); - var selectors = [new(tree.Selector)([el])]; - result = new(tree.Ruleset)(selectors, env.mediaBlocks); - result.multiMedia = true; - } - - delete env.mediaBlocks; - delete env.mediaPath; - - return result; - }, - evalNested: function (env) { - var i, value, - path = env.mediaPath.concat([this]); - - // Extract the media-query conditions separated with `,` (OR). - for (i = 0; i < path.length; i++) { - value = path[i].features instanceof tree.Value ? - path[i].features.value : path[i].features; - path[i] = Array.isArray(value) ? value : [value]; - } - - // Trace all permutations to generate the resulting media-query. - // - // (a, b and c) with nested (d, e) -> - // a and d - // a and e - // b and c and d - // b and c and e - this.features = new(tree.Value)(this.permute(path).map(function (path) { - path = path.map(function (fragment) { - return fragment.toCSS ? fragment : new(tree.Anonymous)(fragment); - }); - - for(i = path.length - 1; i > 0; i--) { - path.splice(i, 0, new(tree.Anonymous)("and")); - } - - return new(tree.Expression)(path); - })); - - // Fake a tree-node that doesn't output anything. - return new(tree.Ruleset)([], []); - }, - permute: function (arr) { - if (arr.length === 0) { - return []; - } else if (arr.length === 1) { - return arr[0]; - } else { - var result = []; - var rest = this.permute(arr.slice(1)); - for (var i = 0; i < rest.length; i++) { - for (var j = 0; j < arr[0].length; j++) { - result.push([arr[0][j]].concat(rest[i])); - } - } - return result; - } - } -}; - -})(require('../tree')); diff --git a/r2/r2/lib/contrib/less.js/lib/less/tree/mixin.js b/r2/r2/lib/contrib/less.js/lib/less/tree/mixin.js deleted file mode 100644 index b441bf3b2..000000000 --- a/r2/r2/lib/contrib/less.js/lib/less/tree/mixin.js +++ /dev/null @@ -1,146 +0,0 @@ -(function (tree) { - -tree.mixin = {}; -tree.mixin.Call = function (elements, args, index, filename, important) { - this.selector = new(tree.Selector)(elements); - this.arguments = args; - this.index = index; - this.filename = filename; - this.important = important; -}; -tree.mixin.Call.prototype = { - eval: function (env) { - var mixins, args, rules = [], match = false; - - for (var i = 0; i < env.frames.length; i++) { - if ((mixins = env.frames[i].find(this.selector)).length > 0) { - args = this.arguments && this.arguments.map(function (a) { - return { name: a.name, value: a.value.eval(env) }; - }); - for (var m = 0; m < mixins.length; m++) { - if (mixins[m].match(args, env)) { - try { - Array.prototype.push.apply( - rules, mixins[m].eval(env, this.arguments, this.important).rules); - match = true; - } catch (e) { - throw { message: e.message, index: this.index, filename: this.filename, stack: e.stack }; - } - } - } - if (match) { - return rules; - } else { - throw { type: 'Runtime', - message: 'No matching definition was found for `' + - this.selector.toCSS().trim() + '(' + - this.arguments.map(function (a) { - return a.toCSS(); - }).join(', ') + ")`", - index: this.index, filename: this.filename }; - } - } - } - throw { type: 'Name', - message: this.selector.toCSS().trim() + " is undefined", - index: this.index, filename: this.filename }; - } -}; - -tree.mixin.Definition = function (name, params, rules, condition, variadic) { - this.name = name; - this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; - this.params = params; - this.condition = condition; - this.variadic = variadic; - this.arity = params.length; - this.rules = rules; - this._lookups = {}; - this.required = params.reduce(function (count, p) { - if (!p.name || (p.name && !p.value)) { return count + 1 } - else { return count } - }, 0); - this.parent = tree.Ruleset.prototype; - this.frames = []; -}; -tree.mixin.Definition.prototype = { - toCSS: function () { return "" }, - variable: function (name) { return this.parent.variable.call(this, name) }, - variables: function () { return this.parent.variables.call(this) }, - find: function () { return this.parent.find.apply(this, arguments) }, - rulesets: function () { return this.parent.rulesets.apply(this) }, - - evalParams: function (env, args) { - var frame = new(tree.Ruleset)(null, []), varargs, arg; - - for (var i = 0, val, name; i < this.params.length; i++) { - arg = args && args[i] - - if (arg && arg.name) { - frame.rules.unshift(new(tree.Rule)(arg.name, arg.value.eval(env))); - args.splice(i, 1); - i--; - continue; - } - - if (name = this.params[i].name) { - if (this.params[i].variadic && args) { - varargs = []; - for (var j = i; j < args.length; j++) { - varargs.push(args[j].value.eval(env)); - } - frame.rules.unshift(new(tree.Rule)(name, new(tree.Expression)(varargs).eval(env))); - } else if (val = (arg && arg.value) || this.params[i].value) { - frame.rules.unshift(new(tree.Rule)(name, val.eval(env))); - } else { - throw { type: 'Runtime', message: "wrong number of arguments for " + this.name + - ' (' + args.length + ' for ' + this.arity + ')' }; - } - } - } - return frame; - }, - eval: function (env, args, important) { - var frame = this.evalParams(env, args), context, _arguments = [], rules, start; - - for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { - _arguments.push((args[i] && args[i].value) || this.params[i].value); - } - frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); - - rules = important ? - this.rules.map(function (r) { - return new(tree.Rule)(r.name, r.value, '!important', r.index); - }) : this.rules.slice(0); - - return new(tree.Ruleset)(null, rules).eval({ - frames: [this, frame].concat(this.frames, env.frames) - }); - }, - match: function (args, env) { - var argsLength = (args && args.length) || 0, len, frame; - - if (! this.variadic) { - if (argsLength < this.required) { return false } - if (argsLength > this.params.length) { return false } - if ((this.required > 0) && (argsLength > this.params.length)) { return false } - } - - if (this.condition && !this.condition.eval({ - frames: [this.evalParams(env, args)].concat(env.frames) - })) { return false } - - len = Math.min(argsLength, this.arity); - - for (var i = 0; i < len; i++) { - if (!this.params[i].name) { - if (args[i].value.eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { - return false; - } - } - } - return true; - } -}; - -})(require('../tree')); diff --git a/r2/r2/lib/contrib/less.js/lib/less/tree/operation.js b/r2/r2/lib/contrib/less.js/lib/less/tree/operation.js deleted file mode 100644 index 1ce22fb04..000000000 --- a/r2/r2/lib/contrib/less.js/lib/less/tree/operation.js +++ /dev/null @@ -1,32 +0,0 @@ -(function (tree) { - -tree.Operation = function (op, operands) { - this.op = op.trim(); - this.operands = operands; -}; -tree.Operation.prototype.eval = function (env) { - var a = this.operands[0].eval(env), - b = this.operands[1].eval(env), - temp; - - if (a instanceof tree.Dimension && b instanceof tree.Color) { - if (this.op === '*' || this.op === '+') { - temp = b, b = a, a = temp; - } else { - throw { name: "OperationError", - message: "Can't substract or divide a color from a number" }; - } - } - return a.operate(this.op, b); -}; - -tree.operate = function (op, a, b) { - switch (op) { - case '+': return a + b; - case '-': return a - b; - case '*': return a * b; - case '/': return a / b; - } -}; - -})(require('../tree')); diff --git a/r2/r2/lib/contrib/less.js/lib/less/tree/paren.js b/r2/r2/lib/contrib/less.js/lib/less/tree/paren.js deleted file mode 100644 index 384a43c74..000000000 --- a/r2/r2/lib/contrib/less.js/lib/less/tree/paren.js +++ /dev/null @@ -1,16 +0,0 @@ - -(function (tree) { - -tree.Paren = function (node) { - this.value = node; -}; -tree.Paren.prototype = { - toCSS: function (env) { - return '(' + this.value.toCSS(env) + ')'; - }, - eval: function (env) { - return new(tree.Paren)(this.value.eval(env)); - } -}; - -})(require('../tree')); diff --git a/r2/r2/lib/contrib/less.js/lib/less/tree/quoted.js b/r2/r2/lib/contrib/less.js/lib/less/tree/quoted.js deleted file mode 100644 index 794bf4cea..000000000 --- a/r2/r2/lib/contrib/less.js/lib/less/tree/quoted.js +++ /dev/null @@ -1,29 +0,0 @@ -(function (tree) { - -tree.Quoted = function (str, content, escaped, i) { - this.escaped = escaped; - this.value = content || ''; - this.quote = str.charAt(0); - this.index = i; -}; -tree.Quoted.prototype = { - toCSS: function () { - if (this.escaped) { - return this.value; - } else { - return this.quote + this.value + this.quote; - } - }, - eval: function (env) { - var that = this; - var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { - return new(tree.JavaScript)(exp, that.index, true).eval(env).value; - }).replace(/@\{([\w-]+)\}/g, function (_, name) { - var v = new(tree.Variable)('@' + name, that.index).eval(env); - return ('value' in v) ? v.value : v.toCSS(); - }); - return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); - } -}; - -})(require('../tree')); diff --git a/r2/r2/lib/contrib/less.js/lib/less/tree/rule.js b/r2/r2/lib/contrib/less.js/lib/less/tree/rule.js deleted file mode 100644 index 9e4e54a3a..000000000 --- a/r2/r2/lib/contrib/less.js/lib/less/tree/rule.js +++ /dev/null @@ -1,42 +0,0 @@ -(function (tree) { - -tree.Rule = function (name, value, important, index, inline) { - this.name = name; - this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); - this.important = important ? ' ' + important.trim() : ''; - this.index = index; - this.inline = inline || false; - - if (name.charAt(0) === '@') { - this.variable = true; - } else { this.variable = false } -}; -tree.Rule.prototype.toCSS = function (env) { - if (this.variable) { return "" } - else { - return this.name + (env.compress ? ':' : ': ') + - this.value.toCSS(env) + - this.important + (this.inline ? "" : ";"); - } -}; - -tree.Rule.prototype.eval = function (context) { - return new(tree.Rule)(this.name, - this.value.eval(context), - this.important, - this.index, this.inline); -}; - -tree.Shorthand = function (a, b) { - this.a = a; - this.b = b; -}; - -tree.Shorthand.prototype = { - toCSS: function (env) { - return this.a.toCSS(env) + "/" + this.b.toCSS(env); - }, - eval: function () { return this } -}; - -})(require('../tree')); diff --git a/r2/r2/lib/contrib/less.js/lib/less/tree/ruleset.js b/r2/r2/lib/contrib/less.js/lib/less/tree/ruleset.js deleted file mode 100644 index 3100cc354..000000000 --- a/r2/r2/lib/contrib/less.js/lib/less/tree/ruleset.js +++ /dev/null @@ -1,225 +0,0 @@ -(function (tree) { - -tree.Ruleset = function (selectors, rules, strictImports) { - this.selectors = selectors; - this.rules = rules; - this._lookups = {}; - this.strictImports = strictImports; -}; -tree.Ruleset.prototype = { - eval: function (env) { - var selectors = this.selectors && this.selectors.map(function (s) { return s.eval(env) }); - var ruleset = new(tree.Ruleset)(selectors, this.rules.slice(0), this.strictImports); - - ruleset.root = this.root; - ruleset.allowImports = this.allowImports; - - // push the current ruleset to the frames stack - env.frames.unshift(ruleset); - - // Evaluate imports - if (ruleset.root || ruleset.allowImports || !ruleset.strictImports) { - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.Import) { - Array.prototype.splice - .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - } - - // Store the frames around mixin definitions, - // so they can be evaluated like closures when the time comes. - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.mixin.Definition) { - ruleset.rules[i].frames = env.frames.slice(0); - } - } - - // Evaluate mixin calls. - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.mixin.Call) { - Array.prototype.splice - .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - - // Evaluate everything else - for (var i = 0, rule; i < ruleset.rules.length; i++) { - rule = ruleset.rules[i]; - - if (! (rule instanceof tree.mixin.Definition)) { - ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; - } - } - - // Pop the stack - env.frames.shift(); - - return ruleset; - }, - match: function (args) { - return !args || args.length === 0; - }, - variables: function () { - if (this._variables) { return this._variables } - else { - return this._variables = this.rules.reduce(function (hash, r) { - if (r instanceof tree.Rule && r.variable === true) { - hash[r.name] = r; - } - return hash; - }, {}); - } - }, - variable: function (name) { - return this.variables()[name]; - }, - rulesets: function () { - if (this._rulesets) { return this._rulesets } - else { - return this._rulesets = this.rules.filter(function (r) { - return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); - }); - } - }, - find: function (selector, self) { - self = self || this; - var rules = [], rule, match, - key = selector.toCSS(); - - if (key in this._lookups) { return this._lookups[key] } - - this.rulesets().forEach(function (rule) { - if (rule !== self) { - for (var j = 0; j < rule.selectors.length; j++) { - if (match = selector.match(rule.selectors[j])) { - if (selector.elements.length > rule.selectors[j].elements.length) { - Array.prototype.push.apply(rules, rule.find( - new(tree.Selector)(selector.elements.slice(1)), self)); - } else { - rules.push(rule); - } - break; - } - } - } - }); - return this._lookups[key] = rules; - }, - // - // Entry point for code generation - // - // `context` holds an array of arrays. - // - toCSS: function (context, env) { - var css = [], // The CSS output - rules = [], // node.Rule instances - _rules = [], // - rulesets = [], // node.Ruleset instances - paths = [], // Current selectors - selector, // The fully rendered selector - rule; - - if (! this.root) { - if (context.length === 0) { - paths = this.selectors.map(function (s) { return [s] }); - } else { - this.joinSelectors(paths, context, this.selectors); - } - } - - // Compile rules and rulesets - for (var i = 0; i < this.rules.length; i++) { - rule = this.rules[i]; - - if (rule.rules || (rule instanceof tree.Directive) || (rule instanceof tree.Media)) { - rulesets.push(rule.toCSS(paths, env)); - } else if (rule instanceof tree.Comment) { - if (!rule.silent) { - if (this.root) { - rulesets.push(rule.toCSS(env)); - } else { - rules.push(rule.toCSS(env)); - } - } - } else { - if (rule.toCSS && !rule.variable) { - rules.push(rule.toCSS(env)); - } else if (rule.value && !rule.variable) { - rules.push(rule.value.toString()); - } - } - } - - rulesets = rulesets.join(''); - - // If this is the root node, we don't render - // a selector, or {}. - // Otherwise, only output if this ruleset has rules. - if (this.root) { - css.push(rules.join(env.compress ? '' : '\n')); - } else { - if (rules.length > 0) { - selector = paths.map(function (p) { - return p.map(function (s) { - return s.toCSS(env); - }).join('').trim(); - }).join(env.compress ? ',' : ',\n'); - - // Remove duplicates - for (var i = rules.length - 1; i >= 0; i--) { - if (_rules.indexOf(rules[i]) === -1) { - _rules.unshift(rules[i]); - } - } - rules = _rules; - - css.push(selector, - (env.compress ? '{' : ' {\n ') + - rules.join(env.compress ? '' : '\n ') + - (env.compress ? '}' : '\n}\n')); - } - } - css.push(rulesets); - - return css.join('') + (env.compress ? '\n' : ''); - }, - - joinSelectors: function (paths, context, selectors) { - for (var s = 0; s < selectors.length; s++) { - this.joinSelector(paths, context, selectors[s]); - } - }, - - joinSelector: function (paths, context, selector) { - var before = [], after = [], beforeElements = [], - afterElements = [], hasParentSelector = false, el; - - for (var i = 0; i < selector.elements.length; i++) { - el = selector.elements[i]; - if (el.combinator.value.charAt(0) === '&') { - hasParentSelector = true; - } - if (hasParentSelector) afterElements.push(el); - else beforeElements.push(el); - } - - if (! hasParentSelector) { - afterElements = beforeElements; - beforeElements = []; - } - - if (beforeElements.length > 0) { - before.push(new(tree.Selector)(beforeElements)); - } - - if (afterElements.length > 0) { - after.push(new(tree.Selector)(afterElements)); - } - - for (var c = 0; c < context.length; c++) { - paths.push(before.concat(context[c]).concat(after)); - } - } -}; -})(require('../tree')); diff --git a/r2/r2/lib/contrib/less.js/lib/less/tree/selector.js b/r2/r2/lib/contrib/less.js/lib/less/tree/selector.js deleted file mode 100644 index 65abbb692..000000000 --- a/r2/r2/lib/contrib/less.js/lib/less/tree/selector.js +++ /dev/null @@ -1,42 +0,0 @@ -(function (tree) { - -tree.Selector = function (elements) { - this.elements = elements; - if (this.elements[0].combinator.value === "") { - this.elements[0].combinator.value = ' '; - } -}; -tree.Selector.prototype.match = function (other) { - var len = this.elements.length, - olen = other.elements.length, - max = Math.min(len, olen); - - if (len < olen) { - return false; - } else { - for (var i = 0; i < max; i++) { - if (this.elements[i].value !== other.elements[i].value) { - return false; - } - } - } - return true; -}; -tree.Selector.prototype.eval = function (env) { - return new(tree.Selector)(this.elements.map(function (e) { - return e.eval(env); - })); -}; -tree.Selector.prototype.toCSS = function (env) { - if (this._css) { return this._css } - - return this._css = this.elements.map(function (e) { - if (typeof(e) === 'string') { - return ' ' + e.trim(); - } else { - return e.toCSS(env); - } - }).join(''); -}; - -})(require('../tree')); diff --git a/r2/r2/lib/contrib/less.js/lib/less/tree/url.js b/r2/r2/lib/contrib/less.js/lib/less/tree/url.js deleted file mode 100644 index 0caec3458..000000000 --- a/r2/r2/lib/contrib/less.js/lib/less/tree/url.js +++ /dev/null @@ -1,25 +0,0 @@ -(function (tree) { - -tree.URL = function (val, paths) { - if (val.data) { - this.attrs = val; - } else { - // Add the base path if the URL is relative and we are in the browser - if (typeof(window) !== 'undefined' && !/^(?:https?:\/\/|file:\/\/|data:|\/)/.test(val.value) && paths.length > 0) { - val.value = paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); - } - this.value = val; - this.paths = paths; - } -}; -tree.URL.prototype = { - toCSS: function () { - return "url(" + (this.attrs ? 'data:' + this.attrs.mime + this.attrs.charset + this.attrs.base64 + this.attrs.data - : this.value.toCSS()) + ")"; - }, - eval: function (ctx) { - return this.attrs ? this : new(tree.URL)(this.value.eval(ctx), this.paths); - } -}; - -})(require('../tree')); diff --git a/r2/r2/lib/contrib/less.js/lib/less/tree/value.js b/r2/r2/lib/contrib/less.js/lib/less/tree/value.js deleted file mode 100644 index 3c1eb29a2..000000000 --- a/r2/r2/lib/contrib/less.js/lib/less/tree/value.js +++ /dev/null @@ -1,24 +0,0 @@ -(function (tree) { - -tree.Value = function (value) { - this.value = value; - this.is = 'value'; -}; -tree.Value.prototype = { - eval: function (env) { - if (this.value.length === 1) { - return this.value[0].eval(env); - } else { - return new(tree.Value)(this.value.map(function (v) { - return v.eval(env); - })); - } - }, - toCSS: function (env) { - return this.value.map(function (e) { - return e.toCSS(env); - }).join(env.compress ? ',' : ', '); - } -}; - -})(require('../tree')); diff --git a/r2/r2/lib/contrib/less.js/lib/less/tree/variable.js b/r2/r2/lib/contrib/less.js/lib/less/tree/variable.js deleted file mode 100644 index ee557e1df..000000000 --- a/r2/r2/lib/contrib/less.js/lib/less/tree/variable.js +++ /dev/null @@ -1,26 +0,0 @@ -(function (tree) { - -tree.Variable = function (name, index, file) { this.name = name, this.index = index, this.file = file }; -tree.Variable.prototype = { - eval: function (env) { - var variable, v, name = this.name; - - if (name.indexOf('@@') == 0) { - name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; - } - - if (variable = tree.find(env.frames, function (frame) { - if (v = frame.variable(name)) { - return v.value.eval(env); - } - })) { return variable } - else { - throw { type: 'Name', - message: "variable " + name + " is undefined", - filename: this.file, - index: this.index }; - } - } -}; - -})(require('../tree')); diff --git a/r2/r2/lib/contrib/less.js/package.json b/r2/r2/lib/contrib/less.js/package.json deleted file mode 100644 index c57989b6d..000000000 --- a/r2/r2/lib/contrib/less.js/package.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name" : "less", - "description" : "Leaner CSS", - "url" : "http://lesscss.org", - "keywords" : ["css", "parser", "lesscss", "browser"], - "author" : "Alexis Sellier ", - "contributors" : [], - "version" : "1.3.0", - "bin" : { "lessc": "./bin/lessc" }, - "main" : "./lib/less/index", - "directories" : { "test": "./test" }, - "engines" : { "node": ">=0.4.0" } -} diff --git a/r2/r2/lib/contrib/less.js/test/css/colors.css b/r2/r2/lib/contrib/less.js/test/css/colors.css deleted file mode 100644 index b4516425a..000000000 --- a/r2/r2/lib/contrib/less.js/test/css/colors.css +++ /dev/null @@ -1,58 +0,0 @@ -#yelow #short { - color: #fea; -} -#yelow #long { - color: #ffeeaa; -} -#yelow #rgba { - color: rgba(255, 238, 170, 0.1); -} -#yelow #argb { - color: #1affeeaa; -} -#blue #short { - color: #00f; -} -#blue #long { - color: #0000ff; -} -#blue #rgba { - color: rgba(0, 0, 255, 0.1); -} -#blue #argb { - color: #1a0000ff; -} -#alpha #hsla { - color: rgba(61, 45, 41, 0.6); -} -#overflow .a { - color: #000000; -} -#overflow .b { - color: #ffffff; -} -#overflow .c { - color: #ffffff; -} -#overflow .d { - color: #00ff00; -} -#grey { - color: #c8c8c8; -} -#808080 { - color: #808080; -} -#00ff00 { - color: #00ff00; -} -.lightenblue { - color: #3333ff; -} -.darkenblue { - color: #0000cc; -} -.unknowncolors { - color: blue2; - border: 2px solid superred; -} diff --git a/r2/r2/lib/contrib/less.js/test/css/comments.css b/r2/r2/lib/contrib/less.js/test/css/comments.css deleted file mode 100644 index 352dd48e3..000000000 --- a/r2/r2/lib/contrib/less.js/test/css/comments.css +++ /dev/null @@ -1,56 +0,0 @@ -/******************\ -* * -* Comment Header * -* * -\******************/ -/* - - Comment - -*/ -/* - * Comment Test - * - * - cloudhead (http://cloudhead.net) - * - */ -/* Colors - * ------ - * #EDF8FC (background blue) - * #166C89 (darkest blue) - * - * Text: - * #333 (standard text) // A comment within a comment! - * #1F9EC9 (standard link) - * - */ -/* @group Variables -------------------- */ -#comments { - /**/ - color: red; - /* A C-style comment */ - - background-color: orange; - font-size: 12px; - /* lost comment */ - content: "content"; - border: 1px solid black; - padding: 0; - margin: 2em; -} -/* commented out - #more-comments { - color: grey; - } -*/ -.selector, -.lots, -.comments { - color: #808080, /* blue */ #ffa500; - -webkit-border-radius: 2px /* webkit only */; - -moz-border-radius: 8px /* moz only with operation */; -} -#last { - color: #0000ff; -} diff --git a/r2/r2/lib/contrib/less.js/test/css/css-3.css b/r2/r2/lib/contrib/less.js/test/css/css-3.css deleted file mode 100644 index 45bdc40dc..000000000 --- a/r2/r2/lib/contrib/less.js/test/css/css-3.css +++ /dev/null @@ -1,58 +0,0 @@ -.comma-delimited { - background: url(bg.jpg) no-repeat, url(bg.png) repeat-x top left, url(bg); - text-shadow: -1px -1px 1px #ff0000, 6px 5px 5px #ffff00; - -moz-box-shadow: 0pt 0pt 2px rgba(255, 255, 255, 0.4) inset, 0pt 4px 6px rgba(255, 255, 255, 0.4) inset; -} -@font-face { - font-family: Headline; - src: local(Futura-Medium), url(fonts.svg#MyGeometricModern) format("svg"); -} -.other { - -moz-transform: translate(0, 11em) rotate(-90deg); -} -p:not([class*="lead"]) { - color: black; -} -input[type="text"].class#id[attr=32]:not(1) { - color: white; -} -div#id.class[a=1][b=2].class:not(1) { - color: white; -} -ul.comma > li:not(:only-child)::after { - color: white; -} -ol.comma > li:nth-last-child(2)::after { - color: white; -} -li:nth-child(4n+1), -li:nth-child(-5n), -li:nth-child(-n+2) { - color: white; -} -a[href^="http://"] { - color: black; -} -a[href$="http://"] { - color: black; -} -form[data-disabled] { - color: black; -} -p::before { - color: black; -} -#issue322 { - -webkit-animation: anim2 7s infinite ease-in-out; -} -@-webkit-keyframes frames { - 0% { - border: 1px; - } - 5.5% { - border: 2px; - } - 100% { - border: 3px; - } -} diff --git a/r2/r2/lib/contrib/less.js/test/css/css-escapes.css b/r2/r2/lib/contrib/less.js/test/css/css-escapes.css deleted file mode 100644 index 278d55763..000000000 --- a/r2/r2/lib/contrib/less.js/test/css/css-escapes.css +++ /dev/null @@ -1,20 +0,0 @@ -.escape\|random\|char { - color: red; -} -.mixin\!tUp { - font-weight: bold; -} -.\34 04 { - background: red; -} -.\34 04 strong { - color: #ff00ff; - font-weight: bold; -} -.trailingTest\+ { - color: red; -} -/* This hideous test of hideousness checks for the selector "blockquote" with various permutations of hex escapes */ -\62\6c\6f \63 \6B \0071 \000075o\74 e { - color: silver; -} diff --git a/r2/r2/lib/contrib/less.js/test/css/css.css b/r2/r2/lib/contrib/less.js/test/css/css.css deleted file mode 100644 index 63d20ec43..000000000 --- a/r2/r2/lib/contrib/less.js/test/css/css.css +++ /dev/null @@ -1,89 +0,0 @@ -@charset "utf-8"; -div { - color: black; -} -div { - width: 99%; -} -* { - min-width: 45em; -} -h1, -h2 > a > p, -h3 { - color: none; -} -div.class { - color: blue; -} -div#id { - color: green; -} -.class#id { - color: purple; -} -.one.two.three { - color: grey; -} -@media print { - font-size: 3em; -} -@media screen { - font-size: 10px; -} -@font-face { - font-family: 'Garamond Pro'; - src: url("/fonts/garamond-pro.ttf"); -} -a:hover, -a:link { - color: #999; -} -p, -p:first-child { - text-transform: none; -} -q:lang(no) { - quotes: none; -} -p + h1 { - font-size: 2.2em; -} -#shorthands { - border: 1px solid #000; - font: 12px/16px Arial; - font: 100%/16px Arial; - margin: 1px 0; - padding: 0 auto; - background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px; -} -#more-shorthands { - margin: 0; - padding: 1px 0 2px 0; - font: normal small/20px 'Trebuchet MS', Verdana, sans-serif; -} -.misc { - -moz-border-radius: 2px; - display: -moz-inline-stack; - width: .1em; - background-color: #009998; - background-image: url(images/image.jpg); - background: -webkit-gradient(linear, left top, left bottom, from(#ff0000), to(#0000ff)); - margin: ; - filter: alpha(opacity=100); -} -#important { - color: red !important; - width: 100%!important; - height: 20px ! important; -} -#data-uri { - background: url(data:image/png;charset=utf-8;base64, - kiVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD/ - k//+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4U - kg9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC); - background-image: url(data:image/x-png,f9difSSFIIGFIFJD1f982FSDKAA9==); -} -#svg-data-uri { - background: transparent url('data:image/svg+xml, '); -} diff --git a/r2/r2/lib/contrib/less.js/test/css/functions.css b/r2/r2/lib/contrib/less.js/test/css/functions.css deleted file mode 100644 index a0f9bd03c..000000000 --- a/r2/r2/lib/contrib/less.js/test/css/functions.css +++ /dev/null @@ -1,43 +0,0 @@ -#functions { - color: #660000; - width: 16; - height: undefined("self"); - border-width: 5; - variable: 11; -} -#built-in { - escaped: -Some::weird(#thing, y); - lighten: #ffcccc; - darken: #330000; - saturate: #203c31; - desaturate: #29332f; - greyscale: #2e2e2e; - spin-p: #bf6a40; - spin-n: #bf4055; - format: "rgb(32, 128, 64)"; - format-string: "hello world"; - format-multiple: "hello earth 2"; - format-url-encode: "red is %23ff0000"; - eformat: rgb(32, 128, 64); - hue: 98; - saturation: 12%; - lightness: 95%; - rounded: 11; - roundedpx: 3px; - percentage: 20%; - color: #ff0011; -} -#built-in .is-a { - color: true; - color1: true; - color2: true; - keyword: true; - number: true; - string: true; - pixel: true; - percent: true; - em: true; -} -#alpha { - alpha: rgba(153, 94, 51, 0.6); -} diff --git a/r2/r2/lib/contrib/less.js/test/css/ie-filters.css b/r2/r2/lib/contrib/less.js/test/css/ie-filters.css deleted file mode 100644 index 933318abf..000000000 --- a/r2/r2/lib/contrib/less.js/test/css/ie-filters.css +++ /dev/null @@ -1,5 +0,0 @@ -.nav { - filter: progid:dximagetransform.microsoft.alpha(opacity=20); - filter: progid:dximagetransform.microsoft.alpha(opacity=0); - filter: progid:dximagetransform.microsoft.gradient(startColorstr="#333333", endColorstr="#000000", GradientType=0); -} diff --git a/r2/r2/lib/contrib/less.js/test/css/import-once.css b/r2/r2/lib/contrib/less.js/test/css/import-once.css deleted file mode 100644 index 3a1ae2507..000000000 --- a/r2/r2/lib/contrib/less.js/test/css/import-once.css +++ /dev/null @@ -1,9 +0,0 @@ -@import "import-test-d.css"; - -.mixin { - height: 10px; - color: #ff0000; -} -#import { - color: #ff0000; -} diff --git a/r2/r2/lib/contrib/less.js/test/css/import.css b/r2/r2/lib/contrib/less.js/test/css/import.css deleted file mode 100644 index 89dc162c5..000000000 --- a/r2/r2/lib/contrib/less.js/test/css/import.css +++ /dev/null @@ -1,23 +0,0 @@ -@import "import-test-d.css"; - -@import url(http://fonts.googleapis.com/css?family=Open+Sans); - -@import url(something.css) screen and (color) and (max-width: 600px); -#import { - color: #ff0000; -} -.mixin { - height: 10px; - color: #ff0000; -} -#import-test { - height: 10px; - color: #ff0000; - width: 10px; - height: 30%; -} -@media screen and (max-width: 600px) { - body { - width: 100%; - } -} diff --git a/r2/r2/lib/contrib/less.js/test/css/javascript.css b/r2/r2/lib/contrib/less.js/test/css/javascript.css deleted file mode 100644 index df48f505c..000000000 --- a/r2/r2/lib/contrib/less.js/test/css/javascript.css +++ /dev/null @@ -1,22 +0,0 @@ -.eval { - js: 42; - js: 2; - js: "hello world"; - js: 1, 2, 3; - title: "node"; - ternary: true; -} -.scope { - var: 42; - escaped: 7px; -} -.vars { - width: 8; -} -.escape-interpol { - width: hello world; -} -.arrays { - ary: "1, 2, 3"; - ary1: "1, 2, 3"; -} diff --git a/r2/r2/lib/contrib/less.js/test/css/lazy-eval.css b/r2/r2/lib/contrib/less.js/test/css/lazy-eval.css deleted file mode 100644 index 1adfb8f38..000000000 --- a/r2/r2/lib/contrib/less.js/test/css/lazy-eval.css +++ /dev/null @@ -1,3 +0,0 @@ -.lazy-eval { - width: 100%; -} diff --git a/r2/r2/lib/contrib/less.js/test/css/media.css b/r2/r2/lib/contrib/less.js/test/css/media.css deleted file mode 100644 index 61d169df8..000000000 --- a/r2/r2/lib/contrib/less.js/test/css/media.css +++ /dev/null @@ -1,79 +0,0 @@ -@media print { - .class { - color: blue; - } - .class .sub { - width: 42; - } - .top, - header > h1 { - color: #444444; - } -} -@media screen { - body { - max-width: 480; - } -} -@media all and (orientation: portrait) { - aside { - float: none; - } -} -@media handheld and (min-width: 42), screen and (min-width: 20em) { - body { - max-width: 480px; - } -} -@media print { - body { - padding: 20px; - } - body header { - background-color: red; - } -} -@media print and (orientation: landscape) { - body { - margin-left: 20px; - } -} -@media a, b and c { - body { - width: 95%; - } -} -@media a and x, b and c and x, a and y, b and c and y { - body { - width: 100%; - } -} -.a { - background: black; -} -@media handheld { - .a { - background: white; - } -} -@media handheld and (max-width: 100px) { - .a { - background: red; - } -} -.b { - background: black; -} -@media handheld { - .b { - background: white; - } -} -@media handheld and (max-width: 200px) { - .b { - background: red; - } -} -@media only screen and (max-width: 200px) { - width: 480px; -} diff --git a/r2/r2/lib/contrib/less.js/test/css/mixins-args.css b/r2/r2/lib/contrib/less.js/test/css/mixins-args.css deleted file mode 100644 index d5b67f304..000000000 --- a/r2/r2/lib/contrib/less.js/test/css/mixins-args.css +++ /dev/null @@ -1,74 +0,0 @@ -#hidden { - color: transparent; -} -#hidden1 { - color: transparent; -} -.two-args { - color: blue; - width: 10px; - height: 99%; - border: 2px dotted #000000; -} -.one-arg { - width: 15px; - height: 49%; -} -.no-parens { - width: 5px; - height: 49%; -} -.no-args { - width: 5px; - height: 49%; -} -.var-args { - width: 45; - height: 17%; -} -.multi-mix { - width: 10px; - height: 29%; - margin: 4; - padding: 5; -} -body { - padding: 30px; - color: #ff0000; -} -.scope-mix { - width: 8; -} -.content { - width: 600px; -} -.content .column { - margin: 600px; -} -#same-var-name { - radius: 5px; -} -#var-inside { - width: 10px; -} -.arguments { - border: 1px solid #000000; - width: 1px; -} -.arguments2 { - border: 0px; - width: 0px; -} -.arguments3 { - border: 0px; - width: 0px; -} -.arguments4 { - border: 0 1 2 3 4; - rest: 1 2 3 4; - width: 0; -} -.edge-case { - border: "{"; - width: "{"; -} diff --git a/r2/r2/lib/contrib/less.js/test/css/mixins-closure.css b/r2/r2/lib/contrib/less.js/test/css/mixins-closure.css deleted file mode 100644 index b1021b6fb..000000000 --- a/r2/r2/lib/contrib/less.js/test/css/mixins-closure.css +++ /dev/null @@ -1,9 +0,0 @@ -.class { - width: 99px; -} -.overwrite { - width: 99px; -} -.nested .class { - width: 5px; -} diff --git a/r2/r2/lib/contrib/less.js/test/css/mixins-guards.css b/r2/r2/lib/contrib/less.js/test/css/mixins-guards.css deleted file mode 100644 index 0c563e529..000000000 --- a/r2/r2/lib/contrib/less.js/test/css/mixins-guards.css +++ /dev/null @@ -1,58 +0,0 @@ -.light1 { - color: white; - margin: 1px; -} -.light2 { - color: black; - margin: 1px; -} -.max1 { - width: 6; -} -.max2 { - width: 8; -} -.glob1 { - margin: auto auto; -} -.ops1 { - height: gt-or-eq; - height: lt-or-eq; -} -.ops2 { - height: gt-or-eq; - height: not-eq; -} -.ops3 { - height: lt-or-eq; - height: not-eq; -} -.default1 { - content: default; -} -.test1 { - content: "true."; -} -.test2 { - content: "false."; -} -.test3 { - content: "false."; -} -.test4 { - content: "false."; -} -.test5 { - content: "false."; -} -.bool1 { - content: true and true; - content: true; - content: false, true; - content: false and true and true, true; - content: false, true and true; - content: false, false, true; - content: false, true and true and true, false; - content: not false; - content: not false and false, not false; -} diff --git a/r2/r2/lib/contrib/less.js/test/css/mixins-important.css b/r2/r2/lib/contrib/less.js/test/css/mixins-important.css deleted file mode 100644 index 2f74c6476..000000000 --- a/r2/r2/lib/contrib/less.js/test/css/mixins-important.css +++ /dev/null @@ -1,17 +0,0 @@ -.class { - border: 1; - boxer: 1; - border: 2 !important; - boxer: 2 !important; - border: 3; - boxer: 3; - border: 4 !important; - boxer: 4 !important; - border: 5; - boxer: 5; - border: 0 !important; - boxer: 0 !important; - border: 9 !important; - border: 9; - boxer: 9; -} diff --git a/r2/r2/lib/contrib/less.js/test/css/mixins-named-args.css b/r2/r2/lib/contrib/less.js/test/css/mixins-named-args.css deleted file mode 100644 index 1c1afaf8f..000000000 --- a/r2/r2/lib/contrib/less.js/test/css/mixins-named-args.css +++ /dev/null @@ -1,20 +0,0 @@ -.named-arg { - color: blue; - width: 5px; - height: 99%; - text-align: center; -} -.class { - width: 5px; - height: 19%; -} -.named-args2 { - width: 15px; - height: 49%; - color: #646464; -} -.named-args3 { - width: 5px; - height: 29%; - color: #123456; -} diff --git a/r2/r2/lib/contrib/less.js/test/css/mixins-nested.css b/r2/r2/lib/contrib/less.js/test/css/mixins-nested.css deleted file mode 100644 index 6378c4756..000000000 --- a/r2/r2/lib/contrib/less.js/test/css/mixins-nested.css +++ /dev/null @@ -1,14 +0,0 @@ -.class .inner { - height: 300; -} -.class .inner .innest { - width: 30; - border-width: 60; -} -.class2 .inner { - height: 600; -} -.class2 .inner .innest { - width: 60; - border-width: 120; -} diff --git a/r2/r2/lib/contrib/less.js/test/css/mixins-pattern.css b/r2/r2/lib/contrib/less.js/test/css/mixins-pattern.css deleted file mode 100644 index 8b8283353..000000000 --- a/r2/r2/lib/contrib/less.js/test/css/mixins-pattern.css +++ /dev/null @@ -1,47 +0,0 @@ -.zero { - variadic: true; - zero: 0; - one: 1; - two: 2; - three: 3; -} -.one { - variadic: true; - one: 1; - one-req: 1; - two: 2; - three: 3; -} -.two { - variadic: true; - two: 2; - three: 3; -} -.three { - variadic: true; - three-req: 3; - three: 3; -} -.left { - left: 1; -} -.right { - right: 1; -} -.border-right { - color: black; - border-right: 4px; -} -.border-left { - color: black; - border-left: 4px; -} -.only-right { - right: 33; -} -.only-left { - left: 33; -} -.left-right { - both: 330; -} diff --git a/r2/r2/lib/contrib/less.js/test/css/mixins.css b/r2/r2/lib/contrib/less.js/test/css/mixins.css deleted file mode 100644 index 45d517932..000000000 --- a/r2/r2/lib/contrib/less.js/test/css/mixins.css +++ /dev/null @@ -1,71 +0,0 @@ -.mixin { - border: 1px solid black; -} -.mixout { - border-color: orange; -} -.borders { - border-style: dashed; -} -#namespace .borders { - border-style: dotted; -} -#namespace .biohazard { - content: "death"; -} -#namespace .biohazard .man { - color: transparent; -} -#theme > .mixin { - background-color: grey; -} -#container { - color: black; - border: 1px solid black; - border-color: orange; - background-color: grey; -} -#header .milk { - color: white; - border: 1px solid black; - background-color: grey; -} -#header #cookie { - border-style: dashed; -} -#header #cookie .chips { - border-style: dotted; -} -#header #cookie .chips .calories { - color: black; - border: 1px solid black; - border-color: orange; - background-color: grey; -} -.secure-zone { - color: transparent; -} -.direct { - border-style: dotted; -} -.bo, -.bar { - width: 100%; -} -.bo { - border: 1px; -} -.ar.bo.ca { - color: black; -} -.jo.ki { - background: none; -} -.extended { - width: 100%; - border: 1px; - background: none; -} -.foo .bar { - width: 100%; -} diff --git a/r2/r2/lib/contrib/less.js/test/css/operations.css b/r2/r2/lib/contrib/less.js/test/css/operations.css deleted file mode 100644 index fb9e0aff7..000000000 --- a/r2/r2/lib/contrib/less.js/test/css/operations.css +++ /dev/null @@ -1,49 +0,0 @@ -#operations { - color: #111111; - height: 9px; - width: 3em; - substraction: 0; - division: 1; -} -#operations .spacing { - height: 9px; - width: 3em; -} -.with-variables { - height: 16em; - width: 24em; - size: 1cm; -} -.with-functions { - color: #646464; - color: #ff8080; - color: #c94a4a; -} -.negative { - height: 0px; - width: 4px; -} -.shorthands { - padding: -1px 2px 0 -4px; -} -.rem-dimensions { - font-size: 5.5rem; -} -.colors { - color: #123; - border-color: #334455; - background-color: #000000; -} -.colors .other { - color: #222222; - border-color: #222222; -} -.negations { - variable: -4px; - variable1: 0px; - variable2: 0px; - variable3: 8px; - variable4: 0px; - paren: -4px; - paren2: 16px; -} diff --git a/r2/r2/lib/contrib/less.js/test/css/parens.css b/r2/r2/lib/contrib/less.js/test/css/parens.css deleted file mode 100644 index 36487fe59..000000000 --- a/r2/r2/lib/contrib/less.js/test/css/parens.css +++ /dev/null @@ -1,20 +0,0 @@ -.parens { - border: 2px solid #000000; - margin: 1px 3px 16 3; - width: 36; - padding: 2px 36px; -} -.more-parens { - padding: 8 4 4 4px; - width: 96; - height: 113; - margin: 12; -} -.nested-parens { - width: 71; - height: 6; -} -.mixed-units { - margin: 2px 4em 1 5pc; - padding: 6px 1em 2px 2; -} diff --git a/r2/r2/lib/contrib/less.js/test/css/rulesets.css b/r2/r2/lib/contrib/less.js/test/css/rulesets.css deleted file mode 100644 index 408c76aad..000000000 --- a/r2/r2/lib/contrib/less.js/test/css/rulesets.css +++ /dev/null @@ -1,33 +0,0 @@ -#first > .one { - font-size: 2em; -} -#first > .one > #second .two > #deux { - width: 50%; -} -#first > .one > #second .two > #deux #third { - height: 100%; -} -#first > .one > #second .two > #deux #third:focus { - color: black; -} -#first > .one > #second .two > #deux #third:focus #fifth > #sixth .seventh #eighth + #ninth { - color: purple; -} -#first > .one > #second .two > #deux #fourth, -#first > .one > #second .two > #deux #five, -#first > .one > #second .two > #deux #six { - color: #110000; -} -#first > .one > #second .two > #deux #fourth .seven, -#first > .one > #second .two > #deux #five .seven, -#first > .one > #second .two > #deux #six .seven, -#first > .one > #second .two > #deux #fourth .eight > #nine, -#first > .one > #second .two > #deux #five .eight > #nine, -#first > .one > #second .two > #deux #six .eight > #nine { - border: 1px solid black; -} -#first > .one > #second .two > #deux #fourth #ten, -#first > .one > #second .two > #deux #five #ten, -#first > .one > #second .two > #deux #six #ten { - color: red; -} diff --git a/r2/r2/lib/contrib/less.js/test/css/scope.css b/r2/r2/lib/contrib/less.js/test/css/scope.css deleted file mode 100644 index 11feda895..000000000 --- a/r2/r2/lib/contrib/less.js/test/css/scope.css +++ /dev/null @@ -1,15 +0,0 @@ -.tiny-scope { - color: #998899; -} -.scope1 { - color: #0000ff; - border-color: #000000; -} -.scope1 .scope2 { - color: #0000ff; -} -.scope1 .scope2 .scope3 { - color: #ff0000; - border-color: #000000; - background-color: #ffffff; -} diff --git a/r2/r2/lib/contrib/less.js/test/css/selectors.css b/r2/r2/lib/contrib/less.js/test/css/selectors.css deleted file mode 100644 index 6f69a8c93..000000000 --- a/r2/r2/lib/contrib/less.js/test/css/selectors.css +++ /dev/null @@ -1,69 +0,0 @@ -h1 a:hover, -h2 a:hover, -h3 a:hover, -h1 p:hover, -h2 p:hover, -h3 p:hover { - color: red; -} -#all { - color: blue; -} -#the { - color: blue; -} -#same { - color: blue; -} -ul, -li, -div, -q, -blockquote, -textarea { - margin: 0; -} -td { - margin: 0; - padding: 0; -} -td, -input { - line-height: 1em; -} -a { - color: red; -} -a:hover { - color: blue; -} -div a { - color: green; -} -p a span { - color: yellow; -} -.foo .bar .qux, -.foo .baz .qux { - display: block; -} -.qux .foo .bar, -.qux .foo .baz { - display: inline; -} -.qux .foo .bar .biz, -.qux .foo .baz .biz { - display: none; -} -.other ::fnord { - color: #ff0000; -} -.other::fnord { - color: #ff0000; -} -.other ::bnord { - color: #ff0000; -} -.other::bnord { - color: #ff0000; -} diff --git a/r2/r2/lib/contrib/less.js/test/css/strings.css b/r2/r2/lib/contrib/less.js/test/css/strings.css deleted file mode 100644 index 0c34134f8..000000000 --- a/r2/r2/lib/contrib/less.js/test/css/strings.css +++ /dev/null @@ -1,40 +0,0 @@ -#strings { - background-image: url("http://son-of-a-banana.com"); - quotes: "~" "~"; - content: "#*%:&^,)!.(~*})"; - empty: ""; - brackets: "{" "}"; - escapes: "\"hello\" \\world"; - escapes2: "\"llo"; -} -#comments { - content: "/* hello */ // not-so-secret"; -} -#single-quote { - quotes: "'" "'"; - content: '""#!&""'; - empty: ''; - semi-colon: ';'; -} -#escaped { - filter: DX.Transform.MS.BS.filter(opacity=50); -} -#one-line { - image: url(http://tooks.com); -} -#crazy { - image: url(http://), "}", url("http://}"); -} -#interpolation { - url: "http://lesscss.org/dev/image.jpg"; - url2: "http://lesscss.org/image-256.jpg"; - url3: "http://lesscss.org#445566"; - url4: "http://lesscss.org/hello"; - url5: "http://lesscss.org/54.4"; -} -.mix-mul-class { - color: #0000ff; - color: #ff0000; - color: #000000; - color: #ffa500; -} diff --git a/r2/r2/lib/contrib/less.js/test/css/variables.css b/r2/r2/lib/contrib/less.js/test/css/variables.css deleted file mode 100644 index 961fe6959..000000000 --- a/r2/r2/lib/contrib/less.js/test/css/variables.css +++ /dev/null @@ -1,27 +0,0 @@ -.variables { - width: 14cm; -} -.variables { - height: 24px; - color: #888888; - font-family: "Trebuchet MS", Verdana, sans-serif; - quotes: "~" "~"; -} -.redefinition { - three: 3; -} -.values { - font-family: 'Trebuchet', 'Trebuchet', 'Trebuchet'; - color: #888888 !important; - url: url('Trebuchet'); - multi: something 'A', B, C, 'Trebuchet'; -} -.variable-names { - name: 'hello'; -} -.alpha { - filter: alpha(opacity=42); -} -a:nth-child(2) { - border: 1px; -} diff --git a/r2/r2/lib/contrib/less.js/test/css/whitespace.css b/r2/r2/lib/contrib/less.js/test/css/whitespace.css deleted file mode 100644 index 56e067fcb..000000000 --- a/r2/r2/lib/contrib/less.js/test/css/whitespace.css +++ /dev/null @@ -1,38 +0,0 @@ -.whitespace { - color: white; -} -.whitespace { - color: white; -} -.whitespace { - color: white; -} -.whitespace { - color: white; -} -.whitespace { - color: white ; -} -.white, -.space, -.mania { - color: white; -} -.no-semi-column { - color: #ffffff; -} -.no-semi-column { - color: white; - white-space: pre; -} -.no-semi-column { - border: 2px solid #ffffff; -} -.newlines { - background: the, - great, - wall; - border: 2px - solid - black; -} diff --git a/r2/r2/lib/contrib/less.js/test/less-test.js b/r2/r2/lib/contrib/less.js/test/less-test.js deleted file mode 100644 index 46412e011..000000000 --- a/r2/r2/lib/contrib/less.js/test/less-test.js +++ /dev/null @@ -1,73 +0,0 @@ -var path = require('path'), - fs = require('fs'), - sys = require('util'); - -var less = require('../lib/less'); - -less.tree.functions.add = function (a, b) { - return new(less.tree.Dimension)(a.value + b.value); -} -less.tree.functions.increment = function (a) { - return new(less.tree.Dimension)(a.value + 1); -} -less.tree.functions._color = function (str) { - if (str.value === "evil red") { return new(less.tree.Color)("600") } -} - -sys.puts("\n" + stylize("LESS", 'underline') + "\n"); - -fs.readdirSync('test/less').forEach(function (file) { - if (! /\.less/.test(file)) { return } - - toCSS('test/less/' + file, function (err, less) { - var name = path.basename(file, '.less'); - - fs.readFile(path.join('test/css', name) + '.css', 'utf-8', function (e, css) { - sys.print("- " + name + ": ") - if (less === css) { sys.print(stylize('OK', 'green')) } - else if (err) { - sys.print(stylize("ERROR: " + (err && err.message), 'red')); - } else { - sys.print(stylize("FAIL", 'yellow')); - } - sys.puts(""); - }); - }); -}); - -function toCSS(path, callback) { - var tree, css; - fs.readFile(path, 'utf-8', function (e, str) { - if (e) { return callback(e) } - - new(less.Parser)({ - paths: [require('path').dirname(path)], - optimization: 0 - }).parse(str, function (err, tree) { - if (err) { - callback(err); - } else { - try { - css = tree.toCSS(); - callback(null, css); - } catch (e) { - callback(e); - } - } - }); - }); -} - -// Stylize a string -function stylize(str, style) { - var styles = { - 'bold' : [1, 22], - 'inverse' : [7, 27], - 'underline' : [4, 24], - 'yellow' : [33, 39], - 'green' : [32, 39], - 'red' : [31, 39] - }; - return '\033[' + styles[style][0] + 'm' + str + - '\033[' + styles[style][1] + 'm'; -} diff --git a/r2/r2/lib/contrib/less.js/test/less/colors.less b/r2/r2/lib/contrib/less.js/test/less/colors.less deleted file mode 100644 index 3f808625b..000000000 --- a/r2/r2/lib/contrib/less.js/test/less/colors.less +++ /dev/null @@ -1,65 +0,0 @@ -#yelow { - #short { - color: #fea; - } - #long { - color: #ffeeaa; - } - #rgba { - color: rgba(255, 238, 170, 0.1); - } - #argb { - color: argb(rgba(255, 238, 170, 0.1)); - } -} - -#blue { - #short { - color: #00f; - } - #long { - color: #0000ff; - } - #rgba { - color: rgba(0, 0, 255, 0.1); - } - #argb { - color: argb(rgba(0, 0, 255, 0.1)); - } -} - -#alpha #hsla { - color: hsla(11, 20%, 20%, 0.6); -} - -#overflow { - .a { color: #111111 - #444444; } // #000000 - .b { color: #eee + #fff; } // #ffffff - .c { color: #aaa * 3; } // #ffffff - .d { color: #00ee00 + #009900; } // #00ff00 -} - -#grey { - color: rgb(200, 200, 200); -} - -#808080 { - color: hsl(50, 0%, 50%); -} - -#00ff00 { - color: hsl(120, 100%, 50%); -} - -.lightenblue { - color: lighten(blue, 10%); -} - -.darkenblue { - color: darken(blue, 10%); -} - -.unknowncolors { - color: blue2; - border: 2px solid superred; -} diff --git a/r2/r2/lib/contrib/less.js/test/less/comments.less b/r2/r2/lib/contrib/less.js/test/less/comments.less deleted file mode 100644 index 1b5c63e44..000000000 --- a/r2/r2/lib/contrib/less.js/test/less/comments.less +++ /dev/null @@ -1,65 +0,0 @@ -/******************\ -* * -* Comment Header * -* * -\******************/ - -/* - - Comment - -*/ - -/* - * Comment Test - * - * - cloudhead (http://cloudhead.net) - * - */ - -//////////////// -@var: "content"; -//////////////// - -/* Colors - * ------ - * #EDF8FC (background blue) - * #166C89 (darkest blue) - * - * Text: - * #333 (standard text) // A comment within a comment! - * #1F9EC9 (standard link) - * - */ - -/* @group Variables -------------------- */ -#comments /* boo */ { - /**/ // An empty comment - color: red; /* A C-style comment */ - background-color: orange; // A little comment - font-size: 12px; - - /* lost comment */ content: @var; - - border: 1px solid black; - - // padding & margin // - padding: 0; // }{ '" - margin: 2em; -} // - -/* commented out - #more-comments { - color: grey; - } -*/ - -.selector /* .with */, .lots, /* of */ .comments { - color: grey, /* blue */ orange; - -webkit-border-radius: 2px /* webkit only */; - -moz-border-radius: 2px * 4 /* moz only with operation */; -} - -#last { color: blue } -// diff --git a/r2/r2/lib/contrib/less.js/test/less/css-3.less b/r2/r2/lib/contrib/less.js/test/less/css-3.less deleted file mode 100644 index bdda76d0a..000000000 --- a/r2/r2/lib/contrib/less.js/test/less/css-3.less +++ /dev/null @@ -1,65 +0,0 @@ -.comma-delimited { - background: url(bg.jpg) no-repeat, url(bg.png) repeat-x top left, url(bg); - text-shadow: -1px -1px 1px red, 6px 5px 5px yellow; - -moz-box-shadow: 0pt 0pt 2px rgba(255, 255, 255, 0.4) inset, - 0pt 4px 6px rgba(255, 255, 255, 0.4) inset; -} -@font-face { - font-family: Headline; - src: local(Futura-Medium), - url(fonts.svg#MyGeometricModern) format("svg"); -} -.other { - -moz-transform: translate(0, 11em) rotate(-90deg); -} -p:not([class*="lead"]) { - color: black; -} - -input[type="text"].class#id[attr=32]:not(1) { - color: white; -} - -div#id.class[a=1][b=2].class:not(1) { - color: white; -} - -ul.comma > li:not(:only-child)::after { - color: white; -} - -ol.comma > li:nth-last-child(2)::after { - color: white; -} - -li:nth-child(4n+1), -li:nth-child(-5n), -li:nth-child(-n+2) { - color: white; -} - -a[href^="http://"] { - color: black; -} - -a[href$="http://"] { - color: black; -} - -form[data-disabled] { - color: black; -} - -p::before { - color: black; -} - -#issue322 { - -webkit-animation: anim2 7s infinite ease-in-out; -} - -@-webkit-keyframes frames { - 0% { border: 1px } - 5.5% { border: 2px } - 100% { border: 3px } -} diff --git a/r2/r2/lib/contrib/less.js/test/less/css-escapes.less b/r2/r2/lib/contrib/less.js/test/less/css-escapes.less deleted file mode 100644 index a2893e581..000000000 --- a/r2/r2/lib/contrib/less.js/test/less/css-escapes.less +++ /dev/null @@ -1,28 +0,0 @@ -@ugly: fuchsia; - -.escape\|random\|char { - color: red; -} - -.mixin\!tUp { - font-weight: bold; -} - -// class="404" -.\34 04 { - background: red; - - strong { - color: @ugly; - .mixin\!tUp; - } -} - -.trailingTest\+ { - color: red; -} - -/* This hideous test of hideousness checks for the selector "blockquote" with various permutations of hex escapes */ -\62\6c\6f \63 \6B \0071 \000075o\74 e { - color: silver; -} \ No newline at end of file diff --git a/r2/r2/lib/contrib/less.js/test/less/css.less b/r2/r2/lib/contrib/less.js/test/less/css.less deleted file mode 100644 index 3654cf827..000000000 --- a/r2/r2/lib/contrib/less.js/test/less/css.less +++ /dev/null @@ -1,100 +0,0 @@ -@charset "utf-8"; -div { color: black; } -div { width: 99%; } - -* { - min-width: 45em; -} - -h1, h2 > a > p, h3 { - color: none; -} - -div.class { - color: blue; -} - -div#id { - color: green; -} - -.class#id { - color: purple; -} - -.one.two.three { - color: grey; -} - -@media print { - font-size: 3em; -} - -@media screen { - font-size: 10px; -} - -@font-face { - font-family: 'Garamond Pro'; - src: url("/fonts/garamond-pro.ttf"); -} - -a:hover, a:link { - color: #999; -} - -p, p:first-child { - text-transform: none; -} - -q:lang(no) { - quotes: none; -} - -p + h1 { - font-size: 2.2em; -} - -#shorthands { - border: 1px solid #000; - font: 12px/16px Arial; - font: 100%/16px Arial; - margin: 1px 0; - padding: 0 auto; - background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px; -} - -#more-shorthands { - margin: 0; - padding: 1px 0 2px 0; - font: normal small/20px 'Trebuchet MS', Verdana, sans-serif; -} - -.misc { - -moz-border-radius: 2px; - display: -moz-inline-stack; - width: .1em; - background-color: #009998; - background-image: url(images/image.jpg); - background: -webkit-gradient(linear, left top, left bottom, from(red), to(blue)); - margin: ; - filter: alpha(opacity=100); -} - -#important { - color: red !important; - width: 100%!important; - height: 20px ! important; -} - -#data-uri { - background: url(data:image/png;charset=utf-8;base64, - kiVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD/ - k//+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4U - kg9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC); - background-image: url(data:image/x-png,f9difSSFIIGFIFJD1f982FSDKAA9==); -} - -#svg-data-uri { - background: transparent url('data:image/svg+xml, '); -} diff --git a/r2/r2/lib/contrib/less.js/test/less/functions.less b/r2/r2/lib/contrib/less.js/test/less/functions.less deleted file mode 100644 index c111f7e56..000000000 --- a/r2/r2/lib/contrib/less.js/test/less/functions.less +++ /dev/null @@ -1,49 +0,0 @@ -#functions { - @var: 10; - color: _color("evil red"); // #660000 - width: increment(15); - height: undefined("self"); - border-width: add(2, 3); - variable: increment(@var); -} - -#built-in { - @r: 32; - escaped: e("-Some::weird(#thing, y)"); - lighten: lighten(#ff0000, 40%); - darken: darken(#ff0000, 40%); - saturate: saturate(#29332f, 20%); - desaturate: desaturate(#203c31, 20%); - greyscale: greyscale(#203c31); - spin-p: spin(hsl(340, 50%, 50%), 40); - spin-n: spin(hsl(30, 50%, 50%), -40); - format: %("rgb(%d, %d, %d)", @r, 128, 64); - format-string: %("hello %s", "world"); - format-multiple: %("hello %s %d", "earth", 2); - format-url-encode: %('red is %A', #ff0000); - eformat: e(%("rgb(%d, %d, %d)", @r, 128, 64)); - - hue: hue(hsl(98, 12%, 95%)); - saturation: saturation(hsl(98, 12%, 95%)); - lightness: lightness(hsl(98, 12%, 95%)); - rounded: round(@r/3); - roundedpx: round(10px / 3); - percentage: percentage(10px / 50); - color: color("#ff0011"); - - .is-a { - color: iscolor(#ddd); - color1: iscolor(red); - color2: iscolor(rgb(0, 0, 0)); - keyword: iskeyword(hello); - number: isnumber(32); - string: isstring("hello"); - pixel: ispixel(32px); - percent: ispercentage(32%); - em: isem(32em); - } -} - -#alpha { - alpha: darken(hsla(25, 50%, 50%, 0.6), 10%); -} diff --git a/r2/r2/lib/contrib/less.js/test/less/ie-filters.less b/r2/r2/lib/contrib/less.js/test/less/ie-filters.less deleted file mode 100644 index bea85b824..000000000 --- a/r2/r2/lib/contrib/less.js/test/less/ie-filters.less +++ /dev/null @@ -1,8 +0,0 @@ -@fat: 0; -@cloudhead: "#000000"; - -.nav { - filter: progid:DXImageTransform.Microsoft.Alpha(opacity = 20); - filter: progid:DXImageTransform.Microsoft.Alpha(opacity=@fat); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#333333", endColorstr=@cloudhead, GradientType=@fat); -} \ No newline at end of file diff --git a/r2/r2/lib/contrib/less.js/test/less/import-once.less b/r2/r2/lib/contrib/less.js/test/less/import-once.less deleted file mode 100644 index 739900a6d..000000000 --- a/r2/r2/lib/contrib/less.js/test/less/import-once.less +++ /dev/null @@ -1,3 +0,0 @@ -@import-once "import/import-test-a"; -@import-once "import/import-test-b"; -@import-once "import/import-test-c"; \ No newline at end of file diff --git a/r2/r2/lib/contrib/less.js/test/less/import.less b/r2/r2/lib/contrib/less.js/test/less/import.less deleted file mode 100644 index 13ed5c5a3..000000000 --- a/r2/r2/lib/contrib/less.js/test/less/import.less +++ /dev/null @@ -1,11 +0,0 @@ -@import url("import/import-test-a.less"); -@import url(http://fonts.googleapis.com/css?family=Open+Sans); - -@import url(something.css) screen and (color) and (max-width: 600px); - -#import-test { - .mixin; - width: 10px; - height: @a + 10%; -} -@import "import/import-test-e" screen and (max-width: 600px); diff --git a/r2/r2/lib/contrib/less.js/test/less/import/import-test-a.less b/r2/r2/lib/contrib/less.js/test/less/import/import-test-a.less deleted file mode 100644 index 7409d0714..000000000 --- a/r2/r2/lib/contrib/less.js/test/less/import/import-test-a.less +++ /dev/null @@ -1,2 +0,0 @@ -@import "import-test-b.less"; -@a: 20%; diff --git a/r2/r2/lib/contrib/less.js/test/less/import/import-test-b.less b/r2/r2/lib/contrib/less.js/test/less/import/import-test-b.less deleted file mode 100644 index ce2d35a83..000000000 --- a/r2/r2/lib/contrib/less.js/test/less/import/import-test-b.less +++ /dev/null @@ -1,8 +0,0 @@ -@import "import-test-c"; - -@b: 100%; - -.mixin { - height: 10px; - color: @c; -} diff --git a/r2/r2/lib/contrib/less.js/test/less/import/import-test-c.less b/r2/r2/lib/contrib/less.js/test/less/import/import-test-c.less deleted file mode 100644 index 111266ba8..000000000 --- a/r2/r2/lib/contrib/less.js/test/less/import/import-test-c.less +++ /dev/null @@ -1,7 +0,0 @@ - -@import "import-test-d.css"; -@c: red; - -#import { - color: @c; -} diff --git a/r2/r2/lib/contrib/less.js/test/less/import/import-test-d.css b/r2/r2/lib/contrib/less.js/test/less/import/import-test-d.css deleted file mode 100644 index 30575f018..000000000 --- a/r2/r2/lib/contrib/less.js/test/less/import/import-test-d.css +++ /dev/null @@ -1 +0,0 @@ -#css { color: yellow; } diff --git a/r2/r2/lib/contrib/less.js/test/less/import/import-test-e.less b/r2/r2/lib/contrib/less.js/test/less/import/import-test-e.less deleted file mode 100644 index 98b84b0a5..000000000 --- a/r2/r2/lib/contrib/less.js/test/less/import/import-test-e.less +++ /dev/null @@ -1,2 +0,0 @@ - -body { width: 100% } diff --git a/r2/r2/lib/contrib/less.js/test/less/javascript.less b/r2/r2/lib/contrib/less.js/test/less/javascript.less deleted file mode 100644 index 71d7af1f2..000000000 --- a/r2/r2/lib/contrib/less.js/test/less/javascript.less +++ /dev/null @@ -1,27 +0,0 @@ -.eval { - js: `42`; - js: `1 + 1`; - js: `"hello world"`; - js: `[1, 2, 3]`; - title: `process.title`; - ternary: `(1 + 1 == 2 ? true : false)`; -} -.scope { - @foo: 42; - var: `this.foo.toJS()`; - escaped: ~`2 + 5 + 'px'`; -} -.vars { - @var: `4 + 4`; - width: @var; -} -.escape-interpol { - @world: "world"; - width: ~`"hello" + " " + @{world}`; -} -.arrays { - @ary: 1, 2, 3; - @ary2: 1 2 3; - ary: `@{ary}.join(', ')`; - ary1: `@{ary2}.join(', ')`; -} diff --git a/r2/r2/lib/contrib/less.js/test/less/lazy-eval.less b/r2/r2/lib/contrib/less.js/test/less/lazy-eval.less deleted file mode 100644 index 72b3fd46e..000000000 --- a/r2/r2/lib/contrib/less.js/test/less/lazy-eval.less +++ /dev/null @@ -1,6 +0,0 @@ -@var: @a; -@a: 100%; - -.lazy-eval { - width: @var; -} diff --git a/r2/r2/lib/contrib/less.js/test/less/media.less b/r2/r2/lib/contrib/less.js/test/less/media.less deleted file mode 100644 index 00ecaf7d6..000000000 --- a/r2/r2/lib/contrib/less.js/test/less/media.less +++ /dev/null @@ -1,79 +0,0 @@ - -// For now, variables can't be declared inside @media blocks. - -@var: 42; - -@media print { - .class { - color: blue; - .sub { - width: @var; - } - } - .top, header > h1 { - color: #222 * 2; - } -} - -@media screen { - @base: 8; - body { max-width: @base * 60; } -} - -@media all and (orientation:portrait) { - aside { float: none; } -} - -@media handheld and (min-width: @var), screen and (min-width: 20em) { - body { - max-width: 480px; - } -} - -body { - @media print { - padding: 20px; - - header { - background-color: red; - } - - @media (orientation:landscape) { - margin-left: 20px; - } - } -} - -body { - @media a, b and c { - width: 95%; - - @media x, y { - width: 100%; - } - } -} - -.mediaMixin(@fallback: 200px) { - background: black; - - @media handheld { - background: white; - - @media (max-width: @fallback) { - background: red; - } - } -} - -.a { - .mediaMixin(100px); -} - -.b { - .mediaMixin(); -} -@smartphone: ~"only screen and (max-width: 200px)"; -@media @smartphone { - width: 480px; -} diff --git a/r2/r2/lib/contrib/less.js/test/less/mixins-args.less b/r2/r2/lib/contrib/less.js/test/less/mixins-args.less deleted file mode 100644 index ea43a0a53..000000000 --- a/r2/r2/lib/contrib/less.js/test/less/mixins-args.less +++ /dev/null @@ -1,130 +0,0 @@ -.mixin (@a: 1px, @b: 50%) { - width: @a * 5; - height: @b - 1%; -} - -.mixina (@style, @width, @color: black) { - border: @width @style @color; -} - -.mixiny -(@a: 0, @b: 0) { - margin: @a; - padding: @b; -} - -.hidden() { - color: transparent; // asd -} - -#hidden { - .hidden; -} - -#hidden1 { - .hidden(); -} - -.two-args { - color: blue; - .mixin(2px, 100%); - .mixina(dotted, 2px); -} - -.one-arg { - .mixin(3px); -} - -.no-parens { - .mixin; -} - -.no-args { - .mixin(); -} - -.var-args { - @var: 9; - .mixin(@var, @var * 2); -} - -.multi-mix { - .mixin(2px, 30%); - .mixiny(4, 5); -} - -.maxa(@arg1: 10, @arg2: #f00) { - padding: @arg1 * 2px; - color: @arg2; -} - -body { - .maxa(15); -} - -@glob: 5; -.global-mixin(@a:2) { - width: @glob + @a; -} - -.scope-mix { - .global-mixin(3); -} - -.nested-ruleset (@width: 200px) { - width: @width; - .column { margin: @width; } -} -.content { - .nested-ruleset(600px); -} - -// - -.same-var-name2(@radius) { - radius: @radius; -} -.same-var-name(@radius) { - .same-var-name2(@radius); -} -#same-var-name { - .same-var-name(5px); -} - -// - -.var-inside () { - @var: 10px; - width: @var; -} -#var-inside { .var-inside; } - -.mixin-arguments (@width: 0px, ...) { - border: @arguments; - width: @width; -} - -.arguments { - .mixin-arguments(1px, solid, black); -} -.arguments2 { - .mixin-arguments(); -} -.arguments3 { - .mixin-arguments; -} - -.mixin-arguments2 (@width, @rest...) { - border: @arguments; - rest: @rest; - width: @width; -} -.arguments4 { - .mixin-arguments2(0, 1, 2, 3, 4); -} - -// Edge cases - -.edge-case { - .mixin-arguments("{"); -} diff --git a/r2/r2/lib/contrib/less.js/test/less/mixins-closure.less b/r2/r2/lib/contrib/less.js/test/less/mixins-closure.less deleted file mode 100644 index 01251d2ad..000000000 --- a/r2/r2/lib/contrib/less.js/test/less/mixins-closure.less +++ /dev/null @@ -1,26 +0,0 @@ -.scope { - @var: 99px; - .mixin () { - width: @var; - } -} - -.class { - .scope > .mixin; -} - -.overwrite { - @var: 0px; - .scope > .mixin; -} - -.nested { - @var: 5px; - .mixin () { - width: @var; - } - .class { - @var: 10px; - .mixin; - } -} diff --git a/r2/r2/lib/contrib/less.js/test/less/mixins-guards.less b/r2/r2/lib/contrib/less.js/test/less/mixins-guards.less deleted file mode 100644 index 1f46e976b..000000000 --- a/r2/r2/lib/contrib/less.js/test/less/mixins-guards.less +++ /dev/null @@ -1,94 +0,0 @@ - -// Stacking, functions.. - -.light (@a) when (lightness(@a) > 50%) { - color: white; -} -.light (@a) when (lightness(@a) < 50%) { - color: black; -} -.light (@a) { - margin: 1px; -} - -.light1 { .light(#ddd) } -.light2 { .light(#444) } - -// Arguments against each other - -.max (@a, @b) when (@a > @b) { - width: @a; -} -.max (@a, @b) when (@a < @b) { - width: @b; -} - -.max1 { .max(3, 6) } -.max2 { .max(8, 1) } - -// Globals inside guards - -@g: auto; - -.glob (@a) when (@a = @g) { - margin: @a @g; -} -.glob1 { .glob(auto) } - -// Other operators - -.ops (@a) when (@a >= 0) { - height: gt-or-eq; -} -.ops (@a) when (@a =< 0) { - height: lt-or-eq; -} -.ops (@a) when not(@a = 0) { - height: not-eq; -} -.ops1 { .ops(0) } -.ops2 { .ops(1) } -.ops3 { .ops(-1) } - -// Scope and default values - -@a: auto; - -.default (@a: inherit) when (@a = inherit) { - content: default; -} -.default1 { .default } - -// true & false keywords -.test (@a) when (@a) { - content: "true."; -} -.test (@a) when not (@a) { - content: "false."; -} - -.test1 { .test(true) } -.test2 { .test(false) } -.test3 { .test(1) } -.test4 { .test(boo) } -.test5 { .test("true") } - -// Boolean expressions - -.bool () when (true) and (false) { content: true and false } // FALSE -.bool () when (true) and (true) { content: true and true } // TRUE -.bool () when (true) { content: true } // TRUE -.bool () when (false) and (false) { content: true } // FALSE -.bool () when (false), (true) { content: false, true } // TRUE -.bool () when (false) and (true) and (true), (true) { content: false and true and true, true } // TRUE -.bool () when (true) and (true) and (false), (false) { content: true and true and false, false } // FALSE -.bool () when (false), (true) and (true) { content: false, true and true } // TRUE -.bool () when (false), (false), (true) { content: false, false, true } // TRUE -.bool () when (false), (false) and (true), (false) { content: false, false and true, false } // FALSE -.bool () when (false), (true) and (true) and (true), (false) { content: false, true and true and true, false } // TRUE -.bool () when not (false) { content: not false } -.bool () when not (true) and not (false) { content: not true and not false } -.bool () when not (true) and not (true) { content: not true and not true } -.bool () when not (false) and (false), not (false) { content: not false and false, not false } - -.bool1 { .bool } diff --git a/r2/r2/lib/contrib/less.js/test/less/mixins-important.less b/r2/r2/lib/contrib/less.js/test/less/mixins-important.less deleted file mode 100644 index 790a4d6e0..000000000 --- a/r2/r2/lib/contrib/less.js/test/less/mixins-important.less +++ /dev/null @@ -1,18 +0,0 @@ - -.mixin (9) { - border: 9 !important; -} -.mixin (@a: 0) { - border: @a; - boxer: @a; -} - -.class { - .mixin(1); - .mixin(2) !important; - .mixin(3); - .mixin(4) !important; - .mixin(5); - .mixin !important; - .mixin(9); -} diff --git a/r2/r2/lib/contrib/less.js/test/less/mixins-named-args.less b/r2/r2/lib/contrib/less.js/test/less/mixins-named-args.less deleted file mode 100644 index 57b07d010..000000000 --- a/r2/r2/lib/contrib/less.js/test/less/mixins-named-args.less +++ /dev/null @@ -1,31 +0,0 @@ -.mixin (@a: 1px, @b: 50%) { - width: @a * 5; - height: @b - 1%; -} -.mixin (@a: 1px, @b: 50%) when (@b > 75%){ - text-align: center; -} - -.named-arg { - color: blue; - .mixin(@b: 100%); -} - -.class { - @var: 20%; - .mixin(@b: @var); -} - -.mixin2 (@a: 1px, @b: 50%, @c: 50) { - width: @a * 5; - height: @b - 1%; - color: #000000 + @c; -} - -.named-args2 { - .mixin2(3px, @c: 100); -} - -.named-args3 { - .mixin2(@b: 30%, @c: #123456); -} \ No newline at end of file diff --git a/r2/r2/lib/contrib/less.js/test/less/mixins-nested.less b/r2/r2/lib/contrib/less.js/test/less/mixins-nested.less deleted file mode 100644 index d086279c8..000000000 --- a/r2/r2/lib/contrib/less.js/test/less/mixins-nested.less +++ /dev/null @@ -1,22 +0,0 @@ -.mix-inner (@var) { - border-width: @var; -} - -.mix (@a: 10) { - .inner { - height: @a * 10; - - .innest { - width: @a; - .mix-inner(@a * 2); - } - } -} - -.class { - .mix(30); -} - -.class2 { - .mix(60); -} diff --git a/r2/r2/lib/contrib/less.js/test/less/mixins-pattern.less b/r2/r2/lib/contrib/less.js/test/less/mixins-pattern.less deleted file mode 100644 index b2121e956..000000000 --- a/r2/r2/lib/contrib/less.js/test/less/mixins-pattern.less +++ /dev/null @@ -1,99 +0,0 @@ -.mixin (...) { - variadic: true; -} -.mixin () { - zero: 0; -} -.mixin (@a: 1px) { - one: 1; -} -.mixin (@a) { - one-req: 1; -} -.mixin (@a: 1px, @b: 2px) { - two: 2; -} - -.mixin (@a, @b, @c) { - three-req: 3; -} - -.mixin (@a: 1px, @b: 2px, @c: 3px) { - three: 3; -} - -.zero { - .mixin(); -} - -.one { - .mixin(1); -} - -.two { - .mixin(1, 2); -} - -.three { - .mixin(1, 2, 3); -} - -// - -.mixout ('left') { - left: 1; -} - -.mixout ('right') { - right: 1; -} - -.left { - .mixout('left'); -} -.right { - .mixout('right'); -} - -// - -.border (@side, @width) { - color: black; - .border-side(@side, @width); -} -.border-side (left, @w) { - border-left: @w; -} -.border-side (right, @w) { - border-right: @w; -} - -.border-right { - .border(right, 4px); -} -.border-left { - .border(left, 4px); -} - -// - - -.border-radius (@r) { - both: @r * 10; -} -.border-radius (@r, left) { - left: @r; -} -.border-radius (@r, right) { - right: @r; -} - -.only-right { - .border-radius(33, right); -} -.only-left { - .border-radius(33, left); -} -.left-right { - .border-radius(33); -} diff --git a/r2/r2/lib/contrib/less.js/test/less/mixins.less b/r2/r2/lib/contrib/less.js/test/less/mixins.less deleted file mode 100644 index 2fd761174..000000000 --- a/r2/r2/lib/contrib/less.js/test/less/mixins.less +++ /dev/null @@ -1,67 +0,0 @@ -.mixin { border: 1px solid black; } -.mixout { border-color: orange; } -.borders { border-style: dashed; } - -#namespace { - .borders { - border-style: dotted; - } - .biohazard { - content: "death"; - .man { - color: transparent; - } - } -} -#theme { - > .mixin { - background-color: grey; - } -} -#container { - color: black; - .mixin; - .mixout; - #theme > .mixin; -} - -#header { - .milk { - color: white; - .mixin; - #theme > .mixin; - } - #cookie { - .chips { - #namespace .borders; - .calories { - #container; - } - } - .borders; - } -} -.secure-zone { #namespace .biohazard .man; } -.direct { - #namespace > .borders; -} - -.bo, .bar { - width: 100%; -} -.bo { - border: 1px; -} -.ar.bo.ca { - color: black; -} -.jo.ki { - background: none; -} -.extended { - .bo; - .jo.ki; -} -.foo .bar { - .bar; -} diff --git a/r2/r2/lib/contrib/less.js/test/less/operations.less b/r2/r2/lib/contrib/less.js/test/less/operations.less deleted file mode 100644 index 46b0aa393..000000000 --- a/r2/r2/lib/contrib/less.js/test/less/operations.less +++ /dev/null @@ -1,62 +0,0 @@ -#operations { - color: #110000 + #000011 + #001100; // #111111 - height: 10px / 2px + 6px - 1px * 2; // 9px - width: 2 * 4 - 5em; // 3em - .spacing { - height: 10px / 2px+6px-1px*2; - width: 2 * 4-5em; - } - substraction: 20 - 10 - 5 - 5; // 0 - division: 20 / 5 / 4; // 1 -} - -@x: 4; -@y: 12em; - -.with-variables { - height: @x + @y; // 16em - width: 12 + @y; // 24em - size: 5cm - @x; // 1cm -} - -.with-functions { - color: rgb(200, 200, 200) / 2; - color: 2 * hsl(0, 50%, 50%); - color: rgb(10, 10, 10) + hsl(0, 50%, 50%); -} - -@z: -2; - -.negative { - height: 2px + @z; // 0px - width: 2px - @z; // 4px -} - -.shorthands { - padding: -1px 2px 0 -4px; // -} - -.rem-dimensions { - font-size: 20rem / 5 + 1.5rem; // 5.5rem -} - -.colors { - color: #123; // #112233 - border-color: #234 + #111111; // #334455 - background-color: #222222 - #fff; // #000000 - .other { - color: 2 * #111; // #222222 - border-color: #333333 / 3 + #111; // #222222 - } -} - -.negations { - @var: 4px; - variable: -@var; // 4 - variable1: -@var + @var; // 0 - variable2: @var + -@var; // 0 - variable3: @var - -@var; // 8 - variable4: -@var - -@var; // 0 - paren: -(@var); // -4px - paren2: -(2 + 2) * -@var; // 16 -} diff --git a/r2/r2/lib/contrib/less.js/test/less/parens.less b/r2/r2/lib/contrib/less.js/test/less/parens.less deleted file mode 100644 index e020c7eb3..000000000 --- a/r2/r2/lib/contrib/less.js/test/less/parens.less +++ /dev/null @@ -1,26 +0,0 @@ -.parens { - @var: 1px; - border: (@var * 2) solid black; - margin: (@var * 1) (@var + 2) (4 * 4) 3; - width: (6 * 6); - padding: 2px (6px * 6px); -} - -.more-parens { - @var: (2 * 2); - padding: (2 * @var) 4 4 (@var * 1px); - width: (@var * @var) * 6; - height: (7 * 7) + (8 * 8); - margin: 4 * (5 + 5) / 2 - (@var * 2); - //margin: (6 * 6)px; -} - -.nested-parens { - width: 2 * (4 * (2 + (1 + 6))) - 1; - height: ((2+3)*(2+3) / (9-4)) + 1; -} - -.mixed-units { - margin: 2px 4em 1 5pc; - padding: (2px + 4px) 1em 2px 2; -} diff --git a/r2/r2/lib/contrib/less.js/test/less/rulesets.less b/r2/r2/lib/contrib/less.js/test/less/rulesets.less deleted file mode 100644 index e81192dbc..000000000 --- a/r2/r2/lib/contrib/less.js/test/less/rulesets.less +++ /dev/null @@ -1,30 +0,0 @@ -#first > .one { - > #second .two > #deux { - width: 50%; - #third { - &:focus { - color: black; - #fifth { - > #sixth { - .seventh #eighth { - + #ninth { - color: purple; - } - } - } - } - } - height: 100%; - } - #fourth, #five, #six { - color: #110000; - .seven, .eight > #nine { - border: 1px solid black; - } - #ten { - color: red; - } - } - } - font-size: 2em; -} diff --git a/r2/r2/lib/contrib/less.js/test/less/scope.less b/r2/r2/lib/contrib/less.js/test/less/scope.less deleted file mode 100644 index da664626d..000000000 --- a/r2/r2/lib/contrib/less.js/test/less/scope.less +++ /dev/null @@ -1,32 +0,0 @@ -@x: blue; -@z: transparent; -@mix: none; - -.mixin { - @mix: #989; -} - -.tiny-scope { - color: @mix; // #989 - .mixin; -} - -.scope1 { - @y: orange; - @z: black; - color: @x; // blue - border-color: @z; // black - .hidden { - @x: #131313; - } - .scope2 { - @y: red; - color: @x; // blue - .scope3 { - @local: white; - color: @y; // red - border-color: @z; // black - background-color: @local; // white - } - } -} diff --git a/r2/r2/lib/contrib/less.js/test/less/selectors.less b/r2/r2/lib/contrib/less.js/test/less/selectors.less deleted file mode 100644 index 238980248..000000000 --- a/r2/r2/lib/contrib/less.js/test/less/selectors.less +++ /dev/null @@ -1,55 +0,0 @@ -h1, h2, h3 { - a, p { - &:hover { - color: red; - } - } -} - -#all { color: blue; } -#the { color: blue; } -#same { color: blue; } - -ul, li, div, q, blockquote, textarea { - margin: 0; -} - -td { - margin: 0; - padding: 0; -} - -td, input { - line-height: 1em; -} - -a { - color: red; - - &:hover { color: blue; } - - div & { color: green; } - - p & span { color: yellow; } -} - -.foo { - .bar, .baz { - & .qux { - display: block; - } - .qux & { - display: inline; - } - .qux & .biz { - display: none; - } - } -} - -.other ::fnord { color: red } -.other::fnord { color: red } -.other { - ::bnord {color: red } - &::bnord {color: red } -} diff --git a/r2/r2/lib/contrib/less.js/test/less/strings.less b/r2/r2/lib/contrib/less.js/test/less/strings.less deleted file mode 100644 index 32fad721a..000000000 --- a/r2/r2/lib/contrib/less.js/test/less/strings.less +++ /dev/null @@ -1,51 +0,0 @@ -#strings { - background-image: url("http://son-of-a-banana.com"); - quotes: "~" "~"; - content: "#*%:&^,)!.(~*})"; - empty: ""; - brackets: "{" "}"; - escapes: "\"hello\" \\world"; - escapes2: "\"llo"; -} -#comments { - content: "/* hello */ // not-so-secret"; -} -#single-quote { - quotes: "'" "'"; - content: '""#!&""'; - empty: ''; - semi-colon: ';'; -} -#escaped { - filter: ~"DX.Transform.MS.BS.filter(opacity=50)"; -} -#one-line { image: url(http://tooks.com) } -#crazy { image: url(http://), "}", url("http://}") } -#interpolation { - @var: '/dev'; - url: "http://lesscss.org@{var}/image.jpg"; - - @var2: 256; - url2: "http://lesscss.org/image-@{var2}.jpg"; - - @var3: #456; - url3: "http://lesscss.org@{var3}"; - - @var4: hello; - url4: "http://lesscss.org/@{var4}"; - - @var5: 54.4px; - url5: "http://lesscss.org/@{var5}"; -} - -// multiple calls with string interpolation - -.mix-mul (@a: green) { - color: ~"@{a}"; -} -.mix-mul-class { - .mix-mul(blue); - .mix-mul(red); - .mix-mul(black); - .mix-mul(orange); -} diff --git a/r2/r2/lib/contrib/less.js/test/less/variables.less b/r2/r2/lib/contrib/less.js/test/less/variables.less deleted file mode 100644 index 66ab4efff..000000000 --- a/r2/r2/lib/contrib/less.js/test/less/variables.less +++ /dev/null @@ -1,54 +0,0 @@ -@a: 2; -@x: @a * @a; -@y: @x + 1; -@z: @x * 2 + @y; - -.variables { - width: @z + 1cm; // 14cm -} - -@b: @a * 10; -@c: #888; - -@fonts: "Trebuchet MS", Verdana, sans-serif; -@f: @fonts; - -@quotes: "~" "~"; -@q: @quotes; - -.variables { - height: @b + @x + 0px; // 24px - color: @c; - font-family: @f; - quotes: @q; -} - -.redefinition { - @var: 4; - @var: 2; - @var: 3; - three: @var; -} - -.values { - @a: 'Trebuchet'; - @multi: 'A', B, C; - font-family: @a, @a, @a; - color: @c !important; - url: url(@a); - multi: something @multi, @a; -} - -.variable-names { - @var: 'hello'; - @name: 'var'; - name: @@name; -} -.alpha { - @var: 42; - filter: alpha(opacity=@var); -} - -a:nth-child(@a) { - border: 1px; -} diff --git a/r2/r2/lib/contrib/less.js/test/less/whitespace.less b/r2/r2/lib/contrib/less.js/test/less/whitespace.less deleted file mode 100644 index cc0a8a324..000000000 --- a/r2/r2/lib/contrib/less.js/test/less/whitespace.less +++ /dev/null @@ -1,37 +0,0 @@ - - -.whitespace - { color: white; } - -.whitespace -{ - color: white; -} - .whitespace -{ color: white; } - -.whitespace{color:white;} -.whitespace { color : white ; } - -.white, -.space, -.mania -{ color: white; } - -.no-semi-column { color: white } -.no-semi-column { - color: white; - white-space: pre -} -.no-semi-column {border: 2px solid white} -.newlines { - background: the, - great, - wall; - border: 2px - solid - black; -} -.empty { - -} diff --git a/r2/r2/lib/js.py b/r2/r2/lib/js.py index 7b16cd2ef..f6854391f 100755 --- a/r2/r2/lib/js.py +++ b/r2/r2/lib/js.py @@ -520,7 +520,7 @@ module["highlight"] = Module("highlight.js", ) module["less"] = Module('less.js', - 'lib/less-1.3.0.min.js', + 'lib/less-1.4.2.js', should_compile=False, ) diff --git a/r2/r2/public/static/js/lib/less-1.3.0.min.js b/r2/r2/public/static/js/lib/less-1.3.0.min.js deleted file mode 100644 index 309bf550d..000000000 --- a/r2/r2/public/static/js/lib/less-1.3.0.min.js +++ /dev/null @@ -1,9 +0,0 @@ -// -// LESS - Leaner CSS v1.3.0 -// http://lesscss.org -// -// Copyright (c) 2009-2011, Alexis Sellier -// Licensed under the Apache 2.0 License. -// -(function(a,b){function c(b){return a.less[b.split("/")[1]]}function l(){var a=document.getElementsByTagName("style");for(var b=0;b0?d.firstChild.nodeValue!==a.nodeValue&&d.replaceChild(a,d.firstChild):d.appendChild(a)})(document.createTextNode(a));c&&g&&(t("saving "+e+" to cache."),g.setItem(e,a),g.setItem(e+":timestamp",c))}function q(a,b,c,e){function i(b,c,d){b.status>=200&&b.status<300?c(b.responseText,b.getResponseHeader("Last-Modified")):typeof d=="function"&&d(b.status,a)}var g=r(),h=f?!1:d.async;typeof g.overrideMimeType=="function"&&g.overrideMimeType("text/css"),g.open("GET",a,h),g.setRequestHeader("Accept",b||"text/x-less, text/css; q=0.9, */*; q=0.5"),g.send(null),f?g.status===0||g.status>=200&&g.status<300?c(g.responseText):e(g.status,a):h?g.onreadystatechange=function(){g.readyState==4&&i(g,c,e)}:i(g,c,e)}function r(){if(a.XMLHttpRequest)return new XMLHttpRequest;try{return new ActiveXObject("MSXML2.XMLHTTP.3.0")}catch(b){return t("browser doesn't support AJAX."),null}}function s(a){return a&&a.parentNode.removeChild(a)}function t(a){d.env=="development"&&typeof console!="undefined"&&console.log("less: "+a)}function u(a,b){var c="less-error-message:"+o(b),e='
  • {content}
  • ',f=document.createElement("div"),g,h,i=[],j=a.filename||b;f.id=c,f.className="less-error-message",h="

    "+(a.message||"There is an error in your .less file")+"

    "+'

    in '+j+" ";var k=function(a,b,c){a.extract[b]&&i.push(e.replace(/\{line\}/,parseInt(a.line)+(b-1)).replace(/\{class\}/,c).replace(/\{content\}/,a.extract[b]))};a.stack?h+="
    "+a.stack.split("\n").slice(1).join("
    "):a.extract&&(k(a,0,""),k(a,1,"line"),k(a,2,""),h+="on line "+a.line+", column "+(a.column+1)+":

    "+"
      "+i.join("")+"
    "),f.innerHTML=h,p([".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #dd6666;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.line {","color: #ff0000;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),f.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),d.env=="development"&&(g=setInterval(function(){document.body&&(document.getElementById(c)?document.body.replaceChild(f,document.getElementById(c)):document.body.insertBefore(f,document.body.firstChild),clearInterval(g))},10))}typeof define=="function"&&define.amd&&define("less",[],function(){return d}),Array.isArray||(Array.isArray=function(a){return Object.prototype.toString.call(a)==="[object Array]"||a instanceof Array}),Array.prototype.forEach||(Array.prototype.forEach=function(a,b){var c=this.length>>>0;for(var d=0;d>>0,c=new Array(b),d=arguments[1];for(var e=0;e>>0,c=0;if(b===0&&arguments.length===1)throw new TypeError;if(arguments.length>=2)var d=arguments[1];else do{if(c in this){d=this[c++];break}if(++c>=b)throw new TypeError}while(!0);for(;c=b)return-1;c<0&&(c+=b);for(;cl&&(k[g]=k[g].slice(f-l),l=f)}function t(a){var c,d,e,h,i,j,n,o;if(a instanceof Function)return a.call(m.parsers);if(typeof a=="string")c=b.charAt(f)===a?a:null,e=1,s();else{s();if(c=a.exec(k[g]))e=c[0].length;else return null}if(c){o=f+=e,j=f+k[g].length-e;while(f=0&&b.charAt(c)!=="\n";c--)d++;return{line:typeof a=="number"?(b.slice(0,a).match(/\n/g)||"").length:null,column:d}}function A(a,b){var c=y(a,b),d=z(a.index,c),e=d.line,f=d.column,g=c.split("\n");this.type=a.type||"Syntax",this.message=a.message,this.filename=a.filename||b.filename,this.index=a.index,this.line=typeof e=="number"?e+1:null,this.callLine=a.call&&z(a.call,c).line+1,this.callExtract=g[z(a.call,c).line],this.stack=a.stack,this.column=f,this.extract=[g[e-1],g[e],g[e+1]]}var b,f,g,h,i,j,k,l,m,n=this,o=function(){},p=this.imports={paths:a&&a.paths||[],queue:[],files:{},contents:{},mime:a&&a.mime,error:null,push:function(b,c){var e=this;this.queue.push(b),d.Parser.importer(b,this.paths,function(a,d,f){e.queue.splice(e.queue.indexOf(b),1),e.files[b]=d,e.contents[b]=f,a&&!e.error&&(e.error=a),c(a,d),e.queue.length===0&&o()},a)}};return this.env=a=a||{},this.optimization="optimization"in this.env?this.env.optimization:1,this.env.filename=this.env.filename||null,m={imports:p,parse:function(h,i){var n,p,q,r,s,u,v=[],w,x=null;f=g=l=j=0,b=h.replace(/\r\n/g,"\n"),k=function(c){var d=0,e=/[^"'`\{\}\/\(\)\\]+/g,f=/\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,g=/"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`\\\r\n]|\\.)*)`/g,h=0,i,j=c[0],k;for(var l=0,m,n;l0&&(x=new A({index:l,type:"Parse",message:"missing closing `}`",filename:a.filename},a)),c.map(function(a){return a.join("")})}([[]]);if(x)return i(x);try{n=new e.Ruleset([],t(this.parsers.primary)),n.root=!0}catch(y){return i(new A(y,a))}n.toCSS=function(b){var f,g,h;return function(f,g){var h=[],i;f=f||{},typeof g=="object"&&!Array.isArray(g)&&(g=Object.keys(g).map(function(a){var b=g[a];return b instanceof e.Value||(b instanceof e.Expression||(b=new e.Expression([b])),b=new e.Value([b])),new e.Rule("@"+a,b,!1,0)}),h=[new e.Ruleset(null,g)]);try{var j=b.call(this,{frames:h}).toCSS([],{compress:f.compress||!1})}catch(k){throw new A(k,a)}if(i=m.imports.error)throw i instanceof A?i:new A(i,a);return f.yuicompress&&d.mode==="node"?c("./cssmin").compressor.cssmin(j):f.compress?j.replace(/(\s)+/g,"$1"):j}}(n.eval);if(f=0&&b.charAt(z)!=="\n";z--)B++;x={type:"Parse",message:"Syntax Error on line "+s,index:f,filename:a.filename,line:s,column:B,extract:[u[s-2],u[s-1],u[s]]}}this.imports.queue.length>0?o=function(){i(x,n)}:i(x,n)},parsers:{primary:function(){var a,b=[];while((a=t(this.mixin.definition)||t(this.rule)||t(this.ruleset)||t(this.mixin.call)||t(this.comment)||t(this.directive))||t(/^[\s\n]+/))a&&b.push(a);return b},comment:function(){var a;if(b.charAt(f)!=="/")return;if(b.charAt(f+1)==="/")return new e.Comment(t(/^\/\/.*/),!0);if(a=t(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/))return new e.Comment(a)},entities:{quoted:function(){var a,c=f,d;b.charAt(c)==="~"&&(c++,d=!0);if(b.charAt(c)!=='"'&&b.charAt(c)!=="'")return;d&&t("~");if(a=t(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/))return new e.Quoted(a[0],a[1]||a[2],d)},keyword:function(){var a;if(a=t(/^[_A-Za-z-][_A-Za-z0-9-]*/))return e.colors.hasOwnProperty(a)?new e.Color(e.colors[a].slice(1)):new e.Keyword(a)},call:function(){var b,c,d=f;if(!(b=/^([\w-]+|%|progid:[\w\.]+)\(/.exec(k[g])))return;b=b[1].toLowerCase();if(b==="url")return null;f+=b.length;if(b==="alpha")return t(this.alpha);t("("),c=t(this.entities.arguments);if(!t(")"))return;if(b)return new e.Call(b,c,d,a.filename)},arguments:function(){var a=[],b;while(b=t(this.entities.assignment)||t(this.expression)){a.push(b);if(!t(","))break}return a},literal:function(){return t(this.entities.dimension)||t(this.entities.color)||t(this.entities.quoted)},assignment:function(){var a,b;if((a=t(/^\w+(?=\s?=)/i))&&t("=")&&(b=t(this.entity)))return new e.Assignment(a,b)},url:function(){var a;if(b.charAt(f)!=="u"||!t(/^url\(/))return;return a=t(this.entities.quoted)||t(this.entities.variable)||t(this.entities.dataURI)||t(/^[-\w%@$\/.&=:;#+?~]+/)||"",u(")"),new e.URL(a.value||a.data||a instanceof e.Variable?a:new e.Anonymous(a),p.paths)},dataURI:function(){var a;if(t(/^data:/)){a={},a.mime=t(/^[^\/]+\/[^,;)]+/)||"",a.charset=t(/^;\s*charset=[^,;)]+/)||"",a.base64=t(/^;\s*base64/)||"",a.data=t(/^,\s*[^)]+/);if(a.data)return a}},variable:function(){var c,d=f;if(b.charAt(f)==="@"&&(c=t(/^@@?[\w-]+/)))return new e.Variable(c,d,a.filename)},color:function(){var a;if(b.charAt(f)==="#"&&(a=t(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/)))return new e.Color(a[1])},dimension:function(){var a,c=b.charCodeAt(f);if(c>57||c<45||c===47)return;if(a=t(/^(-?\d*\.?\d+)(px|%|em|rem|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/))return new e.Dimension(a[1],a[2])},javascript:function(){var a,c=f,d;b.charAt(c)==="~"&&(c++,d=!0);if(b.charAt(c)!=="`")return;d&&t("~");if(a=t(/^`([^`]*)`/))return new e.JavaScript(a[1],f,d)}},variable:function(){var a;if(b.charAt(f)==="@"&&(a=t(/^(@[\w-]+)\s*:/)))return a[1]},shorthand:function(){var a,b;if(!w(/^[@\w.%-]+\/[@\w.-]+/))return;if((a=t(this.entity))&&t("/")&&(b=t(this.entity)))return new e.Shorthand(a,b)},mixin:{call:function(){var c=[],d,g,h,i=f,j=b.charAt(f),k=!1;if(j!=="."&&j!=="#")return;while(d=t(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/))c.push(new e.Element(g,d,f)),g=t(">");t("(")&&(h=t(this.entities.arguments))&&t(")"),t(this.important)&&(k=!0);if(c.length>0&&(t(";")||w("}")))return new e.mixin.Call(c,h||[],i,a.filename,k)},definition:function(){var a,c=[],d,g,h,i,j,k=!1;if(b.charAt(f)!=="."&&b.charAt(f)!=="#"||w(/^[^{]*(;|})/))return;q();if(d=t(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)){a=d[1];do{if(b.charAt(f)==="."&&t(/^\.{3}/)){k=!0;break}if(!(h=t(this.entities.variable)||t(this.entities.literal)||t(this.entities.keyword)))break;if(h instanceof e.Variable)if(t(":"))i=u(this.expression,"expected expression"),c.push({name:h.name,value:i});else{if(t(/^\.{3}/)){c.push({name:h.name,variadic:!0}),k=!0;break}c.push({name:h.name})}else c.push({value:h})}while(t(","));u(")"),t(/^when/)&&(j=u(this.conditions,"expected condition")),g=t(this.block);if(g)return new e.mixin.Definition(a,c,g,j,k);r()}}},entity:function(){return t(this.entities.literal)||t(this.entities.variable)||t(this.entities.url)||t(this.entities.call)||t(this.entities.keyword)||t(this.entities.javascript)||t(this.comment)},end:function(){return t(";")||w("}")},alpha:function(){var a;if(!t(/^\(opacity=/i))return;if(a=t(/^\d+/)||t(this.entities.variable))return u(")"),new e.Alpha(a)},element:function(){var a,b,c,d;c=t(this.combinator),a=t(/^(?:\d+\.\d+|\d+)%/)||t(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)||t("*")||t(this.attribute)||t(/^\([^)@]+\)/),a||t("(")&&(d=t(this.entities.variable))&&t(")")&&(a=new e.Paren(d));if(a)return new e.Element(c,a,f);if(c.value&&c.value.charAt(0)==="&")return new e.Element(c,null,f)},combinator:function(){var a,c=b.charAt(f);if(c===">"||c==="+"||c==="~"){f++;while(b.charAt(f)===" ")f++;return new e.Combinator(c)}if(c==="&"){a="&",f++,b.charAt(f)===" "&&(a="& ");while(b.charAt(f)===" ")f++;return new e.Combinator(a)}return b.charAt(f-1)===" "?new e.Combinator(" "):new e.Combinator(null)},selector:function(){var a,c,d=[],g,h;if(t("("))return a=t(this.entity),u(")"),new e.Selector([new e.Element("",a,f)]);while(c=t(this.element)){g=b.charAt(f),d.push(c);if(g==="{"||g==="}"||g===";"||g===",")break}if(d.length>0)return new e.Selector(d)},tag:function(){return t(/^[a-zA-Z][a-zA-Z-]*[0-9]?/)||t("*")},attribute:function(){var a="",b,c,d;if(!t("["))return;if(b=t(/^[a-zA-Z-]+/)||t(this.entities.quoted))(d=t(/^[|~*$^]?=/))&&(c=t(this.entities.quoted)||t(/^[\w-]+/))?a=[b,d,c.toCSS?c.toCSS():c].join(""):a=b;if(!t("]"))return;if(a)return"["+a+"]"},block:function(){var a;if(t("{")&&(a=t(this.primary))&&t("}"))return a},ruleset:function(){var b=[],c,d,g;q();while(c=t(this.selector)){b.push(c),t(this.comment);if(!t(","))break;t(this.comment)}if(b.length>0&&(d=t(this.block)))return new e.Ruleset(b,d,a.strictImports);j=f,r()},rule:function(){var a,c,d=b.charAt(f),h,l;q();if(d==="."||d==="#"||d==="&")return;if(a=t(this.variable)||t(this.property)){a.charAt(0)!="@"&&(l=/^([^@+\/'"*`(;{}-]*);/.exec(k[g]))?(f+=l[0].length-1,c=new e.Anonymous(l[1])):a==="font"?c=t(this.font):c=t(this.value),h=t(this.important);if(c&&t(this.end))return new e.Rule(a,c,h,i);j=f,r()}},"import":function(){var a,b,c=f;if(t(/^@import\s+/)&&(a=t(this.entities.quoted)||t(this.entities.url))){b=t(this.mediaFeatures);if(t(";"))return new e.Import(a,p,b,c)}},mediaFeature:function(){var a,b,c=[];do if(a=t(this.entities.keyword))c.push(a);else if(t("(")){b=t(this.property),a=t(this.entity);if(!t(")"))return null;if(b&&a)c.push(new e.Paren(new e.Rule(b,a,null,f,!0)));else if(a)c.push(new e.Paren(a));else return null}while(a);if(c.length>0)return new e.Expression(c)},mediaFeatures:function(){var a,b=[];do if(a=t(this.mediaFeature)){b.push(a);if(!t(","))break}else if(a=t(this.entities.variable)){b.push(a);if(!t(","))break}while(a);return b.length>0?b:null},media:function(){var a,b;if(t(/^@media/)){a=t(this.mediaFeatures);if(b=t(this.block))return new e.Media(b,a)}},directive:function(){var a,c,d,g,h,i;if(b.charAt(f)!=="@")return;if(c=t(this["import"])||t(this.media))return c;if(a=t(/^@page|@keyframes/)||t(/^@(?:-webkit-|-moz-|-o-|-ms-)[a-z0-9-]+/)){g=(t(/^[^{]+/)||"").trim();if(d=t(this.block))return new e.Directive(a+" "+g,d)}else if(a=t(/^@[-a-z]+/))if(a==="@font-face"){if(d=t(this.block))return new e.Directive(a,d)}else if((c=t(this.entity))&&t(";"))return new e.Directive(a,c)},font:function(){var a=[],b=[],c,d,f,g;while(g=t(this.shorthand)||t(this.entity))b.push(g);a.push(new e.Expression(b));if(t(","))while(g=t(this.expression)){a.push(g);if(!t(","))break}return new e.Value(a)},value:function(){var a,b=[],c;while(a=t(this.expression)){b.push(a);if(!t(","))break}if(b.length>0)return new e.Value(b)},important:function(){if(b.charAt(f)==="!")return t(/^! *important/)},sub:function(){var a;if(t("(")&&(a=t(this.expression))&&t(")"))return a},multiplication:function(){var a,b,c,d;if(a=t(this.operand)){while(!w(/^\/\*/)&&(c=t("/")||t("*"))&&(b=t(this.operand)))d=new e.Operation(c,[d||a,b]);return d||a}},addition:function(){var a,c,d,g;if(a=t(this.multiplication)){while((d=t(/^[-+]\s+/)||b.charAt(f-1)!=" "&&(t("+")||t("-")))&&(c=t(this.multiplication)))g=new e.Operation(d,[g||a,c]);return g||a}},conditions:function(){var a,b,c=f,d;if(a=t(this.condition)){while(t(",")&&(b=t(this.condition)))d=new e.Condition("or",d||a,b,c);return d||a}},condition:function(){var a,b,c,d,g=f,h=!1;t(/^not/)&&(h=!0),u("(");if(a=t(this.addition)||t(this.entities.keyword)||t(this.entities.quoted))return(d=t(/^(?:>=|=<|[<=>])/))?(b=t(this.addition)||t(this.entities.keyword)||t(this.entities.quoted))?c=new e.Condition(d,a,b,g,h):v("expected expression"):c=new e.Condition("=",a,new e.Keyword("true"),g,h),u(")"),t(/^and/)?new e.Condition("and",c,t(this.condition)):c},operand:function(){var a,c=b.charAt(f+1);b.charAt(f)==="-"&&(c==="@"||c==="(")&&(a=t("-"));var d=t(this.sub)||t(this.entities.dimension)||t(this.entities.color)||t(this.entities.variable)||t(this.entities.call);return a?new e.Operation("*",[new e.Dimension(-1),d]):d},expression:function(){var a,b,c=[],d;while(a=t(this.addition)||t(this.entity))c.push(a);if(c.length>0)return new e.Expression(c)},property:function(){var a;if(a=t(/^(\*?-?[-a-z_0-9]+)\s*:/))return a[1]}}}};if(d.mode==="browser"||d.mode==="rhino")d.Parser.importer=function(a,b,c,d){!/^([a-z]+:)?\//.test(a)&&b.length>0&&(a=b[0]+a),n({href:a,title:a,type:d.mime},function(e){e&&typeof d.errback=="function"?d.errback.call(null,a,b,c,d):c.apply(null,arguments)},!0)};(function(a){function b(b){return a.functions.hsla(b.h,b.s,b.l,b.a)}function c(b){if(b instanceof a.Dimension)return parseFloat(b.unit=="%"?b.value/100:b.value);if(typeof b=="number")return b;throw{error:"RuntimeError",message:"color functions take numbers as parameters"}}function d(a){return Math.min(1,Math.max(0,a))}a.functions={rgb:function(a,b,c){return this.rgba(a,b,c,1)},rgba:function(b,d,e,f){var g=[b,d,e].map(function(a){return c(a)}),f=c(f);return new a.Color(g,f)},hsl:function(a,b,c){return this.hsla(a,b,c,1)},hsla:function(a,b,d,e){function h(a){return a=a<0?a+1:a>1?a-1:a,a*6<1?g+(f-g)*a*6:a*2<1?f:a*3<2?g+(f-g)*(2/3-a)*6:g}a=c(a)%360/360,b=c(b),d=c(d),e=c(e);var f=d<=.5?d*(b+1):d+b-d*b,g=d*2-f;return this.rgba(h(a+1/3)*255,h(a)*255,h(a-1/3)*255,e)},hue:function(b){return new a.Dimension(Math.round(b.toHSL().h))},saturation:function(b){return new a.Dimension(Math.round(b.toHSL().s*100),"%")},lightness:function(b){return new a.Dimension(Math.round(b.toHSL().l*100),"%")},alpha:function(b){return new a.Dimension(b.toHSL().a)},saturate:function(a,c){var e=a.toHSL();return e.s+=c.value/100,e.s=d(e.s),b(e)},desaturate:function(a,c){var e=a.toHSL();return e.s-=c.value/100,e.s=d(e.s),b(e)},lighten:function(a,c){var e=a.toHSL();return e.l+=c.value/100,e.l=d(e.l),b(e)},darken:function(a,c){var e=a.toHSL();return e.l-=c.value/100,e.l=d(e.l),b(e)},fadein:function(a,c){var e=a.toHSL();return e.a+=c.value/100,e.a=d(e.a),b(e)},fadeout:function(a,c){var e=a.toHSL();return e.a-=c.value/100,e.a=d(e.a),b(e)},fade:function(a,c){var e=a.toHSL();return e.a=c.value/100,e.a=d(e.a),b(e)},spin:function(a,c){var d=a.toHSL(),e=(d.h+c.value)%360;return d.h=e<0?360+e:e,b(d)},mix:function(b,c,d){var e=d.value/100,f=e*2-1,g=b.toHSL().a-c.toHSL().a,h=((f*g==-1?f:(f+g)/(1+f*g))+1)/2,i=1-h,j=[b.rgb[0]*h+c.rgb[0]*i,b.rgb[1]*h+c.rgb[1]*i,b.rgb[2]*h+c.rgb[2]*i],k=b.alpha*e+c.alpha*(1-e);return new a.Color(j,k)},greyscale:function(b){return this.desaturate(b,new a.Dimension(100))},e:function(b){return new a.Anonymous(b instanceof a.JavaScript?b.evaluated:b)},escape:function(b){return new a.Anonymous(encodeURI(b.value).replace(/=/g,"%3D").replace(/:/g,"%3A").replace(/#/g,"%23").replace(/;/g,"%3B").replace(/\(/g,"%28").replace(/\)/g,"%29"))},"%":function(b){var c=Array.prototype.slice.call(arguments,1),d=b.value;for(var e=0;e255?255:a<0?0:a).toString(16),a.length===1?"0"+a:a}).join("")},operate:function(b,c){var d=[];c instanceof a.Color||(c=c.toColor());for(var e=0;e<3;e++)d[e]=a.operate(b,this.rgb[e],c.rgb[e]);return new a.Color(d,this.alpha+c.alpha)},toHSL:function(){var a=this.rgb[0]/255,b=this.rgb[1]/255,c=this.rgb[2]/255,d=this.alpha,e=Math.max(a,b,c),f=Math.min(a,b,c),g,h,i=(e+f)/2,j=e-f;if(e===f)g=h=0;else{h=i>.5?j/(2-e-f):j/(e+f);switch(e){case a:g=(b-c)/j+(b255?255:a<0?0:a).toString(16),a.length===1?"0"+a:a}).join("")}}}(c("../tree")),function(a){a.Comment=function(a,b){this.value=a,this.silent=!!b},a.Comment.prototype={toCSS:function(a){return a.compress?"":this.value},eval:function(){return this}}}(c("../tree")),function(a){a.Condition=function(a,b,c,d,e){this.op=a.trim(),this.lvalue=b,this.rvalue=c,this.index=d,this.negate=e},a.Condition.prototype.eval=function(a){var b=this.lvalue.eval(a),c=this.rvalue.eval(a),d=this.index,e,e=function(a){switch(a){case"and":return b&&c;case"or":return b||c;default:if(b.compare)e=b.compare(c);else if(c.compare)e=c.compare(b);else throw{type:"Type",message:"Unable to perform comparison",index:d};switch(e){case-1:return a==="<"||a==="=<";case 0:return a==="="||a===">="||a==="=<";case 1:return a===">"||a===">="}}}(this.op);return this.negate?!e:e}}(c("../tree")),function(a){a.Dimension=function(a,b){this.value=parseFloat(a),this.unit=b||null},a.Dimension.prototype={eval:function(){return this},toColor:function(){return new a.Color([this.value,this.value,this.value])},toCSS:function(){var a=this.value+this.unit;return a},operate:function(b,c){return new a.Dimension(a.operate(b,this.value,c.value),this.unit||c.unit)},compare:function(b){return b instanceof a.Dimension?b.value>this.value?-1:b.value":a.compress?">":" > "}[this.value]}}(c("../tree")),function(a){a.Expression=function(a){this.value=a},a.Expression.prototype={eval:function(b){return this.value.length>1?new a.Expression(this.value.map(function(a){return a.eval(b)})):this.value.length===1?this.value[0].eval(b):this},toCSS:function(a){return this.value.map(function(b){return b.toCSS?b.toCSS(a):""}).join(" ")}}}(c("../tree")),function(a){a.Import=function(b,c,d,e){var f=this;this.index=e,this._path=b,this.features=d&&new a.Value(d),b instanceof a.Quoted?this.path=/\.(le?|c)ss(\?.*)?$/.test(b.value)?b.value:b.value+".less":this.path=b.value.value||b.value,this.css=/css(\?.*)?$/.test(this.path),this.css||c.push(this.path,function(b,c){b&&(b.index=e),f.root=c||new a.Ruleset([],[])})},a.Import.prototype={toCSS:function(a){var b=this.features?" "+this.features.toCSS(a):"";return this.css?"@import "+this._path.toCSS()+b+";\n":""},eval:function(b){var c,d=this.features&&this.features.eval(b);if(this.css)return this;c=new a.Ruleset([],this.root.rules.slice(0));for(var e=0;e1){var d=new a.Element("&",null,0),e=[new a.Selector([d])];c=new a.Ruleset(e,b.mediaBlocks),c.multiMedia=!0}return delete b.mediaBlocks,delete b.mediaPath,c},evalNested:function(b){var c,d,e=b.mediaPath.concat([this]);for(c=0;c0;c--)b.splice(c,0,new a.Anonymous("and"));return new a.Expression(b)})),new a.Ruleset([],[])},permute:function(a){if(a.length===0)return[];if(a.length===1)return a[0];var b=[],c=this.permute(a.slice(1));for(var d=0;d0){c=this.arguments&&this.arguments.map(function(b){return b.eval(a)});for(var g=0;gthis.params.length)return!1;if(this.required>0&&c>this.params.length)return!1}if(this.condition&&!this.condition.eval({frames:[this.evalParams(b,a)].concat(b.frames)}))return!1;d=Math.min(c,this.arity);for(var f=0;fe.selectors[g].elements.length?Array.prototype.push.apply(d,e.find(new a.Selector(b.elements.slice(1)),c)):d.push(e);break}}),this._lookups[g]=d)},toCSS:function(b,c){var d=[],e=[],f=[],g=[],h,i;this.root||(b.length===0?g=this.selectors.map(function(a){return[a]}):this.joinSelectors(g,b,this.selectors));for(var j=0;j0&&(h=g.map(function(a){return a.map(function(a){return a.toCSS(c)}).join("").trim()}).join(c.compress?",":",\n"),d.push(h,(c.compress?"{":" {\n ")+e.join(c.compress?"":"\n ")+(c.compress?"}":"\n}\n"))),d.push(f),d.join("")+(c.compress?"\n":"")},joinSelectors:function(a,b,c){for(var d=0;d0&&e.push(new a.Selector(g)),h.length>0&&f.push(new a.Selector(h));for(var l=0;l0&&(b.value=c[0]+(b.value.charAt(0)==="/"?b.value.slice(1):b.value)),this.value=b,this.paths=c)},b.URL.prototype={toCSS:function(){return"url("+(this.attrs?"data:"+this.attrs.mime+this.attrs.charset+this.attrs.base64+this.attrs.data:this.value.toCSS())+")"},eval:function(a){return this.attrs?this:new b.URL(this.value.eval(a),this.paths)}}}(c("../tree")),function(a){a.Value=function(a){this.value=a,this.is="value"},a.Value.prototype={eval:function(b){return this.value.length===1?this.value[0].eval(b):new a.Value(this.value.map(function(a){return a.eval(b)}))},toCSS:function(a){return this.value.map(function(b){return b.toCSS(a)}).join(a.compress?",":", ")}}}(c("../tree")),function(a){a.Variable=function(a,b,c){this.name=a,this.index=b,this.file=c},a.Variable.prototype={eval:function(b){var c,d,e=this.name;e.indexOf("@@")==0&&(e="@"+(new a.Variable(e.slice(1))).eval(b).value);if(c=a.find(b.frames,function(a){if(d=a.variable(e))return d.value.eval(b)}))return c;throw{type:"Name",message:"variable "+e+" is undefined",filename:this.file,index:this.index}}}}(c("../tree")),function(a){a.find=function(a,b){for(var c=0,d;c1?"["+a.value.map(function(a){return a.toCSS(!1)}).join(", ")+"]":a.toCSS(!1)}}(c("./tree"));var f=location.protocol==="file:"||location.protocol==="chrome:"||location.protocol==="chrome-extension:"||location.protocol==="resource:";d.env=d.env||(location.hostname=="127.0.0.1"||location.hostname=="0.0.0.0"||location.hostname=="localhost"||location.port.length>0||f?"development":"production"),d.async=!1,d.poll=d.poll||(f?1e3:1500),d.watch=function(){return this.watchMode=!0},d.unwatch=function(){return this.watchMode=!1},d.env==="development"?(d.optimization=0,/!watch/.test(location.hash)&&d.watch(),d.watchTimer=setInterval(function(){d.watchMode&&m(function(a,b,c,d,e){b&&p(b.toCSS(),d,e.lastModified)})},d.poll)):d.optimization=3;var g;try{g=typeof a.localStorage=="undefined"?null:a.localStorage}catch(h){g=null}var i=document.getElementsByTagName("link"),j=/^text\/(x-)?less$/;d.sheets=[];for(var k=0;k current) { + chunks[j] = chunks[j].slice(i - current); + current = i; + } + } + function isWhitespace(c) { + // Could change to \s? + var code = c.charCodeAt(0); + return code === 32 || code === 10 || code === 9; + } + // + // Parse from a token, regexp or string, and move forward if match + // + function $(tok) { + var match, args, length, index, k; + + // + // Non-terminal + // + if (tok instanceof Function) { + return tok.call(parser.parsers); + // + // Terminal + // + // Either match a single character in the input, + // or match a regexp in the current chunk (chunk[j]). + // + } else if (typeof(tok) === 'string') { + match = input.charAt(i) === tok ? tok : null; + length = 1; + sync (); + } else { + sync (); + + if (match = tok.exec(chunks[j])) { + length = match[0].length; + } else { + return null; + } + } + + // The match is confirmed, add the match length to `i`, + // and consume any extra white-space characters (' ' || '\n') + // which come after that. The reason for this is that LeSS's + // grammar is mostly white-space insensitive. + // + if (match) { + skipWhitespace(length); + + if(typeof(match) === 'string') { + return match; + } else { + return match.length === 1 ? match[0] : match; + } + } + } + + function skipWhitespace(length) { + var oldi = i, oldj = j, + endIndex = i + chunks[j].length, + mem = i += length; + + while (i < endIndex) { + if (! isWhitespace(input.charAt(i))) { break } + i++; + } + chunks[j] = chunks[j].slice(length + (i - mem)); + current = i; + + if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } + + return oldi !== i || oldj !== j; + } + + function expect(arg, msg) { + var result = $(arg); + if (! result) { + error(msg || (typeof(arg) === 'string' ? "expected '" + arg + "' got '" + input.charAt(i) + "'" + : "unexpected token")); + } else { + return result; + } + } + + function error(msg, type) { + var e = new Error(msg); + e.index = i; + e.type = type || 'Syntax'; + throw e; + } + + // Same as $(), but don't change the state of the parser, + // just return the match. + function peek(tok) { + if (typeof(tok) === 'string') { + return input.charAt(i) === tok; + } else { + if (tok.test(chunks[j])) { + return true; + } else { + return false; + } + } + } + + function getInput(e, env) { + if (e.filename && env.currentFileInfo.filename && (e.filename !== env.currentFileInfo.filename)) { + return parser.imports.contents[e.filename]; + } else { + return input; + } + } + + function getLocation(index, input) { + for (var n = index, column = -1; + n >= 0 && input.charAt(n) !== '\n'; + n--) { column++ } + + return { line: typeof(index) === 'number' ? (input.slice(0, index).match(/\n/g) || "").length : null, + column: column }; + } + + function getDebugInfo(index, inputStream, env) { + var filename = env.currentFileInfo.filename; + if(less.mode !== 'browser' && less.mode !== 'rhino') { + filename = require('path').resolve(filename); + } + + return { + lineNumber: getLocation(index, inputStream).line + 1, + fileName: filename + }; + } + + function LessError(e, env) { + var input = getInput(e, env), + loc = getLocation(e.index, input), + line = loc.line, + col = loc.column, + lines = input.split('\n'); + + this.type = e.type || 'Syntax'; + this.message = e.message; + this.filename = e.filename || env.currentFileInfo.filename; + this.index = e.index; + this.line = typeof(line) === 'number' ? line + 1 : null; + this.callLine = e.call && (getLocation(e.call, input).line + 1); + this.callExtract = lines[getLocation(e.call, input).line]; + this.stack = e.stack; + this.column = col; + this.extract = [ + lines[line - 1], + lines[line], + lines[line + 1] + ]; + } + + LessError.prototype = new Error(); + LessError.prototype.constructor = LessError; + + this.env = env = env || {}; + + // The optimization level dictates the thoroughness of the parser, + // the lower the number, the less nodes it will create in the tree. + // This could matter for debugging, or if you want to access + // the individual nodes in the tree. + this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; + + // + // The Parser + // + return parser = { + + imports: imports, + // + // Parse an input string into an abstract syntax tree, + // call `callback` when done. + // + parse: function (str, callback) { + var root, start, end, zone, line, lines, buff = [], c, error = null; + + i = j = current = furthest = 0; + input = str.replace(/\r\n/g, '\n'); + + // Remove potential UTF Byte Order Mark + input = input.replace(/^\uFEFF/, ''); + + // Split the input into chunks. + chunks = (function (chunks) { + var j = 0, + skip = /(?:@\{[\w-]+\}|[^"'`\{\}\/\(\)\\])+/g, + comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, + string = /"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`]|\\.)*)`/g, + level = 0, + match, + chunk = chunks[0], + inParam; + + for (var i = 0, c, cc; i < input.length;) { + skip.lastIndex = i; + if (match = skip.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + } + } + c = input.charAt(i); + comment.lastIndex = string.lastIndex = i; + + if (match = string.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + continue; + } + } + + if (!inParam && c === '/') { + cc = input.charAt(i + 1); + if (cc === '/' || cc === '*') { + if (match = comment.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + continue; + } + } + } + } + + switch (c) { + case '{': if (! inParam) { level ++; chunk.push(c); break } + case '}': if (! inParam) { level --; chunk.push(c); chunks[++j] = chunk = []; break } + case '(': if (! inParam) { inParam = true; chunk.push(c); break } + case ')': if ( inParam) { inParam = false; chunk.push(c); break } + default: chunk.push(c); + } + + i++; + } + if (level != 0) { + error = new(LessError)({ + index: i-1, + type: 'Parse', + message: (level > 0) ? "missing closing `}`" : "missing opening `{`", + filename: env.currentFileInfo.filename + }, env); + } + + return chunks.map(function (c) { return c.join('') });; + })([[]]); + + if (error) { + return callback(new(LessError)(error, env)); + } + + // Start with the primary rule. + // The whole syntax tree is held under a Ruleset node, + // with the `root` property set to true, so no `{}` are + // output. The callback is called when the input is parsed. + try { + root = new(tree.Ruleset)([], $(this.parsers.primary)); + root.root = true; + root.firstRoot = true; + } catch (e) { + return callback(new(LessError)(e, env)); + } + + root.toCSS = (function (evaluate) { + var line, lines, column; + + return function (options, variables) { + options = options || {}; + var importError, + evalEnv = new tree.evalEnv(options); + + // + // Allows setting variables with a hash, so: + // + // `{ color: new(tree.Color)('#f01') }` will become: + // + // new(tree.Rule)('@color', + // new(tree.Value)([ + // new(tree.Expression)([ + // new(tree.Color)('#f01') + // ]) + // ]) + // ) + // + if (typeof(variables) === 'object' && !Array.isArray(variables)) { + variables = Object.keys(variables).map(function (k) { + var value = variables[k]; + + if (! (value instanceof tree.Value)) { + if (! (value instanceof tree.Expression)) { + value = new(tree.Expression)([value]); + } + value = new(tree.Value)([value]); + } + return new(tree.Rule)('@' + k, value, false, 0); + }); + evalEnv.frames = [new(tree.Ruleset)(null, variables)]; + } + + try { + var evaldRoot = evaluate.call(this, evalEnv); + + new(tree.joinSelectorVisitor)() + .run(evaldRoot); + + new(tree.processExtendsVisitor)() + .run(evaldRoot); + + var css = evaldRoot.toCSS({ + compress: Boolean(options.compress), + dumpLineNumbers: env.dumpLineNumbers, + strictUnits: Boolean(options.strictUnits)}); + } catch (e) { + throw new(LessError)(e, env); + } + + if (options.yuicompress && less.mode === 'node') { + return require('ycssmin').cssmin(css, options.maxLineLen); + } else if (options.compress) { + return css.replace(/(\s)+/g, "$1"); + } else { + return css; + } + }; + })(root.eval); + + // If `i` is smaller than the `input.length - 1`, + // it means the parser wasn't able to parse the whole + // string, so we've got a parsing error. + // + // We try to extract a \n delimited string, + // showing the line where the parse error occured. + // We split it up into two parts (the part which parsed, + // and the part which didn't), so we can color them differently. + if (i < input.length - 1) { + i = furthest; + lines = input.split('\n'); + line = (input.slice(0, i).match(/\n/g) || "").length + 1; + + for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } + + error = { + type: "Parse", + message: "Unrecognised input", + index: i, + filename: env.currentFileInfo.filename, + line: line, + column: column, + extract: [ + lines[line - 2], + lines[line - 1], + lines[line] + ] + }; + } + + var finish = function (e) { + e = error || e || parser.imports.error; + + if (e) { + if (!(e instanceof LessError)) { + e = new(LessError)(e, env); + } + + callback(e); + } + else { + callback(null, root); + } + }; + + if (env.processImports !== false) { + new tree.importVisitor(this.imports, finish) + .run(root); + } else { + finish(); + } + }, + + // + // Here in, the parsing rules/functions + // + // The basic structure of the syntax tree generated is as follows: + // + // Ruleset -> Rule -> Value -> Expression -> Entity + // + // Here's some LESS code: + // + // .class { + // color: #fff; + // border: 1px solid #000; + // width: @w + 4px; + // > .child {...} + // } + // + // And here's what the parse tree might look like: + // + // Ruleset (Selector '.class', [ + // Rule ("color", Value ([Expression [Color #fff]])) + // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) + // Ruleset (Selector [Element '>', '.child'], [...]) + // ]) + // + // In general, most rules will try to parse a token with the `$()` function, and if the return + // value is truly, will return a new node, of the relevant type. Sometimes, we need to check + // first, before parsing, that's when we use `peek()`. + // + parsers: { + // + // The `primary` rule is the *entry* and *exit* point of the parser. + // The rules here can appear at any level of the parse tree. + // + // The recursive nature of the grammar is an interplay between the `block` + // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, + // as represented by this simplified grammar: + // + // primary → (ruleset | rule)+ + // ruleset → selector+ block + // block → '{' primary '}' + // + // Only at one point is the primary rule not called from the + // block rule: at the root level. + // + primary: function () { + var node, root = []; + + while ((node = $(this.extendRule) || $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || + $(this.mixin.call) || $(this.comment) || $(this.directive)) + || $(/^[\s\n]+/) || $(/^;+/)) { + node && root.push(node); + } + return root; + }, + + // We create a Comment node for CSS comments `/* */`, + // but keep the LeSS comments `//` silent, by just skipping + // over them. + comment: function () { + var comment; + + if (input.charAt(i) !== '/') return; + + if (input.charAt(i + 1) === '/') { + return new(tree.Comment)($(/^\/\/.*/), true); + } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { + return new(tree.Comment)(comment); + } + }, + + // + // Entities are tokens which can be found inside an Expression + // + entities: { + // + // A string, which supports escaping " and ' + // + // "milky way" 'he\'s the one!' + // + quoted: function () { + var str, j = i, e, index = i; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; + + e && $('~'); + + if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { + return new(tree.Quoted)(str[0], str[1] || str[2], e, index, env.currentFileInfo); + } + }, + + // + // A catch-all word, such as: + // + // black border-collapse + // + keyword: function () { + var k; + + if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) { + if (tree.colors.hasOwnProperty(k)) { + // detect named color + return new(tree.Color)(tree.colors[k].slice(1)); + } else { + return new(tree.Keyword)(k); + } + } + }, + + // + // A function call + // + // rgb(255, 0, 255) + // + // We also try to catch IE's `alpha()`, but let the `alpha` parser + // deal with the details. + // + // The arguments are parsed with the `entities.arguments` parser. + // + call: function () { + var name, nameLC, args, alpha_ret, index = i; + + if (! (name = /^([\w-]+|%|progid:[\w\.]+)\(/.exec(chunks[j]))) return; + + name = name[1]; + nameLC = name.toLowerCase(); + + if (nameLC === 'url') { return null } + else { i += name.length } + + if (nameLC === 'alpha') { + alpha_ret = $(this.alpha); + if(typeof alpha_ret !== 'undefined') { + return alpha_ret; + } + } + + $('('); // Parse the '(' and consume whitespace. + + args = $(this.entities.arguments); + + if (! $(')')) { + return; + } + + if (name) { return new(tree.Call)(name, args, index, env.currentFileInfo); } + }, + arguments: function () { + var args = [], arg; + + while (arg = $(this.entities.assignment) || $(this.expression)) { + args.push(arg); + if (! $(',')) { break } + } + return args; + }, + literal: function () { + return $(this.entities.dimension) || + $(this.entities.color) || + $(this.entities.quoted) || + $(this.entities.unicodeDescriptor); + }, + + // Assignments are argument entities for calls. + // They are present in ie filter properties as shown below. + // + // filter: progid:DXImageTransform.Microsoft.Alpha( *opacity=50* ) + // + + assignment: function () { + var key, value; + if ((key = $(/^\w+(?=\s?=)/i)) && $('=') && (value = $(this.entity))) { + return new(tree.Assignment)(key, value); + } + }, + + // + // Parse url() tokens + // + // We use a specific rule for urls, because they don't really behave like + // standard function calls. The difference is that the argument doesn't have + // to be enclosed within a string, so it can't be parsed as an Expression. + // + url: function () { + var value; + + if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; + value = $(this.entities.quoted) || $(this.entities.variable) || + $(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/) || ""; + + expect(')'); + + return new(tree.URL)((value.value != null || value instanceof tree.Variable) + ? value : new(tree.Anonymous)(value), env.currentFileInfo); + }, + + // + // A Variable entity, such as `@fink`, in + // + // width: @fink + 2px + // + // We use a different parser for variable definitions, + // see `parsers.variable`. + // + variable: function () { + var name, index = i; + + if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { + return new(tree.Variable)(name, index, env.currentFileInfo); + } + }, + + // A variable entity useing the protective {} e.g. @{var} + variableCurly: function () { + var name, curly, index = i; + + if (input.charAt(i) === '@' && (curly = $(/^@\{([\w-]+)\}/))) { + return new(tree.Variable)("@" + curly[1], index, env.currentFileInfo); + } + }, + + // + // A Hexadecimal color + // + // #4F3C2F + // + // `rgb` and `hsl` colors are parsed through the `entities.call` parser. + // + color: function () { + var rgb; + + if (input.charAt(i) === '#' && (rgb = $(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/))) { + return new(tree.Color)(rgb[1]); + } + }, + + // + // A Dimension, that is, a number and a unit + // + // 0.5em 95% + // + dimension: function () { + var value, c = input.charCodeAt(i); + //Is the first char of the dimension 0-9, '.', '+' or '-' + if ((c > 57 || c < 43) || c === 47 || c == 44) return; + + if (value = $(/^([+-]?\d*\.?\d+)(%|[a-z]+)?/)) { + return new(tree.Dimension)(value[1], value[2]); + } + }, + + // + // A unicode descriptor, as is used in unicode-range + // + // U+0?? or U+00A1-00A9 + // + unicodeDescriptor: function () { + var ud; + + if (ud = $(/^U\+[0-9a-fA-F?]+(\-[0-9a-fA-F?]+)?/)) { + return new(tree.UnicodeDescriptor)(ud[0]); + } + }, + + // + // JavaScript code to be evaluated + // + // `window.location.href` + // + javascript: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '`') { return } + + e && $('~'); + + if (str = $(/^`([^`]*)`/)) { + return new(tree.JavaScript)(str[1], i, e); + } + } + }, + + // + // The variable part of a variable definition. Used in the `rule` parser + // + // @fink: + // + variable: function () { + var name; + + if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } + }, + + // + // extend syntax - used to extend selectors + // + extend: function(isRule) { + var elements, e, index = i, option, extendList = []; + + if (!$(isRule ? /^&:extend\(/ : /^:extend\(/)) { return; } + + do { + option = null; + elements = []; + while (true) { + option = $(/^(all)(?=\s*(\)|,))/); + if (option) { break; } + e = $(this.element); + if (!e) { break; } + elements.push(e); + } + + option = option && option[1]; + + extendList.push(new(tree.Extend)(new(tree.Selector)(elements), option, index)); + + } while($(",")) + + expect(/^\)/); + + if (isRule) { + expect(/^;/); + } + + return extendList; + }, + + // + // extendRule - used in a rule to extend all the parent selectors + // + extendRule: function() { + return this.extend(true); + }, + + // + // Mixins + // + mixin: { + // + // A Mixin call, with an optional argument list + // + // #mixins > .square(#fff); + // .rounded(4px, black); + // .button; + // + // The `while` loop is there because mixins can be + // namespaced, but we only support the child and descendant + // selector for now. + // + call: function () { + var elements = [], e, c, args, delim, arg, index = i, s = input.charAt(i), important = false; + + if (s !== '.' && s !== '#') { return } + + save(); // stop us absorbing part of an invalid selector + + while (e = $(/^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/)) { + elements.push(new(tree.Element)(c, e, i)); + c = $('>'); + } + if ($('(')) { + args = this.mixin.args.call(this, true).args; + expect(')'); + } + + args = args || []; + + if ($(this.important)) { + important = true; + } + + if (elements.length > 0 && ($(';') || peek('}'))) { + return new(tree.mixin.Call)(elements, args, index, env.currentFileInfo, important); + } + + restore(); + }, + args: function (isCall) { + var expressions = [], argsSemiColon = [], isSemiColonSeperated, argsComma = [], expressionContainsNamed, name, nameLoop, value, arg, + returner = {args:null, variadic: false}; + while (true) { + if (isCall) { + arg = $(this.expression); + } else { + $(this.comment); + if (input.charAt(i) === '.' && $(/^\.{3}/)) { + returner.variadic = true; + if ($(";") && !isSemiColonSeperated) { + isSemiColonSeperated = true; + } + (isSemiColonSeperated ? argsSemiColon : argsComma) + .push({ variadic: true }); + break; + } + arg = $(this.entities.variable) || $(this.entities.literal) + || $(this.entities.keyword); + } + + if (!arg) { + break; + } + + nameLoop = null; + if (arg.throwAwayComments) { + arg.throwAwayComments(); + } + value = arg; + var val = null; + + if (isCall) { + // Variable + if (arg.value.length == 1) { + var val = arg.value[0]; + } + } else { + val = arg; + } + + if (val && val instanceof tree.Variable) { + if ($(':')) { + if (expressions.length > 0) { + if (isSemiColonSeperated) { + error("Cannot mix ; and , as delimiter types"); + } + expressionContainsNamed = true; + } + value = expect(this.expression); + nameLoop = (name = val.name); + } else if (!isCall && $(/^\.{3}/)) { + returner.variadic = true; + if ($(";") && !isSemiColonSeperated) { + isSemiColonSeperated = true; + } + (isSemiColonSeperated ? argsSemiColon : argsComma) + .push({ name: arg.name, variadic: true }); + break; + } else if (!isCall) { + name = nameLoop = val.name; + value = null; + } + } + + if (value) { + expressions.push(value); + } + + argsComma.push({ name:nameLoop, value:value }); + + if ($(',')) { + continue; + } + + if ($(';') || isSemiColonSeperated) { + + if (expressionContainsNamed) { + error("Cannot mix ; and , as delimiter types"); + } + + isSemiColonSeperated = true; + + if (expressions.length > 1) { + value = new (tree.Value)(expressions); + } + argsSemiColon.push({ name:name, value:value }); + + name = null; + expressions = []; + expressionContainsNamed = false; + } + } + + returner.args = isSemiColonSeperated ? argsSemiColon : argsComma; + return returner; + }, + // + // A Mixin definition, with a list of parameters + // + // .rounded (@radius: 2px, @color) { + // ... + // } + // + // Until we have a finer grained state-machine, we have to + // do a look-ahead, to make sure we don't have a mixin call. + // See the `rule` function for more information. + // + // We start by matching `.rounded (`, and then proceed on to + // the argument list, which has optional default values. + // We store the parameters in `params`, with a `value` key, + // if there is a value, such as in the case of `@radius`. + // + // Once we've got our params list, and a closing `)`, we parse + // the `{...}` block. + // + definition: function () { + var name, params = [], match, ruleset, param, value, cond, variadic = false; + if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || + peek(/^[^{]*\}/)) return; + + save(); + + if (match = $(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/)) { + name = match[1]; + + var argInfo = this.mixin.args.call(this, false); + params = argInfo.args; + variadic = argInfo.variadic; + + // .mixincall("@{a}"); + // looks a bit like a mixin definition.. so we have to be nice and restore + if (!$(')')) { + furthest = i; + restore(); + } + + $(this.comment); + + if ($(/^when/)) { // Guard + cond = expect(this.conditions, 'expected condition'); + } + + ruleset = $(this.block); + + if (ruleset) { + return new(tree.mixin.Definition)(name, params, ruleset, cond, variadic); + } else { + restore(); + } + } + } + }, + + // + // Entities are the smallest recognized token, + // and can be found inside a rule's value. + // + entity: function () { + return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || + $(this.entities.call) || $(this.entities.keyword) ||$(this.entities.javascript) || + $(this.comment); + }, + + // + // A Rule terminator. Note that we use `peek()` to check for '}', + // because the `block` rule will be expecting it, but we still need to make sure + // it's there, if ';' was ommitted. + // + end: function () { + return $(';') || peek('}'); + }, + + // + // IE's alpha function + // + // alpha(opacity=88) + // + alpha: function () { + var value; + + if (! $(/^\(opacity=/i)) return; + if (value = $(/^\d+/) || $(this.entities.variable)) { + expect(')'); + return new(tree.Alpha)(value); + } + }, + + // + // A Selector Element + // + // div + // + h1 + // #socks + // input[type="text"] + // + // Elements are the building blocks for Selectors, + // they are made out of a `Combinator` (see combinator rule), + // and an element name, such as a tag a class, or `*`. + // + element: function () { + var e, t, c, v; + + c = $(this.combinator); + + e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/) || + $('*') || $('&') || $(this.attribute) || $(/^\([^()@]+\)/) || $(/^[\.#](?=@)/) || $(this.entities.variableCurly); + + if (! e) { + if ($('(')) { + if ((v = ($(this.selector))) && + $(')')) { + e = new(tree.Paren)(v); + } + } + } + + if (e) { return new(tree.Element)(c, e, i) } + }, + + // + // Combinators combine elements together, in a Selector. + // + // Because our parser isn't white-space sensitive, special care + // has to be taken, when parsing the descendant combinator, ` `, + // as it's an empty space. We have to check the previous character + // in the input, to see if it's a ` ` character. More info on how + // we deal with this in *combinator.js*. + // + combinator: function () { + var c = input.charAt(i); + + if (c === '>' || c === '+' || c === '~' || c === '|') { + i++; + while (input.charAt(i).match(/\s/)) { i++ } + return new(tree.Combinator)(c); + } else if (input.charAt(i - 1).match(/\s/)) { + return new(tree.Combinator)(" "); + } else { + return new(tree.Combinator)(null); + } + }, + + // + // A CSS Selector + // + // .class > div + h1 + // li a:hover + // + // Selectors are made out of one or more Elements, see above. + // + selector: function () { + var sel, e, elements = [], c, extend, extendList = []; + + while ((extend = $(this.extend)) || (e = $(this.element))) { + if (extend) { + extendList.push.apply(extendList, extend); + } else { + if (extendList.length) { + error("Extend can only be used at the end of selector"); + } + c = input.charAt(i); + elements.push(e) + e = null; + } + if (c === '{' || c === '}' || c === ';' || c === ',' || c === ')') { break } + } + + if (elements.length > 0) { return new(tree.Selector)(elements, extendList); } + if (extendList.length) { error("Extend must be used to extend a selector, it cannot be used on its own"); } + }, + attribute: function () { + var attr = '', key, val, op; + + if (! $('[')) return; + + if (!(key = $(this.entities.variableCurly))) { + key = expect(/^(?:[_A-Za-z0-9-\*]*\|)?(?:[_A-Za-z0-9-]|\\.)+/); + } + + if ((op = $(/^[|~*$^]?=/))) { + val = $(this.entities.quoted) || $(/^[\w-]+/) || $(this.entities.variableCurly); + } + + expect(']'); + + return new(tree.Attribute)(key, op, val); + }, + + // + // The `block` rule is used by `ruleset` and `mixin.definition`. + // It's a wrapper around the `primary` rule, with added `{}`. + // + block: function () { + var content; + if ($('{') && (content = $(this.primary)) && $('}')) { + return content; + } + }, + + // + // div, .class, body > p {...} + // + ruleset: function () { + var selectors = [], s, rules, debugInfo; + + save(); + + if (env.dumpLineNumbers) + debugInfo = getDebugInfo(i, input, env); + + while (s = $(this.selector)) { + selectors.push(s); + $(this.comment); + if (! $(',')) { break } + $(this.comment); + } + + if (selectors.length > 0 && (rules = $(this.block))) { + var ruleset = new(tree.Ruleset)(selectors, rules, env.strictImports); + if (env.dumpLineNumbers) + ruleset.debugInfo = debugInfo; + return ruleset; + } else { + // Backtrack + furthest = i; + restore(); + } + }, + rule: function (tryAnonymous) { + var name, value, c = input.charAt(i), important; + save(); + + if (c === '.' || c === '#' || c === '&') { return } + + if (name = $(this.variable) || $(this.property)) { + // prefer to try to parse first if its a variable or we are compressing + // but always fallback on the other one + value = !tryAnonymous && (env.compress || (name.charAt(0) === '@')) ? + ($(this.value) || $(this.anonymousValue)) : + ($(this.anonymousValue) || $(this.value)); + + important = $(this.important); + + if (value && $(this.end)) { + return new(tree.Rule)(name, value, important, memo, env.currentFileInfo); + } else { + furthest = i; + restore(); + if (value && !tryAnonymous) { + return this.rule(true); + } + } + } + }, + anonymousValue: function () { + var match; + if (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j])) { + i += match[0].length - 1; + return new(tree.Anonymous)(match[1]); + } + }, + + // + // An @import directive + // + // @import "lib"; + // + // Depending on our environemnt, importing is done differently: + // In the browser, it's an XHR request, in Node, it would be a + // file-system operation. The function used for importing is + // stored in `import`, which we pass to the Import constructor. + // + "import": function () { + var path, features, index = i; + + save(); + + var dir = $(/^@import?\s+/); + + var options = (dir ? $(this.importOptions) : null) || {}; + + if (dir && (path = $(this.entities.quoted) || $(this.entities.url))) { + features = $(this.mediaFeatures); + if ($(';')) { + features = features && new(tree.Value)(features); + return new(tree.Import)(path, features, options, index, env.currentFileInfo); + } + } + + restore(); + }, + + importOptions: function() { + var o, options = {}, optionName, value; + + // list of options, surrounded by parens + if (! $('(')) { return null; } + do { + if (o = $(this.importOption)) { + optionName = o; + value = true; + switch(optionName) { + case "css": + optionName = "less"; + value = false; + break; + case "once": + optionName = "multiple"; + value = false; + break; + } + options[optionName] = value; + if (! $(',')) { break } + } + } while (o); + expect(')'); + return options; + }, + + importOption: function() { + var opt = $(/^(less|css|multiple|once)/); + if (opt) { + return opt[1]; + } + }, + + mediaFeature: function () { + var e, p, nodes = []; + + do { + if (e = $(this.entities.keyword)) { + nodes.push(e); + } else if ($('(')) { + p = $(this.property); + e = $(this.value); + if ($(')')) { + if (p && e) { + nodes.push(new(tree.Paren)(new(tree.Rule)(p, e, null, i, env.currentFileInfo, true))); + } else if (e) { + nodes.push(new(tree.Paren)(e)); + } else { + return null; + } + } else { return null } + } + } while (e); + + if (nodes.length > 0) { + return new(tree.Expression)(nodes); + } + }, + + mediaFeatures: function () { + var e, features = []; + + do { + if (e = $(this.mediaFeature)) { + features.push(e); + if (! $(',')) { break } + } else if (e = $(this.entities.variable)) { + features.push(e); + if (! $(',')) { break } + } + } while (e); + + return features.length > 0 ? features : null; + }, + + media: function () { + var features, rules, media, debugInfo; + + if (env.dumpLineNumbers) + debugInfo = getDebugInfo(i, input, env); + + if ($(/^@media/)) { + features = $(this.mediaFeatures); + + if (rules = $(this.block)) { + media = new(tree.Media)(rules, features); + if(env.dumpLineNumbers) + media.debugInfo = debugInfo; + return media; + } + } + }, + + // + // A CSS Directive + // + // @charset "utf-8"; + // + directive: function () { + var name, value, rules, identifier, e, nodes, nonVendorSpecificName, + hasBlock, hasIdentifier, hasExpression; + + if (input.charAt(i) !== '@') return; + + if (value = $(this['import']) || $(this.media)) { + return value; + } + + save(); + + name = $(/^@[a-z-]+/); + + if (!name) return; + + nonVendorSpecificName = name; + if (name.charAt(1) == '-' && name.indexOf('-', 2) > 0) { + nonVendorSpecificName = "@" + name.slice(name.indexOf('-', 2) + 1); + } + + switch(nonVendorSpecificName) { + case "@font-face": + hasBlock = true; + break; + case "@viewport": + case "@top-left": + case "@top-left-corner": + case "@top-center": + case "@top-right": + case "@top-right-corner": + case "@bottom-left": + case "@bottom-left-corner": + case "@bottom-center": + case "@bottom-right": + case "@bottom-right-corner": + case "@left-top": + case "@left-middle": + case "@left-bottom": + case "@right-top": + case "@right-middle": + case "@right-bottom": + hasBlock = true; + break; + case "@page": + case "@document": + case "@supports": + case "@keyframes": + hasBlock = true; + hasIdentifier = true; + break; + case "@namespace": + hasExpression = true; + break; + } + + if (hasIdentifier) { + name += " " + ($(/^[^{]+/) || '').trim(); + } + + if (hasBlock) + { + if (rules = $(this.block)) { + return new(tree.Directive)(name, rules); + } + } else { + if ((value = hasExpression ? $(this.expression) : $(this.entity)) && $(';')) { + var directive = new(tree.Directive)(name, value); + if (env.dumpLineNumbers) { + directive.debugInfo = getDebugInfo(i, input, env); + } + return directive; + } + } + + restore(); + }, + + // + // A Value is a comma-delimited list of Expressions + // + // font-family: Baskerville, Georgia, serif; + // + // In a Rule, a Value represents everything after the `:`, + // and before the `;`. + // + value: function () { + var e, expressions = [], important; + + while (e = $(this.expression)) { + expressions.push(e); + if (! $(',')) { break } + } + + if (expressions.length > 0) { + return new(tree.Value)(expressions); + } + }, + important: function () { + if (input.charAt(i) === '!') { + return $(/^! *important/); + } + }, + sub: function () { + var a, e; + + if ($('(')) { + if (a = $(this.addition)) { + e = new(tree.Expression)([a]); + expect(')'); + e.parens = true; + return e; + } + } + }, + multiplication: function () { + var m, a, op, operation, isSpaced, expression = []; + if (m = $(this.operand)) { + isSpaced = isWhitespace(input.charAt(i - 1)); + while (!peek(/^\/[*\/]/) && (op = ($('/') || $('*')))) { + if (a = $(this.operand)) { + m.parensInOp = true; + a.parensInOp = true; + operation = new(tree.Operation)(op, [operation || m, a], isSpaced); + isSpaced = isWhitespace(input.charAt(i - 1)); + } else { + break; + } + } + return operation || m; + } + }, + addition: function () { + var m, a, op, operation, isSpaced; + if (m = $(this.multiplication)) { + isSpaced = isWhitespace(input.charAt(i - 1)); + while ((op = $(/^[-+]\s+/) || (!isSpaced && ($('+') || $('-')))) && + (a = $(this.multiplication))) { + m.parensInOp = true; + a.parensInOp = true; + operation = new(tree.Operation)(op, [operation || m, a], isSpaced); + isSpaced = isWhitespace(input.charAt(i - 1)); + } + return operation || m; + } + }, + conditions: function () { + var a, b, index = i, condition; + + if (a = $(this.condition)) { + while ($(',') && (b = $(this.condition))) { + condition = new(tree.Condition)('or', condition || a, b, index); + } + return condition || a; + } + }, + condition: function () { + var a, b, c, op, index = i, negate = false; + + if ($(/^not/)) { negate = true } + expect('('); + if (a = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + if (op = $(/^(?:>=|=<|[<=>])/)) { + if (b = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + c = new(tree.Condition)(op, a, b, index, negate); + } else { + error('expected expression'); + } + } else { + c = new(tree.Condition)('=', a, new(tree.Keyword)('true'), index, negate); + } + expect(')'); + return $(/^and/) ? new(tree.Condition)('and', c, $(this.condition)) : c; + } + }, + + // + // An operand is anything that can be part of an operation, + // such as a Color, or a Variable + // + operand: function () { + var negate, p = input.charAt(i + 1); + + if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } + var o = $(this.sub) || $(this.entities.dimension) || + $(this.entities.color) || $(this.entities.variable) || + $(this.entities.call); + + if (negate) { + o.parensInOp = true; + o = new(tree.Negative)(o); + } + + return o; + }, + + // + // Expressions either represent mathematical operations, + // or white-space delimited Entities. + // + // 1px solid black + // @var * 2 + // + expression: function () { + var e, delim, entities = [], d; + + while (e = $(this.addition) || $(this.entity)) { + entities.push(e); + // operations do not allow keyword "/" dimension (e.g. small/20px) so we support that here + if (!peek(/^\/[\/*]/) && (delim = $('/'))) { + entities.push(new(tree.Anonymous)(delim)); + } + } + if (entities.length > 0) { + return new(tree.Expression)(entities); + } + }, + property: function () { + var name; + + if (name = $(/^(\*?-?[_a-zA-Z0-9-]+)\s*:/)) { + return name[1]; + } + } + } + }; +}; + +if (less.mode === 'browser' || less.mode === 'rhino') { + // + // Used by `@import` directives + // + less.Parser.importer = function (path, currentFileInfo, callback, env) { + if (!/^([a-z-]+:)?\//.test(path) && currentFileInfo.currentDirectory) { + path = currentFileInfo.currentDirectory + path; + } + var sheetEnv = env.toSheet(path); + sheetEnv.processImports = false; + sheetEnv.currentFileInfo = currentFileInfo; + + // We pass `true` as 3rd argument, to force the reload of the import. + // This is so we can get the syntax tree as opposed to just the CSS output, + // as we need this to evaluate the current stylesheet. + loadStyleSheet(sheetEnv, + function (e, root, data, sheet, _, path) { + callback.call(null, e, root, path); + }, true); + }; +} + +(function (tree) { + +tree.functions = { + rgb: function (r, g, b) { + return this.rgba(r, g, b, 1.0); + }, + rgba: function (r, g, b, a) { + var rgb = [r, g, b].map(function (c) { return scaled(c, 256); }); + a = number(a); + return new(tree.Color)(rgb, a); + }, + hsl: function (h, s, l) { + return this.hsla(h, s, l, 1.0); + }, + hsla: function (h, s, l, a) { + h = (number(h) % 360) / 360; + s = clamp(number(s)); l = clamp(number(l)); a = clamp(number(a)); + + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; + + return this.rgba(hue(h + 1/3) * 255, + hue(h) * 255, + hue(h - 1/3) * 255, + a); + + function hue(h) { + h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); + if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; + else if (h * 2 < 1) return m2; + else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; + else return m1; + } + }, + + hsv: function(h, s, v) { + return this.hsva(h, s, v, 1.0); + }, + + hsva: function(h, s, v, a) { + h = ((number(h) % 360) / 360) * 360; + s = number(s); v = number(v); a = number(a); + + var i, f; + i = Math.floor((h / 60) % 6); + f = (h / 60) - i; + + var vs = [v, + v * (1 - s), + v * (1 - f * s), + v * (1 - (1 - f) * s)]; + var perm = [[0, 3, 1], + [2, 0, 1], + [1, 0, 3], + [1, 2, 0], + [3, 1, 0], + [0, 1, 2]]; + + return this.rgba(vs[perm[i][0]] * 255, + vs[perm[i][1]] * 255, + vs[perm[i][2]] * 255, + a); + }, + + hue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().h)); + }, + saturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); + }, + lightness: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); + }, + hsvhue: function(color) { + return new(tree.Dimension)(Math.round(color.toHSV().h)); + }, + hsvsaturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSV().s * 100), '%'); + }, + hsvvalue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSV().v * 100), '%'); + }, + red: function (color) { + return new(tree.Dimension)(color.rgb[0]); + }, + green: function (color) { + return new(tree.Dimension)(color.rgb[1]); + }, + blue: function (color) { + return new(tree.Dimension)(color.rgb[2]); + }, + alpha: function (color) { + return new(tree.Dimension)(color.toHSL().a); + }, + luma: function (color) { + return new(tree.Dimension)(Math.round(color.luma() * color.alpha * 100), '%'); + }, + saturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s += amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + desaturate: function (color, amount) { + var hsl = color.toHSL(); + + hsl.s -= amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + lighten: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l += amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + darken: function (color, amount) { + var hsl = color.toHSL(); + + hsl.l -= amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + fadein: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a += amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fadeout: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a -= amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fade: function (color, amount) { + var hsl = color.toHSL(); + + hsl.a = amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + spin: function (color, amount) { + var hsl = color.toHSL(); + var hue = (hsl.h + amount.value) % 360; + + hsl.h = hue < 0 ? 360 + hue : hue; + + return hsla(hsl); + }, + // + // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein + // http://sass-lang.com + // + mix: function (color1, color2, weight) { + if (!weight) { + weight = new(tree.Dimension)(50); + } + var p = weight.value / 100.0; + var w = p * 2 - 1; + var a = color1.toHSL().a - color2.toHSL().a; + + var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; + + var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, + color1.rgb[1] * w1 + color2.rgb[1] * w2, + color1.rgb[2] * w1 + color2.rgb[2] * w2]; + + var alpha = color1.alpha * p + color2.alpha * (1 - p); + + return new(tree.Color)(rgb, alpha); + }, + greyscale: function (color) { + return this.desaturate(color, new(tree.Dimension)(100)); + }, + contrast: function (color, dark, light, threshold) { + // filter: contrast(3.2); + // should be kept as is, so check for color + if (!color.rgb) { + return null; + } + if (typeof light === 'undefined') { + light = this.rgba(255, 255, 255, 1.0); + } + if (typeof dark === 'undefined') { + dark = this.rgba(0, 0, 0, 1.0); + } + //Figure out which is actually light and dark! + if (dark.luma() > light.luma()) { + var t = light; + light = dark; + dark = t; + } + if (typeof threshold === 'undefined') { + threshold = 0.43; + } else { + threshold = number(threshold); + } + if ((color.luma() * color.alpha) < threshold) { + return light; + } else { + return dark; + } + }, + e: function (str) { + return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); + }, + escape: function (str) { + return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); + }, + '%': function (quoted /* arg, arg, ...*/) { + var args = Array.prototype.slice.call(arguments, 1), + str = quoted.value; + + for (var i = 0; i < args.length; i++) { + str = str.replace(/%[sda]/i, function(token) { + var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); + return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; + }); + } + str = str.replace(/%%/g, '%'); + return new(tree.Quoted)('"' + str + '"', str); + }, + unit: function (val, unit) { + return new(tree.Dimension)(val.value, unit ? unit.toCSS() : ""); + }, + convert: function (val, unit) { + return val.convertTo(unit.value); + }, + round: function (n, f) { + var fraction = typeof(f) === "undefined" ? 0 : f.value; + return this._math(function(num) { return num.toFixed(fraction); }, null, n); + }, + pi: function () { + return new(tree.Dimension)(Math.PI); + }, + mod: function(a, b) { + return new(tree.Dimension)(a.value % b.value, a.unit); + }, + pow: function(x, y) { + if (typeof x === "number" && typeof y === "number") { + x = new(tree.Dimension)(x); + y = new(tree.Dimension)(y); + } else if (!(x instanceof tree.Dimension) || !(y instanceof tree.Dimension)) { + throw { type: "Argument", message: "arguments must be numbers" }; + } + + return new(tree.Dimension)(Math.pow(x.value, y.value), x.unit); + }, + _math: function (fn, unit, n) { + if (n instanceof tree.Dimension) { + return new(tree.Dimension)(fn(parseFloat(n.value)), unit == null ? n.unit : unit); + } else if (typeof(n) === 'number') { + return fn(n); + } else { + throw { type: "Argument", message: "argument must be a number" }; + } + }, + argb: function (color) { + return new(tree.Anonymous)(color.toARGB()); + + }, + percentage: function (n) { + return new(tree.Dimension)(n.value * 100, '%'); + }, + color: function (n) { + if (n instanceof tree.Quoted) { + return new(tree.Color)(n.value.slice(1)); + } else { + throw { type: "Argument", message: "argument must be a string" }; + } + }, + iscolor: function (n) { + return this._isa(n, tree.Color); + }, + isnumber: function (n) { + return this._isa(n, tree.Dimension); + }, + isstring: function (n) { + return this._isa(n, tree.Quoted); + }, + iskeyword: function (n) { + return this._isa(n, tree.Keyword); + }, + isurl: function (n) { + return this._isa(n, tree.URL); + }, + ispixel: function (n) { + return this.isunit(n, 'px'); + }, + ispercentage: function (n) { + return this.isunit(n, '%'); + }, + isem: function (n) { + return this.isunit(n, 'em'); + }, + isunit: function (n, unit) { + return (n instanceof tree.Dimension) && n.unit.is(unit.value || unit) ? tree.True : tree.False; + }, + _isa: function (n, Type) { + return (n instanceof Type) ? tree.True : tree.False; + }, + + /* Blending modes */ + + multiply: function(color1, color2) { + var r = color1.rgb[0] * color2.rgb[0] / 255; + var g = color1.rgb[1] * color2.rgb[1] / 255; + var b = color1.rgb[2] * color2.rgb[2] / 255; + return this.rgb(r, g, b); + }, + screen: function(color1, color2) { + var r = 255 - (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255; + var g = 255 - (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255; + var b = 255 - (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + overlay: function(color1, color2) { + var r = color1.rgb[0] < 128 ? 2 * color1.rgb[0] * color2.rgb[0] / 255 : 255 - 2 * (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255; + var g = color1.rgb[1] < 128 ? 2 * color1.rgb[1] * color2.rgb[1] / 255 : 255 - 2 * (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255; + var b = color1.rgb[2] < 128 ? 2 * color1.rgb[2] * color2.rgb[2] / 255 : 255 - 2 * (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + softlight: function(color1, color2) { + var t = color2.rgb[0] * color1.rgb[0] / 255; + var r = t + color1.rgb[0] * (255 - (255 - color1.rgb[0]) * (255 - color2.rgb[0]) / 255 - t) / 255; + t = color2.rgb[1] * color1.rgb[1] / 255; + var g = t + color1.rgb[1] * (255 - (255 - color1.rgb[1]) * (255 - color2.rgb[1]) / 255 - t) / 255; + t = color2.rgb[2] * color1.rgb[2] / 255; + var b = t + color1.rgb[2] * (255 - (255 - color1.rgb[2]) * (255 - color2.rgb[2]) / 255 - t) / 255; + return this.rgb(r, g, b); + }, + hardlight: function(color1, color2) { + var r = color2.rgb[0] < 128 ? 2 * color2.rgb[0] * color1.rgb[0] / 255 : 255 - 2 * (255 - color2.rgb[0]) * (255 - color1.rgb[0]) / 255; + var g = color2.rgb[1] < 128 ? 2 * color2.rgb[1] * color1.rgb[1] / 255 : 255 - 2 * (255 - color2.rgb[1]) * (255 - color1.rgb[1]) / 255; + var b = color2.rgb[2] < 128 ? 2 * color2.rgb[2] * color1.rgb[2] / 255 : 255 - 2 * (255 - color2.rgb[2]) * (255 - color1.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + difference: function(color1, color2) { + var r = Math.abs(color1.rgb[0] - color2.rgb[0]); + var g = Math.abs(color1.rgb[1] - color2.rgb[1]); + var b = Math.abs(color1.rgb[2] - color2.rgb[2]); + return this.rgb(r, g, b); + }, + exclusion: function(color1, color2) { + var r = color1.rgb[0] + color2.rgb[0] * (255 - color1.rgb[0] - color1.rgb[0]) / 255; + var g = color1.rgb[1] + color2.rgb[1] * (255 - color1.rgb[1] - color1.rgb[1]) / 255; + var b = color1.rgb[2] + color2.rgb[2] * (255 - color1.rgb[2] - color1.rgb[2]) / 255; + return this.rgb(r, g, b); + }, + average: function(color1, color2) { + var r = (color1.rgb[0] + color2.rgb[0]) / 2; + var g = (color1.rgb[1] + color2.rgb[1]) / 2; + var b = (color1.rgb[2] + color2.rgb[2]) / 2; + return this.rgb(r, g, b); + }, + negation: function(color1, color2) { + var r = 255 - Math.abs(255 - color2.rgb[0] - color1.rgb[0]); + var g = 255 - Math.abs(255 - color2.rgb[1] - color1.rgb[1]); + var b = 255 - Math.abs(255 - color2.rgb[2] - color1.rgb[2]); + return this.rgb(r, g, b); + }, + tint: function(color, amount) { + return this.mix(this.rgb(255,255,255), color, amount); + }, + shade: function(color, amount) { + return this.mix(this.rgb(0, 0, 0), color, amount); + }, + extract: function(values, index) { + index = index.value - 1; // (1-based index) + return values.value[index]; + }, + + "data-uri": function(mimetypeNode, filePathNode) { + + if (typeof window !== 'undefined') { + return new tree.URL(filePathNode || mimetypeNode, this.currentFileInfo).eval(this.env); + } + + var mimetype = mimetypeNode.value; + var filePath = (filePathNode && filePathNode.value); + + var fs = require("fs"), + path = require("path"), + useBase64 = false; + + if (arguments.length < 2) { + filePath = mimetype; + } + + if (this.env.isPathRelative(filePath)) { + if (this.currentFileInfo.relativeUrls) { + filePath = path.join(this.currentFileInfo.currentDirectory, filePath); + } else { + filePath = path.join(this.currentFileInfo.entryPath, filePath); + } + } + + // detect the mimetype if not given + if (arguments.length < 2) { + var mime; + try { + mime = require('mime'); + } catch (ex) { + mime = tree._mime; + } + + mimetype = mime.lookup(filePath); + + // use base 64 unless it's an ASCII or UTF-8 format + var charset = mime.charsets.lookup(mimetype); + useBase64 = ['US-ASCII', 'UTF-8'].indexOf(charset) < 0; + if (useBase64) mimetype += ';base64'; + } + else { + useBase64 = /;base64$/.test(mimetype) + } + + var buf = fs.readFileSync(filePath); + + // IE8 cannot handle a data-uri larger than 32KB. If this is exceeded + // and the --ieCompat flag is enabled, return a normal url() instead. + var DATA_URI_MAX_KB = 32, + fileSizeInKB = parseInt((buf.length / 1024), 10); + if (fileSizeInKB >= DATA_URI_MAX_KB) { + + if (this.env.ieCompat !== false) { + if (!this.env.silent) { + console.warn("Skipped data-uri embedding of %s because its size (%dKB) exceeds IE8-safe %dKB!", filePath, fileSizeInKB, DATA_URI_MAX_KB); + } + + return new tree.URL(filePathNode || mimetypeNode, this.currentFileInfo).eval(this.env); + } else if (!this.env.silent) { + // if explicitly disabled (via --no-ie-compat on CLI, or env.ieCompat === false), merely warn + console.warn("WARNING: Embedding %s (%dKB) exceeds IE8's data-uri size limit of %dKB!", filePath, fileSizeInKB, DATA_URI_MAX_KB); + } + } + + buf = useBase64 ? buf.toString('base64') + : encodeURIComponent(buf); + + var uri = "'data:" + mimetype + ',' + buf + "'"; + return new(tree.URL)(new(tree.Anonymous)(uri)); + } +}; + +// these static methods are used as a fallback when the optional 'mime' dependency is missing +tree._mime = { + // this map is intentionally incomplete + // if you want more, install 'mime' dep + _types: { + '.htm' : 'text/html', + '.html': 'text/html', + '.gif' : 'image/gif', + '.jpg' : 'image/jpeg', + '.jpeg': 'image/jpeg', + '.png' : 'image/png' + }, + lookup: function (filepath) { + var ext = require('path').extname(filepath), + type = tree._mime._types[ext]; + if (type === undefined) { + throw new Error('Optional dependency "mime" is required for ' + ext); + } + return type; + }, + charsets: { + lookup: function (type) { + // assumes all text types are UTF-8 + return type && (/^text\//).test(type) ? 'UTF-8' : ''; + } + } +}; + +var mathFunctions = [{name:"ceil"}, {name:"floor"}, {name: "sqrt"}, {name:"abs"}, + {name:"tan", unit: ""}, {name:"sin", unit: ""}, {name:"cos", unit: ""}, + {name:"atan", unit: "rad"}, {name:"asin", unit: "rad"}, {name:"acos", unit: "rad"}], + createMathFunction = function(name, unit) { + return function(n) { + if (unit != null) { + n = n.unify(); + } + return this._math(Math[name], unit, n); + }; + }; + +for(var i = 0; i < mathFunctions.length; i++) { + tree.functions[mathFunctions[i].name] = createMathFunction(mathFunctions[i].name, mathFunctions[i].unit); +} + +function hsla(color) { + return tree.functions.hsla(color.h, color.s, color.l, color.a); +} + +function scaled(n, size) { + if (n instanceof tree.Dimension && n.unit.is('%')) { + return parseFloat(n.value * size / 100); + } else { + return number(n); + } +} + +function number(n) { + if (n instanceof tree.Dimension) { + return parseFloat(n.unit.is('%') ? n.value / 100 : n.value); + } else if (typeof(n) === 'number') { + return n; + } else { + throw { + error: "RuntimeError", + message: "color functions take numbers as parameters" + }; + } +} + +function clamp(val) { + return Math.min(1, Math.max(0, val)); +} + +tree.functionCall = function(env, currentFileInfo) { + this.env = env; + this.currentFileInfo = currentFileInfo; +}; + +tree.functionCall.prototype = tree.functions; + +})(require('./tree')); +(function (tree) { + tree.colors = { + 'aliceblue':'#f0f8ff', + 'antiquewhite':'#faebd7', + 'aqua':'#00ffff', + 'aquamarine':'#7fffd4', + 'azure':'#f0ffff', + 'beige':'#f5f5dc', + 'bisque':'#ffe4c4', + 'black':'#000000', + 'blanchedalmond':'#ffebcd', + 'blue':'#0000ff', + 'blueviolet':'#8a2be2', + 'brown':'#a52a2a', + 'burlywood':'#deb887', + 'cadetblue':'#5f9ea0', + 'chartreuse':'#7fff00', + 'chocolate':'#d2691e', + 'coral':'#ff7f50', + 'cornflowerblue':'#6495ed', + 'cornsilk':'#fff8dc', + 'crimson':'#dc143c', + 'cyan':'#00ffff', + 'darkblue':'#00008b', + 'darkcyan':'#008b8b', + 'darkgoldenrod':'#b8860b', + 'darkgray':'#a9a9a9', + 'darkgrey':'#a9a9a9', + 'darkgreen':'#006400', + 'darkkhaki':'#bdb76b', + 'darkmagenta':'#8b008b', + 'darkolivegreen':'#556b2f', + 'darkorange':'#ff8c00', + 'darkorchid':'#9932cc', + 'darkred':'#8b0000', + 'darksalmon':'#e9967a', + 'darkseagreen':'#8fbc8f', + 'darkslateblue':'#483d8b', + 'darkslategray':'#2f4f4f', + 'darkslategrey':'#2f4f4f', + 'darkturquoise':'#00ced1', + 'darkviolet':'#9400d3', + 'deeppink':'#ff1493', + 'deepskyblue':'#00bfff', + 'dimgray':'#696969', + 'dimgrey':'#696969', + 'dodgerblue':'#1e90ff', + 'firebrick':'#b22222', + 'floralwhite':'#fffaf0', + 'forestgreen':'#228b22', + 'fuchsia':'#ff00ff', + 'gainsboro':'#dcdcdc', + 'ghostwhite':'#f8f8ff', + 'gold':'#ffd700', + 'goldenrod':'#daa520', + 'gray':'#808080', + 'grey':'#808080', + 'green':'#008000', + 'greenyellow':'#adff2f', + 'honeydew':'#f0fff0', + 'hotpink':'#ff69b4', + 'indianred':'#cd5c5c', + 'indigo':'#4b0082', + 'ivory':'#fffff0', + 'khaki':'#f0e68c', + 'lavender':'#e6e6fa', + 'lavenderblush':'#fff0f5', + 'lawngreen':'#7cfc00', + 'lemonchiffon':'#fffacd', + 'lightblue':'#add8e6', + 'lightcoral':'#f08080', + 'lightcyan':'#e0ffff', + 'lightgoldenrodyellow':'#fafad2', + 'lightgray':'#d3d3d3', + 'lightgrey':'#d3d3d3', + 'lightgreen':'#90ee90', + 'lightpink':'#ffb6c1', + 'lightsalmon':'#ffa07a', + 'lightseagreen':'#20b2aa', + 'lightskyblue':'#87cefa', + 'lightslategray':'#778899', + 'lightslategrey':'#778899', + 'lightsteelblue':'#b0c4de', + 'lightyellow':'#ffffe0', + 'lime':'#00ff00', + 'limegreen':'#32cd32', + 'linen':'#faf0e6', + 'magenta':'#ff00ff', + 'maroon':'#800000', + 'mediumaquamarine':'#66cdaa', + 'mediumblue':'#0000cd', + 'mediumorchid':'#ba55d3', + 'mediumpurple':'#9370d8', + 'mediumseagreen':'#3cb371', + 'mediumslateblue':'#7b68ee', + 'mediumspringgreen':'#00fa9a', + 'mediumturquoise':'#48d1cc', + 'mediumvioletred':'#c71585', + 'midnightblue':'#191970', + 'mintcream':'#f5fffa', + 'mistyrose':'#ffe4e1', + 'moccasin':'#ffe4b5', + 'navajowhite':'#ffdead', + 'navy':'#000080', + 'oldlace':'#fdf5e6', + 'olive':'#808000', + 'olivedrab':'#6b8e23', + 'orange':'#ffa500', + 'orangered':'#ff4500', + 'orchid':'#da70d6', + 'palegoldenrod':'#eee8aa', + 'palegreen':'#98fb98', + 'paleturquoise':'#afeeee', + 'palevioletred':'#d87093', + 'papayawhip':'#ffefd5', + 'peachpuff':'#ffdab9', + 'peru':'#cd853f', + 'pink':'#ffc0cb', + 'plum':'#dda0dd', + 'powderblue':'#b0e0e6', + 'purple':'#800080', + 'red':'#ff0000', + 'rosybrown':'#bc8f8f', + 'royalblue':'#4169e1', + 'saddlebrown':'#8b4513', + 'salmon':'#fa8072', + 'sandybrown':'#f4a460', + 'seagreen':'#2e8b57', + 'seashell':'#fff5ee', + 'sienna':'#a0522d', + 'silver':'#c0c0c0', + 'skyblue':'#87ceeb', + 'slateblue':'#6a5acd', + 'slategray':'#708090', + 'slategrey':'#708090', + 'snow':'#fffafa', + 'springgreen':'#00ff7f', + 'steelblue':'#4682b4', + 'tan':'#d2b48c', + 'teal':'#008080', + 'thistle':'#d8bfd8', + 'tomato':'#ff6347', + // 'transparent':'rgba(0,0,0,0)', + 'turquoise':'#40e0d0', + 'violet':'#ee82ee', + 'wheat':'#f5deb3', + 'white':'#ffffff', + 'whitesmoke':'#f5f5f5', + 'yellow':'#ffff00', + 'yellowgreen':'#9acd32' + }; +})(require('./tree')); +(function (tree) { + +tree.Alpha = function (val) { + this.value = val; +}; +tree.Alpha.prototype = { + type: "Alpha", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + eval: function (env) { + if (this.value.eval) { this.value = this.value.eval(env) } + return this; + }, + toCSS: function () { + return "alpha(opacity=" + + (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Anonymous = function (string) { + this.value = string.value || string; +}; +tree.Anonymous.prototype = { + type: "Anonymous", + toCSS: function () { + return this.value; + }, + eval: function () { return this }, + compare: function (x) { + if (!x.toCSS) { + return -1; + } + + var left = this.toCSS(), + right = x.toCSS(); + + if (left === right) { + return 0; + } + + return left < right ? -1 : 1; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Assignment = function (key, val) { + this.key = key; + this.value = val; +}; +tree.Assignment.prototype = { + type: "Assignment", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + toCSS: function () { + return this.key + '=' + (this.value.toCSS ? this.value.toCSS() : this.value); + }, + eval: function (env) { + if (this.value.eval) { + return new(tree.Assignment)(this.key, this.value.eval(env)); + } + return this; + } +}; + +})(require('../tree'));(function (tree) { + +// +// A function call node. +// +tree.Call = function (name, args, index, currentFileInfo) { + this.name = name; + this.args = args; + this.index = index; + this.currentFileInfo = currentFileInfo; +}; +tree.Call.prototype = { + type: "Call", + accept: function (visitor) { + this.args = visitor.visit(this.args); + }, + // + // When evaluating a function call, + // we either find the function in `tree.functions` [1], + // in which case we call it, passing the evaluated arguments, + // if this returns null or we cannot find the function, we + // simply print it out as it appeared originally [2]. + // + // The *functions.js* file contains the built-in functions. + // + // The reason why we evaluate the arguments, is in the case where + // we try to pass a variable to a function, like: `saturate(@color)`. + // The function should receive the value, not the variable. + // + eval: function (env) { + var args = this.args.map(function (a) { return a.eval(env); }), + nameLC = this.name.toLowerCase(), + result, func; + + if (nameLC in tree.functions) { // 1. + try { + func = new tree.functionCall(env, this.currentFileInfo); + result = func[nameLC].apply(func, args); + if (result != null) { + return result; + } + } catch (e) { + throw { type: e.type || "Runtime", + message: "error evaluating function `" + this.name + "`" + + (e.message ? ': ' + e.message : ''), + index: this.index, filename: this.currentFileInfo.filename }; + } + } + + // 2. + return new(tree.Anonymous)(this.name + + "(" + args.map(function (a) { return a.toCSS(env); }).join(', ') + ")"); + }, + + toCSS: function (env) { + return this.eval(env).toCSS(); + } +}; + +})(require('../tree')); +(function (tree) { +// +// RGB Colors - #ff0014, #eee +// +tree.Color = function (rgb, a) { + // + // The end goal here, is to parse the arguments + // into an integer triplet, such as `128, 255, 0` + // + // This facilitates operations and conversions. + // + if (Array.isArray(rgb)) { + this.rgb = rgb; + } else if (rgb.length == 6) { + this.rgb = rgb.match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else { + this.rgb = rgb.split('').map(function (c) { + return parseInt(c + c, 16); + }); + } + this.alpha = typeof(a) === 'number' ? a : 1; +}; +tree.Color.prototype = { + type: "Color", + eval: function () { return this }, + luma: function () { return (0.2126 * this.rgb[0] / 255) + (0.7152 * this.rgb[1] / 255) + (0.0722 * this.rgb[2] / 255); }, + + // + // If we have some transparency, the only way to represent it + // is via `rgba`. Otherwise, we use the hex representation, + // which has better compatibility with older browsers. + // Values are capped between `0` and `255`, rounded and zero-padded. + // + toCSS: function (env, doNotCompress) { + var compress = env && env.compress && !doNotCompress; + if (this.alpha < 1.0) { + return "rgba(" + this.rgb.map(function (c) { + return Math.round(c); + }).concat(this.alpha).join(',' + (compress ? '' : ' ')) + ")"; + } else { + var color = this.rgb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + + if (compress) { + color = color.split(''); + + // Convert color to short format + if (color[0] == color[1] && color[2] == color[3] && color[4] == color[5]) { + color = color[0] + color[2] + color[4]; + } else { + color = color.join(''); + } + } + + return '#' + color; + } + }, + + // + // Operations have to be done per-channel, if not, + // channels will spill onto each other. Once we have + // our result, in the form of an integer triplet, + // we create a new Color node to hold the result. + // + operate: function (env, op, other) { + var result = []; + + if (! (other instanceof tree.Color)) { + other = other.toColor(); + } + + for (var c = 0; c < 3; c++) { + result[c] = tree.operate(env, op, this.rgb[c], other.rgb[c]); + } + return new(tree.Color)(result, this.alpha + other.alpha); + }, + + toHSL: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2, d = max - min; + + if (max === min) { + h = s = 0; + } else { + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, l: l, a: a }; + }, + //Adapted from http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript + toHSV: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, v = max; + + var d = max - min; + if (max === 0) { + s = 0; + } else { + s = d / max; + } + + if (max === min) { + h = 0; + } else { + switch(max){ + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, v: v, a: a }; + }, + toARGB: function () { + var argb = [Math.round(this.alpha * 255)].concat(this.rgb); + return '#' + argb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + }, + compare: function (x) { + if (!x.rgb) { + return -1; + } + + return (x.rgb[0] === this.rgb[0] && + x.rgb[1] === this.rgb[1] && + x.rgb[2] === this.rgb[2] && + x.alpha === this.alpha) ? 0 : -1; + } +}; + + +})(require('../tree')); +(function (tree) { + +tree.Comment = function (value, silent) { + this.value = value; + this.silent = !!silent; +}; +tree.Comment.prototype = { + type: "Comment", + toCSS: function (env) { + return env.compress ? '' : this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.Condition = function (op, l, r, i, negate) { + this.op = op.trim(); + this.lvalue = l; + this.rvalue = r; + this.index = i; + this.negate = negate; +}; +tree.Condition.prototype = { + type: "Condition", + accept: function (visitor) { + this.lvalue = visitor.visit(this.lvalue); + this.rvalue = visitor.visit(this.rvalue); + }, + eval: function (env) { + var a = this.lvalue.eval(env), + b = this.rvalue.eval(env); + + var i = this.index, result; + + var result = (function (op) { + switch (op) { + case 'and': + return a && b; + case 'or': + return a || b; + default: + if (a.compare) { + result = a.compare(b); + } else if (b.compare) { + result = b.compare(a); + } else { + throw { type: "Type", + message: "Unable to perform comparison", + index: i }; + } + switch (result) { + case -1: return op === '<' || op === '=<'; + case 0: return op === '=' || op === '>=' || op === '=<'; + case 1: return op === '>' || op === '>='; + } + } + })(this.op); + return this.negate ? !result : result; + } +}; + +})(require('../tree')); +(function (tree) { + +// +// A number with a unit +// +tree.Dimension = function (value, unit) { + this.value = parseFloat(value); + this.unit = (unit && unit instanceof tree.Unit) ? unit : + new(tree.Unit)(unit ? [unit] : undefined); +}; + +tree.Dimension.prototype = { + type: "Dimension", + accept: function (visitor) { + this.unit = visitor.visit(this.unit); + }, + eval: function (env) { + return this; + }, + toColor: function () { + return new(tree.Color)([this.value, this.value, this.value]); + }, + toCSS: function (env) { + if ((env && env.strictUnits) && !this.unit.isSingular()) { + throw new Error("Multiple units in dimension. Correct the units or use the unit function. Bad unit: "+this.unit.toString()); + } + + var value = this.value, + strValue = String(value); + + if (value !== 0 && value < 0.000001 && value > -0.000001) { + // would be output 1e-6 etc. + strValue = value.toFixed(20).replace(/0+$/, ""); + } + + if (env && env.compress) { + // Zero values doesn't need a unit + if (value === 0 && !this.unit.isAngle()) { + return strValue; + } + + // Float values doesn't need a leading zero + if (value > 0 && value < 1) { + strValue = (strValue).substr(1); + } + } + + return strValue + this.unit.toCSS(env); + }, + + // In an operation between two Dimensions, + // we default to the first Dimension's unit, + // so `1px + 2` will yield `3px`. + operate: function (env, op, other) { + var value = tree.operate(env, op, this.value, other.value), + unit = this.unit.clone(); + + if (op === '+' || op === '-') { + if (unit.numerator.length === 0 && unit.denominator.length === 0) { + unit.numerator = other.unit.numerator.slice(0); + unit.denominator = other.unit.denominator.slice(0); + } else if (other.unit.numerator.length == 0 && unit.denominator.length == 0) { + // do nothing + } else { + other = other.convertTo(this.unit.usedUnits()); + + if(env.strictUnits && other.unit.toString() !== unit.toString()) { + throw new Error("Incompatible units. Change the units or use the unit function. Bad units: '" + unit.toString() + + "' and '" + other.unit.toString() + "'."); + } + + value = tree.operate(env, op, this.value, other.value); + } + } else if (op === '*') { + unit.numerator = unit.numerator.concat(other.unit.numerator).sort(); + unit.denominator = unit.denominator.concat(other.unit.denominator).sort(); + unit.cancel(); + } else if (op === '/') { + unit.numerator = unit.numerator.concat(other.unit.denominator).sort(); + unit.denominator = unit.denominator.concat(other.unit.numerator).sort(); + unit.cancel(); + } + return new(tree.Dimension)(value, unit); + }, + + compare: function (other) { + if (other instanceof tree.Dimension) { + var a = this.unify(), b = other.unify(), + aValue = a.value, bValue = b.value; + + if (bValue > aValue) { + return -1; + } else if (bValue < aValue) { + return 1; + } else { + if (!b.unit.isEmpty() && a.unit.compare(b.unit) !== 0) { + return -1; + } + return 0; + } + } else { + return -1; + } + }, + + unify: function () { + return this.convertTo({ length: 'm', duration: 's', angle: 'rad' }); + }, + + convertTo: function (conversions) { + var value = this.value, unit = this.unit.clone(), + i, groupName, group, conversion, targetUnit, derivedConversions = {}; + + if (typeof conversions === 'string') { + for(i in tree.UnitConversions) { + if (tree.UnitConversions[i].hasOwnProperty(conversions)) { + derivedConversions = {}; + derivedConversions[i] = conversions; + } + } + conversions = derivedConversions; + } + + for (groupName in conversions) { + if (conversions.hasOwnProperty(groupName)) { + targetUnit = conversions[groupName]; + group = tree.UnitConversions[groupName]; + + unit.map(function (atomicUnit, denominator) { + if (group.hasOwnProperty(atomicUnit)) { + if (denominator) { + value = value / (group[atomicUnit] / group[targetUnit]); + } else { + value = value * (group[atomicUnit] / group[targetUnit]); + } + + return targetUnit; + } + + return atomicUnit; + }); + } + } + + unit.cancel(); + + return new(tree.Dimension)(value, unit); + } +}; + +// http://www.w3.org/TR/css3-values/#absolute-lengths +tree.UnitConversions = { + length: { + 'm': 1, + 'cm': 0.01, + 'mm': 0.001, + 'in': 0.0254, + 'pt': 0.0254 / 72, + 'pc': 0.0254 / 72 * 12 + }, + duration: { + 's': 1, + 'ms': 0.001 + }, + angle: { + 'rad': 1/(2*Math.PI), + 'deg': 1/360, + 'grad': 1/400, + 'turn': 1 + } +}; + +tree.Unit = function (numerator, denominator, backupUnit) { + this.numerator = numerator ? numerator.slice(0).sort() : []; + this.denominator = denominator ? denominator.slice(0).sort() : []; + this.backupUnit = backupUnit; +}; + +tree.Unit.prototype = { + type: "Unit", + clone: function () { + return new tree.Unit(this.numerator.slice(0), this.denominator.slice(0), this.backupUnit); + }, + + toCSS: function (env) { + if (this.numerator.length >= 1) { + return this.numerator[0]; + } + if (this.denominator.length >= 1) { + return this.denominator[0]; + } + if ((!env || !env.strictUnits) && this.backupUnit) { + return this.backupUnit; + } + return ""; + }, + + toString: function () { + var i, returnStr = this.numerator.join("*"); + for (i = 0; i < this.denominator.length; i++) { + returnStr += "/" + this.denominator[i]; + } + return returnStr; + }, + + compare: function (other) { + return this.is(other.toString()) ? 0 : -1; + }, + + is: function (unitString) { + return this.toString() === unitString; + }, + + isAngle: function () { + return tree.UnitConversions.angle.hasOwnProperty(this.toCSS()); + }, + + isEmpty: function () { + return this.numerator.length == 0 && this.denominator.length == 0; + }, + + isSingular: function() { + return this.numerator.length <= 1 && this.denominator.length == 0; + }, + + map: function(callback) { + var i; + + for (i = 0; i < this.numerator.length; i++) { + this.numerator[i] = callback(this.numerator[i], false); + } + + for (i = 0; i < this.denominator.length; i++) { + this.denominator[i] = callback(this.denominator[i], true); + } + }, + + usedUnits: function() { + var group, groupName, result = {}; + + for (groupName in tree.UnitConversions) { + if (tree.UnitConversions.hasOwnProperty(groupName)) { + group = tree.UnitConversions[groupName]; + + this.map(function (atomicUnit) { + if (group.hasOwnProperty(atomicUnit) && !result[groupName]) { + result[groupName] = atomicUnit; + } + + return atomicUnit; + }); + } + } + + return result; + }, + + cancel: function () { + var counter = {}, atomicUnit, i, backup; + + for (i = 0; i < this.numerator.length; i++) { + atomicUnit = this.numerator[i]; + if (!backup) { + backup = atomicUnit; + } + counter[atomicUnit] = (counter[atomicUnit] || 0) + 1; + } + + for (i = 0; i < this.denominator.length; i++) { + atomicUnit = this.denominator[i]; + if (!backup) { + backup = atomicUnit; + } + counter[atomicUnit] = (counter[atomicUnit] || 0) - 1; + } + + this.numerator = []; + this.denominator = []; + + for (atomicUnit in counter) { + if (counter.hasOwnProperty(atomicUnit)) { + var count = counter[atomicUnit]; + + if (count > 0) { + for (i = 0; i < count; i++) { + this.numerator.push(atomicUnit); + } + } else if (count < 0) { + for (i = 0; i < -count; i++) { + this.denominator.push(atomicUnit); + } + } + } + } + + if (this.numerator.length === 0 && this.denominator.length === 0 && backup) { + this.backupUnit = backup; + } + + this.numerator.sort(); + this.denominator.sort(); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Directive = function (name, value) { + this.name = name; + + if (Array.isArray(value)) { + this.ruleset = new(tree.Ruleset)([], value); + this.ruleset.allowImports = true; + } else { + this.value = value; + } +}; +tree.Directive.prototype = { + type: "Directive", + accept: function (visitor) { + this.ruleset = visitor.visit(this.ruleset); + this.value = visitor.visit(this.value); + }, + toCSS: function (env) { + if (this.ruleset) { + this.ruleset.root = true; + return this.name + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + } else { + return this.name + ' ' + this.value.toCSS() + ';\n'; + } + }, + eval: function (env) { + var evaldDirective = this; + if (this.ruleset) { + env.frames.unshift(this); + evaldDirective = new(tree.Directive)(this.name); + evaldDirective.ruleset = this.ruleset.eval(env); + env.frames.shift(); + } + return evaldDirective; + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } +}; + +})(require('../tree')); +(function (tree) { + +tree.Element = function (combinator, value, index) { + this.combinator = combinator instanceof tree.Combinator ? + combinator : new(tree.Combinator)(combinator); + + if (typeof(value) === 'string') { + this.value = value.trim(); + } else if (value) { + this.value = value; + } else { + this.value = ""; + } + this.index = index; +}; +tree.Element.prototype = { + type: "Element", + accept: function (visitor) { + this.combinator = visitor.visit(this.combinator); + this.value = visitor.visit(this.value); + }, + eval: function (env) { + return new(tree.Element)(this.combinator, + this.value.eval ? this.value.eval(env) : this.value, + this.index); + }, + toCSS: function (env) { + var value = (this.value.toCSS ? this.value.toCSS(env) : this.value); + if (value == '' && this.combinator.value.charAt(0) == '&') { + return ''; + } else { + return this.combinator.toCSS(env || {}) + value; + } + } +}; + +tree.Attribute = function (key, op, value) { + this.key = key; + this.op = op; + this.value = value; +}; +tree.Attribute.prototype = { + type: "Attribute", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + eval: function (env) { + return new(tree.Attribute)(this.key.eval ? this.key.eval(env) : this.key, + this.op, (this.value && this.value.eval) ? this.value.eval(env) : this.value); + }, + toCSS: function (env) { + var value = this.key.toCSS ? this.key.toCSS(env) : this.key; + + if (this.op) { + value += this.op; + value += (this.value.toCSS ? this.value.toCSS(env) : this.value); + } + + return '[' + value + ']'; + } +}; + +tree.Combinator = function (value) { + if (value === ' ') { + this.value = ' '; + } else { + this.value = value ? value.trim() : ""; + } +}; +tree.Combinator.prototype = { + type: "Combinator", + toCSS: function (env) { + return { + '' : '', + ' ' : ' ', + ':' : ' :', + '+' : env.compress ? '+' : ' + ', + '~' : env.compress ? '~' : ' ~ ', + '>' : env.compress ? '>' : ' > ', + '|' : env.compress ? '|' : ' | ' + }[this.value]; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Expression = function (value) { this.value = value; }; +tree.Expression.prototype = { + type: "Expression", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + eval: function (env) { + var returnValue, + inParenthesis = this.parens && !this.parensInOp, + doubleParen = false; + if (inParenthesis) { + env.inParenthesis(); + } + if (this.value.length > 1) { + returnValue = new(tree.Expression)(this.value.map(function (e) { + return e.eval(env); + })); + } else if (this.value.length === 1) { + if (this.value[0].parens && !this.value[0].parensInOp) { + doubleParen = true; + } + returnValue = this.value[0].eval(env); + } else { + returnValue = this; + } + if (inParenthesis) { + env.outOfParenthesis(); + } + if (this.parens && this.parensInOp && !(env.isMathOn()) && !doubleParen) { + returnValue = new(tree.Paren)(returnValue); + } + return returnValue; + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS ? e.toCSS(env) : ''; + }).join(' '); + }, + throwAwayComments: function () { + this.value = this.value.filter(function(v) { + return !(v instanceof tree.Comment); + }); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Extend = function Extend(selector, option, index) { + this.selector = selector; + this.option = option; + this.index = index; + + switch(option) { + case "all": + this.allowBefore = true; + this.allowAfter = true; + break; + default: + this.allowBefore = false; + this.allowAfter = false; + break; + } +}; + +tree.Extend.prototype = { + type: "Extend", + accept: function (visitor) { + this.selector = visitor.visit(this.selector); + }, + eval: function (env) { + return new(tree.Extend)(this.selector.eval(env), this.option, this.index); + }, + clone: function (env) { + return new(tree.Extend)(this.selector, this.option, this.index); + }, + findSelfSelectors: function (selectors) { + var selfElements = [], + i; + + for(i = 0; i < selectors.length; i++) { + selfElements = selfElements.concat(selectors[i].elements); + } + + this.selfSelectors = [{ elements: selfElements }]; + } +}; + +})(require('../tree')); +(function (tree) { +// +// CSS @import node +// +// The general strategy here is that we don't want to wait +// for the parsing to be completed, before we start importing +// the file. That's because in the context of a browser, +// most of the time will be spent waiting for the server to respond. +// +// On creation, we push the import path to our import queue, though +// `import,push`, we also pass it a callback, which it'll call once +// the file has been fetched, and parsed. +// +tree.Import = function (path, features, options, index, currentFileInfo) { + var that = this; + + this.options = options; + this.index = index; + this.path = path; + this.features = features; + this.currentFileInfo = currentFileInfo; + + if (this.options.less !== undefined) { + this.css = !this.options.less; + } else { + var pathValue = this.getPath(); + if (pathValue && /css([\?;].*)?$/.test(pathValue)) { + this.css = true; + } + } +}; + +// +// The actual import node doesn't return anything, when converted to CSS. +// The reason is that it's used at the evaluation stage, so that the rules +// it imports can be treated like any other rules. +// +// In `eval`, we make sure all Import nodes get evaluated, recursively, so +// we end up with a flat structure, which can easily be imported in the parent +// ruleset. +// +tree.Import.prototype = { + type: "Import", + accept: function (visitor) { + this.features = visitor.visit(this.features); + this.path = visitor.visit(this.path); + this.root = visitor.visit(this.root); + }, + toCSS: function (env) { + var features = this.features ? ' ' + this.features.toCSS(env) : ''; + + if (this.css) { + return "@import " + this.path.toCSS() + features + ';\n'; + } else { + return ""; + } + }, + getPath: function () { + if (this.path instanceof tree.Quoted) { + var path = this.path.value; + return (this.css !== undefined || /(\.[a-z]*$)|([\?;].*)$/.test(path)) ? path : path + '.less'; + } else if (this.path instanceof tree.URL) { + return this.path.value.value; + } + return null; + }, + evalForImport: function (env) { + return new(tree.Import)(this.path.eval(env), this.features, this.options, this.index, this.currentFileInfo); + }, + evalPath: function (env) { + var path = this.path.eval(env); + var rootpath = this.currentFileInfo && this.currentFileInfo.rootpath; + if (rootpath && !(path instanceof tree.URL)) { + var pathValue = path.value; + // Add the base path if the import is relative + if (pathValue && env.isPathRelative(pathValue)) { + path.value = rootpath + pathValue; + } + } + return path; + }, + eval: function (env) { + var ruleset, features = this.features && this.features.eval(env); + + if (this.skip) { return []; } + + if (this.css) { + var newImport = new(tree.Import)(this.evalPath(env), features, this.options, this.index); + if (!newImport.css && this.error) { + throw this.error; + } + return newImport; + } else { + ruleset = new(tree.Ruleset)([], this.root.rules.slice(0)); + + ruleset.evalImports(env); + + return this.features ? new(tree.Media)(ruleset.rules, this.features.value) : ruleset.rules; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.JavaScript = function (string, index, escaped) { + this.escaped = escaped; + this.expression = string; + this.index = index; +}; +tree.JavaScript.prototype = { + type: "JavaScript", + eval: function (env) { + var result, + that = this, + context = {}; + + var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { + return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); + }); + + try { + expression = new(Function)('return (' + expression + ')'); + } catch (e) { + throw { message: "JavaScript evaluation error: `" + expression + "`" , + index: this.index }; + } + + for (var k in env.frames[0].variables()) { + context[k.slice(1)] = { + value: env.frames[0].variables()[k].value, + toJS: function () { + return this.value.eval(env).toCSS(); + } + }; + } + + try { + result = expression.call(context); + } catch (e) { + throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , + index: this.index }; + } + if (typeof(result) === 'string') { + return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); + } else if (Array.isArray(result)) { + return new(tree.Anonymous)(result.join(', ')); + } else { + return new(tree.Anonymous)(result); + } + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Keyword = function (value) { this.value = value }; +tree.Keyword.prototype = { + type: "Keyword", + eval: function () { return this; }, + toCSS: function () { return this.value; }, + compare: function (other) { + if (other instanceof tree.Keyword) { + return other.value === this.value ? 0 : 1; + } else { + return -1; + } + } +}; + +tree.True = new(tree.Keyword)('true'); +tree.False = new(tree.Keyword)('false'); + +})(require('../tree')); +(function (tree) { + +tree.Media = function (value, features) { + var selectors = this.emptySelectors(); + + this.features = new(tree.Value)(features); + this.ruleset = new(tree.Ruleset)(selectors, value); + this.ruleset.allowImports = true; +}; +tree.Media.prototype = { + type: "Media", + accept: function (visitor) { + this.features = visitor.visit(this.features); + this.ruleset = visitor.visit(this.ruleset); + }, + toCSS: function (env) { + var features = this.features.toCSS(env); + + return '@media ' + features + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + }, + eval: function (env) { + if (!env.mediaBlocks) { + env.mediaBlocks = []; + env.mediaPath = []; + } + + var media = new(tree.Media)([], []); + if(this.debugInfo) { + this.ruleset.debugInfo = this.debugInfo; + media.debugInfo = this.debugInfo; + } + var strictMathBypass = false; + if (!env.strictMath) { + strictMathBypass = true; + env.strictMath = true; + } + try { + media.features = this.features.eval(env); + } + finally { + if (strictMathBypass) { + env.strictMath = false; + } + } + + env.mediaPath.push(media); + env.mediaBlocks.push(media); + + env.frames.unshift(this.ruleset); + media.ruleset = this.ruleset.eval(env); + env.frames.shift(); + + env.mediaPath.pop(); + + return env.mediaPath.length === 0 ? media.evalTop(env) : + media.evalNested(env) + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) }, + emptySelectors: function() { + var el = new(tree.Element)('', '&', 0); + return [new(tree.Selector)([el])]; + }, + + evalTop: function (env) { + var result = this; + + // Render all dependent Media blocks. + if (env.mediaBlocks.length > 1) { + var selectors = this.emptySelectors(); + result = new(tree.Ruleset)(selectors, env.mediaBlocks); + result.multiMedia = true; + } + + delete env.mediaBlocks; + delete env.mediaPath; + + return result; + }, + evalNested: function (env) { + var i, value, + path = env.mediaPath.concat([this]); + + // Extract the media-query conditions separated with `,` (OR). + for (i = 0; i < path.length; i++) { + value = path[i].features instanceof tree.Value ? + path[i].features.value : path[i].features; + path[i] = Array.isArray(value) ? value : [value]; + } + + // Trace all permutations to generate the resulting media-query. + // + // (a, b and c) with nested (d, e) -> + // a and d + // a and e + // b and c and d + // b and c and e + this.features = new(tree.Value)(this.permute(path).map(function (path) { + path = path.map(function (fragment) { + return fragment.toCSS ? fragment : new(tree.Anonymous)(fragment); + }); + + for(i = path.length - 1; i > 0; i--) { + path.splice(i, 0, new(tree.Anonymous)("and")); + } + + return new(tree.Expression)(path); + })); + + // Fake a tree-node that doesn't output anything. + return new(tree.Ruleset)([], []); + }, + permute: function (arr) { + if (arr.length === 0) { + return []; + } else if (arr.length === 1) { + return arr[0]; + } else { + var result = []; + var rest = this.permute(arr.slice(1)); + for (var i = 0; i < rest.length; i++) { + for (var j = 0; j < arr[0].length; j++) { + result.push([arr[0][j]].concat(rest[i])); + } + } + return result; + } + }, + bubbleSelectors: function (selectors) { + this.ruleset = new(tree.Ruleset)(selectors.slice(0), [this.ruleset]); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.mixin = {}; +tree.mixin.Call = function (elements, args, index, currentFileInfo, important) { + this.selector = new(tree.Selector)(elements); + this.arguments = args; + this.index = index; + this.currentFileInfo = currentFileInfo; + this.important = important; +}; +tree.mixin.Call.prototype = { + type: "MixinCall", + accept: function (visitor) { + this.selector = visitor.visit(this.selector); + this.arguments = visitor.visit(this.arguments); + }, + eval: function (env) { + var mixins, mixin, args, rules = [], match = false, i, m, f, isRecursive, isOneFound; + + args = this.arguments && this.arguments.map(function (a) { + return { name: a.name, value: a.value.eval(env) }; + }); + + for (i = 0; i < env.frames.length; i++) { + if ((mixins = env.frames[i].find(this.selector)).length > 0) { + isOneFound = true; + for (m = 0; m < mixins.length; m++) { + mixin = mixins[m]; + isRecursive = false; + for(f = 0; f < env.frames.length; f++) { + if ((!(mixin instanceof tree.mixin.Definition)) && mixin === (env.frames[f].originalRuleset || env.frames[f])) { + isRecursive = true; + break; + } + } + if (isRecursive) { + continue; + } + if (mixin.matchArgs(args, env)) { + if (!mixin.matchCondition || mixin.matchCondition(args, env)) { + try { + Array.prototype.push.apply( + rules, mixin.eval(env, args, this.important).rules); + } catch (e) { + throw { message: e.message, index: this.index, filename: this.currentFileInfo.filename, stack: e.stack }; + } + } + match = true; + } + } + if (match) { + return rules; + } + } + } + if (isOneFound) { + throw { type: 'Runtime', + message: 'No matching definition was found for `' + + this.selector.toCSS().trim() + '(' + + (args ? args.map(function (a) { + var argValue = ""; + if (a.name) { + argValue += a.name + ":"; + } + if (a.value.toCSS) { + argValue += a.value.toCSS(); + } else { + argValue += "???"; + } + return argValue; + }).join(', ') : "") + ")`", + index: this.index, filename: this.currentFileInfo.filename }; + } else { + throw { type: 'Name', + message: this.selector.toCSS().trim() + " is undefined", + index: this.index, filename: this.currentFileInfo.filename }; + } + } +}; + +tree.mixin.Definition = function (name, params, rules, condition, variadic) { + this.name = name; + this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; + this.params = params; + this.condition = condition; + this.variadic = variadic; + this.arity = params.length; + this.rules = rules; + this._lookups = {}; + this.required = params.reduce(function (count, p) { + if (!p.name || (p.name && !p.value)) { return count + 1 } + else { return count } + }, 0); + this.parent = tree.Ruleset.prototype; + this.frames = []; +}; +tree.mixin.Definition.prototype = { + type: "MixinDefinition", + accept: function (visitor) { + this.params = visitor.visit(this.params); + this.rules = visitor.visit(this.rules); + this.condition = visitor.visit(this.condition); + }, + toCSS: function () { return ""; }, + variable: function (name) { return this.parent.variable.call(this, name); }, + variables: function () { return this.parent.variables.call(this); }, + find: function () { return this.parent.find.apply(this, arguments); }, + rulesets: function () { return this.parent.rulesets.apply(this); }, + + evalParams: function (env, mixinEnv, args, evaldArguments) { + var frame = new(tree.Ruleset)(null, []), + varargs, arg, + params = this.params.slice(0), + i, j, val, name, isNamedFound, argIndex; + + mixinEnv = new tree.evalEnv(mixinEnv, [frame].concat(mixinEnv.frames)); + + if (args) { + args = args.slice(0); + + for(i = 0; i < args.length; i++) { + arg = args[i]; + if (name = (arg && arg.name)) { + isNamedFound = false; + for(j = 0; j < params.length; j++) { + if (!evaldArguments[j] && name === params[j].name) { + evaldArguments[j] = arg.value.eval(env); + frame.rules.unshift(new(tree.Rule)(name, arg.value.eval(env))); + isNamedFound = true; + break; + } + } + if (isNamedFound) { + args.splice(i, 1); + i--; + continue; + } else { + throw { type: 'Runtime', message: "Named argument for " + this.name + + ' ' + args[i].name + ' not found' }; + } + } + } + } + argIndex = 0; + for (i = 0; i < params.length; i++) { + if (evaldArguments[i]) continue; + + arg = args && args[argIndex]; + + if (name = params[i].name) { + if (params[i].variadic && args) { + varargs = []; + for (j = argIndex; j < args.length; j++) { + varargs.push(args[j].value.eval(env)); + } + frame.rules.unshift(new(tree.Rule)(name, new(tree.Expression)(varargs).eval(env))); + } else { + val = arg && arg.value; + if (val) { + val = val.eval(env); + } else if (params[i].value) { + val = params[i].value.eval(mixinEnv); + frame.resetCache(); + } else { + throw { type: 'Runtime', message: "wrong number of arguments for " + this.name + + ' (' + args.length + ' for ' + this.arity + ')' }; + } + + frame.rules.unshift(new(tree.Rule)(name, val)); + evaldArguments[i] = val; + } + } + + if (params[i].variadic && args) { + for (j = argIndex; j < args.length; j++) { + evaldArguments[j] = args[j].value.eval(env); + } + } + argIndex++; + } + + return frame; + }, + eval: function (env, args, important) { + var _arguments = [], + mixinFrames = this.frames.concat(env.frames), + frame = this.evalParams(env, new(tree.evalEnv)(env, mixinFrames), args, _arguments), + context, rules, start, ruleset; + + frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); + + rules = important ? + this.parent.makeImportant.apply(this).rules : this.rules.slice(0); + + ruleset = new(tree.Ruleset)(null, rules).eval(new(tree.evalEnv)(env, + [this, frame].concat(mixinFrames))); + ruleset.originalRuleset = this; + return ruleset; + }, + matchCondition: function (args, env) { + + if (this.condition && !this.condition.eval( + new(tree.evalEnv)(env, + [this.evalParams(env, new(tree.evalEnv)(env, this.frames.concat(env.frames)), args, [])] + .concat(env.frames)))) { + return false; + } + return true; + }, + matchArgs: function (args, env) { + var argsLength = (args && args.length) || 0, len, frame; + + if (! this.variadic) { + if (argsLength < this.required) { return false } + if (argsLength > this.params.length) { return false } + if ((this.required > 0) && (argsLength > this.params.length)) { return false } + } + + len = Math.min(argsLength, this.arity); + + for (var i = 0; i < len; i++) { + if (!this.params[i].name && !this.params[i].variadic) { + if (args[i].value.eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { + return false; + } + } + } + return true; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Negative = function (node) { + this.value = node; +}; +tree.Negative.prototype = { + type: "Negative", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + toCSS: function (env) { + return '-' + this.value.toCSS(env); + }, + eval: function (env) { + if (env.isMathOn()) { + return (new(tree.Operation)('*', [new(tree.Dimension)(-1), this.value])).eval(env); + } + return new(tree.Negative)(this.value.eval(env)); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Operation = function (op, operands, isSpaced) { + this.op = op.trim(); + this.operands = operands; + this.isSpaced = isSpaced; +}; +tree.Operation.prototype = { + type: "Operation", + accept: function (visitor) { + this.operands = visitor.visit(this.operands); + }, + eval: function (env) { + var a = this.operands[0].eval(env), + b = this.operands[1].eval(env), + temp; + + if (env.isMathOn()) { + if (a instanceof tree.Dimension && b instanceof tree.Color) { + if (this.op === '*' || this.op === '+') { + temp = b, b = a, a = temp; + } else { + throw { type: "Operation", + message: "Can't substract or divide a color from a number" }; + } + } + if (!a.operate) { + throw { type: "Operation", + message: "Operation on an invalid type" }; + } + + return a.operate(env, this.op, b); + } else { + return new(tree.Operation)(this.op, [a, b], this.isSpaced); + } + }, + toCSS: function (env) { + var separator = this.isSpaced ? " " : ""; + return this.operands[0].toCSS() + separator + this.op + separator + this.operands[1].toCSS(); + } +}; + +tree.operate = function (env, op, a, b) { + switch (op) { + case '+': return a + b; + case '-': return a - b; + case '*': return a * b; + case '/': return a / b; + } +}; + +})(require('../tree')); + +(function (tree) { + +tree.Paren = function (node) { + this.value = node; +}; +tree.Paren.prototype = { + type: "Paren", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + toCSS: function (env) { + return '(' + this.value.toCSS(env).trim() + ')'; + }, + eval: function (env) { + return new(tree.Paren)(this.value.eval(env)); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Quoted = function (str, content, escaped, index, currentFileInfo) { + this.escaped = escaped; + this.value = content || ''; + this.quote = str.charAt(0); + this.index = index; + this.currentFileInfo = currentFileInfo; +}; +tree.Quoted.prototype = { + type: "Quoted", + toCSS: function () { + if (this.escaped) { + return this.value; + } else { + return this.quote + this.value + this.quote; + } + }, + eval: function (env) { + var that = this; + var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { + return new(tree.JavaScript)(exp, that.index, true).eval(env).value; + }).replace(/@\{([\w-]+)\}/g, function (_, name) { + var v = new(tree.Variable)('@' + name, that.index, that.currentFileInfo).eval(env, true); + return (v instanceof tree.Quoted) ? v.value : v.toCSS(); + }); + return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); + }, + compare: function (x) { + if (!x.toCSS) { + return -1; + } + + var left = this.toCSS(), + right = x.toCSS(); + + if (left === right) { + return 0; + } + + return left < right ? -1 : 1; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Rule = function (name, value, important, index, currentFileInfo, inline) { + this.name = name; + this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); + this.important = important ? ' ' + important.trim() : ''; + this.index = index; + this.currentFileInfo = currentFileInfo; + this.inline = inline || false; + + if (name.charAt(0) === '@') { + this.variable = true; + } else { this.variable = false } +}; + +tree.Rule.prototype = { + type: "Rule", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + toCSS: function (env) { + if (this.variable) { return "" } + else { + try { + return this.name + (env.compress ? ':' : ': ') + + this.value.toCSS(env) + + this.important + (this.inline ? "" : ";"); + } + catch(e) { + e.index = this.index; + e.filename = this.currentFileInfo.filename; + throw e; + } + } + }, + eval: function (env) { + var strictMathBypass = false; + if (this.name === "font" && !env.strictMath) { + strictMathBypass = true; + env.strictMath = true; + } + try { + return new(tree.Rule)(this.name, + this.value.eval(env), + this.important, + this.index, this.currentFileInfo, this.inline); + } + finally { + if (strictMathBypass) { + env.strictMath = false; + } + } + }, + makeImportant: function () { + return new(tree.Rule)(this.name, + this.value, + "!important", + this.index, this.currentFileInfo, this.inline); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Ruleset = function (selectors, rules, strictImports) { + this.selectors = selectors; + this.rules = rules; + this._lookups = {}; + this.strictImports = strictImports; +}; +tree.Ruleset.prototype = { + type: "Ruleset", + accept: function (visitor) { + this.selectors = visitor.visit(this.selectors); + this.rules = visitor.visit(this.rules); + }, + eval: function (env) { + var selectors = this.selectors && this.selectors.map(function (s) { return s.eval(env) }); + var ruleset = new(tree.Ruleset)(selectors, this.rules.slice(0), this.strictImports); + var rules; + + ruleset.originalRuleset = this; + ruleset.root = this.root; + ruleset.firstRoot = this.firstRoot; + ruleset.allowImports = this.allowImports; + + if(this.debugInfo) { + ruleset.debugInfo = this.debugInfo; + } + + // push the current ruleset to the frames stack + env.frames.unshift(ruleset); + + // currrent selectors + if (!env.selectors) { + env.selectors = []; + } + env.selectors.unshift(this.selectors); + + // Evaluate imports + if (ruleset.root || ruleset.allowImports || !ruleset.strictImports) { + ruleset.evalImports(env); + } + + // Store the frames around mixin definitions, + // so they can be evaluated like closures when the time comes. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Definition) { + ruleset.rules[i].frames = env.frames.slice(0); + } + } + + var mediaBlockCount = (env.mediaBlocks && env.mediaBlocks.length) || 0; + + // Evaluate mixin calls. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Call) { + rules = ruleset.rules[i].eval(env).filter(function(r) { + if ((r instanceof tree.Rule) && r.variable) { + // do not pollute the scope if the variable is + // already there. consider returning false here + // but we need a way to "return" variable from mixins + return !(ruleset.variable(r.name)); + } + return true; + }); + ruleset.rules.splice.apply(ruleset.rules, [i, 1].concat(rules)); + i += rules.length-1; + ruleset.resetCache(); + } + } + + // Evaluate everything else + for (var i = 0, rule; i < ruleset.rules.length; i++) { + rule = ruleset.rules[i]; + + if (! (rule instanceof tree.mixin.Definition)) { + ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; + } + } + + // Pop the stack + env.frames.shift(); + env.selectors.shift(); + + if (env.mediaBlocks) { + for(var i = mediaBlockCount; i < env.mediaBlocks.length; i++) { + env.mediaBlocks[i].bubbleSelectors(selectors); + } + } + + return ruleset; + }, + evalImports: function(env) { + var i, rules; + for (i = 0; i < this.rules.length; i++) { + if (this.rules[i] instanceof tree.Import) { + rules = this.rules[i].eval(env); + if (typeof rules.length === "number") { + this.rules.splice.apply(this.rules, [i, 1].concat(rules)); + i+= rules.length-1; + } else { + this.rules.splice(i, 1, rules); + } + this.resetCache(); + } + } + }, + makeImportant: function() { + return new tree.Ruleset(this.selectors, this.rules.map(function (r) { + if (r.makeImportant) { + return r.makeImportant(); + } else { + return r; + } + }), this.strictImports); + }, + matchArgs: function (args) { + return !args || args.length === 0; + }, + resetCache: function () { + this._rulesets = null; + this._variables = null; + this._lookups = {}; + }, + variables: function () { + if (this._variables) { return this._variables } + else { + return this._variables = this.rules.reduce(function (hash, r) { + if (r instanceof tree.Rule && r.variable === true) { + hash[r.name] = r; + } + return hash; + }, {}); + } + }, + variable: function (name) { + return this.variables()[name]; + }, + rulesets: function () { + return this.rules.filter(function (r) { + return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); + }); + }, + find: function (selector, self) { + self = self || this; + var rules = [], rule, match, + key = selector.toCSS(); + + if (key in this._lookups) { return this._lookups[key] } + + this.rulesets().forEach(function (rule) { + if (rule !== self) { + for (var j = 0; j < rule.selectors.length; j++) { + if (match = selector.match(rule.selectors[j])) { + if (selector.elements.length > rule.selectors[j].elements.length) { + Array.prototype.push.apply(rules, rule.find( + new(tree.Selector)(selector.elements.slice(1)), self)); + } else { + rules.push(rule); + } + break; + } + } + } + }); + return this._lookups[key] = rules; + }, + // + // Entry point for code generation + // + // `context` holds an array of arrays. + // + toCSS: function (env) { + var css = [], // The CSS output + rules = [], // node.Rule instances + _rules = [], // + rulesets = [], // node.Ruleset instances + selector, // The fully rendered selector + debugInfo, // Line number debugging + rule; + + // Compile rules and rulesets + for (var i = 0; i < this.rules.length; i++) { + rule = this.rules[i]; + + if (rule.rules || (rule instanceof tree.Media)) { + rulesets.push(rule.toCSS(env)); + } else if (rule instanceof tree.Directive) { + var cssValue = rule.toCSS(env); + // Output only the first @charset definition as such - convert the others + // to comments in case debug is enabled + if (rule.name === "@charset") { + // Only output the debug info together with subsequent @charset definitions + // a comment (or @media statement) before the actual @charset directive would + // be considered illegal css as it has to be on the first line + if (env.charset) { + if (rule.debugInfo) { + rulesets.push(tree.debugInfo(env, rule)); + rulesets.push(new tree.Comment("/* "+cssValue.replace(/\n/g, "")+" */\n").toCSS(env)); + } + continue; + } + env.charset = true; + } + rulesets.push(cssValue); + } else if (rule instanceof tree.Comment) { + if (!rule.silent) { + if (this.root) { + rulesets.push(rule.toCSS(env)); + } else { + rules.push(rule.toCSS(env)); + } + } + } else { + if (rule.toCSS && !rule.variable) { + if (this.firstRoot && rule instanceof tree.Rule) { + throw { message: "properties must be inside selector blocks, they cannot be in the root.", + index: rule.index, filename: rule.currentFileInfo ? rule.currentFileInfo.filename : null}; + } + rules.push(rule.toCSS(env)); + } else if (rule.value && !rule.variable) { + rules.push(rule.value.toString()); + } + } + } + + // Remove last semicolon + if (env.compress && rules.length) { + rule = rules[rules.length - 1]; + if (rule.charAt(rule.length - 1) === ';') { + rules[rules.length - 1] = rule.substring(0, rule.length - 1); + } + } + + rulesets = rulesets.join(''); + + // If this is the root node, we don't render + // a selector, or {}. + // Otherwise, only output if this ruleset has rules. + if (this.root) { + css.push(rules.join(env.compress ? '' : '\n')); + } else { + if (rules.length > 0) { + debugInfo = tree.debugInfo(env, this); + selector = this.paths.map(function (p) { + return p.map(function (s) { + return s.toCSS(env); + }).join('').trim(); + }).join(env.compress ? ',' : ',\n'); + + // Remove duplicates + for (var i = rules.length - 1; i >= 0; i--) { + if (rules[i].slice(0, 2) === "/*" || _rules.indexOf(rules[i]) === -1) { + _rules.unshift(rules[i]); + } + } + rules = _rules; + + css.push(debugInfo + selector + + (env.compress ? '{' : ' {\n ') + + rules.join(env.compress ? '' : '\n ') + + (env.compress ? '}' : '\n}\n')); + } + } + css.push(rulesets); + + return css.join('') + (env.compress ? '\n' : ''); + }, + + joinSelectors: function (paths, context, selectors) { + for (var s = 0; s < selectors.length; s++) { + this.joinSelector(paths, context, selectors[s]); + } + }, + + joinSelector: function (paths, context, selector) { + + var i, j, k, + hasParentSelector, newSelectors, el, sel, parentSel, + newSelectorPath, afterParentJoin, newJoinedSelector, + newJoinedSelectorEmpty, lastSelector, currentElements, + selectorsMultiplied; + + for (i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + if (el.value === '&') { + hasParentSelector = true; + } + } + + if (!hasParentSelector) { + if (context.length > 0) { + for(i = 0; i < context.length; i++) { + paths.push(context[i].concat(selector)); + } + } + else { + paths.push([selector]); + } + return; + } + + // The paths are [[Selector]] + // The first list is a list of comma seperated selectors + // The inner list is a list of inheritance seperated selectors + // e.g. + // .a, .b { + // .c { + // } + // } + // == [[.a] [.c]] [[.b] [.c]] + // + + // the elements from the current selector so far + currentElements = []; + // the current list of new selectors to add to the path. + // We will build it up. We initiate it with one empty selector as we "multiply" the new selectors + // by the parents + newSelectors = [[]]; + + for (i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + // non parent reference elements just get added + if (el.value !== "&") { + currentElements.push(el); + } else { + // the new list of selectors to add + selectorsMultiplied = []; + + // merge the current list of non parent selector elements + // on to the current list of selectors to add + if (currentElements.length > 0) { + this.mergeElementsOnToSelectors(currentElements, newSelectors); + } + + // loop through our current selectors + for(j = 0; j < newSelectors.length; j++) { + sel = newSelectors[j]; + // if we don't have any parent paths, the & might be in a mixin so that it can be used + // whether there are parents or not + if (context.length == 0) { + // the combinator used on el should now be applied to the next element instead so that + // it is not lost + if (sel.length > 0) { + sel[0].elements = sel[0].elements.slice(0); + sel[0].elements.push(new(tree.Element)(el.combinator, '', 0)); //new Element(el.Combinator, "")); + } + selectorsMultiplied.push(sel); + } + else { + // and the parent selectors + for(k = 0; k < context.length; k++) { + parentSel = context[k]; + // We need to put the current selectors + // then join the last selector's elements on to the parents selectors + + // our new selector path + newSelectorPath = []; + // selectors from the parent after the join + afterParentJoin = []; + newJoinedSelectorEmpty = true; + + //construct the joined selector - if & is the first thing this will be empty, + // if not newJoinedSelector will be the last set of elements in the selector + if (sel.length > 0) { + newSelectorPath = sel.slice(0); + lastSelector = newSelectorPath.pop(); + newJoinedSelector = new(tree.Selector)(lastSelector.elements.slice(0), selector.extendList); + newJoinedSelectorEmpty = false; + } + else { + newJoinedSelector = new(tree.Selector)([], selector.extendList); + } + + //put together the parent selectors after the join + if (parentSel.length > 1) { + afterParentJoin = afterParentJoin.concat(parentSel.slice(1)); + } + + if (parentSel.length > 0) { + newJoinedSelectorEmpty = false; + + // join the elements so far with the first part of the parent + newJoinedSelector.elements.push(new(tree.Element)(el.combinator, parentSel[0].elements[0].value, 0)); + newJoinedSelector.elements = newJoinedSelector.elements.concat(parentSel[0].elements.slice(1)); + } + + if (!newJoinedSelectorEmpty) { + // now add the joined selector + newSelectorPath.push(newJoinedSelector); + } + + // and the rest of the parent + newSelectorPath = newSelectorPath.concat(afterParentJoin); + + // add that to our new set of selectors + selectorsMultiplied.push(newSelectorPath); + } + } + } + + // our new selectors has been multiplied, so reset the state + newSelectors = selectorsMultiplied; + currentElements = []; + } + } + + // if we have any elements left over (e.g. .a& .b == .b) + // add them on to all the current selectors + if (currentElements.length > 0) { + this.mergeElementsOnToSelectors(currentElements, newSelectors); + } + + for(i = 0; i < newSelectors.length; i++) { + if (newSelectors[i].length > 0) { + paths.push(newSelectors[i]); + } + } + }, + + mergeElementsOnToSelectors: function(elements, selectors) { + var i, sel, extendList; + + if (selectors.length == 0) { + selectors.push([ new(tree.Selector)(elements) ]); + return; + } + + for(i = 0; i < selectors.length; i++) { + sel = selectors[i]; + + // if the previous thing in sel is a parent this needs to join on to it + if (sel.length > 0) { + sel[sel.length - 1] = new(tree.Selector)(sel[sel.length - 1].elements.concat(elements), sel[sel.length - 1].extendList); + } + else { + sel.push(new(tree.Selector)(elements)); + } + } + } +}; +})(require('../tree')); +(function (tree) { + +tree.Selector = function (elements, extendList) { + this.elements = elements; + this.extendList = extendList || []; +}; +tree.Selector.prototype = { + type: "Selector", + accept: function (visitor) { + this.elements = visitor.visit(this.elements); + this.extendList = visitor.visit(this.extendList) + }, + match: function (other) { + var elements = this.elements, + len = elements.length, + oelements, olen, max, i; + + oelements = other.elements.slice( + (other.elements.length && other.elements[0].value === "&") ? 1 : 0); + olen = oelements.length; + max = Math.min(len, olen); + + if (olen === 0 || len < olen) { + return false; + } else { + for (i = 0; i < max; i++) { + if (elements[i].value !== oelements[i].value) { + return false; + } + } + } + return true; + }, + eval: function (env) { + return new(tree.Selector)(this.elements.map(function (e) { + return e.eval(env); + }), this.extendList.map(function(extend) { + return extend.eval(env); + })); + }, + toCSS: function (env) { + if (this._css) { return this._css } + + if (this.elements[0].combinator.value === "") { + this._css = ' '; + } else { + this._css = ''; + } + + this._css += this.elements.map(function (e) { + if (typeof(e) === 'string') { + return ' ' + e.trim(); + } else { + return e.toCSS(env); + } + }).join(''); + + return this._css; + } +}; + +})(require('../tree')); +(function (tree) { + +tree.UnicodeDescriptor = function (value) { + this.value = value; +}; +tree.UnicodeDescriptor.prototype = { + type: "UnicodeDescriptor", + toCSS: function (env) { + return this.value; + }, + eval: function () { return this } +}; + +})(require('../tree')); +(function (tree) { + +tree.URL = function (val, currentFileInfo) { + this.value = val; + this.currentFileInfo = currentFileInfo; +}; +tree.URL.prototype = { + type: "Url", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + toCSS: function () { + return "url(" + this.value.toCSS() + ")"; + }, + eval: function (ctx) { + var val = this.value.eval(ctx), rootpath; + + // Add the base path if the URL is relative + rootpath = this.currentFileInfo && this.currentFileInfo.rootpath; + if (rootpath && typeof val.value === "string" && ctx.isPathRelative(val.value)) { + if (!val.quote) { + rootpath = rootpath.replace(/[\(\)'"\s]/g, function(match) { return "\\"+match; }); + } + val.value = rootpath + val.value; + } + + return new(tree.URL)(val, null); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Value = function (value) { + this.value = value; +}; +tree.Value.prototype = { + type: "Value", + accept: function (visitor) { + this.value = visitor.visit(this.value); + }, + eval: function (env) { + if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return new(tree.Value)(this.value.map(function (v) { + return v.eval(env); + })); + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(env.compress ? ',' : ', '); + } +}; + +})(require('../tree')); +(function (tree) { + +tree.Variable = function (name, index, currentFileInfo) { this.name = name, this.index = index, this.currentFileInfo = currentFileInfo }; +tree.Variable.prototype = { + type: "Variable", + eval: function (env) { + var variable, v, name = this.name; + + if (name.indexOf('@@') == 0) { + name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; + } + + if (this.evaluating) { + throw { type: 'Name', + message: "Recursive variable definition for " + name, + filename: this.currentFileInfo.file, + index: this.index }; + } + + this.evaluating = true; + + if (variable = tree.find(env.frames, function (frame) { + if (v = frame.variable(name)) { + return v.value.eval(env); + } + })) { + this.evaluating = false; + return variable; + } + else { + throw { type: 'Name', + message: "variable " + name + " is undefined", + filename: this.currentFileInfo.filename, + index: this.index }; + } + } +}; + +})(require('../tree')); +(function (tree) { + +tree.debugInfo = function(env, ctx) { + var result=""; + if (env.dumpLineNumbers && !env.compress) { + switch(env.dumpLineNumbers) { + case 'comments': + result = tree.debugInfo.asComment(ctx); + break; + case 'mediaquery': + result = tree.debugInfo.asMediaQuery(ctx); + break; + case 'all': + result = tree.debugInfo.asComment(ctx)+tree.debugInfo.asMediaQuery(ctx); + break; + } + } + return result; +}; + +tree.debugInfo.asComment = function(ctx) { + return '/* line ' + ctx.debugInfo.lineNumber + ', ' + ctx.debugInfo.fileName + ' */\n'; +}; + +tree.debugInfo.asMediaQuery = function(ctx) { + return '@media -sass-debug-info{filename{font-family:' + + ('file://' + ctx.debugInfo.fileName).replace(/([.:/\\])/g, function(a){if(a=='\\') a = '\/'; return '\\' + a}) + + '}line{font-family:\\00003' + ctx.debugInfo.lineNumber + '}}\n'; +}; + +tree.find = function (obj, fun) { + for (var i = 0, r; i < obj.length; i++) { + if (r = fun.call(obj, obj[i])) { return r } + } + return null; +}; +tree.jsify = function (obj) { + if (Array.isArray(obj.value) && (obj.value.length > 1)) { + return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; + } else { + return obj.toCSS(false); + } +}; + +})(require('./tree')); +(function (tree) { + + var parseCopyProperties = [ + 'paths', // option - unmodified - paths to search for imports on + 'optimization', // option - optimization level (for the chunker) + 'files', // list of files that have been imported, used for import-once + 'contents', // browser-only, contents of all the files + 'relativeUrls', // option - whether to adjust URL's to be relative + 'strictImports', // option - + 'dumpLineNumbers', // option - whether to dump line numbers + 'compress', // option - whether to compress + 'processImports', // option - whether to process imports. if false then imports will not be imported + 'syncImport', // option - whether to import synchronously + 'mime', // browser only - mime type for sheet import + 'currentFileInfo' // information about the current file - for error reporting and importing and making urls relative etc. + ]; + + //currentFileInfo = { + // 'relativeUrls' - option - whether to adjust URL's to be relative + // 'filename' - full resolved filename of current file + // 'rootpath' - path to append to normal URLs for this node + // 'currentDirectory' - path to the current file, absolute + // 'rootFilename' - filename of the base file + // 'entryPath' = absolute path to the entry file + + tree.parseEnv = function(options) { + copyFromOriginal(options, this, parseCopyProperties); + + if (!this.contents) { this.contents = {}; } + if (!this.files) { this.files = {}; } + + if (!this.currentFileInfo) { + var filename = (options && options.filename) || "input"; + var entryPath = filename.replace(/[^\/\\]*$/, ""); + if (options) { + options.filename = null; + } + this.currentFileInfo = { + filename: filename, + relativeUrls: this.relativeUrls, + rootpath: (options && options.rootpath) || "", + currentDirectory: entryPath, + entryPath: entryPath, + rootFilename: filename + }; + } + }; + + tree.parseEnv.prototype.toSheet = function (path) { + var env = new tree.parseEnv(this); + env.href = path; + //env.title = path; + env.type = this.mime; + return env; + }; + + var evalCopyProperties = [ + 'silent', // whether to swallow errors and warnings + 'verbose', // whether to log more activity + 'compress', // whether to compress + 'yuicompress', // whether to compress with the outside tool yui compressor + 'ieCompat', // whether to enforce IE compatibility (IE8 data-uri) + 'strictMath', // whether math has to be within parenthesis + 'strictUnits' // whether units need to evaluate correctly + ]; + + tree.evalEnv = function(options, frames) { + copyFromOriginal(options, this, evalCopyProperties); + + this.frames = frames || []; + }; + + tree.evalEnv.prototype.inParenthesis = function () { + if (!this.parensStack) { + this.parensStack = []; + } + this.parensStack.push(true); + }; + + tree.evalEnv.prototype.outOfParenthesis = function () { + this.parensStack.pop(); + }; + + tree.evalEnv.prototype.isMathOn = function () { + return this.strictMath ? (this.parensStack && this.parensStack.length) : true; + }; + + tree.evalEnv.prototype.isPathRelative = function (path) { + return !/^(?:[a-z-]+:|\/)/.test(path); + }; + + //todo - do the same for the toCSS env + //tree.toCSSEnv = function (options) { + //}; + + var copyFromOriginal = function(original, destination, propertiesToCopy) { + if (!original) { return; } + + for(var i = 0; i < propertiesToCopy.length; i++) { + if (original.hasOwnProperty(propertiesToCopy[i])) { + destination[propertiesToCopy[i]] = original[propertiesToCopy[i]]; + } + } + } +})(require('./tree'));(function (tree) { + + tree.visitor = function(implementation) { + this._implementation = implementation; + }; + + tree.visitor.prototype = { + visit: function(node) { + + if (node instanceof Array) { + return this.visitArray(node); + } + + if (!node || !node.type) { + return node; + } + + var funcName = "visit" + node.type, + func = this._implementation[funcName], + visitArgs, newNode; + if (func) { + visitArgs = {visitDeeper: true}; + newNode = func.call(this._implementation, node, visitArgs); + if (this._implementation.isReplacing) { + node = newNode; + } + } + if ((!visitArgs || visitArgs.visitDeeper) && node && node.accept) { + node.accept(this); + } + funcName = funcName + "Out"; + if (this._implementation[funcName]) { + this._implementation[funcName](node); + } + return node; + }, + visitArray: function(nodes) { + var i, newNodes = []; + for(i = 0; i < nodes.length; i++) { + var evald = this.visit(nodes[i]); + if (evald instanceof Array) { + newNodes = newNodes.concat(evald); + } else { + newNodes.push(evald); + } + } + if (this._implementation.isReplacing) { + return newNodes; + } + return nodes; + } + }; + +})(require('./tree'));(function (tree) { + tree.importVisitor = function(importer, finish, evalEnv) { + this._visitor = new tree.visitor(this); + this._importer = importer; + this._finish = finish; + this.env = evalEnv || new tree.evalEnv(); + this.importCount = 0; + }; + + tree.importVisitor.prototype = { + isReplacing: true, + run: function (root) { + var error; + try { + // process the contents + this._visitor.visit(root); + } + catch(e) { + error = e; + } + + this.isFinished = true; + + if (this.importCount === 0) { + this._finish(error); + } + }, + visitImport: function (importNode, visitArgs) { + var importVisitor = this, + evaldImportNode; + + if (!importNode.css) { + + try { + evaldImportNode = importNode.evalForImport(this.env); + } catch(e){ + if (!e.filename) { e.index = importNode.index; e.filename = importNode.currentFileInfo.filename; } + // attempt to eval properly and treat as css + importNode.css = true; + // if that fails, this error will be thrown + importNode.error = e; + } + + if (evaldImportNode && !evaldImportNode.css) { + importNode = evaldImportNode; + this.importCount++; + var env = new tree.evalEnv(this.env, this.env.frames.slice(0)); + this._importer.push(importNode.getPath(), importNode.currentFileInfo, function (e, root, imported) { + if (e && !e.filename) { e.index = importNode.index; e.filename = importNode.currentFileInfo.filename; } + if (imported && !importNode.options.multiple) { importNode.skip = imported; } + + var subFinish = function(e) { + importVisitor.importCount--; + + if (importVisitor.importCount === 0 && importVisitor.isFinished) { + importVisitor._finish(e); + } + }; + + if (root) { + importNode.root = root; + new(tree.importVisitor)(importVisitor._importer, subFinish, env) + .run(root); + } else { + subFinish(); + } + }); + } + } + visitArgs.visitDeeper = false; + return importNode; + }, + visitRule: function (ruleNode, visitArgs) { + visitArgs.visitDeeper = false; + return ruleNode; + }, + visitDirective: function (directiveNode, visitArgs) { + this.env.frames.unshift(directiveNode); + return directiveNode; + }, + visitDirectiveOut: function (directiveNode) { + this.env.frames.shift(); + }, + visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { + this.env.frames.unshift(mixinDefinitionNode); + return mixinDefinitionNode; + }, + visitMixinDefinitionOut: function (mixinDefinitionNode) { + this.env.frames.shift(); + }, + visitRuleset: function (rulesetNode, visitArgs) { + this.env.frames.unshift(rulesetNode); + return rulesetNode; + }, + visitRulesetOut: function (rulesetNode) { + this.env.frames.shift(); + }, + visitMedia: function (mediaNode, visitArgs) { + this.env.frames.unshift(mediaNode.ruleset); + return mediaNode; + }, + visitMediaOut: function (mediaNode) { + this.env.frames.shift(); + } + }; + +})(require('./tree'));(function (tree) { + tree.joinSelectorVisitor = function() { + this.contexts = [[]]; + this._visitor = new tree.visitor(this); + }; + + tree.joinSelectorVisitor.prototype = { + run: function (root) { + return this._visitor.visit(root); + }, + visitRule: function (ruleNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + + visitRuleset: function (rulesetNode, visitArgs) { + var context = this.contexts[this.contexts.length - 1]; + var paths = []; + this.contexts.push(paths); + + if (! rulesetNode.root) { + rulesetNode.joinSelectors(paths, context, rulesetNode.selectors); + rulesetNode.paths = paths; + } + }, + visitRulesetOut: function (rulesetNode) { + this.contexts.length = this.contexts.length - 1; + }, + visitMedia: function (mediaNode, visitArgs) { + var context = this.contexts[this.contexts.length - 1]; + mediaNode.ruleset.root = (context.length === 0 || context[0].multiMedia); + } + }; + +})(require('./tree'));(function (tree) { + tree.extendFinderVisitor = function() { + this._visitor = new tree.visitor(this); + this.contexts = []; + this.allExtendsStack = [[]]; + }; + + tree.extendFinderVisitor.prototype = { + run: function (root) { + root = this._visitor.visit(root); + root.allExtends = this.allExtendsStack[0]; + return root; + }, + visitRule: function (ruleNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitRuleset: function (rulesetNode, visitArgs) { + + if (rulesetNode.root) { + return; + } + + var i, j, extend, allSelectorsExtendList = [], extendList; + + // get &:extend(.a); rules which apply to all selectors in this ruleset + for(i = 0; i < rulesetNode.rules.length; i++) { + if (rulesetNode.rules[i] instanceof tree.Extend) { + allSelectorsExtendList.push(rulesetNode.rules[i]); + } + } + + // now find every selector and apply the extends that apply to all extends + // and the ones which apply to an individual extend + for(i = 0; i < rulesetNode.paths.length; i++) { + var selectorPath = rulesetNode.paths[i], + selector = selectorPath[selectorPath.length-1]; + extendList = selector.extendList.slice(0).concat(allSelectorsExtendList).map(function(allSelectorsExtend) { + return allSelectorsExtend.clone(); + }); + for(j = 0; j < extendList.length; j++) { + this.foundExtends = true; + extend = extendList[j]; + extend.findSelfSelectors(selectorPath); + extend.ruleset = rulesetNode; + if (j === 0) { extend.firstExtendOnThisSelectorPath = true; } + this.allExtendsStack[this.allExtendsStack.length-1].push(extend); + } + } + + this.contexts.push(rulesetNode.selectors); + }, + visitRulesetOut: function (rulesetNode) { + if (!rulesetNode.root) { + this.contexts.length = this.contexts.length - 1; + } + }, + visitMedia: function (mediaNode, visitArgs) { + mediaNode.allExtends = []; + this.allExtendsStack.push(mediaNode.allExtends); + }, + visitMediaOut: function (mediaNode) { + this.allExtendsStack.length = this.allExtendsStack.length - 1; + }, + visitDirective: function (directiveNode, visitArgs) { + directiveNode.allExtends = []; + this.allExtendsStack.push(directiveNode.allExtends); + }, + visitDirectiveOut: function (directiveNode) { + this.allExtendsStack.length = this.allExtendsStack.length - 1; + } + }; + + tree.processExtendsVisitor = function() { + this._visitor = new tree.visitor(this); + }; + + tree.processExtendsVisitor.prototype = { + run: function(root) { + var extendFinder = new tree.extendFinderVisitor(); + extendFinder.run(root); + if (!extendFinder.foundExtends) { return root; } + root.allExtends = root.allExtends.concat(this.doExtendChaining(root.allExtends, root.allExtends)); + this.allExtendsStack = [root.allExtends]; + return this._visitor.visit(root); + }, + doExtendChaining: function (extendsList, extendsListTarget, iterationCount) { + // + // chaining is different from normal extension.. if we extend an extend then we are not just copying, altering and pasting + // the selector we would do normally, but we are also adding an extend with the same target selector + // this means this new extend can then go and alter other extends + // + // this method deals with all the chaining work - without it, extend is flat and doesn't work on other extend selectors + // this is also the most expensive.. and a match on one selector can cause an extension of a selector we had already processed if + // we look at each selector at a time, as is done in visitRuleset + + var extendIndex, targetExtendIndex, matches, extendsToAdd = [], newSelector, extendVisitor = this, selectorPath, extend, targetExtend, newExtend; + + iterationCount = iterationCount || 0; + + //loop through comparing every extend with every target extend. + // a target extend is the one on the ruleset we are looking at copy/edit/pasting in place + // e.g. .a:extend(.b) {} and .b:extend(.c) {} then the first extend extends the second one + // and the second is the target. + // the seperation into two lists allows us to process a subset of chains with a bigger set, as is the + // case when processing media queries + for(extendIndex = 0; extendIndex < extendsList.length; extendIndex++){ + for(targetExtendIndex = 0; targetExtendIndex < extendsListTarget.length; targetExtendIndex++){ + + extend = extendsList[extendIndex]; + targetExtend = extendsListTarget[targetExtendIndex]; + + // look for circular references + if (this.inInheritanceChain(targetExtend, extend)) { continue; } + + // find a match in the target extends self selector (the bit before :extend) + selectorPath = [targetExtend.selfSelectors[0]]; + matches = extendVisitor.findMatch(extend, selectorPath); + + if (matches.length) { + + // we found a match, so for each self selector.. + extend.selfSelectors.forEach(function(selfSelector) { + + // process the extend as usual + newSelector = extendVisitor.extendSelector(matches, selectorPath, selfSelector); + + // but now we create a new extend from it + newExtend = new(tree.Extend)(targetExtend.selector, targetExtend.option, 0); + newExtend.selfSelectors = newSelector; + + // add the extend onto the list of extends for that selector + newSelector[newSelector.length-1].extendList = [newExtend]; + + // record that we need to add it. + extendsToAdd.push(newExtend); + newExtend.ruleset = targetExtend.ruleset; + + //remember its parents for circular references + newExtend.parents = [targetExtend, extend]; + + // only process the selector once.. if we have :extend(.a,.b) then multiple + // extends will look at the same selector path, so when extending + // we know that any others will be duplicates in terms of what is added to the css + if (targetExtend.firstExtendOnThisSelectorPath) { + newExtend.firstExtendOnThisSelectorPath = true; + targetExtend.ruleset.paths.push(newSelector); + } + }); + } + } + } + + if (extendsToAdd.length) { + // try to detect circular references to stop a stack overflow. + // may no longer be needed. + this.extendChainCount++; + if (iterationCount > 100) { + var selectorOne = "{unable to calculate}"; + var selectorTwo = "{unable to calculate}"; + try + { + selectorOne = extendsToAdd[0].selfSelectors[0].toCSS(); + selectorTwo = extendsToAdd[0].selector.toCSS(); + } + catch(e) {} + throw {message: "extend circular reference detected. One of the circular extends is currently:"+selectorOne+":extend(" + selectorTwo+")"}; + } + + // now process the new extends on the existing rules so that we can handle a extending b extending c ectending d extending e... + return extendsToAdd.concat(extendVisitor.doExtendChaining(extendsToAdd, extendsListTarget, iterationCount+1)); + } else { + return extendsToAdd; + } + }, + inInheritanceChain: function (possibleParent, possibleChild) { + if (possibleParent === possibleChild) { + return true; + } + if (possibleChild.parents) { + if (this.inInheritanceChain(possibleParent, possibleChild.parents[0])) { + return true; + } + if (this.inInheritanceChain(possibleParent, possibleChild.parents[1])) { + return true; + } + } + return false; + }, + visitRule: function (ruleNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitMixinDefinition: function (mixinDefinitionNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitSelector: function (selectorNode, visitArgs) { + visitArgs.visitDeeper = false; + }, + visitRuleset: function (rulesetNode, visitArgs) { + if (rulesetNode.root) { + return; + } + var matches, pathIndex, extendIndex, allExtends = this.allExtendsStack[this.allExtendsStack.length-1], selectorsToAdd = [], extendVisitor = this, selectorPath; + + // look at each selector path in the ruleset, find any extend matches and then copy, find and replace + + for(extendIndex = 0; extendIndex < allExtends.length; extendIndex++) { + for(pathIndex = 0; pathIndex < rulesetNode.paths.length; pathIndex++) { + + selectorPath = rulesetNode.paths[pathIndex]; + + // extending extends happens initially, before the main pass + if (selectorPath[selectorPath.length-1].extendList.length) { continue; } + + matches = this.findMatch(allExtends[extendIndex], selectorPath); + + if (matches.length) { + + allExtends[extendIndex].selfSelectors.forEach(function(selfSelector) { + selectorsToAdd.push(extendVisitor.extendSelector(matches, selectorPath, selfSelector)); + }); + } + } + } + rulesetNode.paths = rulesetNode.paths.concat(selectorsToAdd); + }, + findMatch: function (extend, haystackSelectorPath) { + // + // look through the haystack selector path to try and find the needle - extend.selector + // returns an array of selector matches that can then be replaced + // + var haystackSelectorIndex, hackstackSelector, hackstackElementIndex, haystackElement, + targetCombinator, i, + extendVisitor = this, + needleElements = extend.selector.elements, + potentialMatches = [], potentialMatch, matches = []; + + // loop through the haystack elements + for(haystackSelectorIndex = 0; haystackSelectorIndex < haystackSelectorPath.length; haystackSelectorIndex++) { + hackstackSelector = haystackSelectorPath[haystackSelectorIndex]; + + for(hackstackElementIndex = 0; hackstackElementIndex < hackstackSelector.elements.length; hackstackElementIndex++) { + + haystackElement = hackstackSelector.elements[hackstackElementIndex]; + + // if we allow elements before our match we can add a potential match every time. otherwise only at the first element. + if (extend.allowBefore || (haystackSelectorIndex == 0 && hackstackElementIndex == 0)) { + potentialMatches.push({pathIndex: haystackSelectorIndex, index: hackstackElementIndex, matched: 0, initialCombinator: haystackElement.combinator}); + } + + for(i = 0; i < potentialMatches.length; i++) { + potentialMatch = potentialMatches[i]; + + // selectors add " " onto the first element. When we use & it joins the selectors together, but if we don't + // then each selector in haystackSelectorPath has a space before it added in the toCSS phase. so we need to work out + // what the resulting combinator will be + targetCombinator = haystackElement.combinator.value; + if (targetCombinator == '' && hackstackElementIndex === 0) { + targetCombinator = ' '; + } + + // if we don't match, null our match to indicate failure + if (!extendVisitor.isElementValuesEqual(needleElements[potentialMatch.matched].value, haystackElement.value) || + (potentialMatch.matched > 0 && needleElements[potentialMatch.matched].combinator.value !== targetCombinator)) { + potentialMatch = null; + } else { + potentialMatch.matched++; + } + + // if we are still valid and have finished, test whether we have elements after and whether these are allowed + if (potentialMatch) { + potentialMatch.finished = potentialMatch.matched === needleElements.length; + if (potentialMatch.finished && + (!extend.allowAfter && (hackstackElementIndex+1 < hackstackSelector.elements.length || haystackSelectorIndex+1 < haystackSelectorPath.length))) { + potentialMatch = null; + } + } + // if null we remove, if not, we are still valid, so either push as a valid match or continue + if (potentialMatch) { + if (potentialMatch.finished) { + potentialMatch.length = needleElements.length; + potentialMatch.endPathIndex = haystackSelectorIndex; + potentialMatch.endPathElementIndex = hackstackElementIndex + 1; // index after end of match + potentialMatches.length = 0; // we don't allow matches to overlap, so start matching again + matches.push(potentialMatch); + } + } else { + potentialMatches.splice(i, 1); + i--; + } + } + } + } + return matches; + }, + isElementValuesEqual: function(elementValue1, elementValue2) { + if (typeof elementValue1 === "string" || typeof elementValue2 === "string") { + return elementValue1 === elementValue2; + } + if (elementValue1 instanceof tree.Attribute) { + if (elementValue1.op !== elementValue2.op || elementValue1.key !== elementValue2.key) { + return false; + } + if (!elementValue1.value || !elementValue2.value) { + if (elementValue1.value || elementValue2.value) { + return false; + } + return true; + } + elementValue1 = elementValue1.value.value || elementValue1.value; + elementValue2 = elementValue2.value.value || elementValue2.value; + return elementValue1 === elementValue2; + } + return false; + }, + extendSelector:function (matches, selectorPath, replacementSelector) { + + //for a set of matches, replace each match with the replacement selector + + var currentSelectorPathIndex = 0, + currentSelectorPathElementIndex = 0, + path = [], + matchIndex, + selector, + firstElement, + match; + + for (matchIndex = 0; matchIndex < matches.length; matchIndex++) { + match = matches[matchIndex]; + selector = selectorPath[match.pathIndex]; + firstElement = new tree.Element( + match.initialCombinator, + replacementSelector.elements[0].value, + replacementSelector.elements[0].index + ); + + if (match.pathIndex > currentSelectorPathIndex && currentSelectorPathElementIndex > 0) { + path[path.length - 1].elements = path[path.length - 1].elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex)); + currentSelectorPathElementIndex = 0; + currentSelectorPathIndex++; + } + + path = path.concat(selectorPath.slice(currentSelectorPathIndex, match.pathIndex)); + + path.push(new tree.Selector( + selector.elements + .slice(currentSelectorPathElementIndex, match.index) + .concat([firstElement]) + .concat(replacementSelector.elements.slice(1)) + )); + currentSelectorPathIndex = match.endPathIndex; + currentSelectorPathElementIndex = match.endPathElementIndex; + if (currentSelectorPathElementIndex >= selector.elements.length) { + currentSelectorPathElementIndex = 0; + currentSelectorPathIndex++; + } + } + + if (currentSelectorPathIndex < selectorPath.length && currentSelectorPathElementIndex > 0) { + path[path.length - 1].elements = path[path.length - 1].elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex)); + currentSelectorPathElementIndex = 0; + currentSelectorPathIndex++; + } + + path = path.concat(selectorPath.slice(currentSelectorPathIndex, selectorPath.length)); + + return path; + }, + visitRulesetOut: function (rulesetNode) { + }, + visitMedia: function (mediaNode, visitArgs) { + var newAllExtends = mediaNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]); + newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, mediaNode.allExtends)); + this.allExtendsStack.push(newAllExtends); + }, + visitMediaOut: function (mediaNode) { + this.allExtendsStack.length = this.allExtendsStack.length - 1; + }, + visitDirective: function (directiveNode, visitArgs) { + var newAllExtends = directiveNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]); + newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, directiveNode.allExtends)); + this.allExtendsStack.push(newAllExtends); + }, + visitDirectiveOut: function (directiveNode) { + this.allExtendsStack.length = this.allExtendsStack.length - 1; + } + }; + +})(require('./tree'));// +// browser.js - client-side engine +// + +var isFileProtocol = /^(file|chrome(-extension)?|resource|qrc|app):/.test(location.protocol); + +less.env = less.env || (location.hostname == '127.0.0.1' || + location.hostname == '0.0.0.0' || + location.hostname == 'localhost' || + location.port.length > 0 || + isFileProtocol ? 'development' + : 'production'); + +// Load styles asynchronously (default: false) +// +// This is set to `false` by default, so that the body +// doesn't start loading before the stylesheets are parsed. +// Setting this to `true` can result in flickering. +// +less.async = less.async || false; +less.fileAsync = less.fileAsync || false; + +// Interval between watch polls +less.poll = less.poll || (isFileProtocol ? 1000 : 1500); + +//Setup user functions +if (less.functions) { + for(var func in less.functions) { + less.tree.functions[func] = less.functions[func]; + } +} + +var dumpLineNumbers = /!dumpLineNumbers:(comments|mediaquery|all)/.exec(location.hash); +if (dumpLineNumbers) { + less.dumpLineNumbers = dumpLineNumbers[1]; +} + +// +// Watch mode +// +less.watch = function () { + if (!less.watchMode ){ + less.env = 'development'; + initRunningMode(); + } + return this.watchMode = true +}; + +less.unwatch = function () {clearInterval(less.watchTimer); return this.watchMode = false; }; + +function initRunningMode(){ + if (less.env === 'development') { + less.optimization = 0; + less.watchTimer = setInterval(function () { + if (less.watchMode) { + loadStyleSheets(function (e, root, _, sheet, env) { + if (e) { + error(e, sheet.href); + } else if (root) { + createCSS(root.toCSS(less), sheet, env.lastModified); + } + }); + } + }, less.poll); + } else { + less.optimization = 3; + } +} + +if (/!watch/.test(location.hash)) { + less.watch(); +} + +var cache = null; + +if (less.env != 'development') { + try { + cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage; + } catch (_) {} +} + +// +// Get all tags with the 'rel' attribute set to "stylesheet/less" +// +var links = document.getElementsByTagName('link'); +var typePattern = /^text\/(x-)?less$/; + +less.sheets = []; + +for (var i = 0; i < links.length; i++) { + if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) && + (links[i].type.match(typePattern)))) { + less.sheets.push(links[i]); + } +} + +// +// With this function, it's possible to alter variables and re-render +// CSS without reloading less-files +// +var session_cache = ''; +less.modifyVars = function(record) { + var str = session_cache; + for (var name in record) { + str += ((name.slice(0,1) === '@')? '' : '@') + name +': '+ + ((record[name].slice(-1) === ';')? record[name] : record[name] +';'); + } + new(less.Parser)(new less.tree.parseEnv(less)).parse(str, function (e, root) { + if (e) { + error(e, "session_cache"); + } else { + createCSS(root.toCSS(less), less.sheets[less.sheets.length - 1]); + } + }); +}; + +less.refresh = function (reload) { + var startTime, endTime; + startTime = endTime = new(Date); + + loadStyleSheets(function (e, root, _, sheet, env) { + if (e) { + return error(e, sheet.href); + } + if (env.local) { + log("loading " + sheet.href + " from cache."); + } else { + log("parsed " + sheet.href + " successfully."); + createCSS(root.toCSS(less), sheet, env.lastModified); + } + log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms'); + (env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms'); + endTime = new(Date); + }, reload); + + loadStyles(); +}; +less.refreshStyles = loadStyles; + +less.refresh(less.env === 'development'); + +function loadStyles() { + var styles = document.getElementsByTagName('style'); + for (var i = 0; i < styles.length; i++) { + if (styles[i].type.match(typePattern)) { + var env = new less.tree.parseEnv(less); + env.filename = document.location.href.replace(/#.*$/, ''); + + new(less.Parser)(env).parse(styles[i].innerHTML || '', function (e, cssAST) { + if (e) { + return error(e, "inline"); + } + var css = cssAST.toCSS(less); + var style = styles[i]; + style.type = 'text/css'; + if (style.styleSheet) { + style.styleSheet.cssText = css; + } else { + style.innerHTML = css; + } + }); + } + } +} + +function loadStyleSheets(callback, reload) { + for (var i = 0; i < less.sheets.length; i++) { + loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1)); + } +} + +function pathDiff(url, baseUrl) { + // diff between two paths to create a relative path + + var urlParts = extractUrlParts(url), + baseUrlParts = extractUrlParts(baseUrl), + i, max, urlDirectories, baseUrlDirectories, diff = ""; + if (urlParts.hostPart !== baseUrlParts.hostPart) { + return ""; + } + max = Math.max(baseUrlParts.directories.length, urlParts.directories.length); + for(i = 0; i < max; i++) { + if (baseUrlParts.directories[i] !== urlParts.directories[i]) { break; } + } + baseUrlDirectories = baseUrlParts.directories.slice(i); + urlDirectories = urlParts.directories.slice(i); + for(i = 0; i < baseUrlDirectories.length-1; i++) { + diff += "../"; + } + for(i = 0; i < urlDirectories.length-1; i++) { + diff += urlDirectories[i] + "/"; + } + return diff; +} + +function extractUrlParts(url, baseUrl) { + // urlParts[1] = protocol&hostname || / + // urlParts[2] = / if path relative to host base + // urlParts[3] = directories + // urlParts[4] = filename + // urlParts[5] = parameters + + var urlPartsRegex = /^((?:[a-z-]+:)?\/+?(?:[^\/\?#]*\/)|([\/\\]))?((?:[^\/\\\?#]*[\/\\])*)([^\/\\\?#]*)([#\?].*)?$/i, + urlParts = url.match(urlPartsRegex), + returner = {}, directories = [], i, baseUrlParts; + + if (!urlParts) { + throw new Error("Could not parse sheet href - '"+url+"'"); + } + + // Stylesheets in IE don't always return the full path + if (!urlParts[1] || urlParts[2]) { + baseUrlParts = baseUrl.match(urlPartsRegex); + if (!baseUrlParts) { + throw new Error("Could not parse page url - '"+baseUrl+"'"); + } + urlParts[1] = urlParts[1] || baseUrlParts[1] || ""; + if (!urlParts[2]) { + urlParts[3] = baseUrlParts[3] + urlParts[3]; + } + } + + if (urlParts[3]) { + directories = urlParts[3].replace(/\\/g, "/").split("/"); + + // extract out . before .. so .. doesn't absorb a non-directory + for(i = 0; i < directories.length; i++) { + if (directories[i] === ".") { + directories.splice(i, 1); + i -= 1; + } + } + + for(i = 0; i < directories.length; i++) { + if (directories[i] === ".." && i > 0) { + directories.splice(i-1, 2); + i -= 2; + } + } + } + + returner.hostPart = urlParts[1]; + returner.directories = directories; + returner.path = urlParts[1] + directories.join("/"); + returner.fileUrl = returner.path + (urlParts[4] || ""); + returner.url = returner.fileUrl + (urlParts[5] || ""); + return returner; +} + +function loadStyleSheet(sheet, callback, reload, remaining) { + + // sheet may be set to the stylesheet for the initial load or a collection of properties including + // some env variables for imports + var hrefParts = extractUrlParts(sheet.href, window.location.href); + var href = hrefParts.url; + var css = cache && cache.getItem(href); + var timestamp = cache && cache.getItem(href + ':timestamp'); + var styles = { css: css, timestamp: timestamp }; + var env; + var newFileInfo = { + relativeUrls: less.relativeUrls, + currentDirectory: hrefParts.path, + filename: href + }; + + if (sheet instanceof less.tree.parseEnv) { + env = new less.tree.parseEnv(sheet); + newFileInfo.entryPath = env.currentFileInfo.entryPath; + newFileInfo.rootpath = env.currentFileInfo.rootpath; + newFileInfo.rootFilename = env.currentFileInfo.rootFilename; + } else { + env = new less.tree.parseEnv(less); + env.mime = sheet.type; + newFileInfo.entryPath = hrefParts.path; + newFileInfo.rootpath = less.rootpath || hrefParts.path; + newFileInfo.rootFilename = href; + } + + if (env.relativeUrls) { + //todo - this relies on option being set on less object rather than being passed in as an option + // - need an originalRootpath + if (less.rootpath) { + newFileInfo.rootpath = extractUrlParts(less.rootpath + pathDiff(hrefParts.path, newFileInfo.entryPath)).path; + } else { + newFileInfo.rootpath = hrefParts.path; + } + } + + xhr(href, sheet.type, function (data, lastModified) { + // Store data this session + session_cache += data.replace(/@import .+?;/ig, ''); + + if (!reload && styles && lastModified && + (new(Date)(lastModified).valueOf() === + new(Date)(styles.timestamp).valueOf())) { + // Use local copy + createCSS(styles.css, sheet); + callback(null, null, data, sheet, { local: true, remaining: remaining }, href); + } else { + // Use remote copy (re-parse) + try { + env.contents[href] = data; // Updating content cache + env.paths = [hrefParts.path]; + env.currentFileInfo = newFileInfo; + + new(less.Parser)(env).parse(data, function (e, root) { + if (e) { return callback(e, null, null, sheet); } + try { + callback(e, root, data, sheet, { local: false, lastModified: lastModified, remaining: remaining }, href); + //TODO - there must be a better way? A generic less-to-css function that can both call error + //and removeNode where appropriate + //should also add tests + if (env.currentFileInfo.rootFilename === href) { + removeNode(document.getElementById('less-error-message:' + extractId(href))); + } + } catch (e) { + callback(e, null, null, sheet); + } + }); + } catch (e) { + callback(e, null, null, sheet); + } + } + }, function (status, url) { + callback({ type: 'File', message: "'" + url + "' wasn't found (" + status + ")" }, null, null, sheet); + }); +} + +function extractId(href) { + return href.replace(/^[a-z-]+:\/+?[^\/]+/, '' ) // Remove protocol & domain + .replace(/^\//, '' ) // Remove root / + .replace(/\.[a-zA-Z]+$/, '' ) // Remove simple extension + .replace(/[^\.\w-]+/g, '-') // Replace illegal characters + .replace(/\./g, ':'); // Replace dots with colons(for valid id) +} + +function createCSS(styles, sheet, lastModified) { + // Strip the query-string + var href = sheet.href || ''; + + // If there is no title set, use the filename, minus the extension + var id = 'less:' + (sheet.title || extractId(href)); + + // If this has already been inserted into the DOM, we may need to replace it + var oldCss = document.getElementById(id); + var keepOldCss = false; + + // Create a new stylesheet node for insertion or (if necessary) replacement + var css = document.createElement('style'); + css.setAttribute('type', 'text/css'); + if (sheet.media) { + css.setAttribute('media', sheet.media); + } + css.id = id; + + if (css.styleSheet) { // IE + try { + css.styleSheet.cssText = styles; + } catch (e) { + throw new(Error)("Couldn't reassign styleSheet.cssText."); + } + } else { + css.appendChild(document.createTextNode(styles)); + + // If new contents match contents of oldCss, don't replace oldCss + keepOldCss = (oldCss !== null && oldCss.childNodes.length > 0 && css.childNodes.length > 0 && + oldCss.firstChild.nodeValue === css.firstChild.nodeValue); + } + + var head = document.getElementsByTagName('head')[0]; + + // If there is no oldCss, just append; otherwise, only append if we need + // to replace oldCss with an updated stylesheet + if (oldCss == null || keepOldCss === false) { + var nextEl = sheet && sheet.nextSibling || null; + (nextEl || document.getElementsByTagName('head')[0]).parentNode.insertBefore(css, nextEl); + } + if (oldCss && keepOldCss === false) { + head.removeChild(oldCss); + } + + // Don't update the local store if the file wasn't modified + if (lastModified && cache) { + log('saving ' + href + ' to cache.'); + try { + cache.setItem(href, styles); + cache.setItem(href + ':timestamp', lastModified); + } catch(e) { + //TODO - could do with adding more robust error handling + log('failed to save'); + } + } +} + +function xhr(url, type, callback, errback) { + var xhr = getXMLHttpRequest(); + var async = isFileProtocol ? less.fileAsync : less.async; + + if (typeof(xhr.overrideMimeType) === 'function') { + xhr.overrideMimeType('text/css'); + } + xhr.open('GET', url, async); + xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5'); + xhr.send(null); + + if (isFileProtocol && !less.fileAsync) { + if (xhr.status === 0 || (xhr.status >= 200 && xhr.status < 300)) { + callback(xhr.responseText); + } else { + errback(xhr.status, url); + } + } else if (async) { + xhr.onreadystatechange = function () { + if (xhr.readyState == 4) { + handleResponse(xhr, callback, errback); + } + }; + } else { + handleResponse(xhr, callback, errback); + } + + function handleResponse(xhr, callback, errback) { + if (xhr.status >= 200 && xhr.status < 300) { + callback(xhr.responseText, + xhr.getResponseHeader("Last-Modified")); + } else if (typeof(errback) === 'function') { + errback(xhr.status, url); + } + } +} + +function getXMLHttpRequest() { + if (window.XMLHttpRequest) { + return new(XMLHttpRequest); + } else { + try { + return new(ActiveXObject)("MSXML2.XMLHTTP.3.0"); + } catch (e) { + log("browser doesn't support AJAX."); + return null; + } + } +} + +function removeNode(node) { + return node && node.parentNode.removeChild(node); +} + +function log(str) { + if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) } +} + +function error(e, rootHref) { + var id = 'less-error-message:' + extractId(rootHref || ""); + var template = '
  • {content}
  • '; + var elem = document.createElement('div'), timer, content, error = []; + var filename = e.filename || rootHref; + var filenameNoPath = filename.match(/([^\/]+(\?.*)?)$/)[1]; + + elem.id = id; + elem.className = "less-error-message"; + + content = '

    ' + (e.type || "Syntax") + "Error: " + (e.message || 'There is an error in your .less file') + + '

    ' + '

    in ' + filenameNoPath + " "; + + var errorline = function (e, i, classname) { + if (e.extract[i] != undefined) { + error.push(template.replace(/\{line\}/, (parseInt(e.line) || 0) + (i - 1)) + .replace(/\{class\}/, classname) + .replace(/\{content\}/, e.extract[i])); + } + }; + + if (e.extract) { + errorline(e, 0, ''); + errorline(e, 1, 'line'); + errorline(e, 2, ''); + content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':

    ' + + '
      ' + error.join('') + '
    '; + } else if (e.stack) { + content += '
    ' + e.stack.split('\n').slice(1).join('
    '); + } + elem.innerHTML = content; + + // CSS for error messages + createCSS([ + '.less-error-message ul, .less-error-message li {', + 'list-style-type: none;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'margin: 0;', + '}', + '.less-error-message label {', + 'font-size: 12px;', + 'margin-right: 15px;', + 'padding: 4px 0;', + 'color: #cc7777;', + '}', + '.less-error-message pre {', + 'color: #dd6666;', + 'padding: 4px 0;', + 'margin: 0;', + 'display: inline-block;', + '}', + '.less-error-message pre.line {', + 'color: #ff0000;', + '}', + '.less-error-message h3 {', + 'font-size: 20px;', + 'font-weight: bold;', + 'padding: 15px 0 5px 0;', + 'margin: 0;', + '}', + '.less-error-message a {', + 'color: #10a', + '}', + '.less-error-message .error {', + 'color: red;', + 'font-weight: bold;', + 'padding-bottom: 2px;', + 'border-bottom: 1px dashed red;', + '}' + ].join('\n'), { title: 'error-message' }); + + elem.style.cssText = [ + "font-family: Arial, sans-serif", + "border: 1px solid #e00", + "background-color: #eee", + "border-radius: 5px", + "-webkit-border-radius: 5px", + "-moz-border-radius: 5px", + "color: #e00", + "padding: 15px", + "margin-bottom: 15px" + ].join(';'); + + if (less.env == 'development') { + timer = setInterval(function () { + if (document.body) { + if (document.getElementById(id)) { + document.body.replaceChild(elem, document.getElementById(id)); + } else { + document.body.insertBefore(elem, document.body.firstChild); + } + clearInterval(timer); + } + }, 10); + } +} +// amd.js +// +// Define Less as an AMD module. +if (typeof define === "function" && define.amd) { + define(function () { return less; } ); +} +})(window);