FANDOM


Lua is a programming language that has been released in numerous versions. Lua 5.1 is a standard, though not the most recent. Scribunto is an extension for MediaWiki that executes code written in Lua 5.1 on the server.

The Lua executes on the server and is therefore considersyed our server-scripting language. Our client-side scripting language is JavaScript. Lua outputs in wikitext and therefore cannot give access to HTML features like JavaScript. It actually resolves itself at the same time as templates so template uses cannot be returned, but templates can be resolved in Lua.

Pages written in Lua are found in the Module namespace. Module outputs are cached for quicker execution, so features unique to a user's cookies or preferences is not possible.

ApplicationsEdit

Most invokables will be turned into templates to make them simpler to use. {{tl}} is a template designed in Lua, used for simple string processing and infinite parameters.

CodenameEdit

A server-side stored version of the system hosted in JavaScript. This allows for queries and comparisons. For example {{#ifeq:<code>{{#invoke:Codename|rel|FFI|full}}|Final Fantasy|success}}</code> becomes "".

Imagine the possibilities! One use returns values in a similar manner to how the JavaScript-backed HTML class "variable-output" works (<span class="variable-output">rel.FFI.full</span> becomes "rel.FFI.full").

One thing that can be done is using the colors outside of their normal text color and background color scenario.

<span style="background:{{#invoke:Codename|rel|FFX|a|background}};border:2px solid {{#invoke:Codename|rel|FFX|b|background}}">{{#invoke:Codename|rel|FFX|full}}</span> ->

Another way in which the module can be used is lookup which allows a value to be searched for in a specific sub-property and returns matching codenames.

{{#invoke:Codename|lookup|rel|full|Final Fantasy}} -> Script error

If the lookup matches multiple codenames then it returns an array. One can return a single member of the array by attaching a number, so:

{{#invoke:Codename|lookup|rel|a|color|black}} -> Script error
{{#invoke:Codename|lookup|rel|a|color|4|black}} -> Script error

Although this feature does not serve much purpose because the order of array members are in an arbitrary order, and a user will unlikely be searching for a specific codename when using it, and even if they were- catching it by specification of number would be worrying.

WikiFunctionsEdit

Some parser functions are written in Lua. {{ifstring}} is actually the only one.

Function Parameters Example Description
ifstring string
search
true - Value if true
false - Value if false (default: blank string)
{{#invoke:WikiFunctions|ifstring|All|B|C}} -> '
{{#invoke:WikiFunctions|ifstring|All|a|C|D}} ->
C'

{{#invoke:WikiFunctions|ifstring|All|A|C|D}} -> C
Tests if string contains search string and prints true or </code>false</code> string accordingly.
ifnum string
true - Value if true
false - Value if false (default: blank string)
{{#invoke:WikiFunctions|ifnum|A|B}} -> '
{{#invoke:WikiFunctions|ifnum|e|B|C}} ->
C'

{{#invoke:WikiFunctions|ifnum|0|B|C}} -> B
Tests if string evaluates as a number and prints true or </code>false</code> string accordingly.
expr expression {{#invoke:WikiFunctions|expr|1+5*6}} -> 31
{{#invoke:WikiFunctions|expr|2<3}} -> 1
{{#invoke:WikiFunctions|expr|2004 % 4 == 0 and (2004 % 100 ~= 0 or 2004 % 400 == 0)}} -> 1
Prints evaluated expression. Uses Lua equation syntax.
arraymap array - Delimiter separated string
delimiter
variable - String to replace
formula - Recurring string contains variable
separator - String appearing after each formula instance (default: empty string)
{{#invoke:WikiFunctions|arraymap|A@B@C@D|@|{X}|.{X}.}}.A..B..C..D.
{{#invoke:WikiFunctions|arraymap|A@B@C@D|@|{X}|I like {X}|,}}I like A, I like B, I like C, I like D
Prints formula repeatedly with instances of variable replaced by members of array, separated by separator string. Note: Parameters cannot be output by the arraymap, though the {{#invoke}} can be substituted to have the output value print to the wikitext with functioning parameters.
lua args[] (see desc) {{#invoke:WikiFunctions|lua|math|sqrt|4}} -> 2
{{#invoke:WikiFunctions|lua|math|pi}} -> 3.1415926535898
{{#invoke:WikiFunctions|lua|string|len|"lol"}} -> 3
Prints Lua variable or function output. The parameters are names of tables, methods, and properties until the functions finds a value or function. If it reaches a value it prints it, if it reaches a function it uses the remaining passed parameters as parameters for that function.

paramargsEdit

paramargs is a function designed to be used in conjunction with templates. The goal of the function is to allow templates to use an infinite number of parameters without needing to be converted to Lua themselves. The general gist of the template is that the templates that use the function submit the parameters submitted to it (in pages it is transcluded in), and runs small string based functionality on them. Its features are similar in manner to arraymap.

All of paramargs parameters are named. Though the template is designed to take the numbered parameters submitted by other templates, it can use numbered parameters in itself to do the same thing.

Parameter Default Purpose
first 1 The number of the first auto-numbered parameter to include.
omit 0 The number of auto-numbered parameters at the end of the argument list to exclude.
variable "{X}" The variable representing an input's value in the format.
length variable false The variable representing the total number of values input.
iteration variable false The variable representing an input's iteration/number in list.
format variable The string returned, with instances of variables inside it changed to intended values on output.
separator "" The content that appears between nodes.
before "" The content that appears before if any parameters are submitted.
after "" The content that appears after if any parameters are submitted.
escape false Boolean for whether to escape characters. Allowing escape characters allows text to be processed after parameters are input. Enables escaping of all code-corruptors.
escape pipe \ (nil) String to replace with the pipe character (|). If escape is false but escape pipe is specified, then escapes pipe but not necessarily others.
escape tempin {@ (nil) String to replace with the template-in string ({{). If escape is false but escape tempin is specified, then escapes template-in strings but not necessarily others.
escape tempout @} (nil) String to replace with the template-out string (}}). If escape is false but escape tempout is specified, then escapes template-out strings but not necessarily others.
escape equals ~ (nil) String to replace with the equals character (=). If escape is false but escape equals is specified, then escapes equals but not necessarily others.

As examples:

{{#invoke:WikiFunctions|paramargs|A|B|C}} -> ABC
{{#invoke:WikiFunctions|paramargs|variable=@|iteration variable=#|format=#:|separator="
"|A|B|C}}
-> 1: A, 2: B, 3: C
{{#invoke:WikiFunctions|paramargs|variable=_X|iteration variable=_#|length variable=_%|format=_X ([%\_#/_%] complete)|escape=true|escape tempin=[|escape tempout=]|A|B|C}} -> Script error

An example of a template that uses paramargs is {{sideicon}}. A user can input infinite parameters of release codenames. The template's use of the function is:

{{#invoke:WikiFunctions|paramargs|variable={X}|format=}}

An example of an input might be: {{sideicon|FFI|FFII}}. Therefore the result on the page would be: <span id="FFI-icon"></span><span id="FFII-icon"></span>.

parampropsEdit

paramprops is a function designed to be used in conjunction with templates. The goal of the function is to allow the same code to be applied to a property of any name, and not have each valid property name be whitelisted. Templates that use the function submit the parameters submitted to it (in pages it is transcluded in), and runs small string based functionality on them. Its features are similar in manner to arraymap.

The properties are not returned in the order they are input, it returns them in alphabetical order. A parameter exists that allows strings to be compared to Lua patterns. An array, it orders them in match importance. For example, { "Dog", "D%lg" } would prioritize "Dog" over "Dig", but "Dig" and "Dug" would be on equal footing (though "Dig" is first alphabetically so that would be first), which would all be above "Cog".

All of paramprops parameters are named. Unlike paramargs, supplying parameters within the invoke rather than transclusions is less advised, though blacklisting of the used properties still allows it to function appropriately.

Parameter Default Purpose
omit {} Lua table of blacklisted properties. Do note that as a Lua-syntax parameter the string inputs have to be surrounded by quotations.
order {} Lua table of sort order Lua patterns. Do note that as a Lua-syntax parameter the string inputs have to be surrounded by quotations.
variable "{v}" The variable representing an input's value in the format.
property "{k}" The variable representing the input's property name in the format.
format variable The string returned, with instances of variables inside it changed to intended values on output.
separator "" The content that appears between nodes.
before "" The content that appears before if any parameters are submitted.
after "" The content that appears after if any parameters are submitted.
escape false Boolean for whether to escape characters. Allowing escape characters allows text to be processed after parameters are input. Enables escaping of all code-corruptors.
escape pipe \ (nil) ). If escape is false but escape pipe is specified, then escapes pipe but not necessarily others.
escape tempin {@ (nil) String to replace with the template-in string ({{). If escape is false but escape tempin is specified, then escapes template-in strings but not necessarily others.
escape tempout @} (nil) String to replace with the template-out string (}}). If escape is false but escape tempout is specified, then escapes template-out strings but not necessarily others.
escape equals ~ (nil) String to replace with the equals character (=). If escape is false but escape equals is specified, then escapes equals but not necessarily others.

As examples:

{{#invoke:WikiFunctions|paramprops|A=1|B=2|C=3}} -> 123
{{#invoke:WikiFunctions|paramprops|format={k}: {v}|omit={"omit", "format"}|A=1|B=2|C=3}} -> A: 1B: 2C: 3
{{#invoke:WikiFunctions|paramprops|variable=V|property=K|format=K = V|separator=, <nowiki/>|before={ <nowiki/>|after=|<nowiki/> }|omit={"variable", "property", "format", "separator", "before", "after"}|A=1|B=2|C=3}} -> { A = 1, B = 2, C = 3, omit = {"variable", "property", "format", "separator", "before", "after"}
{{#invoke:WikiFunctions|paramprops|AA=1|B=2|C=3|order={"B", "%L"}|omit={"order", "omit"}}} -> 231}

An example of a template that uses paramprops is {{tag}}. A user can input any attribute by using the attribute name as the name of the parameter. The template's use of the function is:


{{#invoke:WikiFunctions|paramargs|variable={X}}}

An example of an input might be: {{tag|div|class=aclass|id=anid|data-lol=madeup|content}}. This would appear as: <span id="anid"class="aclass"data-lol="madeup">content</span>.

Where to writeEdit

Lua can only be process when inside a page in the Module namespace. This means it is not possible to test things in your own personal userspace. To test things Module:Sandsea should be utilized. The console in the edit form of a module page may also be a sufficient place to do testing without needing to save anything.

An easy way to write scripts with syntax highlighting support is to use this website, however importing Modules stored on the wiki is impossible this way so they have to be partially copied over; and any tags used in printed outputs will not display because the tags will be interpreted as HTML.

Functions designed to be common use within scripts can be added to Module:FFWiki. Small functions designed to be invoked within templates can be added to Module:WikiFunctions. Collections of related functions are stored in individual modules, such as Module:StringFunctions. Collections of related functions are stored in individual modules, such as Module:Array. Larger and more complex functions or related groups of functions may also be stored at their own module, such as Module:Tl or Module:Codename.

A single syntax error can prevent an entire module from working, and therefore any other scripts that reference functions in a module may also stop working. If one is unsure if what they are doing they should first test in a safe environment (Module:Sandsea, console, external Lua executor). The Module namespace is a a small controlled area, supervised by <Group-designer>. All edits and additions to important modules and creation of new ones will be reviewed and evaluated.

How to writeEdit

CommentsEdit

Comments allow text to avoid being interpreted. These are used for programmer's notes. In-line comments are indicated by two dashes; all code on the line following this is not read as code. Starting a new line will end the comment, the only time a new line is seen as syntactical.

a = b--comment
b = a

Block comments start the same way as an in-line comment, however following it two open square-brackets ([[) should be used. The block comment closes when it sees two close square-brackets (]]).

a = b--[[ comment
b = a
a = b ]]
b = a

It is possible for two close square brackets to appear in valid syntax code. It is for this reason that it is advised block comments are not used to comment out sections of code.

StatementsEdit

<member> = <value>

A standard statement Lua is a member name followed by an assign symbol (=, equals sign) followed by a value. A statement may also be the declaration of a variable (and the implicit assigning of nil), or the variable may be declared and assigned in the same statement.

As an example:

variablename = 5

The running of a function is also a valid statement even if is not returning a value.

functionname()

There is no syntax to separate statements, only the logical end of a statement indicates its end. For example, the assignment symbol, concatenation symbol, and other arithmetic and logical operators will always be followed by a value as part of the same statement. But if a member were to follow a member or value immediately then it would be seen as part of a new statement. Semi-colons can be placed after each statement, though they are not needed. New lines are typically used to follow statements for benefit of those reading or writing the script.

Structures in Lua do not have an implicit end. Keywords are used to indicate code is written for the different parts of the structure. Most structured end with the end keyword.

ArithmeticEdit

Arithmetic allows processing of values.

Operator Meaning
+ Addition
- Subtraction.
* Multiplication
/ Division.
% Modulus.
^ Exponentiation.

This means that on the value part of the equation there does not have to be a single static value, there could be a calculation.

As an example:

variablename = 5 + 5

The member variablename now holds a numeric value of 10.

The math library contains additional mathematical functions.

ConcatenationEdit

Concatenation is the process of connecting two strings. The operator for concatenation is .. (two dots).

For example:

variablename = "T" .. "he"

variablename holds the value "The".

LogicEdit

Logical operators compare values and then return either true or false. Most structures that effect flow make use of logic. Logical operators asks the browser a question, and depending on the browser's answer the code will do different things.

Below are a list of built-in evaluators:

Operator Meaning
== Equal to.
< Less than.
<= Less than or equal to.
> Greater than.
>= Greater than or equal to.
~= Not equal to.
5 == 4 --> false
5 == 5 --> true
5 == 6 --> false
5 < 4  --> false
5 < 5  --> false
5 < 6  --> true
5 <= 4 --> false
5 <= 5 --> true
5 <= 6 --> true
5 > 4  --> true
5 > 5  --> false
5 > 6  --> false
5 >= 4 --> true
5 >= 5 --> true
5 >= 6 --> false
5 ~= 4 --> true
5 ~= 5 --> false
5 ~= 6 --> true

There are three further logic operators. The not operator negates the result. A true result will become false, and a false true.

not true   --> false
not false  --> true
not 5==5   --> false
not 4==5   --> false
not (4==5) --> true
Note above the use of brackets is required in that scenario, otherwise it would read as "
(not 4) == 5"
.

The and operator allows multiple logic equations to be processed, and only if they are all true will the end result be true.

1 == 1 and 2 == 2 and 3 == 3             --> true
1 == 3 and 2 == 2 and 3 == 1             --> false
1 == 2 and 2 == 3 and 3 == 1             --> false
not (1 == 3) and 2 == 2 and not (3 == 1) --> true

The or operator allows multiple logical equations to be processed, and if any one of them is true the end result will be true.

1 == 1 or 2 == 2 or 3 == 3 --> true
1 == 3 or 2 == 2 or 3 == 1 --> true
1 == 2 or 2 == 3 or 3 == 1 --> false

Data typesEdit

Lua has only six main data types. number, string, and boolean are the basic data types, functions are of the function type, the nil value has a nil type, and Lua has its array and object data types as one in the table data type.

Data types are implicit and syntax determines what type of value an input is.

The global type function detects the data type of its input and returns it as a string. This is useful in validating inputs and handling them differently.

Lua does not have standard support for classes, though constructing functions and metatables can be set to append methods and static properties to tables, and functions can be used to standardize properties to create what are effectively classes. Although objects of these classes would be tables, the .__type metaproperty (or .__type metamethod if the value is a function) can be used to give the object a type. The type function in the Module:FFWiki library considers this in its return value.

stringEdit

Strings are text values. When using strings the text is wrapped in either, double quotes (", ") or single quotes (', '), more often than not the former though when working on HTML the latter is usually used to avoid conflicts with double-quotes for attributes. The backslash (\) can be used to escape characters within a string, and \n (backslash, lowercase N) is the new line character.

Alternatively, two square brackets ([[, ]]) can be used for a multi-line string where new lines in the code are new lines on the screen. This syntax can be used like the others, however everything inside is viewed literally. Therefore a use of a backslash will be viewed as a backslash character.

Strings can be concatenated to form new strings. Numbers can also be concatenated with each other and other strings to form new strings, however all other data types will return an error if concatenation is attempted.

A string value can have its length returned by using the # (hash symbol) character before it.

Strings can be compared alphabetically via the ID of the characters with the less and greater than operators (<, >, <=, >=).

The tostring global function converts both boolean values and nil values into the string equivalents of their key words, and converting function and table values will return the string "table".

The ifnotblank function in Module:FFWiki returns false for nil values and empty strings.

The tochartable function in Module:String returns the string as an auto-indexed table to capture aspects of a string without resorting to substrings each time.

numberEdit

Numbers are valid decimal numbers up to 14 significant figures, greater values use that e+ notation, and more decimals are not counted. Numbers can also be input using hexadecimal notation by prefixing it with 0x.

Numbers can have arithmetic and comparison logic performed on them. Strings can have also have arithmetic and logic performed on them if they contain valid number text. For example,
5 + "5" == 10
.

The global tonumber returns input number values as is and converts numerically valid string values to number, but returns nil in every other circumstance.

booleanEdit

There are two boolean values represented by keywords true and false.

The keyword not prefixing a boolean value will give it its opposite meaning, so not true == false.

When boolean values can be used in logic equations inputting only the value, false values will be treated equivalent to nil values. All other potential values are treated as true.

nilEdit

The nil type is a null or undefined type and essentially not a value. When a variable or property is not declared but used the value will benil. When a variable is declared and but not assigned a value or when a function parameter has no value passed the name holds the value of nil, and functions that end without returning a value will return nil.

A nil value cannot be stored in a named parameter of a table, otherwise the key will just be removed. They can be stored in auto-indexed parameters however.

functionEdit

A member of the function type is a function, whether assigned to a variable or created as a named function. The syntax for a function is starting with the function keyword, and a function must also contain brackets containing parameters and an end keyword; like:
function() end

An unnamed function can be executed by surrounding it in brackets and then placing brackets after it to input the function's parameters

Functions can sometimes be passed as parameters in cases like the string library's sort, or in the Module:Array library's foreach.

tableEdit

A table is a member that contains more members. This can mean auto-indexed numbers like in an array, or named properties like in a standard object, or both. Unlike most other languages, indexes in Lua begin from 1 rather than 0. A member that contains a table does not truly contain a table, rather it contains a link to a table. In this I mean if one were to assign one table (say variable a) of a table to another member, (say variable b), unlike other data types the table contained by either member is the same. Adding, removing, or modifying the table under one variable name will also change it at the other. This capability is most commonly seen in functions, as when a table is passed as a parameter to a function, modifications made to that table are made to the table where it was called from. The same cannot be performed with other data types and a modified value will have to be returned.

The syntax for a table is contents wrapped in curly braces ({, }) while its members are separated by commas. If a member is named then its section starts with the name of the parameter followed by an equals sign. If the name is complex then it will have to be wrapped in square brackets ([, ]). Square brackets can also be use to encase a stored value (such as a variable) to name the property based on a calculated value.

The term "complex" here means if the name contains more than just the usual alphanumeric characters accepted in variable names. This includes strings containing a space, a dash, or an equals symbol, and it also includes and other value (besides nil) one would be able to put in this space. Values of even the table and function types will work.

pname = "n-3" a = { "A", "B", n = 1, ["n-2"] = 2, [pname] = 3 }
would appear like this:
a = {
  [1] = "A",
  [2] = "B",
  ["n"] = 1,
  ["n-2"] = 2,
  ["n-3"] = 3  
}

To call a member of a table there are two notations that can be used. For named parameters the table name can be followed by a . (dot) and then the property name. If the property name is complex for one of the previously mentioned reasons (e.g. contains a "-") then they cannot be called in this way.

When calling a complex string property name, a non-string property name, or via a stored name, then square-brackets have to be used to get the value. The table name is followed by square brackets containing the value.

New values can be added to a member after its creation by assigning values using the above mentioned syntax, e.g.
a[3] = "C"
. The table library's insert value allows an auto-indexed value to be added to the table, or a value inserted at a specified index (pushing the other ones up).

Named property values can be removed from the table by assigning nil to them. The table library's remove function removes the last auto-indexed member of the table, or removes a value at a specified index (pushing the other ones down).

The Module:Array library contains functions to manage an array of data. The pop function removes the last-indexed member, the shift function removes the first-indexed member, the push function adds a new auto-indexed value to the end of the table, and unshift inserts a new value to the first index of the table, pushing the others up. The concat function adds the auto-indexed contents of other table onto the end of an original.

The number of auto-indexed elements in a table can be returned by prefixing the table with a hash symbol (#). Named properties are ignored.

Some tables have special properties and are referred to as readonly tables. They are tables whose values cannot be changed and their length cannot be gauged with the hash. The table holding the arguments sent from {{#invoke}} commands, frame.args, is one of these types of table. The Module:FFWiki library's reargs function clones the table into a normal table.

VariablesEdit

Variables come in two kinds, global and local. The difference is the scope. Global are accessible from anywhere in the program while local can only be used from where they are declared and in deeper scopes. A scope is defined by a block, so the contents of a page are a block, the contents of a function on that page are a nested block, and the contents of a selection structure in that function is another nested block. Variables local to the page are accessible from everywhere on that page while variables local to the selection structure are local only to that part of the selection structure (the IF, ELSEIF, and ELSE are each their own block). One would typically indicate a block with the indentations of new lines (two spaces per block), though for shorter structures such as those containing one statement, it is likely that the entire structure will be on one line. Therefore the only way to know is to find where the syntax indicates the block should start and end.

Local variables are set when local precedes the variable name on the first time it is used. While this variable is in scope, assigning a value to a variable of that name will change its value. Prefixing a use of a variable with local while the previous is in scope will create a new variable. If it is in a deeper scope then the first defined one will be unreachable while in that scope, while setting the variable at the same level will make the original variable unreachable.

A global variable's declaration is implicit. Assigning a value to a variable that exists in no local scopes will assign it to a global variable, and if the global variable does not exist then it will be created. Global variables can be reached at any time despite local variables existing with the same name, and this is done through the _G object. _G contains all global objects which are properties of it. _G.variablename will always refer to the global variable. Declaring new global variables while a local one in scope is therefore done by creating it as a new property of _G.

ScopeEdit

Variables and functions can be placed in different scopes. The basic concept is that when variables are set they can be accessed only in areas of the program that need them. Members accessible from everywhere are in the global scope, while those within a smaller scope are in a local scope. The local scope can refer to any number of different levels. For example:

i = 1 --global scope
do
  local i = 2 --local scope
  do
    local i = 3 --more local scope
    do
      local i = 4 --even more local scope
    end
  end
end

To demonstrate the power of levels:

i = 1 --global scope
print(i) --prints 1
do
  print(i) --prints 1
  local i = 2 --local scope
  print(i) --prints 2
  do
    print(i) --prints 2
    local i = 3 --more local scope
    print(i) --prints 3
    do
      print(i) --prints 3
      local i = 4 --even more local scope
      print(i) --prints 4
    end
    print(i) --prints 3
  end
  print(i) --prints 2
end
print(i) --prints 1

As demonstrated above, there are four different i variables in play. The global i, the i local to the first do, and then the other two i variables inside their respective nested do structures.

Prefixing a value with local defines a variable and places it in the current scope. To get or set its value thereafter, local does not have to be prefixed. In fact, doing so at a deeper scope will only create a new variable at that deeper scope, making the variable at a higher level inaccessible during that scope.

If a local variable does not exist in a scope with the used name, then setting a value to a variable will create a global variable. This is seen above on the first line where i is created as a global variable. Although in the code sample prefixing it with local will produce the same output, they are not the same. There are two key differences:

  1. A local variable in a page is not accessible outside of that page.
  2. A global variable is always accessible.

By the second point we mean that if the first i was local, in deeper scopes once a local variable with the name of i were created we could not refer to the i in the highest scope. Members of the global scope are stored in the _G table. As a demonstration:

i = 1
local j = 1
do
  local i = 2
  print(i) -- returns 2
  print(_G.i) -- returns 1
  local j = 2
  print(i) -- returns 1
  print(_G.j) -- returns nil
end

If local variables are obscured by local variables at a deeper level they become inaccessible inside that scope.

A deeper scope is created inside most structures. So there are separate scopes within a function, within an if, an elseif, and an else, within each do iteration (so each loop is its own scope).

So the below code sample is incorrect:

if true then
  local i = 1
else
  local i = 2
end
return i

nil will be returned because neither declaration of i is in the same scope as the return.

This would instead be done like:

local i
if true then
  i = 1
else
  i = 2
end
return i

Which would return 1. However, in many of the cases as above, if the only purpose of the IF is to set different values to a variable then the Ternary IF, or inline IF, is simpler. The equivalent to the above is:

local i = true and 1 or 2
return i
Or more simply the variable can be bypassed and
return true and 1 or 2
would work suitably.

As a further note to scope, when a Module is called via require, anything that happens inside that module occurs independently of where it was called from. This means any modifications to global variables do not apply to where it was called from. The value returned by the module is returned at the place it was called from, but nothing else of the environment is affected.

Multiple ValuesEdit

Lua has a concept that allows more than one value to be the value in a statement. This does not refer to a table, but instead literally multiple values. The values are comma-separated. This is somewhat akin to a function's parameter inputs. As an example:

local x = 5, 6

In the above example, x is being assigned a value of 5, the 6 gets discarded. But not only does Lua allow multiple values to be assigned, but also multiple members to be assigned to:

local x, y = 5

In the above example, x is 5, and y is nil. Naturally, a more logical use of this would be like so:

local x, y = 5, 6

Where both values are assigned numbers, x gets 5 and y gets 6. This could be done for an infinite number of values.

More than just assigning multiple values to variables in the statement however, multiple values have places elsewhere. For example, some functions return multiple values. One example is the string library's gsub function. The function returns the string with replacements made, but as a second value it returns the number of replacements made.

string.gsub("aba", "a", "c") --> returns "cbc", 2

The benefit of this is allowing the return of more details about the process without to return all the data in a table.

Earlier it was mentioned that this multiple value technique was akin to function parameters, and this is actually applicable. Take for example the global print function. The function can take infinite parameters, and putting the result of a function that returns multiple values in there prints all those values.

print(string.gsub("ababa", "a", "c")) --> prints "cbcbc 3"
print(string.gsub("ababa", "a", "c") .. "") --> prints "cbcbc"

In the second example only the first value is returned because processing occurs and therefore it only happens to the first value while the others are ignored and discarded.

Multiple values can often be unwieldy, especially when there will be an unpredictable amount. The Module:Table library's pack function can be used to compact all of these, regardless of amount, into a table. Conversely, the same library's unpack function converts a table's values into a multiple value list which may be useful for passing as a function's parameters.

If one were to want to store a later value but not earlier ones, a function could be used to grab the specific values, or an assignment could be made and immediately overwritten. For example:

--Overwritten assignment (assign first value to a, assign second value to a)
local a, a = string.gsub("aba", "a", "c") --> a = 2
--Anonymous function in Lua 5.1 / FFWiki
local a = (function(...) return arg[2] end)(string.gsub("aba", "a", "c")) --> a = 2
--Anonymous function in Lua 5.2+
local a = (function(...) arg = table.pack(...) return arg[2] end)(string.gsub("aba", "a", "c")) --> a = 2

StructuresEdit

DOEdit

In its basic use, the DO structure sections off a block a code. This has implications on scope. The main use of do is within iteration structures where the block can be executed numerous times.

The syntax for the structure starts with the do keyword and ends with the end keyword.

do
code
end

Demonstrating a DO structure:

do
  local i = 5
  print(i) --prints 5
end
print(i) --prints nil

SelectionEdit

IF, ELSE, and ELSEIFEdit

The IF structures test a condition for a value other than false or nil. If it is not one of those then the code inside the IF will be executed.

The syntax for the structure starts with the if keyword which is followed by the condition value, then the then keyword, followed by a block of code, and ends with the end keyword.

if
value
 then
code
end

Demonstrating IF:

if true then
  print("true")
end
if false then
  print("false")
end

The result of the above would be true would be printed. Since the condition for the second IF structure is false it never runs.

As part of the IF structure, an ELSE structure can be included. Before the end keyword can be the else keyword, which can be followed by a block of code to execute instead if the condition is false or nil

if
value
 then
code
else
code
end

Demonstrating ELSE:

if true then
  print("true")
else
  print("not true")
end
if false then
  print("false")
else
  print("not false")
end

The result of the above would be the printing of true and not false. The condition is true on the first so runs the IF block, and false on the second so runs the ELSE block.

Multiple ELSEIF structures can also be included. These follow the IF within IF structures and offer alternate conditions to run if the first is false. These use the elseif and then keywords.

if
value
 then
code
elseif
value
 then
code
else
code
end

Demonstrating ELSEIF:

if x==nil then
  print("Non-existent")
elseif x<0 then
  print("Negative")
elseif x==0 then
  print("Zero")
else
  print("Positive")
end

The result of the above would be the printing of non-existent if x does not exist, Negative if x is a number less than 0, Zero if x is 0, and Positive in all other circumstances.

Ternary IFEdit

Ternary IF, also known as inline IF, is a way of checking a condition and returning an output. Its benefit over using a standard IF structure is that it works inline. This avoids repeating of variable names and such things and can be done in a single statement. The and and or keyword are used to fulfill this.

It comes in two forms. The first tests a value is not false or nil, and prints it if not, else it prints another given value.

value
 or
else
 then

For example:

print("me and" .. (x or "who knows"))

The above prints "me and who knows" if x is nil or false or "me and " the value of x if it is. For example, if x is you, then the display will be "me and you".

The second form tests a value and prints another given value if true, a given value if not false or nil, or another given value in other circumstances.

test
 and
true
 or
false

For example:

print(x .. "? " .. (x==5 and (x .. " is my favorite number") or ("I hate " .. x)))

The above prints "5? 5 is my favorite number" if x is 5; or "<value of x>? I hate <value of x>" if the value is anything else.

As an example of the benefits of ternary IF, the above with regular IF would be written like so:

local y = x .. "? "
if x==5 then
  y = y .. x .. "my favorite number"
else
  y = y .. "I hate " .. x
end
print(y)

A variable has to be used to achieve the same thing, and specified multiple times. A variable could be avoided, but then print would have to be specified both times, as would the string (x .. "? ").

It should be noted that if a false or nil value is the output for true in the second version of ternary IF, it will not function as one might expect. The way to solve this should be as simple as reversing the condition (such as wrapping it in a not) and reversing the outputs.

For example:

print(ab=="" and nil or ab) --always prints value of ab
 
print(not (ab=="") and ab or nil) --prints nil if ab=="", prints ab otherwise
 
print(ab~="" and ab or nil) --same as above using dedicated operator

If the goal of the logic test is to output boolean values based on an input value (and not necessarily boolean), a ternary IF does not need to be used. What one might hope is achieved (but is not) by (test and false or true) can be achieved by simply using not logic. An equivalent to (test and false or true) is then not not logic.

As a demonstration:

local a = "a"
local b = not not a --> b = true
local c = not not d --> c = false

IterationEdit

Iteration refers to loops. Loops use test values to decide whether to execute block of code, then re-runs the test to decide whether to execute it again. The test usually uses a variable that can change during the course of the block of code, or that the structure itself manages. If this did not occur and the test was not nil or false, then the block would loop indefinitely, unless there were a break or return inside the structure.

break exits out of the immediate loop (the innermost loop, but it will not exit out of a loop the innermost loop is nested in).

The return statement also exits out of loops, but it also exits out of the entire function. See Functions for details.

So a basic loop:

i = 0
while true do
  if i == 5 then break end
  i = i + 1
  print(i)
end

The above loop has an always true condition, so it will loop forever unless the content decides otherwise. The first statement inside the DO block tests if i is equal to 5. At this point it is 0, so it will continue. Then it adds 1 to the value of i and prints the value, 1. It then returns to the loop's condition, true, so continues from the start. The loop will print "1", "2", "3", "4", and "5", then on the next loop i==5 will be true and break will be reached, exiting the loop and continuing the code.

Other languages have a continue statement, Lua does not.

WHILEEdit

A WHILE loop continues to loop while a condition is true. The syntax is while followed by the value, do followed by the code, followed by end.

while
value
 do
code
end

Lua's FOR loop does work in the typical fashion, so one application may be to test if a value, incremented in the code, is less than a value.

local object = { "A", "B", true, "C", "D" }
local i = 1
while i <= #object do
  if object[i] == true then i = i + 1 else print(object[i]) end
  i = i + 1
end

The above will print "A", "B", and "D". The third iteration will detect true which increments i by 1 (on top of the standard increment), so "C" is skipped over.

REPEAT UNTILEdit

The REPEAT UNTIL loop has two differences to the WHILE loop. The first is that the loop repeats until the condition is true (so while the condition is false), rather than while the condition is true. The other different is that it is a post-check loop. What this means is the condition is tested only after the block of code has been executed once.

repeat
code
until
value

To show how this works:

i = 5
while i < 5 do
  print(i)
end
--nothing printed
repeat
  print(i)
until not(i < 5)
--prints 5 once because the condition is only tested at the end
incremental FOREdit

The incremental FOR creates a variable specifically for the loop (which is inaccessible outside of it) and increases it by an amount until it is greater than or equal to another specified value. The increment does not have to be specified and will otherwise be 1. The values are separated by commas, and looks like this:

With increment automatically defined as 1:

for
variable
 =
value
,
until
 do
code
end

With increment specified:

for
variable
 =
value
,
until
,
increment
 do
code
end

The maximum and increment values remain the same throughout. So if using a variable for conditions, these values are only evaluated at the start. Furthermore, while the variable created at the start can be modified in the loop, when it gets back to the top it will be the value it was at the beginning of the iteration plus the increment defined at the start.

A typical use for an incremental FOR loop would be this:

local object = { "A", "B", "C", "D" }
for i = 1, #object do
  print(object[i])
end

This would print "A", "B", "C", and "D". A benefit of using incremental FOR over WHILE is that the variable is automatically disposed of when the loop finishes, while a benefit of WHILE is more control over the incrementing variable. A key difference between them is how variables and functions may be used in the conditions of a WHILE since they are evaluated on each loop, while functions and variables used in an incremental FOR are evaluated once.

FOR IN can iterative over ipairs which works in a similar way when iterating over tables, but incremental FOR offers more control over increment amount and starting value. Incremental FOR is faster. One may opt for ipairs when modifying a table at the same time however. FOR IN with ipairs also breaks the loop when a nil value is found, which is not the case for incremental FOR.

FOR INEdit

A FOR IN loop loops through a set of items. The most common way to use it is to use pairs or ipairs whose value would be a table. The loop then iterates over the table's members (only auto-indexed ones until nil in the latter) and each iteration has a given block run on it. Two variables can be set, one that stores the current key name (or property name), and one that store's the current value.

Syntax with pairs:

for
keyvariable
,
valuevariable
 in pairs(
table
) do
code
end

The value variable (and its preceding comma) are not needed if the value's do not need to be used.

Examples:

local object = { "A", "B", "C", "D", n = 4 }
for k, v in pairs(object) do
  print(k .. ": " .. v)
end

The printed output would be:

1: A
2: B
3: C
4: D
n: 4
local object = { "A", "B", "C", "D", n = 4 }
for k, v in ipairs(object) do
  print(k .. ": " .. v)
end

The printed output would be:

1: A
2: B
3: C
4: D

FunctionsEdit

Functions are samples of code but they are not used where they are written (most of the time). Instead they are called from one or more other points in the code (most of the time). Functions take parameters, which are values passed to the function when calling it.

Functions can modify accessible variables and modify passed tables, though their most common use is with returning values. The return keyword can be used in a function's code and it will terminate processing of the function and return the following value to where the function was called from. return does not have to be followed by a value, and if it does not nil will be returned. Multiple values can be returned, and to make use of them two variables can be set to assign the function value.

function twoplustwo()
  return 2+2
end
print(twoplustwo()) --> 4

A function's parameters are listed linearly in brackets following the function name. When defining the function parameter names can be written comma-separated. The names of these parameters can be used in the function's body, and the values passed to the function when called use these names. The order they are entered into the function is the same as the order the parameters on the function. A special parameter name, ..., can be used as the last parameter of the function. What this means for the function is an infinite number of arguments. In the version of Lua the wiki uses, ... (three dots) can be used as an auto-indexed table of values, so looping through them and specifying specific values by following it with square brackets works.

When calling a function and only a single string value is passed, brackets do not need to be used and instead the value placed after it will be seen as its single parameter. This is not true for any other circumstance. Due to the fact that brackets are usually needed, and required in other languages, including brackets is general practice. The single exception to this rule is when using require, where typically brackets are foregone.

Not all parameters need to have a value passed to them, a value of nil will be assigned to those that are not used in a call. If parameters are optional the function will usually contain code that assigns a default value or switches logic.

function plus(numA, numB)
  return numA + numB
end
print(plus(2, 4)) --> 6

Functions are usually named and use the following syntax:

function functionname(comma, separated, parameters)
  code
end
functionname("parameters", "a")

Functions can be used anonymously though, which means they can be passed as a type of data or executed immediately. An example of a where an anonymous function is useful is the Module:Array library's foreach function, where a function is run on each auto-indexed member of a table. An anonymous function uses the same syntax but a function name is not specified.

An anonymous function can be executed without assigning it to a variable by wrapping it in brackets, then following it with brackets and the input parameters.

An anonymous function would look like this:

(function(a) return 2+a end)(3) --> 5

One of the reasons one may do this is to create a deeper scope, though in Lua this can be done using the DO structure. However one of the more logical reasons is that it allows a block of code to be written and whatever is returned assigned to a variable. The difference is like with Ternary IF, the structure returns a value and does not need to do the assigning itself.

--with anonymous function
local d = (function()
  if 1 == 2 then
    return 5
  end
  return 3
end)()
 
--with REPEAT (for break, repeat's post-check and "until true" guarantees one iteration)
local d
repeat
  if 1 == 2 then
    d = 5
    break
  end
  d = 3
until true
 
--standard
local d
if 1 == 2 then
  d = 5
else
  d = 3
end

MethodsEdit

Methods are functions, though they are functions executed in a certain way. Functions can be a property of a table, or they can be assigned via metatables (see Classes for additional information about that), and if they are either of these things then they can be executed like a method.

A method execution is like a function execution, but instead of a dot, a colon is used. So for example:

a.()--standard function execution
a:()--method execution

The thing that separates them though is that in a method execution the first parameter is always the calling variable itself. This is the only reason the execution of a function from an instance is needed, rather than executing the function from a library. Below are three calls doing identical things:

local a = "ABC"
string.lower(a) --function execution from library
a.lower(a) --function execution from instance
a:lower() --method execution from instance
--All of the above return "abc"

From above you can see how the middle function is worthless as it is a shorter version of the function execution from library, and the initial specification of a is meaningless. It is ultimately just confusing and should be avoided. The method execution does the same thing, and in a clear and more logical way.

If you are carrying what you know of methods over from other languages, it is not possible to run executions on literal values. The value must can be stored in a variable or property, but you can also still run the methods by wrapping the string in brackets.

As an example of setting up a single-use method:

local tbl = { "a", "b", "c", initfunc = function(self) return self[1] end}
function tbl.postfunc(self)
  return self[1]
end
function tbl:postmeth()
  return tbl[3]
end
--the table is called "tbl"
--tbl[1] is "a"
--tbl[2] is "b"
--tbl[3] is "c"
--tbl.initfunc is a function that returns the first parameter of a submitted table
--tbl.postfunc is a function that returns the second parameter of a submitted table
--tbl:postmeth is a function that returns the third parameter of a submitted table
 
print(tbl:initfunc())--prints "a"
print(tbl:postfunc())--prints "b"
print(tbl:postmeth())--prints "c"

The above shows a method being declared, function tbl:postmeth(): there is no reason to do this. The first parameter does not get declared so there is no way to reference it so in the end it gets no benefit of being a method. Defining a function as a method still allows it to function as a regular function. In the example print(tbl.postmeth()) also prints "c".

MetatablesEdit

A table becomes a metatable when it is assigned as one to another table. Metatables can contain a number of specific parameters such as __index which contain functions that get executed when certain events take place. These are referred to as metamethods.

One of the most common uses for metatables is to use default parameters, so this will be explained first. Although it was said that functions are assigned to the parameters, __index is one of a few exception as it also allows for a table to be assigned. Properties where values are assigned rather than an executing function are called metaproperties. Assigning a table to __index makes the assigned table's properties available to tables using the metatable as their metatable.

The main function here is setmetatable.

local mt = {} --create metatable
mt.__index = { a = "A", b = "B", sequel = function(self, prop) return self[prop] .. " II" end } --set properties to inherit
local newtable = { b = "1" } --the table we want to assign the metatable to
 
setmetatable(newtable, mt)
 
print(newtable.a) --prints "A" from metatable
print(newtable.b) --prints "1" from self
print(newtable:sequel("a")) --prints "A II" from metatable func, A from metatable
print(newtable:sequel("b")) --prints "1 II" from metatable func, B from self

So in the above, a metatable is created, and that metatable has indexes in its __index property. The metatable is assigned to a new table, and therefore when the program looks for properties in the table that do not exist, they defer to the metatable's __index.

That is the basic and standard use for metatables, but they get more advanced than that. Functions are typically set to the properties that run when on certain conditions. When __index has a function it is run the script whenever an index is searched for but not found.

So this below example uses it to throw errors rather than nil, which could be totally annoying in many circumstances when you just rather just have nil returned.

local mt = {}
mt.__index = function(t, k)
  if type(k) == "number" then
    if k == 0 then error("Indexes start at 1 in Lua dood.")
    elseif k < 0 then error("A negative number? Are you sure that's what you're looking for? Nothing here.")
    else error((k-#t) .. " out of range. The last index is at " .. #t .. ".")
    end
  else error("No value at this property.")
  end
end
 
local array = {"A"}
 
setmetatable(array, mt)

The above is fairly self-explanatory. The parameter order is the table being used, the key being looked for. So if array[42] was looked for, the error would be "41 out of range. The last index is at 1.". array[1] would return "A" because the script isn't run if the searched field exists.

A more standard example may be what array from Module:Array uses. When array.new is used, a metatable is assigned to a table that allows array methods to be used more easily. It uses this code:

array.__index = function(t, k) if k=="new" or k=="isarray" then return nil end return array[k] end

What this does is fairly easy to explain, if ":new" and ":isarray" were tried to be used then nil would be returned, in all other circumstances it will look look for the index in the array table.

One thing to note is that __index is ignored when setting a metatable. Ergo, though with the current example every object using the array metatable will have it returned in their .__index property, setting the case of an array as a metatable will not work. The property has to specifically belong to the object.

Copying the metatable from another element is possible though, the getmetatable function returns the given metatable of the given object.

Below is a table of the usable events. Do note, the parameter names can be named anything and it is only the order that matters. In uses parameter names are often shortened to a single letter for convenience.

MetapropertiesEdit

Property Description
__index Table of properties used when not found in table. Can also contain a function and be used as a metamethod.
__metatable Value returned when getmetatable is called on table.
__type Value returned when ffwiki.type is called on table. Can also contain a function and be used as a metamethod.


MetamethodsEdit

Called so because the functions automatically pass themselves. Values are always functions.

Property Parameters Description
__index table
key
Called when an index not in the table is requested. Returns function return as value. rawget runs get ignoring __index.
__newindex table
key
value
Called when a previously undefined value is assigned. Not called for table.insert. Assignment does not take place. To otherwise set a previously undefined value, rawset must be used.
__call table
args[]
Function that runs when the table is used as a function.
__tostring table Returns function value when tostring is used on table.
__len table Returns function value when the # (hash) operator is used on table. Will not work in most cases in 5.1
__type table Returns function value when ffwiki.type is used on table.
__unm table Returns function value when attempting to use table as a negative (e.g. -table).
__add a - First value
b - Second value
Runs when table is being added to another value and returns function return value. If both tables have metatables with __add metamethod, then leftmost table's is used.
__sub a - Subtracted from
b - Subtraction value
Runs when table is being subtracted from another value, or when value is being subtracted from table, and returns function return value. If both tables have metatables with __sub metamethod, then subtracted from's table is used.
__mul a - First value
b - Second value
Runs when table is being multiplied with another value and returns function return value. If both tables have metatables with __mul metamethod, then leftmost table's is used.
__div a - Divided value
b - Divided into
Runs when table is being divided into another value, or value is being divided into table, and returns function return value. If both tables have metatables with __div metamethod, then divided value's is used.
__mod a - Divided value
b - Divided into
Runs when table is being modulusified with another value. If both tables have metatables with __mod metamethod, then divided value's is used.
__pow a - Multiplied value
b - Power value
Runs when table is being raised to power of another value, or value is being raised to power of the table, and returns function return value. If both tables have metatables with __pow metamethod, then multiplied value's is used.
__concat a - First value
b - Second value
Runs when table is being concatenated with to another value and returns function return value. If both tables have metatables with __add metamethod, then leftmost table's is used.
__add a - First value
b - Second value
Runs when table is being added to another value and returns function return value. If both tables have metatables with __add metamethod, then leftmost table's is used.
__eq a - First table
b - Second table
Runs when tables are being evaluated for equality (==), are not the same table, and share the same metamethod. If these conditions are met then the function return value is used as the logic value. Also run with same conditions with ~=, and opposite value returned instead.
__lt a - First table
b - Second table
Runs when tables are being evaluated with less-than operator <. The function return value is used as the logic value. If both tables have metatables with __lt metamethod, then leftmost table's is used. Also run with same conditions with greater-than operator (>), with parameters reversed.
__le a - First table
b - Second table
Runs when tables are being evaluated with less-than-or-equal-to operator <=. The function return value is used as the logic value. If both tables have metatables with __le metamethod, then leftmost table's is used. Also run with same conditions with greater-than-or-equal-to operator (>=), with parameters reversed.

Importing modulesEdit

Modules, or libraries, can be imported using the global require function. The parameter contains a string of the name of the module (always in the Module namespace) including the namespace. Modules define an object at the start, append properties (typically functions) and then return them at the end. The imported module is then returned to a variable.

local modulename = require "Module:ModuleName" --format
local ffwiki = require "Module:FFWiki" --example

Importing of the more general libraries such as Module:FFWiki is typically done at the top of a module. Modules may also sometimes be defined in functions so the library is not always imported when the module may not even make reference to it.

Some modules are designed to override existing ones with further functionality. This is true for Module:String and Table. In these instances defining variables of the name locally is not needed.

Modules imported through require operate differently to modules that are invoked from wikitext in the way they interact with the Lua environment. Required modules edits to the environment remain intact, while invoked modules do not. It is this that founds the basis for Template:Var and other modules that use a "/global" suffix (e.g. Module:Variable/global).

Data modulesEdit

Data modules are modules that are imported using mw.loadData. The difference with mw.loadData is that a module only gets loaded once per page load, and if that same module tries to get loaded again it will just find the data that was previously loaded.

Data modules can only contain tables, strings, and numbers. The module itself can run functions however the functions themselves can't be attached to a returned object.

Data modules belonging to a specific module usually have the "/data" suffix (e.g. Module:Codename/data), while projects designed around storing and displaying data usually include "Data" in the title and have multiple data subpages based on the type of data contained (e.g. Module:FFXIV Data, Module:FFXIV Data/Accessories).

Writing #invoke functionsEdit

The {{#invoke}} function takes two parameters, followed by an optional amount of other parameters, which can be named or otherwise. The first parameter matches the name of a module page, and the second matches the name of a function in that module page. The remaining parameters are packed into a Lua readonly table and submitted to the function. The function's returned value is printed to the page where it was found.

Functions using invoke must have its first (and usually only unless it is designed to be called in other ways aside from {{#invoke}}) parameter titled frame. This parameter is a type, and the most important thing about it is it has a property called args, and this property will contain the aforementioned readonly table of parameters.

Therefore to use a parameter, one can type frame.args[parameter name] to get the value that was passed. The parameter names match those used in {{#invoke}}, and unnamed parameters will be in sequence starting from 1 onwards. This functions identically to tables, where the value before the equals is the parameter name, and the contents after is the variable. All values passed as parameters are viewed as strings.

The readonly state of the table means two things, the first is that none of the values can be edited. Therefore if the programmer simply wants to use the input arguments to be put directly to use and have defaults then a new table will have to be created. The second is that the length of the table cannot be gathered. So a FOR IN table cannot iterate over it unless one were to find out the value in another way. To fix this the reargs function on the Module:FFWiki library clones the readonly table into a normal table so arguments are reusable.

In templates blank values are often equivalent to undefined values. Wikitext does not have data types in the normal sense, so it is the closest to a nil type available. An unspecified variable, one the {{#invoke}} never references, does count as nil though. Therefore to test whether parameters exist most of the time the value will have to be checked for not being nil or a blank string. Rather than doing this each time, the ifnotblank function in the Module:FFWiki library exists to check these two things and return true if the value is neither of the aforementioned values, or false if it is. If empty strings should be valid for the parameters, then a technique may be to make the blank value "@nil" instead, and have Lua convert that input to nil. Its status as a string that would unlikely be intended to be an actual input makes this simple.

Rather than using the ifnotblank function each time a parameter is used works, though rather than doing this for all parameters it may be easier to just convert all of the table's empty strings to nil. Of course, this cannot be done with the initial readonly arguments table, however the emptystring function in the Module:FFWiki library does the same thing as reargs but removes all parameters with empty strings from the table. This includes auto-numbered parameters, causing gaps in the numbers.

Though all parameter inputs are viewed as string by Lua, the luaparam function in the Module:FFWiki library evaluates a table containing string values into the different data types. This means a parameter surrounded by quotation marks will be seen as a string, while "true", "false", and "nil" will be seen as those respective values, values inside of curly braces as tables, values surrounded by quotation marks as strings, or calculations as numeric. Functions are detected but they cannot be passed. Concatenation of strings work but is ultimately pointless. Reference to variables or functions also does not work. The detection of a table works by viewing if table syntax appears in the field (outside of a string). This is needed as when tables are used as the last parameter the end invoke syntax will confuse itself with it. Any characters placed before or after the table syntax are entirely ignored, so simply adding whitespace after the table syntax will resolve the issue.

The Frame object has a method called getParent. This method will call a new frame object, this frame object containing the parameters of the page that called the page containing the current frame. In simple, terms, if the page with the {{#invoke}} is transcluded, then the parameters submitted to the page with the {{#tl|invoke}} will be stored in the parent frame. This means that creating a template containing nothing but an {{#invoke}}, the name of a module, and the name of the function could be used identically to using an {{#invoke}}, sans the need of stating the module and function name, so long as the script gets is args from frame:getParent().args. An easy way to use parameters from a template if used, but the {{#invoke}} otherwise, is to use a statement that checks for parameters in the template. Like so:

local f = frame:getParent().args[1] and frame:getParent() or frame

The reason storing the frame is suggested here is because it has other uses, though if one intends only to use the args parameter then that could be stored in the variable to make things simpler. The 1 for the parameter value can be changed to a mandatory named parameter if no non-named parameters are used.

Wikitext used as a parameter in an {{#invoke}} is processed before it gets to the function. This means that parameters with defaults will always pass their defaults to the function and the parameter will be lost. Furthermore, parameters, templates, and MediaWiki tags will not be processed if returned from a Lua function. For templates the expandTemplate of a Frame object can be used. The function contains a table whose title parameter is the name of a template, and whose args parameter is a Lua table with the names of the arguments. For parameters, MediaWiki tags, and templates written in wikitext, the preprocess function of the Frame object can be used to process it. In this process, wikitext parameters are replaced with values from the Frame object's args property.

Though as stated, parameters with defaults will only have the defaults reach the Lua function. To avoid this the unescapewikitext function in the Module:FFWiki library can be used. Escaped syntax passed to the function can be passed to the script fine, then the script can convert it to the valid wikitext and have it go through the Frame object's preprocess method to do the conversion as desired. The escape strings replace existing ones, for example a backslash (\) instead of a pipe (|). If an escape string will conflict with other code then they can be re-specified through the function's parameters.

A lot of wiki functions will revolve around returning wikitext to the form, and most structures will be written using HTML tags. Therefore the mw.html library's Html object will need to be used. HTML building is explained in its own section.

HTML BuildingEdit

Wikitext-valid HTML can be written and returned to the form just fine, however HTML can be better written programmatically. The Html class has a number of functions that modify parts of a HTML element separately, and can then return the HTML when the text is needed. Components of the element are stored in a table and is therefore much easier to manage than cutting and editing a string, or creating numerous temporary variables to help manage it.

A new Html object is created through the mw.html.create function. This has two parameters, the first is the string tag name, e.g. "div", and the second is an optional parameter boolean that can make the tag self-closing (if it isn't on the list of ones to do that automatically, like <br/> and <hr/>)).

The new object can now have methods added. It is likely that the object will want to be stored in a variable, although on smaller projects this might not be needed. The methods can be added in the same statement as the object is created, or in a new statement from the variable, either is fine. So to demonstrate:

local el = mw.html.create("div"):method() --method on creation
el:method() --method post-creation

To add or edit an attribute the attr method can be used. Supplying the name and value in the first and second parameter works, or multiple attributes can be defined at the same time by inputting a table where the attribute names are the property names and the values are the table values. Not all attributes should be added in this way, class and style are exceptions since they do not contain a single value, however since classes and styles cannot be removed they can be reset through attr by specifying the attribute and inputting a blank string.

To add a class the addClass method can be used. The single parameter is a string, and multiple classes can be added by space-separating them in the string.

To add CSS to the style parameter two methods can be used. When adding new CSS specified in Lua the preferred method is to use the css method. The method works like attr in that one can be added by specifying name and value as parameters, or multiple can be added with a table.

The other method of adding CSS is the cssText method. This allows styles to be written out in plaintext, e.g. color:red;font-weight:bold. The reason why this is not preferred when specifying in Lua is that the property names are not checked to see if they already exist in the element. However, this method would need to be used if the CSS styles are specified in the parameters passed to the script.

Content inside of the tags can be added through a number of methods, and the order they are added in. For plain HTML text the wikitext method is used. The input is literally just standard wikitext, although \n counts as a new line character. The newline method is another way to add new lines and takes no parameters.

The node method adds a created HTML element inside the one being operated on. This could be one stored in a variable, or it could be created on the spot inside the method's brackets. The benefits of using a variable is that the element can still be modified after it is added by referencing the variable name. Sorting out the structure of the elements before handling their attributes is an acceptable way to manage things.

Alternatively to using mw.html.create inside of the node method, the tag method can be used. Neither way is right or wrong although it offers a new option. The tag method takes he same properties as the mw.html.create method. The difference between tag and node is that the node method returns the object being operated on, while the tag method returns the newly created object. This means that following methods will apply to the newly created tag. Therefore when done editing the newly created tag, the done method can be used to return power to the element that created the tag. This method could be used a number of times to nest more and more tags, and therefore to return control to the originally created element, the allDone property can be used.

If assigning a value to a variable in the same string of methods as new tags are being used, returning control to the original element needs to be done at the end to store the outermost element. Intending to use an element as a string after creating a tag but not returning control will also not be targeting printing the outermost element.

An element can be recorded in the console with print or mw.log, and can be returned to a page by putting it as a return. If one were to want to use the tags as strings directly, such as with concatenation, then the element must be placed inside the global tostring function.

So here is an example. The Lua:

local el = mw.html.create("div"):addClass("contentbox"):attr("id", "htmlbuildexample")
local header = mw.html.create("div"):addClass("header"):wikitext("Header")
el:node(header)
local content = "This is content"
el:wikitext(content):tag("div"):wikitext("[[File:Core-ffix.png|75px]]"):css("float", "right"):done():tag("div"):css({clear = "both", ["border-bottom"] = "1px solid black"}):allDone()

The wikitext:

<div class="contentbox" id="htmlbuildexample"><div class="header">Header</div>This is content<div style="float:right;">[[File:Core-ffix.png|75px]]</div><div style="clear:both;border-bottom:1px solid black;"></div></div>

The display:

Header
This is content
Core-ffix

ClassesEdit

An object-orientated programming concept is classes. Classes are definitions for objects. Instances of the class inherit properties and methods from the class itself. Lua does not have classes, however using metatables we can utilize a form of inheritance.

A class defines a type of object, so an example of a class might be "Account" for a bank account. The "Account" class may have properties like "balance" and methods like "withdraw". An instance of the "Account" class would be a single account.

While I state that classes may have properties, this is not technically true. Properties can be added though they would have to be the same for all of the objects. Adding variable properties is not possible in this way, the properties would have to be added in the initializer.

A benefit of using classes is the methods are not attached to objects, they only hold a reference to their class which stores the methods. This means additional functions are not added to the table.

Technically speaking properties cannot be set into the class. The property and the value belong to the class object, so trying to modify that property will just be adding the property to the current object and make the class's property inaccessible. There are multiple ways that properties could be handled. The class could contain a table of all the available properties. This could be cycled through in the constructor, and have the values added at that point. The table in the constructor could be made useful and contain default values for when nil values are presented, but if a default value were to be nil then it just would not appear in the table. In the end it may just be simpler to define the properties in the constructor.

So here's how one might do it:

-----------
-- class --
-----------
Account = {
  withdraw = function(self, value) self.balance = self.balance - value return self.balance end,
  deposit = function(self, value) self.balance = self.balance + value return self.balance end
}
 
--------------------------------------------------------
-- set Account's methods to be looked up if not found --
--------------------------------------------------------
Account.__index = Account
 
-----------------
-- constructor --
-----------------
function Account.new(balance)
  --set up new object
  obj = {}
  --inherit class methods
  setmetatable(obj, Account)
  --set new property
  obj.balance = balance or 0
  --return new object
  return obj
end
 
---------------------------------
-- creating object from class  --
---------------------------------
local a = Account.new(6)

The object a above contains the property balance which holds a value of 6 and that is all. However the link set up with the Account class allows it to use the methods found on the Account object. If one were to try to use methods on it:

  • a.balance
    -> 6
  • a:deposit(1)
    -> 7
  • a.balance
    -> 7
  • a:withdraw(3)
    -> 4

The first sample shows the input balance registered, the second shows :deposit operating on the number depositing 1 currency (adding 1 to existing), and the third one shows the balance updated. The fourth sample shows that :withdraw works too.

ConsoleEdit

When editing a page in the Module namespace a console will appear below the editform. Running the console executes the contents of the editform (only the first time) followed by the contents of the console. If a submission is valid, modifications made to the environment including the addition of variable (be them local or global), or alterations made to existing elements are retained. Line numbers in the console start from line 5, and every valid line submitted increments the line number. In other words, submit a valid statement in the console and that will be line 5. Submit the same statement again and that will be line 6.

When the console is cleared or the editform's contents are changed, the next time the console is submitted the environment is reset and the editform is re-submitted.

Instances of mw.log() in the editform will print their values to the console output. Instances of mw.log() and print() in the console will print their values to the console output. print() in the editform will cause an error to be thrown. If an error is thrown then no values will be printed to the editform even if the error occurs after them, which means that detecting the point of error can be difficult.

Any global variables set in the editform cannot be reached by the console. This includes values imported from other modules. To make use of these in the console they can be imported in the console submission. However, modules that return an object can still have their methods and properties used in the console and are stored in the p object. For example, if the Module contains the text: ModName = {} ModName.v = 5 return ModName, then submitting the console containing print(p.v) will print 5 in the console output.

If functions are designed to be called with {{#invoke}} then they will use the frame argument. Therefore to be able to debug the function within the console one would have to do do something like
frame = {} frame.args = { "File:ElfToad-ffv-ios.png", "Elf Toad" } print(p.generate(frame))
, where the contents of
frame.args
are the inputs split into array members where pipes would be used on the page, and the method name after p would be the name of the function being tested. It should be noted that there is a slight difference in doing this because
frame.args
when discovered through {{#invoke}} is a readonly table, this means that ascertaining its length and changing its values is impossible, the same is not true for a standard table. Methods belonging to the frame object will also not carry over.

Furthermore, the value printed in the console will be plain wikitext. To see the output value one would have to copy it into a normal page's editform and preview. This is not exactly the same because wikitext syntax for templates does not evaluate when returned from Lua, but would when text is copied from an edit form. If the value returned from the console goes off screen, placing the cursor left of the text and clicking down and dragging down a bit should highlight the entire line without highlighting anything else.

If there is text in the console then pressing the Enter key will run the contents of the console. Holding shift when pressing the Enter key will create a new line. Pressing down on the lowermost line will make the console's contents blank, while pressing up on the top line will show the previously submitted console code (or the code typed before pressing Down if returning from blanking by that method). Ctrl+Z and Ctrl+Y allows undoing and redoing to go back to the last or following minor change.

LibrariesEdit

globalEdit

Globally stored functions and variables are stored in _G, though they can be used without needing a prefix. However, if one were to call a global function or variable by a string, then they will need to use _G to reference it. For example, _G["print"]().

Function Parameters Example Description
ipairs table for k, v in ipairs({"A", B= "C"}) do print(k .. v) end -> 0A Assigns key and value pairs to variables and iterates over auto-indexed of tables when used in a for loop.
pairs table for k, v in pairs({"A", B= "C"}) do print(k .. v) end -> 0A, BC Assigns key and value pairs to variables and iterates over all members of table when used in a for loop.
print value - Prints value to console. Causes script errors when used in modules, mw.log should be used instead.
require module require "Module:FFWiki" Executes a module without the module being able to modify the environment, such as globals.
tonumber object tonumber("4") -> 4 Returns number of converted value, otherwise nil if it fails to convert.
tostring object tostring(4) -> "4"
tostring(true) -> "true"
Returns string of converted value. Most objects are converted to string automatically when concatenated or printed.
type object type(5) -> number
type("5") -> string
type(true) -> boolean
type({}) -> table
type(function() end) -> function
type(nil) -> nil
type(2, "3") -> number
Returns string name of type of object.
error string - Throws an error with reason specified.
pcall function pcall(function() end) -> true
pcall(function() a = "a" + "a" end) -> false, Lua error at line 1: attempt to perform arithmetic on a string value
Runs function and returns Boolean for whether it was valid (false if causes error). Found errors do not terminate script, though are returned as second output.
setmetatable table - Assigned to.
metatable
- Assigns metatable to given table. Returns table.
getmetatable table - Returns table metatable of given table. If metatable has .__metatable property then that is returned, or if __metatable is a function then the function is run as method and value is returned.
rawset table
index
value
a = {} _G.rawset(a, "b", "c") -> (table: { b = "c" }) Assigns value to index of table. Avoids __newindex metamethod. Returns table.
rawget table
index
a = {b = "c"} _G.rawget(a, "b") -> c Returns index of table. Avoids deferring to __index or running the metamethod of __index.

stringEdit

A number of string functions return multiple parameters. Because print can take infinite parameters, when a string function is returned and printed multiple values are printed. Though if one were to use the return as a value then only the first returned value would be used.

So for example, print(string.byte("ABC", 1, 3)) prints "65 66 67", while print(string.byte("ABC", 1, 3) .. "") prints "65".

Strings must be stored in variables or properties to use the methods.

Module:String can be imported over this module to add additional functions.

Function Parameters Example Description
.byte
:byte
string
start - Index of first character (default: 1)
end - Index of last character (default: start)
string.byte("ABC") → 65
string.byte("ABC", 2) → 66
string.byte("ABC", 2, 3) → 66, 67
string.byte("©", 2) → 169
Returns byte indices of character between start and end as multiple values.
.char args[] - Byte value of characters string.char(65, 66, 67) → ABC
string.char(194, 169) → ©
Returns bytes encoded as UTF-8 string.
.find
:find
string
search - Substring to find within stringoffset - Index to start searching from, negative values count back from end (default: 1).
plain - Boolean for plaintext searching, (default: false).
string.find("bac", "ac") → 2, 3
string.find("cac", "c", 2) → 3, 3
string.find("cac", "c", -1) → 3, 3
string.find("cac", "b") → nil
Returns first and last index substring found within string after offset index as multiple values. Uses Lua Patterns unless plain is true.
.format
:format
string
args[]
string.format("%o", 8) → 10
string.format("%x", 15) → f
string.format("%X", 63) → 3F
string.format("%02x%02x%02x", 10, 50, 60) → 0a323c
string.format("%s is awesome", "Lua") → Lua is awesome
String takes arguments and inputs are formatted certain way. Arguments are representing in the string with format specifiers. %d takes a number and outputs a signed decimal integer string, %f takes a number and outputs a signed floating number. %s takes a string and outputs exactly, %o takes a number and outputs it in octal, %x takes a number and outputs as a lowercase hexadecimal string, %X takes a number and outputs as an uppercase hexadecimal string.

A format specifier of %0NF where "N" is a number and "F" is the format (e.g. x for lowercase hexdec), pads 0 left to the specified length. For floating points a specifier of %.NF where "N" is a number and "F" is the format, formats the point to the specified number of decimal places.
.gsub
:gsub
string
search - string being replaced.
replace - string replacing.
replacements - Number of replacements (optional).
string.gsub("hahaha", "a", "e") → hehehe, 3
string.gsub("hahaha", "a", "e", 2) → heheha, 2
Returns string with instances of search substring replaced by replace substring and replacements made as multiple values. If replacements is used, makes specified replacements from start of string. Uses Lua Patterns.
.len
:len
string string.len("ABC") → 3
string.len("AB©") → 4
Returns number of bytes in string. #[string] works in the same way.
.lower
:lower
string string.lower("AbC") → abc Returns string in lowercase.
.rep
:rep
string
times - Number of times to repeat.
string.rep("ha", 3) → hahaha Returns string repeated specified times.
.reverse
:reverse
string string.reverse("nametag") → gateman
string.reverse("A©E") → E��A
Returns string with byte order reversed. Characters taking up more than one byte will cause problems.
.sub
:sub
string
start - First index
end - Last index (default: #string)
string.sub("heathen", 4) → then
string.sub("heathen", -3) → hen
string.sub("heathen", 2, 4) → eat
string.sub("heathen", 4, -2) → the
string.sub("©", 1, 1) →
Returns string reading from byte at start index to end byte. If values are negative, counts back from end of string. Note: Characters that take up more than one byte take up more than one index. Use
.upper
:upper
<code>string string.upper("aBc") → ABC Returns string in uppercase.

tableEdit

Past versions of Lua had the getN function which returned the greatest numeric index of a table, or in an auto-indexed table, the length. This can be done using #[table].

None of these are methods.

Function Parameters Example Description
.insert (table, value or (table, index, value)
table
index - Index to insert at (default: #table)
value - Value to insert
table.insert({"A", "B"}, "C") → (table: {"A", "B", "C"})
table.insert({"A", "B"}, 2, "C") → (table: {"A", "C", "B"})
Inserts value at given index in table. index must be a number, but can be any number. Moves existing and following indexes up. No return, so input table should be pre-stored.
.remove table
index - Index to remove at (default: #table)
table.remove({"A", "B", "C"}) → C (table: {"A", "B"})
table.remove({"A", "B", "C"}, 2) → B (table: {"A", "C"})
Removes value at given index in table. index must be a number, but can be any number. Moves following indexes down. Returns removed value.
.concat table
delimiter (default: empty string)
start - From index (default: 1)
end - To index (default: #table)
table.concat({"A", "B", "C"}) → ABC
table.concat({"A", "B", "C"}, "@") → A@B@C
table.concat({"A", "B", "C"}, "", 2) → BC
table.concat({"A", "B", "C"}, "", 1, 2) → AB
Returns string of table member values from start index to end index separated by delimiter.
.sort table
function - Comparative function (default: function(i, j) if i < j then return true end end)
table.sort({"B", "A", "D", "C"}) → (table: {"A", "B", "C", "D"})
table.sort({"B", "A", "D", "C"}, function(i, j) if i > j then return true end end) → (table: {"D", "C", "B", "A"})
Reorders table elements using function. The function needs to take two parameters and return true. No return is equivalent to return false, or "do not switch". The default function orders smallest or alphabetically.

mathEdit

mod works but has been removed in 5.2. To use the function a % can be used in an equation, for example what was math.mod(5, 2) can be expressed as 5%2. The fmod function works similarly, however it rounds towards 0 so negative numbers are treated like inverse positive numbers (e.g. -5%4 is 3 and math.fmod(-5, 4) is -1, and 5%-4 is -3 and math.fmod(5, -4) is 1).

The property huge contains the value inf.

The property pi contains the value 3.1415926535898.

Function Parameters Example Description
.sqrt number math.sqrt(4) -> 2 Returns square root of number. Equivalent to number^1/2
.pow number
power
math.pow(5, 2) -> 25 Returns square root of number. Equivalent to number^power.
.fmod number
mod
math.fmod(5, 4) -> 1
math.fmod(-5, -4) -> -1
math.fmod(-5, 4) -> -1
math.fmod(5, -4) -> 1
Returns number modulo mod rounded towards 0.
.min number[] math.min(1, -1) -> -1
math.min(9, 8, 2, 5.5) -> 2
Returns the smallest number of given values.
.max number[] math.max(1, -1) -> 1
math.max(9, 8, 2, 5.5) -> 9
Returns the greatest number of given values.
.floor number math.floor(5.5) -> 5
math.floor(-5.5) -> -6
Returns number rounded down to an integer.
.ceil number math.ceil(5.5) -> 6
math.ceil(-5.5) -> -5
Returns number rounded up to an integer.
.modf number math.modf(5.5) -> 5, 0.5
math.modf(-5.5) -> -5, -0.5
Returns number without decimal places, returns decimal places alone. The first returned value is equivalent to JavaScript's trunc.
.abs number math.abs(5.5) -> 5.5
math.abs(-5.5) -> 5.5
Returns positive form of number.
.random ((max) or (min, max)
min
max
math.random() -> 0.00047147460303804
math.random(3) -> 3
math.random(4, 5) -> 5
When used without parameters, returns random number between 0 and 1. When used with first parameter, returns random integer between 1 and max<code>. When used with two parameters, returns random integer between <code>min and max.
.exp number math.exp(1) -> 2.718281828459 Returns the exponential function ex (inverse of the natural logarithm).
.log number math.log(math.exp(1)) -> 1 Returns the natural logarithm (inverse of the exponential function ex).
.deg number math.deg(math.pi / 2) -> 90 Converts a radian angle to degrees.
.rad number math.rad(90) -> 1.5707963267949 Converts a degree angle to radians.
.sin number math.sin(math.pi / 2) -> 1 Returns the sine of a radian angle.
.cos number math.cos(math.pi) -> -1 Returns the cosine of a radian angle.
.tan number math.tan(math.pi / 4) -> 1 Returns the tangent of a radian angle.
.asin number math.asin(0) -> 0 Returns the arcsine (inverse sine) of a ratio, as a radian angle.
.acos number math.acos(0) -> 1.5707963267949 Returns the arccosine (inverse cosine) of a ratio, as a radian angle.
.atan number math.atan(0) -> 0 Returns the arctangent (inverse tangent) of a ratio, as a radian angle. Ignores signs of angles.
.atan2 number1
number2
math.atan2(0,-1) -> 3.1415926535898 Returns the arctangent (inverse tangent) of two numbers in a ratio as a radian angle. Does not ignore signs.
.sinh number math.sinh(math.log(2)) -> 0.75 Returns the hyperbolic sine of a number.
.cosh number math.cosh(math.log(2)) -> 1.25 Returns the hyperbolic cosine of a number.
.tanh number math.tanh(math.log(2)) -> 0.6 Returns the hyperbolic tangent of a number.
.frexp number math.frexp(8) -> 0.5, 4 Normalizes a number, splitting it into the form base * 2 ^ exp. The base must fall into the interval [.5, 1].
.ldexp number[] math.ldexp(0.5, 4) -> 8 Denormalizes a 2-tuple, returning base * 2 ^ exp. Only works if base falls into interval [.5, 1].

mwEdit

Function Parameters Example Description
.log values[] - Prints values to console. Safer than print as it does not cause script errors when used in modules.
.clone value - Returns a copy of the input value. This means that tables are re-created so two identical tables exist rather than there being two places referencing a single table.
.getLanguage langcode - Language code, e.g. "en" - Returns Language object for specified language code. Most of the time en will be desired so more appropriate to use mw.message.getDefaultLanguage.
.getContentLanguage - - Returns Language object for wiki's default language (en).
.getCurrentFrame - - Returns Frame object for the {{#invoke}} call.
.loadData pagename - Name of Module page - Returns returned readonly functionless table from called Module page. Data stored after first call are not recalled.
.allToString values[] mw.allToString(true, false, 5, nil, 4, function() end) -> "true", "false", "5", "nil", "4", "function" Returns all arguments as string values.
.executeFunction function - Returns given function with frame arguments as its arguments and returns the values with multiple-return values concatenated to a single value.
.executeModule function - Safely executes a function without the function being able to modify the environment, such as globals.

mw.textEdit

Function Parameters Example Description
.trim string
char - String list of chars to trim (default: whitespace characters)
mw.text.trim(" aha ") -> "aha"
mw.text.trim("owcowcowo", "ow") -> "cowc"
Returns string with removed consecutive members of char from start and end.
.truncate string
length - Number of characters
ellipsis - String truncate symbol (default: ...)
adjustLength - Boolean for including ellipsis in length (default: false)
mw.text.truncate("cowowowow", 5) -> cowow...
mw.text.truncate("cowowowow", 6) -> cowowowow
mw.text.truncate("cowowowow", 5, "(...)") -> cowowowow
mw.text.truncate("cowowowow", 5, nil, true) -> co...
Returns string with characters longer than length removed.
.listToText table
separator (default: ", ")
conjunction - Last separator (default: " and ")
mw.text.listToText({"a", 5, "b"}) -> a, 5 and b
mw.text.listToText({"a", 5, "b"}, "; ", "; or ") -> a; 5; or b
Returns string of table member values separated by delimiter, and uses conjunction on rightmost join.
.split string
delimiter - Substring to split string at
code - Boolean for plaintext delimiter (default: true)
mw.text.split("a@b@c@", "@")) -> { "a", "b", "c", "" } Returns auto-indexed table of substrings split from string by delimiter. If plain is true then empty string values are not added. Uses Lua Patterns if plain is false.
.encode string
chars - String list of chars to encode (default: "<>&\"'  (non-break space)")
mw.text.encode("Final Fantasy Wiki's") -> Final Fantasy Wiki's
mw.text.encode("Final Fantasy Wiki's", "ia") -> Final Fantasy Wiki's
Returns string with members of char replaced by HTML entity references.
.decode string
namedrefs - Boolean for including named references (default: false)
left}}&quot;
mw.text.decode(&quot;"&#123;{-&#124;left}&#125;&quot;", true) -> "{{-|left}}"
Returns string with entity references (and optionally some named references) resolved as literal characters. Named references include &lt;, &gt;, &amp;, &quot;, and &nbsp;.
.nowiki string mw.text.nowiki("{{-|left}}") -> &#123;&#123;-&#124;left&#125;&#125; Returns HTML entity reference escaped string.
.tag tagname - String tag
attributes - Table named-index attributes and values (default: {})
content (optional)
mw.text.tag("p") -> <p>
mw.text.tag("p", {class = "para", style = "font-weight: bold"}, "lol") -> <p style="font-weight: bold" class="para">lol</p>
mw.text.tag("input", {type = "submit", value = "Save", id = "btnSave", disabled = true}, false) -> <input value="Save" type="submit" disabled id="btnSave" />
Returns string HTML tag of tagname with given attributes values and content. If content is nil then only opening tag returned. If content is false then a self-closed tag is returned. A key paired with a value of true in the attributes table has a valueless parameter added.

mw.uriEdit

Functions related to URLs and the URI object.

Function Parameters Example Description
.parseQueryString string - Query string mw.uri.parseQueryString("?action=edit&tester=true") -> { action = "edit", tester = "true" }
mw.uri.parseQueryString("css") -> { css = false }
Returns query string as table. Keys without values have their value set to false.
.buildQueryString table mw.uri.buildQueryString({action="edit", tester="true"}) -> action=edit&tester=true
mw.uri.buildQueryString({css=false}) -> css
Returns query string from table. Key set to false just returns key name.
.encode string
encmode string method of encoding of spaces (default: "QUERY")
mw.uri.encode("It's good") -> It%27s+good
mw.uri.encode("It's good", "path") -> It%27s%20good
mw.uri.encode("It's good", "WIKI") -> It%27s_good
Encodes string for URLs. encmode of "QUERY" is for referencing a page name in a query, "WIKI" is for referencing a wiki page name, and "PATH" is for a non-wiki path.
.decode string
encmode string method of decoding (default: "QUERY")
mw.uri.decode("It%27s+good") -> "It's good"
mw.uri.decode("It%27s%20good", "path") -> It's good
mw.uri.decode("It%27s_good", "WIKI") -> It's good
Encodes string for URLs. encmode of "QUERY" is for referencing a page name in a query, "WIKI" is for referencing a wiki page name, and "PATH" is for a non-wiki path.
.anchorEncode string mw.uri.anchorEncode("Aeris's House 1f.") -> Aeris.27s_House_1f. Encodes string for URL hash value.
.fullUrl pagename - String
query - string or table query (optional)
mw.uri.pagename("Help:Lua") -> { host = "finalfantasy.fandom.com", path = "/wiki/Help:Lua", protocol = "https" }
mw.uri.pagename("Help:Lua", "action=edit") -> { host = "finalfantasy.fandom.com", path = "/wiki/Help:Lua", protocol = "https", query = { action = "edit" } }
mw.uri.pagename("Help:Lua", { usetheme = "zidane" ) -> { host = "finalfantasy.fandom.com", path = "/wiki/Help:Lua", protocol = "https", query = { usetheme = "zidane" } }
Returns full URL from page name and string query. Same as canonicalUrl as far as I know (though I'm sure there's a difference)
.localUrl pagename - String
query - string or table query (optional)
mw.uri.pagename("Help:Lua") -> { path = "/wiki/Help:Lua" }
mw.uri.pagename("Help:Lua", "action=edit") -> { path = "/wiki/Help:Lua", query = { action = "edit" } }
mw.uri.pagename("Help:Lua", { usetheme = "zidane" ) -> { path = "/wiki/Help:Lua", query = { usetheme = "zidane" } }
Returns URI object for local URL (no host or port parameters) from page name and string query.
.validate table - mw.uri.validate({"A"}) -> false
mw.uri.validate({path = ""}) -> true
Returns boolean for the valid table being convertible to URI object.
.new table - Returns URI object from table.


mw.languageEdit

Related to the Language object.

Function Parameters Example Description
.fetchLanguageName langcode - string language code mw.language.fetchLanguageName("de") -> Deutsch'
mw.language.fetchLanguageName("bwab2")'
Returns language name of input language code. If does not match language used in software, returns empty string.
.isValidBuiltInCode langcode - string language code mw.language.isValidBuiltInCode("en") -> true
mw.language.isValidBuiltInCode("bwab2") -> true
mw.language.isValidBuiltInCode("@lol") -> false
Returns boolean for string being a technically acceptable name for a language code in the MediaWiki software, regardless of whether it is one. Alternate mw.language.isValidCode also exists but it accepts values that would not be acceptable as MediaWiki language code names.
.new langcode - string language code - Returns mw.Language object for specified language code. Most of the time en will be desired so more appropriate to use mw.message.getDefaultLanguage.

mw.messageEdit

message = { rawParam = function, getDefaultLanguage = function, newFallbackSequence = function, numParam = function, new = function }

mw.titleEdit

mw.title are functions related to the #Title object which contain details about a page on the wiki. A new Title object is created with mw.title.new.

Using titles is expensive as it has to look up and return a page from the database.

Function Parameters Example Description
.new (id - page ID)
(fulltitle - full page title)
(title - page title, nsid - namespace ID)
(title - page title, ns - namespace)
mw.title.new(3) -> Final Fantasy Wiki
mw.title.new("Project:About") -> Final Fantasy Wiki:About
mw.title.new("About, "Project"") -> Final Fantasy Wiki:About
mw.title.new("Project:About", 4) -> Final Fantasy Wiki:About
Returns Title object of given page from ID, full title, or name and namespace.
.getCurrentTitle - mw.title.getCurrentTitle() → Help:Lua Returns Title object of current page.
.equals - mw.title.equals(mw.title.new(3), mw.title.new("Final Fantasy Wiki")) → true
mw.title.equals(mw.title.new(2), mw.title.new("Final Fantasy Wiki")) → true
Returns boolean for two Title objects being for the same page.

mw.siteEdit

Site contains properties about the wiki's software and set-up. The stats sub-table contains further properties and methods regarding stats.

Property Output Description
.siteName Final Fantasy Wiki Name of wiki.
.currentVersion 1.19.24 Version of MediaWiki used by wiki.
.server //finalfantasy.fandom.com Wiki's server/URL.
.stylePath https://slot1-images.wikia.nocookie.net/__cb1581689901344/common/skins URL path for skin files.
.scriptPath URL path for script files.
.namespaces - Table of all namespaces as Namespace objects.
.contentNamespaces - Table of all content namespaces as Namespace objects.
.subjectNamespaces - Table of all subject namespaces as Namespace objects.
.talkNamespaces - Table of all talk namespaces as Namespace objects.
mw.site.statsEdit
PropertiesEdit

These properties are not technically properties of mw.site.stats, they are available from it due to a metatable.

Property Output Description
.users 22099878 Number of registered Wikia users.
.activeUsers
Number of users who have performed an action in the last 30 days.
.pages 335253 Total number of pages on the wiki.
.articles 37194 Total number of articles and disambiguation pages on the wiki.
.pages 335253 Total number of pages on the wiki.
.files 167522 Total number of files on the wiki.
.edits 3246004 Total number of edits made to the wiki.
FunctionsEdit
Function Parameters Example Description
.pagesInCategory category - string category name
pagetype (default: "all")
mw.site.stats.pagesInCategory("Articles for Speedy Deletion") -> 0
mw.site.stats.pagesInCategory("Articles for Speedy Deletion", "files") -> 0
mw.site.stats.pagesInCategory("Articles for Speedy Deletion", "*") -> { files = 0, all = 0, pages = 0, subcats = 0 }
Returns number of pages of pagetype from Category:category. pagetype can be "files" (File namespace), "subcats" (Category namespace), "pages" (remaining namespaces), and "all" (a combination of the previous three). If pagetype is "*" then a table is returned with all values.
.pagesInNamespace namespace - number namespace id mw.site.stats.pagesInNamespace(0) -> 107377 Returns number of pages in namespace.
.usersInGroup group - string group name mw.site.stats.usersInGroup("designer") -> 4 Returns number of users in usergroup.

mw.htmlEdit

mw.html only has one function, the create function. The create function is used to create a new instance of the HTML class.

mw.html.create(
tag
 )

For example:

mw.html.create("div")
-> <div></div>
mw.html.create("hr")
-> <hr />
mw.html.create(
tag
,
args
 )
args is for tables with specific properties. There is only one worthwhile property, the selfClosing boolean to make a tag close at the end. The class automatically does this for tags that self-close, (e.g. <br/>) however this allows tag that do not have to be self-closing to manually do this. Though it should be noted that it is not possibly to set this value to false to turn a self-closing tag into a non-self-closing tag. So <hr/> and <br/> cannot be used as tag pairs.

For example:

mw.html.create("div", { selfClosing = true })
-> <div />
mw.html.create("hr", { selfClosing = false })
-> <hr />

Module:StringEdit

Module:String is meant to override string as it incorporates the functions of the string library while supplying additional string functions.

Function Parameters Example Description
.trim
:trim
Contains mw.text.trim. Enables use as a method.
.split
:split
string
delimiter - Substring to split string at.
removeemptyentries - Boolean for removing empty entries (default: false).
trimentries - Boolean for trimming trailing whitespace (default: false).
string.split("@A@B@C@", "@") → { "", "A", "B", "C", "" }
string.split("@A@B@C@", "@", true) → { "A", "B", "C" }
string.split("@A@B @ @ C@", "@", true, true) → { "A", "B", "C" }
Returns auto-indexed table of substrings split from string by delimiter. If removemptyentries is true then empty string values are not added. If trimentries is true then removes trailing whitespace.
string.charat
:charat
string
number - index
string.charat("okay", 2) → k
string.charat("okay", -1) → y
Returns character at specified index. Negative numbers count back from end.
.tochartable
:tochartable
string string.tochartable("okay") → { "o", "k", "a", "y" } Returns auto-indexed table of characters within string.
.replace
:replace
string
search - string replaced
replace - string replacement
string.replace("ABCD", "BC", "AB") → AABD Returns string with instances of search substring replaced by replace substring. No Lua patterns.
.contains
:contains
string
search
string.contains("ABCD", "BC") → true
string.contains("ABCD", "bc") → false
Returns boolean for string containing search substring.
.startswith
:startswith
string
search
string.startswith("ABCD", "AB") → true
string.startswith("ABCD", "BC") → false
Returns boolean for string beginning with search substring.
.endswith
:endswith
string
search
string.endswith("ABCD", "CD") → true
string.endswith("ABCD", "BC") → false
Returns boolean for string ending with search substring.
.lettersequence - string.lettersequence() Creates a LetterSequence object.
.lettersequence number string.lettersequence(1) → A
string.lettersequence(27) → AA
string.lettersequence(128) → DX
Returns letter sequence from number. Essentially converts a number to a pseudo-base26, where the numbers are letters A-Z.
.lettersequencenumber
:lettersequencenumber
string string.lettersequencenumber("A") → 1
string.lettersequencenumber("AA") → 27
string.lettersequencenumber("DX") → 128
Returns letter sequence from number. Essentially converts a number to a pseudo-base26, where the numbers are letters A-Z.
.ischar
:ischar
string string.ischar("A") → true
string.ischar("1") → true
string.ischar("AA") → false
Returns boolean for if string is a single character.
.isletter
:isletter
string string.isletter("A") → true
string.isletter("1") → false
string.isletter("AA") → false
Returns boolean for if string is a single letter.
.isdigit
:isdigit
string string.isdigit("1") → true
string.isdigit("A") → false
string.isdigit("11") → false
Returns boolean for if string is a single digit.
.isupper
:isupper
string string.isupper("ALLOW 7") → true
string.isupper("Allow 7") → false
string.isupper("129") → true
Returns boolean for if letters in string are uppercase.
.islower
:islower
string string.islower("allow 7") → true
string.islower("Allow 7") → false
string.islower("129") → true
Returns boolean for if letters in string are lowercase.
.isalpha
:isalpha
string string.isalpha("Shell") → true
string.isalpha("She'll") → false
string.isalpha("129") → false
Returns boolean for if string only uses letters.
.isnumeric
:isnumeric
string string.isnumeric("01234") → true
string.isnumeric("A0") → false
Returns boolean for if string only uses numbers.
.isalphanumeric
:isalphanumeric
string string.isalphanumeric("1337") → true
string.isalphanumeric("leet") → true
string.isalphanumeric("l33t") → true
string.isalphanumeric("$3><") → false
Returns boolean for if string only uses letters and numbers.
string.ishexadecimal
:ishexadecimal
string string.ishexadecimal("13A") → true
string.ishexadecimal("13a") → true
string.ishexadecimal("0x13A") → false
string.ishexadecimal("BAG") → false
Returns boolean for if string only uses hexadecimal digits, case insensitive.
.isoctal
:isoctal
string string.isoctal("1337") → true
string.isoctal("800") → false
string.isoctal("0o73") → false
Returns boolean for if string only uses octal digits.

Module:TableEdit

Designed to override table by adding functions. pack and unpack are functions that exist in more modern versions of Lua.

Function Parameters Example Description
.contains table
search
table.contains({"A", B = "CC"}, "CC") → true
table.contains({"A", B = "CC"}, "C") → false
Returns boolean for a member of <coed>table</code> matching search value.
.keys table table.keys({"A", B = "C"}) → { 1, "B" } Returns auto-indexed table of table's keys.
.pack values[] table.pack("A", "B", "C") → { "A", "B", "C", n = 3 } Returns auto-indexed table of values with n property containing number of parameters. Useful for catching all the values returned by multi-value returning functions.
.unpack table
start - From index (default: 1)
end - To index (default: #table)
table.unpack({"A", "B", "C"}) → A, B, C
table.unpack({"A", "B", "C"}, 2) → B, C
table.unpack({"A", "B", "C"}, 1, 2) → A, B
Returns table values from start index to index as multiple values. Useful to print a table's values.
.tostring table table.tostring({"A", "B", "C"}) → { "A", "B", "C" }
table.tostring({"A", "B", C = "D"}) → { "A", "B", C = "D" }
Returns table values in a readable string format. Useful to print a table's values.

Module:ArrayEdit

Module:Array covers functions designed for auto-indexed tables. Array is also a class of object, and new arrays can be created with the array.new function. An array object allows it to use array functions as methods, and sets its ffwiki.type value to "array".

Function Parameters Example Description
.isarray object array.isarray({"A", "B", "C"}) -> true
array.isarray({"A", "B", C= "D"}) -> false
array.isarray("ABC") -> false
Returns boolean for object being auto-indexed table.
.push
:push
table
value - Value to add.
array.push({"A"}, "B") → 2 (table: {"A", "B"}) Adds value to end of table. Returns array's length.
.unshift
:unshift
table
value - Value to add.
array.push({"A"}, "B") → 2 (table: {"B", "A"}) Adds value to start of table. Returns array's length.
.pop
:pop
table array.pop({"A", "B"}) → B (table: {"A"}) Removes last member of table. Returns removed member's value.
.shift
:shift
table array.shift({"A", "B"}) → "A" (table: {"B"}) Removes first member of table. Returns removed member's value.
.reverse
:reverse
table array.reverse({"A", "B"}) -> { "B", "A" } Reverses the order of members in the array. Also returns table.
.concat
:concat
table
append[] - Tables to concatenate to end.
array.concat({"A"}, {"B", "C"}, {"D"}) → { "A" } Appends values from append tables to first table. Also returns table.
.contains
:contains
table
search
array.contains({"AA", "BB", "CC"}, "AA") → true }}
array.contains({"AA", "BB", "CC"}, "A") →
false
Returns boolean for any member of table matching search value.
.indexof
:indexof
table
value - Value to find.
array.indexof({"A", "B", "A"}, "A") → 1 Returns index of first member matching value.
.lastindexof
:lastindexof
table
value - Value to find.
array.indexof({"A", "B", "A"}, "A") → 3 Returns index of last member matching value.
.slice
:slice
table
start - Start index. If negative counts back from end.
end - End index. If negative counts back from end (default: #table).
array.slice({"A", "B", "C"}, 2) → { "C" }
array.slice({"A", "B", "C"}, -1) → { "C" }
array.slice({"A", "B", "C"}, 0, 2) → { 2 = "A", 3 = "B" }
array.slice({"A", "B", "C"}, -2, -1) → { "B", "C" }
Returns table members from start position to end position. If values are negative, counts back from end of table.
.foreach
:foreach
table
function - Function to run (parameters: member value, member index, table).
array.foreach({2, 1, 3}, function(a, b, c) c[b] = a + 1 end) → (table: {3, 2, 4}) Runs function for each member of a table.
.recursiveforeach
:recursiveforeach
table
function - Function to run (parameters: member value, member index, table).
array.recursiveforeach({2, {1, 3}}, function(a, b, c) c[b] = a + 1 end) → (table: {3, 2, 4}) Runs function for each member of a table.
.join
:join
table
delimiter (default: empty string)
last - Last delimiter (default: delimiter
first - Last delimiter (default: delimiter
array.join({"A", "B"}, ", ") → A, B
array.join({"A", "B", "C"}, ", ", ", and ") → A, B, and C
array.join({"A", "B", "C"}, ", and ", nil, " and ") → "A and B, and C
Returns string of table member values separated by delimiter.
.tostring
:tostring
table array.tostring({"A", "B"}) - { "A", "B" } Returns table as readable string.
.print
:print
table array.print({"A", "B"}) - { "A", "B" } Prints table as readable string. Using global print will not print table values. Using print in a script called with {{#invoke}} will cause a script error.
.new ((table) or (values[])) array.new() -> { }:func[]
array.new({"A", "B"}) -> { "A", "B" }:func[]
array.new("A", "B") -> { "A", "B" }:func[]
Creates instance of Array object. An Array object can utilize all the above functions besides isarray as functions, where the parameters are the same but the first parameter is omitted. For example, array:shift() removes the first member of the array, and array:join(", ") returns a string where the array's members are separated by a comma and space.

Module:FFWikiEdit

FFWiki covers miscellaneous commonly useful functions, including Lua-written versions of functions available in MediaWiki.

Function Parameters Example Description
.round number - Number to round
dp - Decimal places (default: 0)
ffwiki.round(10.5) -> Error: Property or function not found.
ffwiki.round(4.4444, 2) -> Error: Property or function not found.
Returns a number rounded given number of decimal places.
.topercent numerator
denominator (default: 1)
round - Decimal places (default: 0)
ffwiki.topercent(0.1) -> Error: Property or function not found.
ffwiki.topercent(1, 3) -> Error: Property or function not found.
ffwiki.topercent(1, 6, 2) -> Error: Property or function not found.
Returns string of fraction expressed as a percentage including symbol.
.cap number
minimum (default: -inf)
maximum (default: inf)
ffwiki.cap(6, 7) -> Error: Property or function not found.
ffwiki.cap(6, nil, 5) -> Error: Property or function not found.
ffwiki.cap(6, 5, 7) -> Error: Property or function not found.
Returns number raised at least to minimum or lowered at least to maximum.
.tounderscore string ffwiki.tounderscore("Final Fantasy Wiki") -> Error: Property or function not found. Returns string with spaces replaced for underscores. Used to make page names URL accessible.
.towikitable table
class
Idk, borked.
.ifnotblank value ffwiki.ifnotblank() -> Error: Property or function not found.
ffwiki.ifnotblank(nil) -> Error: Property or function not found.
ffwiki.ifnotblank("") -> Error: Property or function not found.
ffwiki.ifnotblank("a") -> Error: Property or function not found.
Returns boolean value for input containing data (not nil or empty string).
.reargs Frame.args - Returns standard table of data mimicking frame.args. Necessary to edit data and get length.
.emptystring table ffwiki.emptystring({"A", " ", "B", ""} -> Error: Property or function not found. Returns standard table of data mimicking input table albeit with blank or whitespace inputs removed. Also returns table. Designed to remove blank properties from frame.args.
.luaparam table ffwiki.luaparam({"5", "\"N\"", "true", "{'A', 'B'}", nil}) -> table({ 5, "N", true, { "A", "B" }, 6 = "a" }) Converts frame inputs from wikitext strings to values as if processed by Lua, e.g. inputs surrounded by quotation marks are strings. Does not clone table, so readonly tables like Frame.args will have to be converted first.
.unescapewikitext string
pipe - string pipe escape (|) (default: "\")
tempin string template open ({{)) (default: "{@")
tempout string template out (}}) (default: "@}"
equals - string equals string (=) (default: "~")
ffwiki.unescapwikitext("{@tl\\1~A@}") -> <strong class="error">Error: Property or function not found.</strong>
ffwiki.unescapewikitext("<tl!1?A>", "!", "<", ">", "?") -> <strong class="error">Error: Property or function not found.</strong>
Returns input string with escape substrings replaced with unescaped substrings. If parameters are false then nothing unescapes to that string.
.type value ffwiki.type("4") -> Error: Property or function not found.
ffwiki.type(array.new()) -> array
Returns string name of type of object, like global type. Unlike global type, returns __type metaproperty (or __type metamethod if the value is a function).
.expandTemplate table{title = string, args = table{}}

title
args - table{}

title
args[]
ffwiki.expandTemplate({title = "tl", args = {"A", "expandTemplate"}) -> Error: Property or function not found.

ffwiki.expandTemplate("tl", {"A", "expandTemplate"}) -> Error: Property or function not found.

ffwiki.expandTemplate("tl", "A", "expandTemplate") -> Error: Property or function not found.
Returns code of template from template name and arguments (parameters). Based on the :expandTemplate Frame method designed to be (abstractly) independent of a frame.

switchEdit

Lua does not have a native switch, and so one must get creative to find out equivalents of doing it. For simple switches where values are assigned in each case of the div, the values can be placed in a table where the keys match the cases, and the match can be tested in a loop. If we are still assigning then we might put a function with IF logic inside that takes a short-named parameter that takes the test value so it is not quite the same as typing in a variable name multiple times. If we're not assigning the value then IF, ELSEIF, ELSE may be used but then we are typing in the variable multiple times which feels unnecessary.

The switch function in this library aims to be a more suitable fix. It attempts to mimic the general idea of the SWITCH structure in other languages.

ffwiki.switch(
test
 ,
[ matches
 ,
function ]
 ,
else
)

The above syntax intends to imply that an infinite amount of matches and function pairs can be used, and the else function comes after. The else function is optional. matches is always an auto-indexed table of values, even if it only contains one value.

Tests test value for equivalent inside tables and executes following function if match is found (only for the first match).

ffwiki.switch("A", { "B", "C" }, function() return "1" end, { "A" }, function() return "2" end) --> 2
ffwiki.switch("A", { "B", "C" }, function() return "1" end, { "B" }, function() return "2" end) --> nil

An empty table always counts as a match.

ffwiki.switch("A", { "B", "C" }, function() return "1" end, {}, function() return "2" end) --> 2

If the last function in a table is not prefixed by a match table then it is the assumed else function and runs if no matches have been found.

ffwiki.switch("A", { "B", "C" }, function() return "1" end, function() return "2" end) --> 2

Module:ExprEdit

Module for running calculations from strings. This is primarily for the benefit of passing expressions from {{#invoke}} functions.

Function Parameters Example Description
.calc expression expr.calc("2+2") → 4 Returns expression evaluated.

ClassesEdit

ArrayEdit

The Array class allows the execution of relevant functions from the object. It is a part of Module:Array, where its functions are covered. A new array is created with
array.new()
, and an optional parameter is a table which is converted to an array.

FrameEdit

The Frame class holds information sent by a template (including uses of {{#invoke}}). Frame objects cannot be created in Lua itself, and therefore debugging them can be a nightmare. They are instead created when a function is called from wikitext. The frame is the single parameter of the template, though multiple frames can still exist in each call due to Frame objects having parents, and having a method to call them.

.args

The .args property is a readonly table of the arguments submitted. Parameter names map to property names much the same was as creating a table in Lua would, unnamed parameters become auto-indexed properties.

While the reference to the table can be overwritten, this means nothing. Methods that reference a frame's arguments do not use args as their source, so the originally submitted arguments will still be used.

Due to its readonly state the ffwiki.reargs function exists to clone the table into something editable.

All values stored are strings. The ffwiki.luaparam function exists to convert values from string to different Lua formats in a previously converted table.

Named arguments will have leading and trailing whitespace removed from both the name and the value before they are passed to Lua, whereas unnamed arguments will not have whitespace stripped. Empty or whitespace parameters can be removed from a table with ffwiki.emptystring.

:getParent

The :getParent method gets the current frame's parent frame. The parent frame is the one that called it, i.e. the {{#invoke}} is the original frame, but if that {{#invoke}} is in a template and that template is transcluded, then the parameters submitted to that template is the parent frame. If that template is transcluded in another template, then the parent of the original parent's parent is the parameters submitted to the second template, etc., e.g.:

frame: {{#invoke:Talk|main}}; frame.getParent(): {{Talk}}; frame:getParent():getParent(): {{User:[username]/Talk}}

If a frame has no parent, a Frame object is still returned, it is just one with an empty args table. Therefore checking if mandatory parameters exist in a parent's args table is one way to decide whether to use parameters found on a parent's frame to allow a user to {{#invoke}} directly or use a template (although the template is typically the preferred method as it is more likely to remain, unlike the location of functions).

:expandTemplate

The :expandTemplate method takes the name and arguments of a template and generates its output. Template syntax returned from Lua will not be resolved otherwise.

The reason why such a useful function is found on the Frame object (and thus requires passing it to functions if they are not called by an {{#invoke}} directly) is that parameters can be written in wikitext style and be replaced in the output with the value from its initial arguments table (Note: replacing the args table does not change the arguments that will be replaced).

expandTemplate takes a single parameter, a table with the properties title and args. The args property is a table itself, and containers the template's parameters in a Lua table.

frame:expandTemplate{ title = title, args = table }

For example:

frame:expandTemplate{ title = "tag", args = { "div", class = "aclass", "content" } }
Will result in: <div class="aclass">content</div>, the same as {{tag|div|content}}.

The title parameter functions the same as when transcluding templates, in that not specifying a namespace results in the template being taken from templatespace, while specifying one has it be taken from that namespace.

:preprocess

The :preprocess method evaluates a string as wikitext and returns the code within Lua.

frame:preprocess( string )

Since templates can be created with :expandTemplate, parameters can be taken directly from .args, and most other wikitext can be resolved when returned to the page, this may seem useless.

However its actual use is similar in vein to Html:cssText. For that, it does not care what it contains, it need only be CSS styles. preprocess is to wikitext as that is to CSS. Although there is of course one small difference: CSS can be submitted as a string fine, but wikitext cannot without being resolved before getting to the module.

At least, not without escaping. The ffwiki.unescapewikitext function exists for this purpose. Wikitext can be submitted escaped so templates, pipes, and equals signs are not evaluated before they are submitted to Lua. Escaping via <nowiki> tags means evaluating is not possible to Lua, the input string will always be the same as input.

An example use:

frame:preprocess("'''Bold''', ''italic'', {{tag|a}}, {{{1}}}") (where frame.args == { "A" })
Would output: Bold, italic, <a>, A

LanguageEdit

Part of the mw library and most associated with the mw.language functions, the <code>Language class holds a MediaWiki language and provides methods based on conventions in those languages. This includes number formatting and string formatting.

The class provides a single property, code, which is the language identifier.

Method Parameters Example Description
getCode - {code:"en"}:getCode() -> "en" Returns the object's code prefix. Identical to the value returned by the code property.
lc string {code:"en"}:lc("DoG") -> "dog" Returns string converted to lowercase accounting for special language rules.
uc string {code:"en"}:uc("cog") -> "COG" Returns string converted to uppercase accounting for special language rules.
lcfirst string {code:"en"}:lcfirst("CoW") -> "coW" Returns string with first character converted to lowercase accounting for special language rules.
ucfirst string {code:"en"}:ucfirst("doG") -> "DoG" Returns string with first character converted to uppercase accounting for special language rules.
caseFold {code:"en"}:caseFold("dOg") -> "DOG" Returns converted string to format suitable for case insensitive comparison.
isRTL - {code:"en"}:isRTL() -> false Returns boolean for language read left to right.
plural number - number of items
singular - string</br>plural - string
{code:"en"}:plural(1, "cow", "cows") -> "cow"
{code:"en"}:plural(2, "cow", "cows") -> "cows"
Returns singular or plural depending on if the number of things would require singular or plural in the language.
gender string
male - string
female - string
<code>unknown
- string (default: male)
{code:"en"}:gender("female","dog", "doge")) -> "doge
{code:"en"}:gender("","dog", "doge")) -> "dog"
{code:"en"}:gender("","dog", "doge", "doeg")) -> "doeg"
Returns male string if input is "male", female if "female", and other in all other circumstances. Supposedly you can test by username too.
formatNum number {code:"en"}:formatNum(24525.525) -> "24,525.525" Returns number as string formatted appropriately for language.
parseFormattedNumber string - string number representation {code:"en"}:parseFormattedNumber("24,525.525") -> 24525.525 Returns number from string using language's number presentation format as basis.
formatDate format - string
date - string (default: current datetime)
{code:"en"}:formatDate("Y/m/d H:i:s", "201306151627") -> "2013/06/15 16:27:00
{code:"en"}:formatDate("Y/m/d H:i:s") -> (formatted current UTC date)
Returns date as string following format.

HtmlEdit

The Html class is an object that contains information about a HTML element. Using the value of an object as a string will print the valid HTML syntax of the element given the stored information.

The Html class is used with the mw.html library.

The properties are not meant to be edited themselves, instead the object's methods are to be used to modify the values. However to give an idea of how the class works, this is how the HTML objects are stored:*(An index of "[0]" indicates it is a format for auto-indexed properties with potentially infinite parameters. Where there are duplicate keys it means there are multiple potential formats.)

{
  styles = {
    [0] = {
      name = <property name>,
      val = <value>
    },
    [0] = <css string>
  },
  attributes = {
    [0] = {
      name = <attribute name>,
      val = <value>
    }
  },
  selfClosing = <boolean>,
  nodes = {
    [0] = <wikitext string>,
    [0] = <HtmlObject>
  },
  tagName = <tag name>
}

While classes are handled in attributes, styles are not. This is noteworthy due to the functionality of the getAttr method.

:attr

The :attr method assigns a string value to a string attribute name and assigns that to the calling tag. The calling tag is returned.

It is not possible to add an attribute name without value (which would be valid for boolean attributes like disabled), though simply assigning a blank value in these cases is sufficient.

There are two formats for this method:

HtmlObj:attr(
attributename
 ,
value''
 )

attributename specifies an attribute like id, and the value is the assigned value.

HtmlObj:attr(
attributetable
)

The format of the table would be:

{
attributename
=
value
 }

This is similar to the first method, however using a table allows multiple attributes to be assigned at once.

Examples:

mw.html.create("div"):attr("id", "anid")
-> <div id="anid"></div>
mw.html.create("div"):attr("id", "anid"):attr("id", "newid")
-> <div id="newid"></div>
mw.html.create("div"):attr("id", "anid"):attr("title", "atitle")
-> <div id="newid" title="atitle"></div>
mw.html.create("div"):attr({ id = "anid", title = "atitle" })
-> <div id="anid" title="atitle"></div>
:addClass

The :addClass method adds a class name to the class attribute to the calling element. The calling element is returned. In more complex terms, the method checks whether the tag has a class attribute, and if it does not it adds one with the specified value. If one does exist then it just adds the value onto the end (with a space). This means that multiple classes can be added in one :addClass call if they are space-separated.

Classes can also be added through :attr, however using this functions allows the value held by the class to be appended to rather than replaced.

The format:

HtmlObj:addClass(
classname
 )

Examples:

mw.html.create("div"):addClass("one-class")
-> <div class="one-class"></div>
mw.html.create("div"):addClass("one-class"):addClass("two-class")
-> <div class="one-class two-class"></div>
mw.html.create("div"):addClass("one-class two-class")
-> <div class="one-class two-class"></div>
:css

The :css method pairs a CSS property with a value and adds it to the calling element. The calling element is returned. It works similarly in concept to :attr and how it pairs attributes with values. Using it for a property that does not exist will add it to the element with the given value, and using for one that does will replace the property's value.

There are two formats for this method:

HtmlObj:css(
propertyname
 ,
value
 )

propertyname specifies a property like color, and the value is the assigned value as a string.

HtmlObj:css(
propertytable
)

The format of the table would be:

{
propertyname
=
value
 }

This is similar to the first method, however using a table allows multiple properties to be assigned at once.

Examples:

mw.html.create("div"):css("text-align", "left")
-> <div style="text-align:left;"></div>
mw.html.create("div"):css("text-align", "left"):css("text-align", "right")
-> <div style="text-align:right;"></div>
mw.html.create("div"):css("text-align", "left"):css("color", "red")
-> <div style="text-align:right;color:red"></div>
mw.html.create("div"):css({ ["text-align"] = "left", color = "red"})
-> <div style="text-align:right;color:red"></div>
mw.html.create("div"):css("text-align", "left"):css("color", "red"):attr("style", "margin:0")
-> <div style="margin:0;"></div>
:cssText

The :cssText method adds text to the style property of the calling element. The calling element is returned. :cssText is designed to work similarly to :css, however the reason it is not just another overload of that method is that it handles styles differently. :css logs a property's name and value, while :cssText is a raw form and the Lua class does not distinguish. Due to this there are no checks for duplicate properties.

The format:

HtmlObj:cssText(
css
 )

The input is literally what would go in a style parameter, though trailing semi-colons may be omitted as they are added automatically.

Examples:

mw.html.create("div"):cssText("text-align:left")
-> <div style="text-align:left;"></div>
mw.html.create("div"):cssText("text-align:left;"):css("text-align", "right")
-> <div style="text-align:left;;text-align:right;"></div>
:wikitext

The :wikitext methods adds text to the calling element's content. The calling element is returned. Any valid wikitext works, and HTML elements can be input in their raw form fine. \n does work as a new line character. The element is added as a node, which is also done by :newline, :node, and :tag.

The format:

HtmlObj:wikitext(
wikitext
 )

Example:

mw.html.create("div"):wikitext("Hello"):wikitext(" world")
-> <div>Hello world</div>
:newline

The :newline method represents a new line wikitext, and adds one to the end of the content of the calling element. The calling element is returned. Has the same effect as using \n inside :wikitext.

The format:

HtmlObj:newline()

Example:

mw.html.create("div"):wikitext("A"):newline():wikitext("B")
-> <div>A
B</div>
:node

The :node method appends a Html object to the calling element's content. The calling element is returned. The main benefit of using this is for pre-created Html objects, while :tag can be used for ones created on the spot. With that said, :node may be seen as easier to use in object building chains as the building of the sub-element occurs in the brackets of a method rather than in sequence which may be confusing, especially without whitespace clarity.

The format:

HtmlObj:node(
HtmlObj
 )

Example:

mw.html.create("div"):wikitext("A"):node(mw.html.create("hr")):wikitext("B")
-> <div>A<hr />B</div>
x = mw.html.create("br") mw.html.create("div"):wikitext("A"):node(x):wikitext("B")
-> <div>A<br />B</div>

:tag The :tag methods appends a new instance of a Html object to the calling element's content. Unlike every other method, this method does not return the calling element, instead it returns the Html object created. Its parameters are identical to those of the class's constructor, mw.html.create.

HtmlObj:tag(
tag
,
args
 )

Where args is optional, and is a table that contain the property selfClosing which when set to true makes tags that are not typically self-closing self-close.

mw.html.create("div"):wikitext("A"):tag("div"):wikitext("B")
-> <div>B</div>

Relevant is the :done method.

:done

The :done method returns the Html object creator of an element created through the :tag method. Ergo, it returns control to the element that called the :tag element.

The format:

HtmlObj:done()

Examples:

mw.html.create("div"):tag("div"):wikitext("A"):done()
-> <div><div>A</div></div>
mw.html.create("div"):tag("div"):done():wikitext("A")
-> <div><div></div>A</div>
:allDone

The :allDone method works the same as :done method but acts recursively to find the original element being created.

The format:

HtmlObj:allDone()
For reference, here is what is returned in a chain of four <div> tags:
mw.html.create("div"):tag("div"):tag("div"):tag("div")
-> <div></div>
mw.html.create("div"):tag("div"):tag("div"):tag("div"):done()
-> <div><div></div></div>
mw.html.create("div"):tag("div"):tag("div"):tag("div"):done():done()
-> <div><div><div></div></div></div>
mw.html.create("div"):tag("div"):tag("div"):tag("div"):allDone()
-> <div><div><div><div></div></div></div></div>
:getAttr

Unlike the other methods, the :getAttr method is not designed to be used on the chain of creation (although it still can be). The method returns the value of the specified attribute.

One thing to note about :getAttr is its inability to return the value of the style property. The style attribute is handled separately from other attributes, though what makes this peculiar is that :attr distinguishes uses of the style property and treats it differently while this does not.


Format:

HtmlObj:getAttr(
attributename
 )

Examples:

mw.html.create("div"):getAttr("id")
-> nil
mw.html.create("div"):attr("id", "anid"):getAttr("id")
-> anid
mw.html.create("div"):attr("style", "color:red"):getAttr("style")
-> nil
mw.html.create("div"):addClass("cow dog"):getAttr("class")
-> cow dog

TabberEdit

The Tabber object is associated with Module:Tabber, and they are created through tabber.create. Tabber objects are a type of Html object, though the object remains blind to what tag it is.

In addition to all of the Html methods, Tabber has some of its own. A key feature of tabbers is the ability to append TabberTab objects. Tabbers do not have much need for adding content besides tabs, so wikitext, node, and tag can be ignored.

As a further note, tabber's have special indexing that allows the selection of its tags and properties. Take for example this tabber:

local t = tabber.create()
:addTab(p.createTab("tabA"))
:addTab(p.createTab("tabB"))

Tabs can be selected by numeric index:

t[1]
-> <div class="tabbertab" title="tabA"></div>
t[2]
-> <div class="tabbertab" title="tabB"></div>

Tabs can be selected by named index:

t.tabA
-> <div class="tabbertab" title="tabA"></div>
t["tabB"]
-> <div class="tabbertab" title="tabB"></div>
:addTab

Adds a TabberTab object to the current objects list of tabs. Returns current object.

Format:

TabberObj:addTab(
TabberTabObj
 )

Example:

local tab = tabber.createTab("A", "Content")
tabber.create("battle"):addTab(tab)

-> <div class="tabber" title="battle"><div class="tabbertab" title="A">Content</div></div>

Content
:newTab

Creates a new TabberTab object and appends it to current object. Returns new TabberTab object. The parameters match those of tabber.createTab.

Formats:

TabberObj:newTab()
TabberObj:newTab(
title
 )
TabberObj:newTab(
title
,
content[]
 )

Example:

tabber.create("battle"):newTab("A", "Content")
-> (return: <div class="tabbertab" title="A">Content</div>)}}
->(tabber: <div class="tabber" title="battle"><div class="tabbertab" title="A">Content</div></div>)

TabberTabEdit

The TabberTab object is associated with Module:Tabber. They may be created through tabber.createTab, but may also often be created through Tabber:newTab. TabberTab objects are a type of Html object, though the object remains blind to what tag it is. TabberTab are only designed to be used within a Tabber, it remains contextless outside of one.

In addition to all of the Html methods, TabberTab has some of its own. These relate to tab settings.

:default

The :default method changes whether the current object is marked as default, and returns the current object. It can be used in two ways, the first specifies no parameters and marks the tab as default, the second is to use a boolean value and mark if false unmarks the tab as default, otherwise if its true it marks it default.

Format:

TabberTabObj:default()
TabberTabObj:default(
bool
 )

Examples:

tabber.createTab():default()
-> <div class="tabbertab tabbertabdefault"></div>
tabber.createTab():default(false)
-> <div class="tabbertab"></div>
:done

Replacing the default Html:done, this method always returns the tab's Tabber parent.

Format:

TabberTabObj:default()

Example:

tabber.create():newTab():done()
-> <div class="tabber"><div class="tabbertab"></div></div>

ImageEdit

The Image class holds data for a wikitext image invocation. It is found in Module:Image and the main constructor is new. Using it as a class makes it easy to modify. The class can also add filters to images: filters for images are found in CSS classes that have to be placed in wrappers. Therefore if filters are set, the code will automatically generate the appropriate wrapper with the classes for the filter.

The class does not have accessible properties, only methods. However to give a better understanding of how the class works here are the properties it stores data in:

format
A value from frame, frameless, thumb (alias thumbnail), or a blank value (default).
border
This is a boolean for the presence of border in the syntax. Adds border to the file.
align
A value from left, right, none, center, or a blank value (default). Sets the position of the element. Blank is inline, left and right are floated to either side of content, and none and center are non-floated block elements aligned to the left and center respectively.
valign
A value from baseline, sub, super, top, text-top, middle (also the default), bottom, text-bottom. This is the position of the image position in relation to the text if the image is inline.
width
The specified pixel width of the image. Stored as a number. This is the set width, or the maximum potential width if a height is also specified.
height

The specified pixel height of the image. Stored as a number. This is the set height, or the maximum potential height if a width is also specified.

caption

Text that appears below the image or as hover text.

alt
The alt text of an image is essentially a verbal replacement for the image. It goes in the alt attribute of the HTML <img/> object. The wiki defaults to the file's name (sans filetype), although if the image is generated from this Lua class it will use the caption if one is present.
link

Page image takes the user to when clicked.

filter

Filter the image. grayscale is grayscale, fade lowers the opacity, invert flips the RGB values, flip horizontal flips the image horizontally, flip vertical flips the image vertically, and flip both rotates the image 180 degrees.

:setFormat
Takes string or nil/false for format type.
:setAlign
Takes string or nil/false for align type.
:setValign
Takes string or nil/false for valign type.
:setFilter
Takes string or nil/false for filter type.
:setBorder
Takes boolean for border.
:setWidth
Takes number "npx" string for width.
:setHeight
Takes number "npx" string for height.
:setSize
Takes (width, height), {width=width, height=height}, or {width, height} with values being number "npx" string.
:setCaption
Takes string or nil/false for caption.
:setAlt
Takes string or nil/false for alt text.
:setLink
Takes string or nil/false for page to link to.
:getFormat
Returns image's format as string.
:getAlign
Returns image's alignment as string.
:getValign
Returns image's vertical alignment as string.
:getFilter
Returns image's filters classes as string.
:isBorder
Returns boolean for whether image has border.
:getWidth
Returns image's pixel width as number.
:getHeight
Returns image's pixel width as number.
:getSize
Returns image's pixel maximum dimensions as { height = number, width = number }.
:getCaption
Returns image's caption as string.
:getAlt
Returns image's alt text as string.
:getLink
Returns image's page link as string.
:getExtension
Returns image's file extension as string (e.g. png).
:getPagename
Returns image's file extension as string (e.g. File:Image.png).
:getFilename
Returns image's file extension as string (e.g. Image.png).
:isExist
Returns boolean for whether file exists on the wiki. Will always return true when in console. This is considered expensive and not recommended for use in mainspace.

NamespaceEdit

Namespace objects are returned by some functions in mw.site. The easiest way to return the information for a desired namespace is to use the mw.site.namespaces object, either by referencing the namespace number like mw.site.namespaces[4], or referencing the namespace name, like mw.site.namespaces.Project.

The values of the object are from a query to the database and therefore the object is not intended to be manipulated. There are no functions.

Property Output Description
.id (main): 0
Module: 828
Returns ID of namespace.
.name (main):
Final Fantasy Wiki: Final Fantasy Wiki
Returns name of namespace.
.canonicalName (main):
Final Fantasy Wiki: Project
Returns canonical name of namespace.
.displayName (main): (Main) Returns display name of namespace, only on mainspace.
.aliases (main): mw.site.namespaces[0].aliases → { }
File: mw.site.namespaces[6].aliases → { "Image" }
Returns alternate names for namespaces as auto-indexed table. "Project" does not count.
.isContent (main): true
User: false
Returns boolean for if content namespace.
.isSubject (main): true
File talk: false
Returns boolean for if subject namespace.
.isTalk (main): false
File talk: true
Returns boolean for if talk namespace.
.isMovable (main): true
Special: false
Returns boolean for if pages within the namespace can be moved.
.isCapitalized (main): true
Template: true
Returns boolean for if pages within the namespace have their first letter capitalized.
.isIncludable (main): true
Special: true
Returns boolean for if pages within the namespace can be transcluded.
.hasSubpages (main): true
File: true
Returns boolean for if pages recognize subpages.
.hasGenderDistinction (main): false Returns boolean for if the namespace has different aliases for different genders.
.subject (main): mw.site.namespace[0]
Talk: mw.site.namespace[0]
Returns subject namespace of namespace as Namespace object.
.talk (main): mw.site.namespace[1]
Talk: mw.site.namespace[1]
Returns talk namespace of namespace as Namespace object.

TitleEdit

There are two types of Title objects, pages on the local wiki and pages that are not. Pages that are not can be non-existent pages, but they can also be pages on other wikis for example. Various information cannot be got from these pages like their ID or their contents, though analysis of the given title such as interwiki prefix can still be done.

The below examples make reference to the following IDs:


LetterSequenceEdit

The LetterSequence object is created through the lettersequence function in Module:String if no parameters are passed to it.

There is not much benefit to creating a dedicated LetterSequence object. The lettersequence functions can be used on it by using indexes, and some properties can be modified to choose the case of the response.

:lower

The :lower method sets the LetterSequence object to output lowercase letters rather than the default UPPERCASE. The method returns the LetterSequence object so this can be set on initialization. It can be used in three ways:

LetterSequenceObj:lower() --> Lowercase
LetterSequenceObj:lower(true) --> Lowercase
LetterSequenceObj:lower(false) --> Uppercase
LetterSequence[number]

This works the same as string.lettersequence(number), except this may also be effected by the object's case setting.

LetterSequenceObj[1] --> A
LetterSequence[alpha]

This works the same as string.lettersequencenumber(alpha).

LetterSequenceObj["A"] --> 1
Lua-logo-nolabel

Lua is available as a templating language on Fandom, helping to provide users with the ability to create more maintainable templates and to improve the performance of some of our slowest pages.

Lua is a different coding experience to basic wikitext templates, resembling a more 'traditional' programming syntax. It offers two key advantages: first and foremost is that logical functionality – 'if', 'else', and 'while' statements along with arrays and variable definition, for instance - is built into the Lua language, making the implementation of basic logic much easier in Lua than via MediaWiki's other methods. Second, because Lua is streamlined for logical operations, it performs better than its wikitext counterparts.

Lua (for wiki use) is not intended to replace JavaScript, CSS, or all wikitext templates.

Enabling and support

Lua is enabled by default on all wikis. When enabled, the general standard Lua libraries along with the specialized Scribunto libraries are also available. Fandom's implementation of Scribunto uses most standard features, but not all functions are supported; the differences are detailed in the reference manual.

For more background on the tool, read our introduction to Lua.

Lua module repository

Lua modules can also be loaded from the Fandom Open Source Library using require("Dev:ModuleName"), as opposed to require("Module:ModuleName")[1]. These "global modules" are available for re-use Fandom-wide and are described in more detail here.

Navbox Implementations

These are some Lua implementations for Navboxes:

Documentation and help

Lua documentation on the Fandom Open Source Library:

In addition to this documentation, we have a forum board set up here to ask questions and get help.

See also

Fandom Developers Wiki (dev.fandom.com)

Further help and feedback

References

  1. User blog:Kirkburn/Technical Update: June 24, 2015
Community content is available under CC-BY-SA unless otherwise noted.