Convert Markdown to Styled PDF in n8n
Convert Markdown to Styled PDF in n8n
在 n8n 中将 Markdown 转换为精美 PDF
The n8n Forum’s Most Repeated Question Search the n8n community forum for “Markdown to PDF” and you will find the same question asked repeatedly, with no satisfying answer. The replies fall into three categories. n8n 论坛中被问及次数最多的问题:在 n8n 社区论坛中搜索“Markdown to PDF”,你会发现同一个问题被反复提及,却始终没有令人满意的答案。回复通常分为三类:
“Use a Function node with Puppeteer.” This requires a Chromium binary in your n8n environment, headless browser rendering, and a pile of JavaScript to set up page sizes, margins, and print styles. Self-hosted n8n can make this work with enough effort. n8n Cloud cannot — there is no browser binary available. “使用带有 Puppeteer 的 Function 节点。”这需要在你的 n8n 环境中安装 Chromium 二进制文件、进行无头浏览器渲染,并编写大量的 JavaScript 代码来设置页面尺寸、页边距和打印样式。自托管的 n8n 在投入足够精力后可以实现,但 n8n Cloud 无法做到——因为那里没有可用的浏览器二进制文件。
“Use the HTML-to-PDF community node.” These nodes convert raw HTML, not Markdown. You need to convert Markdown to HTML first (another Function node), then style it with inline CSS (another Function node), then pass it to the PDF node. Three nodes of glue code, and the output still looks like a web page printed to PDF — no proper headers, footers, or page numbers. “使用 HTML-to-PDF 社区节点。”这些节点转换的是原始 HTML,而非 Markdown。你需要先将 Markdown 转换为 HTML(另一个 Function 节点),然后用内联 CSS 设置样式(再一个 Function 节点),最后将其传递给 PDF 节点。这需要三个节点的胶水代码,且输出结果看起来依然像是一个打印成 PDF 的网页——没有标准的页眉、页脚或页码。
“Export from Google Docs.” Create a Google Doc, write content via the API, export as PDF. This technically works but is not automatable for dynamic content. The Google Docs API for formatting is verbose and fragile, and you are creating throwaway documents just to get a PDF. None of these produce a professional document with consistent typography, a header on every page, a footer with page numbers, and controlled margins. “从 Google Docs 导出。”创建一个 Google 文档,通过 API 写入内容,然后导出为 PDF。这在技术上可行,但无法实现动态内容的自动化。Google Docs 的格式化 API 冗长且脆弱,你仅仅为了获取一个 PDF 却要创建一次性的文档。上述所有方法都无法生成具有统一排版、每页页眉、带页码页脚以及受控页边距的专业文档。
Markdown In, Styled PDF Out Iteration Layer Document Generation accepts Markdown content in paragraph blocks — via the markdown field — and renders it into a fully styled PDF. You control the fonts, page size, margins, header, footer, page numbers, heading styles, link colors, and table styling through a JSON document definition.
Markdown 输入,精美 PDF 输出:Iteration Layer 的文档生成功能支持通过 markdown 字段以段落块的形式接收 Markdown 内容,并将其渲染为格式精美的 PDF。你可以通过 JSON 文档定义来控制字体、页面尺寸、页边距、页眉、页脚、页码、标题样式、链接颜色和表格样式。
The Markdown content goes into “type”: “paragraph” blocks with a “markdown” field instead of a “text” field. The rendering engine parses the Markdown and applies your style definitions — headings get your heading font and size, links get your link color, code blocks get your code font, tables get your table styling. The output is a PDF that looks like it came from a design tool, not a browser print dialog. One API call. Fixed credit cost per document. No browser binary, no HTML intermediate step, no throwaway Google Docs.
Markdown 内容被放入 type: "paragraph" 块中,并使用 markdown 字段代替 text 字段。渲染引擎会解析 Markdown 并应用你定义的样式——标题会获得你设置的字体和大小,链接会获得指定的颜色,代码块会使用代码字体,表格则会应用表格样式。输出的 PDF 看起来就像是用专业设计工具制作的,而不是浏览器打印对话框的产物。只需一次 API 调用,每份文档固定扣费。无需浏览器二进制文件,无需 HTML 中间步骤,也无需一次性的 Google 文档。
The Workflow: Webhook to Styled PDF Here is what we are building in n8n: a webhook that receives Markdown content, converts it into a styled PDF with headers, footers, and page numbers, and stores the result. Three nodes. No Function nodes. No Puppeteer. 工作流:Webhook 到精美 PDF。以下是我们将在 n8n 中构建的内容:一个接收 Markdown 内容的 Webhook,将其转换为带有页眉、页脚和页码的精美 PDF,并存储结果。仅需三个节点,无需 Function 节点,无需 Puppeteer。
Step 1: Webhook Trigger Open the n8n canvas and add a new node. Search for “Webhook” and add it. In the node settings, set the HTTP Method to POST. Set Response Mode to “Last Node” so the workflow returns the generated PDF to the caller. The webhook will accept a JSON body with the Markdown content. 第一步:Webhook 触发器。打开 n8n 画布并添加一个新节点。搜索“Webhook”并添加。在节点设置中,将 HTTP 方法设置为 POST。将响应模式(Response Mode)设置为“Last Node”,以便工作流将生成的 PDF 返回给调用者。Webhook 将接收包含 Markdown 内容的 JSON 主体。
(Example JSON omitted for brevity) (示例 JSON 省略)
The Markdown content comes from wherever your process starts — a CMS, a form submission, a GitHub webhook, a previous workflow step, or a manual API call. Markdown 内容可以来自你流程的任何起点——CMS、表单提交、GitHub Webhook、上一个工作流步骤或手动 API 调用。
Step 2: Iteration Layer (Document Generation) Add an Iteration Layer node after the webhook trigger. In the Resource dropdown, select Document Generation. Set the Format to pdf. In the Document JSON field, define the full document structure. 第二步:Iteration Layer(文档生成)。在 Webhook 触发器后添加一个 Iteration Layer 节点。在资源下拉菜单中选择“Document Generation”。将格式设置为“pdf”。在“Document JSON”字段中,定义完整的文档结构。
(Example JSON configuration omitted for brevity) (示例 JSON 配置省略)
The key pieces: 关键部分:
- Page setup: A4 with generous margins. The top margin is larger to accommodate the header. Adjust size to “Letter” for US standard. 页面设置: A4 纸张,留有充足的页边距。顶部边距较大,以便容纳页眉。对于美国标准,可将尺寸调整为“Letter”。
- Styles: Global font, heading hierarchy with decreasing sizes, link styling, and code block formatting. These styles apply to all Markdown content in the document. 样式: 全局字体、递减的标题层级、链接样式和代码块格式。这些样式适用于文档中的所有 Markdown 内容。
- Header: Appears on every page. The document title in small gray text with a subtle bottom border. The header sits inside the top margin area. 页眉: 出现在每一页。文档标题以灰色小字显示,并带有细微的底部边框。页眉位于顶部页边距区域内。
- Footer: Appears on every page. Author name, page number, and total page count — centered with a top border. {{page_number}} and {{total_pages}} are built-in template variables that the rendering engine resolves.
页脚: 出现在每一页。包含作者姓名、页码和总页数,居中显示并带有顶部边框。
{{page_number}}和{{total_pages}}是渲染引擎会自动解析的内置模板变量。 - Content: A headline block for the document title, followed by a paragraph block with “markdown” instead of “text”. The Markdown field accepts the full Markdown string and renders it according to the style definitions above.
内容: 一个用于文档标题的标题块,后跟一个使用
markdown而非text的段落块。Markdown 字段接收完整的 Markdown 字符串,并根据上述样式定义进行渲染。
The paragraph block with the markdown field is what makes this work. All Markdown syntax — headings, bold, italic, links, tables, code blocks, lists — renders with your defined styles. No HTML intermediate. No CSS. The JSON definition controls everything.
带有 markdown 字段的段落块是实现这一功能的关键。所有的 Markdown 语法——标题、粗体、斜体、链接、表格、代码块、列表——都会按照你定义的样式进行渲染。无需 HTML 中间步骤,无需 CSS。一切尽在 JSON 定义之中。