<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-GB">
	<id>https://wiki.shroudforge.net/index.php?action=history&amp;feed=atom&amp;title=Module%3ADependencies</id>
	<title>Module:Dependencies - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.shroudforge.net/index.php?action=history&amp;feed=atom&amp;title=Module%3ADependencies"/>
	<link rel="alternate" type="text/html" href="https://wiki.shroudforge.net/index.php?title=Module:Dependencies&amp;action=history"/>
	<updated>2026-11-05T07:09:00Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.46.2</generator>
	<entry>
		<id>https://wiki.shroudforge.net/index.php?title=Module:Dependencies&amp;diff=88&amp;oldid=prev</id>
		<title>Bonsaibauer: 1 revision imported: Import Star Citizen Modules</title>
		<link rel="alternate" type="text/html" href="https://wiki.shroudforge.net/index.php?title=Module:Dependencies&amp;diff=88&amp;oldid=prev"/>
		<updated>2026-11-04T22:22:09Z</updated>

		<summary type="html">&lt;p&gt;1 revision imported: Import Star Citizen Modules&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw-interface=&quot;&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en-GB&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 22:22, 4 November 2026&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;4&quot; class=&quot;diff-notice&quot; lang=&quot;en-GB&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(No difference)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;!-- diff cache key mediawiki-mediawiki:diff:1.41:old-87:rev-88 --&gt;
