LESS in Java: Running LESS CSS on the JVM
posted under category: CSS on September 13, 2011 by Nathan
Foreword: I am giving a LESS CSS talk at the Adobe MAX 2011 ColdFusion Unconference. Blogging about LESS is just one of my stepping stones to presenting. If you want the really good stuff, you should come to my session!
I recently blogged about LESS ports to other platforms, and I thought about mentioning Java there, but this is not a port so much as just reusing the native implementation. Let me break it down like this: Yes, LESS runs on the Java Virtual Machine. It's not even that hard. How you may ask? Like this...
Mozilla makes browsers and Javascript engines. One of their Javascript engines is called Rhino, a JSR 223 compliant Javascript engine for the JVM. You can run any Javascript in Rhino, except that there is no browser, no window
, no document
and no DOM (I know, it sounds like a dream come true). The conflict comes where LESS.js relies on browser constructs to get its job of compiling and preprocessing LESS CSS into plain CSS, so we have to defeat that.
Lucky for us, we live in the future, and along with our flying cars, we also have Google and GitHub, which pointed me to Asual's project, lesscss-engine. Asual is a software company in Bulgaria, and their GitHub projects are run by Rostislav Hristov.
The easiest method of setting up Asual's solution is to download his browser.js and engine.js, then from Rhino, within Java, include them in the order of browser.js, less.js, then engine.js - the order is important. I did this in an Ant build file like this:
<script language="JavaScript" src="browser.js" />
<script language="JavaScript" src="less.js" />
<script language="JavaScript" src="engine.js" />
From there it's just a matter of calling the engine methods to load LESS CSS code, convert it to CSS and output to a file. Here is how I did it, this is my code that is directly after the script loading:
<script language="JavaScript"><![CDATA[
var inputFile = readFile('input.less');
var css = compileString(inputFile);
writeFile('output.css', css);
function writeFile(filename, content) {
var fstream = new java.io.FileWriter(filename);
var out = new java.io.BufferedWriter(fstream);
out.write(content);
out.close();
}
]]></script>
The engine.js has a number of good helper methods (readFile, writeFile, compileString, etc.), I did it this way in case there were more LESS files to compile and I wanted to add it to the same
css
output string. When you do this, make sure you have the Rhino file, js.jar, in your Ant classpath. In Eclipse I loaded the external jar by adding it to the 'Run as...' dialog when you right-click on your build.xml file. Also make sure you are on Java 1.6+ to support JSR 223 Java Scripting.You aren't limited to compiling LESS when you do this, you know. You can actually do anything you want in Javascript from right inside your Ant build file. It's fantastic.
There are other methods of accomplishing the same goal. Erwan Loisant did something similar by altering the core LESS.js files (including the proper pull request). While he calls his release LESS for Rhino, it's really more of LESS for Ant. Even still, it works great as a rhino-javascript-ant all-in-one solution. I especially like his use of an Ant macrodef to create a <lessjs> tag. His examples work straight across from his blog, perfectly.
Not content to rest on my laurels, I went back to the Asual's LESS Engine project to see if I could make a jar and see what I could do with it. I cloned the GitHub repository locally over http, then I added it as a project to Eclipse. I had to install Maven, which was simple with Eclipse's software installer, and running it is almost exactly like running an Ant build. When you build the project you get a few jars in the
target/
folder. I recommend using the lesscss-engine-1.1.4-jar-with-dependencies.jar
file, as it's the most likely to work anywhere you need it.When I checked the LessEngine class, I noticed a
main
method that was added recently, which means we can call it from the command line, like so:java -jar lesscss-engine-1.1.4-jar-with-dependencies.jar input.less output.css
Incidentally, if Asual (or someone) were to add a -w command line switch to watch the input file for changes, this would essentially make it identical to the Ruby LESS compiler,
lessc
. Except, of course, it would be much faster. Just a thought.So we can call it from the command line. The next, most obvious step, is to put this in an Ant build. This was so simple. Here is what I did:
<java jar="lesscss-engine-1.1.4-jar-with-dependencies.jar" fork="true" dir="${basedir}">
<arg value="input.less" />
<arg value="output.css" />
</java>
Copy and paste that, with the jar, and it will all work as advertised.
To summarize, You can compile LESS on Java. It's fun and easy to do!
If you want to get all the files, or want to see it in action, I'm doing this talk September 28, 2011 at the AZCFUG in Tempe, AZ, then at Adobe Max on October 5th, then again October 12th at the Tucson CFUG. Look forward to more of this kind of chatter here on this blog.