Module:String

--- String is an extension of the string STL which provides operations on -- string values.

--	-- String can be invoked directly (`&#123;{#invoke:String|function|...}}`), -- invoked from a template (`&#123;{template|function|...}}`), or used -- within other modules.

--	--	For additional functions that operate on strings, you can look into the mw.ustring and mw.text --	libraries that comes with Scribunto:

--	* https://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Ustring_library --	* https://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Text_library --	-- On this Wiki, String is used in: --	* Module:Shared --	-- @module		string -- @alias		p -- @attribution  Cephalon Scientia -- @attribution  Gigamicro -- @attribution  NoBrainz -- @image		Panel.png -- @require	Module:Arguments -- @require	Module:Entrypoint -- @require	Module:User error -- @release	stable --

local p = {};

-- Module dependencies  --- local args		 = require('Dev:Arguments'); local entrypoint = require('Dev:Entrypoint'); local userError = require('Dev:User error');

-- Local functions --- For getting frame or parent arguments. Extends args.getArgs with --	additional arguments other than the ones listed here. -- @function		p.getArgs -- @param			{table} frame The input arguments -- @param			{table} options Options for getting the args --					* {boolean} noNil If true, does not replace empty strings, --								strings with only spaces/newlines with nil; default false -- @return			{table} The arguments local function getArgs(frame, options) if type(frame[1]) == 'table' and table.getn(frame) < 2 then frame = frame[1]; end if type(options) ~= 'table' then options = {options}; end local args = args.getArgs(frame, options); local tempArgs = {}; local j = 1; tempArgs = {}; if options.noNil then for i = 1, math.max(#frame, #args) do			if type(args[i]) ~= 'number' then tempArgs[i] = args[i] or frame[i]; elseif not(tempArgs[i]) and type(args[i]) ~= 'number' and frame.args then tempArgs[i] = frame.args[i]; elseif args[i] then tempArgs[j] = args[i]; j = j + 1; end end args = tempArgs; end return args; end

-- Member functions --- --- Performs a case-sensitive check if a string is a substring of a string. -- @function		p.contains -- @param			{string} str A string -- @param          {string} search The element that is being searched for -- @param[opt]		{boolean} ignoreCase If false, search is case-sensitive; true otherwise; defaults to false -- @return			{boolean} True if element exists in List, false otherwise function p.contains(...) local args = getArgs({...}); local str = args[1]; local search = args[2]; local ignoreCase = args[3]; assert(str ~= nil or search ~= nil, 'String.contains(str, search [, ignoreCase]): not enough arguments');

if ignoreCase then if type(str) == 'table' then for i = 1, #str do   			str[i] = string.lower(str[i]); end else str = string.lower(str); end search = string.lower(search); end local isSubstring; if type(str) == 'table' then for i = 1, #str do   		isSubstring = string.find(str[i], search); if isSubstring then return true; end end else isSubstring = string.find(str, search); end return isSubstring ~= nil; end

--- Splits a string into substrings based on a separating character. -- For example, split('Lith V1 Relic', '%s') would return { 'Lith', 'V1', 'Relic' } -- @function		p.split -- @param			{string} str Input string -- @param[opt]		{string} sep A string separator using Lua's character sequences; default '%s', --								 note that separator will be trimmed of whitespace -- @return			{table} A table with substrings of inputstr function p.split(...) local args = getArgs({...}, { noNil = true }); local str = args[1]; local sep = args[2]; assert(str ~= nil, 'String.split(str [, sep]): not enough arguments') if sep == nil then sep = '%s'; end mw.log(sep) local t = {}; if sep == '' then -- Extracting all characters from string str:gsub(".", function(c) table.insert(t, c) end); else for substr in string.gmatch(str, '([^'..sep..']+)') do	       table.insert(t, substr); end end return t; end

--- Checks if a string begins with a certain substring. -- For example calling startsWith ("Lith V1 Relic", "Lith") would return true. -- @function		p.startsWith -- @param		    {string} str String to be checked -- @param			{string} start Potential starting substring of str --	@param			{boolean} ignoreCase If false, search is case-sensitive; true otherwise; defaults to false -- @return			{boolean} True if a string begins with start, false otherwise function p.startsWith(...) local args = getArgs({...}, { noNil = true }); local str = args[1]; local start = args[2]; local ignoreCase = args[3]; assert(not (str == nil or start == nil), 'String.startsWith(str, start): not enough arguments'); -- Technically all strings start with an empty string if start == "" then return true; end if ignoreCase then str = string.lower(str); start = string.lower(start); end return string.sub(str, 1, string.len(start)) == start; end

--- Trims leading and trailing whitespace of a string. -- Source: http://lua-users.org/wiki/StringTrim -- @function		p.trim -- @param			{string} str Input string -- @return			{string} Trimed string function p.trim(...) local args = getArgs({...}, { noNil = true }); local str = args[1]; assert(str ~= nil, 'String.trim(str): not enough arguments'); -- Replaces "^%s*(.-)%s*$" with "%1" in str -- ^%s*(.-)%s*$ matches: -- ^:beginning of string -- %s*:any number of spaces -- (.-):any number of any character, minimum possible, saved to %1 -- %s* again -- $: end of string -- %1 inserts the content of the parentheses return str:gsub("^%s*(.-)%s*$", "%1"); end

--- Returns a string in title casing format. --	Originally from Module:VoidByReward written by User:NoBrainz. -- Reworked on 11/9/2020 by User:Gigamicro. -- @function		p.titleCase -- @param			{string} str Input string -- @return			{string} Trimmed resultant string in title casing format function p.titleCase(...) local args = getArgs({...}, { noNil = true }); local str = args[1]; assert(str ~= nil, 'String.titleCase(str): not enough arguments'); assert(type(str)=='string', 'String.titleCase: expected string, got '..type(s)); return ({ 		p.trim(str):gsub('(%S)(%S*)', function(h,t) return h:upper..t:lower end ) 	})[1]; end

-- TODO: Remove this function because mw.text and mw.uri package already has a similar function --- Returns a string with HTML codes and/or hexadecimal URL encodings replaced --	by the ASCII characters they represent (e.g. "%3A" and "&#58;" to ":"). -- @function       p.unescape -- @param			{string} str Input string -- @return			{string} A string that has its HTML codes and hexadecimal encodings replaced function p.unescape(str) assert(str ~= nil, 'String.unescape(str): not enough arguments'); -- Converting HTML codes to ASCII character (e.g. '&#58;' to ':') str = (str:gsub('&#([%d]+);', function(n) return string.char(n+0) end)); -- Converting hexadecimal codes (two bytes) to ASCII character (e.g. '%3A' to ':') return (str:gsub('%%..', function(n) return string.char(tonumber(string.sub(n, 2), 16)) end)); end

-- All String STL functions  -- -- https://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#String_library p.byte = string.byte; p.char = string.char; p.dump = string.dump; p.find = string.find; p.format = string.format; p.gmatch = string.gmatch; p.gsub = string.gsub; p.len = string.len; p.lower = string.lower; p.match = string.match; p.rep = string.rep; p.reverse = string.reverse; p.sub = string.sub; p.ulower = string.ulower; p.upper = string.upper; p.uupper = string.uupper;

p.__main = entrypoint(p); return p;