Module:shortcut box: Difference between revisions
No edit summary |
No edit summary |
||
| Line 1: | Line 1: | ||
local export = {} | 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 | |||
end | --[==[ | ||
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 | ||
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("_", " ") | |||
if | break | ||
end | end | ||
i = i - 1 | |||
end | end | ||
end | |||
end | |||
target = current_title.fullText | |||
return target | |||
end | |||
if | 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 | ||
end | end | ||
if | if nocat or uses_hidden_category(current_title or get_current_title()) then | ||
return tostring(div) | |||
end | end | ||
return tostring(div) | |||
end | |||
function export.shortcut_t(frame) | |||
local boolean = {type = "boolean"} | |||
return | 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 | ||