Mastering MediaWiki Parser Functions: Essential Techniques for Advanced Users

Why “parser functions” matter (even if you’ve been tinkering with MediaWiki for ages)

When you stare at a wikitext page that magically fills in dates, makes conditional tables, or pulls data from another article, you’re basically watching parser functions at work. For newcomers they look like sorcery; for seasoned editors they’re just another toolbox. This post pulls together the tricks that most “advanced” users either overlook or keep hidden in personal wikis.

Quick refresher – what’s a parser function?

In MediaWiki jargon a parser function is a special construct that starts with # and behaves like a tiny, inline program. It gets evaluated while the wikitext is parsed, before the output is finally rendered. Think of it as a macro that can read variables, do simple math, or decide what to show.

Basic syntax

{{#function_name:parameter1|parameter2|…}}

Everything after the colon up to the closing braces is split on the pipe (|) character; the first piece is the function name, the rest are arguments.

Effective grouping – using variables

Variables are the unsung heroes behind clean, reusable markup. The two main families are {{#vardefine}} / {{#vardefineecho}} (temporary) and the long‑standing “magic words” like {{FULLPAGENAME}}. Here’s a small pattern I use to avoid repeating a long article name:

{{#vardefine:page|{{FULLPAGENAME}}}}
* Link: [[{{#var:page}}]]
* Talk: [[Talk:{{#var:page}}]]

Notice the double‑braces around #var. It’s a tiny detail that trips up newbies: the variable expansion happens after the outer braces are stripped, so you really need both.

Scoping tricks

Variables defined in a #if block stay visible afterwards – an easy way to propagate a value without polluting the global namespace. For instance:

{{#ifexist:{{FULLPAGENAME}}/Data|
  {{#vardefine:data|{{#subpagename:Data}}}}
}}
The data for this page is {{#var:data}}.

If the subpage doesn’t exist, #vardefine never runs, and #var:data stays empty. That’s a clean “optional” pattern.

Conditional logic – #if, #ifeq, #iferror

The simplest conditional is #if. It checks whether its first argument is non‑empty. But most of the time you need to compare two strings, numbers or even the result of an expression. Enter #ifeq and #iferror.

Example – show a warning when a user forgets to fill a required field in a template:

{{#if:{{{title|}}}||
  You must provide a title.
}}

And a numeric check (useful for stats pages):

{{#ifeq:{{#expr:{{{score|0}}} >= 100}}|1|
  {{#iferror:{{#expr:{{{score|0}}}+0}}|
    Score isn’t a number.
  |
    Score is below the threshold.
  }}
}}

Notice the use of #expr to do arithmetic, and the double‑pipe that separates the “true” and “false” branches.

Switching between multiple values – #switch

If you have three or more alternatives, #switch beats stacked #if calls both in readability and performance.

{{#switch:{{{type|default}}}
|article = {{#ifexist:{{FULLPAGENAME}}/Article|Article content}}
|image   = {{#ifexist:{{FULLPAGENAME}}/Image|Image preview}}
|default = Unknown type.
}}

Each = clause can itself contain other parser functions, which makes #switch a tiny control‑center for almost any “type‑based” template.

Expressions – #expr

If you need math or logical operators, #expr is your go‑to. It supports:

  • Arithmetic: +, -, *, /, mod
  • Comparison: =, !=, <, >
  • Logical: and, or, not
  • String functions: strlen, substr

Example – creating a progress bar based on a percentage:

{{#expr:
  {{#if:{{{percent|}}}|{{{percent}}}|0}}
}}

That one‑liner just sanitises the input (defaults to 0) before feeding it to a CSS class or a template that draws the bar.

Namespace and page‑related functions

Sometimes you need to slice a page name: get the title, the namespace, or the URL‑encoded version. MediaWiki offers a set of so‑called “title‑functions”:

  • #titleparts – returns individual parts (namespace, title, subpage, etc.)
  • #urlencode – makes a string safe for URLs
  • #urlencodepath – similar but keeps slashes
  • #rel2abs – converts a relative link to an absolute one

Use case – building a link to the edit form of a related article:

{{#ifexist:{{FULLPAGENAME}}/Reference|
  [{{fullurl:{{FULLPAGENAME}}/Reference|action=edit}} Edit reference]
}}

The fullurl magic word (not a parser function but a sibling) couples nicely with #urlencode when you need to pass parameters.

Formatting helpers – #tag, #timel

Outputting raw HTML is frowned upon, but #tag lets you safely emit a tag with proper escaping:

{{#tag:div|Content here|class=note}}

And for timestamps, #timel can format a Unix timestamp according to a locale‑specific pattern. It’s handy when you want a “last‑updated” line that respects the reader’s language settings.

Transclusion modifiers – includeonly, onlyinclude, noinclude

These aren’t parser functions per se, but they dictate whether a template’s markup is seen by the page that includes it. A quick cheat‑sheet:

  • <includeonly>…</includeonly> – shown only when transcluded, never on the template page itself.
  • <onlyinclude>…</onlyinclude> – everything else is stripped; only the enclosed part appears on transclusion.
  • <noinclude>…</noinclude> – shown on the template page, but never when the template is used elsewhere.

Mixing these with parser functions yields compact “template‑as‑API” constructs. For example, a “data‑sheet” template might expose just a table (wrapped in onlyinclude) while keeping documentation hidden with noinclude.

Advanced pattern – Cascading defaults

One common pain point is letting a user override a default, yet providing fall‑backs without sprinkling #if everywhere. Here’s a neat trick that combines #var and #ifexist:

{{#vardefine:color|{{#ifexist:{{FULLPAGENAME}}/Color|{{#subpagename:Color}}|blue}}}}
This text follows the chosen colour.

If the subpage Color exists, its content wins; otherwise we fall back to “blue”. The pattern works for any setting – icons, language strings, even CSS snippets.

Performance notes – don’t over‑nest

Parser functions are executed sequentially. Deeply nested calls (#if inside #expr inside #switch…) can slow down rendering, especially on high‑traffic wikis. A rule of thumb: if a construct feels like a “spaghetti” of pipes, consider splitting it into a small auxiliary template.

Also, avoid using #expr for simple string checks; #if does the job faster. The MediaWiki engine logs “expensive parser function” warnings for cases that cross a hidden threshold.

Real‑world example – a dynamic “infobox”

Below is a compact infobox template that pulls a page’s subtitle, an optional image, and a stats table, all driven by parser functions. It demonstrates conditional sections, variable scoping, and safe HTML output.

{{#ifexist:{{FULLPAGENAME}}/Subtitle|
  {{#vardefine:subtitle|{{#subpagename:Subtitle}}}}
}}
{{#ifexist:{{FULLPAGENAME}}/Image|
  {{#vardefine:image|{{#subpagename:Image}}}}
}}
{{#ifexist:{{FULLPAGENAME}}/Stats|
  {{#vardefine:stats|{{#subpagename:Stats}}}}
}}

{{#tag:table|{{#if:{{#var:subtitle}}|
  {{#tag:tr|{{#tag:td|{{#var:subtitle}}|colspan=2}}}}
}}
{{#if:{{#var:image}}|
  {{#tag:tr|
    {{#tag:td|{{#var:image}}|width=100}}
    {{#tag:td|{{#var:stats}}}}
  }}
|
  {{#tag:tr|{{#tag:td|{{#var:stats}}|colspan=2}}}}
}}
|class=infobox
}}

What’s happening?

  1. We check for the existence of three optional subpages (subtitle, image, stats).
  2. Each existing subpage gets stored in a temporary variable.
  3. The final table is built with #tag to avoid raw HTML.
  4. Conditional rows appear only when their corresponding data is present.

The result is a tidy infobox that auto‑adjusts its layout without any manual editing.

Debugging tip – #show

When a parser function misbehaves, sprinkle #show into the markup to dump the value of a variable or the result of an expression. Example:

{{#show:{{#var:color}}}}

The output appears on the rendered page, letting you verify the exact string that the parser sees. Once you’re sure, simply remove the line.

Wrapping up – a mental checklist

  • Scope first. Declare temporary variables early, then reuse them.
  • Prefer #if / #ifeq over long #expr. Faster and clearer for simple checks.
  • Group alternatives with #switch. Keeps templates readable.
  • Escape HTML with #tag. Avoid raw tags unless you trust the source.
  • Test with #show. Quick sanity checks save hours of hunting.

Mastering these patterns turns a cluttered, “hand‑rolled” wikitext page into a maintainable, self‑documenting component. The next time you need a dynamic list, a conditional banner, or a multi‑step calculation, reach for the parser function toolbox first – you’ll thank yourself when the page loads in a flash and future editors can read your logic without grimacing.

Subscribe to MediaWiki Tips and Tricks

Don’t miss out on the latest articles. Sign up now to get access to the library of members-only articles.
jamie@example.com
Subscribe