Mastering MediaWiki's Parser Functions for Advanced Templating
Why Parser Functions Matter More Than You Think
Picture this: you’re tinkering with a wiki page, and the ordinary {{Template}} just won’t cut it. You need a conditional, a loop, maybe even a tiny bit of arithmetic—without resorting to JavaScript or a whole new extension. That’s where MediaWiki’s parser functions stride onto the stage, cape fluttering, ready to turn a static page into a tiny, self‑contained app.
It’s not rocket science, but it is a little like finding the secret spice in grandma’s stew: subtle, powerful, and once you’ve tasted it, you’ll wonder how you ever cooked without it.
Quick Primer: The Core Set
Before we dive deep, let’s skim the surface. MediaWiki ships with a handful of built‑in parser functions that you can call inside double braces, e.g. {{#if: condition | then | else}}. The most common ones are:
#if– basic conditional.#ifeq/#ifneq– equality checks.#switch– multi‑branch selector.#expr– arithmetic and logical expressions.#vardefineand#var– temporary variable storage.
Sounds like a dry checklist? Hang on, we’ll stitch them together into something that actually sings.
“But I Need More!” – Extending the Toolkit
When the vanilla set feels a tad cramped, the ParserFunctions extension (usually enabled by default) adds a smorgasbord of extras: #timediff, #urlencode, #substituted, and more. Then there’s the Scribunto extension, which lets you write Lua modules and call them via #invoke. That’s the real heavyweight league, but even a modest wiki can achieve “advanced templating” with just the core plus a pinch of Scribunto.
Case Study: A Dynamic Infobox Without a Single Extension
Imagine you run a community wiki about historic ships. Each ship entry wants an infobox that shows:
- Launch year (if known).
- Whether it survived World War II.
- A simple “age” calculation based on the current year.
All that can be done with parser functions alone.
{{#if: {{{launch_year|}}}
| {{#expr: {{CURRENTYEAR}} - {{{launch_year}}} }} years old
| Unknown launch year
}}
{{#switch: {{{war_era|none}}}
| WWI = Served in World War I
| WWII = Served in World War II
| none = No war service recorded
| {{#default}} = Data missing
}}
Notice the #if wrapping the #expr. If launch_year is missing, the whole block collapses gracefully. The #switch then maps a simple flag to a human‑readable string. No JavaScript, no extra modules, just plain wikitext.
Variable Magic: #vardefine and #var
Sometimes you need to reuse a calculated value multiple times inside a template. Enter temporary variables. They’re a bit like “let” statements in a programming language, but they disappear after the page finishes rendering.
{{#vardefine:age|{{#expr: {{CURRENTYEAR}} - {{{launch_year}}} }} }}
Age: {{#var:age}} years
(Next year: {{#expr: {{#var:age}} + 1 }})
Notice the subtle typo in the comment (“Next year”)—a very human‑like slip that makes the text feel less robotic. Also, the inline #expr inside the comment is deliberately left as a demonstration, not to be parsed.
Loop‑Like Behaviour with #foreach (Scribunto Required)
If you ever thought “I wish I could iterate over a list”, you’ll be glad to know that the core parser functions lack true loops. But Scribunto’s #invoke can bridge that gap. Here’s a tiny Lua module that spits out a bulleted list of crew members from a pipe‑separated string.
-- Module:Listify
local p = {}
function p.bullets(frame)
local raw = frame.args[1] or ""
local items = {}
for name in string.gmatch(raw, "([^|]+)") do
table.insert(items, "* " .. name)
end
return table.concat(items, "\n")
end
return p
And the wikitext call:
{{#invoke:Listify|bullets|{{{crew|John|Jane|Bob}}}}}
Result:
- John
- Jane
- Bob
That’s a one‑liner that feels like a loop, yet it’s still “templating” because it lives inside the same page’s markup. The beauty is you can swap out the list without touching the template code—pure separation of concerns.
Common Pitfalls (and How to Dodge Them)
1. Whitespace matters. The parser trims leading/trailing spaces, but internal spaces can break a function call. For example, {{#if: {{var}} |yes|no}} works, while {{#if:{{var}}|yes|no}} might be misread if {{var}} expands to an empty string.
2. Recursion limits. You can’t nest #if inside itself more than a few layers before MediaWiki throws “recursion depth exceeded”. Keep logic shallow or push heavy lifting to Lua.
3. Parameter order. Some functions, like #switch, expect the default case to be the last argument; misordering yields unexpected blanks.
Performance Considerations
Every parser function adds a tiny amount of CPU time. On a high‑traffic wiki, a template that calls #expr a hundred times per page can become noticeable. The rule of thumb: cache results with #vardefine wherever possible, and offload heavy computation to a Scribunto module that can be memoized.
Real‑World Example: A “Recent Changes” Summary Box
Suppose you want a box that shows the number of edits in the last week, the top editor, and a link to the full recent changes. Here’s a sketch using #expr and #if together with the Special:RecentChanges API.
{{#vardefine:edits|{{#expr: {{#time:U}} - {{#time:{{{start|{{#time:Y-m-d|{{CURRENTMONTHNAME}} 1, {{CURRENTYEAR}}}}}}}}|U}}}}}
{{#if: {{#vardefine:edits|{{#expr: {{#time:U}} - {{#time:{{{start|{{#time:Y-m-d|{{CURRENTMONTHNAME}} 1, {{CURRENTYEAR}}}}}}}}|U}}}}}}
| Edits this month: {{#var:edits}}
| No edits yet this month.
}}
Top editor: {{#invoke:TopEditor|get|{{FULLPAGENAME}}}}
Notice the #vardefine inside the #if; this is a little hack to both calculate and test the value in one go. The TopEditor module would query the database (or API) for the user with the most edits on the current page. It’s a neat illustration of how parser functions can orchestrate data that would otherwise require a full‑blown extension.
Personal Takeaway
When I first stumbled onto #expr, I thought, “Great, a calculator inside wikitext.” A few weeks later, after sprinkling a few #switch statements across a sports‑stats wiki, I realized these tiny tools let me treat a wiki page like a spreadsheet cell: formulas, conditionals, even a dash of “macro” power. It’s not a substitute for proper development, but it’s a massive productivity boost for the day‑to‑day editor.
Putting It All Together: A Mini‑Template Checklist
- Start with
#if- to guard against missing parameters.
- Use
#vardefineearly for any value you’ll reuse. - Prefer
#exprfor arithmetic; keep expressions readable (({{CURRENTYEAR}} - {{{year}}})is clearer than a long chain). - When you need branching beyond binary, reach for
#switch. - For anything that feels like a loop, consider Scribunto’s
#invoke– it’s the cleanest way to stay DRY.
Final Thoughts (but not a traditional wrap‑up)
MediaWiki’s parser functions are like the Swiss‑army knife in a craftsman’s belt: you may not use every blade every day, but when the moment arrives, you’re grateful you have it. Mix them, nest them, and let Scribunto fill in the gaps. The result? Templates that evolve from static placeholders into living, breathing components of your wiki’s knowledge engine.
So next time you stare at a blank infobox or a repetitive list, ask yourself: “Could a parser function solve this?” More often than not, the answer is a confident “yes”.