Transpile CommonMark Markdown to Typst, from within Typst!

Overview
#set document(title: "cmarker.typ") #set page(numbering: "1", number-align: center) #set text(lang: "en") #align(center, text(weight: 700, 1.75em)[cmarker.typ]) #set heading(numbering: "1.") #show link: c => text(underline(c), fill: blue) #set image(height: 2em) #show par: set block(above: 1.2em, below: 1.2em) #align(center)[ https://github.com/SabrinaJewson/cmarker.typ] #"

cmarker

This package enables you to write CommonMark Markdown, and import it directly into Typst.

simple.typ simple.md
#import "@preview/cmarker:0.1.0"

#cmarker.render(read("simple.md"))
# We can write Markdown!

*Using* __lots__ ~of~ `fancy` [features](https://example.org/).
simple.pdf

This document is available in Markdown and rendered PDF formats.

API

We offer a single function:

render(
  markdown,
  smart-punctuation: true,
  blockquote: none,
  h1-level: 1,
  raw-typst: true,
  scope: (:),
  show-source: false,
) -> content

The parameters are as follows:

  • markdown: The CommonMark Markdown string to be processed. Parsed with the pulldown-cmark Rust library. You can set this to read("somefile.md") to import an external markdown file; see the documentation for the read function.

    • Accepted values: All strings.
    • Required.
  • smart-punctuation: Automatically convert ASCII punctuation to Unicode equivalents:

    • nondirectional quotations (" and ') become directional (“” and ‘’);
    • three consecutive full stops (...) become ellipses (…);
    • two and three consecutive hypen-minus signs (-- and ---) become en and em dashes (– and —).

    Note that although Typst also offers this functionality, this conversion is done through the Markdown parser rather than Typst.

    • Accepted values: Booleans.
    • Default value: true.
  • blockquote: A callback to be used when a blockquote is encountered in the Markdown, or none if blockquotes should be treated as normal text. Because Typst does not support blockquotes natively, the user must configure this.

    • Accepted values: Functions accepting content and returning content, or none.
    • Default value: none.

    For example, to display a black border to the left of the text one can use:

     box.with(stroke: (left: 1pt + black), inset: (left: 5pt, y: 6pt))
    
  • h1-level: The level that top-level headings in Markdown should get in Typst. When set to zero, top-level headings are treated as text, ## headings become = headings, ### headings become == headings, et cetera; when set to 2, # headings become == headings, ## headings become === headings, et cetera.

    • Accepted values: Integers in the range [0, 255].
    • Default value: 1.
  • raw-typst: Whether to allow raw Typst code to be injected into the document via HTML comments. If disabled, the comments will act as regular HTML comments.

    • Accepted values: Booleans.
    • Default value: true.

    For example, when this is enabled, <!--raw-typst #circle(radius: 10pt) --> will result in a circle in the document (but only when rendered through Typst). See also <!--typst-begin-exclude--> and <!--typst-end-exclude-->, which is the inverse of this.

  • scope: When raw-typst is enabled, this is a dictionary providing the context in which the evaluated Typst code runs. It is useful to pass values in to code inside <!--raw-typst--> blocks.

    • Accepted values: Any dictionary.
    • Default value: (:).
  • show-source: A debugging tool. When set to true, the Typst code that would otherwise have been displayed will be instead rendered in a code block.

    • Accepted values: Booleans.
    • Default value: false.

This function returns the rendered content.

Supported Markdown Syntax

We support CommonMark with a couple extensions.

  • Paragraph breaks: Two newlines, i.e. one blank line.
  • Hard line breaks (used more in poetry than prose): Put two spaces at the end of the line.
  • *emphasis* or _emphasis_: emphasis
  • **strong** or __strong__: strong
  • ~strikethrough~: strikethrough
  • [links](https://example.org): links
  • ### Headings, where # is a top-level heading, ## a subheading, ### a sub-subheading, etc
  • `inline code blocks`: inline code blocks
  •  ```
     out of line code blocks
     ```
    
    Syntax highlighting can be achieved by specifying a language after the opening backticks:
     ```rust
     let x = 5;
     ```
    
    giving:
     let x = 5;
  • ---, making a horizontal rule:

  •  - Unordered
     - lists
    • Unordered
    • Lists
  •  1. Ordered
     1. Lists
    1. Ordered
    2. Lists
  • > blockquotes, if the blockquote parameter is set.
  • Images: ![Some tiled hexagons](examples/hexagons.png), giving Some tiled hexagons

Interleaving Markdown and Typst

Sometimes, you might want to render a certain section of the document only when viewed as Markdown, or only when viewed through Typst. To achieve the former, you can simply wrap the section in <!--typst-begin-exclude--> and <!--typst-end-exclude-->:

<!--typst-begin-exclude-->
Hello from not Typst!
<!--typst-end-exclude-->

Most Markdown parsers support HTML comments, so from their perspective this is no different to just writing out the Markdown directly; but cmarker.typ knows to search for those comments and avoid rendering the content in between.

Note that when the opening comment is followed by the end of an element, cmarker.typ will close the block for you. For example:

> <!--typst-begin-exclude-->
> One

Two

In this code, “Two” will be given no matter where the document is rendered. This is done to prevent us from generating invalid Typst code.

Conversely, one can put Typst code inside a HTML comment of the form <!--raw-typst […]--> to have it evaluated directly as Typst code (but only if the raw-typst option to render is set to true, otherwise it will just be seen as a regular comment and removed):

<!--raw-typst Hello from #text(fill:blue)[Typst]!-->

Markdown–Typst Polyglots

This project has a manual as a PDF and a README as a Markdown document, but by the power of this library they are in fact the same thing! Furthermore, one can read the README.md in a markdown viewer and it will display correctly, but one can also run typst compile README.md to generate the Typst-typeset README.pdf.

How does this work? We just have to be clever about how we write the README:

<picture>
(Typst preamble content)
#"</picture>
<!--".slice(0,0)
#import "@preview/cmarker:0.1.0"
#let markdown = read("README.md")
#markdown = markdown.slice(markdown.position("</picture>") + "</picture>".len())
#cmarker.render(markdown, h1-level: 0)
/*-->

Regular Markdown goes here…

<!--*///-->

The same code but syntax-highlighted as Typst code helps to illuminate it:

<picture>
(Typst preamble content)
#"</picture>
<!--".slice(0,0)
#import "@preview/cmarker:0.1.0"
#let markdown = read("README.md")
#markdown = markdown.slice(markdown.position("</picture>") + "</picture>".len())
#cmarker.render(markdown, h1-level: 0)
/*-->

Regular Markdown goes here…

<!--*///-->

Limitations

  • We do not currently support HTML tags, and they will be stripped from the output; for example, GitHub supports writing <sub>text</sub> to get subscript text, but we will render that as simply “text”. In future it would be nice to support a subset of HTML tags.
  • We do not currently support Markdown tables and footnotes. In future it would be good to.
  • Although I tried my best to escape everything correctly, I won’t provide a hard guarantee that everything is fully sandboxed even if you set raw-typst: false. That said, Typst itself is well-sandboxed anyway.

Development

  • Build the plugin with ./build.sh, which produces the plugin.wasm necessary to use this.
  • Compile examples with typst compile examples/{name}.typ --root ..
  • Compile this README to PDF with typst compile README.md.
You might also like...
mdBook is a utility to create modern online books from Markdown files.

Create book from markdown files. Like Gitbook but implemented in Rust

Tools - The Rome Toolchain. A linter, compiler, bundler, and more for JavaScript, TypeScript, HTML, Markdown, and CSS.
Tools - The Rome Toolchain. A linter, compiler, bundler, and more for JavaScript, TypeScript, HTML, Markdown, and CSS.

Rome is currently being rewritten in Rust. Read more about it in our latest blog post. The documentation below is out of date and available for poster

A command-line tool aiming to upload the local image used in your markdown file to the GitHub repo and replace the local file path with the returned URL.
A command-line tool aiming to upload the local image used in your markdown file to the GitHub repo and replace the local file path with the returned URL.

Pup A command line tool aiming to upload the local image used in your markdown file to the GitHub repo and replace the local file path with the return

Introducing Inlyne, a GPU powered yet browsless tool to help you quickly view markdown files in the blink of an eye.
Introducing Inlyne, a GPU powered yet browsless tool to help you quickly view markdown files in the blink of an eye.

Inlyne - a GPU powered, browserless, markdown + html viewer inlyne README.md --theme dark/light About Markdown files are a wonderful tool to get forma

A Faster(⚡)  formatter, linter, bundler, and more for JavaScript, TypeScript, JSON, HTML, Markdown, and CSS Lapce Plugin
A Faster(⚡) formatter, linter, bundler, and more for JavaScript, TypeScript, JSON, HTML, Markdown, and CSS Lapce Plugin

Lapce Plugin for Rome Lapce-rome is a Lapce plugin for rome, The Rome is faster ⚡ , A formatter, linter, compiler, bundler, and more for JavaScript, T

scan markdown files and execute `console` blocks

exec-commands − scan markdown files and execute console blocks exec-commands is a utility to update command-line-tool examples embedded in markdown fi

mn is my project to learn rust, I will try to build a markdown editor

med is a markdown editor This is my project to learn rust programming language, I will try to build a powerful markdown editor. Highlight: Support Vim

Simple, omniglot, markdown-based literate programming and living documentation

Betwixt Simple, markdown-based, polyglot literate programming and documentation tests. Read code between the lines Summary Betwixt is heavily inspired

Simple, lightweight, markdown-based notes app I might actually finish eventually

Jupiter A simple markdown & git-based notes app for Linux. Features Lightweight with minimal dependencies Git integration for syncing & versioning Sea

Comments
  • Superscript and subscript HTML tags

    Superscript and subscript HTML tags

    I don’t want to embed a full HTML parser, but I think we can support some basic usage of HTML tags. In particular, GitHub supports:

    • Subscript with <sub>xyz</sub>: xyz
    • Superscript with <sup>xyz</sup>: xyz
    enhancement 
    opened by SabrinaJewson 0
  • Supporting Markdown footnotes

    Supporting Markdown footnotes

    Markdown has footnotes, and we could support them in cmarker. The main difficulty here is that the Markdown parser gives us footnotes in an out-of-band format, whereäs Typst expects them in an in-band format, and so our current single-pass approach would be insufficiënt. I think I would only like to parse the Markdown once, so the strategy I would choose is building a Vec<(usize, CowStr<'_>)> of “places we need to insert a footnote” in our single pass, then add a second pass to fill them in.

    enhancement 
    opened by SabrinaJewson 0
  • Supporting TeX code blocks

    Supporting TeX code blocks

    It would be useful to support TeX code blocks and have them be automatically rendered as Typst math equations. Currently, the only way to achieve this is writing out the equation in both TeX and Typst and using a combination of <!--typst-begin-exclude--> and <!--raw-typst-->.

    enhancement 
    opened by SabrinaJewson 0
Owner
Sabrina Jewson
Hobbyist Rust programmer
Sabrina Jewson
Shell Escape for Typst typesetting system. Linux Only.

Shell Escape for Typst This is a simple shell escape for Typst. It allows you to run shell commands directly from Typst compiler. That said, it does n

Nikolay Stepanov 4 Jun 7, 2023
Packages for Typst.

Typst Packages An experimental package repository for Typst. A searchable list of all packages that were submitted here is available in the official d

Typst 91 Jul 4, 2023
An mdBook backend to output Typst markup, pdf, png, or svg

mdbook-typst mdbook-typst is a backend for mdBook. The backend converts the book to Typst markup and can output any format Typst can (currently pdf, p

Christian Legnitto 18 Dec 16, 2023
LaTeX support for Typst, powered by Rust and WASM.

MiTeX LaTeX support for Typst, powered by Rust and WASM. MiTeX processes LaTeX code into an abstract syntax tree (AST). Then it transforms the AST int

null 58 Jan 1, 2024
A tool to compare how Typst documents would look using different fonts or font variants.

typst-font-compare A tool to compare how Typst documents would look using different fonts or font variants. Installation cargo install --path . Usage

null 3 Feb 15, 2024
🦀️atos for linux by rust - A partial replacement for Apple's atos tool for converting addresses within a binary file to symbols.

atosl-rs ??️ atos for linux by rust - A partial replacement for Apple's atos tool for converting addresses within a binary file to symbols. tested on

everettjf 60 Dec 29, 2022
A command line tool for people of transgender experience to replace their deadname within a Git repo.

chowndn (Change Owner from Dead Name) A command line tool for people of transgender experience to replace their dead name within a Git repo. See chown

Christi Miller 23 Dec 6, 2022
A blazingly fast rust-based bionic reader for blazingly fast reading within a terminal console 🦀

This Rust-based CLI tool reads text and returns it back in bionic reading format for blazingly fast loading and even faster reading! Bionic reading is

Ismet Handzic 5 Aug 5, 2023
A command-line utility which aligns a block of text within the terminal (or a specified number of columns), written in Rust.

align: a command line utility for aligning text. ⭐ Overview Aligns text within the terminal (or a specified number of columns). The text is treated as

Khalil Ouali 6 Aug 11, 2023
A versatile and dynamic music bot designed to elevate the musical experience within Discord servers.

Masayoshi Masayoshi is a discord music bot written in Rust for making a great experience within Discord servers with support to Youtube, SoundCloud, S

null 6 Dec 26, 2023