refactor(docpdf): hand the HTML-input PDF engines the HTML backend's markup - #358
Open
devin-ai-integration[bot] wants to merge 11 commits into
Open
devin-ai-integration[bot] wants to merge 11 commits into
devin-ai-integration[bot] wants to merge 11 commits into
Conversation
WeasyPrint and Prince now read the HTML document backend's page with a print stylesheet layered over its default sheet, from the evaluated document rather than a re-parse of the rendered Markdown. Pandoc keeps reading Markdown; captions are told from emphasized paragraphs by a Lua filter fed the document's caption texts, so the Markdown caption marker is gone. RenderDocument gains a form field and an html response for the service and its Python client. Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
Contributor
Author
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
Build the group key with the same delimiter helper the other strong runs use, so a blank or padded key no longer leaves literal asterisks in pandoc's PDF. Pandoc's filter writes a source notice ahead of a DOT or PlantUML fence instead of dropping the block, the HTML backend's DiagramImages and Math hooks get docrender tests of their own, and the changelog fragment and spec-compliance rows describe the PDF path as it is. Co-Authored-By: jason.han <hanhuijun@gmail.com>
…tation Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
…ing comment A table-kind diagram's Markdown opens with an HTML comment between the caption and its table, which pandoc keeps as a raw block, so the caption filter never saw a captionable block after the caption and, since matching is ordinal, marked no later caption either. The rendering comment now counts as caption evidence, covering the empty rendering whose comment is followed by the reason rather than a table. Co-Authored-By: jason.han <hanhuijun@gmail.com>
…sis marks A caption padded with blanks was written as "* Masses *", which CommonMark does not parse as emphasis, so pandoc's caption filter missed it and, matching ordinally, every caption after it. Captions now go through the same delimited() helper as grouped-table keys, and a blank caption writes no paragraph and is not listed by Captions. Co-Authored-By: jason.han <hanhuijun@gmail.com>
…s indented code A caption padded with four spaces or a tab began its Markdown block with that indentation, which CommonMark parses as an indented code block, so the paragraph never reached pandoc's caption filter and every later caption fell out of step. Captions are now written trimmed, and Captions lists them trimmed to match. Co-Authored-By: jason.han <hanhuijun@gmail.com>
…html-backend Co-Authored-By: jason.han <hanhuijun@gmail.com> # Conflicts: # clients/java/opensysml-client/src/main/java/org/openmbee/opensysml/proto/Sysml.java # clients/node/src/generated/sysml_pb.ts # clients/python/opensysml/proto/sysml_pb2.py # clients/rust/conformance/sysml.descriptor.binpb # internal/docpdf/integration_test.go
An option the selected engine cannot take is reported as unsupported even when the engine itself is not installed. The Python gRPC stub keeps the pinned grpcio-tools 1.83.0 version stamp. Co-Authored-By: jason.han <hanhuijun@gmail.com>
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 and why
The PDF backend's HTML-input engines (
weasyprint,prince) are handed the HTML document backend's markup — generated from the evaluated document — with a print stylesheet layered over the backend's default sheet, instead of HTML thatdocpdfwrote itself from a re-parse of the rendered Markdown.docpdf's block parser, page writer and inline translator (markdown.go,html.go,inline.go) are deleted; the package keeps locating and running tools, drawing Mermaid diagrams, typesetting with KaTeX and the typed errors.docpdf.Rendertakes the evaluated*docir.Document; the CLI evaluates once (repl.Session.EvaluateDocument) and hands the IR over.docrendergainsDiagrams,FormulasandCaptions(what a backend may draw or typeset out of process) and theHTMLOptions.DiagramImages/Mathhooks — the one seam where a diagram block becomes its rasterized image, so DOT/PlantUML rasterization can slot in besidemermaid.gowithout touching it. A table-kind diagram stays a table and takes no image; surplus images are a typedErrorSurplusDiagramImages.internal/docpdf/print.css,@layer opensysml-printafter@layer opensysml, nostyleattributes,--sysml-*tokens only (the docrender override-contract assertions now run over it too). A reader's unlayered-html-csssheet therefore overrides PDF exactly as it overrides HTML.-html-theme,-html-no-default-cssand-html-cssnow reach-doc-form pdf;pandocaccepts-html-css(as extra--css) and rejects the other two with a typed error since its page is its own.pandockeeps reading Markdown. Measured: pandoc cannot tell a caption from an emphasized paragraph by syntax, and the marker only ever served it — so the<!-- caption -->marker leavesdocrender.Markdownentirely (goldens move by that comment line only, see below) and the pandoc converter's generated Lua filter recognizes captions by matching emphasized paragraphs againstdocrender.Captionsin order, and only ahead of a captionable block (table, display math, diagram fence, the rendering comment a table-kind diagram opens with, grouped table's key). DOT/PlantUML sources get an emphasized notice under pandoc as they do under the HTML engines.docrender.Markdownwrites a grouped table's key through the shared strong-span writer, so a blank key no longer yields**zone: **, which pandoc set as literal asterisks.RenderDocumentgainsform(markdown/html) andRenderDocumentResponse.html, advertised as capabilityrender_document_html; the Python client'srender_document(..., form=)follows. PDF is not offered over the service since it needs the CLI's converter toolchain — recorded as a known limitation.Docs:
docs/manual/outputs.md,docs/reference/cli.md(and the regeneratedsysml.1),docs/project/html-document-backend.md(work plan step 2 landed, known limitations),docs/project/spec-compliance.md,.agents/skills/testing-doc-pdf/SKILL.md; changelog fragmentchanges/unreleased/pdf-onto-html-backend.changed.md.How it was verified
Gates (all clean):
go build ./...,go vet ./...,gofmt -l .(empty),go test ./...,make lint,make docs-check,python3 scripts/changelog.py check,make proto-lint proto-breaking, the Python client tests (985 passed, 91 skipped), andOPENSYSML_REQUIRE_TRAINING_CORPUS=1 OPENSYSML_REQUIRE_PILOT_CORPORA=1 go test -count=1 ./internal/core/model -run 'TestTrainingExamples|TestPilotCorpora'.Markdown goldens:
git diff origin/develop -- internal/core/docrender/testdataremoves 31 lines, every one of them<!-- caption -->; nothing else moves. That includes the state-and-event report golden: its state rows (lamp1.lp in on.fast) and event rows (t=0 lamp1.lp: enter: on) render unchanged, and in PDF they go through the HTML backend's page underprint.csslike every other row —TestRenderStateReportPageasserts the page handed to the engines isdocrender.HTML's (span.sysml-statewithdata-machine/data-state/data-region,span.sysml-eventwithdata-event-kind/data-time) with the print layer, andTestRenderStateReportWithInstalledEnginesreads the state paths, event summaries and1 [s]instants back out of each installed engine's PDF.Options an engine cannot take (
-html-theme/-html-no-default-csswith pandoc) are checked before the engine's presence, so the report isunsupported-optioneven where pandoc is not installed (TestRenderUnsupportedOptionBeforeTools).PDF path with the pinned toolchain present
./scripts/download-doc-pdf-toolchain.sh(pandoc 3.10.2, WeasyPrint 69.0, mermaid-cli 11.16.0, KaTeX 0.16.47), thengo test -count=1 ./internal/docpdf/... -run 'Installed|Integration|ArtworkFilter' -vwithOPENSYSML_WEASYPRINT,OPENSYSML_PANDOC,OPENSYSML_MMDC,OPENSYSML_MMDC_PUPPETEERandOPENSYSML_KATEXset:These extract the PDFs' text and assert: emphasis/strong/code runs render as runs (no
*,`,**,](,<a idliteral); the standalone anchor andReftargets are internal destinations and the externalLinka/URI; grouped-table keys are strong headings; the caption is set small while an emphasized body paragraph stays body-sized under both engines, and no{.caption}/[*leaks; KaTeX fonts are embedded and the text carries∝,λand none of$,\propto,_{,<span; the Mermaid diagram is an embedded image with its source gone. The twoArtworkFiltertests run the generated Lua filter under pandoc (-t html) over a document mixing table-kind diagrams — whose Markdown puts a<!-- table rendering -->comment between caption and table — with a Mermaid diagram, a table whose caption is padded to CommonMark's indented-code width (" Subsystems by name "), a table whose caption is blank, a further captioned table and an emphasized prose paragraph repeating a caption's text, and assert every caption is marked once and the prose not; both fail with 0 captions marked without the comment recognized as caption evidence. A caption is written as*Subsystems by name*with its surrounding blanks dropped: kept inside the marks (* Subsystems by name *) CommonMark reads literal asterisks, kept outside them four spaces or a tab at block start (*Subsystems by name*) read as an indented code block, and either way the paragraph never reaches the filter and every later caption falls out of step.docrender.Captionslists the same trimmed text; a blank caption writes no paragraph and is not listed.TestMarkdownPaddedCaption(docrender) pins a caption padded with single blanks, one indented four spaces, one led by a tab, a blank one and a later plain one; the pandoc test fails against the previous renderer with" Subsystems by name "listed untrimmed and the paragraph parsed as code.Prince was not run — it is proprietary and not provisioned; its subtests skip with the typed not-installed error above. Its converter is verified on the input it is handed:
TestRenderHTMLIsTheBackendsPageand the fake-tool tests assert the prepared HTML isdocrender.HTML's page (article.sysml-document,sysml-*classes,data-*attributes) withdocument.css,print.css, KaTeX's sheet and the reader's sheets linked in that order, and the print-stylesheet contract test coversprint.css.Before/after renders, re-adjudicated
Binaries built from
origin/developand this branch rendered the worked example (Observatory::MassReportwith-pdf-title-page -pdf-toc -pdf-number-sections), the math report (Optics::OpticsReport) and each document of the linked set (the CLI refuses-render-documents -doc-form pdf, so each was rendered on its own) underweasyprintandpandoc;pdftotext/pdfinfocompared:Refliterally ([Subsystem Masses](Observatory-Mass.20Appendix.md#tables-masses)); after sets it as link text over a/URIto the sibling's HTML page name, as the HTML form writes it. Same words otherwise[the report](Observatory-SystemReport.md)literal before, link after-doc-toc, and the table of contents now takes a page of its own under pandoc (below)figcaption) rather than above the block, and the lead paragraph wraps differentlynav#TOC { break-after: page }), as it already did underweasyprint, so every later page number shifts by oneNone of the moves changes which text a document carries or its order; the cross-document link is the one behavioral change (a literal Markdown link becoming a link), and a PDF's sibling link pointing at a page file no PDF carries is recorded as a known limitation in
html-document-backend.mdandspec-compliance.md.Checklist
make testandmake lintpass locallychanges/unreleased/<slug>.<section>.md, not as an edit toCHANGELOG.mdmake docs-countsrun if a gate count moved (compliance rows need nothing: the census is counted at docs build)F4,K5) in the body, docs, or changelog