Module:D'ni Tools

From Guild of Archivists

Documentation for this module may be created at Module:D'ni Tools/doc

--
-- This implements several useful functions for dealing with D'ni text in the Wiki.
--
-- parsed_dni() returns a string in which every component is linked to its appropriate Dictionary namespace entry.
-- dnifont2ots() converts a Dnifont string to an ots one
-- dnifont2nts() converts a Dnifont string to an nts one

local p = {}

local args = {}
local origArgs
local root

local output = ''

-- Local Functions

local function num2dnum(str,sep)
        str = str or ''

	str = mw.text.trim(str)
	
	if (sep == nil or sep == '') then
		sep = "|"
	end
	
	local output = "nil"
	local num = tonumber(str)
	
	if (num ~= nil and num >= 0) then
		output = num % 25
		while (num >= 25) do
			num = math.floor(num / 25)
			output = tostring(num % 25)..sep..output
		end
	end 
	
	return output
	
end

local function dnum2num(str,sep)
	
	  str = str or ''
	  sep = sep or ''
	
	  local output = mw.text.trim(str)
	
	  output = mw.ustring.gsub(output,"%d%d",  {["24"] = "O", 
                                 ["23"] = "N", 
                                 ["22"] = "M", 
                                 ["21"] = "L", 
                                 ["20"] = "K", 
                                 ["19"] = "J", 
                                 ["18"] = "I", 
                                 ["17"] = "H",
                                 ["16"] = "G",
                                 ["15"] = "F",
                                 ["14"] = "E",
                                 ["13"] = "D",
                                 ["12"] = "C",
                                 ["11"] = "B",
                                 ["10"] = "A"
                                })
                                
    output = mw.ustring.gsub(output,sep,"") 
    
    output = tonumber(output,25)
    
    return output
                              
end

local function dnum2dnifont(str,min,use25,useWrap)

    str = str or ""
    min = min or 0
    use25 = use25 or false
    useWarp = useWrap or false

    local output = mw.text.trim(str)
    
    if str == "25" and use25 then output = "|"
    elseif str == "0" and useWrap then output = "="
    else 
       output = mw.ustring.gsub(output,"%d%d",  {["24"] = "}", 
                                 ["23"] = "{", 
                                 ["22"] = "\\", 
                                 ["21"] = "]", 
                                 ["20"] = "[", 
                                 ["19"] = "(", 
                                 ["18"] = "*", 
                                 ["17"] = "&",
                                 ["16"] = "^",
                                 ["15"] = "%",
                                 ["14"] = "$",
                                 ["13"] = "#",
                                 ["12"] = "@",
                                 ["11"] = "!",
                                 ["10"] = ")"
                                })

       output = mw.ustring.gsub(output,"%|","")
       if #output < min then output = string.rep("0", (min - #output))..output end
    end

    return output
	
	
end

local function dnifont2dnum(str,sep)

    str = mw.text.trim(str)
    
    local chars = mw.text.split(str,'')
    
    local output = table.concat(chars,sep)
    
    
    output = mw.ustring.gsub(output,"%S",  {["}"] = "24" , 
                                 ["{"] = "23", 
                                 ["\\"] = "22", 
                                 ["]"] = "21", 
                                 ["["] = "20", 
                                 ["("] = "19", 
                                 ["*"] = "18", 
                                 ["&"] = "17",
                                 ["^"] = "16",
                                 ["%"] = "15",
                                 ["$"] = "14",
                                 ["#"] = "13",
                                 ["@"] = "12",
                                 ["!"] = "11",
                                 [")"] = "10"
                                })

    return output
	
end

local function dnifont2ots(str)

    local output = mw.text.trim(str)
    
    output = mw.ustring.gsub(str,"%S",  {["S"] = "sh", 
                                 ["T"] = "th", 
                                 ["O"] = "oy", 
                                 ["c"] = "ch", 
                                 ["a"] = "ah", 
                                 ["E"] = "ee", 
                                 ["A"] = "ay", 
                                 ["u"] = "uh",
                                 ["U"] = "oo",
                                 ["x"] = "ts",
                                 ["d"] = "dh",
                                 ["D"] = "d",
                                 ["k"] = "kh",
                                 ["K"] = "k",
                                 ["I"] = "ai",
                                 ["å"] = "a",
                                })

     return output
end
 
local function dnifont2nts(str)

    local output = mw.text.trim(str)
    
    output = mw.ustring.gsub(str,"%S",  {["S"] = "š", 
                                 ["T"] = "þ", 
                                 ["O"] = "ó", 
                                 ["c"] = "ç", 
                                 ["E"] = "í", 
                                 ["A"] = "é", 
                                 ["U"] = "ú",
                                 ["x"] = "c",
                                 ["d"] = "ð",
                                 ["D"] = "d",
                                 ["k"] = "x",
                                 ["K"] = "k",
                                 ["I"] = "á",
                                 ["å"] = "æ",
                                })

     return output
end



