Module:Icons

From Coral Island Wiki
Jump to navigation Jump to search

Documentation for this module may be created at Module:Icons/doc

local p = {}

local iconData = mw.loadData('Module:Icons/data')
local iconConfig = require('Module:Icons/config')

--[[
	Does both checks as a function rather than writing longform each time and
	also checks a table value's existence
]]
--% Completes a null or empty check on a variable. 
local function exists(object, child)
	if object ~= nil and object ~= '' then
		if child ~= nil then
			if object[child] ~= nil and object[child] ~= '' then
				return true
			else
				return false
			end
		else
			return true
		end
	else
		return false
	end
end

--[[
	If we don't trim spaces shortcode checks will fail, copied from 
	http://lua-users.org/wiki/StringTrim
]]
--% Trims whitespace from a string
local function trim(s)
   return s:match'^()%s*$' and '' or s:match'^%s*(.*%S)'
end

--Default settings
local semanticWiki = false -- Module control
local semanticPlatforms = true -- Function platforms()
local platformMaintenanceEnabled = true
local platformMaintenanceCategory = 'Platforms needed'
local docTableClasses = 'article-table'
local iconSizeDefault = 'x14px'
local falloverIcon = 'Icon question.png'
local maintenanceCategoryEnabled = false
local maintenanceCategory = 'Template with invalid icons'
local iconFrameClass = 'dev-icon-frame'
local imageClassList = {
	['light'] = 'dev-icon-light',
	['dark'] = 'dev-icon-dark',
	['general'] = 'dev-icon-general'
}
local sizeList = {
    ["small"]           = "x10px",
    ["medium"]          = "x14px",
    ["normal"]          = "x14px",
    ["big"]             = "x20px",
}

--Start checking for wiki defined settings and replace the defaults

--Any settings in here only need checking if wiki is semantic enabled.
if exists(iconConfig, 'semanticWiki') then
	semanticWiki = iconConfig.semanticWiki
	if exists(iconConfig, 'semanticPlatforms') then
		semanticPlatforms = iconConfig.semanticPlatforms
	end
end

--For documentation()
if exists(iconConfig, 'docTableClasses') then
	docTableClasses = iconConfig.docTableClasses
end

--Default icon size if not passed through in function calls
if exists(iconConfig, 'iconSizeDefault') then
	iconSizeDefault = iconConfig.iconSizeDefault
end

--[[ Added 
	Class control table to handle light/dark themes. This was originally put 
	into the frontend template, when class handling should be back end. 
	Adding the ['class'] = 'light' or ['class'] = 'dark' parameter to a icon's
	dataset on Module:Icons/data will enable it to access a class if needed.
]]

if exists(iconConfig, 'imageClassList') then
	imageClassList = iconConfig.imageClassList
end

--If the icon is invalid, use this image for the icon
if exists(iconConfig, 'falloverIcon') then
	falloverIcon = iconConfig.falloverIcon
end

if exists(iconConfig, 'maintenanceCategoryEnabled') then
	maintenanceCategory = iconConfig.maintenanceCategoryEnabled
end

-- If we don't want a maintenance category we don't need to set this
if maintenanceCategoryEnabled then
	if exists(iconConfig, 'maintenanceCategory') then
		maintenanceCategory = iconConfig.maintenanceCategory
	end
end

if exists(iconConfig, 'platformMaintenanceEnabled') then
	maintenanceCategory = iconConfig.platformMaintenanceEnabled
end

if platformMaintenance then
	if exists(iconConfig, 'platformMaintenanceCategory') then 
		platformMaintenanceCategory = iconConfig['platformMaintenanceCategory']
	end
end
	

--[[
	Shared function for generating icons, this is used to by p.icons (invoke) 
	and p.moduleIcons (require/mw.load)
]]
local function _generateIcons(iconList, iconSetting, iconLinks, tipOverride, 
		iconCustomClass, iconSize, series)
    if exists(iconSetting) then 
		iconSetting = trim(iconSetting)
        if exists(iconSize, iconSetting) then
            iconSetting = iconSize[iconSetting]
        end
    else
        iconSetting = iconSizeDefault
    end
    -- This is for calls from other Lua modules as the above will result in nil
    if not exists(iconSetting) then
    	if exists(iconSize) then
			iconSetting = iconSize
		else
			iconSetting = iconSizeDefault
		end
    end
    
    if exists(iconLinks) then
        iconLinks = mw.text.split(iconLinks, ",")
    end
        
    if exists(tipOverride) then
        tipOverride = mw.text.split(tipOverride, ",")
    end
    
    if exists(iconCustomClass)then
    	iconCustomClass = '|class=' .. tostring(iconCustomClass);
    else
    	iconCustomClass = ''
    end

    local result = ''

    for k, v in ipairs(iconList) do
        local newIcon = iconData[trim(v)]
        local currentIcon
        local currentTip
        if exists(newIcon) and (newIcon[series] or not series) then
            currentIcon = newIcon.icon
            if exists(tipOverride, k) then
                currentTip = tipOverride[k]
            else
                if exists(iconLinks, k) then
                    currentTip = iconLinks[k]
                else
                    currentTip = newIcon.tip
                end
            end
        else
            currentIcon = falloverIcon
            currentTip = "Unrecognized icon name"
            if maintenanceCategoryEnabled then
            	result = result .. '[[Category:'.. maintenanceCategory .. ']]'
            end
        end
        
        --Create wikitext icon
		local dataLine = '[[File:' .. currentIcon .. '|' .. iconSetting 
			.. '|link='
        if exists(iconLinks, k) then
             dataLine = dataLine .. iconLinks[k]
        else
        	if exists(newIcon, Link) then
        		dataLine= dataLine .. newIcon.link
        	end
        end
        if currentTip ~= nil then
            dataLine = dataLine .. '|' .. currentTip
        end

        dataLine = dataLine .. iconCustomClass .. ']]'

		local createTip = mw.html.create('span')
        	createTip:addClass(iconFrameClass)
        	:attr('title', currentTip)
        	:wikitext(dataLine)
        result = result .. tostring(createTip)
        
        if k < #iconList then
        	result = result .. " "
        end
    end
    
    return result
end

--% Call for other modules to create standarised icons
function p.moduleIcons(iconList, iconSetting, iconLinks, tipOverride,
						iconClass, iconSize, series)
	iconList = mw.text.split(iconList, ',')
	if iconData and iconConfig then
		return _generateIcons(iconList, iconSetting, iconLinks, tipOverride, 
							iconClass, iconSize, series)
	elseif iconData then
		return '<span style="color: red; background: grey">' ..
			'[[Module:Icons/config]] requires configuration.</span>'
	elseif iconConfig then
		return '<span style="color: red; background: grey">' ..
			'[[Module:Icons/data]] requires configuration.</span>'
	else
		return '<span style="color: red; background: grey">' ..
			'[[Module:Icons/config]] and [[Module:Icons/data]]' ..
			'requires configuration.</span>'
	end
end

--% Creates a string icons of consistent size within a span wrapper
--@ iconList (string) The icon short codes to process, each must be split with a comma
--@ iconSetting (string)[opt] A text value of size that is checked to return an actual size
--@ iconLinks (string)[opt] A list of articles for the icons to link to, each is split by a comma and maps exactly to iconList
--@ tipOverride [opt] (string) A list of tooltip text to replace the icon defaults, maps exactly to iconList
--@ iconClass [opt] (string) Any additional CSS classes to be assigned to icons
--@ iconSize [opt] (string) Takes a single defined size and sets it against the icons. Overrides iconSetting
--@ series [opt] (string) Only renders an icon if not set or the icon has the series parameter set
function p.Icons(frame) 
	--[[All icons are now lower case to reduce script errors from 
	incorrectly entering the icon code in a different case to the list]]
	if iconData and iconConfig then
    	local args = require('Dev:Arguments').getArgs(frame)
    	local iconList = mw.text.split(string.lower(args[1]), ',')
    	local iconSetting = args['setting']
    	local iconLinks = args['links']
    	local tipOverride = args['tooltips']
    	local iconClass = args['class']
    	local iconSize = args['size'] or sizeList
    	local series =  args['series']

    	return _generateIcons(iconList, iconSetting, iconLinks, tipOverride, 
    		iconClass, iconSize, series)    
    elseif iconData then
		return '<span style="color: red; background: grey">' ..
			'[[Module:Icons/config]] requires configuration.</span>'
	elseif iconConfig then
		return '<span style="color: red; background: grey">' ..
			'[[Module:Icons/data]] requires configuration.</span>'
	else
		return '<span style="color: red; background: grey">' ..
			'[[Module:Icons/config]] and [[Module:Icons/data]]' ..
			'requires configuration.</span>'
	end
end

--% Creates a list of valid game platforms. 
-- If the wiki has Semantic Mediawiki installed, this can also assign a property
-- (<nowiki>[[Has platforms::]]</nowiki>) to the icons.
--@ 1 (string) A string of game short codes, each split by a comma.

