The current release supports HTML, PDF, XSL-FO and PrettyPrint. Rendering happens from a generic document tree model shared between all parsers, so that no renderer implementation has to understand specifics about a concrete markup syntax like Markdown or reStructuredText.

Customization of the output is possible on two levels, first most formats (except for PrettyPrint) can be styled with CSS. Secondly the rendering of specific nodes can be overridden with a simple partial function as described in Customizing Renderers.

Finally you can develop an entirely new renderer for a format not supported by Laika out of the box. See chapter Implementing a Renderer for details.

HTML

The HTML renderer can be used with the Transform or Render APIs:

Transform from Markdown to HTML fromFile "hello.md" toFile "hello.html"

val doc: Document = Parse as Markdown fromFile "hello.md"
Render as HTML from document toFile "hello.html"

See Using Laika Embedded for more details on these APIs.

If you are using the sbt plugin you can use several of its task for generating HTML output:

  • laika:html for transforming a directory of input files to HTML
  • laika:generate html <other formats> for transforming a directory of input files to HTML and other output formats with a single parse operation
  • laika:site for generating a site optionally containing API documentation (scaladoc) and PDF files.

See Using the sbt Plugin for more details.

Templating

Laika supports Templating for most output formats. The following example uses variable references to include the title and content of the input document, as well as a directive called @toc to inset a table of contents:

<html>
  <head>
    <title>{{document.title}}</title>
  </head>
  <body>
    @:toc.
    <div class="content">
      {{document.content}}
    </div>
  </body>
</html>

If you save such a template in a file called default.template.html in the root directory of your input sources it will get applied to all markup documents in those directories. You can optionally override the template for an individual sub-directory simply by including a different template named default.template.html in that sub-directory.

See Templates for more details.

HTML Renderer Properties

The unformatted property tells the renderer to omit any formatting (line breaks or indentation) around tags. Useful when storing the output in a database for example:

Transform from Markdown to HTML.unformatted fromFile 
  "hello.md" toFile "hello.html"

The withMessageLevel property instructs the renderer to include system messages in the generated HTML. Messages may get inserted into the document tree for problems during parsing or reference resolution, e.g. an internal link to a destination that does not exist. By default these messages are not included in the output. They are mostly useful for testing and debugging, or for providing feedback to application users producing markup input:

Transform from Markdown to HTML.withMessageLevel(Warning) fromFile 
  "hello.md" toFile "hello.html"

CSS, JavaScript and other Files

The generated HTML can be styled with CSS like any other static HTML files. If you transform an entire directory Laika will copy all static files like CSS and JavaScript files over to the target directory alongside the generated HTML. It does that recursively including sub-directories:

Transform from Markdown to HTML fromDirectory "src" toDirectory "target"

Customizing the HTML Renderer

Finally you can adjust the rendered output for one or more node types of the document tree programmatically with a simple partial function:

val open = """<em class="big">"""
val close = "</em>"

Transform from Markdown to HTML rendering { out => 
  { case Emphasized(content, _) => out << open << content << close } 
} fromFile "hello.md" toFile "hello.html"

Note that in some cases the simpler way to achieve the same result may be styling with CSS.

See Customizing Renderers for more details.

PDF

The PDF support in Laika does not require installation of external tools as it is not based on LaTeX like many other PDF renderers. To follow Laika's general principle to allow for embedded use without further installations, it is based on XSL-FO as an interim format and uses Apache FOP for transforming the XSL-FO generated by Laika to the binary PDF file. Therefore several characteristics like performance and memory consumption depend entirely on Apache FOP. If you plan to use Laika's PDF support embedded in live application it is recommended to first do performance and load testing.

Using the PDF renderer requires to add another dependency to your build:

libraryDependencies += "org.planet42" %% "laika-pdf" % "0.6.0"

The PDF renderer can then be used with the Transform or Render APIs:

Transform from Markdown to PDF fromDirectory "src" toFile "out.pdf"

val tree: DocumentTree = Parse as Markdown fromDirectory "src"
Render as PDF from tree toFile "out.pdf"

