<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://armsofgod.wiki.spellsandguns.com/index.php?action=history&amp;feed=atom&amp;title=Module%3ACore</id>
	<title>Module:Core - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://armsofgod.wiki.spellsandguns.com/index.php?action=history&amp;feed=atom&amp;title=Module%3ACore"/>
	<link rel="alternate" type="text/html" href="https://armsofgod.wiki.spellsandguns.com/index.php?title=Module:Core&amp;action=history"/>
	<updated>2026-06-18T04:27:28Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.8</generator>
	<entry>
		<id>https://armsofgod.wiki.spellsandguns.com/index.php?title=Module:Core&amp;diff=2126&amp;oldid=prev</id>
		<title>Ta1ha: fix: scope the +/-1000 Unlimited/disabled sentinel to Pierce/Bounce only (weapon Range 1400, hero/enemy large stats are real numbers)</title>
		<link rel="alternate" type="text/html" href="https://armsofgod.wiki.spellsandguns.com/index.php?title=Module:Core&amp;diff=2126&amp;oldid=prev"/>
		<updated>2026-06-11T02:47:03Z</updated>

		<summary type="html">&lt;p&gt;fix: scope the +/-1000 Unlimited/disabled sentinel to Pierce/Bounce only (weapon Range 1400, hero/enemy large stats are real numbers)&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&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&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 02:47, 11 June 2026&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l188&quot;&gt;Line 188:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 188:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;end&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;end&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;-- &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Render one stat value. The game data uses huge sentinels for &lt;/del&gt;on/off&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;-- &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Stats that use the +/-1000 &lt;/ins&gt;on/off &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;sentinel — a WEAPON convention only:&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;-- &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;mechanics: &amp;gt;&lt;/del&gt;= &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;1000 means &lt;/del&gt;&quot;Unlimited&quot;, &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&amp;lt;= &lt;/del&gt;-1000 &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;means &lt;/del&gt;&quot;disabled&quot; (&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;we&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;-- &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Pierce 1000 &lt;/ins&gt;= &quot;Unlimited&quot;, &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Pierce/Bounce &lt;/ins&gt;-1000 &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;= &lt;/ins&gt;&quot;disabled&quot; (&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;row dropped).&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;-- &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;return nil &lt;/del&gt;so &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;the caller drops the row)&lt;/del&gt;. `signed` adds a &#039;+&#039; prefix&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;-- &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;EVERY other stat is a real number even when large (a sniper&#039;s Range 1400,&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;-- &lt;/del&gt;for modifier-style categories (heroes, blessings, upgrades, ...).&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;-- a boss&#039;s HP/Wave 5000), &lt;/ins&gt;so &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;it must NEVER be sentinel-folded.&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;function p.fmtStat(v, signed)&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;p.SENTINEL_STATS = { Pierce = true, Bounce = true }&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt; &lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;-- Render one stat value&lt;/ins&gt;. `signed` adds a &#039;+&#039; prefix for modifier-style&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;-- &lt;/ins&gt;categories (heroes, blessings, upgrades, ...)&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;. `key` is the stat name;&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;-- the +/-1000 sentinel applies ONLY when key is a SENTINEL_STATS member&lt;/ins&gt;.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;function p.fmtStat(v, signed&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;, key&lt;/ins&gt;)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;   if type(v) == &amp;#039;number&amp;#039; then&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;   if type(v) == &amp;#039;number&amp;#039; then&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     if v &amp;gt;= 1000 then return &#039;Unlimited&#039; end&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;if p.SENTINEL_STATS[key] then&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;    &lt;/del&gt;if v &amp;lt;= -1000 then return nil end&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;      &lt;/ins&gt;if v &amp;gt;= 1000 then return &#039;Unlimited&#039; end&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;      &lt;/ins&gt;if v &amp;lt;= -1000 then return nil &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;end&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;    &lt;/ins&gt;end&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     local s = p.fmtNum(v)&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     local s = p.fmtNum(v)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     if signed and v &amp;gt; 0 then s = &amp;#039;+&amp;#039; .. s end&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     if signed and v &amp;gt; 0 then s = &amp;#039;+&amp;#039; .. s end&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l373&quot;&gt;Line 373:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 380:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;   for _, kv in ipairs(p.statPairs(rec)) do&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;   for _, kv in ipairs(p.statPairs(rec)) do&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     local k, v = kv[1], kv[2]&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     local k, v = kv[1], kv[2]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     local val = p.fmtStat(v, signed)&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     local val = p.fmtStat(v, signed&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;, k&lt;/ins&gt;)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     if val ~= nil then&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     if val ~= nil then&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;       local label = p.statLabelLink(k)&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;       local label = p.statLabelLink(k)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l393&quot;&gt;Line 393:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 400:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;   local parts = {}&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;   local parts = {}&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;   for _, kv in ipairs(p.statPairs(rec)) do&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;   for _, kv in ipairs(p.statPairs(rec)) do&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     local val = p.fmtStat(kv[2], signed)&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     local val = p.fmtStat(kv[2], signed&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;, kv[1]&lt;/ins&gt;)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     if val ~= nil then parts[#parts + 1] = kv[1] .. &amp;#039; &amp;#039; .. val end&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     if val ~= nil then parts[#parts + 1] = kv[1] .. &amp;#039; &amp;#039; .. val end&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;   end&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;   end&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;

