Wiki admins often want to take a template parameter (for example, {{{name}}}
in {{hello|name=James Holden}}
) and manipulate it in some way depending on how the user specifies the parameter, or even whether the user specifies the parameter at all.
In this post, I’m going to walk through some use cases and explain how to solve them. There are two extensions you will need installed on your wiki in order to follow along fully:
- ParserFunctions (required for almost everything)
- ParserPower (only needed for
{{#or:}}
)
Types of parameters
First of all, let’s talk about the two types of parameters. They are:
- Named parameters (like
name
in{{hello|name=James Holden}}
) - Ordered parameters (like the parameter in
{{hello|James Holden}}
)
A named parameter called name
can be accessed via {{{name}}}
in the template body (and this is case-sensitive, |Name=
will not fill {{{name}}}
; and {{{name}}}
and {{{Name}}}
are different in your template code). Ordered parameters can be accessed via {{{1}}}
, {{{2}}}
, {{{3}}}
, etc.1
When you call (transclude) a template, you can also explicitly send an ordered parameter by naming it with the value of a number, for example {{hello|James Holden}}
and {{hello|1=James Holden}}
are exactly identical to each other. If you name an ordered parameter like this, you must also name all subsequent ordered parameters. For example:
{{hello|Amos Burton|Peaches}}
- ok.Amos Burton
will be{{{1}}}
andPeaches
will be{{{2}}}
.{{hello|Amos Burton|2=Peaches}}
- ok.Amos Burton
will be{{{1}}}
andPeaches
will be{{{2}}}
.{{hello|1=Amos Burton|2=Peaches}}
- ok.Amos Burton
will be{{{1}}}
andPeaches
will be{{{2}}}
.{{hello|2=Amos Burton|Peaches}}
- ok.Peaches
will be{{{1}}}
andAmos Burton
will be{{{2}}}
.{{hello|1=Amos Burton|Peaches}}
- not ok.Peaches
will overwriteAmos Burton
for{{{1}}}
, and{{{2}}}
will be empty.{{hello|Amos Burton|1=Peaches}}
- not ok.Peaches
will overwriteAmos Burton
for{{{1}}}
, and{{{2}}}
will be empty.
Parameter types & whitespace
If you use a named parameter, whitespace will be stripped when your value is sent to the template. In other words, {{Hello|name=James Holden}}
is exactly the same as {{Hello|name= James Holden }}
. You can also put new lines without any effect, like:
{{Hello|name=
James Holden
}}
However, if you use ordered parameters, whitespace is not stripped. So these are all different from each other:
{{Hello|James Holden}}
{{Hello|James Holden }}
{{Hello| James Holden}}
If you write the number of the parameter you are transcluding, for example, {{Hello|1= James Holden }}
, then the ordered parameter acts like a named parameter and strips whitespace.
Try it yourself
- On your wiki, create a page called
Template:Hello
. WriteHello, {{{name}}}!
On another page, try writing{{Hello|name=Bobbie Draper}}
and preview/save it. What happens? - Try amending the template code (at
Template:Hello
) toHello, {{{1}}}!
. What happens now? Can you edit the calling code to fix it? - Finally, try the template code
Hello, {{{your_name}}}! I'm {{{my_name}}}.
Play around with this and try reordering the named parameters to see what happens. What if you changeyour_name
to1
andmy_name
to2
? Which version do you think is better? Why? - Ordered parameters seem pretty complicated. Why would you ever want to use them?
Answers
- You should see
Hello, Bobby Draper!
. - If you call the template as
{{Hello|name=Bobbie Draper}}
you’ll seeHello, {{{1}}}!
. We can fix this by writing{{Hello|Bobbie Draper}}
(or the not-recommended option{{Hello|1=Bobbie Draper}}
). - In this case, we’d rather use named parameters of
your_name
andmy_name
, because it would be difficult for the user to remember which is which without names. - If you have a frequently-used template that goes in the middle of paragraph text often, like
{{Item|item_name}}
which adds an icon to the left of the item name & links to the item’s page, you might want an ordered parameter to make the template easier to use, letting editors type less & not have to remember the name of the parameter.
Default values
A “default” value is a value that gets used when you don’t tell it to be something else. In MediaWiki, you can specify a default value of a parameter using a |
symbol, like this:
Hello, {{{your_name|Naomi Nagata}}}! I'm {{{my_name|James Holden}}}.
Here are the possible things you could write, and what happens when you do:
- If you say
{{hello}}
, the output will beHello, Naomi Nagata! I'm James Holden
. - If you say
{{hello|your_name=Rocinante}}
, the output will beHello, Rocinante! I'm James Holden
. - If you say
{{hello|my_name=Rocinante}}
, the output will beHello, Naomi Nagata! I'm Rocinante
. - And if you say
{{hello|your_name=Rocinante|my_name=Canterbury}}
, the output will beHello, Rocinante! I'm Canterbury
.
This is very cool, but there is a problem: If you say {{hello|your_name=|my_name=}}
then the output will be Hello, ! I'm .
That’s not what we want at all! What’s going on?
The syntax {{{your_name|Naomi Nagata}}}
is saying, “if the user doesn’t specify any value for your_name
, write Naomi Nagata
. Otherwise, write the value that the user specifies.” And if you write {{hello|your_name=}}
then you are specifying a value for your_name
- an empty string.
An example
Say you have infobox code that looks like this:
{{InfoboxSpaceship
|name=
|volume=
|owner=
|crew=
|faction=
|destroyed=
}}
If destroyed
isn’t set, then you want the infobox to automatically say “Never,” otherwise the user specifies a date. You also want to distribute this copyable code to everyone so they know what all the parameters are. But as we just saw this won’t work if you write {{{destroyed|Never}}}
!
There are a few ways we can fix this. The first one is to write {{#if:{{{destroyed|}}}|{{{destroyed}}}|Never}}
. Now, if destroyed
is nonempty, we’ll display that; and otherwise, we’ll display the text Never
.
Another way involves ParserPower’s {{#or:}}
parser function, which returns the first non-empty argument it comes across. If you have that extension installed,2 you can write {{#or:{{{destroyed|}}}|Never}}
. If the user writes |destroyed=2350
then this will return 2350
. But if they write |destroyed=
and then close out the template, it’ll skip {{{destroyed|}}}
, which is an empty string, and move on to display Never
.
Try it yourself
- What would happen if we wrote
{{#or:{{{destroyed}}}|Never}}
instead? (In this version, there’s no pipe afterdestroyed
). Why could this be a problem? Can you think of any circumstances in which you’d want this behavior? - Can you rewrite
{{#if:{{{destroyed|}}}|{{{destroyed}}}|Never}}
using theifeq
parser function? You can check out the ifeq docs. Which version do you like better? - Write your own template that uses either the
{{#if:}}
construction or the{{#or:}}
construction to display content with a fallback. Be creative! If you can’t think of any idea, then try writing a sentence advertising a kitten for adoption, where the user specifies either the color of its fur or “unknown” for the fur color.
Answers
- If the user puts
|destroyed=
then nothing will change, but if they delete thedestroyed
parameter altogether, the template will output the literal string{{{destroyed}}}
. One reason we might want this is if we want to ensure users are correctly using copyable code so we want to show something that looks a lot like an error if they leave out a parameter that should be there. {{#ifeq:{{{destroyed|}}}||Never|{{{destroyed}}}<!-- end if -->}}
.- Here’s an example:
Cat for adoption! * Name: {{{name|}}} * Age: {{{age|}}} * Fur color: {{#or:{{{fur_color|}}}|Unknown}}
Advanced default properties
Depending on your use case, there are some different behaviors you might want out of a parameter. Let’s go through each of them and how you can achieve it. In these examples, our template is called Hello
and there’s one parameter called name
.
{{Hello}} should… |
{{Hello|name=}} should… |
Example code to achieve both requirements |
---|---|---|
Error | Show nothing | {{{name}}} |
Show nothing | Show nothing | {{{name|}}} |
Show Avasarala |
Show nothing | {{{name|Avasarala}}} |
Error | Show Avasarala |
{{#or:{{{name}}}|Avasarala}} |
Show nothing | Show Avasarala |
{{#if:{{{name}}}|{{{name|}}}|Avasarala}} |
Show Avasarala |
Show Avasarala |
{{#or:{{{name|}}}|Avasarala}} |
Show Sec General |
Show Avasarala |
{{#or:{{{name|Sec General}}}|Avasarala}} |
Try it yourself
Try each of these and verify they work. You can go to Template:Hello
on your own wiki and preview this:
<includeonly><!-- replace this comment with the parser function code --></includeonly><noinclude>
# v1: {{Hello}}
# v2: {{Hello|name=}}
# v3: {{Hello|name=Chrisjen}}
</noinclude>
Can you rewrite each of the examples that use or:
to use if:
instead?
Answers
{{#or:{{{name}}}|Avasarala}}
can be written as{{#if:{{{name}}}|{{{name}}}|Avasarala}}
{{#or:{{{name|}}}|Avasarala}}
can be written as{{#if:{{{name|}}}|{{{name}}}|Avasarala}}
{{#or:{{{name|Sec General}}}|Avasarala}}
can be written as{{#if:{{{name}}}|{{{name|Sec General}}}|Avasarala}}
Using switch
You can also achieve all of the above results using the #switch
parser function instead of #if
and #or
. Let’s take a look:
{{Hello}} should |
{{Hello|name=}} should |
Example code to achieve both requirements |
---|---|---|
Error | Show Avasarala |
{{#switch:{{{name}}}|=Avasarala|#default={{{name}}}}} |
Show nothing | Show Avasarala |
{{#switch:{{{name}}}|=Avasarala|#default={{{name|}}}}} |
Show Avasarala |
Show Avasarala |
{{#switch:{{{name|}}}|=Avasarala|#default={{{name|}}}}} |
Show Sec General |
Show Avasarala |
{{#switch:{{{name}}}|=Avasarala|#default={{{name|Sec General}}}}} |
Try it yourself
Try each of these and verify they work. Which version do you prefer, using if/or or always using a switch statement? Why?
Other resources
- ParserFunctions help page on mediawiki.org
- ParserFunctions’ string functions help page on mediawiki.org
- Help:Templates on Wikipedia
-
Yes, MediaWiki is 1-indexed. This may annoy some experienced programmers, but it works out nicely when writing Lua scripts, since Lua is also 1-indexed. However, some parser functions are 0-indexed, for example
{{#explode:puppies,kittens|,|1}}
will returnkittens
and notpuppies
. Always check extension documentation or test it yourself to figure out how it’s indexed. ↩︎ -
ParserPower is included on all wiki.gg wikis. ↩︎