See Using Laika Embedded for more details on these APIs.

If you are using the sbt plugin you can use several of its task for generating PDF files:

  • laika:pdf for transforming a directory of input files to a single PDF file
  • laika:generate pdf <other formats> for transforming a directory of input files to PDF and other output formats with a single parse operation
  • laika:site for generating a site optionally containing API documentation (scaladoc) and PDF files.

See Using the sbt Plugin for more details.

CSS for PDF

Laika offers the unusual, but convenient and probably unique feature of CSS styling for PDF. It allows for customization in a syntax familiar to most users. However, the set of available attributes is quite different from what you know from web CSS, as PDF is a page-based format that requires features like page breaks or footnotes that are not available in the context of a web page.

The following example shows the style for headers from Laika's default CSS:

Header {
  font-family: sans-serif;
  font-weight: bold;
  font-size: 12pt;
}

The font-related attributes in this case are identical to the ones you know from web CSS, but the type selector does not refer to an HTML tag, but instead to a class name from the hierarchy of case classes forming the document tree of a parsed input source.

For an overview over the available attributes you can refer to the Formatting Properties chapter in the XSL-FO specification.

For an overview over supported type selectors see the sections following below.

Type Selectors

A type selector in the context of Laika's PDF support does not refer to the name of an HTML tag, but instead to a class name from the hierarchy of case classes forming the document tree of a parsed input source. See Elements Scaladoc for an overview of all node types.

Example:

Paragraph {
  font-size: 12pt;
}

Class Selectors

A class selector refers to a style attribute of a node in the document tree, similar to the class attributes of HTML tags. Only a subset of Laika's nodes get rendered with style attributes. Some exceptions are:

  • Headers get rendered with a level style (level1 to levelN)
  • Titles get rendered with a title style
  • An entry in the table of contents has a toc style
  • Text nodes can have .subscript or .superscript styles
  • Figures come with caption and legion styles

If you customize the renderer you can also add custom styles to any Laika node.

Example for using the title style:

.title {
  font-size: 18pt;
}

Id Selectors

An id selector refers to the unique id of a node in the document tree, similar to the id of an HTML tag. Out of the box only a subset of nodes get rendered with an id: those that internal links refer to, like headers, footnotes or citations.

Example:

#my-header {
  font-size: 18pt;
}

Selector Combinations

Like web CSS Laika supports combinations of selectors to refer to child elements or define styles for multiple selectors at once:

  • Combining type and style selectors: Header.level1 refers to a Header node with a level1 style
  • Combining type and id selectors: Header#my-title refers to a Header node with the id my-title
  • Referring to child elements: Header .section-num refers to a node with a style section-num as a child of a Header node
  • Referring to immediate child elements: Header > .section-num refers to a node with a style section-num as an immediate child of a Header node
  • Referring to multiple selectors: Title, Header refers to both, all Title and all Header nodes

Unsupported Selectors

Some selector types of the CSS specification are not supported as most of them do not add much value in the context of a Laika document tree:

  • Pseudo-classes like :hover
  • Attibute selectors like [attribute~=value] (since Laika nodes do not have many properties)
  • Element1+Element2 or Element1~Element2 for selecting based on sibling elements

Configuration

There are several configuration options for PDF rendering that can be set either in the file directory.conf in the root directory of your input sources or programmatically on the PDF renderer.

In directory.conf you can set the following options:

pdf {
  insertTitles = false
  bookmarks.depth = 3
  toc.depth = 3
  toc.title = "Contents"
}  

The same options are available programmatically through the withConfig method on the PDF renderer:

val config = PDFConfig(
  insertTitles = false, 
  bookmarkDepth = 3,
  tocDepth = 3,
  tocTitle = Some("Contents")
)

Transform from Markdown to PDF.withConfig(config) fromDirectory 
  "source" toFile "out.pdf"
  

