Module:Sprite

local util_args = require('Module:ArgsUtil') local util_table = require('Module:TableUtil') local util_text = require('Module:TextUtil') local util_vars = require("Module:VarsUtil")

local h = {} local p = {} function p.main(frame) local args = util_args.merge h.castArgs(args) return p._main(args) end

function p.sprite(args) return p._main(args) end

function p.spriteImage(args) local sheet = mw.loadData(('Module:%sSprite'):format(args.type)) local settings = util_table.shallowClone(sheet.settings or {}) if args[1] == '' then args[1] = nil end local input = args[1] or settings.emptyimage settings.defaultwidth = settings.width settings.display = args.title or args.display or input util_table.merge(settings, args, sheet.ids[input]) if args.fallback then util_table.mergeDontOverwrite(settings, sheet.ids[args.fallback]) end return tostring(h.sprite(settings)) end

function p._main(args) local sheet = mw.loadData(('Module:%sSprite'):format(args.type)) local settings = util_table.shallowClone(sheet.settings or {}) if args[1] == '' then args[1] = nil end local input = args[1] or settings.emptyimage if not input then return '' end settings.defaultwidth = settings.width util_table.merge(settings, args) h.addDataToArgs(input, settings, sheet.ids) local cat = (not settings.pos and args[1] and not settings.nocat) and  or  return tostring(h.makeOutput(settings)), cat end

function h.castArgs(args) local ARGS_TO_CAST = { 'noimage', 'nolink', 'notext', 'dark', 'black', 'backwards' } for _, v in ipairs(ARGS_TO_CAST) do		if args[v] then args[v] = util_args.castAsBool(args[v]) end end args.width = tonumber(args.width) args.height = tonumber(args.height) args.size = tonumber(args.size) end

function h.addDataToArgs(input, settings, ids) local displayKey = settings.lengthkey or settings.defaultlengthkey or 'link' local idKey = settings.linkkey or settings.defaultlinkkey or 'link' h.getIdAndKey(input, settings, idKey, displayKey) settings.link = (settings.link or settings.id) .. (settings.autolinksuffix or '') util_table.merge(settings, ids[settings.id]) end

function h.getIdAndKey(input, settings, idKey, displayKey) if settings.skiplookup or not settings.lookup then settings.id = input settings.display = input return end local lookup = mw.loadData('Module:' .. settings.lookup) local lookupResult = util_args.lookupVars(input, lookup) or {} settings.id = lookupResult[idKey] or input settings.display = settings.display or lookupResult[displayKey] or input end

function h.makeOutput(settings) if settings.noimage and settings.nolink then return settings.display elseif settings.noimage then return ('%s'):format(settings.destination or settings.id, settings.display) elseif settings.notext and settings.nolink then return h.sprite(settings) elseif settings.notext then local sprite = h.sprite(settings) return h.addLinkToSprite(sprite, settings) elseif settings.nolink then return tostring(h.makeSpriteAndText(settings)) else local sprite = h.makeSpriteAndText(settings) return h.addLinkToSprite(sprite, settings) end end

function h.makeSpriteAndText(settings) local sprite = h.sprite(settings) local spriteText = h.makeSpriteText(settings) local root = mw.html.create('span') :addClass('nowrap') if settings.backwards then root:node(spriteText) root:node(sprite) else root:node(sprite) root:node(spriteText) end return root end

function h.makeSpriteText(settings) local text = mw.html.create('span') if settings.backwards then text:addClass('sprite-text-backwards') else text:addClass('sprite-text') end text:wikitext(settings.display) return text end

function h.addLinkToSprite(sprite, settings) return util_text.link(settings.destination or settings.link, tostring(sprite)) end

function h.sprite(settings) local sprite = mw.html.create('span') :attr('title', settings.display or settings.id) if not settings.notext then sprite:tag('br') end h.addClassesToSprite(sprite, settings) local styles = h.getStyles(settings) sprite:cssText(util_table.concat(styles,';')) return sprite end

function h.addClassesToSprite(sprite, settings) sprite:addClass(settings.class) :addClass('sprite') :addClass(h.getTypeClass(settings)) if settings.black then sprite:addClass('black-sprite') end if settings.dark then sprite:addClass('dark-sprite') end end

function h.getTypeClass(settings) if settings.classname then return settings.classname else local name = settings.name:lower return name .. '-sprite' end end

function h.getStyles(settings) local width = settings.size or settings.width local height = settings.size or settings.height local spacing = settings.spacing * (width / settings.defaultwidth) local sheetWidth = settings.sheetsize local tiles = (sheetWidth + settings.spacing) / (settings.defaultwidth + settings.spacing) local pos = math.abs(settings.pos or 1) - 1 local left = math.floor(pos % tiles * (width + spacing) + 0.5) local top = math.floor(math.floor(pos / tiles) * (height + spacing) + 0.5) local styles = { 'background-position:' .. h.getBackgroundPosition(left, top), 'background-size:' .. h.getBackgroundSize(width, spacing, tiles), util_args.nilToFalse(settings.css) }	if not settings.nosize then styles[#styles+1] = 'width:' .. width .. 'px' styles[#styles+1] = 'height:' .. height .. 'px' end return styles end

function h.getBackgroundPosition(left, top) return ('-%spx -%spx'):format(left, top) end

function h.getBackgroundSize(width, spacing, tiles) local width = math.floor((width + spacing) * tiles - spacing + 0.5) return width .. 'px auto' end

return p