Pojdi na vsebino

Modul:Text

Iz Wikipedije, proste enciklopedije
Documentation icon Dokumentacija modula[predogled] [uredi] [zgodovina] [osveži]

Text – Module containing methods for the manipulation of text, wikimarkup and some HTML.

Functions for templates

[uredi kodo]

All methods have an unnamed parameter containing the text.

The return value is an empty string if the parameter does not meet the conditions. When the condition is matched or some result is successfully found, strings of at least one character are returned.

char
Creates a string from a list of character codes.
1
Space-separated list of character codes
*
Number of repetitions of the list in parameter 1; (Default 1).
errors
0 – Silence errors
concatParams
Combine any number of elements into a list, like table.concat() in Lua.
From a template:
1
First element; missing and empty elements are ignored.
2 3 4 5 6 …
Further list elements
From Lua
args
table (sequence) of the elements
apply
Separator between elements; defaults to |
adapt
optional formatting, which will be applied to each element; must contain %s.
containsCJK
Returns whether the input string contains any CJK characters
  • Returns nothing if there are no CJK characters
removeDelimited
Remove all text between delimiters, including the delimiters themselves.
getPlain
Remove wikimarkup (except templates): comments, tags, bold, italic, nbsp
isLatinRange
Returns some content, unless the string contains a character that would not normally be found in Latin text.
  • Returns nothing if there is a non-Latin string.
isQuote
Returns some content if the parameter passed is a single character, and that character is a quote, such as '.
  • Returns nothing for multiple characters, or if the character passed is not a quote.
listToText
Formats list elements analogously to mw.text.listToText().
The elements are separated by a comma and space ; the word "and" appears between the first and last.
Unnamed parameters become the list items.
Optional parameters for #invoke:
  • format – Every list element will first be formatted with this format string; see here for how to construct this string. The string must contain at least one %s sequence.
  • template=1 – List elements should be taken from the calling template.
Returns the resulting string.
quote
Wrap the string in quotes; quotes can be chosen for a specific language.
1
Input text (will be automatically trimmed); may be empty.
2
(optional) the ISO 639 language code for the quote marks; should be one of the supported languages (nemško)
3
(optional) 2 for second level quotes. This means the single quote marks in a statement such as: Jack said, “Jill said ‘fish’ last Tuesday.”
quoteUnquoted
Wrap the string in quotes; quotes can be chosen for a specific language. Will not quote an empty string, and will not quote if there is a quote at the start or end of the (trimmed) string.
1
Input text (will be automatically trimmed); may be empty.
2
(optional) the ISO 639 language code for the quote marks; should be one of the supported languages (nemško)
3
(optional) 2 for second level quotes. This means the single quote marks in a statement such as: Jack said, “Jill said ‘fish’ last Tuesday.”
removeDiacritics
Removes all diacritical marks from the input.
1
Input text
sentenceTerminated
Is this sentence terminated? Should work with CJK, and allows quotation marks to follow.
  • Returns nothing if the sentence is unterminated.
ucfirstAll
The first letter of every recognized word is converted to upper case. This contrasts with the parser function {{ucfirst:}} which changes only the first character of the whole string passed.
A few common HTML entities are protected; the implementation of this may mean that numerical entities passed (e.g. &) are converted to & form
uprightNonlatin
Takes a string. Italicized non-Latin characters are un-italicized, unless they are a single Greek letter.
zip
Combines a tuple of lists by convolution. This is easiest to explain by example: given two lists, list1 = "a b c" and list2 = "1 2 3", then
zip(liste1, liste2, sep = " ", isep = "-", osep = "/")
outputs
a-1/b-2/c-3
  • 1, 2, 3, … – Lists to be combined
  • sep – A separator (in Lua regex form) used to split the lists. If empty, the lists are split into individual characters.
  • sep1, sep2, sep3, … – Allows a different separator to be used for each list.
  • isep – Output separator; placed between elements which were at the same index in their lists.
  • osep – Output separator; placed between elements which had different original indices; i.e. between the groups joined with isep

Examples and test page

[uredi kodo]

There are tests available (nemško) to illustrate this in practice.

Use in another Lua module

[uredi kodo]

All of the above functions can be called from other Lua modules. Use require(); the below code checks for errors loading it:

