Module:shortcut box: Difference between revisions

From Linguifex
Jump to navigation Jump to search
No edit summary
No edit summary
 
Line 1: Line 1:
local export = {}
local export = {}


function export.show(frame)
local debug_track_module = "Module:debug/track"
local output = {}
local maintenance_category_module = "Module:maintenance category"
-- Hacky way to allow function to be called from other modules.
local pages_module = "Module:pages"
local args = (frame.getParent and frame:getParent().args) or frame
local parameters_module = "Module:parameters"
local demo = false
local template_parser_module = "Module:template parser"
local utilities_module = "Module:utilities"


local FULLPAGENAME = mw.title.getCurrentTitle().fullText
local html_create = mw.html.create
local BASEPAGENAME, SUBPAGENAME = FULLPAGENAME:match("^(.-)/([^/]-)$")
local insert = table.insert
-- BASEPAGENAME = BASEPAGENAME or FULLPAGENAME
local ipairs = ipairs
local require = require
if frame.getParent and FULLPAGENAME == frame:getParent():getTitle() then
local tostring = tostring
demo = true
 
end
--[==[
output[#output + 1] = [[<div class="plainlinks" style="border: 1px solid #aaa; color: black; background: #f9f9f9;
Loaders for functions in other modules, which overwrite themselves with the target function when called. This ensures modules are only loaded when needed, retains the speed/convenience of locally-declared pre-loaded functions, and has no overhead after the first call, since the target functions are called directly in any subsequent calls.]==]
margin: 0 0 .5em 1em; text-align: center; padding: 5px; float: right; clear: both; font-weight: bold; font-size: smaller;">]]
local function format_categories(...)
format_categories = require(utilities_module).format_categories
return format_categories(...)
end
 
local function get_namespace_shortcut(...)
get_namespace_shortcut = require(pages_module).get_namespace_shortcut
return get_namespace_shortcut(...)
end
 
local function get_template_invocation_name(...)
get_template_invocation_name = require(template_parser_module).getTemplateInvocationName
return get_template_invocation_name(...)
end
 
local function process_params(...)
process_params = require(parameters_module).process
return process_params(...)
end
 
local function track(...)
track = require(debug_track_module)
return track(...)
end


if args.temp then
local function uses_hidden_category(...)
output[#output + 1] = "Temporary [[wikt:Wiktionary:Shortcut|shortcut" .. (args[2] and 's' or '') .. "]]:<br/>"
uses_hidden_category = require(maintenance_category_module).uses_hidden_category
else
return uses_hidden_category(...)
output[#output + 1] = "[[wikt:Wiktionary:Shortcut|Shortcut" .. (args[2] and 's' or '') .. "]]:<br/>"
end
end
local attn = false


for i, shortcut in ipairs(args) do
--[==[
local title = mw.title.new(shortcut)
Loaders for objects, which load data (or some other object) into some variable, which can then be accessed as "foo or get_foo()", where the function get_foo sets the object to "foo" and then returns it. This ensures they are only loaded when needed, and avoids the need to check for the existence of the object each time, since once "foo" has been set, "get_foo" will not be called again.]==]
local current_title
if not title then
local function get_current_title()
output[#output + 1] = '<span class="attentionseeking">(<code>' .. mw.text.nowiki(shortcut) .. '</code>)</span><br/>'
current_title, get_current_title = mw.title.getCurrentTitle(), nil
attn = true
return current_title
else
end
local iattn = false


local item
local is_documentation
local function get_is_documentation()
is_documentation, get_is_documentation = require(pages_module).is_documentation(current_title or get_current_title()), nil
return is_documentation
end


if not title.exists then
local target
attn = true
local function get_target()
local query = 'action=edit&redlink=1&preloadtext=' .. mw.uri.encode('#REDIRECT [[' .. FULLPAGENAME .. ']]')
get_target = nil
if title.nsText == "Template" then
-- If it's a documentation page, make the target point to the base page.
item = '<code>{{[' .. tostring(mw.uri.fullUrl(shortcut, query)) .. ' <span style="color:#c20;">' .. title.text .. '</span>]}}</code>'
if is_documentation == nil and get_is_documentation() or is_documentation then
else
target = ((current_title or get_current_title()).basePageTitle or current_title).fullText -- Fallback is a failsafe, but shouldn't be needed.
item = '[' .. tostring(mw.uri.fullUrl(shortcut, query)) .. ' <span style="color:#c20;">' .. shortcut .. '</span>]'
return target
end
local namespace = (current_title or get_current_title()).namespace
-- Unless the page is a template or module, point to the current section with a fragment. Otherwise, just point to the current page.
if not (namespace == 10 or (namespace == 828 and current_title.contentModel == "Scribunto")) then
local current_section = require(pages_module).get_current_section()
if current_section ~= 0 then -- Section 0 is everything before the first heading (i.e. the top of the page).
local headings, i = {}, 0
for heading in require(template_parser_module).find_headings(current_title.content) do
i = i + 1
headings[i] = heading
if heading.section == current_section then
break
end
end
else
end
if title.nsText == "Template" then
-- Once the current section has been found, validate headings in reverse order until a valid one is found.
item = '<code>{{[' .. tostring(mw.uri.fullUrl(shortcut, 'redirect=no')) .. ' ' .. title.text .. ']}}</code>'
while i ~= 0 do
else
local anchor = headings[i]:get_anchor()
item = '[' .. tostring(mw.uri.fullUrl(shortcut, 'redirect=no')) .. ' ' .. shortcut .. ']'
if anchor ~= nil then
end
-- Add the fragment.
current_title.fragment = anchor:gsub("_", " ")
if not demo then
break
local redirectTarget = title.redirectTarget
if redirectTarget then
redirectTarget.fragment = '' -- remove fragment, if present
local targetText = redirectTarget.fullText
if title.nsText == "Template" then
if SUBPAGENAME == 'doc' then
iattn = (targetText ~= BASEPAGENAME)
else
iattn = (targetText ~= FULLPAGENAME)
end
else
if SUBPAGENAME == 'doc' then
iattn = not (targetText == BASEPAGENAME
or targetText == FULLPAGENAME)
else
iattn = not (targetText == FULLPAGENAME
or targetText == FULLPAGENAME .. '/doc')
end
end
end
if not (redirectTarget and redirectTarget.exists) then
iattn = true
end
end
end
i = i - 1
end
end
end
end
target = current_title.fullText
return target
end


if iattn then
local function handle_shortcut(title, demo)
item = '<span class="attentionseeking">' .. item .. '</span>'
local namespace = title.namespace
end
local text = namespace == 0 and title.text or
namespace == 10 and get_template_invocation_name(title, "shortcut") or
get_namespace_shortcut(title) .. ":" .. title.text
local redlink, query = not title.content
if redlink then
query = {
action = "edit",
redlink = true,
preloadtext = not demo and "#REDIRECT [[" .. (target or get_target()) .. "]]" or nil
}
else
query = {
redirect = "no",
}
end
local tag = html_create("code"):wikitext((namespace == 10 and "{{[" or "[") .. tostring(title:fullUrl(query)) .. " ")
if redlink then
text = html_create("span")
:addClass("redlink")
:wikitext(text)
end
tag = tag:node(text):wikitext(namespace == 10 and "]}}" or "]")
if demo then
return tag
elseif redlink then
tag:addClass("attentionseeking")
return tag, "redlink"
end
-- Check the target is correct.
local redirect = title.redirectTarget
if redirect and redirect.fullText == (target or get_target()) then
return tag
end
-- If not, flag for attention.
tag:addClass("attentionseeking")
return tag, "not shortcut"
end


output[#output + 1] = item .. '<br/>'
-- Takes `list`, an array of title objects, and returns a shortcut box.
function export.format_shortcuts(list, temp, nocat, demo)
attn = attn or iattn
if nocat then
track("shortcut box/nocat")
end
local div = html_create("div")
:addClass("noprint")
:addClass("plainlinks")
:addClass("shortcut-box")
:wikitext(("%s[[wikt:Wiktionary:Shortcut|%shortcut%s]]:"):format(
temp and "Temporary " or "",
temp and "s" or "S",
list[2] and "s" or ""
))
local redlink, not_shortcut
for _, shortcut in ipairs(list) do
div:tag("br")
local shortcut, cat = handle_shortcut(shortcut, demo)
div:node(shortcut)
if cat == "redlink" then
redlink = true
elseif cat == "not shortcut" then
not_shortcut = true
end
end
end
end
 
if not args.nocat then
if nocat or uses_hidden_category(current_title or get_current_title()) then
if attn then
return tostring(div)
output[#output + 1] = '[[Category:Shortcut boxes needing attention]]'
end
if SUBPAGENAME ~= 'doc' and FULLPAGENAME ~= 'Template:Shortcut' then
output[#output + 1] = '[[Category:Templates with shortcuts]]'
end
end
end
return tostring(div)
end


output[#output + 1] = '</div>'
function export.shortcut_t(frame)
local boolean = {type = "boolean"}
return table.concat(output)
local params = {
-- Namespace 10 is Template.
[1] = {required = true, type = "title", namespace = 10,
list = true, sublist = "comma without whitespace", flatten = true},
["demo"] = {type = "boolean", demo = true},
["nocat"] = boolean, -- To be removed: no use-case.
["temp"] = boolean,
}
local args = process_params(frame:getParent().args, params)
return export.format_shortcuts(args[1], args.temp, args.nocat, args.demo)
end
end


return export
return export

Latest revision as of 11:11, 2 May 2026



local export = {}

local debug_track_module = "Module:debug/track"
local maintenance_category_module = "Module:maintenance category"
local pages_module = "Module:pages"
local parameters_module = "Module:parameters"
local template_parser_module = "Module:template parser"
local utilities_module = "Module:utilities"

local html_create = mw.html.create
local insert = table.insert
local ipairs = ipairs
local require = require
local tostring = tostring

--[==[
Loaders for functions in other modules, which overwrite themselves with the target function when called. This ensures modules are only loaded when needed, retains the speed/convenience of locally-declared pre-loaded functions, and has no overhead after the first call, since the target functions are called directly in any subsequent calls.]==]
local function format_categories(...)
	format_categories = require(utilities_module).format_categories
	return format_categories(...)
end

local function get_namespace_shortcut(...)
	get_namespace_shortcut = require(pages_module).get_namespace_shortcut
	return get_namespace_shortcut(...)
end

local function get_template_invocation_name(...)
	get_template_invocation_name = require(template_parser_module).getTemplateInvocationName
	return get_template_invocation_name(...)
end

local function process_params(...)
	process_params = require(parameters_module).process
	return process_params(...)
end

local function track(...)
	track = require(debug_track_module)
	return track(...)
end

local function uses_hidden_category(...)
	uses_hidden_category = require(maintenance_category_module).uses_hidden_category
	return uses_hidden_category(...)
end

--[==[
Loaders for objects, which load data (or some other object) into some variable, which can then be accessed as "foo or get_foo()", where the function get_foo sets the object to "foo" and then returns it. This ensures they are only loaded when needed, and avoids the need to check for the existence of the object each time, since once "foo" has been set, "get_foo" will not be called again.]==]
local current_title
local function get_current_title()
	current_title, get_current_title = mw.title.getCurrentTitle(), nil
	return current_title
end

local is_documentation
local function get_is_documentation()
	is_documentation, get_is_documentation = require(pages_module).is_documentation(current_title or get_current_title()), nil
	return is_documentation
end

local target
local function get_target()
	get_target = nil
	-- If it's a documentation page, make the target point to the base page.
	if is_documentation == nil and get_is_documentation() or is_documentation then
		target = ((current_title or get_current_title()).basePageTitle or current_title).fullText -- Fallback is a failsafe, but shouldn't be needed.
		return target
	end
	local namespace = (current_title or get_current_title()).namespace
	-- Unless the page is a template or module, point to the current section with a fragment. Otherwise, just point to the current page.
	if not (namespace == 10 or (namespace == 828 and current_title.contentModel == "Scribunto")) then
		local current_section = require(pages_module).get_current_section()
		if current_section ~= 0 then -- Section 0 is everything before the first heading (i.e. the top of the page).
			local headings, i = {}, 0
			for heading in require(template_parser_module).find_headings(current_title.content) do
				i = i + 1
				headings[i] = heading
				if heading.section == current_section then
					break
				end
			end
			-- Once the current section has been found, validate headings in reverse order until a valid one is found.
			while i ~= 0 do
				local anchor = headings[i]:get_anchor()
				if anchor ~= nil then
					-- Add the fragment.
					current_title.fragment = anchor:gsub("_", " ")
					break
				end
				i = i - 1
			end
		end
	end
	target = current_title.fullText
	return target
end

local function handle_shortcut(title, demo)
	local namespace = title.namespace
	local text = namespace == 0 and title.text or
		namespace == 10 and get_template_invocation_name(title, "shortcut") or
		get_namespace_shortcut(title) .. ":" .. title.text
	local redlink, query = not title.content
	if redlink then
		query = {
			action = "edit",
			redlink = true,
			preloadtext = not demo and "#REDIRECT [[" .. (target or get_target()) .. "]]" or nil
		}
	else
		query = {
			redirect = "no",
		}
	end
	local tag = html_create("code"):wikitext((namespace == 10 and "{{[" or "[") .. tostring(title:fullUrl(query)) .. " ")
	if redlink then
		text = html_create("span")
			:addClass("redlink")
			:wikitext(text)
	end
	tag = tag:node(text):wikitext(namespace == 10 and "]}}" or "]")
	if demo then
		return tag
	elseif redlink then
		tag:addClass("attentionseeking")
		return tag, "redlink"
	end
	-- Check the target is correct.
	local redirect = title.redirectTarget
	if redirect and redirect.fullText == (target or get_target()) then
		return tag
	end
	-- If not, flag for attention.
	tag:addClass("attentionseeking")
	return tag, "not shortcut"
end

-- Takes `list`, an array of title objects, and returns a shortcut box.
function export.format_shortcuts(list, temp, nocat, demo)
	if nocat then
		track("shortcut box/nocat")
	end
	
	local div = html_create("div")
		:addClass("noprint")
		:addClass("plainlinks")
		:addClass("shortcut-box")
		:wikitext(("%s[[wikt:Wiktionary:Shortcut|%shortcut%s]]:"):format(
			temp and "Temporary " or "",
			temp and "s" or "S",
			list[2] and "s" or ""
		))
	
	local redlink, not_shortcut
	for _, shortcut in ipairs(list) do
		div:tag("br")
		local shortcut, cat = handle_shortcut(shortcut, demo)
		div:node(shortcut)
		if cat == "redlink" then
			redlink = true
		elseif cat == "not shortcut" then
			not_shortcut = true
		end
	end
	
	if nocat or uses_hidden_category(current_title or get_current_title()) then
		return tostring(div)
	end
	
	return tostring(div)
end

function export.shortcut_t(frame)
	local boolean = {type = "boolean"}
	local params = {
		-- Namespace 10 is Template.
		[1] = {required = true, type = "title",	namespace = 10,
			list = true, sublist = "comma without whitespace", flatten = true},
		["demo"] = {type = "boolean", demo = true},
		["nocat"] = boolean, -- To be removed: no use-case.
		["temp"] = boolean,
	}
	local args = process_params(frame:getParent().args, params)
	return export.format_shortcuts(args[1], args.temp, args.nocat, args.demo)
end

return export