UESPWiki:MetaTemplate

The UESPWiki – Your source for The Elder Scrolls since 1995
Jump to: navigation, search
Information icon.svg In normal templates, the term "variables" applies to environment-specific information like {{PAGENAME}}. This extension introduces local variables in the traditional sense of the term, which creates a couple of naming ambiguities. For the purposes of this document, "variable" will be used to cover both passed parameters and locally created variables, since they're effectively treated the same once defined. If needed, environment-related variables will be referred to as "environment variables".

MetaTemplate provides several template-related parser functions. These features are intended to permit more powerful templates, more legible templates, and data-sharing between articles. Better documentation for some of the features can be found at Magic Words.

Installation[edit]

As with all modern extensions, the initial installation is to add wfLoadExtension('MetaTemplate'); to LocalSettings.php. If data functions (see below) are enabled, you should also run php maintenance/update.php in order to create the required tables and convert the original MetaTemplate data, if it exists. Note that the old MetaTemplate tables will not be deleted at any time; these must be removed by hand. This allows the old ones to remain available if needed.

Once installed, there are four global variables that govern which functions will be available. All of these are set to true by default; setting them to false will disable the listed functions. In addition to those four, there is another setting which serves as a sanity check for #listsaved.

Global Variable Purpose
$metatemplateEnableCatPageTemplate Enables/disables: <catpagetemplate>
$metatemplateEnableData Enables/disables: {{#listsaved}} {{#load}} {{#preload}} {{#save}} <savemarkup>
$metatemplateEnableDefine Enables/disables: {{#define}} {{#inherit}} {{#local}} {{#preview}} {{#return}} {{#unset}}
$metatemplateEnablePageNames Enables/disables: {{FULLPAGENAME0}} {{FULLPAGENAMEx}} {{NAMESPACEx}} {{NAMESPACE0}} {{NESTLEVEL}} {{PAGENAME0}} {{PAGENAMEx}}
$metatemplateListsavedMaxTemplateSize Limits the size of templates to be used with the #listsaved feature to reduce the chance of creating excessively large, slow-loading pages. (Default: 10000)

Features[edit]

Variable Definition[edit]

All of the following parser functions alter template variables. Most work within the context of the template they're called from, but #inherit and #return interact instead with "parent" templates or pages in order to allow data to be transferred between them.

Conditional expressions couple particularly well with variable definitions. If the same condition needs to be used multiple times, it can instead be stored in a variable using #define or #local to evaluate the condition once, then you would reuse the variable in each necessary subroutine. For example:

[[Category:Online-{{#if:{{{dead|{{#ifeq:{{{health|}}}|0|1}}}}}|Dead NPCs|NPCs}}]]
[[Category:Online-{{#if:{{{dead|{{#ifeq:{{{health|}}}|0|1}}}}}|Dead NPCs|NPCs}}-{{{gender}}}]]
... is both more efficient and more readable as ...
{{#local:npccat|{{#if:{{{dead|{{#ifeq:{{{health|}}}|0|1}}}}}|Dead NPCs|NPCs}}}}
[[Category:Online-{{{npccat}}}]]
[[Category:Online-{{{npccat}}}-{{{gender}}}]]

#define[edit]

Test Page

The main purpose of #define is to provide a default value for a template parameter, but the variable will only be created if it doesn't already exist. However, #define tags can be used to do more than simply replace an input argument:

  • The arguments to a #define tag can contain any combination of other wiki code. In particular, any variables that have previously been defined anywhere in the template or the template's arguments will be recognized. Therefore, #define tags can refer to any of the template's input arguments and can be used to combine or process those arguments.
  • The processing required to parse the arguments is only done once no matter how many times the #define'd variable is subsequently used. Therefore, #define'd variables can increase the efficiency of templates by eliminating repetitive code parsing.
  • Using the case=any option, #define and its derivatives can also be used to allow flexibility in a parameter's capitalization. For example, a parameter might be called maxhp internally but the template call could allow MaxHP, MaxHp, Maxhp or any other variation of lower- and upper-case to be used when the template is called. Note that after such a #define, the original values will no longer exist, leaving only the specified case.
#define
Parameter Scope Description
1 required The name of the variable.
2 required The value that should be assigned.
case optional Set to "any" to recognize parameters or variables with any capitalization rather than forcing a specific capitalization.
if optional This allows the same functionality as the {{#if:...}} function, but with an abbreviated syntax that can be both cleaner and more convenient when writing a template. If the end result is 0 or empty, the check will fail and the function will have no effect; otherwise, it will work as expected.
ifnot optional This works just like if, but will only run if the result of the check is 0 or empty. If you use if and ifnot together, both conditions must be satisfied in order for the function to work.

Each of the following examples assumes that the #define statement appears in a template named Test, which has been called using the code shown under "Template Call".

Example Template Call Result of {{{text}}} Explanation
{{#define:text|foo}} {{Test}} foo Equivalent to called {{Test|text=foo}}.
{{#define:text|foo}} {{Test|text=bar}} bar The value of "foo" is ignored because text already exists with the value "bar".
{{#define:text|foo}} {{Test|TEXT=bar}} foo The template variable is not recognized because its case is different.
{{#define:text|foo|case=any}} {{Test|TEXT=bar}} bar Since case=any has been specified, TEXT is considered equivalent to text and so {{{text}}} will be used after the #define, while {{{TEXT}}} will no longer be valid.
{{#define:text|{{{alttext}}}}} {{Test|alttext=bar}} bar Since alttext is defined but text is not, text takes on alttext's value.

#local[edit]

Test Page

This function assigns a value directly to a variable. If the value already exists, it will be overridden by the new value. If the value does not (i.e., it wasn't passed to the template), this will create it, making it appear as though it had been passed. It is otherwise identical to #define and has the same benefits as well as two additional ones:

  • You can use #local to set a default value for a parameter that is either not set at all or that might be blank, as is common when copying a blank template call. For example, {{#local:text|Default|ifnot={{{text|}}}}}.
  • It can also be used to sanitize values passed to the template. For example, a parameter that expects a purely numerical width might sanitize the width parameter with something like {{#local:width|{{#replace:{{{width}}}|px}}. From that point forward, it would look like the template had always been passed a purely numerical argument with no further need to check or re-sanitize the value.
#local
Parameter Scope Description
1 required The name of the variable.
2 required The value that should be assigned.
case optional Set to "any" to recognize parameters or variables with any capitalization rather than forcing a specific capitalization.
if optional This allows the same functionality as the {{#if:...}} function, but with an abbreviated syntax that can be both cleaner and more convenient when writing a template. If the end result is 0 or empty, the check will fail and the function will have no effect; otherwise, it will work as expected.
ifnot optional This works just like if, but will only run if the result of the check is 0 or empty. If you use if and ifnot together, both conditions must be satisfied in order for the function to work.
Example Template call Result of {{{text}}} Explanation
{{#local:text|foo}} {{Test}} foo Identical to a #define call
{{#local:text|foo}} {{Test|text=bar}} foo Unlike #define, the value used when calling the template is overridden by the #local statement

#preview[edit]

Test Page

The #preview function works exactly like #local, but only when you are previewing a template. It can be used to test exactly what a template will look like for a given set of input arguments. The advantage of using #preview instead of #local for such tests is that #preview can be saved with the template without affecting how it works.

#preview
Parameter Scope Description
1 required The name of the variable.
2 required The value that should be assigned.
case optional Set to "any" to recognize parameters or variables with any capitalization rather than forcing a specific capitalization.
if optional This allows the same functionality as the {{#if:...}} function, but with an abbreviated syntax that can be both cleaner and more convenient when writing a template. If the end result is 0 or empty, the check will fail and the function will have no effect; otherwise, it will work as expected.
ifnot optional This works just like if, but will only run if the result of the check is 0 or empty. If you use if and ifnot together, both conditions must be satisfied in order for the function to work.

#unset[edit]

Test Page

It stands to reason that if you can set a variable, you should also be able to clear it, which is exactly what the #unset function does with each variable passed to it, making it appear to the template as though the variable had never been set and/or passed to the template in the first place. If the variable was passed anonymously or by directly assigning it to a numeric position, the shift parameter can be used to shift any variables above it down by one.

#unset
Parameter Scope Description
1 required The name of the variable.
2 required The value that should be assigned.
shift optional When this option is set, each time a numbered variable is deleted, all those with a higher index number will get shifted down to fill the gap. Thus, if you use {{#unset:1|shift=1}}, what was in {{{2}}} will have shifted into {{{1}}}, what was in {{{3}}} will now be in {{{2}}}, and so forth. Note that using shift with multiple variables works the same as if you'd called #unset with shift multiple times. So, for example, {{#unset:1|2|shift=1}} is equivalent to {{#unset:1|shift=1}}{{#unset:2|shift=1}}, which is almost certainly not what you want, since it unsets {{{1}}} and shifts everything down before unsetting {{{2}}}, so it's actually unsetting what used to be {{{3}}}. While the code may be enhanced to deal with this better later on, for now, if you need to unset multiple numeric variables at once, you should list them in '''descending order''' (<code><nowiki>{{#unset:2|1}}) to avoid the problem.
case optional Set to "any" to recognize parameters or variables with any capitalization rather than forcing a specific capitalization.
if optional This allows the same functionality as the {{#if:...}} function, but with an abbreviated syntax that can be both cleaner and more convenient when writing a template. If the end result is 0 or empty, the check will fail and the function will have no effect; otherwise, it will work as expected.
ifnot optional This works just like if, but will only run if the result of the check is 0 or empty. If you use if and ifnot together, both conditions must be satisfied in order for the function to work.

Variable Passing[edit]

Variable passing functions allow a child template to get data directly from, or send data directly to, its parent without needing to save or load it.

#inherit[edit]

Test Page

This tells a nested template to inherit the values for the listed variables from the template(s) that called it. As many variable names as necessary can be listed in an #inherit statement, and it will recognize variables defined by any possible method (#define, #local, #inherit, #return).

#inherit will check recursively through the entire stack of templates to find any definition of a requested variable. It starts by checking the template itself (i.e., a #define statement preceding a #inherit statement will take precedence, as will any value provided when calling that specific template). If there are any values remaining that haven't been found yet, it then checks the parent template (the template that called the one containing the #inherit statement), then the grandparent, etc.

#inherit
Parameter Scope Description
1+ optional The names of the variables to inherit.
case optional Set to "any" to recognize parameters or variables with any capitalization rather than forcing a specific capitalization.
if optional This allows the same functionality as the {{#if:...}} function, but with an abbreviated syntax that can be both cleaner and more convenient when writing a template. If the end result is 0 or empty, the check will fail and the function will have no effect; otherwise, it will work as expected.
ifnot optional This works just like if, but will only run if the result of the check is 0 or empty. If you use if and ifnot together, both conditions must be satisfied in order for the function to work.

#return[edit]

Test Page

This function returns the values of all listed variables to the parent template. If the variable has already been defined in the parent template, #return will override that value. Unlike most programming languages, execution of a template does not stop at a #return statement. In this context, return means "return these values to the calling template", not "return from this template". Likewise, if the specified variables are subsequently altered in the template, the altered values are not copied to the parent template.

#inherit
Parameter Scope Description
1+ optional The names of the variables to inherit.
case optional Set to "any" to recognize parameters or variables with any capitalization rather than forcing a specific capitalization.
if optional This allows the same functionality as the {{#if:...}} function, but with an abbreviated syntax that can be both cleaner and more convenient when writing a template. If the end result is 0 or empty, the check will fail and the function will have no effect; otherwise, it will work as expected.
ifnot optional This works just like if, but will only run if the result of the check is 0 or empty. If you use if and ifnot together, both conditions must be satisfied in order for the function to work.

Data Sharing[edit]

These functions allow template variables from one page to be used on any other page. They provide an efficient mechanism for sharing information between pages, and therefore make it unnecessary to create stub-like subpages (/Description, /Author) for that purpose.

#listsaved[edit]

Test Page

This function calls a template for each page or set of #save'd data that meets specified criteria. Each template is called with the parameters listed below. #load and #inherit should be used to import any additional data required. If these names are present in the #save'd data, you may want to use the name mapping feature to avoid any overlap.

  • {{{fullpagename}}}, which corresponds to {{FULLPAGENAME}},
  • {{{namespace}}}, which corresponds to {{NAMESPACE}},
  • {{{pagename}}}, which corresponds to {{PAGNAME}},
  • {{{set}}}, which is used in the #load and #save functions to choose which data set to use.

Options for the #listsaved conditions are intentionally limited. If more complex conditions are necessary for a #listsaved call, then a new #save variable should be created to make the #listsaved call possible. For example, if a list containing both Ayleid Ruins and Forts was needed, it is not possible within #listsaved to request "(type=Ayleid Ruin) OR (type=Fort)". Instead, a new #save variable can be created, for example "alttype=Ruin or Fort".

Note that adding #preload to the template can significantly optimize #listsaved's performance.

Differences from Previous Version
  • The function no longer automatically inherits data from the page it's placed on if not found in the #save'd data. #inherit must be used explicitly within the template instead.
  • Templates called by the function now only pass the parameters listed above; all other data is expected to be loaded.
  • Instead of variable pre-loading being defined as part of the #listsaved call—a feature that was almost never used—it is now integrated into the template itself.
  • subset has been deprecated in favor of set to encourage the idea that all sets are equal and that assigning variables to a specific set is beneficial.
#listsaved
Parameter Scope Description
1 required The name of the template to run.
all named parameters
not listed below
2+ Each remaining argument should be a list of variable names and the values that they should match. At least one condition must be specified for any #listsaved call. If more than one condition is provided, then all of the conditions must be met. For example, |type=Ayleid Ruin|namespace=Oblivion, means that type must be set to "Ayleid Ruin" and namespace must be set to "Oblivion" for an article to be a match.
debug optional When this parameter is set, a list of all the templates to be called is returned instead of the results of calling those templates. Normally, this parameter is ignored unless you're using Show Preview; setting it to "always" causes it to always display the list, even during regular viewing.
namespace optional In addition to any values provided by the template, you can always filter based on namespace. Simply specify a namespace here and all results will be limited to that. For the time being, only real namespaces are supported; not those provided by UespCustomCode.
order optional The variables to sort by. This can include saved variable names, as well as any of: namespace (integer), pagename, and set. Unless already specified in the sort order, pagename and set are always added to ensure that ties consistently resolve in the same order.
separator optional This can be used to provide any text that should separate the selected entries. The default value for separator is a newline character. C-style escape sequences are recognized (e.g., '\n' for newline, '\t' for tab). To include spaces in the separator, it needs to be enclosed in quotes (single or double); otherwise the wiki processing will automatically strip any spaces from the end of the string. For example, |separator=' ' will add a single space in between all strings; the pair of quote marks is not considered part of the string.
case optional Set to "any" to recognize parameters or variables with any capitalization rather than forcing a specific capitalization.
if optional This allows the same functionality as the {{#if:...}} function, but with an abbreviated syntax that can be both cleaner and more convenient when writing a template. If the end result is 0 or empty, the check will fail and the function will have no effect; otherwise, it will work as expected.
ifnot optional This works just like if, but will only run if the result of the check is 0 or empty. If you use if and ifnot together, both conditions must be satisfied in order for the function to work.

Example: {{#listsaved:Place Link|type=Ayleid Ruin|namespace=Oblivion}} would create a list of all Ayleid Ruins in Oblivion, formatting each place using {{Place Link}}.

#load[edit]

Test Page

Loads each of the variables listed from the database unless they're already defined. These can subsequently be used just like any other template variable. Any number of variables can be requested.

Generally speaking, #load will cause a database query every time it's called. For that reason, #load commands should be combined into one to the extent possible. The only time #loads should be separate is if they're loading data from different sets or some of variables should only be loaded conditionally. No data will be loaded if all variables are already defined or if a #preload in the template already covers all the variables needed.

#load
Parameter Scope Description
1 required The page to load the data from. If the page is a redirect and there is data for it in the database, then #load will check for data at the redirect target. As with standard wiki usage, only a single redirect is followed. Data sets cannot be split between the redirect page and the page it redirects to. They must all exist on one page or the other.
2+ optional The names of the variables to load. If no variable names are specified, all available variables from the given set will be loaded. This should generally be avoided unless most or all values will be used, as it wastes resources to retrieve unnecessary data and store it in memory.
set optional Can be specified for multiple sets of data that have been #save'd for the requested article, to specify which of the sets should be #load'ed. This can be used to separate different types of information or information for multiple items on the same page, for instance. The default value for set is an empty string.
case optional Set to "any" to recognize parameters or variables with any capitalization rather than forcing a specific capitalization.
if optional This allows the same functionality as the {{#if:...}} function, but with an abbreviated syntax that can be both cleaner and more convenient when writing a template. If the end result is 0 or empty, the check will fail and the function will have no effect; otherwise, it will work as expected.
ifnot optional This works just like if, but will only run if the result of the check is 0 or empty. If you use if and ifnot together, both conditions must be satisfied in order for the function to work.

Example: {{#load:{{{bookPage}}}|author|authprefix|description|linktitle}} can be found in {{Book Link}}, where it loads various information for the requested book.

#preload[edit]

{{#preload:var1|...|varN}} (supports set)

Test Page

#preload saves metadata to the template page telling it what variables should be pre-loaded when using the #listsaved command. When #listsaved encounters this metadata, it bulk loads all of the named variables before calling the specified template. Because the information is bulk-loaded, rather than a page at a time, when used in a template, it can drastically speed up any #listsaved commands that call that template.

You should add #preload to any template called by #listsaved that also uses #load. If you include a variable list the covers the most frequently #loaded variables, it will no longer need to #load them on the page, resulting in drastic performance improvements.

Unlike #load, #preload should be placed in the <noinclude> section of the template or outside of any inclusion tags.

#save[edit]

{{#save:var1|...|varN}} (supports if, mapping)

Test Page
Example: {{#save:description|author}} could be placed in {{Lore Book}}, which would result in the description and author variables being saved for every book page that directly or indirectly includes the Lore Book template.

Each of the variables listed in the parser function is written to the database. As many (or as few) variables as needed can be listed in the parser function.

Optional arguments for #save are:

  • if and ifnot: enable/disable the entire function, see Conditional Expressions for details.
  • set: can be specified if there are multiple sets of data that need to be #save'd for a single article. If set is not specified, it will default to an empty string, however it's strongly encouraged to use a set name where possible, both for organization purposes and possibly a marginal improvement to #load speeds. Any arbitrary string, up to 50 characters in length, can be used for a set name.

Additional information:

  • Variables are normally saved after being fully expanded and parsed. Therefore, if the variables contain complex processing, the processing does not need to be redone by any articles that load the variables. However, in some cases, this is undesirable, as you want a template to be evaluated on the article it's loaded on. In that case, you can add |savemarkup=1 to the save call to force template syntax to be saved verbatim. This will then always take effect for the named variables, even if the user doesn't use <savemarkup>. If you need to have some variables with the savemarkup option and some not, simply split them between two #save calls—variables are always saved all at once, so there's no impact on template performance.
  • #save parser functions are always ignored when saving template pages. This prevents unwanted entries from being added to the database.
  • #save parser functions can be used on redirect pages, even if the #save function appears after the #REDIRECT command.
  • The actual #save operation (writing the data to the database) is only done once per savefile, no matter how many #save commands appear in the savefile. The #save database operation is done after the wiki has saved the article itself to the database. This ensures that the #save database has the correct file revision ID; it also ensures that #load commands can safely be executed concurrently (in separate apache threads) with #save commands without extended database locks.
  • In prior versions of MetaTemplate, the subset parameter was used. For backwards compatibility, this name has been retained, but since no set is subordinate to any other, they are now simply referred to as set. All sets are equal; the default set simply has a blank name.
  • Saved set names and variable names are limited to 50 characters each. There are no such restrictions if the variables are not being saved.

Details[edit]

  • Changing an article with #save'd data will automatically force any pages that #load the data to update: if the description variable is changed on Lore:King, then Lore:Books_K will automatically retrieve the new description.
    • This is accomplished by making the wiki think that the #save file is transcluded in any files that #load its data. In the above example, Lore:Books_K would be listed in Lore:King's "What Links Here" list as a transcluding article; Lore:King would appear in the list of "Templates used on this page" for Lore:Books K. This is purely a book-keeping trick. Lore:King is not actually transcluded in Lore:Books_K (this can be confirmed by looking at the template processing stats hidden in the HTML for Lore:Books_K; "Template argument size" is much smaller than it would be if actual transclusions were being done).
  • #save'd data is correctly updated if the article is renamed or deleted.
  • #save'd data is always updated if the article is purged.
  • #save'd data is automatically deleted from the database if the #save tag is deleted from the article.
  • #save'd data is automatically updated if any templates on the page are updated.
  • <nowiki>...</nowiki> tags are stripped within any saved variables, in both the save document and the load document. In other words, the nowiki tags are effectively ignored; the text within the tags will be wikified.
    • However, the nowiki tags are only removed immediately before the variable is saved. Therefore, nowiki tags can be used if there is a need to force specific variables or templates to be expanded after the variables are #loaded.
      • For example, if {{NAMESPACE}} is used in a saved variable, normally NAMESPACE would always provide the namespace of the original save file—ignoring the namespace of the file that #loads the data.
      • To instead force NAMESPACE to provide the namespace of the final article, even after being loaded, then the original variable definition should use <nowiki>{{NAMESPACE}}</nowiki>.
    • This behavior is definitely unusual, but it's basically an attempt to make the worst of a bad situation.
      • nowiki tags do not like the #save/#load processing. Without any special treatment, any nowiki'd text would be replaced by mangled nonsense (e.g., "UNIQ69c231c93c7370c8{{#if:{{{dosave|}}} | {{#save:variable}} }}") in any #load documents.
      • To make nowiki tags work "as usual" would require special treatment before a variable is saved, then more special treatment after the variable is loaded—special treatment that would require extra processing for every single variable, not just those variables that contain nowiki tags.
      • Effectively, only half of that special treatment has been implemented, namely, the check for nowiki'd text before a variable is #save'd. This unmangles the nowiki'd text before saving it to the database; it does not reinsert the nowiki tags.
      • The decision to not do any special processing after #load'ing the variables is intentional. It is assumed that #load commands may appear multiple times on pages that need a lot of processing, including some traditional "problem" pages (Oblivion:Merchants, Oblivion:Places). Therefore, including extra processing (that is hardly every going to be used) in the #load command may have a noticeable negative impact on site performance. Furthermore, a mechanism was needed for occasionally preserving wiki tags in #save variables (the {{NAMESPACE}} example is likely to be needed on Lore book pages); other ways of accomplishing that goal would be difficult to implement. The upshot is that processing is improved and a new capability is added—at the expense of eliminating the standard nowiki function within #saved variables.
  • Any other nowiki-like tags that "hide" text from the wiki parser are also broken. For example, <pre>...</pre>, <math>...</math>, <cleanspace>...</cleanspace>, and HTML comments.
    • All content within such tags is removed before the value is #save'd. This is the exact same problem that affects nowiki tags, but I'm handling it more simplistically in these cases.
    • The problem is that, during parser processing any such tags get replaced by a mangled "UNIQ...QINU" string (a marker for text that is being hidden from the parser). The original template knows the full context, so it restores the hidden text after parsing is done. But when #load'ed, all information about the hidden text is lost.
      • Instead of even bothering to save the mangled "UNIQ-QINU" string to the database, the code is now completely removing that marker. So in the end there is no visible sign that there was a chunk of problematic text.
    • In general, use of tags like these should be avoided in any templates that are going to be used within #save'd variables
    • However, in some cases, the problem tags can be used completely safely. The basic test is: does the #load'ed value content the correct text, or is it missing a chunk of text?
      • HTML comments can always be safely used in templates (they won't appear in the HTML source code, but presumably they don't need to).
      • If cleanspace tags are being used solely to handle a chunk of initialization (using #local, #define, #preview, etc. to set variables) and does not end up generating any actual text, then cleanspace tags can be used in templates without any problems. Just double-check that the cleanspace tags do not also contain categories.
  • There are actually two database tables associated with these functions: mt_save_set and mt_save_data. mt_save_data stores the actual variables; a numeric index, mt_save_id identifies the savefile. mt_save_set contains a single entry for each savefile, translating the savefile name into the numeric ID used in mt_save_data. mt_save_set also contains bookkeeping data necessary to ensure that database entries are cleaned up when necessary—namely, the article revision ID and a timestamp.

Tag Functions[edit]

catpagetemplate[edit]

<catpagetemplate>...</catpagetemplate>

Test Page

The catpagetemplate tag can be used on category pages to customize the appearance of the listed articles. (MetaTemplate version 1.0)

The contents of the tag should be template code. The code is executed once for each article listed in the category; each time, the parameter 'pagename' is set to the name of the article and 'sortkey' is set to the article's sortkey. By default, the text produced by the code is used for the article's label. In addition, #define statements can be used to customize many other aspects of the category listing.

Examples:

  • <catpagetemplate>{{#label:{{{pagename}}}}}</catpagetemplate>
    • The displayed text for each page would no longer contain any disambiguation data (e.g., "Oblivion:Umbra (person)" would be displayed as "Oblivion:Umbra")
  • <catpagetemplate>{{#define:catgroup|{{#sub:{{{sortkey}}}|0|4}}}}{{#define:catlabel|{{#sortable:{{PAGENAME0}}}}}}</catpagetemplate>
    • The displayed text would no longer include the namespace, and the text would be in "sortable" format
    • The first four letters of the articles would be used to create the sections on the category page, instead of just the first letter
  • <catpagetemplate>{{#load:{{{pagename}}}|catgroup|catlabel|catanchor}}</catpagetemplate>
    • #save'd data would be loaded to get the previously-determined values for catgroup, catlabel, and catanchor (catanchor would allow the category to link directly to the appropriate section of the page).

To limit wiki processing requirements, complex processing would not be appropriate in a catpagetemplate tag—especially since category pages are never cached. One possibility is to use a #load statement to fill in the variables, allowing any work to be done on the individual pages, instead of within the category.

Parameters with special meaning when #define'd within catpagetemplate:

  • Several parameters combine to create the text displayed for a given article; the result is equivalent to:
    • {{{cattextpre}}} [[{{{catpage}}}#{{{catanchor}}}|{{{catlabel}}}]] {{{cattextpost}}}
    • catlabel: the text to use for the article's label; overrides the output text of the tag. The advantage of using catlabel is that the contents of the catpagetemplate tag can then contain extra line breaks or even comments. The disadvantage of using catlabel is that any error messages produced when the template is parsed are lost, making debugging more difficult.
    • cattextpre: text to display before the link to the article; default . A space is automatically added in between the text and the link.
    • cattextpost: text to display after the link to the article; default . A space is automatically added in between the text and the link.
    • catpage: the full name of the article; defaults to {{{pagename}}}. In most cases, there should be no reason to set this parameter. If it is reset, there could be some minor anomalies because the code does not update various secondary settings based on a new value of catpage (e.g., the code does not check whether the page is valid, so the resulting link will be a standard blue link even if the page is non-existent; if a redirect is replaced with a non-redirect, the link will still be italicized, unless catredirect is also set).
    • catanchor: the section of the article to which the link should point; default .
  • catgroup: the group within which the article should be placed; defaults to the first letter of the sort key. catgroup can be a full word, or multiple words; there is no one-letter limitation. Note, however, that the articles are not re-sorted according to their group, therefore catgroup must be some logical derivative of the category sort key.
  • catredirect: is the link a redirect? This can be used to override the italicization of redirects, although normally it probably makes no sense to override the default values.
  • Note, there is no catsortkey parameter; no mechanism has been added for changing the order in which articles appear on the category. The problem is that implementing such a parameter would be incredibly inefficient on large categories (ones with more than 200 articles), because all the articles would have to be read, processed, resorted, and then refiltered to the correct set. It's better to find a way to correctly set the original sortkey.

Input values to catpagetemplate:

  • {{{pagename}}} is the article's full name
  • {{{sortkey}}} is the article's sort key
  • In addition, the article is added to the current template stack. This means that {{PAGENAME0}}, {{FULLPAGENAME0}}, and {{NAMESPACE0}} provide information about the article (unless catpagetemplate calls subtemplates, in which case {{PAGENAMEx}} and the equivalents could be used).

Other points:

  • This feature has been set up so it doesn't eliminate the category changes introduced by the CategoryTree extension. However (at the moment at least), catpagetemplate cannot be used to customize category trees. The options for displaying subcategories on the page are
    • without a catpagetemplate, CategoryTree will generate the subcategories
    • using <catpagetemplate stdsubcat=1>, CategoryTree will generate the subcategories
    • otherwise, catpagetemplate will generate the subcategories
  • When #load is used within catpagetemplate, the code will check to see whether there are multiple sets for the page, and if so, will try generating a category page entry for each set. For example, if several sections of the page should each be listed separately in a category, this provides a mechanism for doing so. [Except this is where catsortkey might be needed... I'm still pondering the details of this feature]

savemarkup[edit]

<savemarkup>...</savemarkup>

Test Page

The savemarkup tag allows you to save templates in their original form rather than having them expanded. This allows the template to be evaluated in the context of the page it's loaded onto rather than the page it's saved from. For example, if you use {{Lore Link|Abnur Tharn}} as the author in a Game Book template in Lore space, it will normally get expanded to Abnur Tharn before being saved. So, when you try to load that book in Online space, it still links to Abnur Tharn rather than Abnur Tharn. However, if you use <savemarkup>{{Lore Link|Abnur Tharn}}</savemarkup>, the order is reversed. That is, the author gets saved as {{Lore Link|Abnur Tharn}} and then gets evaluated after it loads. So on Online pages, the author would be linked to Abnur Tharn as you would expect.

This feature can also be automatically used for specific variables without requiring the use of <savemarkup>. See the ##save for more on that.

Miscellaneous[edit]

NESTLEVEL[edit]

{{NESTLEVEL}}

Test Page

In programming terms, NESTLEVEL is the template stack depth. In English, it's how many "nested" templates have been called before getting to NESTLEVEL. So, if you put {{NESTLEVEL}} directly on a page, it will display 0 since no templates are being called. If you put {{NESTLEVEL}} inside a template and then use that template on a page, the value of NESTLEVEL is 1 since you have called one template between the original page and NESTLEVEL. If you then call that template from yet another template, the number goes up to 2 and so on. This is most effectively used in templates like {{FMI}} to detect whether they're being called from the main Lore page or if they're being transcluded somewhere else.

If you need to test NESTLEVEL at various depths while designing a template, you can use {{NESTLEVEL|2}}, for example, and it will always display 2. You can also define or pass a variable named nestlevel. Like with the specified value, any number found in nestlevel will always be returned, regardless of the actual level of nesting. In the event that both are specified, the first version takes precedence.

Namespace and Pagename[edit]

  • NAMESPACE0, PAGENAME0, and FULLPAGENAME0 variables
  • NAMESPACEx, PAGENAMEx, and FULLPAGENAMEx variables (technically these are parser functions, but they are set up to be called as {{PAGENAMEx:arg}} instead of {{#PAGENAMEx:arg}} so that they are as similar as possible to the base variables)

Differences from Previous Version[edit]

  • case, if, and ifnot are now available on all variable and data-sharing functions.
  • #preview now works in all namespaces.
  • #load now supports "load all from set" functionality.
  • #load and #save no longer inherit or change the subset variable; that feature wasn't used significantly and if not understood, it could potentially lead to unintended results.
  • subset deprecated in favor of set to encourage the idea that all sets are equal and that assigning variables to a specific set is a beneficial.

General Notes[edit]

All the functions listed in the Variable Definition and Data Sharing sections support conditional expressions as well as a case-insensitive option, as detailed below.

Conditional Expressions[edit]

Test Page

Name Mapping[edit]

Most functions that deal with variables from outside the immediate template allow you to use different names between the source and the destination. For example, you might have a template that saves a Quest ID as simply id, but in another template, you want to load that as questid. To do so, you would use: {{#load:Quest Page|id->questid}}.

In each case, the mapping direction is from->to. Using id->questid as an example:

  • {{#load:Quest Page|id->questid}} loads id from the quest page to questid in the template.
  • {{#save:id->questid}} gets id from the template to questid in the data saved on the page.
  • {{#inherit:id->questid}} inherits id from the parent template to questid in the local template.
  • {{#return:id->questid}} returns id from the current template to questid in the parent template.
  • {{#listsaved:Template|condition=yes}} loads id from each page and sends it to the template as questid.
  • {{#preload:id->questid}} doesn't do anything on its own, but when either <catpagetemplate> or #listsaved find it, they will bulk load the data exactly as noted in #load, above.

Notes

  • Numeric variables are forbidden on both the from and to sides.
  • Safety when moving named variables is left entirely up to the editor. Overlapping mappings, such as id->here|id2->here|id2->elsewhere will not produce an error, though they're unlikely to be what the editor intends.

Special Pages[edit]

Special:MetaVarsOnPage[edit]

This special page allows you to see the #saved variables on a page. Simply enter the full page name and, if desired, the maximum number of items on any given page, and the results will be displayed.

Caution: When paging through data, the page will always start with a full set, even if it was partly displayed on the previous page of data. On pages with large enough sets, you could end up simply paging through the same data repeatedly and will have to increase the number of results returned in order to continue. As of this writing, the default value of 50 is large enough for all but a handful of pages (and any sandboxes that copy these pages):

Special:PagesWithMetaVar[edit]

This special page lists all pages containing a specific variable and/or set. Either the set name or a variable name must be provided. If you want to look for a variable within a specific set, both can be entered. You cannot leave the set at "Any" while the variable name is blank.

For the variable drop-down box, the 25 most common variables will be listed. For the namespace drop-down box, only namespaces that have actual #saved data in them are listed. Note: This data is updated every time the special page is viewed, which is not optimal on a large wiki with many users, but should pose no problems for UESP.

API[edit]

MetaTemplate includes an API property module which allows you to query pages for all #saved values, or for specific sets or values. The module can be requested using a standard prop parameter, using the name metavars. Parameters are listed below. Maximum values are listed as <value for most users>/<value for high-limits users>. On UESP, bots and admins both have the high-limits right.

Parameter Name Generator Parameter Name Purpose
mvcontinue gmvcontinue When more results are available, use this to continue. Normally only emitted by the generator, but can be emitted by the standard module if result set is very large.
gmvlimit The maximum number of pages to return (default: 10; max: 500/5000). Note that this parameter is enabled only in generator mode. Limiting standard results is possible, but not particularly useful in most instances. Sets and variable names provide more meaningful limitations. This also follows the behaviour of the similar prop=pageprops module, which doesn't support limits either.
mvset gmvset Only sets with the names specified will be returned. In generator mode, only pages with the sets specified will be returned. Supports multiple values (max: 50/500) using standard pipe separation. To get the main set of variables, use an empty value. To get only the main set, use mvset=| (the trailing pipe will be ignored).
mvvar gmvvar Only variables with the names specified will be returned. In generator mode, only pages with the variables specified will be returned. Supports multiple values (max: 50/500) using standard pipe separation.

Examples[edit]

Query parameters shown are limited to those that matter and separated for readability. Note: the queries below include &format=jsonfm to make them more human-readable; &format=json is the preferred format for programmatic use, and is the default in MediaWiki 1.25 and above.