mirror of
https://github.com/mii443/obsidian-typst.git
synced 2025-08-23 00:25:43 +00:00
Canvas element now resizes
This commit is contained in:
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "obsidian-typst"
|
name = "obsidian-typst"
|
||||||
version = "0.3.0"
|
version = "0.4.1"
|
||||||
authors = ["fenjalien"]
|
authors = ["fenjalien"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "Renders `typst` code blocks to images with Typst."
|
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
|
// @ts-ignore
|
||||||
import typst_wasm_bin from './pkg/obsidian_typst_bg.wasm'
|
import typst_wasm_bin from './pkg/obsidian_typst_bg.wasm'
|
||||||
import typstInit, * as typst from './pkg/obsidian_typst'
|
import typstInit, * as typst from './pkg/obsidian_typst'
|
||||||
|
import TypstCanvasElement from 'typst-canvas-element';
|
||||||
|
|
||||||
// temp.track()
|
// temp.track()
|
||||||
|
|
||||||
@ -27,7 +28,7 @@ const DEFAULT_SETTINGS: TypstPluginSettings = {
|
|||||||
override_math: false,
|
override_math: false,
|
||||||
preamable: {
|
preamable: {
|
||||||
shared: "#let pxToPt = (p) => if p == auto {p} else {p * DPR * (72/96) * 1pt}\n#set text(fill: white, size: pxToPt(SIZE))",
|
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)"
|
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())
|
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()
|
await loadMathJax()
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
this.tex2chtml = MathJax.tex2chtml
|
this.tex2chtml = MathJax.tex2chtml
|
||||||
this.overrideMathJax(this.settings.override_math)
|
this.overrideMathJax(this.settings.override_math)
|
||||||
|
|
||||||
this.addCommand({
|
this.addCommand({
|
||||||
id: "typst-math-override",
|
id: "math-override",
|
||||||
name: "Toggle Math Block Override",
|
name: "Toggle Math Block Override",
|
||||||
callback: () => this.overrideMathJax(!this.settings.override_math)
|
callback: () => this.overrideMathJax(!this.settings.override_math)
|
||||||
})
|
})
|
||||||
this.addCommand({
|
this.addCommand({
|
||||||
id: "typst-update-files",
|
id: "update-files",
|
||||||
name: "Update Cached .typ Files",
|
name: "Update Cached .typ Files",
|
||||||
callback: () => this.updateFileCache()
|
callback: () => this.updateFileCache()
|
||||||
})
|
})
|
||||||
|
|
||||||
this.addSettingTab(new TypstSettingTab(this.app, this));
|
this.addSettingTab(new TypstSettingTab(this.app, this));
|
||||||
this.registerMarkdownCodeBlockProcessor("typst", (source, el, ctx) => {
|
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");
|
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"}`)
|
return this.compiler.compile(source, this.settings.pixel_per_pt, `${this.settings.fill}${this.settings.noFill ? "00" : "ff"}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
typst2Canvas(source: string) {
|
typstToSizedImage(source: string, size: number, display: boolean, fontSize: number) {
|
||||||
const image = this.typst2Image(source)
|
const sizing = `#let (WIDTH, HEIGHT, SIZE, DPR) = (${display ? size : "auto"}, ${!display ? size : "auto"}, ${fontSize}, ${window.devicePixelRatio})`
|
||||||
let canvas = createEl("canvas", {
|
return this.typstToImage(
|
||||||
attr: {
|
`${sizing}\n${this.settings.preamable.shared}\n${source}`
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
compileTypst(source: string, display: boolean) {
|
typstToCanvas(source: string, display: boolean) {
|
||||||
const fontSize = parseFloat(document.body.getCssPropertyValue("--font-text-size"))
|
let canvas = new TypstCanvasElement();
|
||||||
let size = null;
|
canvas.source = source
|
||||||
let line_height;
|
canvas.display = display
|
||||||
try {
|
return canvas
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
typstMath2Html(source: string, r: { display: boolean }) {
|
typstMath2Html(source: string, r: { display: boolean }) {
|
||||||
const display = r.display;
|
const display = r.display;
|
||||||
source = `${this.settings.preamable.math}\n${display ? `$ ${source} $` : `$${source}$`}`
|
source = `${this.settings.preamable.math}\n${display ? `$ ${source} $` : `$${source}$`}`
|
||||||
return this.compileTypst(source, display)
|
return this.typstToCanvas(source, display)
|
||||||
}
|
}
|
||||||
|
|
||||||
onunload() {
|
onunload() {
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
"id": "obsidian-typst",
|
"id": "obsidian-typst",
|
||||||
"name": "Obsidian Typst",
|
"name": "Obsidian Typst",
|
||||||
"version": "0.3.0",
|
"version": "0.4.1",
|
||||||
"minAppVersion": "1.0.0",
|
"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",
|
"author": "fenjalien",
|
||||||
"authorUrl": "https://github.com/fenjalien",
|
"authorUrl": "https://github.com/fenjalien",
|
||||||
"isDesktopOnly": true
|
"isDesktopOnly": true
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "obsidian-typst-plugin",
|
"name": "obsidian-typst-plugin",
|
||||||
"version": "0.3.0",
|
"version": "0.4.1",
|
||||||
"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": {
|
||||||
|
@ -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.3.0": "1.0.0",
|
||||||
"0.2.0": "1.0.0",
|
"0.2.0": "1.0.0",
|
||||||
"0.1.0": "1.0.0"
|
"0.1.0": "1.0.0"
|
||||||
|
Reference in New Issue
Block a user