Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Transformers

Transformers modify source content before it’s injected into a target. They’re specified as pipe-delimited filters on the target tag, letting each target adapt the same content for its specific context.

Syntax

Transformers appear after the block name, separated by |:

<!-- {=blockName|trim|indent:"  "} -->
<!-- {/blockName} -->

Multiple transformers are applied left to right. Each receives the output of the previous one.

Arguments

Some transformers take arguments, specified after a : delimiter:

<!-- {=block|indent:">>> "} -->
<!-- {=block|codeBlock:"typescript"} -->
<!-- {=block|replace:"old":"new"} -->

String arguments are quoted. Numeric arguments are unquoted:

<!-- {=block|indent:4} -->

Available transformers

trim

Removes whitespace from both ends of the content.

<!-- {=block|trim} -->

Before: \n Hello world! \n After: Hello world!

trimStart

Removes whitespace from the start of the content.

<!-- {=block|trimStart} -->

Aliases: trim_start

trimEnd

Removes whitespace from the end of the content.

<!-- {=block|trimEnd} -->

Aliases: trim_end

indent

Prepends a string to each non-empty line. Empty lines are preserved as-is by default.

<!-- {=block|indent:"  "} -->

Before:

line one
line two

line four

After:

  line one
  line two

  line four

To include empty lines (indent them too), pass true as a second argument:

<!-- {=block|indent:"  ":true} -->

With true, every line gets the indent — including empty lines. Without it (default), empty lines stay completely empty.

prefix

Prepends a string to the entire content (not per-line).

<!-- {=block|prefix:"\n"} -->

Before: Hello After: \nHello

suffix

Appends a string to the entire content.

<!-- {=block|suffix:"\n"} -->

Before: Hello After: Hello\n

linePrefix

Prepends a string to each non-empty line. Similar to indent but with a clearer name for the intent.

<!-- {=block|linePrefix:"// "} -->

Before:

line one
line two

After:

// line one
// line two

To also prefix empty lines, pass true as a second argument. This is essential for code comment blocks where every line needs a comment marker:

<!-- {=block|linePrefix:"//! ":true} -->

Before:

A fast HTTP client.

Supports async and blocking modes.

After:

//! A fast HTTP client.
//!
//! Supports async and blocking modes.

Note: when true is set, the prefix is applied to empty lines too, so "//! " on an empty line produces //! (with trailing space). If you need a shorter prefix on empty lines (e.g., //! without the space), use linePrefix:"//! " (without true) and then handle the empty lines separately, or use replace to clean up trailing spaces.

Aliases: line_prefix

lineSuffix

Appends a string to each non-empty line. Empty lines are left empty by default.

<!-- {=block|lineSuffix:" \\"} -->

Before:

line one
line two

After:

line one \
line two \

To also suffix empty lines, pass true as a second argument:

<!-- {=block|lineSuffix:";":true} -->

Aliases: line_suffix

wrap

Wraps the entire content with a string on both sides.

<!-- {=block|wrap:"**"} -->

Before: important text After: **important text**

code

Wraps the content in inline code backticks.

<!-- {=block|code} -->

Before: my-lib After: `my-lib`

codeBlock

Wraps the content in a fenced code block. Optionally specify a language.

<!-- {=block|codeBlock:"typescript"} -->

Before: const x = 1; After:

```typescript
const x = 1;
```

Without a language argument:

<!-- {=block|codeBlock} -->

replace

Replaces all occurrences of a search string with a replacement. Takes exactly two arguments.

<!-- {=block|replace:"foo":"bar"} -->

Before: foo is great, foo forever After: bar is great, bar forever

Chaining transformers

Transformers compose left to right. This is powerful for adapting content to different contexts.

Example: Rust doc comments

Provider content as plain text, transformed into /// doc comments. Use true to ensure empty lines also get the comment prefix:

<!-- {=docs|trim|linePrefix:"/// ":true} -->
<!-- {/docs} -->

If the source contains:

A fast HTTP client.

Supports async and blocking modes.

The target receives:

/// A fast HTTP client.
///
/// Supports async and blocking modes.

Without true, the empty line would be left completely blank, which breaks the doc comment block in Rust.

Example: JSDoc comments

<!-- {=docs|trim|linePrefix:" * ":true} -->
<!-- {/docs} -->

Each line (including empty lines) gets the * prefix, producing valid JSDoc content.

Example: Code block with trimming

<!-- {=example|trim|codeBlock:"rust"} -->
<!-- {/example} -->

Trims the whitespace first, then wraps in a fenced code block.

Naming conventions

All transformers support both camelCase and snake_case names:

camelCasesnake_case
trimStarttrim_start
trimEndtrim_end
codeBlockcode_block
linePrefixline_prefix
lineSuffixline_suffix