Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Leverage mitex plugin to render latex equations #12

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

co1emi11er2
Copy link

@co1emi11er2 co1emi11er2 commented Jan 16, 2025

Currently Rough Implementation

This pull request extends the show_raw method for LaTexStrings. It would be great if we could leverage mitex to render latex equations into typst. It is a rough implementation, but I wanted to spark a discussion.

Try it out and see what you think

Import Typstry (using this branch) and Handcalcs

julia> using Handcalcs

julia> using Typstry

This command adds mitex package to the preamble

julia> context[:preamble] = TypstString(TypstText(context[:preamble] * TypstString(TypstText("#import \"@preview/mitex:0.2.4\": *\n"))))
TypstString(TypstText("#set page(margin: 1em, height: auto, width: auto, fill: white)\n#set text(16pt, font: \"JuliaMono\")\n#import \"@preview/mitex:0.2.4\": *\n"))

Then try the following:

julia> TypstString(
       @handcalcs begin
       x = 5
       y = 20
       z = x^2 + y
       end
       ) |> render;

You should get an output like the following:
CleanShot 2025-01-16 at 15 36 09@2x

I currently opened an issue for the [10pt] being rendered. You can see the issue here: mitex-rs/mitex#191

Otherwise mitex works pretty well. It can even render color:

julia> TypstString(
       @handcalcs begin
       x = 5
       y = 20
       z = x^2 + y
       end color = :blue
       ) |> render;

CleanShot 2025-01-16 at 15 39 34@2x

@co1emi11er2
Copy link
Author

co1emi11er2 commented Jan 16, 2025

Adding @nathanrboyer to this. I know he wanted typst integration with handcalcs. This may be a potential quick fix once it is cleaned up. The true typst backend to handcalcs could still come later on, but I know that is a much bigger undertaking.

@jakobjpeters
Copy link
Owner

jakobjpeters commented Jan 16, 2025

That's really cool! I hadn't known about mitex either. It might be useful to use a context parameter to import mitex automatically such as:

