Module:Shortcut
-- 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 &lt; 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(&quot;&amp;#123;&amp;#123;%s[[%s|%s]]&amp;#125;&amp;#125;&quot;, prefix, templatePath, shortcut)
 				or string.format(&quot;[[%s]]&quot;, shortcut)
 		else
 			listItems[i] = frame:expandTemplate{
 				title = 'No redirect',
 				args = templateMode and {templatePath, shortcut} or {shortcut, shortcut}
 			}
 			if templateMode then
 				listItems[i] = string.format(&quot;&amp;#123;&amp;#123;%s%s&amp;#125;&amp;#125;&quot;, prefix, listItems[i])
 			end
 		end
 	end
 	table.insert(listItems, options.msg)
 
 	-- Return an error if we have nothing to display
 	if #listItems &lt; 1 then
 		local msg = cfg['no-content-error']
 		msg = string.format('&lt;strong class=&quot;error&quot;&gt;%s&lt;/strong&gt;', 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 &gt; 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