&lt;/table&gt;</summary>
		<author><name>Bonsaibauer</name></author>
	</entry>
	<entry>
		<id>https://wiki.shroudforge.net/index.php?title=Module:Dependencies&amp;diff=87&amp;oldid=prev</id>
		<title>starcitizen&gt;Alistar Bot: Sync from Git (becda4f): draw SVG thumbnails as silhouettes (via update-page on MediaWiki MCP Server)</title>
		<link rel="alternate" type="text/html" href="https://wiki.shroudforge.net/index.php?title=Module:Dependencies&amp;diff=87&amp;oldid=prev"/>
		<updated>2026-10-08T16:49:48Z</updated>

		<summary type="html">&lt;p&gt;Sync from Git (becda4f): draw SVG thumbnails as silhouettes (via update-page on MediaWiki MCP Server)&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;require(&amp;#039;strict&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
--- @module Dependencies&lt;br /&gt;
--- The folded &amp;quot;Technical details&amp;quot; panel Module:Documentation shows on module and&lt;br /&gt;
--- template pages: which pages use the page, what it uses, and the functions a&lt;br /&gt;
--- module defines; and the `dependencies` Bucket row each page writes so the&lt;br /&gt;
--- modules and stylesheets it uses can list it. Forward lists come from the&lt;br /&gt;
--- page&amp;#039;s own source; reverse lists come from the rows other pages wrote.&lt;br /&gt;
&lt;br /&gt;
local parse = require(&amp;#039;Module:Dependencies/Parse&amp;#039;)&lt;br /&gt;
local mbox = require(&amp;#039;Module:Mbox&amp;#039;)&lt;br /&gt;
local icon = require(&amp;#039;Module:Icon&amp;#039;)&lt;br /&gt;
local yesno = require(&amp;#039;Module:Yesno&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
local BUCKET = &amp;#039;dependencies&amp;#039;&lt;br /&gt;
local NS_TEMPLATE = 10&lt;br /&gt;
local NS_MODULE = 828&lt;br /&gt;
local HEADING = &amp;#039;Technical details&amp;#039;&lt;br /&gt;
local ICON = &amp;#039;WikimediaUI-Code.svg&amp;#039;&lt;br /&gt;
local ROW_ICONS = {&lt;br /&gt;
	source = &amp;#039;CdxIconReference.svg&amp;#039;,&lt;br /&gt;
	usedBy = &amp;#039;CdxIconArrowPrevious.svg&amp;#039;,&lt;br /&gt;
	uses = &amp;#039;CdxIconArrowNext.svg&amp;#039;,&lt;br /&gt;
	functions = &amp;#039;CdxIconFunction.svg&amp;#039;,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
local UNUSED_TEXT = &amp;#039;No template invokes it and no module requires or loads it. &amp;#039;&lt;br /&gt;
	.. &amp;#039;If an article invokes it directly, call it through a template instead.&amp;#039;&lt;br /&gt;
local UNAVAILABLE_TEXT = &amp;#039;Unavailable: looking up the pages that use it failed on this render. &amp;#039;&lt;br /&gt;
	.. &amp;#039;Purge the page to retry.&amp;#039;&lt;br /&gt;
&lt;br /&gt;
--- @class DependenciesContext&lt;br /&gt;
--- @field title string the documented page, e.g. `Module:Mbox`&lt;br /&gt;
--- @field prefix string its namespace with the colon, e.g. `Module:`&lt;br /&gt;
--- @field namespace integer&lt;br /&gt;
--- @field content string|nil its source&lt;br /&gt;
--- @field isCurrent boolean the render is the page itself, not its /doc or another page&lt;br /&gt;
--- @field excluded boolean a sandbox or testcases page, whose dependencies are not real usage&lt;br /&gt;
&lt;br /&gt;
--- @class DependenciesGroup&lt;br /&gt;
--- @field label string e.g. `Required by`&lt;br /&gt;
--- @field items string[] wikitext, one per list item&lt;br /&gt;
--- @field note string|nil wikitext under the list&lt;br /&gt;
--- @field modifier string|nil the list&amp;#039;s `t-dependencies__list--` modifier&lt;br /&gt;
&lt;br /&gt;
--- @class DependenciesReport&lt;br /&gt;
--- @field usedBy DependenciesGroup[]|nil nil when the reverse lookup failed&lt;br /&gt;
--- @field uses DependenciesGroup[]&lt;br /&gt;
--- @field usedByCount integer distinct pages across `usedBy`&lt;br /&gt;
--- @field usesCount integer entries across `uses`&lt;br /&gt;
--- @field unused boolean a module nothing invokes, requires or loads&lt;br /&gt;
--- @field functions ModuleTocFunction[]&lt;br /&gt;
&lt;br /&gt;
--- @class DependenciesSource&lt;br /&gt;
--- @field label string plain text for the folded header, e.g. `wiki-tools`&lt;br /&gt;
--- @field text string wikitext, one line of the Source row&lt;br /&gt;
&lt;br /&gt;
--- @class DependenciesPanelOptions&lt;br /&gt;
--- @field page string|nil the page to describe; default the current page, or the page a /doc documents&lt;br /&gt;
--- @field addCategories boolean|string|nil defaults to true except on a /doc render&lt;br /&gt;
--- @field sources DependenciesSource[]|nil&lt;br /&gt;
&lt;br /&gt;
--- @param title table mw.title&lt;br /&gt;
--- @return boolean&lt;br /&gt;
local function isExcluded(title)&lt;br /&gt;
	local text = title.text:lower()&lt;br /&gt;
	return text:find(&amp;#039;^sandbox/&amp;#039;) ~= nil or text:find(&amp;#039;/sandbox&amp;#039;) ~= nil or text:find(&amp;#039;/testcases&amp;#039;) ~= nil&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- @param pageName string|nil&lt;br /&gt;
--- @return DependenciesContext|nil&lt;br /&gt;
local function context(pageName)&lt;br /&gt;
	local current = mw.title.getCurrentTitle()&lt;br /&gt;
	local target = pageName and mw.title.new(pageName) or current&lt;br /&gt;
	if target == nil then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	if target.isSubpage and target.subpageText:lower() == &amp;#039;doc&amp;#039; then&lt;br /&gt;
		target = target.basePageTitle&lt;br /&gt;
	end&lt;br /&gt;
	if target.namespace ~= NS_TEMPLATE and target.namespace ~= NS_MODULE then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	return {&lt;br /&gt;
		title = target.prefixedText,&lt;br /&gt;
		prefix = target.prefixedText:match(&amp;#039;^[^:]+:&amp;#039;),&lt;br /&gt;
		namespace = target.namespace,&lt;br /&gt;
		content = target:getContent(),&lt;br /&gt;
		isCurrent = current.prefixedText == target.prefixedText,&lt;br /&gt;
		excluded = isExcluded(target),&lt;br /&gt;
	}&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- @param list any&lt;br /&gt;
--- @param value string&lt;br /&gt;
--- @return boolean&lt;br /&gt;
local function contains(list, value)&lt;br /&gt;
	for _, item in ipairs(type(list) == &amp;#039;table&amp;#039; and list or {}) do&lt;br /&gt;
		if item == value then&lt;br /&gt;
			return true&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return false&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- `files` with the files `extra` names added.&lt;br /&gt;
--- @param files DependenciesFiles&lt;br /&gt;
--- @param extra DependenciesFiles&lt;br /&gt;
--- @return DependenciesFiles&lt;br /&gt;
local function mergeFiles(files, extra)&lt;br /&gt;
	local merged = { names = {}, urls = {}, dynamic = {} }&lt;br /&gt;
	for _, key in ipairs({ &amp;#039;names&amp;#039;, &amp;#039;dynamic&amp;#039; }) do&lt;br /&gt;
		local seen = {}&lt;br /&gt;
		for _, list in ipairs({ files[key], extra[key] }) do&lt;br /&gt;
			for _, value in ipairs(list) do&lt;br /&gt;
				if not seen[value] then&lt;br /&gt;
					seen[value] = true&lt;br /&gt;
					merged[key][#merged[key] + 1] = value&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		table.sort(merged[key])&lt;br /&gt;
	end&lt;br /&gt;
	local seen = {}&lt;br /&gt;
	for _, list in ipairs({ files.urls, extra.urls }) do&lt;br /&gt;
		for _, url in ipairs(list) do&lt;br /&gt;
			local key = url.name .. &amp;#039;|&amp;#039; .. url.path&lt;br /&gt;
			if not seen[key] then&lt;br /&gt;
				seen[key] = true&lt;br /&gt;
				merged.urls[#merged.urls + 1] = url&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return merged&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- What the page itself uses: a module&amp;#039;s requires, loads, stylesheets and&lt;br /&gt;
--- files, a template&amp;#039;s invokes, stylesheets and files. The files include those&lt;br /&gt;
--- the page&amp;#039;s own `/styles.css` names when the page loads it; any other&lt;br /&gt;
--- stylesheet lists its files on the page that owns it.&lt;br /&gt;
--- @param ctx DependenciesContext&lt;br /&gt;
--- @return table&lt;br /&gt;
local function forward(ctx)&lt;br /&gt;
	local found&lt;br /&gt;
	if ctx.namespace == NS_MODULE then&lt;br /&gt;
		found = parse.lua(ctx.content)&lt;br /&gt;
		found.invokes = {}&lt;br /&gt;
	else&lt;br /&gt;
		found = {&lt;br /&gt;
			requires = {},&lt;br /&gt;
			loads = {},&lt;br /&gt;
			dynamic = {},&lt;br /&gt;
			strict = false,&lt;br /&gt;
			invokes = parse.invokes(ctx.content),&lt;br /&gt;
			styles = parse.styles(ctx.content),&lt;br /&gt;
			files = parse.files(ctx.content),&lt;br /&gt;
		}&lt;br /&gt;
	end&lt;br /&gt;
	local own = ctx.title .. &amp;#039;/styles.css&amp;#039;&lt;br /&gt;
	local stylesheet = contains(found.styles, own) and mw.title.new(own)&lt;br /&gt;
	local css = stylesheet and stylesheet:getContent()&lt;br /&gt;
	if css then&lt;br /&gt;
		found.files = mergeFiles(found.files, parse.stylesheetFiles(css))&lt;br /&gt;
	end&lt;br /&gt;
	return found&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- The page&amp;#039;s `dependencies` row, or nil when it uses nothing.&lt;br /&gt;
--- @param found table&lt;br /&gt;
--- @return table|nil&lt;br /&gt;
local function rowFor(found)&lt;br /&gt;
	local invokes, calls, seen = {}, {}, {}&lt;br /&gt;
	for _, call in ipairs(found.invokes) do&lt;br /&gt;
		if not seen[call.module] then&lt;br /&gt;
			seen[call.module] = true&lt;br /&gt;
			invokes[#invokes + 1] = call.module&lt;br /&gt;
		end&lt;br /&gt;
		calls[#calls + 1] = call.module .. &amp;#039;|&amp;#039; .. call.func&lt;br /&gt;
	end&lt;br /&gt;
	local row = {}&lt;br /&gt;
	local function set(field, list)&lt;br /&gt;
		if list[1] ~= nil then&lt;br /&gt;
			row[field] = list&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	set(&amp;#039;requires&amp;#039;, found.requires)&lt;br /&gt;
	set(&amp;#039;loads&amp;#039;, found.loads)&lt;br /&gt;
	set(&amp;#039;invokes&amp;#039;, invokes)&lt;br /&gt;
	set(&amp;#039;invoke_calls&amp;#039;, calls)&lt;br /&gt;
	set(&amp;#039;styles&amp;#039;, found.styles)&lt;br /&gt;
	if next(row) == nil then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	return row&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- @param ctx DependenciesContext&lt;br /&gt;
--- @param found table&lt;br /&gt;
local function write(ctx, found)&lt;br /&gt;
	if not ctx.isCurrent or ctx.excluded then&lt;br /&gt;
		return&lt;br /&gt;
	end&lt;br /&gt;
	local row = rowFor(found)&lt;br /&gt;
	if row == nil then&lt;br /&gt;
		return&lt;br /&gt;
	end&lt;br /&gt;
	pcall(function()&lt;br /&gt;
		mw.ext.bucket(BUCKET).put(row)&lt;br /&gt;
	end)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Splits the rows naming `title` into the pages that invoke, require and load&lt;br /&gt;
--- it, and the pages that load its `/styles.css`.&lt;br /&gt;
--- @param rows table[] raw Bucket rows keyed by field name (page_name, requires, loads, invokes, invoke_calls, styles)&lt;br /&gt;
--- @param title string&lt;br /&gt;
--- @return { invokedBy: { page: string, funcs: string[] }[], requiredBy: string[], loadedBy: string[], styledBy: string[] }&lt;br /&gt;
local function group(rows, title)&lt;br /&gt;
	local back = { invokedBy = {}, requiredBy = {}, loadedBy = {}, styledBy = {} }&lt;br /&gt;
	local prefix = title .. &amp;#039;|&amp;#039;&lt;br /&gt;
	local stylesheet = title .. &amp;#039;/styles.css&amp;#039;&lt;br /&gt;
	for _, row in ipairs(rows) do&lt;br /&gt;
		local page = row.page_name&lt;br /&gt;
		if page and page ~= title then&lt;br /&gt;
			if contains(row.invokes, title) then&lt;br /&gt;
				local funcs, seen = {}, {}&lt;br /&gt;
				for _, call in ipairs(type(row.invoke_calls) == &amp;#039;table&amp;#039; and row.invoke_calls or {}) do&lt;br /&gt;
					local func = call:sub(1, #prefix) == prefix and call:sub(#prefix + 1) or nil&lt;br /&gt;
					if func and not seen[func] then&lt;br /&gt;
						seen[func] = true&lt;br /&gt;
						funcs[#funcs + 1] = func&lt;br /&gt;
					end&lt;br /&gt;
				end&lt;br /&gt;
				back.invokedBy[#back.invokedBy + 1] = { page = page, funcs = funcs }&lt;br /&gt;
			end&lt;br /&gt;
			if contains(row.requires, title) then&lt;br /&gt;
				back.requiredBy[#back.requiredBy + 1] = page&lt;br /&gt;
			end&lt;br /&gt;
			if contains(row.loads, title) then&lt;br /&gt;
				back.loadedBy[#back.loadedBy + 1] = page&lt;br /&gt;
			end&lt;br /&gt;
			if contains(row.styles, stylesheet) then&lt;br /&gt;
				back.styledBy[#back.styledBy + 1] = page&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	table.sort(back.invokedBy, function(a, b)&lt;br /&gt;
		return a.page &amp;lt; b.page&lt;br /&gt;
	end)&lt;br /&gt;
	table.sort(back.requiredBy)&lt;br /&gt;
	table.sort(back.loadedBy)&lt;br /&gt;
	table.sort(back.styledBy)&lt;br /&gt;
	return back&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- The pages that use `title`, or nil when the lookup failed.&lt;br /&gt;
--- Queries Bucket directly: Module:BucketQuery would load and link every&lt;br /&gt;
--- manifest registered ahead of this one on each documentation render.&lt;br /&gt;
--- @param title string&lt;br /&gt;
--- @return table|nil&lt;br /&gt;
local function reverse(title)&lt;br /&gt;
	local ok, rows = pcall(function()&lt;br /&gt;
		local bucket = mw.ext.bucket&lt;br /&gt;
		return bucket(BUCKET)&lt;br /&gt;
			.select(&amp;#039;page_name&amp;#039;, &amp;#039;requires&amp;#039;, &amp;#039;loads&amp;#039;, &amp;#039;invokes&amp;#039;, &amp;#039;invoke_calls&amp;#039;, &amp;#039;styles&amp;#039;)&lt;br /&gt;
			.where(&lt;br /&gt;
				bucket.Or(&lt;br /&gt;
					{ &amp;#039;requires&amp;#039;, title },&lt;br /&gt;
					{ &amp;#039;loads&amp;#039;, title },&lt;br /&gt;
					{ &amp;#039;invokes&amp;#039;, title },&lt;br /&gt;
					{ &amp;#039;styles&amp;#039;, title .. &amp;#039;/styles.css&amp;#039; }&lt;br /&gt;
				)&lt;br /&gt;
			)&lt;br /&gt;
			.limit(5000)&lt;br /&gt;
			.run()&lt;br /&gt;
	end)&lt;br /&gt;
	if not ok or type(rows) ~= &amp;#039;table&amp;#039; then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	return group(rows, title)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- @param text string&lt;br /&gt;
--- @return string&lt;br /&gt;
local function code(text)&lt;br /&gt;
	return &amp;#039;&amp;lt;code&amp;gt;&amp;#039; .. mw.text.nowiki(text) .. &amp;#039;&amp;lt;/code&amp;gt;&amp;#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- A link to `name` as a row shows it: one of the documented page&amp;#039;s own subpages&lt;br /&gt;
--- relative (`/styles.css`), otherwise without `prefix`, the namespace the row&lt;br /&gt;
--- already implies.&lt;br /&gt;
--- @param name string&lt;br /&gt;
--- @param ctx DependenciesContext&lt;br /&gt;
--- @param prefix string&lt;br /&gt;
--- @return string&lt;br /&gt;
local function link(name, ctx, prefix)&lt;br /&gt;
	local own = ctx.title .. &amp;#039;/&amp;#039;&lt;br /&gt;
	local text = name&lt;br /&gt;
	if name:sub(1, #own) == own then&lt;br /&gt;
		text = name:sub(#own)&lt;br /&gt;
	elseif name:sub(1, #prefix) == prefix then&lt;br /&gt;
		text = name:sub(#prefix + 1)&lt;br /&gt;
	end&lt;br /&gt;
	if text == name then&lt;br /&gt;
		return &amp;#039;[[&amp;#039; .. name .. &amp;#039;]]&amp;#039;&lt;br /&gt;
	end&lt;br /&gt;
	return &amp;#039;[[&amp;#039; .. name .. &amp;#039;|&amp;#039; .. text .. &amp;#039;]]&amp;#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- @param names string[]&lt;br /&gt;
--- @param ctx DependenciesContext&lt;br /&gt;
--- @param prefix string&lt;br /&gt;
--- @return string[]&lt;br /&gt;
local function links(names, ctx, prefix)&lt;br /&gt;
	local items = {}&lt;br /&gt;
	for i, name in ipairs(names) do&lt;br /&gt;
		items[i] = link(name, ctx, prefix)&lt;br /&gt;
	end&lt;br /&gt;
	return items&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- The templates that invoke the page, each with the functions it calls. When&lt;br /&gt;
--- every one calls the same single function, the note names it once instead.&lt;br /&gt;
--- @param entries { page: string, funcs: string[] }[]&lt;br /&gt;
--- @param ctx DependenciesContext&lt;br /&gt;
--- @return string[] items&lt;br /&gt;
--- @return string|nil note&lt;br /&gt;
local function invokers(entries, ctx)&lt;br /&gt;
	local shared = entries[1] and entries[1].funcs[1]&lt;br /&gt;
	for _, entry in ipairs(entries) do&lt;br /&gt;
		if #entry.funcs ~= 1 or entry.funcs[1] ~= shared then&lt;br /&gt;
			shared = nil&lt;br /&gt;
			break&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	local items = {}&lt;br /&gt;
	for i, entry in ipairs(entries) do&lt;br /&gt;
		items[i] = link(entry.page, ctx, &amp;#039;Template:&amp;#039;)&lt;br /&gt;
		if shared == nil and entry.funcs[1] ~= nil then&lt;br /&gt;
			local funcs = {}&lt;br /&gt;
			for j, func in ipairs(entry.funcs) do&lt;br /&gt;
				funcs[j] = code(func)&lt;br /&gt;
			end&lt;br /&gt;
			items[i] = items[i] .. &amp;#039; (&amp;#039; .. table.concat(funcs, &amp;#039;, &amp;#039;) .. &amp;#039;)&amp;#039;&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if shared == nil then&lt;br /&gt;
		return items, nil&lt;br /&gt;
	end&lt;br /&gt;
	return items, (#entries &amp;gt; 1 and &amp;#039;All via &amp;#039; or &amp;#039;Via &amp;#039;) .. code(shared)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- @param into DependenciesGroup[]&lt;br /&gt;
--- @param label string&lt;br /&gt;
--- @param items string[]&lt;br /&gt;
--- @param note string|nil&lt;br /&gt;
--- @param modifier string|nil&lt;br /&gt;
local function addGroup(into, label, items, note, modifier)&lt;br /&gt;
	if items[1] ~= nil then&lt;br /&gt;
		into[#into + 1] = { label = label, items = items, note = note, modifier = modifier }&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- What is wrong with each media URL, by file name: a path that is not the&lt;br /&gt;
--- md5 directories of the name, or a file that has moved, which `[[File:]]`&lt;br /&gt;
--- follows but a URL does not.&lt;br /&gt;
--- @param urls DependenciesFileUrl[]&lt;br /&gt;
--- @return table&amp;lt;string, string[]&amp;gt;&lt;br /&gt;
local function urlProblems(urls)&lt;br /&gt;
	local problems, checked = {}, {}&lt;br /&gt;
	local function add(name, text)&lt;br /&gt;
		problems[name] = problems[name] or {}&lt;br /&gt;
		problems[name][#problems[name] + 1] = text&lt;br /&gt;
	end&lt;br /&gt;
	for _, url in ipairs(urls) do&lt;br /&gt;
		local md5 = mw.hash.hashValue(&amp;#039;md5&amp;#039;, (url.name:gsub(&amp;#039; &amp;#039;, &amp;#039;_&amp;#039;)))&lt;br /&gt;
		local expected = md5:sub(1, 1) .. &amp;#039;/&amp;#039; .. md5:sub(1, 2)&lt;br /&gt;
		if url.path ~= expected then&lt;br /&gt;
			add(url.name, &amp;#039;URL path &amp;#039; .. code(url.path) .. &amp;#039; should be &amp;#039; .. code(expected))&lt;br /&gt;
		end&lt;br /&gt;
		if not checked[url.name] then&lt;br /&gt;
			checked[url.name] = true&lt;br /&gt;
			-- isRedirect is an expensive lookup: past the page&amp;#039;s limit it throws.&lt;br /&gt;
			local ok, target = pcall(function()&lt;br /&gt;
				local title = mw.title.new(&amp;#039;File:&amp;#039; .. url.name)&lt;br /&gt;
				return title and title.isRedirect and title.redirectTarget&lt;br /&gt;
			end)&lt;br /&gt;
			if ok and target then&lt;br /&gt;
				add(url.name, &amp;#039;moved to [[:File:&amp;#039; .. target.text .. &amp;#039;|&amp;#039; .. target.text .. &amp;#039;]], update the URL&amp;#039;)&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return problems&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- The Files group&amp;#039;s items. On the page itself each name follows a thumbnail,&lt;br /&gt;
--- which records the file as used by the page; anywhere else (its /doc, a&lt;br /&gt;
--- sandbox) the name alone, so only the page whose source names a file is&lt;br /&gt;
--- recorded as using it.&lt;br /&gt;
--- @param files DependenciesFiles&lt;br /&gt;
--- @param ctx DependenciesContext&lt;br /&gt;
--- @return string[]&lt;br /&gt;
local function fileItems(files, ctx)&lt;br /&gt;
	local thumbnails = ctx.isCurrent and not ctx.excluded&lt;br /&gt;
	local problems = urlProblems(files.urls)&lt;br /&gt;
	local items = {}&lt;br /&gt;
	for _, name in ipairs(files.names) do&lt;br /&gt;
		local item = &amp;#039;[[:File:&amp;#039; .. name .. &amp;#039;|&amp;#039; .. name .. &amp;#039;]]&amp;#039;&lt;br /&gt;
		if thumbnails then&lt;br /&gt;
			-- The wiki recolours most icons, so an SVG shows as a silhouette in the text&lt;br /&gt;
			-- colour: styles.css blackens it and `skin-invert` whitens it on a dark theme.&lt;br /&gt;
			local class = name:lower():find(&amp;#039;%.svg$&amp;#039;) and &amp;#039;t-dependencies__thumb t-dependencies__thumb--svg skin-invert&amp;#039;&lt;br /&gt;
				or &amp;#039;t-dependencies__thumb&amp;#039;&lt;br /&gt;
			item = &amp;#039;&amp;lt;span class=&amp;quot;&amp;#039; .. class .. &amp;#039;&amp;quot;&amp;gt;[[File:&amp;#039; .. name .. &amp;#039;|20x20px|link=|alt=]]&amp;lt;/span&amp;gt;&amp;#039; .. item&lt;br /&gt;
		end&lt;br /&gt;
		if problems[name] then&lt;br /&gt;
			item = item&lt;br /&gt;
				.. &amp;#039; &amp;lt;span class=&amp;quot;t-dependencies__warning&amp;quot;&amp;gt;(&amp;#039;&lt;br /&gt;
				.. table.concat(problems[name], &amp;#039;; &amp;#039;)&lt;br /&gt;
				.. &amp;#039;)&amp;lt;/span&amp;gt;&amp;#039;&lt;br /&gt;
		end&lt;br /&gt;
		items[#items + 1] = item&lt;br /&gt;
	end&lt;br /&gt;
	for _, pattern in ipairs(files.dynamic) do&lt;br /&gt;
		items[#items + 1] = code(pattern)&lt;br /&gt;
	end&lt;br /&gt;
	return items&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- @param back table&lt;br /&gt;
--- @return integer&lt;br /&gt;
local function countPages(back)&lt;br /&gt;
	local seen, count = {}, 0&lt;br /&gt;
	local function add(page)&lt;br /&gt;
		if not seen[page] then&lt;br /&gt;
			seen[page] = true&lt;br /&gt;
			count = count + 1&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	for _, entry in ipairs(back.invokedBy) do&lt;br /&gt;
		add(entry.page)&lt;br /&gt;
	end&lt;br /&gt;
	for _, key in ipairs({ &amp;#039;requiredBy&amp;#039;, &amp;#039;loadedBy&amp;#039;, &amp;#039;styledBy&amp;#039; }) do&lt;br /&gt;
		for _, page in ipairs(back[key]) do&lt;br /&gt;
			add(page)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return count&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- What the panel shows for the page, before any markup.&lt;br /&gt;
--- @param ctx DependenciesContext&lt;br /&gt;
--- @param found table forward()&amp;#039;s result&lt;br /&gt;
--- @param back table|nil reverse()&amp;#039;s result; nil when the lookup failed&lt;br /&gt;
--- @return DependenciesReport&lt;br /&gt;
local function report(ctx, found, back)&lt;br /&gt;
	local uses, usesCount = {}, 0&lt;br /&gt;
	if ctx.namespace == NS_TEMPLATE then&lt;br /&gt;
		local calls = {}&lt;br /&gt;
		for i, call in ipairs(found.invokes) do&lt;br /&gt;
			calls[i] = code(call.func) .. &amp;#039; in [[&amp;#039; .. call.module .. &amp;#039;]]&amp;#039;&lt;br /&gt;
		end&lt;br /&gt;
		addGroup(uses, &amp;#039;Invokes&amp;#039;, calls)&lt;br /&gt;
		usesCount = #calls&lt;br /&gt;
	else&lt;br /&gt;
		local requires = links(found.requires, ctx, &amp;#039;Module:&amp;#039;)&lt;br /&gt;
		for _, pattern in ipairs(found.dynamic) do&lt;br /&gt;
			requires[#requires + 1] = code(pattern)&lt;br /&gt;
		end&lt;br /&gt;
		addGroup(uses, &amp;#039;Requires&amp;#039;, requires)&lt;br /&gt;
		addGroup(uses, &amp;#039;Loads&amp;#039;, links(found.loads, ctx, &amp;#039;Module:&amp;#039;))&lt;br /&gt;
		usesCount = #requires + #found.loads&lt;br /&gt;
	end&lt;br /&gt;
	addGroup(uses, &amp;#039;Styles&amp;#039;, links(found.styles, ctx, ctx.prefix))&lt;br /&gt;
	addGroup(uses, &amp;#039;Files&amp;#039;, fileItems(found.files, ctx), nil, &amp;#039;files&amp;#039;)&lt;br /&gt;
	usesCount = usesCount + #found.styles + #found.files.names + #found.files.dynamic&lt;br /&gt;
&lt;br /&gt;
	local result = {&lt;br /&gt;
		uses = uses,&lt;br /&gt;
		usesCount = usesCount,&lt;br /&gt;
		usedByCount = 0,&lt;br /&gt;
		unused = false,&lt;br /&gt;
		functions = {},&lt;br /&gt;
	}&lt;br /&gt;
	if back ~= nil then&lt;br /&gt;
		local usedBy = {}&lt;br /&gt;
		local items, note = invokers(back.invokedBy, ctx)&lt;br /&gt;
		addGroup(usedBy, &amp;#039;Invoked by&amp;#039;, items, note)&lt;br /&gt;
		addGroup(usedBy, &amp;#039;Required by&amp;#039;, links(back.requiredBy, ctx, &amp;#039;Module:&amp;#039;))&lt;br /&gt;
		addGroup(usedBy, &amp;#039;Loaded by&amp;#039;, links(back.loadedBy, ctx, &amp;#039;Module:&amp;#039;))&lt;br /&gt;
		addGroup(usedBy, &amp;#039;Styles used by&amp;#039;, links(back.styledBy, ctx, ctx.prefix))&lt;br /&gt;
		result.usedBy = usedBy&lt;br /&gt;
		result.usedByCount = countPages(back)&lt;br /&gt;
		result.unused = ctx.namespace == NS_MODULE&lt;br /&gt;
			and not ctx.excluded&lt;br /&gt;
			and back.invokedBy[1] == nil&lt;br /&gt;
			and back.requiredBy[1] == nil&lt;br /&gt;
			and back.loadedBy[1] == nil&lt;br /&gt;
	end&lt;br /&gt;
	if ctx.namespace == NS_MODULE then&lt;br /&gt;
		-- Required here, not at the top: every page records the modules it loads&lt;br /&gt;
		-- and re-parses when one changes, and template pages never need this one.&lt;br /&gt;
		result.functions = require(&amp;#039;Module:Module toc&amp;#039;).functions(ctx.content)&lt;br /&gt;
	end&lt;br /&gt;
	return result&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- @param ctx DependenciesContext&lt;br /&gt;
--- @param found table&lt;br /&gt;
--- @param result DependenciesReport&lt;br /&gt;
--- @return string&lt;br /&gt;
local function categories(ctx, found, result)&lt;br /&gt;
	local out = {}&lt;br /&gt;
	if ctx.namespace == NS_TEMPLATE and found.invokes[1] ~= nil then&lt;br /&gt;
		out[#out + 1] = &amp;#039;[[Category:Lua-based templates]]&amp;#039;&lt;br /&gt;
	end&lt;br /&gt;
	if ctx.namespace == NS_MODULE and found.strict then&lt;br /&gt;
		out[#out + 1] = &amp;#039;[[Category:Strict mode modules]]&amp;#039;&lt;br /&gt;
	end&lt;br /&gt;
	if result.unused then&lt;br /&gt;
		out[#out + 1] = &amp;#039;[[Category:Unused modules]]&amp;#039;&lt;br /&gt;
	end&lt;br /&gt;
	return table.concat(out)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- @param addCategories boolean|string|nil&lt;br /&gt;
--- @return boolean&lt;br /&gt;
local function categoriesEnabled(addCategories)&lt;br /&gt;
	-- Yesno&amp;#039;s `default` only covers an unrecognised string, not a nil argument&lt;br /&gt;
	-- (a #invoke omitting the parameter, or a Lua caller passing nothing).&lt;br /&gt;
	local enabled = yesno(addCategories)&lt;br /&gt;
	if enabled == nil then&lt;br /&gt;
		local current = mw.title.getCurrentTitle()&lt;br /&gt;
		return not (current.isSubpage and current.subpageText:lower() == &amp;#039;doc&amp;#039;)&lt;br /&gt;
	end&lt;br /&gt;
	return enabled == true&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- @param items string[]&lt;br /&gt;
--- @param modifier string|nil&lt;br /&gt;
--- @return table mw.html&lt;br /&gt;
local function list(items, modifier)&lt;br /&gt;
	local root = mw.html.create(&amp;#039;ul&amp;#039;):addClass(&amp;#039;t-dependencies__list&amp;#039;)&lt;br /&gt;
	if modifier then&lt;br /&gt;
		root:addClass(&amp;#039;t-dependencies__list--&amp;#039; .. modifier)&lt;br /&gt;
	end&lt;br /&gt;
	for _, item in ipairs(items) do&lt;br /&gt;
		root:tag(&amp;#039;li&amp;#039;):wikitext(item)&lt;br /&gt;
	end&lt;br /&gt;
	return root&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- @param groups DependenciesGroup[]&lt;br /&gt;
--- @return string&lt;br /&gt;
local function groupsHtml(groups)&lt;br /&gt;
	local root = mw.html.create(&amp;#039;div&amp;#039;):addClass(&amp;#039;t-dependencies__groups&amp;#039;)&lt;br /&gt;
	for _, entry in ipairs(groups) do&lt;br /&gt;
		root:tag(&amp;#039;div&amp;#039;)&lt;br /&gt;
			:addClass(&amp;#039;t-dependencies__sublabel&amp;#039;)&lt;br /&gt;
			:wikitext(entry.label)&lt;br /&gt;
			:tag(&amp;#039;span&amp;#039;)&lt;br /&gt;
			:addClass(&amp;#039;t-dependencies__count&amp;#039;)&lt;br /&gt;
			:wikitext(#entry.items)&lt;br /&gt;
		local body = root:tag(&amp;#039;div&amp;#039;):addClass(&amp;#039;t-dependencies__items&amp;#039;):node(list(entry.items, entry.modifier))&lt;br /&gt;
		if entry.note then&lt;br /&gt;
			body:tag(&amp;#039;div&amp;#039;):addClass(&amp;#039;t-dependencies__note&amp;#039;):wikitext(entry.note)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return tostring(root)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- @param title string&lt;br /&gt;
--- @param functions ModuleTocFunction[]&lt;br /&gt;
--- @return string&lt;br /&gt;
local function functionsHtml(title, functions)&lt;br /&gt;
	local items = {}&lt;br /&gt;
	for i, func in ipairs(functions) do&lt;br /&gt;
		items[i] = string.format(&lt;br /&gt;
			&amp;#039;[[%s#L-%d|%s]]&amp;lt;span class=&amp;quot;t-dependencies__line&amp;quot;&amp;gt;L%d&amp;lt;/span&amp;gt;&amp;#039;,&lt;br /&gt;
			title,&lt;br /&gt;
			func.line,&lt;br /&gt;
			mw.text.nowiki(func.name),&lt;br /&gt;
			func.line&lt;br /&gt;
		)&lt;br /&gt;
	end&lt;br /&gt;
	return tostring(list(items, &amp;#039;code&amp;#039;))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- @param label string&lt;br /&gt;
--- @param file string&lt;br /&gt;
--- @param content string wikitext&lt;br /&gt;
--- @param modifier string|nil&lt;br /&gt;
--- @return string&lt;br /&gt;
local function row(label, file, content, modifier)&lt;br /&gt;
	local root = mw.html.create(&amp;#039;div&amp;#039;):addClass(&amp;#039;t-dependencies__row&amp;#039;)&lt;br /&gt;
	if modifier then&lt;br /&gt;
		root:addClass(&amp;#039;t-dependencies__row--&amp;#039; .. modifier)&lt;br /&gt;
	end&lt;br /&gt;
	root:tag(&amp;#039;div&amp;#039;)&lt;br /&gt;
		:addClass(&amp;#039;t-dependencies__label&amp;#039;)&lt;br /&gt;
		:wikitext(icon.render({ icon = file, mask = true, size = &amp;#039;1em&amp;#039;, class = &amp;#039;t-dependencies__icon&amp;#039; }))&lt;br /&gt;
		:wikitext(label)&lt;br /&gt;
	root:tag(&amp;#039;div&amp;#039;):addClass(&amp;#039;t-dependencies__content&amp;#039;):wikitext(content)&lt;br /&gt;
	return tostring(root)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- The folded header: the heading, then plain-text facts. It sits inside&lt;br /&gt;
--- &amp;lt;summary&amp;gt;, so it must hold no link.&lt;br /&gt;
--- @param facts string[]&lt;br /&gt;
--- @param unused boolean&lt;br /&gt;
--- @return string&lt;br /&gt;
local function summary(facts, unused)&lt;br /&gt;
	local root = mw.html.create(&amp;#039;span&amp;#039;):addClass(&amp;#039;t-dependencies__summary&amp;#039;)&lt;br /&gt;
	root:tag(&amp;#039;span&amp;#039;):addClass(&amp;#039;t-dependencies__heading&amp;#039;):wikitext(HEADING)&lt;br /&gt;
	if unused or facts[1] ~= nil then&lt;br /&gt;
		local meta = root:tag(&amp;#039;span&amp;#039;):addClass(&amp;#039;t-dependencies__meta&amp;#039;)&lt;br /&gt;
		if unused then&lt;br /&gt;
			meta:tag(&amp;#039;span&amp;#039;):addClass(&amp;#039;t-dependencies__chip&amp;#039;):wikitext(&amp;#039;Unused&amp;#039;)&lt;br /&gt;
		end&lt;br /&gt;
		if facts[1] ~= nil then&lt;br /&gt;
			meta:tag(&amp;#039;span&amp;#039;):wikitext(table.concat(facts, &amp;#039; · &amp;#039;))&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return tostring(root)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- The panel for `options.page`, followed by its categories. Writes the page&amp;#039;s&lt;br /&gt;
--- row when the render is the page itself.&lt;br /&gt;
--- @param options DependenciesPanelOptions|nil&lt;br /&gt;
--- @return string&lt;br /&gt;
function p.panel(options)&lt;br /&gt;
	options = options or {}&lt;br /&gt;
	local rows, facts, unused, cats = {}, {}, false, &amp;#039;&amp;#039;&lt;br /&gt;
	local lines = {}&lt;br /&gt;
	for _, source in ipairs(options.sources or {}) do&lt;br /&gt;
		lines[#lines + 1] = &amp;#039;&amp;lt;div&amp;gt;&amp;#039; .. source.text .. &amp;#039;&amp;lt;/div&amp;gt;&amp;#039;&lt;br /&gt;
		facts[#facts + 1] = source.label&lt;br /&gt;
	end&lt;br /&gt;
	if lines[1] ~= nil then&lt;br /&gt;
		rows[#rows + 1] = row(&amp;#039;Source&amp;#039;, ROW_ICONS.source, table.concat(lines))&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local ctx = context(options.page)&lt;br /&gt;
	if ctx ~= nil and ctx.content ~= nil then&lt;br /&gt;
		local found = forward(ctx)&lt;br /&gt;
		write(ctx, found)&lt;br /&gt;
		local back = reverse(ctx.title)&lt;br /&gt;
		local result = report(ctx, found, back)&lt;br /&gt;
		unused = result.unused&lt;br /&gt;
		if unused then&lt;br /&gt;
			local content = &amp;#039;&amp;lt;div&amp;gt;&amp;#039; .. UNUSED_TEXT .. &amp;#039;&amp;lt;/div&amp;gt;&amp;#039;&lt;br /&gt;
			if result.usedBy[1] ~= nil then&lt;br /&gt;
				content = content .. groupsHtml(result.usedBy)&lt;br /&gt;
			end&lt;br /&gt;
			rows[#rows + 1] = row(&amp;#039;Used by&amp;#039;, ROW_ICONS.usedBy, content, &amp;#039;warning&amp;#039;)&lt;br /&gt;
		elseif back == nil then&lt;br /&gt;
			if ctx.namespace == NS_MODULE then&lt;br /&gt;
				rows[#rows + 1] = row(&amp;#039;Used by&amp;#039;, ROW_ICONS.usedBy, UNAVAILABLE_TEXT, &amp;#039;muted&amp;#039;)&lt;br /&gt;
			end&lt;br /&gt;
		elseif result.usedBy[1] ~= nil then&lt;br /&gt;
			rows[#rows + 1] = row(&amp;#039;Used by&amp;#039;, ROW_ICONS.usedBy, groupsHtml(result.usedBy))&lt;br /&gt;
			facts[#facts + 1] = &amp;#039;used by &amp;#039; .. result.usedByCount&lt;br /&gt;
		end&lt;br /&gt;
		if result.uses[1] ~= nil then&lt;br /&gt;
			rows[#rows + 1] = row(&amp;#039;Uses&amp;#039;, ROW_ICONS.uses, groupsHtml(result.uses))&lt;br /&gt;
			facts[#facts + 1] = &amp;#039;uses &amp;#039; .. result.usesCount&lt;br /&gt;
		end&lt;br /&gt;
		if result.functions[1] ~= nil then&lt;br /&gt;
			rows[#rows + 1] = row(&amp;#039;Functions&amp;#039;, ROW_ICONS.functions, functionsHtml(ctx.title, result.functions))&lt;br /&gt;
		end&lt;br /&gt;
		if categoriesEnabled(options.addCategories) then&lt;br /&gt;
			cats = categories(ctx, found, result)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if rows[1] == nil then&lt;br /&gt;
		return cats&lt;br /&gt;
	end&lt;br /&gt;
	local frame = mw.getCurrentFrame()&lt;br /&gt;
	-- Module:Icon leaves its stylesheet to the caller; the row icons need it.&lt;br /&gt;
	local styles = frame:extensionTag({ name = &amp;#039;templatestyles&amp;#039;, args = { src = &amp;#039;Module:Icon/styles.css&amp;#039; } })&lt;br /&gt;
		.. frame:extensionTag({ name = &amp;#039;templatestyles&amp;#039;, args = { src = &amp;#039;Module:Dependencies/styles.css&amp;#039; } })&lt;br /&gt;
	return styles&lt;br /&gt;
		.. mbox.render({&lt;br /&gt;
			title = summary(facts, unused),&lt;br /&gt;
			text = table.concat(rows),&lt;br /&gt;
			icon = ICON,&lt;br /&gt;
			class = &amp;#039;t-dependencies&amp;#039;,&lt;br /&gt;
		})&lt;br /&gt;
		.. cats&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- `{{#invoke:Dependencies|main}}`, for MediaWiki:Scribunto-doc-page-does-not-exist.&lt;br /&gt;
--- @param frame table&lt;br /&gt;
--- @return string&lt;br /&gt;
function p.main(frame)&lt;br /&gt;
	return p.panel()&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Test-only exports. Not part of the public API.&lt;br /&gt;
p._internal = {&lt;br /&gt;
	group = group,&lt;br /&gt;
	report = report,&lt;br /&gt;
	rowFor = rowFor,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>starcitizen&gt;Alistar Bot</name></author>
	</entry>
</feed>