Модуль:Спрайт
Материал из Playzone Minecraft Wiki
Для документации этого модуля может быть создана страница Модуль:Спрайт/doc
local p = {} -- Основа спрайта function p.base( f ) local args = f if f == mw.getCurrentFrame() then args = require( 'Модуль:ProcessArgs' ).merge( true ) else f = mw.getCurrentFrame() end -- Настройки по умолчанию local default = { ["масштаб"] = 1, ["формат"] = 256, ["разм"] = 16, ["поз"] = 1, ["выравн"] = 'text-top' } local defaultStyle = default if args["настройки"] then local settings = mw.loadData( 'Модуль:' .. args["настройки"] ) if not settings["таблстилей"] then -- Создаём отдельную копию текущих настроек по умолчанию: defaultStyle = mw.clone( default ) end for k, v in pairs( settings ) do default[k] = v end end -- Выбрать настройки указанные или по умолчанию local setting = function( arg ) return args[arg] or default[arg] end -- Начало сборки кода local sprite = mw.html.create( 'span' ):addClass( 'sprite' ) -- создать <span class="sprite">...</span> sprite:tag( 'br' ) -- добавить <br> -- CSS-стили -- Метод css от mw.html производит очень медленное экранирование входных данных, что тормозит работу в два раза. В обход -- этого стили будут создаваться вручную, и будут передаваться через метод cssText, который делает только экранирование HTML, -- что куда быстрее. local styles = {} if setting('таблстилей') then -- использовать CSS-классы для общих настроек sprite:addClass(setting( 'имякласса' ) or mw.ustring.lower( setting( 'имя' ):gsub( ' ', '-' ) ) .. '-sprite') else table.insert(styles, 'background-image: {{FileUrl|' .. ( setting( 'изобр' ) or setting( 'имя' ) .. 'CSS.png' ) .. '}}') end local class = setting('класс') if class then sprite:addClass(class) end local size = setting( 'разм' ) local pos = math.abs( setting( 'поз' ) ) - 1 local sheetWidth = setting( 'формат' ) local tiles = sheetWidth / size local left = pos % tiles * size local top = math.floor( pos / tiles ) * size local scale = setting( 'масштаб' ) local autoscale = setting( 'автомасштаб' ) local align = setting('выравн') if left > 0 or top > 0 then table.insert(styles, 'background-position: -' .. left * scale .. 'px -' .. top * scale .. 'px') end if not autoscale and scale ~= defaultStyle["масштаб"] then table.insert(styles, 'background-size: ' .. sheetWidth * scale .. 'px auto') end if size ~= defaultStyle["разм"] or ( not autoscale and scale ~= defaultStyle["масштаб"] ) then table.insert(styles, 'height: ' .. size * scale .. 'px') table.insert(styles, 'width: ' .. size * scale .. 'px') end if align ~= defaultStyle["выравн"] then table.insert(styles, 'vertical-align: ' .. align) end table.insert(styles, setting('css')) sprite:cssText(table.concat(styles, ';')) -- Текстовые данные local root local test = setting('текст') local spriteText if test then root = mw.html.create( 'span' ):addClass( 'nowrap' ) spriteText = mw.html.create( 'span' ):addClass( 'sprite-text' ):wikitext(test) end local title = setting( 'назв' ) if title then ( root or sprite ):attr('title', title) end if not root then root = mw.html.create( '' ) end root:node( sprite ) if spriteText then root:node( spriteText ) end -- Ссылка local link = setting( 'ссылка' ) or "" if link ~= "" and mw.ustring.lower( link ) ~= 'none' then -- Внешняя ссылка if link:find( '//' ) then return '[' .. link .. ' ' .. tostring( root ) .. ']' end -- Внутренняя ссылка local linkPrefix = setting( 'предссылки' ) or '' return '[[' .. linkPrefix .. link .. '|' .. tostring( root ) .. ']]' end return tostring( root ) end -- Весь спрайт function p.sprite( f ) local args = f if f == mw.getCurrentFrame() then args = require( 'Module:ProcessArgs' ).merge( true ) end local categories = {} local idData = args["данныеID"] if not idData then local default = {} if args["настройки"] then default = mw.loadData( 'Модуль:' .. args["настройки"] ) end local name = args["имя"] or default["имя"] local ids = mw.loadData( 'Модуль:' .. ( args["IDы"] or default["IDы"] or name .. 'Спрайт/ID' ) )["IDы"] ids = ids["IDы"] or ids local id = mw.text.trim( tostring(args[1] or '') ) if tonumber(id) then idData = {["поз"] = id} table.insert(categories, '[[Категория:Страницы, использующие для спрайтов числовые идентификаторы]]') else idData = ids[id] or ids[mw.ustring.lower( id ):gsub( '[_%-%s%+]+', '-' )] end end local title = mw.title.getCurrentTitle() -- запретить категории соответственно в подстраницах, в пространствах участников и на страницах обсуждений local disallowCats = title.isSubpage or title:inNamespace(2) or (title.namespace % 2 == 1) if idData then if type(idData) == 'table' then -- новый формат полей ID if idData["устарел"] and not disallowCats then table.insert( categories, '[[Категория:Страницы с устаревшими названиями спрайтов]]' ) end args["поз"] = idData["поз"] else -- старый формат args["поз"] = idData end elseif not disallowCats then table.insert( categories, '[[Категория:Страницы с отсутствующими спрайтами]]' ) end return p.base( args ), table.concat( categories, '' ) end -- Ссылки function p.link( f ) local args = f if f == mw.getCurrentFrame() then args = require( 'Module:ProcessArgs' ).merge( true ) end if not args["ID"] then args["ID"] = args["ид"] -- для совместимости end local link = args[1] if args[1] and not args["ID"] then link = args[1]:match( '^(.-)%+' ) or args[1] end local text = args["текст"] or args[2] or link args[1] = args["ID"] or args[1] args["ссылка"] = args["ссылка"] or link args["текст"] = text return p.sprite( args ) end -- Документация function p.doc( f ) local args = f if f == mw.getCurrentFrame() then args = f.args else f = mw.getCurrentFrame() end local settingsPage = mw.text.trim( args[1] ) local settings = mw.loadData( 'Модуль:' .. settingsPage ) local idsPage = 'Модуль:' .. ( settings["IDы"] or settings["имя"] .. 'Спрайт/ID' ) local spriteargs = {} for k, v in pairs(args) do if type(k) ~= 'number' then spriteargs[k] = v end end local getProtection = function( title, action, extra ) local protections = { 'edit' } if extra then table.insert( protections, extra ) end local addProtection = function( protection ) if protection == 'autoconfirmed' then protection = 'editsemiprotected' elseif protection == 'sysop' then protection = 'editprotected' end table.insert( protections, protection ) end local direct = title.protectionLevels[action] for _, protection in ipairs( direct ) do addProtection( protection ) end local cascading = title.cascadingProtection.restrictions[action] or {} if #cascading > 0 then table.insert( protections, 'protect' ) end for _, protection in ipairs( cascading ) do addProtection( protection ) end return table.concat( protections, ',' ) end local body if args.refresh then body = mw.html.create( '' ) else local idsTitle = mw.title.new( idsPage ) local spritesheet = settings["изобр"] or settings["имя"] .. 'CSS.png' local spriteTitle = mw.title.new( 'Файл:' .. spritesheet ) local idsProtection = getProtection( idsTitle, 'edit' ) local spriteProtection = getProtection( spriteTitle, 'upload', 'upload,reupload' ) body = mw.html.create( 'div' ):attr( { id = 'spritedoc', ['data-idspage'] = idsTitle.id, ['data-idsprotection'] = idsProtection, ['data-idstimestamp'] = f:callParserFunction( 'REVISIONTIMESTAMP', idsPage ), ['data-spritesheet'] = spritesheet, ['data-spriteprotection'] = spriteProtection, ['data-pos'] = settings["поз"] or 1, ['data-refreshtext'] = mw.text.nowiki( '{{#invoke:Спрайт|doc|' .. settingsPage .. '|обновить=1}}' ) } ) end local data = mw.loadData( idsPage ) local sections = {} for _, sectionData in ipairs( data["разделы"] or {"Некатегоризованные"} ) do local sectionTag = body:tag( 'div' ):addClass( 'spritedoc-section' ):attr( 'data-section-id', sectionData["ID"] ) -- https://phabricator.wikimedia.org/T73594 sectionTag:wikitext( '<h3>', sectionData[1], '</h3>' ) sections[sectionData["ID"]] = { boxes = sectionTag:tag( 'ul' ):addClass( 'spritedoc-boxes' ) } end local keyedData = {} for name, idData in pairs( data["IDы"] ) do table.insert( keyedData, { ["ключ"] = mw.ustring.lower( name ), ["имя"] = name, ["данные"] = idData } ) end table.sort( keyedData, function( a, b ) return a["ключ"] < b["ключ"] end ) for _, data in ipairs( keyedData ) do local idData = data["данные"] local pos = idData["поз"] local section = sections[idData["раздел"]] local names = section[pos] if not names then local box = section.boxes:tag( 'li' ):addClass( 'spritedoc-box' ):attr( 'data-pos', pos ) local lspriteargs = mw.clone(spriteargs) lspriteargs["поз"] = pos lspriteargs["настройки"] = settingsPage box:tag( 'div' ):addClass( 'spritedoc-image' ) :wikitext( p.base(lspriteargs) ) names = box:tag( 'ul' ):addClass( 'spritedoc-names' ) section[pos] = names end local nameElem = mw.html.create( 'li' ):addClass( 'spritedoc-name' ) local codeElem = nameElem:tag( 'code' ):wikitext( data["имя"] ) if idData["устарел"] then codeElem:addClass( 'spritedoc-deprecated' ) end names:wikitext( tostring( nameElem ) ) end if args["обновить"] then return '', tostring( body ) end return f:callParserFunction( '#widget:Stylesheet', { page = 'SpriteDoc' } ), tostring( body ) end return p