Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create artifact without reading a file. #345

Closed
kwinso opened this issue Sep 12, 2023 · 3 comments · Fixed by #381
Closed

Create artifact without reading a file. #345

kwinso opened this issue Sep 12, 2023 · 3 comments · Fixed by #381
Labels
documentation Improvements or additions to documentation enhancement New feature or request

Comments

@kwinso
Copy link

kwinso commented Sep 12, 2023

Is your feature request related to a problem? Please describe.
I'm wandering if I can directly pass typst source code to the compiler without file path?

Describe the solution you'd like
Basically, I want to pass source code to the compiler and get artifact which can be rendered to svg.
I want to build plugin for Obsidian, so creating file for every little math block in the obsidian document is a bit overhead. So, is there a way to just directly send source code and get artifact back?

@Myriad-Dreamin
Copy link
Owner

Myriad-Dreamin commented Sep 12, 2023

Hi, friend. I'm sorry that the compiler in browser is quite undocumented to this time. I'm writing many comments and documents for this library.

Regarding to your question, please write your owned AccessModel according to the compiler sample here, for example:

export class InMemoryAccessModel implements FsAccessModel {
  public mTimes: Map<string, Date | undefined> = new Map();
  public mData: Map<string, Uint8Array | undefined> = new Map();
  constructor(private root: string, options?: FetchAccessOptions) {
    if (root.endsWith('/')) {
      this.root = this.root.slice(0, this.root.length - 1);
    }
  }

  addFile(path: string, data: Uint8Array, mtime?: Date) {
    this.mTimes.set(path, mtime);
    this.mData.set(path, data);
  }

  addSourceFile(path: string, data: string, mtime?: Date) {
    const encoder = new TextEncoder();
    this.addFile(path, encoder.encode(data), mtime);
  }

  reset() {
    this.mTimes.clear();
    this.mData.clear();
  }

  resolvePath(path: string): string {
    return this.root + path;
  }

  getMTime(path: string): Date | undefined {
    if (this.mTimes.has(path)) {
      return this.mTimes.get(path);
    }
    throw new Error(`no such file ${path}`);
  }

  isFile(): boolean | undefined {
    return true;
  }

  getRealPath(path: string): string | undefined {
    return path;
  }


  readAll(path: string): Uint8Array | undefined {
    if (this.mData.has(path)) {
      return this.mData.get(path);
    }
    throw new Error(`no such file ${path}`);
  }
}

const accessModel = new InMemoryAccessModel('memory');

let compilerPlugin = window.TypstCompileModule.createTypstCompiler();
compilerPlugin
  .init({
    beforeBuild: [
      window.TypstCompileModule.withAccessModel(accessModel),
    ],
    getModule: () =>
      '/base/node_modules/@myriaddreamin/typst-ts-web-compiler/pkg/typst_ts_web_compiler_bg.wasm',
  })
  .then(() => {
    document.getElementById('compile-button').addEventListener('click', () => {
      runCompile();
    });
    return runCompile();
  });

Then you can manage resources for typst in memory:

accessModel.addSourceFile('/code-block-0001.typ', 'Hello, Typst', new Date());
accessModel.addSourceFile('/code-block-0002.typ', 'Hello, Typst', new Date());
accessModel.addSourceFile('/code-block-0003.typ', 'Hello, Typst', new Date());
// ...

I cannot ensure it works perfectly but I will at least provide well-designed AccessModel like InMemoryAccessModel in next release.

If you encounter more problems, feel free to ask me.

@Myriad-Dreamin
Copy link
Owner

For people who want to find tsDoc about the Compiler and Renderer interfaces of typst.ts, It is here, which is better than nothing.

@Myriad-Dreamin
Copy link
Owner

There is a new api addSource which overlays static files over provided AccessModel. The api is available since v0.4.0-rc5.

Usage example:

import { createTypstCompiler } from 'typst';
const compiler = createTypstCompiler();
await compiler.init();
compiler.addSource('/main.typ', 'Hello, typst!');
await compiler.compile({ mainFilePath: '/main.typ' });

Similarly, you can add data files via shadow apis:

/**
 * The interface of Typst compiler.
 */
export interface TypstCompiler {
    /**
     * Add a shadow file to the compiler.
     * @param {string} path - The path to the shadow file.
     * @param {Uint8Array} content - The content of the shadow file.
     *
     */
    mapShadow(path: string, content: Uint8Array): void;
    /**
     * Remove a shadow file from the compiler.
     * @param {string} path - The path to the shadow file.
     */
    unmapShadow(path: string): void;
    /**
     * Reset the shadow files.
     * Note: this function is independent to the {@link reset} function.
     */
    resetShadow(): void;
}

@Myriad-Dreamin Myriad-Dreamin added enhancement New feature or request documentation Improvements or additions to documentation labels Sep 21, 2023
@Myriad-Dreamin Myriad-Dreamin linked a pull request Oct 29, 2023 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants