Jump to content
Toggle menu
  • 8 articles
  • 75 files
  • 7 users
  • 37.8K edits
Neodyland Wiki
Toggle preferences menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.

Module:Clickable button: Difference between revisions

From Neodyland Wiki
import from module:clickable button/sandbox that'll likely be merged into module:clickable button
m 9 revisions imported
 
(6 intermediate revisions by 2 users not shown)
Line 1: Line 1:
-- [[w:en:Module:Clickable button]]
--------------------------------------------------------------------------------
-- Builds Codex's button component. See [[wmdoc:codex/latest]].
--- @module 'CodexClickableButton'
-- Implements [[Template:Clickable button]] and others.
--- Generates wikitext for clickable Codex button.
-- Wiki's [[Special:Version]] must have @wikimedia/codex and its dependences.
---
-- To add icons: [[Template:Clickable button/styles.css]].
--- Outputs wikitext to render the (button component)[mdoc:codex/latest/components/demos/button.html]
--- from the (Codex design system for Wikimedia)[https://doc.wikimedia.org/codex/latest].
---- Options to include an icon or create an icon-only button.
---- Target a URL or a wikilink
---- Set the weight, size and state of the button (enabled or disabled).
---- Dummy button creation can be disabled.
---
--- Includes helper functions for URL parsing and cleaning, and adding tracking
--- categories. Intended for use in templates and other modules.
--- Supports legacy parameters. To add icons, see CSS link in constants below.
---
--- @author [[User:Waddie96]]
--- @license CC-BY-SA-4.0/GFDL
--- @class CodexClickableButton extends ClickableButton
---  Table containing arguments for the button.
--- @class args table
--- @field label? string The button's visible text label.
--- @field link? string|'no' The target wikilink for the button.
--- @field url? string The target external URL for the button.
--- @field icon? string The name of the icon to display found in CSS file.
--- @field color? 'blue'|'green'|'red'|string Legacy color parameter.
--- @field class? string Custom CSS classes for the button.
--- @field weight? 'quiet'|'normal'|'primary' The visual weight of the button.
--- @field size? 'small'|'medium'|'large' The size of the button.
--- @field action? 'progressive'|'destructive'|'default'|string The action type of the button.
--- @field disabled? boolean|'1'|string Whether the button is disabled/greyed out. `disabled` is `true` if: `link` = `'no'` or `false` or `disabled` = `'1'` or `true`.
--- @field style? string Custom inline CSS styles.
--- @field nocat? boolean|string If `true`, suppresses tracking categories.
--- @field category? string An additional category to add.
--- @field aria-label? string The ARIA label for accessibility.
--- @field arialabel? string (alias for aria-label)
--- @field aria_label? string (alias for aria-label)
--- @field [1]? string Positional argument 1 (alias for link/label).
--- @field [2]? string Positional argument 2 (alias for label).
--- @var categories? string|boolean Additional categories to add.
--- @var ariaDisabled? boolean Internal flag indicating if the button is functionally disabled for ARIA.
--- @var oldClassMatched string|boolean Internal flag for outdated classes.
--- @var isUrl boolean Whether the link is a URL.
--- @var errorText string|nil
--- @var tblClasses table Classes for the button span tag.
--- @var pageTitle mw.title Title of the current page.
--- @todo [[Module:Neturl]] [[Module:Check for unknown parameters]]
 
local yesno = require('Module:Yesno')
local delink = require('Module:Delink')._delink


local p = {}
local p = {}


function p.main(frame)
function p.main(frame)
local args = require('Module:Arguments').getArgs(frame, {
local getArgs = require('Module:Arguments').getArgs
wrappers = 'Template:Clickable button', 'Template:Clickable button/sandbox',
local args = getArgs(frame)
'Template:Cdx-button'})
return p._main(args)
 
-- Return empty string if no arguments were supplied
local hasInput = false
for k, v in pairs(args) do
if v and v ~= "" then
hasInput = true
break
end
end
if not hasInput then
return ''
end
 
return frame:extensionTag(
'templatestyles', '', { src = 'Template:Clickable button/styles.css' }
) .. p.luaMain(args)
end
end


function p.luaMain(args)
function p._main(args)
 
-- If first arg or a url is not provided,
-- Backward compatibility:
-- but we have a second arg, make a button.
 
-- Otherwise, return nothing.
-- @TODO: In future, can format any wikilinks removing underscores,
args.originalInput = args[1]
--       URL-coding using [[Module:Format link]] and [[Module:Urldecode]]
args[1] = delink({args[1]})
--        like in [[Template:Format linkr]]
if args[1] == "" then
-- It's weird that we may make a link a label above, but if we truly only got 1=,
args[1] = nil
-- then that would mean it's intentional to make both the link and label the same.
-- Ensure label is set from priority: label= > 2= > 1=
args.label = args.label or args[2] or args[1]
 
--Disable if link=no or disabled=1
args.disabled = (args.link == "no") or (args.disabled == "1")
 
args.link = args.link or args[1]
 
-- Remove positional args after assigning
args[1] = nil
args[2] = nil
 
--[[ Remove links if disabled
if args.disabled then
args.link = nil
args.url = nil
end ]]
 
-- Make aria-disabled=true later on if no link
if args.link and args.link ~= "no" then
args.ariaDisabled = false
else
-- If no link whatsoever, make dummy button.
-- But for accessibility, ARIA must know it won't do anything.
args.ariaDisabled = true
-- Option to forcefully disable dummy buttons.
-- args.disabled = true
end
end
-- Normalize ARIA label keys
    args.aria_label = args.aria_label or args['aria-label'] or args.arialabel


-- Determine action from old parameters color/class
if not args[1] and not args.url then
local color = type(args.color) == 'string' and args.color:lower()
if args[2] then
local class = type(args.class) == 'string' and args.class:lower()
p.nolink = true
if (color == "blue"
else
or color == "green"
return ''
or class == 'ui-button-green'
end
or class == 'ui-button-blue'
or class == 'mw-ui-progressive'
or class == 'progressive') then
args.action = "progressive"
elseif (color == "red"
    or class == 'ui-button-red'
or class == 'mw-ui-destructive'
or class == 'destructive') then
args.action = "destructive"
end
end


local data = p.makeLinkData(args)
local data = p.makeLinkData(args)
 
local link = p.renderLink(args.originalInput, data)
-- Error if ARIA label required and not provided
local trackingCategories = p.renderTrackingCategories(args)
if data == 'error-no-aria' then
return link .. trackingCategories
return '<strong class="error">Clickable button error: A button without' ..
' a visible label needs an [[WAI-ARIA|ARIA]] label, please define it using "' ..
'aria-label".</strong>'
end
 
return p.renderLink(data)
end
end


-- Constructs attributes for the HTML elements.
function p.makeLinkData(args)
function p.makeLinkData(args)
local data = {}
local data = {}


-- Decide link vs. url vs. none
-- Get the link and display values,
-- URL has priority over link if both provided. Also, clean URL
-- and find whether we are outputting
-- a wikilink or a URL.
if args.url then
if args.url then
data.isUrl = true
data.isUrl = true
-- Clean up URL
data.link = args.url
local label
if args[1] then
data.url, label = p.url(args.url, args.label)
data.display = args[1]
-- Make pretty link label using the URL if no label
elseif args[2] then
data.label = args.label or label
data.display = args[2]
elseif args.link then
else
data.display = args.url
p.urlisdisplay = true
end
else
data.isUrl = false
data.isUrl = false
data.link = args.link
p.urlisdisplay = false
data.label = args.label
data.link = args[1]
elseif not args.url and not args.link then
if args[2] then
-- Dummy button, no link at all
data.display = args[2]
data.label = args.label
else
data.display = args[1]
end
if args[1] and args[1]:find('http') then
data.isUrl = true
end
end
end
-- Make sure if icon-only button or no label at all button (i.e. dummy button) it has aria-label else error.
if (not data.label
if yesno(args.link) == false then
and not args.aria_label
p.nolink = true
and not args.disabled
and not args.ariaDisabled) then
return 'error-no-aria'
end
end
-- Colours
-- For the merge with {{clickable button}}
local colour = args.color and args.color:lower()


-- Classes
-- Classes
local class = type(args.class) == 'string' and args.class:lower()
local class = args.class and args.class:lower()
data.classes = {'cdx-button', 'cdx-button--fake-button'}
data.classes = {}
local action = type(args.action) == 'string' and args.action:lower() or 'default'
if class == 'ui-button-green'
local weight = type(args.weight) == 'string' and args.weight:lower() or 'normal'
or class == 'ui-button-blue'
local size  = type(args.size) == 'string' and args.size:lower() or 'medium'
or class == 'ui-button-red'
 
then
table.insert(data.classes, 'cdx-button--action-' .. action)
table.insert(
table.insert(data.classes, 'cdx-button--weight-' .. weight)
data.classes,
table.insert(data.classes, 'cdx-button--size-' .. size)
'submit ui-button ui-widget ui-state-default ui-corner-all'
 
.. ' ui-button-text-only ui-button-text'
-- Disabled state
)
data.disabled = args.disabled
if data.disabled then
table.insert(data.classes, 'cdx-button--fake-button--disabled')
else
else
table.insert(data.classes, 'cdx-button--fake-button--enabled')
table.insert(data.classes, 'mw-ui-button')
end
end
 
-- Icon
--If class is unset,
local icon = type(args.icon) == 'string' and args.icon:lower()
--then let color determine class
if icon then
if not class then
data.iconSpan = mw.html.create('span')
if colour == 'blue' then
:addClass('cdx-button__icon cdx-demo-css-icon--' .. icon)
class = 'mw-ui-progressive'
:attr('aria-hidden', 'true')
elseif colour == 'red' then
class = 'mw-ui-destructive'
elseif colour == 'green' then
class = 'mw-ui-constructive'
end
end
end
 
data.aria_label = args.aria_label
if class then
data.ariaDisabled = args.ariaDisabled
table.insert(data.classes, class)
 
return data
end
 
function p.renderLink(data)
-- Build span tag
local span = mw.html.create('span')
for _, class in ipairs(data.classes or {}) do
span:addClass(class)
end
span:attr('role', 'button')
if data.aria_label then
span:attr('aria-label', data.aria_label)
end
-- ARIA disabled attribute for disabled/no-link/dummy buttons
if data.disabled or data.ariaDisabled then
span:attr('aria-disabled', 'true')
elseif data.disabled == false then
span:attr('aria-disabled', 'false')
end
if data.iconSpan then
span:node(data.iconSpan)
end
if data.label then
span:wikitext(data.label)
end
end


local display = tostring(span)
-- Styles
 
do
if data.disabled then
--[[
return display
-- Check whether we are on the same page as we have specified in
end
-- args[1], but not if we are using a URL link, as then args[1] is only
if data.isUrl then
-- a display value. If we are currently on the page specified in
-- mw.logObject(data)
-- args[1] make the button colour darker so that it stands out from
return string.format('<span class="plainlinks">[%s %s]</span>', data.url, display)
-- other buttons on the page.
elseif data.isUrl == false then
--]]
return string.format('[[%s|%s]]', data.link, display)
local success, linkTitle, currentTitle
else
if not data.isUrl then
-- No url/link provided
currentTitle = mw.title.getCurrentTitle()
return display
success, linkTitle = pcall(mw.title.new, args[1])
elseif p.urlisdisplay then
currentTitle = mw.title.getCurrentTitle()
end
if success
and linkTitle
and mw.title.equals(currentTitle, linkTitle)
and not p.urlisdisplay
then
if class == 'ui-button-blue'
or class == 'mw-ui-progressive'
or class == 'mw-ui-constructive'
then
data.backgroundColor = '#2962CB'
data.color = '#fff'
elseif class == 'ui-button-green' then
data.backgroundColor = '#008B6D'
elseif class == 'ui-button-red' or class == 'mw-ui-destructive' then
data.backgroundColor = '#A6170F'
else
data.backgroundColor = '#CCC'
data.color = '#666'
end
elseif p.urlisdisplay then
data.dummyLink = tostring(currentTitle)
end
-- Add user-specified styles.
data.style = args.style
end
end
return data
end
end


-- Cleans up and validates a URL.
function p.renderLink(originalInput, data)
-- Copied from [[en:Module:URL]] with minor modifications.
-- Render the display span tag.
local display
do
local displaySpan = mw.html.create('span')
for i, class in ipairs(data.classes or {}) do
displaySpan:addClass(class)
end


local function safeUri(s)
displaySpan
local success, uri = pcall(function()
:css{
return mw.uri.new(s)
['background-color'] = data.backgroundColor,
end)
color = data.color
if success then
}
return uri
if data.style then
displaySpan:cssText(data.style)
end
displaySpan:wikitext(data.display)
display = tostring(displaySpan)
end
end
end


local function extractUrl(extract)
-- Render the link
local url = extract
local link
url = mw.ustring.gsub(url, '^[Hh][Tt][Tt][Pp]([Ss]?):(/?)([^/])',
if originalInput and originalInput:find('|') then
  'http%1://%3')
link = string.format('[[%s|%s]]', delink({originalInput, wikilinks = 'target'}), display)
local uri = safeUri(url);
elseif p.nolink then
if uri and uri.host then
if p.urlisdisplay then
return url
link = string.format('[[%s|%s]]', data.dummyLink, display)
else
link = string.format('%s', display)
end
else
if data.isUrl then
link = string.format('[%s %s]', data.link, display)
else
link = string.format('[[%s |%s]]', data.link, display)
end
end
end
function p._url(url, text)
url = mw.text.trim(url or '')
text = mw.text.trim(text or '')
if url == '' then
return text
end
end


-- If the URL contains any unencoded spaces, encode them, because MediaWiki will otherwise interpret a space as the end of the URL.
return string.format('<span class="plainlinks clickbutton">%s</span>', link)
url = mw.ustring.gsub(url, '%s', function(s) return mw.uri.encode(s,
end
  'PATH')
  end)


-- If there is an empty query string or fragment id, remove it as it will cause mw.uri.new to throw an error
function p.renderTrackingCategories(args)
url = mw.ustring.gsub(url, '#$', '')
if yesno(args.category) == false then
url = mw.ustring.gsub(url, '%?$', '')
return ''
 
-- If it's an HTTP[S] URL without the double slash, fix it.
url = mw.ustring.gsub(url, '^[Hh][Tt][Tt][Pp]([Ss]?):(/?)([^/])', 'http%1://%3')
 
local uri = safeUri(url)
 
-- Handle URL's without a protocol and URL's that are protocol-relative,
-- e.g. www.example.com/foo or www.example.com:8080/foo, and //www.example.com/foo
if uri and (not uri.protocol or (uri.protocol and not uri.host)) and url:sub(1, 2) ~= '//' then
url = 'http://' .. url
uri = safeUri(url)
end
end
 
local class = args.class and args.class:lower()
if text == '' then
if class == 'ui-button-green'
if uri then
or class == 'ui-button-blue'
if uri.path == '/' then uri.path = '' end
or class == 'ui-button-red'
 
then
local port = ''
return '[[Category:Pages using old style ui-button-color]]'
if uri.port then port = ':' .. uri.port end
else
 
return ''
text = mw.ustring.lower(uri.host or '') .. port .. (uri.relativePath or '')
 
-- Add <wbr> before _/.-# sequences
text = mw.ustring.gsub(text, "(/+)", "<wbr/>%1") -- This entry MUST be the first. "<wbr/>" has a "/" in it, you know.
text = mw.ustring.gsub(text, "(%.+)", "<wbr/>%1")
-- text = mw.ustring.gsub(text,"(%-+)","<wbr/>%1") -- DISABLED for now
text = mw.ustring.gsub(text, "(%#+)", "<wbr/>%1")
text = mw.ustring.gsub(text, "(_+)", "<wbr/>%1")
else -- URL is badly-formed, so just display whatever was passed in
text = url
end
end
end
return url, text
end
function p.url(URL, TEXT)
local url = URL or ''
local text = TEXT or ''
url = url or extractUrl(url) or extractUrl(text) or ''
-- Strip out HTML tags and [ ] from URL
url = (url or ''):gsub("<[^>]*>", ""):gsub("[%[%]]", "")
-- Truncate anything after a space
url = url:gsub("%%20", " "):gsub(" .*", "")
return p._url(url, text)
end
end


return p
return p

Latest revision as of 17:55, 12 August 2026

Module documentation[ view · edit · history · purge ]
This documentation is transcluded from Module:Clickable button/doc.

Template:Template rating

Template:Uses templatestyles

Generates wikitext for clickable Codex button. Renders the button component from the Codex design system for Wikimedia. Includes helper functions for URL parsing and cleaning, adding tracking categories. Intended for use in templates and other modules. Implements Template:Clickable button and others. Supports legacy parameters.

  • Options to include an icon or create an icon-only button.
  • Target a URL or a wikilink
  • Set the weight, size and state of the button (enabled or disabled).
  • Dummy button creation can be disabled.

For more information on appropriate usage of UI buttons, see the Codex documentation.

  • Inserts two CSS files. Module:Clickable button/styles.css is required and makes minor tweaks for word-wrapping if the visible label is too long, centering or aligning button left or right, and minimum widths as is needed for icon-only buttons and labels containing two characters or less.
  • The second CSS file, Module:Clickable button/icons.css, is prepended to the button's HTML only if an icon is used.
  • Supports legacy parameters from previous templates.

Usage in wikitext

edit

Some arguments are case-insensitive.

{{#invoke:Clickable button|main
| 1        = <!-- Alias for wikilink -->
| 2        = <!-- Alias for label -->
| label    = <!-- Button visible text label -->
| link     = <!-- Target wikilink -->
| url      = <!-- Target external URL -->
<!-- Inputs action, weight, size, and icon are case-insensitive -->
| action   = <!-- progressive | destructive | default: default. -->
| weight   = <!-- primary | quiet | default: normal. -->
| size     = <!-- small | large | default: medium. Automatically chooses size based on line-height and device. -->
| icon     = <!-- Name of icon, stored in [[Module:Clickable button/icons.css]] e.g., search  -->
| disabled = <!-- `true` or any other true value like `1` or `yes`. -->
| aria-label = <!-- [[w:ARIA]] label for accessibility DOM tree. -->
| nocat      = <!-- `true` to not auto-categorize. -->
<!-- Others -->
| category = <!-- Category name e.g., Category:Name or Name or [[Category:Name]] -->
| class    = <!-- Custom CSS class without quotation marks -->
| style    = <!-- Custom CSS styling without quotation marks -->
<!-- Legacy arguments -->
| color    = <!-- blue | red --> 
}}

Usage in other modules

edit

Ensure you know what to expect from the function you call from another module.

  • function p.main(frame) emits TemplateStyles for the CSS files with the wikitext, and pre-processes the arguments in a frame using Module:Arguments, e.g. ignore blank values'', and trim trailing whitespace.
  • function p._main(arguments) Parses the arguments such as lowercase appropriate arguments, account for use of legacy parameters and decides whether aria-disabled should be true.
  • function p.url(url, [label]) is available, not for button creation, but as an adaption of Module:URL to clean and normalise a URL string and optionally generate a label.
  • The module's other functions, such as makeLinkData() and renderLink(), are localised/local to the module and would need to be made global first to be accessible to other modules.

To call p.main() for example, use:

local createButton = require( 'Module:Clickable button/sandbox' )
buttonWikitext = createButton.main( {
    link = 'South Africa',
    label = 'Go to South Africa',
    action = 'progressive'
    weight = 'default',
    size = 'medium',
    icon = 'link-external',
} ) 
return buttonWikitext

and the value of buttonWikitext would be:

<<templatestyles src="Module:Cdx-button/styles.css" /><templatestyles src="Module:Cdx-button/icons.css" /><span class="cdx-button cdx-button--fake-button cdx-button--action-progressive cdx-button--weight-quiet cdx-button--size-medium" role="button" aria-disabled="false"><span class="cdx-button__icon cdx-demo-css-icon--link-external" aria-hidden="true"></span>Go to South Africa</span>

Function _main would output:

<span class="cdx-button cdx-button--fake-button cdx-button--action-progressive cdx-button--weight-quiet cdx-button--size-medium" role="button" aria-disabled="false"><span class="cdx-button__icon cdx-demo-css-icon--link-external" aria-hidden="true"></span>Go to South Africa</span>

As a result, unless a CSS file is added to give the appropriate class an icon, the icon will not render.

Implementation

edit

Length of visible label

edit

See the Codex button component documentation.


--------------------------------------------------------------------------------
--- @module 'CodexClickableButton'
--- Generates wikitext for clickable Codex button.
--- 
--- Outputs wikitext to render the (button component)[mdoc:codex/latest/components/demos/button.html]
--- from the (Codex design system for Wikimedia)[https://doc.wikimedia.org/codex/latest].
---- Options to include an icon or create an icon-only button.
---- Target a URL or a wikilink
---- Set the weight, size and state of the button (enabled or disabled).
---- Dummy button creation can be disabled.
---
--- Includes helper functions for URL parsing and cleaning, and adding tracking 
--- categories. Intended for use in templates and other modules.
--- Supports legacy parameters. To add icons, see CSS link in constants below.
---
--- @author [[User:Waddie96]]
--- @license CC-BY-SA-4.0/GFDL
--- @class CodexClickableButton extends ClickableButton
---  Table containing arguments for the button.
--- @class args table
--- @field label? string The button's visible text label.
--- @field link? string|'no' The target wikilink for the button.
--- @field url? string The target external URL for the button.
--- @field icon? string The name of the icon to display found in CSS file.
--- @field color? 'blue'|'green'|'red'|string Legacy color parameter.
--- @field class? string Custom CSS classes for the button.
--- @field weight? 'quiet'|'normal'|'primary' The visual weight of the button.
--- @field size? 'small'|'medium'|'large' The size of the button.
--- @field action? 'progressive'|'destructive'|'default'|string The action type of the button.
--- @field disabled? boolean|'1'|string Whether the button is disabled/greyed out. `disabled` is `true` if: `link` = `'no'` or `false` or `disabled` = `'1'` or `true`.
--- @field style? string Custom inline CSS styles.
--- @field nocat? boolean|string If `true`, suppresses tracking categories.
--- @field category? string An additional category to add.
--- @field aria-label? string The ARIA label for accessibility.
--- @field arialabel? string (alias for aria-label)
--- @field aria_label? string (alias for aria-label)
--- @field [1]? string Positional argument 1 (alias for link/label).
--- @field [2]? string Positional argument 2 (alias for label).
--- @var categories? string|boolean Additional categories to add.
--- @var ariaDisabled? boolean Internal flag indicating if the button is functionally disabled for ARIA.
--- @var oldClassMatched string|boolean Internal flag for outdated classes.
--- @var isUrl boolean Whether the link is a URL.
--- @var errorText string|nil 
--- @var tblClasses table Classes for the button span tag.
--- @var pageTitle mw.title Title of the current page.
--- @todo [[Module:Neturl]] [[Module:Check for unknown parameters]]

local yesno = require('Module:Yesno')
local delink = require('Module:Delink')._delink

local p = {}

function p.main(frame)
	local getArgs = require('Module:Arguments').getArgs
	local args = getArgs(frame)
	return p._main(args)
end

function p._main(args)
	-- If first arg or a url is not provided,
	-- but we have a second arg, make a button.
	-- Otherwise, return nothing.
	args.originalInput = args[1]
	args[1] = delink({args[1]})
	if args[1] == "" then
		args[1] = nil
	end

	if not args[1] and not args.url then
		if args[2] then
			p.nolink = true
		else
			return ''
		end
	end

	local data = p.makeLinkData(args)
	local link = p.renderLink(args.originalInput, data)
	local trackingCategories = p.renderTrackingCategories(args)
	return link .. trackingCategories
end

function p.makeLinkData(args)
	local data = {}

	-- Get the link and display values,
	-- and find whether we are outputting
	-- a wikilink or a URL.
	if args.url then
		data.isUrl = true
		data.link = args.url
		if args[1] then
			data.display = args[1]
		elseif args[2] then
			data.display = args[2]
		else
			data.display = args.url
			p.urlisdisplay = true
		end
	else
		data.isUrl = false
		p.urlisdisplay = false
		data.link = args[1]
		if args[2] then
			data.display = args[2]
		else
			data.display = args[1]
		end
		if args[1] and args[1]:find('http') then
			data.isUrl = true
		end
	end
	
	if yesno(args.link) == false then
		p.nolink = true
	end

	-- Colours
	-- For the merge with {{clickable button}}
	local colour = args.color and args.color:lower()

	-- Classes
	local class = args.class and args.class:lower()
	data.classes = {}
	if class == 'ui-button-green'
		or class == 'ui-button-blue'
		or class == 'ui-button-red'
	then
		table.insert(
			data.classes,
			'submit ui-button ui-widget ui-state-default ui-corner-all'
				.. ' ui-button-text-only ui-button-text'
		)
	else
		table.insert(data.classes, 'mw-ui-button')
	end
	
	--If class is unset,
	--then let color determine class
	if not class then
		if colour == 'blue' then
			class = 'mw-ui-progressive'
		elseif colour == 'red' then
			class = 'mw-ui-destructive'
		elseif colour == 'green' then
			class = 'mw-ui-constructive'
		end
	end
	
	if class then
		table.insert(data.classes, class)
	end

	-- Styles
	do
		--[[
		-- Check whether we are on the same page as we have specified in
		-- args[1], but not if we are using a URL link, as then args[1] is only
		-- a display value. If we are currently on the page specified in
		-- args[1] make the button colour darker so that it stands out from
		-- other buttons on the page.
		--]]
		local success, linkTitle, currentTitle
		if not data.isUrl then
			currentTitle = mw.title.getCurrentTitle()
			success, linkTitle = pcall(mw.title.new, args[1])
		elseif p.urlisdisplay then
			currentTitle = mw.title.getCurrentTitle()
		end
		if success
			and linkTitle
			and mw.title.equals(currentTitle, linkTitle)
			and not p.urlisdisplay
		then
			if class == 'ui-button-blue'
				or class == 'mw-ui-progressive'
				or class == 'mw-ui-constructive'
			then
				data.backgroundColor = '#2962CB'
				data.color = '#fff'
			elseif class == 'ui-button-green' then
				data.backgroundColor = '#008B6D'
			elseif class == 'ui-button-red' or class == 'mw-ui-destructive' then
				data.backgroundColor = '#A6170F'
			else
				data.backgroundColor = '#CCC'
				data.color = '#666'
			end
		elseif p.urlisdisplay then
			data.dummyLink = tostring(currentTitle)
		end
		-- Add user-specified styles.
		data.style = args.style
	end
	return data
end

function p.renderLink(originalInput, data)
	-- Render the display span tag.
	local display
	do
		local displaySpan = mw.html.create('span')
		for i, class in ipairs(data.classes or {}) do
			displaySpan:addClass(class)
		end

		displaySpan
			:css{
				['background-color'] = data.backgroundColor,
				color = data.color
			}
		if data.style then
			displaySpan:cssText(data.style)
		end
		displaySpan:wikitext(data.display)
		display = tostring(displaySpan)
	end

	-- Render the link
	local link
	if originalInput and originalInput:find('|') then
		link = string.format('[[%s|%s]]', delink({originalInput, wikilinks = 'target'}), display)
	elseif p.nolink then
		if p.urlisdisplay then
			link = string.format('[[%s|%s]]', data.dummyLink, display)
		else
			link = string.format('%s', display)
		end
	else
		if data.isUrl then
			link = string.format('[%s %s]', data.link, display)
		else
			link = string.format('[[%s |%s]]', data.link, display)
		end
	end

	return string.format('<span class="plainlinks clickbutton">%s</span>', link)
end

function p.renderTrackingCategories(args)
	if yesno(args.category) == false then
		return ''
	end
	local class = args.class and args.class:lower()
	if class == 'ui-button-green'
		or class == 'ui-button-blue'
		or class == 'ui-button-red'
	then
		return '[[Category:Pages using old style ui-button-color]]'
	else
		return ''
	end
end

return p
Cookies help us deliver our services. By using our services, you agree to our use of cookies.