local function new_engine(dir)
local engine = astra_internal__new_templating_engine(dir)
local Jinja2EngineWrapper = { engine = engine }
local templates_re = require("validation").regex([[(?:index)?\.(html|lua)$]])
local function normalize_paths(path)
if path:sub(1, 1) ~= "/" then
path = "/" .. path
end
if path == "/" then
return { "/" }
end
if path:sub(-1) == "/" then
return { path, path:sub(1, -2) }
else
return { path, path .. "/" }
end
end
function Jinja2EngineWrapper:add_to_server(server, context)
local names = self.engine:get_template_names()
for _, value in ipairs(names) do
local path = templates_re:replace(value, "")
local content = self.engine:render(value, context)
for _, route in ipairs(normalize_paths(path)) do
server:get(route, function(_, response)
response:set_header("Content-Type", "text/html")
return content
end)
end
end
end
function Jinja2EngineWrapper:add_to_server_debug(server, context)
local names = self.engine:get_template_names()
for _, value in ipairs(names) do
local path = templates_re:replace(value, "")
for _, route in ipairs(normalize_paths(path)) do
server:get(route, function(_, response)
self.engine:reload_templates()
response:set_header("Content-Type", "text/html")
return self.engine:render(value, context)
end)
end
end
end
function Jinja2EngineWrapper.debug_watch(_, server, dir_path)
local serde = require("serde")
local fs = require("fs")
local files = {}
local function read_recursive(path)
for _, i in ipairs(fs.read_dir(path)) do
if i:file_type():is_file() then
pcall(function()
local file_details = fs.get_metadata(i:path())
table.insert(files, { i:path(), file_details:last_modified() })
end)
elseif i:file_type():is_dir() then
read_recursive(i:path())
end
end
end
local did_change = false
spawn_interval(function()
local old_files = serde.json.encode(files)
files = {}
read_recursive(dir_path)
if old_files ~= serde.json.encode(files) then
did_change = true
else
did_change = false
end
end, 500)
server:get("/debug.js", function(_, response)
response:set_header("Content-Type", "text/javascript")
return [[setInterval(async ()=>{const response=await fetch("/debug");if(response.ok &&(await response.text())=="true"){window.location.reload();}},100);]]
end)
server:get("/debug", function()
return tostring(did_change)
end)
end
local templating_methods = {
"add_template",
"add_template_file",
"get_template_names",
"exclude_templates",
"reload_templates",
"context_add",
"context_remove",
"context_get",
"add_function",
"render",
}
for _, method in ipairs(templating_methods) do
Jinja2EngineWrapper[method] = function(self, ...)
return self.engine[method](self.engine, ...)
end
end
return Jinja2EngineWrapper
end
local function markdown_ast(input)
return astra_internal__new_markdown_ast(input)
end
local function markdown_html(input)
return astra_internal__new_markdown_html(input)
end
return {
jinja2 = { new = new_engine },
markdown = {
to_ast = markdown_ast,
to_html = markdown_html,
},
}