trailing whitespace from the target string. In some circumstances this is desirable, in
other cases one may want to preserve the whitespace.  
The first character has an index value of 1.  
If one requests a negative value, this function will select a character by counting backwards
from the end of the string. In other words pos = -1 is the same as asking for the last character.  
A requested value of zero, or a value greater than the length of the string returns an error.  
function str.pos
local new_args = str._getParameters( .args, {'target', 'pos'} )
local target_str = new_args['target'] or ''
local pos = tonumber( new_args['pos'] ) or 0  
if pos == 0 or math.abs(pos) > mw.ustring.len( target_str ) then
return str._error( 'String index out of range' )
end  
return mw.ustring.sub( target_str, pos, pos )
end  
---
str_find  
This function duplicates the behavior of , including all of its quirks.
This is provided in order to support existing templates, but is NOT RECOMMENDED for
new code and templates. New code is recommended to use the "find" function instead.  
Returns the first index in "source" that is a match to "target". Indexing is 1-based,
and the function returns -1 if the "target" string is not present in "source".  
Important Note: If the "target" string is empty / missing, this function returns a
value of "1", which is generally unexpected behavior, and must be accounted for
separatetly.  
function str.str_find
local new_args = str._getParameters( .args, {'source', 'target'} )
local source_str = new_args['source'] or ''
local target_str = new_args['target'] or ''  
if target_str == '' then
return 1
end  
local start = mw.ustring.find( source_str, target_str, 1, true )
if start == nil then
start = -1
end  
return start
end  
---
find  
This function allows one to search for a target string or pattern within another
string.  
Usage:  
OR  
Parameters
source: The string to search
target: The string or pattern to find within source
start: The index within the source string to start the search, defaults to 1
plain: Boolean flag indicating that target should be understood as plain
text and not as a Lua style regular expression, defaults to true  
If invoked using named parameters, Mediawiki will automatically remove any leading or
trailing whitespace from the parameter. In some circumstances this is desirable, in
other cases one may want to preserve the whitespace.  
This function returns the first index >= "start" where "target" can be found
within "source". Indices are 1-based. If "target" is not found, then this
function returns 0. If either "source" or "target" are missing / empty, this
function also returns 0.  
This function should be safe for UTF-8 strings.  
function str.find
local new_args = str._getParameters( .args, {'source', 'target', 'start', 'plain' } )
local source_str = new_args['source'] or ''
local pattern = new_args['target'] or ''
local start_pos = tonumber(new_args['start']) or 1
local plain = new_args['plain'] or true  
if source_str == * or pattern == * then
return 0
end  
plain = str._getBoolean( plain )  
local start = mw.ustring.find( source_str, pattern, start_pos, plain )
if start == nil then
start = 0
end  
return start
end  
---
replace  
This function allows one to replace a target string or pattern within another
string.  
Usage:  
OR  
Parameters
source: The string to search
pattern: The string or pattern to find within source
replace: The replacement text
count: The number of occurences to replace, defaults to all.
plain: Boolean flag indicating that pattern should be understood as plain
text and not as a Lua style regular expression, defaults to true  
function str.replace
local new_args = str._getParameters( .args, {'source', 'pattern', 'replace', 'count', 'plain' } )
local source_str = new_args['source'] or ''
local pattern = new_args['pattern'] or ''
local replace = new_args['replace'] or ''
local count = tonumber( new_args['count'] )
local plain = new_args['plain'] or true  
if source_str == * or pattern == * then
return source_str
end
plain = str._getBoolean( plain )  
if plain then
pattern = str._escapePattern( pattern )
replace = string.gsub( replace, "%%", "%%%%" ) --Only need to escape replacement sequences.
end  
local result  
if count ~= nil then
result = mw.ustring.gsub( source_str, pattern, replace, count )
else
result = mw.ustring.gsub( source_str, pattern, replace )
end  
return result
end  
---
simple function to pipe string.rep to templates.  
function str.rep
local repetitions = tonumber( .args[2] )
if not repetitions then
return str._error( 'function rep expects a number as second parameter, received "' .. ( .args[2] or '' ) .. '"' )
end
return string.rep( .args[1] or '', repetitions )
end  
--[[
escapePattern  
This function escapes special characters from a Lua string pattern. See [1]
for details on how patterns work.  
[1] https://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Patterns  
Usage:  
Parameters
pattern_string: The pattern string to escape.
function str.escapePattern
local pattern_str = .args[1]
if not pattern_str then
return str._error( 'No pattern string specified' )
end
local result = str._escapePattern( pattern_str )
return result
end  
---
count
This function counts the number of occurrences of one string in another.  
function str.count
local args = str._getParameters(.args, {'source', 'pattern', 'plain'})
local source = args.source or ''
local pattern = args.pattern or ''
local plain = str._getBoolean(args.plain or true)
if plain then
pattern = str._escapePattern(pattern)
end
local _, count = mw.ustring.gsub(source, pattern, '')
return count
end  
---
endswith
This function determines whether a string ends with another string.  
function str.endswith
local args = str._getParameters(.args, {'source', 'pattern'})
local source = args.source or ''
local pattern = args.pattern or ''
if pattern == '' then
-- All strings end with the empty string.
return "yes"
end
if mw.ustring.sub(source, -mw.ustring.len(pattern), -1) == pattern then
return "yes"
else
return ""
end
end  
---
join  
Join all non empty arguments together; the first argument is the separator.
Usage:  
function str.join
local args = {}
local sep
for _, v in ipairs( .args ) do
if sep then
if v ~= '' then
table.insert(args, v)
end
else
sep = v
end
end
return table.concat( args, sep or '' )
end  
---
Helper function that populates the argument list given that user may need to use a mix of
named and unnamed parameters. This is relevant because named parameters are not
identical to unnamed parameters due to string trimming, and when dealing with strings
we sometimes want to either preserve or remove that whitespace depending on the application.  
function str._getParameters( frame_args, arg_list )
local new_args = {}
local index = 1
local value  
for _, arg in ipairs( arg_list ) do
value = frame_args[arg]
if value == nil then
value = frame_args[index]
index = index + 1
end
new_args[arg] = value
end  
return new_args
end  
---
Helper function to handle error messages.  
function str._error( error_str )
local = mw.getCurrentFrame
local error_category = .args.error_category or 'Errors reported by Module String'
local ignore_errors = .args.ignore_errors or false
local no_category = .args.no_category or false  
if str._getBoolean(ignore_errors) then
return ''
end  
local error_str = '<strong>String Module Error: ' .. error_str .. '</strong>'
if error_category ~= '' and not str._getBoolean( no_category ) then
error_str = '' .. error_str
end  
return error_str
end  
---
Helper Function to interpret boolean strings  
function str._getBoolean( boolean_str )
local boolean_value  
if type( boolean_str ) == 'string' then
boolean_str = boolean_str:lower
if boolean_str == 'false' or boolean_str == 'no' or boolean_str == '0'
or boolean_str == '' then
boolean_value = false
else
boolean_value = true
end
elseif type( boolean_str ) == 'boolean' then
boolean_value = boolean_str
else