Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/xecades/markdown-it-typst

Plugin to transform Typst code to SVG image for markdown-it markdown parser.
https://github.com/xecades/markdown-it-typst

markdown markdown-it typst

Last synced: 2 days ago
JSON representation

Plugin to transform Typst code to SVG image for markdown-it markdown parser.

Awesome Lists containing this project

README

        

# markdown-it-typst

[![npm version][npm-version-src]][npm-version-href]
[![npm downloads][npm-downloads-src]][npm-downloads-href]
[![bundle][bundle-src]][bundle-href]
[![JSDocs][jsdocs-src]][jsdocs-href]
[![License][license-src]][license-href]

A simple [`typst.ts`](https://github.com/Myriad-Dreamin/typst.ts) wrapper that adds [Typst](https://github.com/typst/typst) support to [`markdown-it`](https://github.com/markdown-it/markdown-it).

**WARNING**: It's NOT recommended to run this plugin on browser side, as it is not optimized for tree-shaking. (See [`typst.ts` Documentation](https://myriad-dreamin.github.io/typst.ts/cookery/guide/all-in-one-node.html)) However, utilizing the browser-side version of `typst.ts` is still possible, any PRs regarding this are welcome.

---

## Usage

```bash
npm install markdown-it-typst
```

```ts
import MarkdownIt from "markdown-it";
import MarkdownItTypst from "markdown-it-typst";

const md = new MarkdownIt().use(MarkdownItTypst);
const code = `
\`\`\`typst
#set text(font: "New Computer Modern")

Let $a$, $b$, and $c$ be the side
lengths of right-angled triangle.
Then, we know that:
$ a^2 + b^2 = c^2 $

Prove by induction:
$ sum_(k=1)^n k = (n(n+1)) / 2 $
\`\`\`
`;

const html = md.render(code);

console.log(html);

// Output:
//
//


//
// [...]
//
//

```

The code above will render the following web page (Without additional styling):

![](./images/result1.png)

---

## Features

- **Able to import packages**:

~~~md
**Normal** *Markdown* code :-)

```typst
#import "@preview/cetz:0.2.2": canvas, draw, tree
#canvas(length: 2.5cm, {
import draw: *
tree.tree(
draw-node: (node, ..) => {
if node.content == [] { return none }
circle((), radius: .35, stroke: black)
content((), [#node.content])
},
draw-edge: (from, to, pa, child) => {
if child.content == [] { return none }
tree.default-draw-edge(from, to, pa, child)
},
([15], ([13], [12], [14]), ([17], [16], ([18], [], [18])))
)
})
```
~~~

![](./images/result2.png)

- **Able to import external files**:

~~~md
```typst
#figure(
image("./images/cat.png", width: 200pt),
caption: [`/bin/cat`],
)
```
~~~

![](./images/result3.png)

---

## Options

Default options:

```ts
const md = new MarkdownIt().use(MarkdownItTypst, {
identifier: "typst",
typstWrapper: (code: string) =>
"#set page(width: auto, height: auto, margin: 5pt)\n" +
"#set text(size: 18pt)\n" +
code,
svgWrapper: (svg: string) => '

\n' + svg + "\n
",
});
```

### `identifier`

- Type: `string | string[]`
- Default: `"typst"`

The language identifier(s) of the Typst code block. Only code blocks with the specified identifiers will be processed.

### `typstWrapper`

- Type: `(code: string) => string`
- Default: `(code: string) => "#set page(width: auto, height: auto, margin: 5pt)\n#set text(size: 18pt)\n" + code`

Typst code will be wrapped with this function before being compiled.

### `svgWrapper`

- Type: `(svg: string) => string`
- Default: `(svg: string) => '

\n' + svg + "\n
"`

The SVG output will be wrapped with this function during rendering.

---

## Examples

The probably most handy application is to render CeTZ graphs in Markdown:

```ts
const md = new MarkdownIt().use(MarkdownItTypst, {
typstWrapper: (code: string) =>
"#set page(width: auto, height: auto, margin: 5pt)\n" +
'#import "@preview/cetz:0.2.2": canvas, draw, vector, matrix\n' +
"#canvas(length: 1cm, {\n" +
" import draw: *\n" +
code +
"})",
identifier: "cetz",
});
```

~~~md
Electromagnetic waves are **transverse** waves:

```cetz
// Code borrowed from CeTZ: https://typst.app/universe/package/cetz/

// Set up the transformation matrix
set-transform(matrix.transform-rotate-dir((1, 1, -1.3), (0, 1, .3)))
scale(x: 1.5, z: -1)

grid((0,-2), (8,2), stroke: gray + .5pt)

// Draw a sine wave on the xy plane
let wave(amplitude: 1, fill: none, phases: 2, scale: 8, samples: 100) = {
line(..(for x in range(0, samples + 1) {
let x = x / samples
let p = (2 * phases * calc.pi) * x
((x * scale, calc.sin(p) * amplitude),)
}), fill: fill)

let subdivs = 8
for phase in range(0, phases) {
let x = phase / phases
for div in range(1, subdivs + 1) {
let p = 2 * calc.pi * (div / subdivs)
let y = calc.sin(p) * amplitude
let x = x * scale + div / subdivs * scale / phases
line((x, 0), (x, y), stroke: rgb(0, 0, 0, 150) + .5pt)
}
}
}

group({
rotate(x: 90deg)
wave(amplitude: 1.6, fill: rgb(0, 0, 255, 50))
})
wave(amplitude: 1, fill: rgb(255, 0, 0, 50))
```
~~~

![](./images/result4.png)

The option `typstWrapper` can serve as a way to inject the necessary imports and setup code for typst. However, it may appear ugly to have such long code in the wrapper function. A better way it to utilize the `#import` directive in the Typst code block:

```ts
const md = new MarkdownIt().use(MarkdownItTypst, {
typstWrapper: (code: string) =>
'#import("./preset.typ")\n' + code,
});
```

---

## License

[MIT](./LICENSE) License © 2024 [Xecades](https://github.com/xecades)

[npm-version-src]: https://img.shields.io/npm/v/markdown-it-typst?style=flat&colorA=080f12&colorB=1fa669
[npm-version-href]: https://npmjs.com/package/markdown-it-typst
[npm-downloads-src]: https://img.shields.io/npm/dm/markdown-it-typst?style=flat&colorA=080f12&colorB=1fa669
[npm-downloads-href]: https://npmjs.com/package/markdown-it-typst
[bundle-src]: https://img.shields.io/bundlephobia/minzip/markdown-it-typst?style=flat&colorA=080f12&colorB=1fa669&label=minzip
[bundle-href]: https://bundlephobia.com/result?p=markdown-it-typst
[license-src]: https://img.shields.io/github/license/xecades/markdown-it-typst.svg?style=flat&colorA=080f12&colorB=1fa669
[license-href]: https://github.com/xecades/markdown-it-typst/blob/main/LICENSE
[jsdocs-src]: https://img.shields.io/badge/jsdocs-reference-080f12?style=flat&colorA=080f12&colorB=1fa669
[jsdocs-href]: https://www.jsdocs.io/package/markdown-it-typst