&lt;!-- diff cache key armsofgodwiki:diff:1.41:old-2116:rev-2126:php=table --&gt;
&lt;/table&gt;</summary>
		<author><name>Ta1ha</name></author>
	</entry>
	<entry>
		<id>https://armsofgod.wiki.spellsandguns.com/index.php?title=Module:Core&amp;diff=2116&amp;oldid=prev</id>
		<title>Ta1ha: bot: linkify stat labels -&gt; stat pages (infobox + comparison/index headers)</title>
		<link rel="alternate" type="text/html" href="https://armsofgod.wiki.spellsandguns.com/index.php?title=Module:Core&amp;diff=2116&amp;oldid=prev"/>
		<updated>2026-06-10T18:49:26Z</updated>

		<summary type="html">&lt;p&gt;bot: linkify stat labels -&amp;gt; stat pages (infobox + comparison/index headers)&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&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&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 18:49, 10 June 2026&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l285&quot;&gt;Line 285:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 285:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;   [&amp;#039;Electric Damage&amp;#039;] = {&amp;#039;--dmg-electric&amp;#039;, &amp;#039;#4ea3ff&amp;#039;, &amp;#039;wm-dmg-electric&amp;#039;},&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;   [&amp;#039;Electric Damage&amp;#039;] = {&amp;#039;--dmg-electric&amp;#039;, &amp;#039;#4ea3ff&amp;#039;, &amp;#039;wm-dmg-electric&amp;#039;},&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;}&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;}&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;-- ----- stat page links -------------------------------------------------&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;-- Per-stat reverse-lookup pages exist for every stat modified by at least&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;-- one hero / blessing / upgrade / passive / Crux power, and the codex Tips&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;-- pages double as hubs for the stats sharing their title (Holy / Fire /&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;-- Electric Damage, Critical Damage, Pierce, Bounce, Projectiles, Stagger,&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;-- Stun). A stat label is linkified ONLY when one of those pages exists, so&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;-- a page-less stat renders as plain text — never a redlink. Both sets are&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;-- computed from the source Data pages at render time, mirroring how the&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;-- page set itself is derived at emit time, so they match by construction.&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;-- Same alias fold as Module:StatIndex: the game data calls one mechanic&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;-- both &#039;Explosive Range&#039; and &#039;Explosive Radius&#039;; the page lives at&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;-- &#039;Explosive Radius&#039;.&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;local STAT_PAGE_ALIAS = {[&#039;Explosive Range&#039;] = &#039;Explosive Radius&#039;}&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;-- Enemy-only scaling keys: never booster-modified, never get stat pages.&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;local NON_PAGE_STATS = {[&#039;Health&#039;] = true, [&#039;HP per Wave&#039;] = true,&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;                        [&#039;Damage per Wave&#039;] = true}&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;local MODIFIER_CATS = {&#039;Characters&#039;, &#039;Blessings&#039;, &#039;Upgrades&#039;, &#039;Passives&#039;, &#039;Crux&#039;}&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;-- Set (key -&amp;gt; true) of stat keys modified by at least one booster record&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;-- (memoized per parse).&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;local _boosterKeys = nil&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;function p.boosterStatKeys()&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;  if _boosterKeys == nil then&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;    local keys = {}&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;    for _, cat in ipairs(MODIFIER_CATS) do&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;      for _, r in ipairs(p.load(cat)) do&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;        for k in pairs(r.stats or {}) do keys[k] = true end&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;      end&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;    end&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;    for k in pairs(NON_PAGE_STATS) do keys[k] = nil end&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;    if keys[&#039;Explosive Range&#039;] then keys[&#039;Explosive Radius&#039;] = true end&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;    _boosterKeys = keys&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;  end&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;  return _boosterKeys&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;end&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;-- Page title of a stat&#039;s reference page, or nil when no page exists.&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;-- Codex-hosted hubs win (link target = the codex record&#039;s slug — never&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;-- rebuilt from the name); otherwise booster-modified stats point at their&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;-- emitted reverse-lookup page, whose title IS the stat name.&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;function p.statPageTarget(stat)&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;  if not stat or stat == &#039;&#039; then return nil end&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;  local key = STAT_PAGE_ALIAS[stat] or stat&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;  if NON_PAGE_STATS[key] then return nil end&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;  local cx = p.codexFor(key, &#039;Tips&#039;)&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;  if cx and cx.slug then return cx.slug end&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;  if p.boosterStatKeys()[key] then return key end&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;  return nil&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;end&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;-- &#039;[[&amp;lt;page&amp;gt;|&amp;lt;stat&amp;gt;]]&#039; when the stat has a reference page, else the plain&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;-- label unchanged.&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;function p.statLabelLink(stat)&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;  local target = p.statPageTarget(stat)&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;  if not target then return stat end&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;  if target == stat then return &#039;[[&#039; .. stat .. &#039;]]&#039; end&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;  return &#039;[[&#039; .. target .. &#039;|&#039; .. stat .. &#039;]]&#039;&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;end&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;-- Ordered {key, value} pairs of rec.stats per STAT_ORDER (extras appended&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;-- Ordered {key, value} pairs of rec.stats per STAT_ORDER (extras appended&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l303&quot;&gt;Line 303:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 365:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;-- Infobox &amp;#039;Stats&amp;#039; cell: one glyph+label+value line per stat, &amp;lt;br&amp;gt;-joined.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;-- Infobox &amp;#039;Stats&amp;#039; cell: one glyph+label+value line per stat, &amp;lt;br&amp;gt;-joined.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;-- &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Elemental &lt;/del&gt;damage labels &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;link &lt;/del&gt;to the damage-type &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;hub &lt;/del&gt;pages.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;-- &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Every stat label whose reference page exists links to it (elemental&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;-- &lt;/ins&gt;damage labels to the damage-type &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;hubs, booster-modified stats to their&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;-- reverse-lookup &lt;/ins&gt;pages&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;); page-less stats stay plain text. Values and&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;-- glyphs are untouched&lt;/ins&gt;.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;function p.statsBlock(rec, signed)&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;function p.statsBlock(rec, signed)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;   local lines = {}&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;   local lines = {}&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l310&quot;&gt;Line 310:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 375:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     local val = p.fmtStat(v, signed)&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     local val = p.fmtStat(v, signed)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     if val ~= nil then&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     if val ~= nil then&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;      local label = p.statLabelLink(k)&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;       local chip = p.DMG_CHIP[k]&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;       local chip = p.DMG_CHIP[k]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;       if chip then&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;       if chip then&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;         lines[#lines + 1] = p.statGlyph(k) .. &amp;#039;&amp;lt;span class=&amp;quot;&amp;#039; .. chip[3]&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;         lines[#lines + 1] = p.statGlyph(k) .. &amp;#039;&amp;lt;span class=&amp;quot;&amp;#039; .. chip[3]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;           .. &amp;#039;&amp;quot; style=&amp;quot;color:var(&amp;#039; .. chip[1] .. &amp;#039;, &amp;#039; .. chip[2]&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;           .. &amp;#039;&amp;quot; style=&amp;quot;color:var(&amp;#039; .. chip[1] .. &amp;#039;, &amp;#039; .. chip[2]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;           .. &quot;);\&quot;&amp;gt;&#039;&#039;&#039;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[[&lt;/del&gt;&quot; .. &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;k .. &#039;|&#039; .. k &lt;/del&gt;.. &quot;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;]]&lt;/del&gt;:&#039;&#039;&#039; &quot; .. val .. &#039;&amp;lt;/span&amp;gt;&#039;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;           .. &quot;);\&quot;&amp;gt;&#039;&#039;&#039;&quot; .. &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;label &lt;/ins&gt;.. &quot;:&#039;&#039;&#039; &quot; .. val .. &#039;&amp;lt;/span&amp;gt;&#039;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;       else&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;       else&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;         lines[#lines + 1] = p.statGlyph(k) .. &quot;&#039;&#039;&#039;&quot; .. &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;k &lt;/del&gt;.. &quot;:&#039;&#039;&#039; &quot; .. val&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;         lines[#lines + 1] = p.statGlyph(k) .. &quot;&#039;&#039;&#039;&quot; .. &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;label &lt;/ins&gt;.. &quot;:&#039;&#039;&#039; &quot; .. val&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;       end&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;       end&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     end&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     end&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l769&quot;&gt;Line 769:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 835:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     recs[#recs + 1] = p.augmented(cat, r)&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;     recs[#recs + 1] = p.augmented(cat, r)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;   end&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;   end&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;   &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;return Index&lt;/del&gt;.&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;render(recs, &lt;/del&gt;INDEX_OPTS[cat] or {})&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;   &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;-- Linkify stat-name column headers to their reference pages (existence-&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;  -- checked via statPageTarget; non-stat headers pass through untouched).&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;  -- Works on a copy so the shared INDEX_OPTS table is never mutated&lt;/ins&gt;.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;  local base = &lt;/ins&gt;INDEX_OPTS[cat] or {}&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;  local opts = {thumbnail_size = base.thumbnail_size,&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;                sort_default = base.sort_default, columns = {}}&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;  for _, c in ipairs(base.columns or {}) do&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;    local nm = c.name&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;    local target = p.statPageTarget(nm)&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;    if target then&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;      nm = (target == nm) and (&#039;[[&#039; .. nm .. &#039;]]&#039;)&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;        or (&#039;[[&#039; .. target .. &#039;|&#039; .. nm .. &#039;]]&#039;)&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;      if base.sort_default == c.name then opts.sort_default = nm end&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;    end&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;    opts.columns[#opts.columns + 1] = {name = nm, source = c.source}&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;  end&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;  return Index.render(recs, opts&lt;/ins&gt;)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;end&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;end&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;

&lt;!-- diff cache key armsofgodwiki:diff:1.41:old-2082:rev-2116:php=table --&gt;
&lt;/table&gt;</summary>
		<author><name>Ta1ha</name></author>
	</entry>
	<entry>
		<id>https://armsofgod.wiki.spellsandguns.com/index.php?title=Module:Core&amp;diff=2082&amp;oldid=prev</id>
		<title>Ta1ha: bot: documentation pass — editor-facing docs (data descriptions, module comments, template usage, Help rewrite)</title>
		<link rel="alternate" type="text/html" href="https://armsofgod.wiki.spellsandguns.com/index.php?title=Module:Core&amp;diff=2082&amp;oldid=prev"/>
		<updated>2026-06-10T16:04:40Z</updated>

		<summary type="html">&lt;p&gt;bot: documentation pass — editor-facing docs (data descriptions, module comments, template usage, Help rewrite)&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&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&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 16:04, 10 June 2026&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l1&quot;&gt;Line 1:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 1:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;-- Module:Core — &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;shared registry, loaders and render-time computation&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;-- Module:Core — &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;the engine room &lt;/ins&gt;of this wiki.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;-- (Arms of God). THE single source &lt;/del&gt;of &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;derivation logic: every table, list,&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-added&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;-- infobox value, badge and summary on &lt;/del&gt;this wiki &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;is computed HERE (or in a&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-added&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;-- module that requires this one) at render time, from the source&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-added&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;-- Data:&amp;lt;Category&amp;gt;.json pages. There are no precomputed / derived Data pages&lt;/del&gt;.&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-added&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;--&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;--&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;-- &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Source record contract (one Data:&amp;lt;Cat&amp;gt;.json per category, array `records`):&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;-- &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;WHAT IT DOES&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;--   &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;id&lt;/del&gt;, &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;slug&lt;/del&gt;, &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;name&lt;/del&gt;, &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;icon            — identity (slug computed by flatten.py&lt;/del&gt;,&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;--   &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Every infobox value&lt;/ins&gt;, &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;index table&lt;/ins&gt;, &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;badge&lt;/ins&gt;, &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;tag link&lt;/ins&gt;, &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;sort order and&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;-- &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;                                    NEVER recomputed &lt;/del&gt;in &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Lua)&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;-- &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;  lore join on this wiki is computed here (or &lt;/ins&gt;in &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;a module that&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;--   &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;tier, price, locked             — shop categories&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;--   &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;require&lt;/ins&gt;()&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;s this one) at render time, from the ten source&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;--   type, state                     — Crux &lt;/del&gt;(&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;type also on Codex entries&lt;/del&gt;)&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;--   Data:&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&amp;lt;Category&amp;gt;&lt;/ins&gt;.json &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;pages. There are no precomputed data pages:&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;--   &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;tags     = {&quot;Melee&quot;,&quot;Sword&quot;}    — tag KEYS; text joins &lt;/del&gt;Data:&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Tags&lt;/del&gt;.json&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;--   &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;edit a value on a Data page, purge&lt;/ins&gt;, &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;and every view of it updates&lt;/ins&gt;.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;--   &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;tag_source                      — raw game tag family (weapons)&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-added&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;--   stats    = {[&quot;Damage&quot;]=11&lt;/del&gt;, .&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;..} — raw numeric stats (&quot;15%&quot; strings kept)&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-added&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;--   description                     — prose (lore / description / objective)&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-added&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;--&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;--&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;-- Cross-category functions (find, tagMembership, codexFor) load &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;several&lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;-- &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;HOW TO INVOKE&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;-- Data pages in one parse &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;— requires &lt;/del&gt;the host&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&#039;s &lt;/del&gt;256 MiB &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Scribunto &lt;/del&gt;cap.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;--   You normally don&#039;t invoke Core directly. Each category module&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;--   (Module:Weapons, Module:Enemies, ...) is a thin shim that binds a&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;--   category name and forwards to the entry points at the bottom of&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;--   this file:&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;--     {{#invoke:Weapons|infobox|id=Cutter}}     -&amp;gt; p.infoboxEntry&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;--     {{#invoke:Weapons|body|id=Cutter}}        -&amp;gt; p.bodyEntry&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;--     {{#invoke:Weapons|index}}                 -&amp;gt; p.indexEntry&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;--     {{#invoke:Weapons|render|id=Cutter}}      -&amp;gt; p.renderEntry (all-in-one)&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;--&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;-- SOURCE DATA IT READS (see each page&#039;s own `description` for fields)&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;--   Data:Weapons.json, Data:Characters.json, Data:Blessings.json,&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;--   Data:Upgrades.json, Data:Crux.json, Data:Passives.json,&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;--   Data:Enemies.json, Data:Achievements.json, Data:Codex.json,&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;--   Data:Tags.json&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;--   Common record fields: id, slug, name, icon, tier, price, locked,&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;--   type, state, tags[] (keys into Data:Tags.json), stats{}, description.&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;--&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;-- EDITING NOTES&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;--   * `slug` IS the page title. Never rebuild it from `name` in Lua —&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;--     always read rec.slug.&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;--   * Presentation config (stat display order, glyphs, infobox field&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;--     lists, index columns, sort keys) lives in the tables below and is&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;--     editable on-wiki in this one place.&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;--   * &lt;/ins&gt;Cross-category functions (find, tagMembership, codexFor) load&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;-- &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;    several &lt;/ins&gt;Data pages in one parse&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;; &lt;/ins&gt;the host &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;runs Scribunto with a&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;--     raised (&lt;/ins&gt;256 MiB&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;) memory &lt;/ins&gt;cap &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;to allow this.&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;--   * See Help:Wiki Editing for the full architecture guide&lt;/ins&gt;.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;local p = {}&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;local p = {}&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l51&quot;&gt;Line 51:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 70:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;-- ===================================================================&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;-- ===================================================================&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;-- &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;SC-01: canonicalise &lt;/del&gt;mw.loadJsonData&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&#039;s frozen &lt;/del&gt;table once.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;-- mw.loadJsonData &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;returns a read-only &lt;/ins&gt;table &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;with quirky numeric keys;&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;-- copy it &lt;/ins&gt;once &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;into a plain mutable table so the rest of the module can&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;-- treat records as ordinary Lua tables&lt;/ins&gt;.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;local function fix(t)&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;local function fix(t)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;   if type(t) ~= &amp;#039;table&amp;#039; then return t end&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;   if type(t) ~= &amp;#039;table&amp;#039; then return t end&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l167&quot;&gt;Line 167:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 188:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;end&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;end&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;-- Render one stat value. nil &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;=&amp;gt; drop &lt;/del&gt;the row &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;(disabled sentinel&lt;/del&gt;).&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;-- Render one stat value. &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;The game data uses huge sentinels for on/off&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;-- &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Mirrors flatten&#039;s historic fmt_stat_value exactly&lt;/del&gt;.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;-- mechanics: &amp;gt;= 1000 means &quot;Unlimited&quot;, &amp;lt;= -1000 means &quot;disabled&quot; (we&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;-- return &lt;/ins&gt;nil &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;so the caller drops &lt;/ins&gt;the row). &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;`signed` adds a &#039;+&#039; prefix&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;-- &lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;for modifier-style categories (heroes, blessings, upgrades, ...)&lt;/ins&gt;.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;function p.fmtStat(v, signed)&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;function p.fmtStat(v, signed)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;   if type(v) == &amp;#039;number&amp;#039; then&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;   if type(v) == &amp;#039;number&amp;#039; then&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;

&lt;!-- diff cache key armsofgodwiki:diff:1.41:old-1928:rev-2082:php=table --&gt;
&lt;/table&gt;</summary>
		<author><name>Ta1ha</name></author>
	</entry>
	<entry>
		<id>https://armsofgod.wiki.spellsandguns.com/index.php?title=Module:Core&amp;diff=1928&amp;oldid=prev</id>
		<title>Ta1ha: bot: render-time derivation refactor (phase 1)</title>
		<link rel="alternate" type="text/html" href="https://armsofgod.wiki.spellsandguns.com/index.php?title=Module:Core&amp;diff=1928&amp;oldid=prev"/>
		<updated>2026-06-10T08:29:13Z</updated>

		<summary type="html">&lt;p&gt;bot: render-time derivation refactor (phase 1)&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;-- Module:Core — shared registry, loaders and render-time computation&lt;br /&gt;
-- (Arms of God). THE single source of derivation logic: every table, list,&lt;br /&gt;
-- infobox value, badge and summary on this wiki is computed HERE (or in a&lt;br /&gt;
-- module that requires this one) at render time, from the source&lt;br /&gt;
-- Data:&amp;lt;Category&amp;gt;.json pages. There are no precomputed / derived Data pages.&lt;br /&gt;
--&lt;br /&gt;
-- Source record contract (one Data:&amp;lt;Cat&amp;gt;.json per category, array `records`):&lt;br /&gt;
--   id, slug, name, icon            — identity (slug computed by flatten.py,&lt;br /&gt;
--                                     NEVER recomputed in Lua)&lt;br /&gt;
--   tier, price, locked             — shop categories&lt;br /&gt;
--   type, state                     — Crux (type also on Codex entries)&lt;br /&gt;
--   tags     = {&amp;quot;Melee&amp;quot;,&amp;quot;Sword&amp;quot;}    — tag KEYS; text joins Data:Tags.json&lt;br /&gt;
--   tag_source                      — raw game tag family (weapons)&lt;br /&gt;
--   stats    = {[&amp;quot;Damage&amp;quot;]=11, ...} — raw numeric stats (&amp;quot;15%&amp;quot; strings kept)&lt;br /&gt;
--   description                     — prose (lore / description / objective)&lt;br /&gt;
--&lt;br /&gt;
-- Cross-category functions (find, tagMembership, codexFor) load several&lt;br /&gt;
-- Data pages in one parse — requires the host&amp;#039;s 256 MiB Scribunto cap.&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
-- ===================================================================&lt;br /&gt;
-- registry&lt;br /&gt;
-- ===================================================================&lt;br /&gt;
p.CATEGORIES = {&lt;br /&gt;
  {name = &amp;#039;Weapons&amp;#039;,      singular = &amp;#039;Weapon&amp;#039;},&lt;br /&gt;
  {name = &amp;#039;Characters&amp;#039;,   singular = &amp;#039;Character&amp;#039;},&lt;br /&gt;
  {name = &amp;#039;Blessings&amp;#039;,    singular = &amp;#039;Blessing&amp;#039;},&lt;br /&gt;
  {name = &amp;#039;Upgrades&amp;#039;,     singular = &amp;#039;Upgrade&amp;#039;},&lt;br /&gt;
  {name = &amp;#039;Crux&amp;#039;,         singular = &amp;#039;Crux&amp;#039;},&lt;br /&gt;
  {name = &amp;#039;Passives&amp;#039;,     singular = &amp;#039;Passive&amp;#039;},&lt;br /&gt;
  {name = &amp;#039;Enemies&amp;#039;,      singular = &amp;#039;Enemy&amp;#039;},&lt;br /&gt;
  {name = &amp;#039;Achievements&amp;#039;, singular = &amp;#039;Achievement&amp;#039;},&lt;br /&gt;
  {name = &amp;#039;Codex&amp;#039;,        singular = &amp;#039;Codex&amp;#039;},&lt;br /&gt;
  {name = &amp;#039;Tags&amp;#039;,         singular = &amp;#039;Tag&amp;#039;},&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
local ALIAS = {}&lt;br /&gt;
for _, c in ipairs(p.CATEGORIES) do&lt;br /&gt;
  ALIAS[c.name:lower()] = c.name&lt;br /&gt;
  ALIAS[c.singular:lower()] = c.name&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- &amp;#039;Weapon&amp;#039; / &amp;#039;weapons&amp;#039; / &amp;#039;Weapons&amp;#039; -&amp;gt; &amp;#039;Weapons&amp;#039;; nil when not a category.&lt;br /&gt;
function p.resolveCategory(word)&lt;br /&gt;
  if not word or word == &amp;#039;&amp;#039; then return nil end&lt;br /&gt;
  return ALIAS[(word:gsub(&amp;#039;^%s+&amp;#039;, &amp;#039;&amp;#039;):gsub(&amp;#039;%s+$&amp;#039;, &amp;#039;&amp;#039;)):lower()]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- ===================================================================&lt;br /&gt;
-- data loading (memoized per parse)&lt;br /&gt;
-- ===================================================================&lt;br /&gt;
&lt;br /&gt;
-- SC-01: canonicalise mw.loadJsonData&amp;#039;s frozen table once.&lt;br /&gt;
local function fix(t)&lt;br /&gt;
  if type(t) ~= &amp;#039;table&amp;#039; then return t end&lt;br /&gt;
  local out = {}&lt;br /&gt;
  for k, v in pairs(t) do&lt;br /&gt;
    out[k] = fix(v)&lt;br /&gt;
    if type(k) == &amp;#039;number&amp;#039; then out[tostring(k)] = out[k] end&lt;br /&gt;
  end&lt;br /&gt;
  return out&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local _data = {}&lt;br /&gt;
function p.load(cat)&lt;br /&gt;
  cat = p.resolveCategory(cat) or cat&lt;br /&gt;
  if _data[cat] == nil then&lt;br /&gt;
    local ok, d = pcall(mw.loadJsonData, &amp;#039;Data:&amp;#039; .. cat .. &amp;#039;.json&amp;#039;)&lt;br /&gt;
    if ok and type(d) == &amp;#039;table&amp;#039; then&lt;br /&gt;
      _data[cat] = fix(d).records or {}&lt;br /&gt;
    else&lt;br /&gt;
      _data[cat] = {}&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
  return _data[cat]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local _byId = {}&lt;br /&gt;
function p.byId(cat)&lt;br /&gt;
  cat = p.resolveCategory(cat) or cat&lt;br /&gt;
  if _byId[cat] == nil then&lt;br /&gt;
    local m = {}&lt;br /&gt;
    for _, r in ipairs(p.load(cat)) do&lt;br /&gt;
      if r.id then m[r.id] = r end&lt;br /&gt;
      if r.slug then m[r.slug] = r end&lt;br /&gt;
    end&lt;br /&gt;
    _byId[cat] = m&lt;br /&gt;
  end&lt;br /&gt;
  return _byId[cat]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Iterate every category&amp;#039;s records: returns a list of {cat=&amp;lt;name&amp;gt;, recs=&amp;lt;list&amp;gt;}.&lt;br /&gt;
function p.all()&lt;br /&gt;
  local out = {}&lt;br /&gt;
  for _, c in ipairs(p.CATEGORIES) do&lt;br /&gt;
    out[#out + 1] = {cat = c.name, recs = p.load(c.name)}&lt;br /&gt;
  end&lt;br /&gt;
  return out&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- First record across all categories matching slug or (lowercased) name.&lt;br /&gt;
-- Registry order wins on collisions (live entity beats its Codex entry).&lt;br /&gt;
function p.find(key)&lt;br /&gt;
  if not key or key == &amp;#039;&amp;#039; then return nil, nil end&lt;br /&gt;
  local k = mw.ustring.lower(key)&lt;br /&gt;
  for _, c in ipairs(p.CATEGORIES) do&lt;br /&gt;
    for _, r in ipairs(p.load(c.name)) do&lt;br /&gt;
      if r.slug == key or (r.slug and mw.ustring.lower(r.slug) == k)&lt;br /&gt;
        or (r.name and mw.ustring.lower(r.name) == k) then&lt;br /&gt;
        return c.name, r&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
  return nil, nil&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- ===================================================================&lt;br /&gt;
-- small helpers&lt;br /&gt;
-- ===================================================================&lt;br /&gt;
function p.slugFor(rec) return rec and rec.slug or &amp;#039;&amp;#039; end&lt;br /&gt;
function p.iconFor(rec) return rec and rec.icon or &amp;#039;&amp;#039; end&lt;br /&gt;
&lt;br /&gt;
function p.normName(s)&lt;br /&gt;
  s = mw.ustring.lower(s or &amp;#039;&amp;#039;)&lt;br /&gt;
  return (mw.ustring.gsub(s, &amp;#039;[^%w]&amp;#039;, &amp;#039;&amp;#039;))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.link(rec)&lt;br /&gt;
  if not rec then return &amp;#039;&amp;#039; end&lt;br /&gt;
  local slug = rec.slug or rec.name or &amp;#039;&amp;#039;&lt;br /&gt;
  return &amp;#039;[[&amp;#039; .. slug .. &amp;#039;|&amp;#039; .. (rec.name or slug) .. &amp;#039;]]&amp;#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- icon + linked name wrapped in .wm-tip (Common.js hover-infobox popup).&lt;br /&gt;
function p.iconLink(rec, size)&lt;br /&gt;
  if not rec then return &amp;#039;&amp;#039; end&lt;br /&gt;
  local slug = rec.slug or rec.name or &amp;#039;&amp;#039;&lt;br /&gt;
  local name = rec.name or slug&lt;br /&gt;
  local tip = &amp;#039;&amp;lt;span class=&amp;quot;wm-tip&amp;quot; data-tip-title=&amp;quot;&amp;#039; .. slug .. &amp;#039;&amp;quot;&amp;gt;&amp;#039;&lt;br /&gt;
  if rec.icon and rec.icon ~= &amp;#039;&amp;#039; then&lt;br /&gt;
    return tip .. &amp;#039;[[File:&amp;#039; .. rec.icon .. &amp;#039;|&amp;#039; .. (size or 24) .. &amp;#039;px|link=&amp;#039;&lt;br /&gt;
      .. slug .. &amp;#039;]] [[&amp;#039; .. slug .. &amp;#039;|&amp;#039; .. name .. &amp;#039;]]&amp;lt;/span&amp;gt;&amp;#039;&lt;br /&gt;
  end&lt;br /&gt;
  return tip .. &amp;#039;[[&amp;#039; .. slug .. &amp;#039;|&amp;#039; .. name .. &amp;#039;]]&amp;lt;/span&amp;gt;&amp;#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- &amp;#039;56.1&amp;#039; / &amp;#039;6&amp;#039; (no trailing .0); non-numbers pass through as strings.&lt;br /&gt;
function p.fmtNum(v)&lt;br /&gt;
  if type(v) == &amp;#039;number&amp;#039; then&lt;br /&gt;
    if v == math.floor(v) then return string.format(&amp;#039;%d&amp;#039;, v) end&lt;br /&gt;
    return tostring(v)&lt;br /&gt;
  end&lt;br /&gt;
  return tostring(v or &amp;#039;&amp;#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.round1(x)&lt;br /&gt;
  return math.floor(x * 10 + 0.5) / 10&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Parse a stat value to a number: 11 -&amp;gt; 11, &amp;#039;15%&amp;#039; -&amp;gt; 15, else nil.&lt;br /&gt;
function p.numStat(v)&lt;br /&gt;
  if type(v) == &amp;#039;number&amp;#039; then return v end&lt;br /&gt;
  if type(v) == &amp;#039;string&amp;#039; then&lt;br /&gt;
    return tonumber(v) or tonumber(v:match(&amp;#039;^%s*([%-%d%.]+)&amp;#039;))&lt;br /&gt;
  end&lt;br /&gt;
  return nil&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Render one stat value. nil =&amp;gt; drop the row (disabled sentinel).&lt;br /&gt;
-- Mirrors flatten&amp;#039;s historic fmt_stat_value exactly.&lt;br /&gt;
function p.fmtStat(v, signed)&lt;br /&gt;
  if type(v) == &amp;#039;number&amp;#039; then&lt;br /&gt;
    if v &amp;gt;= 1000 then return &amp;#039;Unlimited&amp;#039; end&lt;br /&gt;
    if v &amp;lt;= -1000 then return nil end&lt;br /&gt;
    local s = p.fmtNum(v)&lt;br /&gt;
    if signed and v &amp;gt; 0 then s = &amp;#039;+&amp;#039; .. s end&lt;br /&gt;
    return s&lt;br /&gt;
  end&lt;br /&gt;
  local s = tostring(v or &amp;#039;&amp;#039;)&lt;br /&gt;
  if signed and s ~= &amp;#039;&amp;#039; and s:sub(1, 1) ~= &amp;#039;-&amp;#039; and s:sub(1, 1) ~= &amp;#039;+&amp;#039; then&lt;br /&gt;
    s = &amp;#039;+&amp;#039; .. s&lt;br /&gt;
  end&lt;br /&gt;
  return s&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.firstSentence(text, cap)&lt;br /&gt;
  local t = (text or &amp;#039;&amp;#039;):gsub(&amp;#039;^%s+&amp;#039;, &amp;#039;&amp;#039;)&lt;br /&gt;
  t = t:match(&amp;#039;^[^\n]*&amp;#039;) or t&lt;br /&gt;
  local s = t:match(&amp;#039;^(.-[%.!%?])%s&amp;#039;) or t:match(&amp;#039;^(.-[%.!%?])$&amp;#039;) or t&lt;br /&gt;
  cap = cap or 140&lt;br /&gt;
  if mw.ustring.len(s) &amp;gt; cap then s = mw.ustring.sub(s, 1, cap) end&lt;br /&gt;
  return s&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- ===================================================================&lt;br /&gt;
-- stat presentation config&lt;br /&gt;
-- ===================================================================&lt;br /&gt;
&lt;br /&gt;
-- Canonical display order for the stats block (JSON object key order is&lt;br /&gt;
-- not visible to Lua). Unknown stats append alphabetically at the end.&lt;br /&gt;
local STAT_ORDER = {&lt;br /&gt;
  &amp;#039;Damage&amp;#039;, &amp;#039;Damage per Wave&amp;#039;, &amp;#039;Health&amp;#039;, &amp;#039;HP per Wave&amp;#039;,&lt;br /&gt;
  &amp;#039;Holy Damage&amp;#039;, &amp;#039;Fire Damage&amp;#039;, &amp;#039;Electric Damage&amp;#039;,&lt;br /&gt;
  &amp;#039;Damage vs Burning&amp;#039;, &amp;#039;Damage vs Shocked&amp;#039;, &amp;#039;Melee Damage&amp;#039;, &amp;#039;Range Damage&amp;#039;,&lt;br /&gt;
  &amp;#039;Attack Speed&amp;#039;, &amp;#039;Critical Chance&amp;#039;, &amp;#039;Critical Damage&amp;#039;, &amp;#039;Range&amp;#039;,&lt;br /&gt;
  &amp;#039;Health Points&amp;#039;, &amp;#039;HP Rate&amp;#039;, &amp;#039;HP Delay&amp;#039;,&lt;br /&gt;
  &amp;#039;Pierce&amp;#039;, &amp;#039;Projectiles&amp;#039;, &amp;#039;Bounce&amp;#039;,&lt;br /&gt;
  &amp;#039;Explosive Chance&amp;#039;, &amp;#039;Explosive Radius&amp;#039;, &amp;#039;Explosive Range&amp;#039;, &amp;#039;HP Steal&amp;#039;,&lt;br /&gt;
  &amp;#039;Armor&amp;#039;, &amp;#039;Dodge&amp;#039;, &amp;#039;Speed&amp;#039;, &amp;#039;Resources&amp;#039;, &amp;#039;Rarity Find&amp;#039;,&lt;br /&gt;
  &amp;#039;Stagger&amp;#039;, &amp;#039;Stun&amp;#039;, &amp;#039;Freeze&amp;#039;, &amp;#039;XP Gain&amp;#039;, &amp;#039;Pickup Range&amp;#039;, &amp;#039;Cooldown&amp;#039;,&lt;br /&gt;
}&lt;br /&gt;
local STAT_RANK = {}&lt;br /&gt;
for i, k in ipairs(STAT_ORDER) do STAT_RANK[k] = i end&lt;br /&gt;
&lt;br /&gt;
-- Stat name -&amp;gt; in-game glyph file (18px next to each stat row).&lt;br /&gt;
local STAT_GLYPHS = {&lt;br /&gt;
  [&amp;#039;Damage&amp;#039;] = &amp;#039;Stat_Damage.png&amp;#039;,&lt;br /&gt;
  [&amp;#039;Fire Damage&amp;#039;] = &amp;#039;Stat_Fire.png&amp;#039;,&lt;br /&gt;
  [&amp;#039;Electric Damage&amp;#039;] = &amp;#039;Stat_Electric.png&amp;#039;,&lt;br /&gt;
  [&amp;#039;Holy Damage&amp;#039;] = &amp;#039;Stat_Physical.png&amp;#039;,&lt;br /&gt;
  [&amp;#039;Attack Speed&amp;#039;] = &amp;#039;Stat_AttackSpeed.png&amp;#039;,&lt;br /&gt;
  [&amp;#039;Critical Chance&amp;#039;] = &amp;#039;Stat_Critical.png&amp;#039;,&lt;br /&gt;
  [&amp;#039;Critical Damage&amp;#039;] = &amp;#039;Stat_CriticalDmg.png&amp;#039;,&lt;br /&gt;
  [&amp;#039;Range&amp;#039;] = &amp;#039;Stat_Range.png&amp;#039;,&lt;br /&gt;
  [&amp;#039;Pierce&amp;#039;] = &amp;#039;Stat_Pierce.png&amp;#039;,&lt;br /&gt;
  [&amp;#039;Bounce&amp;#039;] = &amp;#039;Stat_Bounce.png&amp;#039;,&lt;br /&gt;
  [&amp;#039;Projectiles&amp;#039;] = &amp;#039;Stat_Projectiles.png&amp;#039;,&lt;br /&gt;
  [&amp;#039;Stagger&amp;#039;] = &amp;#039;Stat_Stagger.png&amp;#039;,&lt;br /&gt;
  [&amp;#039;Stun&amp;#039;] = &amp;#039;Stat_Stun.png&amp;#039;,&lt;br /&gt;
  [&amp;#039;Freeze&amp;#039;] = &amp;#039;Stat_Freeze.png&amp;#039;,&lt;br /&gt;
  [&amp;#039;Explosive Chance&amp;#039;] = &amp;#039;Stat_ExplosiveChance.png&amp;#039;,&lt;br /&gt;
  [&amp;#039;Explosive Radius&amp;#039;] = &amp;#039;Stat_ExplosiveRadius.png&amp;#039;,&lt;br /&gt;
  [&amp;#039;Explosive Range&amp;#039;] = &amp;#039;Stat_ExplosiveRadius.png&amp;#039;,&lt;br /&gt;
  [&amp;#039;HP Steal&amp;#039;] = &amp;#039;Stat_HPSteal.png&amp;#039;,&lt;br /&gt;
  [&amp;#039;Health Points&amp;#039;] = &amp;#039;Stat_HP.png&amp;#039;,&lt;br /&gt;
  [&amp;#039;HP Rate&amp;#039;] = &amp;#039;Stat_HPRate.png&amp;#039;,&lt;br /&gt;
  [&amp;#039;HP Delay&amp;#039;] = &amp;#039;Stat_HPDelay.png&amp;#039;,&lt;br /&gt;
  [&amp;#039;Speed&amp;#039;] = &amp;#039;Stat_Speed.png&amp;#039;,&lt;br /&gt;
  [&amp;#039;Armor&amp;#039;] = &amp;#039;Stat_Armor.png&amp;#039;,&lt;br /&gt;
  [&amp;#039;Dodge&amp;#039;] = &amp;#039;Stat_Dodge.png&amp;#039;,&lt;br /&gt;
  [&amp;#039;Resources&amp;#039;] = &amp;#039;Stat_Resources.png&amp;#039;,&lt;br /&gt;
  [&amp;#039;Pickup Range&amp;#039;] = &amp;#039;Stat_PickupRange.png&amp;#039;,&lt;br /&gt;
  [&amp;#039;Rarity Find&amp;#039;] = &amp;#039;Stat_RarityFind.png&amp;#039;,&lt;br /&gt;
  [&amp;#039;XP Gain&amp;#039;] = &amp;#039;Stat_XPGain.png&amp;#039;,&lt;br /&gt;
  [&amp;#039;Cooldown&amp;#039;] = &amp;#039;Stat_Cooldown.png&amp;#039;,&lt;br /&gt;
  [&amp;#039;Damage vs Burning&amp;#039;] = &amp;#039;Stat_VsFire.png&amp;#039;,&lt;br /&gt;
  [&amp;#039;Damage vs Shocked&amp;#039;] = &amp;#039;Stat_VsElectric.png&amp;#039;,&lt;br /&gt;
  [&amp;#039;Health&amp;#039;] = &amp;#039;Stat_HitPoints.png&amp;#039;,&lt;br /&gt;
}&lt;br /&gt;
p.STAT_GLYPHS = STAT_GLYPHS&lt;br /&gt;
&lt;br /&gt;
function p.statGlyph(stat)&lt;br /&gt;
  local f = STAT_GLYPHS[stat]&lt;br /&gt;
  if f then return &amp;#039;[[File:&amp;#039; .. f .. &amp;#039;|18px|link=]] &amp;#039; end&lt;br /&gt;
  return &amp;#039;&amp;#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Elemental damage accent chips (dark-theme tokens with inline fallbacks).&lt;br /&gt;
p.DMG_CHIP = {&lt;br /&gt;
  [&amp;#039;Holy Damage&amp;#039;]     = {&amp;#039;--dmg-holy&amp;#039;, &amp;#039;#e8c34a&amp;#039;, &amp;#039;wm-dmg-holy&amp;#039;},&lt;br /&gt;
  [&amp;#039;Fire Damage&amp;#039;]     = {&amp;#039;--dmg-fire&amp;#039;, &amp;#039;#ff6b35&amp;#039;, &amp;#039;wm-dmg-fire&amp;#039;},&lt;br /&gt;
  [&amp;#039;Electric Damage&amp;#039;] = {&amp;#039;--dmg-electric&amp;#039;, &amp;#039;#4ea3ff&amp;#039;, &amp;#039;wm-dmg-electric&amp;#039;},&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
-- Ordered {key, value} pairs of rec.stats per STAT_ORDER (extras appended&lt;br /&gt;
-- alphabetically).&lt;br /&gt;
function p.statPairs(rec)&lt;br /&gt;
  local stats = (rec and rec.stats) or {}&lt;br /&gt;
  local known, extra = {}, {}&lt;br /&gt;
  for k in pairs(stats) do&lt;br /&gt;
    if STAT_RANK[k] then known[#known + 1] = k else extra[#extra + 1] = k end&lt;br /&gt;
  end&lt;br /&gt;
  table.sort(known, function(a, b) return STAT_RANK[a] &amp;lt; STAT_RANK[b] end)&lt;br /&gt;
  table.sort(extra)&lt;br /&gt;
  local out = {}&lt;br /&gt;
  for _, k in ipairs(known) do out[#out + 1] = {k, stats[k]} end&lt;br /&gt;
  for _, k in ipairs(extra) do out[#out + 1] = {k, stats[k]} end&lt;br /&gt;
  return out&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Infobox &amp;#039;Stats&amp;#039; cell: one glyph+label+value line per stat, &amp;lt;br&amp;gt;-joined.&lt;br /&gt;
-- Elemental damage labels link to the damage-type hub pages.&lt;br /&gt;
function p.statsBlock(rec, signed)&lt;br /&gt;
  local lines = {}&lt;br /&gt;
  for _, kv in ipairs(p.statPairs(rec)) do&lt;br /&gt;
    local k, v = kv[1], kv[2]&lt;br /&gt;
    local val = p.fmtStat(v, signed)&lt;br /&gt;
    if val ~= nil then&lt;br /&gt;
      local chip = p.DMG_CHIP[k]&lt;br /&gt;
      if chip then&lt;br /&gt;
        lines[#lines + 1] = p.statGlyph(k) .. &amp;#039;&amp;lt;span class=&amp;quot;&amp;#039; .. chip[3]&lt;br /&gt;
          .. &amp;#039;&amp;quot; style=&amp;quot;color:var(&amp;#039; .. chip[1] .. &amp;#039;, &amp;#039; .. chip[2]&lt;br /&gt;
          .. &amp;quot;);\&amp;quot;&amp;gt;&amp;#039;&amp;#039;&amp;#039;[[&amp;quot; .. k .. &amp;#039;|&amp;#039; .. k .. &amp;quot;]]:&amp;#039;&amp;#039;&amp;#039; &amp;quot; .. val .. &amp;#039;&amp;lt;/span&amp;gt;&amp;#039;&lt;br /&gt;
      else&lt;br /&gt;
        lines[#lines + 1] = p.statGlyph(k) .. &amp;quot;&amp;#039;&amp;#039;&amp;#039;&amp;quot; .. k .. &amp;quot;:&amp;#039;&amp;#039;&amp;#039; &amp;quot; .. val&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
  return table.concat(lines, &amp;#039;&amp;lt;br&amp;gt;&amp;#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- One-line plain-text summary for index columns (Effects / Modifiers).&lt;br /&gt;
function p.effectsSummary(rec, signed)&lt;br /&gt;
  local parts = {}&lt;br /&gt;
  for _, kv in ipairs(p.statPairs(rec)) do&lt;br /&gt;
    local val = p.fmtStat(kv[2], signed)&lt;br /&gt;
    if val ~= nil then parts[#parts + 1] = kv[1] .. &amp;#039; &amp;#039; .. val end&lt;br /&gt;
  end&lt;br /&gt;
  if #parts &amp;gt; 0 then return table.concat(parts, &amp;#039;, &amp;#039;) end&lt;br /&gt;
  local texts = {}&lt;br /&gt;
  for _, key in ipairs(rec.tags or {}) do&lt;br /&gt;
    local t = p.tagText(key)&lt;br /&gt;
    if t and t ~= &amp;#039;&amp;#039; then texts[#texts + 1] = t end&lt;br /&gt;
  end&lt;br /&gt;
  if #texts &amp;gt; 0 then return table.concat(texts, &amp;#039; &amp;#039;) end&lt;br /&gt;
  local d = (rec.description or &amp;#039;&amp;#039;):gsub(&amp;#039;^%s+&amp;#039;, &amp;#039;&amp;#039;)&lt;br /&gt;
  if d ~= &amp;#039;&amp;#039; then return mw.ustring.sub(p.firstSentence(d, 120), 1, 120) end&lt;br /&gt;
  return &amp;#039;&amp;#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.availability(locked)&lt;br /&gt;
  if locked then return &amp;#039;Must be unlocked&amp;#039; end&lt;br /&gt;
  return &amp;#039;Unlocked from start&amp;#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local CRUX_STATE = {&lt;br /&gt;
  Acquired = &amp;#039;Default&amp;#039;,&lt;br /&gt;
  Unlocked = &amp;#039;Unlocked from start&amp;#039;,&lt;br /&gt;
  Locked = &amp;#039;Must be unlocked&amp;#039;,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
-- Melee vs Ranged: the melee weapons carry the Melee tag (or raw&lt;br /&gt;
-- tag_source family &amp;#039;Melee&amp;#039;); everything else is Ranged.&lt;br /&gt;
function p.weaponClass(rec)&lt;br /&gt;
  for _, k in ipairs(rec.tags or {}) do&lt;br /&gt;
    if k == &amp;#039;Melee&amp;#039; then return &amp;#039;Melee&amp;#039; end&lt;br /&gt;
  end&lt;br /&gt;
  if rec.tag_source == &amp;#039;Melee&amp;#039; then return &amp;#039;Melee&amp;#039; end&lt;br /&gt;
  return &amp;#039;Ranged&amp;#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- ===================================================================&lt;br /&gt;
-- tags&lt;br /&gt;
-- ===================================================================&lt;br /&gt;
local _tagByKey = nil&lt;br /&gt;
function p.tagRec(key)&lt;br /&gt;
  if _tagByKey == nil then&lt;br /&gt;
    _tagByKey = {}&lt;br /&gt;
    for _, r in ipairs(p.load(&amp;#039;Tags&amp;#039;)) do&lt;br /&gt;
      _tagByKey[r.id or r.name] = r&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
  return _tagByKey[key]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.tagText(key)&lt;br /&gt;
  local r = p.tagRec(key)&lt;br /&gt;
  return (r and r.text) or &amp;#039;&amp;#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Tag link wrapped for the hover-tooltip JS. Slug comes from the tag&amp;#039;s&lt;br /&gt;
-- own source record (never recomputed here).&lt;br /&gt;
function p.tagLink(key)&lt;br /&gt;
  local r = p.tagRec(key)&lt;br /&gt;
  if not r or not r.slug then return key end&lt;br /&gt;
  return &amp;#039;&amp;lt;span class=&amp;quot;wm-tip&amp;quot; data-tip-title=&amp;quot;&amp;#039; .. r.slug .. &amp;#039;&amp;quot;&amp;gt;[[&amp;#039;&lt;br /&gt;
    .. r.slug .. &amp;#039;|&amp;#039; .. key .. &amp;#039;]]&amp;lt;/span&amp;gt;&amp;#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Body &amp;#039;Tags&amp;#039; section: list of &amp;quot;&amp;lt;link&amp;gt; – &amp;lt;text&amp;gt;&amp;quot; strings.&lt;br /&gt;
function p.tagsBody(rec)&lt;br /&gt;
  local out = {}&lt;br /&gt;
  for _, key in ipairs(rec.tags or {}) do&lt;br /&gt;
    local text = p.tagText(key)&lt;br /&gt;
    if text ~= &amp;#039;&amp;#039; then&lt;br /&gt;
      out[#out + 1] = p.tagLink(key) .. &amp;#039; – &amp;#039; .. text&lt;br /&gt;
    else&lt;br /&gt;
      out[#out + 1] = p.tagLink(key)&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
  return out&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Cross-category tag membership map: {tagkey -&amp;gt; {catName -&amp;gt; {rec,...}}}.&lt;br /&gt;
-- One scan per parse (memoized); powers tag pages + Used-by counts.&lt;br /&gt;
local TAG_BEARING = {&amp;#039;Weapons&amp;#039;, &amp;#039;Characters&amp;#039;, &amp;#039;Blessings&amp;#039;, &amp;#039;Upgrades&amp;#039;,&lt;br /&gt;
                     &amp;#039;Passives&amp;#039;, &amp;#039;Enemies&amp;#039;}&lt;br /&gt;
p.TAG_BEARING = TAG_BEARING&lt;br /&gt;
&lt;br /&gt;
local _membership = nil&lt;br /&gt;
function p.tagMembership()&lt;br /&gt;
  if _membership == nil then&lt;br /&gt;
    _membership = {}&lt;br /&gt;
    for _, cat in ipairs(TAG_BEARING) do&lt;br /&gt;
      for _, r in ipairs(p.load(cat)) do&lt;br /&gt;
        for _, key in ipairs(r.tags or {}) do&lt;br /&gt;
          _membership[key] = _membership[key] or {}&lt;br /&gt;
          _membership[key][cat] = _membership[key][cat] or {}&lt;br /&gt;
          local bucket = _membership[key][cat]&lt;br /&gt;
          bucket[#bucket + 1] = r&lt;br /&gt;
        end&lt;br /&gt;
      end&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
  return _membership&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.usedByCount(key)&lt;br /&gt;
  local m = p.tagMembership()[key]&lt;br /&gt;
  if not m then return 0 end&lt;br /&gt;
  local n = 0&lt;br /&gt;
  for _, recs in pairs(m) do n = n + #recs end&lt;br /&gt;
  return n&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- ===================================================================&lt;br /&gt;
-- codex joins (by normalized name)&lt;br /&gt;
-- ===================================================================&lt;br /&gt;
local _codexByType = nil&lt;br /&gt;
local function codexIndex()&lt;br /&gt;
  if _codexByType == nil then&lt;br /&gt;
    _codexByType = {}&lt;br /&gt;
    for _, r in ipairs(p.load(&amp;#039;Codex&amp;#039;)) do&lt;br /&gt;
      local t = r.type or &amp;#039;&amp;#039;&lt;br /&gt;
      _codexByType[t] = _codexByType[t] or {}&lt;br /&gt;
      _codexByType[t][p.normName(r.name or r.id)] = r&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
  return _codexByType&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- The codex entry describing an entity (Weapons / Enemies join), or nil.&lt;br /&gt;
function p.codexFor(name, codexType)&lt;br /&gt;
  local idx = codexIndex()&lt;br /&gt;
  local key = p.normName(name)&lt;br /&gt;
  if codexType then&lt;br /&gt;
    return (idx[codexType] or {})[key]&lt;br /&gt;
  end&lt;br /&gt;
  for _, bucket in pairs(idx) do&lt;br /&gt;
    if bucket[key] then return bucket[key] end&lt;br /&gt;
  end&lt;br /&gt;
  return nil&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- ===================================================================&lt;br /&gt;
-- computed infobox (per category) — same field names/values the&lt;br /&gt;
-- infobox Templates and index columns have always consumed.&lt;br /&gt;
-- ===================================================================&lt;br /&gt;
local INFOBOX_BUILDERS = {&lt;br /&gt;
  Weapons = function(rec)&lt;br /&gt;
    return {&lt;br /&gt;
      Class = p.weaponClass(rec),&lt;br /&gt;
      Tier = rec.tier,&lt;br /&gt;
      Price = p.fmtNum(rec.price),&lt;br /&gt;
      Availability = p.availability(rec.locked),&lt;br /&gt;
      Stats = p.statsBlock(rec, false),&lt;br /&gt;
      Damage = rec.stats and rec.stats[&amp;#039;Damage&amp;#039;] ~= nil&lt;br /&gt;
        and p.fmtNum(rec.stats[&amp;#039;Damage&amp;#039;]) or nil,&lt;br /&gt;
      [&amp;#039;Attack Speed&amp;#039;] = rec.stats and rec.stats[&amp;#039;Attack Speed&amp;#039;] ~= nil&lt;br /&gt;
        and p.fmtNum(rec.stats[&amp;#039;Attack Speed&amp;#039;]) or nil,&lt;br /&gt;
    }&lt;br /&gt;
  end,&lt;br /&gt;
  Characters = function(rec)&lt;br /&gt;
    local hp = rec.stats and rec.stats[&amp;#039;Health Points&amp;#039;]&lt;br /&gt;
    return {&lt;br /&gt;
      Availability = p.availability(rec.locked),&lt;br /&gt;
      Stats = p.statsBlock(rec, true),&lt;br /&gt;
      Modifiers = p.effectsSummary(rec, true),&lt;br /&gt;
      [&amp;#039;Health Points&amp;#039;] = hp ~= nil and p.fmtStat(hp, true) or nil,&lt;br /&gt;
    }&lt;br /&gt;
  end,&lt;br /&gt;
  Crux = function(rec)&lt;br /&gt;
    return {&lt;br /&gt;
      Type = rec.type,&lt;br /&gt;
      Availability = CRUX_STATE[rec.state] or rec.state or &amp;#039;&amp;#039;,&lt;br /&gt;
      Stats = p.statsBlock(rec, true),&lt;br /&gt;
      Effects = p.effectsSummary(rec, true),&lt;br /&gt;
    }&lt;br /&gt;
  end,&lt;br /&gt;
  Enemies = function(rec)&lt;br /&gt;
    local ib = {Stats = p.statsBlock(rec, false)}&lt;br /&gt;
    if rec.tags and #rec.tags &amp;gt; 0 then&lt;br /&gt;
      local links = {}&lt;br /&gt;
      for _, k in ipairs(rec.tags) do links[#links + 1] = p.tagLink(k) end&lt;br /&gt;
      ib.Classification = table.concat(links, &amp;#039;, &amp;#039;)&lt;br /&gt;
    end&lt;br /&gt;
    local st = rec.stats or {}&lt;br /&gt;
    for _, k in ipairs({&amp;#039;Health&amp;#039;, &amp;#039;Damage&amp;#039;, &amp;#039;Speed&amp;#039;, &amp;#039;Resources&amp;#039;}) do&lt;br /&gt;
      if st[k] ~= nil then ib[k] = p.fmtNum(st[k]) end&lt;br /&gt;
    end&lt;br /&gt;
    if st[&amp;#039;HP per Wave&amp;#039;] ~= nil then ib[&amp;#039;HP/Wave&amp;#039;] = p.fmtNum(st[&amp;#039;HP per Wave&amp;#039;]) end&lt;br /&gt;
    if st[&amp;#039;Damage per Wave&amp;#039;] ~= nil then ib[&amp;#039;Dmg/Wave&amp;#039;] = p.fmtNum(st[&amp;#039;Damage per Wave&amp;#039;]) end&lt;br /&gt;
    return ib&lt;br /&gt;
  end,&lt;br /&gt;
  Achievements = function(rec)&lt;br /&gt;
    return {Objective = rec.description or &amp;#039;&amp;#039;}&lt;br /&gt;
  end,&lt;br /&gt;
  Codex = function(rec)&lt;br /&gt;
    return {&lt;br /&gt;
      Type = rec.type,&lt;br /&gt;
      Summary = p.firstSentence(rec.description or &amp;#039;&amp;#039;, 140),&lt;br /&gt;
    }&lt;br /&gt;
  end,&lt;br /&gt;
  Tags = function(rec)&lt;br /&gt;
    local text = rec.text or &amp;#039;&amp;#039;&lt;br /&gt;
    if text == &amp;#039;&amp;#039; then text = &amp;quot;&amp;#039;&amp;#039;(no effect text provided by the game data)&amp;#039;&amp;#039;&amp;quot; end&lt;br /&gt;
    return {Effect = text, [&amp;#039;Used by&amp;#039;] = p.usedByCount(rec.id or rec.name)}&lt;br /&gt;
  end,&lt;br /&gt;
}&lt;br /&gt;
local function shopInfobox(rec)&lt;br /&gt;
  return {&lt;br /&gt;
    Tier = rec.tier,&lt;br /&gt;
    Price = p.fmtNum(rec.price),&lt;br /&gt;
    Availability = p.availability(rec.locked),&lt;br /&gt;
    Stats = p.statsBlock(rec, true),&lt;br /&gt;
    Effects = p.effectsSummary(rec, true),&lt;br /&gt;
  }&lt;br /&gt;
end&lt;br /&gt;
INFOBOX_BUILDERS.Blessings = shopInfobox&lt;br /&gt;
INFOBOX_BUILDERS.Upgrades = shopInfobox&lt;br /&gt;
INFOBOX_BUILDERS.Passives = shopInfobox&lt;br /&gt;
&lt;br /&gt;
function p.computedInfobox(cat, rec)&lt;br /&gt;
  local b = INFOBOX_BUILDERS[cat]&lt;br /&gt;
  if not b then return {} end&lt;br /&gt;
  return b(rec)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- ===================================================================&lt;br /&gt;
-- body sections (computed)&lt;br /&gt;
-- ===================================================================&lt;br /&gt;
function p.bodySection(cat, rec, section)&lt;br /&gt;
  if section == &amp;#039;Tags&amp;#039; then&lt;br /&gt;
    return p.tagsBody(rec)&lt;br /&gt;
  end&lt;br /&gt;
  if section == &amp;#039;Description&amp;#039; or section == &amp;#039;Objective&amp;#039; then&lt;br /&gt;
    return rec.description or &amp;#039;&amp;#039;&lt;br /&gt;
  end&lt;br /&gt;
  if section == &amp;#039;Lore&amp;#039; then&lt;br /&gt;
    if cat == &amp;#039;Weapons&amp;#039; or cat == &amp;#039;Enemies&amp;#039; then&lt;br /&gt;
      local cx = p.codexFor(rec.name, cat)&lt;br /&gt;
      if cx and cx.description and cx.description ~= &amp;#039;&amp;#039; then&lt;br /&gt;
        return cx.description&lt;br /&gt;
      end&lt;br /&gt;
      if cat == &amp;#039;Enemies&amp;#039; then return rec.description or &amp;#039;&amp;#039; end&lt;br /&gt;
      return &amp;#039;&amp;#039;&lt;br /&gt;
    end&lt;br /&gt;
    -- Characters / Codex: own prose.&lt;br /&gt;
    return rec.description or &amp;#039;&amp;#039;&lt;br /&gt;
  end&lt;br /&gt;
  return &amp;#039;&amp;#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local BODY_ORDER = {&lt;br /&gt;
  Weapons = {&amp;#039;Lore&amp;#039;, &amp;#039;Tags&amp;#039;},&lt;br /&gt;
  Characters = {&amp;#039;Lore&amp;#039;, &amp;#039;Tags&amp;#039;},&lt;br /&gt;
  Blessings = {&amp;#039;Description&amp;#039;, &amp;#039;Tags&amp;#039;},&lt;br /&gt;
  Upgrades = {&amp;#039;Description&amp;#039;, &amp;#039;Tags&amp;#039;},&lt;br /&gt;
  Passives = {&amp;#039;Description&amp;#039;, &amp;#039;Tags&amp;#039;},&lt;br /&gt;
  Crux = {&amp;#039;Description&amp;#039;},&lt;br /&gt;
  Enemies = {&amp;#039;Lore&amp;#039;},&lt;br /&gt;
  Achievements = {&amp;#039;Objective&amp;#039;},&lt;br /&gt;
  Codex = {&amp;#039;Lore&amp;#039;},&lt;br /&gt;
  Tags = {},&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
-- ===================================================================&lt;br /&gt;
-- sorting (per-category index order, computed at render time so the&lt;br /&gt;
-- source page order never matters)&lt;br /&gt;
-- ===================================================================&lt;br /&gt;
local CRUX_TYPE_ORDER = {Unique = 1, Action = 2, Buff = 3, Debuff = 4, Aura = 5}&lt;br /&gt;
local CODEX_TYPE_ORDER = {Enemies = 1, Weapons = 2, Events = 3, Tips = 4}&lt;br /&gt;
local ROMAN = {I = 1, II = 2, III = 3, IV = 4, V = 5}&lt;br /&gt;
&lt;br /&gt;
local function familyKey(name)&lt;br /&gt;
  local head, tail = name:match(&amp;#039;^(.*)%s(%S+)$&amp;#039;)&lt;br /&gt;
  if head and ROMAN[tail] then&lt;br /&gt;
    return mw.ustring.lower(head), ROMAN[tail]&lt;br /&gt;
  end&lt;br /&gt;
  if name:sub(-5) == &amp;#039; Plus&amp;#039; then&lt;br /&gt;
    return mw.ustring.lower(name:sub(1, -6)), 2&lt;br /&gt;
  end&lt;br /&gt;
  return mw.ustring.lower(name), 0&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local SORT_KEYS = {&lt;br /&gt;
  Weapons = function(r) return {tonumber(r.tier) or 9, mw.ustring.lower(r.name or &amp;#039;&amp;#039;)} end,&lt;br /&gt;
  Characters = function(r) return {mw.ustring.lower(r.name or &amp;#039;&amp;#039;)} end,&lt;br /&gt;
  Blessings = function(r) return {tonumber(r.tier) or 9, mw.ustring.lower(r.name or &amp;#039;&amp;#039;)} end,&lt;br /&gt;
  Upgrades = function(r) return {tonumber(r.tier) or 9, mw.ustring.lower(r.name or &amp;#039;&amp;#039;)} end,&lt;br /&gt;
  Passives = function(r)&lt;br /&gt;
    local fam, rank = familyKey(r.name or &amp;#039;&amp;#039;)&lt;br /&gt;
    return {fam, rank, r.name or &amp;#039;&amp;#039;}&lt;br /&gt;
  end,&lt;br /&gt;
  Crux = function(r) return {CRUX_TYPE_ORDER[r.type] or 9, mw.ustring.lower(r.name or &amp;#039;&amp;#039;)} end,&lt;br /&gt;
  Enemies = function(r) return {mw.ustring.lower(r.name or &amp;#039;&amp;#039;)} end,&lt;br /&gt;
  Achievements = function(r) return {mw.ustring.lower(r.name or &amp;#039;&amp;#039;)} end,&lt;br /&gt;
  Codex = function(r) return {CODEX_TYPE_ORDER[r.type] or 9, mw.ustring.lower(r.name or &amp;#039;&amp;#039;)} end,&lt;br /&gt;
  Tags = function(r) return {mw.ustring.lower(r.name or &amp;#039;&amp;#039;)} end,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
local function keyLess(a, b)&lt;br /&gt;
  for i = 1, math.max(#a, #b) do&lt;br /&gt;
    local x, y = a[i], b[i]&lt;br /&gt;
    if x == nil then return true end&lt;br /&gt;
    if y == nil then return false end&lt;br /&gt;
    if x ~= y then&lt;br /&gt;
      if type(x) == &amp;#039;number&amp;#039; and type(y) == &amp;#039;number&amp;#039; then return x &amp;lt; y end&lt;br /&gt;
      return tostring(x) &amp;lt; tostring(y)&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
  return false&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Stable per-category sort of the records list (returns a new list).&lt;br /&gt;
function p.sorted(cat)&lt;br /&gt;
  local keyfn = SORT_KEYS[cat] or function(r) return {mw.ustring.lower(r.name or &amp;#039;&amp;#039;)} end&lt;br /&gt;
  local list = {}&lt;br /&gt;
  for i, r in ipairs(p.load(cat)) do list[#list + 1] = {i = i, r = r, k = keyfn(r)} end&lt;br /&gt;
  table.sort(list, function(a, b)&lt;br /&gt;
    if keyLess(a.k, b.k) then return true end&lt;br /&gt;
    if keyLess(b.k, a.k) then return false end&lt;br /&gt;
    return a.i &amp;lt; b.i&lt;br /&gt;
  end)&lt;br /&gt;
  local out = {}&lt;br /&gt;
  for _, e in ipairs(list) do out[#out + 1] = e.r end&lt;br /&gt;
  return out&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- ===================================================================&lt;br /&gt;
-- index page config + entry points shared by the per-category shims&lt;br /&gt;
-- ===================================================================&lt;br /&gt;
local INDEX_OPTS = {&lt;br /&gt;
  Weapons = {columns = {{name = &amp;#039;Thumbnail&amp;#039;, source = &amp;#039;thumbnail&amp;#039;}, {name = &amp;#039;Name&amp;#039;, source = &amp;#039;link&amp;#039;}, {name = &amp;#039;Tier&amp;#039;, source = &amp;#039;Tier&amp;#039;}, {name = &amp;#039;Price&amp;#039;, source = &amp;#039;Price&amp;#039;}, {name = &amp;#039;Damage&amp;#039;, source = &amp;#039;Damage&amp;#039;}, {name = &amp;#039;Attack Speed&amp;#039;, source = &amp;#039;Attack Speed&amp;#039;}}, thumbnail_size = 48},&lt;br /&gt;
  Characters = {columns = {{name = &amp;#039;Thumbnail&amp;#039;, source = &amp;#039;thumbnail&amp;#039;}, {name = &amp;#039;Name&amp;#039;, source = &amp;#039;link&amp;#039;}, {name = &amp;#039;Modifiers&amp;#039;, source = &amp;#039;Modifiers&amp;#039;}, {name = &amp;#039;Health Points&amp;#039;, source = &amp;#039;Health Points&amp;#039;}}, thumbnail_size = 64},&lt;br /&gt;
  Blessings = {columns = {{name = &amp;#039;Thumbnail&amp;#039;, source = &amp;#039;thumbnail&amp;#039;}, {name = &amp;#039;Name&amp;#039;, source = &amp;#039;link&amp;#039;}, {name = &amp;#039;Tier&amp;#039;, source = &amp;#039;Tier&amp;#039;}, {name = &amp;#039;Price&amp;#039;, source = &amp;#039;Price&amp;#039;}, {name = &amp;#039;Effects&amp;#039;, source = &amp;#039;Effects&amp;#039;}}, thumbnail_size = 48},&lt;br /&gt;
  Upgrades = {columns = {{name = &amp;#039;Thumbnail&amp;#039;, source = &amp;#039;thumbnail&amp;#039;}, {name = &amp;#039;Name&amp;#039;, source = &amp;#039;link&amp;#039;}, {name = &amp;#039;Tier&amp;#039;, source = &amp;#039;Tier&amp;#039;}, {name = &amp;#039;Price&amp;#039;, source = &amp;#039;Price&amp;#039;}, {name = &amp;#039;Effects&amp;#039;, source = &amp;#039;Effects&amp;#039;}}, thumbnail_size = 48},&lt;br /&gt;
  Passives = {columns = {{name = &amp;#039;Thumbnail&amp;#039;, source = &amp;#039;thumbnail&amp;#039;}, {name = &amp;#039;Name&amp;#039;, source = &amp;#039;link&amp;#039;}, {name = &amp;#039;Tier&amp;#039;, source = &amp;#039;Tier&amp;#039;}, {name = &amp;#039;Price&amp;#039;, source = &amp;#039;Price&amp;#039;}, {name = &amp;#039;Effects&amp;#039;, source = &amp;#039;Effects&amp;#039;}}, thumbnail_size = 48},&lt;br /&gt;
  Crux = {columns = {{name = &amp;#039;Thumbnail&amp;#039;, source = &amp;#039;thumbnail&amp;#039;}, {name = &amp;#039;Name&amp;#039;, source = &amp;#039;link&amp;#039;}, {name = &amp;#039;Type&amp;#039;, source = &amp;#039;Type&amp;#039;}, {name = &amp;#039;Effects&amp;#039;, source = &amp;#039;Effects&amp;#039;}}, thumbnail_size = 48},&lt;br /&gt;
  Enemies = {columns = {{name = &amp;#039;Thumbnail&amp;#039;, source = &amp;#039;thumbnail&amp;#039;}, {name = &amp;#039;Name&amp;#039;, source = &amp;#039;link&amp;#039;}, {name = &amp;#039;Health&amp;#039;, source = &amp;#039;Health&amp;#039;}, {name = &amp;#039;HP/Wave&amp;#039;, source = &amp;#039;HP/Wave&amp;#039;}, {name = &amp;#039;Damage&amp;#039;, source = &amp;#039;Damage&amp;#039;}, {name = &amp;#039;Dmg/Wave&amp;#039;, source = &amp;#039;Dmg/Wave&amp;#039;}, {name = &amp;#039;Speed&amp;#039;, source = &amp;#039;Speed&amp;#039;}, {name = &amp;#039;Resources&amp;#039;, source = &amp;#039;Resources&amp;#039;}}, thumbnail_size = 48},&lt;br /&gt;
  Achievements = {columns = {{name = &amp;#039;Thumbnail&amp;#039;, source = &amp;#039;thumbnail&amp;#039;}, {name = &amp;#039;Name&amp;#039;, source = &amp;#039;link&amp;#039;}, {name = &amp;#039;Objective&amp;#039;, source = &amp;#039;Objective&amp;#039;}}, thumbnail_size = 48},&lt;br /&gt;
  Codex = {columns = {{name = &amp;#039;Thumbnail&amp;#039;, source = &amp;#039;thumbnail&amp;#039;}, {name = &amp;#039;Name&amp;#039;, source = &amp;#039;link&amp;#039;}, {name = &amp;#039;Type&amp;#039;, source = &amp;#039;Type&amp;#039;}, {name = &amp;#039;Summary&amp;#039;, source = &amp;#039;Summary&amp;#039;}}, thumbnail_size = 48},&lt;br /&gt;
  Tags = {columns = {{name = &amp;#039;Tag&amp;#039;, source = &amp;#039;link&amp;#039;}, {name = &amp;#039;Effect&amp;#039;, source = &amp;#039;Effect&amp;#039;}, {name = &amp;#039;Used by&amp;#039;, source = &amp;#039;Used by&amp;#039;}}, thumbnail_size = 16},&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
-- Visible infobox fields per category — MUST match the rows declared in&lt;br /&gt;
-- Template:&amp;lt;Cat&amp;gt;_infobox.&lt;br /&gt;
local INFOBOX_FIELD_ORDER = {&lt;br /&gt;
  Weapons = {&amp;#039;Tier&amp;#039;, &amp;#039;Price&amp;#039;, &amp;#039;Availability&amp;#039;, &amp;#039;Stats&amp;#039;, &amp;#039;Class&amp;#039;},&lt;br /&gt;
  Characters = {&amp;#039;Availability&amp;#039;, &amp;#039;Stats&amp;#039;},&lt;br /&gt;
  Blessings = {&amp;#039;Tier&amp;#039;, &amp;#039;Price&amp;#039;, &amp;#039;Availability&amp;#039;, &amp;#039;Stats&amp;#039;},&lt;br /&gt;
  Upgrades = {&amp;#039;Tier&amp;#039;, &amp;#039;Price&amp;#039;, &amp;#039;Availability&amp;#039;, &amp;#039;Stats&amp;#039;},&lt;br /&gt;
  Passives = {&amp;#039;Tier&amp;#039;, &amp;#039;Price&amp;#039;, &amp;#039;Stats&amp;#039;},&lt;br /&gt;
  Crux = {&amp;#039;Type&amp;#039;, &amp;#039;Availability&amp;#039;, &amp;#039;Stats&amp;#039;},&lt;br /&gt;
  Enemies = {&amp;#039;Classification&amp;#039;, &amp;#039;Stats&amp;#039;},&lt;br /&gt;
  Achievements = {},&lt;br /&gt;
  Codex = {&amp;#039;Type&amp;#039;},&lt;br /&gt;
  Tags = {&amp;#039;Effect&amp;#039;, &amp;#039;Used by&amp;#039;},&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
-- Record (shallow copy) augmented with the computed infobox dict, so the&lt;br /&gt;
-- pure Module:Index renderer keeps working unchanged.&lt;br /&gt;
function p.augmented(cat, rec)&lt;br /&gt;
  local out = {}&lt;br /&gt;
  for k, v in pairs(rec) do out[k] = v end&lt;br /&gt;
  out.infobox = p.computedInfobox(cat, rec)&lt;br /&gt;
  return out&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function resolveRec(cat, frame)&lt;br /&gt;
  local id = frame and frame.args and (frame.args.id or frame.args[1])&lt;br /&gt;
  if id then id = (tostring(id):gsub(&amp;#039;^%s+&amp;#039;, &amp;#039;&amp;#039;):gsub(&amp;#039;%s+$&amp;#039;, &amp;#039;&amp;#039;)) end&lt;br /&gt;
  if not id or id == &amp;#039;&amp;#039; then return nil, &amp;#039;&amp;#039; end&lt;br /&gt;
  local rec = p.byId(cat)[id]&lt;br /&gt;
  if not rec then&lt;br /&gt;
    return nil, mw.getCurrentFrame():preprocess(&lt;br /&gt;
      &amp;#039;&amp;lt;i&amp;gt;Unknown &amp;#039; .. cat .. &amp;#039; record: &amp;#039; .. mw.text.nowiki(id) .. &amp;#039;&amp;lt;/i&amp;gt;&amp;#039;)&lt;br /&gt;
  end&lt;br /&gt;
  return rec, nil&lt;br /&gt;
end&lt;br /&gt;
p.resolveRec = resolveRec&lt;br /&gt;
&lt;br /&gt;
local function asParam(v)&lt;br /&gt;
  if v == nil then return &amp;#039;&amp;#039; end&lt;br /&gt;
  return tostring(v)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function renderInfobox(cat, rec)&lt;br /&gt;
  local ib = p.computedInfobox(cat, rec)&lt;br /&gt;
  local out = {&amp;#039;{{&amp;#039; .. cat .. &amp;#039;_infobox&amp;#039;}&lt;br /&gt;
  out[#out + 1] = &amp;#039;| name = &amp;#039; .. asParam(rec.name)&lt;br /&gt;
  out[#out + 1] = &amp;#039;| id   = &amp;#039; .. asParam(rec.id)&lt;br /&gt;
  out[#out + 1] = &amp;#039;| icon = &amp;#039; .. asParam(rec.icon)&lt;br /&gt;
  for _, field in ipairs(INFOBOX_FIELD_ORDER[cat] or {}) do&lt;br /&gt;
    out[#out + 1] = &amp;#039;| &amp;#039; .. field .. &amp;#039; = &amp;#039; .. asParam(ib[field])&lt;br /&gt;
  end&lt;br /&gt;
  out[#out + 1] = &amp;#039;}}&amp;#039;&lt;br /&gt;
  return table.concat(out, &amp;#039;\n&amp;#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function renderSectionBody(content)&lt;br /&gt;
  if content == nil or content == &amp;#039;&amp;#039; then return &amp;#039;&amp;#039; end&lt;br /&gt;
  if type(content) == &amp;#039;table&amp;#039; then&lt;br /&gt;
    if #content == 0 then return &amp;#039;&amp;#039; end&lt;br /&gt;
    local lines = {}&lt;br /&gt;
    for _, line in ipairs(content) do lines[#lines + 1] = &amp;#039;* &amp;#039; .. tostring(line) end&lt;br /&gt;
    return table.concat(lines, &amp;#039;\n&amp;#039;)&lt;br /&gt;
  end&lt;br /&gt;
  return tostring(content)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- ----- entry points used by the per-category shim modules -------------&lt;br /&gt;
&lt;br /&gt;
function p.infoboxEntry(cat, frame)&lt;br /&gt;
  local rec, missing = resolveRec(cat, frame)&lt;br /&gt;
  if missing then return missing end&lt;br /&gt;
  if not rec then return &amp;#039;&amp;#039; end&lt;br /&gt;
  return mw.getCurrentFrame():preprocess(renderInfobox(cat, rec))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.bodyEntry(cat, frame)&lt;br /&gt;
  local rec, missing = resolveRec(cat, frame)&lt;br /&gt;
  if missing then return missing end&lt;br /&gt;
  if not rec then return &amp;#039;&amp;#039; end&lt;br /&gt;
  local section = frame and frame.args and frame.args.section&lt;br /&gt;
  if section and section ~= &amp;#039;&amp;#039; then&lt;br /&gt;
    return mw.getCurrentFrame():preprocess(&lt;br /&gt;
      renderSectionBody(p.bodySection(cat, rec, section)))&lt;br /&gt;
  end&lt;br /&gt;
  local out = {}&lt;br /&gt;
  for _, sec in ipairs(BODY_ORDER[cat] or {}) do&lt;br /&gt;
    local body = renderSectionBody(p.bodySection(cat, rec, sec))&lt;br /&gt;
    if body ~= &amp;#039;&amp;#039; then&lt;br /&gt;
      out[#out + 1] = &amp;#039;&amp;#039;&lt;br /&gt;
      out[#out + 1] = &amp;#039;== &amp;#039; .. sec .. &amp;#039; ==&amp;#039;&lt;br /&gt;
      out[#out + 1] = body&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
  return mw.getCurrentFrame():preprocess(table.concat(out, &amp;#039;\n&amp;#039;))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.indexEntry(cat, frame)&lt;br /&gt;
  local Index = require(&amp;#039;Module:Index&amp;#039;)&lt;br /&gt;
  local recs = {}&lt;br /&gt;
  for _, r in ipairs(p.sorted(cat)) do&lt;br /&gt;
    recs[#recs + 1] = p.augmented(cat, r)&lt;br /&gt;
  end&lt;br /&gt;
  return Index.render(recs, INDEX_OPTS[cat] or {})&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.renderEntry(cat, frame)&lt;br /&gt;
  local rec, missing = resolveRec(cat, frame)&lt;br /&gt;
  if missing then return missing end&lt;br /&gt;
  if not rec then return &amp;#039;&amp;#039; end&lt;br /&gt;
  local CrossRef = require(&amp;#039;Module:CrossRef&amp;#039;)&lt;br /&gt;
  local parts = {&lt;br /&gt;
    renderInfobox(cat, rec),&lt;br /&gt;
    p.bodyEntry(cat, frame),&lt;br /&gt;
    CrossRef.compute(cat, rec),&lt;br /&gt;
  }&lt;br /&gt;
  return mw.getCurrentFrame():preprocess(table.concat(parts, &amp;#039;\n&amp;#039;))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Ta1ha</name></author>
	</entry>
</feed>