BloodCaster (обс. | вклад) Нет описания правки |
BloodCaster (обс. | вклад) Нет описания правки |
||
Строка 68: | Строка 68: | ||
if setting(page) then |
if setting(page) then |
||
args['масштаб'] = args['масштаб'] or 1 |
args['масштаб'] = args['масштаб'] or 1 |
||
− | scaleq = setting(page)['множитель'] or 1 |
+ | scaleq = setting(page)['множитель'] or setting('множитель') or 1 |
args['разм'] = setting(page)['разм'] or setting('разм') |
args['разм'] = setting(page)['разм'] or setting('разм') |
||
args['формат'] = setting(page)['формат'] or setting('формат') |
args['формат'] = setting(page)['формат'] or setting('формат') |
Версия от 16:49, 25 апреля 2018
Этот модуль реализует систему спрайтов Minecraft Wiki. Больше информации расположено на указанной странице и на страницах документации шаблонов спрайтов.
Аргументы страницы, вызвавшей модуль, автоматически объединяются с аргументами, переданными модулю напрямую (последние перезаписывают первые). Также все аргументы нормализуются (при этом удаляются стоящие в начале и в конце пробелы, а пустые аргументы задаются как равные nil
).
Зависит от
-- Модуль для отображения иконок из таблиц спрайтов.
-- Внимание: Неосторожные изменения модуля могут привести к проблемам на большом количестве статей!
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 = {}
local page = setting('страница') or ''
if setting('таблстилей') then -- использовать CSS-классы для указания файла
sprite:addClass(setting('имякласса') or mw.ustring.lower(setting('имя'):gsub(' ', '-')) .. '-sprite')
else -- указывать файл напрямую
table.insert(styles, 'background-image: {{FileUrl|' .. (setting('изобр') or setting('имя') .. page .. 'CSS.png') .. '}}')
end
local class = setting('класс') -- CSS-класс спрайта
if class then
sprite:addClass(class)
end
-- Настройки страницы многостраничного спрайта
local scaleq = 1
if setting(page) then
args['масштаб'] = args['масштаб'] or 1
scaleq = setting(page)['множитель'] or setting('множитель') or 1
args['разм'] = setting(page)['разм'] or setting('разм')
args['формат'] = setting(page)['формат'] or setting('формат')
end
local size = setting('разм') -- размер спрайта в пикселях
local v_size = setting('верт_разм') or 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 ) * v_size -- вертикальная координата спрайта
local scale = setting('масштаб') * scaleq -- масштаб спрайта (во сколько раз увеличить или уменьшить размер)
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: ' .. v_size * scale .. 'px')
table.insert(styles, 'width: ' .. size * scale .. 'px')
end
-- Выравнивание
if align ~= defaultStyle["выравн"] then
table.insert(styles, 'vertical-align: ' .. align)
end
-- Дополнительный CSS-код, указанный в параметре
table.insert(styles, setting('css'))
-- Применение полученных CSS-стилей к спрайту.
sprite:cssText(table.concat(styles, ';'))
-- Собственно спрайт.
local root
-- Текстовые данные
local text = setting('текст')
local spriteText
if text then
root = mw.html.create('span'):addClass('nowrap')
spriteText = mw.html.create('span'):addClass('sprite-text'):wikitext(text)
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
-- Данная функция предварительно готовит данные для функции p.base, а затем вызывает её. Её следует вызывать на страницах вики-проекта
-- (через любой из спрайтовых шаблонов)
function p.sprite(f)
-- Параметры
local args = f
if f == mw.getCurrentFrame() then
args = require('Модуль: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 = args["некат"] or title.isSubpage or title.isTalkPage or title:inNamespace(2)
if idData then
if type(idData) == 'table' then -- новый формат полей ID
if idData["устарел"] and not disallowCats then
table.insert(categories, '[[Категория:Страницы с устаревшими названиями спрайтов]]')
end
args["поз"] = idData["поз"]
args["страница"] = idData["страница"]
else -- старый формат
args["поз"] = idData
end
elseif not disallowCats then
table.insert(categories, '[[Категория:Страницы с отсутствующими спрайтами]]')
end
-- Передача полученных данных функции p.base, её вызов и простановка категорий.
return p.base(args), table.concat(categories, '')
end
-- Ссылки
function p.link(f)
-- Параметры
local args = f
if f == mw.getCurrentFrame() then
args = require('Модуль: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
-- Указание аргументов для функции p.sprite
args[1] = args["ID"] or args[1]
args["ссылка"] = args["ссылка"] or link
args["текст"] = text
-- Вызов p.sprite
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