Lift Weekly Recap 4
Ohai, week 4! Yeah, I said I’d try and do this one earlier, but man that did not work out… In the ongoing search for a home other than the mailing list for these, I’m going to try parking them on this fine svbtle blog. This still isn’t the best place—for one thing, it’s not something that can be easily handed off—but I don’t currently have time to put them anywhere else, and I like having a place to link to that isn’t Google Groups. For now, the body will be cross-posted to the mailing list, and we’ll see how folks like that.
As an ongoing rule, if you have any ideas for things that might be mentioned in something like this, drop me a line at savedfastcool AT gmail.com ! In the meantime, on to the fun stuff!
Firstly, a flash back to the new lift-markdown
module. When I first wrote about it, I mentioned that there was a way to turn off verbatim XML. In fact, there’s a fairly straightforward way to customize the handling of most markdown entities in the form of a Decorator. A quick example here:
class MyThreadLocalTransformer extends Transformer {
private[this] val threadLocalTransformer = new ThreadLocal[SingleThreadedTransformer] {
override def initialValue = new SingleThreadedTransformer {
override val deco = new Decorator {
override val allowVerbatimXml = false
override def decorateImg(alt:String, src:String, title:Option[String]) = src
}
}
}
override def apply(s: String) = threadLocalTransformer.get()(s)
}
The above code block demonstrates the creation of a new net.liftweb.markdown.Transformer
subclass that (a) keeps a thread-local copy of a transformer (because transformers use Scala parser-combinators, which are not thread-safe!) and (b) overrides its decorator to disallow verbatim XML and to make it so that, when parsing an image entity (![alt text](http://url/to/image
), we emit the image URL rather than a full img
tag. A full accounting of the methods that can be overridden in Decorator
, and their default implementations, can be found in the Decorator.scala
file on GitHub.
One thing worth noting: when disabling verbatim XML handling, currently XML tags are handled as links instead. So, for example, with verbatim XML disabled, the Markdown string dan balan ![boom](http://slam.dam) <span>bam</span>
will be parsed as <p>dan balan http://slam.dam <a href="span">span</a>bam<a href="/span">/span</a></p>
.
In addition to this bit of enrichment, another tidbit about Markdown support: lift-util
now has a helper MarkdownParser
singleton. This singleton has a parse
function that can take a String
and produce a fully-parsed NodeSeq
, wrapped in a Box
in case of failure, containing the parsed XML from the Markdown String. The output of lift-markdown
is parsed using the HTML5 parser that is also used by default in templates. You can use it like this:
> import net.liftweb.util._
import net.liftweb.util._
> MarkdownParser.parse("Boom! [Get out the way](http://google.com) ![Get out the way](/images/booyan.jpg) <span>Get out the way!</span>")
Full(<p>Boom! <a href="http://google.com">Get out the way</a> <img alt="Get out the way" src="/images/booyan.jpg"/> <span>Get out the way!</span></p>
)
Enough about Markdown! A small structural change: before, in order to use Lift’s wizard stuff, you had to add the lift-wizard
package to your dependencies and import net.liftweb.wizard._
. Lift Wizard is now part of lift-webkit
, so you don’t need to add any more dependencies, and you get the wizard classes imported by simply importing net.liftweb.http._
.
In a similar vein, the lift:a
snippet is no longer available in Lift 3. Instead, you should use the SHtml.ajax*
methods bound to a link’s onclick
handler. lift:a
was pretty unwieldy, and has been deprecated since the early Lift 2.5 milestones.
Last one for this week, a small tidbit: the lift:surround
snippet in Lift 3 has a new golden delicious attribute, eat
. When present on the element, lift:surround
will drop the element that invoked the surround. This is useful when surround
is used with an HTML data-bind
attribute but the HTML element it’s put on should be removed in the process. For example:
<div data-lift="surround?with=template">
This is a test!
</div>
After Lift processing, if the template just included an html
/body
combination, this would produce:
<html>
<body>
<div>
This is a test!
</div>
</body>
</html>
With the eat
parameter:
<div data-lift="surround?with=template&eat">
This is a test!
</div>
You would instead get:
<html>
<body>
This is a test!
</body>
</html>
And that’s it for this week! Next week, we’ll look at some new customizability in CometActor
, and some really nice customizability added to data-
attribute handling. Fun times!