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

ref!(math-renderer): modularize image generation to make way for typst #1448

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions lua/neorg/modules/core/highlights/module.lua
Original file line number Diff line number Diff line change
Expand Up @@ -368,10 +368,10 @@ module.config.public = {
escape = "+@type",
},

-- Rendered Latex, this will dictate the foreground color of latex images rendered via
-- core.latex.renderer
-- Rendered Latex, this will dictate the foreground color of math images rendered via
-- core.math.renderer
rendered = {
latex = "+Normal",
math = "+Normal",
},
},

Expand Down
11 changes: 6 additions & 5 deletions lua/neorg/modules/core/latex/renderer/module.lua
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Requires:
There's a highlight group that controls the foreground color of the rendered latex:
`@norg.rendered.latex`, configurable in `core.highlights`
--]]

local nio
local neorg = require("neorg.core")
local module = neorg.modules.create("core.latex.renderer")
Expand Down Expand Up @@ -173,11 +174,11 @@ module.public = {
module.private.cleared_at_cursor = {}
module.required["core.integrations.treesitter"].execute_query(
[[
(
(inline_math) @latex
(#offset! @latex 0 1 0 -1)
)
]],
(
(inline_math) @latex
(#offset! @latex 0 1 0 -1)
)
]],
function(query, id, node)
if query.captures[id] ~= "latex" then
return
Expand Down
133 changes: 133 additions & 0 deletions lua/neorg/modules/core/math/renderer/latex/module.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
--[[
file: Math-Renderer-LaTeX
title: Convert LaTeX snippets into image files
summary: A module that provides images of LaTeX for `core.math.renderer`
---

The module is used by `core.math.renderer` to render math blocks as LaTeX.

Requires:
- `latex` executable in path with the following packages:
- standalone
- amsmath
- amssymb
- graphicx
- `dvipng` executable in path (normally comes with LaTeX)

A highlight group that controls the foreground color of the rendered math: `@neorg.rendered.math`,
configurable in `core.highlights`. It links to `Normal` by default

Note, when `'concealcursor'` contains `"n"` This plugin will fail for the time being.
--]]
local nio
local neorg = require("neorg.core")
local module = neorg.modules.create("core.math.renderer.latex")

module.load = function()
nio = require("nio")
end

module.config.public = {
-- "Dots Per Inch" increasing this value will result in crisper images at the expense of
-- performance
dpi = 350,
}

module.private = {}

---@type MathImageGenerator
module.public = {
---Returns a filepath where the rendered image sits
---@async
---@param snippet string the full latex snippet to convert to an image
---@param foreground_color { r: number, g: number, b: number }
---@return string | nil
async_generate_image = function(snippet, foreground_color)
local document_name = module.private.async_create_latex_document(snippet)

if not document_name then
return
end

local cwd = nio.fn.fnamemodify(document_name, ":h")
local create_dvi = nio.process.run({
cmd = "latex",
args = {
"--interaction=nonstopmode",
"--output-format=dvi",
document_name,
},
cwd = cwd,
})
if not create_dvi or type(create_dvi) == "string" then
return
end
local res = create_dvi.result()
if res ~= 0 then
return
end

local png_result = nio.fn.tempname()
png_result = ("%s.png"):format(png_result)

local fg = module.private.format_color(foreground_color)
local dvipng = nio.process.run({
cmd = "dvipng",
args = {
"-D",
module.config.public.dpi,
"-T",
"tight",
"-bg",
"Transparent",
"-fg",
fg,
"-o",
png_result,
document_name .. ".dvi",
},
})

if not dvipng or type(dvipng) == "string" then
return
end
res = dvipng.result()
if res ~= 0 then
return
end

return png_result
end,
}

---Writes a latex snippet to a file and wraps it with latex headers so it will render nicely
---@async
---@param snippet string latex snippet (if it's math it should include the surrounding $$)
---@return string temp file path
module.private.async_create_latex_document = function(snippet)
local tempname = nio.fn.tempname()
local tempfile = nio.file.open(tempname, "w")

local content = table.concat({
"\\documentclass[6pt]{standalone}",
"\\usepackage{amsmath}",
"\\usepackage{amssymb}",
"\\usepackage{graphicx}",
"\\begin{document}",
snippet,
"\\end{document}",
}, "\n")

tempfile.write(content)
tempfile.close()

return tempname
end

---Format the foreground color information into something that can be passed to the dvipng command
---@param foreground_color {r: number, g: number, b: number}
module.private.format_color = function(foreground_color)
return ("rgb %s %s %s"):format(foreground_color.r, foreground_color.g, foreground_color.b)
end

return module
Loading
Loading