Module:Icon box/sandbox

require('strict')

local p = {}

-- FUNCTIONS TO GENERATE LINKS AND ICONS

local function exists(title) 
	local success, titleExists = pcall(function() return title.exists end)
	-- If success = false, then we're out of expensive parser function calls
	-- in that case, assume it exists
	return not success or titleExists
end

-- If requested link doesn't exist, instead return link to directory
local defaultPortal = '[[Portal:Contents/Portals|Portal<br/>Directory]]'
local defaultWikiproject = '[[Wikipedia:WikiProject Council/Directory|WikiProject<br/>Directory]]'
local defaultNoticeboard = '[[Wikipedia:Regional notice boards|Regional<br/>Notice Boards]]'

local function portalLink(item)
	local title = mw.title.new('Portal:' .. item)
            
    if title and exists(title) then
	    local separator = mw.ustring.len(item) > 24 and '&#32;' or '<br/>'
        return string.format('[[Portal:%s|%s%sportal]]',
			item, item, separator), true
	end
    return defaultPortal, false
end

local function wikiProjectLink(item)
	local title = mw.title.new('Wikipedia:WikiProject '..item)

    if title and exists(title) then
	    local separator = mw.ustring.len(item) > 24 and '&#32;' or '<br/>'
        return string.format('[[Wikipedia:WikiProject %s|WikiProject%s%s]]',
			item, separator, item), true
	end
    return defaultWikiproject, false
end

-- Function to infer a country from a string (item)
-- String can either be country name, ISO 3166 code, or adjectival form,
-- or other miscellaneous string found in countryMap in [[Module:Icon box/data]]
local function findCountry(item)
	local country = item
	local countryMap = require('Module:Icon box/data').countryMap
	if countryMap[item] then
		country = countryMap[item]
	else
		local adjective = require('Module:CountryAdjectiveDemonym').getCountryFromAdjective
		local adjName = adjective({args={item}})
		if adjName and adjName ~= '' then
			country = adjName
		elseif mw.ustring.match(item,'^%a%a%a?$') or mw.ustring.match(item,'^%a%a%a?-%a%a%a?$') then
			local iso3166 = require('Module:ISO_3166').luaname
			local isoName = iso3166({item,nocat='true'})
			if isoName and isoName ~= '' then
				country = isoName
			end
		end
	end
	return country
end

local function noticeboardLink(country)
	local linkMap = require('Module:Icon box/data').linkMap
	local titleStr = linkMap[country] or "Wikipedia talk:WikiProject "..country
	local title = mw.title.new(titleStr)
	local text
	if title and exists(title) then
		local textMap = require('Module:Icon box/data').textMap
		text = (textMap[country] or country).."<br/>notice board"
		return '[['..titleStr..'|'..text..']]', true
	end
	return defaultNoticeboard, false
end

-- Function to generate link to work group or task force subproject
-- Arguments:
--   project = name of wikiproject
--   workgroup = name of work group or task force within wikiproject
--   groupType = either "work group" or "task force"
--   label = if non-nil, override workgroup in displayed link
local function workgroupLink(project, workgroup, groupType, label)
	label = label or workgroup
	local title = mw.title.new('Wikipedia:WikiProject '..project..'/'..workgroup..' '..groupType)

	if title and exists(title) then
		local separator = mw.ustring.len(workgroup) > 24 and '&#32;' or '<br/>'
		return string.format('[[Wikipedia:WikiProject %s/%s %s|%s%s%s]]',
			project, workgroup, groupType, label, separator, groupType), true
	end
    return defaultWikiproject, false
end
	
local function getImage(item,args)
	local getPortalImage = require('Module:Portal')._image
	local img = args.image or getPortalImage(item, true)
	local ilink = args.ilink
	if ilink then
		img = img:gsub("|link%s*=%s*[^|}]*","")
		img = img.."|link="..(ilink == 'none' and '' or ilink)
	end
	return '[[File:'..img..'|48x24px]]'
end

--FUNCTIONS TO GENERATE HTML+CSS
--The HTML has a container, which has a table, which has one or more rows, each of which has an icon and a link
--Note that the code generates UL/LI so that each row is a list entry: this is so screen readers operate correctly

