GFM + XSS sanitization, all in your browser
Markdown is a lightweight markup language by John Gruber (2004) that converts plain text to HTML. It's used in README files on GitHub, Slack messages, Discord, Notion, Reddit, Stack Overflow. This converter supports GitHub-Flavored Markdown (GFM) — tables, fenced code blocks, task lists and auto-links. Output is sanitized with DOMPurify against XSS.
Markdown is a lightweight markup language created in 2004 by John Gruber together with Aaron Swartz. The goal: write text in plain text that is still structured and can be converted to HTML easily. Today Markdown is the de facto standard for technical documentation and is used on GitHub (READMEs, issues, pull requests), Notion, Discord, Slack, Reddit, Stack Overflow and in many static site generators (Jekyll, Hugo, Next.js, Astro).
.md file opens, diffs and merges cleanly in any text editor, any Git repository and any platform.The following elements cover 90% of everyday use:
# Heading 1
## Heading 2
### Heading 3
**bold text** *italic text* ~~strikethrough~~
- bullet list item
- another item
- nested item
1. ordered list item
2. second item
[Link text](https://calcsi.com)

`inline code`
```js
// fenced code block
console.log('Hello, Markdown');
```
| Column A | Column B |
| -------- | -------- |
| cell 1 | cell 2 |
| cell 3 | cell 4 |
> A blockquote.
- [x] completed task
- [ ] open task
- [ ]), strikethrough (~~text~~), auto-links and syntax highlighting for code blocks. This tool uses GFM by default.README.md as its entry point.The tool uses the marked library with gfm: true and breaks: true enabled — that is GitHub Flavored Markdown on top of CommonMark. This covers nearly all GitHub-, Slack- and Notion-compatible Markdown.
No. Conversion runs entirely in the browser via the marked and DOMPurify JavaScript libraries. Your text never leaves your device. You can even disconnect from the network once the page is loaded.
Use the syntax . Example: . The alt text matters for accessibility and SEO. To set size or class, you can write an <img> tag directly — the converter accepts inline HTML.
Yes. Markdown allows inline HTML, so you can use e.g. <details> for collapsible sections or <kbd> for keystrokes. Note: the result is sanitized with DOMPurify before display, removing <script>, inline event handlers and similar XSS vectors.
Yes. With GFM enabled, pipe tables are supported — columns are separated with | and the header is separated from data rows by a --- divider. Alignment is set with colons: :--- left, :---: center, ---: right.
Yes. Click the Copy HTML button to copy the rendered HTML to your clipboard, then paste it in an email client, CMS or code editor.
Markdown was released in 2004 by John Gruber as a "text-to-HTML" writing language and has since become the lingua franca of developer documentation, README files, static site generators and chat tools. For a long time there was no formal spec, which led to dozens of incompatible parsers. CommonMark (commonmark.org) finally defined the syntax precisely in 2014: # headings, **bold**, *italic*, lists with - or 1., code with backticks, links as [text](url), blockquotes with > and inline HTML are now interpreted the same everywhere.
Beyond CommonMark, GitHub Flavored Markdown (GFM), MultiMarkdown and MDX have become widespread. GFM adds pipe tables (| A | B |), strikethrough with ~~text~~, task lists (- [ ], - [x]), autolinks and language-hinted code fences (```js). Our converter uses the marked library with { gfm: true, breaks: true } — so you get all GFM features plus hard line breaks, just like GitHub Issues and Slack render them.
Security-critical: Markdown allows embedded HTML, and a naive renderer would let an attacker inject XSS. We therefore pipe the HTML output through DOMPurify, which strips dangerous tags (<script>, <iframe>), on* event handlers and javascript: URLs before Vue's v-html renders. That way you can safely preview Markdown from untrusted sources.
Conversion is live — everything happens client-side, with no upload. Follow these steps:
# for headings, - or * for lists, **bold** and *italic*.| and a separator row | --- |, task lists with - [x], code fences with language hint such as ```python.Copy HTML to put the rendered, DOMPurify-sanitized HTML on your clipboard — ready to paste into a CMS, email template or static site..md, version it in Git and use the tool as a quick preview. The source stays versioned, while the HTML build happens in CI.Here are typical Markdown inputs and their HTML results:
# Title turns into <h1>Title</h1>, ## Subtitle into <h2>Subtitle</h2> and so on through level 6.**Important** renders as <strong>Important</strong>, *emphasis* as <em>emphasis</em>, `code` as <code>code</code>.| Name | Age |\n| ---- | --- |\n| Anna | 29 | renders a full <table> with <thead> and <tbody>.js plus code plus three backticks produces <pre><code class="language-js">...</code></pre> — ready for Highlight.js or Prism.- [x] done and - [ ] open produce <input type="checkbox" checked disabled> and unchecked — perfect for issues and to-do lists.Markdown is intentionally minimal — anything beyond CommonMark + GFM is non-portable. First: footnotes, definition lists and math (KaTeX) are part of neither CommonMark nor GFM; Pandoc and MultiMarkdown handle them, our converter does not. If you need math, embed $$E=mc^2$$ and have KaTeX or MathJax render it downstream. Second: frontmatter. YAML blocks at file top (---\ntitle: X\n---) belong to static site generators (Jekyll, Hugo, MkDocs), not to Markdown syntax. They would render here as heading ---. Third and critical — XSS: Markdown allows <script> tags and <a href="javascript:..."> links as inline HTML. A naive renderer would execute the payload. We filter the HTML output with DOMPurify; dangerous tags, event-handler attributes and JS URLs are removed before Vue renders. Even with that protection, never trust unknown Markdown blindly in production — some user-provided Markdown engines enable allowDangerousHtml by default, bypassing sanitization. Fourth: HTML encoding. Characters like < and > must be written as </> when meant literally — otherwise Markdown reads them as HTML. Fifth: link prefetching. Browsers may prefetch http(s):// links on hover. For sensitive URLs (magic links) that is a privacy issue; use rel="noopener noreferrer" or nofollow.
breaks: true). Not supported: footnotes, MathJax/KaTeX, frontmatter, MDX/JSX.<script>, <iframe>, on* handlers and javascript: URLs. For production we still recommend an additional Content Security Policy (script-src 'self'), because defense in depth is always better.`x = 1`), triple for blocks (with language hint ```js). Markdown automatically turns this into <code> elements and HTML-encodes characters like <, so the browser will not execute anything.| --- |, otherwise pipes are interpreted as text. Example: | Name | Age | <br> | --- | --- | <br> | Anna | 29 |. Also, every row must have the same column count.. For larger texts a CDN is preferable.marked and DOMPurify run as JavaScript libraries entirely client-side. No data is sent to CalcSI. Copy-to-clipboard uses the local navigator.clipboard API too.