├── .gitignore
├── README.md
├── pom.xml
└── src
├── it
├── basic
│ ├── invoker.properties
│ ├── pom.xml
│ ├── src
│ │ └── main
│ │ │ └── less
│ │ │ └── test.less
│ └── verify.groovy
├── custom-lessjs
│ ├── invoker.properties
│ ├── pom.xml
│ ├── src
│ │ └── main
│ │ │ └── webapp
│ │ │ ├── js
│ │ │ └── less-rhino-1.6.2.js
│ │ │ └── less
│ │ │ └── test.less
│ └── verify.groovy
├── excludes
│ ├── invoker.properties
│ ├── pom.xml
│ ├── src
│ │ └── main
│ │ │ └── less
│ │ │ ├── exclude.less
│ │ │ └── test.less
│ └── verify.groovy
├── filename-suffix
│ ├── invoker.properties
│ ├── pom.xml
│ ├── src
│ │ └── main
│ │ │ └── less
│ │ │ └── test.less
│ └── verify.groovy
├── includes
│ ├── invoker.properties
│ ├── pom.xml
│ ├── src
│ │ └── main
│ │ │ └── less
│ │ │ ├── include.less
│ │ │ └── test.less
│ └── verify.groovy
├── list
│ ├── invoker.properties
│ ├── pom.xml
│ ├── src
│ │ └── main
│ │ │ └── less
│ │ │ ├── import2
│ │ │ ├── import2a
│ │ │ │ └── less1import2a1.less
│ │ │ ├── less1import2a.less
│ │ │ └── less1import2b.less
│ │ │ ├── less1.less
│ │ │ ├── less1import1.less
│ │ │ ├── less1import1a.less
│ │ │ ├── less1import2.less
│ │ │ ├── less1import3.less
│ │ │ └── less2.less
│ └── verify.groovy
├── nodejs
│ ├── invoker.properties
│ ├── pom.xml
│ ├── src
│ │ └── main
│ │ │ └── less
│ │ │ └── test.less
│ └── verify.groovy
├── settings.xml
├── skip
│ ├── invoker.properties
│ ├── pom.xml
│ └── verify.groovy
└── webapp
│ ├── invoker.properties
│ ├── pom.xml
│ ├── src
│ └── main
│ │ └── webapp
│ │ └── less
│ │ └── test.less
│ └── verify.groovy
├── main
├── java
│ └── org
│ │ └── lesscss
│ │ └── mojo
│ │ ├── AbstractLessCssMojo.java
│ │ ├── CompileMojo.java
│ │ ├── ListMojo.java
│ │ └── NodeJsLessCompiler.java
└── resources
│ ├── META-INF
│ └── m2e
│ │ └── lifecycle-mapping-metadata.xml
│ └── org
│ └── lesscss
│ └── mojo
│ └── js
│ ├── less
│ ├── browser.js
│ ├── colors.js
│ ├── env.js
│ ├── extend-visitor.js
│ ├── functions.js
│ ├── import-visitor.js
│ ├── index.js
│ ├── join-selector-visitor.js
│ ├── lessc_helper.js
│ ├── parser.js
│ ├── rhino.js
│ ├── source-map-output.js
│ ├── to-css-visitor.js
│ ├── tree.js
│ ├── tree
│ │ ├── alpha.js
│ │ ├── anonymous.js
│ │ ├── assignment.js
│ │ ├── call.js
│ │ ├── color.js
│ │ ├── comment.js
│ │ ├── condition.js
│ │ ├── dimension.js
│ │ ├── directive.js
│ │ ├── element.js
│ │ ├── expression.js
│ │ ├── extend.js
│ │ ├── import.js
│ │ ├── javascript.js
│ │ ├── keyword.js
│ │ ├── media.js
│ │ ├── mixin.js
│ │ ├── negative.js
│ │ ├── operation.js
│ │ ├── paren.js
│ │ ├── quoted.js
│ │ ├── ratio.js
│ │ ├── rule.js
│ │ ├── ruleset.js
│ │ ├── selector.js
│ │ ├── unicode-descriptor.js
│ │ ├── url.js
│ │ ├── value.js
│ │ └── variable.js
│ └── visitor.js
│ └── lessc.js
└── test
├── java
└── org
│ └── lesscss
│ └── mojo
│ ├── AbstractLessCssMojoTest.java
│ ├── CompileMojoTest.java
│ ├── CompileOnChangeMojoTest.java
│ └── ListMojoTest.java
└── resources
├── less
├── 1
│ └── reset.less
├── 2
│ └── 21
│ │ └── variables.less
└── bootstrap.less
└── pom.xml
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | .classpath
3 | .project
4 | .settings/
5 | target/
6 | .DS_Store
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Official LESS CSS Maven Plugin
2 | ==============================
3 |
4 | **Latest release** 1.7.0.1.1 - The 1.1 release that is compatible with less 1.7.0
5 |
6 |
7 | Usage
8 | -----
9 |
10 | Declare the plugin and its goals. The process-sources phase is bound to by default:
11 |
12 |
13 | org.lesscss
14 | lesscss-maven-plugin
15 | 1.7.0.1.1
16 |
17 |
18 |
19 | compile
20 |
21 |
22 |
23 |
24 |
25 | To run the compiler manually just execute: mvn lesscss:compile
26 |
27 |
28 | Example configuration for web project
29 | -------------------------------------
30 |
31 |
32 | org.lesscss
33 | lesscss-maven-plugin
34 | 1.7.0.1.1
35 |
36 | ${project.basedir}/src/main/webapp/less
37 | ${project.build.directory}/${project.build.finalName}/css
38 | true
39 |
40 | main.less
41 |
42 |
43 |
44 |
45 |
46 | compile
47 |
48 |
49 |
50 |
51 |
52 |
53 | All configuration options
54 | -------------------------
55 |
56 | + **outputDirectory** `File` - The directory for compiled CSS stylesheets. Default value is: ${project.build.directory}.
57 |
58 | + **sourceDirectory** `File` - The source directory containing the LESS sources. Default value is: ${project.basedir}/src/main/less.
59 |
60 | + **compress** `boolean` - When true the LESS compiler will compress the CSS stylesheets. Default value is: false.
61 | + **encoding** `String` The character encoding the LESS compiler will use for writing the CSS stylesheets. Default value is: ${project.build.sourceEncoding}.
62 |
63 | + **excludes** `String[]` - List of files to exclude. Specified as fileset patterns which are relative to the source directory.
64 |
65 | + **force** `boolean` - When true forces the LESS compiler to always compile the LESS sources. By default LESS sources are only compiled when modified (including imports) or the CSS stylesheet does not exists. Default value is: false.
66 |
67 | + **includes** `String[]` - List of files to include. Specified as fileset patterns which are relative to the source directory. Default value is: { "**\/*.less" }
68 |
69 | + **lessJs** `String` - The location of the LESS JavaScript file.
70 |
71 | + **watch** `boolean` - When true the plugin watches the sourceDirectory and recompiles the included files after they changed. Instead of configuring it in the pom you can use that option at the command line like this "mvn lesscss:compile -Dlesscss.watch=true". Then it doesn't interfere with other maven lifecycle phases and you can just kill the watch process e.g. with crtl-c. Default value is: false.
72 |
73 | + **watchInterval** `int` - The interval in milliseconds the plugin waits between the check for file changes. Default value is: 1000 ms.
74 |
75 | + **outputFileFormat** `String` - The format of the output files. Default is: '{fileName}.css'. examples: '{fileName}.min.css', 'min-{fileName}.css', '{fileName}.anything'.
76 |
77 | List sources
78 | ------------
79 |
80 | To list the LESS sources in your project the lesscss:list goal can be used. It lists the LESS sources and it's imports based on sourceDirectory and optionally includes and excludes configuration options.
81 |
82 |
83 | Support
84 | -------
85 |
86 | Have a question, or found an issue? Just create a issue: https://github.com/marceloverdijk/lesscss-maven-plugin/issues
87 |
88 |
89 | Authors
90 | -------
91 |
92 | **Marcel Overdijk**
93 |
94 | + marcel@overdijk.me
95 | + http://twitter.com/marceloverdijk
96 | + http://github.com/marceloverdijk
97 |
98 | **Christophe Popov**
99 |
100 | + http://twitter.com/chpopov
101 | + http://uk.linkedin.com/in/hpopov/
102 |
103 |
104 | Copyright and License
105 | ---------------------
106 |
107 | Copyright 2012 Marcel Overdijk
108 |
109 | Licensed under the Apache License, Version 2.0 (the "License");
110 | you may not use this file except in compliance with the License.
111 | You may obtain a copy of the License at
112 |
113 | http://www.apache.org/licenses/LICENSE-2.0
114 |
115 | Unless required by applicable law or agreed to in writing, software
116 | distributed under the License is distributed on an "AS IS" BASIS,
117 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
118 | See the License for the specific language governing permissions and
119 | limitations under the License.
120 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 | org.lesscss
5 | lesscss-maven-plugin
6 | 1.7.0.1.2-SNAPSHOT
7 | maven-plugin
8 | Official LESS CSS Maven Plugin
9 | Official LESS CSS Maven Plugin
10 | http://github.com/marceloverdijk/lesscss-maven-plugin
11 |
12 |
13 | org.sonatype.oss
14 | oss-parent
15 | 7
16 |
17 |
18 |
19 | UTF-8
20 | UTF-8
21 |
22 |
23 |
24 |
25 | commons-logging
26 | commons-logging
27 | 1.1.1
28 |
29 |
30 | commons-io
31 | commons-io
32 | 2.4
33 |
34 |
35 | junit
36 | junit
37 | 4.10
38 | test
39 |
40 |
41 | org.slf4j
42 | slf4j-api
43 | 1.7.2
44 | test
45 |
46 |
47 | org.apache.maven
48 | maven-plugin-api
49 | 2.0
50 |
51 |
52 | org.apache.maven.plugin-testing
53 | maven-plugin-testing-harness
54 | 1.3
55 | test
56 |
57 |
58 | slf4j-jdk14
59 | org.slf4j
60 |
61 |
62 | slf4j-nop
63 | org.slf4j
64 |
65 |
66 |
67 |
68 | org.codehaus.plexus
69 | plexus-utils
70 | 3.0
71 |
72 |
73 | org.lesscss
74 | lesscss
75 | 1.7.0.1.1
76 |
77 |
78 | org.mockito
79 | mockito-core
80 | 1.9.0
81 | test
82 |
83 |
84 | org.powermock
85 | powermock-module-junit4
86 | 1.4.11
87 | test
88 |
89 |
90 | org.powermock
91 | powermock-api-mockito
92 | 1.4.11
93 | test
94 |
95 |
96 | org.sonatype.plexus
97 | plexus-build-api
98 | 0.0.7
99 |
100 |
101 |
102 |
103 |
104 |
105 | org.apache.maven.plugins
106 | maven-compiler-plugin
107 | 2.3.2
108 |
109 | UTF-8
110 | 1.5
111 | 1.5
112 |
113 |
114 |
115 | org.apache.maven.plugins
116 | maven-invoker-plugin
117 | 1.5
118 |
119 | ${project.build.directory}/it
120 | true
121 | ${project.build.directory}/local-repo
122 | verify
123 | src/it
124 | src/it/settings.xml
125 |
129 |
130 |
131 |
132 | integration-test
133 |
134 | install
135 | run
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 | The Apache Software License, Version 2.0
146 | http://www.apache.org/licenses/LICENSE-2.0.txt
147 | repo
148 |
149 |
150 |
151 |
152 |
153 | marceloverdijk
154 | Marcel Overdijk
155 | marcel@overdijk.me
156 |
157 | Lead Developer
158 |
159 | +2
160 |
161 |
162 | cpopov
163 | Christophe Popov
164 | chrpopov.gmail.com
165 | http://uk.linkedin.com/in/hpopov/
166 |
167 | Developer
168 |
169 | 0
170 |
171 |
172 |
173 |
174 | GitHub
175 | http://github.com/marceloverdijk/lesscss-maven-plugin/issues
176 |
177 |
178 |
179 | scm:git:git@github.com:marceloverdijk/lesscss-maven-plugin.git
180 | scm:git:git@github.com:marceloverdijk/lesscss-maven-plugin.git
181 | http://github.com/marceloverdijk/lesscss-maven-plugin
182 |
183 |
184 |
185 | 2.0
186 |
187 |
188 |
189 |
--------------------------------------------------------------------------------
/src/it/basic/invoker.properties:
--------------------------------------------------------------------------------
1 | invoker.goals = clean compile
--------------------------------------------------------------------------------
/src/it/basic/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 | org.lesscss.it
5 | basic
6 | testing
7 |
8 |
9 |
10 |
11 | org.lesscss
12 | lesscss-maven-plugin
13 | @project.version@
14 |
15 |
16 |
17 | compile
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/it/basic/src/main/less/test.less:
--------------------------------------------------------------------------------
1 | @color: #4d926f;
2 |
3 | #header {
4 | color: @color;
5 | }
6 | h2 {
7 | color: @color;
8 | }
--------------------------------------------------------------------------------
/src/it/basic/verify.groovy:
--------------------------------------------------------------------------------
1 | expected = """#header {
2 | color: #4d926f;
3 | }
4 | h2 {
5 | color: #4d926f;
6 | }
7 |
8 | """
9 |
10 | css = new File(basedir, "target/test.css")
11 | assert css.exists()
12 | assert css.getText().equals(expected)
13 |
--------------------------------------------------------------------------------
/src/it/custom-lessjs/invoker.properties:
--------------------------------------------------------------------------------
1 | invoker.goals = clean compile
--------------------------------------------------------------------------------
/src/it/custom-lessjs/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 | org.lesscss.it
5 | custom-lessjs
6 | testing
7 |
8 |
9 |
10 |
11 | org.lesscss
12 | lesscss-maven-plugin
13 | @project.version@
14 |
15 | ${project.basedir}/src/main/webapp/js/less-rhino-1.6.2.js
16 | ${project.basedir}/src/main/webapp/less
17 | ${project.build.directory}/${project.build.finalName}/css
18 |
19 |
20 |
21 |
22 | compile
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/src/it/custom-lessjs/src/main/webapp/less/test.less:
--------------------------------------------------------------------------------
1 | @color: #4d926f;
2 |
3 | #header {
4 | color: @color;
5 | }
6 | h2 {
7 | color: @color;
8 | }
--------------------------------------------------------------------------------
/src/it/custom-lessjs/verify.groovy:
--------------------------------------------------------------------------------
1 | expected = """#header {
2 | color: #4d926f;
3 | }
4 | h2 {
5 | color: #4d926f;
6 | }
7 |
8 | """
9 |
10 | css = new File(basedir, "target/custom-lessjs-testing/css/test.css")
11 | assert css.exists()
12 | assert css.getText().equals(expected)
--------------------------------------------------------------------------------
/src/it/excludes/invoker.properties:
--------------------------------------------------------------------------------
1 | invoker.goals = clean compile
--------------------------------------------------------------------------------
/src/it/excludes/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 | org.lesscss.it
5 | excludes
6 | testing
7 |
8 |
9 |
10 |
11 | org.lesscss
12 | lesscss-maven-plugin
13 | @project.version@
14 |
15 |
16 | exclude.less
17 |
18 |
19 |
20 |
21 |
22 | compile
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/src/it/excludes/src/main/less/exclude.less:
--------------------------------------------------------------------------------
1 | @color: #4d926f;
2 |
3 | #header {
4 | color: @color;
5 | }
6 | h2 {
7 | color: @color;
8 | }
--------------------------------------------------------------------------------
/src/it/excludes/src/main/less/test.less:
--------------------------------------------------------------------------------
1 | @color: #4d926f;
2 |
3 | #header {
4 | color: @color;
5 | }
6 | h2 {
7 | color: @color;
8 | }
--------------------------------------------------------------------------------
/src/it/excludes/verify.groovy:
--------------------------------------------------------------------------------
1 | assert new File(basedir, "target/test.css").exists()
2 | assert !new File(basedir, "target/exclude.css").exists()
3 |
--------------------------------------------------------------------------------
/src/it/filename-suffix/invoker.properties:
--------------------------------------------------------------------------------
1 | invoker.goals = clean compile
--------------------------------------------------------------------------------
/src/it/filename-suffix/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 | org.lesscss.it
5 | filename-suffix
6 | testing
7 |
8 |
9 |
10 |
11 | org.lesscss
12 | lesscss-maven-plugin
13 | @project.version@
14 |
15 | min-{fileName}-1.33.7.css
16 |
17 |
18 |
19 |
20 | compile
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/it/filename-suffix/src/main/less/test.less:
--------------------------------------------------------------------------------
1 | @color: #4d926f;
2 |
3 | #header {
4 | color: @color;
5 | }
6 | h2 {
7 | color: @color;
8 | }
--------------------------------------------------------------------------------
/src/it/filename-suffix/verify.groovy:
--------------------------------------------------------------------------------
1 | expected = """#header {
2 | color: #4d926f;
3 | }
4 | h2 {
5 | color: #4d926f;
6 | }
7 |
8 | """
9 |
10 | css = new File(basedir, "target/min-test-1.33.7.css")
11 | assert css.exists()
12 | assert css.getText().equals(expected)
13 |
--------------------------------------------------------------------------------
/src/it/includes/invoker.properties:
--------------------------------------------------------------------------------
1 | invoker.goals = clean compile
--------------------------------------------------------------------------------
/src/it/includes/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 | org.lesscss.it
5 | includes
6 | testing
7 |
8 |
9 |
10 |
11 | org.lesscss
12 | lesscss-maven-plugin
13 | @project.version@
14 |
15 |
16 | include.less
17 |
18 |
19 |
20 |
21 |
22 | compile
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/src/it/includes/src/main/less/include.less:
--------------------------------------------------------------------------------
1 | @color: #4d926f;
2 |
3 | #header {
4 | color: @color;
5 | }
6 | h2 {
7 | color: @color;
8 | }
--------------------------------------------------------------------------------
/src/it/includes/src/main/less/test.less:
--------------------------------------------------------------------------------
1 | @color: #4d926f;
2 |
3 | #header {
4 | color: @color;
5 | }
6 | h2 {
7 | color: @color;
8 | }
--------------------------------------------------------------------------------
/src/it/includes/verify.groovy:
--------------------------------------------------------------------------------
1 | assert !new File(basedir, "target/test.css").exists()
2 | assert new File(basedir, "target/include.css").exists()
3 |
--------------------------------------------------------------------------------
/src/it/list/invoker.properties:
--------------------------------------------------------------------------------
1 | invoker.goals = clean lesscss:list
--------------------------------------------------------------------------------
/src/it/list/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 | org.lesscss.it
5 | list
6 | testing
7 |
8 |
9 |
10 |
11 | org.lesscss
12 | lesscss-maven-plugin
13 | @project.version@
14 |
15 |
16 | less1.less
17 | less2.less
18 |
19 |
20 |
21 |
22 |
23 | compile
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/src/it/list/src/main/less/import2/import2a/less1import2a1.less:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marceloverdijk/lesscss-maven-plugin/0ce62351150c0cb3d2e1b6e413d29bbd9ddab4cd/src/it/list/src/main/less/import2/import2a/less1import2a1.less
--------------------------------------------------------------------------------
/src/it/list/src/main/less/import2/less1import2a.less:
--------------------------------------------------------------------------------
1 | @import "import2a/less1import2a1.less";
--------------------------------------------------------------------------------
/src/it/list/src/main/less/import2/less1import2b.less:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marceloverdijk/lesscss-maven-plugin/0ce62351150c0cb3d2e1b6e413d29bbd9ddab4cd/src/it/list/src/main/less/import2/less1import2b.less
--------------------------------------------------------------------------------
/src/it/list/src/main/less/less1.less:
--------------------------------------------------------------------------------
1 | @import "less1import1.less";
2 | @import "less1import2.less";
3 | @import "less1import3.less";
--------------------------------------------------------------------------------
/src/it/list/src/main/less/less1import1.less:
--------------------------------------------------------------------------------
1 | @import "less1import1a.less";
--------------------------------------------------------------------------------
/src/it/list/src/main/less/less1import1a.less:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marceloverdijk/lesscss-maven-plugin/0ce62351150c0cb3d2e1b6e413d29bbd9ddab4cd/src/it/list/src/main/less/less1import1a.less
--------------------------------------------------------------------------------
/src/it/list/src/main/less/less1import2.less:
--------------------------------------------------------------------------------
1 | @import "import2/less1import2a.less";
2 | @import "import2/less1import2b.less";
--------------------------------------------------------------------------------
/src/it/list/src/main/less/less1import3.less:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marceloverdijk/lesscss-maven-plugin/0ce62351150c0cb3d2e1b6e413d29bbd9ddab4cd/src/it/list/src/main/less/less1import3.less
--------------------------------------------------------------------------------
/src/it/list/src/main/less/less2.less:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/marceloverdijk/lesscss-maven-plugin/0ce62351150c0cb3d2e1b6e413d29bbd9ddab4cd/src/it/list/src/main/less/less2.less
--------------------------------------------------------------------------------
/src/it/list/verify.groovy:
--------------------------------------------------------------------------------
1 | log = new File(basedir, "build.log")
2 | assert log.getText().contains("The following LESS sources have been resolved:");
3 | assert log.getText().contains("less1.less");
4 | assert log.getText().contains("|-- less1import1.less");
5 | assert log.getText().contains("| `-- less1import1a.less");
6 | assert log.getText().contains("|-- less1import2.less");
7 | assert log.getText().contains("| |-- import2/less1import2a.less");
8 | assert log.getText().contains("| | `-- import2a/less1import2a1.less");
9 | assert log.getText().contains("| `-- import2/less1import2b.less");
10 | assert log.getText().contains("`-- less1import3.less");
11 | assert log.getText().contains("less2.less");
--------------------------------------------------------------------------------
/src/it/nodejs/invoker.properties:
--------------------------------------------------------------------------------
1 | invoker.goals = clean compile
--------------------------------------------------------------------------------
/src/it/nodejs/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 | org.lesscss.it
5 | nodejs
6 | testing
7 |
8 |
9 |
10 |
11 | com.github.skwakman.nodejs-maven-plugin
12 | nodejs-maven-plugin
13 | 1.0.3
14 |
15 |
16 | initialize
17 |
18 | extract
19 |
20 |
21 |
22 |
23 | ${project.build.directory}/nodejs
24 |
25 |
26 |
27 | org.lesscss
28 | lesscss-maven-plugin
29 | @project.version@
30 |
31 |
32 |
33 | compile
34 |
35 |
36 |
37 |
38 | ${project.build.directory}/nodejs/node
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/src/it/nodejs/src/main/less/test.less:
--------------------------------------------------------------------------------
1 | @color: #4d926f;
2 |
3 | #header {
4 | color: @color;
5 | }
6 | h2 {
7 | color: @color;
8 | }
--------------------------------------------------------------------------------
/src/it/nodejs/verify.groovy:
--------------------------------------------------------------------------------
1 | expected = """#header {
2 | color: #4d926f;
3 | }
4 | h2 {
5 | color: #4d926f;
6 | }
7 | """
8 |
9 | css = new File(basedir, "target/test.css")
10 | assert css.exists()
11 | assert css.getText().equals(expected)
12 |
--------------------------------------------------------------------------------
/src/it/settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | it-repo
5 |
6 | true
7 |
8 |
9 |
10 | local.central
11 | @localRepositoryUrl@
12 |
13 | true
14 |
15 |
16 | true
17 |
18 |
19 |
20 |
21 |
22 | local.central
23 | @localRepositoryUrl@
24 |
25 | true
26 |
27 |
28 | true
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/src/it/skip/invoker.properties:
--------------------------------------------------------------------------------
1 | invoker.goals = clean compile
--------------------------------------------------------------------------------
/src/it/skip/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 | org.lesscss.it
5 | skip
6 | testing
7 |
8 |
9 | true
10 |
11 |
12 |
13 |
14 | org.lesscss
15 | lesscss-maven-plugin
16 | @project.version@
17 |
18 |
19 |
20 | compile
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/it/skip/verify.groovy:
--------------------------------------------------------------------------------
1 | log = new File(basedir, "build.log")
2 | assert log.getText().contains("Skipping plugin execution per configuration");
--------------------------------------------------------------------------------
/src/it/webapp/invoker.properties:
--------------------------------------------------------------------------------
1 | invoker.goals = clean compile
--------------------------------------------------------------------------------
/src/it/webapp/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 | org.lesscss.it
5 | webapp
6 | testing
7 |
8 |
9 |
10 |
11 | org.lesscss
12 | lesscss-maven-plugin
13 | @project.version@
14 |
15 | ${project.basedir}/src/main/webapp/less
16 | ${project.build.directory}/${project.build.finalName}/css
17 |
18 |
19 |
20 |
21 | compile
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/src/it/webapp/src/main/webapp/less/test.less:
--------------------------------------------------------------------------------
1 | @color: #4d926f;
2 |
3 | #header {
4 | color: @color;
5 | }
6 | h2 {
7 | color: @color;
8 | }
--------------------------------------------------------------------------------
/src/it/webapp/verify.groovy:
--------------------------------------------------------------------------------
1 | expected = """#header {
2 | color: #4d926f;
3 | }
4 | h2 {
5 | color: #4d926f;
6 | }
7 |
8 | """
9 |
10 | css = new File(basedir, "target/webapp-testing/css/test.css")
11 | assert css.exists()
12 | assert css.getText().equals(expected)
13 |
--------------------------------------------------------------------------------
/src/main/java/org/lesscss/mojo/AbstractLessCssMojo.java:
--------------------------------------------------------------------------------
1 | /* Copyright 2011-2012 The Apache Software Foundation.
2 | *
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 | package org.lesscss.mojo;
16 |
17 | import java.io.File;
18 |
19 | import org.apache.maven.plugin.AbstractMojo;
20 | import org.codehaus.plexus.util.Scanner;
21 | import org.sonatype.plexus.build.incremental.BuildContext;
22 |
23 | /**
24 | * Abstract class which provides common configuration properties and methods.
25 | *
26 | * @author Marcel Overdijk
27 | */
28 | public abstract class AbstractLessCssMojo extends AbstractMojo {
29 |
30 | /** @component */
31 | protected BuildContext buildContext;
32 |
33 | /**
34 | * The source directory containing the LESS sources.
35 | *
36 | * @parameter expression="${lesscss.sourceDirectory}" default-value="${project.basedir}/src/main/less"
37 | * @required
38 | */
39 | protected File sourceDirectory;
40 |
41 | /**
42 | * List of files to include. Specified as fileset patterns which are relative to the source directory. Default value is: { "**\/*.less" }
43 | *
44 | * @parameter
45 | */
46 | protected String[] includes = new String[] { "**/*.less" };
47 |
48 | /**
49 | * List of files to exclude. Specified as fileset patterns which are relative to the source directory.
50 | *
51 | * @parameter
52 | */
53 | protected String[] excludes = new String[] {};
54 |
55 | /**
56 | * Scans for the LESS sources that should be compiled.
57 | *
58 | * @return The list of LESS sources.
59 | */
60 | protected String[] getIncludedFiles() {
61 | Scanner scanner = buildContext.newScanner(sourceDirectory, true);
62 | scanner.setIncludes(includes);
63 | scanner.setExcludes(excludes);
64 | scanner.scan();
65 | return scanner.getIncludedFiles();
66 | }
67 |
68 | /**
69 | * Whether to skip plugin execution.
70 | * This makes the build more controllable from profiles.
71 | *
72 | * @parameter expression="${lesscss.skip}" default-value="false"
73 | */
74 | protected boolean skip;
75 | }
76 |
--------------------------------------------------------------------------------
/src/main/java/org/lesscss/mojo/CompileMojo.java:
--------------------------------------------------------------------------------
1 | /* Copyright 2011-2012 The Apache Software Foundation.
2 | *
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 | package org.lesscss.mojo;
16 |
17 | import java.io.File;
18 | import java.io.IOException;
19 | import java.net.MalformedURLException;
20 | import java.util.Arrays;
21 |
22 | import org.apache.maven.plugin.MojoExecutionException;
23 | import org.codehaus.plexus.util.StringUtils;
24 | import org.lesscss.LessCompiler;
25 | import org.lesscss.LessException;
26 | import org.lesscss.LessSource;
27 | import org.sonatype.plexus.build.incremental.BuildContext;
28 |
29 | /**
30 | * Goal which compiles the LESS sources to CSS stylesheets.
31 | *
32 | * @author Marcel Overdijk
33 | * @goal compile
34 | * @phase process-sources
35 | */
36 | public class CompileMojo extends AbstractLessCssMojo {
37 |
38 | /**
39 | * The directory for compiled CSS stylesheets.
40 | *
41 | * @parameter expression="${lesscss.outputDirectory}" default-value="${project.build.directory}"
42 | * @required
43 | */
44 | protected File outputDirectory;
45 |
46 | /**
47 | * When true the LESS compiler will compress the CSS stylesheets.
48 | *
49 | * @parameter expression="${lesscss.compress}" default-value="false"
50 | */
51 | private boolean compress;
52 |
53 | /**
54 | * When true the plugin will watch for changes in LESS files and compile if it detects one.
55 | *
56 | * @parameter expression="${lesscss.watch}" default-value="false"
57 | */
58 | protected boolean watch=false;
59 |
60 | /**
61 | * When true the plugin will watch for changes in LESS files and compile if it detects one.
62 | *
63 | * @parameter expression="${lesscss.watchInterval}" default-value="1000"
64 | */
65 | private int watchInterval=1000;
66 |
67 | /**
68 | * The character encoding the LESS compiler will use for writing the CSS stylesheets.
69 | *
70 | * @parameter expression="${lesscss.encoding}" default-value="${project.build.sourceEncoding}"
71 | */
72 | private String encoding;
73 |
74 | /**
75 | * When true forces the LESS compiler to always compile the LESS sources. By default LESS sources are only compiled when modified (including imports) or the CSS stylesheet does not exists.
76 | *
77 | * @parameter expression="${lesscss.force}" default-value="false"
78 | */
79 | private boolean force;
80 |
81 | /**
82 | * The location of the LESS JavasSript file.
83 | *
84 | * @parameter
85 | */
86 | private File lessJs;
87 |
88 | /**
89 | * The location of the NodeJS executable.
90 | *
91 | * @parameter
92 | */
93 | private String nodeExecutable;
94 |
95 | /**
96 | * The format of the output file names.
97 | *
98 | * @parameter
99 | */
100 | private String outputFileFormat;
101 |
102 | private static final String FILE_NAME_FORMAT_PARAMETER_REGEX = "\\{fileName\\}";
103 |
104 | /**
105 | * Execute the MOJO.
106 | *
107 | * @throws MojoExecutionException
108 | * if something unexpected occurs.
109 | */
110 | public void execute() throws MojoExecutionException {
111 | if (getLog().isDebugEnabled()) {
112 | getLog().debug("sourceDirectory = " + sourceDirectory);
113 | getLog().debug("outputDirectory = " + outputDirectory);
114 | getLog().debug("includes = " + Arrays.toString(includes));
115 | getLog().debug("excludes = " + Arrays.toString(excludes));
116 | getLog().debug("force = " + force);
117 | getLog().debug("lessJs = " + lessJs);
118 | getLog().debug("skip = " + skip);
119 | }
120 |
121 | if(!skip){
122 | executeInternal();
123 | } else {
124 | getLog().info("Skipping plugin execution per configuration");
125 | }
126 | }
127 |
128 | private void executeInternal() throws MojoExecutionException {
129 | long start = System.currentTimeMillis();
130 |
131 | String[] files = getIncludedFiles();
132 |
133 | if (files == null || files.length < 1) {
134 | getLog().info("Nothing to compile - no LESS sources found");
135 | } else {
136 | if (getLog().isDebugEnabled()) {
137 | getLog().debug("included files = " + Arrays.toString(files));
138 | }
139 |
140 | Object lessCompiler = initLessCompiler();
141 | if (watch){
142 | getLog().info("Watching "+sourceDirectory);
143 | if (force){
144 | force=false;
145 | getLog().info("Disabled the 'force' flag in watch mode.");
146 | }
147 | Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
148 | while (watch && !Thread.currentThread().isInterrupted()){
149 | compileIfChanged(files, lessCompiler);
150 | try {
151 | Thread.sleep(watchInterval);
152 | } catch (InterruptedException e) {
153 | System.out.println("interrupted");
154 | }
155 | }
156 | } else {
157 | compileIfChanged(files, lessCompiler);
158 | }
159 |
160 | getLog().info("Complete Less compile job finished in " + (System.currentTimeMillis() - start) + " ms");
161 | }
162 | }
163 |
164 | private void compileIfChanged(String[] files, Object lessCompiler) throws MojoExecutionException {
165 | try {
166 | for (String file : files) {
167 | File input = new File(sourceDirectory, file);
168 |
169 | buildContext.removeMessages(input);
170 |
171 | if(outputFileFormat != null){
172 | file = outputFileFormat.replaceAll(FILE_NAME_FORMAT_PARAMETER_REGEX, file.replace(".less", ""));
173 | }
174 |
175 | File output = new File(outputDirectory, file.replace(".less", ".css"));
176 |
177 | if (!output.getParentFile().exists() && !output.getParentFile().mkdirs()) {
178 | throw new MojoExecutionException("Cannot create output directory " + output.getParentFile());
179 | }
180 |
181 | try {
182 | LessSource lessSource = new LessSource(input);
183 | if (force || !output.exists() || output.lastModified() < lessSource.getLastModifiedIncludingImports()) {
184 | long compilationStarted = System.currentTimeMillis();
185 | getLog().info("Compiling LESS source: " + file + "...");
186 | if (lessCompiler instanceof LessCompiler) {
187 | ((LessCompiler) lessCompiler).compile(lessSource, output, force);
188 | } else {
189 | ((NodeJsLessCompiler) lessCompiler).compile(lessSource, output, force);
190 | }
191 | buildContext.refresh(output);
192 | getLog().info("Finished compilation to "+outputDirectory+" in " + (System.currentTimeMillis() - compilationStarted) + " ms");
193 | }
194 | else if (!watch) {
195 | getLog().info("Bypassing LESS source: " + file + " (not modified)");
196 | }
197 | } catch (IOException e) {
198 | buildContext.addMessage(input, 0, 0, "Error compiling LESS source", BuildContext.SEVERITY_ERROR, e);
199 | throw new MojoExecutionException("Error while compiling LESS source: " + file, e);
200 | } catch (LessException e) {
201 | String message = e.getMessage();
202 | if (StringUtils.isEmpty(message)) {
203 | message = "Error compiling LESS source";
204 | }
205 | buildContext.addMessage(input, 0, 0, "Error compiling LESS source", BuildContext.SEVERITY_ERROR, e);
206 | throw new MojoExecutionException("Error while compiling LESS source: " + file, e);
207 | } catch (InterruptedException e) {
208 | buildContext.addMessage(input, 0, 0, "Error compiling LESS source", BuildContext.SEVERITY_ERROR, e);
209 | throw new MojoExecutionException("Error while compiling LESS source: " + file, e);
210 | }
211 | }
212 | } finally {
213 | if (lessCompiler instanceof NodeJsLessCompiler) {
214 | ((NodeJsLessCompiler) lessCompiler).close();
215 | }
216 | }
217 | }
218 |
219 | private Object initLessCompiler() throws MojoExecutionException {
220 | if (nodeExecutable != null) {
221 | NodeJsLessCompiler lessCompiler;
222 | try {
223 | lessCompiler = new NodeJsLessCompiler(nodeExecutable, compress, encoding, getLog());
224 | } catch (IOException e) {
225 | throw new MojoExecutionException(e.getMessage(), e);
226 | }
227 | if (lessJs != null) {
228 | throw new MojoExecutionException(
229 | "Custom LESS JavaScript is not currently supported when using nodeExecutable");
230 | }
231 | return lessCompiler;
232 | } else {
233 | LessCompiler lessCompiler = new LessCompiler();
234 | lessCompiler.setCompress(compress);
235 | lessCompiler.setEncoding(encoding);
236 | if (lessJs != null) {
237 | try {
238 | lessCompiler.setLessJs(lessJs.toURI().toURL());
239 | } catch (MalformedURLException e) {
240 | throw new MojoExecutionException(
241 | "Error while loading LESS JavaScript: " + lessJs.getAbsolutePath(), e);
242 | }
243 | }
244 | return lessCompiler;
245 | }
246 | }
247 | }
248 |
--------------------------------------------------------------------------------
/src/main/java/org/lesscss/mojo/ListMojo.java:
--------------------------------------------------------------------------------
1 | /* Copyright 2011-2012 The Apache Software Foundation.
2 | *
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 | package org.lesscss.mojo;
16 |
17 | import java.io.File;
18 | import java.io.FileNotFoundException;
19 | import java.io.IOException;
20 | import java.util.Arrays;
21 | import java.util.Iterator;
22 | import java.util.Map.Entry;
23 |
24 | import org.apache.maven.plugin.MojoExecutionException;
25 | import org.lesscss.LessSource;
26 |
27 | /**
28 | * Goal which list the LESS sources and its imports.
29 | *
30 | * @author Marcel Overdijk
31 | * @goal list
32 | */
33 | public class ListMojo extends AbstractLessCssMojo {
34 |
35 | /**
36 | * Execute the MOJO.
37 | *
38 | * @throws MojoExecutionException
39 | * if something unexpected occurs.
40 | */
41 | public void execute() throws MojoExecutionException {
42 | if (getLog().isDebugEnabled()) {
43 | getLog().debug("sourceDirectory = " + sourceDirectory);
44 | getLog().debug("includes = " + Arrays.toString(includes));
45 | getLog().debug("excludes = " + Arrays.toString(excludes));
46 | }
47 |
48 | String[] files = getIncludedFiles();
49 |
50 | if (files == null || files.length < 1) {
51 | getLog().info("No LESS sources found");
52 | } else {
53 | getLog().info("The following LESS sources have been resolved:");
54 |
55 | for (String file : files) {
56 | File lessFile = new File(sourceDirectory, file);
57 | try {
58 | LessSource lessSource = new LessSource(lessFile);
59 | listLessSource(lessSource, file, 0, false);
60 | } catch (FileNotFoundException e) {
61 | throw new MojoExecutionException("Error while loading LESS source: " + lessFile.getAbsolutePath(), e);
62 | } catch (IOException e) {
63 | throw new MojoExecutionException("Error while loading LESS source: " + lessFile.getAbsolutePath(), e);
64 | }
65 | }
66 | }
67 | }
68 |
69 | private void listLessSource(LessSource lessSource, String path, int level, boolean last) {
70 | String prefix = "";
71 | if (level > 0) {
72 | for (int i = 1; i <= level; i++) {
73 | if (i == level && last) {
74 | prefix = prefix + "`-- ";
75 | } else if (i == level) {
76 | prefix = prefix + "|-- ";
77 | } else {
78 | prefix = prefix + "| ";
79 | }
80 | }
81 | }
82 |
83 | getLog().info(prefix + path);
84 |
85 | Iterator> it = lessSource.getImports().entrySet().iterator();
86 | while (it.hasNext()) {
87 | Entry entry = it.next();
88 | listLessSource(entry.getValue(), entry.getKey(), level + 1, !it.hasNext());
89 | }
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/src/main/java/org/lesscss/mojo/NodeJsLessCompiler.java:
--------------------------------------------------------------------------------
1 | /* Copyright 2013 the original author or authors.
2 | *
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 | package org.lesscss.mojo;
16 |
17 | import java.io.File;
18 | import java.io.FileInputStream;
19 | import java.io.FileOutputStream;
20 | import java.io.IOException;
21 | import java.io.InputStream;
22 | import java.util.Arrays;
23 | import java.util.List;
24 |
25 | import org.apache.commons.io.FileUtils;
26 | import org.apache.commons.io.IOUtils;
27 | import org.apache.maven.plugin.logging.Log;
28 | import org.lesscss.LessException;
29 | import org.lesscss.LessSource;
30 |
31 | public class NodeJsLessCompiler {
32 |
33 | private static final List resources = Arrays.asList(
34 | "lessc.js",
35 | "less/visitor.js",
36 | "less/tree.js",
37 | "less/to-css-visitor.js",
38 | "less/source-map-output.js",
39 | "less/rhino.js",
40 | "less/parser.js",
41 | "less/lessc_helper.js",
42 | "less/join-selector-visitor.js",
43 | "less/index.js",
44 | "less/import-visitor.js",
45 | "less/functions.js",
46 | "less/extend-visitor.js",
47 | "less/env.js",
48 | "less/colors.js",
49 | "less/browser.js",
50 | "less/tree/variable.js",
51 | "less/tree/value.js",
52 | "less/tree/url.js",
53 | "less/tree/unicode-descriptor.js",
54 | "less/tree/selector.js",
55 | "less/tree/ruleset.js",
56 | "less/tree/rule.js",
57 | "less/tree/ratio.js",
58 | "less/tree/quoted.js",
59 | "less/tree/paren.js",
60 | "less/tree/operation.js",
61 | "less/tree/negative.js",
62 | "less/tree/mixin.js",
63 | "less/tree/media.js",
64 | "less/tree/keyword.js",
65 | "less/tree/javascript.js",
66 | "less/tree/import.js",
67 | "less/tree/extend.js",
68 | "less/tree/expression.js",
69 | "less/tree/element.js",
70 | "less/tree/directive.js",
71 | "less/tree/dimension.js",
72 | "less/tree/condition.js",
73 | "less/tree/comment.js",
74 | "less/tree/color.js",
75 | "less/tree/call.js",
76 | "less/tree/assignment.js",
77 | "less/tree/anonymous.js",
78 | "less/tree/alpha.js");
79 |
80 | private final Log log;
81 |
82 | private final boolean compress;
83 |
84 | private final String encoding;
85 |
86 | private final File tempDir;
87 |
88 | private final String nodeExecutablePath;
89 |
90 | public NodeJsLessCompiler(boolean compress, String encoding, Log log) throws IOException {
91 | this("node", compress, encoding, log);
92 | }
93 |
94 | public NodeJsLessCompiler(String nodeExecutablePath, boolean compress,
95 | String encoding, Log log) throws IOException {
96 | this.compress = compress;
97 | this.encoding = encoding;
98 | this.log = log;
99 | this.nodeExecutablePath = nodeExecutablePath;
100 |
101 | tempDir = createTempDir("lessc");
102 | new File(tempDir, "less/tree").mkdirs();
103 | for (String resource : resources) {
104 | InputStream in = NodeJsLessCompiler.class.getClassLoader()
105 | .getResourceAsStream("org/lesscss/mojo/js/" + resource);
106 | FileOutputStream out = new FileOutputStream(new File(tempDir, resource));
107 | IOUtils.copy(in, out);
108 | in.close();
109 | out.close();
110 | }
111 | }
112 |
113 | public void close() {
114 | for (String resource : resources) {
115 | File tempFile = new File(tempDir, resource);
116 | if (!tempFile.delete()) {
117 | log.warn("Could not delete temp file: " + tempFile.getAbsolutePath());
118 | }
119 | }
120 | File lessSubdir = new File(tempDir, "less");
121 | File treeSubdir = new File(lessSubdir, "tree");
122 | if (!treeSubdir.delete()) {
123 | log.warn("Could not delete temp dir: " + treeSubdir.getAbsolutePath());
124 | }
125 | if (!lessSubdir.delete()) {
126 | log.warn("Could not delete temp dir: " + lessSubdir.getAbsolutePath());
127 | }
128 | if (!tempDir.delete()) {
129 | log.warn("Could not delete temp dir: " + tempDir.getAbsolutePath());
130 | }
131 | }
132 |
133 | public void compile(LessSource input, File output, boolean force)
134 | throws IOException, LessException, InterruptedException {
135 | if (force || !output.exists() || output.lastModified() < input.getLastModifiedIncludingImports()) {
136 | String data = compile(input.getNormalizedContent());
137 | FileUtils.writeStringToFile(output, data, encoding);
138 | }
139 | }
140 |
141 | private String compile(String input) throws LessException, IOException, InterruptedException {
142 | long start = System.currentTimeMillis();
143 |
144 | File inputFile = File.createTempFile("lessc-input-", ".less");
145 | FileOutputStream out = new FileOutputStream(inputFile);
146 | IOUtils.write(input, out);
147 | out.close();
148 | File outputFile = File.createTempFile("lessc-output-", ".css");
149 | File lesscJsFile = new File(tempDir, "lessc.js");
150 |
151 | ProcessBuilder pb = new ProcessBuilder(nodeExecutablePath, lesscJsFile.getAbsolutePath(),
152 | inputFile.getAbsolutePath(), outputFile.getAbsolutePath(), String.valueOf(compress));
153 | pb.redirectErrorStream(true);
154 | Process process = pb.start();
155 | IOUtils.copy(process.getInputStream(), System.out);
156 |
157 | int exitStatus = process.waitFor();
158 |
159 | FileInputStream in = new FileInputStream(outputFile);
160 | String result = IOUtils.toString(in);
161 | in.close();
162 | if (!inputFile.delete()) {
163 | log.warn("Could not delete temp file: " + inputFile.getAbsolutePath());
164 | }
165 | if (!outputFile.delete()) {
166 | log.warn("Could not delete temp file: " + outputFile.getAbsolutePath());
167 | }
168 | if (exitStatus != 0) {
169 | throw new LessException(result, null);
170 | }
171 |
172 | log.debug("Finished compilation of LESS source in " + (System.currentTimeMillis() - start) + " ms.");
173 |
174 | return result;
175 | }
176 |
177 | // copied from guava's Files.createTempDir, with added prefix
178 | private static File createTempDir(String prefix) {
179 | final int tempDirAttempts = 10000;
180 | File baseDir = new File(System.getProperty("java.io.tmpdir"));
181 | String baseName = prefix + "-" + System.currentTimeMillis() + "-";
182 | for (int counter = 0; counter < tempDirAttempts; counter++) {
183 | File tempDir = new File(baseDir, baseName + counter);
184 | if (tempDir.mkdir()) {
185 | return tempDir;
186 | }
187 | }
188 | throw new IllegalStateException("Failed to create directory within " + tempDirAttempts
189 | + " attempts (tried " + baseName + "0 to " + baseName + (tempDirAttempts - 1) + ')');
190 | }
191 | }
192 |
--------------------------------------------------------------------------------
/src/main/resources/META-INF/m2e/lifecycle-mapping-metadata.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | compile
7 |
8 |
9 |
10 |
11 | true
12 | false
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/main/resources/org/lesscss/mojo/js/less/colors.js:
--------------------------------------------------------------------------------
1 | (function (tree) {
2 | tree.colors = {
3 | 'aliceblue':'#f0f8ff',
4 | 'antiquewhite':'#faebd7',
5 | 'aqua':'#00ffff',
6 | 'aquamarine':'#7fffd4',
7 | 'azure':'#f0ffff',
8 | 'beige':'#f5f5dc',
9 | 'bisque':'#ffe4c4',
10 | 'black':'#000000',
11 | 'blanchedalmond':'#ffebcd',
12 | 'blue':'#0000ff',
13 | 'blueviolet':'#8a2be2',
14 | 'brown':'#a52a2a',
15 | 'burlywood':'#deb887',
16 | 'cadetblue':'#5f9ea0',
17 | 'chartreuse':'#7fff00',
18 | 'chocolate':'#d2691e',
19 | 'coral':'#ff7f50',
20 | 'cornflowerblue':'#6495ed',
21 | 'cornsilk':'#fff8dc',
22 | 'crimson':'#dc143c',
23 | 'cyan':'#00ffff',
24 | 'darkblue':'#00008b',
25 | 'darkcyan':'#008b8b',
26 | 'darkgoldenrod':'#b8860b',
27 | 'darkgray':'#a9a9a9',
28 | 'darkgrey':'#a9a9a9',
29 | 'darkgreen':'#006400',
30 | 'darkkhaki':'#bdb76b',
31 | 'darkmagenta':'#8b008b',
32 | 'darkolivegreen':'#556b2f',
33 | 'darkorange':'#ff8c00',
34 | 'darkorchid':'#9932cc',
35 | 'darkred':'#8b0000',
36 | 'darksalmon':'#e9967a',
37 | 'darkseagreen':'#8fbc8f',
38 | 'darkslateblue':'#483d8b',
39 | 'darkslategray':'#2f4f4f',
40 | 'darkslategrey':'#2f4f4f',
41 | 'darkturquoise':'#00ced1',
42 | 'darkviolet':'#9400d3',
43 | 'deeppink':'#ff1493',
44 | 'deepskyblue':'#00bfff',
45 | 'dimgray':'#696969',
46 | 'dimgrey':'#696969',
47 | 'dodgerblue':'#1e90ff',
48 | 'firebrick':'#b22222',
49 | 'floralwhite':'#fffaf0',
50 | 'forestgreen':'#228b22',
51 | 'fuchsia':'#ff00ff',
52 | 'gainsboro':'#dcdcdc',
53 | 'ghostwhite':'#f8f8ff',
54 | 'gold':'#ffd700',
55 | 'goldenrod':'#daa520',
56 | 'gray':'#808080',
57 | 'grey':'#808080',
58 | 'green':'#008000',
59 | 'greenyellow':'#adff2f',
60 | 'honeydew':'#f0fff0',
61 | 'hotpink':'#ff69b4',
62 | 'indianred':'#cd5c5c',
63 | 'indigo':'#4b0082',
64 | 'ivory':'#fffff0',
65 | 'khaki':'#f0e68c',
66 | 'lavender':'#e6e6fa',
67 | 'lavenderblush':'#fff0f5',
68 | 'lawngreen':'#7cfc00',
69 | 'lemonchiffon':'#fffacd',
70 | 'lightblue':'#add8e6',
71 | 'lightcoral':'#f08080',
72 | 'lightcyan':'#e0ffff',
73 | 'lightgoldenrodyellow':'#fafad2',
74 | 'lightgray':'#d3d3d3',
75 | 'lightgrey':'#d3d3d3',
76 | 'lightgreen':'#90ee90',
77 | 'lightpink':'#ffb6c1',
78 | 'lightsalmon':'#ffa07a',
79 | 'lightseagreen':'#20b2aa',
80 | 'lightskyblue':'#87cefa',
81 | 'lightslategray':'#778899',
82 | 'lightslategrey':'#778899',
83 | 'lightsteelblue':'#b0c4de',
84 | 'lightyellow':'#ffffe0',
85 | 'lime':'#00ff00',
86 | 'limegreen':'#32cd32',
87 | 'linen':'#faf0e6',
88 | 'magenta':'#ff00ff',
89 | 'maroon':'#800000',
90 | 'mediumaquamarine':'#66cdaa',
91 | 'mediumblue':'#0000cd',
92 | 'mediumorchid':'#ba55d3',
93 | 'mediumpurple':'#9370d8',
94 | 'mediumseagreen':'#3cb371',
95 | 'mediumslateblue':'#7b68ee',
96 | 'mediumspringgreen':'#00fa9a',
97 | 'mediumturquoise':'#48d1cc',
98 | 'mediumvioletred':'#c71585',
99 | 'midnightblue':'#191970',
100 | 'mintcream':'#f5fffa',
101 | 'mistyrose':'#ffe4e1',
102 | 'moccasin':'#ffe4b5',
103 | 'navajowhite':'#ffdead',
104 | 'navy':'#000080',
105 | 'oldlace':'#fdf5e6',
106 | 'olive':'#808000',
107 | 'olivedrab':'#6b8e23',
108 | 'orange':'#ffa500',
109 | 'orangered':'#ff4500',
110 | 'orchid':'#da70d6',
111 | 'palegoldenrod':'#eee8aa',
112 | 'palegreen':'#98fb98',
113 | 'paleturquoise':'#afeeee',
114 | 'palevioletred':'#d87093',
115 | 'papayawhip':'#ffefd5',
116 | 'peachpuff':'#ffdab9',
117 | 'peru':'#cd853f',
118 | 'pink':'#ffc0cb',
119 | 'plum':'#dda0dd',
120 | 'powderblue':'#b0e0e6',
121 | 'purple':'#800080',
122 | 'red':'#ff0000',
123 | 'rosybrown':'#bc8f8f',
124 | 'royalblue':'#4169e1',
125 | 'saddlebrown':'#8b4513',
126 | 'salmon':'#fa8072',
127 | 'sandybrown':'#f4a460',
128 | 'seagreen':'#2e8b57',
129 | 'seashell':'#fff5ee',
130 | 'sienna':'#a0522d',
131 | 'silver':'#c0c0c0',
132 | 'skyblue':'#87ceeb',
133 | 'slateblue':'#6a5acd',
134 | 'slategray':'#708090',
135 | 'slategrey':'#708090',
136 | 'snow':'#fffafa',
137 | 'springgreen':'#00ff7f',
138 | 'steelblue':'#4682b4',
139 | 'tan':'#d2b48c',
140 | 'teal':'#008080',
141 | 'thistle':'#d8bfd8',
142 | 'tomato':'#ff6347',
143 | 'turquoise':'#40e0d0',
144 | 'violet':'#ee82ee',
145 | 'wheat':'#f5deb3',
146 | 'white':'#ffffff',
147 | 'whitesmoke':'#f5f5f5',
148 | 'yellow':'#ffff00',
149 | 'yellowgreen':'#9acd32'
150 | };
151 | })(require('./tree'));
152 |
--------------------------------------------------------------------------------
/src/main/resources/org/lesscss/mojo/js/less/env.js:
--------------------------------------------------------------------------------
1 | (function (tree) {
2 |
3 | var parseCopyProperties = [
4 | 'paths', // option - unmodified - paths to search for imports on
5 | 'optimization', // option - optimization level (for the chunker)
6 | 'files', // list of files that have been imported, used for import-once
7 | 'contents', // browser-only, contents of all the files
8 | 'relativeUrls', // option - whether to adjust URL's to be relative
9 | 'rootpath', // option - rootpath to append to URL's
10 | 'strictImports', // option -
11 | 'insecure', // option - whether to allow imports from insecure ssl hosts
12 | 'dumpLineNumbers', // option - whether to dump line numbers
13 | 'compress', // option - whether to compress
14 | 'processImports', // option - whether to process imports. if false then imports will not be imported
15 | 'syncImport', // option - whether to import synchronously
16 | 'javascriptEnabled',// option - whether JavaScript is enabled. if undefined, defaults to true
17 | 'mime', // browser only - mime type for sheet import
18 | 'useFileCache', // browser only - whether to use the per file session cache
19 | 'currentFileInfo' // information about the current file - for error reporting and importing and making urls relative etc.
20 | ];
21 |
22 | //currentFileInfo = {
23 | // 'relativeUrls' - option - whether to adjust URL's to be relative
24 | // 'filename' - full resolved filename of current file
25 | // 'rootpath' - path to append to normal URLs for this node
26 | // 'currentDirectory' - path to the current file, absolute
27 | // 'rootFilename' - filename of the base file
28 | // 'entryPath' - absolute path to the entry file
29 | // 'reference' - whether the file should not be output and only output parts that are referenced
30 |
31 | tree.parseEnv = function(options) {
32 | copyFromOriginal(options, this, parseCopyProperties);
33 |
34 | if (!this.contents) { this.contents = {}; }
35 | if (!this.files) { this.files = {}; }
36 |
37 | if (!this.currentFileInfo) {
38 | var filename = (options && options.filename) || "input";
39 | var entryPath = filename.replace(/[^\/\\]*$/, "");
40 | if (options) {
41 | options.filename = null;
42 | }
43 | this.currentFileInfo = {
44 | filename: filename,
45 | relativeUrls: this.relativeUrls,
46 | rootpath: (options && options.rootpath) || "",
47 | currentDirectory: entryPath,
48 | entryPath: entryPath,
49 | rootFilename: filename
50 | };
51 | }
52 | };
53 |
54 | var evalCopyProperties = [
55 | 'silent', // whether to swallow errors and warnings
56 | 'verbose', // whether to log more activity
57 | 'compress', // whether to compress
58 | 'yuicompress', // whether to compress with the outside tool yui compressor
59 | 'ieCompat', // whether to enforce IE compatibility (IE8 data-uri)
60 | 'strictMath', // whether math has to be within parenthesis
61 | 'strictUnits', // whether units need to evaluate correctly
62 | 'cleancss', // whether to compress with clean-css
63 | 'sourceMap', // whether to output a source map
64 | 'importMultiple'// whether we are currently importing multiple copies
65 | ];
66 |
67 | tree.evalEnv = function(options, frames) {
68 | copyFromOriginal(options, this, evalCopyProperties);
69 |
70 | this.frames = frames || [];
71 | };
72 |
73 | tree.evalEnv.prototype.inParenthesis = function () {
74 | if (!this.parensStack) {
75 | this.parensStack = [];
76 | }
77 | this.parensStack.push(true);
78 | };
79 |
80 | tree.evalEnv.prototype.outOfParenthesis = function () {
81 | this.parensStack.pop();
82 | };
83 |
84 | tree.evalEnv.prototype.isMathOn = function () {
85 | return this.strictMath ? (this.parensStack && this.parensStack.length) : true;
86 | };
87 |
88 | tree.evalEnv.prototype.isPathRelative = function (path) {
89 | return !/^(?:[a-z-]+:|\/)/.test(path);
90 | };
91 |
92 | tree.evalEnv.prototype.normalizePath = function( path ) {
93 | var
94 | segments = path.split("/").reverse(),
95 | segment;
96 |
97 | path = [];
98 | while (segments.length !== 0 ) {
99 | segment = segments.pop();
100 | switch( segment ) {
101 | case ".":
102 | break;
103 | case "..":
104 | if ((path.length === 0) || (path[path.length - 1] === "..")) {
105 | path.push( segment );
106 | } else {
107 | path.pop();
108 | }
109 | break;
110 | default:
111 | path.push( segment );
112 | break;
113 | }
114 | }
115 |
116 | return path.join("/");
117 | };
118 |
119 | //todo - do the same for the toCSS env
120 | //tree.toCSSEnv = function (options) {
121 | //};
122 |
123 | var copyFromOriginal = function(original, destination, propertiesToCopy) {
124 | if (!original) { return; }
125 |
126 | for(var i = 0; i < propertiesToCopy.length; i++) {
127 | if (original.hasOwnProperty(propertiesToCopy[i])) {
128 | destination[propertiesToCopy[i]] = original[propertiesToCopy[i]];
129 | }
130 | }
131 | };
132 |
133 | })(require('./tree'));
134 |
--------------------------------------------------------------------------------
/src/main/resources/org/lesscss/mojo/js/less/import-visitor.js:
--------------------------------------------------------------------------------
1 | (function (tree) {
2 | tree.importVisitor = function(importer, finish, evalEnv) {
3 | this._visitor = new tree.visitor(this);
4 | this._importer = importer;
5 | this._finish = finish;
6 | this.env = evalEnv || new tree.evalEnv();
7 | this.importCount = 0;
8 | };
9 |
10 | tree.importVisitor.prototype = {
11 | isReplacing: true,
12 | run: function (root) {
13 | var error;
14 | try {
15 | // process the contents
16 | this._visitor.visit(root);
17 | }
18 | catch(e) {
19 | error = e;
20 | }
21 |
22 | this.isFinished = true;
23 |
24 | if (this.importCount === 0) {
25 | this._finish(error);
26 | }
27 | },
28 | visitImport: function (importNode, visitArgs) {
29 | var importVisitor = this,
30 | evaldImportNode,
31 | inlineCSS = importNode.options.inline;
32 |
33 | if (!importNode.css || inlineCSS) {
34 |
35 | try {
36 | evaldImportNode = importNode.evalForImport(this.env);
37 | } catch(e){
38 | if (!e.filename) { e.index = importNode.index; e.filename = importNode.currentFileInfo.filename; }
39 | // attempt to eval properly and treat as css
40 | importNode.css = true;
41 | // if that fails, this error will be thrown
42 | importNode.error = e;
43 | }
44 |
45 | if (evaldImportNode && (!evaldImportNode.css || inlineCSS)) {
46 | importNode = evaldImportNode;
47 | this.importCount++;
48 | var env = new tree.evalEnv(this.env, this.env.frames.slice(0));
49 |
50 | if (importNode.options.multiple) {
51 | env.importMultiple = true;
52 | }
53 |
54 | this._importer.push(importNode.getPath(), importNode.currentFileInfo, importNode.options, function (e, root, imported, fullPath) {
55 | if (e && !e.filename) { e.index = importNode.index; e.filename = importNode.currentFileInfo.filename; }
56 |
57 | if (imported && !env.importMultiple) { importNode.skip = imported; }
58 |
59 | var subFinish = function(e) {
60 | importVisitor.importCount--;
61 |
62 | if (importVisitor.importCount === 0 && importVisitor.isFinished) {
63 | importVisitor._finish(e);
64 | }
65 | };
66 |
67 | if (root) {
68 | importNode.root = root;
69 | importNode.importedFilename = fullPath;
70 | if (!inlineCSS && !importNode.skip) {
71 | new(tree.importVisitor)(importVisitor._importer, subFinish, env)
72 | .run(root);
73 | return;
74 | }
75 | }
76 |
77 | subFinish();
78 | });
79 | }
80 | }
81 | visitArgs.visitDeeper = false;
82 | return importNode;
83 | },
84 | visitRule: function (ruleNode, visitArgs) {
85 | visitArgs.visitDeeper = false;
86 | return ruleNode;
87 | },
88 | visitDirective: function (directiveNode, visitArgs) {
89 | this.env.frames.unshift(directiveNode);
90 | return directiveNode;
91 | },
92 | visitDirectiveOut: function (directiveNode) {
93 | this.env.frames.shift();
94 | },
95 | visitMixinDefinition: function (mixinDefinitionNode, visitArgs) {
96 | this.env.frames.unshift(mixinDefinitionNode);
97 | return mixinDefinitionNode;
98 | },
99 | visitMixinDefinitionOut: function (mixinDefinitionNode) {
100 | this.env.frames.shift();
101 | },
102 | visitRuleset: function (rulesetNode, visitArgs) {
103 | this.env.frames.unshift(rulesetNode);
104 | return rulesetNode;
105 | },
106 | visitRulesetOut: function (rulesetNode) {
107 | this.env.frames.shift();
108 | },
109 | visitMedia: function (mediaNode, visitArgs) {
110 | this.env.frames.unshift(mediaNode.ruleset);
111 | return mediaNode;
112 | },
113 | visitMediaOut: function (mediaNode) {
114 | this.env.frames.shift();
115 | }
116 | };
117 |
118 | })(require('./tree'));
--------------------------------------------------------------------------------
/src/main/resources/org/lesscss/mojo/js/less/index.js:
--------------------------------------------------------------------------------
1 | var path = require('path'),
2 | url = require('url'),
3 | request,
4 | fs = require('fs');
5 |
6 | var less = {
7 | version: [1, 5, 1],
8 | Parser: require('./parser').Parser,
9 | tree: require('./tree'),
10 | render: function (input, options, callback) {
11 | options = options || {};
12 |
13 | if (typeof(options) === 'function') {
14 | callback = options, options = {};
15 | }
16 |
17 | var parser = new(less.Parser)(options),
18 | ee;
19 |
20 | if (callback) {
21 | parser.parse(input, function (e, root) {
22 | try { callback(e, root && root.toCSS && root.toCSS(options)); }
23 | catch (err) { callback(err); }
24 | });
25 | } else {
26 | ee = new (require('events').EventEmitter)();
27 |
28 | process.nextTick(function () {
29 | parser.parse(input, function (e, root) {
30 | if (e) { return ee.emit('error', e); }
31 | try { ee.emit('success', root.toCSS(options)); }
32 | catch (err) { ee.emit('error', err); }
33 | });
34 | });
35 | return ee;
36 | }
37 | },
38 | formatError: function(ctx, options) {
39 | options = options || {};
40 |
41 | var message = "";
42 | var extract = ctx.extract;
43 | var error = [];
44 | var stylize = options.color ? require('./lessc_helper').stylize : function (str) { return str; };
45 |
46 | // only output a stack if it isn't a less error
47 | if (ctx.stack && !ctx.type) { return stylize(ctx.stack, 'red'); }
48 |
49 | if (!ctx.hasOwnProperty('index') || !extract) {
50 | return ctx.stack || ctx.message;
51 | }
52 |
53 | if (typeof(extract[0]) === 'string') {
54 | error.push(stylize((ctx.line - 1) + ' ' + extract[0], 'grey'));
55 | }
56 |
57 | if (typeof(extract[1]) === 'string') {
58 | var errorTxt = ctx.line + ' ';
59 | if (extract[1]) {
60 | errorTxt += extract[1].slice(0, ctx.column) +
61 | stylize(stylize(stylize(extract[1][ctx.column], 'bold') +
62 | extract[1].slice(ctx.column + 1), 'red'), 'inverse');
63 | }
64 | error.push(errorTxt);
65 | }
66 |
67 | if (typeof(extract[2]) === 'string') {
68 | error.push(stylize((ctx.line + 1) + ' ' + extract[2], 'grey'));
69 | }
70 | error = error.join('\n') + stylize('', 'reset') + '\n';
71 |
72 | message += stylize(ctx.type + 'Error: ' + ctx.message, 'red');
73 | ctx.filename && (message += stylize(' in ', 'red') + ctx.filename +
74 | stylize(' on line ' + ctx.line + ', column ' + (ctx.column + 1) + ':', 'grey'));
75 |
76 | message += '\n' + error;
77 |
78 | if (ctx.callLine) {
79 | message += stylize('from ', 'red') + (ctx.filename || '') + '/n';
80 | message += stylize(ctx.callLine, 'grey') + ' ' + ctx.callExtract + '/n';
81 | }
82 |
83 | return message;
84 | },
85 | writeError: function (ctx, options) {
86 | options = options || {};
87 | if (options.silent) { return; }
88 | console.error(less.formatError(ctx, options));
89 | }
90 | };
91 |
92 | ['color', 'directive', 'operation', 'dimension',
93 | 'keyword', 'variable', 'ruleset', 'element',
94 | 'selector', 'quoted', 'expression', 'rule',
95 | 'call', 'url', 'alpha', 'import',
96 | 'mixin', 'comment', 'anonymous', 'value',
97 | 'javascript', 'assignment', 'condition', 'paren',
98 | 'media', 'unicode-descriptor', 'negative', 'extend'
99 | ].forEach(function (n) {
100 | require('./tree/' + n);
101 | });
102 |
103 |
104 | var isUrlRe = /^(?:https?:)?\/\//i;
105 |
106 | less.Parser.fileLoader = function (file, currentFileInfo, callback, env) {
107 | var pathname, dirname, data,
108 | newFileInfo = {
109 | relativeUrls: env.relativeUrls,
110 | entryPath: currentFileInfo.entryPath,
111 | rootpath: currentFileInfo.rootpath,
112 | rootFilename: currentFileInfo.rootFilename
113 | };
114 |
115 | function handleDataAndCallCallback(data) {
116 | var j = file.lastIndexOf('/');
117 |
118 | // Pass on an updated rootpath if path of imported file is relative and file
119 | // is in a (sub|sup) directory
120 | //
121 | // Examples:
122 | // - If path of imported file is 'module/nav/nav.less' and rootpath is 'less/',
123 | // then rootpath should become 'less/module/nav/'
124 | // - If path of imported file is '../mixins.less' and rootpath is 'less/',
125 | // then rootpath should become 'less/../'
126 | if(newFileInfo.relativeUrls && !/^(?:[a-z-]+:|\/)/.test(file) && j != -1) {
127 | var relativeSubDirectory = file.slice(0, j+1);
128 | newFileInfo.rootpath = newFileInfo.rootpath + relativeSubDirectory; // append (sub|sup) directory path of imported file
129 | }
130 | newFileInfo.currentDirectory = pathname.replace(/[^\\\/]*$/, "");
131 | newFileInfo.filename = pathname;
132 |
133 | callback(null, data, pathname, newFileInfo);
134 | }
135 |
136 | var isUrl = isUrlRe.test( file );
137 | if (isUrl || isUrlRe.test(currentFileInfo.currentDirectory)) {
138 | if (request === undefined) {
139 | try { request = require('request'); }
140 | catch(e) { request = null; }
141 | }
142 | if (!request) {
143 | callback({ type: 'File', message: "optional dependency 'request' required to import over http(s)\n" });
144 | return;
145 | }
146 |
147 | var urlStr = isUrl ? file : url.resolve(currentFileInfo.currentDirectory, file),
148 | urlObj = url.parse(urlStr);
149 |
150 | request.get({uri: urlStr, strictSSL: !env.insecure }, function (error, res, body) {
151 | if (res.statusCode === 404) {
152 | callback({ type: 'File', message: "resource '" + urlStr + "' was not found\n" });
153 | return;
154 | }
155 | if (!body) {
156 | console.error( 'Warning: Empty body (HTTP '+ res.statusCode + ') returned by "' + urlStr +'"' );
157 | }
158 | if (error) {
159 | callback({ type: 'File', message: "resource '" + urlStr + "' gave this Error:\n "+ error +"\n" });
160 | }
161 | pathname = urlStr;
162 | dirname = urlObj.protocol +'//'+ urlObj.host + urlObj.pathname.replace(/[^\/]*$/, '');
163 | handleDataAndCallCallback(body);
164 | });
165 | } else {
166 |
167 | var paths = [currentFileInfo.currentDirectory].concat(env.paths);
168 | paths.push('.');
169 |
170 | if (env.syncImport) {
171 | for (var i = 0; i < paths.length; i++) {
172 | try {
173 | pathname = path.join(paths[i], file);
174 | fs.statSync(pathname);
175 | break;
176 | } catch (e) {
177 | pathname = null;
178 | }
179 | }
180 |
181 | if (!pathname) {
182 | callback({ type: 'File', message: "'" + file + "' wasn't found" });
183 | return;
184 | }
185 |
186 | try {
187 | data = fs.readFileSync(pathname, 'utf-8');
188 | handleDataAndCallCallback(data);
189 | } catch (e) {
190 | callback(e);
191 | }
192 | } else {
193 | (function tryPathIndex(i) {
194 | if (i < paths.length) {
195 | pathname = path.join(paths[i], file);
196 | fs.stat(pathname, function (err) {
197 | if (err) {
198 | tryPathIndex(i + 1);
199 | } else {
200 | fs.readFile(pathname, 'utf-8', function(e, data) {
201 | if (e) { callback(e); }
202 | handleDataAndCallCallback(data);
203 | });
204 | }
205 | });
206 | } else {
207 | callback({ type: 'File', message: "'" + file + "' wasn't found" });
208 | }
209 | }(0));
210 | }
211 | }
212 | };
213 |
214 | require('./env');
215 | require('./functions');
216 | require('./colors');
217 | require('./visitor.js');
218 | require('./import-visitor.js');
219 | require('./extend-visitor.js');
220 | require('./join-selector-visitor.js');
221 | require('./to-css-visitor.js');
222 | require('./source-map-output.js');
223 |
224 | for (var k in less) { exports[k] = less[k]; }
225 |
--------------------------------------------------------------------------------
/src/main/resources/org/lesscss/mojo/js/less/join-selector-visitor.js:
--------------------------------------------------------------------------------
1 | (function (tree) {
2 | tree.joinSelectorVisitor = function() {
3 | this.contexts = [[]];
4 | this._visitor = new tree.visitor(this);
5 | };
6 |
7 | tree.joinSelectorVisitor.prototype = {
8 | run: function (root) {
9 | return this._visitor.visit(root);
10 | },
11 | visitRule: function (ruleNode, visitArgs) {
12 | visitArgs.visitDeeper = false;
13 | },
14 | visitMixinDefinition: function (mixinDefinitionNode, visitArgs) {
15 | visitArgs.visitDeeper = false;
16 | },
17 |
18 | visitRuleset: function (rulesetNode, visitArgs) {
19 | var context = this.contexts[this.contexts.length - 1];
20 | var paths = [];
21 | this.contexts.push(paths);
22 |
23 | if (! rulesetNode.root) {
24 | rulesetNode.selectors = rulesetNode.selectors.filter(function(selector) { return selector.getIsOutput(); });
25 | if (rulesetNode.selectors.length === 0) {
26 | rulesetNode.rules.length = 0;
27 | }
28 | rulesetNode.joinSelectors(paths, context, rulesetNode.selectors);
29 | rulesetNode.paths = paths;
30 | }
31 | },
32 | visitRulesetOut: function (rulesetNode) {
33 | this.contexts.length = this.contexts.length - 1;
34 | },
35 | visitMedia: function (mediaNode, visitArgs) {
36 | var context = this.contexts[this.contexts.length - 1];
37 | mediaNode.rules[0].root = (context.length === 0 || context[0].multiMedia);
38 | }
39 | };
40 |
41 | })(require('./tree'));
--------------------------------------------------------------------------------
/src/main/resources/org/lesscss/mojo/js/less/lessc_helper.js:
--------------------------------------------------------------------------------
1 | // lessc_helper.js
2 | //
3 | // helper functions for lessc
4 | var lessc_helper = {
5 |
6 | //Stylize a string
7 | stylize : function(str, style) {
8 | var styles = {
9 | 'reset' : [0, 0],
10 | 'bold' : [1, 22],
11 | 'inverse' : [7, 27],
12 | 'underline' : [4, 24],
13 | 'yellow' : [33, 39],
14 | 'green' : [32, 39],
15 | 'red' : [31, 39],
16 | 'grey' : [90, 39]
17 | };
18 | return '\033[' + styles[style][0] + 'm' + str +
19 | '\033[' + styles[style][1] + 'm';
20 | },
21 |
22 | //Print command line options
23 | printUsage: function() {
24 | console.log("usage: lessc [option option=parameter ...] [destination]");
25 | console.log("");
26 | console.log("If source is set to `-' (dash or hyphen-minus), input is read from stdin.");
27 | console.log("");
28 | console.log("options:");
29 | console.log(" -h, --help Print help (this message) and exit.");
30 | console.log(" --include-path=PATHS Set include paths. Separated by `:'. Use `;' on Windows.");
31 | console.log(" -M, --depends Output a makefile import dependency list to stdout");
32 | console.log(" --no-color Disable colorized output.");
33 | console.log(" --no-ie-compat Disable IE compatibility checks.");
34 | console.log(" --no-js Disable JavaScript in less files");
35 | console.log(" -l, --lint Syntax check only (lint).");
36 | console.log(" -s, --silent Suppress output of error messages.");
37 | console.log(" --strict-imports Force evaluation of imports.");
38 | console.log(" --insecure Allow imports from insecure https hosts.");
39 | console.log(" -v, --version Print version number and exit.");
40 | console.log(" -x, --compress Compress output by removing some whitespaces.");
41 | console.log(" --clean-css Compress output using clean-css");
42 | console.log(" --source-map[=FILENAME] Outputs a v3 sourcemap to the filename (or output filename.map)");
43 | console.log(" --source-map-rootpath=X adds this path onto the sourcemap filename and less file paths");
44 | console.log(" --source-map-basepath=X Sets sourcemap base path, defaults to current working directory.");
45 | console.log(" --source-map-less-inline puts the less files into the map instead of referencing them");
46 | console.log(" --source-map-map-inline puts the map (and any less files) into the output css file");
47 | console.log(" --source-map-url=URL the complete url and filename put in the less file");
48 | console.log(" -rp, --rootpath=URL Set rootpath for url rewriting in relative imports and urls.");
49 | console.log(" Works with or without the relative-urls option.");
50 | console.log(" -ru, --relative-urls re-write relative urls to the base less file.");
51 | console.log(" -sm=on|off Turn on or off strict math, where in strict mode, math");
52 | console.log(" --strict-math=on|off requires brackets. This option may default to on and then");
53 | console.log(" be removed in the future.");
54 | console.log(" -su=on|off Allow mixed units, e.g. 1px+1em or 1px*1px which have units");
55 | console.log(" --strict-units=on|off that cannot be represented.");
56 | console.log(" --global-var='VAR=VALUE' Defines a variable that can be referenced by the file.");
57 | console.log(" --modify-var='VAR=VALUE' Modifies a variable already declared in the file.");
58 | console.log("");
59 | console.log("-------------------------- Deprecated ----------------");
60 | console.log(" -O0, -O1, -O2 Set the parser's optimization level. The lower");
61 | console.log(" the number, the less nodes it will create in the");
62 | console.log(" tree. This could matter for debugging, or if you");
63 | console.log(" want to access the individual nodes in the tree.");
64 | console.log(" --line-numbers=TYPE Outputs filename and line numbers.");
65 | console.log(" TYPE can be either 'comments', which will output");
66 | console.log(" the debug info within comments, 'mediaquery'");
67 | console.log(" that will output the information within a fake");
68 | console.log(" media query which is compatible with the SASS");
69 | console.log(" format, and 'all' which will do both.");
70 | console.log(" --verbose Be verbose.");
71 | console.log("");
72 | console.log("Report bugs to: http://github.com/less/less.js/issues");
73 | console.log("Home page: ");
74 | }
75 | };
76 |
77 | // Exports helper functions
78 | for (var h in lessc_helper) { exports[h] = lessc_helper[h]; }
79 |
--------------------------------------------------------------------------------
/src/main/resources/org/lesscss/mojo/js/less/rhino.js:
--------------------------------------------------------------------------------
1 | /*jshint rhino:true, unused: false */
2 | /*global name:true, less, loadStyleSheet */
3 | var name;
4 |
5 | function error(e, filename) {
6 |
7 | var content = "Error : " + filename + "\n";
8 |
9 | filename = e.filename || filename;
10 |
11 | if (e.message) {
12 | content += e.message + "\n";
13 | }
14 |
15 | var errorline = function (e, i, classname) {
16 | if (e.extract[i]) {
17 | content +=
18 | String(parseInt(e.line, 10) + (i - 1)) +
19 | ":" + e.extract[i] + "\n";
20 | }
21 | };
22 |
23 | if (e.stack) {
24 | content += e.stack;
25 | } else if (e.extract) {
26 | content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':\n';
27 | errorline(e, 0);
28 | errorline(e, 1);
29 | errorline(e, 2);
30 | }
31 | print(content);
32 | }
33 |
34 | function loadStyleSheet(sheet, callback, reload, remaining) {
35 | var endOfPath = Math.max(name.lastIndexOf('/'), name.lastIndexOf('\\')),
36 | sheetName = name.slice(0, endOfPath + 1) + sheet.href,
37 | contents = sheet.contents || {},
38 | input = readFile(sheetName);
39 |
40 | input = input.replace(/^\xEF\xBB\xBF/, '');
41 |
42 | contents[sheetName] = input;
43 |
44 | var parser = new less.Parser({
45 | paths: [sheet.href.replace(/[\w\.-]+$/, '')],
46 | contents: contents
47 | });
48 | parser.parse(input, function (e, root) {
49 | if (e) {
50 | return error(e, sheetName);
51 | }
52 | try {
53 | callback(e, root, input, sheet, { local: false, lastModified: 0, remaining: remaining }, sheetName);
54 | } catch(e) {
55 | error(e, sheetName);
56 | }
57 | });
58 | }
59 |
60 | function writeFile(filename, content) {
61 | var fstream = new java.io.FileWriter(filename);
62 | var out = new java.io.BufferedWriter(fstream);
63 | out.write(content);
64 | out.close();
65 | }
66 |
67 | // Command line integration via Rhino
68 | (function (args) {
69 | var output,
70 | compress = false,
71 | i,
72 | path;
73 |
74 | for(i = 0; i < args.length; i++) {
75 | switch(args[i]) {
76 | case "-x":
77 | compress = true;
78 | break;
79 | default:
80 | if (!name) {
81 | name = args[i];
82 | } else if (!output) {
83 | output = args[i];
84 | } else {
85 | print("unrecognised parameters");
86 | print("input_file [output_file] [-x]");
87 | }
88 | }
89 | }
90 |
91 | if (!name) {
92 | print('No files present in the fileset; Check your pattern match in build.xml');
93 | quit(1);
94 | }
95 | path = name.split("/");path.pop();path=path.join("/");
96 |
97 | var input = readFile(name);
98 |
99 | if (!input) {
100 | print('lesscss: couldn\'t open file ' + name);
101 | quit(1);
102 | }
103 |
104 | var result;
105 | try {
106 | var parser = new less.Parser();
107 | parser.parse(input, function (e, root) {
108 | if (e) {
109 | error(e, name);
110 | quit(1);
111 | } else {
112 | result = root.toCSS({compress: compress || false});
113 | if (output) {
114 | writeFile(output, result);
115 | print("Written to " + output);
116 | } else {
117 | print(result);
118 | }
119 | quit(0);
120 | }
121 | });
122 | }
123 | catch(e) {
124 | error(e, name);
125 | quit(1);
126 | }
127 | print("done");
128 | }(arguments));
--------------------------------------------------------------------------------
/src/main/resources/org/lesscss/mojo/js/less/source-map-output.js:
--------------------------------------------------------------------------------
1 | (function (tree) {
2 |
3 | tree.sourceMapOutput = function (options) {
4 | this._css = [];
5 | this._rootNode = options.rootNode;
6 | this._writeSourceMap = options.writeSourceMap;
7 | this._contentsMap = options.contentsMap;
8 | this._sourceMapFilename = options.sourceMapFilename;
9 | this._outputFilename = options.outputFilename;
10 | this._sourceMapURL = options.sourceMapURL;
11 | this._sourceMapBasepath = options.sourceMapBasepath;
12 | this._sourceMapRootpath = options.sourceMapRootpath;
13 | this._outputSourceFiles = options.outputSourceFiles;
14 | this._sourceMapGeneratorConstructor = options.sourceMapGenerator || require("source-map").SourceMapGenerator;
15 |
16 | if (this._sourceMapRootpath && this._sourceMapRootpath.charAt(this._sourceMapRootpath.length-1) !== '/') {
17 | this._sourceMapRootpath += '/';
18 | }
19 |
20 | this._lineNumber = 0;
21 | this._column = 0;
22 | };
23 |
24 | tree.sourceMapOutput.prototype.normalizeFilename = function(filename) {
25 | if (this._sourceMapBasepath && filename.indexOf(this._sourceMapBasepath) === 0) {
26 | filename = filename.substring(this._sourceMapBasepath.length);
27 | if (filename.charAt(0) === '\\' || filename.charAt(0) === '/') {
28 | filename = filename.substring(1);
29 | }
30 | }
31 | return (this._sourceMapRootpath || "") + filename.replace(/\\/g, '/');
32 | };
33 |
34 | tree.sourceMapOutput.prototype.add = function(chunk, fileInfo, index, mapLines) {
35 |
36 | //ignore adding empty strings
37 | if (!chunk) {
38 | return;
39 | }
40 |
41 | var lines,
42 | sourceLines,
43 | columns,
44 | sourceColumns,
45 | i;
46 |
47 | if (fileInfo) {
48 | var inputSource = this._contentsMap[fileInfo.filename].substring(0, index);
49 | sourceLines = inputSource.split("\n");
50 | sourceColumns = sourceLines[sourceLines.length-1];
51 | }
52 |
53 | lines = chunk.split("\n");
54 | columns = lines[lines.length-1];
55 |
56 | if (fileInfo) {
57 | if (!mapLines) {
58 | this._sourceMapGenerator.addMapping({ generated: { line: this._lineNumber + 1, column: this._column},
59 | original: { line: sourceLines.length, column: sourceColumns.length},
60 | source: this.normalizeFilename(fileInfo.filename)});
61 | } else {
62 | for(i = 0; i < lines.length; i++) {
63 | this._sourceMapGenerator.addMapping({ generated: { line: this._lineNumber + i + 1, column: i === 0 ? this._column : 0},
64 | original: { line: sourceLines.length + i, column: i === 0 ? sourceColumns.length : 0},
65 | source: this.normalizeFilename(fileInfo.filename)});
66 | }
67 | }
68 | }
69 |
70 | if (lines.length === 1) {
71 | this._column += columns.length;
72 | } else {
73 | this._lineNumber += lines.length - 1;
74 | this._column = columns.length;
75 | }
76 |
77 | this._css.push(chunk);
78 | };
79 |
80 | tree.sourceMapOutput.prototype.isEmpty = function() {
81 | return this._css.length === 0;
82 | };
83 |
84 | tree.sourceMapOutput.prototype.toCSS = function(env) {
85 | this._sourceMapGenerator = new this._sourceMapGeneratorConstructor({ file: this._outputFilename, sourceRoot: null });
86 |
87 | if (this._outputSourceFiles) {
88 | for(var filename in this._contentsMap) {
89 | this._sourceMapGenerator.setSourceContent(this.normalizeFilename(filename), this._contentsMap[filename]);
90 | }
91 | }
92 |
93 | this._rootNode.genCSS(env, this);
94 |
95 | if (this._css.length > 0) {
96 | var sourceMapURL,
97 | sourceMapContent = JSON.stringify(this._sourceMapGenerator.toJSON());
98 |
99 | if (this._sourceMapURL) {
100 | sourceMapURL = this._sourceMapURL;
101 | } else if (this._sourceMapFilename) {
102 | sourceMapURL = this.normalizeFilename(this._sourceMapFilename);
103 | }
104 |
105 | if (this._writeSourceMap) {
106 | this._writeSourceMap(sourceMapContent);
107 | } else {
108 | sourceMapURL = "data:application/json," + encodeURIComponent(sourceMapContent);
109 | }
110 |
111 | if (sourceMapURL) {
112 | this._css.push("/*# sourceMappingURL=" + sourceMapURL + " */");
113 | }
114 | }
115 |
116 | return this._css.join('');
117 | };
118 |
119 | })(require('./tree'));
120 |
--------------------------------------------------------------------------------
/src/main/resources/org/lesscss/mojo/js/less/to-css-visitor.js:
--------------------------------------------------------------------------------
1 | (function (tree) {
2 | tree.toCSSVisitor = function(env) {
3 | this._visitor = new tree.visitor(this);
4 | this._env = env;
5 | };
6 |
7 | tree.toCSSVisitor.prototype = {
8 | isReplacing: true,
9 | run: function (root) {
10 | return this._visitor.visit(root);
11 | },
12 |
13 | visitRule: function (ruleNode, visitArgs) {
14 | if (ruleNode.variable) {
15 | return [];
16 | }
17 | return ruleNode;
18 | },
19 |
20 | visitMixinDefinition: function (mixinNode, visitArgs) {
21 | return [];
22 | },
23 |
24 | visitExtend: function (extendNode, visitArgs) {
25 | return [];
26 | },
27 |
28 | visitComment: function (commentNode, visitArgs) {
29 | if (commentNode.isSilent(this._env)) {
30 | return [];
31 | }
32 | return commentNode;
33 | },
34 |
35 | visitMedia: function(mediaNode, visitArgs) {
36 | mediaNode.accept(this._visitor);
37 | visitArgs.visitDeeper = false;
38 |
39 | if (!mediaNode.rules.length) {
40 | return [];
41 | }
42 | return mediaNode;
43 | },
44 |
45 | visitDirective: function(directiveNode, visitArgs) {
46 | if (directiveNode.currentFileInfo.reference && !directiveNode.isReferenced) {
47 | return [];
48 | }
49 | if (directiveNode.name === "@charset") {
50 | // Only output the debug info together with subsequent @charset definitions
51 | // a comment (or @media statement) before the actual @charset directive would
52 | // be considered illegal css as it has to be on the first line
53 | if (this.charset) {
54 | if (directiveNode.debugInfo) {
55 | var comment = new tree.Comment("/* " + directiveNode.toCSS(this._env).replace(/\n/g, "")+" */\n");
56 | comment.debugInfo = directiveNode.debugInfo;
57 | return this._visitor.visit(comment);
58 | }
59 | return [];
60 | }
61 | this.charset = true;
62 | }
63 | return directiveNode;
64 | },
65 |
66 | checkPropertiesInRoot: function(rules) {
67 | var ruleNode;
68 | for(var i = 0; i < rules.length; i++) {
69 | ruleNode = rules[i];
70 | if (ruleNode instanceof tree.Rule && !ruleNode.variable) {
71 | throw { message: "properties must be inside selector blocks, they cannot be in the root.",
72 | index: ruleNode.index, filename: ruleNode.currentFileInfo ? ruleNode.currentFileInfo.filename : null};
73 | }
74 | }
75 | },
76 |
77 | visitRuleset: function (rulesetNode, visitArgs) {
78 | var rule, rulesets = [];
79 | if (rulesetNode.firstRoot) {
80 | this.checkPropertiesInRoot(rulesetNode.rules);
81 | }
82 | if (! rulesetNode.root) {
83 |
84 | rulesetNode.paths = rulesetNode.paths
85 | .filter(function(p) {
86 | var i;
87 | if (p[0].elements[0].combinator.value === ' ') {
88 | p[0].elements[0].combinator = new(tree.Combinator)('');
89 | }
90 | for(i = 0; i < p.length; i++) {
91 | if (p[i].getIsReferenced() && p[i].getIsOutput()) {
92 | return true;
93 | }
94 | return false;
95 | }
96 | });
97 |
98 | // Compile rules and rulesets
99 | for (var i = 0; i < rulesetNode.rules.length; i++) {
100 | rule = rulesetNode.rules[i];
101 |
102 | if (rule.rules) {
103 | // visit because we are moving them out from being a child
104 | rulesets.push(this._visitor.visit(rule));
105 | rulesetNode.rules.splice(i, 1);
106 | i--;
107 | continue;
108 | }
109 | }
110 | // accept the visitor to remove rules and refactor itself
111 | // then we can decide now whether we want it or not
112 | if (rulesetNode.rules.length > 0) {
113 | rulesetNode.accept(this._visitor);
114 | }
115 | visitArgs.visitDeeper = false;
116 |
117 | this._mergeRules(rulesetNode.rules);
118 | this._removeDuplicateRules(rulesetNode.rules);
119 |
120 | // now decide whether we keep the ruleset
121 | if (rulesetNode.rules.length > 0 && rulesetNode.paths.length > 0) {
122 | rulesets.splice(0, 0, rulesetNode);
123 | }
124 | } else {
125 | rulesetNode.accept(this._visitor);
126 | visitArgs.visitDeeper = false;
127 | if (rulesetNode.firstRoot || rulesetNode.rules.length > 0) {
128 | rulesets.splice(0, 0, rulesetNode);
129 | }
130 | }
131 | if (rulesets.length === 1) {
132 | return rulesets[0];
133 | }
134 | return rulesets;
135 | },
136 |
137 | _removeDuplicateRules: function(rules) {
138 | // remove duplicates
139 | var ruleCache = {},
140 | ruleList, rule, i;
141 | for(i = rules.length - 1; i >= 0 ; i--) {
142 | rule = rules[i];
143 | if (rule instanceof tree.Rule) {
144 | if (!ruleCache[rule.name]) {
145 | ruleCache[rule.name] = rule;
146 | } else {
147 | ruleList = ruleCache[rule.name];
148 | if (ruleList instanceof tree.Rule) {
149 | ruleList = ruleCache[rule.name] = [ruleCache[rule.name].toCSS(this._env)];
150 | }
151 | var ruleCSS = rule.toCSS(this._env);
152 | if (ruleList.indexOf(ruleCSS) !== -1) {
153 | rules.splice(i, 1);
154 | } else {
155 | ruleList.push(ruleCSS);
156 | }
157 | }
158 | }
159 | }
160 | },
161 |
162 | _mergeRules: function (rules) {
163 | var groups = {},
164 | parts,
165 | rule,
166 | key;
167 |
168 | for (var i = 0; i < rules.length; i++) {
169 | rule = rules[i];
170 |
171 | if ((rule instanceof tree.Rule) && rule.merge) {
172 | key = [rule.name,
173 | rule.important ? "!" : ""].join(",");
174 |
175 | if (!groups[key]) {
176 | parts = groups[key] = [];
177 | } else {
178 | rules.splice(i--, 1);
179 | }
180 |
181 | parts.push(rule);
182 | }
183 | }
184 |
185 | Object.keys(groups).map(function (k) {
186 | parts = groups[k];
187 |
188 | if (parts.length > 1) {
189 | rule = parts[0];
190 |
191 | rule.value = new (tree.Value)(parts.map(function (p) {
192 | return p.value;
193 | }));
194 | }
195 | });
196 | }
197 | };
198 |
199 | })(require('./tree'));
--------------------------------------------------------------------------------
/src/main/resources/org/lesscss/mojo/js/less/tree.js:
--------------------------------------------------------------------------------
1 | (function (tree) {
2 |
3 | tree.debugInfo = function(env, ctx, lineSeperator) {
4 | var result="";
5 | if (env.dumpLineNumbers && !env.compress) {
6 | switch(env.dumpLineNumbers) {
7 | case 'comments':
8 | result = tree.debugInfo.asComment(ctx);
9 | break;
10 | case 'mediaquery':
11 | result = tree.debugInfo.asMediaQuery(ctx);
12 | break;
13 | case 'all':
14 | result = tree.debugInfo.asComment(ctx) + (lineSeperator || "") + tree.debugInfo.asMediaQuery(ctx);
15 | break;
16 | }
17 | }
18 | return result;
19 | };
20 |
21 | tree.debugInfo.asComment = function(ctx) {
22 | return '/* line ' + ctx.debugInfo.lineNumber + ', ' + ctx.debugInfo.fileName + ' */\n';
23 | };
24 |
25 | tree.debugInfo.asMediaQuery = function(ctx) {
26 | return '@media -sass-debug-info{filename{font-family:' +
27 | ('file://' + ctx.debugInfo.fileName).replace(/([.:/\\])/g, function (a) {
28 | if (a == '\\') {
29 | a = '\/';
30 | }
31 | return '\\' + a;
32 | }) +
33 | '}line{font-family:\\00003' + ctx.debugInfo.lineNumber + '}}\n';
34 | };
35 |
36 | tree.find = function (obj, fun) {
37 | for (var i = 0, r; i < obj.length; i++) {
38 | if (r = fun.call(obj, obj[i])) { return r; }
39 | }
40 | return null;
41 | };
42 |
43 | tree.jsify = function (obj) {
44 | if (Array.isArray(obj.value) && (obj.value.length > 1)) {
45 | return '[' + obj.value.map(function (v) { return v.toCSS(false); }).join(', ') + ']';
46 | } else {
47 | return obj.toCSS(false);
48 | }
49 | };
50 |
51 | tree.toCSS = function (env) {
52 | var strs = [];
53 | this.genCSS(env, {
54 | add: function(chunk, fileInfo, index) {
55 | strs.push(chunk);
56 | },
57 | isEmpty: function () {
58 | return strs.length === 0;
59 | }
60 | });
61 | return strs.join('');
62 | };
63 |
64 | tree.outputRuleset = function (env, output, rules) {
65 | output.add((env.compress ? '{' : ' {\n'));
66 | env.tabLevel = (env.tabLevel || 0) + 1;
67 | var tabRuleStr = env.compress ? '' : Array(env.tabLevel + 1).join(" "),
68 | tabSetStr = env.compress ? '' : Array(env.tabLevel).join(" ");
69 | for(var i = 0; i < rules.length; i++) {
70 | output.add(tabRuleStr);
71 | rules[i].genCSS(env, output);
72 | output.add(env.compress ? '' : '\n');
73 | }
74 | env.tabLevel--;
75 | output.add(tabSetStr + "}");
76 | };
77 |
78 | })(require('./tree'));
79 |
--------------------------------------------------------------------------------
/src/main/resources/org/lesscss/mojo/js/less/tree/alpha.js:
--------------------------------------------------------------------------------
1 | (function (tree) {
2 |
3 | tree.Alpha = function (val) {
4 | this.value = val;
5 | };
6 | tree.Alpha.prototype = {
7 | type: "Alpha",
8 | accept: function (visitor) {
9 | this.value = visitor.visit(this.value);
10 | },
11 | eval: function (env) {
12 | if (this.value.eval) { return new tree.Alpha(this.value.eval(env)); }
13 | return this;
14 | },
15 | genCSS: function (env, output) {
16 | output.add("alpha(opacity=");
17 |
18 | if (this.value.genCSS) {
19 | this.value.genCSS(env, output);
20 | } else {
21 | output.add(this.value);
22 | }
23 |
24 | output.add(")");
25 | },
26 | toCSS: tree.toCSS
27 | };
28 |
29 | })(require('../tree'));
30 |
--------------------------------------------------------------------------------
/src/main/resources/org/lesscss/mojo/js/less/tree/anonymous.js:
--------------------------------------------------------------------------------
1 | (function (tree) {
2 |
3 | tree.Anonymous = function (string, index, currentFileInfo, mapLines) {
4 | this.value = string.value || string;
5 | this.index = index;
6 | this.mapLines = mapLines;
7 | this.currentFileInfo = currentFileInfo;
8 | };
9 | tree.Anonymous.prototype = {
10 | type: "Anonymous",
11 | eval: function () { return this; },
12 | compare: function (x) {
13 | if (!x.toCSS) {
14 | return -1;
15 | }
16 |
17 | var left = this.toCSS(),
18 | right = x.toCSS();
19 |
20 | if (left === right) {
21 | return 0;
22 | }
23 |
24 | return left < right ? -1 : 1;
25 | },
26 | genCSS: function (env, output) {
27 | output.add(this.value, this.currentFileInfo, this.index, this.mapLines);
28 | },
29 | toCSS: tree.toCSS
30 | };
31 |
32 | })(require('../tree'));
33 |
--------------------------------------------------------------------------------
/src/main/resources/org/lesscss/mojo/js/less/tree/assignment.js:
--------------------------------------------------------------------------------
1 | (function (tree) {
2 |
3 | tree.Assignment = function (key, val) {
4 | this.key = key;
5 | this.value = val;
6 | };
7 | tree.Assignment.prototype = {
8 | type: "Assignment",
9 | accept: function (visitor) {
10 | this.value = visitor.visit(this.value);
11 | },
12 | eval: function (env) {
13 | if (this.value.eval) {
14 | return new(tree.Assignment)(this.key, this.value.eval(env));
15 | }
16 | return this;
17 | },
18 | genCSS: function (env, output) {
19 | output.add(this.key + '=');
20 | if (this.value.genCSS) {
21 | this.value.genCSS(env, output);
22 | } else {
23 | output.add(this.value);
24 | }
25 | },
26 | toCSS: tree.toCSS
27 | };
28 |
29 | })(require('../tree'));
30 |
--------------------------------------------------------------------------------
/src/main/resources/org/lesscss/mojo/js/less/tree/call.js:
--------------------------------------------------------------------------------
1 | (function (tree) {
2 |
3 | //
4 | // A function call node.
5 | //
6 | tree.Call = function (name, args, index, currentFileInfo) {
7 | this.name = name;
8 | this.args = args;
9 | this.index = index;
10 | this.currentFileInfo = currentFileInfo;
11 | };
12 | tree.Call.prototype = {
13 | type: "Call",
14 | accept: function (visitor) {
15 | this.args = visitor.visit(this.args);
16 | },
17 | //
18 | // When evaluating a function call,
19 | // we either find the function in `tree.functions` [1],
20 | // in which case we call it, passing the evaluated arguments,
21 | // if this returns null or we cannot find the function, we
22 | // simply print it out as it appeared originally [2].
23 | //
24 | // The *functions.js* file contains the built-in functions.
25 | //
26 | // The reason why we evaluate the arguments, is in the case where
27 | // we try to pass a variable to a function, like: `saturate(@color)`.
28 | // The function should receive the value, not the variable.
29 | //
30 | eval: function (env) {
31 | var args = this.args.map(function (a) { return a.eval(env); }),
32 | nameLC = this.name.toLowerCase(),
33 | result, func;
34 |
35 | if (nameLC in tree.functions) { // 1.
36 | try {
37 | func = new tree.functionCall(env, this.currentFileInfo);
38 | result = func[nameLC].apply(func, args);
39 | /*jshint eqnull:true */
40 | if (result != null) {
41 | return result;
42 | }
43 | } catch (e) {
44 | throw { type: e.type || "Runtime",
45 | message: "error evaluating function `" + this.name + "`" +
46 | (e.message ? ': ' + e.message : ''),
47 | index: this.index, filename: this.currentFileInfo.filename };
48 | }
49 | }
50 |
51 | return new tree.Call(this.name, args, this.index, this.currentFileInfo);
52 | },
53 |
54 | genCSS: function (env, output) {
55 | output.add(this.name + "(", this.currentFileInfo, this.index);
56 |
57 | for(var i = 0; i < this.args.length; i++) {
58 | this.args[i].genCSS(env, output);
59 | if (i + 1 < this.args.length) {
60 | output.add(", ");
61 | }
62 | }
63 |
64 | output.add(")");
65 | },
66 |
67 | toCSS: tree.toCSS
68 | };
69 |
70 | })(require('../tree'));
71 |
--------------------------------------------------------------------------------
/src/main/resources/org/lesscss/mojo/js/less/tree/color.js:
--------------------------------------------------------------------------------
1 | (function (tree) {
2 | //
3 | // RGB Colors - #ff0014, #eee
4 | //
5 | tree.Color = function (rgb, a) {
6 | //
7 | // The end goal here, is to parse the arguments
8 | // into an integer triplet, such as `128, 255, 0`
9 | //
10 | // This facilitates operations and conversions.
11 | //
12 | if (Array.isArray(rgb)) {
13 | this.rgb = rgb;
14 | } else if (rgb.length == 6) {
15 | this.rgb = rgb.match(/.{2}/g).map(function (c) {
16 | return parseInt(c, 16);
17 | });
18 | } else {
19 | this.rgb = rgb.split('').map(function (c) {
20 | return parseInt(c + c, 16);
21 | });
22 | }
23 | this.alpha = typeof(a) === 'number' ? a : 1;
24 | };
25 |
26 | var transparentKeyword = "transparent";
27 |
28 | tree.Color.prototype = {
29 | type: "Color",
30 | eval: function () { return this; },
31 | luma: function () { return (0.2126 * this.rgb[0] / 255) + (0.7152 * this.rgb[1] / 255) + (0.0722 * this.rgb[2] / 255); },
32 |
33 | genCSS: function (env, output) {
34 | output.add(this.toCSS(env));
35 | },
36 | toCSS: function (env, doNotCompress) {
37 | var compress = env && env.compress && !doNotCompress;
38 |
39 | // If we have some transparency, the only way to represent it
40 | // is via `rgba`. Otherwise, we use the hex representation,
41 | // which has better compatibility with older browsers.
42 | // Values are capped between `0` and `255`, rounded and zero-padded.
43 | if (this.alpha < 1.0) {
44 | if (this.alpha === 0 && this.isTransparentKeyword) {
45 | return transparentKeyword;
46 | }
47 | return "rgba(" + this.rgb.map(function (c) {
48 | return Math.round(c);
49 | }).concat(this.alpha).join(',' + (compress ? '' : ' ')) + ")";
50 | } else {
51 | var color = this.toRGB();
52 |
53 | if (compress) {
54 | var splitcolor = color.split('');
55 |
56 | // Convert color to short format
57 | if (splitcolor[1] === splitcolor[2] && splitcolor[3] === splitcolor[4] && splitcolor[5] === splitcolor[6]) {
58 | color = '#' + splitcolor[1] + splitcolor[3] + splitcolor[5];
59 | }
60 | }
61 |
62 | return color;
63 | }
64 | },
65 |
66 | //
67 | // Operations have to be done per-channel, if not,
68 | // channels will spill onto each other. Once we have
69 | // our result, in the form of an integer triplet,
70 | // we create a new Color node to hold the result.
71 | //
72 | operate: function (env, op, other) {
73 | var result = [];
74 |
75 | if (! (other instanceof tree.Color)) {
76 | other = other.toColor();
77 | }
78 |
79 | for (var c = 0; c < 3; c++) {
80 | result[c] = tree.operate(env, op, this.rgb[c], other.rgb[c]);
81 | }
82 | return new(tree.Color)(result, this.alpha + other.alpha);
83 | },
84 |
85 | toRGB: function () {
86 | return '#' + this.rgb.map(function (i) {
87 | i = Math.round(i);
88 | i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16);
89 | return i.length === 1 ? '0' + i : i;
90 | }).join('');
91 | },
92 |
93 | toHSL: function () {
94 | var r = this.rgb[0] / 255,
95 | g = this.rgb[1] / 255,
96 | b = this.rgb[2] / 255,
97 | a = this.alpha;
98 |
99 | var max = Math.max(r, g, b), min = Math.min(r, g, b);
100 | var h, s, l = (max + min) / 2, d = max - min;
101 |
102 | if (max === min) {
103 | h = s = 0;
104 | } else {
105 | s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
106 |
107 | switch (max) {
108 | case r: h = (g - b) / d + (g < b ? 6 : 0); break;
109 | case g: h = (b - r) / d + 2; break;
110 | case b: h = (r - g) / d + 4; break;
111 | }
112 | h /= 6;
113 | }
114 | return { h: h * 360, s: s, l: l, a: a };
115 | },
116 | //Adapted from http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript
117 | toHSV: function () {
118 | var r = this.rgb[0] / 255,
119 | g = this.rgb[1] / 255,
120 | b = this.rgb[2] / 255,
121 | a = this.alpha;
122 |
123 | var max = Math.max(r, g, b), min = Math.min(r, g, b);
124 | var h, s, v = max;
125 |
126 | var d = max - min;
127 | if (max === 0) {
128 | s = 0;
129 | } else {
130 | s = d / max;
131 | }
132 |
133 | if (max === min) {
134 | h = 0;
135 | } else {
136 | switch(max){
137 | case r: h = (g - b) / d + (g < b ? 6 : 0); break;
138 | case g: h = (b - r) / d + 2; break;
139 | case b: h = (r - g) / d + 4; break;
140 | }
141 | h /= 6;
142 | }
143 | return { h: h * 360, s: s, v: v, a: a };
144 | },
145 | toARGB: function () {
146 | var argb = [Math.round(this.alpha * 255)].concat(this.rgb);
147 | return '#' + argb.map(function (i) {
148 | i = Math.round(i);
149 | i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16);
150 | return i.length === 1 ? '0' + i : i;
151 | }).join('');
152 | },
153 | compare: function (x) {
154 | if (!x.rgb) {
155 | return -1;
156 | }
157 |
158 | return (x.rgb[0] === this.rgb[0] &&
159 | x.rgb[1] === this.rgb[1] &&
160 | x.rgb[2] === this.rgb[2] &&
161 | x.alpha === this.alpha) ? 0 : -1;
162 | }
163 | };
164 |
165 | tree.Color.fromKeyword = function(keyword) {
166 | if (tree.colors.hasOwnProperty(keyword)) {
167 | // detect named color
168 | return new(tree.Color)(tree.colors[keyword].slice(1));
169 | }
170 | if (keyword === transparentKeyword) {
171 | var transparent = new(tree.Color)([0, 0, 0], 0);
172 | transparent.isTransparentKeyword = true;
173 | return transparent;
174 | }
175 | };
176 |
177 |
178 | })(require('../tree'));
179 |
--------------------------------------------------------------------------------
/src/main/resources/org/lesscss/mojo/js/less/tree/comment.js:
--------------------------------------------------------------------------------
1 | (function (tree) {
2 |
3 | tree.Comment = function (value, silent, index, currentFileInfo) {
4 | this.value = value;
5 | this.silent = !!silent;
6 | this.currentFileInfo = currentFileInfo;
7 | };
8 | tree.Comment.prototype = {
9 | type: "Comment",
10 | genCSS: function (env, output) {
11 | if (this.debugInfo) {
12 | output.add(tree.debugInfo(env, this), this.currentFileInfo, this.index);
13 | }
14 | output.add(this.value.trim()); //TODO shouldn't need to trim, we shouldn't grab the \n
15 | },
16 | toCSS: tree.toCSS,
17 | isSilent: function(env) {
18 | var isReference = (this.currentFileInfo && this.currentFileInfo.reference && !this.isReferenced),
19 | isCompressed = env.compress && !this.value.match(/^\/\*!/);
20 | return this.silent || isReference || isCompressed;
21 | },
22 | eval: function () { return this; },
23 | markReferenced: function () {
24 | this.isReferenced = true;
25 | }
26 | };
27 |
28 | })(require('../tree'));
29 |
--------------------------------------------------------------------------------
/src/main/resources/org/lesscss/mojo/js/less/tree/condition.js:
--------------------------------------------------------------------------------
1 | (function (tree) {
2 |
3 | tree.Condition = function (op, l, r, i, negate) {
4 | this.op = op.trim();
5 | this.lvalue = l;
6 | this.rvalue = r;
7 | this.index = i;
8 | this.negate = negate;
9 | };
10 | tree.Condition.prototype = {
11 | type: "Condition",
12 | accept: function (visitor) {
13 | this.lvalue = visitor.visit(this.lvalue);
14 | this.rvalue = visitor.visit(this.rvalue);
15 | },
16 | eval: function (env) {
17 | var a = this.lvalue.eval(env),
18 | b = this.rvalue.eval(env);
19 |
20 | var i = this.index, result;
21 |
22 | result = (function (op) {
23 | switch (op) {
24 | case 'and':
25 | return a && b;
26 | case 'or':
27 | return a || b;
28 | default:
29 | if (a.compare) {
30 | result = a.compare(b);
31 | } else if (b.compare) {
32 | result = b.compare(a);
33 | } else {
34 | throw { type: "Type",
35 | message: "Unable to perform comparison",
36 | index: i };
37 | }
38 | switch (result) {
39 | case -1: return op === '<' || op === '=<' || op === '<=';
40 | case 0: return op === '=' || op === '>=' || op === '=<' || op === '<=';
41 | case 1: return op === '>' || op === '>=';
42 | }
43 | }
44 | })(this.op);
45 | return this.negate ? !result : result;
46 | }
47 | };
48 |
49 | })(require('../tree'));
50 |
--------------------------------------------------------------------------------
/src/main/resources/org/lesscss/mojo/js/less/tree/dimension.js:
--------------------------------------------------------------------------------
1 | (function (tree) {
2 |
3 | //
4 | // A number with a unit
5 | //
6 | tree.Dimension = function (value, unit) {
7 | this.value = parseFloat(value);
8 | this.unit = (unit && unit instanceof tree.Unit) ? unit :
9 | new(tree.Unit)(unit ? [unit] : undefined);
10 | };
11 |
12 | tree.Dimension.prototype = {
13 | type: "Dimension",
14 | accept: function (visitor) {
15 | this.unit = visitor.visit(this.unit);
16 | },
17 | eval: function (env) {
18 | return this;
19 | },
20 | toColor: function () {
21 | return new(tree.Color)([this.value, this.value, this.value]);
22 | },
23 | genCSS: function (env, output) {
24 | if ((env && env.strictUnits) && !this.unit.isSingular()) {
25 | throw new Error("Multiple units in dimension. Correct the units or use the unit function. Bad unit: "+this.unit.toString());
26 | }
27 |
28 | var value = this.value,
29 | strValue = String(value);
30 |
31 | if (value !== 0 && value < 0.000001 && value > -0.000001) {
32 | // would be output 1e-6 etc.
33 | strValue = value.toFixed(20).replace(/0+$/, "");
34 | }
35 |
36 | if (env && env.compress) {
37 | // Zero values doesn't need a unit
38 | if (value === 0 && this.unit.isLength()) {
39 | output.add(strValue);
40 | return;
41 | }
42 |
43 | // Float values doesn't need a leading zero
44 | if (value > 0 && value < 1) {
45 | strValue = (strValue).substr(1);
46 | }
47 | }
48 |
49 | output.add(strValue);
50 | this.unit.genCSS(env, output);
51 | },
52 | toCSS: tree.toCSS,
53 |
54 | // In an operation between two Dimensions,
55 | // we default to the first Dimension's unit,
56 | // so `1px + 2` will yield `3px`.
57 | operate: function (env, op, other) {
58 | /*jshint noempty:false */
59 | var value = tree.operate(env, op, this.value, other.value),
60 | unit = this.unit.clone();
61 |
62 | if (op === '+' || op === '-') {
63 | if (unit.numerator.length === 0 && unit.denominator.length === 0) {
64 | unit.numerator = other.unit.numerator.slice(0);
65 | unit.denominator = other.unit.denominator.slice(0);
66 | } else if (other.unit.numerator.length === 0 && unit.denominator.length === 0) {
67 | // do nothing
68 | } else {
69 | other = other.convertTo(this.unit.usedUnits());
70 |
71 | if(env.strictUnits && other.unit.toString() !== unit.toString()) {
72 | throw new Error("Incompatible units. Change the units or use the unit function. Bad units: '" + unit.toString() +
73 | "' and '" + other.unit.toString() + "'.");
74 | }
75 |
76 | value = tree.operate(env, op, this.value, other.value);
77 | }
78 | } else if (op === '*') {
79 | unit.numerator = unit.numerator.concat(other.unit.numerator).sort();
80 | unit.denominator = unit.denominator.concat(other.unit.denominator).sort();
81 | unit.cancel();
82 | } else if (op === '/') {
83 | unit.numerator = unit.numerator.concat(other.unit.denominator).sort();
84 | unit.denominator = unit.denominator.concat(other.unit.numerator).sort();
85 | unit.cancel();
86 | }
87 | return new(tree.Dimension)(value, unit);
88 | },
89 |
90 | compare: function (other) {
91 | if (other instanceof tree.Dimension) {
92 | var a = this.unify(), b = other.unify(),
93 | aValue = a.value, bValue = b.value;
94 |
95 | if (bValue > aValue) {
96 | return -1;
97 | } else if (bValue < aValue) {
98 | return 1;
99 | } else {
100 | if (!b.unit.isEmpty() && a.unit.compare(b.unit) !== 0) {
101 | return -1;
102 | }
103 | return 0;
104 | }
105 | } else {
106 | return -1;
107 | }
108 | },
109 |
110 | unify: function () {
111 | return this.convertTo({ length: 'm', duration: 's', angle: 'rad' });
112 | },
113 |
114 | convertTo: function (conversions) {
115 | var value = this.value, unit = this.unit.clone(),
116 | i, groupName, group, targetUnit, derivedConversions = {}, applyUnit;
117 |
118 | if (typeof conversions === 'string') {
119 | for(i in tree.UnitConversions) {
120 | if (tree.UnitConversions[i].hasOwnProperty(conversions)) {
121 | derivedConversions = {};
122 | derivedConversions[i] = conversions;
123 | }
124 | }
125 | conversions = derivedConversions;
126 | }
127 | applyUnit = function (atomicUnit, denominator) {
128 | /*jshint loopfunc:true */
129 | if (group.hasOwnProperty(atomicUnit)) {
130 | if (denominator) {
131 | value = value / (group[atomicUnit] / group[targetUnit]);
132 | } else {
133 | value = value * (group[atomicUnit] / group[targetUnit]);
134 | }
135 |
136 | return targetUnit;
137 | }
138 |
139 | return atomicUnit;
140 | };
141 |
142 | for (groupName in conversions) {
143 | if (conversions.hasOwnProperty(groupName)) {
144 | targetUnit = conversions[groupName];
145 | group = tree.UnitConversions[groupName];
146 |
147 | unit.map(applyUnit);
148 | }
149 | }
150 |
151 | unit.cancel();
152 |
153 | return new(tree.Dimension)(value, unit);
154 | }
155 | };
156 |
157 | // http://www.w3.org/TR/css3-values/#absolute-lengths
158 | tree.UnitConversions = {
159 | length: {
160 | 'm': 1,
161 | 'cm': 0.01,
162 | 'mm': 0.001,
163 | 'in': 0.0254,
164 | 'pt': 0.0254 / 72,
165 | 'pc': 0.0254 / 72 * 12
166 | },
167 | duration: {
168 | 's': 1,
169 | 'ms': 0.001
170 | },
171 | angle: {
172 | 'rad': 1/(2*Math.PI),
173 | 'deg': 1/360,
174 | 'grad': 1/400,
175 | 'turn': 1
176 | }
177 | };
178 |
179 | tree.Unit = function (numerator, denominator, backupUnit) {
180 | this.numerator = numerator ? numerator.slice(0).sort() : [];
181 | this.denominator = denominator ? denominator.slice(0).sort() : [];
182 | this.backupUnit = backupUnit;
183 | };
184 |
185 | tree.Unit.prototype = {
186 | type: "Unit",
187 | clone: function () {
188 | return new tree.Unit(this.numerator.slice(0), this.denominator.slice(0), this.backupUnit);
189 | },
190 | genCSS: function (env, output) {
191 | if (this.numerator.length >= 1) {
192 | output.add(this.numerator[0]);
193 | } else
194 | if (this.denominator.length >= 1) {
195 | output.add(this.denominator[0]);
196 | } else
197 | if ((!env || !env.strictUnits) && this.backupUnit) {
198 | output.add(this.backupUnit);
199 | }
200 | },
201 | toCSS: tree.toCSS,
202 |
203 | toString: function () {
204 | var i, returnStr = this.numerator.join("*");
205 | for (i = 0; i < this.denominator.length; i++) {
206 | returnStr += "/" + this.denominator[i];
207 | }
208 | return returnStr;
209 | },
210 |
211 | compare: function (other) {
212 | return this.is(other.toString()) ? 0 : -1;
213 | },
214 |
215 | is: function (unitString) {
216 | return this.toString() === unitString;
217 | },
218 |
219 | isLength: function () {
220 | return Boolean(this.toCSS().match(/px|em|%|in|cm|mm|pc|pt|ex/));
221 | },
222 |
223 | isEmpty: function () {
224 | return this.numerator.length === 0 && this.denominator.length === 0;
225 | },
226 |
227 | isSingular: function() {
228 | return this.numerator.length <= 1 && this.denominator.length === 0;
229 | },
230 |
231 | map: function(callback) {
232 | var i;
233 |
234 | for (i = 0; i < this.numerator.length; i++) {
235 | this.numerator[i] = callback(this.numerator[i], false);
236 | }
237 |
238 | for (i = 0; i < this.denominator.length; i++) {
239 | this.denominator[i] = callback(this.denominator[i], true);
240 | }
241 | },
242 |
243 | usedUnits: function() {
244 | var group, result = {}, mapUnit;
245 |
246 | mapUnit = function (atomicUnit) {
247 | /*jshint loopfunc:true */
248 | if (group.hasOwnProperty(atomicUnit) && !result[groupName]) {
249 | result[groupName] = atomicUnit;
250 | }
251 |
252 | return atomicUnit;
253 | };
254 |
255 | for (var groupName in tree.UnitConversions) {
256 | if (tree.UnitConversions.hasOwnProperty(groupName)) {
257 | group = tree.UnitConversions[groupName];
258 |
259 | this.map(mapUnit);
260 | }
261 | }
262 |
263 | return result;
264 | },
265 |
266 | cancel: function () {
267 | var counter = {}, atomicUnit, i, backup;
268 |
269 | for (i = 0; i < this.numerator.length; i++) {
270 | atomicUnit = this.numerator[i];
271 | if (!backup) {
272 | backup = atomicUnit;
273 | }
274 | counter[atomicUnit] = (counter[atomicUnit] || 0) + 1;
275 | }
276 |
277 | for (i = 0; i < this.denominator.length; i++) {
278 | atomicUnit = this.denominator[i];
279 | if (!backup) {
280 | backup = atomicUnit;
281 | }
282 | counter[atomicUnit] = (counter[atomicUnit] || 0) - 1;
283 | }
284 |
285 | this.numerator = [];
286 | this.denominator = [];
287 |
288 | for (atomicUnit in counter) {
289 | if (counter.hasOwnProperty(atomicUnit)) {
290 | var count = counter[atomicUnit];
291 |
292 | if (count > 0) {
293 | for (i = 0; i < count; i++) {
294 | this.numerator.push(atomicUnit);
295 | }
296 | } else if (count < 0) {
297 | for (i = 0; i < -count; i++) {
298 | this.denominator.push(atomicUnit);
299 | }
300 | }
301 | }
302 | }
303 |
304 | if (this.numerator.length === 0 && this.denominator.length === 0 && backup) {
305 | this.backupUnit = backup;
306 | }
307 |
308 | this.numerator.sort();
309 | this.denominator.sort();
310 | }
311 | };
312 |
313 | })(require('../tree'));
314 |
--------------------------------------------------------------------------------
/src/main/resources/org/lesscss/mojo/js/less/tree/directive.js:
--------------------------------------------------------------------------------
1 | (function (tree) {
2 |
3 | tree.Directive = function (name, value, index, currentFileInfo) {
4 | this.name = name;
5 |
6 | if (Array.isArray(value)) {
7 | this.rules = [new(tree.Ruleset)([], value)];
8 | this.rules[0].allowImports = true;
9 | } else {
10 | this.value = value;
11 | }
12 | this.currentFileInfo = currentFileInfo;
13 |
14 | };
15 | tree.Directive.prototype = {
16 | type: "Directive",
17 | accept: function (visitor) {
18 | this.rules = visitor.visit(this.rules);
19 | this.value = visitor.visit(this.value);
20 | },
21 | genCSS: function (env, output) {
22 | output.add(this.name, this.currentFileInfo, this.index);
23 | if (this.rules) {
24 | tree.outputRuleset(env, output, this.rules);
25 | } else {
26 | output.add(' ');
27 | this.value.genCSS(env, output);
28 | output.add(';');
29 | }
30 | },
31 | toCSS: tree.toCSS,
32 | eval: function (env) {
33 | var evaldDirective = this;
34 | if (this.rules) {
35 | env.frames.unshift(this);
36 | evaldDirective = new(tree.Directive)(this.name, null, this.index, this.currentFileInfo);
37 | evaldDirective.rules = [this.rules[0].eval(env)];
38 | evaldDirective.rules[0].root = true;
39 | env.frames.shift();
40 | }
41 | return evaldDirective;
42 | },
43 | variable: function (name) { return tree.Ruleset.prototype.variable.call(this.rules[0], name); },
44 | find: function () { return tree.Ruleset.prototype.find.apply(this.rules[0], arguments); },
45 | rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.rules[0]); },
46 | markReferenced: function () {
47 | var i, rules;
48 | this.isReferenced = true;
49 | if (this.rules) {
50 | rules = this.rules[0].rules;
51 | for (i = 0; i < rules.length; i++) {
52 | if (rules[i].markReferenced) {
53 | rules[i].markReferenced();
54 | }
55 | }
56 | }
57 | }
58 | };
59 |
60 | })(require('../tree'));
61 |
--------------------------------------------------------------------------------
/src/main/resources/org/lesscss/mojo/js/less/tree/element.js:
--------------------------------------------------------------------------------
1 | (function (tree) {
2 |
3 | tree.Element = function (combinator, value, index, currentFileInfo) {
4 | this.combinator = combinator instanceof tree.Combinator ?
5 | combinator : new(tree.Combinator)(combinator);
6 |
7 | if (typeof(value) === 'string') {
8 | this.value = value.trim();
9 | } else if (value) {
10 | this.value = value;
11 | } else {
12 | this.value = "";
13 | }
14 | this.index = index;
15 | this.currentFileInfo = currentFileInfo;
16 | };
17 | tree.Element.prototype = {
18 | type: "Element",
19 | accept: function (visitor) {
20 | this.combinator = visitor.visit(this.combinator);
21 | this.value = visitor.visit(this.value);
22 | },
23 | eval: function (env) {
24 | return new(tree.Element)(this.combinator,
25 | this.value.eval ? this.value.eval(env) : this.value,
26 | this.index,
27 | this.currentFileInfo);
28 | },
29 | genCSS: function (env, output) {
30 | output.add(this.toCSS(env), this.currentFileInfo, this.index);
31 | },
32 | toCSS: function (env) {
33 | var value = (this.value.toCSS ? this.value.toCSS(env) : this.value);
34 | if (value === '' && this.combinator.value.charAt(0) === '&') {
35 | return '';
36 | } else {
37 | return this.combinator.toCSS(env || {}) + value;
38 | }
39 | }
40 | };
41 |
42 | tree.Attribute = function (key, op, value) {
43 | this.key = key;
44 | this.op = op;
45 | this.value = value;
46 | };
47 | tree.Attribute.prototype = {
48 | type: "Attribute",
49 | accept: function (visitor) {
50 | this.value = visitor.visit(this.value);
51 | },
52 | eval: function (env) {
53 | return new(tree.Attribute)(this.key.eval ? this.key.eval(env) : this.key,
54 | this.op, (this.value && this.value.eval) ? this.value.eval(env) : this.value);
55 | },
56 | genCSS: function (env, output) {
57 | output.add(this.toCSS(env));
58 | },
59 | toCSS: function (env) {
60 | var value = this.key.toCSS ? this.key.toCSS(env) : this.key;
61 |
62 | if (this.op) {
63 | value += this.op;
64 | value += (this.value.toCSS ? this.value.toCSS(env) : this.value);
65 | }
66 |
67 | return '[' + value + ']';
68 | }
69 | };
70 |
71 | tree.Combinator = function (value) {
72 | if (value === ' ') {
73 | this.value = ' ';
74 | } else {
75 | this.value = value ? value.trim() : "";
76 | }
77 | };
78 | tree.Combinator.prototype = {
79 | type: "Combinator",
80 | _outputMap: {
81 | '' : '',
82 | ' ' : ' ',
83 | ':' : ' :',
84 | '+' : ' + ',
85 | '~' : ' ~ ',
86 | '>' : ' > ',
87 | '|' : '|'
88 | },
89 | _outputMapCompressed: {
90 | '' : '',
91 | ' ' : ' ',
92 | ':' : ' :',
93 | '+' : '+',
94 | '~' : '~',
95 | '>' : '>',
96 | '|' : '|'
97 | },
98 | genCSS: function (env, output) {
99 | output.add((env.compress ? this._outputMapCompressed : this._outputMap)[this.value]);
100 | },
101 | toCSS: tree.toCSS
102 | };
103 |
104 | })(require('../tree'));
105 |
--------------------------------------------------------------------------------
/src/main/resources/org/lesscss/mojo/js/less/tree/expression.js:
--------------------------------------------------------------------------------
1 | (function (tree) {
2 |
3 | tree.Expression = function (value) { this.value = value; };
4 | tree.Expression.prototype = {
5 | type: "Expression",
6 | accept: function (visitor) {
7 | this.value = visitor.visit(this.value);
8 | },
9 | eval: function (env) {
10 | var returnValue,
11 | inParenthesis = this.parens && !this.parensInOp,
12 | doubleParen = false;
13 | if (inParenthesis) {
14 | env.inParenthesis();
15 | }
16 | if (this.value.length > 1) {
17 | returnValue = new(tree.Expression)(this.value.map(function (e) {
18 | return e.eval(env);
19 | }));
20 | } else if (this.value.length === 1) {
21 | if (this.value[0].parens && !this.value[0].parensInOp) {
22 | doubleParen = true;
23 | }
24 | returnValue = this.value[0].eval(env);
25 | } else {
26 | returnValue = this;
27 | }
28 | if (inParenthesis) {
29 | env.outOfParenthesis();
30 | }
31 | if (this.parens && this.parensInOp && !(env.isMathOn()) && !doubleParen) {
32 | returnValue = new(tree.Paren)(returnValue);
33 | }
34 | return returnValue;
35 | },
36 | genCSS: function (env, output) {
37 | for(var i = 0; i < this.value.length; i++) {
38 | this.value[i].genCSS(env, output);
39 | if (i + 1 < this.value.length) {
40 | output.add(" ");
41 | }
42 | }
43 | },
44 | toCSS: tree.toCSS,
45 | throwAwayComments: function () {
46 | this.value = this.value.filter(function(v) {
47 | return !(v instanceof tree.Comment);
48 | });
49 | }
50 | };
51 |
52 | })(require('../tree'));
53 |
--------------------------------------------------------------------------------
/src/main/resources/org/lesscss/mojo/js/less/tree/extend.js:
--------------------------------------------------------------------------------
1 | (function (tree) {
2 |
3 | tree.Extend = function Extend(selector, option, index) {
4 | this.selector = selector;
5 | this.option = option;
6 | this.index = index;
7 |
8 | switch(option) {
9 | case "all":
10 | this.allowBefore = true;
11 | this.allowAfter = true;
12 | break;
13 | default:
14 | this.allowBefore = false;
15 | this.allowAfter = false;
16 | break;
17 | }
18 | };
19 |
20 | tree.Extend.prototype = {
21 | type: "Extend",
22 | accept: function (visitor) {
23 | this.selector = visitor.visit(this.selector);
24 | },
25 | eval: function (env) {
26 | return new(tree.Extend)(this.selector.eval(env), this.option, this.index);
27 | },
28 | clone: function (env) {
29 | return new(tree.Extend)(this.selector, this.option, this.index);
30 | },
31 | findSelfSelectors: function (selectors) {
32 | var selfElements = [],
33 | i,
34 | selectorElements;
35 |
36 | for(i = 0; i < selectors.length; i++) {
37 | selectorElements = selectors[i].elements;
38 | // duplicate the logic in genCSS function inside the selector node.
39 | // future TODO - move both logics into the selector joiner visitor
40 | if (i > 0 && selectorElements.length && selectorElements[0].combinator.value === "") {
41 | selectorElements[0].combinator.value = ' ';
42 | }
43 | selfElements = selfElements.concat(selectors[i].elements);
44 | }
45 |
46 | this.selfSelectors = [{ elements: selfElements }];
47 | }
48 | };
49 |
50 | })(require('../tree'));
51 |
--------------------------------------------------------------------------------
/src/main/resources/org/lesscss/mojo/js/less/tree/import.js:
--------------------------------------------------------------------------------
1 | (function (tree) {
2 | //
3 | // CSS @import node
4 | //
5 | // The general strategy here is that we don't want to wait
6 | // for the parsing to be completed, before we start importing
7 | // the file. That's because in the context of a browser,
8 | // most of the time will be spent waiting for the server to respond.
9 | //
10 | // On creation, we push the import path to our import queue, though
11 | // `import,push`, we also pass it a callback, which it'll call once
12 | // the file has been fetched, and parsed.
13 | //
14 | tree.Import = function (path, features, options, index, currentFileInfo) {
15 | this.options = options;
16 | this.index = index;
17 | this.path = path;
18 | this.features = features;
19 | this.currentFileInfo = currentFileInfo;
20 |
21 | if (this.options.less !== undefined || this.options.inline) {
22 | this.css = !this.options.less || this.options.inline;
23 | } else {
24 | var pathValue = this.getPath();
25 | if (pathValue && /css([\?;].*)?$/.test(pathValue)) {
26 | this.css = true;
27 | }
28 | }
29 | };
30 |
31 | //
32 | // The actual import node doesn't return anything, when converted to CSS.
33 | // The reason is that it's used at the evaluation stage, so that the rules
34 | // it imports can be treated like any other rules.
35 | //
36 | // In `eval`, we make sure all Import nodes get evaluated, recursively, so
37 | // we end up with a flat structure, which can easily be imported in the parent
38 | // ruleset.
39 | //
40 | tree.Import.prototype = {
41 | type: "Import",
42 | accept: function (visitor) {
43 | this.features = visitor.visit(this.features);
44 | this.path = visitor.visit(this.path);
45 | if (!this.options.inline) {
46 | this.root = visitor.visit(this.root);
47 | }
48 | },
49 | genCSS: function (env, output) {
50 | if (this.css) {
51 | output.add("@import ", this.currentFileInfo, this.index);
52 | this.path.genCSS(env, output);
53 | if (this.features) {
54 | output.add(" ");
55 | this.features.genCSS(env, output);
56 | }
57 | output.add(';');
58 | }
59 | },
60 | toCSS: tree.toCSS,
61 | getPath: function () {
62 | if (this.path instanceof tree.Quoted) {
63 | var path = this.path.value;
64 | return (this.css !== undefined || /(\.[a-z]*$)|([\?;].*)$/.test(path)) ? path : path + '.less';
65 | } else if (this.path instanceof tree.URL) {
66 | return this.path.value.value;
67 | }
68 | return null;
69 | },
70 | evalForImport: function (env) {
71 | return new(tree.Import)(this.path.eval(env), this.features, this.options, this.index, this.currentFileInfo);
72 | },
73 | evalPath: function (env) {
74 | var path = this.path.eval(env);
75 | var rootpath = this.currentFileInfo && this.currentFileInfo.rootpath;
76 |
77 | if (!(path instanceof tree.URL)) {
78 | if (rootpath) {
79 | var pathValue = path.value;
80 | // Add the base path if the import is relative
81 | if (pathValue && env.isPathRelative(pathValue)) {
82 | path.value = rootpath + pathValue;
83 | }
84 | }
85 | path.value = env.normalizePath(path.value);
86 | }
87 |
88 | return path;
89 | },
90 | eval: function (env) {
91 | var ruleset, features = this.features && this.features.eval(env);
92 |
93 | if (this.skip) { return []; }
94 |
95 | if (this.options.inline) {
96 | //todo needs to reference css file not import
97 | var contents = new(tree.Anonymous)(this.root, 0, {filename: this.importedFilename}, true);
98 | return this.features ? new(tree.Media)([contents], this.features.value) : [contents];
99 | } else if (this.css) {
100 | var newImport = new(tree.Import)(this.evalPath(env), features, this.options, this.index);
101 | if (!newImport.css && this.error) {
102 | throw this.error;
103 | }
104 | return newImport;
105 | } else {
106 | ruleset = new(tree.Ruleset)([], this.root.rules.slice(0));
107 |
108 | ruleset.evalImports(env);
109 |
110 | return this.features ? new(tree.Media)(ruleset.rules, this.features.value) : ruleset.rules;
111 | }
112 | }
113 | };
114 |
115 | })(require('../tree'));
116 |
--------------------------------------------------------------------------------
/src/main/resources/org/lesscss/mojo/js/less/tree/javascript.js:
--------------------------------------------------------------------------------
1 | (function (tree) {
2 |
3 | tree.JavaScript = function (string, index, escaped) {
4 | this.escaped = escaped;
5 | this.expression = string;
6 | this.index = index;
7 | };
8 | tree.JavaScript.prototype = {
9 | type: "JavaScript",
10 | eval: function (env) {
11 | var result,
12 | that = this,
13 | context = {};
14 |
15 | var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) {
16 | return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env));
17 | });
18 |
19 | try {
20 | expression = new(Function)('return (' + expression + ')');
21 | } catch (e) {
22 | throw { message: "JavaScript evaluation error: " + e.message + " from `" + expression + "`" ,
23 | index: this.index };
24 | }
25 |
26 | for (var k in env.frames[0].variables()) {
27 | /*jshint loopfunc:true */
28 | context[k.slice(1)] = {
29 | value: env.frames[0].variables()[k].value,
30 | toJS: function () {
31 | return this.value.eval(env).toCSS();
32 | }
33 | };
34 | }
35 |
36 | try {
37 | result = expression.call(context);
38 | } catch (e) {
39 | throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" ,
40 | index: this.index };
41 | }
42 | if (typeof(result) === 'string') {
43 | return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index);
44 | } else if (Array.isArray(result)) {
45 | return new(tree.Anonymous)(result.join(', '));
46 | } else {
47 | return new(tree.Anonymous)(result);
48 | }
49 | }
50 | };
51 |
52 | })(require('../tree'));
53 |
54 |
--------------------------------------------------------------------------------
/src/main/resources/org/lesscss/mojo/js/less/tree/keyword.js:
--------------------------------------------------------------------------------
1 | (function (tree) {
2 |
3 | tree.Keyword = function (value) { this.value = value; };
4 | tree.Keyword.prototype = {
5 | type: "Keyword",
6 | eval: function () { return this; },
7 | genCSS: function (env, output) {
8 | output.add(this.value);
9 | },
10 | toCSS: tree.toCSS,
11 | compare: function (other) {
12 | if (other instanceof tree.Keyword) {
13 | return other.value === this.value ? 0 : 1;
14 | } else {
15 | return -1;
16 | }
17 | }
18 | };
19 |
20 | tree.True = new(tree.Keyword)('true');
21 | tree.False = new(tree.Keyword)('false');
22 |
23 | })(require('../tree'));
24 |
--------------------------------------------------------------------------------
/src/main/resources/org/lesscss/mojo/js/less/tree/media.js:
--------------------------------------------------------------------------------
1 | (function (tree) {
2 |
3 | tree.Media = function (value, features, index, currentFileInfo) {
4 | this.index = index;
5 | this.currentFileInfo = currentFileInfo;
6 |
7 | var selectors = this.emptySelectors();
8 |
9 | this.features = new(tree.Value)(features);
10 | this.rules = [new(tree.Ruleset)(selectors, value)];
11 | this.rules[0].allowImports = true;
12 | };
13 | tree.Media.prototype = {
14 | type: "Media",
15 | accept: function (visitor) {
16 | this.features = visitor.visit(this.features);
17 | this.rules = visitor.visit(this.rules);
18 | },
19 | genCSS: function (env, output) {
20 | output.add('@media ', this.currentFileInfo, this.index);
21 | this.features.genCSS(env, output);
22 | tree.outputRuleset(env, output, this.rules);
23 | },
24 | toCSS: tree.toCSS,
25 | eval: function (env) {
26 | if (!env.mediaBlocks) {
27 | env.mediaBlocks = [];
28 | env.mediaPath = [];
29 | }
30 |
31 | var media = new(tree.Media)([], [], this.index, this.currentFileInfo);
32 | if(this.debugInfo) {
33 | this.rules[0].debugInfo = this.debugInfo;
34 | media.debugInfo = this.debugInfo;
35 | }
36 | var strictMathBypass = false;
37 | if (!env.strictMath) {
38 | strictMathBypass = true;
39 | env.strictMath = true;
40 | }
41 | try {
42 | media.features = this.features.eval(env);
43 | }
44 | finally {
45 | if (strictMathBypass) {
46 | env.strictMath = false;
47 | }
48 | }
49 |
50 | env.mediaPath.push(media);
51 | env.mediaBlocks.push(media);
52 |
53 | env.frames.unshift(this.rules[0]);
54 | media.rules = [this.rules[0].eval(env)];
55 | env.frames.shift();
56 |
57 | env.mediaPath.pop();
58 |
59 | return env.mediaPath.length === 0 ? media.evalTop(env) :
60 | media.evalNested(env);
61 | },
62 | variable: function (name) { return tree.Ruleset.prototype.variable.call(this.rules[0], name); },
63 | find: function () { return tree.Ruleset.prototype.find.apply(this.rules[0], arguments); },
64 | rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.rules[0]); },
65 | emptySelectors: function() {
66 | var el = new(tree.Element)('', '&', this.index, this.currentFileInfo);
67 | return [new(tree.Selector)([el], null, null, this.index, this.currentFileInfo)];
68 | },
69 | markReferenced: function () {
70 | var i, rules = this.rules[0].rules;
71 | this.isReferenced = true;
72 | for (i = 0; i < rules.length; i++) {
73 | if (rules[i].markReferenced) {
74 | rules[i].markReferenced();
75 | }
76 | }
77 | },
78 |
79 | evalTop: function (env) {
80 | var result = this;
81 |
82 | // Render all dependent Media blocks.
83 | if (env.mediaBlocks.length > 1) {
84 | var selectors = this.emptySelectors();
85 | result = new(tree.Ruleset)(selectors, env.mediaBlocks);
86 | result.multiMedia = true;
87 | }
88 |
89 | delete env.mediaBlocks;
90 | delete env.mediaPath;
91 |
92 | return result;
93 | },
94 | evalNested: function (env) {
95 | var i, value,
96 | path = env.mediaPath.concat([this]);
97 |
98 | // Extract the media-query conditions separated with `,` (OR).
99 | for (i = 0; i < path.length; i++) {
100 | value = path[i].features instanceof tree.Value ?
101 | path[i].features.value : path[i].features;
102 | path[i] = Array.isArray(value) ? value : [value];
103 | }
104 |
105 | // Trace all permutations to generate the resulting media-query.
106 | //
107 | // (a, b and c) with nested (d, e) ->
108 | // a and d
109 | // a and e
110 | // b and c and d
111 | // b and c and e
112 | this.features = new(tree.Value)(this.permute(path).map(function (path) {
113 | path = path.map(function (fragment) {
114 | return fragment.toCSS ? fragment : new(tree.Anonymous)(fragment);
115 | });
116 |
117 | for(i = path.length - 1; i > 0; i--) {
118 | path.splice(i, 0, new(tree.Anonymous)("and"));
119 | }
120 |
121 | return new(tree.Expression)(path);
122 | }));
123 |
124 | // Fake a tree-node that doesn't output anything.
125 | return new(tree.Ruleset)([], []);
126 | },
127 | permute: function (arr) {
128 | if (arr.length === 0) {
129 | return [];
130 | } else if (arr.length === 1) {
131 | return arr[0];
132 | } else {
133 | var result = [];
134 | var rest = this.permute(arr.slice(1));
135 | for (var i = 0; i < rest.length; i++) {
136 | for (var j = 0; j < arr[0].length; j++) {
137 | result.push([arr[0][j]].concat(rest[i]));
138 | }
139 | }
140 | return result;
141 | }
142 | },
143 | bubbleSelectors: function (selectors) {
144 | this.rules = [new(tree.Ruleset)(selectors.slice(0), [this.rules[0]])];
145 | }
146 | };
147 |
148 | })(require('../tree'));
149 |
--------------------------------------------------------------------------------
/src/main/resources/org/lesscss/mojo/js/less/tree/mixin.js:
--------------------------------------------------------------------------------
1 | (function (tree) {
2 |
3 | tree.mixin = {};
4 | tree.mixin.Call = function (elements, args, index, currentFileInfo, important) {
5 | this.selector = new(tree.Selector)(elements);
6 | this.arguments = args;
7 | this.index = index;
8 | this.currentFileInfo = currentFileInfo;
9 | this.important = important;
10 | };
11 | tree.mixin.Call.prototype = {
12 | type: "MixinCall",
13 | accept: function (visitor) {
14 | this.selector = visitor.visit(this.selector);
15 | this.arguments = visitor.visit(this.arguments);
16 | },
17 | eval: function (env) {
18 | var mixins, mixin, args, rules = [], match = false, i, m, f, isRecursive, isOneFound, rule;
19 |
20 | args = this.arguments && this.arguments.map(function (a) {
21 | return { name: a.name, value: a.value.eval(env) };
22 | });
23 |
24 | for (i = 0; i < env.frames.length; i++) {
25 | if ((mixins = env.frames[i].find(this.selector)).length > 0) {
26 | isOneFound = true;
27 | for (m = 0; m < mixins.length; m++) {
28 | mixin = mixins[m];
29 | isRecursive = false;
30 | for(f = 0; f < env.frames.length; f++) {
31 | if ((!(mixin instanceof tree.mixin.Definition)) && mixin === (env.frames[f].originalRuleset || env.frames[f])) {
32 | isRecursive = true;
33 | break;
34 | }
35 | }
36 | if (isRecursive) {
37 | continue;
38 | }
39 | if (mixin.matchArgs(args, env)) {
40 | if (!mixin.matchCondition || mixin.matchCondition(args, env)) {
41 | try {
42 | if (!(mixin instanceof tree.mixin.Definition)) {
43 | mixin = new tree.mixin.Definition("", [], mixin.rules, null, false);
44 | mixin.originalRuleset = mixins[m].originalRuleset || mixins[m];
45 | }
46 | //if (this.important) {
47 | // isImportant = env.isImportant;
48 | // env.isImportant = true;
49 | //}
50 | Array.prototype.push.apply(
51 | rules, mixin.eval(env, args, this.important).rules);
52 | //if (this.important) {
53 | // env.isImportant = isImportant;
54 | //}
55 | } catch (e) {
56 | throw { message: e.message, index: this.index, filename: this.currentFileInfo.filename, stack: e.stack };
57 | }
58 | }
59 | match = true;
60 | }
61 | }
62 | if (match) {
63 | if (!this.currentFileInfo || !this.currentFileInfo.reference) {
64 | for (i = 0; i < rules.length; i++) {
65 | rule = rules[i];
66 | if (rule.markReferenced) {
67 | rule.markReferenced();
68 | }
69 | }
70 | }
71 | return rules;
72 | }
73 | }
74 | }
75 | if (isOneFound) {
76 | throw { type: 'Runtime',
77 | message: 'No matching definition was found for `' +
78 | this.selector.toCSS().trim() + '(' +
79 | (args ? args.map(function (a) {
80 | var argValue = "";
81 | if (a.name) {
82 | argValue += a.name + ":";
83 | }
84 | if (a.value.toCSS) {
85 | argValue += a.value.toCSS();
86 | } else {
87 | argValue += "???";
88 | }
89 | return argValue;
90 | }).join(', ') : "") + ")`",
91 | index: this.index, filename: this.currentFileInfo.filename };
92 | } else {
93 | throw { type: 'Name',
94 | message: this.selector.toCSS().trim() + " is undefined",
95 | index: this.index, filename: this.currentFileInfo.filename };
96 | }
97 | }
98 | };
99 |
100 | tree.mixin.Definition = function (name, params, rules, condition, variadic) {
101 | this.name = name;
102 | this.selectors = [new(tree.Selector)([new(tree.Element)(null, name, this.index, this.currentFileInfo)])];
103 | this.params = params;
104 | this.condition = condition;
105 | this.variadic = variadic;
106 | this.arity = params.length;
107 | this.rules = rules;
108 | this._lookups = {};
109 | this.required = params.reduce(function (count, p) {
110 | if (!p.name || (p.name && !p.value)) { return count + 1; }
111 | else { return count; }
112 | }, 0);
113 | this.parent = tree.Ruleset.prototype;
114 | this.frames = [];
115 | };
116 | tree.mixin.Definition.prototype = {
117 | type: "MixinDefinition",
118 | accept: function (visitor) {
119 | this.params = visitor.visit(this.params);
120 | this.rules = visitor.visit(this.rules);
121 | this.condition = visitor.visit(this.condition);
122 | },
123 | variable: function (name) { return this.parent.variable.call(this, name); },
124 | variables: function () { return this.parent.variables.call(this); },
125 | find: function () { return this.parent.find.apply(this, arguments); },
126 | rulesets: function () { return this.parent.rulesets.apply(this); },
127 |
128 | evalParams: function (env, mixinEnv, args, evaldArguments) {
129 | /*jshint boss:true */
130 | var frame = new(tree.Ruleset)(null, []),
131 | varargs, arg,
132 | params = this.params.slice(0),
133 | i, j, val, name, isNamedFound, argIndex;
134 |
135 | mixinEnv = new tree.evalEnv(mixinEnv, [frame].concat(mixinEnv.frames));
136 |
137 | if (args) {
138 | args = args.slice(0);
139 |
140 | for(i = 0; i < args.length; i++) {
141 | arg = args[i];
142 | if (name = (arg && arg.name)) {
143 | isNamedFound = false;
144 | for(j = 0; j < params.length; j++) {
145 | if (!evaldArguments[j] && name === params[j].name) {
146 | evaldArguments[j] = arg.value.eval(env);
147 | frame.rules.unshift(new(tree.Rule)(name, arg.value.eval(env)));
148 | isNamedFound = true;
149 | break;
150 | }
151 | }
152 | if (isNamedFound) {
153 | args.splice(i, 1);
154 | i--;
155 | continue;
156 | } else {
157 | throw { type: 'Runtime', message: "Named argument for " + this.name +
158 | ' ' + args[i].name + ' not found' };
159 | }
160 | }
161 | }
162 | }
163 | argIndex = 0;
164 | for (i = 0; i < params.length; i++) {
165 | if (evaldArguments[i]) { continue; }
166 |
167 | arg = args && args[argIndex];
168 |
169 | if (name = params[i].name) {
170 | if (params[i].variadic && args) {
171 | varargs = [];
172 | for (j = argIndex; j < args.length; j++) {
173 | varargs.push(args[j].value.eval(env));
174 | }
175 | frame.rules.unshift(new(tree.Rule)(name, new(tree.Expression)(varargs).eval(env)));
176 | } else {
177 | val = arg && arg.value;
178 | if (val) {
179 | val = val.eval(env);
180 | } else if (params[i].value) {
181 | val = params[i].value.eval(mixinEnv);
182 | frame.resetCache();
183 | } else {
184 | throw { type: 'Runtime', message: "wrong number of arguments for " + this.name +
185 | ' (' + args.length + ' for ' + this.arity + ')' };
186 | }
187 |
188 | frame.rules.unshift(new(tree.Rule)(name, val));
189 | evaldArguments[i] = val;
190 | }
191 | }
192 |
193 | if (params[i].variadic && args) {
194 | for (j = argIndex; j < args.length; j++) {
195 | evaldArguments[j] = args[j].value.eval(env);
196 | }
197 | }
198 | argIndex++;
199 | }
200 |
201 | return frame;
202 | },
203 | eval: function (env, args, important) {
204 | var _arguments = [],
205 | mixinFrames = this.frames.concat(env.frames),
206 | frame = this.evalParams(env, new(tree.evalEnv)(env, mixinFrames), args, _arguments),
207 | rules, ruleset;
208 |
209 | frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env)));
210 |
211 | rules = this.rules.slice(0);
212 |
213 | ruleset = new(tree.Ruleset)(null, rules);
214 | ruleset.originalRuleset = this;
215 | ruleset = ruleset.eval(new(tree.evalEnv)(env, [this, frame].concat(mixinFrames)));
216 | if (important) {
217 | ruleset = this.parent.makeImportant.apply(ruleset);
218 | }
219 | return ruleset;
220 | },
221 | matchCondition: function (args, env) {
222 | if (this.condition && !this.condition.eval(
223 | new(tree.evalEnv)(env,
224 | [this.evalParams(env, new(tree.evalEnv)(env, this.frames.concat(env.frames)), args, [])] // the parameter variables
225 | .concat(this.frames) // the parent namespace/mixin frames
226 | .concat(env.frames)))) { // the current environment frames
227 | return false;
228 | }
229 | return true;
230 | },
231 | matchArgs: function (args, env) {
232 | var argsLength = (args && args.length) || 0, len;
233 |
234 | if (! this.variadic) {
235 | if (argsLength < this.required) { return false; }
236 | if (argsLength > this.params.length) { return false; }
237 | } else {
238 | if (argsLength < (this.required - 1)) { return false; }
239 | }
240 |
241 | len = Math.min(argsLength, this.arity);
242 |
243 | for (var i = 0; i < len; i++) {
244 | if (!this.params[i].name && !this.params[i].variadic) {
245 | if (args[i].value.eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) {
246 | return false;
247 | }
248 | }
249 | }
250 | return true;
251 | }
252 | };
253 |
254 | })(require('../tree'));
255 |
--------------------------------------------------------------------------------
/src/main/resources/org/lesscss/mojo/js/less/tree/negative.js:
--------------------------------------------------------------------------------
1 | (function (tree) {
2 |
3 | tree.Negative = function (node) {
4 | this.value = node;
5 | };
6 | tree.Negative.prototype = {
7 | type: "Negative",
8 | accept: function (visitor) {
9 | this.value = visitor.visit(this.value);
10 | },
11 | genCSS: function (env, output) {
12 | output.add('-');
13 | this.value.genCSS(env, output);
14 | },
15 | toCSS: tree.toCSS,
16 | eval: function (env) {
17 | if (env.isMathOn()) {
18 | return (new(tree.Operation)('*', [new(tree.Dimension)(-1), this.value])).eval(env);
19 | }
20 | return new(tree.Negative)(this.value.eval(env));
21 | }
22 | };
23 |
24 | })(require('../tree'));
25 |
--------------------------------------------------------------------------------
/src/main/resources/org/lesscss/mojo/js/less/tree/operation.js:
--------------------------------------------------------------------------------
1 | (function (tree) {
2 |
3 | tree.Operation = function (op, operands, isSpaced) {
4 | this.op = op.trim();
5 | this.operands = operands;
6 | this.isSpaced = isSpaced;
7 | };
8 | tree.Operation.prototype = {
9 | type: "Operation",
10 | accept: function (visitor) {
11 | this.operands = visitor.visit(this.operands);
12 | },
13 | eval: function (env) {
14 | var a = this.operands[0].eval(env),
15 | b = this.operands[1].eval(env),
16 | temp;
17 |
18 | if (env.isMathOn()) {
19 | if (a instanceof tree.Dimension && b instanceof tree.Color) {
20 | if (this.op === '*' || this.op === '+') {
21 | temp = b, b = a, a = temp;
22 | } else {
23 | throw { type: "Operation",
24 | message: "Can't substract or divide a color from a number" };
25 | }
26 | }
27 | if (!a.operate) {
28 | throw { type: "Operation",
29 | message: "Operation on an invalid type" };
30 | }
31 |
32 | return a.operate(env, this.op, b);
33 | } else {
34 | return new(tree.Operation)(this.op, [a, b], this.isSpaced);
35 | }
36 | },
37 | genCSS: function (env, output) {
38 | this.operands[0].genCSS(env, output);
39 | if (this.isSpaced) {
40 | output.add(" ");
41 | }
42 | output.add(this.op);
43 | if (this.isSpaced) {
44 | output.add(" ");
45 | }
46 | this.operands[1].genCSS(env, output);
47 | },
48 | toCSS: tree.toCSS
49 | };
50 |
51 | tree.operate = function (env, op, a, b) {
52 | switch (op) {
53 | case '+': return a + b;
54 | case '-': return a - b;
55 | case '*': return a * b;
56 | case '/': return a / b;
57 | }
58 | };
59 |
60 | })(require('../tree'));
61 |
--------------------------------------------------------------------------------
/src/main/resources/org/lesscss/mojo/js/less/tree/paren.js:
--------------------------------------------------------------------------------
1 |
2 | (function (tree) {
3 |
4 | tree.Paren = function (node) {
5 | this.value = node;
6 | };
7 | tree.Paren.prototype = {
8 | type: "Paren",
9 | accept: function (visitor) {
10 | this.value = visitor.visit(this.value);
11 | },
12 | genCSS: function (env, output) {
13 | output.add('(');
14 | this.value.genCSS(env, output);
15 | output.add(')');
16 | },
17 | toCSS: tree.toCSS,
18 | eval: function (env) {
19 | return new(tree.Paren)(this.value.eval(env));
20 | }
21 | };
22 |
23 | })(require('../tree'));
24 |
--------------------------------------------------------------------------------
/src/main/resources/org/lesscss/mojo/js/less/tree/quoted.js:
--------------------------------------------------------------------------------
1 | (function (tree) {
2 |
3 | tree.Quoted = function (str, content, escaped, index, currentFileInfo) {
4 | this.escaped = escaped;
5 | this.value = content || '';
6 | this.quote = str.charAt(0);
7 | this.index = index;
8 | this.currentFileInfo = currentFileInfo;
9 | };
10 | tree.Quoted.prototype = {
11 | type: "Quoted",
12 | genCSS: function (env, output) {
13 | if (!this.escaped) {
14 | output.add(this.quote, this.currentFileInfo, this.index);
15 | }
16 | output.add(this.value);
17 | if (!this.escaped) {
18 | output.add(this.quote);
19 | }
20 | },
21 | toCSS: tree.toCSS,
22 | eval: function (env) {
23 | var that = this;
24 | var value = this.value.replace(/`([^`]+)`/g, function (_, exp) {
25 | return new(tree.JavaScript)(exp, that.index, true).eval(env).value;
26 | }).replace(/@\{([\w-]+)\}/g, function (_, name) {
27 | var v = new(tree.Variable)('@' + name, that.index, that.currentFileInfo).eval(env, true);
28 | return (v instanceof tree.Quoted) ? v.value : v.toCSS();
29 | });
30 | return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index, this.currentFileInfo);
31 | },
32 | compare: function (x) {
33 | if (!x.toCSS) {
34 | return -1;
35 | }
36 |
37 | var left = this.toCSS(),
38 | right = x.toCSS();
39 |
40 | if (left === right) {
41 | return 0;
42 | }
43 |
44 | return left < right ? -1 : 1;
45 | }
46 | };
47 |
48 | })(require('../tree'));
49 |
--------------------------------------------------------------------------------
/src/main/resources/org/lesscss/mojo/js/less/tree/ratio.js:
--------------------------------------------------------------------------------
1 | (function (tree) {
2 |
3 | tree.Ratio = function (value) {
4 | this.value = value;
5 | };
6 | tree.Ratio.prototype = {
7 | toCSS: function (env) {
8 | return this.value;
9 | },
10 | eval: function () { return this }
11 | };
12 |
13 | })(require('../tree'));
14 |
--------------------------------------------------------------------------------
/src/main/resources/org/lesscss/mojo/js/less/tree/rule.js:
--------------------------------------------------------------------------------
1 | (function (tree) {
2 |
3 | tree.Rule = function (name, value, important, merge, index, currentFileInfo, inline) {
4 | this.name = name;
5 | this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]);
6 | this.important = important ? ' ' + important.trim() : '';
7 | this.merge = merge;
8 | this.index = index;
9 | this.currentFileInfo = currentFileInfo;
10 | this.inline = inline || false;
11 | this.variable = (name.charAt(0) === '@');
12 | };
13 |
14 | tree.Rule.prototype = {
15 | type: "Rule",
16 | accept: function (visitor) {
17 | this.value = visitor.visit(this.value);
18 | },
19 | genCSS: function (env, output) {
20 | output.add(this.name + (env.compress ? ':' : ': '), this.currentFileInfo, this.index);
21 | try {
22 | this.value.genCSS(env, output);
23 | }
24 | catch(e) {
25 | e.index = this.index;
26 | e.filename = this.currentFileInfo.filename;
27 | throw e;
28 | }
29 | output.add(this.important + ((this.inline || (env.lastRule && env.compress)) ? "" : ";"), this.currentFileInfo, this.index);
30 | },
31 | toCSS: tree.toCSS,
32 | eval: function (env) {
33 | var strictMathBypass = false;
34 | if (this.name === "font" && !env.strictMath) {
35 | strictMathBypass = true;
36 | env.strictMath = true;
37 | }
38 | try {
39 | return new(tree.Rule)(this.name,
40 | this.value.eval(env),
41 | this.important,
42 | this.merge,
43 | this.index, this.currentFileInfo, this.inline);
44 | }
45 | finally {
46 | if (strictMathBypass) {
47 | env.strictMath = false;
48 | }
49 | }
50 | },
51 | makeImportant: function () {
52 | return new(tree.Rule)(this.name,
53 | this.value,
54 | "!important",
55 | this.merge,
56 | this.index, this.currentFileInfo, this.inline);
57 | }
58 | };
59 |
60 | })(require('../tree'));
61 |
--------------------------------------------------------------------------------
/src/main/resources/org/lesscss/mojo/js/less/tree/selector.js:
--------------------------------------------------------------------------------
1 | (function (tree) {
2 |
3 | tree.Selector = function (elements, extendList, condition, index, currentFileInfo, isReferenced) {
4 | this.elements = elements;
5 | this.extendList = extendList || [];
6 | this.condition = condition;
7 | this.currentFileInfo = currentFileInfo || {};
8 | this.isReferenced = isReferenced;
9 | if (!condition) {
10 | this.evaldCondition = true;
11 | }
12 | };
13 | tree.Selector.prototype = {
14 | type: "Selector",
15 | accept: function (visitor) {
16 | this.elements = visitor.visit(this.elements);
17 | this.extendList = visitor.visit(this.extendList);
18 | this.condition = visitor.visit(this.condition);
19 | },
20 | createDerived: function(elements, extendList, evaldCondition) {
21 | /*jshint eqnull:true */
22 | evaldCondition = evaldCondition != null ? evaldCondition : this.evaldCondition;
23 | var newSelector = new(tree.Selector)(elements, extendList || this.extendList, this.condition, this.index, this.currentFileInfo, this.isReferenced);
24 | newSelector.evaldCondition = evaldCondition;
25 | return newSelector;
26 | },
27 | match: function (other) {
28 | var elements = this.elements,
29 | len = elements.length,
30 | oelements, olen, max, i;
31 |
32 | oelements = other.elements.slice(
33 | (other.elements.length && other.elements[0].value === "&") ? 1 : 0);
34 | olen = oelements.length;
35 | max = Math.min(len, olen);
36 |
37 | if (olen === 0 || len < olen) {
38 | return 0;
39 | } else {
40 | for (i = 0; i < max; i++) {
41 | if (elements[i].value !== oelements[i].value) {
42 | return 0;
43 | }
44 | }
45 | }
46 | return max; // return number of matched selectors
47 | },
48 | eval: function (env) {
49 | var evaldCondition = this.condition && this.condition.eval(env);
50 |
51 | return this.createDerived(this.elements.map(function (e) {
52 | return e.eval(env);
53 | }), this.extendList.map(function(extend) {
54 | return extend.eval(env);
55 | }), evaldCondition);
56 | },
57 | genCSS: function (env, output) {
58 | var i, element;
59 | if ((!env || !env.firstSelector) && this.elements[0].combinator.value === "") {
60 | output.add(' ', this.currentFileInfo, this.index);
61 | }
62 | if (!this._css) {
63 | //TODO caching? speed comparison?
64 | for(i = 0; i < this.elements.length; i++) {
65 | element = this.elements[i];
66 | element.genCSS(env, output);
67 | }
68 | }
69 | },
70 | toCSS: tree.toCSS,
71 | markReferenced: function () {
72 | this.isReferenced = true;
73 | },
74 | getIsReferenced: function() {
75 | return !this.currentFileInfo.reference || this.isReferenced;
76 | },
77 | getIsOutput: function() {
78 | return this.evaldCondition;
79 | }
80 | };
81 |
82 | })(require('../tree'));
83 |
--------------------------------------------------------------------------------
/src/main/resources/org/lesscss/mojo/js/less/tree/unicode-descriptor.js:
--------------------------------------------------------------------------------
1 | (function (tree) {
2 |
3 | tree.UnicodeDescriptor = function (value) {
4 | this.value = value;
5 | };
6 | tree.UnicodeDescriptor.prototype = {
7 | type: "UnicodeDescriptor",
8 | genCSS: function (env, output) {
9 | output.add(this.value);
10 | },
11 | toCSS: tree.toCSS,
12 | eval: function () { return this; }
13 | };
14 |
15 | })(require('../tree'));
16 |
--------------------------------------------------------------------------------
/src/main/resources/org/lesscss/mojo/js/less/tree/url.js:
--------------------------------------------------------------------------------
1 | (function (tree) {
2 |
3 | tree.URL = function (val, currentFileInfo) {
4 | this.value = val;
5 | this.currentFileInfo = currentFileInfo;
6 | };
7 | tree.URL.prototype = {
8 | type: "Url",
9 | accept: function (visitor) {
10 | this.value = visitor.visit(this.value);
11 | },
12 | genCSS: function (env, output) {
13 | output.add("url(");
14 | this.value.genCSS(env, output);
15 | output.add(")");
16 | },
17 | toCSS: tree.toCSS,
18 | eval: function (ctx) {
19 | var val = this.value.eval(ctx), rootpath;
20 |
21 | // Add the base path if the URL is relative
22 | rootpath = this.currentFileInfo && this.currentFileInfo.rootpath;
23 | if (rootpath && typeof val.value === "string" && ctx.isPathRelative(val.value)) {
24 | if (!val.quote) {
25 | rootpath = rootpath.replace(/[\(\)'"\s]/g, function(match) { return "\\"+match; });
26 | }
27 | val.value = rootpath + val.value;
28 | }
29 |
30 | val.value = ctx.normalizePath(val.value);
31 |
32 | return new(tree.URL)(val, null);
33 | }
34 | };
35 |
36 | })(require('../tree'));
37 |
--------------------------------------------------------------------------------
/src/main/resources/org/lesscss/mojo/js/less/tree/value.js:
--------------------------------------------------------------------------------
1 | (function (tree) {
2 |
3 | tree.Value = function (value) {
4 | this.value = value;
5 | };
6 | tree.Value.prototype = {
7 | type: "Value",
8 | accept: function (visitor) {
9 | this.value = visitor.visit(this.value);
10 | },
11 | eval: function (env) {
12 | if (this.value.length === 1) {
13 | return this.value[0].eval(env);
14 | } else {
15 | return new(tree.Value)(this.value.map(function (v) {
16 | return v.eval(env);
17 | }));
18 | }
19 | },
20 | genCSS: function (env, output) {
21 | var i;
22 | for(i = 0; i < this.value.length; i++) {
23 | this.value[i].genCSS(env, output);
24 | if (i+1 < this.value.length) {
25 | output.add((env && env.compress) ? ',' : ', ');
26 | }
27 | }
28 | },
29 | toCSS: tree.toCSS
30 | };
31 |
32 | })(require('../tree'));
33 |
--------------------------------------------------------------------------------
/src/main/resources/org/lesscss/mojo/js/less/tree/variable.js:
--------------------------------------------------------------------------------
1 | (function (tree) {
2 |
3 | tree.Variable = function (name, index, currentFileInfo) {
4 | this.name = name;
5 | this.index = index;
6 | this.currentFileInfo = currentFileInfo;
7 | };
8 | tree.Variable.prototype = {
9 | type: "Variable",
10 | eval: function (env) {
11 | var variable, v, name = this.name;
12 |
13 | if (name.indexOf('@@') === 0) {
14 | name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value;
15 | }
16 |
17 | if (this.evaluating) {
18 | throw { type: 'Name',
19 | message: "Recursive variable definition for " + name,
20 | filename: this.currentFileInfo.file,
21 | index: this.index };
22 | }
23 |
24 | this.evaluating = true;
25 |
26 | if (variable = tree.find(env.frames, function (frame) {
27 | if (v = frame.variable(name)) {
28 | return v.value.eval(env);
29 | }
30 | })) {
31 | this.evaluating = false;
32 | return variable;
33 | }
34 | else {
35 | throw { type: 'Name',
36 | message: "variable " + name + " is undefined",
37 | filename: this.currentFileInfo.filename,
38 | index: this.index };
39 | }
40 | }
41 | };
42 |
43 | })(require('../tree'));
44 |
--------------------------------------------------------------------------------
/src/main/resources/org/lesscss/mojo/js/less/visitor.js:
--------------------------------------------------------------------------------
1 | (function (tree) {
2 |
3 | tree.visitor = function(implementation) {
4 | this._implementation = implementation;
5 | };
6 |
7 | tree.visitor.prototype = {
8 | visit: function(node) {
9 |
10 | if (node instanceof Array) {
11 | return this.visitArray(node);
12 | }
13 |
14 | if (!node || !node.type) {
15 | return node;
16 | }
17 |
18 | var funcName = "visit" + node.type,
19 | func = this._implementation[funcName],
20 | visitArgs, newNode;
21 | if (func) {
22 | visitArgs = {visitDeeper: true};
23 | newNode = func.call(this._implementation, node, visitArgs);
24 | if (this._implementation.isReplacing) {
25 | node = newNode;
26 | }
27 | }
28 | if ((!visitArgs || visitArgs.visitDeeper) && node && node.accept) {
29 | node.accept(this);
30 | }
31 | funcName = funcName + "Out";
32 | if (this._implementation[funcName]) {
33 | this._implementation[funcName](node);
34 | }
35 | return node;
36 | },
37 | visitArray: function(nodes) {
38 | var i, newNodes = [];
39 | for(i = 0; i < nodes.length; i++) {
40 | var evald = this.visit(nodes[i]);
41 | if (evald instanceof Array) {
42 | evald = this.flatten(evald);
43 | newNodes = newNodes.concat(evald);
44 | } else {
45 | newNodes.push(evald);
46 | }
47 | }
48 | if (this._implementation.isReplacing) {
49 | return newNodes;
50 | }
51 | return nodes;
52 | },
53 | doAccept: function (node) {
54 | node.accept(this);
55 | },
56 | flatten: function(arr, master) {
57 | return arr.reduce(this.flattenReduce.bind(this), master || []);
58 | },
59 | flattenReduce: function(sum, element) {
60 | if (element instanceof Array) {
61 | sum = this.flatten(element, sum);
62 | } else {
63 | sum.push(element);
64 | }
65 | return sum;
66 | }
67 | };
68 |
69 | })(require('./tree'));
--------------------------------------------------------------------------------
/src/main/resources/org/lesscss/mojo/js/lessc.js:
--------------------------------------------------------------------------------
1 | var less = require('./less/index');
2 | var fs = require('fs');
3 |
4 | var inputFile = process.argv[2];
5 | var outputFile = process.argv[3];
6 | var compress = (process.argv[4] !== 'false');
7 |
8 | var inputText = fs.readFileSync(inputFile, 'utf8');
9 | var parser = new less.Parser();
10 | parser.parse(inputText, function(e, tree) {
11 | if (e instanceof Object) {
12 | throw e;
13 | };
14 | try {
15 | var result = tree.toCSS({compress: compress});
16 | fs.writeFileSync(outputFile, result);
17 | } catch (e) {
18 | fs.writeFileSync(outputFile, e.message);
19 | process.exit(1);
20 | }
21 | });
22 |
--------------------------------------------------------------------------------
/src/test/java/org/lesscss/mojo/AbstractLessCssMojoTest.java:
--------------------------------------------------------------------------------
1 | /* Copyright 2011-2012 The Apache Software Foundation.
2 | *
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 | package org.lesscss.mojo;
16 |
17 | import static org.mockito.Matchers.eq;
18 | import static org.mockito.Matchers.same;
19 | import static org.mockito.Mockito.verify;
20 | import static org.powermock.api.mockito.PowerMockito.when;
21 |
22 | import java.io.File;
23 |
24 | import org.apache.maven.plugin.MojoExecutionException;
25 | import org.apache.maven.plugin.testing.AbstractMojoTestCase;
26 | import org.codehaus.plexus.util.Scanner;
27 | import org.junit.After;
28 | import org.junit.Before;
29 | import org.junit.Test;
30 | import org.junit.runner.RunWith;
31 | import org.lesscss.mojo.AbstractLessCssMojo;
32 | import org.mockito.Mock;
33 | import org.powermock.core.classloader.annotations.PrepareForTest;
34 | import org.powermock.modules.junit4.PowerMockRunner;
35 | import org.sonatype.plexus.build.incremental.BuildContext;
36 |
37 | @PrepareForTest(AbstractLessCssMojo.class)
38 | @RunWith(PowerMockRunner.class)
39 | public class AbstractLessCssMojoTest extends AbstractMojoTestCase {
40 |
41 | private AbstractLessCssMojo mojo;
42 |
43 | private File sourceDirectory = new File("./source");
44 |
45 | private String[] includes = new String[] { "include" };
46 |
47 | private String[] excludes = new String[] { "exclude" };
48 |
49 | private String[] files = new String[] { "file" };
50 |
51 | @Mock
52 | private BuildContext buildContext;
53 |
54 | @Mock
55 | private Scanner scanner;
56 |
57 | @Before
58 | public void setUp() throws Exception {
59 | mojo = new AbstractLessCssMojo() {
60 | public void execute() throws MojoExecutionException {
61 | }
62 | };
63 |
64 | setVariableValueToObject(mojo, "buildContext", buildContext);
65 | setVariableValueToObject(mojo, "sourceDirectory", sourceDirectory);
66 | setVariableValueToObject(mojo, "includes", includes);
67 | setVariableValueToObject(mojo, "excludes", excludes);
68 | }
69 |
70 | @Test
71 | public void testGetFiles() throws Exception {
72 | when(buildContext.newScanner(sourceDirectory, true)).thenReturn(scanner);
73 | when(scanner.getIncludedFiles()).thenReturn(files);
74 |
75 | assertSame(files, mojo.getIncludedFiles());
76 |
77 | verify(buildContext).newScanner(same(sourceDirectory), eq(true));
78 | verify(scanner).setIncludes(same(includes));
79 | verify(scanner).setExcludes(same(excludes));
80 | verify(scanner).scan();
81 | }
82 |
83 | @After
84 | public void tearDown() {
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/src/test/java/org/lesscss/mojo/CompileOnChangeMojoTest.java:
--------------------------------------------------------------------------------
1 | package org.lesscss.mojo;
2 |
3 | import java.io.File;
4 |
5 | import org.apache.maven.plugin.MojoExecutionException;
6 | import org.apache.maven.plugin.testing.AbstractMojoTestCase;
7 | import org.junit.Rule;
8 | import org.junit.Test;
9 | import org.junit.rules.TemporaryFolder;
10 |
11 | /**
12 | * Tests the watch mode of the CompileMojo.
13 | */
14 | public class CompileOnChangeMojoTest extends AbstractMojoTestCase {
15 | @Rule
16 | public TemporaryFolder tempFolder = new TemporaryFolder();
17 |
18 | /** {@inheritDoc} */
19 | protected void setUp() throws Exception {
20 | // required
21 | super.setUp();
22 | }
23 |
24 | /** {@inheritDoc} */
25 | protected void tearDown() throws Exception {
26 | // required
27 | super.tearDown();
28 | }
29 |
30 | /**
31 | * @throws Exception
32 | * This test touches two files and checks if the bootstrap.css
33 | * file has been recompiled after every touch.
34 | */
35 | @Test
36 | public void testIfFileChangeCausesRecompilation() throws Exception {
37 | File pom = getTestFile("src/test/resources/pom.xml");
38 | assertNotNull(pom);
39 | assertTrue(pom.exists());
40 | final CompileMojo compileMojo = (CompileMojo) lookupMojo("compile", pom);
41 | assertNotNull(compileMojo);
42 |
43 | File generatedFile = new File(compileMojo.outputDirectory, "bootstrap.css");
44 | long oldLastModified = generatedFile.lastModified();
45 |
46 | compileMojo.outputDirectory = tempFolder.newFolder();
47 |
48 | /*
49 | * Run the watching compileMojo in a new thread. This way we can test
50 | * recompilation and stop the watching mode asynchronous in this thread.
51 | */
52 | Thread watchThread = new Thread() {
53 | public void run() {
54 | try {
55 | compileMojo.execute();
56 | } catch (MojoExecutionException e) {
57 | assertTrue(e.getLongMessage(), true);
58 | }
59 | }
60 | };
61 | watchThread.start();
62 |
63 | long newLastModified = checkIfFileHasBeenChanged(compileMojo, oldLastModified);
64 |
65 | touchFile(compileMojo, "1/reset.less");
66 | newLastModified = checkIfFileHasBeenChanged(compileMojo, newLastModified);
67 |
68 | touchFile(compileMojo, "2/21/variables.less");
69 | checkIfFileHasBeenChanged(compileMojo, newLastModified);
70 | watchThread.interrupt();
71 | }
72 |
73 | private long checkIfFileHasBeenChanged(final CompileMojo compileMojo, long lastModified) throws InterruptedException {
74 | long newLastModified = lastModified;
75 | long oldLastModified = lastModified;
76 |
77 | File generatedFile = null;
78 | long startMillies = System.currentTimeMillis();
79 | long currentMillies = startMillies;
80 | // check for a maximum of ten seconds if the file has been changed
81 | while (oldLastModified >= newLastModified && ((currentMillies - startMillies) < 10000)) {
82 | Thread.sleep(200); // wait for 0.2 seconds
83 | generatedFile = new File(compileMojo.outputDirectory, "bootstrap.css");
84 | newLastModified = generatedFile.lastModified();
85 | currentMillies = System.currentTimeMillis();
86 | }
87 | assertTrue("No recompilation has been done within " + (currentMillies - startMillies) + " ms.",
88 | newLastModified > oldLastModified);
89 | return newLastModified;
90 | }
91 |
92 | private long touchFile(final CompileMojo compileMojo, String file2Touch) throws InterruptedException {
93 | File lessFile = new File(compileMojo.sourceDirectory, file2Touch);
94 |
95 | /*
96 | * The last modified value might be rounded down on a second by the
97 | * platform. This way the last compilation and the touch may end up with
98 | * the same millis avoiding the compilation. To prevent that the thread
99 | * has to sleep a second.
100 | */
101 | Thread.sleep(1000);
102 | long currentMillies = System.currentTimeMillis();
103 | // touch the less file
104 | lessFile.setLastModified(currentMillies);
105 | return currentMillies;
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/src/test/java/org/lesscss/mojo/ListMojoTest.java:
--------------------------------------------------------------------------------
1 | /* Copyright 2011-2012 The Apache Software Foundation.
2 | *
3 | * Licensed under the Apache License, Version 2.0 (the "License");
4 | * you may not use this file except in compliance with the License.
5 | * You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software
10 | * distributed under the License is distributed on an "AS IS" BASIS,
11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | * See the License for the specific language governing permissions and
13 | * limitations under the License.
14 | */
15 | package org.lesscss.mojo;
16 |
17 | import static org.mockito.Mockito.inOrder;
18 | import static org.mockito.Mockito.verify;
19 | import static org.powermock.api.mockito.PowerMockito.when;
20 | import static org.powermock.api.mockito.PowerMockito.whenNew;
21 |
22 | import java.io.File;
23 | import java.io.FileNotFoundException;
24 | import java.io.IOException;
25 | import java.util.LinkedHashMap;
26 |
27 | import org.apache.maven.plugin.MojoExecutionException;
28 | import org.apache.maven.plugin.logging.Log;
29 | import org.apache.maven.plugin.testing.AbstractMojoTestCase;
30 | import org.codehaus.plexus.util.Scanner;
31 | import org.junit.After;
32 | import org.junit.Before;
33 | import org.junit.Test;
34 | import org.junit.runner.RunWith;
35 | import org.lesscss.LessSource;
36 | import org.lesscss.mojo.ListMojo;
37 | import org.mockito.InOrder;
38 | import org.mockito.Mock;
39 | import org.powermock.core.classloader.annotations.PrepareForTest;
40 | import org.powermock.modules.junit4.PowerMockRunner;
41 | import org.sonatype.plexus.build.incremental.BuildContext;
42 |
43 | @PrepareForTest(ListMojo.class)
44 | @RunWith(PowerMockRunner.class)
45 | public class ListMojoTest extends AbstractMojoTestCase {
46 |
47 | private ListMojo mojo;
48 |
49 | private File sourceDirectory = new File("./source");
50 |
51 | private String[] includes = new String[] { "include" };
52 |
53 | private String[] excludes = new String[] { "exclude" };
54 |
55 | private String[] files = new String[] { "file" };
56 |
57 | @Mock
58 | private Log log;
59 |
60 | @Mock
61 | private LessSource lessSource1;
62 |
63 | @Mock
64 | private LessSource lessSource1import1;
65 |
66 | @Mock
67 | private LessSource lessSource1import1a;
68 |
69 | @Mock
70 | private LessSource lessSource1import2;
71 |
72 | @Mock
73 | private LessSource lessSource1import2a;
74 |
75 | @Mock
76 | private LessSource lessSource1import2b;
77 |
78 | @Mock
79 | private LessSource lessSource1import3;
80 |
81 | @Mock
82 | private LessSource lessSource2;
83 |
84 | @Mock
85 | private BuildContext buildContext;
86 |
87 | @Mock
88 | private Scanner scanner;
89 |
90 | @Before
91 | public void setUp() throws Exception {
92 | mojo = new ListMojo();
93 | mojo.setLog(log);
94 |
95 | setVariableValueToObject(mojo, "buildContext", buildContext);
96 | setVariableValueToObject(mojo, "sourceDirectory", sourceDirectory);
97 | setVariableValueToObject(mojo, "includes", includes);
98 | setVariableValueToObject(mojo, "excludes", excludes);
99 | }
100 |
101 | @SuppressWarnings("serial")
102 | @Test
103 | public void testExecution() throws Exception {
104 | files = new String[] { "less1.less", "less2.less" };
105 |
106 | when(buildContext.newScanner(sourceDirectory, true)).thenReturn(scanner);
107 | when(scanner.getIncludedFiles()).thenReturn(files);
108 |
109 | whenNew(LessSource.class).withArguments(new File(sourceDirectory, "less1.less")).thenReturn(lessSource1);
110 | when(lessSource1.getImports()).thenReturn(new LinkedHashMap() {
111 | {
112 | put("less1import1.less", lessSource1import1);
113 | put("less1import2.less", lessSource1import2);
114 | put("less1import3.less", lessSource1import3);
115 | }
116 | });
117 | when(lessSource1import1.getImports()).thenReturn(new LinkedHashMap() {
118 | {
119 | put("less1import1a.less", lessSource1import1a);
120 | }
121 | });
122 | when(lessSource1import2.getImports()).thenReturn(new LinkedHashMap() {
123 | {
124 | put("less1import2a.less", lessSource1import2a);
125 | put("less1import2b.less", lessSource1import2b);
126 | }
127 | });
128 |
129 | whenNew(LessSource.class).withArguments(new File(sourceDirectory, "less2.less")).thenReturn(lessSource2);
130 |
131 | mojo.execute();
132 |
133 | InOrder inOrder = inOrder(log);
134 | inOrder.verify(log).info("The following LESS sources have been resolved:");
135 | inOrder.verify(log).info("less1.less");
136 | inOrder.verify(log).info("|-- less1import1.less");
137 | inOrder.verify(log).info("| `-- less1import1a.less");
138 | inOrder.verify(log).info("|-- less1import2.less");
139 | inOrder.verify(log).info("| |-- less1import2a.less");
140 | inOrder.verify(log).info("| `-- less1import2b.less");
141 | inOrder.verify(log).info("`-- less1import3.less");
142 | inOrder.verify(log).info("less2.less");
143 | inOrder.verifyNoMoreInteractions();
144 | }
145 |
146 | @Test
147 | public void testExecutionIncludedFilesEmpty() throws Exception {
148 | files = new String[] {};
149 |
150 | when(buildContext.newScanner(sourceDirectory, true)).thenReturn(scanner);
151 | when(scanner.getIncludedFiles()).thenReturn(files);
152 |
153 | mojo.execute();
154 |
155 | verify(log).info("No LESS sources found");
156 | }
157 |
158 | @Test
159 | public void testExecutionIncludedFilesNull() throws Exception {
160 | files = null;
161 |
162 | when(buildContext.newScanner(sourceDirectory, true)).thenReturn(scanner);
163 | when(scanner.getIncludedFiles()).thenReturn(files);
164 |
165 | mojo.execute();
166 |
167 | verify(log).info("No LESS sources found");
168 | }
169 |
170 | @Test(expected = MojoExecutionException.class)
171 | public void testExecutionFileNotFoundException() throws Exception {
172 | files = new String[] { "less.less" };
173 |
174 | when(buildContext.newScanner(sourceDirectory, true)).thenReturn(scanner);
175 | when(scanner.getIncludedFiles()).thenReturn(files);
176 |
177 | whenNew(LessSource.class).withArguments(new File(sourceDirectory, "less.less")).thenThrow(new FileNotFoundException(""));
178 |
179 | mojo.execute();
180 | }
181 |
182 | @Test(expected = MojoExecutionException.class)
183 | public void testExecutionIOException() throws Exception {
184 | files = new String[] { "less.less" };
185 |
186 | when(buildContext.newScanner(sourceDirectory, true)).thenReturn(scanner);
187 | when(scanner.getIncludedFiles()).thenReturn(files);
188 |
189 | whenNew(LessSource.class).withArguments(new File(sourceDirectory, "less.less")).thenThrow(new IOException(""));
190 |
191 | mojo.execute();
192 | }
193 |
194 | @After
195 | public void tearDown() {
196 | }
197 | }
198 |
--------------------------------------------------------------------------------
/src/test/resources/less/1/reset.less:
--------------------------------------------------------------------------------
1 | //
2 | // Modals
3 | // Adapted from http://github.com/necolas/normalize.css
4 | // --------------------------------------------------
5 |
6 |
7 | // Display in IE6-9 and FF3
8 | // -------------------------
9 |
10 | article,
11 | aside,
12 | details,
13 | figcaption,
14 | figure,
15 | footer,
16 | header,
17 | hgroup,
18 | nav,
19 | section {
20 | display: block;
21 | }
22 |
23 | // Display block in IE6-9 and FF3
24 | // -------------------------
25 |
26 | audio,
27 | canvas,
28 | video {
29 | display: inline-block;
30 | *display: inline;
31 | *zoom: 1;
32 | }
33 |
34 | // Prevents modern browsers from displaying 'audio' without controls
35 | // -------------------------
36 |
37 | audio:not([controls]) {
38 | display: none;
39 | }
40 |
41 | // Base settings
42 | // -------------------------
43 |
44 | html {
45 | font-size: 100%;
46 | -webkit-text-size-adjust: 100%;
47 | -ms-text-size-adjust: 100%;
48 | }
49 |
50 | // Hover & Active
51 | a:hover,
52 | a:active {
53 | outline: 0;
54 | }
55 |
56 | // Prevents sub and sup affecting line-height in all browsers
57 | // -------------------------
58 |
59 | sub,
60 | sup {
61 | position: relative;
62 | font-size: 75%;
63 | line-height: 0;
64 | vertical-align: baseline;
65 | }
66 | sup {
67 | top: -0.5em;
68 | }
69 | sub {
70 | bottom: -0.25em;
71 | }
72 |
73 | // Img border in a's and image quality
74 | // -------------------------
75 |
76 | img {
77 | /* Responsive images (ensure images don't scale beyond their parents) */
78 | max-width: 100%; /* Part 1: Set a maxium relative to the parent */
79 | width: auto\9; /* IE7-8 need help adjusting responsive images */
80 | height: auto; /* Part 2: Scale the height according to the width, otherwise you get stretching */
81 |
82 | vertical-align: middle;
83 | border: 0;
84 | -ms-interpolation-mode: bicubic;
85 | }
86 |
87 | // Prevent max-width from affecting Google Maps
88 | #map_canvas img {
89 | max-width: none;
90 | }
91 |
92 | // Forms
93 | // -------------------------
94 |
95 | // Font size in all browsers, margin changes, misc consistency
96 | button,
97 | input,
98 | select,
99 | textarea {
100 | margin: 0;
101 | font-size: 100%;
102 | vertical-align: middle;
103 | }
104 | button,
105 | input {
106 | *overflow: visible; // Inner spacing ie IE6/7
107 | line-height: normal; // FF3/4 have !important on line-height in UA stylesheet
108 | }
109 | button::-moz-focus-inner,
110 | input::-moz-focus-inner { // Inner padding and border oddities in FF3/4
111 | padding: 0;
112 | border: 0;
113 | }
114 | button,
115 | input[type="button"],
116 | input[type="reset"],
117 | input[type="submit"] {
118 | cursor: pointer; // Cursors on all buttons applied consistently
119 | -webkit-appearance: button; // Style clickable inputs in iOS
120 | }
121 | input[type="search"] { // Appearance in Safari/Chrome
122 | -webkit-box-sizing: content-box;
123 | -moz-box-sizing: content-box;
124 | box-sizing: content-box;
125 | -webkit-appearance: textfield;
126 | }
127 | input[type="search"]::-webkit-search-decoration,
128 | input[type="search"]::-webkit-search-cancel-button {
129 | -webkit-appearance: none; // Inner-padding issues in Chrome OSX, Safari 5
130 | }
131 | textarea {
132 | overflow: auto; // Remove vertical scrollbar in IE6-9
133 | vertical-align: top; // Readability and alignment cross-browser
134 | }
135 |
--------------------------------------------------------------------------------
/src/test/resources/less/2/21/variables.less:
--------------------------------------------------------------------------------
1 | // Variables
2 | // --------------------------------------------------
3 |
4 |
5 | // Global values
6 | // --------------------------------------------------
7 |
8 |
9 | // Grays
10 | // -------------------------
11 | @black: #000;
12 | @grayDarker: #222;
13 | @grayDark: #333;
14 | @gray: #555;
15 | @grayLight: #999;
16 | @grayLighter: #eee;
17 | @white: #fff;
18 |
19 |
20 | // Accent colors
21 | // -------------------------
22 | @blue: #049cdb;
23 | @blueDark: #0064cd;
24 | @green: #46a546;
25 | @red: #9d261d;
26 | @yellow: #ffc40d;
27 | @orange: #f89406;
28 | @pink: #c3325f;
29 | @purple: #7a43b6;
30 |
31 |
32 | // Scaffolding
33 | // -------------------------
34 | @bodyBackground: yellow;
35 | @textColor: yellow;
36 | //#c0c0c0;
37 |
38 |
39 | // Links
40 | // -------------------------
41 | @linkColor: #c0c0c0;
42 | @linkColorHover: darken(@linkColor, 15%);
43 |
44 |
45 | // Typography
46 | // -------------------------
47 | @sansFontFamily: "Helvetica Neue", Helvetica, Arial, sans-serif;
48 | @serifFontFamily: Georgia, "Times New Roman", Times, serif;
49 | @monoFontFamily: Monaco, Menlo, Consolas, "Courier New", monospace;
50 |
51 | @baseFontSize: 14px;
52 | @baseFontFamily: @sansFontFamily;
53 | @baseLineHeight: 20px;
54 | @altFontFamily: @serifFontFamily;
55 |
56 | @headingsFontFamily: inherit; // empty to use BS default, @baseFontFamily
57 | @headingsFontWeight: bold; // instead of browser default, bold
58 | @headingsColor: inherit; // empty to use BS default, @textColor
59 |
60 |
61 | // Tables
62 | // -------------------------
63 | @tableBackground: transparent; // overall background-color
64 | @tableBackgroundAccent: #f9f9f9; // for striping
65 | @tableBackgroundHover: #f5f5f5; // for hover
66 | @tableBorder: #ddd; // table and cell border
67 |
68 |
69 | // Buttons
70 | // -------------------------
71 | @btnBackground: @white;
72 | @btnBackgroundHighlight: darken(@white, 10%);
73 | @btnBorder: #bbb;
74 |
75 | @btnPrimaryBackground: @linkColor;
76 | @btnPrimaryBackgroundHighlight: spin(@btnPrimaryBackground, 20%);
77 |
78 | @btnInfoBackground: #5bc0de;
79 | @btnInfoBackgroundHighlight: #2f96b4;
80 |
81 | @btnSuccessBackground: #62c462;
82 | @btnSuccessBackgroundHighlight: #51a351;
83 |
84 | @btnWarningBackground: lighten(@orange, 15%);
85 | @btnWarningBackgroundHighlight: @orange;
86 |
87 | @btnDangerBackground: #ee5f5b;
88 | @btnDangerBackgroundHighlight: #bd362f;
89 |
90 | @btnInverseBackground: #444;
91 | @btnInverseBackgroundHighlight: @grayDarker;
92 |
93 |
94 | // Forms
95 | // -------------------------
96 | @inputBackground: @white;
97 | @inputBorder: #ccc;
98 | @inputBorderRadius: 3px;
99 | @inputDisabledBackground: @grayLighter;
100 | @formActionsBackground: #f5f5f5;
101 |
102 | // Dropdowns
103 | // -------------------------
104 | @dropdownBackground: @white;
105 | @dropdownBorder: rgba(0,0,0,.2);
106 | @dropdownDividerTop: #e5e5e5;
107 | @dropdownDividerBottom: @white;
108 |
109 | @dropdownLinkColor: @grayDark;
110 |
111 | @dropdownLinkColorHover: @white;
112 | @dropdownLinkBackgroundHover: @dropdownLinkBackgroundActive;
113 |
114 | @dropdownLinkColorActive: @dropdownLinkColor;
115 | @dropdownLinkBackgroundActive: @linkColor;
116 |
117 |
118 |
119 | // COMPONENT VARIABLES
120 | // --------------------------------------------------
121 |
122 | // Z-index master list
123 | // -------------------------
124 | // Used for a bird's eye view of components dependent on the z-axis
125 | // Try to avoid customizing these :)
126 | @zindexDropdown: 1000;
127 | @zindexPopover: 1010;
128 | @zindexTooltip: 1030;
129 | @zindexFixedNavbar: 1030;
130 | @zindexModalBackdrop: 1040;
131 | @zindexModal: 1050;
132 |
133 |
134 | // Sprite icons path
135 | // -------------------------
136 | @iconSpritePath: "../img/glyphicons-halflings.png";
137 | @iconWhiteSpritePath: "../img/glyphicons-halflings-white.png";
138 |
139 |
140 | // Input placeholder text color
141 | // -------------------------
142 | @placeholderText: @grayLight;
143 |
144 |
145 | // Hr border color
146 | // -------------------------
147 | @hrBorder: @grayLighter;
148 |
149 |
150 | // Horizontal forms & lists
151 | // -------------------------
152 | @horizontalComponentOffset: 180px;
153 |
154 |
155 | // Wells
156 | // -------------------------
157 | @wellBackground: #f5f5f5;
158 |
159 |
160 | // Navbar
161 | // -------------------------
162 | @navbarCollapseWidth: 979px;
163 |
164 | @navbarHeight: 40px;
165 | @navbarBackground: darken(@navbarBackgroundHighlight, 5%);
166 | @navbarBackgroundHighlight: #ffffff;
167 | @navbarBorder: darken(@navbarBackground, 12%);
168 |
169 | @navbarText: @gray;
170 | @navbarLinkColor: @gray;
171 | @navbarLinkColorHover: @grayDark;
172 | @navbarLinkColorActive: @gray;
173 | @navbarLinkBackgroundHover: transparent;
174 | @navbarLinkBackgroundActive: darken(@navbarBackground, 5%);
175 |
176 | @navbarBrandColor: @navbarLinkColor;
177 |
178 | // Inverted navbar
179 | @navbarInverseBackground: #111111;
180 | @navbarInverseBackgroundHighlight: #222222;
181 | @navbarInverseBorder: #252525;
182 |
183 | @navbarInverseText: @grayLight;
184 | @navbarInverseLinkColor: @grayLight;
185 | @navbarInverseLinkColorHover: @white;
186 | @navbarInverseLinkColorActive: @navbarInverseLinkColorHover;
187 | @navbarInverseLinkBackgroundHover: transparent;
188 | @navbarInverseLinkBackgroundActive: @navbarInverseBackground;
189 |
190 | @navbarInverseSearchBackground: lighten(@navbarInverseBackground, 25%);
191 | @navbarInverseSearchBackgroundFocus: @white;
192 | @navbarInverseSearchBorder: @navbarInverseBackground;
193 | @navbarInverseSearchPlaceholderColor: #ccc;
194 |
195 | @navbarInverseBrandColor: @navbarInverseLinkColor;
196 |
197 |
198 | // Pagination
199 | // -------------------------
200 | @paginationBackground: #fff;
201 | @paginationBorder: #ddd;
202 | @paginationActiveBackground: #f5f5f5;
203 |
204 |
205 | // Hero unit
206 | // -------------------------
207 | @heroUnitBackground: @grayLighter;
208 | @heroUnitHeadingColor: inherit;
209 | @heroUnitLeadColor: inherit;
210 |
211 |
212 | // Form states and alerts
213 | // -------------------------
214 | @warningText: #c09853;
215 | @warningBackground: #fcf8e3;
216 | @warningBorder: darken(spin(@warningBackground, -10), 3%);
217 |
218 | @errorText: #b94a48;
219 | @errorBackground: #f2dede;
220 | @errorBorder: darken(spin(@errorBackground, -10), 3%);
221 |
222 | @successText: #468847;
223 | @successBackground: #dff0d8;
224 | @successBorder: darken(spin(@successBackground, -10), 5%);
225 |
226 | @infoText: #3a87ad;
227 | @infoBackground: #d9edf7;
228 | @infoBorder: darken(spin(@infoBackground, -10), 7%);
229 |
230 |
231 | // Tooltips and popovers
232 | // -------------------------
233 | @tooltipColor: #fff;
234 | @tooltipBackground: #000;
235 | @tooltipArrowWidth: 5px;
236 | @tooltipArrowColor: @tooltipBackground;
237 |
238 | @popoverBackground: #fff;
239 | @popoverArrowWidth: 10px;
240 | @popoverArrowColor: #fff;
241 | @popoverTitleBackground: darken(@popoverBackground, 3%);
242 |
243 | // Special enhancement for popovers
244 | @popoverArrowOuterWidth: @popoverArrowWidth + 1;
245 | @popoverArrowOuterColor: rgba(0,0,0,.25);
246 |
247 |
248 |
249 | // GRID
250 | // --------------------------------------------------
251 |
252 |
253 | // Default 940px grid
254 | // -------------------------
255 | @gridColumns: 12;
256 | @gridColumnWidth: 60px;
257 | @gridGutterWidth: 20px;
258 | @gridRowWidth: (@gridColumns * @gridColumnWidth) + (@gridGutterWidth * (@gridColumns - 1));
259 |
260 | // 1200px min
261 | @gridColumnWidth1200: 70px;
262 | @gridGutterWidth1200: 30px;
263 | @gridRowWidth1200: (@gridColumns * @gridColumnWidth1200) + (@gridGutterWidth1200 * (@gridColumns - 1));
264 |
265 | // 768px-979px
266 | @gridColumnWidth768: 42px;
267 | @gridGutterWidth768: 20px;
268 | @gridRowWidth768: (@gridColumns * @gridColumnWidth768) + (@gridGutterWidth768 * (@gridColumns - 1));
269 |
270 |
271 | // Fluid grid
272 | // -------------------------
273 | @fluidGridColumnWidth: percentage(@gridColumnWidth/@gridRowWidth);
274 | @fluidGridGutterWidth: percentage(@gridGutterWidth/@gridRowWidth);
275 |
276 | // 1200px min
277 | @fluidGridColumnWidth1200: percentage(@gridColumnWidth1200/@gridRowWidth1200);
278 | @fluidGridGutterWidth1200: percentage(@gridGutterWidth1200/@gridRowWidth1200);
279 |
280 | // 768px-979px
281 | @fluidGridColumnWidth768: percentage(@gridColumnWidth768/@gridRowWidth768);
282 | @fluidGridGutterWidth768: percentage(@gridGutterWidth768/@gridRowWidth768);
283 |
--------------------------------------------------------------------------------
/src/test/resources/less/bootstrap.less:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap v2.1.1
3 | *
4 | * Copyright 2012 Twitter, Inc
5 | * Licensed under the Apache License v2.0
6 | * http://www.apache.org/licenses/LICENSE-2.0
7 | *
8 | * Designed and built with all the love in the world @twitter by @mdo and @fat.
9 | */
10 |
11 | /*
12 | Attention:
13 | Any changes of this file will be lost on the next compile run of the .less files!
14 | */
15 |
16 | // CSS Reset
17 | @import "1/reset.less";
18 |
19 | // Core variables and mixins
20 | @import "2/21/variables.less"; // Modify this for custom colors, font-sizes, etc
21 |
--------------------------------------------------------------------------------
/src/test/resources/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 | org.lesscss.it
5 | includes
6 | testing
7 |
8 |
9 |
10 | org.lesscss
11 | lesscss-maven-plugin
12 | @project.version@
13 |
14 | src/test/resources/less
15 | true
16 |
17 | bootstrap.less
18 |
19 |
20 |
21 |
22 |
23 | compile
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------