JuliaKurs23/_extensions/quarto-ext/latex-environment/latex-environment.lua

151 lines
4.3 KiB
Lua
Raw Permalink Normal View History

2023-05-12 20:42:26 +02:00
-- environment.lua
-- Copyright (C) 2020 by RStudio, PBC
local classEnvironments = pandoc.MetaMap({})
local classCommands = pandoc.MetaMap({})
-- helper that identifies arrays
local function tisarray(t)
local i = 0
for _ in pairs(t) do
i = i + 1
if t[i] == nil then return false end
end
return true
end
-- reads the environments
local function readEnvironments(meta)
local env = meta['environments']
if env ~= nil then
if tisarray(env) then
-- read an array of strings
for i, v in ipairs(env) do
local value = pandoc.utils.stringify(v)
classEnvironments[value] = value
end
else
-- read key value pairs
for k, v in pairs(env) do
local key = pandoc.utils.stringify(k)
local value = pandoc.utils.stringify(v)
classEnvironments[key] = value
end
end
end
end
local function readCommands(meta)
local env = meta['commands']
if env ~= nil then
if tisarray(env) then
-- read an array of strings
for i, v in ipairs(env) do
local value = pandoc.utils.stringify(v)
classCommands[value] = value
end
else
-- read key value pairs
for k, v in pairs(env) do
local key = pandoc.utils.stringify(k)
local value = pandoc.utils.stringify(v)
classCommands[key] = value
end
end
end
end
local function readEnvsAndCommands(meta)
readEnvironments(meta)
readCommands(meta)
end
-- use the environments from metadata to
-- emit a custom environment for latex
local function writeEnvironments(divEl)
if quarto.doc.is_format("latex") then
for k, v in pairs(classEnvironments) do
if divEl.attr.classes:includes(k) then
-- process this into a latex environment
local beginEnv = '\\begin' .. '{' .. v .. '}'
local endEnv = '\n\\end{' .. v .. '}'
-- check if custom options or arguments are present
-- and add them to the environment accordingly
local opts = divEl.attr.attributes['options']
if opts then
beginEnv = beginEnv .. '[' .. opts .. ']'
end
local args = divEl.attr.attributes['arguments']
if args then
beginEnv = beginEnv .. '{' .. args .. '}'
end
-- if the first and last div blocks are paragraphs then we can
-- bring the environment begin/end closer to the content
if #divEl.content > 0 and divEl.content[1].t == "Para" and divEl.content[#divEl.content].t == "Para" then
table.insert(divEl.content[1].content, 1, pandoc.RawInline('tex', beginEnv .. "\n"))
table.insert(divEl.content[#divEl.content].content, pandoc.RawInline('tex', "\n" .. endEnv))
else
table.insert(divEl.content, 1, pandoc.RawBlock('tex', beginEnv))
table.insert(divEl.content, pandoc.RawBlock('tex', endEnv))
end
return divEl
end
end
end
end
2024-05-14 00:11:21 +02:00
local function buildCommandArgs(opts, format)
local function wrap(o)
return string.format(format, o)
end
local t = pandoc.List()
for str in string.gmatch(opts, "([^"..",".."]+)") do
t:insert(str)
end
return table.concat(t:map(wrap), "")
end
2023-05-12 20:42:26 +02:00
-- use the environments from metadata to
-- emit a custom environment for latex
local function writeCommands(spanEl)
if quarto.doc.is_format("latex") then
for k, v in pairs(classCommands) do
if spanEl.attr.classes:includes(k) then
-- resolve the begin command
2024-05-14 00:11:21 +02:00
local beginCommand = '\\' .. pandoc.utils.stringify(v)
2023-05-12 20:42:26 +02:00
local opts = spanEl.attr.attributes['options']
2024-05-14 00:11:21 +02:00
local args = spanEl.attr.attributes['arguments']
2023-05-12 20:42:26 +02:00
if opts then
2024-05-14 00:11:21 +02:00
beginCommand = beginCommand .. buildCommandArgs(opts, "[%s]")
2023-05-12 20:42:26 +02:00
end
2024-05-14 00:11:21 +02:00
if args then
beginCommand = beginCommand .. buildCommandArgs(args, "{%s}")
end
local beginCommandRaw = pandoc.RawInline('latex', beginCommand .. '{')
2023-05-12 20:42:26 +02:00
-- the end command
2024-05-14 00:11:21 +02:00
local endCommandRaw = pandoc.RawInline('latex', '}')
2023-05-12 20:42:26 +02:00
-- attach the raw inlines to the span contents
local result = spanEl.content
2024-05-14 00:11:21 +02:00
table.insert(result, 1, beginCommandRaw)
table.insert(result, endCommandRaw)
2023-05-12 20:42:26 +02:00
return result
end
end
end
end
-- Run in two passes so we process metadata
-- and then process the divs
return {
{ Meta = readEnvsAndCommands },
{ Div = writeEnvironments, Span = writeCommands }
}