#typst #browser #document #web #render #ts

reflexo

A portable format to show (typst) document in web browser

8 releases

0.5.0-rc3 Apr 5, 2024
0.5.0-rc2 Mar 25, 2024
0.4.2-rc9 Mar 18, 2024
0.4.2-rc6.2 Jan 21, 2024

#45 in WebAssembly

Download history 3/week @ 2024-01-20 4/week @ 2024-02-17 44/week @ 2024-02-24 44/week @ 2024-03-02 528/week @ 2024-03-16 869/week @ 2024-03-23 375/week @ 2024-03-30 238/week @ 2024-04-06 86/week @ 2024-04-13 28/week @ 2024-04-20

793 downloads per month
Used in 4 crates (2 directly)

Apache-2.0

150KB
3.5K SLoC

typst.ts

Markdown | typst | Online SVG | Online Canvas

typst_ts::ci Apache-2 License

typst.ts is a project dedicated to bring the power of typst to the world of JavaScript. In short, it provides an typst::World implementation and several exporters to help compile and render your Typst document typically inside Browser Environment. In the scope of server-side rendering collaborated by $\textcolor{#3c9123}{\textsf{server}}$ and $\textcolor{#0074d9}{\textsf{browser}}$, there would be a data flow like this:

Data Flow

Specifically, it first typically presents a typst document in three forms:

  • Form1: Render to SVG and then embed it as a high-quality vectored image directly.

  • Form2: Preprocessed to a Vector Format artifact.

  • Form3: Manipulate a canvas element directly.

The Form2: Vector Format is developed specially for typst documents, and it has several fancy features:

Data Flow

So with Form2, you can continue rendering the document in different ways:

Static but responsive rendering

Example Application: single-file, typst-book and hexo-renderer-typst

A compressed artifact containing data for different theme and screen settings. The bundle size of artifacts is optimized for typst documents.

Incremental server-side rendering

Example Application: typst-preview

Build a server for compilation with Compiler Service, streaming the artifact, and render it incrementally.

Serverless client-side rendering

Example Application: single-file

Run the entire typst directly in browser, like typst.app.

Application

Installation (CLI)

Install latest CLI of typst.ts via cargo:

cargo install --locked --git https://github.com/Myriad-Dreamin/typst.ts typst-ts-cli

Or Download the latest release from GitHub Releases.

Installation (Packages)

The JavaScript packages are published on npm.

The rust crates are not published on crates.io yet, since it has the git dependency on typst.

Installation (All-in-one Bundle)

Download the latest bundle file from GitHub Releases.

Documentation

See Documentation.

Templates

Please check Templates and usage in Get Started.

Minimal Example

Note: In default, all-in-one.bundle.js will download the font assets from GitHub in browser, so you need to connect to the Internet.

Download all-in-one.bundle.js from GitHub Releases and start a local server with following content of index.html:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Svg Document</title>
    <script type="module" src="http://localhost:12345/all-in-one.bundle.js" id="typst"></script>
  </head>
  <body>
    <textarea id="input" style="width: 100%"></textarea>
    <div id="content"></div>
    <script>
      const input = document.getElementById('input');
      input.value = 'Hello, Typst!';
      document.getElementById('typst').addEventListener('load', function () {
        const compile = function (mainContent) {
          $typst.svg({ mainContent }).then(svg => {
            console.log(`rendered! SvgElement { len: ${svg.length} }`);
            // append svg text
            document.getElementById('content').innerHTML = svg;
          });
        };
        input.oninput = () => compile(input.value);
        compile(input.value);
      });
    </script>
  </body>
</html>

And you will see the result.

You can also load the all-in-one bundle file and wasm modules from jsdelivr:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Svg Document</title>
    <script
      type="module"
      src="https://cdn.jsdelivr.net/npm/@myriaddreamin/typst.ts/dist/esm/contrib/all-in-one-lite.bundle.js"
      id="typst"
    ></script>
  </head>
  <body>
    <textarea id="input" style="width: 100%"></textarea>
    <div id="content"></div>
    <script>
      const input = document.getElementById('input');
      input.value = 'Hello, Typst!';
      document.getElementById('typst').addEventListener('load', function () {
        $typst.setCompilerInitOptions({
          getModule: () =>
            'https://cdn.jsdelivr.net/npm/@myriaddreamin/typst-ts-web-compiler/pkg/typst_ts_web_compiler_bg.wasm',
        });
        $typst.setRendererInitOptions({
          getModule: () =>
            'https://cdn.jsdelivr.net/npm/@myriaddreamin/typst-ts-renderer/pkg/typst_ts_renderer_bg.wasm',
        });

        const compile = function (mainContent) {
          $typst.svg({ mainContent }).then(svg => {
            console.log(`rendered! SvgElement { len: ${svg.length} }`);
            // append svg text
            document.getElementById('content').innerHTML = svg;
          });
        };
        input.oninput = () => compile(input.value);
        compile(input.value);
      });
    </script>
  </body>
</html>

Develop projects along with a local built typst.ts

You can put your owned projects under the projects folder, and that yarn workspace will automatically identify your project. We recommend you to use git, Yarn, and turbo to manage your projects.

To develop core external projects, e.g. typst-preview, you could initialize them by command:

git submodule update --init --checkout projects/typst-preview
Example: build and run

Ensured that you have built typst.ts from source, you can build and run the project by (typst-preview as an example):

# install dependencies for project
yarn install --pure-lockfile
# build typst-preview and its dependencies
turbo build --filter=typst-preview
@myriaddreamin/typst-ts-renderer:build: cache hit, replaying logs bc0a0b151bd8eb6d
@myriaddreamin/typst.ts:build: cache hit, replaying logs 729cb43a3242b80
typst-preview-frontend:build: cache miss, executing 5ae30471e8957877
typst-preview-frontend:build: ...
typst-preview-frontend:build: ✓ built in 1.25s
typst-preview-frontend:build: Done in 4.57s.
typst-preview:build: cache miss, executing a1bd8ca8233f8a0c
typst-preview:build: ...
typst-preview:build: ✓ built in 1.01s
typst-preview:build: Done in 3.73s.

The project (typst-preview as an example) will cache and use the local built packages.

Build from source and check

Note: you could build from source with/without wasm-pack.

Note: see Troubleshooting WASM Build for (especially) Arch Linux users.

Note: Since we use turborepo for >=v0.4.0 development, if you are the earlier developer of typst.ts, please clean up all of your node_modules and dist folders before running the commands.

# build all of typescript packages
$ yarn install && yarn run build:pkg
# compile typst document for demo
$ cargo run --bin typst-ts-dev-server -- compile --compiler debug corpus --cat skyzh-cv
# start a local server
$ cargo run --bin typst-ts-dev-server -- run http --corpus ./fuzzers/corpora/

And open your browser to http://localhost:20810/.

You can also run yarn run build:core instead of yarn run build:pkg to build core library (@myriaddreamin/typst.ts) and avoid building the WASM modules from source.

Hot Reload

To develop typst.ts with its Wasm renderer, you can run the following command:

cargo run --bin typst-ts-dev-server -- watch renderer
# or run with yarn script
yarn watch:renderer

And open your browser to http://localhost:20810/.

Concept: Precompiler

The precompiler is capable of producing artifact outputs from a Typst project. Thet artifact outputs can be easily distributed to remote endpoints.

Install latest precompiler via cargo:

cargo install --locked --git https://github.com/Myriad-Dreamin/typst.ts typst-ts-cli

Or Download the latest release from GitHub Releases.

Concept: Renderer

The renderer accepts an input in artifact format and renders the document as HTML elements.

Import typst.ts in your project:

  • Using @myriaddreamin/typst.ts

    import { $typst } from '@myriaddreamin/typst.ts/dist/esm/contrib/snippet.mjs';
    const mainContent = 'Hello, typst!';
    
    console.log(await $typst.svg({ mainContent }));
    

    Specify correct path to the wasm modules if it complains.

    $typst.setCompilerInitOptions({ getModule: ... });
    $typst.setRendererInitOptions({ getModule: ... });
    

    The path option is likely required in browser but not in node.js.

    Further reading: Get Started with Typst.ts

  • Using @myriaddreamin/typst.react

    import { TypstDocument } from '@myriaddreamin/typst.react';
    
    export const App = (artifact: Uint8Array) => {
      return (
        <div>
          <h1>Demo: Embed Your Typst Document in React</h1>
          <TypstDocument fill="#343541" artifact={artifact} />
        </div>
      );
    };
    
  • Using @myriaddreamin/typst.angular

    In the module file of your awesome component.

    /// component.module.ts
    import { TypstDocumentModule } from '@myriaddreamin/typst.angular';
    

    Using directive typst-document in your template file.

    <typst-document fill="#343541" artifact="{{ artifact }}"></typst-document>
    
  • Using @myriaddreamin/typst.vue3

    Coming soon.

Dependencies

~4–11MB
~119K SLoC