function p.platforms(frame)
	--[[All icons are now lower case to reduce script errors from 
	incorrectly entering the icon code in a different case to the list]]
    local args = require('Dev:Arguments').getArgs(frame)
    local icons = args[1]
    local result = ''
	if icons then
		icons = mw.text.split(string.lower(icons), ',')
    	for k, v in ipairs(icons) do
        	local currentIcon = iconData[trim(v)]

	        if exists(currentIcon, 'platform') then
    	    	--Only required on semantic enabled wikis 
        	    local createSM
        		if semanticWiki and semanticPlatforms then
			    	createSM = mw.html.create('span')
					createSM:css('display', 'none')
					    :wikitext('[[Has platform::' .. currentIcon.tip .. ']]')
    	        else
        	        createSM = ''
            	end

	            local createPlatform = mw.html.create('span')
    	        	createPlatform:addClass(iconFrameClass)
        	    		:attr('title', currentIcon.tip)
            			:wikitext('[[File:' 
            				.. currentIcon.icon 
            				.. '|alt='
            				.. currentIcon.tip
            				.. '|x14px|link=]]')
	            		:allDone()
    	        	-- prepends any semantic properties to the start of the icon
        	    	result = result .. tostring(createSM) 
            			.. tostring(createPlatform)
	            if k < #icons then
    	            result = result .. " "
        	    end
	        end
	    end
	end
    --[[
    	If there are no valid platform codes in the list the function defaults 
    	to an on page indicator with optional category.
    ]]
    if not exists(result) then
        result = '<sup>[Platforms needed]</sup>'
        if platformMaintenanceEnabled then
         result = result .. '[[Category:' .. platformMaintenanceCategory 
        	.. ']]'
        end
    end
    
    return result
end

--% Self generating function that displays all available icons and their short codes in a table set.
function p.documentation()
    local keys = {}
    for k in pairs(iconData) do
        table.insert(keys, k)
    end
 
    table.sort(keys)
    local result = mw.html.create('table')
    result:addClass(docTableClasses)
   		:tag('tr')
   			:tag('th')
   				:wikitext('prefix')
   				:done()
   			:tag('th')
   				:wikitext('Icon')
   				:done()
   			:tag('th')
   				:wikitext('prefix')
   				:done()
   			:tag('th')
   				:wikitext('Icon')
   				:done()
   			:tag('th')
   				:wikitext('prefix')
   				:done()
   			:tag('th')
   				:wikitext('Icon')

    local columns = 3
    local tableRow
    for k,v in ipairs(keys) do
        local set = (k - 1) % columns + 1
    	if set == 1 then
    		tableRow = result:tag('tr')	
    	end
    	
    	tableRow:tag('td')
    		:wikitext(v)

		local i = iconData[v]
        local newFile
        if exists(i) and i.class ~= nil then
        	newFile = mw.html.create('span')
        		:addClass(imageClassList[i.class])
        		:wikitext('[[File:' .. i.icon .. '|x25px]]')
        elseif exists(i.icon) then
        	newFile = mw.html.create('span')
        		:wikitext('[[File:' .. i.icon .. '|x25px]]')
        end
        
        tableRow:tag('td')
        	:node(newFile)
    end
 
    return result
end

--% Maintenance function for sorting long icon Data lists. Results are passed to parser profile data for copying
function p.sortList()
	local keys = {}
	for k in pairs(iconData) do
		table.insert(keys, k)
	end
	
	table.sort(keys)
	local result = 'return {'
	for k,v in ipairs(keys) do
		local ins = iconData[v]
		result = result .. '\n\t[\'' .. string.gsub(v, '\'', '\\\'') .. '\'] = {'
			.. '\n\t\t[\'icon\']  = \'' .. string.gsub(ins.icon, '\'', '\\\'') 
			.. '\','
		if ins.link then
			result = result .. '\n\t\t[\'link\'] = \'' 
				.. string.gsub(ins.link, '\'', '\\\'')  .. '\','
		end
		
		if ins.tip then
			result = result .. '\n\t\t[\'tip\'] = \'' 
				.. string.gsub(ins.tip, '\'', '\\\'')  .. '\',\n\t},'
		end
		
		if ins.platform then
			result = result .. '\n\t\t[\'platform\'] = \'' 
				.. string.gsub(ins.platform, '\'', '\\\'')  .. '\',\n\t},'
		end
		
		if ins.alt then
			result = result .. '\n\t\t[\'alt\'] = \'' 
				.. string.gsub(ins.alt, '\'', '\\\'')  .. '\',\n\t},'
		end
	end
	
	result = result .. '\n}'
	mw.log(result)
end

return p