Module:Hatnote list

From Zoophilia Wiki
Revision as of 21:33, 18 April 2016 by meta>Nihiltres (Removed behaviour of terminating list at empty page parameter; inconsistent with behaviour elsewhere)
Jump to navigationJump to search

Usage from wikitext

This module is not designed be used directly from wikitext even though forSee does take an initial frame argument and could potentially be used from wikitext, e.g.:

  • {{hatnote|PREFIX {{#invoke:Hatnote list|forSee|{{tl|For}}|Module:For|{{tl|About}}|Module:About}} POSTFIX}}
    PREFIX Lua error at line 103: attempt to call field 'formatPages' (a nil value). POSTFIX

Usage from Lua

To call the module, use <syntaxhighlight lang="lua">local mHatList = require('Module:Hatnote list')</syntaxhighlight> or similar, then access its methods through the mHatList variable (or whatever was used).

andList

andList takes a list in table form, and returns a string with the list separated with "and" and commas as appropriate.

orList

orList takes a list in table form, and returns a string with the list separated with "or" and commas as appropriate.

forSee

_forSee takes three arguments: a table of trimmed arguments with blanks removed, a "from" number with the index to start at, and an options table, and returns a string with a number of "For X, see [[Y]]" sentences. The links are formatted using the methods from Module:Hatnote.

As a convenience, the forSee method (without the leading underscore) takes the same arguments except with a frame instead of an args table, using getArgs() from Module:Arguments to preprocess the arguments.


--------------------------------------------------------------------------------
-- For see
--
-- Makes a "For X, see [[Y]]." list from raw parameters. Intended for the
-- {{about}} and {{redirect}} templates and their variants. Also incidentally
-- introduces andList & orList helpers, useful for other hatnote lists.
--------------------------------------------------------------------------------

local mArguments --initialize lazily
local mHatnote = require('Module:Hatnote')
local libraryUtil = require('libraryUtil')
local checkType = libraryUtil.checkType
local p = {}

function p.andList (andTable)
	-- Stringifies a list with "and"
	local andString = (#andTable > 2 and mw.text.listToText(andTable, nil, ', and ')) or
		mw.text.listToText(andTable)
	return andString
end

function p.orList (orTable)
	-- Stringifies a list with "or"
	local orString = (#andTable > 2 and mw.text.listToText(andTable, nil, ', or ')) or
		mw.text.listToText(andTable, nil, ' or ')
	return orString
end

function p.forSee (frame, from, options)
	-- Calls _forSee but pulls from the frame.
	mArguments = require('Module:Arguments')
	getArgs = mArguments.getArgs

	local args = getArgs(frame)
	return p._forSee(args, from, options)
end

function p._forSee (args, from, options)
	-- Produces a "For X, see [[Y]]" string from arguments. Expects index gaps
	-- but not blank or whitespace values; those should be filtered. Ignores
	-- arguments less than "from", and named arguments.

	-- Type-checks and defaults
	checkType("_forSee", 1, args, 'table')
	checkType("_forSee", 2, from, 'number', true)
	from = from or 1
	checkType("_forSee", 3, options, 'table', true)
	options = options or {}
	local defaultOptions = {
		title = mw.title.getCurrentTitle().text,
		disambiguator = ' (disambiguation)',
		otherText = 'other uses'
	}
	for k, v in pairs(defaultOptions) do
		if options[k] == nil then options[k] = v end
	end

	-- maxArg's gotten manually because getArgs() and table.maxn aren't friends
	local maxArg = 0
	for k, v in pairs(args) do
		if type(k) == 'number' and k > maxArg then maxArg = k end
	end

	-- Structure the data out from the parameter list
	-- forTable is the wrapper table, with forRow rows
	-- Each row's a table with one "use" string and one "see" table
	local forTable = {}
	local i = from
	local terminated = false
	-- Repeat to generate and append each row
	repeat
		-- New empty row
		local forRow = {}
		-- If there's a blank use, assume the list's ended, use the default,
		-- and break at the end of this loop-through.
		forRow.use = args[i] or options.otherText
		if not args[i] then terminated = true end
		-- New empty list of pages
		forRow.see = {}
		-- If there's not at least one page listed, assume the list's ended, use
		-- the default, and break at end of this loop-through.
		table.insert(forRow.see, args[i + 1] or (options.title .. options.disambiguator))
		-- If the option after next is "and", do an inner loop where we collect
		-- items following "and"'s until the "and"'s stop. If there's a blank
		-- where we'd expect an item, ignore it: "1|and||and|3" → {1, 3}
		while args[i + 2] == 'and' do
			if args[i + 3] then 
				table.insert(forRow.see, args[i + 3])
			end
			-- Increment to the next "and"
			i = i + 2
		end
		-- Increment to the next use
		i = i + 2
		-- Add the row to the table
		table.insert(forTable, forRow)
	until terminated or i > maxArg

	-- Stringify the table, which is easy because it's structured now
	local strList = {}
	for k, v in pairs(forTable) do
		local useStr = v.use
		local seeStr = p.andList(mHatnote.formatPages(unpack(v.see)))
		table.insert(strList, string.format('For %s, see %s.', useStr, seeStr))
	end
	return mw.text.listToText(strList, ' ', ' ')
end

return p