local function createContainer(args)
	local isRight = (args.align == 'right')

	local container = mw.html.create('div')
	    :attr('aria-label',args.ariaLabel or '')
	    :addClass('noprint')
	    :addClass('portal')
        :addClass(isRight and 'floatright' or 'floatleft')
        :attr('role', 'navigation')
        :css('border', 'solid #777799 1px')
        :css('margin', isRight and '0.2em 0 0.2em 0.2em' or '0.2em 0.2em 0.2em 0')
	return container
end

local function createList(container, args)
    local bgColor = args.color or 'var(--background-color-base, #fff)'
    local textColor = args.color and '#202122' or 'inherit'

	local list = container:tag('ul')
	    :css('display','table')
	    :css('list-style','none')
        :css('border-spacing','2px')
	    :css('margin',0)
	    :css('background',bgColor)
	    :css('color',textColor)
	    :css('font-size',args.size)
		:css('line-height',args.lh)
		:css('max-width',args.width)
	return list
end

local function createRow(list)
	return list:tag('li')
	           :css('display','table-row')
			   :css('min-height','24px')
end

local function createImageSpan(row, img)
	return row:tag('span')
			   :css('display','table-cell')
			   :css('text-align','center')
			   :css('vertical-align','middle')
			   :css('padding','1px')
			   :wikitext(img)
end

-- function to generate HTML span for link
-- Arguments:
--   row = parent HTML for link
--   text = link to display
--   item = name of project/portal to link to (for formatting)
--   args = arguments passed to module
local function createLinkSpan(row, text, item, args)
	return row:tag('span')
		    :css('display','table-cell')
            :css('padding','0 0.2em')
		    :css('text-align',args.talign)
		    :css('vertical-align','middle')
		    :css('font-weight','bold')
			:css('font-size',mw.ustring.len(item) > 40 and '88%' or '')
		    :wikitext(text)
end

-- set defaults and units on arguments passed to module
local function processArgs(args)
	args.align = args.align or args.float or 'right'
	args.size = args.size or 8
	if tonumber(args.size) then
		args.size = args.size..'pt'
	end
	args.lh = args.lh or '110%' 
	args.width = args.width or 200
	if tonumber(args.width) then
		args.width = args.width..'px'
	end
	args.talign = args.talign or 'center'
	local yesNo = require('Module:Yesno')
	args.nodefault = yesNo(args.nodefault)
	return args
end

local function generateBoxName(portals, projects, noticeboards)
	if portals then
		if projects or noticeboards then
			return 'Portals and projects'
		end
		return 'Portals'
	end
	if projects then
		return 'Wikiprojects'
	end
	if noticeboards then
		return 'Noticeboards'
	end
	return 'Icon box'
end

local function iterateItems(list, items, linkFcn, args)
	local hasItem = false
	for _, item in ipairs(items) do
		item = findCountry(item)
		local text, itemExists = linkFcn(item)
		if itemExists or (not args.nodefault) then
			hasItem = true
			item = itemExists and item or 'regional'
			local img = getImage(item, args)
			local row = createRow(list)
	    	createImageSpan(row, img)
			createLinkSpan(row, text, item, args)
		end
	end
	return hasItem
end

-- function that creates portal or wikiproject boxes
-- Arguments:
--   portals = list of portals to display (or nil)
--   projects = list of projects to display (or nil)
--   noticeboards = list of noticeboards to display (or nil)
--   args = parameters for display
--      args.align: how to place box on page, default "right"
--      args.color: background color for box
--      args.size: font size. If bare number, interpreted as pt
--      args.lh: line height
--      args.width: width of box. If bare number, interpreted as px
--      args.talign: alignment of link text, defaults to "center"
function p._main(portals, projects, noticeboards, args)
	args = processArgs(args)
	args.ariaLabel = generateBoxName(portals, projects, noticeboards)
	
	local container = createContainer(args)
	local list = createList(container, args)

	local hasItem = false
	if portals and iterateItems(list, portals, portalLink, args) then
		hasItem = true
	end
	if projects and iterateItems(list, projects, wikiProjectLink, args) then
		hasItem = true
	end
	if noticeboards and iterateItems(list, noticeboards, noticeboardLink, args) then
		hasItem = true
	end

	if not hasItem then
		return nil
	end
	return container	
end

