「モジュール:Infobox/former/sandbox」の版間の差分
表示
< モジュール:Infobox | former
削除された内容 追加された内容
m編集の要約なし |
Navbarの表示形式を現行のTemplate:Infoboxに近い形にする |
||
(2人の利用者による、間の4版が非表示) | |||
1行目: | 1行目: | ||
local p = {} |
local p = {} |
||
local args = {} |
|||
local origArgs = {} |
|||
local root |
|||
local empty_row_categories = {} |
|||
local category_in_empty_row_pattern = '%[%[%s*[Cc][Aa][Tt][Ee][Gg][Oo][Rr][Yy]%s*:[^]]*]]' |
|||
function |
local function fixChildBoxes(sval, tt) |
||
local function notempty( s ) return s and s:match( '%S' ) end |
|||
local args = require('Module:Arguments').getArgs(frame, {parentOnly = true}) --引数取得 |
|||
if notempty(sval) then |
|||
local marker = '<span class=special_infobox_marker>' |
|||
local s = sval |
|||
s = mw.ustring.gsub(s, '(<%s*[Tt][Rr])', marker .. '%1') |
|||
s = mw.ustring.gsub(s, '(</[Tt][Rr]%s*>)', '%1' .. marker) |
|||
if s:match(marker) then |
|||
s = mw.ustring.gsub(s, marker .. '%s*' .. marker, '') |
|||
s = mw.ustring.gsub(s, '([\r\n]|-[^\r\n]*[\r\n])%s*' .. marker, '%1') |
|||
s = mw.ustring.gsub(s, marker .. '%s*([\r\n]|-)', '%1') |
|||
s = mw.ustring.gsub(s, '(</[Cc][Aa][Pp][Tt][Ii][Oo][Nn]%s*>%s*)' .. marker, '%1') |
|||
s = mw.ustring.gsub(s, '(<%s*[Tt][Aa][Bb][Ll][Ee][^<>]*>%s*)' .. marker, '%1') |
|||
s = mw.ustring.gsub(s, '^(%{|[^\r\n]*[\r\n]%s*)' .. marker, '%1') |
|||
s = mw.ustring.gsub(s, '([\r\n]%{|[^\r\n]*[\r\n]%s*)' .. marker, '%1') |
|||
s = mw.ustring.gsub(s, marker .. '(%s*</[Tt][Aa][Bb][Ll][Ee]%s*>)', '%1') |
|||
s = mw.ustring.gsub(s, marker .. '(%s*\n|%})', '%1') |
|||
end |
|||
if s:match(marker) then |
|||
local subcells = mw.text.split(s, marker) |
|||
s = '' |
|||
for k = 1, #subcells do |
|||
if k == 1 then |
|||
s = s .. subcells[k] .. '</' .. tt .. '></tr>' |
|||
elseif k == #subcells then |
|||
local rowstyle = ' style="display:none"' |
|||
if notempty(subcells[k]) then rowstyle = '' end |
|||
s = s .. '<tr' .. rowstyle ..'><' .. tt .. ' colspan=2>\n' .. |
|||
subcells[k] |
|||
elseif notempty(subcells[k]) then |
|||
if (k % 2) == 0 then |
|||
s = s .. subcells[k] |
|||
else |
|||
s = s .. '<tr><' .. tt .. ' colspan=2>\n' .. |
|||
subcells[k] .. '</' .. tt .. '></tr>' |
|||
end |
|||
end |
|||
end |
|||
end |
|||
-- the next two lines add a newline at the end of lists for the PHP parser |
|||
-- [[Special:Diff/849054481]] |
|||
-- remove when [[:phab:T191516]] is fixed or OBE |
|||
s = mw.ustring.gsub(s, '([\r\n][%*#;:][^\r\n]*)$', '%1\n') |
|||
s = mw.ustring.gsub(s, '^([%*#;:][^\r\n]*)$', '%1\n') |
|||
s = mw.ustring.gsub(s, '^([%*#;:])', '\n%1') |
|||
s = mw.ustring.gsub(s, '^(%{%|)', '\n%1') |
|||
return s |
|||
else |
|||
return sval |
|||
end |
|||
end |
|||
-- Returns the union of the values of two tables, as a sequence. |
|||
local function union(t1, t2) |
|||
local vals = {} |
|||
for k, v in pairs(t1) do |
|||
vals[v] = true |
|||
end |
|||
for k, v in pairs(t2) do |
|||
vals[v] = true |
|||
end |
|||
local ret = {} |
|||
for k, v in pairs(vals) do |
|||
table.insert(ret, k) |
|||
end |
|||
return ret |
|||
end |
|||
-- Returns a table containing the numbers of the arguments that exist |
|||
-- for the specified prefix. For example, if the prefix was 'data', and |
|||
-- 'data1', 'data2', and 'data5' exist, it would return {1, 2, 5}. |
|||
local function getArgNums(prefix) |
|||
local nums = {} |
|||
for k, v in pairs(args) do |
|||
local num = tostring(k):match('^' .. prefix .. '([1-9]%d*)$') |
|||
if num then table.insert(nums, tonumber(num)) end |
|||
end |
|||
table.sort(nums) |
|||
return nums |
|||
end |
|||
-- Adds a row to the infobox, with either a header cell |
|||
-- or a label/data cell combination. |
|||
local function addRow(rowArgs) |
|||
if rowArgs.header and rowArgs.header ~= '_BLANK_' then |
|||
root |
|||
:tag('tr') |
|||
:addClass(rowArgs.rowclass) |
|||
:cssText(rowArgs.rowstyle) |
|||
:tag('th') |
|||
:attr('colspan', '2') |
|||
:addClass('infobox-header') |
|||
:addClass(rowArgs.class) |
|||
:addClass(args.headerclass) |
|||
-- @deprecated next; target .infobox-<name> .infobox-header |
|||
:cssText(args.headerstyle) |
|||
:cssText(rowArgs.rowcellstyle) |
|||
:wikitext(fixChildBoxes(rowArgs.header, 'th')) |
|||
if rowArgs.data then |
|||
--root:wikitext( |
|||
--'[[Category:Pages which use infobox templates with ignored data cells]]' |
|||
--) |
|||
end |
|||
elseif rowArgs.data and rowArgs.data:gsub( |
|||
category_in_empty_row_pattern, '' |
|||
):match('^%S') then |
|||
local row = root:tag('tr') |
|||
row:addClass(rowArgs.rowclass) |
|||
row:cssText(rowArgs.rowstyle) |
|||
if rowArgs.label then |
|||
row |
|||
:tag('th') |
|||
:attr('scope', 'row') |
|||
:addClass('infobox-label') |
|||
:cssText('white-space:nowrap;') |
|||
-- @deprecated next; target .infobox-<name> .infobox-label |
|||
:cssText(args.labelstyle) |
|||
:cssText(rowArgs.rowcellstyle) |
|||
:wikitext(rowArgs.label) |
|||
:done() |
|||
end |
|||
local dataCell = row:tag('td') |
|||
dataCell |
|||
:attr('colspan', not rowArgs.label and '2' or nil) |
|||
:addClass(not rowArgs.label and 'infobox-full-data' or 'infobox-data') |
|||
:addClass(rowArgs.class) |
|||
-- @deprecated next; target .infobox-<name> .infobox(-full)-data |
|||
:cssText(rowArgs.datastyle) |
|||
:cssText(rowArgs.rowcellstyle) |
|||
:wikitext(fixChildBoxes(rowArgs.data, 'td')) |
|||
else |
|||
table.insert(empty_row_categories, rowArgs.data or '') |
|||
end |
|||
end |
|||
local function renderTitle() |
|||
if not args.title then return end |
|||
root |
|||
:tag('caption') |
|||
:addClass('infobox-title') |
|||
:addClass(args.titleclass) |
|||
-- @deprecated next; target .infobox-<name> .infobox-title |
|||
:cssText(args.titlestyle) |
|||
:attr('itemprop', 'name') |
|||
:wikitext(args.title) |
|||
end |
|||
local function renderAboveRow() |
|||
if not args.above then return end |
|||
root |
|||
:tag('tr') |
|||
:tag('th') |
|||
:attr('colspan', '2') |
|||
:addClass('infobox-above') |
|||
:addClass(args.aboveclass) |
|||
-- @deprecated next; target .infobox-<name> .infobox-above |
|||
:cssText(args.abovestyle) |
|||
:attr('itemprop', args.aboveitemprop) |
|||
:attr('itemtype', args.aboveitemtype) |
|||
:attr('itemref', args.aboveitemref) |
|||
:wikitext(fixChildBoxes(args.above,'th')) |
|||
end |
|||
local function renderBelowRow() |
|||
if not args.below then return end |
|||
root |
|||
:tag('tr') |
|||
:tag('td') |
|||
:attr('colspan', '2') |
|||
:addClass('infobox-below') |
|||
:addClass(args.belowclass) |
|||
-- @deprecated next; target .infobox-<name> .infobox-below |
|||
:cssText(args.belowstyle) |
|||
:wikitext(fixChildBoxes(args.below,'td')) |
|||
end |
|||
local function addSubheaderRow(subheaderArgs) |
|||
if subheaderArgs.data and |
|||
subheaderArgs.data:gsub(category_in_empty_row_pattern, ''):match('^%S') then |
|||
local row = root:tag('tr') |
|||
row:addClass(subheaderArgs.rowclass) |
|||
local dataCell = row:tag('td') |
|||
dataCell |
|||
:attr('colspan', '2') |
|||
:addClass('infobox-subheader') |
|||
:addClass(subheaderArgs.class) |
|||
:cssText(subheaderArgs.datastyle) |
|||
:cssText(subheaderArgs.rowcellstyle) |
|||
:wikitext(fixChildBoxes(subheaderArgs.data, 'td')) |
|||
else |
|||
table.insert(empty_row_categories, subheaderArgs.data or '') |
|||
end |
|||
end |
|||
local function renderSubheaders() |
|||
if args.subheader then |
|||
args.subheader1 = args.subheader |
|||
end |
|||
if args.subheaderrowclass then |
|||
args.subheaderrowclass1 = args.subheaderrowclass |
|||
end |
|||
local subheadernums = getArgNums('subheader') |
|||
for k, num in ipairs(subheadernums) do |
|||
addSubheaderRow({ |
|||
data = args['subheader' .. tostring(num)], |
|||
-- @deprecated next; target .infobox-<name> .infobox-subheader |
|||
datastyle = args.subheaderstyle, |
|||
rowcellstyle = args['subheaderstyle' .. tostring(num)], |
|||
class = args.subheaderclass, |
|||
rowclass = args['subheaderrowclass' .. tostring(num)] |
|||
}) |
|||
end |
|||
end |
|||
local function addImageRow(imageArgs) |
|||
if imageArgs.data and |
|||
imageArgs.data:gsub(category_in_empty_row_pattern, ''):match('^%S') then |
|||
local row = root:tag('tr') |
|||
row:addClass(imageArgs.rowclass) |
|||
local dataCell = row:tag('td') |
|||
dataCell |
|||
:attr('colspan', '2') |
|||
:addClass('infobox-image') |
|||
:addClass(imageArgs.class) |
|||
:cssText(imageArgs.datastyle) |
|||
:wikitext(fixChildBoxes(imageArgs.data, 'td')) |
|||
else |
|||
table.insert(empty_row_categories, imageArgs.data or '') |
|||
end |
|||
end |
|||
local function renderImages() |
|||
if args.image then |
|||
args.image1 = args.image |
|||
end |
|||
if args.caption then |
|||
args.caption1 = args.caption |
|||
end |
|||
local imagenums = getArgNums('image') |
|||
for k, num in ipairs(imagenums) do |
|||
local caption = args['caption' .. tostring(num)] |
|||
local data = mw.html.create():wikitext(args['image' .. tostring(num)]) |
|||
if caption then |
|||
data |
|||
:tag('div') |
|||
:addClass('infobox-caption') |
|||
-- @deprecated next; target .infobox-<name> .infobox-caption |
|||
:cssText(args.captionstyle) |
|||
:wikitext(caption) |
|||
end |
|||
addImageRow({ |
|||
data = tostring(data), |
|||
-- @deprecated next; target .infobox-<name> .infobox-image |
|||
datastyle = args.imagestyle, |
|||
class = args.imageclass, |
|||
rowclass = args['imagerowclass' .. tostring(num)] |
|||
}) |
|||
end |
|||
end |
|||
-- When autoheaders are turned on, preprocesses the rows |
|||
local function preprocessRows() |
|||
if not args.autoheaders then return end |
|||
local rownums = union(getArgNums('header'), getArgNums('data')) |
|||
table.sort(rownums) |
|||
local lastheader |
|||
for k, num in ipairs(rownums) do |
|||
if args['header' .. tostring(num)] then |
|||
if lastheader then |
|||
args['header' .. tostring(lastheader)] = nil |
|||
end |
|||
lastheader = num |
|||
elseif args['data' .. tostring(num)] and |
|||
args['data' .. tostring(num)]:gsub( |
|||
category_in_empty_row_pattern, '' |
|||
):match('^%S') then |
|||
local data = args['data' .. tostring(num)] |
|||
if data:gsub(category_in_empty_row_pattern, ''):match('%S') then |
|||
lastheader = nil |
|||
end |
|||
end |
|||
end |
|||
if lastheader then |
|||
args['header' .. tostring(lastheader)] = nil |
|||
end |
|||
end |
|||
-- Gets the union of the header and data argument numbers, |
|||
-- and renders them all in order |
|||
local function renderRows() |
|||
local rownums = union(getArgNums('header'), getArgNums('data')) |
|||
table.sort(rownums) |
|||
for k, num in ipairs(rownums) do |
|||
addRow({ |
|||
header = args['header' .. tostring(num)], |
|||
label = args['label' .. tostring(num)], |
|||
data = args['data' .. tostring(num)], |
|||
datastyle = args.datastyle, |
|||
class = args['class' .. tostring(num)], |
|||
rowclass = args['rowclass' .. tostring(num)], |
|||
-- @deprecated next; target .infobox-<name> rowclass |
|||
rowstyle = args['rowstyle' .. tostring(num)], |
|||
rowcellstyle = args['rowcellstyle' .. tostring(num)] |
|||
}) |
|||
end |
|||
end |
|||
local function renderNavBar() |
|||
if not args.name and not args.tnavbar then return end |
|||
root |
|||
:tag('tr') |
|||
:tag('td') |
|||
:attr('colspan', '2') |
|||
:addClass('infobox-navbar') |
|||
:wikitext(require('Module:Navbar/sandbox')._navbar{ |
|||
template = args.name, |
|||
text = 'テンプレートを', |
|||
}) |
|||
end |
|||
local function loadTemplateStyles() |
|||
local frame = mw.getCurrentFrame() |
|||
local base_templatestyles = frame:extensionTag{ |
|||
name = 'templatestyles', args = { src = 'Template:Infobox/styles.css' } |
|||
} |
|||
return table.concat({ |
|||
base_templatestyles, |
|||
}) |
|||
end |
|||
local function _infobox() |
|||
args = require('Module:Arguments').getArgs(origArgs, {parentOnly = true}) --引数取得 |
|||
local child = (args.child == 'yes') |
local child = (args.child == 'yes') |
||
local subbox = (args.subbox == 'yes') |
local subbox = (args.subbox == 'yes') |
||
71行目: | 422行目: | ||
body[num][str] = (body[num][str] or '') .. v |
body[num][str] = (body[num][str] or '') .. v |
||
end |
end |
||
end |
|||
--[[ |
|||
Template:Infobox/row |
|||
]] |
|||
local function row(header, headerstyle, label, labelstyle, data, datastyle, rowstyle, class, rowclass, id, itemprop, rowitemprop, itemtype, rowitemtype, itemref, rowitemref) |
|||
local result ='' |
|||
if header then |
|||
result = '<tr style="' .. (rowstyle or '') ..'"' .. (rowitemtype and (' itemscope itemtype="' .. rowitemtype .. '"') or '') .. ' itemref="' .. (rowitemref or '') .. '"><th scope="col" colspan="2" class="' .. (class or '') .. '" style="text-align:center; ' .. (headerstyle or '') .. '">' .. header .. '</th></tr>' |
|||
elseif data then |
|||
result = '<tr class="' .. (rowclass or '') .. '" style="' .. (rowstyle or '') .. '" itemprop="' .. (rowitemprop or '') .. '"' .. (rowitemtype and (' itemscope itemtype="' .. rowitemtype .. '"') or '') .. ' itemref="' .. (rowitemref or '') .. '">' |
|||
if label then |
|||
result = result .. '<th scope="row" style="text-align:left; white-space:nowrap; ' .. (labelstyle or '') .. '">' .. label .. '</th><td class="' .. (class or '') .. '" style="' .. (datastyle or '') .. '" itemprop="' .. (itemprop or '') .. '"' .. (itemtype and (' itemscope itemtype="' .. itemtype .. '"') or '') .. ' itemref="' .. (itemref or '') .. '">' |
|||
else |
|||
result = result .. '<td colspan="2" class="' .. (class or '') .. '" style="text-align:center; ' .. (datastyle or '') .. '" itemprop="' .. (itemprop or '') .. '"' .. (itemtype and (' itemscope itemtype="' .. rowitemtype .. '"') or '') .. ' itemref="' .. (itemref or '') .. '">' |
|||
end |
|||
result = result .. '\n' .. data .. '</td></tr>' |
|||
end |
|||
return result |
|||
end |
end |
||
97行目: | 429行目: | ||
--ヘッダー部 |
--ヘッダー部 |
||
if not child then |
if not child then |
||
root = mw.html.create('table') |
|||
--tableタグ |
|||
result = '<table class="' .. (subbox and '' or 'infobox ') .. (args.bodyclass or '') .. '" style="' .. (subbox and 'min-width:100%; margin:-3px; ' or 'width:22em; ') .. (args.bodystyle or '') .. '"' .. (args.bodyitemtype and (' itemscope itemtype="' .. args.bodyitemtype .. '"') or '') .. ' itemref="' .. (args.bodyitemref or '') .. '">' |
|||
root |
|||
if args.title then |
|||
:addClass(args.subbox == 'yes' and 'infobox-subbox' or 'infobox') |
|||
--captionタグ |
|||
:addClass(args.bodyclass) |
|||
result = result .. '<caption itemprop="name" class="' .. (args.titleclass or '') .. ' style="' .. (args.titlestyle or '') .. '">' .. args.title .. '</caption>' |
|||
-- @deprecated next; target .infobox-<name> |
|||
end |
|||
:cssText(args.subbox == 'yes' and 'min-width:100%; width:calc(100% + 6px); margin:-3px;' or 'width:22em;') |
|||
if args.above then |
|||
:cssText(args.bodystyle) |
|||
result = result .. '<tr><th colspan="2" class="' .. (args.aboveclass or '') .. '" style="text-align:center; font-size:125%; font-weight:bold; ' .. (args.abovestyle or '') .. '" itemprop="' .. (args.aboveitemprop or '') .. '"' .. (args.aboveitemtype and (' itemscope itemtype="' .. args.aboveitemtype .. '"') or '') .. ' itemref="' .. (args.aboveitemref or '') .. '">' .. args.above ..'</th></tr>' |
|||
:attr('itemtype', args.bodyitemtype) |
|||
end |
|||
renderTitle() |
|||
renderAboveRow() |
|||
else |
else |
||
root = mw.html.create() |
|||
if args.title then |
|||
result = '<b itemprop="name' .. '"' .. (args.bodyitemtype and (' itemscope itemtype="' .. args.bodyitemtype .. '"') or '') .. ' itemref="' .. (args.bodyitemref or '') .. '">' .. args.title .. '</b>' |
|||
root |
|||
:tag('b') |
|||
:attr('itemprop', 'name') |
|||
:attr('itemtype', args.bodyitemtype) |
|||
:attr('itemref', args.bodyitemref) |
|||
:wikitext(args.title) |
|||
end |
end |
||
renderSubheaders() |
|||
for k, v in pairs(h.subheader) do |
|||
renderImages() |
|||
result = result .. row(nil, nil, nil, nil, v[1], v.style or h.subheader.style, v.rowstyle, h.subheader.class, v.rowclass, nil, nil, nil, nil, nil, nil, nil) |
|||
preprocessRows() |
|||
end |
|||
renderRows() |
|||
for k, v in pairs(h.image) do |
|||
renderBelowRow() |
|||
result = result .. row(nil, nil, nil, nil, v[1] and (v[1] .. (v.caption or '')), v.style or h.image.style, v.rowstyle, h.image.class, v.rowclass, nil, nil, nil, nil, nil, nil, nil) |
|||
renderNavBar() |
|||
end |
|||
--本体部ソート |
|||
for k, v in pairs(body) do |
|||
sbody[#sbody + 1] = v |
|||
end |
|||
table.sort(sbody, |
|||
function (a, b) return a[1] < b[1] end |
|||
) |
|||
--本体部 |
|||
for k, v in ipairs(sbody) do |
|||
result = result .. row(v.header, v.headerstyle, v.label, v.labelstyle, v.data, v.datastyle, v.rowstyle, v.class, v.rowclass, v.id, v.itemprop, v.rowitemprop, v.itemtype, v.rowitemtype, v.itemref, v.rowitemref) |
|||
end |
|||
--フッター部 |
|||
if args.below then |
|||
result = result .. '<tr><td colspan="2" class="' .. (args.belowclass or '') .. '" style="text-align:center; ' .. (args.belowstyle or '') .. '">' .. args.below .. '</td></tr>' |
|||
end |
|||
if link then |
|||
--Template:Transclude |
|||
link = string.gsub(link, ':?[Tt]emplate:', '') |
|||
if not string.find(link, ':') then |
|||
link = 'Template:' .. link |
|||
end |
|||
result = result .. '<tr class="noprint"><td colspan=2 style="text-align:right; font-size:85%;">[[' .. link .. '|テンプレートを表示]]</td></tr>' |
|||
end |
|||
--tableタグ閉じ |
--tableタグ閉じ |
||
151行目: | 465行目: | ||
--出力 |
--出力 |
||
return loadTemplateStyles() .. tostring(root) |
|||
return result |
|||
end |
|||
function p.infobox(frame) |
|||
-- If called via #invoke, use the args passed into the invoking template. |
|||
-- Otherwise, for testing purposes, assume args are being passed directly in. |
|||
if frame == mw.getCurrentFrame() then |
|||
origArgs = frame:getParent().args |
|||
else |
|||
origArgs = frame |
|||
end |
|||
-- parseDataParameters() -- 後ほど移入する |
|||
return _infobox() |
|||
end |
end |
||
2023年8月27日 (日) 14:33時点における最新版
これはモジュール:Infobox/former (差分)のモジュール・サンドボックスページです。 |
このLuaモジュールは550,000以上のページで使われています。 余計な混乱やサーバーへの負荷を避けるために、どんな変更でも最初はモジュールのサンドボックス・サブページ、テストケース・サブページで試すべきです。そうすれば、試した変更を1度の編集でこのモジュールに加えることができます。しかし、最初にあなたの提案した変更を、この項目のノートで議論するようにお願いします。 |
local p = {}
local args = {}
local origArgs = {}
local root
local empty_row_categories = {}
local category_in_empty_row_pattern = '%[%[%s*[Cc][Aa][Tt][Ee][Gg][Oo][Rr][Yy]%s*:[^]]*]]'
local function fixChildBoxes(sval, tt)
local function notempty( s ) return s and s:match( '%S' ) end
if notempty(sval) then
local marker = '<span class=special_infobox_marker>'
local s = sval
s = mw.ustring.gsub(s, '(<%s*[Tt][Rr])', marker .. '%1')
s = mw.ustring.gsub(s, '(</[Tt][Rr]%s*>)', '%1' .. marker)
if s:match(marker) then
s = mw.ustring.gsub(s, marker .. '%s*' .. marker, '')
s = mw.ustring.gsub(s, '([\r\n]|-[^\r\n]*[\r\n])%s*' .. marker, '%1')
s = mw.ustring.gsub(s, marker .. '%s*([\r\n]|-)', '%1')
s = mw.ustring.gsub(s, '(</[Cc][Aa][Pp][Tt][Ii][Oo][Nn]%s*>%s*)' .. marker, '%1')
s = mw.ustring.gsub(s, '(<%s*[Tt][Aa][Bb][Ll][Ee][^<>]*>%s*)' .. marker, '%1')
s = mw.ustring.gsub(s, '^(%{|[^\r\n]*[\r\n]%s*)' .. marker, '%1')
s = mw.ustring.gsub(s, '([\r\n]%{|[^\r\n]*[\r\n]%s*)' .. marker, '%1')
s = mw.ustring.gsub(s, marker .. '(%s*</[Tt][Aa][Bb][Ll][Ee]%s*>)', '%1')
s = mw.ustring.gsub(s, marker .. '(%s*\n|%})', '%1')
end
if s:match(marker) then
local subcells = mw.text.split(s, marker)
s = ''
for k = 1, #subcells do
if k == 1 then
s = s .. subcells[k] .. '</' .. tt .. '></tr>'
elseif k == #subcells then
local rowstyle = ' style="display:none"'
if notempty(subcells[k]) then rowstyle = '' end
s = s .. '<tr' .. rowstyle ..'><' .. tt .. ' colspan=2>\n' ..
subcells[k]
elseif notempty(subcells[k]) then
if (k % 2) == 0 then
s = s .. subcells[k]
else
s = s .. '<tr><' .. tt .. ' colspan=2>\n' ..
subcells[k] .. '</' .. tt .. '></tr>'
end
end
end
end
-- the next two lines add a newline at the end of lists for the PHP parser
-- [[Special:Diff/849054481]]
-- remove when [[:phab:T191516]] is fixed or OBE
s = mw.ustring.gsub(s, '([\r\n][%*#;:][^\r\n]*)$', '%1\n')
s = mw.ustring.gsub(s, '^([%*#;:][^\r\n]*)$', '%1\n')
s = mw.ustring.gsub(s, '^([%*#;:])', '\n%1')
s = mw.ustring.gsub(s, '^(%{%|)', '\n%1')
return s
else
return sval
end
end
-- Returns the union of the values of two tables, as a sequence.
local function union(t1, t2)
local vals = {}
for k, v in pairs(t1) do
vals[v] = true
end
for k, v in pairs(t2) do
vals[v] = true
end
local ret = {}
for k, v in pairs(vals) do
table.insert(ret, k)
end
return ret
end
-- Returns a table containing the numbers of the arguments that exist
-- for the specified prefix. For example, if the prefix was 'data', and
-- 'data1', 'data2', and 'data5' exist, it would return {1, 2, 5}.
local function getArgNums(prefix)
local nums = {}
for k, v in pairs(args) do
local num = tostring(k):match('^' .. prefix .. '([1-9]%d*)$')
if num then table.insert(nums, tonumber(num)) end
end
table.sort(nums)
return nums
end
-- Adds a row to the infobox, with either a header cell
-- or a label/data cell combination.
local function addRow(rowArgs)
if rowArgs.header and rowArgs.header ~= '_BLANK_' then
root
:tag('tr')
:addClass(rowArgs.rowclass)
:cssText(rowArgs.rowstyle)
:tag('th')
:attr('colspan', '2')
:addClass('infobox-header')
:addClass(rowArgs.class)
:addClass(args.headerclass)
-- @deprecated next; target .infobox-<name> .infobox-header
:cssText(args.headerstyle)
:cssText(rowArgs.rowcellstyle)
:wikitext(fixChildBoxes(rowArgs.header, 'th'))
if rowArgs.data then
--root:wikitext(
--'[[Category:Pages which use infobox templates with ignored data cells]]'
--)
end
elseif rowArgs.data and rowArgs.data:gsub(
category_in_empty_row_pattern, ''
):match('^%S') then
local row = root:tag('tr')
row:addClass(rowArgs.rowclass)
row:cssText(rowArgs.rowstyle)
if rowArgs.label then
row
:tag('th')
:attr('scope', 'row')
:addClass('infobox-label')
:cssText('white-space:nowrap;')
-- @deprecated next; target .infobox-<name> .infobox-label
:cssText(args.labelstyle)
:cssText(rowArgs.rowcellstyle)
:wikitext(rowArgs.label)
:done()
end
local dataCell = row:tag('td')
dataCell
:attr('colspan', not rowArgs.label and '2' or nil)
:addClass(not rowArgs.label and 'infobox-full-data' or 'infobox-data')
:addClass(rowArgs.class)
-- @deprecated next; target .infobox-<name> .infobox(-full)-data
:cssText(rowArgs.datastyle)
:cssText(rowArgs.rowcellstyle)
:wikitext(fixChildBoxes(rowArgs.data, 'td'))
else
table.insert(empty_row_categories, rowArgs.data or '')
end
end
local function renderTitle()
if not args.title then return end
root
:tag('caption')
:addClass('infobox-title')
:addClass(args.titleclass)
-- @deprecated next; target .infobox-<name> .infobox-title
:cssText(args.titlestyle)
:attr('itemprop', 'name')
:wikitext(args.title)
end
local function renderAboveRow()
if not args.above then return end
root
:tag('tr')
:tag('th')
:attr('colspan', '2')
:addClass('infobox-above')
:addClass(args.aboveclass)
-- @deprecated next; target .infobox-<name> .infobox-above
:cssText(args.abovestyle)
:attr('itemprop', args.aboveitemprop)
:attr('itemtype', args.aboveitemtype)
:attr('itemref', args.aboveitemref)
:wikitext(fixChildBoxes(args.above,'th'))
end
local function renderBelowRow()
if not args.below then return end
root
:tag('tr')
:tag('td')
:attr('colspan', '2')
:addClass('infobox-below')
:addClass(args.belowclass)
-- @deprecated next; target .infobox-<name> .infobox-below
:cssText(args.belowstyle)
:wikitext(fixChildBoxes(args.below,'td'))
end
local function addSubheaderRow(subheaderArgs)
if subheaderArgs.data and
subheaderArgs.data:gsub(category_in_empty_row_pattern, ''):match('^%S') then
local row = root:tag('tr')
row:addClass(subheaderArgs.rowclass)
local dataCell = row:tag('td')
dataCell
:attr('colspan', '2')
:addClass('infobox-subheader')
:addClass(subheaderArgs.class)
:cssText(subheaderArgs.datastyle)
:cssText(subheaderArgs.rowcellstyle)
:wikitext(fixChildBoxes(subheaderArgs.data, 'td'))
else
table.insert(empty_row_categories, subheaderArgs.data or '')
end
end
local function renderSubheaders()
if args.subheader then
args.subheader1 = args.subheader
end
if args.subheaderrowclass then
args.subheaderrowclass1 = args.subheaderrowclass
end
local subheadernums = getArgNums('subheader')
for k, num in ipairs(subheadernums) do
addSubheaderRow({
data = args['subheader' .. tostring(num)],
-- @deprecated next; target .infobox-<name> .infobox-subheader
datastyle = args.subheaderstyle,
rowcellstyle = args['subheaderstyle' .. tostring(num)],
class = args.subheaderclass,
rowclass = args['subheaderrowclass' .. tostring(num)]
})
end
end
local function addImageRow(imageArgs)
if imageArgs.data and
imageArgs.data:gsub(category_in_empty_row_pattern, ''):match('^%S') then
local row = root:tag('tr')
row:addClass(imageArgs.rowclass)
local dataCell = row:tag('td')
dataCell
:attr('colspan', '2')
:addClass('infobox-image')
:addClass(imageArgs.class)
:cssText(imageArgs.datastyle)
:wikitext(fixChildBoxes(imageArgs.data, 'td'))
else
table.insert(empty_row_categories, imageArgs.data or '')
end
end
local function renderImages()
if args.image then
args.image1 = args.image
end
if args.caption then
args.caption1 = args.caption
end
local imagenums = getArgNums('image')
for k, num in ipairs(imagenums) do
local caption = args['caption' .. tostring(num)]
local data = mw.html.create():wikitext(args['image' .. tostring(num)])
if caption then
data
:tag('div')
:addClass('infobox-caption')
-- @deprecated next; target .infobox-<name> .infobox-caption
:cssText(args.captionstyle)
:wikitext(caption)
end
addImageRow({
data = tostring(data),
-- @deprecated next; target .infobox-<name> .infobox-image
datastyle = args.imagestyle,
class = args.imageclass,
rowclass = args['imagerowclass' .. tostring(num)]
})
end
end
-- When autoheaders are turned on, preprocesses the rows
local function preprocessRows()
if not args.autoheaders then return end
local rownums = union(getArgNums('header'), getArgNums('data'))
table.sort(rownums)
local lastheader
for k, num in ipairs(rownums) do
if args['header' .. tostring(num)] then
if lastheader then
args['header' .. tostring(lastheader)] = nil
end
lastheader = num
elseif args['data' .. tostring(num)] and
args['data' .. tostring(num)]:gsub(
category_in_empty_row_pattern, ''
):match('^%S') then
local data = args['data' .. tostring(num)]
if data:gsub(category_in_empty_row_pattern, ''):match('%S') then
lastheader = nil
end
end
end
if lastheader then
args['header' .. tostring(lastheader)] = nil
end
end
-- Gets the union of the header and data argument numbers,
-- and renders them all in order
local function renderRows()
local rownums = union(getArgNums('header'), getArgNums('data'))
table.sort(rownums)
for k, num in ipairs(rownums) do
addRow({
header = args['header' .. tostring(num)],
label = args['label' .. tostring(num)],
data = args['data' .. tostring(num)],
datastyle = args.datastyle,
class = args['class' .. tostring(num)],
rowclass = args['rowclass' .. tostring(num)],
-- @deprecated next; target .infobox-<name> rowclass
rowstyle = args['rowstyle' .. tostring(num)],
rowcellstyle = args['rowcellstyle' .. tostring(num)]
})
end
end
local function renderNavBar()
if not args.name and not args.tnavbar then return end
root
:tag('tr')
:tag('td')
:attr('colspan', '2')
:addClass('infobox-navbar')
:wikitext(require('Module:Navbar/sandbox')._navbar{
template = args.name,
text = 'テンプレートを',
})
end
local function loadTemplateStyles()
local frame = mw.getCurrentFrame()
local base_templatestyles = frame:extensionTag{
name = 'templatestyles', args = { src = 'Template:Infobox/styles.css' }
}
return table.concat({
base_templatestyles,
})
end
local function _infobox()
args = require('Module:Arguments').getArgs(origArgs, {parentOnly = true}) --引数取得
local child = (args.child == 'yes')
local subbox = (args.subbox == 'yes')
local h = {subheader = {}, image = {{}}} --ヘッダー部(subheader, image)テーブル
local body, sbody = {}, {} --本体部テーブル, ソート済み本体部テーブル
local link = args.tnavbar or args.name --(フッター部)テンプレート名
local result = '' --結果格納用
--[[
subheader, image用引数振り分け
]]
local function args2tbl(str, k, v)
local num = string.match(k, '%d*$')
num = (num == '') and 1 or tonumber(num)
h[str][num] = h[str][num] or {}
if k == str then
h[str][1][1] = v
elseif string.match(k, str .. '%d+') then
h[str][num][1] = v
elseif string.find(k, 'style') then
if string.match(k, 'style$') then
h[str]['style'] = v
else
h[str][num]['style'] = v
end
elseif string.find(k, 'rowclass') then
if string.match(k, 'rowclass$') then
h[str]['rowclass'] = v
else
h[str][num]['rowclass'] = v
end
elseif string.match(k, 'class$') then
h[str]['class'] = v
end
end
--[[
引数振り分け
]]
for k, v in pairs(args) do
--subheader
if string.find(k, 'subheader') then
args2tbl('subheader', k, v)
--image
elseif string.find(k, 'image') then
args2tbl('image', k, v)
elseif string.find(k, 'caption') then
if string.match(k, 'caption$') then
h['image'][1]['caption'] = '<div style="' .. (args.captionstyle or '') .. '">' .. v .. '</div>'
elseif string.match(k, 'caption%d+') then
local num = tonumber(string.match(k, '%d*$'))
h['image'][num] = h['image'][num] or {}
h['image'][num]['caption'] = '<div style="' .. (args.captionstyle or '') .. '">' .. v .. '</div>'
end
--その他(本体部)
elseif string.match(k, '^%D+%d+$') then
local str, num = string.match(k, '^(%D+)(%d+)$')
num = tonumber(num)
if not body[num] then
local OddOrEven = (num % 2 ~= 0) and 'odd' or 'even'
body[num] = {
num,
headerstyle = (args.headerstyle or '') .. (args[OddOrEven .. 'headerstyle'] or ''),
labelstyle = (args.labelstyle or '') .. (args[OddOrEven .. 'labelstyle'] or ''),
datastyle = (args.datastyle or '') .. (args[OddOrEven .. 'datastyle'] or '')
}
end
body[num][str] = (body[num][str] or '') .. v
end
end
--[[
Template:Infobox
]]
--ヘッダー部
if not child then
root = mw.html.create('table')
root
:addClass(args.subbox == 'yes' and 'infobox-subbox' or 'infobox')
:addClass(args.bodyclass)
-- @deprecated next; target .infobox-<name>
:cssText(args.subbox == 'yes' and 'min-width:100%; width:calc(100% + 6px); margin:-3px;' or 'width:22em;')
:cssText(args.bodystyle)
:attr('itemtype', args.bodyitemtype)
renderTitle()
renderAboveRow()
else
root = mw.html.create()
root
:tag('b')
:attr('itemprop', 'name')
:attr('itemtype', args.bodyitemtype)
:attr('itemref', args.bodyitemref)
:wikitext(args.title)
end
renderSubheaders()
renderImages()
preprocessRows()
renderRows()
renderBelowRow()
renderNavBar()
--tableタグ閉じ
if not child then
result = result .. '</table>'
end
--出力
return loadTemplateStyles() .. tostring(root)
end
function p.infobox(frame)
-- If called via #invoke, use the args passed into the invoking template.
-- Otherwise, for testing purposes, assume args are being passed directly in.
if frame == mw.getCurrentFrame() then
origArgs = frame:getParent().args
else
origArgs = frame
end
-- parseDataParameters() -- 後ほど移入する
return _infobox()
end
return p