Skip to content

feat(download): rename Raw tab to Download and add HTML/RTF/PDF page export - #579

Merged
tkuhn merged 1 commit into
masterfrom
download-tab-doc-export
Jul 31, 2026
Merged

feat(download): rename Raw tab to Download and add HTML/RTF/PDF page export#579
tkuhn merged 1 commit into
masterfrom
download-tab-doc-export

Conversation

@tkuhn

@tkuhn tkuhn commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Closes #578.

The Raw tab is now the Download tab (?tab=raw kept as a legacy alias) and offers the page's content as downloadable documents next to the existing RDF links: HTML, RTF (opens in Word and LibreOffice, covering the Word/ODF ask without heavy dependencies), and PDF.

What's in here

  • New export package: a format-neutral DocumentModel (sections, paragraphs, tables, lists) built by DocumentModelBuilder from the page's view displays, mirroring the QueryResult* rendering conventions (_label fallbacks, _noheader, multi-value columns, action-mapping/source columns dropped, header views as headings, query-form views skipped). IRIs link to the IRI itself so documents carry resolvable links.
  • Writers: HtmlWriter (no dependency), hand-rolled RtfWriter (no dependency), and PdfWriter via the only new dependency, io.github.openhtmltopdf:openhtmltopdf-pdfbox (with a strip-and-retry fallback for ill-formed embedded paragraph HTML).
  • DownloadDocPage at /download-doc (type, id, context, format=pdf|rtf|html); HTML serves inline, RTF/PDF as attachments. DownloadRdfLinks renamed to DownloadLinks with a "Document formats" section above the RDF sections.
  • Shared view-display resolution: downloads now use the new public AbstractResourceWithProfile.fetchViewDisplaysSync(), reusing the page-rendering logic (ref-scoped query for spaces, preset-supplied views, own-classes matching). The previously duplicated copy in DownloadRdfPage had drifted and silently dropped class-targeted and preset views — this also fixes the existing RDF download. Query fetching moved to ViewDataFetcher; buildQueryRef gained ViewList's context/root_np auto-fill.
  • PDF emoji: monochrome Noto Emoji (OFL, license bundled) registered as a fallback font so view-title emoji render as glyphs instead of #; fonts/** excluded from Maven resource filtering, which corrupts binaries.

Testing

  • 953 tests green, including new unit tests for the writers (RTF escaping/surrogate pairs, XHTML strictness, PDF magic bytes + emoji-glyph regression via PDFBox text extraction), the builder's column conventions, and the page constants.
  • Verified end-to-end on a local instance: tab rename + ?tab=raw alias, all three formats on space/user/part pages (PDF inspected visually and via pdftotext, RTF round-tripped through LibreOffice), export sections match the Content tab exactly, RDF links unchanged.

Notes

  • Cold-cache exports share the RDF download's existing behavior (up to 30s query wait; sparse if the view-display cache is cold — warm in practice since the user just viewed the page).
  • CJK text still renders as missing glyphs in PDF (base-14 fonts); a DejaVu fallback could be added the same way later.
  • .docx/.odt writers can be added on the same DocumentModel if RTF proves insufficient.

🤖 Generated with Claude Code

…export (#578)

The Raw tab is now the Download tab (?tab=raw kept as a legacy alias) and
offers the page's content as downloadable documents next to the existing
RDF links: HTML, RTF (opens in Word and LibreOffice), and PDF.

- New export package: format-neutral DocumentModel built from the page's
  view displays (mirroring the QueryResult* rendering conventions), with
  HTML, hand-rolled RTF, and openhtmltopdf-based PDF writers; served by
  DownloadDocPage at /download-doc.
- View-display resolution for downloads is now
  AbstractResourceWithProfile.fetchViewDisplaysSync(), reusing the page
  logic (ref-scoped query, preset-supplied views, own-classes matching);
  the previous duplicated copy in DownloadRdfPage had drifted and dropped
  class-targeted and preset views, which also fixes the RDF download.
- Query fetching shared via ViewDataFetcher; buildQueryRef gained
  ViewList's context/root_np auto-fill.
- Monochrome Noto Emoji (OFL) bundled as PDF fallback font so emoji in
  view titles render as glyphs instead of '#'; fonts are excluded from
  Maven resource filtering, which corrupts binaries.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@tkuhn
tkuhn merged commit fec9dc0 into master Jul 31, 2026
8 checks passed
@tkuhn
tkuhn deleted the download-tab-doc-export branch July 31, 2026 05:15
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.

Tab "download" to allow for downloading page in formats such as Word

1 participant