-- Function to generate box that links to work group or task force
-- Arguments:
--   args = parameters for display
--      args[1] or args.wpname: name of wikiproject
--      args[2] or args.wgname: name of work group or task force
--      args.type: "workgroup" or "taskforce" depending on which is desired
--      args.image: override image shown in box (without namespace prefix)
--      args.ilink: override link in image
--      other optional arguments documented in p._main() above
function p._workgroup(args)
	args = processArgs(args)
	args.color = args.color or '#FFFFFE'
	args.wpname = args.wpname or args[1] or '?'
	args.wgname = args.wgname or args[2] or 'regional'
	local groupType = ''
	if args.type == 'workgroup' then
		groupType = 'work group'
		args.ariaLabel = 'Workgroups'
	elseif args.type == 'taskforce' then
		groupType = 'task force'
		args.ariaLabel = 'Taskforces'
	end

	local container = createContainer(args)
	local list = createList(container, args)
	local row = createRow(list)
	local img = getImage(args.wgname,args)
	local text, wgExists

	text, wgExists = workgroupLink(args.wpname, args.wgname, groupType, args.label)
	createImageSpan(row, img)
	createLinkSpan(row, text, wgExists and args.wgname or '', args)
	return container
end

-- Functions to separate named and positional arguments out of frame
-- Also sets default single item to "?"
-- Forbids use of image and ilink arguments
local function separateArgs(frame)
	local getArgs = require('Module:Arguments').getArgs
	local portalArgs = require('Module:Portal')._processPortalArgs
	local args = getArgs(frame)
	local items, namedArgs = portalArgs(args)
	if not items[1] then
		table.insert(items,'?')
	end
	args.image = nil
	args.ilink = nil
	return items, namedArgs
end


local function getNumericArgs(args, param)
	local pattern = "^"..param.."_?(%d+)$"
	local results = {}
	for k, v in pairs(args) do
		local m = tonumber(mw.ustring.match(k, pattern))
		if m then
			results[m] = v
		end
	end
	local compressSparseArray = require('Module:TableTools').compressSparseArray
	return compressSparseArray(results)
end

-- ENTRY POINTS FOR TEMPLATES

function p.main(frame)
	local getArgs = require('Module:Arguments').getArgs
	local args = getArgs(frame)
	local portals = getNumericArgs(args,"portal")
	local projects = getNumericArgs(args,"project")
	local noticeboards = getNumericArgs(args,"noticeboard")
	local result = p._main(portals, projects, noticeboards, args)
	return result and tostring(result) or ""
end

function p.portal(frame)
	local portals, args = separateArgs(frame)
	local result = p._main(portals, nil, nil, args)
	return result and tostring(result) or ""
end

function p.wikiproject(frame)
	local projects, args = separateArgs(frame)
	local result = p._main(nil, projects, nil, args)
	return result and tostring(result) or ""
end

function p.noticeboard(frame)
	local noticeboards, args = separateArgs(frame)
	local result = p._main(nil, nil, noticeboards, args)
	return result and tostring(result) or ""
end

function p.all(frame)
	local getArgs = require('Module:Arguments').getArgs
	local args = getArgs(frame)
	local item = args[1]
	if not item then
		return ""
	end
	local result = p._main({item},{item},{item},args)
	return result and tostring(result) or ""
end

function p.workgroup(frame)
	local getArgs = require('Module:Arguments').getArgs
	local args = getArgs(frame)
	args.type = 'workgroup'
	local result = p._workgroup(args)
	return result and tostring(result) or ""
end

function p.taskforce(frame)
	local getArgs = require('Module:Arguments').getArgs
	local args = getArgs(frame)
	args.type = 'taskforce'
	local result = p._workgroup(args)
	return result and tostring(result) or ""
end

return p

Content Disclaimer

Informasi ini disarikan dari Wikipedia dan disajikan kembali untuk tujuan edukasi. Konten tersedia di bawah lisensi CC BY-SA 3.0. Kami tidak bertanggung jawab atas ketidakakuratan data yang bersumber dari kontribusi publik tersebut.

  1. The information displayed on this website is sourced in part or in whole from Wikipedia and has been adapted for the purpose of restating it. We strive to provide accurate and relevant information, however:
  2. There is no guarantee of absolute accuracy. Wikipedia is an open, collaborative project that can be edited by anyone, so information is subject to change.
  3. It is not intended to constitute professional advice. The content displayed is for informational and educational purposes only. For important decisions (e.g., medical, legal, or financial), please consult a professional.
  4. Content copyright. Wikipedia is licensed under the Creative Commons Attribution-ShareAlike License (CC BY-SA). This means that content may be reused with appropriate attribution and shared under a similar license.
  5. Responsible use. Any risk arising from the use of information from this website is entirely the responsibility of the user.