MeshWeaver.Markdown.Export
3.0.0-rc3
dotnet add package MeshWeaver.Markdown.Export --version 3.0.0-rc3
NuGet\Install-Package MeshWeaver.Markdown.Export -Version 3.0.0-rc3
<PackageReference Include="MeshWeaver.Markdown.Export" Version="3.0.0-rc3" />
<PackageVersion Include="MeshWeaver.Markdown.Export" Version="3.0.0-rc3" />
<PackageReference Include="MeshWeaver.Markdown.Export" />
paket add MeshWeaver.Markdown.Export --version 3.0.0-rc3
#r "nuget: MeshWeaver.Markdown.Export, 3.0.0-rc3"
#:package MeshWeaver.Markdown.Export@3.0.0-rc3
#addin nuget:?package=MeshWeaver.Markdown.Export&version=3.0.0-rc3&prerelease
#tool nuget:?package=MeshWeaver.Markdown.Export&version=3.0.0-rc3&prerelease
MeshWeaver.Markdown.Export
Server-side export of markdown nodes to PDF and DOCX. No Pandoc, no Node.js; PDF is printed by the headless Chromium the portal image ships (see PDF Export).
Pipeline: Markdig AST → Document model → { print HTML + CSS Paged Media → browser, for PDF |
DocumentFormat.OpenXml, for DOCX }.
Features:
- Embedded layout areas (
@@("…/area/Foo/…")) resolved to real document structure — see below. - Table of contents (built from document heading structure; PDF entries are links AND carry the page each section starts on — read back out of a first print, then verified against the published one, because CSS cannot name a target's page. See the doc page).
- Page break rules (before H1, between subtree children, explicit
\newpage/ ``). - Branded cover page, running header, and running footer (with
N / Mpage numbers in PDF) resolved from aCorporateIdentitymesh node. - MeshWeaver annotations become native Word comments and tracked changes in DOCX.
- Mermaid / MathJax SVGs captured from the client's already-rendered DOM and embedded as images.
Embedded layout areas
A document can embed a live view with @@(…). Every export resolves those embeds server-side,
because none of the three outputs has a browser session to fill them in later:
markdown ──parse──▶ ExportMarkdownPipeline ──find embeds──▶ LayoutAreaResolver.RenderEmbed
│
AreaMarkupRenderer
(one walk of the control tree)
│
┌────────────────────────────┴────────────────────┐
MarkupNode.Render() MarkupToDocument
→ HTML (email / print) → DocumentElement
(print HTML / OpenXml)
Two rules keep this from rotting the way it did before:
- One pipeline.
Ast/ExportMarkdownPipelineis used both to find embeds and to render the document, so whatever the resolver can find, the builder can render. The original defect was two pipelines:DocumentBuilderbuilt its own withoutLayoutAreaMarkdownExtension, so@@(…)parsed as a paragraph and every PDF/DOCX printed the embed's source text. - One control walk.
Html/AreaMarkupRendererreads the area once into aMarkupNodetree; HTML and the document model are two serializations of that tree, not two traversals. Teaching the renderer a new control reaches every format at once.
Resolution is reactive (it opens each area's synchronization stream and waits for the tree to settle) while the document build is a synchronous AST walk, so areas are resolved in a prior pass and looked up by key during the walk — the same split already used for client-captured Mermaid/Math SVGs.
An area that cannot be resolved becomes a visible, localized notice (export.areaUnavailable),
never a silent gap: a document that looks complete while missing a section its author placed is
worse than one that says so. One unresolvable area never fails the export.
Note on images: the content-fidelity renderers draw no images at all (both emit bracketed alt
text — Pdf/DocumentPrintComposer and Docx/DocxDocumentRenderer), so an area's pictures do not
appear in PDF/DOCX. Links do survive, absolutised against the portal's base URL so they still work
once the file is mailed on. The pixel path does render images, and inlines them as data: URIs
via SlideAssetInliner because its print document is loaded from file:// under a restrictive CSP.
Pixel-faithful deck export (opt-in)
Deck → PDF can additionally render pixel-faithfully (DocumentExportOptions.Fidelity = Pixel):
the deck is composed into one self-contained HTML document carrying the live stage CSS
(SlidePrintComposer.ThemeTokens + Pixel/SlidePrint.css) and printed by a headless browser, so CSS
gradients, background images, raw-HTML slide bodies, CSS layout and transforms survive — none of
which the document model can express.
The portal-ai image ships the browser (deploy/base-images/portal-ai: a Playwright
headless-shell Chromium at /usr/bin/chromium, CHROME_BIN set) — it has to, because since #1230
the browser prints every PDF, not just this one. Resolution stays overridable:
HeadlessChromiumPdfRenderer takes MarkdownExportConfig.PixelRendering.ExecutablePath, then
MESHWEAVER_CHROMIUM_PATH / CHROME_BIN / PUPPETEER_EXECUTABLE_PATH, then the platform's usual
locations. Where none exists, pixel fidelity is not offered and a PDF export fails loudly rather
than returning a file that quietly lost its formatting.
Full reference: Doc/Architecture/PixelFaithfulExport.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- DocumentFormat.OpenXml (>= 3.5.1)
- HtmlAgilityPack (>= 1.12.4)
- Markdig (>= 1.3.2)
- MeshWeaver.ContentCollections (>= 3.0.0-rc3)
- MeshWeaver.Data.Contract (>= 3.0.0-rc3)
- MeshWeaver.Graph (>= 3.0.0-rc3)
- MeshWeaver.Kernel.Hub (>= 3.0.0-rc3)
- MeshWeaver.Layout (>= 3.0.0-rc3)
- MeshWeaver.Markdown (>= 3.0.0-rc3)
- MeshWeaver.Markdown.Export.Contract (>= 3.0.0-rc3)
- MeshWeaver.Mesh.Contract (>= 3.0.0-rc3)
- MeshWeaver.Messaging.Hub (>= 3.0.0-rc3)
- UglyToad.PdfPig (>= 1.7.0-custom-5)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 3.0.0-rc3 | 38 | 8/16/2026 |
| 3.0.0-rc2 | 54 | 8/14/2026 |
| 3.0.0-rc1 | 48 | 8/13/2026 |
| 3.0.0-preview1 | 194 | 4/16/2026 |