<?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%3AIcon</id>
	<title>Module:Icon - 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%3AIcon"/>
	<link rel="alternate" type="text/html" href="https://wiki.shroudforge.net/index.php?title=Module:Icon&amp;action=history"/>
	<updated>2026-11-05T04:40: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:Icon&amp;diff=44&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:Icon&amp;diff=44&amp;oldid=prev"/>
		<updated>2026-11-04T21:58:42Z</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-43:rev-44 --&gt;
&lt;/table&gt;</summary>
		<author><name>Bonsaibauer</name></author>
	</entry>
	<entry>
		<id>https://wiki.shroudforge.net/index.php?title=Module:Icon&amp;diff=43&amp;oldid=prev</id>
		<title>starcitizen&gt;Alistar Bot: Icon.src: decode the filepath URL so client-side mask consumers get real chars (not &amp;#58;) (via update-page on MediaWiki MCP Server)</title>
		<link rel="alternate" type="text/html" href="https://wiki.shroudforge.net/index.php?title=Module:Icon&amp;diff=43&amp;oldid=prev"/>
		<updated>2026-06-27T22:19:13Z</updated>

		<summary type="html">&lt;p&gt;Icon.src: decode the filepath URL so client-side mask consumers get real chars (not :) (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 Icon&lt;br /&gt;
--- Renders a single inline icon, either as a rasterised [[File:]] thumbnail or as&lt;br /&gt;
--- a CSS mask filled with currentColor (so it recolours with the surrounding&lt;br /&gt;
--- text). Optionally linked. The shared icon primitive behind Module:IconText,&lt;br /&gt;
--- Module:IconLink, and Module:BadgeLua.&lt;br /&gt;
---&lt;br /&gt;
--- `render` returns markup ONLY — no &amp;lt;templatestyles&amp;gt;. Callers load&lt;br /&gt;
--- Module:Icon/styles.css themselves, so the style tag never ends up inside a&lt;br /&gt;
--- wikilink label when a caller wraps the icon in a link of its own (e.g.&lt;br /&gt;
--- BadgeLua&amp;#039;s whole-pill link). The wikitext entry point `main` does emit the&lt;br /&gt;
--- stylesheet, since it returns a standalone value.&lt;br /&gt;
&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 DEFAULT_SIZE = &amp;#039;20px&amp;#039;&lt;br /&gt;
&lt;br /&gt;
--- @class IconProps&lt;br /&gt;
--- @field icon string         File name (without the File: prefix)&lt;br /&gt;
--- @field size? string        CSS length; default &amp;#039;20px&amp;#039;&lt;br /&gt;
--- @field mask? boolean       Render as a currentColor mask instead of a thumbnail&lt;br /&gt;
--- @field link? string        Link target; nil/empty = unlinked&lt;br /&gt;
--- @field title? string       Tooltip / caption&lt;br /&gt;
--- @field class? string       Extra class(es) on the icon element&lt;br /&gt;
&lt;br /&gt;
--- Resolve the icon&amp;#039;s file URL for use as a CSS mask image.&lt;br /&gt;
--- @param icon string&lt;br /&gt;
--- @return string&lt;br /&gt;
local function getIconSrc(icon)&lt;br /&gt;
	return mw.getCurrentFrame():callParserFunction(&amp;#039;filepath&amp;#039;, { icon, &amp;#039;nowiki&amp;#039; })&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Public: resolve an icon file name to its URL (for callers that paint their own&lt;br /&gt;
--- mask client-side, e.g. an AG Grid badge cell). Decoded to a plain URL — the&lt;br /&gt;
--- `nowiki` filepath HTML-encodes `:` as `&amp;amp;#58;`, which a browser decodes inside an&lt;br /&gt;
--- HTML style attribute (the server-rendered mask) but NOT when a script assigns it&lt;br /&gt;
--- to a CSS custom property, so client-side callers need the real characters.&lt;br /&gt;
--- @param icon string&lt;br /&gt;
--- @return string&lt;br /&gt;
function p.src(icon)&lt;br /&gt;
	return mw.text.decode(getIconSrc(icon), true)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Space-joined class list for the icon element: the base `t-icon`, the `--mask`&lt;br /&gt;
--- modifier when masked, then any caller class (its existing slot class, e.g.&lt;br /&gt;
--- `t-icon-text__icon`, so consumer selectors keep working).&lt;br /&gt;
--- @param mask boolean&lt;br /&gt;
--- @param extra string|nil&lt;br /&gt;
--- @return string&lt;br /&gt;
local function iconClass(mask, extra)&lt;br /&gt;
	local classes = { &amp;#039;t-icon&amp;#039; }&lt;br /&gt;
	if mask then&lt;br /&gt;
		classes[#classes + 1] = &amp;#039;t-icon--mask&amp;#039;&lt;br /&gt;
	end&lt;br /&gt;
	if extra and extra ~= &amp;#039;&amp;#039; then&lt;br /&gt;
		classes[#classes + 1] = extra&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;
--- Render as a recolourable CSS mask span, optionally wrapped in a link.&lt;br /&gt;
--- @param props IconProps&lt;br /&gt;
--- @return string&lt;br /&gt;
local function renderMask(props)&lt;br /&gt;
	local span = mw.html.create(&amp;#039;span&amp;#039;):addClass(iconClass(true, props.class)):cssText(&lt;br /&gt;
		string.format(&amp;#039;--t-icon-url: &amp;quot;%s&amp;quot;; width: %s; height: %s;&amp;#039;, getIconSrc(props.icon), props.size, props.size)&lt;br /&gt;
	)&lt;br /&gt;
	if props.title then&lt;br /&gt;
		span:attr(&amp;#039;title&amp;#039;, props.title)&lt;br /&gt;
	end&lt;br /&gt;
	local markup = tostring(span)&lt;br /&gt;
	if props.link and props.link ~= &amp;#039;&amp;#039; then&lt;br /&gt;
		return string.format(&amp;#039;[[%s|%s]]&amp;#039;, props.link, markup)&lt;br /&gt;
	end&lt;br /&gt;
	return markup&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Render as a [[File:]] thumbnail. `link=` (empty) suppresses the file link&lt;br /&gt;
--- unless a target is given; `metadata` keeps it out of the MultimediaViewer.&lt;br /&gt;
--- @param props IconProps&lt;br /&gt;
--- @return string&lt;br /&gt;
local function renderThumb(props)&lt;br /&gt;
	local parts = {&lt;br /&gt;
		&amp;#039;File:&amp;#039; .. props.icon,&lt;br /&gt;
		props.size,&lt;br /&gt;
		&amp;#039;link=&amp;#039; .. (props.link or &amp;#039;&amp;#039;),&lt;br /&gt;
		&amp;#039;class=metadata &amp;#039; .. iconClass(false, props.class),&lt;br /&gt;
	}&lt;br /&gt;
	if props.title then&lt;br /&gt;
		parts[#parts + 1] = props.title&lt;br /&gt;
	end&lt;br /&gt;
	return &amp;#039;[[&amp;#039; .. table.concat(parts, &amp;#039;|&amp;#039;) .. &amp;#039;]]&amp;#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Render an icon. Returns markup only (no templatestyles).&lt;br /&gt;
--- @param props IconProps&lt;br /&gt;
--- @return string&lt;br /&gt;
function p.render(props)&lt;br /&gt;
	if not props.icon or props.icon == &amp;#039;&amp;#039; then&lt;br /&gt;
		error(&amp;#039;Module:Icon: no icon provided&amp;#039;)&lt;br /&gt;
	end&lt;br /&gt;
	local resolved = {&lt;br /&gt;
		icon = props.icon,&lt;br /&gt;
		size = props.size or DEFAULT_SIZE,&lt;br /&gt;
		mask = props.mask and true or false,&lt;br /&gt;
		link = props.link,&lt;br /&gt;
		title = props.title,&lt;br /&gt;
		class = props.class,&lt;br /&gt;
	}&lt;br /&gt;
	if resolved.mask then&lt;br /&gt;
		return renderMask(resolved)&lt;br /&gt;
	end&lt;br /&gt;
	return renderThumb(resolved)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Wikitext entry point. Unlike `render`, this emits the stylesheet.&lt;br /&gt;
--- @param frame mw.frame&lt;br /&gt;
--- @return string&lt;br /&gt;
function p.main(frame)&lt;br /&gt;
	local getArgs = require(&amp;#039;Module:Arguments&amp;#039;).getArgs&lt;br /&gt;
	local args = getArgs(frame)&lt;br /&gt;
	local styles = mw.getCurrentFrame():extensionTag({&lt;br /&gt;
		name = &amp;#039;templatestyles&amp;#039;,&lt;br /&gt;
		args = { src = &amp;#039;Module:Icon/styles.css&amp;#039; },&lt;br /&gt;
	})&lt;br /&gt;
	return styles&lt;br /&gt;
		.. p.render({&lt;br /&gt;
			icon = args.icon or args[1],&lt;br /&gt;
			size = args.size,&lt;br /&gt;
			mask = yesno(args.mask),&lt;br /&gt;
			link = args.link,&lt;br /&gt;
			title = args.title or args.iconTitle,&lt;br /&gt;
			class = args.class,&lt;br /&gt;
		})&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>