Draft42 Demo

Code Blocks

2025, 15 Dec

Code is everywhere in technical writing. Here's how it looks when published with Draft42.

Basic Code Blocks

Drop in a code block with a language identifier and syntax highlighting just works:

pub struct TokenStream<'a> {
    tokens: &'a [Token],
    position: usize,
}

impl<'a> TokenStream<'a> {
    pub fn peek(&self) -> Option<&Token> {
        self.tokens.get(self.position)
    }

    pub fn advance(&mut self) -> Option<Token> {
        let token = self.tokens.get(self.position).cloned();
        self.position += 1;
        token
    }
}
rust

File Labels

You can label your code with the file attribute to add a filename in the header—useful when showing code from a specific file:

pub fn expect(&mut self, kind: TokenKind) -> Result<Token> {
    match self.advance() {
        Some(token) if token.kind == kind => Ok(token),
        Some(token) => Err(ParseError::unexpected_token(token, kind)),
        None => Err(ParseError::unexpected_eof()),
    }
}
token_stream.rs
rust

Line Highlighting

You can highlight specific lines in the code to draw attention to specific areas. Here, lines 8-11 show the core loop logic:

pub fn separated_list<T>(
    parser: &mut Parser,
    separator: TokenKind,
    element: impl Fn(&mut Parser) -> Result<T>,
) -> Result<Vec<T>> {
    let mut items = vec![element(parser)?];

    while parser.stream.peek().map(|t| t.kind) == Some(separator) {
        parser.stream.advance();
        items.push(element(parser)?);
    }

    Ok(items)
}
combinators.rs
rust

Captions

The caption attribute adds a description below the code block:

impl Parser {
    fn synchronize(&mut self) {
        while let Some(token) = self.stream.peek() {
            match token.kind {
                TokenKind::Semicolon => {
                    self.stream.advance();
                    return;
                }
                TokenKind::Fn | TokenKind::Let => return,
                _ => self.stream.advance(),
            }
        }
    }
}
parser.rs
rust
Error recovery skips to the next statement boundary after a parse error

Multiple Languages

Syntax highlighting works across languages:

async function fetchData(url) {
    const response = await fetch(url);
    if (!response.ok) {
        throw new Error(`HTTP error: ${response.status}`);
    }
    return response.json();
}
handler.js
js
def process_items(items):
    return [
        item.upper()
        for item in items
        if item.startswith('_')
    ]
processor.py
python
type user = {
  id: int,
  name: string,
  email: option<string>,
}

let display = user =>
  switch user.email {
  | Some(email) => `${user.name} <${email}>`
  | None => user.name
  }
User.res
rescript
interface User {
    id: number;
    name: string;
    email?: string;
}

type Result<T> =
    | { success: true; data: T }
    | { success: false; error: string };
types.ts
typescript

Inline Code

Use backticks for inline code like TokenKind::LParen or Result<T> within text.

Combining Everything

All attributes work together. Here the highlighted lines show the expect calls that enforce the delimiters:

pub fn delimited<T>(
    parser: &mut Parser,
    open: TokenKind,
    inner: impl Fn(&mut Parser) -> Result<T>,
    close: TokenKind,
) -> Result<T> {
    parser.stream.expect(open)?;
    let result = inner(parser)?;
    parser.stream.expect(close)?;
    Ok(result)
}
delimited.rs
rust
Helper for parsing delimited expressions like (foo) or [bar]

That's it for code blocks. Syntax highlighting, file labels, line highlights, and captions—use them to make your code samples clear and nice looking.