local function parseDniWord(input,count)

    local output 

    local name = 'quote'..count

    local word = mw.text.trim(input)
    local first = mw.ustring.sub(word,1,1)
    local last = mw.ustring.sub(word,-1,-1)
    local prefix = ''
    local suffix = ''

    if (word == mw.ustring.lower(mw.title.getCurrentTitle().rootText)) then
         prefix = '\'\'\''
         suffix = prefix
    end 


    if (word == '') then
        output = ' '
    elseif (word == '&nbsp;') then
        output = '&nbsp;'
    elseif (word == '.' or word == '?' or word == '!' or word == ',') then
        output = first
    elseif (first == '-') then
        output = prefix..'[[Dictionary:'..word..'|'..mw.ustring.sub(word,2,-1)..']]'..suffix
        mw.smw.subobject('ContainsTerm=Dictionary:'..word,name)
    elseif (last == '-') then
        output = prefix..'[[Dictionary:'..word..'|'..mw.ustring.sub(word,1,-2)..']]'..suffix
        mw.smw.subobject('ContainsTerm=Dictionary:'..word,name)
    elseif (first == '.' or first == '!' or first == '?' or first == ',') then
        output = first..prefix..'[[Dictionary:'..mw.ustring.sub(word,2,-1)..'|'..mw.ustring.sub(word,2,-1)..']]'..suffix
        mw.smw.subobject('ContainsTerm=Dictionary:'..mw.ustring.sub(word,1,-2),name)
    elseif (last == ',') then
        output = prefix..'[[Dictionary:'..mw.ustring.sub(word,1,-2)..'|'..mw.ustring.sub(word,1,-2)..']]'..suffix..last
        mw.smw.subobject('ContainsTerm=Dictionary:'..mw.ustring.sub(word,1,-2),name)
    else
        output = prefix..'[[Dictionary:'..word..'|'..word..']]'..suffix
        mw.smw.subobject('ContainsTerm=Dictionary:'..word,name)
    end


    return output
end

local function preprocessSingleArg(argName)
    -- If the argument exists and isn't blank, add it to the argument table.
    -- Blank arguments are treated as nil to match the behaviour of ParserFunctions.
    if origArgs[argName] and origArgs[argName] ~= '' then
        args[argName] = origArgs[argName]
    end
end

function p.parsed_dni(frame)
    -- If called via #invoke, use the args passed into the invoking template.
    -- Otherwise, for testing purposes, assume args are being passed directly in.
    if frame == mw.getCurrentFrame() then
        origArgs = frame:getParent().args
    else
        origArgs = frame.args
    end

    count=0
    if (frame:callParserFunction('#varexists:count') ~= '1') then
        frame:callParserFunction('#vardefine:count','0')
    else
        count = tonumber(frame:callParserFunction('#var:count'))
        count = count + 1
        frame:callParserFunction('#vardefine:count',count)
    end

    for word in ipairs(origArgs) do
        output = output..parseDniWord(origArgs[word],count)
    end
    name='quote'..count
    quote=string.gsub(output,'%|','{{!}}')
--    quote=mw.text.nowiki(output)
    mw.smw.subobject('ContainsQuote='..quote,name)

    return output
end

-- For call by other Modules
function p._num2dnum(str,sep)
   return num2dnum(str,sep)
end

function p._dnum2num(str,sep)
   return dnum2num(str,sep)
end

function p._dnum2dnifont(str,min,use25,useWrap)
   return dnum2dnifont(str,min,use25,useWrap)
end

function p._dnifont2dnum(str,sep)
   return dnifont2dnum(str,sep)
end

function p._num2dnifont(str,min,use25,useWrap)
   return dnum2dnifont(num2dnum(str),min,use25,useWrap)

end

function p.dnifont2ots(frame)

    return dnifont2ots(frame.args[1])
end

function p.dnifont2nts(frame)

    return dnifont2nts(frame.args[1])
end

function p.num2dnum(frame)

    -- If called via #invoke, use the args passed into the invoking template.
    -- Otherwise, for testing purposes, assume args are being passed directly in.
    if frame == mw.getCurrentFrame() then
        origArgs = frame:getParent().args
    else
        origArgs = frame.args
    end

    preprocessSingleArg(1)
    preprocessSingleArg('val')
    preprocessSingleArg('format')
    preprocessSingleArg('sep')

    local output 
	

    local val = args['val'] or args[1]
	
	if (args['format'] == 'dnifont') then
		output = dnum2dnifont(num2dnum(val))
	else
		output = num2dnum(val,args['sep'])
		
	end
	
    return output
end

function p.dnifont2dnum(frame)

    -- If called via #invoke, use the args passed into the invoking template.
    -- Otherwise, for testing purposes, assume args are being passed directly in.
    if frame == mw.getCurrentFrame() then
        origArgs = frame:getParent().args
    else
        origArgs = frame.args
    end

    preprocessSingleArg(1)
    preprocessSingleArg('sep')

	return dnifont2dnum(args[1],args['sep'])
end

function p.dnum2num(frame)

    -- If called via #invoke, use the args passed into the invoking template.
    -- Otherwise, for testing purposes, assume args are being passed directly in.
    if frame == mw.getCurrentFrame() then
        origArgs = frame:getParent().args
    else
        origArgs = frame.args
    end

    preprocessSingleArg(1)
    preprocessSingleArg('sep')

	return dnum2num(args[1],args['sep'])
end

return p