diff --git a/Cargo.toml b/Cargo.toml index e54154f..03f81bc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "obsidian-typst" -version = "0.3.0" +version = "0.4.1" authors = ["fenjalien"] edition = "2021" description = "Renders `typst` code blocks to images with Typst." diff --git a/main.ts b/main.ts index 8c91624..3c27048 100644 --- a/main.ts +++ b/main.ts @@ -3,6 +3,7 @@ import { App, HexString, Notice, Plugin, PluginSettingTab, Setting, Workspace, l // @ts-ignore import typst_wasm_bin from './pkg/obsidian_typst_bg.wasm' import typstInit, * as typst from './pkg/obsidian_typst' +import TypstCanvasElement from 'typst-canvas-element'; // temp.track() @@ -27,7 +28,7 @@ const DEFAULT_SETTINGS: TypstPluginSettings = { override_math: false, preamable: { shared: "#let pxToPt = (p) => if p == auto {p} else {p * DPR * (72/96) * 1pt}\n#set text(fill: white, size: pxToPt(SIZE))", - math: "#set page(width: pxToPt(WIDTH), height: pxToPt(HEIGHT), margin: 0pt)\n#set align(horizon)\n#import \"physics.typ\": *", + math: "#set page(width: pxToPt(WIDTH), height: pxToPt(HEIGHT), margin: 0pt)\n#set align(horizon)", code: "#set page(width: auto, height: auto, margin: 1em)" } } @@ -51,88 +52,55 @@ export default class TypstPlugin extends Plugin { this.app.metadataCache.on("resolved", () => this.updateFileCache()) ) + TypstCanvasElement.compile = (a, b, c, d) => this.typstToSizedImage(a, b, c, d) + customElements.define("typst-canvas", TypstCanvasElement, { extends: "canvas" }) + await loadMathJax() // @ts-expect-error this.tex2chtml = MathJax.tex2chtml this.overrideMathJax(this.settings.override_math) this.addCommand({ - id: "typst-math-override", + id: "math-override", name: "Toggle Math Block Override", callback: () => this.overrideMathJax(!this.settings.override_math) }) this.addCommand({ - id: "typst-update-files", + id: "update-files", name: "Update Cached .typ Files", callback: () => this.updateFileCache() }) this.addSettingTab(new TypstSettingTab(this.app, this)); this.registerMarkdownCodeBlockProcessor("typst", (source, el, ctx) => { - el.appendChild(this.compileTypst(`${this.settings.preamable.code}\n${source}`, true)) + el.appendChild(this.typstToCanvas(`${this.settings.preamable.code}\n${source}`, true)) }) console.log("loaded Typst"); } - typst2Image(source: string) { + typstToImage(source: string) { return this.compiler.compile(source, this.settings.pixel_per_pt, `${this.settings.fill}${this.settings.noFill ? "00" : "ff"}`) } - typst2Canvas(source: string) { - const image = this.typst2Image(source) - let canvas = createEl("canvas", { - attr: { - width: image.width, - height: image.height - }, - cls: "typst" - }) - - let ctx = canvas.getContext("2d"); - - ctx!.imageSmoothingEnabled = true - ctx!.imageSmoothingQuality = "high" - ctx?.putImageData(image, 0, 0); - return canvas + typstToSizedImage(source: string, size: number, display: boolean, fontSize: number) { + const sizing = `#let (WIDTH, HEIGHT, SIZE, DPR) = (${display ? size : "auto"}, ${!display ? size : "auto"}, ${fontSize}, ${window.devicePixelRatio})` + return this.typstToImage( + `${sizing}\n${this.settings.preamable.shared}\n${source}` + ) } - compileTypst(source: string, display: boolean) { - const fontSize = parseFloat(document.body.getCssPropertyValue("--font-text-size")) - let size = null; - let line_height; - try { - if (display) { - size = parseFloat(document.body.getCssPropertyValue("--file-line-width")) - } else { - line_height = parseFloat(document.body.getCssPropertyValue("--line-height-normal")) - size = line_height * fontSize - } - - let canvas = this.typst2Canvas(`#let (WIDTH, HEIGHT, SIZE, DPR) = (${display ? size : "auto"}, ${!display ? size : "auto"}, ${fontSize}, ${window.devicePixelRatio})\n${this.settings.preamable.shared}\n${source}`) - - if (display) { - canvas.style.width = `100%`; - } else { - console.log(size, fontSize, line_height); - - canvas.style.verticalAlign = "bottom" - canvas.style.height = `${size}px` - } - - return canvas - } catch (error) { - console.error(error); - let span = createSpan() - span.innerText = error - return span - } + typstToCanvas(source: string, display: boolean) { + let canvas = new TypstCanvasElement(); + canvas.source = source + canvas.display = display + return canvas } typstMath2Html(source: string, r: { display: boolean }) { const display = r.display; source = `${this.settings.preamable.math}\n${display ? `$ ${source} $` : `$${source}$`}` - return this.compileTypst(source, display) + return this.typstToCanvas(source, display) } onunload() { diff --git a/manifest.json b/manifest.json index 2e6c799..be663f6 100644 --- a/manifest.json +++ b/manifest.json @@ -1,9 +1,9 @@ { "id": "obsidian-typst", "name": "Obsidian Typst", - "version": "0.3.0", + "version": "0.4.1", "minAppVersion": "1.0.0", - "description": "Renders `typst` code blocks to images with Typst.", + "description": "Renders `typst` code blocks and math blocks to images with Typst.", "author": "fenjalien", "authorUrl": "https://github.com/fenjalien", "isDesktopOnly": true diff --git a/package.json b/package.json index c7c34e9..3ad368c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "obsidian-typst-plugin", - "version": "0.3.0", + "version": "0.4.1", "description": "Renders `typst` code blocks to images with Typst.", "main": "main.js", "scripts": { diff --git a/styles.css b/styles.css index e69de29..e30dc71 100644 --- a/styles.css +++ b/styles.css @@ -0,0 +1 @@ +/* styles */ \ No newline at end of file diff --git a/typst-canvas-element.ts b/typst-canvas-element.ts new file mode 100644 index 0000000..0c46c54 --- /dev/null +++ b/typst-canvas-element.ts @@ -0,0 +1,62 @@ +export default class TypstCanvasElement extends HTMLCanvasElement { + static compile: (source: string, size: number, display: boolean, fontSize: number) => ImageData; + + source: string + display: boolean + resizeObserver: ResizeObserver + size: number + + connectedCallback() { + if (!this.isConnected) { + console.log("called before connection"); + return; + } + this.draw() + if (this.display) { + this.resizeObserver = new ResizeObserver((entries) => { + if (entries[0]?.contentBoxSize[0].inlineSize !== this.size) { + this.draw() + } + }) + this.resizeObserver.observe(this.parentElement!.parentElement!) + } + } + + disconnectedCallback() { + if (this.display) { + this.resizeObserver.disconnect() + } + } + + draw() { + + let fontSize = parseFloat(this.getCssPropertyValue("--font-text-size")) + this.size = this.display ? this.parentElement!.parentElement!.innerWidth : parseFloat(this.getCssPropertyValue("--line-height-normal")) * fontSize + // console.log(size, this.parentElement); + + + if (this.display) { + this.style.width = "100%" + } else { + this.style.verticalAlign = "bottom" + this.style.height = `${this.size}px` + } + + let image: ImageData; + let ctx = this.getContext("2d")!; + try { + image = TypstCanvasElement.compile(this.source, this.size, this.display, fontSize) + } catch (error) { + console.error(error); + this.outerText = error + return + } + + this.width = image.width + this.height = image.height + + ctx.imageSmoothingEnabled = true + ctx.imageSmoothingQuality = "high" + ctx.putImageData(image, 0, 0); + } +} \ No newline at end of file diff --git a/versions.json b/versions.json index 97de6c7..3e26717 100644 --- a/versions.json +++ b/versions.json @@ -1,4 +1,6 @@ { + "0.4.1": "1.0.0", + "0.4.0": "1.0.0", "0.3.0": "1.0.0", "0.2.0": "1.0.0", "0.1.0": "1.0.0"