🪵 bbmd

Tagged template literals

In Creating blocks, we saw how to create blocks using tagged template literals with b.md and incrementally adopt existing template literals into Bbmd blocks.

However, tagged template literals offer additional features that make them worth using even when you're not parsing raw markdown strings.

Block-level tagged templates

Most block factory functions can be called as tagged template literals, not just b.md. This means you can write terse, readable code by mixing template syntax with block composition.

b.p`Hello, ${b.b`world`}!`
Hello, **world**!

Compare the two approaches — both produce identical output, but the tagged template reads more naturally and avoids the noise of commas and quotes around string fragments.

b.p`Follow these steps${b.fn`See the full guide`} to get started.`
b.p("Follow these steps", b.fn("See the full guide"), " to get started.")
Follow these steps[^1] to get started.

[^1]: See the full guide

This works with most blocks, with the exception of blocks which require more complex call signatures like tables and links.

b.doc(
  b.h`User Guide`,
  b.p`Welcome to the ${b.b`Acme`} platform.`,
  b.bq`This is ${b.i`important`} information.
  And here is more important information.`,
)
# User Guide
Welcome to the **Acme** platform.
> This is *important* information.
> And here is more important information.
MarkdownDocument
├── MarkdownHeadingBlock [level=1]
│   └── "User Guide"
├── MarkdownParagraphBlock
│   ├── "Welcome to the "
│   ├── MarkdownBoldBlock
│   │   └── "Acme"
│   └── " platform."
└── _MarkdownBlockquoteBlock
    ├── _MarkdownInlineBlock
    │   ├── "This is "
    │   ├── MarkdownItalicBlock
    │   │   └── "important"
    │   └── " information."
    └── "And here is more important information."

Nested tagged templates

Tagged templates compose naturally — you can nest them as deeply as you like.

b.p`This has ${b.b`bold and ${b.i`italic`}`} text.`
This has **bold and *italic*** text.
MarkdownParagraphBlock
├── "This has "
├── MarkdownBoldBlock
│   ├── "bold and "
│   └── MarkdownItalicBlock
│       └── "italic"
└── " text."

When to use which

As a rule of thumb, use tagged templates when you have a mix of static text and interpolations — that's where they cut the most noise. Use functional calls when the content is a single variable or only injected blocks with no surrounding text.

// ✅ tagged template — static text mixed with blocks
b.p`Follow these steps ${fn} to get started.`
b.p`Welcome to the ${b.b`Acme`} platform.`

// ✅ functional — single variables
b.h(project.title)
b.b(userName)

// ❌ avoid — tagged template wrapping a single value
b.h`${project.title}`
b.p`${userName}`

Mixing approaches

You can freely mix tagged templates and functional calls in the same document. Use whichever is clearest for each block.

const users = [b.b`Alice`, "Bob"]
const teamName = "Engineering"
b.doc(
  b.h(teamName),
  b.p`Here are the current ${b.b("active")} members:`,
  b.list.ul(...users),
)
# Engineering
Here are the current **active** members:
- **Alice**
- Bob
MarkdownDocument
├── MarkdownHeadingBlock [level=1]
│   └── "Engineering"
├── MarkdownParagraphBlock
│   ├── "Here are the current "
│   ├── MarkdownBoldBlock
│   │   └── "active"
│   └── " members:"
└── MarkdownUnorderedListBlock
    ├── MarkdownUnorderedListItemBlock
    │   └── MarkdownBoldBlock
    │       └── "Alice"
    └── MarkdownUnorderedListItemBlock
        └── "Bob"

Automatic trimming

When using tagged template literals, Bbmd automatically trims leading and trailing whitespace from your content. This means you can format your markdown in a more readable way in your IDE without worrying about unintended whitespace affecting your output.

In this example, notice that the contents of b.md were:

  1. Automatically de-dented — b.md strips the common leading indentation from all lines, so you can indent your template to match surrounding code without that indentation leaking into the output.
  2. Trimmed of leading/trailing lines — b.md removes empty lines at the start and end, so you can use the natural multi-line template format without manual .trim() calls.
b.md`
  # Hello, world!

  This is a paragraph with some **bold** text.

  - And
  - A
  - List
`
# Hello, world!

This is a paragraph with some **bold** text.

- And
- A
- List

Syntax highlighting

Bbmd provides a VS Code extension that adds Markdown syntax highlighting inside b.md tagged template literals. This means you get full Markdown highlighting directly in your TypeScript and JavaScript files.

The extension works with .ts, .tsx, .js, .jsx, .mjs, and .cjs files.

On this page