-- TODO 1: normalize keys with leading spaces, which don't get removed when
-- "Tracking/" is prefixed.
-- TODO 2: avoid weird inputs like "", which don't register as invalid since
-- "Tracking/" is a valid page title.
-- TODO 3: use varargs instead of a table input, then recurse with track().
local title_make_title_module = "Module:title/makeTitle"
-- Transclusion-based tracking as subpages of ].
-- Tracked pages can be found at ].
local error = error
local find = string.find
local log = mw.log
local sub = string.sub
local type = type
local invalid_tracking_key_key = "debug/track/invalid key"
local function make_title(...)
make_title = require(title_make_title_module)
return make_title(...)
end
local memo
local function track(key)
if not memo then
memo = {}
-- Return if memoized.
elseif memo then
return
end
-- Throw an error if `key` isn't a string.
local key_type = type(key)
if key_type ~= "string" then
error("Tracking keys supplied to ] must be strings; received " .. key_type .. ".", 3)
end
-- make_title returns nil for invalid titles, but "#" is treated as a
-- fragment separator (e.g. "foo#bar" generates the title "foo"), so it
-- needs to be manually excluded.
local title = not find(key, "#", nil, true) and make_title(4, "Tracking/" .. key)
if not title then
-- Track uses of invalid keys. Instead of recursing, simply memoize the
-- invalid key and replace it with the 'invalid tracking key' key.
-- ]
log("Invalid tracking key: " .. key)
memo = true
key = invalid_tracking_key_key
if memo then
return
end
title = make_title(4, "Tracking/" .. key)
end
-- Normalize the key by treating it as a subpage of "Tracking", which gives
-- the normalized title without the initial "Tracking/". If the normalized
-- form has been memoized, don't transclude the page again. Otherwise,
-- transclude the page using the `content` key on the title, which is the
-- cheapest way to trigger transclusion, as it avoids any parser expansion
-- of the target page.
local normalized = sub(title.text, 10) -- excludes "Tracking/"
if not memo then
title = title.content
memo = true
end
-- Memoize the original key.
memo = true
end
return function(input)
if input == nil then
error("No tracking key supplied to ].", 2)
elseif type(input) ~= "table" then
track(input)
return true
end
local key = input
if key == nil then
error("No tracking keys in table supplied to ].", 2)
end
local i = 1
repeat
track(key)
i = i + 1
key = input
until key == nil
return true
end