Table of Contents
ParserFunctions Plugin
Compatible with DokuWiki
- 2025-05-14 "Librarian" yes
- 2024-02-06 "Kaos" yes
- 2023-04-04 "Jack Jackrum" yes
- 2022-07-31 "Igor" unknown
Description
Provides additional parser functions for DokuWiki inspired by the MediaWiki ParserFunctions Extension.
For now, just #if
, #ifeq
, #ifexist
and #switch
functions are available, but it works very well and is a perfect companion for Templater and WST plugins (tested).
Please, help to translate: translate.dokuwiki.org/plugin/parserfunctions
Installation
Please refer to Extension Manager for additional info on how to search and install extensions in DokuWiki. Refer to Plugins on how to install plugins manually.
Syntax
Basic syntax:
{{#function: argument 1 | argument 2 | argument 3 ... #}}
Please, note that:
- This plugin starts with
{{#
and ends with#}}
. MediaWiki ends with}}
, don't forget the difference! - Empty spaces at the beginning and end of the arguments are ignored. To include white spaces at the beginning and/or end, enclose the argument between double quotes:
" string "
- Empty spaces in the middle are ok if they are just one, but more than 1 space will be trimmed to one single space. No workarounds.
- Functions can be nested! In theory, there is no limit to how many functions you can nest. Tested with 5 levels.
Escape Sequences
These are special characters for most ParserFunctions:
=
equals sign|
vertical bar (a.k.a. pipe)#
number sign (a.k.a. sharp, hash or pound sign){
and}
keys
The equal sign =
can be used outside #switch
whithout need of any escape sequence. So you can use it in #if
or #ifeq
but, inside a #switch
, it need to be escaped (if your intention is to use it as part of a string value). However, |
and #
need to be escaped in all the functions if you wish to add them to your string value or a switch case. And keys ({
and }
) are special in DokuWiki in general (at least when used 2 as in {{image}}
).
- As of 2025-01-18,
#
is no longer a special character for ParserFunctions and therefore does not need to be escaped.
There are two ways to escape them: the new and recommended way, and the old and deprecated one, kept for backwards compatibility.
The new and RECOMMENDED way, following the standard DokuWiki Syntax, wrap them in %%
(but not <nowiki>
tag):
character | sequence |
---|---|
= | %%=%% |
| | %%|%% |
{ | See exception below |
} | See exception below |
- Please note that you must not use spaces or put other characters inside the escape sequence:
- wrong:
%% = %%
<nowiki>=</nowiki>
- right:
%%=%%
- If you wish to escape an entire phrase with one or more special characters:
- wrong:
%%This is a = test.%%
%%This is a <nowiki>=</nowiki> test.%%
- right:
%%This is a %%=%% test.%%
<nowiki>This is a %%=%% test.</nowiki>
- Exception:
- You can escape keys as normal, as in
%%{{image}}%%
or<nowiki>{{image}}</nowiki>
, with or without spaces and other characters.
The old and DEPRECATED way, kept only for backwards compatibility:
character | sequence |
---|---|
= | &#61; |
| | &#124; |
{ | &#123; |
} | &#125; |
# | # (don't need to be scaped anymore) |
No new scape sequences will be added, it's a deprecated way and will be removed soon or later. Use %%
instead.
#if
This function evaluates a test string and determines whether or not it is empty. A test string containing only white space is considered to be empty.
{{#if: test string | value if test string is not empty | value if test string is empty (or only white space) #}}
{{#if: first parameter | second parameter | third parameter #}}
This function first tests whether the first parameter is not empty. If the first parameter is not empty, the function displays the second argument. If the first parameter is empty or contains only whitespace characters (spaces, newlines, etc.) it displays the third argument.
It can be written in many ways: with or without spaces, line breaks, etc.
{{#if: | yes | no#}} → no {{#if: string | yes | no#}} → yes {{#if: | yes | no#}} → no {{#if: | yes | no#}} → no
The test string is always interpreted as pure text, so mathematical expressions are not evaluated (see #ifexpr
for that):
{{#if: 1==2 | yes | no #}} → yes {{#if: 0 | yes | no #}} → yes
The second (true) and third parameter (false) may be omitted. It's usefull when user wants the result to be null:
{{#if: foo | yes #}} → yes {{#if: | yes #}} → {{#if: foo | | no#}} → {{#if: foo #}} →
If you are using Templater or WST plugins, you can also use a parameter as the test string in your #if
statement. Templater uses @parameter@
and WST adopts {{{parameter}}}
.
{{#if:{{{1}}}|You entered text in variable 1|There is no text in variable 1#}} {{#if:@1@|You entered text in variable 1|There is no text in variable 1#}}
To return the same text as the one given in the parameter just repete the string in the second field. You can use the third field as a “default” parameter or leave it blank to hide it.
{{#if: {{{1}}} | {{{1}}} | #}} → use {{{1}}} or hide if blank {{#if: @1@ | @1@ | default value #}} → use @1@ or "default value" if blank
#ifeq
This function compares two input strings, determines whether they are identical, and returns one of two strings based on the result. If more comparisons and output strings are required, consider using #switch
.
{{#ifeq: string 1 | string 2 | value if identical | value if different #}}
If both strings are valid numerical values, the strings are compared numerically:
{{#ifeq: 01 | 1 | equal | not equal#}} → equal {{#ifeq: 0 | -0 | equal | not equal#}} → equal {{#ifeq: 1e3 | 1000 | equal | not equal#}} → equal {{#ifeq: {{#expr:10^3#}} | 1000 | equal | not equal#}} → BUG
BUG: the
#expr
function has not yet been implemented, but if it had been it could be used, since nested functions work.
Otherwise, the comparison is made as text; this comparison is case-sensitive:
{{#ifeq: foo | bar | equal | not equal#}} → not equal {{#ifeq: foo | Foo | equal | not equal#}} → not equal {{#ifeq: "01" | "1" | equal | not equal#}} → not equal [^1] {{#ifeq: 10^3 | 1000 | equal | not equal#}} → not equal [^2]
[^1]
: compare to similar example above, without the quotes.
[^2]
: compare to similar example above, with #expr
returning a valid number first.
There is no convention for the order, but it is simpler to read if the parameter goes first. For example, in a WST template, whose parameters are enclosed by {{{params}}}
:
This {{#ifeq: {{{1}}} | short | 20 | 40 #}} is equal to this {{#ifeq: short | {{{1}}} | 20 | 40 #}}, order does not matter!
#ifexist
This function takes an input string and tries to figure out whether it is a page, a media (image), a namespace, a path to a folder, or a path to a file. It returns one of two values, depending on whether or not the page / media / folder / file exists on the local wiki.
{{#ifexist: page, media, namespace, or file/folder path | value if exists | value if doesn't exist #}}
The function evaluates to:
true
if thepage, media, namespace, file or folder
exists.error
if thepage, media, namespace, file or folder
parameter is not provided or only blanks.
If it is a page doesn't matter if it contains content, or if it is visibly blank, even if it contains hidden content (metadata like category links or magic words). If it exists, so it's true
. Only pages that are redlinked are evaluated as false
, including if the page used to exist but has been deleted.
If “start” page exists:
{{#ifexist: start | exist | doesn't exist #}} → exist
If page help
exists under namespace wiki
, you can write with or without spaces:
{{#ifexist: wiki:help | yes | no #}} → yes {{#ifexist: wiki : help | yes | no #}} → yes {{#ifexist: wiki:help | | no #}} → (empty) {{#ifexist: wiki:help #}} → (empty)
Or, on Unix-like systems only:
{{#ifexist: /data/pages/wiki/help.txt | yes | no #}} → yes {{#ifexist: data/pages/wiki/help.txt | yes | no #}} → yes {{#ifexist: data/pages/wiki/help | yes | no #}} → no {{#ifexist: /var/www/html/dw/data/pages/wiki/help.txt | yes | no #}} → yes
Medias, Other Files and Folders
Let's test if image wiki:dokuwiki-128.png
() exists?
{{#ifexist: wiki:dokuwiki-128.png | true | false #}} → true {{#ifexist: wiki/dokuwiki-128.png | true | false #}} → false {{#ifexist: /data/media/wiki/dokuwiki-128.png | true | false #}} → true {{#ifexist: data/media/wiki/dokuwiki-128.png | true | false #}} → true
Let's test if a plugin exists (is installed). What about parserfunctions
? For this we have to test if a folder exists. Result depends on whether it exists on your wiki or not. For this example, we will assume the plugin is installed.
{{#ifexist: /lib/plugins/parserfunctions | true | false #}} → true {{#ifexist: lib/plugins/parserfunctions | true | false #}} → true {{#ifexist: lib/plugins/ParserFunctions | true | false #}} → false
It's case sensitive!
#switch
This function compares one input value against several test cases, returning an associated string if a match is found.
{{#switch: comparison string | case = result | case = result | ... | case = result | default result #}}
Examples:
{{#switch: baz | foo = Foo | baz = Baz | Bar #}} → Baz {{#switch: foo | foo = Foo | baz = Baz | Bar #}} → Foo {{#switch: zzz | foo = Foo | baz = Baz | Bar #}} → Bar
Default
The default result
is returned if no case
string matches the comparison string
:
{{#switch: test | foo = Foo | baz = Baz | Bar #}} → Bar
The “default case” can be declared in two ways:
- Implicit: declared last, after all cases. A single string, without an explicit case name (as in the previous examples).
- Explicit: declared in any position, but you have to use the magic word
#default
, followed by the=
sign, and thevalue
, as in#default = any value here
.
{{#switch: test | foo = Foo | bar = Bar | sorry! #}} → sorry! {{#switch: test | foo = Foo | bar = Bar | #default = sorry! #}} → sorry!
Number sign
#
must be used to define a explicit #default. We did it this way so that the user can choose the word “default” as a case of the switch. And because MediaWiki implements it that way.
Additionally, the default result can be omitted if you do not wish to return anything if the test parameter value does not match any of the cases. All of these situations are the same:
{{#switch: zoo | foo = Foo | bar = Bar #}} → {{#switch: zoo | foo = Foo | bar = Bar | #}} →
Grouping results
It is possible to have 'fall through' values, where several case
strings return the same result
string. This minimizes duplication.
{{#switch: comparison string | case1 = result1 | case2 | case3 | case4 = result234 | case5 = result5 | case6 | case7 = result67 | case8 = | #default = default result #}}
Here cases 2, 3 and 4 all returns result234
; cases 6 and 7 both returns result67
.
And case8 will return nothing, because we used equal (=
) sign, and this is OK, since plugin understand you want this way.
Also, comparison string can be just “<empty>
” or just “<one or more blank spaces>
”. One or more blank spaces are trimmed and become empty. You can assign an empty case for these situations, or leave it to the default:
{{#switch: | = result for empty comparison string | ... other cases ... | default result #}}
Use with template parameters
This plugin is compatible with Templater and WST. This is because ParserFunctions are rendered after them.
WST template → {{#switch: {{{1}}} | foo = Foo | baz = Baz | Bar #}} Templater template → {{#switch: @1@ | foo = Foo | baz = Baz | Bar #}}
In the above case, if {{{1}}}
or @1@
equals foo
, the function will return Foo
. If it equals baz
, the function will return Baz
. If the parameter is empty or does not exist, the function will return Bar
.
Works with named case strings of course: {{{parameter}}}
or @parameter@
. Function evaluates the parameter's value, not the parameter itself. If parameter is empty, it will return the default value. If there is no default value it is empty
(= ''
).
Comparison behavior
As with #ifeq
, the comparison is made numerically if both the comparison string and the case string being tested are numeric.
Raw equal signs
Remember that raw equals signs =
can be escaped by %%=%%
.
Replacing #ifeq
#switch
can be used to reduce expansion depth, and can be nested (as any other function): function inside function, #switch
inside another #switch
or an #if
inside a #switch
etc, are possible!
Development
The source code of the plugin is available on GitHub: nerun/dokuwiki-plugin-parserfunctions.
Changelog
- added support for nested functions (2025-07-02 17:52)
- Improved PHP-Doc of functions, checkExistence for IFEXIST, regex etc (2025-07-01 22:17)
- syntax optimization, creation of helper (2025-07-01 20:16)
- improved error handling (2025-01-19 19:17)
- ifexist: added media, files and folders search (2025-01-19 18:12)
- Implemented #ifexist (2025-01-19 16:55)
- Switch: implemented fall through cases. (2025-01-18 22:01)
- Switch: implemented #default = value. (2025-01-18 20:31)
Known Bugs and Issues
- none for now.
ToDo/Wish List
Discussion
Ask here!