<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>http://159.13.49.45/index.php?action=history&amp;feed=atom&amp;title=Module%3AText</id>
	<title>Module:Text - Revision history</title>
	<link rel="self" type="application/atom+xml" href="http://159.13.49.45/index.php?action=history&amp;feed=atom&amp;title=Module%3AText"/>
	<link rel="alternate" type="text/html" href="http://159.13.49.45/index.php?title=Module:Text&amp;action=history"/>
	<updated>2026-04-03T22:54:12Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.0</generator>
	<entry>
		<id>http://159.13.49.45/index.php?title=Module:Text&amp;diff=439&amp;oldid=prev</id>
		<title>Nat: 1 revision imported</title>
		<link rel="alternate" type="text/html" href="http://159.13.49.45/index.php?title=Module:Text&amp;diff=439&amp;oldid=prev"/>
		<updated>2025-04-07T11:03:29Z</updated>

		<summary type="html">&lt;p&gt;1 revision imported&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 11:03, 7 April 2025&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-notice&quot; lang=&quot;en&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(No difference)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;</summary>
		<author><name>Nat</name></author>
	</entry>
	<entry>
		<id>http://159.13.49.45/index.php?title=Module:Text&amp;diff=438&amp;oldid=prev</id>
		<title>wikipedia&gt;Hike395: factor data out into Module:Text/data, loaded via mw.loadData</title>
		<link rel="alternate" type="text/html" href="http://159.13.49.45/index.php?title=Module:Text&amp;diff=438&amp;oldid=prev"/>
		<updated>2024-09-21T14:01:27Z</updated>

		<summary type="html">&lt;p&gt;factor data out into Module:Text/data, loaded via mw.loadData&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;local yesNo = require(&amp;quot;Module:Yesno&amp;quot;)&lt;br /&gt;
local Text = { serial = &amp;quot;2022-07-21&amp;quot;,&lt;br /&gt;
               suite  = &amp;quot;Text&amp;quot; }&lt;br /&gt;