local lucky, Text = pcall( require, "Module:Text" ) if type( Text ) == "table" then  Text = Text.Text() else  -- In the event of errors, Text is an error message.  return "<span class=\"error\">" .. Text .. "</span>" end 

You may then call:

  • Text.char( apply, again, accept )
  • Text.concatParams( args, separator, format )
  • Text.containsCJK( s )
  • Text.removeDelimited( s )
  • Text.getPlain( s )
  • Text.isLatinRange( s )
  • Text.isQuote( c )
  • Text.listToText( table, format )
  • Text.quote( s, lang, mode )
  • Text.quoteUnquoted( s, lang, mode )
  • Text.removeDiacritics( s )
  • Text.sentenceTerminated( s )
  • Text.ucfirstAll( s )
  • Text.uprightNonlatin( s )
  • Text.zip(…)
  • Text.test( s )

Usage

[uredi kodo]

This is a general library; use it anywhere.

Dependencies

[uredi kodo]

None.

See also

[uredi kodo]
local Text = { serial = "2024-06-05",  suite = "Text",  item = 29387871 } --[=[ Text utilities ]=] local Failsafe = Text local GlobalMod = Text local Patterns = { } local RangesLatin = false local SeekQuote = false    local foreignModule = function ( access, advanced, append, alt, alert )  -- Fetch global module  -- Precondition:  -- access -- string, with name of base module  -- advanced -- true, for require(); else mw.loadData()  -- append -- string, with subpage part, if any; or false  -- alt -- number, of wikidata item of root; or false  -- alert -- true, for throwing error on data problem  -- Postcondition:  -- Returns whatever, probably table  -- 2019-10-29  local storage = access  local finer = function ()  if append then  storage = string.format( "%s/%s",  storage,  append )  end  end  local fun, lucky, r, suited  if advanced then  fun = require  else  fun = mw.loadData  end  GlobalMod.globalModules = GlobalMod.globalModules or { }  suited = GlobalMod.globalModules[ access ]  if not suited then  finer()  lucky, r = pcall( fun, "Module:" .. storage )  end  if not lucky then  if not suited and  type( alt ) == "number" and  alt > 0 then  suited = string.format( "Q%d", alt )  suited = mw.wikibase.getSitelink( suited )  GlobalMod.globalModules[ access ] = suited or true  end  if type( suited ) == "string" then  storage = suited  finer()  lucky, r = pcall( fun, storage )  end  if not lucky and alert then  error( "Missing or invalid page: " .. storage, 0 )  end  end  return r end -- foreignModule()    local function factoryQuote()  -- Create quote definitions  if not Text.quoteLang then  local quoting = foreignModule( "Text",  false,  "quoting",  Text.item )  if type( quoting ) == "table" then  Text.quoteLang = quoting.langs  Text.quoteType = quoting.types  end  if type( Text.quoteLang ) ~= "table" then  Text.quoteLang = { }  end  if type( Text.quoteType ) ~= "table" then  Text.quoteType = { }  end  if type( Text.quoteLang.en ) ~= "string" then  Text.quoteLang.en = "ld"  end  if type( Text.quoteType[ Text.quoteLang.en ] ) ~= "table" then  Text.quoteType[ Text.quoteLang.en ] = { { 8220, 8221 },  { 8216, 8217 } }  end  end end -- factoryQuote()    local function fiatQuote( apply, alien, advance )  -- Quote text  -- Parameter:  -- apply -- string, with text  -- alien -- string, with language code  -- advance -- number, with level 1 or 2  local r = apply  local quotes, suite  factoryQuote()  if alien then  suite = mw.text.trim( alien )  if suite == "" then  suite = false  else  local s = Text.quoteLang[ suite ]  if s then  suite = s  else  local slang = suite:match( "^(%l+)-" )  if slang then  suite = Text.quoteLang[ slang ]  end  end  end  end  if not suite then  suite = Text.quoteLang.en  end  quotes = Text.quoteType[ suite ]  if quotes then  local space  if quotes[ 3 ] then  space = "&#160;"  else  space = ""  end  quotes = quotes[ advance ]  if quotes then  r = mw.ustring.format( "%s%s%s%s%s",  mw.ustring.char( quotes[ 1 ] ),  space,  apply,  space,  mw.ustring.char( quotes[ 2 ] ) )  end  else  mw.log( "fiatQuote() " .. suite )  end  return r end -- fiatQuote()    Text.char = function ( apply, again, accept )  -- Create string from codepoints  -- Parameter:  -- apply -- table (sequence) with numerical codepoints, or nil  -- again -- number of repetitions, or nil  -- accept -- true, if no error messages to be appended  -- Returns: string  local r  if type( apply ) == "table" then  local bad = { }  local codes = { }  local s  for k, v in pairs( apply ) do  s = type( v )  if s == "number" then  if v < 32 and v ~= 9 and v ~= 10 then  v = tostring( v )  else  v = math.floor( v )  s = false  end  elseif s ~= "string" then  v = tostring( v )  end  if s then  table.insert( bad, v )  else  table.insert( codes, v )  end  end -- for k, v  if #bad == 0 then  if #codes > 0 then  r = mw.ustring.char( unpack( codes ) )  if again then  if type( again ) == "number" then  local n = math.floor( again )  if n > 1 then  r = r:rep( n )  elseif n < 1 then  r = ""  end  else  s = "bad repetitions: " .. tostring( again )  end  end  end  else  s = "bad codepoints: " .. table.concat( bad, " " )  end  if s and not accept then  r = tostring( mw.html.create( "span" )  :addClass( "error" )  :wikitext( s ) )  end  end  return r or "" end -- Text.char()    Text.concatParams = function ( args, apply, adapt )  -- Concat list items into one string  -- Parameter:  -- args -- table (sequence) with numKey=string  -- apply -- string (optional); separator (default: "|")  -- adapt -- string (optional); format including "%s"  -- Returns: string  local collect = { }  for k, v in pairs( args ) do  if type( k ) == "number" then  v = mw.text.trim( v )  if v ~= "" then  if adapt then  v = mw.ustring.format( adapt, v )  end  table.insert( collect, v )  end  end  end -- for k, v  return table.concat( collect, apply or "|" ) end -- Text.concatParams()    Text.containsCJK = function ( analyse )  -- Is any CJK code within?  -- Parameter:  -- analyse -- string  -- Returns: true, if CJK detected  local r  if not Patterns.CJK then  Patterns.CJK = mw.ustring.char( 91,  0x3400, 45, 0x9FFF,  0x20000, 45, 0x2B81F,  93 )  end  if mw.ustring.find( analyse, Patterns.CJK ) then  r = true  else  r = false  end  return r end -- Text.containsCJK()    Text.getPlain = function ( adjust )  -- Remove wikisyntax from string, except templates  -- Parameter:  -- adjust -- string  -- Returns: string  local i = adjust:find( "<!--", 1, true )  local r = adjust  local j  while i do  j = r:find( "-->", i + 3, true )  if j then  r = r:sub( 1, i ) .. r:sub( j + 3 )  else  r = r:sub( 1, i )  end  i = r:find( "<!--", i, true )  end -- "<!--"  r = r:gsub( "(</?%l[^>]*>)", "" )  :gsub( "'''(.+)'''", "%1" )  :gsub( "''(.+)''", "%1" )  :gsub( "&nbsp;", " " )  return mw.text.unstrip( r ) end -- Text.getPlain()    Text.isLatinRange = function ( adjust )  -- Are characters expected to be latin or symbols within latin texts?  -- Precondition:  -- adjust -- string, or nil for initialization  -- Returns: true, if valid for latin only  local r  if not RangesLatin then  RangesLatin = { { 0x07, 0x02AF },  { 0x1D6B, 0x1D9A },  { 0x1E00, 0x1EFF },  { 0x2002, 0x203A },  { 0x2190, 0x23BD } }  end  if not Patterns.Latin then  local range  Patterns.Latin = "^["  for i = 1, #RangesLatin do  range = RangesLatin[ i ]  Patterns.Latin = Patterns.Latin ..  mw.ustring.char( range[ 1 ], 45, range[ 2 ] )  end -- for i  Patterns.Latin = Patterns.Latin .. "]*$"  end  if adjust then  if mw.ustring.match( adjust, Patterns.Latin ) then  r = true  else  r = false  end  end  return r end -- Text.isLatinRange()    Text.isQuote = function ( ask )  -- Is this character any quotation mark?  -- Parameter:  -- ask -- string, with single character  -- Returns: true, if ask is quotation mark  local r  if not SeekQuote then  SeekQuote = mw.ustring.char( 34, -- "  39, -- '  171, -- laquo  187, -- raquo  8216, -- lsquo  8217, -- rsquo  8218, -- sbquo  8220, -- ldquo  8221, -- rdquo  8222, -- bdquo  8249, -- lsaquo  8250, -- rsaquo  0x300C, -- CJK  0x300D, -- CJK  0x300E, -- CJK  0x300F ) -- CJK  end  if ask == "" then  r = false  elseif mw.ustring.find( SeekQuote, ask, 1, true ) then  r = true  else  r = false  end  return r end -- Text.isQuote()    Text.listToText = function ( args, adapt )  -- Format list items similar to mw.text.listToText()  -- Parameter:  -- args -- table (sequence) with numKey=string  -- adapt -- string (optional); format including "%s"  -- Returns: string  local collect = { }  for k, v in pairs( args ) do  if type( k ) == "number" then  v = mw.text.trim( v )  if v ~= "" then  if adapt then  v = mw.ustring.format( adapt, v )  end  table.insert( collect, v )  end  end  end -- for k, v  return mw.text.listToText( collect ) end -- Text.listToText()    Text.quote = function ( apply, alien, advance )  -- Quote text  -- Parameter:  -- apply -- string, with text  -- alien -- string, with language code, or nil  -- advance -- number, with level 1 or 2, or nil  -- Returns: quoted string  local mode, slang  if type( alien ) == "string" then  slang = mw.text.trim( alien ):lower()  else  local pageLang = mw.title.getCurrentTitle().pageLanguage  if pageLang then  slang = pageLang.code  else  slang = mw.language.getContentLanguage():getCode()  end  end  if advance == 2 then  mode = 2  else  mode = 1  end  return fiatQuote( mw.text.trim( apply ), slang, mode ) end -- Text.quote()    Text.quoteUnquoted = function ( apply, alien, advance )  -- Quote text, if not yet quoted and not empty  -- Parameter:  -- apply -- string, with text  -- alien -- string, with language code, or nil  -- advance -- number, with level 1 or 2, or nil  -- Returns: string; possibly quoted  local r = mw.text.trim( apply )  local s = mw.ustring.sub( r, 1, 1 )  if s ~= "" and not Text.isQuote( s, advance ) then  s = mw.ustring.sub( r, -1, 1 )  if not Text.isQuote( s ) then  r = Text.quote( r, alien, advance )  end  end  return r end -- Text.quoteUnquoted()    Text.removeDiacritics = function ( adjust )  -- Remove all diacritics  -- Parameter:  -- adjust -- string  -- Returns: string; all latin letters should be ASCII  -- or basic greek or cyrillic or symbols etc.  local cleanup, decomposed  if not Patterns.Combined then  Patterns.Combined = mw.ustring.char( 91,  0x0300, 45, 0x036F,  0x1AB0, 45, 0x1AFF,  0x1DC0, 45, 0x1DFF,  0xFE20, 45, 0xFE2F,  93 )  end  decomposed = mw.ustring.toNFD( adjust )  cleanup = mw.ustring.gsub( decomposed, Patterns.Combined, "" )  return mw.ustring.toNFC( cleanup ) end -- Text.removeDiacritics()    Text.removeWhitespace = function ( adjust )  -- Remove all whitespace, or replace with ASCII space  -- Parameter:  -- adjust -- string  -- Returns: string; modified  local r = mw.text.decode( adjust )  if r:find( "&", 1, true ) then  r = r:gsub( "&lrm;", "" )  :gsub( "&rlm;", "" )  :gsub( "&zwj;", "" )  :gsub( "&zwnj;", "" )  :gsub( "&thinsp;", " " )  :gsub( "&ensp;", " " )  :gsub( "&emsp;", " " )  end  if not Patterns.Whitespace then  Patterns.Whitespace = mw.ustring.char( 0x00AD,  91, 0x200C, 45, 0x200F, 93,  91, 0x2028, 45, 0x202E, 93,  0x205F,  0x2060 )  Patterns.Space = mw.ustring.char( 0x00A0,  0x1680,  91, 0x2000, 45, 0x200A, 93,  0x202F,  0x205F,  0x3000,  0x303F )  end  r = mw.ustring.gsub( r, Patterns.Whitespace, "" )  r = mw.ustring.gsub( r, Patterns.Space, " " )  return mw.text.trim( r ) end -- Text.removeWhitespace()    Text.sentenceTerminated = function ( analyse )  -- Is string terminated by dot, question or exclamation mark?  -- Quotation, link termination and so on granted  -- Parameter:  -- analyse -- string  -- Returns: true, if sentence terminated  local r = mw.text.trim( analyse )  local lt = r:find( "<", 1, true )  if not Patterns.Terminated then  Patterns.Terminated = mw.ustring.char( 91,  0x3002,  0xFF01,  0xFF0E,  0xFF1F )  .. "!%.%?…][\"'%]‹›«»‘’“”]*$"  end  if lt then  r = r:gsub( "</span>", "" )  end  if mw.ustring.find( r, Patterns.Terminated ) then  r = true  elseif lt then  local s = "<bdi[^>]* dir=\"([lr]t[rl])\".+</bdi></bdo>"  s = r:match( s )  if s then  if mw.language.getContentLanguage():isRTL() then  r = ( s == "ltr" )  else  r = ( s == "rtl" )  end  else  r = false  end  else  r = false  end  return r end -- Text.sentenceTerminated()    Text.tokenWords = function ( adjust )  -- Split text in words of digits or letters  -- Precondition:  -- adjust -- string  -- Returns: string with  local r = mw.uri.decode( adjust, "WIKI" )  if r:find( "&", 1, true ) then  r = mw.text.decode( r )  end  r = Text.removeWhitespace( r )  r = mw.ustring.gsub( r, "[%p%s]+", " " )  return r end -- Text.tokenWords()    Text.ucfirstAll = function ( adjust )  -- Capitalize all words  -- Precondition:  -- adjust -- string  -- Returns: string with all first letters in upper case  local r = " " .. adjust  local i = 1  local c, j, m  if adjust:find( "&" ) then  r = r:gsub( "&amp;", "&#38;" )  :gsub( "&lt;", "&#60;" )  :gsub( "&gt;", "&#62;" )  :gsub( "&nbsp;", "&#160;" )  :gsub( "&thinsp;", "&#8201;" )  :gsub( "&zwnj;", "&#8204;" )  :gsub( "&zwj;", "&#8205;" )  :gsub( "&lrm;", "&#8206;" )  :gsub( "&rlm;", "&#8207;" )  m = true  end  while i do  i = mw.ustring.find( r, "%W%l", i )  if i then  j = i + 1  c = mw.ustring.upper( mw.ustring.sub( r, j, j ) )  r = string.format( "%s%s%s",  mw.ustring.sub( r, 1, i ),  c,  mw.ustring.sub( r, i + 2 ) )  i = j  end  end -- while i  r = r:sub( 2 )  if m then  r = r:gsub( "&#38;", "&amp;" )  :gsub( "&#60;", "&lt;" )  :gsub( "&#62;", "&gt;" )  :gsub( "&#160;", "&nbsp;" )  :gsub( "&#8201;", "&thinsp;" )  :gsub( "&#8204;", "&zwnj;" )  :gsub( "&#8205;", "&zwj;" )  :gsub( "&#8206;", "&lrm;" )  :gsub( "&#8207;", "&rlm;" )  :gsub( "&#X(%x+);", "&#x%1;" )  end  return r end -- Text.ucfirstAll()    Text.uprightNonlatin = function ( adjust )  -- Ensure non-italics for non-latin text parts  -- One single greek letter might be granted  -- Precondition:  -- adjust -- string  -- Returns: string with non-latin parts enclosed in <span>  local r  Text.isLatinRange()  if mw.ustring.match( adjust, Patterns.Latin ) then  -- latin only, horizontal dashes, quotes  r = adjust  else  local c  local e = mw.html.create( "span" )  local j = false  local k = 1  local m = false  local n = mw.ustring.len( adjust )  local p  local flat = function ( a )  -- isLatin  local range  for i = 1, #RangesLatin do  range = RangesLatin[ i ]  if a >= range[ 1 ] and a <= range[ 2 ] then  return true  end  end -- for i  end -- flat()  local focus = function ( a )  -- char is not ambivalent  local r = ( a > 64 )  if r then  r = ( a < 8192 or a > 8212 )  else  r = ( a == 38 or a == 60 ) -- '&' '<'  end  return r  end -- focus()  local form = function ( a )  return string.format( p,  r,  mw.ustring.sub( adjust, k, j - 1 ),  mw.ustring.sub( adjust, j, a ) )  end -- form()  e:attr( "dir", "auto" )  :css( "font-style", "normal" )  :wikitext( "%s" )  p = "%s%s" .. tostring( e )  r = ""  for i = 1, n do  c = mw.ustring.codepoint( adjust, i, i )  if focus( c ) then  if flat( c ) then  if j then  if m then  if i == m then  -- single greek letter.  j = false  end  m = false  end  if j then  local nx = i - 1  local s = ""  for ix = nx, 1, -1 do  c = mw.ustring.sub( adjust, ix, ix )  if c == " " or c == "(" then  nx = nx - 1  s = c .. s  else  break -- for ix  end  end -- for ix  r = form( nx ) .. s  j = false  k = i  end  end  elseif not j then  j = i  if c >= 880 and c <= 1023 then  -- single greek letter?  m = i + 1  else  m = false  end  end  elseif m then  m = m + 1  end  end -- for i  if j and ( not m or m < n ) then  r = form( n )  else  r = r .. mw.ustring.sub( adjust, k )  end  end  return r end -- Text.uprightNonlatin()    Failsafe.failsafe = function ( atleast )  -- Retrieve versioning and check for compliance  -- Precondition:  -- atleast -- string, with required version  -- or wikidata|item|~|@ or false  -- Postcondition:  -- Returns string -- with queried version/item, also if problem  -- false -- if appropriate  -- 2024-03-01  local since = atleast  local last = ( since == "~" )  local linked = ( since == "@" )  local link = ( since == "item" )  local r  if last or link or linked or since == "wikidata" then  local item = Failsafe.item  since = false  if type( item ) == "number" and item > 0 then  local suited = string.format( "Q%d", item )  if link then  r = suited  else  local entity = mw.wikibase.getEntity( suited )  if type( entity ) == "table" then  local seek = Failsafe.serialProperty or "P348"  local vsn = entity:formatPropertyValues( seek )  if type( vsn ) == "table" and  type( vsn.value ) == "string" and  vsn.value ~= "" then  if last and vsn.value == Failsafe.serial then  r = false  elseif linked then  if mw.title.getCurrentTitle().prefixedText  == mw.wikibase.getSitelink( suited ) then  r = false  else  r = suited  end  else  r = vsn.value  end  end  end  end  elseif link then  r = false  end  end  if type( r ) == "nil" then  if not since or since <= Failsafe.serial then  r = Failsafe.serial  else  r = false  end  end  return r end -- Failsafe.failsafe()    Text.test = function ( about )  local r  if about == "quote" then  factoryQuote()  r = { QuoteLang = Text.quoteLang,  QuoteType = Text.quoteType }  end  return r end -- Text.test()    -- Export local p = { }  function p.char( frame )  local params = frame:getParent().args  local story = params[ 1 ]  local codes, lenient, multiple  if not story then  params = frame.args  story = params[ 1 ]  end  if story then  local items = mw.text.split( story, "%s+" )  if #items > 0 then  local j  lenient = ( params.errors == "0" )  codes = { }  multiple = tonumber( params[ "*" ] )  for k, v in pairs( items ) do  if v:sub( 1, 1 ) == "x" then  j = tonumber( "0" .. v )  elseif v == "" then  v = false  else  j = tonumber( v )  end  if v then  table.insert( codes, j or v )  end  end -- for k, v  end  end  return Text.char( codes, multiple, lenient ) end  function p.concatParams( frame )  local args  local template = frame.args.template  if type( template ) == "string" then  template = mw.text.trim( template )  template = ( template == "1" )  end  if template then  args = frame:getParent().args  else  args = frame.args  end  return Text.concatParams( args,  frame.args.separator,  frame.args.format ) end  function p.containsCJK( frame )  return Text.containsCJK( frame.args[ 1 ] or "" ) and "1" or "" end  function p.getPlain( frame )  return Text.getPlain( frame.args[ 1 ] or "" ) end  function p.isLatinRange( frame )  return Text.isLatinRange( frame.args[ 1 ] or "" ) and "1" or "" end  function p.isQuote( frame )  return Text.isQuote( frame.args[ 1 ] or "" ) and "1" or "" end    function p.listToFormat(frame)  local lists = {}  local pformat = frame.args["format"]  local sep = frame.args["sep"] or ";"   -- Parameter parsen: Listen  for k, v in pairs(frame.args) do  local knum = tonumber(k)  if knum then lists[knum] = v end  end   -- Listen splitten  local maxListLen = 0  for i = 1, #lists do  lists[i] = mw.text.split(lists[i], sep)  if #lists[i] > maxListLen then maxListLen = #lists[i] end  end   -- Ergebnisstring generieren  local result = ""  local result_line = ""  for i = 1, maxListLen do  result_line = pformat  for j = 1, #lists do  result_line = mw.ustring.gsub( result_line,  "%%s",  lists[ j ][ i ],  1 )  end  result = result .. result_line  end   return result end    function p.listToText( frame )  local args  local template = frame.args.template  if type( template ) == "string" then  template = mw.text.trim( template )  template = ( template == "1" )  end  if template then  args = frame:getParent().args  else  args = frame.args  end  return Text.listToText( args, frame.args.format ) end    function p.quote( frame )  local slang = frame.args[2]  if type( slang ) == "string" then  slang = mw.text.trim( slang )  if slang == "" then  slang = false  end  end  return Text.quote( frame.args[ 1 ] or "",  slang,  tonumber( frame.args[3] ) ) end    function p.quoteUnquoted( frame )  local slang = frame.args[2]  if type( slang ) == "string" then  slang = mw.text.trim( slang )  if slang == "" then  slang = false  end  end  return Text.quoteUnquoted( frame.args[ 1 ] or "",  slang,  tonumber( frame.args[3] ) ) end    function p.removeDiacritics( frame )  return Text.removeDiacritics( frame.args[ 1 ] or "" ) end  function p.sentenceTerminated( frame )  return Text.sentenceTerminated( frame.args[ 1 ] or "" ) and "1" or "" end  function p.tokenWords( frame )  return Text.tokenWords( frame.args[ 1 ] or "" ) end  function p.ucfirstAll( frame )  return Text.ucfirstAll( frame.args[ 1 ] or "" ) end  function p.unstrip( frame )  return mw.text.trim( mw.text.unstrip( frame.args[ 1 ] or "" ) ) end  function p.uprightNonlatin( frame )  return Text.uprightNonlatin( frame.args[ 1 ] or "" ) end    function p.zip(frame)  local lists = {}  local seps = {}  local defaultsep = frame.args["sep"] or ""  local innersep = frame.args["isep"] or ""  local outersep = frame.args["osep"] or ""   -- Parameter parsen  for k, v in pairs(frame.args) do  local knum = tonumber(k)  if knum then lists[knum] = v else  if string.sub(k, 1, 3) == "sep" then  local sepnum = tonumber(string.sub(k, 4))  if sepnum then seps[sepnum] = v end  end  end  end  -- sofern keine expliziten Separatoren angegeben sind, den Standardseparator verwenden  for i = 1, math.max(#seps, #lists) do  if not seps[i] then seps[i] = defaultsep end  end   -- Listen splitten  local maxListLen = 0  for i = 1, #lists do  lists[i] = mw.text.split(lists[i], seps[i])  if #lists[i] > maxListLen then maxListLen = #lists[i] end  end   local result = ""  for i = 1, maxListLen do  if i ~= 1 then result = result .. outersep end  for j = 1, #lists do  if j ~= 1 then result = result .. innersep end  result = result .. (lists[j][i] or "")  end  end  return result end    p.failsafe = function ( frame )  -- Versioning interface  local s = type( frame )  local since  if s == "table" then  since = frame.args[ 1 ]  elseif s == "string" then  since = frame  end  if since then  since = mw.text.trim( since )  if since == "" then  since = false  end  end  return Failsafe.failsafe( since ) or "" end -- p.failsafe()    p.Text = function ()  return Text end -- p.Text  setmetatable( p, { __call = function ( func, ... )  setmetatable( p, nil )  return Failsafe  end } )  return p