Scala embedded DSL for templates and CSS?

137 views
Skip to first unread message

Jxtps

unread,
Sep 14, 2010, 3:06:04 AM9/14/10
to play-framework
Ok, so this might be a bit crazy, but wouldn't it be neat to create a
"simple" embedded scala DSL for building templates? And even for the
CSS? Then you get as much compile time checking as you could
reasonably hope for, plus code completion and whatever refactoring etc
your IDE may support. You could even put in scaladoc comments for the
HTML tags so that when hovering you'd get some tutorial/reference
info. Great for beginners, and great re-use of the power the IDE
brings (indentation, formatting, syntax highlighting, etc, etc).

I'm thinking something along the lines of:

import MyCss._
class MyTemplate(foo:MyModel) extends ScalaTemplateBase {
def render():String = {
div(myKlass+myIdentifier) {
p {
"Hello, world! " + foo.toString
}
}
}
}

The div, p, etc functions would be defined in ScalaTemplateBase (or
whatever would be a suitable hierarchy) along the lines of:

def div(css:CSS=null, attrs:Map[String,String]=Nil):String =
tag("div",css, attrs)

and tag would be defined appropriately to use the body etc. And then a
CSS DSL like so:

object MyCSS extends CSS {
val myKlass = new CssClass;
val myIdentifier = new CssIdentifier;

def renderCss():String = {
// Code that produces the actual CSS based on the classes and
identifiers declared above
// Override e.g. + and * to allow CSS combinations:
// myKlass * myIdentifier + foo => ".myKlass#myIdentifier foo"
}
}

It would seem like it wouldn't be that much work to create something
that is *very* close to the neatness of haml and sass, but with the
added benefit of compile time checks etc - even for the basic CSS
classes/identifiers.

Layouts could be done by inheritance of traits, whichever makes the
most sense. It would then be used in your controller like so:

object MyController extends Controller {
def myAction(foo:Int) {
render(new MyTemplate(MyModel.find(foo)));
}
}

For content negotiation the template can have multiple render
functions with very sensible base class defaults (e.g. XML and JSON
rendering should basically be done by either serializing all public
fields, or annotating the fields that should be included/excluded).

Cons: whoever writes the template needs to know a little scala, though
frankly I don't know how much worse that would be compared to learning
a template language, and the actual text to be output needs to be in
quotes and concatenated.

The latter is actually a benefit when internationalizing since then
you don't get the "inverted template" problem where you find yourself
using the template language escape sequence to call the translation
function all over the place.

What do you think?

(please forgive syntax etc errors)

Julien Tournay

unread,
Sep 14, 2010, 5:09:22 AM9/14/10
to play-fr...@googlegroups.com
Hi,

Yep, this kind of DSL exists in other languages (see WASH here http://blog.uncommons.org/2008/12/03/generating-html-with-haskell/).
I think you should do to a simple proof of concept, and try to do a simple app with it.
That way you'll see if scala fits for that, if it's readable enough, if it's easy to create tags etc.

jto.



--
You received this message because you are subscribed to the Google Groups "play-framework" group.
To post to this group, send email to play-fr...@googlegroups.com.
To unsubscribe from this group, send email to play-framewor...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/play-framework?hl=en.




--
Real Programmers don't need comments-- the code is obvious.

Arthur

unread,
Sep 14, 2010, 7:47:24 AM9/14/10
to play-framework
This might work as a module but it should not be included in the main
release. Providing a new way to create views (other than HTML +
groovy and CSS) adds to confusion for new beginners and increases the
ramp up time before a team can start productively developing with the
play framework.

Being able to take HTML and CSS that can come straight from a web
designer and then adding in some ifs and dynamically added values from
a controller allows developers to focus on the core of their product
without having to concentrate on what is an almost but not quite HTML
and CSS clone.

Sorry for the rant, but this is the sort of thinking that turns me off
other frameworks. Yes, it is clever but it is not intuitive and easy
to get your head around if you're not using it every day.

On Sep 14, 10:09 am, Julien Tournay <boudhe...@gmail.com> wrote:
> Hi,
>
> Yep, this kind of DSL exists in other languages (see WASH herehttp://blog.uncommons.org/2008/12/03/generating-html-with-haskell/).
> > play-framewor...@googlegroups.com<play-framework%2Bunsubscribe@go oglegroups.com>
> > .

Jxtps

unread,
Sep 14, 2010, 11:42:57 AM9/14/10
to play-framework
Julien: I will post back if I put something together.

Arthur: No worries - I think this type of template "language" would be
most at home in a small, dev-oriented team. But there it could be
really awesome ;)

Julien Tournay

unread,
Sep 14, 2010, 2:09:45 PM9/14/10
to play-fr...@googlegroups.com
I think the syntax you posted could be simplified by removing "{ }"s and using operators
Maybe something like:

html <<
   head
   ++
   body << 
     p#id << "Hello World"

(well, not sure it's easier in fact...)

Basically "html", "body" etc. are Objects that extends a superclass (lets call it Node)
Node defines "<<" and "++" methods, each taking a List[Node] as parameter.

# is also a function that sets the id, would be nice to have "." for classes (css syntax) but I don't think scala would let you use that as a function name.

"Hello World" would be implicitly converted to some sort of TextNode.

The all thing builds a tree of Nodes, each node "knows" how to render itself, and you just have to call a rendering method recursively to get the whole document rendered.

I'm not sure how to iterate over a list, maybe by using for + yield, like:

ul <<
   for(x <- xs)
       yield li << x

That's just some ideas that came while writing, maybe they suck or are not feasible.

jto.


To unsubscribe from this group, send email to play-framewor...@googlegroups.com.

For more options, visit this group at http://groups.google.com/group/play-framework?hl=en.

Jxtps

unread,
Sep 14, 2010, 4:46:00 PM9/14/10
to play-framework
In order to know where to put the end tag you'd need to use blocks?

Maybe that can be achieved with operators as well, but it seems like
it would be more brittle and not leverage the nice block-based code
indentation, brace matching etc that the IDE provides?

I'm essentially looking for something very close to haml, but without
all the implementation effort ;)

(yes, I'm aware of scaml - I'm also looking to get the IDE/compiler
support "for free")

Marcus Downing

unread,
Sep 15, 2010, 9:35:27 AM9/15/10
to play-framework
I've seen this done before in Scala, and didn't like it. In my
opinion, Scala DSLs like this often make the mistake of adding more
complexity than they remove. Quirks aside, HTML, CSS and JS are
perfectly good and standard languages; you gain little by abstracting
away from them, while losing the benefits of using a standard.

However, if you want to achieve the same result as a tool like HAML,
SASS or LESS, why not look at helping to port/integrate these tools
into Play rather than inventing another?
Reply all
Reply to author
Forward
0 new messages