scribble-tools
| (require scribble-tools) | package: scribble-tools |
This library provides Scribble forms for typesetting CSS, C, C++, CSV, HTML, Java, JavaScript, JSON, Go, Haskell, LaTeX, Makefile, Markdown, Objective-C, plist, Python, Racket, Rhombus, Rust, shell scripts (Bash/Zsh/PowerShell), Swift, TeX, TSV, WebAssembly (WAT), YAML, and Scribble snippets with syntax coloring.
The inline forms (css-code, c-code, cpp-code, csv-code, go-code, html-code, java-code, js-code, json-code, haskell-code, latex-code, makefile-code, markdown-code, objc-code, pascal-code, plist-code, python-code, racket-code, rhombus-code, rust-code, shell-code, swift-code, tex-code, tsv-code, wasm-code, yaml-code, and scribble-code) produce content.
The block forms (cssblock, cblock, cppblock, csvblock, htmlblock, goblock, javablock, jsblock, jsonblock, markdownblock, haskellblock, latexblock, makefileblock, objcblock, pascalblock, plistblock, pythonblock, racketblock, rhombusblock, rustblock, shellblock, swiftblock, texblock, tsvblock, wasmblock, yamlblock, and scribbleblock) produce code blocks with optional line numbers, file labels, and escapes.
1 Guide
This section gives a practical introduction to the forms and the most useful options.
1.1 Inline Forms
Use inline forms when you want code inside running text:
Language |
| Scribble Form |
CSS |
| @css-code{.card { color: #c33; }} |
C |
| @c-code{int answer = 42;} |
C++ |
| @cpp-code{std::vector<int> xs = {1, 2, 3};} |
CSV |
| @csv-code["name,age"] |
Go |
| @go-code{func add(x int, y int) int { return x + y }} |
HTML |
| @html-code{<button class="primary">Save</button>} |
Java |
| @java-code{class Example { void run() { System.out.println("hi"); } }} |
JavaScript |
| @js-code{const total = items.reduce((a, b) => a + b, 0);} |
JSON |
| @json-code["{\"name\": \"Ada\"}"] |
Haskell |
| @haskell-code{sumSquares xs = sum (map (^ (2 :: Int)) xs)} |
LaTeX |
| @latex-code{\section{Intro}} |
Makefile |
| @makefile-code{all: build test} |
Markdown |
| @markdown-code["# Hello"] |
Objective-C |
| @objc-code{@"Hello"} |
Pascal |
| @pascal-code{function Add(x, y: Integer): Integer; begin Add := x + y; end;} |
plist |
| @plist-code{<plist/>} |
Python |
| @python-code{def total(xs): return sum(xs)} |
Racket |
| @racket-code{(define (add x y) (+ x y))} |
Rhombus |
| @rhombus-code{fun add(x, y): x + y} |
Shell |
| @shell-code[#:shell 'bash]{if [ -f ~/.zshrc ]; then echo ok; fi} |
Rust |
| @rust-code{let xs: Vec<i32> = vec![1, 2, 3];} |
Swift |
| @swift-code{let answer = 42} |
TeX |
| @tex-code{\hbox{Hello}} |
TSV |
| @tsv-code["name\tage"] |
WebAssembly |
| @wasm-code{(module (func (result i32) (i32.const 42)))} |
YAML |
| @yaml-code["name: Ada"] |
Scribble |
| @scribble-code{"@bold{Hello} world."} |
Language |
| Result |
CSS |
| .card { color: #c33; } |
C |
| int answer = 42; |
C++ |
| std::vector<int> xs = {1, 2, 3}; |
CSV |
| name,age |
Go |
| |
HTML |
| |
Java |
| |
JavaScript |
| |
JSON |
| {"name": "Ada"} |
Haskell |
| sumSquares xs = sum (map (^ (2 :: Int)) xs) |
LaTeX |
| \section{Intro} |
Makefile |
| all: build test |
Markdown |
| # Hello |
Objective-C |
| Hello |
Pascal |
| function Add(x, y: Integer): Integer; begin Add := x + y; end; |
plist |
| <plist/> |
Python |
| def total(xs): return sum(xs) |
Racket |
| (define (add x y) (+ x y)) |
Rhombus |
| fun add(x, y): x + y |
Shell |
| |
Rust |
| |
Swift |
| let answer = 42 |
TeX |
| \hbox{Hello} |
TSV |
| name age |
WebAssembly |
| |
YAML |
| name: Ada |
Scribble |
| @bold{Hello} world. |
If you want scribble-code to link identifiers to their documentation, you need to provide a context. Either add "#:context #'here" when calling scribble-code, or set the context using a parameter:
@current-scribble-context[#'here] @scribble-code["@bold{Hello} world."]
@bold{Hello} world.
1.2 Block Forms
Use block forms for larger snippets:
|
|
| |||||||||||||
|
|
| |||||||||||||
|
|
| |||||||||||||
|
|
| |||||||||||||
|
|
| |||||||||||||
|
|
| |||||||||||||
|
|
|
1.3 Block Form Decorations
Use these options to add decorations to block output:
Scribble source |
| Rendered result | |||||||||
|
|
| |||||||||
|
|
| |||||||||
|
|
|
1.4 Preview Visualizations
css-code and cssblock can show visual helpers:
.badge { color: #0a7; background: linear-gradient(90deg, #0a7, #5cf); font-family: "Fira Code", monospace;Aa margin: 16px; border-radius: 4px; border-radius: 8px; }
1.5 Escapes
All forms support escapes to splice Scribble content:
.notice { color: tomato; }
1.6 Documentation Links
By default, code output includes documentation links for common identifiers:
CSS properties (for example display, grid, border-radius).
Common JavaScript classes, methods, and language keywords (for example Array, querySelector, map, const).
Common Go language keywords, predeclared identifiers, and selected standard-library identifiers (for example func, nil, and Println) are linked to the official Go spec and package documentation.
Common Java language keywords and standard-library identifiers (for example class, String, System, and @Override) are linked to the official Oracle Java Language Specification and Java SE API docs.
Common LaTeX commands and environments (for example \section, \label, \begin{itemize}) are linked to the LaTeX2e reference manual at latexref.xyz, while TikZ commands used inside LaTeX snippets (for example \draw) are linked to tikz.dev.
Common shell keywords and builtins (for example if, setopt, Get-ChildItem), linked to GNU Bash, Zsh, or PowerShell documentation.
Common WebAssembly instructions and declarations (for example module, func, local.get, i32.add), linked to the WebAssembly Core Spec site by default.
2 Reference
This section documents each form and procedure in detail.
2.1 Inline Forms
2.1.1 Web Languages
syntax
(css-code maybe-option ... str-expr ...+)
maybe-option =
| #:color-swatch? color-swatch?-expr | #:font-preview? font-preview?-expr | #:dimension-preview? dimension-preview?-expr | #:mdn-links? mdn-links?-expr | #:preview-mode preview-mode-expr | #:preview-tooltips? preview-tooltips?-expr | #:preview-css-url preview-css-url-expr | #:escape escape-id
#:color-swatch? controls whether detected CSS color literals are followed by a small color swatch (default: #t). Gradient literals (for example linear-gradient (...)) are shown as a small bar swatch.
#:font-preview? controls whether font-family declarations are followed by a small Aa preview in the selected font (default: #t).
#:dimension-preview? controls whether spacing and radius declarations such as margin, padding, gap, and border-radius get tiny inline visualizers (default: #t).
#:mdn-links? controls whether common CSS tokens are wrapped as hyperlinks to MDN documentation (default: #t).
#:preview-mode controls when previews are shown: 'always, 'hover, or 'none (default: 'always).
#:preview-tooltips? controls whether preview decorations expose tooltips (hover/focus) and related runtime tooltip behavior (default: #t).
#:preview-css-url optionally points to an external stylesheet for preview UI classes. When provided, the runtime loads that stylesheet instead of injecting inline preview CSS.
An optional #:escape identifier configures escapes of the form (escape-id expr) to splice expr-produced elements into the typeset output.
Example: h1 { color: #c33; }
syntax
(html-code maybe-escape str-expr ...+)
maybe-escape =
| #:mdn-links? mdn-links?-expr | #:escape escape-id
An optional #:escape identifier configures escapes of the form (escape-id expr) to splice expr-produced elements into the typeset output.
#:mdn-links? controls whether common HTML tokens are wrapped as hyperlinks to MDN documentation, including CSS and JavaScript tokens that appear inside <style> and <script> sections (default: #t).
Example: <em class="note">Hi</em>
syntax
(js-code maybe-escape str-expr ...+)
maybe-escape =
| #:jsx? jsx?-expr | #:mdn-links? mdn-links?-expr | #:escape escape-id
#:jsx? enables JSX-aware tokenization for snippets that contain embedded tags (default: #f).
#:mdn-links? controls whether common JavaScript tokens are wrapped as hyperlinks to MDN documentation (default: #t).
An optional #:escape identifier configures escapes of the form (escape-id expr) to splice expr-produced elements into the typeset output.
Example: const n = 42;
2.1.2 Programming Languages
syntax
(c-code maybe-escape str-expr ...+)
maybe-escape =
| #:escape escape-id
Common C keywords and standard library identifiers are linked to cppreference. The bundled identifier map was generated in 2026.
Example: int answer = 42;
syntax
(cpp-code maybe-escape str-expr ...+)
maybe-escape =
| #:escape escape-id
Common C++ keywords and standard library identifiers are linked to cppreference. The bundled identifier map was generated in 2026.
Example: std::vector<int> xs = {1, 2, 3};
syntax
(objc-code maybe-escape str-expr ...+)
maybe-escape =
| #:escape escape-id
Example: Hello
syntax
(haskell-code maybe-escape str-expr ...+)
maybe-escape =
| #:escape escape-id
Example: sumSquares xs = sum (map (^ (2 :: Int)) xs)
syntax
(java-code maybe-escape str-expr ...+)
maybe-escape =
| #:escape escape-id
Common Java language keywords and selected standard-library identifiers are linked to the official Oracle Java Language Specification and Java SE API documentation.
Example: class Example { void run() { System.out.println("hi"); } }
syntax
(pascal-code maybe-escape str-expr ...+)
maybe-escape =
| #:escape escape-id
Pascal snippets link language-reference entries and bundled Free Pascal API identifiers from the official Free Pascal documentation.
Example: function Add(x, y: Integer): Integer; begin Add := x + y; end;
syntax
(python-code maybe-escape str-expr ...+)
maybe-escape =
| #:escape escape-id
An optional #:escape identifier configures escapes of the form (escape-id expr) to splice expr-produced elements into the typeset output.
Example: def answer(): return 42
syntax
(racket-code maybe-escape str-expr ...+)
maybe-escape =
| #:escape escape-id
Example: (define (add x y) (+ x y))
syntax
(rhombus-code maybe-escape str-expr ...+)
maybe-escape =
| #:escape escape-id
Example: fun add(x, y): x + y
syntax
(swift-code maybe-escape str-expr ...+)
maybe-escape =
| #:escape escape-id
Example: let answer = 42
syntax
(rust-code maybe-escape str-expr ...+)
maybe-escape =
| #:escape escape-id
Common Rust keywords, standard library types and traits, and common macros such as vec! and println! are linked to the official Rust documentation site at doc.rust-lang.org.
Example: let xs: Vec<i32> = vec![1, 2, 3];
syntax
(wasm-code maybe-escape str-expr ...+)
maybe-escape =
| #:docs-source docs-source-expr | #:escape escape-id
#:docs-source selects where WebAssembly documentation links point: 'wasm-spec-3.0, 'mdn, or 'none. The default comes from current-wasm-docs-source, which defaults to 'wasm-spec-3.0.
An optional #:escape identifier configures escapes of the form (escape-id expr) to splice expr-produced elements into the typeset output.
2.1.3 Document Languages
syntax
(latex-code maybe-escape str-expr ...+)
maybe-escape =
| #:escape escape-id
Example: \section{Intro}
syntax
(markdown-code maybe-escape str-expr ...+)
maybe-escape =
| #:escape escape-id
Example: # Hello
syntax
(scribble-code maybe-options str-expr ...+)
maybe-options =
| #:context context-expr | #:escape escape-id
#:context supplies syntax context for identifier link resolution (default: (current-scribble-context)). Recommended: use #'here when you want identifiers in a snippet to resolve against the current manual’s for-label imports.
An optional #:escape identifier configures escapes of the form (escape-id expr) to splice expr-produced elements into the typeset output.
Example: @bold{Hi} there.
syntax
(tex-code maybe-escape str-expr ...+)
maybe-escape =
| #:escape escape-id
Example: \hbox{Hello}
2.1.4 Tooling and Config
syntax
(makefile-code maybe-escape str-expr ...+)
maybe-escape =
| #:escape escape-id
Example: all: build test
syntax
(json-code maybe-escape str-expr ...+)
maybe-escape =
| #:escape escape-id
Example: {"name": "Ada"}
syntax
(plist-code maybe-escape str-expr ...+)
maybe-escape =
| #:escape escape-id
Example: <plist/>
syntax
(shell-code maybe-options str-expr ...+)
maybe-options =
| #:shell shell-expr | #:docs-source docs-source-expr | #:escape escape-id
#:shell selects shell flavor: 'bash, 'zsh, 'powershell, or 'pwsh. Default: (current-scribble-shell).
#:docs-source selects where shell documentation links point: 'auto, 'bash, 'zsh, 'powershell, 'posix, or 'none. Default: (current-shell-docs-source). When the effective value is 'auto, links follow the effective shell: 'bash when #:shell (or current-scribble-shell) is 'bash, 'zsh when it is 'zsh, and 'powershell when it is 'powershell or 'pwsh.
An optional #:escape identifier configures escapes of the form (escape-id expr) to splice expr-produced elements into the typeset output.
Example: if [ -f ~/.zshrc ]; then echo ok; fi
syntax
(tsv-code maybe-escape str-expr ...+)
maybe-escape =
| #:escape escape-id
Example: name age
syntax
(yaml-code maybe-escape str-expr ...+)
maybe-escape =
| #:escape escape-id
Example: name: Ada
2.1.5 Data Formats
syntax
(csv-code maybe-escape str-expr ...+)
maybe-escape =
| #:escape escape-id
Example: name,age
syntax
(go-code maybe-escape str-expr ...+)
maybe-escape =
| #:escape escape-id
Common Go language keywords, predeclared identifiers, and selected standard-library identifiers are linked to the official Go spec and package documentation.
2.2 Block Forms
2.2.1 Web Languages
syntax
(cssblock option ... str-expr ...+)
option = #:indent indent-expr | #:line-numbers line-number-expr | #:line-number-sep line-number-sep-expr | #:copy-button? copy-button?-expr | #:color-swatch? color-swatch?-expr | #:font-preview? font-preview?-expr | #:dimension-preview? dimension-preview?-expr | #:mdn-links? mdn-links?-expr | #:preview-mode preview-mode-expr | #:preview-tooltips? preview-tooltips?-expr | #:preview-css-url preview-css-url-expr | #:file filename-expr | #:escape escape-id
indent-expr : exact-nonnegative-integer?
line-number-expr : (or/c #f exact-nonnegative-integer?)
line-number-sep-expr : exact-nonnegative-integer?
#:indent controls left indentation in spaces (default: 0).
#:line-numbers enables line numbers when not #f, using the given start number (default: #f).
#:line-number-sep controls the spacing between the line number and code (default: 1).
#:copy-button? controls whether a copy icon appears on hover/focus to copy the block text to the clipboard (default: #t).
#:color-swatch? controls whether detected CSS color literals are followed by a small swatch; gradient literals are shown as a small bar (default: #t).
#:font-preview? controls whether font-family declarations are followed by a small Aa preview (default: #t).
#:dimension-preview? controls whether spacing and radius declarations (for example margin, padding, gap, letter-spacing, text-indent, filter: blur (...), and border-radius) are followed by small visualizer decorations (default: #t).
#:mdn-links? controls whether common CSS tokens are wrapped as hyperlinks to MDN documentation (default: #t).
#:preview-mode controls when previews are shown: 'always, 'hover, or 'none (default: 'always).
#:preview-tooltips? controls whether preview decorations include tooltip text and interactive hover/focus tooltip UI (default: #t).
#:preview-css-url optionally points to an external stylesheet URL/path for preview classes; when set, runtime links that stylesheet instead of injecting inline preview CSS (default: #f).
#:file wraps the result in filebox with filename-expr as label (default: #f, i.e. no file label).
#:escape changes the escape identifier; subforms of the shape (escape-id expr) splice expr as content (default escape id: unsyntax).
Example:
1 .card { 2 color: #c33; 3 }
syntax
(cssblock0 option ... str-expr ...+)
Example:
.compact { color: #444; }
syntax
(htmlblock option ... str-expr ...+)
option = #:indent indent-expr | #:line-numbers line-number-expr | #:line-number-sep line-number-sep-expr | #:copy-button? copy-button?-expr | #:mdn-links? mdn-links?-expr | #:file filename-expr | #:escape escape-id
indent-expr : exact-nonnegative-integer?
line-number-expr : (or/c #f exact-nonnegative-integer?)
line-number-sep-expr : exact-nonnegative-integer?
#:indent controls left indentation in spaces (default: 0).
#:line-numbers enables line numbers when not #f, using the given start number (default: #f).
#:line-number-sep controls the spacing between the line number and code (default: 1).
#:copy-button? controls whether a copy icon appears on hover/focus to copy the block text to the clipboard (default: #t).
#:mdn-links? controls whether common HTML tokens are wrapped as hyperlinks to MDN documentation, including CSS and JavaScript tokens that appear inside <style> and <script> sections (default: #t).
#:file wraps the result in filebox with filename-expr as label (default: #f, i.e. no file label).
#:escape changes the escape identifier; subforms of the shape (escape-id expr) splice expr as content (default escape id: unsyntax).
Example:
syntax
(htmlblock0 option ... str-expr ...+)
Example:
syntax
(jsblock option ... str-expr ...+)
option = #:indent indent-expr | #:line-numbers line-number-expr | #:line-number-sep line-number-sep-expr | #:copy-button? copy-button?-expr | #:jsx? jsx?-expr | #:mdn-links? mdn-links?-expr | #:file filename-expr | #:escape escape-id
indent-expr : exact-nonnegative-integer?
line-number-expr : (or/c #f exact-nonnegative-integer?)
line-number-sep-expr : exact-nonnegative-integer?
#:indent controls left indentation in spaces (default: 0).
#:line-numbers enables line numbers when not #f, using the given start number (default: #f).
#:line-number-sep controls the spacing between the line number and code (default: 1).
#:copy-button? controls whether a copy icon appears on hover/focus to copy the block text to the clipboard (default: #t).
#:jsx? enables JSX-aware tokenization for snippets containing embedded tags (default: #f).
#:mdn-links? controls whether common JavaScript tokens are wrapped as hyperlinks to MDN documentation (default: #t).
#:file wraps the result in filebox with filename-expr as label (default: #f, i.e. no file label).
#:escape changes the escape identifier; subforms of the shape (escape-id expr) splice expr as content (default escape id: unsyntax).
Example:
syntax
(jsblock0 option ... str-expr ...+)
Example:
2.2.2 Programming Languages
syntax
(cblock option ... str-expr ...+)
Example:
"demo.c"
int main(void) { return 0; }
syntax
(cblock0 option ... str-expr ...+)
syntax
(cppblock option ... str-expr ...+)
syntax
(cppblock0 option ... str-expr ...+)
syntax
(goblock option ... str-expr ...+)
syntax
(goblock0 option ... str-expr ...+)
syntax
(javablock option ... str-expr ...+)
syntax
(javablock0 option ... str-expr ...+)
syntax
(objcblock option ... str-expr ...+)
syntax
(objcblock0 option ... str-expr ...+)
syntax
(haskellblock option ... str-expr ...+)
syntax
(haskellblock0 option ... str-expr ...+)
syntax
(pascalblock option ... str-expr ...+)
syntax
(pascalblock0 option ... str-expr ...+)
syntax
(pythonblock option ... str-expr ...+)
option = #:indent indent-expr | #:line-numbers line-number-expr | #:line-number-sep line-number-sep-expr | #:copy-button? copy-button?-expr | #:file filename-expr | #:escape escape-id
indent-expr : exact-nonnegative-integer?
line-number-expr : (or/c #f exact-nonnegative-integer?)
line-number-sep-expr : exact-nonnegative-integer?
#:indent controls left indentation in spaces (default: 0).
#:line-numbers enables line numbers when not #f, using the given start number (default: #f).
#:line-number-sep controls the spacing between the line number and code (default: 1).
#:copy-button? controls whether a copy icon appears on hover/focus to copy the block text to the clipboard (default: #t).
#:file wraps the result in filebox with filename-expr as label (default: #f, i.e. no file label).
#:escape changes the escape identifier; subforms of the shape (escape-id expr) splice expr as content (default escape id: unsyntax).
Example:
1 def double(n): 2 return n * 2
syntax
(pythonblock0 option ... str-expr ...+)
Example:
def greet(name): return f"Hello, {name}"
syntax
(racketblock option ... str-expr ...+)
syntax
(racketblock0 option ... str-expr ...+)
syntax
(rhombusblock option ... str-expr ...+)
syntax
(rhombusblock0 option ... str-expr ...+)
syntax
(swiftblock option ... str-expr ...+)
syntax
(swiftblock0 option ... str-expr ...+)
syntax
(rustblock option ... str-expr ...+)
syntax
(rustblock0 option ... str-expr ...+)
syntax
(wasmblock option ... str-expr ...+)
option = #:indent indent-expr | #:line-numbers line-number-expr | #:line-number-sep line-number-sep-expr | #:copy-button? copy-button?-expr | #:docs-source docs-source-expr | #:file filename-expr | #:escape escape-id
indent-expr : exact-nonnegative-integer?
line-number-expr : (or/c #f exact-nonnegative-integer?)
line-number-sep-expr : exact-nonnegative-integer?
#:indent controls left indentation in spaces (default: 0).
#:line-numbers enables line numbers when not #f, using the given start number (default: #f).
#:line-number-sep controls the spacing between the line number and code (default: 1).
#:copy-button? controls whether a copy icon appears on hover/focus to copy the block text to the clipboard (default: #t).
#:docs-source selects WebAssembly link targets: 'wasm-spec-3.0, 'mdn, or 'none. Default: (current-wasm-docs-source).
#:file wraps the result in filebox with filename-expr as label (default: #f, i.e. no file label).
#:escape changes the escape identifier; subforms of the shape (escape-id expr) splice expr as content (default escape id: unsyntax).
Example:
syntax
(wasmblock0 option ... str-expr ...+)
Example:
2.2.3 Document Languages
syntax
(latexblock option ... str-expr ...+)
syntax
(latexblock0 option ... str-expr ...+)
syntax
(markdownblock option ... str-expr ...+)
syntax
(markdownblock0 option ... str-expr ...+)
syntax
(texblock option ... str-expr ...+)
syntax
(texblock0 option ... str-expr ...+)
2.2.4 Tooling and Config
syntax
(makefileblock option ... str-expr ...+)
syntax
(makefileblock0 option ... str-expr ...+)
syntax
(jsonblock option ... str-expr ...+)
Example:
1 { 2 "name": "Ada", 3 "active": true 4 }
syntax
(jsonblock0 option ... str-expr ...+)
syntax
(plistblock option ... str-expr ...+)
syntax
(plistblock0 option ... str-expr ...+)
syntax
(shellblock option ... str-expr ...+)
option = #:shell shell-expr | #:docs-source docs-source-expr | #:indent indent-expr | #:line-numbers line-number-expr | #:line-number-sep line-number-sep-expr | #:copy-button? copy-button?-expr | #:file filename-expr | #:escape escape-id
indent-expr : exact-nonnegative-integer?
line-number-expr : (or/c #f exact-nonnegative-integer?)
line-number-sep-expr : exact-nonnegative-integer?
#:shell selects shell flavor: 'bash, 'zsh, 'powershell, or 'pwsh. Default: (current-scribble-shell).
#:docs-source selects link targets: 'auto, 'bash, 'zsh, 'powershell, 'posix, or 'none. Default: (current-shell-docs-source). With 'auto, links follow the effective shell selected by #:shell (or current-scribble-shell).
#:indent controls left indentation in spaces (default: 0).
#:line-numbers enables line numbers when not #f, using the given start number (default: #f).
#:line-number-sep controls the spacing between the line number and code (default: 1).
#:copy-button? controls whether a copy icon appears on hover/focus to copy the block text to the clipboard (default: #t).
#:file wraps the result in filebox with filename-expr as label (default: #f, i.e. no file label).
#:escape changes the escape identifier; subforms of the shape (escape-id expr) splice expr as content (default escape id: unsyntax).
Example:
syntax
(shellblock0 option ... str-expr ...+)
Example:
syntax
(yamlblock option ... str-expr ...+)
syntax
(yamlblock0 option ... str-expr ...+)
Example:
name: Ada active: true
2.2.5 Data Formats
syntax
(csvblock option ... str-expr ...+)
syntax
(csvblock0 option ... str-expr ...+)
syntax
(tsvblock option ... str-expr ...+)
syntax
(tsvblock0 option ... str-expr ...+)
parameter
(current-wasm-docs-source) → (or/c 'wasm-spec-3.0 'mdn 'none)
(current-wasm-docs-source src) → void? src : (or/c 'wasm-spec-3.0 'mdn 'none)
parameter
(current-scribble-shell) → (or/c 'bash 'zsh 'powershell 'pwsh)
(current-scribble-shell sh) → void? sh : (or/c 'bash 'zsh 'powershell 'pwsh)
parameter
→ (or/c 'auto 'bash 'zsh 'powershell 'pwsh 'posix 'none) (current-shell-docs-source src) → void? src : (or/c 'auto 'bash 'zsh 'powershell 'pwsh 'posix 'none)
parameter
(current-scribble-context) → (or/c #f syntax?)
(current-scribble-context ctx) → void? ctx : (or/c #f syntax?)
syntax
(scribbleblock option ... str-expr ...+)
option = #:indent indent-expr | #:line-numbers line-number-expr | #:line-number-sep line-number-sep-expr | #:lang lang-expr | #:context context-expr | #:copy-button? copy-button?-expr | #:file filename-expr | #:escape escape-id
indent-expr : exact-nonnegative-integer?
line-number-expr : (or/c #f exact-nonnegative-integer?)
line-number-sep-expr : exact-nonnegative-integer?
lang-expr : string?
context-expr : (or/c #f syntax?)
The most important option is #:context. If provided identifiers will be linked to their documentation entries. If you are using the same context several times, it can be convenient to set the parameter current-scribble-context instead of using #:context repeatedly.
Options:
#:indent controls left indentation in spaces (default: 0).
#:line-numbers enables line numbers when not #f, using the given start number (default: #f).
#:line-number-sep controls the spacing between the line number and code (default: 1).
#:lang chooses the language line used for parsing/linking when the snippet itself does not start with #lang (default: "scribble/manual").
#:context supplies syntax context for identifier link resolution (default: (current-scribble-context)). Recommended: use #'here when you want identifiers in a snippet to resolve against the current manual’s for-label imports.
#:copy-button? controls whether a copy icon appears on hover/focus to copy the block text to the clipboard (default: #t).
#:file wraps the result in filebox with filename-expr as label (default: #f, i.e. no file label).
#:escape changes the escape identifier; subforms of the shape (escape-id expr) splice expr as content (default escape id: unsyntax).
Example:
syntax
(scribbleblock0 option ... str-expr ...+)
Example:
2.3 Preview Legend
Rendered legend example:
.legend { color: #c33; background: linear-gradient(90deg, red, blue); margin: 4px; margin: 12px; margin: 28px; filter: blur(2px); filter: blur(8px); filter: blur(18px); border-radius: 2px; border-radius: 6px; border-radius: 9px; font-family: "Fira Code", monospace;Aa font-family: "Georgia", serif;Aa font-family: "Helvetica Neue", Arial, sans-serif;Aa }
Color square: a detected color literal such as #c33 or red.
Gradient bar: a detected gradient literal such as linear-gradient (...).
Spacing bar: detected spacing-sized values (for example margin, gap, letter-spacing, or filter: blur (...)) scaled to a compact width.
Radius chip: detected border-radius values, where the chip corner radius mirrors the declaration.
Font Aa: preview of font-family, including fallback resolution tooltip and missing-font warning.
2.4 MDN Maps
MDN maps control which CSS/HTML/JavaScript/WebAssembly identifiers become links to the MDN documentation site. The procedures below let you inspect the active map, install overrides, reset to defaults, and export the bundled entries. Most users will not need these tools, but they are useful when you want to add links that are not covered by the default maps.
procedure
(mdn-map-path) → path?
procedure
(mdn-entry? v) → boolean?
v : any/c
procedure
(mdn-install-map! entries-or-path) → path?
entries-or-path :
(or/c path-string? (listof (list/c symbol? symbol? string? string?)))
procedure
procedure
(mdn-export-default-map! dest) → path-string?
dest : path-string?
Command-line helper:
racket -l scribble-tools/mdn-map-tool -- --path |
racket -l scribble-tools/mdn-map-tool -- --export-default mdn-map.rktd |
racket -l scribble-tools/mdn-map-tool -- --build-default mdn-map-built.rktd |
racket -l scribble-tools/mdn-map-tool -- --install mdn-map.rktd |
racket -l scribble-tools/mdn-map-tool -- --update-from mdn-map-custom.rktd |
racket -l scribble-tools/mdn-map-tool -- --reset |
Map build pipeline (dedupe + optional merge):
racket -l scribble-tools/mdn-map-build -- --stats |
racket -l scribble-tools/mdn-map-build -- --out mdn-map-built.rktd |
racket -l scribble-tools/mdn-map-build -- --merge mdn-map-custom.rktd --out mdn-map-merged.rktd |
racket -l scribble-tools/mdn-map-build -- --merge mdn-map-custom.rktd --install |
3 Extended Examples
This chapter provides longer rendered examples for each supported language. Each block uses line numbers and a file label to make lexer behavior and documentation links easier to inspect.
3.1 Web Languages
3.1.1 CSS
"extended/styles.css"
1 :root { 2 --brand: #0b62a3; 3 --accent: oklch(66% 0.18 28); 4 } 5 6 .layout { 7 display: grid; 8 grid-template-columns: 240px 1fr; 9 gap: clamp(0.75rem, 2vw, 1.5rem); 10 margin: 16px; 11 border-radius: 9px; 12 background: linear-gradient(90deg, #f6f8fb, #eef3ff); 13 } 14 15 .button { 16 color: white; 17 background: color-mix(in srgb, var--brand(--brand) 80%, black); 18 border: 1px solid #0a4f83; 19 padding: 0.5rem 0.8rem; 20 font-family: "Fira Code", "JetBrains Mono", monospace;Aa 21 }
3.1.2 HTML
"extended/index.html"
1 <!doctype html> 2 <html lang="en"> 3 <head> 4 <meta charset="utf-8"> 5 <title>Extended Example</title> 6 <style> 7 .hero { color: #c33; margin: 12px; } 8 .hero em { font-family: "Georgia", serif;Aa } 9 </style> 10 </head> 11 <body> 12 <main id="app"> 13 <h1 class="hero">Hello <em>world</em></h1> 14 <button type="button" data-role="save">Save</button> 15 </main> 16 <script> 17 const root = document.querySelector("#app"); 18 if (root) root.setAttribute("data-ready", "yes"); 19 </script> 20 </body> 21 </html>
3.1.3 JavaScript
"extended/app.js"
1 function quickSort(xs, cmp = (a, b) => a - b) { 2 if (xs.length <= 1) return xs.slice(); 3 const [pivot, ...rest] = xs; 4 const left = []; 5 const right = []; 6 for (const x of rest) { 7 if (cmp(x, pivot) < 0) left.push(x); else right.push(x); 8 } 9 return [...quickSort(left, cmp), pivot, ...quickSort(right, cmp)]; 10 } 11 12 function renderNumbers(listEl, numbers) { 13 listEl.textContent = ""; 14 for (const n of numbers) { 15 const li = document.createElement("li"); 16 li.textContent = String(n); 17 listEl.append(li); 18 } 19 } 20 21 function parseInput(inputEl) { 22 return inputEl.value 23 .split(/[\\s,]+/) 24 .map((s) => s.trim()) 25 .filter(Boolean) 26 .map(Number) 27 .filter((n) => Number.isFinite(n)); 28 } 29 30 function boot() { 31 const inputEl = document.querySelector("#numbers"); 32 const buttonEl = document.querySelector("#sort"); 33 const listEl = document.querySelector("#result"); 34 if (!inputEl || !buttonEl || !listEl) return; 35 36 buttonEl.addEventListener("click", () => { 37 const data = parseInput(inputEl); 38 const sorted = quickSort(data); 39 renderNumbers(listEl, sorted); 40 }); 41 } 42 43 boot();
3.2 Programming Languages
3.2.1 C
"extended/cache.c"
1 typedef struct { 2 const char *key; 3 int value; 4 } entry_t; 5 6 static int lookup(const entry_t *entries, int count, const char *key) { 7 for (int i = 0; i < count; ++i) { 8 if (strcmp(entries[i].key, key) == 0) { 9 return entries[i].value; 10 } 11 } 12 return -1; 13 }
3.2.2 C++
"extended/cache.cpp"
1 #include <algorithm> 2 #include <string> 3 #include <vector> 4 5 struct Entry { 6 std::string title; 7 int score; 8 }; 9 10 std::vector<std::string> top_titles(std::vector<Entry> entries) { 11 std::sort(entries.begin(), entries.end(), 12 [](const Entry &a, const Entry &b) { return a.score > b.score; }); 13 std::vector<std::string> out; 14 for (const auto &entry : entries) out.push_back(entry.title); 15 return out; 16 }
3.2.3 Objective-C
"extended/view.m"
1 #import <Foundation/Foundation.h> 2 3 @interface Greeter : NSObject 4 - (NSString *)messageFor:(NSString *)name; 5 @end 6 7 @implementation Greeter 8 - (NSString *)messageFor:(NSString *)name { 9 return [NSString stringWithFormat:@"Hello, %@", name]; 10 } 11 @end
3.2.4 Haskell
"extended/Stats.hs"
1 module Stats where 2 3 sumSquares :: [Int] -> Int 4 sumSquares xs = sum (map square xs) 5 where 6 square n = n * n 7 8 describe :: [Int] -> String 9 describe xs = 10 "count=" ++ show (length xs) ++ ", total=" ++ show (sum xs)
3.2.5 Java
"extended/QuickSort.java"
1 class QuickSort { 2 static void quickSort(int[] xs, int lo, int hi) { 3 if (lo >= hi) { 4 return; 5 } 6 7 int pivot = xs[(lo + hi) / 2]; 8 int i = lo; 9 int j = hi; 10 11 while (i <= j) { 12 while (xs[i] < pivot) { 13 i++; 14 } 15 while (xs[j] > pivot) { 16 j--; 17 } 18 if (i <= j) { 19 int tmp = xs[i]; 20 xs[i] = xs[j]; 21 xs[j] = tmp; 22 i++; 23 j--; 24 } 25 } 26 27 quickSort(xs, lo, j); 28 quickSort(xs, i, hi); 29 } 30 }
3.2.6 Pascal
"extended/helpers.pas"
1 function Factorial(n: Integer): Integer; 2 begin 3 if n <= 1 then 4 Factorial := 1 5 else 6 Factorial := n * Factorial(n - 1); 7 end;
3.2.7 Python
"extended/report.py"
1 from dataclasses import dataclass 2 3 4 @dataclass 5 class Entry: 6 title: str 7 score: int 8 9 10 def top_entries(rows, limit=3): 11 ranked = sorted(rows, key=lambda row: row.score, reverse=True) 12 return [entry.title for entry in ranked[:limit] if entry.score >= 0] 13 14 15 def format_report(rows): 16 titles = top_entries(rows) 17 if not titles: 18 return "no entries" 19 return ", ".join(titles)
3.2.8 Racket
"extended/helpers.rkt"
1 (define (group-by-length words) 2 (for/fold ([ht (hash)]) 3 ([word (in-list words)]) 4 (define len (string-length word)) 5 (hash-update ht len (lambda (xs) (cons word xs)) '()))) 6 7 (group-by-length '("css" "html" "scribble"))
3.2.9 Rhombus
"extended/helpers.rhm"
1 fun summarize(name, count): 2 if count == 1: 3 "$name has 1 item" 4 else: 5 "$name has $(count) items"
3.2.10 Swift
"extended/helpers.swift"
1 struct Entry { 2 let title: String 3 let score: Int 4 } 5 6 func topTitles(_ entries: [Entry], limit: Int = 3) -> [String] { 7 entries 8 .sorted { $0.score > $1.score } 9 .prefix(limit) 10 .map(\.title) 11 }
3.2.11 Rust
"extended/helpers.rs"
1 use std::collections::HashMap; 2 3 fn histogram(words: &[&str]) -> HashMap<String, usize> { 4 let mut counts = HashMap::new(); 5 for word in words { 6 *counts.entry((*word).to_string()).or_insert(0) += 1; 7 } 8 counts 9 }
3.2.12 WebAssembly
"extended/module.wat"
1 (module 2 (memory (export "mem") 1) 3 (func $sum_to_acc (param $i i32) (param $n i32) (param $acc i32) (result i32) 4 (if (result i32) (i32.le_s (local.get $i) (local.get $n)) 5 (then 6 (call $sum_to_acc 7 (i32.add (local.get $i) (i32.const 1)) 8 (local.get $n) 9 (i32.add (local.get $acc) (local.get $i)))) 10 (else 11 (local.get $acc)))) 12 (func (export "sum_to") (param $n i32) (result i32) 13 (call $sum_to_acc (i32.const 0) (local.get $n) (i32.const 0))))
3.3 Document Languages
3.3.1 LaTeX
"extended/doc.tex"
1 \section{Overview} 2 \[ 3 f(x) = x^2 + 2x + 1 4 \] 5 6 \usepackage{tikz} 7 8 \begin{tikzpicture} 9 \draw (0,0) -- (2,1); 10 \node[right] at (2,1) {Endpoint}; 11 \end{tikzpicture}
3.3.2 Markdown
"extended/notes.md"
1 # Release Notes 2 3 ## Highlights 4 5 - Added Python support 6 - Migrated lexers to the `lexers` package 7 - Expanded rendered examples 8 9 ```bash 10 raco test private/lang-code.rkt 11 ``` 12 13 ```racket 14 (define (build-docs) 15 (displayln "scribblings/scribble-tools.scrbl")) 16 ```
3.3.3 Scribble
"extended/guide.scrbl"
1 @title{Extended Scribble Example} 2 @section{Overview} 3 This paragraph includes @bold{inline formatting}, 4 @italic{emphasis}, and @racket[code] references. 5 @itemlist[ 6 @item{First point} 7 @item{Second point} 8 @item{Third point} 9 ] 10 @subsection{Details} 11 See @secref["reference-inline-forms"] for inline forms. 12
3.3.4 TeX
"extended/doc.tex"
1 \def\foo#1{$$#1^2$$ \verb|x+y|} 2 \hbox{Hello} 3 \vskip 1em 4 \centerline{\foo{n}}
3.4 Tooling and Config
3.4.1 Makefile
"extended/Makefile"
1 APP = scribble-tools 2 3 .PHONY: docs test 4 5 all: docs test | html 6 7 docs: 8 raco scribble +m --html --dest html scribblings/scribble-tools.scrbl && printf '%s\n' done 9 10 test: 11 raco test private/lang-code.rkt 12 13 build: 14 ${CC} -o $@ $<
3.4.2 JSON
"extended/config.json"
1 { 2 "name": "scribble-tools", 3 "features": { 4 "copyButton": true, 5 "lineNumbers": true, 6 "links": ["mdn", "shell-docs", "wasm-spec"] 7 }, 8 "targets": ["html", "manual"] 9 }
3.4.3 plist
"extended/Info.plist"
1 <?xml version="1.0" encoding="UTF-8"?> 2 <plist version="1.0"> 3 <dict> 4 <key>CFBundleName</key> 5 <string>scribble-tools</string> 6 <key>CFBundleVersion</key> 7 <string>1.0</string> 8 </dict> 9 </plist>
3.4.4 Shell
This utility copies one directory tree to another and validates arguments before running the copy operation.
"extended/copy-tree.sh"
1 #!/usr/bin/env bash 2 set -euo pipefail 3 4 usage() { 5 echo "usage: $0 <source-dir> [dest-dir]" 6 } 7 8 copy_tree() { 9 local src="$1" 10 local dst="$2" 11 mkdir -p "$dst" 12 cp -R "$src"/. "$dst"/ 13 } 14 15 main() { 16 if [ "$#" -lt 1 ] || [ "$#" -gt 2 ]; then 17 usage 18 return 2 19 fi 20 local src="$1" 21 local dst="${2:-./out}" 22 if [ ! -d "$src" ]; then 23 echo "error: source directory not found: $src" >&2 24 return 1 25 fi 26 copy_tree "$src" "$dst" 27 echo "copied $src -> $dst" 28 } 29 30 main "$@"
3.4.5 YAML
"extended/config.yaml"
1 name: scribble-tools 2 features: 3 copy_button: true 4 line_numbers: true 5 docs_links: 6 - mdn 7 - shell-docs 8 - wasm-spec
3.5 Data Formats
3.5.1 CSV and TSV
"extended/people.csv"
1 name,role,active 2 Ada,author,true 3 Grace,editor,false 4 Linus,reviewer,true
"extended/people.tsv"
1 name role active 2 Ada author true 3 Grace editor false 4 Linus reviewer true
3.5.2 Go
"extended/quicksort.go"
1 package main 2 3 func quickSort(xs []int) []int { 4 if len(xs) < 2 { 5 return xs 6 } 7 8 pivot := xs[0] 9 var left, right []int 10 for _, x := range xs[1:] { 11 if x < pivot { 12 left = append(left, x) 13 } else { 14 right = append(right, x) 15 } 16 } 17 18 left = quickSort(left) 19 right = quickSort(right) 20 return append(append(left, pivot), right...) 21 }