fenjalien / obsidian-typst

Renders typst code blocks in Obsidian into images using Typst through the power of WASM!
Apache License 2.0
308 stars 14 forks source link

Inline math blocks don't render edge of tall expressions #17

Open jac0b-w opened 11 months ago

jac0b-w commented 11 months ago

$|e^(i(arrow(k) dot arrow(r)))|^2_7$ incorrectly renders the superscript and subscript numbers like so: image

fenjalien commented 10 months ago

It'll be because the Typst content is too tall for the page size (which is set to the line height). I'll look into allowing the page height for inline math to be auto.

fenjalien commented 10 months ago

Unfortuntaly this doesn't look like it can be fixed until #5 as a known length is required to size the image correctly. For a block its the width of the page and for inline elements its the line height. So by removing the line height you can't really size its width, you also won't be able to align the baseline.

The best workaround I can think of is to just change the line height but you can't really do that on a line-by-line basis. One idea I have though is to create a typst html element whose body is some Typst source and gets rendered as such. It would allow the passing of a custom height to the element. (fyi you can write pure html in Obsidian files)

<typst height="30">some typst source here</typst>
yonatankremer commented 2 weeks ago

finally found some kind of workaround: if you look at equations' body when using a sub/super script, it seems to use the attach function, which takes "base" as an input. Couldn't find a better way to check whether "attach" was called, but that'll work for now:

show math.equation.where(block: false): it => {

if it.body.has("base") { math.script(it, cramped: true) } else { it } }

first edit: it does apply it to the entire equation, might work on it sometime but I should study lol

yonatankremer commented 2 weeks ago

update: anything else I try gets rejected by the compiler (maximum show rule depth exceeded).

it's like it doesn't let you access content's body at all, on purpose

spend WAY too much time on it, I think that's the best it gets:

let bb(c) = {

c.has("base") }

let ia(c) = {

let isChild = c.body.fields().keys().contains("children")

if isChild { if c.body.children.any(bb) { math.script(c) } else { c } } else { if c.body.fields().keys().contains("base") { math.script(c) } else { c } } }

show math.equation.where(block: false): it => {

ia(it) }

yonatankremer commented 2 weeks ago

Final. Due to funky ways Typst seems to store content, there needs to be an extra "children" check (didn't see this part specified in the docs, just experimentation, might've missed something. Moreover, it doesn't seem to be possible to modify just a part of a content instance, the only way is to get .fields(), and then there is no simple way back.

#let fixBase(eq) = {

  let isChild = eq.body.fields().keys().contains("children")

  if isChild {
    if eq.body.children.any(it => {it.has("base")}) {
      math.script(eq)
    } else {
      eq
    }
  } else {
    if eq.body.fields().keys().contains("base") {
      math.script(eq)
    } else {
      c
    }
  }
}

#show math.equation.where(block: false): it => {
  fixBase(it)
}

last one ffs

#show math.equation.where(block: false): it => {
  show math.attach: math.script
  it
}