Trying to make CoffeeScript work with Scalate and Play
A few weeks ago, I wrote about integrating Scalate with Play.
The next steps in my Play Scala adventure will be trying to get the CoffeeScript module to work. I also hope to integrate HTML5 Boilerplate with Jade and Scalate Layouts.
Since my last writing, the Scalate Team has created a new branch for Scala 2.8.x (that's compatible with Play) and released 1.5.2. To upgrade my Play application to use this version, I changed my dependencies.yml to have the following:
- org.fusesource.scalate -> scalate-core 1.5.2-scala_2.8.1: transitive: false - org.fusesource.scalate -> scalate-util 1.5.2-scala_2.8.1: transitive: false
Unfortunately, this release breaks Scalate's CoffeeScript support because it wraps the code with illegal comments. This has been fixed in the latest snapshot, but no new release has been cut. However, even if it did work, it's not quite what I'm looking for. The 1.5.2 release allows for compiling inline CoffeeScript on-the-fly, but I'd rather store my .coffee files external to the page.
To try and figure out how to do this, I sent a message to the Scalate Google Group asking Does Scalate allow for referencing (and compiling) CoffeeScript files like the plugin for Play? My email prompted the Scalate Team to do some modifications that seemed to do exactly what I was looking for.
http://scalate.fusesource.org/source.html
http://scalate.fusesource.org/building.html
then run this...
cd samples/scalate-example mvn jetty:runthen open http://localhost:8080/coffee/index
there are 2 sample jade files which use embedded coffee or a separate coffee file (using the .js extension in the <script src attribute>
https://github.com/scalate/scalate/tree/master/samples/scalate-exampl...
e.g. here's a jade file references a separate .js file for a coffee script which gets converted to .js on the server...
https://github.com/scalate/scalate/blob/master/samples/scalate-exampl...
To try out the improved CoffeeScript support, I checked out the source and fumbled with Git branches for a bit before I got latest version of Scalate to build. Unfortunately, it didn't work because Play doesn't know how to process the .js and .css files.
@67o8fflce Application.foo.js action not found Action not found Action Application.foo.js could not be found. Error raised is Controller controllers.Application.foo not found play.exceptions.ActionNotFoundException: Action Application.foo.js not found at play.mvc.ActionInvoker.getActionMethod(ActionInvoker.java: 588) at play.mvc.ActionInvoker.resolve(ActionInvoker.java:85) at Invocation.HTTP Request(Play!) Caused by: java.lang.Exception: Controller controllers.Application.foo not found ... 3 more 08:20:21,133 ERROR ~
Based on this error, I assumed I needed a Controller to do receive the .js and .css requests and compile them accordingly with Scalate. I changed my Jade template to have the following:
script(src="/assets/foo.js" type="text/javascript")
Then I added a new route to my Play application:
GET / Application.index GET /assets/{template} ScalateResource.process
My ScalateResource.scala class is as follows:
package controllers import play.mvc._ object ScalateResource extends Controller { def process(args: (Symbol, Any)*) = { var template = params.get("template") // replace .js with .coffee template = template.replace(".js", ".coffee") // replace .css with .scss template = template.replace(".css", ".scss") ScalateTemplate(template).render(); } }
Unfortunately, when I tried to access http://localhost:9000/assets/foo.js, I received the following error:
TemplateException occured : Not a template file extension (md | markdown | ssp | scaml | mustache | jade), you requested: coffee
At this point, I still haven't figured out how to solve this. I can only assume that the reason this works in the example application is because it uses a TemplateEngineFilter that's mapped to /*.
As I see it, I have a few choices if I want to continue using CoffeeScript and Scalate in my application:
- Revert to an older build of Scalate that uses the in-browser CoffeeScript compiler.
- Try to get a new version released that fixes the comment bug and use inline CoffeeScript.
- Keep trying to figure out how to get external files compiled by Scalate.
Obviously, I'd like to do #3 the most, but with the lack of responses from the Scalate group, this seems like the most challenging. Since #1 is the easiest (and I can complete without anyone's help), I'll be going that route for now. With any luck, the 2nd and third solutions will surface as options before my talk in November.
Update Oct 4, 2011: I was able to get external CoffeeScript files working! It was rather simple actually. I just tried the Play CoffeeScript module again, using Scalate's {uri("/path")}
helper. For example, in a Jade template:
script(type="text/javascript" src={uri("/public/javascripts/script.coffee")})
This compiles the CoffeeScript file on the server and returns JavaScript. Sweet!