This is a simple templating thingy. Basically like the C pre-processor, but for HTML.
Run this with the .template.html files you want to "compile" as the arguments.
--[[
An HTML pre-processor
BSD Zero Clause License
Copyright (c) 2023 icri.neocities.org
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
]]
local DEBUG = false
local compile
local commands
commands = {
template = function(scope, params)
return compile(params .. ".template.html", setmetatable({}, { __index = scope }))
end,
---Set a variable
---@param params string
set = function(scope, params)
local name, value = params:match("^(%S+)%s+(.*)$")
if value then
if DEBUG then print(("Set: %s to %s"):format(name, value)) end
scope[name] = value
return ""
end
if DEBUG then
print(("Warning: \"%s\" failed to match for set"):format(params))
end
end,
---Set only if not already set
default = function(scope, params)
local name, value = params:match("^(%S+)%s+(.*)$")
if value then
if scope[name] ~= nil then return "" end
if DEBUG then
print(("Set: %s to %s"):format(name, value))
end
scope[name] = value
return ""
end
if DEBUG then
print(("Warning: \"%s\" failed to match for set"):format(params))
end
end,
get = function(scope, params)
local value = scope[params]
if value then return value end
if DEBUG then
print(("Warning: \"%s\" failed to get value"):format(params))
end
end,
---Obtains the verbatim text content
---@param scope table
---@param params string
---@return string
include = function(scope, params)
local file = io.open(params) or error(("Invalid file for include %s"):format(params))
return file:read("*a") ---@as string
end,
includequot = function(scope, params)
local result = commands.include(scope, params)
result = result:gsub("&", "&"):gsub("<", "<"):gsub(">", ">")
return result
end,
---Gets output of pygmentize
---@param scope table
---@param params string
pygmentize = function(scope, params)
local filename = params:gsub("'", "\\'")
local proc = io.popen(("pygmentize -f html '%s'"):format(filename)) or error("Failed to run pygmentize")
local result = proc:read("*a")
proc:close()
return result
end,
}
---Compile the template file
---@param template string
function compile(template, scope)
scope = scope or {}
print("Compiling ", template)
local file = io.open(template) or error(("Could not open file %s"):format(template))
local data = file:read("*a") --[[@as string]]
local result = data:gsub("<!%-%-(%S+)%s+(.-)%-%->", function(command, params)
if DEBUG then print(command, params) end
local executor = commands[command]
if executor then
return executor(scope, params)
end
end)
return result
end
for i = 1, #arg do
local template = arg[i]
local dest = template:match("^(.+).template.html$")
if not dest then
print(("Warn: Invalid template specified %s"):format(template))
end
local destinationFile = io.open(dest .. ".html", "w") or error("Failed to open output")
destinationFile:write(compile(template))
end