Improve package loading times

This commit is contained in:
Jack
2023-11-02 12:10:38 +00:00
parent d01e7ed2e7
commit 8a9592d5eb
6 changed files with 86 additions and 45 deletions

2
.gitignore vendored
View File

@ -25,3 +25,5 @@ data.json
# Added by cargo # Added by cargo
target target
*.wasm

View File

@ -12,36 +12,6 @@ if you want to view the source, please visit the github repository of this plugi
`; `;
const prod = (process.argv[2] === "production"); const prod = (process.argv[2] === "production");
import * as fs from 'fs';
import * as path from 'path';
let wasmPlugin = {
name: 'wasm',
setup(build) {
// let path = require('path')
// let fs = require('fs')
// Resolve ".wasm" files to a path with a namespace
build.onResolve({ filter: /\.wasm$/ }, args => {
if (args.resolveDir === '') {
return // Ignore unresolvable paths
}
return {
path: path.isAbsolute(args.path) ? args.path : path.join(args.resolveDir, args.path),
namespace: 'wasm-binary',
}
})
// Virtual modules in the "wasm-binary" namespace contain the
// actual bytes of the WebAssembly file. This uses esbuild's
// built-in "binary" loader instead of manually embedding the
// binary data inside JavaScript code ourselves.
build.onLoad({ filter: /.*/, namespace: 'wasm-binary' }, async (args) => ({
contents: await fs.promises.readFile(args.path),
loader: 'binary',
}))
},
}
const context = await esbuild.context({ const context = await esbuild.context({
banner: { banner: {
@ -70,8 +40,11 @@ const context = await esbuild.context({
sourcemap: prod ? false : "inline", sourcemap: prod ? false : "inline",
treeShaking: true, treeShaking: true,
outfile: "main.js", outfile: "main.js",
define: {
PLUGIN_VERSION: JSON.stringify(process.env.npm_package_version)
},
plugins: [ plugins: [
inlineWorkerPlugin({ format: "cjs", target: "es2018", plugins: [wasmPlugin] }) inlineWorkerPlugin({ format: "cjs", target: "es2018" })
] ]
}) })

15
package-lock.json generated
View File

@ -1,14 +1,15 @@
{ {
"name": "obsidian-typst-plugin", "name": "obsidian-typst-plugin",
"version": "0.5.1", "version": "0.8alpha",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "obsidian-typst-plugin", "name": "obsidian-typst-plugin",
"version": "0.5.1", "version": "0.8alpha",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@capacitor/core": "^5.5.1",
"obsidian": "latest", "obsidian": "latest",
"obsidian-typst": "file:pkg", "obsidian-typst": "file:pkg",
"svgo": "^3.0.2", "svgo": "^3.0.2",
@ -34,6 +35,14 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/@capacitor/core": {
"version": "5.5.1",
"resolved": "https://registry.npmjs.org/@capacitor/core/-/core-5.5.1.tgz",
"integrity": "sha512-VG6Iv8Q7ZAbvjodxpvjcSe0jfxUwZXnvjbi93ehuJ6eYP8U926qLSXyrT/DToZq+F6v/HyGyVgn3mrE/9jW2Tg==",
"dependencies": {
"tslib": "^2.1.0"
}
},
"node_modules/@codemirror/state": { "node_modules/@codemirror/state": {
"version": "6.2.1", "version": "6.2.1",
"resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.2.1.tgz", "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.2.1.tgz",
@ -2502,7 +2511,7 @@
}, },
"pkg": { "pkg": {
"name": "obsidian-typst", "name": "obsidian-typst",
"version": "0.5.1" "version": "0.7.1"
}, },
"pkg/pkg": { "pkg/pkg": {
"extraneous": true "extraneous": true

View File

@ -1,6 +1,6 @@
{ {
"name": "obsidian-typst-plugin", "name": "obsidian-typst-plugin",
"version": "0.7.1", "version": "0.8alpha",
"description": "Renders `typst` code blocks to images with Typst.", "description": "Renders `typst` code blocks to images with Typst.",
"main": "main.js", "main": "main.js",
"scripts": { "scripts": {
@ -25,6 +25,7 @@
"typescript": "^5.1" "typescript": "^5.1"
}, },
"dependencies": { "dependencies": {
"@capacitor/core": "^5.5.1",
"obsidian": "latest", "obsidian": "latest",
"obsidian-typst": "file:pkg", "obsidian-typst": "file:pkg",
"svgo": "^3.0.2", "svgo": "^3.0.2",

View File

@ -1,11 +1,11 @@
//@ts-ignore //@ts-ignore
import wasmBin from '../pkg/obsidian_typst_bg.wasm' // import wasmBin from '../pkg/obsidian_typst_bg.wasm'
import * as typst from '../pkg' import typstInit, * as typst from '../pkg'
import { CompileImageCommand, CompileSvgCommand } from "src/types"; import { CompileImageCommand, CompileSvgCommand } from "src/types";
typst.initSync(wasmBin); // typst.initSync(wasmBin);
let canUseSharedArrayBuffer = new Boolean(false); let canUseSharedArrayBuffer = new Boolean(false);
@ -27,11 +27,20 @@ function requestData(path: string): string {
throw buffer[0] throw buffer[0]
} }
const compiler = new typst.SystemWorld("", requestData) let compiler: typst.SystemWorld; //= new typst.SystemWorld("", requestData)
onmessage = (ev: MessageEvent<CompileImageCommand | CompileSvgCommand | true>) => { // Receive data from main thread
// `true` means a sharedarraybuffer can be used
// `Array` is a list of fonts to be added to the compiler
// `string` the url to the web assembly binary data
onmessage = (ev: MessageEvent<CompileImageCommand | CompileSvgCommand | true | string>) => {
if (ev.data == true) { if (ev.data == true) {
canUseSharedArrayBuffer = ev.data canUseSharedArrayBuffer = ev.data
} else if (typeof ev.data == "string") {
typstInit(ev.data).then(_ => {
compiler = new typst.SystemWorld("", requestData)
console.log("Typst web assembly loaded!");
})
} else if (ev.data instanceof Array) { } else if (ev.data instanceof Array) {
ev.data.forEach(font => compiler.add_font(new Uint8Array(font))) ev.data.forEach(font => compiler.add_font(new Uint8Array(font)))
} else if ("format" in ev.data) { } else if ("format" in ev.data) {
@ -41,8 +50,6 @@ onmessage = (ev: MessageEvent<CompileImageCommand | CompileSvgCommand | true>) =
} else if (ev.data.format == "svg") { } else if (ev.data.format == "svg") {
postMessage(compiler.compile_svg(ev.data.source, ev.data.path)) postMessage(compiler.compile_svg(ev.data.source, ev.data.path))
} }
// postMessage(compile(ev.data))
} else { } else {
throw ev; throw ev;
} }

View File

@ -1,5 +1,7 @@
import { App, renderMath, HexString, Platform, Plugin, PluginSettingTab, Setting, loadMathJax, normalizePath } from 'obsidian'; import { App, renderMath, HexString, Platform, Plugin, PluginSettingTab, Setting, loadMathJax, normalizePath, Notice, requestUrl } from 'obsidian';
import { CapacitorHttp } from '@capacitor/core';
declare const PLUGIN_VERSION: string;
// @ts-ignore // @ts-ignore
import CompilerWorker from "./compiler.worker.ts" import CompilerWorker from "./compiler.worker.ts"
@ -19,7 +21,8 @@ interface TypstPluginSettings {
shared: string, shared: string,
math: string, math: string,
code: string, code: string,
} },
plugin_version: string,
} }
const DEFAULT_SETTINGS: TypstPluginSettings = { const DEFAULT_SETTINGS: TypstPluginSettings = {
@ -34,7 +37,8 @@ const DEFAULT_SETTINGS: TypstPluginSettings = {
shared: "#set text(fill: white, size: SIZE)\n#set page(width: WIDTH, height: HEIGHT)", shared: "#set text(fill: white, size: SIZE)\n#set page(width: WIDTH, height: HEIGHT)",
math: "#set page(margin: 0pt)\n#set align(horizon)", math: "#set page(margin: 0pt)\n#set align(horizon)",
code: "#set page(margin: (y: 1em, x: 0pt))" code: "#set page(margin: (y: 1em, x: 0pt))"
} },
plugin_version: PLUGIN_VERSION
} }
export default class TypstPlugin extends Plugin { export default class TypstPlugin extends Plugin {
@ -47,11 +51,35 @@ export default class TypstPlugin extends Plugin {
prevCanvasHeight: number = 0; prevCanvasHeight: number = 0;
textEncoder: TextEncoder textEncoder: TextEncoder
fs: any; fs: any;
wasmPath = ".obsidian/plugins/typst/obsidian_typst_compiler.wasm"
async onload() { async onload() {
console.log("loading Typst Renderer");
this.textEncoder = new TextEncoder() this.textEncoder = new TextEncoder()
await this.loadSettings() await this.loadSettings()
this.compilerWorker = (new CompilerWorker() as Worker); this.compilerWorker = (new CompilerWorker() as Worker);
if (!await this.app.vault.adapter.exists(this.wasmPath) || this.settings.plugin_version != PLUGIN_VERSION) {
new Notice("Typst Renderer: Downloading required web assembly component!", 5000);
try {
await this.fetchWasm()
new Notice("Typst Renderer: Web assembly component downloaded!", 5000)
} catch (error) {
new Notice("Typst Renderer: Failed to fetch component: " + error, 0)
console.error("Typst Renderer: Failed to fetch component: " + error)
}
}
this.compilerWorker.postMessage(
URL.createObjectURL(
new Blob(
[await this.app.vault.adapter.readBinary(this.wasmPath)],
{ type: "application/wasm" }
)
)
)
if (!Platform.isMobileApp) { if (!Platform.isMobileApp) {
this.compilerWorker.postMessage(true); this.compilerWorker.postMessage(true);
this.fs = require("fs") this.fs = require("fs")
@ -97,6 +125,26 @@ export default class TypstPlugin extends Plugin {
console.log("loaded Typst Renderer"); console.log("loaded Typst Renderer");
} }
async fetchWasm() {
let response
let data
response = requestUrl(`https://api.github.com/repos/fenjalien/obsidian-typst/releases/tags/${PLUGIN_VERSION}`)
data = await response.json
let asset = data.assets.find((a: any) => a.name == "obsidian_typst_compiler.wasm")
if (asset == undefined) {
throw "Could not find the correct file!"
}
response = requestUrl({url: asset.url, headers: {"Accept": "application/octet-stream"}})
data = await response.arrayBuffer
await this.app.vault.adapter.writeBinary(
this.wasmPath,
data
)
this.settings.plugin_version = PLUGIN_VERSION
await this.saveSettings()
}
async compileToTypst(path: string, source: string, size: number, display: boolean): Promise<ImageData> { async compileToTypst(path: string, source: string, size: number, display: boolean): Promise<ImageData> {
return await navigator.locks.request("typst renderer compiler", async (lock) => { return await navigator.locks.request("typst renderer compiler", async (lock) => {
@ -282,6 +330,7 @@ export default class TypstPlugin extends Plugin {
async saveSettings() { async saveSettings() {
await this.saveData(this.settings); await this.saveData(this.settings);
} }
} }
class TypstSettingTab extends PluginSettingTab { class TypstSettingTab extends PluginSettingTab {