diff options
-rw-r--r-- | docs/pages/9 - Contrib Modules.md | 150 |
1 files changed, 149 insertions, 1 deletions
diff --git a/docs/pages/9 - Contrib Modules.md b/docs/pages/9 - Contrib Modules.md index 9b44082d..4ddf097a 100644 --- a/docs/pages/9 - Contrib Modules.md +++ b/docs/pages/9 - Contrib Modules.md @@ -97,7 +97,155 @@ object project extends ScalaModule { ### Twirl -(todo) +Twirl templates support. + +To declare a module that needs to compile twirl templates you must extend the `mill.twirllib.TwirlModule` trait when defining your module. +Also note that twirl templates get compiled into scala code, so you also need to extend `ScalaModule`. + +```scala +import $ivy.`com.lihaoyi::mill-contrib-twirllib:0.3.2`, mill.twirllib._ +object app extends ScalaModule with TwirlModule { + +} +``` + +#### Configuration options + +* ` def twirlVersion: T[String]` (mandatory) - the version of the twirl compiler to use, like "1.3.15" + +#### Details + +The following filesystem layout is expected: + +```text +build.sc +app/ + views/ + view1.scala.html + view2.scala.html +``` + +`TwirlModule` adds the `compileTwirl` task to the module: +``` +mill app.compileTwirl +``` + +(it will be automatically run whenever you compile your module) + +This task will compile `*.scala.html` templates (and others, like `*.scala.txt`) into the `out/app/compileTwirl/dest` +directory. This directory must be added to the generated sources of the module to be compiled and made accessible from the rest of the code: +```scala +object app extends ScalaModule with TwirlModule { + def twirlVersion = "1.3.15" + def generatedSources = T{ Seq(compileTwirl().classes) } +} +``` + +#### Caveats + +There is a couple of caveats, to be aware of, as of now (in `v0.3.2`). + +##### Packages +First, if you structure your twirl templates into packages, like this: +```text +build.sc +app/ + src/hello/ + Main.scala + views/ + hello/ + another/ + view1.scala.html + view2.scala.html +``` + +the generated sources in the `out` directory will look like this: +```text +build.sc +out/app/compileTwirl/dest/ + hello/ + another/ + html/ + view1.template.scala + view2.template.scala +``` + +Looking at the `mill show app.compileTwirl` in this setup shows this: +``` +{ + ... + "classes": "ref: ... : .../out/app/compileTwirl/dest/html" +} +``` + +Basically it means that currently `TwirlModule` expects all templates to be html and with no packages. +So adding this directly to the generated sources will not exactly work as expected (as there might not even be a `out/app/compileTwirl/dest/html` directory +at all, unless you have templates in the default package). + +The workaround is simple, though: +```scala +object app extends ScalaModule with TwirlModule { + def twirlVersion = "1.3.15" + override def generatedSources = T{ + val classes = compileTwirl().classes + Seq(classes.copy(path = classes.path / up)) // we just move one dir up + } +} +``` + +This should cover the problem with templates under packages, and also should make other-than-html +templates available as well. + +##### Default imports + +Another problem is with some default imports that the twirl sbt plugin assumes, but it seems not to work with `TwirlModule`. + +If you reference `Html` in your templates, like + +```scala +// wrapper.scala.html +@(content: Html) +<div class="wrapper"> + @content +</div> +``` + +the template will not compile. You'll need to add this import: +``` +@import play.twirl.api._ +``` + +in the template that uses twirl classes. + +Another one is `@defining`, which might be used like this: +``` +@defining({ + val calculatedClass = { + // do some calculations here + } + calculatedClass +}) { calculatedClass => + <div class="@calculatedClass">stuff 1</div> + <div class="@calculatedClass">stuff 2</div> +} +``` + +You'll need this import: +```scala +@import play.twirl.api.TwirlFeatureImports._ +``` + +At some point `TwirlModule` might get support for the additional "default" imports, which will make this much easier, +but right now it is unimplemented + +```scala + // REMIND currently it's not possible to override these default settings + private def twirlAdditionalImports: Seq[String] = Nil +``` + +#### Example +There's an [example project](https://github.com/lihaoyi/cask/tree/master/example/twirl) + ## Thirdparty Mill Plugins |