From f52f223bcc9e67f203282a03fa76bbcdc98568c3 Mon Sep 17 00:00:00 2001 From: Max Goodman Date: Wed, 7 Nov 2012 13:54:54 -0800 Subject: [PATCH] Add temporary bundled copy of less.js. This is for use until we have less.js packaged in production. --- r2/Makefile | 2 +- r2/r2/lib/contrib/less.js/CHANGELOG | 41 + r2/r2/lib/contrib/less.js/LICENSE | 179 + r2/r2/lib/contrib/less.js/Makefile | 75 + r2/r2/lib/contrib/less.js/README.md | 20 + .../contrib/less.js/benchmark/benchmark.less | 3979 +++++++++++++++++ .../less.js/benchmark/less-benchmark.js | 47 + r2/r2/lib/contrib/less.js/bin/lessc | 143 + r2/r2/lib/contrib/less.js/lib/less/browser.js | 380 ++ r2/r2/lib/contrib/less.js/lib/less/colors.js | 152 + r2/r2/lib/contrib/less.js/lib/less/cssmin.js | 355 ++ .../lib/contrib/less.js/lib/less/functions.js | 228 + r2/r2/lib/contrib/less.js/lib/less/index.js | 148 + r2/r2/lib/contrib/less.js/lib/less/parser.js | 1334 ++++++ r2/r2/lib/contrib/less.js/lib/less/rhino.js | 62 + r2/r2/lib/contrib/less.js/lib/less/tree.js | 17 + .../contrib/less.js/lib/less/tree/alpha.js | 17 + .../less.js/lib/less/tree/anonymous.js | 13 + .../less.js/lib/less/tree/assignment.js | 17 + .../lib/contrib/less.js/lib/less/tree/call.js | 48 + .../contrib/less.js/lib/less/tree/color.js | 101 + .../contrib/less.js/lib/less/tree/comment.js | 14 + .../less.js/lib/less/tree/condition.js | 42 + .../less.js/lib/less/tree/dimension.js | 49 + .../less.js/lib/less/tree/directive.js | 35 + .../contrib/less.js/lib/less/tree/element.js | 52 + .../less.js/lib/less/tree/expression.js | 23 + .../contrib/less.js/lib/less/tree/import.js | 83 + .../less.js/lib/less/tree/javascript.js | 51 + .../contrib/less.js/lib/less/tree/keyword.js | 19 + .../contrib/less.js/lib/less/tree/media.js | 114 + .../contrib/less.js/lib/less/tree/mixin.js | 146 + .../less.js/lib/less/tree/operation.js | 32 + .../contrib/less.js/lib/less/tree/paren.js | 16 + .../contrib/less.js/lib/less/tree/quoted.js | 29 + .../lib/contrib/less.js/lib/less/tree/rule.js | 42 + .../contrib/less.js/lib/less/tree/ruleset.js | 225 + .../contrib/less.js/lib/less/tree/selector.js | 42 + .../lib/contrib/less.js/lib/less/tree/url.js | 25 + .../contrib/less.js/lib/less/tree/value.js | 24 + .../contrib/less.js/lib/less/tree/variable.js | 26 + r2/r2/lib/contrib/less.js/package.json | 13 + r2/r2/lib/contrib/less.js/test/css/colors.css | 58 + .../lib/contrib/less.js/test/css/comments.css | 56 + r2/r2/lib/contrib/less.js/test/css/css-3.css | 58 + .../contrib/less.js/test/css/css-escapes.css | 20 + r2/r2/lib/contrib/less.js/test/css/css.css | 89 + .../contrib/less.js/test/css/functions.css | 43 + .../contrib/less.js/test/css/ie-filters.css | 5 + .../contrib/less.js/test/css/import-once.css | 9 + r2/r2/lib/contrib/less.js/test/css/import.css | 23 + .../contrib/less.js/test/css/javascript.css | 22 + .../contrib/less.js/test/css/lazy-eval.css | 3 + r2/r2/lib/contrib/less.js/test/css/media.css | 79 + .../contrib/less.js/test/css/mixins-args.css | 74 + .../less.js/test/css/mixins-closure.css | 9 + .../less.js/test/css/mixins-guards.css | 58 + .../less.js/test/css/mixins-important.css | 17 + .../less.js/test/css/mixins-named-args.css | 20 + .../less.js/test/css/mixins-nested.css | 14 + .../less.js/test/css/mixins-pattern.css | 47 + r2/r2/lib/contrib/less.js/test/css/mixins.css | 71 + .../contrib/less.js/test/css/operations.css | 49 + r2/r2/lib/contrib/less.js/test/css/parens.css | 20 + .../lib/contrib/less.js/test/css/rulesets.css | 33 + r2/r2/lib/contrib/less.js/test/css/scope.css | 15 + .../contrib/less.js/test/css/selectors.css | 69 + .../lib/contrib/less.js/test/css/strings.css | 40 + .../contrib/less.js/test/css/variables.css | 27 + .../contrib/less.js/test/css/whitespace.css | 38 + r2/r2/lib/contrib/less.js/test/less-test.js | 73 + .../lib/contrib/less.js/test/less/colors.less | 65 + .../contrib/less.js/test/less/comments.less | 65 + .../lib/contrib/less.js/test/less/css-3.less | 65 + .../less.js/test/less/css-escapes.less | 28 + r2/r2/lib/contrib/less.js/test/less/css.less | 100 + .../contrib/less.js/test/less/functions.less | 49 + .../contrib/less.js/test/less/ie-filters.less | 8 + .../less.js/test/less/import-once.less | 3 + .../lib/contrib/less.js/test/less/import.less | 11 + .../test/less/import/import-test-a.less | 2 + .../test/less/import/import-test-b.less | 8 + .../test/less/import/import-test-c.less | 7 + .../test/less/import/import-test-d.css | 1 + .../test/less/import/import-test-e.less | 2 + .../contrib/less.js/test/less/javascript.less | 27 + .../contrib/less.js/test/less/lazy-eval.less | 6 + .../lib/contrib/less.js/test/less/media.less | 79 + .../less.js/test/less/mixins-args.less | 130 + .../less.js/test/less/mixins-closure.less | 26 + .../less.js/test/less/mixins-guards.less | 94 + .../less.js/test/less/mixins-important.less | 18 + .../less.js/test/less/mixins-named-args.less | 31 + .../less.js/test/less/mixins-nested.less | 22 + .../less.js/test/less/mixins-pattern.less | 99 + .../lib/contrib/less.js/test/less/mixins.less | 67 + .../contrib/less.js/test/less/operations.less | 62 + .../lib/contrib/less.js/test/less/parens.less | 26 + .../contrib/less.js/test/less/rulesets.less | 30 + .../lib/contrib/less.js/test/less/scope.less | 32 + .../contrib/less.js/test/less/selectors.less | 55 + .../contrib/less.js/test/less/strings.less | 51 + .../contrib/less.js/test/less/variables.less | 54 + .../contrib/less.js/test/less/whitespace.less | 37 + 104 files changed, 10958 insertions(+), 1 deletion(-) create mode 100644 r2/r2/lib/contrib/less.js/CHANGELOG create mode 100644 r2/r2/lib/contrib/less.js/LICENSE create mode 100644 r2/r2/lib/contrib/less.js/Makefile create mode 100644 r2/r2/lib/contrib/less.js/README.md create mode 100644 r2/r2/lib/contrib/less.js/benchmark/benchmark.less create mode 100644 r2/r2/lib/contrib/less.js/benchmark/less-benchmark.js create mode 100755 r2/r2/lib/contrib/less.js/bin/lessc create mode 100644 r2/r2/lib/contrib/less.js/lib/less/browser.js create mode 100644 r2/r2/lib/contrib/less.js/lib/less/colors.js create mode 100644 r2/r2/lib/contrib/less.js/lib/less/cssmin.js create mode 100644 r2/r2/lib/contrib/less.js/lib/less/functions.js create mode 100644 r2/r2/lib/contrib/less.js/lib/less/index.js create mode 100644 r2/r2/lib/contrib/less.js/lib/less/parser.js create mode 100644 r2/r2/lib/contrib/less.js/lib/less/rhino.js create mode 100644 r2/r2/lib/contrib/less.js/lib/less/tree.js create mode 100644 r2/r2/lib/contrib/less.js/lib/less/tree/alpha.js create mode 100644 r2/r2/lib/contrib/less.js/lib/less/tree/anonymous.js create mode 100644 r2/r2/lib/contrib/less.js/lib/less/tree/assignment.js create mode 100644 r2/r2/lib/contrib/less.js/lib/less/tree/call.js create mode 100644 r2/r2/lib/contrib/less.js/lib/less/tree/color.js create mode 100644 r2/r2/lib/contrib/less.js/lib/less/tree/comment.js create mode 100644 r2/r2/lib/contrib/less.js/lib/less/tree/condition.js create mode 100644 r2/r2/lib/contrib/less.js/lib/less/tree/dimension.js create mode 100644 r2/r2/lib/contrib/less.js/lib/less/tree/directive.js create mode 100644 r2/r2/lib/contrib/less.js/lib/less/tree/element.js create mode 100644 r2/r2/lib/contrib/less.js/lib/less/tree/expression.js create mode 100644 r2/r2/lib/contrib/less.js/lib/less/tree/import.js create mode 100644 r2/r2/lib/contrib/less.js/lib/less/tree/javascript.js create mode 100644 r2/r2/lib/contrib/less.js/lib/less/tree/keyword.js create mode 100644 r2/r2/lib/contrib/less.js/lib/less/tree/media.js create mode 100644 r2/r2/lib/contrib/less.js/lib/less/tree/mixin.js create mode 100644 r2/r2/lib/contrib/less.js/lib/less/tree/operation.js create mode 100644 r2/r2/lib/contrib/less.js/lib/less/tree/paren.js create mode 100644 r2/r2/lib/contrib/less.js/lib/less/tree/quoted.js create mode 100644 r2/r2/lib/contrib/less.js/lib/less/tree/rule.js create mode 100644 r2/r2/lib/contrib/less.js/lib/less/tree/ruleset.js create mode 100644 r2/r2/lib/contrib/less.js/lib/less/tree/selector.js create mode 100644 r2/r2/lib/contrib/less.js/lib/less/tree/url.js create mode 100644 r2/r2/lib/contrib/less.js/lib/less/tree/value.js create mode 100644 r2/r2/lib/contrib/less.js/lib/less/tree/variable.js create mode 100644 r2/r2/lib/contrib/less.js/package.json create mode 100644 r2/r2/lib/contrib/less.js/test/css/colors.css create mode 100644 r2/r2/lib/contrib/less.js/test/css/comments.css create mode 100644 r2/r2/lib/contrib/less.js/test/css/css-3.css create mode 100644 r2/r2/lib/contrib/less.js/test/css/css-escapes.css create mode 100644 r2/r2/lib/contrib/less.js/test/css/css.css create mode 100644 r2/r2/lib/contrib/less.js/test/css/functions.css create mode 100644 r2/r2/lib/contrib/less.js/test/css/ie-filters.css create mode 100644 r2/r2/lib/contrib/less.js/test/css/import-once.css create mode 100644 r2/r2/lib/contrib/less.js/test/css/import.css create mode 100644 r2/r2/lib/contrib/less.js/test/css/javascript.css create mode 100644 r2/r2/lib/contrib/less.js/test/css/lazy-eval.css create mode 100644 r2/r2/lib/contrib/less.js/test/css/media.css create mode 100644 r2/r2/lib/contrib/less.js/test/css/mixins-args.css create mode 100644 r2/r2/lib/contrib/less.js/test/css/mixins-closure.css create mode 100644 r2/r2/lib/contrib/less.js/test/css/mixins-guards.css create mode 100644 r2/r2/lib/contrib/less.js/test/css/mixins-important.css create mode 100644 r2/r2/lib/contrib/less.js/test/css/mixins-named-args.css create mode 100644 r2/r2/lib/contrib/less.js/test/css/mixins-nested.css create mode 100644 r2/r2/lib/contrib/less.js/test/css/mixins-pattern.css create mode 100644 r2/r2/lib/contrib/less.js/test/css/mixins.css create mode 100644 r2/r2/lib/contrib/less.js/test/css/operations.css create mode 100644 r2/r2/lib/contrib/less.js/test/css/parens.css create mode 100644 r2/r2/lib/contrib/less.js/test/css/rulesets.css create mode 100644 r2/r2/lib/contrib/less.js/test/css/scope.css create mode 100644 r2/r2/lib/contrib/less.js/test/css/selectors.css create mode 100644 r2/r2/lib/contrib/less.js/test/css/strings.css create mode 100644 r2/r2/lib/contrib/less.js/test/css/variables.css create mode 100644 r2/r2/lib/contrib/less.js/test/css/whitespace.css create mode 100644 r2/r2/lib/contrib/less.js/test/less-test.js create mode 100644 r2/r2/lib/contrib/less.js/test/less/colors.less create mode 100644 r2/r2/lib/contrib/less.js/test/less/comments.less create mode 100644 r2/r2/lib/contrib/less.js/test/less/css-3.less create mode 100644 r2/r2/lib/contrib/less.js/test/less/css-escapes.less create mode 100644 r2/r2/lib/contrib/less.js/test/less/css.less create mode 100644 r2/r2/lib/contrib/less.js/test/less/functions.less create mode 100644 r2/r2/lib/contrib/less.js/test/less/ie-filters.less create mode 100644 r2/r2/lib/contrib/less.js/test/less/import-once.less create mode 100644 r2/r2/lib/contrib/less.js/test/less/import.less create mode 100644 r2/r2/lib/contrib/less.js/test/less/import/import-test-a.less create mode 100644 r2/r2/lib/contrib/less.js/test/less/import/import-test-b.less create mode 100644 r2/r2/lib/contrib/less.js/test/less/import/import-test-c.less create mode 100644 r2/r2/lib/contrib/less.js/test/less/import/import-test-d.css create mode 100644 r2/r2/lib/contrib/less.js/test/less/import/import-test-e.less create mode 100644 r2/r2/lib/contrib/less.js/test/less/javascript.less create mode 100644 r2/r2/lib/contrib/less.js/test/less/lazy-eval.less create mode 100644 r2/r2/lib/contrib/less.js/test/less/media.less create mode 100644 r2/r2/lib/contrib/less.js/test/less/mixins-args.less create mode 100644 r2/r2/lib/contrib/less.js/test/less/mixins-closure.less create mode 100644 r2/r2/lib/contrib/less.js/test/less/mixins-guards.less create mode 100644 r2/r2/lib/contrib/less.js/test/less/mixins-important.less create mode 100644 r2/r2/lib/contrib/less.js/test/less/mixins-named-args.less create mode 100644 r2/r2/lib/contrib/less.js/test/less/mixins-nested.less create mode 100644 r2/r2/lib/contrib/less.js/test/less/mixins-pattern.less create mode 100644 r2/r2/lib/contrib/less.js/test/less/mixins.less create mode 100644 r2/r2/lib/contrib/less.js/test/less/operations.less create mode 100644 r2/r2/lib/contrib/less.js/test/less/parens.less create mode 100644 r2/r2/lib/contrib/less.js/test/less/rulesets.less create mode 100644 r2/r2/lib/contrib/less.js/test/less/scope.less create mode 100644 r2/r2/lib/contrib/less.js/test/less/selectors.less create mode 100644 r2/r2/lib/contrib/less.js/test/less/strings.less create mode 100644 r2/r2/lib/contrib/less.js/test/less/variables.less create mode 100644 r2/r2/lib/contrib/less.js/test/less/whitespace.less diff --git a/r2/Makefile b/r2/Makefile index b4e52d558..3bd992c69 100644 --- a/r2/Makefile +++ b/r2/Makefile @@ -135,7 +135,7 @@ endef $(foreach plugin,$(PLUGINS),$(eval $(call PLUGIN_STATIC_TEMPLATE,$(plugin)))) #### Stylesheets -LESSC := lessc +LESSC := r2/lib/contrib/less.js/bin/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 new file mode 100644 index 000000000..b72af3357 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/CHANGELOG @@ -0,0 +1,41 @@ +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 new file mode 100644 index 000000000..40f3b781b --- /dev/null +++ b/r2/r2/lib/contrib/less.js/LICENSE @@ -0,0 +1,179 @@ + + 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 new file mode 100644 index 000000000..32d7cc044 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/Makefile @@ -0,0 +1,75 @@ +# +# 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 new file mode 100644 index 000000000..726d6910f --- /dev/null +++ b/r2/r2/lib/contrib/less.js/README.md @@ -0,0 +1,20 @@ +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 new file mode 100644 index 000000000..bf7fef73a --- /dev/null +++ b/r2/r2/lib/contrib/less.js/benchmark/benchmark.less @@ -0,0 +1,3979 @@ +@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 new file mode 100644 index 000000000..68fe1ad4c --- /dev/null +++ b/r2/r2/lib/contrib/less.js/benchmark/less-benchmark.js @@ -0,0 +1,47 @@ +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 new file mode 100755 index 000000000..9855e851a --- /dev/null +++ b/r2/r2/lib/contrib/less.js/bin/lessc @@ -0,0 +1,143 @@ +#!/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 new file mode 100644 index 000000000..cab913be0 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/lib/less/browser.js @@ -0,0 +1,380 @@ +// +// 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) + ':

    ' + + '
      ' + error.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); + } +} + diff --git a/r2/r2/lib/contrib/less.js/lib/less/colors.js b/r2/r2/lib/contrib/less.js/lib/less/colors.js new file mode 100644 index 000000000..ed4c2838b --- /dev/null +++ b/r2/r2/lib/contrib/less.js/lib/less/colors.js @@ -0,0 +1,152 @@ +(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 new file mode 100644 index 000000000..427de71c0 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/lib/less/cssmin.js @@ -0,0 +1,355 @@ +/** + * 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 new file mode 100644 index 000000000..6eb34bac8 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/lib/less/functions.js @@ -0,0 +1,228 @@ +(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 new file mode 100644 index 000000000..a11fa998d --- /dev/null +++ b/r2/r2/lib/contrib/less.js/lib/less/index.js @@ -0,0 +1,148 @@ +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 new file mode 100644 index 000000000..d732e1b15 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/lib/less/parser.js @@ -0,0 +1,1334 @@ +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 new file mode 100644 index 000000000..a2c5662fd --- /dev/null +++ b/r2/r2/lib/contrib/less.js/lib/less/rhino.js @@ -0,0 +1,62 @@ +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 new file mode 100644 index 000000000..24ecd7120 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/lib/less/tree.js @@ -0,0 +1,17 @@ +(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 new file mode 100644 index 000000000..139ae9204 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/lib/less/tree/alpha.js @@ -0,0 +1,17 @@ +(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 new file mode 100644 index 000000000..460c9ec78 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/lib/less/tree/anonymous.js @@ -0,0 +1,13 @@ +(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 new file mode 100644 index 000000000..70ce6e2f0 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/lib/less/tree/assignment.js @@ -0,0 +1,17 @@ +(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 new file mode 100644 index 000000000..c1465dd47 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/lib/less/tree/call.js @@ -0,0 +1,48 @@ +(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 new file mode 100644 index 000000000..37ce1781d --- /dev/null +++ b/r2/r2/lib/contrib/less.js/lib/less/tree/color.js @@ -0,0 +1,101 @@ +(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 new file mode 100644 index 000000000..f4a33840d --- /dev/null +++ b/r2/r2/lib/contrib/less.js/lib/less/tree/comment.js @@ -0,0 +1,14 @@ +(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 new file mode 100644 index 000000000..6b79dc960 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/lib/less/tree/condition.js @@ -0,0 +1,42 @@ +(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 new file mode 100644 index 000000000..9a6fce3dd --- /dev/null +++ b/r2/r2/lib/contrib/less.js/lib/less/tree/dimension.js @@ -0,0 +1,49 @@ +(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 new file mode 100644 index 000000000..27538332a --- /dev/null +++ b/r2/r2/lib/contrib/less.js/lib/less/tree/directive.js @@ -0,0 +1,35 @@ +(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 new file mode 100644 index 000000000..14b08d2ea --- /dev/null +++ b/r2/r2/lib/contrib/less.js/lib/less/tree/element.js @@ -0,0 +1,52 @@ +(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 new file mode 100644 index 000000000..fbfa9c5b7 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/lib/less/tree/expression.js @@ -0,0 +1,23 @@ +(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 new file mode 100644 index 000000000..7a977def2 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/lib/less/tree/import.js @@ -0,0 +1,83 @@ +(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 new file mode 100644 index 000000000..772a31ddd --- /dev/null +++ b/r2/r2/lib/contrib/less.js/lib/less/tree/javascript.js @@ -0,0 +1,51 @@ +(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 new file mode 100644 index 000000000..701b79e57 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/lib/less/tree/keyword.js @@ -0,0 +1,19 @@ +(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 new file mode 100644 index 000000000..2b7b26e58 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/lib/less/tree/media.js @@ -0,0 +1,114 @@ +(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 new file mode 100644 index 000000000..b441bf3b2 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/lib/less/tree/mixin.js @@ -0,0 +1,146 @@ +(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 new file mode 100644 index 000000000..1ce22fb04 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/lib/less/tree/operation.js @@ -0,0 +1,32 @@ +(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 new file mode 100644 index 000000000..384a43c74 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/lib/less/tree/paren.js @@ -0,0 +1,16 @@ + +(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 new file mode 100644 index 000000000..794bf4cea --- /dev/null +++ b/r2/r2/lib/contrib/less.js/lib/less/tree/quoted.js @@ -0,0 +1,29 @@ +(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 new file mode 100644 index 000000000..9e4e54a3a --- /dev/null +++ b/r2/r2/lib/contrib/less.js/lib/less/tree/rule.js @@ -0,0 +1,42 @@ +(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 new file mode 100644 index 000000000..3100cc354 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/lib/less/tree/ruleset.js @@ -0,0 +1,225 @@ +(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 new file mode 100644 index 000000000..65abbb692 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/lib/less/tree/selector.js @@ -0,0 +1,42 @@ +(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 new file mode 100644 index 000000000..0caec3458 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/lib/less/tree/url.js @@ -0,0 +1,25 @@ +(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 new file mode 100644 index 000000000..3c1eb29a2 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/lib/less/tree/value.js @@ -0,0 +1,24 @@ +(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 new file mode 100644 index 000000000..ee557e1df --- /dev/null +++ b/r2/r2/lib/contrib/less.js/lib/less/tree/variable.js @@ -0,0 +1,26 @@ +(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 new file mode 100644 index 000000000..c57989b6d --- /dev/null +++ b/r2/r2/lib/contrib/less.js/package.json @@ -0,0 +1,13 @@ +{ + "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 new file mode 100644 index 000000000..b4516425a --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/css/colors.css @@ -0,0 +1,58 @@ +#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 new file mode 100644 index 000000000..352dd48e3 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/css/comments.css @@ -0,0 +1,56 @@ +/******************\ +* * +* 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 new file mode 100644 index 000000000..45bdc40dc --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/css/css-3.css @@ -0,0 +1,58 @@ +.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 new file mode 100644 index 000000000..278d55763 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/css/css-escapes.css @@ -0,0 +1,20 @@ +.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 new file mode 100644 index 000000000..63d20ec43 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/css/css.css @@ -0,0 +1,89 @@ +@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 new file mode 100644 index 000000000..a0f9bd03c --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/css/functions.css @@ -0,0 +1,43 @@ +#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 new file mode 100644 index 000000000..933318abf --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/css/ie-filters.css @@ -0,0 +1,5 @@ +.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 new file mode 100644 index 000000000..3a1ae2507 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/css/import-once.css @@ -0,0 +1,9 @@ +@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 new file mode 100644 index 000000000..89dc162c5 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/css/import.css @@ -0,0 +1,23 @@ +@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 new file mode 100644 index 000000000..df48f505c --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/css/javascript.css @@ -0,0 +1,22 @@ +.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 new file mode 100644 index 000000000..1adfb8f38 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/css/lazy-eval.css @@ -0,0 +1,3 @@ +.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 new file mode 100644 index 000000000..61d169df8 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/css/media.css @@ -0,0 +1,79 @@ +@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 new file mode 100644 index 000000000..d5b67f304 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/css/mixins-args.css @@ -0,0 +1,74 @@ +#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 new file mode 100644 index 000000000..b1021b6fb --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/css/mixins-closure.css @@ -0,0 +1,9 @@ +.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 new file mode 100644 index 000000000..0c563e529 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/css/mixins-guards.css @@ -0,0 +1,58 @@ +.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 new file mode 100644 index 000000000..2f74c6476 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/css/mixins-important.css @@ -0,0 +1,17 @@ +.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 new file mode 100644 index 000000000..1c1afaf8f --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/css/mixins-named-args.css @@ -0,0 +1,20 @@ +.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 new file mode 100644 index 000000000..6378c4756 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/css/mixins-nested.css @@ -0,0 +1,14 @@ +.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 new file mode 100644 index 000000000..8b8283353 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/css/mixins-pattern.css @@ -0,0 +1,47 @@ +.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 new file mode 100644 index 000000000..45d517932 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/css/mixins.css @@ -0,0 +1,71 @@ +.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 new file mode 100644 index 000000000..fb9e0aff7 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/css/operations.css @@ -0,0 +1,49 @@ +#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 new file mode 100644 index 000000000..36487fe59 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/css/parens.css @@ -0,0 +1,20 @@ +.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 new file mode 100644 index 000000000..408c76aad --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/css/rulesets.css @@ -0,0 +1,33 @@ +#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 new file mode 100644 index 000000000..11feda895 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/css/scope.css @@ -0,0 +1,15 @@ +.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 new file mode 100644 index 000000000..6f69a8c93 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/css/selectors.css @@ -0,0 +1,69 @@ +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 new file mode 100644 index 000000000..0c34134f8 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/css/strings.css @@ -0,0 +1,40 @@ +#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 new file mode 100644 index 000000000..961fe6959 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/css/variables.css @@ -0,0 +1,27 @@ +.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 new file mode 100644 index 000000000..56e067fcb --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/css/whitespace.css @@ -0,0 +1,38 @@ +.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 new file mode 100644 index 000000000..46412e011 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/less-test.js @@ -0,0 +1,73 @@ +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 new file mode 100644 index 000000000..3f808625b --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/less/colors.less @@ -0,0 +1,65 @@ +#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 new file mode 100644 index 000000000..1b5c63e44 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/less/comments.less @@ -0,0 +1,65 @@ +/******************\ +* * +* 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 new file mode 100644 index 000000000..bdda76d0a --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/less/css-3.less @@ -0,0 +1,65 @@ +.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 new file mode 100644 index 000000000..a2893e581 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/less/css-escapes.less @@ -0,0 +1,28 @@ +@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 new file mode 100644 index 000000000..3654cf827 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/less/css.less @@ -0,0 +1,100 @@ +@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 new file mode 100644 index 000000000..c111f7e56 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/less/functions.less @@ -0,0 +1,49 @@ +#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 new file mode 100644 index 000000000..bea85b824 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/less/ie-filters.less @@ -0,0 +1,8 @@ +@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 new file mode 100644 index 000000000..739900a6d --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/less/import-once.less @@ -0,0 +1,3 @@ +@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 new file mode 100644 index 000000000..13ed5c5a3 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/less/import.less @@ -0,0 +1,11 @@ +@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 new file mode 100644 index 000000000..7409d0714 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/less/import/import-test-a.less @@ -0,0 +1,2 @@ +@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 new file mode 100644 index 000000000..ce2d35a83 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/less/import/import-test-b.less @@ -0,0 +1,8 @@ +@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 new file mode 100644 index 000000000..111266ba8 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/less/import/import-test-c.less @@ -0,0 +1,7 @@ + +@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 new file mode 100644 index 000000000..30575f018 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/less/import/import-test-d.css @@ -0,0 +1 @@ +#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 new file mode 100644 index 000000000..98b84b0a5 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/less/import/import-test-e.less @@ -0,0 +1,2 @@ + +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 new file mode 100644 index 000000000..71d7af1f2 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/less/javascript.less @@ -0,0 +1,27 @@ +.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 new file mode 100644 index 000000000..72b3fd46e --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/less/lazy-eval.less @@ -0,0 +1,6 @@ +@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 new file mode 100644 index 000000000..00ecaf7d6 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/less/media.less @@ -0,0 +1,79 @@ + +// 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 new file mode 100644 index 000000000..ea43a0a53 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/less/mixins-args.less @@ -0,0 +1,130 @@ +.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 new file mode 100644 index 000000000..01251d2ad --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/less/mixins-closure.less @@ -0,0 +1,26 @@ +.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 new file mode 100644 index 000000000..1f46e976b --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/less/mixins-guards.less @@ -0,0 +1,94 @@ + +// 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 new file mode 100644 index 000000000..790a4d6e0 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/less/mixins-important.less @@ -0,0 +1,18 @@ + +.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 new file mode 100644 index 000000000..57b07d010 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/less/mixins-named-args.less @@ -0,0 +1,31 @@ +.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 new file mode 100644 index 000000000..d086279c8 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/less/mixins-nested.less @@ -0,0 +1,22 @@ +.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 new file mode 100644 index 000000000..b2121e956 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/less/mixins-pattern.less @@ -0,0 +1,99 @@ +.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 new file mode 100644 index 000000000..2fd761174 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/less/mixins.less @@ -0,0 +1,67 @@ +.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 new file mode 100644 index 000000000..46b0aa393 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/less/operations.less @@ -0,0 +1,62 @@ +#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 new file mode 100644 index 000000000..e020c7eb3 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/less/parens.less @@ -0,0 +1,26 @@ +.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 new file mode 100644 index 000000000..e81192dbc --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/less/rulesets.less @@ -0,0 +1,30 @@ +#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 new file mode 100644 index 000000000..da664626d --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/less/scope.less @@ -0,0 +1,32 @@ +@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 new file mode 100644 index 000000000..238980248 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/less/selectors.less @@ -0,0 +1,55 @@ +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 new file mode 100644 index 000000000..32fad721a --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/less/strings.less @@ -0,0 +1,51 @@ +#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 new file mode 100644 index 000000000..66ab4efff --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/less/variables.less @@ -0,0 +1,54 @@ +@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 new file mode 100644 index 000000000..cc0a8a324 --- /dev/null +++ b/r2/r2/lib/contrib/less.js/test/less/whitespace.less @@ -0,0 +1,37 @@ + + +.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 { + +}