Contributing a format
September 6, 2026 ยท View on GitHub
Each new format ships the same five parts: a pure core parser, a
registry.rs entry, a shared scenario, a passing fixtures verify, and a
passing test core --parity. The pull request pastes the source URL,
attaches the capture output, and attaches the expected output image.
Checklist
A format is complete when all of the following hold in one pull request:
crates/dezoomify-coreparses the metadata and plans tiles from supplied bytes only. Core performs no network, filesystem, clock, or task effects, per Architecture.crates/dezoomify-core/src/core/registry.rsregisters the format with a stable id and a user-visible display name. Registry order defines automatic precedence; put the new entry where discovery must try it.testdata/scenarios/<id>/holds redactedroutes.json, payloads, andscenario.json, pertestdata/scenarios/README.md.cargo xtask fixtures verifypasses.cargo xtask test core --paritypasses.
Workflow
1. Paste the URL
Find a public viewer page or metadata file that shows the format. Paste the URL into the pull request description. Use only public pages: no credentials, no signed URLs, no personal data. Public demo keys embedded in fixture URLs are allowed; private tokens are never committed. See Security.
2. Capture redacted fixtures
Run the capture helper from the repository root:
cargo xtask fixtures capture --url <url> --out <scenario-id> --redact
Pass --also <url> for each extra metadata resource the parser needs (for
example a viewer page plus its info.json). The helper fetches with plain
curl: credential-free requests, bounded redirects, bounded time, and a
per-payload size cap. It saves routes.json plus payloads under
testdata/scenarios/<scenario-id>/ and prints a manifest snippet plus next
steps.
Redaction is mandatory, not optional: the command fails closed without
--redact. It drops URL fragments, rejects URLs with userinfo, replaces
sensitive query values (apiKey, token, auth, session, signature,
secret, password, cookie, and case variants) with REDACTED, scrubs
the same values from text payloads, and stores only the Content-Type
response header. Colons in payload paths become %3A so the tree checks out
on Windows.
After capture, review the changes before anything else:
git status --porcelain -- testdata/scenarios
git diff -- testdata/scenarios/<scenario-id>
Confirm no secret, token, cookie, or personal string remains. Insert the
printed manifest entries (sorted) into testdata/scenarios/manifest.json
with accurate license_provenance, then run
cargo xtask fixtures verify. Verification never rewrites files; fix the
fixtures until it passes.
3. Add the core parser and register it
Implement the format in crates/dezoomify-core following the neighboring
format modules: recognize the URL shape and metadata bytes, describe the
image catalog, and plan the tile grid. Keep the code pure and deterministic:
fixed parsing, no network, stable ordering. Register the stable id in
crates/dezoomify-core/src/core/registry.rs in precedence order and cover
the parser with unit cases plus the shared parity suite.
4. Save the expected output
Run the native app against the loopback fixtures once the scenario serves, and save the expected output image for the pull request:
cargo xtask fixtures serve --port 0
dezoomify "<viewer-or-metadata-url>" expected.png
Attach expected.png to the pull request so reviewers compare pixels, not
promises. Name the produced files with the shared output / save
vocabulary; never export or download for the saved files.
5. Verify and open the pull request
Run the gates from the repository root:
cargo xtask fixtures verify
cargo xtask test core --parity
cargo xtask test scenario --scenario <scenario-id>
The pull request contains the pasted URL, the capture output, the expected
output image, and the checklist above. Reviewers check redaction, license
provenance, registry precedence, and parity before merge. Live checks
(cargo xtask test live --public) stay advisory and never replace scenario
coverage, per Testing.