Configuration

Laika has a rich set of features and keeps almost every module customizable or even replaceable, and as a consequence there is a lot to configure.

This chapter puts the focus on the basic configuration options that you are most likely to use on a day-to-day basis.

If you want to dig deeper and tweak or extend the way Laika parses or renders, see the intro sections to Customizing Laika and Extending Laika for an overview.

Theme Settings

Laika comes with a lightweight default theme called Helium. Since the theme offers a lot of configuration options it has its own dedicated chapter Theme Settings.

To just give a brief overview, those settings allow you to configure:

These settings also have their dedicated Navigation chapter, including configuration examples, therefore we'll just give a brief overview of available configuration options here and link to the relevant sections.

Run Modes

These settings are available in the library API and the sbt plugin.

Strict Mode

Strict mode switches off all extensions and only uses features defined in the spec of the markup languages.

This might be useful if you develop applications with user input for example, and want to ensure that only standard markup features are exposed to users.

Markup extensions enabled by default are:

To disable all these extensions you can use the strict flag:

laikaConfig := LaikaConfig.defaults.strict
import laika.api._
import laika.format._

val transformer = Transformer
  .from(Markdown)
  .to(HTML)
  .using(Markdown.GitHubFlavor)
  .strict
  .build

Raw Content

Raw content is the term Laika uses for any markup syntax that allows the inclusion of content in the output format, e.g. HTML.

This is disabled by default, even if it is part of the original text markup specification as in the case of Markdown.

This is to generally discourage to tie markup input to a concrete output format, as Laika supports multiple formats like HTML, EPUB and PDF and an API where users can easily add their own format. Markup files containing raw HTML could not be used for those.

Secondly, when the markup originates from user input in a web application, it would not be safe to use without additional filtering. By default Laika does not filter any tags, not even <script> tags, but whitelist filtering can be added fairly easily through Laika's customization hooks like AST Rewriting or Overriding Renderers.

You can enable verbatim HTML and other raw formats explicitly in the configuration:

laikaConfig := LaikaConfig.defaults.withRawContent
import laika.api._
import laika.format._

val transformer = Transformer
  .from(Markdown)
  .to(HTML)
  .using(Markdown.GitHubFlavor)
  .withRawContent
  .build

Character Encoding

The default encoding in Laika is UTF-8.

When you need to work with different encodings you can override the default:

import scala.io.Codec

laikaConfig := LaikaConfig.defaults.withEncoding(Codec.ISO8859)
import scala.io.Codec

implicit val codec:Codec = Codec.ISO8859

This has to be in scope where you specify the input and ouput files for your transformer

Error Handling

Text markup parsers are usually very resilient. For any input they cannot make sense of they fall back to rendering it back as raw text. If, for example you start an emphasized span with an '*', but then never close the span, it will simply be treated as a literal and will not trigger an error.

But there are two groups of errors that do cause a transformation to fail.

Error Types

The handling of the second kind of error can be controlled via configuration.

Default Behaviour

AST nodes that capture errors carry an error message, a severity and a fallback node to use if configuration would allow to proceed with rendering.

Laika comes with two configuration options that control how these nodes are dealt with:

This means, by default the presence of one or more invalid nodes in the AST of a document causes the transformation to fail, with all their message collected in the returned error type.

Visual Debugging

In some cases you may prefer to examine the errors in the rendered content, or you are processing user input where it is more helpful to display them in context than just as a list of error messages.

You can achieve this by basically flipping the two default values in the configuration:

import laika.config.MessageFilters

laikaConfig := LaikaConfig.defaults
  .withMessageFilters(MessageFilters.forVisualDebugging)
import laika.api._
import laika.format._
import laika.config.MessageFilters

val transformer = Transformer
  .from(Markdown)
  .to(HTML)
  .using(Markdown.GitHubFlavor)
  .withMessageFilters(MessageFilters.forVisualDebugging)
  .build

Now rendering proceeds even with invalid nodes and they will be rendered in the location of the document they occurred in. In HTML output these node are rendered as a span with the class runtime-message and a second class for the level (warning, error, etc.), so that their display can be controlled via CSS.

The AST Renderer

If you need even more low-level insight, you can use the included AST renderer to get a formatted output of the entire AST structure.

Longer plain text spans are truncated in this output format to put the emphasis on the structure of the document.

Create a file with the content some *text* example in the input directory and run:

laikaAST

This task is a shortcut for laikaGenerate ast

import laika.api._
import laika.format._

val input = "some *text* example"

val res = Transformer
  .from(Markdown)
  .to(AST)
  .build
  .transform(input)

The output for the small example above will have the following format:

RootElement - Blocks: 1
. Paragraph - Spans: 3
. . Text - 'some '
. . Emphasized - Spans: 1
. . . Text - 'text'
. . Text - ' example'

User-Defined Variables

Finally, the entire machinery for passing configuration around can be used by users, too.

You can define variables in any of the following scopes:

This is an example for defining two variables globally:

laikaConfig := LaikaConfig.defaults
  .withConfigValue("version.latest", "2.4.6")
  .withConfigValue("license", "Apache 2.0")
import laika.api._
import laika.format._

val transformer = Transformer
  .from(Markdown)
  .to(HTML)
  .using(Markdown.GitHubFlavor)
  .withConfigValue("version.latest", "2.4.6")
  .withConfigValue("license", "Apache 2.0")
  .build

These values can then be accessed via Substitution Variables in templates or in markup files:

The latest release is ${version.latest}.
It's released under the ${license} license.

If you define them in a narrower scope and not globally, they won't be available outside of that scope.

There are three namespaces for variable keys which are used by the library, laika.*, cursor.* and helium.*. As long as you avoid these three namespaces, you can freely use any configuration keys.