Three things found in the check before a release. A directory of
screenshots taken while working on the interface had been committed; it
is removed and ignored, because it is a working note rather than part of
the service. Two branches kept pointing at the history from before the
licence changed, which is the only place that history was still reachable;
they are gone. The page title still named the service the way it was named
before it became apsis-book.
The binary was checked from an empty directory with no content tree and no
frontend build beside it: it serves every route from what it carries.
Copying a formula from a page gave one character per line: the SGP4 a_1
block arrived as a hundred and thirty-two lines for a hundred and
thirty-two characters. That is how a browser copies MathML, which is one
element per token and is walked one element at a time.
The rendering was not the fault. The block was measured in place and the
six rows each hold their two cells side by side, with the tokens of a row
sharing a baseline, and a screenshot agrees. What was wrong is what a
reader gets when they take the formula away.
The source is therefore carried beside the MathML in an element that can
be selected, and the MathML is taken out of selection. A copy now yields
the notation the formula was written in, on one line, which is what a
reader can paste into a tool that understands it.
The source is trimmed when it is rendered, because the delimiters of a
display formula sit on their own lines and the newline after the opening
pair was arriving as a leading space.
A doc comment names an item by its full path, as in
`NoiseTemperature::from_noise_figure_db`. A path has no space in it, so
the column could shrink and the word could not, and the interface page of
a crate scrolled sideways on a phone. The body of a document now breaks a
word rather than overflow.
The audit that renders every route now covers the whole interface: 744
combinations, being ninety-three routes in both languages and both themes
at two widths, and it passes. It reports four things, which are the four
ways a page has failed here before: a page that does not load, a page
with almost no text, a page that scrolls sideways, and a formula that
loses a letter or a digit.
Two mistakes of the audit itself are fixed rather than worked around.
It awaited a `Runtime.evaluate` that called `location.reload`. Such a
call destroys its own execution context, so the reply never arrives, the
promise never settles and the run hangs until the environment kills it.
The preferences are now set once per language on a page that stays put,
and each route is reached by an ordinary navigation.
It gave the browser a function whose comment contained a backtick. The
backtick closed the template literal that held the function, so the script
did not parse at all.
The formula comparison now treats a command name as notation, as it
already did for the operators: \Delta draws a Greek letter and \sqrt a
radical sign, so neither is drawn as the letters of its own name.
A bracketed group was never given its power, so `(1 - e^2)^2` and every
line of that shape were shown as source. An operator written with its
spacing was emitted as bare text, and a browser drops bare text inside a
row, which lost the sign of a difference: `1 - e^2` came out as `1e^2`.
A parenthesis holding words was read as a note about the equation rather
than as part of it, so `(cos theta)` and `(m * g)` broke the lines that
held them; the parser now decides, and the column a note is set in is
what marks it. A vertical bar ended an absolute value only from the
outside, so `| f'(x) | * | x| / | f(x) |` did not read.
A grid track of `minmax(28rem, 1fr)` is wider than a phone, so the
interface page of a crate scrolled sideways. The track now takes
`min(28rem, 100%)` and shrinks to the width it has.
The equations of the documents went from seventy being set as formulas
to ninety-six. What is left is pseudocode and matrices, which are source
rather than formulas.
A translation was filed under the item name alone. The name is not
unique: `new` is used by fifty-nine crates and `kind` by fifteen, and
they do not all mean the same thing by it, so a name-only translation
could be shown against the wrong documentation. A translation is now
looked up by `crate::name` first, then by `Type::name` for two items
of one crate that share a name, and only then by the bare name.
The facade crate sits directly in `crates` and re-exports every layer.
It defines nothing of its own, so listing it repeated every item of the
layers under a second name. The generator skips it and the catalog
carries forty crates.
The first batch of Chinese translations is in, covering the foundation,
time, coordinate, geodesy, frames, Kepler, SGP4 and linear algebra
crates.
A page change did not move the scroll position, so following a link from
the bottom of a long document landed in the middle of the next one. The
scroll now follows the path rather than the fragment, so a filter applied
to the page a reader is on leaves them where they are. The browser fires
`popstate` for a fragment navigation as well as for a traversal, so
there is no event that means "this was a traversal" on its own, and going
back starts at the top rather than where the reader left.
The interface index listed fifteen crates in one grid. It is now grouped
by layer, with the title and order the concept documentation already
declares, and a card shows the opening sentence of the crate summary
rather than the whole of it, which is what made the cards four hundred
pixels tall.
A tool result showed its column headings, scalar labels and notes in the
reader's language, but left the table body in English. Text cells are now
looked up as well. Units are written with a power, and are set as one.
A tool description is Markdown, so it is now rendered as such, as are the
parameter help and the notes. A formula written between dollar signs is
set the same way in both places.
The graph took over three seconds to draw. The force layout ran four
hundred and twenty steps of repulsion between every pair of nodes, which
is quadratic in the node count and was doing that work through a reactive
proxy inside an effect that read the state it wrote, so it rescheduled
itself on every run. The repulsion now runs on a grid over neighbouring
cells, and the effect no longer tracks its own writes.
The physics layer covered two unrelated subjects, so it is presented as
two. Formulas are written between dollar signs and translated to MathML,
which the browser sets itself, so no script has to run. The palette is
now two sets of the same variables with a toggle between them, and below
a thousand pixels the sidebar is a drawer over the page.