mirror of
https://github.com/mii443/obsidian-typst.git
synced 2025-08-22 16:15:34 +00:00
Canvas element now resizes
This commit is contained in:
@ -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."
|
||||
|
72
main.ts
72
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() {
|
||||
|
@ -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
|
||||
|
@ -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": {
|
||||
|
@ -0,0 +1 @@
|
||||
/* styles */
|
62
typst-canvas-element.ts
Normal file
62
typst-canvas-element.ts
Normal file
@ -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);
|
||||
}
|
||||
}
|
@ -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"
|
||||
|
Reference in New Issue
Block a user