Module:WikiProjectBanner/K
MyWikiBiz, Author Your Legacy — Saturday December 28, 2024
Jump to navigationJump to searchDocumentation for this module may be created at Module:WikiProjectBanner/K/doc
local export = {} -- TODO: a submodule for categorisation may be needed -- these also need to be checked for existence by the documentation page local m_common_data = require('Module:WikiProjectBanner/common data') local importance_grades, quality_grades, importance_scales, quality_scales, stock_notices = m_common_data.importance_grades, m_common_data.quality_grades, m_common_data.importance_scales, m_common_data.quality_scales, m_common_data.stock_notices -- creates a wrapper object which tracks unused template arguments local function track_usage(args) local tracker = {} for key in pairs(args) do tracker[key] = true end return setmetatable({}, { __index = function (self, key) local value = args[key] tracker[key] = nil self[key] = value return value end }), tracker end -- resolves a quality or importance assessment grade; returns a grade data table and status local function resolve_grade(scale_config, scales, grades, args, grade_param, title) if args == true then return grades.na, 'demo' end if type(scale_config) == "string" then scale_config = scales[scale_config] elseif not scale_config then scale_config = scales.standard end local ns ns = mw.site.namespaces[title.namespace].subject if ns.id == 0 then ns = "_MAIN" else ns = ns.canonicalName end if title.isRedirect and scale_config._REDIRECT then local redir_grade = scale_config._REDIRECT[ns] or scale_config._REDIRECT._OTHER if redir_grade then return grades[redir_grade], 'redirect' end end scale_config = scale_config[ns] or scale_config._OTHER if not scale_config then return nil end if type(scale_config) == "string" then return grades[scale_config] end local resolver = {} for _, item in ipairs(scale_config) do local grade = grades[item] resolver[item] = grade if grade.aliases then for _, item in ipairs(grade.aliases) do resolver[item] = grade end end end local grade = args[grade_param] if grade then grade = tostring(grade):lower() if resolver[grade] then return resolver[grade], 'valid' else return resolver[scale_config[1]], 'invalid' end else return resolver[scale_config[1]], 'default' end end -- constructs banner markup and the category list. for internal use only (which includes unit tests). function export.build_banner(banner_config, banner_hooks, title, banner_args, out, categories) local yesno = require('Module:yesno') out.root = mw.html.create('') local state = {} -- for use by hooks only local function call_hook(hookfunc, ...) if not hookfunc then return true end return hookfunc(--[[ not yet determined ]]) end -- basic skeleton out.wrapper = out.root:tag('table') :addClass('tmbox tmbox-notice collapsible innercollapse wpb') out.header_row = out.wrapper:tag('tr') :addClass('wpb-header') out.header_name = out.header_row:tag('td') :css('text-align', 'right') :css('padding', '0.3em 1em 0.3em 0.3em') :css('width', '50%') :css('font-weight', 'bold') out.header_rating = out.header_row:tag('th') :css('text-align', 'left') :css('width', '50%') :css('padding', '0.3em 0.3em 0.3em 0') out.content = out.wrapper:tag('tr') :tag('td') :addClass('mbox-text') :css('padding', '3px 0 3px 5px') :attr('colspan', '2') :tag('table') :css('background', 'transparent') :css('border', 'none') :css('padding', '0') :css('width', '100%') :attr('cellspacing', '0') out.has_more = false out.content_more = mw.html.create('table') :addClass('collapsible collapsed') :css('width', '100%') :css('background', 'transparent') :tag('tr') :tag('th') :attr('colspan', '3') :css('text-align', 'left') :css('padding', '0.2em 2px 0.2em 0') :wikitext(banner_config.more_header or "More information") :done() :done() -- does anyone still use this? local is_small = (banner_args ~= true) and yesno(banner_args.small) if is_small then out.wrapper:addClass("mbox-small") end -- the blurb local page_type = require('Module:pagetype')._main { page = title.fullText } local blurb_row = out.content:tag('tr') if banner_config.image_left then out.blurb_image_left = blurb_row:tag('td'):addClass('mbox-image') end out.blurb_text = blurb_row:tag('td'):addClass('mbox-text') if banner_config.image_right then out.blurb_image_right = blurb_row:tag('td'):addClass('mbox-imageright') end if banner_config.image_left then out.blurb_image_left:wikitext(('[[File:%s|%s]]'):format( banner_config.image_left, is_small and (banner_config.image_left_size_small or "40px") or (banner_config.image_left_size_big or "80px") )) end if banner_config.image_right then out.blurb_image_right:wikitext(('[[File:%s|%s]]'):format( banner_config.image_right, is_small and (banner_config.image_right_size_small or "40px") or (banner_config.image_right_size_big or "80px") )) end out.blurb_text:attr('colspan', (banner_config.image_left and 1 or 0) + (banner_config.image_right and 1 or 0) + 1 ) if banner_config.portal then local m_portal = require("Module:Portal") out.blurb_text:wikitext(m_portal._portal({ banner_config.portal }, {})) end local project_link = banner_config.project_link or ("Wikipedia:WikiProject " .. banner_config.project) local project_name = banner_config.project_name or ("WikiProject " .. banner_config.project) if banner_config.blurb then out.blurb_text:wikitext(banner_config.blurb) else local project_scope = banner_config.project_scope or ("[[" .. banner_config.project .. "]]") local project_link_talk = project_link:gsub("^Wikipedia:", "Wikipedia talk:") -- XXX: avoiding title objects because they are "expensive" to create out.blurb_text:wikitext(( "This %s is within the scope of '''[[%s|%s]]''', a collaborative effort " .. "to improve the coverage of %s on Wikipedia. If you would like to participate, " .. "please visit the project page, where you can join the [[%s|discussion]] and " .. "see a list of open tasks." ):format( page_type, project_link, project_name, project_scope, project_link_talk )) end out.header_name:wikitext(("[[%s|%s]]"):format(project_link, project_name)) function out.row_pair(in_more) local parent = out.content if in_more then out.has_more = true parent = out.content_more end local row = parent:tag('tr') local cell_img, cell_text cell_img = row:tag('td') cell_text = row:tag('td') :attr('colspan', '2') :addClass('mbox-text') return cell_img, cell_text end -- normalise parameters local quality_grade, quality_grade_status = resolve_grade( banner_config.quality_scale, quality_scales, quality_grades, banner_args, 'class', title ) if quality_grade_status == 'invalid' then -- TODO: add a category end local imp_grade, imp_grade_status if quality_grade and quality_grade.force_imp then imp_grade, imp_grade_status = quality_grade.force_imp, 'forced' else imp_grade, imp_grade_status = resolve_grade( banner_config.importance_scale, importance_scales, importance_grades, banner_args, banner_config.importance_param or 'importance', title ) end if imp_grade_status == 'invalid' then -- TODO: add a category end if quality_grade then out.qual_label, out.qual_text = out.row_pair() out.qual_label :addClass('assess') :css('text-align', 'center') :css('white-space', 'nowrap') :css('font-weight', 'bold') :css('background', quality_grade.color) if quality_grade.icon then out.qual_label :wikitext('[[File:' .. quality_grade.icon .. '|16px]] ') end out.qual_label:wikitext(quality_grade.short) out.qual_text:wikitext(("This %s %s on the project's [[%s|quality scale]]."):format( page_type, quality_grade.rated_text or "has been rated as '''" .. quality_grade.full .. "'''", banner_config.quality_scale_link or (project_link .. "/Assessment#Quality scale") )) -- TODO: add a category -- TODO: assessment checklists end if imp_grade then out.imp_label, out.imp_text = out.row_pair() out.imp_label :addClass('import') :css('text-align', 'center') :css('white-space', 'nowrap') :css('font-weight', 'bold') :css('background', imp_grade.color) out.imp_label:wikitext(imp_grade.name) out.imp_text:wikitext(("This %s %s on the project's [[%s|importance scale]]."):format( page_type, quality_grade.rated_text or "has been rated as '''" .. imp_grade.name .. "-importance'''", banner_config.importance_scale_link or (project_link .. "/Assessment#Importance scale") )) -- TODO: add a category end -- rating text for banner headers inside {{WikiProjectBannerShell}} if quality_grade or imp_grade then out.header_rating:wikitext("(Rated ") if quality_grade then out.header_rating:wikitext(quality_grade.short) if imp_grade then out.header_rating:wikitext(", ") end end if imp_grade then out.header_rating:wikitext(imp_grade.name .. "-importance") end out.header_rating:wikitext(")") end -- field, like in {{WikiProject Systems}} or {{Maths rating}} if banner_config.field then local field_config = banner_config.field local field if banner_args ~= true then field = false local field_id = banner_args[field_config.arg_name or 'field'] if field_id then field = field_config.fields[field_id] if type(field) == 'string' then field = field_config.fields[field] end end end out.field_icon, out.field_text = out.row_pair() if field then out.field_icon:wikitext(("[[File:%s|link=%s]]"):format( field.icon, field.link )) out.field_text:wikitext(("This %s is within the field of [[%s|%s]]."):format( page_type, field.link, field.name )) else out.field_icon:wikitext(("[[File:Purple question mark.svg|link=%s]]"):format( field_config.unassessed_link )) out.field_text:wikitext(("This %s is [[%s|not associated with a particular field]]."):format( page_type, field_config.unassessed_link )) if field == false then -- TODO: add a category because an invalid field has been specified end end end -- task forces for _, tf_info in ipairs(banner_config.task_forces or {}) do -- TODO: is this row needed? local needed = (banner_args == true) or banner_args[tf_info.param] if tf_info.force then -- {{WikiProject Software}} forces WikiProject Computing's banner for example needed = true end if needed then local short_name = tf_info.short_name or tf_info.name if tf_info.link then out.header_name:wikitext((" / [[%s|%s]]"):format(tf_info.link, short_name)) else out.header_name:wikitext((" / %s"):format(short_name)) end local node_icon, node_text = out.row_pair() if tf_info.icon then node_icon:wikitext(('[[File:%s|x25px|link=%s]]'):format(tf_info.icon, tf_info.link or '')) end -- TODO: node_text:wikitext("This %s is supported by %s.") -- TODO: add categories end end -- requests and other notices (photograph, maps, attention, etc.) for _, nt_info in ipairs(banner_config.notices or { stock_notices.auto, stock_notices.attention }) do if type(nt_info) == 'string' then nt_info = stock_notices[nt_info] or error("Invalid stock notice '" .. nt_info .. "' specified in banner configuration") end local needed = (banner_args == true) or banner_args[nt_info.param] if needed then local node_icon, node_text = out.row_pair() if nt_info.icon then node_icon:wikitext(('[[File:%s|x25px|link=%s]]'):format(nt_info.icon, nt_info.link or '')) end -- TODO: fill node_text -- TODO: add categories end end if out.has_more then out.content:wikitext(tostring(out.content_more)) end end function export.render_banner(frame) local banner_name, is_templ = frame:getParent():getTitle():gsub("^Template:", "") banner_name = banner_name:match("^(.*)/sandbox$") or banner_name if is_templ == 0 then error("This module must be invoked from within a template") end local demo = false if mw.isSubsting() then local result = { } for key, value in pairs(frame:getParent().args) do table.insert(result, "|" .. key .. "=" .. value) end return "{{" .. banner_name .. table.concat(result) .. "}}" elseif mw.title.getCurrentTitle().fullText == frame:getParent():getTitle() then demo = true elseif mw.title.getCurrentTitle().namespace == mw.site.namespaces.Module.id then -- we are viewing it on the banner config page (?) demo = true end local banner_args, unused_args if not demo then banner_args, unused_args = track_usage(frame:getParent().args) else banner_args, unused_args = frame:getParent().args, {} end local success, banner_config, banner_data success, banner_config = pcall(mw.loadData, "Module:WikiProjectBanner/config/" .. banner_name) if not success then error("Banner data page [[Module:WikiProjectBanner/config/" .. banner_name .. "]] does not exist") end success, banner_hooks = pcall(require, "Module:WikiProjectBanner/config/" .. banner_name .. "/hooks") or {} if not success then banner_hooks = {} end local out, categories = {}, {} export.build_banner( banner_config, banner_hooks, -- banner config mw.title.getCurrentTitle(), demo or banner_args, -- current environment out, categories -- output ) if next(unused_args) then -- TODO: output a category for unused arguments end -- categories local sort_key = banner_args.listas or mw.title.getCurrentTitle().text if (#categories > 0) and yesno(banner_args.category, true) then categories = "[[Category:" .. table.concat(categories, "|" .. sort_key .. "]][[Category:") .. "|" .. sort_key .. "]]" else categories = "" end return tostring(out.root) .. categories end return export