Lua modules
A great many wikis keep their templates' logic in Lua, and Wikven runs a real MediaWiki at build time, so a module runs the way it always does. The page that invokes it is written out with the module's answer already in it; the module itself never becomes a page of the published site. Lua on a MediaWiki is Scribunto, which MediaWiki bundles.
Both products render Lua, but only the Docker image needs nothing from you; the standalone binary wants an interpreter installed on arm64. The table below has the three cases. A build that cannot render Lua stops and says so, rather than publishing pages with {{#invoke:}} showing in them.
Enabling it
Name it in your .wikven.yaml file and that is all. Scribunto is bundled with MediaWiki, so it needs no WikvenRepositories entry, and on most builds the engine needs no configuration either.
extensions:
- Scribunto
Writing a module
A module is content, so it lives in your source tree beside your pages. Its file carries no .wikitext marker, because a Module: page's content model is Lua and not wikitext:
src/
Module/
Example
Home.wikitext
A file named Module/Example.wikitext is imported too, but the bare name is the convention, and it is the one Wikven maps a page back to when it needs the file that page came from.
A name with no extension leaves your editor with nothing to go on, so it will not colour the file or offer you Lua anything. Every editor can be told once, by the name rather than the extension:
In .vscode/settings.json, or your user settings:
{
"files.associations": {
"**/Module/*": "lua"
}
}
In .helix/languages.toml beside the source, or ~/.config/helix/languages.toml:
[[language]]
name = "lua"
file-types = [{ glob = "**/Module/*" }]
In ~/.vim/filetype.vim, or anywhere your vimrc is sourced from:
autocmd BufRead,BufNewFile */Module/* setfiletype lua
The other way round works as well: a file named Module/Example.lua is imported, because the marker is only needed where the title would otherwise be wikitext. But the name is kept as it is, so the page becomes Module:Example.lua and every {{#invoke:}} has to spell it that way.
The module is ordinary Lua. This one is the module this site really has, in full:
local p = {}
function p.thisPage( frame )
return '<code>' .. mw.title.getCurrentTitle().text .. '</code>'
end
return p
and the page invokes it the ordinary way:
{{#invoke:Example|thisPage}}
Which, run on this page as you read it, answered:
Lua modules/en
The invocation sits outside the <translate> tags, because a module's return value is not a translation unit. It reaches a reader of any language exactly as the module wrote it, so the words belong in the sentence around it and not in the module.
What reaches the published site
The module's output, and nothing else. Module: is not a content namespace, so the module is never exported as a page and its Lua source is not published; what a reader downloads is the page with that answer already in it. Nothing runs in the reader's browser, because nothing is left to run: the module ran once, at build time.
That is worth knowing when you decide what to put in a module. Anything a module computes from the wiki's own content — a table assembled from other pages, a sorted list, a page's own order in a series — is computed once and frozen. Anything a module would need at read time, like the reader's clock or a query, has nowhere to run.
Which product renders it
Scribunto has two engines and picks between them itself. The first is luasandbox, a PHP extension; the second runs an external lua program, and falls back to an interpreter Scribunto carries in its own source tree. Which one you get depends on the product, and only one of the three arrangements asks anything of you.
| Product | Engine | What you configure |
|---|---|---|
| Docker image | luasandbox, compiled into its PHP |
nothing |
| Standalone binary, x86-64 | the interpreter Scribunto ships | nothing |
| Standalone binary, arm64 | an interpreter you install | luaPath, below
|
The arm64 row is not a wikven limitation. Scribunto has no arm64 interpreter to offer. The five it bundles are all Intel — Linux and Windows in 32- and 64-bit, macOS in 64 — and it picks among them by operating system and integer size, so on arm64 it takes the x86-64 Linux one, which will not start. Install Lua 5.1 — apt install lua5.1 on Debian and Ubuntu; LuaJIT serves too, being Lua 5.1 — and name it:
extensions:
- Scribunto
config:
ScribuntoEngineConf:
luastandalone:
luaPath: /usr/bin/lua5.1
That setting is read on every product, so a source tree carrying it builds the same everywhere.
When the build and the site disagree
Two things can be out of step here, and what the site asked for decides which is which: Lua the site asked for and this build cannot give ends the build, and Lua the site never asked for is only reported, with the bake going on.
Modules with no Scribunto. A source tree with Module: files and no Scribunto in extensions is built, and told what those files come to: a {{#invoke:}} is left in the page as its own source text, and a module named with the .wikitext marker is published as a page — your Lua, exported for the world to read. The build says what it sees rather than deciding for you, because a Module: file is a guess read off a name and may be on its way in, on its way out, or kept for something else.
Wikven: the source has 1 Lua module file(s) (Module:Example) and Scribunto is not in
extensions, so a {{#invoke:}} is left in the page as its own source text, and a module
named with the .wikitext marker is exported as a page. Add Scribunto to extensions if
those modules are meant to run.
Scribunto with no engine. A site that lists Scribunto is refused wherever nothing can run it — in practice, the binary on arm64 with no luaPath set. This one is refused rather than reported: the site asked for Lua in so many words, and this build cannot give it. The engine is not merely looked for but run, because the interpreter Scribunto would have chosen on arm64 exists and is marked executable and still cannot start; nothing short of running it tells the difference.
Wikven: this site lists Scribunto and no Lua engine is available here. The Docker image
compiles luasandbox into its PHP. The standalone binary carries no engine of its own and
falls back to the lua interpreter Scribunto ships, which is built for 64-bit x86 Linux and
did not run here. Install a Lua 5.1 interpreter and name it under
ScribuntoEngineConf.luastandalone.luaPath, bake this site with the Docker image, or drop
Scribunto from extensions and the Module: pages with it.
That refusal is in the exit status as well as in words, so a script that bakes and then deploys stops rather than shipping nothing. The report above stays a report: a bake that prints it exits zero like any other, and writes the site it described.
This documentation site uses a module itself, and the page you are reading is baked with the image on every change, with the module's answer asserted to be in it. The binary is held to the same rule on a source tree of its own, x86-64 on every change and arm64 on every nightly, so each row of the table above is something a machine checks rather than something this page claims.