Документация
require('strict')
-- Этот модуль реализован шаблонами {{Таблица эпизодов}}, {{Таблица эпизодов/шапка}} и {{Таблица эпизодов/часть}}.
local HTMLcolor = mw.loadData('Модуль:Color contrast/colors')
local contrast_ratio = require('Модуль:Color contrast')._ratio
local plainText = require('Модуль:Таблица эпизодов/Plain text')._main
local anchor = require('Модуль:Якорь').main
local match = mw.ustring.match
local lower = mw.ustring.lower
local gsub = mw.ustring.gsub
--------------------------------------------------------------------------------
-- Local functions
--------------------------------------------------------------------------------
local function isExistNumsCols(args)
local forceoverall = args.forceoverall or args['ОбщийНомер']
local overall = args.overall or args['Номер']
local season = args.season or args['Сезон']
local series = args.series or args['Серия']
if forceoverall
or season and series
or overall and season and series
then
return true
end
return false
end
--------------------------------------------------------------------------------
-- EpisodeTable class
-- The main class.
--------------------------------------------------------------------------------
local EpisodeTable = {}
function EpisodeTable.cell(background, width, text, reference, textColor)
local cell = mw.html.create('th')
-- Ячейка
cell:attr('scope', 'col')
:css('background', background or '#ccccff')
:css('width', width ~= '' and width .. '%' or nil)
:css('color', textColor)
:wikitext(text)
-- Сноска на примечание
if reference then
cell:wikitext(' ' .. EpisodeTable.reference(reference, background))
end
return cell
end
function EpisodeTable.reference(reference, background)
-- контрастность с непосещенной и посещенной ссылкой
local link1_cr = contrast_ratio{background or '#ccccff', '#0645AD', ['error']=0}
local link2_cr = contrast_ratio{background or '#ccccff', '#0B0080', ['error']=0}
local refspan = mw.html.create('span')
:wikitext(reference)
if link1_cr < 7 or link2_cr < 7 then
refspan
:css('color', link1_cr < 3 and link2_cr < 3 and 'white' or 'black')
:css('background-color', link1_cr < 3 and link2_cr < 3 and '#f8f9fa' or 'transparent')
:css('padding', '1px')
:css('display', 'inline-block')
:css('line-height', '50%')
end
return tostring(refspan)
end
function EpisodeTable.abbr(text, title)
local abbr = mw.html.create('abbr')
abbr:attr('title', title)
:wikitext(text)
return tostring(abbr)
end
function EpisodeTable.part(args)
local row = mw.html.create('tr')
local cellColor = args.c or args['Цвет'] or args['цвет']
local cellRef = args.r or args['Ссылка'] or args['ссылка']
local subTitle = args.subtitle or args['Подзаголовок'] or args['подзаголовок'] or args['Текст'] or args['текст']
-- Цвет по умолчанию
if not cellColor or cellColor == '' then
cellColor = '#ccccff'
end
-- Добавление # при необходимости
if cellColor and not HTMLcolor[cellColor] then
cellColor = '#'..(match(cellColor, '^[%s#]*([a-fA-F0-9]+)%s*$') or 'ccccff')
end
local black_cr = contrast_ratio{'black', cellColor or '#ccccff', ['error']=0}
local white_cr = contrast_ratio{'white', cellColor or '#ccccff', ['error']=0}
local partTypes = {
{'act', 'акт', 'Акт'},
{'chapter', 'глава', 'Глава'},
{'part', 'часть', 'Часть'},
{'p', 'ч', 'Часть'},
{'volume', 'том', 'Том'},
{'week', 'неделя', 'Неделя'},
}
local displaytext = ''
local isAnyPartSet = false
local partValue
for k, v in pairs(partTypes) do
partValue = args[v[1]] or args[v[2]] or args[v[3]]
if partValue then
isAnyPartSet = true
displaytext = v[3] .. ' ' .. partValue
end
end
if subTitle then
displaytext = displaytext .. ((isAnyPartSet and ': ' or '') .. subTitle)
end
local displayTextAnchor = plainText(displaytext)
row:tag('td')
:attr('colspan', 13)
:attr('id', args.id or displayTextAnchor)
:css('text-align', 'center')
:css('background-color', cellColor or '#ccccff')
:css('color', black_cr > white_cr and 'black' or 'white')
:wikitext("'''" .. displaytext .. "'''" .. (cellRef and " " .. EpisodeTable.reference(cellRef, cellColor) or ''))
return tostring(row)
end
function EpisodeTable.new(args, dontclose)
args = args or {}
local categories = ''
local background = args.background or args['ЦветФона']
if background == '' or background =='#' then
background = nil
end
-- Добавление # при необходимости
if background and not HTMLcolor[background] then
background = '#'..(match(background, '^[%s#]*([a-fA-F0-9]+)%s*$') or '')
end
-- Ширина ячеек по умолчанию
local defaultwidths = {
overall=5, ['Номер']=5, ['номер']=5,
overall2=5, ['Номер2']=5, ['номер2']=5,
season=5, ['Сезон']=5, ['сезон']=5,
series=5, ['Серия']=5, ['серия']=5,
airdate=10, ['ДатаПоказа']=10, ['датапоказа']=10,
altdate=10, ['ДатаПоказа2']=10, ['датапоказа2']=10,
prodcode=7, ['ПродКод']=7, ['продкод']=7,
viewers=10, ['Зрителей']=10, ['зрителей']=10
}
-- Создание таблицы эпизодов
local root = mw.html.create('table')
local totalWidth = args.total_width or args['ОбщаяШирина'] or args['общаяширина']
root:addClass('wikitable')
:addClass('plainrowheaders')
:addClass('wikiepisodetable')
:css('width', totalWidth and gsub(totalWidth, '%%', '') .. '%' or '100%')
-- Заголовок
local caption = args.caption or args['Заголовок'] or args['заголовок']
if caption then
root:tag('caption')
:wikitext(caption)
end
-- Цветовой контраст; добавление в категории, если основное пространство имен
local title = mw.title.getCurrentTitle()
local black_cr = contrast_ratio{background or '#ccccff', 'black', ['error']=0}
local white_cr = contrast_ratio{'white', background or '#ccccff', ['error']=0}
if title.namespace == 0 and background and black_cr < 4.5 and white_cr < 4.5 then
categories = categories .. '[[Категория:Википедия:Потенциально нечитаемые таблицы эпизодов]]'
end
-- Основная строка
local textColor = background and (black_cr > white_cr and 'black' or 'white') or 'black'
local mainRow = root:tag('tr')
mainRow
:css('color', textColor)
:css('text-align', 'center')
-- Ячейки
do
local used_season = false
local numsColsExist = isExistNumsCols(args)
local country = args.country or args['Страна'] or args['страна'] or ''
local viewersType = args.viewers_type or args['ЗрителейТ'] or args['зрителейТ']
if not viewersType or viewersType == '' then
viewersType = 'млн'
end
local overallColName = EpisodeTable.abbr('№', 'Номер') .. ((args.season or args['Сезон'] or args.forceoverall or args['ОбщийНомер']) and '<br>общий' or '')
local overall2ColName = EpisodeTable.abbr('№', 'Номер') .. (args['Номер2ТАббр'] and args['Номер2АббрТ'] and '<br>' .. EpisodeTable.abbr(args['Номер2ТАббр'], args['Номер2АббрТ']) or '')
local seasonColName = EpisodeTable.abbr('№', 'Номер') .. (numsColsExist and '<br>сезона' or ' в<br>сезоне')
local seriesColName = EpisodeTable.abbr('№', 'Номер') .. (numsColsExist and '<br>серии' or ' в<br>сезоне')
local prodcodeColName = EpisodeTable.abbr('Произв.', 'Производственный') .. '<br>код'
local viewersColName = 'Зрители ' .. country .. '<br>(' .. viewersType .. ')'
--- {'paramEng', 'paramRus', 'paramRus', 'ColumnName'}
local cellNames = {
{'overall', 'Номер', 'номер', overallColName},
{'overall2', 'Номер2', 'номер2', overall2ColName},
{'season', 'Сезон', 'сезон', seasonColName},
{'series', 'Серия', 'серия', seriesColName},
{'title', 'Название', 'название', 'Название'},
{'aux1', 'Столбец1', 'столбец1', ''},
{'director', 'Режиссер', 'Режиссёр', 'Режиссёр'},
{'writer', 'Сценарист', 'сценарист', 'Автор сценария'},
{'aux2', 'Столбец2', 'столбец2', ''},
{'aux3', 'Столбец3', 'столбец3', ''},
{'airdate', 'ДатаПоказа', 'датапоказа', 'Дата премьеры'},
{'altdate', 'ДатаПоказа2', 'датапоказа2', ''},
{'prodcode', 'ПродКод', 'продкод', prodcodeColName},
{'viewers', 'Зрителей', 'зрителей', viewersColName},
{'aux4', 'Столбец4', 'столбец4', ''}
}
for k, v in pairs(cellNames) do
-- local cellWidth = args[v[1]] or args[v[2]] or args[v[3]]
local cellWidth, argName
argName = args[v[1]] and v[1] or args[v[2]] and v[2] or args[v[3]] and v[3]
if argName then
cellWidth = args[argName]
argName = lower(argName)
end
if cellWidth and ((argName ~= 'series' or argName ~= 'серия')
or (argName == 'series' or argName == 'серия' and used_season == false))
then
if argName == 'season' or argName == 'сезон' then used_season = true end
if (k <= 3 and cellWidth == '') then cellWidth = '5' end
if (cellWidth == '' and defaultwidths[argName]) then cellWidth = defaultwidths[argName] end
local cellText = args[argName .. 'T'] or args[argName .. 'Т']
local cellRef = args[argName .. 'R'] or args[argName .. 'С']
mainRow:node(EpisodeTable.cell(background, cellWidth, cellText or v[4], cellRef, textColor))
end
end
-- Эпизоды (серии)
local episodes = args.episodes or args['Эпизоды'] or args['эпизоды']
local anchor = args.anchor or args['Якорь'] or args['якорь']
if episodes then
if anchor then
episodes = gsub(episodes, '(id=")(ep%w+")', '%1' .. anchor .. '%2')
end
root:node(episodes)
end
end
if title.namespace == 0 then
categories = categories .. '[[Категория:Википедия:Статьи использующие шаблон таблица эпизодов]]'
end
root = tostring(root)
return (dontclose and gsub(root, '</table>', '') or root) .. categories
end
--------------------------------------------------------------------------------
-- Экспорт
--------------------------------------------------------------------------------
local p = {}
function p.main(frame)
local args = require('Модуль:Arguments').getArgs(frame, {
removeBlanks = false,
wrappers = {
'Шаблон:Таблица эпизодов',
'Шаблон:Таблица эпизодов/песочница'
},
})
return EpisodeTable.new(args)
end
function p.maint(frame)
local args = require('Модуль:Arguments').getArgs(frame, {
removeBlanks = false,
wrappers = {
'Шаблон:Таблица эпизодов/шапка',
'Шаблон:Таблица эпизодов/песочница/шапка'
}
})
return EpisodeTable.new(args, true)
end
function p.part(frame)
local args = require('Модуль:Arguments').getArgs(frame, {
removeBlanks = false,
wrappers = {
'Шаблон:Таблица эпизодов/часть',
'Шаблон:Таблица эпизодов/песочница/часть'
}
})
return EpisodeTable.part(args)
end
function p.ref(frame)
local args = require('Модуль:Arguments').getArgs(frame, {
removeBlanks = false,
-- wrappers = 'Шаблон:Таблица эпизодов/примечание'
})
return EpisodeTable.reference(args.r, args.b)
end
return p