These properties control the following aspects of the rendering:

  • insertTitles inserts a title per directory and markup file into the document to give it more structure, since all documents get merged into a single target PDF. Tree titles can be set per directory with the title attribute in the file directory.conf, document titles in the configuration header of the markup document, unless there is already a title element in the content of the document. The default value is true.
  • bookmarkDepth the number of levels bookmarks should be generated for, you can use 0 to switch off bookmark generation entirely. Every level of the tree hierarchy will be considered for a bookmark entry: directories, files and sections within files. The default value is Int.MaxValue.
  • tocDepth the number of levels to generate a table of contents for, you can use 0 to switch off toc generation entirely. Every level of the tree hierarchy will be considered for an entry in the table of contents: directories, files and sections within files. The default value is Int.MaxValue.
  • tocTitle specifies the title for the table of contents. The default value is None.

For more details on these features see Document Structure.

Finally, the withMessageLevel property instructs the renderer to include system messages in the generated PDF. Messages may get inserted into the document tree for problems during parsing or reference resolution, e.g. an internal link to a destination that does not exist. By default these messages are not included in the output. They are mostly useful for testing and debugging, or for providing feedback to application users producing markup input:

Transform from Markdown to PDF.withMessageLevel(Warning) fromDirectory 
  "source" toFile "out.pdf"

XSL-FO Templates

Like the HTML renderer, the PDF renderer supports templating. However, there should be significantly less scenarios where you'd need to use them, as most of the visual aspects of the rendering can be controlled by Laika's CSS for PDF feature. Since the PDF renderer uses XSL-FO as its interim format, the templating is based on this format.

You can have a look at the default XSL-FO template used by the PDF renderer for reference.

You can override it if required by saving a custom template in a file called default.template.fo in the root directory of your input sources.

Customizing the XSL-FO Renderer

Finally you can adjust the fo tags rendered for one or more node types of the document tree programmatically with a simple partial function:

Transform from Markdown to HTML rendering { out => { 
  case elem @ Emphasized(content, _) => out.inline(
    elem.copy(options = Style("myStyle")), content
  ) 
}} fromDirectory "src" toFile "out.pdf"

Note that in most cases the simpler way to achieve the same result will be styling with CSS.

See Customizing Renderers for more details.

XSL-FO

XSL-FO is primarily intended as an interim format for producing PDF output, but you can alternatively use it as the final output format and then post-process it with other tools.

The XSL-FO renderer can be used with the Transform or Render APIs:

Transform from Markdown to XSLFO fromFile "hello.md" toFile "hello.fo"

val doc: Document = Parse as Markdown fromFile "hello.md"
Render as XSLFO from document toFile "hello.fo"

See Using Laika Embedded for more details on these APIs.

If you are using the sbt plugin you can use several of its task for generating XSL-FO output:

  • laika:xslfo for transforming a directory of input files to XSL-FO
  • laika:generate xslfo <other formats> for transforming a directory of input files to XSL-FO and other output formats with a single parse operation

See Using the sbt Plugin for more details.

For customizing XSL-FO rendering the same approach applies as for PDF rendering as the latter uses XSL-FO as an interim format. See the sections above on CSS for PDF, XSL-FO Templates and Customizing the XSL-FO Renderer for more details.

The XLSFO renderer instance also has similar properties as the HTML renderer: withMessageLevel and unformatted for controlling aspect of the output as described in HTML Renderer Properties and finally withStyles to programmatically apply a custom CSS declarations.

PrettyPrint

A renderer that visualizes the document tree structure, essentially a formatted toString for a tree of case classes, mainly useful for testing and debugging purposes.

You can use this renderer with the Transform API:

val input = "some *text* example"

Transform from Markdown to PrettyPrint fromString input toString

res0: java.lang.String = Document - Blocks: 1
. Paragraph - Spans: 3
. . Text - 'some '
. . Emphasized - Spans: 1
. . . Text - 'text'
. . Text - ' example'

Alternatively you can use the Render API to render an existing document:

val input = "some *text* example"

val doc = Parse as Markdown fromString input

Render as PrettyPrint from doc toString

The above will yield the same result as the previous example.

Finally, if you are using the sbt plugin you can use the laika:prettyPrint task.