Skip to content

The pages say where a document's files come from - #18

Merged
fabeat merged 7 commits into
mainfrom
feature/file-finder
Oct 30, 2026
Merged

fabeat merged 7 commits into
mainfrom
feature/file-finder

Conversation

@fabeat

@fabeat fabeat commented Oct 29, 2026

Copy link
Copy Markdown
Contributor

The site says where a document's and a deck's files come from — and the two finders cannot drift apart.

This branch carries the chrome: → templates-file: rename of #17 as well, so the diff shows both until that pull request merges. Once it does, this one shows only its own commits.

The page

One page, in content/general/, at /files/.

The two finders are the same shape by design — that is what lets one adapter serve both packages — so the site's own rule of one list, one home applies: the four methods are one list, read out of both interfaces, and carried by one page. The halves' differences are told in the same page, the way general/directives.md tells the two halves' opposite policies.

It covers: what a finder is, the four methods, the three roles, the names the library composes, "a finder answers; it does not refuse", why the scope check stays with the library, the disk finder, and each half's own arrangement — the Word half stages a .dotx, the slides half stages a master and refuses one it cannot serve.

Every example on the page is a real document and a real deck, built by the two libraries while the page is built.

The vocabularies

Two, and both are shared — read out of both packages and held to one list:

  • finder-methods — the four public methods.
  • finder-roles — theme, picture, document.

A shared vocabulary is compared across the halves, so tools/check-reference.php fails if the two drift apart on the names. The counts move from 24 vocabularies and 227 names to 26 and 236.

The claim tests

tests/Claims/finder.php — seventeen claims, each checked against the code:

  • the drift guard — the two interfaces have the same method names, the same parameter types and defaults, and the same return types;
  • the page lists every method and every role, and the counts it states are the code's;
  • a finder answers null and refuses nothing;
  • the scope check stays with the library — a finder that answers a path out of scope is refused by ThemeNotFound, not by the finder;
  • the same document, and the same deck, from a finder as from a directory — compared by part, never by archive bytes;
  • withTheme() resolves the name once;
  • a failure names the themes that resolve;
  • a master the source cannot serve is refused with UnservedTemplate;
  • the roles the library actually asks with, and that a picture reaches the document;
  • one adapter serves both halves — the site's own MemoryFinder implements both interfaces.

tests/Claims/behaviour.php gained one claim: the two halves do opposite things with a name they do not know — the Word half writes it out, the slides half refuses it by name.

The new exception on the error pages

UnservedTemplate is not an InvalidInput: neither the deck's author nor the theme's author can fix it — the program that brought the source can. The three pages that count the exceptions beside InvalidInput are updated, and the sentences that named them are rewritten to name them.

What did not change

The site's claims about the two halves' opposite policies, and every example on every page.

The library renamed the key that points at a file of template definitions:
`chrome:` is `templates-file:` now, and the file it names is a templates file.
The word "chrome" keeps its other meaning — the shapes a template draws — and
the pages keep it there.

The exceptions follow the library: `ChromeNotFound` and `ChromeTooLarge` are
`TemplatesFileNotFound` and `TemplatesFileTooLarge`, and a templates file that
holds a slide is now `MalformedTemplatesFile` rather than a case of
`MalformedChrome`.
Both libraries now read every file through a `Files\FileFinder`, and the two
interfaces have the same shape — so one adapter serves both packages, and a
program that keeps its themes in a database writes it once.

The page is in the half that is about both libraries, because the finder is:
one shape, one list of methods, one set of roles. The two halves' own pages
point at it, and the halves' differences — the Word half stages a template, the
slides half stages a master and refuses one it cannot serve — are told there.

Two vocabularies come with it, read out of the code rather than written down:
the four methods a finder has, and the three roles a name is resolved in. The
claims suite holds the two interfaces to each other, so they cannot drift apart
without a test failing — which is what lets one adapter serve both.

The examples on the page are built through a finder: the builder learned a third
word for a fence, `finder`, and the theme they use is in memory rather than in a
directory. The slides half gained an exception, `UnservedTemplate`, and the
renderer's method count and the number of exceptions beside `InvalidInput` both
moved, so the pages that state them say the new numbers.
The example builder read the whole fence of an example with one pattern: the
opening fence, the direction the example runs in, the words that may follow
it, the body, and the closing fence of the same length. Sonar counted that
pattern at 24, where 20 is the most it allows, and the count was fair — one
pattern was carrying five jobs.

It carries two now. The opening fence is one pattern, and the closing fence is
another, built from the fence that was opened: a closing fence has to be as
long as the opening one, and its length is only known once the opening one has
been read. The pattern that finds the opening fence counts 19, and the one
that finds the closing fence counts two.

What the builder accepts has not changed. The same fences are read, the same
bodies are taken out of them, and the same blocks are hashed into the same
keys: a check of the new search against the old pattern over every block of
the site and over twenty thousand made-up ones found no difference, and a
build from an empty cache writes the manifest it wrote before.

The claims suite named the house theme's file and what that file holds in
eight places and in five. They are two constants now, named for what they are.
The page about the finder was added to a section the skill bundle claims to cover, and
the bundle did not carry it: `tools/check-skill.php` says so, and the pipeline never ran
the check that would have said it — the npm script the workflow calls was the weaker of
the two the repository held under the same name. The bundle carries the page now, the
skill check runs beside the link check, and the composer script delegates rather than
keeping a second and weaker copy of the same name.

The page makes two copies of the code: the interface it shows and the adapter a reader
would take. Both are compared with the code now, so a signature that moves and an adapter
that stops sorting are failures rather than prose that is quietly wrong. The names the
page lists say which half composes them, and a claim reads that column out of the two
theme loaders rather than out of the page.

The method names the pages state in prose were claims nothing checked: the slides half's
index named five methods of a renderer and four of a reader, and a rename would have left
the sentence standing with every gate green. They are asked of the code now, and the count
of a list is asked of it in one place rather than two.

The page is shorter for it. The sentences that repeated the library's own docblocks are
gone, `Files\DiskFinder` is no longer called the default where a finder is optional and
the disk is what is left without one, and the roles table no longer says where a role is
looked for in a way that was false.
Sonar read the claim about which half composes which theme file and found a
ternary inside a ternary. The answer was right and the reading was not: three
clauses in one expression, and a reader has to hold all of them to see which
one applies. It is a method now — `finderHalf()` says whether a file is
composed by both halves, by the Word half or by the slides half, in the words
the page's table uses — and the claim compares the page's column with the two
theme loaders' lists through it.

The loader that reads the adapter the page shows used `require`, and the rule
is right to ask about it: the file is a temporary one, written from the page's
own code, read to declare the class, and removed again as soon as the class is
in memory. Nothing re-reads it — a class cannot be declared twice in one
process, so the loader already remembers the classes it has loaded and hands
the one that is already there to the second claim that asks for it. The file
was read once anyway, and `require_once` says so where the guard used to be
the only thing that said it.

The claims can still fail. With the helper answering "both" for every file,
the claim about the halves goes red; with the page's table saying "Word"
where the library says "both", it goes red as well. With the page's adapter
no longer sorting its themes, the two claims about the adapter go red, so the
class is loaded and run rather than merely read.
@sonarqubecloud

Copy link
Copy Markdown

@fabeat
fabeat merged commit 8ec0b17 into main Oct 30, 2026
3 checks passed
@fabeat
fabeat deleted the feature/file-finder branch October 30, 2026 09:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant