<?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%3AMainpage%2FHero</id>
	<title>Module:Mainpage/Hero - 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%3AMainpage%2FHero"/>
	<link rel="alternate" type="text/html" href="https://wiki.shroudforge.net/index.php?title=Module:Mainpage/Hero&amp;action=history"/>
	<updated>2026-11-05T02:21:18Z</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:Mainpage/Hero&amp;diff=20&amp;oldid=prev</id>
		<title>Bonsaibauer: 1 revision imported: Import of Star-Citizen-Modules</title>
		<link rel="alternate" type="text/html" href="https://wiki.shroudforge.net/index.php?title=Module:Mainpage/Hero&amp;diff=20&amp;oldid=prev"/>
		<updated>2026-11-04T21:58:40Z</updated>

		<summary type="html">&lt;p&gt;1 revision imported: Import of 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 21:58, 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-19:rev-20 --&gt;
&lt;/table&gt;</summary>
		<author><name>Bonsaibauer</name></author>
	</entry>
	<entry>
		<id>https://wiki.shroudforge.net/index.php?title=Module:Mainpage/Hero&amp;diff=19&amp;oldid=prev</id>
		<title>starcitizen&gt;Alistar Bot: Build chips come from the patches array; hero values from the hero section (via update-page on MediaWiki MCP Server)</title>
		<link rel="alternate" type="text/html" href="https://wiki.shroudforge.net/index.php?title=Module:Mainpage/Hero&amp;diff=19&amp;oldid=prev"/>
		<updated>2026-08-26T20:59:25Z</updated>

		<summary type="html">&lt;p&gt;Build chips come from the patches array; hero values from the hero section (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 Mainpage/Hero&lt;br /&gt;
--- The full-bleed hero band: patch status, wiki statline, lede, search trigger&lt;br /&gt;
--- and the chip strip.&lt;br /&gt;
---&lt;br /&gt;
--- NOTHING here fetches the artwork. The band carries the image URL in a&lt;br /&gt;
--- `data-gadget-mainpage-hero-src` attribute and the `mainpage` gadget&lt;br /&gt;
--- ([[MediaWiki:Gadget-mainpage.js]]) loads it after `window.load`, fading it in&lt;br /&gt;
--- by adding `home-hero--loaded`. That is what keeps a 1920px photograph off the&lt;br /&gt;
--- critical path and lets the band render — legibly, over its own ground colour&lt;br /&gt;
--- — for a reader on Save-Data or with scripts off.&lt;br /&gt;
---&lt;br /&gt;
--- The gadget hooks are all `data-gadget-mainpage-*`, per the house convention:&lt;br /&gt;
--- prefixing by gadget name means `grep gadget-mainpage-` finds every emitter&lt;br /&gt;
--- and the one gadget that consumes them.&lt;br /&gt;
---&lt;br /&gt;
--- Everything variable here comes from [[Module:Mainpage/settings.json]].&lt;br /&gt;
&lt;br /&gt;
local cfg = require(&amp;#039;Module:Mainpage/Config&amp;#039;)&lt;br /&gt;
local nav = require(&amp;#039;Module:Mainpage/Nav&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
--- Width of the thumbnail handed to the gadget. Large enough for a 2x 960px&lt;br /&gt;
--- band; the gadget requests it lazily so the size costs nothing up front.&lt;br /&gt;
local HERO_WIDTH = &amp;#039;1920&amp;#039;&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
--- The build chips, one per entry in `patches`. The live build takes the&lt;br /&gt;
--- filled marker and the live colour, every other channel the hollow one —&lt;br /&gt;
--- and WHICH entry is live is Config&amp;#039;s answer, not one computed here, so the&lt;br /&gt;
--- chip and the patch card below can never disagree.&lt;br /&gt;
---&lt;br /&gt;
--- An entry with no name is skipped, and with none left the strip is not&lt;br /&gt;
--- emitted at all rather than rendered empty.&lt;br /&gt;
---&lt;br /&gt;
--- @param root mw.html&lt;br /&gt;
local function renderStatus(root)&lt;br /&gt;
	local status = mw.html.create(&amp;#039;div&amp;#039;):addClass(&amp;#039;home-hero__status&amp;#039;)&lt;br /&gt;
	local live = cfg.livePatch()&lt;br /&gt;
	local any = false&lt;br /&gt;
&lt;br /&gt;
	for _, patch in ipairs(cfg.list(&amp;#039;patches&amp;#039;)) do&lt;br /&gt;
		if patch.name then&lt;br /&gt;
			local isLive = patch == live&lt;br /&gt;
			local label = patch.channel and (patch.channel .. &amp;#039; &amp;#039; .. patch.name) or patch.name&lt;br /&gt;
&lt;br /&gt;
			status:tag(&amp;#039;span&amp;#039;):addClass(isLive and &amp;#039;home-hero__status-live&amp;#039; or &amp;#039;home-hero__status-ptu&amp;#039;):wikitext(&lt;br /&gt;
				(isLive and &amp;#039;●&amp;#039; or &amp;#039;◌&amp;#039;)&lt;br /&gt;
					.. &amp;#039; &amp;#039;&lt;br /&gt;
					.. (patch.page and string.format(&amp;#039;[[%s|%s]]&amp;#039;, patch.page, label) or label)&lt;br /&gt;
			)&lt;br /&gt;
			any = true&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if any then&lt;br /&gt;
		root:node(status)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- The three site figures. `mw.site.stats` rather than the magic words so the&lt;br /&gt;
--- numbers arrive as numbers and can be formatted once, in the content&lt;br /&gt;
--- language, the way {{NUMBEROFARTICLES}} would have done.&lt;br /&gt;
---&lt;br /&gt;
--- Each figure is marked `data-gadget-mainpage-stat`, which is the gadget&amp;#039;s&lt;br /&gt;
--- hook for rolling the digits on load — it needs to know which figure it is&lt;br /&gt;
--- animating so it can count from a sensible starting point.&lt;br /&gt;
local STATS = {&lt;br /&gt;
	{ key = &amp;#039;articles&amp;#039;, label = &amp;#039;Articles&amp;#039;, icon = &amp;#039;article&amp;#039; },&lt;br /&gt;
	{ key = &amp;#039;edits&amp;#039;, label = &amp;#039;Edits&amp;#039;, icon = &amp;#039;edit&amp;#039; },&lt;br /&gt;
	{ key = &amp;#039;users&amp;#039;, label = &amp;#039;Registered users&amp;#039;, icon = &amp;#039;userAvatar&amp;#039; },&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
--- @param content mw.html&lt;br /&gt;
local function renderStatline(content)&lt;br /&gt;
	local lang = mw.language.getContentLanguage()&lt;br /&gt;
&lt;br /&gt;
	-- A description list, because that is the shape of the data: three labelled&lt;br /&gt;
	-- figures. The label is an icon plus visually-hidden text, so the meaning&lt;br /&gt;
	-- survives with images off or under a screen reader.&lt;br /&gt;
	local list = content:tag(&amp;#039;dl&amp;#039;):addClass(&amp;#039;home-hero__statline&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
	for _, stat in ipairs(STATS) do&lt;br /&gt;
		local group = list:tag(&amp;#039;div&amp;#039;):addClass(&amp;#039;home-hero__stat&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
		local label = group:tag(&amp;#039;dt&amp;#039;):addClass(&amp;#039;home-hero__stat-label&amp;#039;)&lt;br /&gt;
		label&lt;br /&gt;
			:tag(&amp;#039;span&amp;#039;)&lt;br /&gt;
			:addClass(&amp;#039;citizen-ui-icon&amp;#039;)&lt;br /&gt;
			:addClass(&amp;#039;mw-ui-icon-&amp;#039; .. stat.icon)&lt;br /&gt;
			:addClass(&amp;#039;mw-ui-icon-wikimedia-&amp;#039; .. stat.icon)&lt;br /&gt;
			:attr(&amp;#039;aria-hidden&amp;#039;, &amp;#039;true&amp;#039;)&lt;br /&gt;
		label:tag(&amp;#039;span&amp;#039;):addClass(&amp;#039;home-hero__sr&amp;#039;):wikitext(stat.label)&lt;br /&gt;
&lt;br /&gt;
		group&lt;br /&gt;
			:tag(&amp;#039;dd&amp;#039;)&lt;br /&gt;
			:addClass(&amp;#039;home-hero__stat-value&amp;#039;)&lt;br /&gt;
			:attr(&amp;#039;data-gadget-mainpage-stat&amp;#039;, stat.key)&lt;br /&gt;
			:wikitext(lang:formatNum(mw.site.stats[stat.key]))&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- @param content mw.html&lt;br /&gt;
--- @param frame mw.frame&lt;br /&gt;
local function renderSearch(content, frame)&lt;br /&gt;
	local tails = cfg.section(&amp;#039;hero&amp;#039;).searchTails or {}&lt;br /&gt;
&lt;br /&gt;
	-- `role=&amp;quot;button&amp;quot;` and not a real &amp;lt;button&amp;gt;: the element opens Citizen&amp;#039;s own&lt;br /&gt;
	-- search overlay, which the skin binds by the `citizen-search-trigger`&lt;br /&gt;
	-- class. A &amp;lt;button&amp;gt; here would be a second, competing control.&lt;br /&gt;
	local search = content&lt;br /&gt;
		:tag(&amp;#039;div&amp;#039;)&lt;br /&gt;
		:addClass(&amp;#039;home-hero__search&amp;#039;)&lt;br /&gt;
		:addClass(&amp;#039;citizen-search-trigger&amp;#039;)&lt;br /&gt;
		:attr(&amp;#039;role&amp;#039;, &amp;#039;button&amp;#039;)&lt;br /&gt;
		:wikitext(&amp;#039;[[File:WikimediaUI-Search.svg|16px|link=|alt=]]&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
	local label = search:tag(&amp;#039;span&amp;#039;):addClass(&amp;#039;home-hero__search-label&amp;#039;)&lt;br /&gt;
	label:wikitext(&amp;#039;Search&amp;amp;nbsp;&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
	local tail = label:tag(&amp;#039;span&amp;#039;):addClass(&amp;#039;home-hero__search-tail&amp;#039;)&lt;br /&gt;
	if tails[1] ~= nil then&lt;br /&gt;
		-- The tail the gadget rolls through. The FIRST value is also what is&lt;br /&gt;
		-- rendered here, so the server-side text is one of the real phrases&lt;br /&gt;
		-- rather than a placeholder that flashes and is replaced.&lt;br /&gt;
		tail:attr(&amp;#039;data-gadget-mainpage-search-tails&amp;#039;, table.concat(tails, &amp;#039;|&amp;#039;))&lt;br /&gt;
		tail:wikitext(tails[1])&lt;br /&gt;
	else&lt;br /&gt;
		tail:wikitext(&amp;#039;the Star Citizen Wiki&amp;#039;)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	search:wikitext(frame:expandTemplate({ title = &amp;#039;Key press&amp;#039;, args = { &amp;#039;/&amp;#039; } }))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- @param content mw.html&lt;br /&gt;
local function renderChips(content)&lt;br /&gt;
	local strip = content:tag(&amp;#039;div&amp;#039;):addClass(&amp;#039;home-hero__tabs&amp;#039;)&lt;br /&gt;
	for _, chip in ipairs(nav.chips()) do&lt;br /&gt;
		local wikitext = nav.renderLink(chip)&lt;br /&gt;
		if wikitext then&lt;br /&gt;
			strip:wikitext(wikitext)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- @class HeroProps&lt;br /&gt;
--- @field lazyArt? boolean  Emit the gadget&amp;#039;s artwork hook. False renders the&lt;br /&gt;
---        band exactly as a reader with no JavaScript, or with Save-Data on,&lt;br /&gt;
---        receives it: no artwork is ever fetched.&lt;br /&gt;
&lt;br /&gt;
--- @param props HeroProps&lt;br /&gt;
--- @return string&lt;br /&gt;
function p.render(props)&lt;br /&gt;
	props = props or {}&lt;br /&gt;
	local frame = mw.getCurrentFrame()&lt;br /&gt;
&lt;br /&gt;
	local root = mw.html.create(&amp;#039;div&amp;#039;):addClass(&amp;#039;home-band&amp;#039;):addClass(&amp;#039;home-hero&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
	if props.lazyArt ~= false then&lt;br /&gt;
		local image = cfg.section(&amp;#039;hero&amp;#039;).image&lt;br /&gt;
		if image then&lt;br /&gt;
			root:attr(&amp;#039;data-gadget-mainpage-hero-src&amp;#039;, frame:callParserFunction(&amp;#039;filepath&amp;#039;, { image, HERO_WIDTH }))&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Both are empty and both are painted entirely in CSS: the media box is&lt;br /&gt;
	-- where the gadget puts the photograph, the scrim is the gradient that&lt;br /&gt;
	-- keeps the text legible over whatever the photograph turns out to be.&lt;br /&gt;
	root:tag(&amp;#039;div&amp;#039;):addClass(&amp;#039;home-hero__media&amp;#039;)&lt;br /&gt;
	root:tag(&amp;#039;div&amp;#039;):addClass(&amp;#039;home-hero__scrim&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
	renderStatus(root)&lt;br /&gt;
&lt;br /&gt;
	-- home-band__inner is the measured column every band shares, so the hero&amp;#039;s&lt;br /&gt;
	-- text lines up with the cards below it.&lt;br /&gt;
	local content = root:tag(&amp;#039;div&amp;#039;):addClass(&amp;#039;home-band__inner&amp;#039;):addClass(&amp;#039;home-hero__content&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
	renderStatline(content)&lt;br /&gt;
&lt;br /&gt;
	-- The trailing space is load-bearing: the two halves are one sentence set in&lt;br /&gt;
	-- two tones, and mw.html concatenates its children with nothing between&lt;br /&gt;
	-- them, so without it the dim half would butt against the bright one.&lt;br /&gt;
	local hero = cfg.section(&amp;#039;hero&amp;#039;)&lt;br /&gt;
	content&lt;br /&gt;
		:tag(&amp;#039;div&amp;#039;)&lt;br /&gt;
		:addClass(&amp;#039;home-hero__title&amp;#039;)&lt;br /&gt;
		:wikitext((hero.lede or &amp;#039;Bespoke Star Citizen and Squadron&amp;amp;nbsp;42 wiki.&amp;#039;) .. &amp;#039; &amp;#039;)&lt;br /&gt;
		:tag(&amp;#039;span&amp;#039;)&lt;br /&gt;
		:addClass(&amp;#039;home-hero__title-dim&amp;#039;)&lt;br /&gt;
		:wikitext(hero.ledeDetail or &amp;#039;Held the line since 2016.&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
	renderSearch(content, frame)&lt;br /&gt;
	renderChips(content)&lt;br /&gt;
&lt;br /&gt;
	return tostring(root)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>starcitizen&gt;Alistar Bot</name></author>
	</entry>
</feed>