Moduł:Infobox: Różnice pomiędzy wersjami

Z PUTwiki
Przejdź do nawigacjiPrzejdź do wyszukiwania
m 1 wersja
 
(Nie pokazano 2 wersji utworzonych przez 2 użytkowników)
Linia 1: Linia 1:
require("strict")
local p = {}
local resources = mw.loadData("Moduł:Infobox/resources")
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 has_rows = false
local lists = {
plainlist_t = {
patterns = {
'^plainlist$',
'%splainlist$',
'^plainlist%s',
'%splainlist%s'
},
found = false,
styles = 'Plainlist/styles.css'
},
hlist_t = {
patterns = {
'^hlist$',
'%shlist$',
'^hlist%s',
'%shlist%s'
},
found = false,
styles = 'Hlist/styles.css'
}
}


local function P(frame, qid, pid)
local function has_list_class(args_to_check)
local sd = require("Module:Wikidane/select")
for _, list in pairs(lists) do
return sd.selectProperty(pid, sd.prepareFilters(frame), qid)
if not list.found then
for _, arg in pairs(args_to_check) do
for _, pattern in ipairs(list.patterns) do
if mw.ustring.find(arg or '', pattern) then
list.found = true
break
end
end
if list.found then break end
end
end
end
end
end


local function isNullOrWhiteSpace(text)
local function fixChildBoxes(sval, tt)
return (text == nil)
local function notempty( s ) return s and s:match( '%S' ) end
or (#text <= 0)
or string.match(text, "^%s+$")
if notempty(sval) then
local marker = '<span class=special_infobox_marker>'
local s = sval
-- start moving templatestyles and categories inside of table rows
local slast = ''
while slast ~= s do
slast = s
s = mw.ustring.gsub(s, '(</[Tt][Rr]%s*>%s*)(%[%[%s*[Cc][Aa][Tt][Ee][Gg][Oo][Rr][Yy]%s*:[^]]*%]%])', '%2%1')
s = mw.ustring.gsub(s, '(</[Tt][Rr]%s*>%s*)(\127[^\127]*UNIQ%-%-templatestyles%-%x+%-QINU[^\127]*\127)', '%2%1')
end
-- end moving templatestyles and categories inside of table rows
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
end


local function addClass(attributes, class)
-- Cleans empty tables
if not class or (#class == 0) then
local function cleanInfobox()
return attributes
root = tostring(root)
end
if has_rows == false then
root = mw.ustring.gsub(root, '<table[^<>]*>%s*</table>', '')
if not attributes or (#attributes == 0) then
return "class=\""..class.."\""
end
end
local r, c = string.gsub(attributes or "", "%f[%w]class%s*=%s*['\"]", "%0"..class.." ", 1)
if c == 1 then
return r
end
return "class=\""..class.."\" "..attributes
end
end


local function iboxSpan(header, text, row, cell)
-- Returns the union of the values of two tables, as a sequence.
assert(type(header) == "boolean")
local function union(t1, t2)


local result = {}
local vals = {}
table.insert(result, "|-")
for k, v in pairs(t1) do
if row and (#row > 0) then
vals[v] = true
table.insert(result, " ")
end
table.insert(result, row)
for k, v in pairs(t2) do
vals[v] = true
end
end
 
local ret = {}
table.insert(result, "\n")
for k, v in pairs(vals) do
table.insert(result, header and "!" or "|")
table.insert(ret, k)
if cell and (#cell > 0) then
table.insert(result, cell)
table.insert(result,' ')
end
end
return ret
table.insert(result, 'colspan="2"|')
table.insert(result, text)
table.insert(result, "\n|-\n")
return table.concat(result)
end
end


local function emptyCategory(frame, emptyCat)
-- Returns a table containing the numbers of the arguments that exist
if not emptyCat or (mw.title.getCurrentTitle().namespace ~= 0) then
-- for the specified prefix. For example, if the prefix was 'data', and
return ""
-- 'data1', 'data2', and 'data5' exist, it would return {1, 2, 5}.
end
local function getArgNums(prefix)
local nums = {}
if mw.ustring.match(emptyCat, "%[%[[Kk]ategoria:.-%]%]") then
for k, v in pairs(args) do
return emptyCat
local num = tostring(k):match('^' .. prefix .. '([1-9]%d*)$')
if num then table.insert(nums, tonumber(num)) end
end
end
table.sort(nums)
local template = frame:getParent():getTitle()
return nums
local infobox = mw.ustring.match(template, "^Szablon:(.- infobox)$")
return mw.ustring.format(resources.catMissingData, infobox or template, emptyCat)
end
end


local function InputData(frame, Q, demo, source, sourcepropid)
-- Adds a row to the infobox, with either a header cell
local ns = mw.title.getCurrentTitle().namespace
-- or a label/data cell combination.
local add = frame.args["dodaj"]
local function addRow(rowArgs)
local cell = frame.args["pole"]
local propid = frame.args[sourcepropid or "cecha"]
local emptyCat = frame.args["kategoria brak"]
local value = frame.args[source or 1]
add = (add == nil) or (#add > 0)
if rowArgs.header and rowArgs.header ~= '_BLANK_' then
has_rows = true
has_list_class({ rowArgs.rowclass, rowArgs.class, args.headerclass })
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 using infobox templates with ignored data cells]]'
)
end
elseif rowArgs.data and rowArgs.data:gsub(category_in_empty_row_pattern, ''):match('^%S') then
has_rows = true
has_list_class({ rowArgs.rowclass, rowArgs.class })
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')
-- @deprecated next; target .infobox-<name> .infobox-label
:cssText(args.labelstyle)
:cssText(rowArgs.rowcellstyle)
:wikitext(rowArgs.label)
:done()
end


if emptyCat and (#emptyCat == 0) then
local dataCell = row:tag('td')
emptyCat = false
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
end


if propid and (#propid == 0) then
local function renderTitle()
propid = false
if not args.title then return end
end
if isNullOrWhiteSpace(value) then
value = false
end
local demovalue = false
if value then
demovalue = mw.ustring.match(value, "^%s*{{{(.-)}}}%s*$")
end
local wdvalue = false
if add and not demo and (not value or demovalue) and propid then
local pid, qid, prop = P(frame, Q, propid)
if pid and qid and prop then
value = require("Moduł:Wikidane/format").run(frame, pid, prop)
if not value or (#value <= 0) then
value = false
else
wdvalue = true
end
end
end


if add and not demo and (not value or (demovalue and not wdvalue)) and emptyCat then
has_rows = true
cell = addClass(cell, resources.classEmpty)
has_list_class({args.titleclass})
value = (value or "") .. emptyCategory(frame, emptyCat)
end
if not demo and demovalue then
root
cell = addClass(cell, resources.classMissingArg)
:tag('caption')
if ns == 0 then
:addClass('infobox-title')
value = value..resources.catMissingArg
:addClass(args.titleclass)
end
-- @deprecated next; target .infobox-<name> .infobox-title
end
:cssText(args.titlestyle)
:wikitext(args.title)
return add and value or false, cell, demovalue, propid
end
end


local function Qdemo(frame)
local function renderAboveRow()
local Q = frame:getParent().args.Q
if not args.above then return end
if Q and string.match(Q, "^%d") then
 
Q = "Q"..Q
has_rows = true
end
has_list_class({ args.aboveclass })
if Q then
-- jest Q to nie demo
return Q, false
end
for k, v in pairs(frame:getParent().args) do
root
-- nie ma Q lecz dowolny argument to również nie demo
:tag('tr')
return nil, false
:tag('th')
end
:attr('colspan', '2')
 
:addClass('infobox-above')
-- nie ma Q ani żadnego parametru, jeśli to źródło szablonu, to musi to być demo
:addClass(args.aboveclass)
return nil, (mw.title.getCurrentTitle().fullText == frame:getParent():getTitle())
-- @deprecated next; target .infobox-<name> .infobox-above
:cssText(args.abovestyle)
:wikitext(fixChildBoxes(args.above,'th'))
end
end


local function editWDlink(qid, pid)
local function renderBelowRow()
return "<span class=\"plainlinks wdlink\" title=\"edytuj dane z infoboxu w Wikidanych\">&#x5B;[https://www.wikidata.org/wiki/"..qid.."#"..pid.." e]&#x5D;</span>"
if not args.below then return end
end


local function imageWDdemo(pid)
has_rows = true
if pid then
has_list_class({ args.belowclass })
if string.match(pid, "^P%d+$") then
return "[[:d:Property:"..pid.."|"..pid.."]]"
end
return "<span class=\"wdimgdemo\">"..pid.."</span>"
root
end
: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
end


local function propertyLabel(frame, propid, propid2)
local function addSubheaderRow(subheaderArgs)
local lang = mw.getContentLanguage()
if subheaderArgs.data and
if not propid2 then
subheaderArgs.data:gsub(category_in_empty_row_pattern, ''):match('^%S') then
local pid, qid, prop = P(frame, propid, "P1629")
has_rows = true
if pid and qid and prop then
has_list_class({ subheaderArgs.rowclass, subheaderArgs.class })
mw.logObject(prop, "P1629")
local value = require("Moduł:Wikidane/format").run(frame, pid, prop)
local row = root:tag('tr')
if value and (#value > 0) then
row:addClass(subheaderArgs.rowclass)
value = mw.ustring.gsub(value, "(|)(%l)", function(bar, lcase) return bar..lang:ucfirst(lcase) end)
 
return lang:ucfirst(value)
local dataCell = row:tag('td')
end
dataCell
end
: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
end


local label1 = mw.wikibase.label(propid)
local function renderSubheaders()
if not label1 or (#label1 <= 0) then
if args.subheader then
return false
args.subheader1 = args.subheader
end
end
if args.subheaderrowclass then
if not propid2 then
args.subheaderrowclass1 = args.subheaderrowclass
return lang:ucfirst(label1)
end
end
local subheadernums = getArgNums('subheader')
local label2 = mw.wikibase.label(propid2)
for k, num in ipairs(subheadernums) do
if not label2 or (#label2 <= 0) then
addSubheaderRow({
return false
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
end
local function addImageRow(imageArgs)
if imageArgs.data and
imageArgs.data:gsub(category_in_empty_row_pattern, ''):match('^%S') then
has_rows = true
has_list_class({ imageArgs.rowclass, imageArgs.class })
local cp1 = { mw.ustring.codepoint(label1, 1, mw.ustring.len(label1)) }
local row = root:tag('tr')
local cp2 = { mw.ustring.codepoint(label2, 1, mw.ustring.len(label2)) }
row:addClass(imageArgs.rowclass)
local len = #cp1 < #cp2 and #cp1 or #cp2
-- find common suffix
local suffix = false
for i = 1, len do
if cp1[#cp1-i+1] ~= cp2[#cp2-i+1] then
suffix = len - i + 1
break
end
end


while (suffix < len) and (cp1[#cp1 - suffix + 1] ~= 32) do
local dataCell = row:tag('td')
suffix = suffix + 1
dataCell
end
:attr('colspan', '2')
:addClass('infobox-image')
if suffix < len then
:addClass(imageArgs.class)
label1 = mw.ustring.char(unpack(cp1, 1, #cp1 - suffix))
:cssText(imageArgs.datastyle)
:wikitext(fixChildBoxes(imageArgs.data, 'td'))
else
table.insert(empty_row_categories, imageArgs.data or '')
end
end
return lang:ucfirst(mw.text.trim(label1).." i "..mw.text.trim(label2))
end
end


local function makeDemoArg(wrap, ...)
local function renderImages()
local count = select('#', ...)
if args.image then
if count <= 0 then
args.image1 = args.image
return
end
end
 
if args.caption then
local items = {}
args.caption1 = args.caption
local index = 1
while index <= count do
local v = select(index, ...)
if v and (type(v) == "string") then
table.insert(items, v)
end
index = index + 1
end
end
local imagenums = getArgNums('image')
if #items <= 0 then
for k, num in ipairs(imagenums) do
return
local caption = args['caption' .. tostring(num)]
end
local data = mw.html.create():wikitext(args['image' .. tostring(num)])
 
if caption then
local prefix = wrap and "{{{" or ""
data
local suffix = wrap and "}}}" or ""
:tag('div')
return prefix..table.concat(items,"&#x7C;")..suffix
:addClass('infobox-caption')
end
-- @deprecated next; target .infobox-<name> .infobox-caption
 
:cssText(args.captionstyle)
local function SecondaryInfobox(templateTitle, message)
:wikitext(caption)
local contents = mw.title.getCurrentTitle():getContent()
local infoboxPattern = "{{ *(%f[%a][%a ]-%f[ ] infobox)%s*|"
local start = 1
while true do
mw.logObject(start, "Kolejny:start")
local s, e, n = mw.ustring.find(contents, infoboxPattern, start, false)
if not s then
break
end
end
addImageRow({
mw.logObject({s, e, n}, "Kolejny:find{s e n}")
data = tostring(data),
local prefix = mw.ustring.match(n, "^(%a-):")
-- @deprecated next; target .infobox-<name> .infobox-image
mw.logObject(prefix, "Kolejny:prefix")
datastyle = args.imagestyle,
local ns = 10
class = args.imageclass,
if prefix then
rowclass = args['imagerowclass' .. tostring(num)]
prefix = mw.getCurrentLang():ucfirst(prefix)
})
ns = mw.site.namespaces[prefix] or ns
end
mw.logObject(ns, "Kolejny:ns")
local infoboxTitle = mw.title.new(n, ns)
mw.logObject(infoboxTitle, "Kolejny:infoboxTitle")
if templateTitle == infoboxTitle then
mw.logObject(start == 1 and "" or message, "Kolejny:return")
return start == 1 and "" or message
end
start = e
end
end
mw.log("Kolejny: BRAK")
return mw.title.getCurrentTitle().namespace == 0
and "?" -- tego przypadku nie powinno być w przestrzeni głównej
or false -- a poza nią to nie ma takiego znaczenia
end
end


return {
-- When autoheaders are turned on, preprocesses the rows
["Q"] = function(frame)
local function preprocessRows()
local Q, demo = Qdemo(frame)
if not args.autoheaders then return end
return demo and "demo" or Q
end,
["Demo"] = function(frame)
local rownums = union(getArgNums('header'), getArgNums('data'))
local args = require('Module:Arguments').getArgs(frame, { trim = false, removeBlanks = false })
table.sort(rownums)
local result = {}
local lastheader
local i = 1
for k, num in ipairs(rownums) do
local wd = false
if args['header' .. tostring(num)] then
while true do
if lastheader then
local v = args[i]
args['header' .. tostring(lastheader)] = nil
i = i + 1
if not v then
break
end
end
lastheader = num
if #v == 0 then
elseif args['data' .. tostring(num)] and
if wd then
args['data' .. tostring(num)]:gsub(
table.insert(result, "")
category_in_empty_row_pattern, ''
end
):match('^%S') then
local data = args['data' .. tostring(num)]
wd = true
if data:gsub(category_in_empty_row_pattern, ''):match('%S') then
else
lastheader = nil
table.insert(result, wd and imageWDdemo(v) or v)
wd = false
end
end
end
end
end
if #result then
if lastheader then
local result = "{{{"..table.concat(result,"&#x7C;").."}}}"
args['header' .. tostring(lastheader)] = nil
mw.logObject(result, "result")
end
return result
end
end
 
end,
-- Gets the union of the header and data argument numbers,
-- and renders them all in order
["Kolejny"] = function(frame)
local function renderRows()
local message = frame.args[1]
if not message or (#mw.text.trim(message) == 0) then
message = "tak"
end
local templateTitle = mw.title.new(frame:getParent():getTitle())
return SecondaryInfobox(templateTitle, message)
end,


["Test"] = function(frame)
local rownums = union(getArgNums('header'), getArgNums('data'))
local Q, demo = Qdemo(frame)
table.sort(rownums)
if demo then
for k, num in ipairs(rownums) do
return "demo"
addRow({
end
header = args['header' .. tostring(num)],
label = args['label' .. tostring(num)],
local i = 1
data = args['data' .. tostring(num)],
local sd = require("Module:Wikidane/select")
datastyle = args.datastyle,
while true do
class = args['class' .. tostring(num)],
local pid = frame.args[i]
rowclass = args['rowclass' .. tostring(num)],
if not pid then
-- @deprecated next; target .infobox-<name> rowclass
return
rowstyle = args['rowstyle' .. tostring(num)],
end
rowcellstyle = args['rowcellstyle' .. tostring(num)]
})
local pid, qid, prop = sd.selectProperty(pid, {}, Q)
end
if qid then
end
return pid
end
i = i + 1
end
end,


["Tytuł"] = function(frame)
local function renderNavBar()
local Q, demo = Qdemo(frame)
if not args.name then return end
local emptyCat = frame.args["kategoria brak"]
local attrs = frame.args["pole"]
local props = frame.args["cecha"] or resources.defaultTitle2Property
local text1 = frame.args[1]
local text2 = frame.args[2]
local text3 = frame.args[3]
if isNullOrWhiteSpace(text1) then
text1 = false
end
if isNullOrWhiteSpace(text2) then
text2 = false
end
if isNullOrWhiteSpace(text3) then
text3 = false
end


local demo1 = false
has_rows = true
if text1 then
root
demo1 = mw.ustring.match(text1, "^{{{(.-)}}}$")
:tag('tr')
end
:tag('td')
local demo2 = false
:attr('colspan', '2')
if text2 then
:addClass('infobox-navbar')
demo2 = mw.ustring.match(text2, "^{{{(.-)}}}$")
:wikitext(require('Module:Navbar')._navbar{
end
args.name,
local demo3 = false
mini = 1,
if text3 then
})
demo3 = mw.ustring.match(text3, "^{{{(.-)}}}$")
end
end


local Q, demo = Qdemo(frame)
local function renderItalicTitle()
local italicTitle = args['italic title'] and mw.ustring.lower(args['italic title'])
if italicTitle == '' or italicTitle == 'force' or italicTitle == 'yes' then
root:wikitext(require('Module:Italic title')._main({}))
end
end


local builder = mw.html.create()
-- Categories in otherwise empty rows are collected in empty_row_categories.
builder:wikitext("|+")
-- This function adds them to the module output. It is not affected by
if attrs and (#attrs > 0) then
-- args.decat because this module should not prevent module-external categories
builder:wikitext(" ", attrs, " | ")
-- from rendering.
end
local function renderEmptyRowCategories()
for _, s in ipairs(empty_row_categories) do
root:wikitext(s)
end
end


local titleWithText = false
-- Render tracking categories. args.decat == turns off tracking categories.
local function appendPart(class)
local function renderTrackingCategories()
if titleWithText then
if args.decat == 'yes' then return end
builder:tag("br")
if args.child == 'yes' then
end
if args.title then
root:wikitext(
titleWithText = true
'[[Category:Pages using embedded infobox templates with the title parameter]]'
return builder:tag("span"):addClass(class)
)
end
end
elseif #(getArgNums('data')) == 0 and mw.title.getCurrentTitle().namespace == 0 then
local label = false
root:wikitext('[[Category:Articles using infobox templates with no data rows]]')
if demo and demo1 then
end
appendPart(resources.classTitle1):wikitext("{{{", demo1, "&#x7C;", imageWDdemo("Etykieta"), "}}}")
end
elseif demo then
appendPart(resources.classTitle1):wikitext(imageWDdemo("Etykieta"))
elseif text1 and (#text1 > 0) then
appendPart(resources.classTitle1):wikitext(text1)
else
label = mw.wikibase.label(Q)
if label then
appendPart(resources.classTitle1):wikitext(label)
end
end
local props1 = {}
local props2 = {}
for propid in string.gmatch(props, "%S+") do
table.insert(props1, propid)
table.insert(props2, "&#x7C;")
table.insert(props2, imageWDdemo(propid))
end
props2 = table.concat(props2, "")
mw.text.split(props, "%s")
if demo and demo2 then
appendPart(resources.classTitle2):wikitext("{{{", demo2, props2, "}}}")
elseif demo and (#props1 > 0) then
appendPart(resources.classTitle2):wikitext("{{{", props2, "}}}")
elseif text2 and (#text2 > 0) then
appendPart(resources.classTitle2):wikitext(text2)
elseif #props1 > 0 then
local pid, qid, prop
for _, propid in ipairs(props1) do
pid, qid, prop = P(frame, Q, propid)
if qid and prop then
local text2 = require("Moduł:Wikidane/format").run(frame, pid, prop)
if text2 then
local lang = mw.getContentLanguage()
local l = label and lang:caseFold(label) or label
local t1 = text1 and lang:caseFold(text1) or text1
local t2, _ = mw.ustring.gsub(text2, "</?[A-Za-z]+ ?[^<>]*/?>", "") -- remove HTML tags
t2 = lang:caseFold(t2)
if (t2 ~= t1) and (t2 ~= l) then
appendPart(resources.classTitle2):wikitext(text2)
break
end
end
end
end
end
if text3 and (#text3 > 0) then
appendPart(resources.classTitle3):wikitext(text3)
end
if not titleWithText then
-- use page title
local title = mw.title.getCurrentTitle()
local text = title.text
local nodisambig = mw.ustring.match(text, "^(.-)%s+%([^%(%)]+%)$")
if nodisambig and (#nodisambig > 0) then
text = nodisambig
end
appendPart(resources.classEmpty):wikitext(text, emptyCategory(frame, emptyCat))
end
if not titleWithText then
-- no text
return
end
builder:wikitext("\n")
return builder:allDone()
end,


["Grafika"] = function(frame)
--[=[
local add = frame.args["dodaj"]
Loads the templatestyles for the infobox.
add = (add == nil) or (#add > 0)
if not add then
return
end
local function formatFile(file, alt, format, description)
local function removeLinks(text)
--mw.logObject(text, "RemoveLinks:input")
if text then
text = mw.ustring.gsub(text, "%s+", " ") -- compact white characters into one space
text = mw.ustring.gsub(text, "%[https?://[^%[%]%s|]+%]", "") -- remove LZ
text = mw.ustring.gsub(text, "%[https?://[^%[%]%s|]+ ([^%[%]|]+)%]", "%1") -- remove LZ, leave description
text = mw.ustring.gsub(text, "%[%[[^%[%]|]+|([^%[%]|]*)%]%]", "%1" ) -- remove wikilinks, leave description
text = mw.ustring.gsub(text, "%[%[([^%[%]|]*)%]%]", "%1" ) -- remove wikilinks, leave description
text = mw.ustring.gsub(text, "%s+", " ") -- compact white characters into one space again
text = mw.text.nowiki(text)
end
--mw.logObject(text, "RemoveLinks:output")
return text
end


local result = {}
TODO: FINISH loading base templatestyles here rather than in
table.insert(result, "[[Plik:")
MediaWiki:Common.css. There are 4-5000 pages with 'raw' infobox tables.
table.insert(result, file)
See [[Mediawiki_talk:Common.css/to_do#Infobox]] and/or come help :).
if format and (#format > 0) then
When we do this we should clean up the inline CSS below too.
table.insert(result, "|")
Will have to do some bizarre conversion category like with sidebar.
table.insert(result, format)
if mw.ustring.match(format, "^%s*alt%s*=") or mw.ustring.match(format, "|%s*alt%s*=") then
alt = false
end
end
if alt and (#alt > 0) then
table.insert(result, "|alt=")
table.insert(result, removeLinks(alt))
end
if description and (#description > 0) then
table.insert(result, "|")
table.insert(result, removeLinks(description))
end
table.insert(result,"]]")
return table.concat(result)
end
local function checkIfFileExists(file)
local pattern, _ = mw.ustring.gsub( file, "([%(%)%.%%%+%-%*%?%[%^%$%]])", "%%%1" )
pattern, _ = mw.ustring.gsub(pattern, "[ _]", "[ _]")
pattern = "%[%[%s*(%a+)%s*:"..pattern.."%s*[%]|]"
--mw.logObject(pattern, "Grafika:checkIfFileExists PATTERN")
local contents = mw.title.getCurrentTitle():getContent()
local start = 1
while true do
--mw.logObject(start, "Grafika:checkIfFileExists NEXT")
local s, e, n = mw.ustring.find(contents, pattern, start, false)
if not s then
--mw.logObject(file, "Grafika:checkIfFileExists FALSE")
return false
end
--mw.logObject({n,file}, "Grafika:checkIfFileExists{n,file}")
local title = mw.title.new(file, n)
if title and (title.namespace == 6) then
--mw.logObject(file, "Grafika:checkIfFileExists TRUE")
return true
end
start = e
end
end
local Q, demo = Qdemo(frame)
local row = frame.args["wiersz"]
local cell = frame.args["pole"]
local format = frame.args["format"]
local imageTitle = false
local secondary = false
local callingTemplate = frame:getParent():getTitle()
if mw.title.new(callingTemplate) == mw.title.new("Szablon:Infobox grafika") then
imageTitle = frame:getParent().args["tytuł grafiki"]
secondary = frame:getParent().args["kolejny"]
else
imageTitle = frame.args["tytuł grafiki"]
if (#callingTemplate > 8) and (mw.ustring.sub(callingTemplate, -8) == " infobox") then
secondary = SecondaryInfobox(callingTemplate, callingTemplate)
end
end


if format and (#format <= 0) then
]=]
format = nil
local function loadTemplateStyles()
end
local frame = mw.getCurrentFrame()
mw.logObject(secondary,"secondary")
local hlist_templatestyles = ''
if lists.hlist_t.found then
local wdExists = false
hlist_templatestyles = frame:extensionTag{
name = 'templatestyles', args = { src = lists.hlist_t.styles }
local function loadPicture(file, description, fileProperty, descProperty, defaultFormat)
}
if file == "nie" then
end
return
end
local plainlist_templatestyles = ''
if lists.plainlist_t.found then
if isNullOrWhiteSpace(file) then
plainlist_templatestyles = frame:extensionTag{
file = false
name = 'templatestyles', args = { src = lists.plainlist_t.styles }
description = false
}
elseif isNullOrWhiteSpace(description) then
end
description = false
end
-- See function description
local base_templatestyles = frame:extensionTag{
if isNullOrWhiteSpace(fileProperty) then
name = 'templatestyles', args = { src = 'Module:Infobox/styles.css' }
fileProperty = false
}
descProperty = false
elseif isNullOrWhiteSpace(descProperty) then
descProperty = false
end
local alt = false
local desc = nil
local patched = false
if fileProperty then
alt = mw.wikibase.label(fileProperty)
end
local demoFile = false
local demoDescription = false
if file then
demoFile = mw.ustring.match(file, "^{{{(.-)}}}$")
if not demoFile then
file = mw.ustring.gsub(file, "%s*[Pp]lik%s*:%s*", "Plik:")
file = mw.ustring.gsub(file, "%s*[Ff]ile%s*:%s*", "Plik:")
file = mw.ustring.gsub(file, "%s*[Gg]rafika%s*:%s*", "Plik:")
file = mw.ustring.gsub(file, "%s*[Ii]mage%s*:%s*", "Plik:")
if mw.ustring.match(file, "^Plik:(.*)") then
    file = mw.ustring.match(file, "^Plik:(.*)")
    patched = true
elseif mw.ustring.match(file, "%[%[Plik:([^%[%]|]+)[|%]]") then
    file = mw.ustring.match(file, "%[%[Plik:([^%[%]|]+)[|%]]")
    patched = true
end
end
end
if description then
demoDescription = mw.ustring.match(description, "^{{{(.-)}}}$")
end
if not demo and (not file or demoFile) and fileProperty then
if secondary and (#secondary > 0) then
mw.logObject(secondary, "Grafika: nie ładuję obrazka z Wikidanych na drugim lub kolejnym infoboksie")
return
end
local pid, qid, prop = P(frame, Q, fileProperty)
if pid and qid and prop then
for _, v in ipairs(prop) do
if v.mainsnak and (v.mainsnak.snaktype == "value") and (v.mainsnak.datatype == "commonsMedia") and v.mainsnak.datavalue and (v.mainsnak.datavalue.type == "string") then
local commonMedia = v.mainsnak.datavalue.value
if not isNullOrWhiteSpace(commonMedia) then
if checkIfFileExists(commonMedia) then
mw.logObject(commonMedia, "Grafika: obrazek, który jest oferowany w Wikidanych, już jest umieszczony w kodzie strony")
wdExists = true
return
end
file = commonMedia
alt = mw.wikibase.label(v.mainsnak.property)
desc = require("Moduł:Wikidane/format/qualifiers").TEXT1(v, nil, "P2096")
break
end
end
end
end
if file and descProperty then
pid, qid, prop = P(frame, Q, descProperty)
if pid and qid and prop then
local v = require("Moduł:Wikidane/format").run(frame, pid, prop)
if not isNullOrWhiteSpace(v) then
description = v
end
end
end
end
if not demo and file then
return {
formatFile(file, alt, format or defaultFormat, desc or description)..(patched and resources.catPatchedFile or ""),
description or desc
}
end
if demo and (demoFile or fileProperty) then
return {
formatFile(makeDemoArg(true, demoFile, imageWDdemo(fileProperty)), alt, format or defaultFormat, false),
makeDemoArg(true, demoDescription, imageWDdemo(descProperty))
}
end
end


local args = {
local templatestyles = ''
file = "grafika", description = "opis grafiki", fileProperty = "cecha", descProperty = "cecha opisu", defaultFormat = "250x250px",
if args['templatestyles'] then
fileN = "%d. grafika", descriptionN = "%d. opis grafiki", filePropertyN = "%d. cecha", descPropertyN = "%d. cecha opisu", defaultFormatN = "100x100px",
templatestyles = frame:extensionTag{
name = 'templatestyles', args = { src = args['templatestyles'] }
}
}
end
local bigImage = loadPicture(frame.args[args.file], frame.args[args.description], frame.args[args.fileProperty], frame.args[args.descProperty], args.defaultFormat)
mw.logObject(bigImage, "bigImage")
local smallImages = {}
local index = 1
while true do
local file = frame.args[mw.ustring.format(args.fileN, index)]
local description = frame.args[mw.ustring.format(args.descriptionN, index)]
local fileProperty = frame.args[mw.ustring.format(args.filePropertyN, index)]
local descProperty = frame.args[mw.ustring.format(args.descPropertyN, index)]
if not file and not fileProperty then
break
end
index = index + 1
local image = loadPicture(file, description, fileProperty, descProperty, args.defaultFormatN)
if image then
table.insert(smallImages, image)
end
end
local result = {}
if wdExists and secondary and (#secondary == 0) and (mw.title.getCurrentTitle().namespace == 0) then
table.insert(result, '|- style="display:none"\n| colspan="2" |"')
table.insert(result, resources.catIgnoreImage)
table.insert(result, '\n')
end
if bigImage then
if imageTitle and (#imageTitle > 0) then
table.insert(bigImage, 1, '<span style="font-weight: bold>'..imageTitle..'</span>')
end
table.insert(result, iboxSpan(false, table.concat(bigImage, "<br />"), row, cell))
end
if #smallImages > 0 then
local index = 1
table.insert(result, '|-')
table.insert(result, row)
table.insert(result, '\n|colspan="2" padding="0" ')
table.insert(result, cell)
table.insert(result, '|\n{| class="ibox2"\n')
-- display images in pairs
while (index + 1) <= #smallImages do
local image1 = smallImages[index + 0]
local image2 = smallImages[index + 1]
-- both files must exists
table.insert(result, '|-\n|')
table.insert(result, image1[1])
table.insert(result, '\n|')
table.insert(result, image2[1])
table.insert(result, '\n')
-- descriptions are optional
if image1[2] or image2[2] then
table.insert(result, '|-\n|')
table.insert(result, image1[2] or "")
table.insert(result, '\n|')
table.insert(result, image2[2] or "")
table.insert(result, '\n')
end
-- next pair
index = index + 2
end
-- display last odd image
if index == #smallImages then
local image = smallImages[index]
table.insert(result, '|-\n|colspan=2|')
table.insert(result, image[1])
table.insert(result, '\n')
if image[2] then
table.insert(result, '|-\n|colspan=2|')
table.insert(result, image[2])
table.insert(result, '\n')
end
end
table.insert(result, '|-\n|}\n|-\n')
end
if (#result > 0) and frame.args["dodaj zamykający wiersz"] then
-- łatka na wywołanie w szablonie wewnątrz #if:,
-- który obcina odstępy, w tym znak nowej linii
-- a domyślnie wynik kończy się tym znakiem
table.insert(result, '|-\n')
end
if #result > 0 then
return table.concat(result)
end
end,
["Grupa"] = function(frame)
local child_templatestyles = ''
local Q, demo = Qdemo(frame)
if args['child templatestyles'] then
local emptyCat = frame.args["kategoria brak"]
child_templatestyles = frame:extensionTag{
local header = frame.args["nagłówek"]
name = 'templatestyles', args = { src = args['child templatestyles'] }
local headerRow = frame.args["wiersz nagłówka"]
}
local headerCell = frame.args["pole nagłówka"]
end
local lineClass = frame.args["klasa kreski"]
local result = {}
local append = function(text)
if (#result == 0) and header then
local cell = headerCell
if #header == 0 then
cell = addClass(headerCell, resources.classEmpty)
header = emptyCategory(frame, emptyCat)
elseif not demo and mw.ustring.match(header, "^{{{(.-)}}}$") then
cell = addClass(headerCell, resources.classMissingArg)
end
table.insert(result, iboxSpan(true, header, headerRow, cell))
end
table.insert(result, text)
end
local total = false
local sep = false
local i = 1
while true do
local arg = frame.args[i]
if not arg then
break
end
i = i + 1
arg = string.match(arg, "^(.-)%s*$") -- trim remaing space
if arg == "-" then
sep = true
elseif #arg > 0 then -- real content
local next = false
for line in mw.text.gsplit(arg, "\n%f[|!]", false) do
if next then
append("\n")
end
next = true
if sep and (#line >= 2) and (string.byte(line, 1) == 124) and (string.byte(line, 2) == 45) then
-- row with separator line
local class = string.match(line, 'class="(.-)"')
local newClass = resources.classSeparator
if lineClass and (#lineClass > 0) then
newClass = newClass.." "..lineClass
end
if class then
line = string.gsub(line, 'class="', 'class="'..newClass.." ", 1)
else
line = mw.text.trim(line)..' class="'..newClass..'"'
end
else
-- content or row without separator line
sep = false
end
append(line)
end
end
end
return table.concat(result)
local grandchild_templatestyles = ''
end,
if args['grandchild templatestyles'] then
grandchild_templatestyles = frame:extensionTag{
name = 'templatestyles', args = { src = args['grandchild templatestyles'] }
}
end
["Blok"] = function(frame)
return table.concat({
local Q, demo = Qdemo(frame)
-- hlist -> plainlist -> base is best-effort to preserve old Common.css ordering.
local headerRow = frame.args["wiersz nagłówka"]
-- this ordering is not a guarantee because the rows of interest invoking
local headerCell = frame.args["pole nagłówka"]
-- each class may not be on a specific page
local row = frame.args["wiersz"]
hlist_templatestyles,
local label = frame.args["nagłówek"]
plainlist_templatestyles,
local value, cell, demovalue, propid = InputData(frame, Q, demo)
base_templatestyles,
templatestyles,
child_templatestyles,
grandchild_templatestyles
})
end


if label == "-" then
-- common functions between the child and non child cases
label = false
local function structure_infobox_common()
row = addClass(row, resources.classSeparator)
renderSubheaders()
elseif label and (#label == 0) then
renderImages()
label = false
preprocessRows()
elseif not label and propid then
renderRows()
label = propertyLabel(frame, propid)
renderBelowRow()
end
renderNavBar()
renderItalicTitle()
local demolabel = false
renderEmptyRowCategories()
if label then
renderTrackingCategories()
demolabel = mw.ustring.match(label, "^{{{(.-)}}}$")
cleanInfobox()
end
end
local text = false
if demo and demovalue and propid then
text = "{{{"..demovalue.."&#x7C;"..imageWDdemo(propid).."}}}"
elseif demo and propid then
text = "{{{"..imageWDdemo(propid).."}}}"
elseif demo and demolabel then
text = "{{{"..demovalue.."}}}"
elseif value then
text = value
end
if not text then
return
end
local header
if label == false then
header = false
elseif label and (#label > 0) then
header = label
elseif demo and demolabel and propid then
header = "{{{"..demolabel.."&#x7C;"..imageWDdemo("label").."}}}"
elseif demo and propid then
header = "{{{"..imageWDdemo("label").."}}}"
elseif demo and demolabel then
header = "{{{"..demolabel.."}}}"
elseif propid then
header = "{{{nagłówek}}}"..resources.catMissingLabel
elseif demo then
header = "{{{nagłówek}}}"
end
local result = {}
if header then
table.insert(result, iboxSpan(true, header, headerRow, headerCell))
end
table.insert(result, iboxSpan(false, text, row, cell))
return table.concat(result)
end,


["Wiersz"] = function(frame)
-- Specify the overall layout of the infobox, with special settings if the
local Q, demo = Qdemo(frame)
-- infobox is used as a 'child' inside another infobox.
local row = frame.args["wiersz"]
local function _infobox()
local label = frame.args["etykieta"]
if args.child ~= 'yes' then
local value, cell, demovalue, propid = InputData(frame, Q, demo)
root = mw.html.create('table')


if label and (#label == 0) then
root
label = false
:addClass(args.subbox == 'yes' and 'infobox-subbox' or 'infobox')
end
:addClass(args.bodyclass)
-- @deprecated next; target .infobox-<name>
:cssText(args.bodystyle)
if not label and propid then
has_list_class({ args.bodyclass })
label = propertyLabel(frame, propid)
 
end
renderTitle()
renderAboveRow()
local demolabel = false
else
if label then
root = mw.html.create()
demolabel = mw.ustring.match(label, "^{{{(.-)}}}$")
end
local builder = mw.html.create()
builder:wikitext("|-")
if row and (#row > 0) then
builder:wikitext(" ", row, " | ")
end


builder:wikitext("\n! ")
root
:wikitext(args.title)
if label and (#label > 0) then
end
builder:wikitext(label)
structure_infobox_common()
elseif demo and demolabel and propid then
builder:wikitext("{{{", demolabel, "&#x7C;", imageWDdemo("label"), "}}}")
elseif demo and propid then
builder:wikitext("{{{", imageWDdemo("label"), "}}}")
elseif demo and demolabel then
builder:wikitext("{{{", demolabel, "}}}")
elseif propid then
builder:wikitext("{{{etykieta}}}", resources.catMissingLabel)
else
builder:wikitext("{{{etykieta}}}")
end
builder:wikitext("\n| ")
if cell and (#cell > 0) then
builder:wikitext(cell)
builder:wikitext("| ")
end
if demo and demovalue and propid then
builder:wikitext("{{{", demovalue, "&#x7C;", imageWDdemo(propid), "}}}")
elseif demo and propid then
builder:wikitext("{{{", imageWDdemo(propid), "}}}")
elseif demo and demovalue then
builder:wikitext("{{{", demovalue, "}}}")
elseif value then
builder:wikitext(value)
else
return
end
builder:wikitext("\n|-")
return builder:allDone()
end,
["Wiersz2"] = function(frame)
return loadTemplateStyles() .. root
local Q, demo = Qdemo(frame)
end
local row = frame.args["wiersz"]
local label = frame.args["etykieta"]
local label1 = frame.args["etykieta 1"]
local label2 = frame.args["etykieta 2"]
local value1, cell, demovalue1, propid1 = InputData(frame, Q, demo, 1, "cecha 1")
local value2, _, demovalue2, propid2 = InputData(frame, Q, demo, 2, "cecha 2")


if label and (#label == 0) then
-- If the argument exists and isn't blank, add it to the argument table.
label = false
-- Blank arguments are treated as nil to match the behaviour of ParserFunctions.
end
local function preprocessSingleArg(argName)
if origArgs[argName] and origArgs[argName] ~= '' then
if not label and propid1 and propid2 then
args[argName] = origArgs[argName]
label = propertyLabel(frame, propid1, propid2)
end
end
end


if label1 and (#label1 == 0) then
-- Assign the parameters with the given prefixes to the args table, in order, in
label1 = false
-- batches of the step size specified. This is to prevent references etc. from
end
-- appearing in the wrong order. The prefixTable should be an array containing
-- tables, each of which has two possible fields, a "prefix" string and a
if not label1 and propid1 then
-- "depend" table. The function always parses parameters containing the "prefix"
label1 = propertyLabel(frame, propid1)
-- string, but only parses parameters in the "depend" table if the prefix
end
-- parameter is present and non-blank.
local function preprocessArgs(prefixTable, step)
if type(prefixTable) ~= 'table' then
error("Non-table value detected for the prefix table", 2)
end
if type(step) ~= 'number' then
error("Invalid step value detected", 2)
end


if label2 and (#label2 == 0) then
-- Get arguments without a number suffix, and check for bad input.
label2 = false
for i,v in ipairs(prefixTable) do
if type(v) ~= 'table' or type(v.prefix) ~= "string" or
(v.depend and type(v.depend) ~= 'table') then
error('Invalid input detected to preprocessArgs prefix table', 2)
end
end
preprocessSingleArg(v.prefix)
if not label2 and propid2 then
-- Only parse the depend parameter if the prefix parameter is present
label2 = propertyLabel(frame, propid2)
-- and not blank.
if args[v.prefix] and v.depend then
for j, dependValue in ipairs(v.depend) do
if type(dependValue) ~= 'string' then
error('Invalid "depend" parameter value detected in preprocessArgs')
end
preprocessSingleArg(dependValue)
end
end
end
end


local demolabel1 = false
-- Get arguments with number suffixes.
if label1 then
local a = 1 -- Counter variable.
demolabel1 = mw.ustring.match(label1, "^{{{(.-)}}}$")
local moreArgumentsExist = true
end
while moreArgumentsExist == true do
moreArgumentsExist = false
local demolabel2 = false
for i = a, a + step - 1 do
if label2 then
for j,v in ipairs(prefixTable) do
demolabel2 = mw.ustring.match(label2, "^{{{(.-)}}}$")
local prefixArgName = v.prefix .. tostring(i)
end
if origArgs[prefixArgName] then
-- Do another loop if any arguments are found, even blank ones.
local builder = mw.html.create()
moreArgumentsExist = true
builder:wikitext("|-")
preprocessSingleArg(prefixArgName)
if row and (#row > 0) then
builder:wikitext(" ", row, " | ")
end
 
builder:wikitext("\n! ")
if demo then
if label and (#label > 0) then
builder:wikitext(label)
else
if label1 and (#label1 > 0) then
builder:wikitext(label1)
elseif demolabel1 and propid1 then
builder:wikitext("{{{", demolabel1, "&#x7C;", imageWDdemo("label1"), "}}}")
elseif propid1 then
builder:wikitext("{{{", imageWDdemo("label1"), "}}}")
elseif demolabel1 then
builder:wikitext("{{{", demolabel1, "}}}")
elseif propid1 then
builder:wikitext("{{{etykieta 1}}}", resources.catMissingLabel)
else
builder:wikitext("{{{etykieta 1}}}")
end
end
builder:wikitext(" i ")
-- Process the depend table if the prefix argument is present
if label2 and (#label2 > 0) then
-- and not blank, or we are processing "prefix1" and "prefix" is
builder:wikitext(label2)
-- present and not blank, and if the depend table is present.
elseif demolabel2 and propid2 then
if v.depend and (args[prefixArgName] or (i == 1 and args[v.prefix])) then
builder:wikitext("{{{", demolabel2, "&#x7C;", imageWDdemo("label2"), "}}}")
for j,dependValue in ipairs(v.depend) do
elseif propid2 then
local dependArgName = dependValue .. tostring(i)
builder:wikitext("{{{", imageWDdemo("label2"), "}}}")
preprocessSingleArg(dependArgName)
elseif demolabel2 then
end
builder:wikitext("{{{", demolabel2, "}}}")
elseif propid2 then
builder:wikitext("{{{etykieta 2}}}", resources.catMissingLabel)
else
builder:wikitext("{{{etykieta 2}}}")
end
end
end
end
elseif value1 and value2 and label then
builder:wikitext(label)
elseif value1 and value2 and label1 and label2 then
builder:wikitext(label1, " i ", label2)
elseif value1 and value2 then
builder:wikitext("{{{etykieta}}}", resources.catMissingLabel)
elseif value1 and label1 then
builder:wikitext(label1)
elseif value1 then
builder:wikitext("{{{etykieta 1}}}", resources.catMissingLabel)
elseif value2 and label2 then
builder:wikitext(label2)
elseif value2 then
builder:wikitext("{{{etykieta 2}}}", resources.catMissingLabel)
else
return
end
end
a = a + step
end
end
-- Parse the data parameters in the same order that the old {{infobox}} did, so
-- that references etc. will display in the expected places. Parameters that
-- depend on another parameter are only processed if that parameter is present,
-- to avoid phantom references appearing in article reference lists.
local function parseDataParameters()
preprocessSingleArg('autoheaders')
preprocessSingleArg('child')
preprocessSingleArg('bodyclass')
preprocessSingleArg('subbox')
preprocessSingleArg('bodystyle')
preprocessSingleArg('title')
preprocessSingleArg('titleclass')
preprocessSingleArg('titlestyle')
preprocessSingleArg('above')
preprocessSingleArg('aboveclass')
preprocessSingleArg('abovestyle')
preprocessArgs({
{prefix = 'subheader', depend = {'subheaderstyle', 'subheaderrowclass'}}
}, 10)
preprocessSingleArg('subheaderstyle')
preprocessSingleArg('subheaderclass')
preprocessArgs({
{prefix = 'image', depend = {'caption', 'imagerowclass'}}
}, 10)
preprocessSingleArg('captionstyle')
preprocessSingleArg('imagestyle')
preprocessSingleArg('imageclass')
preprocessArgs({
{prefix = 'header'},
{prefix = 'data', depend = {'label'}},
{prefix = 'rowclass'},
{prefix = 'rowstyle'},
{prefix = 'rowcellstyle'},
{prefix = 'class'}
}, 50)
preprocessSingleArg('headerclass')
preprocessSingleArg('headerstyle')
preprocessSingleArg('labelstyle')
preprocessSingleArg('datastyle')
preprocessSingleArg('below')
preprocessSingleArg('belowclass')
preprocessSingleArg('belowstyle')
preprocessSingleArg('name')
-- different behaviour for italics if blank or absent
args['italic title'] = origArgs['italic title']
preprocessSingleArg('decat')
preprocessSingleArg('templatestyles')
preprocessSingleArg('child templatestyles')
preprocessSingleArg('grandchild templatestyles')
end


builder:wikitext("\n| ")
-- If called via #invoke, use the args passed into the invoking template.
if cell and (#cell > 0) then
-- Otherwise, for testing purposes, assume args are being passed directly in.
builder:wikitext(cell)
function p.infobox(frame)
builder:wikitext("| ")
if frame == mw.getCurrentFrame() then
end
origArgs = frame:getParent().args
else
local br = true
origArgs = frame
if demo and demovalue1 and propid1 then
end
builder:wikitext("{{{", demovalue1, "&#x7C;", imageWDdemo(propid1), "}}}")
elseif demo and propid1 then
builder:wikitext("{{{", imageWDdemo(propid1), "}}}")
elseif demo and demovalue1 then
builder:wikitext("{{{", demovalue1, "}}}")
elseif value1 then
builder:wikitext(value1)
else
br = false
end
if demo and demovalue2 and propid2 then
if br then builder:tag("br") end
builder:wikitext("{{{", demovalue2, "&#x7C;", imageWDdemo(propid2), "}}}")
elseif demo and propid2 then
if br then builder:tag("br") end
builder:wikitext("{{{", imageWDdemo(propid2), "}}}")
elseif demo and demovalue2 then
if br then builder:tag("br") end
builder:wikitext("{{{", demovalue2, "}}}")
elseif value2 then
if br then builder:tag("br") end
builder:wikitext(value2)
end
builder:wikitext("\n|-")
return builder:allDone()
end,
["Fragment"] = function(frame)
parseDataParameters()
local Q, demo = Qdemo(frame)
local value, unused, demovalue, propid = InputData(frame, Q, demo)
local text = false
if demo and demovalue and propid then
text = "{{{"..demovalue.."&#x7C;"..imageWDdemo(propid).."}}}"
elseif demo and propid then
text = "{{{"..imageWDdemo(propid).."}}}"
elseif demo and demolabel then
text =  "{{{"..demovalue.."}}}"
elseif value then
return value
end
return text and '|-\n|colspan="2"| '..text.."\n" or ""
end,
["Drzewo"] = function(frame)
return _infobox()
local Q, demo = Qdemo(frame)
end
local headerRow = frame.args["wiersz nagłówka"]
local headerCell = frame.args["pole nagłówka"]
local header = frame.args["nagłówek"]
local row = frame.args["wiersz"] or 'class="tree"'
local cell = frame.args["pole"]
local text = false
if demo then
text = imageWDdemo("'''Skrypt Lua'''")
else
if not Q then
local entity = mw.wikibase.getEntity()
if not entity then
return
end
Q = entity.id
end
text = require("Module:Wikidane/Tree").classTree(frame, Q)
end
if not text then
return
end
if header == "-" then
header = false
row = addClass(row, resources.classSeparator)
elseif header and (#header == 0) then
label = false
end
local result = {}
if header then
table.insert(result, iboxSpan(true, header, headerRow, headerCell))
end
table.insert(result, iboxSpan(false, text, row, cell))
return table.concat(result, "")
end,


["Projekt"] = function(frame)
-- For calling via #invoke within a template
local Q, demo = Qdemo(frame)
function p.infoboxTemplate(frame)
local entity = mw.wikibase.getEntity(Q)
origArgs = {}
local standardLink = function(sitelink)
for k,v in pairs(frame.args) do origArgs[k] = mw.text.trim(v) end
return entity and entity.sitelinks and entity.sitelinks[sitelink] and entity.sitelinks[sitelink].title
end
parseDataParameters()
local standardProp = function(pid)
local pid, qid, prop = require("Module:Wikidane/select").selectProperty(pid, {}, Q)
if prop and prop[1] then
local snak = prop[1].mainsnak
if (snak.snaktype == "value") and (snak.datatype == "string") then
return snak.datavalue.value
end
end
end
local demoProp = function(sitelink, arg)
local demovalue = false
if arg then
demovalue = mw.ustring.match(arg, "^{{{(.-)}}}$")
end
local result = {}
if demovalue then
table.insert(result, "&#8203;") -- wrap here
table.insert(result, "{{{")
table.insert(result, demovalue)
table.insert(result, "&#x7C;&#8203;")
table.insert(result, imageWDdemo(sitelink))
table.insert(result, "}}}&#8203;")
else
table.insert(result, "&#8203;")
table.insert(result, imageWDdemo(sitelink))
table.insert(result, "&#8203;")
end
return table.concat(result)
end
local projects = {
{
arg = "wikipedia",
icon = "wikipedia",
text = function()
if demo then
return "Wikipedia w języku [[:d:Property:P424|P424]]"
end
local wikilang = arg or standardProp("P424")
if wikilang == "pl" then
return "Wikipedia w [[Wikipedia:Strona główna|języku polskim]]"
end
if wikilang then
return mw.ustring.format("Wikipedia w [[:%s:|języku %s]]", wikilang, mw.loadData("Module:Lang/data")[wikilang].miejscownik)
end
end,
},
{
arg = "c",
icon = "commons",
text = function(arg)
local link = false
if demo then
link = demoProp("commonswiki", arg)
elseif arg then
link = arg
else
link = standardLink("commonswiki")
if not link then
local cat = standardProp("P373")
if cat then
link = "Category:"..cat
else
--or standardProp("P910") -- main category article
end
end
end
if link then
return mw.ustring.format("[[commons:%s|Multimedia w Wikimedia Commons]]", link)
end
end,
},
{
arg = "n",
icon = "wikinews",
text = function(arg)
local link = demo and demoProp("plwikinews", arg) or (arg or standardLink("plwikinews"))
if link then
return mw.ustring.format("[[n:%s|Wiadomości w Wikinews]]", link)
end
end,
},
{
arg = "q",
icon = "wikicytaty",
text = function(arg)
local link = demo and demoProp("plwikiquote", arg) or (arg or standardLink("plwikiquote"))
if link then
return mw.ustring.format("[[q:%s|Teksty w Wikicytatach]]", link)
end
end,
},
{
arg = "s",
icon = "wikiźródła",
text = function(arg)
local link = demo and demoProp("plwikisource", arg) or (arg or standardLink("plwikisource"))
if link then
return mw.ustring.format("[[s:%s|Teksty w Wikiźródłach]]", link)
end
end,
},
{
arg = "wikt",
icon = "wikisłownik",
text = function(arg)
-- nie ma jeszcze linków w Wikidanych
local link = arg or (demo and "" or false)
if link then
return mw.ustring.format("[[wikt:%s|Hasło w Wikisłowniku]]", link)
end
end,
},
{
arg = "wikispecies",
icon = "wikispecies",
text = function(arg)
local link = demo and demoProp("specieswiki", arg) or (arg or standardLink("specieswiki"))
if link then
return mw.ustring.format("[[wikispecies:%s|Systematyka w Wikispecies]]", link)
end
end,
},
{
arg = "voy",
icon = "wikipodróże",
text = function(arg)
local link = demo and demoProp("plwikivoyage", arg) or (arg or standardLink("plwikivoyage"))
if link then
return mw.ustring.format("[[voy:%s|Informacje w Wikipodróżach]]", link)
end
end,
},
{
arg = "b",
icon = "wikibooks",
text = function(arg)
local link = demo and demoProp("plwikibooks", arg) or (arg or standardLink("plwikibooks"))
if link then
return mw.ustring.format("[[b:%s|Książki w Wikibooks]]", link)
end
end,
},
{
arg = "wikt:cat",
icon = "wikisłownik",
text = function(arg)
if demo then
return "W Wikisłowniku: słownik języka [[:d:Property:P424|P424]]"
end
if arg then
local data = mw.loadData("Module:Lang/data")[standardProp("P424") or ""]
return mw.ustring.format("W Wikisłowniku: [[wikt:Kategoria:%s|słownik języka%s]]", arg, data and (" "..data["dopełniacz"]) or "")
end
end,
},
}
local result = {}
return _infobox()
for _, project in ipairs(projects) do
end
local param = frame.args[project.arg]
return p
if param then
local text = project.text(#param > 0 and param or nil)
if text then
if #result == 0 then
local header = frame.args["nagłówek"] or resources.defaultProjectHeader
if #header > 0 then
table.insert(result, iboxSpan(true, header, frame.args["wiersz nagłówka"], frame.args["pole nagłówka"]))
end
end
--local icon = "<div style=\"float:left; margin-right: 0.5em\">[[Plik:"..require("Module:Ikona").plik(project.icon).."|20px]]</div>"
local icon = "[[Plik:"..require("Module:Ikona").plik(project.icon).."|20px|link=|alt=]]"
table.insert(result, iboxSpan(false, icon..text, addClass(frame.args["wiersz"], resources.classSisterProject), frame.args["pole"]))
end
end
end
return table.concat(result, "")
end,
 
["Państwo"] = function(frame)
local Q, demo = Qdemo(frame)
if not Q then
Q = mw.wikibase.getEntityIdForCurrentPage()
end
if not Q then
return
end
local statements = mw.wikibase.getBestStatements(Q, "P17")
local errorCat = frame.args.kategoria
local link = frame.args.link
local altlink = frame.args.altlink
local nazwa = frame.args.nazwa
local opis = frame.args.opis
local results = {}
for i, s in ipairs(statements) do
local countryName = mw.wikibase.renderSnak(s.mainsnak)
local templateCountry = mw.title.new("Państwo dane "..countryName, "Szablon")
local result
if templateCountry.exists then
local dependent = frame:expandTemplate{ title = "Terytorium zależne", args = {
[1] = countryName,
[2] = countryName
}}
if dependent and (#dependent == 0) then
dependent = nil
end
result = frame:expandTemplate{ title = templateCountry.text, args = {
[1] = "infobox państwo/core",
wariant = dependent or countryName,
link = link,
altlink = altlink,
nazwa = nazwa,
rozmiar = i == 1 and opis or "&nbsp;"
}}
else -- nie ma szablonu państwa
result = frame:expandTemplate{ title = "Infobox wiersz", args = {
[1] = "[[Państwo]]",
[2] = errorCat.."WD"..tostring(i)..": "..countryName,
kol2 = 'class="linksInherit" style="background:yellow; color:red;"'
}}
end
if result then
table.insert(results, result)
end
end
return table.concat(results)
end,
 
}

Aktualna wersja na dzień 21:56, 7 gru 2025

Funkcja zwraca wartość opcjonalnego pola Q w wywołaniu szablonu (infoboksu), który ma wskazywać na źródłowy element w Wikidanych, jeśli szablon jest używany poza przestrzenią główną. Na stronie definiującej szablon (kod źródłowy infoboksu) zwraca wartość „demo”. Jeśli parametr nie został podany zwraca tekst pusty. Z tego parametru domyślnie korzystają pozostałe funkcje modułu, które próbują uzupełnić automatycznie brakujące dane.

Funkcja renderująca zapis pola z demonstracją odwołania do Wikidanych. Przyjmuję listę nazw argumentów będących nazwami pól szablonu lub cech z Wikidanych. Cechy są identyfikowane pustą nazwą poprzedzającą.

{{#invoke:Infobox|Demo|nazwa||wd}}Błąd skryptu: nie ma takiej funkcji „Demo”.

Kolejny

[edytuj kod]

Funkcja do wywołania bezpośrednio z infoboksu sprawdzająca czy szablon ją wywołujący jest kolejnym infoboksem na stronie. Działa przy założeniu, że na stronie osadzone są infoboksy różnych typów.

pole wartość domyślna opis
1 tak Treść zwracana jako wynik jeśli szablon infoboksu nie jest pierwszy na stronie.

Funkcja sprawdzająca czy istnieje jakakolwiek zdefiniowana cecha w Wikidanych z podanej listy. Każdą cechę należy podać w oddzielnym parametrze. Na stronie definiującej szablon zwraca niepustą wartość („demo”).

pole wartość domyślna opis
parametr indeksowany brak Identyfikator cechy w postaci Pnnnn.

Tytuł

[edytuj kod]
Błąd skryptu: nie ma takiej funkcji „Tytuł”.

Funkcja generuje nagłówek infoboksu – odpowiednik {{infobox tytuł}}. Jest to pole nagłówka tabeli definiowane jako |+. Teksty kolejnych poziomów są oddzielane znacznikiem nowej linii (<br>).

pole wartość domyślna opis
kategoria brak brak Nazwa kategorii generowanej w artykule, jeśli wygenerowany nagłówek jest pusty. Można podać pełny wikilink do kategorii lub ostatni człon nazwy (zwykle nazwa pola). Standardowa nazwa [[Kategoria:Infoboksy – brak danych – ''nazwa infoboksu'' – ''kategoria brak'']] zostanie wygenerowana automatycznie. Jeśli parametru nie podano to kategoria nie jest generowana.
pole brak Atrybuty nagłówka tabeli.
cecha P1705 P1448 Lista cech, z których pierwsza niepusta wartość będzie użyta jako treść drugiego poziomu, jeśli nie podano jej jawnie w parametrze. Domyślnie są to „nazwa oryginalna” lub „nazwa oficjalna”.
1 Etykieta z Wikidanych Tekst główny nagłówka infoboksu. Niepusta treść jest owijana w <span class="iboxt1">.
2 Pierwsza niepusta wartość cechy z listy przekazanej przez pole cecha Tekst drugiego poziomu nagłówka infoboksu. Niepusta treść jest owijana w <span class="iboxt2">.
3 brak Tekst trzeciego poziomu nagłówka infoboksu. Niepusta treść jest owijana w <span class="iboxt3">.

Grafika

[edytuj kod]

Funkcja do wstawiania sekcji obrazkowej. Składa się ona z jednego opcjonalnego dużego obrazka i opcjonalnej listy małych ilustracji umieszczanych w parach obok siebie.

pole wartość domyślna opis
wiersz brak Opcjonalne atrybuty wiersza.
dodaj brak Dodatkowy warunek wyświetlania treści infoboksu. Wartość pusta oznacza, że nie zostania wygenerowana żadna treść w infoboksie.
pole brak Atrybuty komórki tabeli z wartością wyświetlaną.
format 250x250px lub 100x100px Zwykle rozmiar obrazka.
grafika brak Nazwa pliku na commons użytego jako ilustracja albo wartość nie w celu wyłączenia wyświetlania ilustracji. Domyślnym formatem dla tej grafiki jest 250x250px.
opis grafiki brak Opcjonalny opis umieszczany pod ilustracją.
cecha brak Identyfikator cechy w Wikidanych zawierającą wskazanie do pliku na commons.
cecha opisu brak Identyfikator cechy z artykułem opisującym ilustrację (np. herb lub flagę).
N. grafika[mini 1] brak Nazwa pliku na commons użytego jako ilustracja albo wartość nie w celu wyłączenia wyświetlania ilustracji. Domyślnym formatem dla tej grafiki jest 100x100px.
N. opis grafiki[mini 1] brak Opcjonalny opis umieszczany pod ilustracją.
N. cecha[mini 1] brak Identyfikator cechy w Wikidanych zawierającą wskazanie do pliku na commons.
N. cecha opisu[mini 1] brak Identyfikator cechy z artykułem opisującym ilustrację (np. herb lub flagę).
  1. 1,0 1,1 1,2 1,3 Lista małych obrazków wprowadzana jest przez parametry z dodatkowym indeksem N. numerowanym od 1 w górę. Są one umieszczane w dwukolumnowej tabeli ze stylem class="ibox2".

Grupa

[edytuj kod]

Funkcja ułatwiająca generowanie grup wierszy z nagłówkiem.

pole wartość domyślna opis
kategoria brak brak Nazwa kategorii generowanej w artykule, jeśli podany (wygenerowany) nagłówek jest pusty. Można podać pełny wikilink do kategorii lub ostatni człon nazwy (zwykle nazwa pola). Standardowa nazwa [[Kategoria:Infoboksy – brak danych – ''nazwa infoboksu'' – ''kategoria brak'']] zostanie wygenerowana automatycznie. Jeśli parametru nie podano to kategoria nie jest generowana.
nagłówek brak Tytuł nagłówka grupy.
pole nagłówka brak Atrybuty pola nagłówka.
wiersz nagłówka brak Atrybuty wiersza nagłówka.
klasa kreski iboxs Klasa dodawana do atrybutu class wiersza tabeli, gdy wymagana jest kreska. Odpowiedni styl powinien być zdefiniowany w globalnym common.css.
parametry indeksowane brak Treść wierszy infoboksu lub „-” w miejscu gdzie ma być separator. Wiersze infoboksu muszą być generowane jako fragment tabeli w wikikodzie.
Błąd skryptu: nie ma takiej funkcji „Blok”.

Elementarny generator pionowego pola infoboksu (z opisem nad wartością). Generowane są tylko niepuste wartości. Domyślnie generowana treść ma postać:

<strong class="error"><span class="scribunto-error mw-scribunto-error-94db6fa2">Błąd skryptu: nie ma takiej funkcji „Blok”.</span></strong>
pole wartość domyślna opis
wiersz nagłówka brak Atrybuty wiersza tabeli z nagłówkiem.
pole nagłówka brak Atrybuty komórki tabeli z nagłówkiem.
wiersz brak Atrybuty wiersza tabeli z wartością wyświetlaną.
nagłówek brak Tytuł nagłówka.
dodaj brak Dodatkowy warunek wyświetlania treści infoboksu. Wartość pusta oznacza, że nie zostania wygenerowana żadna treść w infoboksie.
pole brak Atrybuty komórki tabeli z wartością wyświetlaną.
cecha brak Identyfikator cechy w Wikidanych, której wartość będzie wyświetlana jeśli nie zostanie jawnie przekazana w wywołaniu. Może być również źródłem nazwy nagłówka, jeśli nie jest podany, a jednocześnie istnieje polska etykieta dla podanej cechy w Wikidanych.
kategoria brak brak Nazwa kategorii generowanej w artykule, jeśli wygenerowany tekst jest pusty. Można podać pełny wikilink do kategorii lub ostatni człon nazwy (zwykle nazwa pola). Standardowa nazwa [[Kategoria:Infoboksy – brak danych – ''nazwa infoboksu'' – ''kategoria brak'']] zostanie wygenerowana automatycznie. Jeśli parametru nie podano to kategoria nie jest generowana.
1 brak Wartość wyświetlana.

Wiersz

[edytuj kod]
Błąd skryptu: nie ma takiej funkcji „Wiersz”.

Elementarny generator pola infoboksu. Generowane są tylko niepuste wartości. Domyślnie generowana treść ma postać:

<strong class="error"><span class="scribunto-error mw-scribunto-error-308c6710">Błąd skryptu: nie ma takiej funkcji „Wiersz”.</span></strong>
pole wartość domyślna opis
wiersz brak Opcjonalne atrybuty wiersza.
etykieta brak Tytuł pola opisu wartości.
dodaj brak Dodatkowy warunek wyświetlania treści infoboksu. Wartość pusta oznacza, że nie zostania wygenerowana żadna treść w infoboksie.
pole brak Atrybuty komórki tabeli z wartością wyświetlaną.
cecha brak Identyfikator cechy w Wikidanych, której wartość będzie wyświetlana jeśli nie zostanie jawnie przekazana w wywołaniu. Może być również źródłem nazwy nagłówka, jeśli nie jest podany, a jednocześnie istnieje polska etykieta dla podanej cechy w Wikidanych.
kategoria brak brak Nazwa kategorii generowanej w artykule, jeśli wygenerowany tekst jest pusty. Można podać pełny wikilink do kategorii lub ostatni człon nazwy (zwykle nazwa pola). Standardowa nazwa [[Kategoria:Infoboksy – brak danych – ''nazwa infoboksu'' – ''kategoria brak'']] zostanie wygenerowana automatycznie. Jeśli parametru nie podano to kategoria nie jest generowana.
1 brak Wartość wyświetlana.

Drzewo

[edytuj kod]

TODO

Projekt

[edytuj kod]
Błąd skryptu: nie ma takiej funkcji „Projekt”.

Generator linków do projektów siostrzanych. Aby włączyć linkowanie do określonego projektu siostrzanego należy podać jawny parametr (nawet pusty) odpowiedzialny za jego prezentację.

pole wartość domyślna opis
wiersz nagłówka brak Atrybuty wiersza tabeli z nagłówkiem.
pole nagłówka brak Atrybuty komórki tabeli z nagłówkiem.
wiersz brak Atrybuty wiersza tabeli z wartością wyświetlaną.
nagłówek W projektach Wikimedia Tytuł nagłówka. Jeśli podany pusty to nagłówek nie jest wyświetlany.
pole brak Atrybuty komórki tabeli z wartością wyświetlaną.
wikipedia brak Włącza generowanie linku do innej wersji językowej Wikipedii. Zastosowanie dla {{język infobox}}.
c brak Włącza generowanie linku do commons.
n brak Włącza generowanie linku do Wikinews.
q brak Włącza generowanie linku do Wikicytatów.
s brak Włącza generowanie linku do Wikiźródeł.
wikt brak Włącza generowanie linku do hasła w Wikisłowniku.
wikispecies brak Włącza generowanie linku do Wikispecies.
voy brak Włącza generowanie linku do Wikipodróży.
b brak Włącza generowanie linku do Wikibooks.
wikt:cat brak Włącza generowanie linku do kategorii w Wikisłowniku.

Państwo

[edytuj kod]

Funkcja pomocnicza dla {{Infobox państwo}} generująca wyniki na podstawie cechy [[:d:Property:P17|]] (P17) w Wikidanych.


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 has_rows = false
local lists = {
	plainlist_t = {
		patterns = {
			'^plainlist$',
			'%splainlist$',
			'^plainlist%s',
			'%splainlist%s'
		},
		found = false,
		styles = 'Plainlist/styles.css'
	},
	hlist_t = {
		patterns = {
			'^hlist$',
			'%shlist$',
			'^hlist%s',
			'%shlist%s'
		},
		found = false,
		styles = 'Hlist/styles.css'
	}
}

local function has_list_class(args_to_check)
	for _, list in pairs(lists) do
		if not list.found then
			for _, arg in pairs(args_to_check) do
				for _, pattern in ipairs(list.patterns) do
					if mw.ustring.find(arg or '', pattern) then
						list.found = true
						break
					end
				end
				if list.found then break end
			end
		end
	end
end

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
		-- start moving templatestyles and categories inside of table rows
		local slast = ''
		while slast ~= s do
			slast = s
			s = mw.ustring.gsub(s, '(</[Tt][Rr]%s*>%s*)(%[%[%s*[Cc][Aa][Tt][Ee][Gg][Oo][Rr][Yy]%s*:[^]]*%]%])', '%2%1')
			s = mw.ustring.gsub(s, '(</[Tt][Rr]%s*>%s*)(\127[^\127]*UNIQ%-%-templatestyles%-%x+%-QINU[^\127]*\127)', '%2%1')
		end
		-- end moving templatestyles and categories inside of table rows
		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

-- Cleans empty tables
local function cleanInfobox()
	root = tostring(root)
	if has_rows == false then
		root = mw.ustring.gsub(root, '<table[^<>]*>%s*</table>', '')
	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
		has_rows = true
		has_list_class({ rowArgs.rowclass, rowArgs.class, args.headerclass })
		
		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 using infobox templates with ignored data cells]]'
			)
		end
	elseif rowArgs.data and rowArgs.data:gsub(category_in_empty_row_pattern, ''):match('^%S') then
		has_rows = true
		has_list_class({ rowArgs.rowclass, rowArgs.class })
		
		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')
					-- @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

	has_rows = true
	has_list_class({args.titleclass})
	
	root
		:tag('caption')
			:addClass('infobox-title')
			:addClass(args.titleclass)
			-- @deprecated next; target .infobox-<name> .infobox-title
			:cssText(args.titlestyle)
			:wikitext(args.title)
	
end

local function renderAboveRow()
	if not args.above then return end

	has_rows = true
	has_list_class({ args.aboveclass })
	
	root
		:tag('tr')
			:tag('th')
				:attr('colspan', '2')
				:addClass('infobox-above')
				:addClass(args.aboveclass)
				-- @deprecated next; target .infobox-<name> .infobox-above
				:cssText(args.abovestyle)
				:wikitext(fixChildBoxes(args.above,'th'))
end

local function renderBelowRow()
	if not args.below then return end

	has_rows = true
	has_list_class({ args.belowclass })
	
	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
		has_rows = true
		has_list_class({ subheaderArgs.rowclass, subheaderArgs.class })
		
		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

		has_rows = true
		has_list_class({ imageArgs.rowclass, imageArgs.class })
		
		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 then return end

	has_rows = true
	root
		:tag('tr')
			:tag('td')
				:attr('colspan', '2')
				:addClass('infobox-navbar')
				:wikitext(require('Module:Navbar')._navbar{
					args.name,
					mini = 1,
				})
end

local function renderItalicTitle()
	local italicTitle = args['italic title'] and mw.ustring.lower(args['italic title'])
	if italicTitle == '' or italicTitle == 'force' or italicTitle == 'yes' then
		root:wikitext(require('Module:Italic title')._main({}))
	end
end

-- Categories in otherwise empty rows are collected in empty_row_categories.
-- This function adds them to the module output. It is not affected by
-- args.decat because this module should not prevent module-external categories
-- from rendering.
local function renderEmptyRowCategories()
	for _, s in ipairs(empty_row_categories) do
		root:wikitext(s)
	end
end

-- Render tracking categories. args.decat == turns off tracking categories.
local function renderTrackingCategories()
	if args.decat == 'yes' then return end
	if args.child == 'yes' then
		if args.title then
			root:wikitext(
				'[[Category:Pages using embedded infobox templates with the title parameter]]'
			)
		end
	elseif #(getArgNums('data')) == 0 and mw.title.getCurrentTitle().namespace == 0 then
		root:wikitext('[[Category:Articles using infobox templates with no data rows]]')
	end
end

--[=[
Loads the templatestyles for the infobox.

TODO: FINISH loading base templatestyles here rather than in
MediaWiki:Common.css. There are 4-5000 pages with 'raw' infobox tables.
See [[Mediawiki_talk:Common.css/to_do#Infobox]] and/or come help :).
When we do this we should clean up the inline CSS below too.
Will have to do some bizarre conversion category like with sidebar.

]=]
local function loadTemplateStyles()
	local frame = mw.getCurrentFrame()
	
	local hlist_templatestyles = ''
	if lists.hlist_t.found then
		hlist_templatestyles = frame:extensionTag{
			name = 'templatestyles', args = { src = lists.hlist_t.styles }
		}
	end
	
	local plainlist_templatestyles = ''
	if lists.plainlist_t.found then
		plainlist_templatestyles = frame:extensionTag{
			name = 'templatestyles', args = { src = lists.plainlist_t.styles }
		}
	end
	
	-- See function description
	local base_templatestyles = frame:extensionTag{
		name = 'templatestyles', args = { src = 'Module:Infobox/styles.css' }
	}

	local templatestyles = ''
	if args['templatestyles'] then
		templatestyles = frame:extensionTag{
			name = 'templatestyles', args = { src = args['templatestyles'] }
		}
	end
	
	local child_templatestyles = ''
	if args['child templatestyles'] then
		child_templatestyles = frame:extensionTag{
			name = 'templatestyles', args = { src = args['child templatestyles'] }
		}
	end
	
	local grandchild_templatestyles = ''
	if args['grandchild templatestyles'] then
		grandchild_templatestyles = frame:extensionTag{
			name = 'templatestyles', args = { src = args['grandchild templatestyles'] }
		}
	end
	
	return table.concat({
		-- hlist -> plainlist -> base is best-effort to preserve old Common.css ordering.
		-- this ordering is not a guarantee because the rows of interest invoking
		-- each class may not be on a specific page
		hlist_templatestyles,
		plainlist_templatestyles,
		base_templatestyles,
		templatestyles,
		child_templatestyles,
		grandchild_templatestyles
	})
end

-- common functions between the child and non child cases
local function structure_infobox_common()
	renderSubheaders()
	renderImages()
	preprocessRows()
	renderRows()
	renderBelowRow()
	renderNavBar()
	renderItalicTitle()
	renderEmptyRowCategories()
	renderTrackingCategories()
	cleanInfobox()
end

-- Specify the overall layout of the infobox, with special settings if the
-- infobox is used as a 'child' inside another infobox.
local function _infobox()
	if args.child ~= 'yes' 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.bodystyle)
		
		has_list_class({ args.bodyclass })

		renderTitle()
		renderAboveRow()
	else
		root = mw.html.create()

		root
			:wikitext(args.title)
	end
	structure_infobox_common()
	
	return loadTemplateStyles() .. root
end

-- If the argument exists and isn't blank, add it to the argument table.
-- Blank arguments are treated as nil to match the behaviour of ParserFunctions.
local function preprocessSingleArg(argName)
	if origArgs[argName] and origArgs[argName] ~= '' then
		args[argName] = origArgs[argName]
	end
end

-- Assign the parameters with the given prefixes to the args table, in order, in
-- batches of the step size specified. This is to prevent references etc. from
-- appearing in the wrong order. The prefixTable should be an array containing
-- tables, each of which has two possible fields, a "prefix" string and a
-- "depend" table. The function always parses parameters containing the "prefix"
-- string, but only parses parameters in the "depend" table if the prefix
-- parameter is present and non-blank.
local function preprocessArgs(prefixTable, step)
	if type(prefixTable) ~= 'table' then
		error("Non-table value detected for the prefix table", 2)
	end
	if type(step) ~= 'number' then
		error("Invalid step value detected", 2)
	end

	-- Get arguments without a number suffix, and check for bad input.
	for i,v in ipairs(prefixTable) do
		if type(v) ~= 'table' or type(v.prefix) ~= "string" or
			(v.depend and type(v.depend) ~= 'table') then
			error('Invalid input detected to preprocessArgs prefix table', 2)
		end
		preprocessSingleArg(v.prefix)
		-- Only parse the depend parameter if the prefix parameter is present
		-- and not blank.
		if args[v.prefix] and v.depend then
			for j, dependValue in ipairs(v.depend) do
				if type(dependValue) ~= 'string' then
					error('Invalid "depend" parameter value detected in preprocessArgs')
				end
				preprocessSingleArg(dependValue)
			end
		end
	end

	-- Get arguments with number suffixes.
	local a = 1 -- Counter variable.
	local moreArgumentsExist = true
	while moreArgumentsExist == true do
		moreArgumentsExist = false
		for i = a, a + step - 1 do
			for j,v in ipairs(prefixTable) do
				local prefixArgName = v.prefix .. tostring(i)
				if origArgs[prefixArgName] then
					-- Do another loop if any arguments are found, even blank ones.
					moreArgumentsExist = true
					preprocessSingleArg(prefixArgName)
				end
				-- Process the depend table if the prefix argument is present
				-- and not blank, or we are processing "prefix1" and "prefix" is
				-- present and not blank, and if the depend table is present.
				if v.depend and (args[prefixArgName] or (i == 1 and args[v.prefix])) then
					for j,dependValue in ipairs(v.depend) do
						local dependArgName = dependValue .. tostring(i)
						preprocessSingleArg(dependArgName)
					end
				end
			end
		end
		a = a + step
	end
end

-- Parse the data parameters in the same order that the old {{infobox}} did, so
-- that references etc. will display in the expected places. Parameters that
-- depend on another parameter are only processed if that parameter is present,
-- to avoid phantom references appearing in article reference lists.
local function parseDataParameters()

	preprocessSingleArg('autoheaders')
	preprocessSingleArg('child')
	preprocessSingleArg('bodyclass')
	preprocessSingleArg('subbox')
	preprocessSingleArg('bodystyle')
	preprocessSingleArg('title')
	preprocessSingleArg('titleclass')
	preprocessSingleArg('titlestyle')
	preprocessSingleArg('above')
	preprocessSingleArg('aboveclass')
	preprocessSingleArg('abovestyle')
	preprocessArgs({
		{prefix = 'subheader', depend = {'subheaderstyle', 'subheaderrowclass'}}
	}, 10)
	preprocessSingleArg('subheaderstyle')
	preprocessSingleArg('subheaderclass')
	preprocessArgs({
		{prefix = 'image', depend = {'caption', 'imagerowclass'}}
	}, 10)
	preprocessSingleArg('captionstyle')
	preprocessSingleArg('imagestyle')
	preprocessSingleArg('imageclass')
	preprocessArgs({
		{prefix = 'header'},
		{prefix = 'data', depend = {'label'}},
		{prefix = 'rowclass'},
		{prefix = 'rowstyle'},
		{prefix = 'rowcellstyle'},
		{prefix = 'class'}
	}, 50)
	preprocessSingleArg('headerclass')
	preprocessSingleArg('headerstyle')
	preprocessSingleArg('labelstyle')
	preprocessSingleArg('datastyle')
	preprocessSingleArg('below')
	preprocessSingleArg('belowclass')
	preprocessSingleArg('belowstyle')
	preprocessSingleArg('name')
	-- different behaviour for italics if blank or absent
	args['italic title'] = origArgs['italic title']
	preprocessSingleArg('decat')
	preprocessSingleArg('templatestyles')
	preprocessSingleArg('child templatestyles')
	preprocessSingleArg('grandchild templatestyles')
end

-- If called via #invoke, use the args passed into the invoking template.
-- Otherwise, for testing purposes, assume args are being passed directly in.
function p.infobox(frame)
	if frame == mw.getCurrentFrame() then
		origArgs = frame:getParent().args
	else
		origArgs = frame
	end
	
	parseDataParameters()
	
	return _infobox()
end

-- For calling via #invoke within a template
function p.infoboxTemplate(frame)
	origArgs = {}
	for k,v in pairs(frame.args) do origArgs[k] = mw.text.trim(v) end
	
	parseDataParameters()
	
	return _infobox()
end
return p