Changes since v0.1.0
This book is a record of how mdbook-listings reached v0.1.0. The crate
kept moving after the book closed, so this page lists the changes that
postdate the prose. The chapters themselves are left as the v0.1.0 record
and do not describe what follows.
Unreleased — e2e suite back on released playwright-rs
The v0.1.1 entry below
records the e2e suite moving onto playwright-rust main to dogfood
unreleased changes there. That arrangement is over: the suite and the
screenshot tool now build against the released playwright-rs on
crates.io. A branch dependency re-resolves on every upstream commit, so
each commit to the fork opened dependency-update PRs here (two at a
time, the trace crate moving in lockstep) for changes no test in this
repo exercised. Releases still dogfood the fork — we cut them — and CI
now derives its browser install from the crate itself rather than a
separately pinned Playwright version, so a version bump moves the crate,
its driver, and the browsers together.
Unreleased — two new verify warnings for callout slips
A {{#callout}} directive that names no marker fails the build
(chapter 7 covers why). The opposite slip built
clean: add a CALLOUT: marker to a source file, freeze it, and nothing
reminds you that no prose ever picks the label up. The badge renders, the
hover text reads fine, and the page looks finished. A downstream author
hit it the ordinary way (marker added while editing the source, prose
deferred to a later chapter) and had to check by experiment whether
adding the marker early was safe.
verify now reports each such marker as a warning naming the frozen file
and line. Only markers that actually render count. This book keeps every
old version of its listings as diff history, and a marker in a version no
chapter shows, or outside every include’s slice, or on an unchanged line
of a diff, produces no badge and stays silent. The first draft of the
check skipped that rule, warned on every marker in every frozen file, and
buried the signal in old versions; with it, the 21 warnings this book
reports (as of this writing) are badges rendered somewhere with no prose
pointing at them. Warnings leave the exit code at 0, so a book that wants annotation
without prose still builds.
A related slip involves slices rather than missing prose. A marker
annotates the line that follows it, so a sliced include whose range ends
on a marker line renders the badge while excluding the one line it
points at. Slice bounds are line numbers, and a listing’s line numbers
shift every refreeze; a range that ended cleanly before a marker one week
ends on top of it the next, and the built page gives no sign. The same
downstream author hit this one too, with a marker that was picked up in
prose (in another chapter), so the orphan warning above had nothing to
say about it. verify now warns on any sliced include whose end line is
a marker, naming the chapter and line of the directive, the range, and
the annotated line the slice excludes.
v0.2.0 — one authoring idiom for both directives
Every chapter in this book wraps its includes in a ```rust block,
because until now the build failed without one. {{#diff}} never had
that requirement, and nothing in the syntax said which directive wanted
the wrapper. A downstream author hit the asymmetry while writing a
chapter against the crate and reported it.
{{#include}} no longer needs a surrounding fence. An include on a
line of its own now renders the whole block, the way a diff always has.
The highlight language comes from the file extension, or from a new
lang="..." argument when the extension doesn’t name it. The one case
that still fails is a directive sharing its line with prose: a code block
has to start a line, so see {{#include listings/foo.rs}} above has no
rendering.
Both forms produce byte-identical output, so the fenced includes
throughout these chapters render exactly as they always did. This page is
the only place in the book that uses the new form. What follows is a bare
{{#include snippets/render-block-snippet-v1.rs}} with no fence around
it, showing the code that does the work:
#![allow(unused)]
fn main() {
/// The fence to wrap `body` in so the body cannot close it: one longer
/// than the longest fence-shaped run already in the body, and never
/// shorter than CommonMark's minimum of 3.
pub(crate) fn fence_for_body(body: &str, char: u8) -> Fence {
let longest_run = body
.lines()
.map(|line| {
let trimmed = line.trim_start();
if line.len() - trimmed.len() > 3 {
return 0;
}
trimmed.bytes().take_while(|&b| b == char).count()
})
.filter(|&run| run >= 3)
.max()
.unwrap_or(0);
Fence {
char,
count: longest_run.saturating_add(1).max(3),
}
}
/// Render `body` as a self-contained fenced block carrying `info` as its
/// opener's info string.
pub(crate) fn render_block(info: &str, body: &str) -> String {
let fence = fence_for_body(body, b'`').render();
let body = body.trim_end_matches('\n').replace("\{{", "\\\{{");
format!("{fence}{info}\n{body}\n{fence}\n")
}
}
{{#diff}} no longer breaks out of its own block when the listings it
compares contain a fence. Its wrapper was three backticks regardless of
content, so the first ``` inside a diffed Markdown listing closed it
early and the rest of the diff spilled into the page as prose. Both
directives now size the fence they emit to what it wraps, which is what
1 computes.
v0.1.1 — e2e suite tracks playwright-rust main
tests/e2e_callouts.rshas moved past its frozen listings. The e2e suite and the screenshot tool now build againstplaywright-rustmain rather than the releasedplaywright-rs0.14, dogfooding unreleased changes there the way this book dogfoodsmdbook-listings. On main,Page::locator()returns aLocatordirectly instead of a future, so the live test file drops the.awaitthat the chapter 5 and 6 listings show after everylocator()call. The frozene2e-callouts-v*andcapture-screenshots-v*listings stay as the v0.1.0 record.
v0.1.1 — List of Listings
- List of Listings index. A
{{#list-of-listings}}marker renders a book-wide index of every numbered listing, grouped by the chapter it appears in and linking to each one. Opt-in through[preprocessor.listings] list-of-listings; this book’s List of Listings page uses it. - Stable listing cross-references. A listing can carry a
label="..."on its{{#include}}or{{#diff}}directive, and prose anywhere in the book can point at it with alisting-refdirective that renders the listing’s current number, hyperlinked — so “see Listing 3.1” stays correct when numbers shift. An unknown or duplicated label fails the build. That reference is live: it resolves to chapter 3’s acceptance-criteria listing. - List of Listings in the sidebar. With
[preprocessor.listings] list-of-listings-sidebar, the numbered listings show in the sidebar, built in the browser."nested"puts each of the page you’re on into mdbook’s own header tree, under the heading it lives beneath, so it appears only while you’re on that page and its section is open and folds away with the heading."append"instead adds a self-contained “Listings” section below the table of contents, listing the whole book independent of the theme’s nav. This book turns on"nested", so the sidebar here shows this page’s listings under their sections.
v0.1.1 — listing numbers and captions
- Automatic listing numbers. Every listing renders a
Listing N.Mlabel, whereNis the chapter’s section number andMis the listing’s order of appearance. Numbering is opt-in through[preprocessor.listings] number-listings; this book turns it on. - Optional captions.
{{#include}}and{{#diff}}accept acaption="..."argument, rendered with the number asListing N.M — caption. - Listing-scoped callout badges. A callout badge reads as
5.3.1(its listing number plus the within-listing ordinal) rather than a bare1, both in the listing and in prose cross-references, so a badge says which listing it belongs to. - Pill-shaped badges. Badges render as pills at any width, so a bare
1and a scoped5.3.1share one shape. {{#diff}}context window. An optionalcontext=Nargument sets the unified-diff context radius (default 3), so a hunk can show enough surrounding lines to place a change. Used in Show Diffs Between Slices.
These features are active in this rendered book, but the prose, the listings, and the captured screenshots predate them: the screenshots show bare ordinals, and no chapter teaches numbering or captions. For the full entry and commit history, see the project CHANGELOG.