-
Notifications
You must be signed in to change notification settings - Fork 25
How To Use Actuarius
#How To Use Actuarius#
These are the recipes you need to use Actuarius in your own apps. First I will cover the basic instructions, then I will describe ways to modify Actuarius’ behavior. For more details I recommend the Actuarius ScalaDoc.
##Maven & sbt##
You can get Actuarius binaries from the henkelmann.eu
Maven Repo.
For artifact id's, repo URL, version etc. please consult the project README.
##Basic Usage## Once you have Actuarius on your classpath, you can easily process Markdown input. The simplest way to do that is like this:
import eu.henkelmann.actuarius.ActuariusTransformer
val transformer = new ActuariusTransformer()
def markdownToHtmlSnippet(input:String):String = transformer(input)
Note that you need a separate instance for each thread you run transformations in. Actuarius is based on Scala’s Parser Combinators which are (regrettably) not thread-safe (see http://scala-programming-language.1934581.n4.nabble.com/Scala-Parsers-are-not-thread-safe-td2243477.html). However, the overhead for creating ActuariusTransformer instances is very small, so this should not be a performance problem.
If you want to give a class the ability to parse Markdown, you can also mixin the eu.henkelmann.actuarius.Transformer
trait. This will add the same apply method that the Standalone ActuariusTransformer
offers. In fact, ActuariusTransformer
is a simple class that only mixes in Transformer
:
class ActuariusTransformer extends Transformer
##Converting output to XML/XHTML##
Actuarius only outputs String
s. The reason for this is that Markdown allows you to use verbatim HTML in your text.
Actuarius cannot guarantee that this is well formed, so it cannot create scala.xml.NodeSeq
instances. (An alternative
to Actuarius, the Knockoff project outputs NodeSeq
s that contain
scala.xml.Unparsed
nodes for not well formed blocks. This might however mean that you think you have well-formed XML
when in fact you haven’t, as the Unparsed
nodes may contain anything.)
So if you want the output of Actuarius as XML NodeSeq
instances you have two choices:
- Wrap the output in
String
s representing the enclosing tags you want for your output, then parse it manually. - Just wrap the output in an
Unparsed
node.
The first method would look something like this:
def markdownToNodeSeq(input:String):NodeSeq =
scala.xml.XML.loadString("<div>" + transformer(input) + "</div>")
If you allow verbatim XML/HTML in your input, this may fail, as the input might already be not well formed. So if you convert
to NodeSeq
s this way, you should either disable verbatim XML (see below) so Actuarius can guarantee only to output well
formed XML or add proper error handling for input that cannot be turned into well-formed XML.
You have to take care when mixing inline html with inline Markdown, as you can accidently cause the output to be not well-formed anymore, even if your tags themselves are in fact well-formed. The following Markdown will cause Actuarius to emit not well-formed HTML:
This <span>*is not</span>* well formed!
The output will be:
<p>This <span><em>is not</span></em> well formed!</p>
This is the same behavior as the original Markdown.
Wrapping the output in Unparsed
nodes works something like this:
def markdownToUnparsedNodeSeq(input:String):NodeSeq =
new scala.xml.Unparsed(transformer(input))
Note that this is actually cheating, as the output looks like a proper NodeSeq
when in fact it isn’t. It is up to you
which of the three methods (plain String
output, parsed NodeSeq
, fake Unparsed
) you use. I use Actuarius for the
content of my Blog. As I want the pages and Atom feed to be well-formed, I use the “proper” parsing method, as I immediately
notice errors in my page when I write an article. (I prefer a 500 error that I notice immediately over broken XHTML)
##Customizing the Output of Actuarius##
You can modify the output of Actuarius. A typical use-case would be if you want to add attributes to some of the emitted
tags. The eu.henkelmann.actuarius.Transformer
trait has a method def deco():Decorator
that returns a
eu.henkelmann.actuarius.Decorator
instance. That trait defines a number of methods that influence the output of the
Transformer
that returns it. In order to customize that behavior, create your own Transformer
class by mixing in
the Transformer
trait and override the deco()
method to return your own Decorator
. The most comfortable way is
probably to make your own Transformer
its own Decorator
by mixing in both traits and have deco()
return this
:
import eu.henkelmann.actuarius.{Decorator, Transformer}
class MyDecoratingTransformer extends Transformer with Decorator {
override def deco() = this
}
Now you can overwrite any of the methods in Decorator
to influence the output of your Transformer
. There are three
types of methods that influence the output:
-
Decorator methods for block elements like paragraphs and code blocks. These exist for the opening and closing tags and have to return a
String
with the opening/closing tag respectively. They are nameddecorateFooOpen
anddecorateFooClose
. Note that if you return broken tags or not matching tags from these methods, yourTransformer
’s output will not be proper XML anymore, so be warned! -
Decorator methods for inline elements like emphasis or links. These get passed the content(s) of the inline elements and have to return the content wrapped the way you want it.
-
Other methods. Currently there is a method to control the usage of verbatim XML and the way nested blocks are indented.
So as an example assume we want to wrap our paragraphs into <div>
s instead of <p>
s and give those <div>
s a class="myParagraph"
attribute. Also we want to disable verbatim XML to make sure nobody sneaks any nasty stuff into the output (this is
useful if you process user content with Actuarius) and that the output is always well-formed XML snippets. Also we want to use the <blink>
element for emphasis instead of <em>
, as it is a sign for aesthetic and professional web pages. So we extend our custom Transformer
/Decorator
like this:
import eu.henkelmann.actuarius.{Decorator, Transformer}
class MyDecoratingTransformer extends Transformer with Decorator {
override def deco() = this
override def allowVerbatimXml():Boolean = false
override def decorateParagraphOpen():String = "<div class=\"myParagraph\">"
override def decorateParagraphClose():String = "</div>\n"
override def decorateEmphasis(text:String):String = "<blink>" + text + "</blink>"
}
This should be enough to get you started with Actuarius, for more details I recommend having a look at the Javadoc
and at the sources. I did my best to make them clean, well-readable and well-documented. As the project is still brand new there is no user group or anything yet.
But feel free to mail me with any questions, comments, (constructive) criticism at christoph-actuarius_at_henkelmann.eu
(just replace _at_
with @
).
If you find Actuarius useful, I would like to hear from you!