Scripting
The whole point of writing this as a CLI instead of just a simple script to convert folders of markdown was to be able to add and extend the basic functionality as needed.
Here's where the hooks
folder is being used and this part of the documentation
is a quick reference on how this works.
Language
lua is the language of choice, primarily because it's
very easy to add more functionality by just bringing in .lua
files from the
web and adding them to your project.
Here's what a simple writer function would look like, this function adds a
Hello World
heading to every html/markdown file that alvu would process.
-- add-hello-world.lua
-- a special json library injected by alvu
local json = require("json")
function Writer(filedata)
-- convert the file's information into
-- a lua accessible table
local source_data = json.decode(filedata)
-- concatenate the heading with the rest of the content
source_data.content = "<h1>Hello World</h1>" .. source_data.content
-- send back serialized json data to the tool
return json.encode(source_data)
end
While the comments might already help you out, let's just lay them down as simple points
- You get data from alvu in the
Writer
function as a serialized/stringified JSON. - You can manipulate the data in lua using the helper library
json
- Return the data as a serialized JSON, so the modifications can be processed.
You'll learn more about helper libraries as we move ahead.
Data Injection
There are going to be cases where you might wanna pass back data from the lua
function to the templates and if you wish to build an automatic
index.html
file that lists all the posts of your blog from a certain folder.
This can be done by passing one of two keys in the returned JSON. data
or
extras
Something like this,
local json = require("json")
function Writer()
return json.encode({
data = {
name = "reaper"
}
-- or
extras = {
name = "reaper"
}
})
end
You don't have to send back the whole source_content
for each file since it's
only merged when you send something back, else the original is kept as is and
not all keys that you send back are taken into consideration.
If you did send the above data name = "reaper"
and would like to access it in
all templates, you could just do the following
<p>
{ { .Data.name } }
</p>
<!-- or if you set it under extras -->
<p>
{ { .Extras.name } }
</p>
The lua table could nest as much as needed and the same could be accessed in the templates, but try to avoid it.
and yes, all templates, each hook runs on each template and every
manipulation cascades on the other so if you are running a lot of hooks, name
them with numbers (eg: 01-add-navigation.lua
) if you wish for them to follow a
certain sequence
Single File Hooks
In most cases you use hooks for common functionality but there's definitely cases where just one file needs to be processed with hook and that's easily doable with alvu.
You use the ForFile
global value in the lua hook and the hook will only run for that
file. An example of this would look something like this.
---@diagnostic disable-next-line: undefined-global
local wdir = workingdir
local json = require("json")
ForFile = "00-readme.md"
function Writer(filedata)
local sourcedata = json.decode(filedata)
if sourcedata.name == "00-readme.html"
then
local f = assert(io.open(wdir.."/../readme.md", "rb"))
local content = f:read("*all")
f:close()
sourcedata.content = content
end
return json.encode(sourcedata)
end
The above only runs for the file 00-readme.md
and is responsible for copying the contents
of the readme.md
and overwriting the 00-readme.md
file's content with it at build time