Markdown to HTML
Convert Markdown to HTML. Stdlib only — no pip install. Raw HTML in the input is escaped by default so the output is safe to send in an email body without worrying about user-supplied <script> tags executing.
Tool ID
markdown-to-html
Credential Required
No.
Input Properties
| Property | Type | Default | Description |
|---|---|---|---|
markdown |
string | "" |
Markdown text to convert. Use this OR file, one required. |
file |
string | "" |
Path to a .md file to read. Use this OR markdown. |
wrap |
string | "fragment" |
fragment = just the converted HTML body. full = complete <!DOCTYPE html> document with inline CSS, suitable for sending as the whole email body or saving as a standalone .html file. |
title |
string | "" |
Title for the <title> tag when wrap=full. Ignored otherwise. |
Published Outputs
| Output | Description |
|---|---|
html |
The converted HTML |
length |
Character count of the HTML output |
wrapped |
"true" if full document, "false" if fragment |
Supported Markdown features
| Markdown | HTML |
|---|---|
# H1 through ###### H6 |
<h1> … <h6> |
**bold** / __bold__ |
<strong> |
*italic* / _italic_ |
<em> |
~~strike~~ |
<del> |
`inline code` |
<code> |
```lang\n...\n``` |
<pre><code class="language-lang"> |
- item, * item, + item |
<ul><li> |
1. item |
<ol><li> |
> quote |
<blockquote> |
[text](url) |
<a href> |
 |
<img src alt> |
---, ***, ___ |
<hr> |
Bare https://... URL |
Autolinked |
| Two trailing spaces | <br> |
| Blank line between blocks | Paragraph boundary |
Not supported
Deliberately scoped down. Nested lists of arbitrary depth, tables, HTML passthrough, footnotes, and definition lists are not handled. If your input uses those, the text is rendered as literal text (safe fallback, ugly output). For those cases, use pandoc via runtime-env instead of this tool.
Example — fragment (typical email body)
Input:
tool: markdown-to-html
properties:
markdown: |
# Daily Brief
**San Francisco**: 55°F, overcast. Rain tomorrow.
## Stocks
- AAPL: $266.01
- MSFT: $424.35
[Full report](https://example.com/report)
wrap: fragment
Actual captured output:
<h1>Daily Brief</h1>
<p><strong>San Francisco</strong>: 55°F, overcast. Rain tomorrow.</p>
<h2>Stocks</h2>
<ul>
<li>AAPL: $266.01</li>
<li>MSFT: $424.35</li>
</ul>
<p><a href="https://example.com/report">Full report</a></p>
Example — full document
With wrap: full and title: "My Report", you get a complete styled document:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>My Report</title>
<style>
body { font-family: -apple-system, Segoe UI, Roboto, sans-serif;
max-width: 720px; margin: 2em auto; padding: 0 1em; color: #222;
line-height: 1.5; }
/* ...etc */
</style>
</head>
<body>
...your content...
</body>
</html>
Ready to save as an .html file, attach to an email, or use as the body of an HTML email.
Chaining Patterns
- AI task (anthropic/openai/etc.) → markdown-to-html → email AI generates a markdown report, this tool formats it as HTML, email task sends. The common "pretty AI output" pipeline.
- rss-reader → ai → markdown-to-html → email — daily digest, summarized, pretty.
- daily-brief → markdown-to-html → email — upgrade the
daily-briefjob from plain text to nicely formatted HTML. - file-management (read .md) → markdown-to-html → file-management (write .html) — convert a docs folder of .md to .html.
XSS safety
Raw HTML in the input is HTML-escaped. This is confirmed behavior, not aspirational:
Input:
Hello <script>alert(1)</script>
<img src=x onerror=alert(2)>
Output (escaped, not executed):
<p>Hello <script>alert(1)</script></p>
<p><img src=x onerror=alert(2)></p>
So you can safely pass untrusted markdown (e.g. AI-generated content, or user-submitted text) through this tool and render the result in an email client or browser without XSS exposure. The trade-off is you can't intentionally embed raw HTML — use the markdown syntax instead.
Email integration tip
For HTML email with the email tool, set the body to the output of this tool and the contentType to text/html. Most modern mail clients render the styling. For strict formatting, use wrap=full and the inline CSS will travel with the email.