Tuesday, June 5, 2012

Running less.js on the JVM Server

less.js is a css
templating language with a javascript file to convert templates into
a CSS file.

The less.js
distribution includes a Rhino patch to run less.js from the command
line using rhino. less.js no longer produces a Rhino
version, but the patch remains available in the master branch.

less.js 1.3.0 uses
ECMA-5 and will attempt to upgrade the Object and Array prototypes if
run in a non-ECMA-5 environment. This prevents the script running in
many ECMA environments that ship with jdk6.

There are two
popular jars available that provide a Java API for less.js. Both of
them use Rhino to run the script in the JVM.

Asual`s has been
around longer and hacks the rhino patch to run as a library. Asual
requires the latest version of Rhino.

lesscss-java
claims to be the official java version and includes envjs (mimic a
browser's script environment for running html apps offline). This
allows the library to run less.js just as it would run in the
browser. Envjs requires the latest version of rhino.

If you try and run
less.js using the ECMA script in jdk6, you may find that the core
object/prototypes are sealed and cannot be extended.

The version of ECMA
script on Mac jvms seems to be only ECMA-3.1 or JavaScript 1.5. To
run less.js you have to patch it to use utility functions instead of
ECMA-5 functions. less.js also requires window and document objects to function. However, you can get away with the following environment. var window = {}; var location = {port:0}; var document = { getElementsByTagName: function(){return []}, getElementById: function(){return null} }; var require = function(arg) { return window.less[arg.split('/')[1]]; };

less.js uses XMLHttpRequest to import referenced documents. If you want to load other files yourself, best to override the window.less.Parser.importer function.

To help debug less.js errors the above has a fix for issue 592. All new window.less.Parser have a imports.contents map and this map needs to have the basename of any imported file to resolve error locations. If the map does not contain the basename, a charAt error is thrown.

If running server
side you may also be interested in this patch to inline both less and
CSS files. The opaque flag above turns this on.