--[=[&lt;br /&gt;
Text utilities&lt;br /&gt;
]=]&lt;br /&gt;
&lt;br /&gt;
local function fiatQuote( apply, alien, advance )&lt;br /&gt;
    -- Quote text&lt;br /&gt;
    -- Parameter:&lt;br /&gt;
    --     apply    -- string, with text&lt;br /&gt;
    --     alien    -- string, with language code&lt;br /&gt;
    --     advance  -- number, with level 1 or 2&lt;br /&gt;
    local r = apply and tostring(apply) or &amp;quot;&amp;quot;&lt;br /&gt;
    alien = alien or &amp;quot;en&amp;quot;&lt;br /&gt;
    advance = tonumber(advance) or 0&lt;br /&gt;
    local suite&lt;br /&gt;
    local data = mw.loadData(&amp;#039;Module:Text/data&amp;#039;)&lt;br /&gt;
    local QuoteLang = data.QuoteLang&lt;br /&gt;
    local QuoteType = data.QuoteType&lt;br /&gt;
    local slang = alien:match( &amp;quot;^(%l+)-&amp;quot; )&lt;br /&gt;
    suite = QuoteLang[alien] or slang and QuoteLang[slang] or QuoteLang[&amp;quot;en&amp;quot;]&lt;br /&gt;
    if suite then&lt;br /&gt;
        local quotes = QuoteType[ suite ]&lt;br /&gt;
        if quotes then&lt;br /&gt;
            local space&lt;br /&gt;
            if quotes[ 3 ] then&lt;br /&gt;
                space = &amp;quot;&amp;amp;#160;&amp;quot;&lt;br /&gt;
            else&lt;br /&gt;
                space = &amp;quot;&amp;quot;&lt;br /&gt;
            end&lt;br /&gt;
            quotes = quotes[ advance ]&lt;br /&gt;
            if quotes then&lt;br /&gt;
                r = mw.ustring.format( &amp;quot;%s%s%s%s%s&amp;quot;,&lt;br /&gt;
                                       mw.ustring.char( quotes[ 1 ] ),&lt;br /&gt;
                                       space,&lt;br /&gt;
                                       apply,&lt;br /&gt;
                                       space,&lt;br /&gt;
                                       mw.ustring.char( quotes[ 2 ] ) )&lt;br /&gt;
            end&lt;br /&gt;
        else&lt;br /&gt;
            mw.log( &amp;quot;fiatQuote() &amp;quot; .. suite )&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return r&lt;br /&gt;
end -- fiatQuote()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Text.char = function ( apply, again, accept )&lt;br /&gt;
    -- Create string from codepoints&lt;br /&gt;
    -- Parameter:&lt;br /&gt;
    --     apply   -- table (sequence) with numerical codepoints, or nil&lt;br /&gt;
    --     again   -- number of repetitions, or nil&lt;br /&gt;
    --     accept  -- true, if no error messages to be appended&lt;br /&gt;
    -- Returns: string&lt;br /&gt;
    local r = &amp;quot;&amp;quot;&lt;br /&gt;
    apply = type(apply) == &amp;quot;table&amp;quot; and apply or {}&lt;br /&gt;
    again = math.floor(tonumber(again) or 1)&lt;br /&gt;
    if again &amp;lt; 1 then&lt;br /&gt;
    	return &amp;quot;&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
    local bad   = { }&lt;br /&gt;
    local codes = { }&lt;br /&gt;
    for _, v in ipairs( apply ) do&lt;br /&gt;
    	local n = tonumber(v)&lt;br /&gt;
    	if not n or (n &amp;lt; 32 and n ~= 9 and n ~= 10) then&lt;br /&gt;
    		table.insert(bad, tostring(v))&lt;br /&gt;
    	else&lt;br /&gt;
    		table.insert(codes, math.floor(n))&lt;br /&gt;
		end&lt;br /&gt;
    end &lt;br /&gt;
    if #bad &amp;gt; 0 then&lt;br /&gt;
    	if not accept then&lt;br /&gt;
    		r = tostring(  mw.html.create( &amp;quot;span&amp;quot; )&lt;br /&gt;
                    		:addClass( &amp;quot;error&amp;quot; )&lt;br /&gt;
                    		:wikitext( &amp;quot;bad codepoints: &amp;quot; .. table.concat( bad, &amp;quot; &amp;quot; )) )&lt;br /&gt;
    	end&lt;br /&gt;
    	return r&lt;br /&gt;
    end&lt;br /&gt;
    if #codes &amp;gt; 0 then&lt;br /&gt;
    	r = mw.ustring.char( unpack( codes ) )&lt;br /&gt;
    	if again &amp;gt; 1 then&lt;br /&gt;
    		r = r:rep(again)&lt;br /&gt;
    	end&lt;br /&gt;
	end&lt;br /&gt;
    return r&lt;br /&gt;
end -- Text.char()&lt;br /&gt;
&lt;br /&gt;
local function trimAndFormat(args, fmt)&lt;br /&gt;
	local result = {}&lt;br /&gt;
	if type(args) ~= &amp;#039;table&amp;#039; then&lt;br /&gt;
		args = {args}&lt;br /&gt;
	end&lt;br /&gt;
	for _, v in ipairs(args) do&lt;br /&gt;
		v = mw.text.trim(tostring(v))&lt;br /&gt;
		if v ~= &amp;quot;&amp;quot; then&lt;br /&gt;
			table.insert(result,fmt and mw.ustring.format(fmt, v) or v)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return result&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
Text.concatParams = function ( args, apply, adapt )&lt;br /&gt;
    -- Concat list items into one string&lt;br /&gt;
    -- Parameter:&lt;br /&gt;
    --     args   -- table (sequence) with numKey=string&lt;br /&gt;
    --     apply  -- string (optional); separator (default: &amp;quot;|&amp;quot;)&lt;br /&gt;
    --     adapt  -- string (optional); format including &amp;quot;%s&amp;quot;&lt;br /&gt;
    -- Returns: string&lt;br /&gt;
    local collect = { }&lt;br /&gt;
    return table.concat(trimAndFormat(args,adapt), apply or &amp;quot;|&amp;quot;)&lt;br /&gt;
end -- Text.concatParams()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Text.containsCJK = function ( s )&lt;br /&gt;
    -- Is any CJK code within?&lt;br /&gt;
    -- Parameter:&lt;br /&gt;
    --     s  -- string&lt;br /&gt;
    -- Returns: true, if CJK detected&lt;br /&gt;
    s = s and tostring(s) or &amp;quot;&amp;quot;&lt;br /&gt;
    local patternCJK = mw.loadData(&amp;#039;Module:Text/data&amp;#039;).PatternCJK&lt;br /&gt;
    return mw.ustring.find( s, patternCJK ) ~= nil&lt;br /&gt;
end -- Text.containsCJK()&lt;br /&gt;
&lt;br /&gt;
Text.removeDelimited = function (s, prefix, suffix)&lt;br /&gt;
	-- Remove all text in s delimited by prefix and suffix (inclusive)&lt;br /&gt;
	-- Arguments:&lt;br /&gt;
	--    s = string to process&lt;br /&gt;
	--    prefix = initial delimiter&lt;br /&gt;
	--    suffix = ending delimiter&lt;br /&gt;
	-- Returns: stripped string&lt;br /&gt;
	s = s and tostring(s) or &amp;quot;&amp;quot;&lt;br /&gt;
	prefix = prefix and tostring(prefix) or &amp;quot;&amp;quot;&lt;br /&gt;
	suffix = suffix and tostring(suffix) or &amp;quot;&amp;quot;&lt;br /&gt;
	local prefixLen = mw.ustring.len(prefix)&lt;br /&gt;
	local suffixLen = mw.ustring.len(suffix)&lt;br /&gt;
	if prefixLen == 0 or suffixLen == 0 then&lt;br /&gt;
		return s&lt;br /&gt;
	end&lt;br /&gt;
	local i = s:find(prefix, 1, true)&lt;br /&gt;
	local r = s&lt;br /&gt;
	local j&lt;br /&gt;
	while i do&lt;br /&gt;
		j = r:find(suffix, i + prefixLen)&lt;br /&gt;
		if j then&lt;br /&gt;
			r = r:sub(1, i - 1)..r:sub(j+suffixLen)&lt;br /&gt;
		else&lt;br /&gt;
			r = r:sub(1, i - 1)&lt;br /&gt;
		end&lt;br /&gt;
		i = r:find(prefix, 1, true)&lt;br /&gt;
	end&lt;br /&gt;
	return r&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
Text.getPlain = function ( adjust )&lt;br /&gt;
    -- Remove wikisyntax from string, except templates&lt;br /&gt;
    -- Parameter:&lt;br /&gt;
    --     adjust  -- string&lt;br /&gt;
    -- Returns: string&lt;br /&gt;
    local r = Text.removeDelimited(adjust,&amp;quot;&amp;lt;!--&amp;quot;,&amp;quot;--&amp;gt;&amp;quot;)&lt;br /&gt;
    r = r:gsub( &amp;quot;(&amp;lt;/?%l[^&amp;gt;]*&amp;gt;)&amp;quot;, &amp;quot;&amp;quot; )&lt;br /&gt;
         :gsub( &amp;quot;&amp;#039;&amp;#039;&amp;#039;&amp;quot;, &amp;quot;&amp;quot; )&lt;br /&gt;
         :gsub( &amp;quot;&amp;#039;&amp;#039;&amp;quot;, &amp;quot;&amp;quot; )&lt;br /&gt;
         :gsub( &amp;quot;&amp;amp;nbsp;&amp;quot;, &amp;quot; &amp;quot; )&lt;br /&gt;
    return r&lt;br /&gt;
end -- Text.getPlain()&lt;br /&gt;
&lt;br /&gt;
Text.isLatinRange = function (s)&lt;br /&gt;
    -- Are characters expected to be latin or symbols within latin texts?&lt;br /&gt;
    -- Arguments:&lt;br /&gt;
    --  s = string to analyze&lt;br /&gt;
    -- Returns: true, if valid for latin only&lt;br /&gt;
    s = s and tostring(s) or &amp;quot;&amp;quot;  --- ensure input is always string&lt;br /&gt;
    local PatternLatin = mw.loadData(&amp;#039;Module:Text/data&amp;#039;).PatternLatin&lt;br /&gt;
    return mw.ustring.match(s, PatternLatin) ~= nil&lt;br /&gt;
end -- Text.isLatinRange()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Text.isQuote = function ( s )&lt;br /&gt;
    -- Is this character any quotation mark?&lt;br /&gt;
    -- Parameter:&lt;br /&gt;
    --     s = single character to analyze&lt;br /&gt;
    -- Returns: true, if s is quotation mark&lt;br /&gt;
    s = s and tostring(s) or &amp;quot;&amp;quot;&lt;br /&gt;
    if s == &amp;quot;&amp;quot; then&lt;br /&gt;
    	return false&lt;br /&gt;
    end&lt;br /&gt;
    local SeekQuote = mw.loadData(&amp;#039;Module:Text/data&amp;#039;).SeekQuote&lt;br /&gt;
    return mw.ustring.find( SeekQuote, s, 1, true ) ~= nil&lt;br /&gt;
end -- Text.isQuote()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Text.listToText = function ( args, adapt )&lt;br /&gt;
    -- Format list items similar to mw.text.listToText()&lt;br /&gt;
    -- Parameter:&lt;br /&gt;
    --     args   -- table (sequence) with numKey=string&lt;br /&gt;
    --     adapt  -- string (optional); format including &amp;quot;%s&amp;quot;&lt;br /&gt;
    -- Returns: string&lt;br /&gt;
    return mw.text.listToText(trimAndFormat(args, adapt))&lt;br /&gt;
end -- Text.listToText()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Text.quote = function ( apply, alien, advance )&lt;br /&gt;
    -- Quote text&lt;br /&gt;
    -- Parameter:&lt;br /&gt;
    --     apply    -- string, with text&lt;br /&gt;
    --     alien    -- string, with language code, or nil&lt;br /&gt;
    --     advance  -- number, with level 1 or 2, or nil&lt;br /&gt;
    -- Returns: quoted string&lt;br /&gt;
    apply = apply and tostring(apply) or &amp;quot;&amp;quot;&lt;br /&gt;
    local mode, slang&lt;br /&gt;
    if type( alien ) == &amp;quot;string&amp;quot; then&lt;br /&gt;
        slang = mw.text.trim( alien ):lower()&lt;br /&gt;
    else&lt;br /&gt;
        slang = mw.title.getCurrentTitle().pageLanguage&lt;br /&gt;
        if not slang then&lt;br /&gt;
            -- TODO FIXME: Introduction expected 2017-04&lt;br /&gt;
            slang = mw.language.getContentLanguage():getCode()&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    if advance == 2 then&lt;br /&gt;
        mode = 2&lt;br /&gt;
    else&lt;br /&gt;
        mode = 1&lt;br /&gt;
    end&lt;br /&gt;
    return fiatQuote( mw.text.trim( apply ), slang, mode )&lt;br /&gt;
end -- Text.quote()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Text.quoteUnquoted = function ( apply, alien, advance )&lt;br /&gt;
    -- Quote text, if not yet quoted and not empty&lt;br /&gt;
    -- Parameter:&lt;br /&gt;
    --     apply    -- string, with text&lt;br /&gt;
    --     alien    -- string, with language code, or nil&lt;br /&gt;
    --     advance  -- number, with level 1 or 2, or nil&lt;br /&gt;
    -- Returns: string; possibly quoted&lt;br /&gt;
    local r = mw.text.trim( apply and tostring(apply) or &amp;quot;&amp;quot; )&lt;br /&gt;
    local s = mw.ustring.sub( r, 1, 1 )&lt;br /&gt;
    if s ~= &amp;quot;&amp;quot;  and  not Text.isQuote( s, advance ) then&lt;br /&gt;
        s = mw.ustring.sub( r, -1, 1 )&lt;br /&gt;
        if not Text.isQuote( s ) then&lt;br /&gt;
            r = Text.quote( r, alien, advance )&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return r&lt;br /&gt;
end -- Text.quoteUnquoted()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Text.removeDiacritics = function ( adjust )&lt;br /&gt;
    -- Remove all diacritics&lt;br /&gt;
    -- Parameter:&lt;br /&gt;
    --     adjust  -- string&lt;br /&gt;
    -- Returns: string; all latin letters should be ASCII&lt;br /&gt;
    --                  or basic greek or cyrillic or symbols etc.&lt;br /&gt;
    local cleanup, decomposed&lt;br /&gt;
    local PatternCombined = mw.loadData(&amp;#039;Module:Text/data&amp;#039;).PatternCombined&lt;br /&gt;
    decomposed = mw.ustring.toNFD( adjust and tostring(adjust) or &amp;quot;&amp;quot; )&lt;br /&gt;
    cleanup    = mw.ustring.gsub( decomposed, PatternCombined, &amp;quot;&amp;quot; )&lt;br /&gt;
    return mw.ustring.toNFC( cleanup )&lt;br /&gt;
end -- Text.removeDiacritics()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Text.sentenceTerminated = function ( analyse )&lt;br /&gt;
    -- Is string terminated by dot, question or exclamation mark?&lt;br /&gt;
    --     Quotation, link termination and so on granted&lt;br /&gt;
    -- Parameter:&lt;br /&gt;
    --     analyse  -- string&lt;br /&gt;
    -- Returns: true, if sentence terminated&lt;br /&gt;
    local r&lt;br /&gt;
    local PatternTerminated = mw.loadData(&amp;#039;Module:Text/data&amp;#039;).PatternTerminated&lt;br /&gt;
    if mw.ustring.find( analyse, PatternTerminated ) then&lt;br /&gt;
        r = true&lt;br /&gt;
    else&lt;br /&gt;
        r = false&lt;br /&gt;
    end&lt;br /&gt;
    return r&lt;br /&gt;
end -- Text.sentenceTerminated()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Text.ucfirstAll = function ( adjust)&lt;br /&gt;
    -- Capitalize all words&lt;br /&gt;
    -- Arguments:&lt;br /&gt;
    --     adjust = string to adjust&lt;br /&gt;
    -- Returns: string with all first letters in upper case&lt;br /&gt;
    adjust = adjust and tostring(adjust) or &amp;quot;&amp;quot;&lt;br /&gt;
    local r = mw.text.decode(adjust,true)&lt;br /&gt;
    local i = 1&lt;br /&gt;
    local c, j, m&lt;br /&gt;
    m = (r ~= adjust)&lt;br /&gt;
    r = &amp;quot; &amp;quot;..r&lt;br /&gt;
    while i do&lt;br /&gt;
        i = mw.ustring.find( r, &amp;quot;%W%l&amp;quot;, i )&lt;br /&gt;
        if i then&lt;br /&gt;
            j = i + 1&lt;br /&gt;
            c = mw.ustring.upper( mw.ustring.sub( r, j, j ) )&lt;br /&gt;
            r = string.format( &amp;quot;%s%s%s&amp;quot;,&lt;br /&gt;
                               mw.ustring.sub( r, 1, i ),&lt;br /&gt;
                               c,&lt;br /&gt;
                               mw.ustring.sub( r, i + 2 ) )&lt;br /&gt;
            i = j&lt;br /&gt;
        end&lt;br /&gt;
    end -- while i&lt;br /&gt;
    r = r:sub( 2 )&lt;br /&gt;
    if m then&lt;br /&gt;
    	r = mw.text.encode(r)&lt;br /&gt;
    end&lt;br /&gt;
    return r&lt;br /&gt;
end -- Text.ucfirstAll()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Text.uprightNonlatin = function ( adjust )&lt;br /&gt;
    -- Ensure non-italics for non-latin text parts&lt;br /&gt;
    --     One single greek letter might be granted&lt;br /&gt;
    -- Precondition:&lt;br /&gt;
    --     adjust  -- string&lt;br /&gt;
    -- Returns: string with non-latin parts enclosed in &amp;lt;span&amp;gt;&lt;br /&gt;
    local r&lt;br /&gt;
    local data = mw.loadData(&amp;#039;Module:Text/data&amp;#039;)&lt;br /&gt;
    local PatternLatin = data.PatternLatin&lt;br /&gt;
    local RangesLatin = data.RangesLatin&lt;br /&gt;
    local NumLatinRanges = data.NumLatinRanges&lt;br /&gt;
    if mw.ustring.match( adjust, PatternLatin ) then&lt;br /&gt;
        -- latin only, horizontal dashes, quotes&lt;br /&gt;
        r = adjust&lt;br /&gt;
    else&lt;br /&gt;
        local c&lt;br /&gt;
        local j    = false&lt;br /&gt;
        local k    = 1&lt;br /&gt;
        local m    = false&lt;br /&gt;
        local n    = mw.ustring.len( adjust )&lt;br /&gt;
        local span = &amp;quot;%s%s&amp;lt;span dir=&amp;#039;auto&amp;#039; style=&amp;#039;font-style:normal&amp;#039;&amp;gt;%s&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
        local flat = function ( a )&lt;br /&gt;
                  -- isLatin&lt;br /&gt;
                  local range&lt;br /&gt;
                  -- NumLatinRanges has to be precomputed because # does not work from loadData&lt;br /&gt;
                  for i = 1, NumLatinRanges do&lt;br /&gt;
                      range = RangesLatin[ i ]&lt;br /&gt;
                      if a &amp;gt;= range[ 1 ]  and  a &amp;lt;= range[ 2 ] then&lt;br /&gt;
                          return true&lt;br /&gt;
                      end&lt;br /&gt;
                  end    -- for i&lt;br /&gt;
              end -- flat()&lt;br /&gt;
        local focus = function ( a )&lt;br /&gt;
                  -- char is not ambivalent&lt;br /&gt;
                  local r = ( a &amp;gt; 64 )&lt;br /&gt;
                  if r then&lt;br /&gt;
                      r = ( a &amp;lt; 8192  or  a &amp;gt; 8212 )&lt;br /&gt;
                  else&lt;br /&gt;
                      r = ( a == 38  or  a == 60 )    -- &amp;#039;&amp;amp;&amp;#039; &amp;#039;&amp;lt;&amp;#039;&lt;br /&gt;
                  end&lt;br /&gt;
                  return r&lt;br /&gt;
              end -- focus()&lt;br /&gt;
        local form = function ( a )&lt;br /&gt;
                return string.format( span,&lt;br /&gt;
                                      r,&lt;br /&gt;
                                      mw.ustring.sub( adjust, k, j - 1 ),&lt;br /&gt;
                                      mw.ustring.sub( adjust, j, a ) )&lt;br /&gt;
              end -- form()&lt;br /&gt;
        r = &amp;quot;&amp;quot;&lt;br /&gt;
        for i = 1, n do&lt;br /&gt;
            c = mw.ustring.codepoint( adjust, i, i )&lt;br /&gt;
            if focus( c ) then&lt;br /&gt;
                if flat( c ) then&lt;br /&gt;
                    if j then&lt;br /&gt;
                        if m then&lt;br /&gt;
                            if i == m then&lt;br /&gt;
                                -- single greek letter.&lt;br /&gt;
                                j = false&lt;br /&gt;
                            end&lt;br /&gt;
                            m = false&lt;br /&gt;
                        end&lt;br /&gt;
                        if j then&lt;br /&gt;
                            local nx = i - 1&lt;br /&gt;
                            local s  = &amp;quot;&amp;quot;&lt;br /&gt;
                            for ix = nx, 1, -1 do&lt;br /&gt;
                                c = mw.ustring.sub( adjust, ix, ix )&lt;br /&gt;
                                if c == &amp;quot; &amp;quot;  or  c == &amp;quot;(&amp;quot; then&lt;br /&gt;
                                    nx = nx - 1&lt;br /&gt;
                                    s  = c .. s&lt;br /&gt;
                                else&lt;br /&gt;
                                    break -- for ix&lt;br /&gt;
                                end&lt;br /&gt;
                            end -- for ix&lt;br /&gt;
                            r = form( nx ) .. s&lt;br /&gt;
                            j = false&lt;br /&gt;
                            k = i&lt;br /&gt;
                        end&lt;br /&gt;
                    end&lt;br /&gt;
                elseif not j then&lt;br /&gt;
                    j = i&lt;br /&gt;
                    if c &amp;gt;= 880  and  c &amp;lt;= 1023 then&lt;br /&gt;
                        -- single greek letter?&lt;br /&gt;
                        m = i + 1&lt;br /&gt;
                    else&lt;br /&gt;
                        m = false&lt;br /&gt;
                    end&lt;br /&gt;
                end&lt;br /&gt;
            elseif m then&lt;br /&gt;
                m = m + 1&lt;br /&gt;
            end&lt;br /&gt;
        end    -- for i&lt;br /&gt;
        if j  and  ( not m  or  m &amp;lt; n ) then&lt;br /&gt;
            r = form( n )&lt;br /&gt;
        else&lt;br /&gt;
            r = r .. mw.ustring.sub( adjust, k )&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return r&lt;br /&gt;
end -- Text.uprightNonlatin()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Text.test = function ( about )&lt;br /&gt;
    local r&lt;br /&gt;
    if about == &amp;quot;quote&amp;quot; then&lt;br /&gt;
        data = mw.loadData(&amp;#039;Module:Text/data&amp;#039;)&lt;br /&gt;
        r = { }&lt;br /&gt;
        r.QuoteLang = data.QuoteLang&lt;br /&gt;
        r.QuoteType = data.QuoteType&lt;br /&gt;
    end&lt;br /&gt;
    return r&lt;br /&gt;
end -- Text.test()&lt;br /&gt;
&lt;br /&gt;
-- Non Unicode-aware version of mw.text.split and mw.text.gsplit&lt;br /&gt;
-- based on [[phab:diffusion/ELUA/browse/master/includes/Engines/LuaCommon/lualib/mw.text.lua]]&lt;br /&gt;
-- These run up to 60 times faster than the Unicode-aware versions&lt;br /&gt;
Text.split = function ( text, pattern, plain )&lt;br /&gt;
	local ret = {}&lt;br /&gt;
	for m in Text.gsplit( text, pattern, plain ) do&lt;br /&gt;
		ret[#ret+1] = m&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
Text.gsplit = function ( text, pattern, plain )&lt;br /&gt;
	local s, l = 1, string.len( text )&lt;br /&gt;
	return function ()&lt;br /&gt;
		if s then&lt;br /&gt;
			local e, n = string.find( text, pattern, s, plain )&lt;br /&gt;
			local ret&lt;br /&gt;
			if not e then&lt;br /&gt;
				ret = string.sub( text, s )&lt;br /&gt;
				s = nil&lt;br /&gt;
			elseif n &amp;lt; e then&lt;br /&gt;
				-- Empty separator!&lt;br /&gt;
				ret = string.sub( text, s, e )&lt;br /&gt;
				if e &amp;lt; l then&lt;br /&gt;
					s = e + 1&lt;br /&gt;
				else&lt;br /&gt;
					s = nil&lt;br /&gt;
				end&lt;br /&gt;
			else&lt;br /&gt;
				ret = e &amp;gt; s and string.sub( text, s, e - 1 ) or &amp;#039;&amp;#039;&lt;br /&gt;
				s = n + 1&lt;br /&gt;
			end&lt;br /&gt;
			return ret&lt;br /&gt;
		end&lt;br /&gt;
	end, nil, nil&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Export&lt;br /&gt;
local p = { }&lt;br /&gt;
&lt;br /&gt;
for _, func in ipairs({&amp;#039;containsCJK&amp;#039;,&amp;#039;isLatinRange&amp;#039;,&amp;#039;isQuote&amp;#039;,&amp;#039;sentenceTerminated&amp;#039;}) do&lt;br /&gt;
	p[func] = function (frame) &lt;br /&gt;
		return Text[func]( frame.args[ 1 ] or &amp;quot;&amp;quot; ) and &amp;quot;1&amp;quot; or &amp;quot;&amp;quot;&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
for _, func in ipairs({&amp;#039;getPlain&amp;#039;,&amp;#039;removeDiacritics&amp;#039;,&amp;#039;ucfirstAll&amp;#039;,&amp;#039;uprightNonlatin&amp;#039;}) do&lt;br /&gt;
	p[func] = function (frame) &lt;br /&gt;
		return Text[func]( frame.args[ 1 ] or &amp;quot;&amp;quot; )&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.char( frame )&lt;br /&gt;
    local params = frame:getParent().args&lt;br /&gt;
    local story = params[ 1 ]&lt;br /&gt;
    local codes, lenient, multiple&lt;br /&gt;
    if not story then&lt;br /&gt;
        params = frame.args&lt;br /&gt;
        story  = params[ 1 ]&lt;br /&gt;
    end&lt;br /&gt;
    if story then&lt;br /&gt;
        local items = mw.text.split( mw.text.trim(story), &amp;quot;%s+&amp;quot; )&lt;br /&gt;
        if #items &amp;gt; 0 then&lt;br /&gt;
            local j&lt;br /&gt;
            lenient  = (yesNo(params.errors) == false)&lt;br /&gt;
            codes    = { }&lt;br /&gt;
            multiple = tonumber( params[ &amp;quot;*&amp;quot; ] )&lt;br /&gt;
            for _, v in ipairs( items ) do&lt;br /&gt;
            	j = tonumber((v:sub( 1, 1 ) == &amp;quot;x&amp;quot; and &amp;quot;0&amp;quot; or &amp;quot;&amp;quot;) .. v)&lt;br /&gt;
                table.insert( codes,  j or v )&lt;br /&gt;
            end &lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return Text.char( codes, multiple, lenient )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.concatParams( frame )&lt;br /&gt;
    local args&lt;br /&gt;
    local template = frame.args.template&lt;br /&gt;
    if type( template ) == &amp;quot;string&amp;quot; then&lt;br /&gt;
        template = mw.text.trim( template )&lt;br /&gt;
        template = ( template == &amp;quot;1&amp;quot; )&lt;br /&gt;
    end&lt;br /&gt;
    if template then&lt;br /&gt;
        args = frame:getParent().args&lt;br /&gt;
    else&lt;br /&gt;
        args = frame.args&lt;br /&gt;
    end&lt;br /&gt;
    return Text.concatParams( args,&lt;br /&gt;
                              frame.args.separator,&lt;br /&gt;
                              frame.args.format )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function p.listToFormat(frame)&lt;br /&gt;
    local lists = {}&lt;br /&gt;
    local pformat = frame.args[&amp;quot;format&amp;quot;]&lt;br /&gt;
    local sep = frame.args[&amp;quot;sep&amp;quot;] or &amp;quot;;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    -- Parameter parsen: Listen&lt;br /&gt;
    for k, v in pairs(frame.args) do&lt;br /&gt;
        local knum = tonumber(k)&lt;br /&gt;
        if knum then lists[knum] = v end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- Listen splitten&lt;br /&gt;
    local maxListLen = 0&lt;br /&gt;
    for i = 1, #lists do&lt;br /&gt;
        lists[i] = mw.text.split(lists[i], sep)&lt;br /&gt;
        if #lists[i] &amp;gt; maxListLen then maxListLen = #lists[i] end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- Ergebnisstring generieren&lt;br /&gt;
    local result = &amp;quot;&amp;quot;&lt;br /&gt;
    local result_line = &amp;quot;&amp;quot;&lt;br /&gt;
    for i = 1, maxListLen do&lt;br /&gt;
        result_line = pformat&lt;br /&gt;
        for j = 1, #lists do&lt;br /&gt;
            result_line = mw.ustring.gsub(result_line, &amp;quot;%%s&amp;quot;, lists[j][i], 1)&lt;br /&gt;
        end&lt;br /&gt;
        result = result .. result_line&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return result&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function p.listToText( frame )&lt;br /&gt;
    local args&lt;br /&gt;
    local template = frame.args.template&lt;br /&gt;
    if type( template ) == &amp;quot;string&amp;quot; then&lt;br /&gt;
        template = mw.text.trim( template )&lt;br /&gt;
        template = ( template == &amp;quot;1&amp;quot; )&lt;br /&gt;
    end&lt;br /&gt;
    if template then&lt;br /&gt;
        args = frame:getParent().args&lt;br /&gt;
    else&lt;br /&gt;
        args = frame.args&lt;br /&gt;
    end&lt;br /&gt;
    return Text.listToText( args, frame.args.format )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function p.quote( frame )&lt;br /&gt;
    local slang = frame.args[2]&lt;br /&gt;
    if type( slang ) == &amp;quot;string&amp;quot; then&lt;br /&gt;
        slang = mw.text.trim( slang )&lt;br /&gt;
        if slang == &amp;quot;&amp;quot; then&lt;br /&gt;
            slang = false&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return Text.quote( frame.args[ 1 ] or &amp;quot;&amp;quot;,&lt;br /&gt;
                       slang,&lt;br /&gt;
                       tonumber( frame.args[3] ) )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function p.quoteUnquoted( frame )&lt;br /&gt;
    local slang = frame.args[2]&lt;br /&gt;
    if type( slang ) == &amp;quot;string&amp;quot; then&lt;br /&gt;
        slang = mw.text.trim( slang )&lt;br /&gt;
        if slang == &amp;quot;&amp;quot; then&lt;br /&gt;
            slang = false&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return Text.quoteUnquoted( frame.args[ 1 ] or &amp;quot;&amp;quot;,&lt;br /&gt;
                               slang,&lt;br /&gt;
                               tonumber( frame.args[3] ) )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function p.zip(frame)&lt;br /&gt;
    local lists = {}&lt;br /&gt;
    local seps = {}&lt;br /&gt;
    local defaultsep = frame.args[&amp;quot;sep&amp;quot;] or &amp;quot;&amp;quot;&lt;br /&gt;
    local innersep = frame.args[&amp;quot;isep&amp;quot;] or &amp;quot;&amp;quot;&lt;br /&gt;
    local outersep = frame.args[&amp;quot;osep&amp;quot;] or &amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    -- Parameter parsen&lt;br /&gt;
    for k, v in pairs(frame.args) do&lt;br /&gt;
        local knum = tonumber(k)&lt;br /&gt;
        if knum then lists[knum] = v else&lt;br /&gt;
            if string.sub(k, 1, 3) == &amp;quot;sep&amp;quot; then&lt;br /&gt;
                local sepnum = tonumber(string.sub(k, 4))&lt;br /&gt;
                if sepnum then seps[sepnum] = v end&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    -- sofern keine expliziten Separatoren angegeben sind, den Standardseparator verwenden&lt;br /&gt;
    for i = 1, math.max(#seps, #lists) do&lt;br /&gt;
        if not seps[i] then seps[i] = defaultsep end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- Listen splitten&lt;br /&gt;
    local maxListLen = 0&lt;br /&gt;
    for i = 1, #lists do&lt;br /&gt;
        lists[i] = mw.text.split(lists[i], seps[i])&lt;br /&gt;
        if #lists[i] &amp;gt; maxListLen then maxListLen = #lists[i] end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local result = &amp;quot;&amp;quot;&lt;br /&gt;
    for i = 1, maxListLen do&lt;br /&gt;
        if i ~= 1 then result = result .. outersep end&lt;br /&gt;
        for j = 1, #lists do&lt;br /&gt;
            if j ~= 1 then result = result .. innersep end&lt;br /&gt;
            result = result .. (lists[j][i] or &amp;quot;&amp;quot;)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return result&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function p.split(frame)&lt;br /&gt;
	local text = frame.args.text or frame.args[1] or &amp;#039;&amp;#039;&lt;br /&gt;
	local pattern = frame.args.pattern or frame.args[2] or &amp;#039;&amp;#039;&lt;br /&gt;
	local plain = yesNo(frame.args.plain or frame.args[3])&lt;br /&gt;
	local index = tonumber(frame.args.index) or tonumber(frame.args[4]) or 1&lt;br /&gt;
	local a = Text.split(text, pattern, plain)&lt;br /&gt;
	if index &amp;lt; 0 then index = #a + index + 1 end&lt;br /&gt;
	return a[index]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function p.failsafe()&lt;br /&gt;
    return Text.serial&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
p.Text = function ()&lt;br /&gt;
    return Text&lt;br /&gt;
end -- p.Text&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>wikipedia&gt;Hike395</name></author>
	</entry>
</feed>