<?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%3AMbox</id>
	<title>Module:Mbox - 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%3AMbox"/>
	<link rel="alternate" type="text/html" href="https://wiki.shroudforge.net/index.php?title=Module:Mbox&amp;action=history"/>
	<updated>2026-11-05T04:13:14Z</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:Mbox&amp;diff=78&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:Mbox&amp;diff=78&amp;oldid=prev"/>
		<updated>2026-11-04T22:22:06Z</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-77:rev-78 --&gt;
&lt;/table&gt;</summary>
		<author><name>Bonsaibauer</name></author>
	</entry>
	<entry>
		<id>https://wiki.shroudforge.net/index.php?title=Module:Mbox&amp;diff=77&amp;oldid=prev</id>
		<title>starcitizen&gt;Alistar Bot: Sync from Git (documentation-review-fixes cf68268) (via update-page on MediaWiki MCP Server)</title>
		<link rel="alternate" type="text/html" href="https://wiki.shroudforge.net/index.php?title=Module:Mbox&amp;diff=77&amp;oldid=prev"/>
		<updated>2026-09-28T17:57:25Z</updated>

		<summary type="html">&lt;p&gt;Sync from Git (documentation-review-fixes cf68268) (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 Mbox&lt;br /&gt;
--- The box behind page notices, hatnotes and Entity empty states: a title, an&lt;br /&gt;
--- optional body that opens in place as a &amp;lt;details&amp;gt; disclosure, a type colour&lt;br /&gt;
--- and an optional icon. Module:Hatnote, Module:Entity/EmptyState and&lt;br /&gt;
--- Module:Dependencies draw through render(); the notice templates call main()&lt;br /&gt;
--- via #invoke.&lt;br /&gt;
&lt;br /&gt;
local libraryUtil = require(&amp;#039;libraryUtil&amp;#039;)&lt;br /&gt;
local checkType = libraryUtil.checkType&lt;br /&gt;
local checkTypeForNamedArg = libraryUtil.checkTypeForNamedArg&lt;br /&gt;
local details = require(&amp;#039;Module:Details&amp;#039;)&lt;br /&gt;
local icon = require(&amp;#039;Module:Icon&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
local TYPES = { notice = true, warning = true, error = true }&lt;br /&gt;
&lt;br /&gt;
--- @class MboxProps&lt;br /&gt;
--- @field title string         Headline wikitext.&lt;br /&gt;
--- @field text? string         Body wikitext; given, the box becomes a collapsible &amp;lt;details&amp;gt;.&lt;br /&gt;
--- @field type? string         &amp;#039;notice&amp;#039; (default), &amp;#039;warning&amp;#039; or &amp;#039;error&amp;#039;; anything else is &amp;#039;notice&amp;#039;.&lt;br /&gt;
--- @field icon? string         File name, without the File: prefix.&lt;br /&gt;
--- @field iconMask? boolean    CSS mask (default) so the icon takes the title colour; false renders a [[File:]] thumbnail.&lt;br /&gt;
--- @field placeholder? boolean Dashed slot standing in for an empty section; carries no role.&lt;br /&gt;
--- @field open? boolean        Body starts open. Defaults to false.&lt;br /&gt;
--- @field class? string        Extra classes on the root (metadata, plainlinks, selfref, …).&lt;br /&gt;
&lt;br /&gt;
--- @param value any&lt;br /&gt;
--- @return boolean&lt;br /&gt;
local function isNonEmptyString(value)&lt;br /&gt;
	return type(value) == &amp;#039;string&amp;#039; and value ~= &amp;#039;&amp;#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- @param props MboxProps&lt;br /&gt;
--- @return string&lt;br /&gt;
local function rootClass(props)&lt;br /&gt;
	-- TextExtracts drops div elements and the classes in $wgExtractsRemoveClasses but keeps&lt;br /&gt;
	-- &amp;lt;details&amp;gt;, so only noexcerpt (one of those classes) keeps a disclosure box&amp;#039;s text out of&lt;br /&gt;
	-- the meta description and Page Previews; a static box&amp;#039;s div root is dropped either way.&lt;br /&gt;
	local classes = { &amp;#039;t-mbox&amp;#039;, &amp;#039;t-mbox--&amp;#039; .. props.type, &amp;#039;navigation-not-searchable&amp;#039;, &amp;#039;noexcerpt&amp;#039; }&lt;br /&gt;
	if props.placeholder then&lt;br /&gt;
		classes[#classes + 1] = &amp;#039;t-mbox--placeholder&amp;#039;&lt;br /&gt;
	end&lt;br /&gt;
	if isNonEmptyString(props.class) then&lt;br /&gt;
		classes[#classes + 1] = props.class&lt;br /&gt;
	end&lt;br /&gt;
	return table.concat(classes, &amp;#039; &amp;#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Icon, title and, for a disclosure, the chevron.&lt;br /&gt;
--- @param props MboxProps&lt;br /&gt;
--- @param withIndicator boolean&lt;br /&gt;
--- @return string&lt;br /&gt;
local function headerContent(props, withIndicator)&lt;br /&gt;
	local parts = {}&lt;br /&gt;
	if isNonEmptyString(props.icon) then&lt;br /&gt;
		local mask = props.iconMask ~= false&lt;br /&gt;
		parts[#parts + 1] = icon.render({&lt;br /&gt;
			icon = props.icon,&lt;br /&gt;
			mask = mask,&lt;br /&gt;
			-- A [[File:]] size must be in px; the mask scales with the title.&lt;br /&gt;
			size = mask and &amp;#039;1em&amp;#039; or &amp;#039;14px&amp;#039;,&lt;br /&gt;
			class = &amp;#039;t-mbox__icon&amp;#039;,&lt;br /&gt;
		})&lt;br /&gt;
	end&lt;br /&gt;
	parts[#parts + 1] = tostring(mw.html.create(&amp;#039;span&amp;#039;):addClass(&amp;#039;t-mbox__title&amp;#039;):wikitext(props.title))&lt;br /&gt;
	if withIndicator then&lt;br /&gt;
		-- The Citizen collapse icon Module:CollapsibleCard uses; styles.css rotates it.&lt;br /&gt;
		parts[#parts + 1] =&lt;br /&gt;
			tostring(mw.html.create(&amp;#039;span&amp;#039;):addClass(&amp;#039;citizen-ui-icon mw-ui-icon-wikimedia-collapse t-mbox__indicator&amp;#039;))&lt;br /&gt;
	end&lt;br /&gt;
	return table.concat(parts)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- @param props MboxProps&lt;br /&gt;
--- @return string&lt;br /&gt;
local function renderStatic(props)&lt;br /&gt;
	local root = mw.html.create(&amp;#039;div&amp;#039;):addClass(rootClass(props))&lt;br /&gt;
	if not props.placeholder then&lt;br /&gt;
		root:attr(&amp;#039;role&amp;#039;, &amp;#039;note&amp;#039;)&lt;br /&gt;
	end&lt;br /&gt;
	root:tag(&amp;#039;div&amp;#039;):addClass(&amp;#039;t-mbox__header&amp;#039;):wikitext(headerContent(props, false))&lt;br /&gt;
	return tostring(root)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- @param props MboxProps&lt;br /&gt;
--- @return string&lt;br /&gt;
local function renderDisclosure(props)&lt;br /&gt;
	-- Newlines let a body that starts with a list or table parse as block wikitext.&lt;br /&gt;
	local body = mw.html.create(&amp;#039;div&amp;#039;):addClass(&amp;#039;t-mbox__text&amp;#039;):newline():wikitext(props.text):newline()&lt;br /&gt;
	return details.getWikitext({&lt;br /&gt;
		details = { content = tostring(body), class = rootClass(props), open = props.open },&lt;br /&gt;
		summary = { content = headerContent(props, true), class = &amp;#039;t-mbox__header&amp;#039; },&lt;br /&gt;
	})&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- @param props MboxProps&lt;br /&gt;
--- @return string&lt;br /&gt;
function p.render(props)&lt;br /&gt;
	checkType(&amp;#039;Module:Mbox.render&amp;#039;, 1, props, &amp;#039;table&amp;#039;)&lt;br /&gt;
	checkTypeForNamedArg(&amp;#039;Module:Mbox.render&amp;#039;, &amp;#039;title&amp;#039;, props.title, &amp;#039;string&amp;#039;)&lt;br /&gt;
&lt;br /&gt;
	local resolved = {&lt;br /&gt;
		title = props.title,&lt;br /&gt;
		text = isNonEmptyString(props.text) and props.text or nil,&lt;br /&gt;
		type = TYPES[props.type] and props.type or &amp;#039;notice&amp;#039;,&lt;br /&gt;
		icon = props.icon,&lt;br /&gt;
		iconMask = props.iconMask,&lt;br /&gt;
		placeholder = props.placeholder == true,&lt;br /&gt;
		open = props.open == true,&lt;br /&gt;
		class = props.class,&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	local frame = mw.getCurrentFrame()&lt;br /&gt;
	local styles = frame:extensionTag({ name = &amp;#039;templatestyles&amp;#039;, args = { src = &amp;#039;Module:Mbox/styles.css&amp;#039; } })&lt;br /&gt;
	if isNonEmptyString(resolved.icon) then&lt;br /&gt;
		styles = styles .. frame:extensionTag({ name = &amp;#039;templatestyles&amp;#039;, args = { src = &amp;#039;Module:Icon/styles.css&amp;#039; } })&lt;br /&gt;
	end&lt;br /&gt;
	local markup = resolved.text and renderDisclosure(resolved) or renderStatic(resolved)&lt;br /&gt;
	return styles .. markup&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- #invoke entry. Reads only the invocation&amp;#039;s own arguments, so the calling&lt;br /&gt;
--- template&amp;#039;s parameters (CommLink&amp;#039;s `type`, TranscriptNotice&amp;#039;s&lt;br /&gt;
--- `type`) never reach the box.&lt;br /&gt;
--- @param frame mw.frame&lt;br /&gt;
--- @return string&lt;br /&gt;
function p.main(frame)&lt;br /&gt;
	local args = require(&amp;#039;Module:Arguments&amp;#039;).getArgs(frame, { frameOnly = true })&lt;br /&gt;
	local yesno = require(&amp;#039;Module:Yesno&amp;#039;)&lt;br /&gt;
	local title = args.title or args[1]&lt;br /&gt;
	if not title then&lt;br /&gt;
		return require(&amp;#039;Module:Error&amp;#039;).error({ message = &amp;#039;Error: no title specified.&amp;#039; })&lt;br /&gt;
	end&lt;br /&gt;
	return p.render({&lt;br /&gt;
		title = title,&lt;br /&gt;
		text = args.text or args[2],&lt;br /&gt;
		type = args.type,&lt;br /&gt;
		icon = args.icon,&lt;br /&gt;
		iconMask = yesno(args.iconmask, true),&lt;br /&gt;
		placeholder = yesno(args.placeholder, false),&lt;br /&gt;
		open = yesno(args.open, false),&lt;br /&gt;
		class = args.class,&lt;br /&gt;
	})&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Alias for `{{#invoke:Mbox|mbox}}` invocations.&lt;br /&gt;
p.mbox = p.main&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>starcitizen&gt;Alistar Bot</name></author>
	</entry>
</feed>