| Line 1: |
Line 1: |
| − | -- Inputs: | + | -- |
| − | -- image - Can either be a bare filename (with or without the File:/Image: prefix) or a fully formatted image link | + | -- This module implements {{Infobox}} |
| − | -- page - page to display for multipage images (DjVu)
| + | -- |
| − | -- size - size to display the image
| |
| − | -- maxsize - maximum size for image
| |
| − | -- sizedefault - default size to display the image if size param is blank
| |
| − | -- alt - alt text for image
| |
| − | -- title - title text for image
| |
| − | -- border - set to yes if border
| |
| − | -- center - set to yes, if the image has to be centered
| |
| − | -- upright - upright image param
| |
| − | -- suppressplaceholder - if yes then checks to see if image is a placeholder and suppresses it
| |
| − | -- link - page to visit when clicking on image
| |
| − | -- Outputs:
| |
| − | -- Formatted image.
| |
| − | -- More details available at the "Module:InfoboxImage/doc" page | |
| | | | |
| − | local i = {}; | + | local p = {} |
| | | | |
| − | local placeholder_image = { | + | local navbar = require('Module:Navbar')._navbar |
| − | "Blue - Replace this image female.svg",
| |
| − | "Blue - Replace this image male.svg",
| |
| − | "Female no free image yet.png",
| |
| − | "Flag of None (square).svg",
| |
| − | "Flag of None.svg",
| |
| − | "Flag of.svg",
| |
| − | "Green - Replace this image female.svg",
| |
| − | "Green - Replace this image male.svg",
| |
| − | "Image is needed female.svg",
| |
| − | "Image is needed male.svg",
| |
| − | "Location map of None.svg",
| |
| − | "Male no free image yet.png",
| |
| − | "Missing flag.png",
| |
| − | "No flag.svg",
| |
| − | "No free portrait.svg",
| |
| − | "No portrait (female).svg",
| |
| − | "No portrait (male).svg",
| |
| − | "Red - Replace this image female.svg",
| |
| − | "Red - Replace this image male.svg",
| |
| − | "Replace this image female (blue).svg",
| |
| − | "Replace this image female.svg",
| |
| − | "Replace this image male (blue).svg",
| |
| − | "Replace this image male.svg",
| |
| − | "Silver - Replace this image female.svg",
| |
| − | "Silver - Replace this image male.svg",
| |
| − | "Replace this image.svg",
| |
| − | "Cricket no pic.png",
| |
| − | "CarersLogo.gif",
| |
| − | "Diagram Needed.svg",
| |
| − | "Example.jpg",
| |
| − | "Image placeholder.png",
| |
| − | "No male portrait.svg",
| |
| − | "Nocover-upload.png",
| |
| − | "NoDVDcover copy.png",
| |
| − | "Noribbon.svg",
| |
| − | "No portrait-BFD-test.svg",
| |
| − | "Placeholder barnstar ribbon.png",
| |
| − | "Project Trains no image.png",
| |
| − | "Image-request.png",
| |
| − | "Sin bandera.svg",
| |
| − | "Sin escudo.svg",
| |
| − | "Replace this image - temple.png",
| |
| − | "Replace this image butterfly.png",
| |
| − | "Replace this image.svg",
| |
| − | "Replace this image1.svg",
| |
| − | "Resolution angle.png",
| |
| − | "Image-No portrait-text-BFD-test.svg",
| |
| − | "Insert image here.svg",
| |
| − | "No image available.png",
| |
| − | "NO IMAGE YET square.png",
| |
| − | "NO IMAGE YET.png",
| |
| − | "No Photo Available.svg",
| |
| − | "No Screenshot.svg",
| |
| − | "No-image-available.jpg",
| |
| − | "Null.png",
| |
| − | "PictureNeeded.gif",
| |
| − | "Place holder.jpg",
| |
| − | "Unbenannt.JPG",
| |
| − | "UploadACopyrightFreeImage.svg",
| |
| − | "UploadAnImage.gif",
| |
| − | "UploadAnImage.svg",
| |
| − | "UploadAnImageShort.svg",
| |
| − | "CarersLogo.gif",
| |
| − | "Diagram Needed.svg",
| |
| − | "No male portrait.svg",
| |
| − | "NoDVDcover copy.png",
| |
| − | "Placeholder barnstar ribbon.png",
| |
| − | "Project Trains no image.png",
| |
| − | "Image-request.png",
| |
| − | "Noimage.gif",
| |
| − | }
| |
| | | | |
| − | function i.IsPlaceholder(image)
| + | local args = {} |
| − | -- change underscores to spaces
| + | local origArgs = {} |
| − | image = mw.ustring.gsub(image, "_", " ");
| + | local root |
| − | assert(image ~= nil, 'mw.ustring.gsub(image, "_", " ") must not return nil')
| |
| − | -- if image starts with [[ then remove that and anything after |
| |
| − | if mw.ustring.sub(image,1,2) == "[[" then
| |
| − | image = mw.ustring.sub(image,3);
| |
| − | image = mw.ustring.gsub(image, "([^|]*)|.*", "%1");
| |
| − | assert(image ~= nil, 'mw.ustring.gsub(image, "([^|]*)|.*", "%1") must not return nil')
| |
| − | end
| |
| − | -- Trim spaces
| |
| − | image = mw.ustring.gsub(image, '^[ ]*(.-)[ ]*$', '%1');
| |
| − | assert(image ~= nil, "mw.ustring.gsub(image, '^[ ]*(.-)[ ]*$', '%1') must not return nil")
| |
| − | -- remove prefix if exists
| |
| − | local allNames = mw.site.namespaces[6].aliases
| |
| − | allNames[#allNames + 1] = mw.site.namespaces[6].name
| |
| − | allNames[#allNames + 1] = mw.site.namespaces[6].canonicalName
| |
| − | for i, name in ipairs(allNames) do
| |
| − | if mw.ustring.lower(mw.ustring.sub(image, 1, mw.ustring.len(name) + 1)) == mw.ustring.lower(name .. ":") then
| |
| − | image = mw.ustring.sub(image, mw.ustring.len(name) + 2);
| |
| − | break
| |
| − | end
| |
| − | end
| |
| − | -- Trim spaces
| |
| − | image = mw.ustring.gsub(image, '^[ ]*(.-)[ ]*$', '%1');
| |
| − | -- capitalise first letter
| |
| − | image = mw.ustring.upper(mw.ustring.sub(image,1,1)) .. mw.ustring.sub(image,2);
| |
| | | | |
| − | for i,j in pairs(placeholder_image) do
| + | local function notempty( s ) return s and s:match( '%S' ) end |
| − | if image == j then
| + | |
| − | return true
| + | local function fixChildBoxes(sval, tt) |
| − | end
| + | if notempty(sval) then |
| − | end
| + | local marker = '<span class=special_infobox_marker>' |
| − | return false
| + | 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 |
| | + | -- https://en.wikipedia.org/w/index.php?title=Template_talk:Infobox_musical_artist&oldid=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 |
| | + | |
| | + | local function union(t1, t2) |
| | + | -- Returns the union of the values of two tables, as a sequence. |
| | + | 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 |
| | + | |
| | + | local function getArgNums(prefix) |
| | + | -- 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 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 |
| | + | |
| | + | local function addRow(rowArgs) |
| | + | -- Adds a row to the infobox, with either a header cell |
| | + | -- or a label/data cell combination. |
| | + | if rowArgs.header and rowArgs.header ~= '_BLANK_' then |
| | + | root |
| | + | :tag('tr') |
| | + | :addClass(rowArgs.rowclass) |
| | + | :cssText(rowArgs.rowstyle) |
| | + | :attr('id', rowArgs.rowid) |
| | + | :tag('th') |
| | + | :attr('colspan', 2) |
| | + | :attr('id', rowArgs.headerid) |
| | + | :addClass(rowArgs.class) |
| | + | :addClass(args.headerclass) |
| | + | :css('text-align', 'center') |
| | + | :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 then |
| | + | if not rowArgs.data:gsub('%[%[%s*[Cc][Aa][Tt][Ee][Gg][Oo][Rr][Yy]%s*:[^]]*]]', ''):match('^%S') then |
| | + | rowArgs.rowstyle = 'display:none' |
| | + | end |
| | + | local row = root:tag('tr') |
| | + | row:addClass(rowArgs.rowclass) |
| | + | row:cssText(rowArgs.rowstyle) |
| | + | row:attr('id', rowArgs.rowid) |
| | + | if rowArgs.label then |
| | + | row |
| | + | :tag('th') |
| | + | :attr('scope', 'row') |
| | + | :attr('id', rowArgs.labelid) |
| | + | :cssText(args.labelstyle) |
| | + | :cssText(rowArgs.rowcellstyle) |
| | + | :wikitext(rowArgs.label) |
| | + | :done() |
| | + | end |
| | + | |
| | + | local dataCell = row:tag('td') |
| | + | if not rowArgs.label then |
| | + | dataCell |
| | + | :attr('colspan', 2) |
| | + | :css('text-align', 'center') |
| | + | end |
| | + | dataCell |
| | + | :attr('id', rowArgs.dataid) |
| | + | :addClass(rowArgs.class) |
| | + | :cssText(rowArgs.datastyle) |
| | + | :cssText(rowArgs.rowcellstyle) |
| | + | :wikitext(fixChildBoxes(rowArgs.data, 'td')) |
| | + | end |
| | + | end |
| | + | |
| | + | local function renderTitle() |
| | + | if not args.title then return end |
| | + | |
| | + | root |
| | + | :tag('caption') |
| | + | :addClass(args.titleclass) |
| | + | :cssText(args.titlestyle) |
| | + | :wikitext(args.title) |
| | + | end |
| | + | |
| | + | local function renderAboveRow() |
| | + | if not args.above then return end |
| | + | |
| | + | root |
| | + | :tag('tr') |
| | + | :tag('th') |
| | + | :attr('colspan', 2) |
| | + | :addClass(args.aboveclass) |
| | + | :css('text-align', 'center') |
| | + | :css('font-size', '125%') |
| | + | :css('font-weight', 'bold') |
| | + | :cssText(args.abovestyle) |
| | + | :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(args.belowclass) |
| | + | :css('text-align', 'center') |
| | + | :cssText(args.belowstyle) |
| | + | :wikitext(fixChildBoxes(args.below,'td')) |
| | + | 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 |
| | + | addRow({ |
| | + | data = args['subheader' .. tostring(num)], |
| | + | datastyle = args.subheaderstyle, |
| | + | rowcellstyle = args['subheaderstyle' .. tostring(num)], |
| | + | class = args.subheaderclass, |
| | + | rowclass = args['subheaderrowclass' .. tostring(num)] |
| | + | }) |
| | + | 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') |
| | + | :cssText(args.captionstyle) |
| | + | :wikitext(caption) |
| | + | end |
| | + | addRow({ |
| | + | data = tostring(data), |
| | + | datastyle = args.imagestyle, |
| | + | class = args.imageclass, |
| | + | rowclass = args['imagerowclass' .. tostring(num)] |
| | + | }) |
| | + | end |
| | end | | end |
| | | | |
| − | function i.InfoboxImage(frame) | + | local function preprocessRows() |
| − | local image = frame.args["image"];
| + | -- Gets the union of the header and data argument numbers, |
| − |
| + | -- and renders them all in order using addRow. |
| − | if image == "" or image == nil then
| + | local rownums = union(getArgNums('header'), getArgNums('data')) |
| − | return "";
| + | table.sort(rownums) |
| − | end
| + | local lastheader |
| − | if image == " " then
| + | for k, num in ipairs(rownums) do |
| − | return image;
| + | if args['header' .. tostring(num)] then |
| − | end
| + | if lastheader then |
| − | if frame.args["suppressplaceholder"] ~= "no" then
| + | args['header' .. tostring(lastheader)] = nil |
| − | if i.IsPlaceholder(image) == true then
| + | end |
| − | return "";
| + | lastheader = num |
| − | end
| + | elseif args['data' .. tostring(num)] and args['data' .. tostring(num)]:gsub('%[%[%s*[Cc][Aa][Tt][Ee][Gg][Oo][Rr][Yy]%s*:[^]]*]]', ''):match('^%S') then |
| − | end
| + | local data = args['data' .. tostring(num)] |
| | + | if data:gsub('%[%[%s*[Cc][Aa][Tt][Ee][Gg][Oo][Rr][Yy]%s*:[^]]*]]', ''):match('%S') then |
| | + | lastheader = nil |
| | + | end |
| | + | end |
| | + | end |
| | + | if lastheader then |
| | + | args['header' .. tostring(lastheader)] = nil |
| | + | end |
| | + | end |
| | | | |
| − | if mw.ustring.lower(mw.ustring.sub(image,1,5)) == "http:" then
| + | local function renderRows() |
| − | return "";
| + | -- Gets the union of the header and data argument numbers, |
| − | end
| + | -- and renders them all in order using addRow. |
| − | if mw.ustring.lower(mw.ustring.sub(image,1,6)) == "[http:" then
| + | local rownums = union(getArgNums('header'), getArgNums('data')) |
| − | return "";
| + | table.sort(rownums) |
| − | end
| + | for k, num in ipairs(rownums) do |
| − | if mw.ustring.lower(mw.ustring.sub(image,1,7)) == "[[http:" then
| + | addRow({ |
| − | return "";
| + | header = args['header' .. tostring(num)], |
| − | end
| + | label = args['label' .. tostring(num)], |
| − | if mw.ustring.lower(mw.ustring.sub(image,1,6)) == "https:" then
| + | data = args['data' .. tostring(num)], |
| − | return "";
| + | datastyle = args.datastyle, |
| − | end
| + | class = args['class' .. tostring(num)], |
| − | if mw.ustring.lower(mw.ustring.sub(image,1,7)) == "[https:" then
| + | rowclass = args['rowclass' .. tostring(num)], |
| − | return "";
| + | rowstyle = args['rowstyle' .. tostring(num)], |
| − | end
| + | rowcellstyle = args['rowcellstyle' .. tostring(num)], |
| − | if mw.ustring.lower(mw.ustring.sub(image,1,8)) == "[[https:" then
| + | dataid = args['dataid' .. tostring(num)], |
| − | return "";
| + | labelid = args['labelid' .. tostring(num)], |
| − | end
| + | headerid = args['headerid' .. tostring(num)], |
| | + | rowid = args['rowid' .. tostring(num)] |
| | + | }) |
| | + | end |
| | + | end |
| | | | |
| − | if mw.ustring.sub(image,1,2) == "[[" then
| + | local function renderNavBar() |
| − | -- search for thumbnail images and add to tracking cat if found
| + | if not args.name then return end |
| − | local cat = "";
| + | |
| − | if mw.title.getCurrentTitle().namespace == 0 and (mw.ustring.find(image, "|%s*thumb%s*[|%]]") or mw.ustring.find(image, "|%s*thumbnail%s*[|%]]")) then
| + | root |
| − | cat = "[[Category:Pages using infoboxes with thumbnail images]]";
| + | :tag('tr') |
| − | end
| + | :tag('td') |
| − | return image .. cat;
| + | :attr('colspan', '2') |
| − | elseif mw.ustring.sub(image,1,2) == "{{" and mw.ustring.sub(image,1,3) ~= "{{{" then
| + | :css('text-align', 'right') |
| − | return image;
| + | :wikitext(navbar{ |
| − | elseif mw.ustring.sub(image,1,1) == "<" then
| + | args.name, |
| − | return image;
| + | mini = 1, |
| − | elseif mw.ustring.sub(image,1,5) == mw.ustring.char(127).."UNIQ" then
| + | }) |
| − | -- Found strip marker at begining, so pass don't process at all
| |
| − | return image;
| |
| − | elseif mw.ustring.sub(image,4,9) == "`UNIQ-" then
| |
| − | -- Found strip marker at begining, so pass don't process at all
| |
| − | return image;
| |
| − | else
| |
| − | local result = "";
| |
| − | local page = frame.args["page"];
| |
| − | local size = frame.args["size"];
| |
| − | local maxsize = frame.args["maxsize"];
| |
| − | local sizedefault = frame.args["sizedefault"];
| |
| − | local alt = frame.args["alt"];
| |
| − | local link = frame.args["link"];
| |
| − | local title = frame.args["title"];
| |
| − | local border = frame.args["border"];
| |
| − | local upright = frame.args["upright"] or "";
| |
| − | local thumbtime = frame.args["thumbtime"] or "";
| |
| − | local center= frame.args["center"];
| |
| − |
| |
| − | -- remove prefix if exists
| |
| − | local allNames = mw.site.namespaces[6].aliases
| |
| − | allNames[#allNames + 1] = mw.site.namespaces[6].name
| |
| − | allNames[#allNames + 1] = mw.site.namespaces[6].canonicalName
| |
| − | for i, name in ipairs(allNames) do
| |
| − | if mw.ustring.lower(mw.ustring.sub(image, 1, mw.ustring.len(name) + 1)) == mw.ustring.lower(name .. ":") then
| |
| − | image = mw.ustring.sub(image, mw.ustring.len(name) + 2);
| |
| − | break
| |
| − | end
| |
| − | end
| |
| − |
| |
| − | if maxsize ~= "" and maxsize ~= nil then
| |
| − | -- if no sizedefault then set to maxsize
| |
| − | if sizedefault == "" or sizedefault == nil then
| |
| − | sizedefault = maxsize
| |
| − | end
| |
| − | -- check to see if size bigger than maxsize
| |
| − | if size ~= "" and size ~= nil then
| |
| − | local sizenumber = tonumber(mw.ustring.match(size,"%d*")) or 0;
| |
| − | local maxsizenumber = tonumber(mw.ustring.match(maxsize,"%d*")) or 0;
| |
| − | if sizenumber>maxsizenumber and maxsizenumber>0 then
| |
| − | size = maxsize;
| |
| − | end
| |
| − | end
| |
| − | end
| |
| − | -- add px to size if just a number
| |
| − | if (tonumber(size) or 0) > 0 then
| |
| − | size = size .. "px";
| |
| − | end
| |
| − | -- add px to sizedefault if just a number
| |
| − | if (tonumber(sizedefault) or 0) > 0 then
| |
| − | sizedefault = sizedefault .. "px";
| |
| − | end
| |
| − |
| |
| − | result = "[[File:" .. image;
| |
| − | if page ~= "" and page ~= nil then
| |
| − | result = result .. "|page=" .. page;
| |
| − | end
| |
| − | if size ~= "" and size ~= nil then
| |
| − | result = result .. "|" .. size;
| |
| − | elseif sizedefault ~= "" and sizedefault ~= nil then
| |
| − | result = result .. "|" .. sizedefault;
| |
| − | else
| |
| − | result = result .. "|frameless";
| |
| − | end
| |
| − | if center == "yes" then
| |
| − | result = result .. "|center"
| |
| − | end
| |
| − | if alt ~= "" and alt ~= nil then
| |
| − | result = result .. "|alt=" .. alt;
| |
| − | end
| |
| − | if link ~= "" and link ~= nil then
| |
| − | result = result .. "|link=" .. link;
| |
| − | end
| |
| − | if border == "yes" then
| |
| − | result = result .. "|border";
| |
| − | end
| |
| − | if upright == "yes" then
| |
| − | result = result .. "|upright";
| |
| − | elseif upright ~= "" then
| |
| − | result = result .. "|upright=" .. upright;
| |
| − | end
| |
| − | if thumbtime ~= "" then
| |
| − | result = result .. "|thumbtime=" .. thumbtime;
| |
| − | end
| |
| − | if title ~= "" and title ~= nil then
| |
| − | result = result .. "|" .. title;
| |
| − | elseif alt ~= "" and alt ~= nil then
| |
| − | result = result .. "|" .. alt;
| |
| − | end
| |
| − | result = result .. "]]";
| |
| − |
| |
| − | return result;
| |
| − | end
| |
| | end | | end |
| | | | |
| − | return i; | + | 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(mw.getCurrentFrame():expandTemplate({title = 'italic title'})) |
| | + | end |
| | + | end |
| | + | |
| | + | local function renderTrackingCategories() |
| | + | if args.decat ~= 'yes' then |
| | + | if args.child == 'yes' then |
| | + | if args.title then |
| | + | root:wikitext('[[Category:Pages which use embedded infobox templates with the title parameter]]') |
| | + | end |
| | + | elseif #(getArgNums('data')) == 0 and mw.title.getCurrentTitle().namespace == 0 then |
| | + | root:wikitext('[[Category:Articles which use infobox templates with no data rows]]') |
| | + | end |
| | + | end |
| | + | end |
| | + | |
| | + | local function _infobox() |
| | + | -- Specify the overall layout of the infobox, with special settings |
| | + | -- if the infobox is used as a 'child' inside another infobox. |
| | + | if args.child ~= 'yes' then |
| | + | root = mw.html.create('table') |
| | + | |
| | + | root |
| | + | :addClass((args.subbox ~= 'yes') and 'infobox' or nil) |
| | + | :addClass(args.bodyclass) |
| | + | |
| | + | if args.subbox == 'yes' then |
| | + | root |
| | + | :css('padding', '0') |
| | + | :css('border', 'none') |
| | + | :css('margin', '-3px') |
| | + | :css('width', 'auto') |
| | + | :css('min-width', '100%') |
| | + | :css('font-size', '100%') |
| | + | :css('clear', 'none') |
| | + | :css('float', 'none') |
| | + | :css('background-color', 'transparent') |
| | + | else |
| | + | root |
| | + | :css('width', '22em') |
| | + | end |
| | + | root |
| | + | :cssText(args.bodystyle) |
| | + | |
| | + | renderTitle() |
| | + | renderAboveRow() |
| | + | else |
| | + | root = mw.html.create() |
| | + | |
| | + | root |
| | + | :wikitext(args.title) |
| | + | end |
| | + | |
| | + | renderSubheaders() |
| | + | renderImages() |
| | + | if args.autoheaders then |
| | + | preprocessRows() |
| | + | end |
| | + | renderRows() |
| | + | renderBelowRow() |
| | + | renderNavBar() |
| | + | renderItalicTitle() |
| | + | renderTrackingCategories() |
| | + | |
| | + | return tostring(root) |
| | + | end |
| | + | |
| | + | local function preprocessSingleArg(argName) |
| | + | -- 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. |
| | + | if origArgs[argName] and origArgs[argName] ~= '' then |
| | + | args[argName] = origArgs[argName] |
| | + | end |
| | + | end |
| | + | |
| | + | local function preprocessArgs(prefixTable, step) |
| | + | -- 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. |
| | + | 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 |
| | + | moreArgumentsExist = true -- Do another loop if any arguments are found, even blank ones. |
| | + | 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 |
| | + | |
| | + | local function parseDataParameters() |
| | + | -- 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. |
| | + | 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'}, |
| | + | {prefix = 'dataid'}, |
| | + | {prefix = 'labelid'}, |
| | + | {prefix = 'headerid'}, |
| | + | {prefix = 'rowid'} |
| | + | }, 50) |
| | + | preprocessSingleArg('headerclass') |
| | + | preprocessSingleArg('headerstyle') |
| | + | preprocessSingleArg('labelstyle') |
| | + | preprocessSingleArg('datastyle') |
| | + | preprocessSingleArg('below') |
| | + | preprocessSingleArg('belowclass') |
| | + | preprocessSingleArg('belowstyle') |
| | + | preprocessSingleArg('name') |
| | + | args['italic title'] = origArgs['italic title'] -- different behaviour if blank or absent |
| | + | preprocessSingleArg('decat') |
| | + | 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 |
| | + | |
| | + | function p.infoboxTemplate(frame) |
| | + | -- For calling via #invoke within a template |
| | + | origArgs = {} |
| | + | for k,v in pairs(frame.args) do origArgs[k] = mw.text.trim(v) end |
| | + | |
| | + | parseDataParameters() |
| | + | |
| | + | return _infobox() |
| | + | end |
| | + | return p |