feat(docpdf): draw DOT and PlantUML diagrams in PDF output and export every form from VS Code - #356
Open
devin-ai-integration[bot] wants to merge 9 commits into
Open
devin-ai-integration[bot] wants to merge 9 commits into
devin-ai-integration[bot] wants to merge 9 commits into
Conversation
DOT blocks are drawn through Graphviz (OPENSYSML_DOT, or dot on PATH), with the layout engine the block's header names, and PlantUML blocks through the PlantUML jar (OPENSYSML_PLANTUML_JAR) run by java (OPENSYSML_JAVA, or java on PATH) in pipe mode. Both tools are optional: without one, its blocks stay as source under a notice naming the variable to set; a tool that fails is the typed error mmdc failures already produce, with its stderr. The toolchain script pins Graphviz and the PlantUML jar by digest, and a CI job runs the PDF integration tests against the pinned toolchain, with OPENSYSML_REQUIRE_PDF_TOOLCHAIN turning an absent tool into a failure. 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:
|
…ts provision Co-Authored-By: jason.han <hanhuijun@gmail.com>
…dot and PlantUML as .puml The server lists the forms opensysml/render writes under the experimental capability openSysmlRenderForms; the extension offers those (or the documented five) in a quick pick and sends the choice as form on the request. Co-Authored-By: jason.han <hanhuijun@gmail.com>
… their variables and the export form picker Co-Authored-By: jason.han <hanhuijun@gmail.com>
Co-Authored-By: jason.han <hanhuijun@gmail.com>
…ml-pdf-and-export
Co-Authored-By: jason.han <hanhuijun@gmail.com>
…ml-pdf-and-export Co-Authored-By: jason.han <hanhuijun@gmail.com> # Conflicts: # docs/reference/environment.md
…ing it in the render directory 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
PDF output draws DOT and PlantUML blocks
-render-document -doc-form pdf -diagram-form dot|plantumlkept every DOT and PlantUML block as source under a notice; only Mermaid was drawn. The PDF backend now draws all three forms, each through an external tool located the waymmdcalready is:dot, located byOPENSYSML_DOTorPATH. The layout engine is the one the block's// layout:header names (dot,neato,neato -n,neato -n2), so the positioned layouts the DOT writer emits render where they were placed.java -jar <jar> -tsvg -pipe, source on stdin, SVG on stdout), the jar located byOPENSYSML_PLANTUML_JAR,javabyOPENSYSML_JAVAorPATH. When Graphviz was located, PlantUML is pointed at the samedotthroughGRAPHVIZ_DOT.ErrorToolFailedmmdcfailures already produce, carrying the tool's stderr. A tool that exits 0 without writing an SVG is the same typed failure. Mermaid stays required.SVG, not PDF, for Graphviz. Measured with WeasyPrint 69.0: an
<img>referencingdot -Tpdfoutput is refused (ERROR: Failed to load image at 'file:///…/g.pdf', the figure is left blank), while-Tsvgoutput embeds with its text and edges intact. PlantUML's-tsvgis used for the same reason.Structure. The rasterization lives in
docpdf's tool layer:converter.gogains the tool table entries and atoolRun(the subprocess mechanicsrunToolalready had, plus stdin/stdout/env),graphviz.goandplantuml.gosit besidemermaid.gobehind one smallrasterizerinterface, anddiagrams.goproduces onediagram{Image | Notice}per diagram block in document order.html.goandmarkdown.go's only change is the one call site that dispatches on the block's form, so the HTML-renderer migration of the PDF backend deletes them cleanly.Toolchain and CI.
scripts/download-doc-pdf-toolchain.shnow also pins Graphviz 16.1.0 (the upstream Ubuntu 22.04/24.04/26.04.debbundle, unpacked underbuild/doc-pdf/graphvizwith a wrapper that points it at its own libraries and plugin table;neatolinkslibgts-0.7.so.5, which the script checks for and the CI job installs) and PlantUML 1.2026.8, both by SHA-256, and printsOPENSYSML_DOT/OPENSYSML_PLANTUML_JARwith the others. No job ran that script in CI before, so the installed-tool tests only ever skipped there; a newpdf-toolchainjob provisions the toolchain (cached on the script's digest) and runsgo test -run Installed ./internal/docpdfwithOPENSYSML_REQUIRE_PDF_TOOLCHAIN=1, under which an absent provisioned tool fails instead of skipping (Prince, commercial and never provisioned, still skips).The VS Code panel exports every form
SysML: Export Diagramrendered throughopensysml/renderwithout aform, so it always saved the server's default (Mermaid). It now:initializeundercapabilities.experimental.openSysmlRenderForms(text,mermaid,markdown,dot,plantuml), falling back to that documented list against an older server;formonopensysml/render;.mmdMermaid,.dotGraphviz DOT,.pumlPlantUML,.mdMarkdown,.txtText — each with its own filter, and writes the artifact.One command, as before (the pick is inside it), so the title-bar and context-menu entries in
package.jsonare untouched. The pick → request → save sequence iseditors/vscode/src/export.ts, written against a smallExportHostso it is unit-testable;diagram.tssupplies the VS Code implementation.The LSP side is
RenderFormsCapabilityininternal/lsp/render.go, advertised fromview.Forms()so the list cannot drift from what the server writes.A
WrongFormErrorfor a rendering of no named view (the panel's whole-document tree) used to open with:; it now opens with the kind.Documentation
docs/project/view-rendering-forms.md,docs/manual/outputs.md,docs/reference/cli.md,docs/reference/environment.md(the ten PDF tool variables andOPENSYSML_REQUIRE_PDF_TOOLCHAIN),docs/reference/lsp.md(openSysmlRenderForms),docs/guide/08-editors.md(Exporting a diagram),editors/vscode/README.md,.agents/skills/testing-doc-pdf/SKILL.md, anddocs/project/spec-compliance.md's DOT, PlantUML and PDF rows.Specification basis
Not a language-semantics change. In
docs/project/spec-compliance.mdthe PDF document-rendering row moves from "DOT and PlantUML blocks are kept as source" to drawn-through-optional-tools, and the DOT/PlantUML form rows say where Graphviz and the jar now run; the Known Limitation that PDF output draws Mermaid only is replaced by the optional-tool statement. Known limitation kept: Java is the one tooldownload-doc-pdf-toolchain.shdoes not provision (the CI runner's JDK is used).How it was verified
PDF, with the toolchain provisioned by the extended script
OPENSYSML_REQUIRE_PDF_TOOLCHAIN=1, so a skip would have failed:TestRenderDiagramsWithInstalledGraphvizrenders a// layout: neato -nblock and checks the SVG keeps the stated positions (Tank right of Pump);TestRenderDiagramsWithInstalledPlantUMLrenders a diagram through the jar and checks a block the jar rejects isErrorToolFailedcarrying itsSyntax Errormessage.Without the tools (
PATHholding only Go, noOPENSYSML_*), the same three tests skip with the reason:The worked example (
docs/manual/examples/observatory.sysml,Observatory::MassReport) rendered to PDF under each-diagram-form, checked with pypdf: underdotandplantumlthe PDF carries no notice and the two figures' labels («part»,camera : Camera, …) are vector text, as the Mermaid ones are; withOPENSYSML_DOT=/nonexistentthe render still succeeds and the text carries the notice namingOPENSYSML_DOTabove thedigraphsource; withOPENSYSML_PLANTUML_JAR=/nonexistent.jar, the notice namesOPENSYSML_PLANTUML_JARabove the@startumlsource.Unit tests with fake tools (no toolchain needed),
internal/docpdf/diagrams_test.goandcmd/sysml/render_document_pdf_test.go: missing Graphviz / jar / java keeping the source under a notice naming the variable; a fakedotand a fakejavadrawing SVGs;-Tsvgand the layout engine picked per header (dot,neato,neato -n,neato -n2, unknown header); pipe-mode arguments and source on stdin; Graphviz, java and PlantUML failures carrying stderr; a tool that exits 0 without an SVG; block ordering of a mixed Mermaid/DOT/PlantUML document; Mermaid still required; both-diagram-formvalues end to end through the CLI.LSP
internal/lsp/render_test.go:TestRenderAnswersEveryAdvertisedFormreadsopenSysmlRenderFormsfrominitialize(exactlytext, mermaid, markdown, dot, plantuml) and renders a view in each, checking the answer'sformand a non-empty artifact.VS Code
editors/vscode/src/export.test.ts: forms from the capability, the documented fallback, de-duplication; the.mmd/.dot/.puml/.md/.txtmapping and matching filters; picker labels; the request carryingform; the saved artifact; cancel at the pick, cancel at the save dialog; a server refusal; the server answering another form than asked.Driven in a real VS Code (1.137.0) with the packaged extension and a freshly built
sysml-lsp:make build-lsp && make vscode-package; installed the.vsixinto an isolated--user-data-dir/--extensions-dirprofile withopensysml.server.pathatbin/sysml-lspandopensysml.trace.server: verbose; opened a workspace holding avehicle.sysml(part def Vehicle { part engine; part wheels; } part car : Vehicle;).SysML: Export Diagram: the quick pick listed exactlytext,mermaid,markdown,dot,plantuml, each with its extension and description.dot: the save dialog defaulted tovehicle.dotin the workspace with theGraphviz DOTfilter; saved; the file opens with// layout: dotanddigraph, naming Vehicle, engine, wheels and car.plantuml(vehicle.puml,PlantUMLfilter, file starts@startuml),mermaid(vehicle.mmd,flowchart TD) andtext(vehicle.txt, one element per line).Sending request 'opensysml/render - (11)'with"view": "#tree"and"form": "dot", theinitializeresponse advertising the five forms, and oneExported <form> of vehicle.sysml to <path>line per save; each saved file's bytes equal the artifact in the response.markdownfor the tree: no dialog, the error notificationRendering vehicle.sysml failed: a tree rendering is not written as markdown; ask for text, mermaid, dot or plantuml, novehicle.mdwritten. (The run that found the doubled colon predates theWrongFormErrorfix in this PR.)Not exercised by hand: a table view exported as Markdown, and the title-bar / context-menu entry points (they run the same command).
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