fix: six say-vs-do mismatches — PDF/A name, 413 hint, format lists, .htm, env - #140
Merged
Merged
Conversation
…s, .htm
PDF/A results downloaded as `<name>.pdfa`, an extension no OS opens as a
PDF. `_DOWNLOAD_SUFFIX` in app/api/routes/convert.py maps the pdfa target
to `<name>_pdfa.pdf` for the single download and the batch ZIP entries;
app/static/js/app.js mirrors it for its no-Content-Disposition fallback
(a test keeps the two maps in sync). The `_pdfa` suffix follows the
`_compressed` / `_pages` convention for outputs that share their
source's extension; a plain `<name>.pdf` was rejected because it
collides with the source in the Downloads folder.
The anonymous 413 hint on /convert and /compress still promised "up to
50 MB" after registering; the free tier allows 100 MB. The number now
comes from get_quota("free"), and the stale tier numbers in the adjacent
comments are gone.
The homepage drop-zone captions left out AVIF, HEIF, ICO, HTML, EML,
FLV, WMV, AAC, WMA and OPUS (compress mode: AVIF). Only the "Supported:"
label is translated now (existing msgid); the format tokens are plain
text, so five dead msgids leave the catalogs and a new converter needs
no catalog work. A parity test compares the rendered captions (DE + EN)
with /api/v1/formats. Rendering the lists from the registry was
considered and rejected: route plumbing for the same guarantee.
/formats filed AVIF and EML under "Other"; they now sit under Images and
Documents, and a test fails for any uncategorised source format.
/convert/html-to-pdf offered .htm in its file picker, but no converter
accepted it, so the user got stuck at "Please select a target format".
.htm is now registered on HtmlToPdfConverter: same class, same
_deny_url_fetcher guard. Dropping .htm from `accept` was rejected, since
drag & drop would still dead-end. Because .htm is typically Word's
windows-1252 "Save as Web Page" export, non-UTF-8 HTML now reaches
WeasyPrint as bytes (_html_source), so its <meta charset> is honoured
instead of every umlaut becoming U+FFFD in a "successful" conversion;
the SSRF test now covers both the str and the bytes path and asserts
that each resource URL hits the guard. The write_pdf() line references
of the CVE-2026-55073 assessment (ci.yml, CHANGELOG) move with the code.
Each fix comes with a regression test that fails on main.
Full suite 1197 green (63 skipped locally: WeasyPrint/pikepdf/ffmpeg-gated,
run in CI); ruff + format + i18n-drift + pip-audit clean.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…lias The docs, the office compose overlay and the converter's error message all name the DOCX -> PDF engine variable FILEMORPH_OFFICE_ENGINE, but Settings.office_engine only read OFFICE_ENGINE, so following the docs silently did nothing. The field now reads both via AliasChoices; the documented name wins when both are set in the same source. Making OFFICE_ENGINE canonical instead was rejected: every doc, the overlay and the error message already use the prefixed name, and the deployments that followed them are the ones this fixes. docker-compose.office.yml also pinned FILEMORPH_OFFICE_ENGINE=auto under `environment:`, which Compose ranks above the base file's `env_file: .env`. With the alias in place that pin would have overridden the operator's .env and silently turned a legacy OFFICE_ENGINE=mammoth into auto. The overlay no longer sets the variable (auto is the default), and .env.example lists it commented out so a copied template can't shadow a legacy value either. Behaviour change for self-hosters: a FILEMORPH_OFFICE_ENGINE of libreoffice or mammoth now takes effect instead of auto; libreoffice needs the office image. The CHANGELOG says so. Kept as a separate commit so it can be reverted on its own. Full suite 1203 green (63 skipped locally: WeasyPrint/pikepdf/ffmpeg-gated, run in CI); ruff + format + i18n-drift + pip-audit clean. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
scripts/make_testdata_format_fixes.py writes byte-stable fixtures for the manual test round of the two preceding commits: a text PDF (reportlab invariant mode) for the PDF/A download name, and a windows-1252 .htm with a <meta charset> plus a UTF-8 .html, both with umlauts, for the HTML -> PDF encoding fix. Output goes to the gitignored docs-internal/testdata/ folder; only the script ships, same pattern as make_testdata_ia_rework.py. Full suite 1203 green (63 skipped locally: WeasyPrint/pikepdf/ffmpeg-gated, run in CI); ruff + format + i18n-drift + pip-audit clean. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MrChengLen
force-pushed
the
pr-format-consistency
branch
from
September 25, 2026 13:38
88337d8 to
3f826e7
Compare
MrChengLen
added a commit
that referenced
this pull request
Sep 25, 2026
…registry The homepage FAQ answer "Which file formats can I convert?", the /llms.txt format sentence, the JSON-LD featureList and the README drop-zone mockup still listed the formats from before HEIF, AVIF, ICO, HTML, EML, FLV, WMV, AAC, WMA and Opus were added. #140 fixed the drop-zone caption, so the homepage FAQ contradicted the caption above it. All four now name every source format of get_public_conversions(), the data /api/v1/formats serves. The README "Supported Formats" table lacked HTML and EML (now a "Web & email" row: they only convert to PDF, and in the Documents row they would have implied EML -> TXT/HTML) and PDF as an image output. Kept as hand-written text plus a parity test, the pattern #140 set for the drop-zone caption on the same page. Rejected: deriving the lists from the registry at runtime. The JSON-LD is built in app/core at import time and can't import the /formats category map from a route module, so that map would have to move; format_label() prints WEBM and MD, so a casing map and alias de-duplication would be needed; the FAQ would become a five-placeholder msgid. More moving parts than four text edits, for a list that changes a few times a year — and the README can't be derived at all. tests/test_format_lists_match_registry.py (7 tests) compares each surface with the registry: the FAQ in EN and DE, including a check that /de/ shows the German answer (a fuzzy catalog entry would fall back to the English text, which lists the right formats); llms.txt; the JSON-LD "Convert ..." entries; the README mockup; the README table inputs, and each table row's outputs against the union of what that row's inputs convert to. Run before the text edits, all 7 failed and named exactly the missing formats. test_jsonld_webapplication_has_featurelist rejected "avif" anywhere in the feature list. It was written on 2026-06-05, before AVIF conversion shipped (7caa75e, 2026-07-15), to block an AVIF auto-routing claim. It now ignores bracketed format lists and still rejects AVIF everywhere else; Accept-header auto-routing still doesn't ship. A keyword list was tried first and dropped in review: it missed rewordings and flagged the real DOCX two-engine routing. The jsonld.py comment now points at that test instead of docs/claims-audit.md, which isn't in the public repo. i18n: extract + update left the DE entry fuzzy with the old list and the old EN msgid as #~; translated, flag and obsolete entry dropped, compiled. DE 776/776 translated, no fuzzy. Reviewed: security-auditor PASS; code-reviewer findings applied. Full suite 1216 green (63 skipped); ruff + i18n-drift + pip-audit clean; Tailwind bundle unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Sep 25, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Six verified places where the UI, API or docs said one thing and the code did another. Each fix has a regression test that fails on
main..pdf.pdf → pdfaresults were named<stem>.pdfa, which no OS opens as a PDF. They are now<stem>_pdfa.pdffor the single download, the batch ZIP entries and the JS fallback name. The_pdfasuffix follows the_compressed/_pagesconvention for outputs that share their source's extension.app/core/quotas.py./api/v1/formats./formatscategories. AVIF now sits under Images and EML under Documents; both were in "Other"..htmdead end on/convert/html-to-pdf..htm, but no converter accepted it..htmis now an alias of HTML → PDF: sameHtmlToPdfConverter, same_deny_url_fetcherguard.<meta charset>is honoured, so umlauts no longer come out as�.FILEMORPH_OFFICE_ENGINEwas ignored.OFFICE_ENGINE. Both names are accepted now; the documented one wins within the same source.docker-compose.office.ymlno longer pins the value underenvironment:, which overrode.env.Commits
301c891: fixes 1–5bdc5870: fix 6. This changes runtime behaviour, so it is a separate commit that can be reverted on its own.3f826e7:scripts/make_testdata_format_fixes.py, byte-stable fixtures for the manual test round (text PDF, windows-1252.htm, UTF-8.html). Only the script ships.Please merge with a merge commit, not squash. Rebased onto
mainafter #137 and #139.A
FILEMORPH_OFFICE_ENGINEoflibreofficeormammothnow takes effect; until now the app silently ranauto.libreofficeneeds thefilemorph:officeimage.Verification
mainfor the intended reason.Deferred (out of scope, tracked separately)
llms.txt, the JSON-LD feature list and the README.docs/api-usage-guide.mdanddocs/self-hosting.mdare stale, and the duplicate-name doc says_2where the code produces_1.safe_download_nametruncation drops the extension for names longer than ~191 characters, on all routes..github/workflows/docker.ymlhas been stored with CRLF sincef72dedc.🤖 Generated with Claude Code