mitex(tc) && print(io, "#import \"@preview/mitex:0.2.4\": mi\n\"")`

The project's current roadmap is:

  1. Stop conflating a value's format with the mode
  2. Submit JuliaCon proposals
  3. Implement show_typst(::IO, ::TypstContext, ::Expr)

I love the feature you've implemented here and will absolutely merge it, but need to resolve item 1 before implementing new formats. For example, it would be nice to be able to render both a raw text block ``latex ... `` and rendered latex using mitex. However, a consistent but flexible API for choosing between these formats is eluding me. This work is in-progress, challenging to design, and the primary task I'm stuck on. Please let me know if you have thoughts about it.

I'm hoping to complete item 3 prior to JuliaCon, which would clear the way for a Typst backend in Handcalcs.jl :)

@co1emi11er2
Copy link
Author

co1emi11er2 commented Jan 17, 2025

Cool! Yeah I like that context parameter idea.

I agree that being able to render raw text block and choosing mitex option would be good.

I find API is always the hardest part for me. I personally like the way Latexify.jl allows for the changing of settings. You can see it here: https://korsbo.github.io/Latexify.jl/stable/#Setting-your-own-defaults. I ended up doing the same for handcalcs. I looked into preferences.jl but it seemed a little more confusing.

I usually find my favorite API by just imagining what I wish it was without any syntax constraints. In this case for me it would be matching Typst 1 to 1 as best as I can. This may not be what you are looking for, but something like this would be cool for building typst documents:

@typst_report begin

"""
#import \"@preview/mitex:0.2.4\": *

= Header 1
This is normal typst markdown

#align(right)[#text(fill:green)[OK]]

See the equation below:	
"""
# can comment as normal
@mi(@handcalcs begin
x = 5
y = 20
z = x^2 + y^2
end
)

# mitex is a centered math environment.
@mitex(@handcalcs begin
x = 5
y = 20
z = x^2 + y^2
end
)

# this would simply pass the raw text block (unless settings were changed maybe)
@handcalcs begin
x = 5
y = 20
z = x^2 + y^2
end

# some no render function that does not print
@no_render(
a = 5
)

"""
Can I interpolate *a* here: $$(a). What syntax should it be?	
"""

end

This would essentially be the render function that prints each piece. It basically just opens an io and then adds the_expr |> TypstString |> show_typst to each expression.

@jakobjpeters
Copy link
Owner

jakobjpeters commented Jan 17, 2025

I personally like the way Latexify.jl allows for the changing of settings. You can see it here: https://korsbo.github.io/Latexify.jl/stable/#Setting-your-own-defaults.

I agree this is good design. The next release will use a TypstContext which can be mutated by the user to specify the default behavior.

The two main contenders in terms of how to select between formats is

  • A. Each type has a unique format
    • Pros: Simple to think about and document.
    • Cons:
      • It is ambiguous when to switch between modes. For example, it's pretty clear that a vector should be switched to math mode. However, should TypstString(1; mode = markup) be formatted as 1, #1, or $1$?
      • In some cases, it is difficult to choose what the default format should be. Ideally, this should be consistent for similar or related types. However, some types have a more specific or semantically rich representation that differs from the rest. For example, a Vector should probably be a mathematical vector but a Range is both a Vector and corresponds to Typst's code mode range.
      • Requires implementing more types and having the user perform more type conversions.
  • B. Each type can have multiple formats, specified by a format parameter
    • Pros: Works with preexisting types, is very flexible
    • Cons:
      • More complicated to implement and document, since formats overlap
        • Implementation needs to branch and error for unsupported formats
      • Still requires a default format
      • Is still ambiguous about switching modes

I've tried out both, which unfortunately took a lot of time. I was initially averse to option A because I wanted to avoid creating a bunch of new types. However, B feels pretty messy and doesn't really solve any of the problems with A. Option A also seems to align with your proposal, where a LaTeXString is a raw text block and whatever is returned by mitex is rendered latex. Do you think option A is a good plan? It's currently implemented locally, but has some remaining work.

In the upcoming support for Expr, I intend to implement @typst to support behavior similar to what your example shows. Each element in the block would printed in Typst format and concatenated. This enables a really cool feature where you can choose whether to transpile Julia function calls to Typst function calls or just render it syntactically. The idea to have something like @no_render is new and good!

@jakobjpeters
Copy link
Owner

This would essentially be the render function that prints each piece. It basically just opens an io and then adds the_expr |> TypstString |> show_typst to each expression.

Missed this the first time, yes exactly!

@co1emi11er2
Copy link
Author

I think I like the option A idea. I will try to look into it more these next few days/weeks depending on time. This is awesome work so far! This is the main thing I want to figure out right now. That being how everything will work together: quarto, typst, Pluto, Handcalcs, Jupyter, Drwatson, etc.

At work it’s a pain to get things unblocked due to security measures so it has been hard trying to use quarto somewhat which relies on so many executables. I don’t know how I would ensure all users are able to get everything installed and working. Being able to rely on just Julia and Typst for reports would be so nice.

An interactive Pluto file to typst output would pretty amazing from a user standpoint, but we just have to take it one piece at a time.

@jakobjpeters
Copy link
Owner

An interactive Pluto file to typst output

Do you mean rendering a cell or the entire file?
Rendering a cell already works in Pluto and Jupyter. It doesn't currently work in Quarto, and I haven't investigated why yet.

@jakobjpeters
Copy link
Owner

Oh my documentation says it works in Quarto, maybe I fixed it. Guess I'll have to check haha

@jakobjpeters
Copy link
Owner

At work it’s a pain to get things unblocked due to security measures so it has been hard trying to use quarto somewhat which relies on so many executables. I don’t know how I would ensure all users are able to get everything installed and working. Being able to rely on just Julia and Typst for reports would be so nice.

That's good work you're putting in, keep it up!

@co1emi11er2
Copy link
Author

Oh my documentation says it works in Quarto, maybe I fixed it. Guess I'll have to check haha

I haven’t tried your package with it. That is just with Handcalcs/jupyter. It’s just the work hurdles with quarto and relying on the Latex pdf render (currently) that is too difficult currently.

@co1emi11er2
Copy link
Author

An interactive Pluto file to typst output

Do you mean rendering a cell or the entire file? Rendering a cell already works in Pluto and Jupyter. It doesn't currently work in Quarto, and I haven't investigated why yet.

I can currently create an interactive Pluto file using handcalcs, but our calculations must be printed to pdf. There is currently no Pluto -> quarto(pdf) or Pluto -> typst(pdf) that exists

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants