diff --git a/Shortcut/config.lua b/Shortcut/config.lua new file mode 100644 index 0000000..987af39 --- /dev/null +++ b/Shortcut/config.lua @@ -0,0 +1,27 @@ +-- This module holds configuration data for [[Module:Shortcut]]. + +return { + +-- The heading at the top of the shortcut box. It accepts the following parameter: +-- $1 - the total number of shortcuts. (required) +['shortcut-heading'] = '[[BKD:Viết tắt|{{PLURAL:$1|Shortcut|Shortcuts}}]]', + +-- The heading when |redirect=yes is given. It accepts the following parameter: +-- $1 - the total number of shortcuts. (required) +['redirect-heading'] = '[[BKD:Trang đổi hướng|{{PLURAL:$1|Redirect|Redirects}}]]', + +-- The error message to display when a shortcut is invalid (is not a string, or +-- is the blank string). It accepts the following parameter: +-- $1 - the number of the shortcut in the argument list. (required) +['invalid-shortcut-error'] = 'shortcut #$1 was invalid (shortcuts must be ' .. + 'strings of at least one character in length)', + +-- The error message to display when no shortcuts or other displayable content +-- were specified. (required) +['no-content-error'] = 'Error: no shortcuts were specified and the ' .. + mw.text.nowiki('|msg=') .. + ' parameter was not set.', + +-- A category to add when the no-content-error message is displayed. (optional) +['no-content-error-category'] = 'Shortcut templates with missing parameters', +} diff --git a/Shortcut/main.lua b/Shortcut/main.lua new file mode 100644 index 0000000..7231376 --- /dev/null +++ b/Shortcut/main.lua @@ -0,0 +1,155 @@ +-- This module implements {{shortcut}}. + +-- Set constants +local CONFIG_MODULE = 'Module:Shortcut/config' + +-- Load required modules +local checkType = require('libraryUtil').checkType +local yesno = require('Module:Yesno') + +local p = {} + +local function message(msg, ...) + return mw.message.newRawMessage(msg, ...):plain() +end + +local function makeCategoryLink(cat) + return string.format('[[%s:%s]]', mw.site.namespaces[14].name, cat) +end + +function p._main(shortcuts, options, frame, cfg) + checkType('_main', 1, shortcuts, 'table') + checkType('_main', 2, options, 'table', true) + options = options or {} + frame = frame or mw.getCurrentFrame() + cfg = cfg or mw.loadData(CONFIG_MODULE) + local templateMode = options.template and yesno(options.template) + local redirectMode = options.redirect and yesno(options.redirect) + local isCategorized = not options.category or yesno(options.category) ~= false + + -- Validate shortcuts + for i, shortcut in ipairs(shortcuts) do + if type(shortcut) ~= 'string' or #shortcut < 1 then + error(message(cfg['invalid-shortcut-error'], i), 2) + end + end + + -- Make the list items. These are the shortcuts plus any extra lines such + -- as options.msg. + local listItems = {} + for i, shortcut in ipairs(shortcuts) do + local templatePath, prefix + if templateMode then + -- Namespace detection + local titleObj = mw.title.new(shortcut, 10) + if titleObj.namespace == 10 then + templatePath = titleObj.fullText + else + templatePath = shortcut + end + prefix = options['pre' .. i] or options.pre or '' + end + if options.target and yesno(options.target) then + listItems[i] = templateMode + and string.format("{{%s[[%s|%s]]}}", prefix, templatePath, shortcut) + or string.format("[[%s]]", shortcut) + else + listItems[i] = frame:expandTemplate{ + title = 'No redirect', + args = templateMode and {templatePath, shortcut} or {shortcut, shortcut} + } + if templateMode then + listItems[i] = string.format("{{%s%s}}", prefix, listItems[i]) + end + end + end + table.insert(listItems, options.msg) + + -- Return an error if we have nothing to display + if #listItems < 1 then + local msg = cfg['no-content-error'] + msg = string.format('%s', msg) + if isCategorized and cfg['no-content-error-category'] then + msg = msg .. makeCategoryLink(cfg['no-content-error-category']) + end + return msg + end + + local root = mw.html.create() + root:wikitext(frame:extensionTag{ name = 'templatestyles', args = { src = 'Module:Shortcut/styles.css'} }) + -- Anchors + local anchorDiv = root + :tag('div') + :addClass('module-shortcutanchordiv') + for i, shortcut in ipairs(shortcuts) do + local anchor = mw.uri.anchorEncode(shortcut) + anchorDiv:tag('span'):attr('id', anchor) + end + + -- Shortcut heading + local shortcutHeading + do + local nShortcuts = #shortcuts + if nShortcuts > 0 then + local headingMsg = options['shortcut-heading'] or + redirectMode and cfg['redirect-heading'] or + cfg['shortcut-heading'] + shortcutHeading = message(headingMsg, nShortcuts) + shortcutHeading = frame:preprocess(shortcutHeading) + end + end + + -- Shortcut box + local shortcutList = root + :tag('div') + :addClass('module-shortcutboxplain noprint') + :attr('role', 'note') + if options.float and options.float:lower() == 'left' then + shortcutList:addClass('module-shortcutboxleft') + end + if options.clear and options.clear ~= '' then + shortcutList:css('clear', options.clear) + end + if shortcutHeading then + shortcutList + :tag('div') + :addClass('module-shortcutlist') + :wikitext(shortcutHeading) + end + + local ubl = require('Module:List').unbulleted(listItems) + shortcutList:wikitext(ubl) + return tostring(root) +end + +function p.main(frame) + local args = require('Module:Arguments').getArgs(frame) + + -- Separate shortcuts from options + local shortcuts, options = {}, {} + for k, v in pairs(args) do + if type(k) == 'number' then + shortcuts[k] = v + else + options[k] = v + end + end + + -- Compress the shortcut array, which may contain nils. + local function compressArray(t) + local nums, ret = {}, {} + for k in pairs(t) do + nums[#nums + 1] = k + end + table.sort(nums) + for i, num in ipairs(nums) do + ret[i] = t[num] + end + return ret + end + shortcuts = compressArray(shortcuts) + + return p._main(shortcuts, options, frame) +end + +return p