A JavaScript library for converting Markdown to Typst code.
See as an example use case the demo of this repository published as a static website: https://Mapaor.github.io/markdown2typst.
- ✔ Headings
- ✔ Bold, italics, striketrought, code
- ✔ Bulleted lists, numbered lists
- ✔ Links
- ✔ Images (only local)
- ✔ Math (inline and block equations)
- ✔ Tables
- ✔ Quotes
- ✔ Code blocks (with highlighting)
- ✔ Dividers (horizontal rule)
- ✔ Footnotes
- ✔ Table of Contents (ToC)
- ✘ Mermaid diagrams --> Coming soon(!)
- ✘ Checklists --> Coming soon(!)
- ✘ HTML, GeoJSON, STL --> Not Typst compatible.
Only works with YAML for now, TOML support is planned.
Currently supported keys:
title(rich text string)author(string or array of strings)description(string)keywords(array of strings)date(YYYY-MM-DD string)abstract(rich text string)lang(string)region(string)
For more information see Typst Document Function, Jekyll Frontmatter Docs or check the examples.
Chosen display of the front-matter keys or custom options parameters (example)
By design the choice has been to support mainly the Typst document parameters, that in principle are just metadata. However the title, and author and date are also displayed. Those could be displayed in any way in Typst, the chosen one has been the more basic and default way: simply non-style top-centered Title, author and date. With newlines between them. Support for setting the language and a custom abstract in the frontmatter (or custom options) has also been added.
The following is a complete Markdown example of all the supported front-matter keys:
---
title: The Fellowship of the Ring
author:
- John Doe
- Jack Doe
- Jane Doe
description: This is just an example document, this information is in principle stored as metadata only but it can be displayed using context document.
keywords:
- example
- document
- lotr
- typst
date: 2026-01-12
abstract: In this paper we assess the impacts of the One Ring on Middle Earth and its inhabitants, analyzing both economic and social factors.
lang: en
region: gb
---
And the corresponding Typst output is:
// =============== FRONTMATTER ===============
#set document(
title: [The Fellowship of the Ring],
author: ("John Doe", "Jack Doe", "Jane Doe"),
description: [This is just an example document, this information is in principle stored as metadata only but it can be displayed using context document.],
keywords: ("example", "document", "lotr", "typst"),
date: datetime(day: 12, month: 1, year: 2026)
)
#let abstract = [In this paper we assess the impacts of the One Ring on Middle Earth and its inhabitants, analyzing both economic and social factors.]
#align(center)[
#title() \ \ #context document.author.join(", ", last: " & ") \ \ #context document.date.display() \ \ \ *Abstract* \ #abstract
]
#set text(lang: "en", region: "gb")
// ============================================
Note: any non-standard key is simply ignored, all keys are optional. The front-matter as a whole is obviously also optional.
Package link:
https://www.npmjs.com/package/markdown2typst
Install it:
npm install markdown2typst<script src="https://cdn.jsdelivr.net/npm/markdown2typst@latest/dist/markdown2typst.min.js"></script>
<script src="https://unpkg.com/markdown2typst@latest/dist/markdown2typst.min.js"></script>
# Clone the repository
git clone https://github.com/Mapaor/markdown2typst.git
cd markdown2typst
# Install dependencies
npm install
# Build the bundle
npm run buildA javascript bundle will appear in the dist folder. Make the desired changes to the library and then build again if you need. To test your modifications still comply with what's expected from the library run the tests.
# Testing
npm run testimport { markdown2typst } from 'markdown2typst';
const markdown = '# Hello Typst\n\nThis is a **test**.';
const typst = markdown2typst(markdown);
console.log(typst);import { markdown2typst } from 'markdown2typst';
import { readFileSync } from 'fs';
const markdown = readFileSync('./example-file.md', 'utf-8');
const typst = markdown2typst(markdown);
console.log(typst);Suppose you've downloaded the JS bundle and saved it in a assets folder, now for using it in your website you would simply do:
import { markdown2typst } from './assets/markdown2typst.min.js';
const markdown = '# Hello Typst\n\nThis is a **test**.';
const typst = markdown2typst(markdown);
console.log(typst);<script type="module">
import { markdown2typst } from './assets/markdown2typst.min.js';
const markdown = '# Hello Typst';
const typst = markdown2typst(markdown);
console.log(typst);
</script><script src="https://cdn.jsdelivr.net/npm/markdown2typst@latest/dist/markdown2typst.min.js"></script>
<script>
const markdown = '# Hello Typst\n\nThis is a **test**.';
const typst = markdown2typst(markdown);
console.log(typst);
</script>import markdown2typst from 'https://cdn.jsdelivr.net/npm/markdown2typst@latest/dist/markdown2typst.min.js';
const markdown = '# Hello Typst\n\nThis is a **test**.';
const typst = markdown2typst(markdown);
console.log(typst);Which is what the demo uses.
See the Examples page for basic and advanced examples on how to use the library and all the features it supports.
Check the Architecture doc for getting a better understanding of how the library works under the hood.
Contributions are more than welcome! See the Contributing guide.
Built thanks to the following open-source projects:
- unified - Text processing framework
- remark - Markdown processor. Plugins used:
- esbuild - Fast bundler
- tex2typst - Typst conversion for LaTeX equations
- js-yaml - YAML parser
This code was initially based on the code by zhaoyiqun (@cosformula on GitHub), more specifically in his markdownToTypst.ts custom conversion library (renderer to Typst code) built for his open source project MDXport.
- Finish an initial working version
- Add frontmatter support and also allow to pass the keys as custom options of the main function
- Publish to npm
- Add a comprehensive test suite
- Add CLI tool
- Support custom templates
- Support more Markdown extensions/flavors/specs