autoreview, Бюрократы, Проверяющие участников, developer, editor, Администраторы интерфейса, reviewer, Администраторы, translator
2802
правки
imported>Иван Богданов (шаблон) |
Oles (обсуждение | вклад) (робот добавил: bn:টেমপ্লেট:Str left) |
||
Строка 1: | Строка 1: | ||
{{ {{{ | -- | ||
| | -- This module implements {{Navbox}} | ||
-- | |||
local p = {} | |||
local getArgs -- lazily initialized | |||
[[Категория: | |||
[[ | local args | ||
</ | local tableRowAdded = false | ||
local border | |||
local maintitle | |||
local name | |||
local above | |||
local image | |||
local below | |||
local titlestyle | |||
local groupstyle | |||
local bodystyle | |||
local basestyle | |||
local liststyle | |||
local oddstyle | |||
local evenstyle | |||
local evenoddARG | |||
local abovestyle | |||
local belowstyle | |||
local imageleft | |||
local imageleftstyle | |||
local listnums = {} | |||
local function trim(s) | |||
return (mw.ustring.gsub(s, "^%s*(.-)%s*$", "%1")) | |||
end | |||
local function addNewline(s) | |||
if s:match('^[*:;#]') or s:match('^{|') then | |||
return '\n' .. s ..'\n' | |||
else | |||
return s | |||
end | |||
end | |||
local function addTableRow(tbl) | |||
-- If any other rows have already been added, then we add a 2px gutter row. | |||
if tableRowAdded then | |||
tbl | |||
:tag('tr') | |||
:css('height', '2px') | |||
:tag('td') | |||
:attr('colspan',2) | |||
end | |||
tableRowAdded = true | |||
return tbl:tag('tr') | |||
end | |||
local function renderNavBar(titleCell) | |||
-- Depending on the presence of the navbar and/or show/hide link, we may need to add a spacer div on the left | |||
-- or right to keep the title centered. | |||
local spacerSide = nil | |||
if args.navbar == 'off' then | |||
-- No navbar, and client wants no spacer, i.e. wants the title to be shifted to the left. If there's | |||
-- also no show/hide link, then we need a spacer on the right to achieve the left shift. | |||
if args.state == 'plain' then spacerSide = 'right' end | |||
elseif args.navbar == 'plain' or (not name and mw.getCurrentFrame():getParent():getTitle():gsub('/sandbox$', '') == 'Шаблон:Навигационная таблица') then | |||
-- No navbar. Need a spacer on the left to balance out the width of the show/hide link. | |||
if args.state ~= 'plain' then spacerSide = 'left' end | |||
else | |||
-- Will render navbar (or error message). If there's no show/hide link, need a spacer on the right | |||
-- to balance out the width of the navbar. | |||
if args.state == 'plain' then spacerSide = 'right' end | |||
--- Мagnifying glass creation | |||
titleCell | |||
:tag('span') | |||
:css('float', 'left') | |||
:css('text-align', 'left') | |||
:css('width', '3.8em') | |||
:wikitext('[[File:Searchtool.svg|14px|Просмотр этого шаблона|link=Template:' .. name .. ']]') | |||
end | |||
-- Render the spacer div. | |||
if spacerSide then | |||
titleCell | |||
:tag('span') | |||
:css('float', spacerSide) | |||
:css('width', '3em') | |||
:wikitext(' ') | |||
end | |||
end | |||
-- | |||
-- Title row | |||
-- | |||
local function renderTitleRow(tbl) | |||
if not maintitle then return end | |||
local titleRow = addTableRow(tbl) | |||
if args.titlegroup then | |||
titleRow | |||
:tag('th') | |||
:attr('scope', 'row') | |||
:addClass('navbox-group') | |||
:addClass(args.titlegroupclass) | |||
:cssText(basestyle) | |||
:cssText(groupstyle) | |||
:cssText(args.titlegroupstyle) | |||
:wikitext(args.titlegroup) | |||
end | |||
local titleCell = titleRow:tag('th'):attr('scope', 'col') | |||
if args.titlegroup then | |||
titleCell | |||
:css('border-left', '2px solid #fdfdfd') | |||
:css('width', '100%') | |||
end | |||
local titleColspan = 2 | |||
if imageleft then titleColspan = titleColspan + 1 end | |||
if image then titleColspan = titleColspan + 1 end | |||
if args.titlegroup then titleColspan = titleColspan - 1 end | |||
titleCell | |||
:cssText(basestyle) | |||
:cssText(titlestyle) | |||
:addClass('navbox-title') | |||
:attr('colspan', titleColspan) | |||
renderNavBar(titleCell) | |||
titleCell | |||
:tag('div') | |||
:addClass(args.titleclass) | |||
:css('font-size', '114%') | |||
:wikitext(addNewline(maintitle)) | |||
end | |||
-- | |||
-- Above/Below rows | |||
-- | |||
local function getAboveBelowColspan() | |||
local ret = 2 | |||
if imageleft then ret = ret + 1 end | |||
if image then ret = ret + 1 end | |||
return ret | |||
end | |||
local function renderAboveRow(tbl) | |||
if not above then return end | |||
addTableRow(tbl) | |||
:tag('td') | |||
:addClass('navbox-abovebelow') | |||
:addClass(args.aboveclass) | |||
:cssText(basestyle) | |||
:cssText(abovestyle) | |||
:attr('colspan', getAboveBelowColspan()) | |||
:tag('div') | |||
:wikitext(addNewline(above)) | |||
end | |||
local function renderBelowRow(tbl) | |||
if not below then return end | |||
addTableRow(tbl) | |||
:tag('td') | |||
:addClass('navbox-abovebelow') | |||
:addClass(args.belowclass) | |||
:cssText(basestyle) | |||
:cssText(belowstyle) | |||
:attr('colspan', getAboveBelowColspan()) | |||
:tag('div') | |||
:wikitext(addNewline(below)) | |||
end | |||
-- | |||
-- List rows | |||
-- | |||
local function renderListRow(tbl, listnum) | |||
local row = addTableRow(tbl) | |||
if listnum == 1 and imageleft then | |||
row | |||
:tag('td') | |||
:addClass('navbox-image') | |||
:addClass(args.imageclass) | |||
:css('width', '1%') | |||
:css('padding', '0px 7px 0px 0px') | |||
:cssText(imageleftstyle) | |||
:attr('rowspan', 2 * #listnums - 1) | |||
:tag('div') | |||
:wikitext(addNewline(imageleft)) | |||
end | |||
if (args['group' .. listnum] or args['заголовок' .. listnum]) then | |||
local groupCell = row:tag('th') | |||
groupCell | |||
:attr('scope', 'row') | |||
:addClass('navbox-group') | |||
:addClass(args.groupclass) | |||
:cssText(basestyle) | |||
-- заголовки без списков - для обратной совместимости, только в нашем разделе | |||
if not (args['list' .. listnum] or args['список' .. listnum]) then | |||
groupCell | |||
:attr('colspan', '2') | |||
:css('text-align', 'center') | |||
end | |||
if args.groupwidth then | |||
groupCell:css('width', args.groupwidth) | |||
end | |||
groupCell | |||
:cssText(groupstyle) | |||
:cssText(args['group' .. listnum .. 'style']) | |||
:wikitext(args['group' .. listnum] or args['заголовок' .. listnum]) | |||
end | |||
if args['list' .. listnum] or args['список' .. listnum] then | |||
local listCell = row:tag('td') | |||
if (args['group' .. listnum] or args['заголовок' .. listnum]) then | |||
listCell | |||
:css('text-align', 'left') | |||
:css('border-left-width', '2px') | |||
:css('border-left-style', 'solid') | |||
else | |||
listCell:attr('colspan', 2) | |||
end | |||
if not args.groupwidth then | |||
listCell:css('width', '100%') | |||
end | |||
local isOdd = (listnum % 2) == 1 | |||
local rowstyle = evenstyle | |||
if isOdd then rowstyle = oddstyle end | |||
local evenOdd | |||
if evenoddARG == 'swap' then | |||
if isOdd then evenOdd = 'even' else evenOdd = 'odd' end | |||
else | |||
if isOdd then evenOdd = evenoddARG or 'odd' else evenOdd = evenoddARG or 'even' end | |||
end | |||
listCell | |||
:css('padding', '0px') | |||
:cssText(liststyle) | |||
:cssText(rowstyle) | |||
:cssText(args['list' .. listnum .. 'style']) | |||
:addClass('navbox-list') | |||
:addClass('navbox-' .. evenOdd) | |||
:addClass(args.listclass) | |||
:tag('div') | |||
:css('padding', (listnum == 1 and args.list1padding) or args.listpadding or '0em 0.25em') | |||
:wikitext('\n' .. (args['list' .. listnum] or args['список' .. listnum])) | |||
end | |||
if listnum == 1 and image then | |||
row | |||
:tag('td') | |||
:addClass('navbox-image') | |||
:addClass(args.imageclass) | |||
:css('width', '1%') | |||
:css('padding', '0px 0px 0px 7px') | |||
:cssText(imagestyle) | |||
:attr('rowspan', 2 * #listnums - 1) | |||
:tag('div') | |||
:wikitext(addNewline(image)) | |||
end | |||
end | |||
-- | |||
-- Tracking categories | |||
-- | |||
local function needsChangetoSubgroups() | |||
for i = 1, 23 do | |||
if (args['group' .. i] or args['заголовок' .. i]) and not (args['list' .. i] or args['список' .. i]) then | |||
return true | |||
end | |||
end | |||
return false | |||
end | |||
local function needsHorizontalLists() | |||
if border == 'child' or border == 'subgroup' or args.tracking == 'no' then return false end | |||
local listClasses = {'plainlist', 'hlist', 'hlist hnum', 'hlist hwrap', 'hlist vcard', 'vcard hlist', 'hlist vevent'} | |||
for i, cls in ipairs(listClasses) do | |||
if args.listclass == cls or args.bodyclass == cls then | |||
return false | |||
end | |||
end | |||
return true | |||
end | |||
local function hasBackgroundColors() | |||
return mw.ustring.match(titlestyle or '','background') or mw.ustring.match(groupstyle or '','background') or mw.ustring.match(basestyle or '','background') | |||
end | |||
local function isIllegible() | |||
local styleratio = require('Module:Color contrast')._styleratio | |||
for key, style in pairs(args) do | |||
if tostring(key):match("style$") then | |||
if styleratio{mw.text.unstripNoWiki(style)} < 4.5 then | |||
return true | |||
end | |||
end | |||
end | |||
return false | |||
end | |||
local function getTrackingCategories() | |||
local cats = {} | |||
if needsChangetoSubgroups() then table.insert(cats, 'Навигационные шаблоны с ошибочным использованием заголовков') end | |||
if needsHorizontalLists() then table.insert(cats, 'Навигационные шаблоны без горизонтальных списков') end | |||
if hasBackgroundColors() then table.insert(cats, 'Навигационные шаблоны, использующие фоновые цвета') end | |||
if isIllegible() then table.insert(cats, 'Потенциально нечитаемые навигационные шаблоны') end | |||
return cats | |||
end | |||
local function renderTrackingCategories(builder) | |||
local title = mw.title.getCurrentTitle() | |||
if title.namespace ~= 10 then return end -- not in template space | |||
local subpage = title.subpageText | |||
if subpage == 'doc' or subpage == 'sandbox' or subpage == 'testcases' then return end | |||
for i, cat in ipairs(getTrackingCategories()) do | |||
builder:wikitext('[[Категория:' .. cat .. ']]') | |||
end | |||
end | |||
-- | |||
-- Main navbox tables | |||
-- | |||
local function renderMainTable() | |||
local tbl = mw.html.create('table') | |||
:addClass('nowraplinks') | |||
:addClass(args.bodyclass) | |||
if maintitle and (args.state ~= 'plain' and args.state ~= 'off') then | |||
tbl | |||
:addClass('collapsible') | |||
:addClass(args.state or 'autocollapse') | |||
end | |||
tbl:css('border-spacing', 0) | |||
if border == 'subgroup' or border == 'child' or border == 'none' then | |||
tbl | |||
:addClass('navbox-subgroup') | |||
:css('background', 'transparent') | |||
:cssText(bodystyle) | |||
:cssText(args.style) | |||
else -- regular navbox - bodystyle and style will be applied to the wrapper table | |||
tbl | |||
:addClass('navbox-inner') | |||
:css('background', 'transparent') | |||
:css('color', 'inherit') | |||
end | |||
tbl:cssText(args.innerstyle) | |||
renderTitleRow(tbl) | |||
renderAboveRow(tbl) | |||
for i, listnum in ipairs(listnums) do | |||
renderListRow(tbl, listnum) | |||
end | |||
renderBelowRow(tbl) | |||
return tbl | |||
end | |||
function p._navbox(navboxArgs) | |||
args = navboxArgs | |||
for k, v in pairs(args) do | |||
local listnum = ('' .. k):match('^list(%d+)$') or ('' .. k):match('^список(%d+)$') | |||
if listnum then table.insert(listnums, tonumber(listnum)) end | |||
end | |||
-- заголовки без списков - для обратной совместимости, только в нашем разделе | |||
for k, v in pairs(args) do | |||
local double = false | |||
local groupnum = ('' .. k):match('^заголовок(%d+)$') --group не нужен, так как в английском шаблоне эта фукнциональность не поддерживается | |||
if groupnum then | |||
for k2, v2 in pairs(listnums) do | |||
if tonumber(groupnum) == v2 then | |||
double = true | |||
break | |||
end | |||
end | |||
if not double then table.insert(listnums, tonumber(groupnum)) end --добавляем только номера заголовков, для которых нет списков | |||
end | |||
end | |||
table.sort(listnums) | |||
border = trim(args.border or args[1] or '') | |||
maintitle = args.title or args['заголовок'] | |||
name = args.name or args['имя'] | |||
above = args.above or args['вверху'] | |||
image = args.image or args['изображение'] | |||
imagestyle = args.imagestyle or args['стиль_изображения'] | |||
imageleft = args.imageleft or args['изображение2'] or args['изображение_слева'] | |||
imageleftstyle = args.imageleftstyle or args.imagestyle2 or args['стиль_изображения_слева'] | |||
below = args.below or args['внизу'] | |||
titlestyle = args.titlestyle or args['стиль_основного_заголовка'] | |||
groupstyle = args.groupstyle or args['стиль_заголовков'] | |||
bodystyle = args.bodystyle or args['стиль_тела'] | |||
basestyle = args.basestyle or args['стиль'] | |||
liststyle = args.liststyle or args['стиль_списков'] | |||
oddstyle = args.oddstyle or args['стиль_нечетных'] | |||
evenstyle = args.evenstyle or args['стиль_четных'] | |||
abovestyle = args.abovestyle or args['стиль_вверху'] | |||
belowstyle = args.belowstyle or args['стиль_внизу'] | |||
evenoddARG = args.evenodd or args['четные_нечетные'] | |||
-- render the main body of the navbox | |||
local tbl = renderMainTable() | |||
-- render the appropriate wrapper around the navbox, depending on the border param | |||
local res = mw.html.create() | |||
if border == 'none' then | |||
res:node(tbl) | |||
elseif border == 'subgroup' or border == 'child' then | |||
-- We assume that this navbox is being rendered in a list cell of a parent navbox, and is | |||
-- therefore inside a div with padding:0em 0.25em. We start with a </div> to avoid the | |||
-- padding being applied, and at the end add a <div> to balance out the parent's </div> | |||
res | |||
:wikitext('</div>') -- XXX: hack due to lack of unclosed support in mw.html. | |||
:node(tbl) | |||
:wikitext('<div>') -- XXX: hack due to lack of unclosed support in mw.html. | |||
else | |||
res | |||
:tag('table') | |||
:addClass('navbox') | |||
:css('border-spacing', 0) | |||
:cssText(bodystyle) | |||
:cssText(args.style) | |||
:tag('tr') | |||
:tag('td') | |||
:css('padding', '2px') | |||
:node(tbl) | |||
end | |||
renderTrackingCategories(res) | |||
return tostring(res) | |||
end | |||
function p.navbox(frame) | |||
if not getArgs then | |||
getArgs = require('Module:Arguments').getArgs | |||
end | |||
args = getArgs(frame, {wrappers = 'Шаблон:Навигационная таблица'}) | |||
-- Read the arguments in the order they'll be output in, to make references number in the right order. | |||
local _ | |||
_ = maintitle | |||
_ = above | |||
for i = 1, 23 do | |||
_ = args["group" .. tostring(i)] and args["заголовок" .. tostring(i)] | |||
_ = args["list" .. tostring(i)] and args["список" .. tostring(i)] | |||
end | |||
_ = below | |||
return p._navbox(args) | |||
end | |||
return p |
правки