<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://cardbot.wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Cabalex</id>
	<title>cardbot.wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://cardbot.wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Cabalex"/>
	<link rel="alternate" type="text/html" href="https://cardbot.wiki/wiki/Special:Contributions/Cabalex"/>
	<updated>2026-04-17T10:24:42Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.45.3</generator>
	<entry>
		<id>https://cardbot.wiki/index.php?title=MediaWiki:Common.css&amp;diff=191</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=MediaWiki:Common.css&amp;diff=191"/>
		<updated>2026-04-15T19:55:40Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* CSS placed here will be applied to all skins */&lt;br /&gt;
.image-buttons, .image-buttons ul {&lt;br /&gt;
	display: flex;&lt;br /&gt;
	align-items: stretch;&lt;br /&gt;
	justify-content: space-evenly;&lt;br /&gt;
	gap: 1rem;&lt;br /&gt;
	list-style: none;&lt;br /&gt;
}&lt;br /&gt;
.image-buttons ul li {&lt;br /&gt;
	width: 100%;&lt;br /&gt;
	flex-shrink: 1;&lt;br /&gt;
	flex-grow: 1;&lt;br /&gt;
}&lt;br /&gt;
.image-button-container {&lt;br /&gt;
	display: flex;&lt;br /&gt;
	border: 1px solid #aaa;&lt;br /&gt;
	width: 100%;&lt;br /&gt;
	height: 100%;&lt;br /&gt;
}&lt;br /&gt;
.image-button-container img {&lt;br /&gt;
	width: 100%;&lt;br /&gt;
	height: 100%;&lt;br /&gt;
	object-fit: contain;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=MediaWiki:Common.css&amp;diff=190</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=MediaWiki:Common.css&amp;diff=190"/>
		<updated>2026-04-15T19:53:59Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* CSS placed here will be applied to all skins */&lt;br /&gt;
.image-buttons, .image-buttons ul {&lt;br /&gt;
	display: flex;&lt;br /&gt;
	align-items: stretch;&lt;br /&gt;
	justify-content: space-evenly;&lt;br /&gt;
	gap: 1rem;&lt;br /&gt;
	list-style: none;&lt;br /&gt;
}&lt;br /&gt;
.image-button-container {&lt;br /&gt;
	display: flex;&lt;br /&gt;
	border: 1px solid #aaa;&lt;br /&gt;
	width: 100%;&lt;br /&gt;
	height: 100%;&lt;br /&gt;
}&lt;br /&gt;
.image-button-container img {&lt;br /&gt;
	width: 100%;&lt;br /&gt;
	height: 100%;&lt;br /&gt;
	object-fit: contain;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=MediaWiki:Common.css&amp;diff=189</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=MediaWiki:Common.css&amp;diff=189"/>
		<updated>2026-04-15T19:52:46Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* CSS placed here will be applied to all skins */&lt;br /&gt;
.image-buttons, .image-buttons ul {&lt;br /&gt;
	display: flex;&lt;br /&gt;
	align-items: stretch;&lt;br /&gt;
	justify-content: space-evenly;&lt;br /&gt;
	gap: 1rem;&lt;br /&gt;
}&lt;br /&gt;
.image-button-container {&lt;br /&gt;
	display: flex;&lt;br /&gt;
	border: 1px solid #aaa;&lt;br /&gt;
}&lt;br /&gt;
.image-button-container img {&lt;br /&gt;
	width: 100%;&lt;br /&gt;
	height: 100%;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=Template:Image_button&amp;diff=188</id>
		<title>Template:Image button</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=Template:Image_button&amp;diff=188"/>
		<updated>2026-04-15T19:49:18Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;image-button-container {{#if:{{{label|}}}|has-text}}&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;!-- Main image with link --&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;image {{{image-hover|hide-on-hover}}}&amp;quot;&amp;gt;[[File:{{{image}}}|{{{size|330px}}}|link={{{link|}}}|class={{{imageClass|}}} ]]&amp;lt;/div&amp;gt;&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
    Hover image with same link (positioned absolutely)&lt;br /&gt;
    --&amp;gt;{{#if:{{{image-hover|}}}|&amp;lt;div class=&amp;quot;hover-image&amp;quot;&amp;gt;[[File:{{{image-hover}}}|{{{size|330px}}}|link={{{link}}}|class={{{imageClass|}}}]]&amp;lt;/div&amp;gt;}}&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
    --&amp;gt;&amp;lt;div class=&amp;quot;image-button--gloss&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
    --&amp;gt;{{#if:{{{label|}}}|&amp;lt;div class=&amp;quot;image-button--text&amp;quot;&amp;gt;[[{{{link}}}|{{{label}}}]]&amp;lt;/div&amp;gt;}}&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
--&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/includeonly&amp;gt;&amp;lt;!--&lt;br /&gt;
Link text below (if needed)&lt;br /&gt;
--&amp;gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{doc}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=Template:Image_button&amp;diff=187</id>
		<title>Template:Image button</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=Template:Image_button&amp;diff=187"/>
		<updated>2026-04-15T19:47:58Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;image-button-container {{#if:{{{label|}}}|has-text}}&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;!-- Main image with link --&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;image {{{image-hover|hide-on-hover}}}&amp;quot;&amp;gt;[[File:{{{image}}}|{{{size|330px}}}|link={{link}}|class={{{imageClass|}}} ]]&amp;lt;/div&amp;gt;&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
    Hover image with same link (positioned absolutely)&lt;br /&gt;
    --&amp;gt;{{#if:{{{image-hover|}}}|&amp;lt;div class=&amp;quot;hover-image&amp;quot;&amp;gt;[[File:{{{image-hover}}}|{{{size|330px}}}|link={{{link}}}|class={{{imageClass|}}}]]&amp;lt;/div&amp;gt;}}&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
    --&amp;gt;&amp;lt;div class=&amp;quot;image-button--gloss&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
    --&amp;gt;{{#if:{{{label|}}}|&amp;lt;div class=&amp;quot;image-button--text&amp;quot;&amp;gt;[[{{{link}}}|{{{label}}}]]&amp;lt;/div&amp;gt;}}&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
--&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/includeonly&amp;gt;&amp;lt;!--&lt;br /&gt;
Link text below (if needed)&lt;br /&gt;
--&amp;gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{doc}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=Template:Image_button&amp;diff=186</id>
		<title>Template:Image button</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=Template:Image_button&amp;diff=186"/>
		<updated>2026-04-15T19:45:57Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;image-button-container {{#if:{{#var:label}}|has-text}}&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;!-- Main image with link --&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;image {{{image-hover|hide-on-hover}}}&amp;quot;&amp;gt;[[File:{{{image}}}|{{{size|330px}}}|link={{link}}|class={{{imageClass|}}} ]]&amp;lt;/div&amp;gt;&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
    Hover image with same link (positioned absolutely)&lt;br /&gt;
    --&amp;gt;{{#if:{{{image-hover|}}}|&amp;lt;div class=&amp;quot;hover-image&amp;quot;&amp;gt;[[File:{{{image-hover}}}|{{{size|330px}}}|link={{{link}}}|class={{{imageClass|}}}]]&amp;lt;/div&amp;gt;}}&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
    --&amp;gt;&amp;lt;div class=&amp;quot;image-button--gloss&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
    --&amp;gt;{{#if:{{{label}}}|&amp;lt;div class=&amp;quot;image-button--text&amp;quot;&amp;gt;[[{{{link}}}|{{{label}}}]]&amp;lt;/div&amp;gt;}}&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
--&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/includeonly&amp;gt;&amp;lt;!--&lt;br /&gt;
Link text below (if needed)&lt;br /&gt;
--&amp;gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{doc}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=Template:MainPage&amp;diff=185</id>
		<title>Template:MainPage</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=Template:MainPage&amp;diff=185"/>
		<updated>2026-04-15T19:39:26Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&amp;quot;image-buttons&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;{{Image button|link=Metal Cardbot (season)|image=Metal Cardbot logo.png}}&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;{{Image button|link=Metal Cardbot S|image=Metal Cardbot S logo.png}}&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;{{Image button|link=Metal Cardbot W|image=Metal Cardbot W logo.png}}&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Metal Cardbot&#039;&#039;&#039; is a 2023 Korean animated mecha series created by [[SAMG Entertainment]], directed by [[OSROCTION]] and animated by [[NAVY Co, Ltd.]]. A boy named [[Jun]] discovers the [[Metal Breath]], a mysterious device that allows him to capture and command a species of transforming robots known as [[Metal Cardbots]], who take refuge on [[Earth]] after their home planet [[Machina]] was destroyed.&lt;br /&gt;
&lt;br /&gt;
Metal Cardbot currently has three main seasons ([[Metal Cardbot (series)|Metal Cardbot]], [[Metal Cardbot S]], [[Metal Cardbot W]]) and two Chinese spinoff seasons ([[Metal Cardbot: Beast Energy]], [[Metal Cardbot: Zerg Crisis]]). The first season has been dubbed in a variety of languages, including [[English localization|English]], [[Chinese localization|Chinese]], [[Russian localization|Russian]], [[Indonesian localization|Indonesian]], and [[Spanish localization|Spanish]]).&lt;br /&gt;
&lt;br /&gt;
== Contributions ==&lt;br /&gt;
As this wiki is currently under construction, and we want to ensure cardbot.wiki remains a reliable source of Metal Cardbot info, this wiki isn&#039;t open for direct contributions at this time. However, we&#039;re always open to suggestions and corrections! If you have something to add, [https://forms.gle/cAYv3CQWy4yfakws7 please use this form].&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=Template:Image_button&amp;diff=184</id>
		<title>Template:Image button</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=Template:Image_button&amp;diff=184"/>
		<updated>2026-04-15T19:35:59Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&amp;lt;!--&lt;br /&gt;
Variables&lt;br /&gt;
--&amp;gt;{{#vardefine:link|{{{link|}}}}}&amp;lt;!--&lt;br /&gt;
--&amp;gt;{{#vardefine:label|{{{label|}}}}}&amp;lt;!--&lt;br /&gt;
Single container div for positioning&lt;br /&gt;
--&amp;gt;&amp;lt;div class=&amp;quot;image-button-container {{#if:{{#var:label}}|has-text}}&amp;quot;&amp;gt;&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
    Main image with link&lt;br /&gt;
    --&amp;gt;&amp;lt;div class=&amp;quot;image {{#if:{{{image-hover|}}}|hide-on-hover}}&amp;quot;&amp;gt;{{#if:{{{image|}}}|[[File:{{#replace:{{{image|}}}|File:}}|{{{size|330px}}}|link={{#var:link}}|class={{{imageClass|}}} ]]}}&amp;lt;/div&amp;gt;&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
    Hover image with same link (positioned absolutely)&lt;br /&gt;
    --&amp;gt;{{#if:{{{image-hover|}}}|&amp;lt;div class=&amp;quot;hover-image&amp;quot;&amp;gt;[[File:{{#replace:{{{image-hover|}}}|File:}}|{{{size|330px}}}|link={{#var:link}}|class={{{imageClass|}}}]]&amp;lt;/div&amp;gt;}}&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
    --&amp;gt;&amp;lt;div class=&amp;quot;image-button--gloss&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
    --&amp;gt;{{#if:{{#var:label}}|&amp;lt;div class=&amp;quot;image-button--text&amp;quot;&amp;gt;[[{{#var:link}}|{{#var:label}}]]&amp;lt;/div&amp;gt;}}&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
--&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/includeonly&amp;gt;&amp;lt;!--&lt;br /&gt;
Link text below (if needed)&lt;br /&gt;
--&amp;gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{doc}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=Template:MainPage&amp;diff=183</id>
		<title>Template:MainPage</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=Template:MainPage&amp;diff=183"/>
		<updated>2026-04-15T19:34:48Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&amp;quot;portal-buttons&amp;quot;&amp;gt;{{Template:Image button|Metal Cardbot (season)|image=File:Metal Cardbot logo}}{{Template:Image button|Metal Cardbot S|image=File:Metal Cardbot S logo}}{{Template:Image button|Metal Cardbot W|image=File:Metal Cardbot W logo}}&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Metal Cardbot&#039;&#039;&#039; is a 2023 Korean animated mecha series created by [[SAMG Entertainment]], directed by [[OSROCTION]] and animated by [[NAVY Co, Ltd.]]. A boy named [[Jun]] discovers the [[Metal Breath]], a mysterious device that allows him to capture and command a species of transforming robots known as [[Metal Cardbots]], who take refuge on [[Earth]] after their home planet [[Machina]] was destroyed.&lt;br /&gt;
&lt;br /&gt;
Metal Cardbot currently has three main seasons ([[Metal Cardbot (series)|Metal Cardbot]], [[Metal Cardbot S]], [[Metal Cardbot W]]) and two Chinese spinoff seasons ([[Metal Cardbot: Beast Energy]], [[Metal Cardbot: Zerg Crisis]]). The first season has been dubbed in a variety of languages, including [[English localization|English]], [[Chinese localization|Chinese]], [[Russian localization|Russian]], [[Indonesian localization|Indonesian]], and [[Spanish localization|Spanish]]).&lt;br /&gt;
&lt;br /&gt;
== Contributions ==&lt;br /&gt;
As this wiki is currently under construction, and we want to ensure cardbot.wiki remains a reliable source of Metal Cardbot info, this wiki isn&#039;t open for direct contributions at this time. However, we&#039;re always open to suggestions and corrections! If you have something to add, [https://forms.gle/cAYv3CQWy4yfakws7 please use this form].&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=Template:Image_button&amp;diff=182</id>
		<title>Template:Image button</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=Template:Image_button&amp;diff=182"/>
		<updated>2026-04-15T19:32:47Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: Created page with &amp;quot;This creates one of the stylized and formatted buttons on the main page.  == Usage == Groups of this template should be wrapped inside of &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;div class=&amp;quot;image-buttons&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; and each entry should be a separate line in an unordered list. This div can be given one of the classes &amp;lt;code&amp;gt;columns-x&amp;lt;/code&amp;gt; where x is a number from 1 to 9, and the links will line up in that many columns if...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This creates one of the stylized and formatted buttons on the [[{{MediaWiki:Mainpage}}|main page]].&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
Groups of this template should be wrapped inside of &amp;lt;code&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;div class=&amp;quot;image-buttons&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/nowiki&amp;gt;&amp;lt;/code&amp;gt; and each entry should be a separate line in an [[wikipedia:Help:Lists#Basically|unordered list]]. This div can be given one of the classes &amp;lt;code&amp;gt;columns-x&amp;lt;/code&amp;gt; where x is a number from 1 to 9, and the links will line up in that many columns if space permits (default is 3). See [[Template:Image_button/styles.css]] for the full definitions of these classes and styling for this template.&lt;br /&gt;
&lt;br /&gt;
===Parameters===&lt;br /&gt;
&amp;lt;templatedata&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;description&amp;quot;: {&lt;br /&gt;
		&amp;quot;en&amp;quot;: &amp;quot;Creates stylized and formatted buttons.&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
	&amp;quot;format&amp;quot;: &amp;quot;inline&amp;quot;,&lt;br /&gt;
	&amp;quot;params&amp;quot;: {&lt;br /&gt;
		&amp;quot;link&amp;quot;: {&lt;br /&gt;
			&amp;quot;label&amp;quot;: {&lt;br /&gt;
				&amp;quot;en&amp;quot;: &amp;quot;Link&amp;quot;&lt;br /&gt;
			},&lt;br /&gt;
			&amp;quot;description&amp;quot;: {&lt;br /&gt;
				&amp;quot;en&amp;quot;: &amp;quot;The target page for the link.&amp;quot;&lt;br /&gt;
			},&lt;br /&gt;
			&amp;quot;required&amp;quot;: true,&lt;br /&gt;
			&amp;quot;example&amp;quot;: &amp;quot;Main Page&amp;quot;,&lt;br /&gt;
			&amp;quot;type&amp;quot;: &amp;quot;wiki-page-name&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
        &amp;quot;label&amp;quot;: {&lt;br /&gt;
            &amp;quot;label&amp;quot;: {&lt;br /&gt;
                &amp;quot;en&amp;quot;: &amp;quot;Label&amp;quot;&lt;br /&gt;
            },&lt;br /&gt;
            &amp;quot;description&amp;quot;: {&lt;br /&gt;
                &amp;quot;en&amp;quot;: &amp;quot;Text to display as image label.&amp;quot;&lt;br /&gt;
            },&lt;br /&gt;
            &amp;quot;required&amp;quot;: false,&lt;br /&gt;
            &amp;quot;suggested&amp;quot;: true,&lt;br /&gt;
            &amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
		&amp;quot;image&amp;quot;: {&lt;br /&gt;
			&amp;quot;label&amp;quot;: {&lt;br /&gt;
				&amp;quot;en&amp;quot;: &amp;quot;Image&amp;quot;&lt;br /&gt;
			},&lt;br /&gt;
			&amp;quot;description&amp;quot;: {&lt;br /&gt;
				&amp;quot;en&amp;quot;: &amp;quot;Button image to display.&amp;quot;&lt;br /&gt;
			},&lt;br /&gt;
			&amp;quot;required&amp;quot;: true,&lt;br /&gt;
			&amp;quot;suggested&amp;quot;: true,&lt;br /&gt;
			&amp;quot;type&amp;quot;: &amp;quot;wiki-file-name&amp;quot;&lt;br /&gt;
        },&lt;br /&gt;
        &amp;quot;image-hover&amp;quot;: {&lt;br /&gt;
			&amp;quot;label&amp;quot;: {&lt;br /&gt;
				&amp;quot;en&amp;quot;: &amp;quot;Image on Hover&amp;quot;&lt;br /&gt;
			},&lt;br /&gt;
			&amp;quot;description&amp;quot;: {&lt;br /&gt;
				&amp;quot;en&amp;quot;: &amp;quot;Button image to display when hovered.&amp;quot;&lt;br /&gt;
			},&lt;br /&gt;
			&amp;quot;required&amp;quot;: false,&lt;br /&gt;
			&amp;quot;suggested&amp;quot;: true,&lt;br /&gt;
			&amp;quot;type&amp;quot;: &amp;quot;wiki-file-name&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
		&amp;quot;size&amp;quot;: {&lt;br /&gt;
			&amp;quot;label&amp;quot;: {&lt;br /&gt;
				&amp;quot;en&amp;quot;: &amp;quot;Image size&amp;quot;&lt;br /&gt;
			},&lt;br /&gt;
			&amp;quot;description&amp;quot;: {&lt;br /&gt;
				&amp;quot;en&amp;quot;: &amp;quot;The size of the image, in px.&amp;quot;&lt;br /&gt;
			},&lt;br /&gt;
			&amp;quot;required&amp;quot;: false,&lt;br /&gt;
			&amp;quot;default&amp;quot;: &amp;quot;576px&amp;quot;,&lt;br /&gt;
			&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
		&amp;quot;imageClass&amp;quot;: {&lt;br /&gt;
			&amp;quot;label&amp;quot;: &amp;quot;Image class&amp;quot;,&lt;br /&gt;
			&amp;quot;description&amp;quot;: &amp;quot;A class to give directly to the image&amp;quot;,&lt;br /&gt;
			&amp;quot;example&amp;quot;: &amp;quot;invert-on-dark&amp;quot;,&lt;br /&gt;
			&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;,&lt;br /&gt;
			&amp;quot;suggestedvalues&amp;quot;: [&lt;br /&gt;
				&amp;quot;invert-on-dark&amp;quot;,&lt;br /&gt;
				&amp;quot;invert-on-light&amp;quot;&lt;br /&gt;
			]&lt;br /&gt;
		}&lt;br /&gt;
	},&lt;br /&gt;
	&amp;quot;paramOrder&amp;quot;: [&lt;br /&gt;
		&amp;quot;link&amp;quot;,&lt;br /&gt;
        &amp;quot;label&amp;quot;,&lt;br /&gt;
		&amp;quot;image&amp;quot;,&lt;br /&gt;
        &amp;quot;image-hover&amp;quot;,&lt;br /&gt;
		&amp;quot;size&amp;quot;,&lt;br /&gt;
		&amp;quot;imageClass&amp;quot;&lt;br /&gt;
	]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/templatedata&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;noinclude&amp;gt;&lt;br /&gt;
[[Category:Template documentation]]&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=Template:Clickable_button&amp;diff=181</id>
		<title>Template:Clickable button</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=Template:Clickable_button&amp;diff=181"/>
		<updated>2026-04-15T19:27:23Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;onlyinclude&amp;gt;{{#if:{{{3|{{{external|}}}}}}&lt;br /&gt;
  | &amp;lt;span class=&amp;quot;plainlinks&amp;quot; {{#if:{{{id|}}}|id=&amp;quot;{{{id}}}&amp;quot;}}&amp;gt;[{{{1|{{{target|//parameter_target_is_empty.de}}}}}} &amp;lt;span class=&amp;quot;submit ui-button ui-widget ui-state-default ui-corner-all {{Clickable button/iconclass&lt;br /&gt;
    |{{{4|{{{iconPrimary|}}}}}}&lt;br /&gt;
    |{{{5|{{{iconSecondary|}}}}}}&lt;br /&gt;
    |{{{2|{{{text|&amp;lt;noinclude&amp;gt;x&amp;lt;/noinclude&amp;gt;}}}}}}&lt;br /&gt;
  }} {{{class|}}}&amp;quot; role=&amp;quot;button&amp;quot; aria-disabled=&amp;quot;false&amp;quot;&amp;gt;&amp;lt;!-- // --&amp;gt;{{#if:{{{4|{{{iconPrimary|}}}}}}&lt;br /&gt;
  |&amp;lt;span class=&amp;quot;ui-button-icon-primary ui-icon {{{4|{{{iconPrimary}}}}}}&amp;quot;&amp;gt;&amp;amp;nbsp;&amp;lt;/span&amp;gt;&lt;br /&gt;
  }}&amp;lt;span class=&amp;quot;ui-button-text&amp;quot;&amp;gt;{{{2|{{{text|Parameter &#039;&#039;&#039;text&#039;&#039;&#039; is empty}}}}}}&amp;lt;/span&amp;gt;{{#if:{{{5|{{{iconSecondary|}}}}}}&lt;br /&gt;
  |&amp;lt;span class=&amp;quot;ui-button-icon-secondary ui-icon {{{5|{{{iconSecondary|}}}}}}&amp;quot;&amp;gt;&amp;amp;nbsp;&amp;lt;/span&amp;gt;&lt;br /&gt;
  }}&amp;lt;/span&amp;gt;]&amp;lt;/span&amp;gt;&amp;lt;!--&lt;br /&gt;
  --&amp;gt;&lt;br /&gt;
  | [[{{{1|{{{target|Parameter target is empty!}}}}}}|&amp;lt;span class=&amp;quot;submit ui-button ui-widget ui-state-default ui-corner-all {{Clickable button/iconclass&lt;br /&gt;
    |{{{4|{{{iconPrimary|}}}}}}&lt;br /&gt;
    |{{{5|{{{iconSecondary|}}}}}}&lt;br /&gt;
    |{{{2|{{{text|&amp;lt;noinclude&amp;gt;x&amp;lt;/noinclude&amp;gt;}}}}}}&lt;br /&gt;
  }} {{{class|}}}&amp;quot; role=&amp;quot;button&amp;quot; aria-disabled=&amp;quot;false&amp;quot; {{#if:{{{id|}}}|id=&amp;quot;{{{id}}}&amp;quot;}}&amp;gt;&amp;lt;!-- // --&amp;gt;{{#if:{{{4|{{{iconPrimary|}}}}}}&lt;br /&gt;
  |&amp;lt;span class=&amp;quot;ui-button-icon-primary ui-icon {{{4|{{{iconPrimary}}}}}}&amp;quot;&amp;gt;&amp;amp;nbsp;&amp;lt;/span&amp;gt;&lt;br /&gt;
  }}&amp;lt;span class=&amp;quot;ui-button-text&amp;quot;&amp;gt;{{{2|{{{text|Parameter &#039;&#039;&#039;text&#039;&#039;&#039; is empty}}}}}}&amp;lt;/span&amp;gt;{{#if:{{{5|{{{iconSecondary|}}}}}}&lt;br /&gt;
  |&amp;lt;span class=&amp;quot;ui-button-icon-secondary ui-icon {{{5|{{{iconSecondary|}}}}}}&amp;quot;&amp;gt;&amp;amp;nbsp;&amp;lt;/span&amp;gt;&lt;br /&gt;
  }}&amp;lt;/span&amp;gt;]]&lt;br /&gt;
}}&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--&amp;gt;&amp;lt;/onlyinclude&amp;gt;&lt;br /&gt;
{{documentation}}&lt;br /&gt;
&amp;lt;!-- Add categories and interwikis to Template:Clickable button/doc subpage, not here! --&amp;gt;&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=Template:MainPage&amp;diff=180</id>
		<title>Template:MainPage</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=Template:MainPage&amp;diff=180"/>
		<updated>2026-04-15T19:23:16Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&amp;quot;portal-buttons&amp;quot;&amp;gt;{{Template:Clickable button|Metal Cardbot (season)|[[File:Metal Cardbot logo.png]]|class=mw-ui-{{{class|button}}}}}{{Template:Clickable button|Metal Cardbot S|[[File:Metal Cardbot S logo.png]]|class=mw-ui-{{{class|button}}}}}{{Template:Clickable button|Metal Cardbot W|[[File:Metal Cardbot W logo.png]]|class=mw-ui-{{{class|button}}}}}&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Metal Cardbot&#039;&#039;&#039; is a 2023 Korean animated mecha series created by [[SAMG Entertainment]], directed by [[OSROCTION]] and animated by [[NAVY Co, Ltd.]]. A boy named [[Jun]] discovers the [[Metal Breath]], a mysterious device that allows him to capture and command a species of transforming robots known as [[Metal Cardbots]], who take refuge on [[Earth]] after their home planet [[Machina]] was destroyed.&lt;br /&gt;
&lt;br /&gt;
Metal Cardbot currently has three main seasons ([[Metal Cardbot (series)|Metal Cardbot]], [[Metal Cardbot S]], [[Metal Cardbot W]]) and two Chinese spinoff seasons ([[Metal Cardbot: Beast Energy]], [[Metal Cardbot: Zerg Crisis]]). The first season has been dubbed in a variety of languages, including [[English localization|English]], [[Chinese localization|Chinese]], [[Russian localization|Russian]], [[Indonesian localization|Indonesian]], and [[Spanish localization|Spanish]]).&lt;br /&gt;
&lt;br /&gt;
== Contributions ==&lt;br /&gt;
As this wiki is currently under construction, and we want to ensure cardbot.wiki remains a reliable source of Metal Cardbot info, this wiki isn&#039;t open for direct contributions at this time. However, we&#039;re always open to suggestions and corrections! If you have something to add, [https://forms.gle/cAYv3CQWy4yfakws7 please use this form].&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=Template:PortalButton&amp;diff=179</id>
		<title>Template:PortalButton</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=Template:PortalButton&amp;diff=179"/>
		<updated>2026-04-15T06:34:37Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;span style=&amp;quot;display: inline-block; position:absolute; height:2.4em; overflow:hidden; margin-top: 1px; margin-left: 1px;&amp;quot;&amp;gt;[[{{{file|{{{File|{{{image|{{{icon|{{{3|File:Icon.png}}}}}}}}}}}}}}}|link={{{link|{{{page|{{{url|{{{2|Main Page}}}}}}}}}}}}|frameless|upright={{{upright|{{{scale|1}}}}}}]]&amp;lt;/span&amp;gt;{{Template:Clickable button|{{{link|}}}|&amp;lt;span style{{=}}&amp;quot;display: inline-block; padding-left: {{{offset|0}}}&amp;quot;&amp;gt;{{{text|}}}&amp;lt;/span&amp;gt;|class=mw-ui-{{{class|button}}}}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{documentation}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=Main_Page&amp;diff=178</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=Main_Page&amp;diff=178"/>
		<updated>2026-04-15T06:32:41Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:&amp;lt;span style=&amp;quot;position: absolute; clip: rect(1px 1px 1px 1px); clip: rect(1px, 1px, 1px, 1px);&amp;quot;&amp;gt;{{FULLPAGENAME}}&amp;lt;/span&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
{{MainPage}}&lt;br /&gt;
&amp;lt;!-- To edit this page visit Template:MainPage --&amp;gt;&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=Template:MainPage&amp;diff=177</id>
		<title>Template:MainPage</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=Template:MainPage&amp;diff=177"/>
		<updated>2026-04-15T06:32:27Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&amp;quot;portal-buttons&amp;quot;&amp;gt;{{PortalButton|image=File:Metal Cardbot logo.png|link=Metal Cardbot (season)}}{{PortalButton|image=File:Metal Cardbot S logo.png|link=Metal Cardbot S}}{{PortalButton|image=File:Metal Cardbot W logo.png|link=Metal Cardbot W}}&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Metal Cardbot&#039;&#039;&#039; is a 2023 Korean animated mecha series created by [[SAMG Entertainment]], directed by [[OSROCTION]] and animated by [[NAVY Co, Ltd.]]. A boy named [[Jun]] discovers the [[Metal Breath]], a mysterious device that allows him to capture and command a species of transforming robots known as [[Metal Cardbots]], who take refuge on [[Earth]] after their home planet [[Machina]] was destroyed.&lt;br /&gt;
&lt;br /&gt;
Metal Cardbot currently has three main seasons ([[Metal Cardbot (series)|Metal Cardbot]], [[Metal Cardbot S]], [[Metal Cardbot W]]) and two Chinese spinoff seasons ([[Metal Cardbot: Beast Energy]], [[Metal Cardbot: Zerg Crisis]]). The first season has been dubbed in a variety of languages, including [[English localization|English]], [[Chinese localization|Chinese]], [[Russian localization|Russian]], [[Indonesian localization|Indonesian]], and [[Spanish localization|Spanish]]).&lt;br /&gt;
&lt;br /&gt;
== Contributions ==&lt;br /&gt;
As this wiki is currently under construction, and we want to ensure cardbot.wiki remains a reliable source of Metal Cardbot info, this wiki isn&#039;t open for direct contributions at this time. However, we&#039;re always open to suggestions and corrections! If you have something to add, [https://forms.gle/cAYv3CQWy4yfakws7 please use this form].&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=MediaWiki:Common.css&amp;diff=176</id>
		<title>MediaWiki:Common.css</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=MediaWiki:Common.css&amp;diff=176"/>
		<updated>2026-04-15T06:31:43Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: Created page with &amp;quot;/* CSS placed here will be applied to all skins */ .portal-buttons { 	display: flex; 	gap: 1rem; }&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* CSS placed here will be applied to all skins */&lt;br /&gt;
.portal-buttons {&lt;br /&gt;
	display: flex;&lt;br /&gt;
	gap: 1rem;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=Template:MainPage&amp;diff=175</id>
		<title>Template:MainPage</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=Template:MainPage&amp;diff=175"/>
		<updated>2026-04-15T06:30:57Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: Created page with &amp;quot;&amp;lt;div class=&amp;quot;portal-buttons&amp;quot;&amp;gt; {{PortalButton|image=File:Metal Cardbot logo.png|link=Metal Cardbot (season)}} {{PortalButton|image=File:Metal Cardbot S logo.png|link=Metal Cardbot S}} {{PortalButton|image=File:Metal Cardbot W logo.png|link=Metal Cardbot W}} &amp;lt;/div&amp;gt;  &amp;#039;&amp;#039;&amp;#039;Metal Cardbot&amp;#039;&amp;#039;&amp;#039; is a 2023 Korean animated mecha series created by SAMG Entertainment, directed by OSROCTION and animated by NAVY Co, Ltd.. A boy named Jun discovers the Metal Breath, a my...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&amp;quot;portal-buttons&amp;quot;&amp;gt;&lt;br /&gt;
{{PortalButton|image=File:Metal Cardbot logo.png|link=Metal Cardbot (season)}}&lt;br /&gt;
{{PortalButton|image=File:Metal Cardbot S logo.png|link=Metal Cardbot S}}&lt;br /&gt;
{{PortalButton|image=File:Metal Cardbot W logo.png|link=Metal Cardbot W}}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Metal Cardbot&#039;&#039;&#039; is a 2023 Korean animated mecha series created by [[SAMG Entertainment]], directed by [[OSROCTION]] and animated by [[NAVY Co, Ltd.]]. A boy named [[Jun]] discovers the [[Metal Breath]], a mysterious device that allows him to capture and command a species of transforming robots known as [[Metal Cardbots]], who take refuge on [[Earth]] after their home planet [[Machina]] was destroyed.&lt;br /&gt;
&lt;br /&gt;
Metal Cardbot currently has three main seasons ([[Metal Cardbot (series)|Metal Cardbot]], [[Metal Cardbot S]], [[Metal Cardbot W]]) and two Chinese spinoff seasons ([[Metal Cardbot: Beast Energy]], [[Metal Cardbot: Zerg Crisis]]). The first season has been dubbed in a variety of languages, including [[English localization|English]], [[Chinese localization|Chinese]], [[Russian localization|Russian]], [[Indonesian localization|Indonesian]], and [[Spanish localization|Spanish]]).&lt;br /&gt;
&lt;br /&gt;
== Contributions ==&lt;br /&gt;
As this wiki is currently under construction, and we want to ensure cardbot.wiki remains a reliable source of Metal Cardbot info, this wiki isn&#039;t open for direct contributions at this time. However, we&#039;re always open to suggestions and corrections! If you have something to add, [https://forms.gle/cAYv3CQWy4yfakws7 please use this form].&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=MediaWiki:Spam-whitelist&amp;diff=174</id>
		<title>MediaWiki:Spam-whitelist</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=MediaWiki:Spam-whitelist&amp;diff=174"/>
		<updated>2026-04-15T06:30:53Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt; #&amp;lt;!-- leave this line exactly as it is --&amp;gt; &amp;lt;pre&amp;gt;&lt;br /&gt;
# External URLs matching this list will *not* be blocked even if they would&lt;br /&gt;
# have been blocked by block list entries.&lt;br /&gt;
#&lt;br /&gt;
# Syntax is as follows:&lt;br /&gt;
#   * Everything from a &amp;quot;#&amp;quot; character to the end of the line is a comment&lt;br /&gt;
#   * Every non-blank line is a regex fragment which will only match hosts inside URLs&lt;br /&gt;
forms.gle&lt;br /&gt;
 #&amp;lt;/pre&amp;gt; &amp;lt;!-- leave this line exactly as it is --&amp;gt;&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=MediaWiki:Spam-whitelist&amp;diff=173</id>
		<title>MediaWiki:Spam-whitelist</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=MediaWiki:Spam-whitelist&amp;diff=173"/>
		<updated>2026-04-15T06:30:33Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt; #&amp;lt;!-- leave this line exactly as it is --&amp;gt; &amp;lt;pre&amp;gt;&lt;br /&gt;
# External URLs matching this list will *not* be blocked even if they would&lt;br /&gt;
# have been blocked by block list entries.&lt;br /&gt;
#&lt;br /&gt;
# Syntax is as follows:&lt;br /&gt;
#   * Everything from a &amp;quot;#&amp;quot; character to the end of the line is a comment&lt;br /&gt;
#   * Every non-blank line is a regex fragment which will only match hosts inside URLs&lt;br /&gt;
https:\/\/forms\.gle&lt;br /&gt;
 #&amp;lt;/pre&amp;gt; &amp;lt;!-- leave this line exactly as it is --&amp;gt;&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=File:Metal_Cardbot_W_logo_EN.png&amp;diff=172</id>
		<title>File:Metal Cardbot W logo EN.png</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=File:Metal_Cardbot_W_logo_EN.png&amp;diff=172"/>
		<updated>2026-04-15T06:29:02Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Licensing ==&lt;br /&gt;
{{Fairuse}}&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=File:Metal_Cardbot_W_logo.png&amp;diff=171</id>
		<title>File:Metal Cardbot W logo.png</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=File:Metal_Cardbot_W_logo.png&amp;diff=171"/>
		<updated>2026-04-15T06:28:07Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Licensing ==&lt;br /&gt;
{{Fairuse}}&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=File:Metal_Cardbot_S_logo_EN.png&amp;diff=170</id>
		<title>File:Metal Cardbot S logo EN.png</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=File:Metal_Cardbot_S_logo_EN.png&amp;diff=170"/>
		<updated>2026-04-15T06:24:43Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Licensing ==&lt;br /&gt;
{{Fairuse}}&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=File:Metal_Cardbot_S_logo.png&amp;diff=169</id>
		<title>File:Metal Cardbot S logo.png</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=File:Metal_Cardbot_S_logo.png&amp;diff=169"/>
		<updated>2026-04-15T06:23:59Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
== Licensing ==&lt;br /&gt;
{{Fairuse}}&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=Template:PortalButton&amp;diff=168</id>
		<title>Template:PortalButton</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=Template:PortalButton&amp;diff=168"/>
		<updated>2026-04-15T06:22:39Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;span style=&amp;quot;display: inline-block; position:absolute; height:2.4em; overflow:hidden; margin-top: 1px; margin-left: 1px;&amp;quot;&amp;gt;[[{{{file|{{{File|{{{image|{{{icon|{{{3|File:Icon.png}}}}}}}}}}}}}}}|link={{{link|{{{page|{{{url|{{{2|Main Page}}}}}}}}}}}}|frameless|upright={{{upright|{{{scale|0.135}}}}}}]]&amp;lt;/span&amp;gt;{{Template:Clickable button|{{{link|}}}|&amp;lt;span style{{=}}&amp;quot;display: inline-block; padding-left: {{{offset|0}}}&amp;quot;&amp;gt;{{{text|{{{name|{{{title|{{{content|{{{1|Test button name}}}}}}}}}}}}}}}&amp;lt;/span&amp;gt;|class=mw-ui-{{{class|button}}}}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{documentation}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=File:Metal_Cardbot_logo_EN.png&amp;diff=167</id>
		<title>File:Metal Cardbot logo EN.png</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=File:Metal_Cardbot_logo_EN.png&amp;diff=167"/>
		<updated>2026-04-15T06:19:17Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: The English version of the Metal Cardbot logo.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Summary ==&lt;br /&gt;
The English version of the Metal Cardbot logo.&lt;br /&gt;
== Licensing ==&lt;br /&gt;
{{Fairuse}}&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=MediaWiki:Licenses&amp;diff=166</id>
		<title>MediaWiki:Licenses</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=MediaWiki:Licenses&amp;diff=166"/>
		<updated>2026-04-15T06:17:19Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: Created page with &amp;quot;- * Fair use: ** Fairuse|This will be used in a way that qualifies as fair use under US law * Own image: ** Self|I created this image myself. * Wikimedia: ** From Wikimedia|I got this from Wikipedia or another Wikimedia project * Free licenses: ** CC-BY-SA|This is licensed under the Creative Commons Attribution-Share Alike License ** Other free|This is licensed under another free license * Other ** PD|This is in the public domain  ** Permission|This is copyrighted, but u...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-&lt;br /&gt;
* Fair use:&lt;br /&gt;
** Fairuse|This will be used in a way that qualifies as fair use under US law&lt;br /&gt;
* Own image:&lt;br /&gt;
** Self|I created this image myself.&lt;br /&gt;
* Wikimedia:&lt;br /&gt;
** From Wikimedia|I got this from Wikipedia or another Wikimedia project&lt;br /&gt;
* Free licenses:&lt;br /&gt;
** CC-BY-SA|This is licensed under the Creative Commons Attribution-Share Alike License&lt;br /&gt;
** Other free|This is licensed under another free license&lt;br /&gt;
* Other&lt;br /&gt;
** PD|This is in the public domain &lt;br /&gt;
** Permission|This is copyrighted, but use is permitted by the copyright holder&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=File:Metal_Cardbot_logo.png&amp;diff=165</id>
		<title>File:Metal Cardbot logo.png</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=File:Metal_Cardbot_logo.png&amp;diff=165"/>
		<updated>2026-04-15T06:15:53Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=Template:PortalButton&amp;diff=164</id>
		<title>Template:PortalButton</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=Template:PortalButton&amp;diff=164"/>
		<updated>2026-04-15T06:14:27Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: Created page with &amp;quot;&amp;lt;span style=&amp;quot;display: inline-block; position:absolute; opacity:{{{opacity|0.3}}}; height:2.4em; overflow:hidden; margin-top: 1px; margin-left: 1px;&amp;quot;&amp;gt;0.135}}}}}}&amp;lt;/span&amp;gt;{{Template:Clickable button|{{{link|{{{page|{{{2|{{{utrl|Main Page}}}}}}}}}}}}|&amp;lt;span style{{=}}&amp;quot;display: inline-block; padding-left: {{{offset|0...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;span style=&amp;quot;display: inline-block; position:absolute; opacity:{{{opacity|0.3}}}; height:2.4em; overflow:hidden; margin-top: 1px; margin-left: 1px;&amp;quot;&amp;gt;[[{{{file|{{{File|{{{image|{{{icon|{{{3|File:Icon.png}}}}}}}}}}}}}}}|link={{{link|{{{page|{{{url|{{{2|Main Page}}}}}}}}}}}}|frameless|upright={{{upright|{{{scale|0.135}}}}}}]]&amp;lt;/span&amp;gt;{{Template:Clickable button|{{{link|{{{page|{{{2|{{{utrl|Main Page}}}}}}}}}}}}|&amp;lt;span style{{=}}&amp;quot;display: inline-block; padding-left: {{{offset|0}}}&amp;quot;&amp;gt;{{{text|{{{name|{{{title|{{{content|{{{1|Test button name}}}}}}}}}}}}}}}&amp;lt;/span&amp;gt;|class=mw-ui-{{{class|button}}}}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{documentation}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=Template:Clickable_button&amp;diff=163</id>
		<title>Template:Clickable button</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=Template:Clickable_button&amp;diff=163"/>
		<updated>2026-04-15T06:13:18Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: Created page with &amp;quot;&amp;lt;span class=&amp;quot;mw-ui-button {{#switch: {{{color|white}}} | red = mw-ui-destructive | green = mw-ui-progressive | white = | blue = mw-ui-progressive}}&amp;quot; role=&amp;quot;button&amp;quot; aria-disabled=&amp;quot;false&amp;quot;&amp;gt;{{{text|{{{1|Button text}}}}}}&amp;lt;/span&amp;gt;&amp;lt;noinclude&amp;gt;{{Documentation}} &amp;lt;/noinclude&amp;gt;&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;span class=&amp;quot;mw-ui-button {{#switch: {{{color|white}}} | red = mw-ui-destructive | green = mw-ui-progressive | white = | blue = mw-ui-progressive}}&amp;quot; role=&amp;quot;button&amp;quot; aria-disabled=&amp;quot;false&amp;quot;&amp;gt;{{{text|{{{1|Button text}}}}}}&amp;lt;/span&amp;gt;&amp;lt;noinclude&amp;gt;{{Documentation}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=Main_Page&amp;diff=162</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=Main_Page&amp;diff=162"/>
		<updated>2026-04-15T05:58:04Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DISPLAYTITLE:&amp;lt;span style=&amp;quot;position: absolute; clip: rect(1px 1px 1px 1px); clip: rect(1px, 1px, 1px, 1px);&amp;quot;&amp;gt;{{FULLPAGENAME}}&amp;lt;/span&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Metal Cardbot&#039;&#039;&#039; is a 2023 Korean animated mecha series created by [[SAMG Entertainment]], directed by [[OSROCTION]] and animated by [[NAVY Co, Ltd.]]. A boy named [[Jun]] discovers the [[Metal Breath]], a mysterious device that allows him to capture and command a species of transforming robots known as [[Metal Cardbots]], who take refuge on [[Earth]] after their home planet [[Machina]] was destroyed.&lt;br /&gt;
&lt;br /&gt;
Metal Cardbot currently has three main seasons ([[Metal Cardbot (series)|Metal Cardbot]], [[Metal Cardbot S]], [[Metal Cardbot W]]) and two Chinese spinoff seasons ([[Metal Cardbot: Beast Energy]], [[Metal Cardbot: Zerg Crisis]]). The first season has been dubbed in a variety of languages, including [[English localization|English]], [[Chinese localization|Chinese]], [[Russian localization|Russian]], [[Indonesian localization|Indonesian]], and [[Spanish localization|Spanish]]).&lt;br /&gt;
&lt;br /&gt;
== Contributions ==&lt;br /&gt;
As this wiki is currently under construction, and we want to ensure cardbot.wiki remains a reliable source of Metal Cardbot info, this wiki isn&#039;t open for direct contributions at this time. However, we&#039;re always open to suggestions and corrections! If you have something to add, [https://forms.gle/cAYv3CQWy4yfakws7 please use this form].&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=Metal_Cardbot_(series)&amp;diff=161</id>
		<title>Metal Cardbot (series)</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=Metal_Cardbot_(series)&amp;diff=161"/>
		<updated>2026-04-15T05:54:35Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: Created page with &amp;quot;{{Season }}  {{about|the first season of Metal Cardbot}}  &amp;#039;&amp;#039;&amp;#039;Metal Cardbot&amp;#039;&amp;#039;&amp;#039; is a 2023 animated mecha show produced by SAMG Entertainment in cooperation with Navy Co., Ltd. and OSROCTION.  ==Episodes==&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Season }}&lt;br /&gt;
&lt;br /&gt;
{{about|the first season of Metal Cardbot}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Metal Cardbot&#039;&#039;&#039; is a 2023 animated mecha show produced by [[SAMG Entertainment]] in cooperation with [[Navy Co., Ltd.]] and [[OSROCTION]].&lt;br /&gt;
&lt;br /&gt;
==Episodes==&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=Template:About&amp;diff=160</id>
		<title>Template:About</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=Template:About&amp;diff=160"/>
		<updated>2026-04-15T05:54:22Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;This page is about {{{1}}}. {{#if:{{{2|}}}|For {{{2}}}, see {{{3}}}.|}} {{#if:{{{4|}}}|For {{{4}}}, see {{{5}}}.|}}&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=Template:About&amp;diff=159</id>
		<title>Template:About</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=Template:About&amp;diff=159"/>
		<updated>2026-04-15T05:53:51Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;This page is about {{{1}}}. {{#if:{{{2|}}}|For {{{2}}}, see {{{3}}}|}}. {{#if:{{{4|}}}|For {{{4}}}, see {{{5}}}|}}&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=Template:About&amp;diff=158</id>
		<title>Template:About</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=Template:About&amp;diff=158"/>
		<updated>2026-04-15T05:52:30Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: Created page with &amp;quot;&amp;#039;&amp;#039;This page is about {{{1}}}. {{#if:{{{2}}}|For {{{2}}}, see {{{3}}}|}}. {{#if:{{{4}}}|For {{{4}}}, see {{{5}}}|}}&amp;#039;&amp;#039;&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;This page is about {{{1}}}. {{#if:{{{2}}}|For {{{2}}}, see {{{3}}}|}}. {{#if:{{{4}}}|For {{{4}}}, see {{{5}}}|}}&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=Template:TOC_limit&amp;diff=157</id>
		<title>Template:TOC limit</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=Template:TOC_limit&amp;diff=157"/>
		<updated>2026-04-15T05:28:11Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;templatestyles src=&amp;quot;Template:TOC limit/styles.css&amp;quot; /&amp;gt;&amp;lt;div class=&amp;quot;toclimit-{{{1|{{{limit|3}}}}}}&amp;quot;&amp;gt;__TOC__&amp;lt;/div&amp;gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{documentation}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=Template:Navbox&amp;diff=155</id>
		<title>Template:Navbox</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=Template:Navbox&amp;diff=155"/>
		<updated>2026-04-15T05:28:11Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;{{#invoke:Navbox|navbox}}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{Documentation}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=Template:Icon&amp;diff=153</id>
		<title>Template:Icon</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=Template:Icon&amp;diff=153"/>
		<updated>2026-04-15T05:28:11Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#invoke:Icon|main}}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{documentation}}&lt;br /&gt;
&amp;lt;!-- Categories go on the /doc subpage, and interwikis go on Wikidata. --&amp;gt;&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=Template:Template_other&amp;diff=151</id>
		<title>Template:Template other</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=Template:Template_other&amp;diff=151"/>
		<updated>2026-04-15T05:28:10Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#switch:&lt;br /&gt;
  &amp;lt;!--If no or empty &amp;quot;demospace&amp;quot; parameter then detect namespace--&amp;gt;&lt;br /&gt;
  {{#if:{{{demospace|}}}&lt;br /&gt;
  | {{lc: {{{demospace}}} }}    &amp;lt;!--Use lower case &amp;quot;demospace&amp;quot;--&amp;gt;&lt;br /&gt;
  | {{#ifeq:{{NAMESPACE}}|{{ns:Template}}&lt;br /&gt;
    | template&lt;br /&gt;
    | other&lt;br /&gt;
    }}&lt;br /&gt;
  }}&lt;br /&gt;
| template = {{{1|}}}&lt;br /&gt;
| other&lt;br /&gt;
| #default = {{{2|}}}&lt;br /&gt;
}}&amp;lt;!--End switch--&amp;gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{documentation}}&lt;br /&gt;
&amp;lt;!-- Add categories and interwikis to the /doc subpage, not here! --&amp;gt;&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=Module:Template_link_general&amp;diff=149</id>
		<title>Module:Template link general</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=Module:Template_link_general&amp;diff=149"/>
		<updated>2026-04-15T05:28:10Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- This implements Template:Template link general and various other templates in its family&lt;br /&gt;
local getArgs = require(&#039;Module:Arguments&#039;).getArgs&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
-- Is a string non-empty?&lt;br /&gt;
local function _ne(s) &lt;br /&gt;
	return s ~= nil and s ~= &amp;quot;&amp;quot;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local nw = mw.text.nowiki&lt;br /&gt;
&lt;br /&gt;
local function addTemplate(s)&lt;br /&gt;
	local i, _ = s:find(&#039;:&#039;, 1, true)&lt;br /&gt;
	if i == nil then&lt;br /&gt;
		return &#039;Template:&#039; .. s&lt;br /&gt;
	end&lt;br /&gt;
	local ns = s:sub(1, i - 1)&lt;br /&gt;
	if ns == &#039;&#039; or mw.site.namespaces[ns] then&lt;br /&gt;
		return s&lt;br /&gt;
	else&lt;br /&gt;
		return &#039;Template:&#039; .. s&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function trimTemplate(s)&lt;br /&gt;
	local needle = &#039;template:&#039;&lt;br /&gt;
	if s:sub(1, needle:len()):lower() == needle then&lt;br /&gt;
		return s:sub(needle:len() + 1)	&lt;br /&gt;
	else&lt;br /&gt;
		return s&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Builds the link part&lt;br /&gt;
local function linkTitle(args)&lt;br /&gt;
	local titleObj&lt;br /&gt;
	if args[&#039;1&#039;] then&lt;br /&gt;
		-- This handles :Page and other NS&lt;br /&gt;
		titleObj = mw.title.new(args[&#039;1&#039;], &#039;Template&#039;)&lt;br /&gt;
	else&lt;br /&gt;
		titleObj = mw.title.getCurrentTitle()&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local textPart = args.alttext&lt;br /&gt;
	if not _ne(textPart) then&lt;br /&gt;
		if titleObj ~= nil then&lt;br /&gt;
			textPart = titleObj:inNamespace(&amp;quot;Template&amp;quot;) and args[&#039;1&#039;] or titleObj.fullText&lt;br /&gt;
		else&lt;br /&gt;
			-- redlink&lt;br /&gt;
			textPart = args[&#039;1&#039;]&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if _ne(args.subst) then&lt;br /&gt;
		-- HACK: the ns thing above is probably broken&lt;br /&gt;
		textPart = &#039;subst:&#039; .. textPart&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if _ne(args.brace) then&lt;br /&gt;
		textPart = nw(&#039;{{&#039;) .. textPart .. nw(&#039;}}&#039;)&lt;br /&gt;
	elseif _ne(args.braceinside) then&lt;br /&gt;
		textPart = nw(&#039;{&#039;) .. textPart .. nw(&#039;}&#039;)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local titlePart&lt;br /&gt;
	if _ne(args.nolink) then&lt;br /&gt;
		titlePart = textPart&lt;br /&gt;
	else&lt;br /&gt;
		titlePart = &#039;[[&#039; .. (titleObj ~= nil and titleObj.fullText or addTemplate(args[&#039;1&#039;])) ..&lt;br /&gt;
			&#039;|&#039; .. textPart .. &#039;]]&#039;&lt;br /&gt;
	end&lt;br /&gt;
	if _ne(args.braceinside) then&lt;br /&gt;
		titlePart = nw(&#039;{&#039;) .. titlePart .. nw(&#039;}&#039;)&lt;br /&gt;
	end&lt;br /&gt;
	local bold = _ne(args.bold) or _ne(args.boldlink) or _ne(args.boldname)&lt;br /&gt;
	if bold then&lt;br /&gt;
		titlePart = &amp;quot;&#039;&#039;&#039;&amp;quot; .. titlePart .. &amp;quot;&#039;&#039;&#039;&amp;quot;&lt;br /&gt;
	end&lt;br /&gt;
	if _ne(args.nowrapname) then&lt;br /&gt;
		titlePart = &#039;&amp;lt;span class=&amp;quot;nowrap&amp;quot;&amp;gt;&#039; .. titlePart .. &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
	end&lt;br /&gt;
	return titlePart&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.main(frame)&lt;br /&gt;
	local args = getArgs(frame, {&lt;br /&gt;
		trim = true,&lt;br /&gt;
		removeBlanks = false&lt;br /&gt;
	})&lt;br /&gt;
	return p._main(args)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p._main(args)&lt;br /&gt;
	local italic = _ne(args.italic) or _ne(args.italics)&lt;br /&gt;
	local dontBrace = _ne(args.brace) or _ne(args.braceinside)&lt;br /&gt;
	local code = _ne(args.code) or _ne(args.tt)&lt;br /&gt;
	local show_result = _ne(args._show_result)&lt;br /&gt;
	local expand = _ne(args._expand)&lt;br /&gt;
	&lt;br /&gt;
	local titlePart = linkTitle(args)&lt;br /&gt;
	&lt;br /&gt;
	-- Build the arguments&lt;br /&gt;
	local textPart = &amp;quot;&amp;quot;&lt;br /&gt;
	local textPartBuffer = &amp;quot;&amp;amp;#124;&amp;quot;&lt;br /&gt;
	local codeArguments = {}&lt;br /&gt;
	local codeArgumentsString = &amp;quot;&amp;quot;&lt;br /&gt;
	local i = 2&lt;br /&gt;
	local j = 1&lt;br /&gt;
	while args[i] do&lt;br /&gt;
		local val = args[i]&lt;br /&gt;
		if val ~= &amp;quot;&amp;quot; then&lt;br /&gt;
			if _ne(args.nowiki) then&lt;br /&gt;
				-- Unstrip nowiki tags first because calling nw on something that already contains nowiki tags will&lt;br /&gt;
				-- mangle the nowiki strip marker and result in literal UNIQ...QINU showing up&lt;br /&gt;
				val = nw(mw.text.unstripNoWiki(val))&lt;br /&gt;
			end&lt;br /&gt;
			local k, v = string.match(val, &amp;quot;(.*)=(.*)&amp;quot;)&lt;br /&gt;
			if not k then&lt;br /&gt;
				codeArguments[j] = val&lt;br /&gt;
				j = j + 1&lt;br /&gt;
			else&lt;br /&gt;
				codeArguments[k] = v&lt;br /&gt;
			end&lt;br /&gt;
			codeArgumentsString = codeArgumentsString .. textPartBuffer .. val&lt;br /&gt;
			if italic then&lt;br /&gt;
				val = &#039;&amp;lt;span style=&amp;quot;font-style:italic;&amp;quot;&amp;gt;&#039; .. val .. &#039;&amp;lt;/span&amp;gt;&#039;&lt;br /&gt;
			end&lt;br /&gt;
			textPart = textPart .. textPartBuffer .. val&lt;br /&gt;
		end&lt;br /&gt;
		i = i + 1&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- final wrap&lt;br /&gt;
	local ret = titlePart .. textPart&lt;br /&gt;
	if not dontBrace then ret = nw(&#039;{{&#039;) .. ret .. nw(&#039;}}&#039;) end&lt;br /&gt;
	if _ne(args.a) then ret = nw(&#039;*&#039;) .. &#039;&amp;amp;nbsp;&#039; .. ret end&lt;br /&gt;
	if _ne(args.kbd) then ret = &#039;&amp;lt;kbd&amp;gt;&#039; .. ret .. &#039;&amp;lt;/kbd&amp;gt;&#039; end&lt;br /&gt;
	if code then&lt;br /&gt;
		ret = &#039;&amp;lt;code&amp;gt;&#039; .. ret .. &#039;&amp;lt;/code&amp;gt;&#039;&lt;br /&gt;
	elseif _ne(args.plaincode) then&lt;br /&gt;
		ret = &#039;&amp;lt;code style=&amp;quot;border:none;background:transparent;color:inherit&amp;quot;&amp;gt;&#039; .. ret .. &#039;&amp;lt;/code&amp;gt;&#039;&lt;br /&gt;
	end&lt;br /&gt;
	if _ne(args.nowrap) then ret = &#039;&amp;lt;span class=&amp;quot;nowrap&amp;quot;&amp;gt;&#039; .. ret .. &#039;&amp;lt;/span&amp;gt;&#039; end&lt;br /&gt;
	&lt;br /&gt;
	--[[ Wrap as html?? &lt;br /&gt;
	local span = mw.html.create(&#039;span&#039;)&lt;br /&gt;
	span:wikitext(ret)&lt;br /&gt;
	--]]&lt;br /&gt;
	if _ne(args.debug) then ret = ret .. &#039;\n&amp;lt;pre&amp;gt;&#039; .. mw.text.encode(mw.dumpObject(args)) .. &#039;&amp;lt;/pre&amp;gt;&#039; end&lt;br /&gt;
&lt;br /&gt;
	if show_result then&lt;br /&gt;
		if _ne(args.nocat) then codeArguments[&#039;nocat&#039;] = true end&lt;br /&gt;
		local result = mw.getCurrentFrame():expandTemplate{title = addTemplate(args[1]), args = codeArguments}&lt;br /&gt;
		ret = ret .. &amp;quot; → &amp;quot; .. result&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if expand then&lt;br /&gt;
		local query = mw.text.encode(&#039;{{&#039; .. addTemplate(args[1]) .. string.gsub(codeArgumentsString, textPartBuffer, &amp;quot;|&amp;quot;) .. &#039;}}&#039;)&lt;br /&gt;
		local url = mw.uri.fullUrl(&#039;special:ExpandTemplates&#039;, &#039;wpInput=&#039; .. query)&lt;br /&gt;
		mw.log()&lt;br /&gt;
		ret = ret .. &amp;quot; [&amp;quot; .. tostring(url) .. &amp;quot;]&amp;quot;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=Template:Template_link_expanded&amp;diff=147</id>
		<title>Template:Template link expanded</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=Template:Template_link_expanded&amp;diff=147"/>
		<updated>2026-04-15T05:28:07Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#Invoke:Template link general|main|code=on}}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{Documentation|1=Template:Tlg/doc&lt;br /&gt;
|content = {{tlg/doc|tlx}}&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;!-- Add categories to the /doc subpage, not here! --&amp;gt;&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=Template:Tlx&amp;diff=145</id>
		<title>Template:Tlx</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=Template:Tlx&amp;diff=145"/>
		<updated>2026-04-15T05:28:06Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Template:Template link expanded]]&lt;br /&gt;
&lt;br /&gt;
{{Redirect category shell|&lt;br /&gt;
{{R from move}}&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=Module:TableTools&amp;diff=143</id>
		<title>Module:TableTools</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=Module:TableTools&amp;diff=143"/>
		<updated>2026-04-15T05:28:05Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;------------------------------------------------------------------------------------&lt;br /&gt;
--                                   TableTools                                   --&lt;br /&gt;
--                                                                                --&lt;br /&gt;
-- This module includes a number of functions for dealing with Lua tables.        --&lt;br /&gt;
-- It is a meta-module, meant to be called from other Lua modules, and should not --&lt;br /&gt;
-- be called directly from #invoke.                                               --&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local libraryUtil = require(&#039;libraryUtil&#039;)&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
-- Define often-used variables and functions.&lt;br /&gt;
local floor = math.floor&lt;br /&gt;
local infinity = math.huge&lt;br /&gt;
local checkType = libraryUtil.checkType&lt;br /&gt;
local checkTypeMulti = libraryUtil.checkTypeMulti&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- isPositiveInteger&lt;br /&gt;
--&lt;br /&gt;
-- This function returns true if the given value is a positive integer, and false&lt;br /&gt;
-- if not. Although it doesn&#039;t operate on tables, it is included here as it is&lt;br /&gt;
-- useful for determining whether a given table key is in the array part or the&lt;br /&gt;
-- hash part of a table.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.isPositiveInteger(v)&lt;br /&gt;
	return type(v) == &#039;number&#039; and v &amp;gt;= 1 and floor(v) == v and v &amp;lt; infinity&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- isNan&lt;br /&gt;
--&lt;br /&gt;
-- This function returns true if the given number is a NaN value, and false if&lt;br /&gt;
-- not. Although it doesn&#039;t operate on tables, it is included here as it is useful&lt;br /&gt;
-- for determining whether a value can be a valid table key. Lua will generate an&lt;br /&gt;
-- error if a NaN is used as a table key.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.isNan(v)&lt;br /&gt;
	return type(v) == &#039;number&#039; and v ~= v&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- shallowClone&lt;br /&gt;
--&lt;br /&gt;
-- This returns a clone of a table. The value returned is a new table, but all&lt;br /&gt;
-- subtables and functions are shared. Metamethods are respected, but the returned&lt;br /&gt;
-- table will have no metatable of its own.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.shallowClone(t)&lt;br /&gt;
	checkType(&#039;shallowClone&#039;, 1, t, &#039;table&#039;)&lt;br /&gt;
	local ret = {}&lt;br /&gt;
	for k, v in pairs(t) do&lt;br /&gt;
		ret[k] = v&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- removeDuplicates&lt;br /&gt;
--&lt;br /&gt;
-- This removes duplicate values from an array. Non-positive-integer keys are&lt;br /&gt;
-- ignored. The earliest value is kept, and all subsequent duplicate values are&lt;br /&gt;
-- removed, but otherwise the array order is unchanged.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.removeDuplicates(arr)&lt;br /&gt;
	checkType(&#039;removeDuplicates&#039;, 1, arr, &#039;table&#039;)&lt;br /&gt;
	local isNan = p.isNan&lt;br /&gt;
	local ret, exists = {}, {}&lt;br /&gt;
	for _, v in ipairs(arr) do&lt;br /&gt;
		if isNan(v) then&lt;br /&gt;
			-- NaNs can&#039;t be table keys, and they are also unique, so we don&#039;t need to check existence.&lt;br /&gt;
			ret[#ret + 1] = v&lt;br /&gt;
		elseif not exists[v] then&lt;br /&gt;
			ret[#ret + 1] = v&lt;br /&gt;
			exists[v] = true&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- numKeys&lt;br /&gt;
--&lt;br /&gt;
-- This takes a table and returns an array containing the numbers of any numerical&lt;br /&gt;
-- keys that have non-nil values, sorted in numerical order.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.numKeys(t)&lt;br /&gt;
	checkType(&#039;numKeys&#039;, 1, t, &#039;table&#039;)&lt;br /&gt;
	local isPositiveInteger = p.isPositiveInteger&lt;br /&gt;
	local nums = {}&lt;br /&gt;
	for k in pairs(t) do&lt;br /&gt;
		if isPositiveInteger(k) then&lt;br /&gt;
			nums[#nums + 1] = k&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	table.sort(nums)&lt;br /&gt;
	return nums&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- affixNums&lt;br /&gt;
--&lt;br /&gt;
-- This takes a table and returns an array containing the numbers of keys with the&lt;br /&gt;
-- specified prefix and suffix. For example, for the table&lt;br /&gt;
-- {a1 = &#039;foo&#039;, a3 = &#039;bar&#039;, a6 = &#039;baz&#039;} and the prefix &amp;quot;a&amp;quot;, affixNums will return&lt;br /&gt;
-- {1, 3, 6}.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.affixNums(t, prefix, suffix)&lt;br /&gt;
	checkType(&#039;affixNums&#039;, 1, t, &#039;table&#039;)&lt;br /&gt;
	checkType(&#039;affixNums&#039;, 2, prefix, &#039;string&#039;, true)&lt;br /&gt;
	checkType(&#039;affixNums&#039;, 3, suffix, &#039;string&#039;, true)&lt;br /&gt;
&lt;br /&gt;
	local function cleanPattern(s)&lt;br /&gt;
		-- Cleans a pattern so that the magic characters ()%.[]*+-?^$ are interpreted literally.&lt;br /&gt;
		return s:gsub(&#039;([%(%)%%%.%[%]%*%+%-%?%^%$])&#039;, &#039;%%%1&#039;)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	prefix = prefix or &#039;&#039;&lt;br /&gt;
	suffix = suffix or &#039;&#039;&lt;br /&gt;
	prefix = cleanPattern(prefix)&lt;br /&gt;
	suffix = cleanPattern(suffix)&lt;br /&gt;
	local pattern = &#039;^&#039; .. prefix .. &#039;([1-9]%d*)&#039; .. suffix .. &#039;$&#039;&lt;br /&gt;
&lt;br /&gt;
	local nums = {}&lt;br /&gt;
	for k in pairs(t) do&lt;br /&gt;
		if type(k) == &#039;string&#039; then&lt;br /&gt;
			local num = mw.ustring.match(k, pattern)&lt;br /&gt;
			if num then&lt;br /&gt;
				nums[#nums + 1] = tonumber(num)&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	table.sort(nums)&lt;br /&gt;
	return nums&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- numData&lt;br /&gt;
--&lt;br /&gt;
-- Given a table with keys like {&amp;quot;foo1&amp;quot;, &amp;quot;bar1&amp;quot;, &amp;quot;foo2&amp;quot;, &amp;quot;baz2&amp;quot;}, returns a table&lt;br /&gt;
-- of subtables in the format&lt;br /&gt;
-- {[1] = {foo = &#039;text&#039;, bar = &#039;text&#039;}, [2] = {foo = &#039;text&#039;, baz = &#039;text&#039;}}.&lt;br /&gt;
-- Keys that don&#039;t end with an integer are stored in a subtable named &amp;quot;other&amp;quot;. The&lt;br /&gt;
-- compress option compresses the table so that it can be iterated over with&lt;br /&gt;
-- ipairs.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.numData(t, compress)&lt;br /&gt;
	checkType(&#039;numData&#039;, 1, t, &#039;table&#039;)&lt;br /&gt;
	checkType(&#039;numData&#039;, 2, compress, &#039;boolean&#039;, true)&lt;br /&gt;
	local ret = {}&lt;br /&gt;
	for k, v in pairs(t) do&lt;br /&gt;
		local prefix, num = mw.ustring.match(tostring(k), &#039;^([^0-9]*)([1-9][0-9]*)$&#039;)&lt;br /&gt;
		if num then&lt;br /&gt;
			num = tonumber(num)&lt;br /&gt;
			local subtable = ret[num] or {}&lt;br /&gt;
			if prefix == &#039;&#039; then&lt;br /&gt;
				-- Positional parameters match the blank string; put them at the start of the subtable instead.&lt;br /&gt;
				prefix = 1&lt;br /&gt;
			end&lt;br /&gt;
			subtable[prefix] = v&lt;br /&gt;
			ret[num] = subtable&lt;br /&gt;
		else&lt;br /&gt;
			local subtable = ret.other or {}&lt;br /&gt;
			subtable[k] = v&lt;br /&gt;
			ret.other = subtable&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if compress then&lt;br /&gt;
		local other = ret.other&lt;br /&gt;
		ret = p.compressSparseArray(ret)&lt;br /&gt;
		ret.other = other&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- compressSparseArray&lt;br /&gt;
--&lt;br /&gt;
-- This takes an array with one or more nil values, and removes the nil values&lt;br /&gt;
-- while preserving the order, so that the array can be safely traversed with&lt;br /&gt;
-- ipairs.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.compressSparseArray(t)&lt;br /&gt;
	checkType(&#039;compressSparseArray&#039;, 1, t, &#039;table&#039;)&lt;br /&gt;
	local ret = {}&lt;br /&gt;
	local nums = p.numKeys(t)&lt;br /&gt;
	for _, num in ipairs(nums) do&lt;br /&gt;
		ret[#ret + 1] = t[num]&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- sparseIpairs&lt;br /&gt;
--&lt;br /&gt;
-- This is an iterator for sparse arrays. It can be used like ipairs, but can&lt;br /&gt;
-- handle nil values.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.sparseIpairs(t)&lt;br /&gt;
	checkType(&#039;sparseIpairs&#039;, 1, t, &#039;table&#039;)&lt;br /&gt;
	local nums = p.numKeys(t)&lt;br /&gt;
	local i = 0&lt;br /&gt;
	local lim = #nums&lt;br /&gt;
	return function ()&lt;br /&gt;
		i = i + 1&lt;br /&gt;
		if i &amp;lt;= lim then&lt;br /&gt;
			local key = nums[i]&lt;br /&gt;
			return key, t[key]&lt;br /&gt;
		else&lt;br /&gt;
			return nil, nil&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- size&lt;br /&gt;
--&lt;br /&gt;
-- This returns the size of a key/value pair table. It will also work on arrays,&lt;br /&gt;
-- but for arrays it is more efficient to use the # operator.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.size(t)&lt;br /&gt;
	checkType(&#039;size&#039;, 1, t, &#039;table&#039;)&lt;br /&gt;
	local i = 0&lt;br /&gt;
	for _ in pairs(t) do&lt;br /&gt;
		i = i + 1&lt;br /&gt;
	end&lt;br /&gt;
	return i&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function defaultKeySort(item1, item2)&lt;br /&gt;
	-- &amp;quot;number&amp;quot; &amp;lt; &amp;quot;string&amp;quot;, so numbers will be sorted before strings.&lt;br /&gt;
	local type1, type2 = type(item1), type(item2)&lt;br /&gt;
	if type1 ~= type2 then&lt;br /&gt;
		return type1 &amp;lt; type2&lt;br /&gt;
	elseif type1 == &#039;table&#039; or type1 == &#039;boolean&#039; or type1 == &#039;function&#039; then&lt;br /&gt;
		return tostring(item1) &amp;lt; tostring(item2)&lt;br /&gt;
	else&lt;br /&gt;
		return item1 &amp;lt; item2&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- keysToList&lt;br /&gt;
--&lt;br /&gt;
-- Returns an array of the keys in a table, sorted using either a default&lt;br /&gt;
-- comparison function or a custom keySort function.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.keysToList(t, keySort, checked)&lt;br /&gt;
	if not checked then&lt;br /&gt;
		checkType(&#039;keysToList&#039;, 1, t, &#039;table&#039;)&lt;br /&gt;
		checkTypeMulti(&#039;keysToList&#039;, 2, keySort, {&#039;function&#039;, &#039;boolean&#039;, &#039;nil&#039;})&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local arr = {}&lt;br /&gt;
	local index = 1&lt;br /&gt;
	for k in pairs(t) do&lt;br /&gt;
		arr[index] = k&lt;br /&gt;
		index = index + 1&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if keySort ~= false then&lt;br /&gt;
		keySort = type(keySort) == &#039;function&#039; and keySort or defaultKeySort&lt;br /&gt;
		table.sort(arr, keySort)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return arr&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- sortedPairs&lt;br /&gt;
--&lt;br /&gt;
-- Iterates through a table, with the keys sorted using the keysToList function.&lt;br /&gt;
-- If there are only numerical keys, sparseIpairs is probably more efficient.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.sortedPairs(t, keySort)&lt;br /&gt;
	checkType(&#039;sortedPairs&#039;, 1, t, &#039;table&#039;)&lt;br /&gt;
	checkType(&#039;sortedPairs&#039;, 2, keySort, &#039;function&#039;, true)&lt;br /&gt;
&lt;br /&gt;
	local arr = p.keysToList(t, keySort, true)&lt;br /&gt;
&lt;br /&gt;
	local i = 0&lt;br /&gt;
	return function ()&lt;br /&gt;
		i = i + 1&lt;br /&gt;
		local key = arr[i]&lt;br /&gt;
		if key ~= nil then&lt;br /&gt;
			return key, t[key]&lt;br /&gt;
		else&lt;br /&gt;
			return nil, nil&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- isArray&lt;br /&gt;
--&lt;br /&gt;
-- Returns true if the given value is a table and all keys are consecutive&lt;br /&gt;
-- integers starting at 1.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.isArray(v)&lt;br /&gt;
	if type(v) ~= &#039;table&#039; then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	local i = 0&lt;br /&gt;
	for _ in pairs(v) do&lt;br /&gt;
		i = i + 1&lt;br /&gt;
		if v[i] == nil then&lt;br /&gt;
			return false&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return true&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- isArrayLike&lt;br /&gt;
--&lt;br /&gt;
-- Returns true if the given value is iterable and all keys are consecutive&lt;br /&gt;
-- integers starting at 1.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.isArrayLike(v)&lt;br /&gt;
	if not pcall(pairs, v) then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	local i = 0&lt;br /&gt;
	for _ in pairs(v) do&lt;br /&gt;
		i = i + 1&lt;br /&gt;
		if v[i] == nil then&lt;br /&gt;
			return false&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return true&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- invert&lt;br /&gt;
--&lt;br /&gt;
-- Transposes the keys and values in an array. For example, {&amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;, &amp;quot;c&amp;quot;} -&amp;gt;&lt;br /&gt;
-- {a = 1, b = 2, c = 3}. Duplicates are not supported (result values refer to&lt;br /&gt;
-- the index of the last duplicate) and NaN values are ignored.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.invert(arr)&lt;br /&gt;
	checkType(&amp;quot;invert&amp;quot;, 1, arr, &amp;quot;table&amp;quot;)&lt;br /&gt;
	local isNan = p.isNan&lt;br /&gt;
	local map = {}&lt;br /&gt;
	for i, v in ipairs(arr) do&lt;br /&gt;
		if not isNan(v) then&lt;br /&gt;
			map[v] = i&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return map&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- listToSet&lt;br /&gt;
--&lt;br /&gt;
-- Creates a set from the array part of the table. Indexing the set by any of the&lt;br /&gt;
-- values of the array returns true. For example, {&amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;, &amp;quot;c&amp;quot;} -&amp;gt;&lt;br /&gt;
-- {a = true, b = true, c = true}. NaN values are ignored as Lua considers them&lt;br /&gt;
-- never equal to any value (including other NaNs or even themselves).&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.listToSet(arr)&lt;br /&gt;
	checkType(&amp;quot;listToSet&amp;quot;, 1, arr, &amp;quot;table&amp;quot;)&lt;br /&gt;
	local isNan = p.isNan&lt;br /&gt;
	local set = {}&lt;br /&gt;
	for _, v in ipairs(arr) do&lt;br /&gt;
		if not isNan(v) then&lt;br /&gt;
			set[v] = true&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return set&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- deepCopy&lt;br /&gt;
--&lt;br /&gt;
-- Recursive deep copy function. Preserves identities of subtables.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
local function _deepCopy(orig, includeMetatable, already_seen)&lt;br /&gt;
	if type(orig) ~= &amp;quot;table&amp;quot; then&lt;br /&gt;
		return orig&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- already_seen stores copies of tables indexed by the original table.&lt;br /&gt;
	local copy = already_seen[orig]&lt;br /&gt;
	if copy ~= nil then&lt;br /&gt;
		return copy&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	copy = {}&lt;br /&gt;
	already_seen[orig] = copy -- memoize before any recursion, to avoid infinite loops&lt;br /&gt;
	&lt;br /&gt;
	for orig_key, orig_value in pairs(orig) do&lt;br /&gt;
		copy[_deepCopy(orig_key, includeMetatable, already_seen)] = _deepCopy(orig_value, includeMetatable, already_seen)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	if includeMetatable then&lt;br /&gt;
		local mt = getmetatable(orig)&lt;br /&gt;
		if mt ~= nil then&lt;br /&gt;
			setmetatable(copy, _deepCopy(mt, true, already_seen))&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return copy&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.deepCopy(orig, noMetatable, already_seen)&lt;br /&gt;
	checkType(&amp;quot;deepCopy&amp;quot;, 3, already_seen, &amp;quot;table&amp;quot;, true)&lt;br /&gt;
	return _deepCopy(orig, not noMetatable, already_seen or {})&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- sparseConcat&lt;br /&gt;
--&lt;br /&gt;
-- Concatenates all values in the table that are indexed by a number, in order.&lt;br /&gt;
-- sparseConcat{a, nil, c, d}  =&amp;gt;  &amp;quot;acd&amp;quot;&lt;br /&gt;
-- sparseConcat{nil, b, c, d}  =&amp;gt;  &amp;quot;bcd&amp;quot;&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.sparseConcat(t, sep, i, j)&lt;br /&gt;
	local arr = {}&lt;br /&gt;
&lt;br /&gt;
	local arr_i = 0&lt;br /&gt;
	for _, v in p.sparseIpairs(t) do&lt;br /&gt;
		arr_i = arr_i + 1&lt;br /&gt;
		arr[arr_i] = v&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return table.concat(arr, sep, i, j)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- length&lt;br /&gt;
--&lt;br /&gt;
-- Finds the length of an array, or of a quasi-array with keys such as &amp;quot;data1&amp;quot;,&lt;br /&gt;
-- &amp;quot;data2&amp;quot;, etc., using an exponential search algorithm. It is similar to the&lt;br /&gt;
-- operator #, but may return a different value when there are gaps in the array&lt;br /&gt;
-- portion of the table. Intended to be used on data loaded with mw.loadData. For&lt;br /&gt;
-- other tables, use #.&lt;br /&gt;
-- Note: #frame.args in frame object always be set to 0, regardless of  the number&lt;br /&gt;
-- of unnamed template parameters, so use this function for frame.args.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.length(t, prefix)&lt;br /&gt;
	-- requiring module inline so that [[Module:Exponential search]] which is&lt;br /&gt;
	-- only needed by this one function doesn&#039;t get millions of transclusions&lt;br /&gt;
	local expSearch = require(&amp;quot;Module:Exponential search&amp;quot;)&lt;br /&gt;
	checkType(&#039;length&#039;, 1, t, &#039;table&#039;)&lt;br /&gt;
	checkType(&#039;length&#039;, 2, prefix, &#039;string&#039;, true)&lt;br /&gt;
	return expSearch(function (i)&lt;br /&gt;
		local key&lt;br /&gt;
		if prefix then&lt;br /&gt;
			key = prefix .. tostring(i)&lt;br /&gt;
		else&lt;br /&gt;
			key = i&lt;br /&gt;
		end&lt;br /&gt;
		return t[key] ~= nil&lt;br /&gt;
	end) or 0&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- inArray&lt;br /&gt;
--&lt;br /&gt;
-- Returns true if searchElement is a member of the array, and false otherwise.&lt;br /&gt;
-- Equivalent to JavaScript array.includes(searchElement) or&lt;br /&gt;
-- array.includes(searchElement, fromIndex), except fromIndex is 1 indexed&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.inArray(array, searchElement, fromIndex)&lt;br /&gt;
	checkType(&amp;quot;inArray&amp;quot;, 1, array, &amp;quot;table&amp;quot;)&lt;br /&gt;
	-- if searchElement is nil, error?&lt;br /&gt;
&lt;br /&gt;
	fromIndex = tonumber(fromIndex)&lt;br /&gt;
	if fromIndex then&lt;br /&gt;
		if (fromIndex &amp;lt; 0) then&lt;br /&gt;
			fromIndex = #array + fromIndex + 1&lt;br /&gt;
		end&lt;br /&gt;
		if fromIndex &amp;lt; 1 then fromIndex = 1 end&lt;br /&gt;
		for _, v in ipairs({unpack(array, fromIndex)}) do&lt;br /&gt;
			if v == searchElement then&lt;br /&gt;
				return true&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		for _, v in pairs(array) do&lt;br /&gt;
			if v == searchElement then&lt;br /&gt;
				return true&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return false&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- merge&lt;br /&gt;
--&lt;br /&gt;
-- Given the arrays, returns an array containing the elements of each input array&lt;br /&gt;
-- in sequence.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.merge(...)&lt;br /&gt;
	local arrays = {...}&lt;br /&gt;
	local ret = {}&lt;br /&gt;
	for i, arr in ipairs(arrays) do&lt;br /&gt;
		checkType(&#039;merge&#039;, i, arr, &#039;table&#039;)&lt;br /&gt;
		for _, v in ipairs(arr) do&lt;br /&gt;
			ret[#ret + 1] = v&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
-- extend&lt;br /&gt;
--&lt;br /&gt;
-- Extends the first array in place by appending all elements from the second&lt;br /&gt;
-- array.&lt;br /&gt;
------------------------------------------------------------------------------------&lt;br /&gt;
function p.extend(arr1, arr2)&lt;br /&gt;
	checkType(&#039;extend&#039;, 1, arr1, &#039;table&#039;)&lt;br /&gt;
	checkType(&#039;extend&#039;, 2, arr2, &#039;table&#039;)&lt;br /&gt;
&lt;br /&gt;
	for _, v in ipairs(arr2) do&lt;br /&gt;
		arr1[#arr1 + 1] = v&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=Module:List&amp;diff=141</id>
		<title>Module:List</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=Module:List&amp;diff=141"/>
		<updated>2026-04-15T05:27:59Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;local libUtil = require(&#039;libraryUtil&#039;)&lt;br /&gt;
local checkType = libUtil.checkType&lt;br /&gt;
local mTableTools = require(&#039;Module:TableTools&#039;)&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
local listTypes = {&lt;br /&gt;
	[&#039;bulleted&#039;] = true,&lt;br /&gt;
	[&#039;unbulleted&#039;] = true,&lt;br /&gt;
	[&#039;horizontal&#039;] = true,&lt;br /&gt;
	[&#039;ordered&#039;] = true,&lt;br /&gt;
	[&#039;horizontal_ordered&#039;] = true&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function p.makeListData(listType, args)&lt;br /&gt;
	-- Constructs a data table to be passed to p.renderList.&lt;br /&gt;
	local data = {}&lt;br /&gt;
&lt;br /&gt;
	-- Classes and TemplateStyles&lt;br /&gt;
	data.classes = {}&lt;br /&gt;
	data.templatestyles = &#039;&#039;&lt;br /&gt;
	if listType == &#039;horizontal&#039; or listType == &#039;horizontal_ordered&#039; then&lt;br /&gt;
		table.insert(data.classes, &#039;hlist&#039;)&lt;br /&gt;
		data.templatestyles = mw.getCurrentFrame():extensionTag{&lt;br /&gt;
			name = &#039;templatestyles&#039;, args = { src = &#039;Hlist/styles.css&#039; }&lt;br /&gt;
		}&lt;br /&gt;
	elseif listType == &#039;unbulleted&#039; then&lt;br /&gt;
		table.insert(data.classes, &#039;plainlist&#039;)&lt;br /&gt;
		data.templatestyles = mw.getCurrentFrame():extensionTag{&lt;br /&gt;
			name = &#039;templatestyles&#039;, args = { src = &#039;Plainlist/styles.css&#039; }&lt;br /&gt;
		}&lt;br /&gt;
	end&lt;br /&gt;
	table.insert(data.classes, args.class)&lt;br /&gt;
&lt;br /&gt;
	-- Main div style&lt;br /&gt;
	data.style = args.style&lt;br /&gt;
&lt;br /&gt;
	-- Indent for horizontal lists&lt;br /&gt;
	if listType == &#039;horizontal&#039; or listType == &#039;horizontal_ordered&#039; then&lt;br /&gt;
		local indent = tonumber(args.indent)&lt;br /&gt;
		indent = indent and indent * 1.6 or 0&lt;br /&gt;
		if indent &amp;gt; 0 then&lt;br /&gt;
			data.marginLeft = indent .. &#039;em&#039;&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- List style types for ordered lists&lt;br /&gt;
	-- This could be &amp;quot;1, 2, 3&amp;quot;, &amp;quot;a, b, c&amp;quot;, or a number of others. The list style&lt;br /&gt;
	-- type is either set by the &amp;quot;type&amp;quot; attribute or the &amp;quot;list-style-type&amp;quot; CSS&lt;br /&gt;
	-- property.&lt;br /&gt;
	if listType == &#039;ordered&#039; or listType == &#039;horizontal_ordered&#039; then &lt;br /&gt;
		data.listStyleType = args.list_style_type or args[&#039;list-style-type&#039;]&lt;br /&gt;
		data.type = args[&#039;type&#039;]&lt;br /&gt;
&lt;br /&gt;
		-- Detect invalid type attributes and attempt to convert them to&lt;br /&gt;
		-- list-style-type CSS properties.&lt;br /&gt;
		if data.type &lt;br /&gt;
			and not data.listStyleType&lt;br /&gt;
			and not tostring(data.type):find(&#039;^%s*[1AaIi]%s*$&#039;)&lt;br /&gt;
		then&lt;br /&gt;
			data.listStyleType = data.type&lt;br /&gt;
			data.type = nil&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- List tag type&lt;br /&gt;
	if listType == &#039;ordered&#039; or listType == &#039;horizontal_ordered&#039; then&lt;br /&gt;
		data.listTag = &#039;ol&#039;&lt;br /&gt;
	else&lt;br /&gt;
		data.listTag = &#039;ul&#039;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Start number for ordered lists&lt;br /&gt;
	data.start = args.start&lt;br /&gt;
	if listType == &#039;horizontal_ordered&#039; then&lt;br /&gt;
		-- Apply fix to get start numbers working with horizontal ordered lists.&lt;br /&gt;
		local startNum = tonumber(data.start)&lt;br /&gt;
		if startNum then&lt;br /&gt;
			data.counterReset = &#039;listitem &#039; .. tostring(startNum - 1)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- List style&lt;br /&gt;
	 -- ul_style and ol_style are included for backwards compatibility. No&lt;br /&gt;
	 -- distinction is made for ordered or unordered lists.&lt;br /&gt;
	data.listStyle = args.list_style&lt;br /&gt;
&lt;br /&gt;
	-- List items&lt;br /&gt;
	-- li_style is included for backwards compatibility. item_style was included&lt;br /&gt;
	-- to be easier to understand for non-coders.&lt;br /&gt;
	data.itemStyle = args.item_style or args.li_style&lt;br /&gt;
	data.items = {}&lt;br /&gt;
	for _, num in ipairs(mTableTools.numKeys(args)) do&lt;br /&gt;
		local item = {}&lt;br /&gt;
		item.content = args[num]&lt;br /&gt;
		item.style = args[&#039;item&#039; .. tostring(num) .. &#039;_style&#039;]&lt;br /&gt;
			or args[&#039;item_style&#039; .. tostring(num)]&lt;br /&gt;
		item.value = args[&#039;item&#039; .. tostring(num) .. &#039;_value&#039;]&lt;br /&gt;
			or args[&#039;item_value&#039; .. tostring(num)]&lt;br /&gt;
		table.insert(data.items, item)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return data&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.renderList(data)&lt;br /&gt;
	-- Renders the list HTML.&lt;br /&gt;
	&lt;br /&gt;
	-- Return the blank string if there are no list items.&lt;br /&gt;
	if type(data.items) ~= &#039;table&#039; or #data.items &amp;lt; 1 then&lt;br /&gt;
		return &#039;&#039;&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Render the main div tag.&lt;br /&gt;
	local root = mw.html.create(&#039;div&#039;)&lt;br /&gt;
	for _, class in ipairs(data.classes or {}) do&lt;br /&gt;
		root:addClass(class)&lt;br /&gt;
	end&lt;br /&gt;
	root:css{[&#039;margin-left&#039;] = data.marginLeft}&lt;br /&gt;
	if data.style then&lt;br /&gt;
		root:cssText(data.style)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Render the list tag.&lt;br /&gt;
	local list = root:tag(data.listTag or &#039;ul&#039;)&lt;br /&gt;
	list&lt;br /&gt;
		:attr{start = data.start, type = data.type}&lt;br /&gt;
		:css{&lt;br /&gt;
			[&#039;counter-reset&#039;] = data.counterReset,&lt;br /&gt;
			[&#039;list-style-type&#039;] = data.listStyleType&lt;br /&gt;
		}&lt;br /&gt;
	if data.listStyle then&lt;br /&gt;
		list:cssText(data.listStyle)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Render the list items&lt;br /&gt;
	for _, t in ipairs(data.items or {}) do&lt;br /&gt;
		local item = list:tag(&#039;li&#039;)&lt;br /&gt;
		if data.itemStyle then&lt;br /&gt;
			item:cssText(data.itemStyle)&lt;br /&gt;
		end&lt;br /&gt;
		if t.style then&lt;br /&gt;
			item:cssText(t.style)&lt;br /&gt;
		end&lt;br /&gt;
		item&lt;br /&gt;
			:attr{value = t.value}&lt;br /&gt;
			:wikitext(t.content)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return data.templatestyles .. tostring(root)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.renderTrackingCategories(args)&lt;br /&gt;
	local isDeprecated = false -- Tracks deprecated parameters.&lt;br /&gt;
	for k, v in pairs(args) do&lt;br /&gt;
		k = tostring(k)&lt;br /&gt;
		if k:find(&#039;^item_style%d+$&#039;) or k:find(&#039;^item_value%d+$&#039;) then&lt;br /&gt;
			isDeprecated = true&lt;br /&gt;
			break&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	local ret = &#039;&#039;&lt;br /&gt;
	if isDeprecated then&lt;br /&gt;
		ret = ret .. &#039;[[Category:Pages using module:list with deprecated parameters]]&#039;&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.makeList(listType, args)&lt;br /&gt;
	if not listType or not listTypes[listType] then&lt;br /&gt;
		error(string.format(&lt;br /&gt;
			&amp;quot;bad argument #1 to &#039;makeList&#039; (&#039;%s&#039; is not a valid list type)&amp;quot;,&lt;br /&gt;
			tostring(listType)&lt;br /&gt;
		), 2)&lt;br /&gt;
	end&lt;br /&gt;
	checkType(&#039;makeList&#039;, 2, args, &#039;table&#039;)&lt;br /&gt;
	local data = p.makeListData(listType, args)&lt;br /&gt;
	local list = p.renderList(data)&lt;br /&gt;
	local trackingCategories = p.renderTrackingCategories(args)&lt;br /&gt;
	return list .. trackingCategories&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
for listType in pairs(listTypes) do&lt;br /&gt;
	p[listType] = function (frame)&lt;br /&gt;
		local mArguments = require(&#039;Module:Arguments&#039;)&lt;br /&gt;
		local origArgs = mArguments.getArgs(frame, {&lt;br /&gt;
			frameOnly = ((frame and frame.args and frame.args.frameonly or &#039;&#039;) ~= &#039;&#039;),&lt;br /&gt;
			valueFunc = function (key, value)&lt;br /&gt;
			if not value or not mw.ustring.find(value, &#039;%S&#039;) then return nil end&lt;br /&gt;
			if mw.ustring.find(value, &#039;^%s*[%*#;:]&#039;) then&lt;br /&gt;
				return value&lt;br /&gt;
			else&lt;br /&gt;
				return value:match(&#039;^%s*(.-)%s*$&#039;)&lt;br /&gt;
			end&lt;br /&gt;
			return nil&lt;br /&gt;
		end&lt;br /&gt;
		})&lt;br /&gt;
		-- Copy all the arguments to a new table, for faster indexing.&lt;br /&gt;
		local args = {}&lt;br /&gt;
		for k, v in pairs(origArgs) do&lt;br /&gt;
			args[k] = v&lt;br /&gt;
		end&lt;br /&gt;
		return p.makeList(listType, args)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=Module:String&amp;diff=139</id>
		<title>Module:String</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=Module:String&amp;diff=139"/>
		<updated>2026-04-15T05:27:55Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;--[[&lt;br /&gt;
&lt;br /&gt;
This module is intended to provide access to basic string functions.&lt;br /&gt;
&lt;br /&gt;
Most of the functions provided here can be invoked with named parameters,&lt;br /&gt;
unnamed parameters, or a mixture.  If named parameters are used, Mediawiki will&lt;br /&gt;
automatically remove any leading or trailing whitespace from the parameter.&lt;br /&gt;
Depending on the intended use, it may be advantageous to either preserve or&lt;br /&gt;
remove such whitespace.&lt;br /&gt;
&lt;br /&gt;
Global options&lt;br /&gt;
    ignore_errors: If set to &#039;true&#039; or 1, any error condition will result in&lt;br /&gt;
        an empty string being returned rather than an error message.&lt;br /&gt;
&lt;br /&gt;
    error_category: If an error occurs, specifies the name of a category to&lt;br /&gt;
        include with the error message.  The default category is&lt;br /&gt;
        [Category:Errors reported by Module String].&lt;br /&gt;
&lt;br /&gt;
    no_category: If set to &#039;true&#039; or 1, no category will be added if an error&lt;br /&gt;
        is generated.&lt;br /&gt;
&lt;br /&gt;
Unit tests for this module are available at Module:String/tests.&lt;br /&gt;
]]&lt;br /&gt;
&lt;br /&gt;
local str = {}&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
len&lt;br /&gt;
&lt;br /&gt;
This function returns the length of the target string.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
{{#invoke:String|len|target_string|}}&lt;br /&gt;
OR&lt;br /&gt;
{{#invoke:String|len|s=target_string}}&lt;br /&gt;
&lt;br /&gt;
Parameters&lt;br /&gt;
    s: The string whose length to report&lt;br /&gt;
&lt;br /&gt;
If invoked using named parameters, Mediawiki will automatically remove any leading or&lt;br /&gt;
trailing whitespace from the target string.&lt;br /&gt;
]]&lt;br /&gt;
function str.len( frame )&lt;br /&gt;
	local new_args = str._getParameters( frame.args, {&#039;s&#039;} )&lt;br /&gt;
	local s = new_args[&#039;s&#039;] or &#039;&#039;&lt;br /&gt;
	return mw.ustring.len( s )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
sub&lt;br /&gt;
&lt;br /&gt;
This function returns a substring of the target string at specified indices.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
{{#invoke:String|sub|target_string|start_index|end_index}}&lt;br /&gt;
OR&lt;br /&gt;
{{#invoke:String|sub|s=target_string|i=start_index|j=end_index}}&lt;br /&gt;
&lt;br /&gt;
Parameters&lt;br /&gt;
    s: The string to return a subset of&lt;br /&gt;
    i: The first index of the substring to return, defaults to 1.&lt;br /&gt;
    j: The last index of the string to return, defaults to the last character.&lt;br /&gt;
&lt;br /&gt;
The first character of the string is assigned an index of 1.  If either i or j&lt;br /&gt;
is a negative value, it is interpreted the same as selecting a character by&lt;br /&gt;
counting from the end of the string.  Hence, a value of -1 is the same as&lt;br /&gt;
selecting the last character of the string.&lt;br /&gt;
&lt;br /&gt;
If the requested indices are out of range for the given string, an error is&lt;br /&gt;
reported.&lt;br /&gt;
]]&lt;br /&gt;
function str.sub( frame )&lt;br /&gt;
	local new_args = str._getParameters( frame.args, { &#039;s&#039;, &#039;i&#039;, &#039;j&#039; } )&lt;br /&gt;
	local s = new_args[&#039;s&#039;] or &#039;&#039;&lt;br /&gt;
	local i = tonumber( new_args[&#039;i&#039;] ) or 1&lt;br /&gt;
	local j = tonumber( new_args[&#039;j&#039;] ) or -1&lt;br /&gt;
&lt;br /&gt;
	local len = mw.ustring.len( s )&lt;br /&gt;
&lt;br /&gt;
	-- Convert negatives for range checking&lt;br /&gt;
	if i &amp;lt; 0 then&lt;br /&gt;
		i = len + i + 1&lt;br /&gt;
	end&lt;br /&gt;
	if j &amp;lt; 0 then&lt;br /&gt;
		j = len + j + 1&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if i &amp;gt; len or j &amp;gt; len or i &amp;lt; 1 or j &amp;lt; 1 then&lt;br /&gt;
		return str._error( &#039;String subset index out of range&#039; )&lt;br /&gt;
	end&lt;br /&gt;
	if j &amp;lt; i then&lt;br /&gt;
		return str._error( &#039;String subset indices out of order&#039; )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return mw.ustring.sub( s, i, j )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
This function implements that features of {{str sub old}} and is kept in order&lt;br /&gt;
to maintain these older templates.&lt;br /&gt;
]]&lt;br /&gt;
function str.sublength( frame )&lt;br /&gt;
	local i = tonumber( frame.args.i ) or 0&lt;br /&gt;
	local len = tonumber( frame.args.len )&lt;br /&gt;
	return mw.ustring.sub( frame.args.s, i + 1, len and ( i + len ) )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
_match&lt;br /&gt;
&lt;br /&gt;
This function returns a substring from the source string that matches a&lt;br /&gt;
specified pattern. It is exported for use in other modules&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
strmatch = require(&amp;quot;Module:String&amp;quot;)._match&lt;br /&gt;
sresult = strmatch( s, pattern, start, match, plain, nomatch )&lt;br /&gt;
&lt;br /&gt;
Parameters&lt;br /&gt;
    s: The string to search&lt;br /&gt;
    pattern: The pattern or string to find within the string&lt;br /&gt;
    start: The index within the source string to start the search.  The first&lt;br /&gt;
        character of the string has index 1.  Defaults to 1.&lt;br /&gt;
    match: In some cases it may be possible to make multiple matches on a single&lt;br /&gt;
        string.  This specifies which match to return, where the first match is&lt;br /&gt;
        match= 1.  If a negative number is specified then a match is returned&lt;br /&gt;
        counting from the last match.  Hence match = -1 is the same as requesting&lt;br /&gt;
        the last match.  Defaults to 1.&lt;br /&gt;
    plain: A flag indicating that the pattern should be understood as plain&lt;br /&gt;
        text.  Defaults to false.&lt;br /&gt;
    nomatch: If no match is found, output the &amp;quot;nomatch&amp;quot; value rather than an error.&lt;br /&gt;
&lt;br /&gt;
For information on constructing Lua patterns, a form of [regular expression], see:&lt;br /&gt;
&lt;br /&gt;
* http://www.lua.org/manual/5.1/manual.html#5.4.1&lt;br /&gt;
* http://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Patterns&lt;br /&gt;
* http://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Ustring_patterns&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
-- This sub-routine is exported for use in other modules&lt;br /&gt;
function str._match( s, pattern, start, match_index, plain_flag, nomatch )&lt;br /&gt;
	if s == &#039;&#039; then&lt;br /&gt;
		return str._error( &#039;Target string is empty&#039; )&lt;br /&gt;
	end&lt;br /&gt;
	if pattern == &#039;&#039; then&lt;br /&gt;
		return str._error( &#039;Pattern string is empty&#039; )&lt;br /&gt;
	end&lt;br /&gt;
	start = tonumber(start) or 1&lt;br /&gt;
	if math.abs(start) &amp;lt; 1 or math.abs(start) &amp;gt; mw.ustring.len( s ) then&lt;br /&gt;
		return str._error( &#039;Requested start is out of range&#039; )&lt;br /&gt;
	end&lt;br /&gt;
	if match_index == 0 then&lt;br /&gt;
		return str._error( &#039;Match index is out of range&#039; )&lt;br /&gt;
	end&lt;br /&gt;
	if plain_flag then&lt;br /&gt;
		pattern = str._escapePattern( pattern )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local result&lt;br /&gt;
	if match_index == 1 then&lt;br /&gt;
		-- Find first match is simple case&lt;br /&gt;
		result = mw.ustring.match( s, pattern, start )&lt;br /&gt;
	else&lt;br /&gt;
		if start &amp;gt; 1 then&lt;br /&gt;
			s = mw.ustring.sub( s, start )&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		local iterator = mw.ustring.gmatch(s, pattern)&lt;br /&gt;
		if match_index &amp;gt; 0 then&lt;br /&gt;
			-- Forward search&lt;br /&gt;
			for w in iterator do&lt;br /&gt;
				match_index = match_index - 1&lt;br /&gt;
				if match_index == 0 then&lt;br /&gt;
					result = w&lt;br /&gt;
					break&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			-- Reverse search&lt;br /&gt;
			local result_table = {}&lt;br /&gt;
			local count = 1&lt;br /&gt;
			for w in iterator do&lt;br /&gt;
				result_table[count] = w&lt;br /&gt;
				count = count + 1&lt;br /&gt;
			end&lt;br /&gt;
&lt;br /&gt;
			result = result_table[ count + match_index ]&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if result == nil then&lt;br /&gt;
		if nomatch == nil then&lt;br /&gt;
			return str._error( &#039;Match not found&#039; )&lt;br /&gt;
		else&lt;br /&gt;
			return nomatch&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		return result&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
match&lt;br /&gt;
&lt;br /&gt;
This function returns a substring from the source string that matches a&lt;br /&gt;
specified pattern.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
{{#invoke:String|match|source_string|pattern_string|start_index|match_number|plain_flag|nomatch_output}}&lt;br /&gt;
OR&lt;br /&gt;
{{#invoke:String|match|s=source_string|pattern=pattern_string|start=start_index&lt;br /&gt;
    |match=match_number|plain=plain_flag|nomatch=nomatch_output}}&lt;br /&gt;
&lt;br /&gt;
Parameters&lt;br /&gt;
    s: The string to search&lt;br /&gt;
    pattern: The pattern or string to find within the string&lt;br /&gt;
    start: The index within the source string to start the search.  The first&lt;br /&gt;
        character of the string has index 1.  Defaults to 1.&lt;br /&gt;
    match: In some cases it may be possible to make multiple matches on a single&lt;br /&gt;
        string.  This specifies which match to return, where the first match is&lt;br /&gt;
        match= 1.  If a negative number is specified then a match is returned&lt;br /&gt;
        counting from the last match.  Hence match = -1 is the same as requesting&lt;br /&gt;
        the last match.  Defaults to 1.&lt;br /&gt;
    plain: A flag indicating that the pattern should be understood as plain&lt;br /&gt;
        text.  Defaults to false.&lt;br /&gt;
    nomatch: If no match is found, output the &amp;quot;nomatch&amp;quot; value rather than an error.&lt;br /&gt;
&lt;br /&gt;
If invoked using named parameters, Mediawiki will automatically remove any leading or&lt;br /&gt;
trailing whitespace from each string.  In some circumstances this is desirable, in&lt;br /&gt;
other cases one may want to preserve the whitespace.&lt;br /&gt;
&lt;br /&gt;
If the match_number or start_index are out of range for the string being queried, then&lt;br /&gt;
this function generates an error.  An error is also generated if no match is found.&lt;br /&gt;
If one adds the parameter ignore_errors=true, then the error will be suppressed and&lt;br /&gt;
an empty string will be returned on any failure.&lt;br /&gt;
&lt;br /&gt;
For information on constructing Lua patterns, a form of [regular expression], see:&lt;br /&gt;
&lt;br /&gt;
* http://www.lua.org/manual/5.1/manual.html#5.4.1&lt;br /&gt;
* http://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Patterns&lt;br /&gt;
* http://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Ustring_patterns&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
-- This is the entry point for #invoke:String|match&lt;br /&gt;
function str.match( frame )&lt;br /&gt;
	local new_args = str._getParameters( frame.args, {&#039;s&#039;, &#039;pattern&#039;, &#039;start&#039;, &#039;match&#039;, &#039;plain&#039;, &#039;nomatch&#039;} )&lt;br /&gt;
	local s = new_args[&#039;s&#039;] or &#039;&#039;&lt;br /&gt;
	local start = tonumber( new_args[&#039;start&#039;] ) or 1&lt;br /&gt;
	local plain_flag = str._getBoolean( new_args[&#039;plain&#039;] or false )&lt;br /&gt;
	local pattern = new_args[&#039;pattern&#039;] or &#039;&#039;&lt;br /&gt;
	local match_index = math.floor( tonumber(new_args[&#039;match&#039;]) or 1 )&lt;br /&gt;
	local nomatch = new_args[&#039;nomatch&#039;]&lt;br /&gt;
&lt;br /&gt;
	return str._match( s, pattern, start, match_index, plain_flag, nomatch )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
pos&lt;br /&gt;
&lt;br /&gt;
This function returns a single character from the target string at position pos.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
{{#invoke:String|pos|target_string|index_value}}&lt;br /&gt;
OR&lt;br /&gt;
{{#invoke:String|pos|target=target_string|pos=index_value}}&lt;br /&gt;
&lt;br /&gt;
Parameters&lt;br /&gt;
    target: The string to search&lt;br /&gt;
    pos: The index for the character to return&lt;br /&gt;
&lt;br /&gt;
If invoked using named parameters, Mediawiki will automatically remove any leading or&lt;br /&gt;
trailing whitespace from the target string.  In some circumstances this is desirable, in&lt;br /&gt;
other cases one may want to preserve the whitespace.&lt;br /&gt;
&lt;br /&gt;
The first character has an index value of 1.&lt;br /&gt;
&lt;br /&gt;
If one requests a negative value, this function will select a character by counting backwards&lt;br /&gt;
from the end of the string.  In other words pos = -1 is the same as asking for the last character.&lt;br /&gt;
&lt;br /&gt;
A requested value of zero, or a value greater than the length of the string returns an error.&lt;br /&gt;
]]&lt;br /&gt;
function str.pos( frame )&lt;br /&gt;
	local new_args = str._getParameters( frame.args, {&#039;target&#039;, &#039;pos&#039;} )&lt;br /&gt;
	local target_str = new_args[&#039;target&#039;] or &#039;&#039;&lt;br /&gt;
	local pos = tonumber( new_args[&#039;pos&#039;] ) or 0&lt;br /&gt;
&lt;br /&gt;
	if pos == 0 or math.abs(pos) &amp;gt; mw.ustring.len( target_str ) then&lt;br /&gt;
		return str._error( &#039;String index out of range&#039; )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return mw.ustring.sub( target_str, pos, pos )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
str_find&lt;br /&gt;
&lt;br /&gt;
This function duplicates the behavior of {{str_find}}, including all of its quirks.&lt;br /&gt;
This is provided in order to support existing templates, but is NOT RECOMMENDED for&lt;br /&gt;
new code and templates.  New code is recommended to use the &amp;quot;find&amp;quot; function instead.&lt;br /&gt;
&lt;br /&gt;
Returns the first index in &amp;quot;source&amp;quot; that is a match to &amp;quot;target&amp;quot;.  Indexing is 1-based,&lt;br /&gt;
and the function returns -1 if the &amp;quot;target&amp;quot; string is not present in &amp;quot;source&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Important Note: If the &amp;quot;target&amp;quot; string is empty / missing, this function returns a&lt;br /&gt;
value of &amp;quot;1&amp;quot;, which is generally unexpected behavior, and must be accounted for&lt;br /&gt;
separatetly.&lt;br /&gt;
]]&lt;br /&gt;
function str.str_find( frame )&lt;br /&gt;
	local new_args = str._getParameters( frame.args, {&#039;source&#039;, &#039;target&#039;} )&lt;br /&gt;
	local source_str = new_args[&#039;source&#039;] or &#039;&#039;&lt;br /&gt;
	local target_str = new_args[&#039;target&#039;] or &#039;&#039;&lt;br /&gt;
&lt;br /&gt;
	if target_str == &#039;&#039; then&lt;br /&gt;
		return 1&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local start = mw.ustring.find( source_str, target_str, 1, true )&lt;br /&gt;
	if start == nil then&lt;br /&gt;
		start = -1&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return start&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
find&lt;br /&gt;
&lt;br /&gt;
This function allows one to search for a target string or pattern within another&lt;br /&gt;
string.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
{{#invoke:String|find|source_str|target_string|start_index|plain_flag}}&lt;br /&gt;
OR&lt;br /&gt;
{{#invoke:String|find|source=source_str|target=target_str|start=start_index|plain=plain_flag}}&lt;br /&gt;
&lt;br /&gt;
Parameters&lt;br /&gt;
    source: The string to search&lt;br /&gt;
    target: The string or pattern to find within source&lt;br /&gt;
    start: The index within the source string to start the search, defaults to 1&lt;br /&gt;
    plain: Boolean flag indicating that target should be understood as plain&lt;br /&gt;
        text and not as a Lua style regular expression, defaults to true&lt;br /&gt;
&lt;br /&gt;
If invoked using named parameters, Mediawiki will automatically remove any leading or&lt;br /&gt;
trailing whitespace from the parameter.  In some circumstances this is desirable, in&lt;br /&gt;
other cases one may want to preserve the whitespace.&lt;br /&gt;
&lt;br /&gt;
This function returns the first index &amp;gt;= &amp;quot;start&amp;quot; where &amp;quot;target&amp;quot; can be found&lt;br /&gt;
within &amp;quot;source&amp;quot;.  Indices are 1-based.  If &amp;quot;target&amp;quot; is not found, then this&lt;br /&gt;
function returns 0.  If either &amp;quot;source&amp;quot; or &amp;quot;target&amp;quot; are missing / empty, this&lt;br /&gt;
function also returns 0.&lt;br /&gt;
&lt;br /&gt;
This function should be safe for UTF-8 strings.&lt;br /&gt;
]]&lt;br /&gt;
function str.find( frame )&lt;br /&gt;
	local new_args = str._getParameters( frame.args, {&#039;source&#039;, &#039;target&#039;, &#039;start&#039;, &#039;plain&#039; } )&lt;br /&gt;
	local source_str = new_args[&#039;source&#039;] or &#039;&#039;&lt;br /&gt;
	local pattern = new_args[&#039;target&#039;] or &#039;&#039;&lt;br /&gt;
	local start_pos = tonumber(new_args[&#039;start&#039;]) or 1&lt;br /&gt;
	local plain = new_args[&#039;plain&#039;] or true&lt;br /&gt;
&lt;br /&gt;
	if source_str == &#039;&#039; or pattern == &#039;&#039; then&lt;br /&gt;
		return 0&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	plain = str._getBoolean( plain )&lt;br /&gt;
&lt;br /&gt;
	local start = mw.ustring.find( source_str, pattern, start_pos, plain )&lt;br /&gt;
	if start == nil then&lt;br /&gt;
		start = 0&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return start&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
replace&lt;br /&gt;
&lt;br /&gt;
This function allows one to replace a target string or pattern within another&lt;br /&gt;
string.&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
{{#invoke:String|replace|source_str|pattern_string|replace_string|replacement_count|plain_flag}}&lt;br /&gt;
OR&lt;br /&gt;
{{#invoke:String|replace|source=source_string|pattern=pattern_string|replace=replace_string|&lt;br /&gt;
   count=replacement_count|plain=plain_flag}}&lt;br /&gt;
&lt;br /&gt;
Parameters&lt;br /&gt;
    source: The string to search&lt;br /&gt;
    pattern: The string or pattern to find within source&lt;br /&gt;
    replace: The replacement text&lt;br /&gt;
    count: The number of occurences to replace, defaults to all.&lt;br /&gt;
    plain: Boolean flag indicating that pattern should be understood as plain&lt;br /&gt;
        text and not as a Lua style regular expression, defaults to true&lt;br /&gt;
]]&lt;br /&gt;
function str.replace( frame )&lt;br /&gt;
	local new_args = str._getParameters( frame.args, {&#039;source&#039;, &#039;pattern&#039;, &#039;replace&#039;, &#039;count&#039;, &#039;plain&#039; } )&lt;br /&gt;
	local source_str = new_args[&#039;source&#039;] or &#039;&#039;&lt;br /&gt;
	local pattern = new_args[&#039;pattern&#039;] or &#039;&#039;&lt;br /&gt;
	local replace = new_args[&#039;replace&#039;] or &#039;&#039;&lt;br /&gt;
	local count = tonumber( new_args[&#039;count&#039;] )&lt;br /&gt;
	local plain = new_args[&#039;plain&#039;] or true&lt;br /&gt;
&lt;br /&gt;
	if source_str == &#039;&#039; or pattern == &#039;&#039; then&lt;br /&gt;
		return source_str&lt;br /&gt;
	end&lt;br /&gt;
	plain = str._getBoolean( plain )&lt;br /&gt;
&lt;br /&gt;
	if plain then&lt;br /&gt;
		pattern = str._escapePattern( pattern )&lt;br /&gt;
		replace = string.gsub( replace, &amp;quot;%%&amp;quot;, &amp;quot;%%%%&amp;quot; ) --Only need to escape replacement sequences.&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local result&lt;br /&gt;
&lt;br /&gt;
	if count ~= nil then&lt;br /&gt;
		result = mw.ustring.gsub( source_str, pattern, replace, count )&lt;br /&gt;
	else&lt;br /&gt;
		result = mw.ustring.gsub( source_str, pattern, replace )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return result&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
    simple function to pipe string.rep to templates.&lt;br /&gt;
]]&lt;br /&gt;
function str.rep( frame )&lt;br /&gt;
	local repetitions = tonumber( frame.args[2] )&lt;br /&gt;
	if not repetitions then&lt;br /&gt;
		return str._error( &#039;function rep expects a number as second parameter, received &amp;quot;&#039; .. ( frame.args[2] or &#039;&#039; ) .. &#039;&amp;quot;&#039; )&lt;br /&gt;
	end&lt;br /&gt;
	return string.rep( frame.args[1] or &#039;&#039;, repetitions )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
escapePattern&lt;br /&gt;
&lt;br /&gt;
This function escapes special characters from a Lua string pattern. See [1]&lt;br /&gt;
for details on how patterns work.&lt;br /&gt;
&lt;br /&gt;
[1] https://www.mediawiki.org/wiki/Extension:Scribunto/Lua_reference_manual#Patterns&lt;br /&gt;
&lt;br /&gt;
Usage:&lt;br /&gt;
{{#invoke:String|escapePattern|pattern_string}}&lt;br /&gt;
&lt;br /&gt;
Parameters&lt;br /&gt;
    pattern_string: The pattern string to escape.&lt;br /&gt;
]]&lt;br /&gt;
function str.escapePattern( frame )&lt;br /&gt;
	local pattern_str = frame.args[1]&lt;br /&gt;
	if not pattern_str then&lt;br /&gt;
		return str._error( &#039;No pattern string specified&#039; )&lt;br /&gt;
	end&lt;br /&gt;
	local result = str._escapePattern( pattern_str )&lt;br /&gt;
	return result&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
count&lt;br /&gt;
This function counts the number of occurrences of one string in another.&lt;br /&gt;
]]&lt;br /&gt;
function str.count(frame)&lt;br /&gt;
	local args = str._getParameters(frame.args, {&#039;source&#039;, &#039;pattern&#039;, &#039;plain&#039;})&lt;br /&gt;
	local source = args.source or &#039;&#039;&lt;br /&gt;
	local pattern = args.pattern or &#039;&#039;&lt;br /&gt;
	local plain = str._getBoolean(args.plain or true)&lt;br /&gt;
	if plain then&lt;br /&gt;
		pattern = str._escapePattern(pattern)&lt;br /&gt;
	end&lt;br /&gt;
	local _, count = mw.ustring.gsub(source, pattern, &#039;&#039;)&lt;br /&gt;
	return count&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
endswith&lt;br /&gt;
This function determines whether a string ends with another string.&lt;br /&gt;
]]&lt;br /&gt;
function str.endswith(frame)&lt;br /&gt;
	local args = str._getParameters(frame.args, {&#039;source&#039;, &#039;pattern&#039;})&lt;br /&gt;
	local source = args.source or &#039;&#039;&lt;br /&gt;
	local pattern = args.pattern or &#039;&#039;&lt;br /&gt;
	if pattern == &#039;&#039; then&lt;br /&gt;
		-- All strings end with the empty string.&lt;br /&gt;
		return &amp;quot;yes&amp;quot;&lt;br /&gt;
	end&lt;br /&gt;
	if mw.ustring.sub(source, -mw.ustring.len(pattern), -1) == pattern then&lt;br /&gt;
		return &amp;quot;yes&amp;quot;&lt;br /&gt;
	else&lt;br /&gt;
		return &amp;quot;&amp;quot;&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
join&lt;br /&gt;
&lt;br /&gt;
Join all non empty arguments together; the first argument is the separator.&lt;br /&gt;
Usage:&lt;br /&gt;
{{#invoke:String|join|sep|one|two|three}}&lt;br /&gt;
]]&lt;br /&gt;
function str.join(frame)&lt;br /&gt;
	local args = {}&lt;br /&gt;
	local sep&lt;br /&gt;
	for _, v in ipairs( frame.args ) do&lt;br /&gt;
		if sep then&lt;br /&gt;
			if v ~= &#039;&#039; then&lt;br /&gt;
				table.insert(args, v)&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			sep = v&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return table.concat( args, sep or &#039;&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- findpagetext returns the position of a piece of text in a page&lt;br /&gt;
-- First positional parameter or |text is the search text&lt;br /&gt;
-- Optional parameter |title is the page title, defaults to current page&lt;br /&gt;
-- Optional parameter |plain is either true for plain search (default) or false for Lua pattern search&lt;br /&gt;
-- Optional parameter |nomatch is the return value when no match is found; default is nil&lt;br /&gt;
function str._findpagetext(args)&lt;br /&gt;
	-- process parameters&lt;br /&gt;
	local nomatch = args.nomatch or &amp;quot;&amp;quot;&lt;br /&gt;
	if nomatch == &amp;quot;&amp;quot; then nomatch = nil end&lt;br /&gt;
	--&lt;br /&gt;
	local text = mw.text.trim(args[1] or args.text or &amp;quot;&amp;quot;)&lt;br /&gt;
	if text == &amp;quot;&amp;quot; then return nil end&lt;br /&gt;
	--&lt;br /&gt;
	local title = args.title or &amp;quot;&amp;quot;&lt;br /&gt;
	local titleobj&lt;br /&gt;
	if title == &amp;quot;&amp;quot; then&lt;br /&gt;
		titleobj = mw.title.getCurrentTitle()&lt;br /&gt;
	else&lt;br /&gt;
		titleobj = mw.title.new(title)&lt;br /&gt;
	end&lt;br /&gt;
	--&lt;br /&gt;
	local plain = args.plain or &amp;quot;&amp;quot;&lt;br /&gt;
	if plain:sub(1, 1) == &amp;quot;f&amp;quot; then plain = false else plain = true end&lt;br /&gt;
	-- get the page content and look for &#039;text&#039; - return position or nomatch&lt;br /&gt;
	local content = titleobj and titleobj:getContent()&lt;br /&gt;
	return content and mw.ustring.find(content, text, 1, plain) or nomatch&lt;br /&gt;
end&lt;br /&gt;
function str.findpagetext(frame)&lt;br /&gt;
	local args = frame.args&lt;br /&gt;
	local pargs = frame:getParent().args&lt;br /&gt;
	for k, v in pairs(pargs) do&lt;br /&gt;
		args[k] = v&lt;br /&gt;
	end&lt;br /&gt;
	if not (args[1] or args.text) then return nil end&lt;br /&gt;
	-- just the first value&lt;br /&gt;
	return (str._findpagetext(args))&lt;br /&gt;
end&lt;br /&gt;
--[[&lt;br /&gt;
Helper function that populates the argument list given that user may need to use a mix of&lt;br /&gt;
named and unnamed parameters.  This is relevant because named parameters are not&lt;br /&gt;
identical to unnamed parameters due to string trimming, and when dealing with strings&lt;br /&gt;
we sometimes want to either preserve or remove that whitespace depending on the application.&lt;br /&gt;
]]&lt;br /&gt;
function str._getParameters( frame_args, arg_list )&lt;br /&gt;
	local new_args = {}&lt;br /&gt;
	local index = 1&lt;br /&gt;
	local value&lt;br /&gt;
&lt;br /&gt;
	for _, arg in ipairs( arg_list ) do&lt;br /&gt;
		value = frame_args[arg]&lt;br /&gt;
		if value == nil then&lt;br /&gt;
			value = frame_args[index]&lt;br /&gt;
			index = index + 1&lt;br /&gt;
		end&lt;br /&gt;
		new_args[arg] = value&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return new_args&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
Helper function to handle error messages.&lt;br /&gt;
]]&lt;br /&gt;
function str._error( error_str )&lt;br /&gt;
	local frame = mw.getCurrentFrame()&lt;br /&gt;
	local error_category = frame.args.error_category or &#039;Errors reported by Module String&#039;&lt;br /&gt;
	local ignore_errors = frame.args.ignore_errors or false&lt;br /&gt;
	local no_category = frame.args.no_category or false&lt;br /&gt;
&lt;br /&gt;
	if str._getBoolean(ignore_errors) then&lt;br /&gt;
		return &#039;&#039;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local error_str = &#039;&amp;lt;strong class=&amp;quot;error&amp;quot;&amp;gt;String Module Error: &#039; .. error_str .. &#039;&amp;lt;/strong&amp;gt;&#039;&lt;br /&gt;
	if error_category ~= &#039;&#039; and not str._getBoolean( no_category ) then&lt;br /&gt;
		error_str = &#039;[[Category:&#039; .. error_category .. &#039;]]&#039; .. error_str&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return error_str&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
Helper Function to interpret boolean strings&lt;br /&gt;
]]&lt;br /&gt;
function str._getBoolean( boolean_str )&lt;br /&gt;
	local boolean_value&lt;br /&gt;
&lt;br /&gt;
	if type( boolean_str ) == &#039;string&#039; then&lt;br /&gt;
		boolean_str = boolean_str:lower()&lt;br /&gt;
		if boolean_str == &#039;false&#039; or boolean_str == &#039;no&#039; or boolean_str == &#039;0&#039;&lt;br /&gt;
				or boolean_str == &#039;&#039; then&lt;br /&gt;
			boolean_value = false&lt;br /&gt;
		else&lt;br /&gt;
			boolean_value = true&lt;br /&gt;
		end&lt;br /&gt;
	elseif type( boolean_str ) == &#039;boolean&#039; then&lt;br /&gt;
		boolean_value = boolean_str&lt;br /&gt;
	else&lt;br /&gt;
		error( &#039;No boolean value found&#039; )&lt;br /&gt;
	end&lt;br /&gt;
	return boolean_value&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
Helper function that escapes all pattern characters so that they will be treated&lt;br /&gt;
as plain text.&lt;br /&gt;
]]&lt;br /&gt;
function str._escapePattern( pattern_str )&lt;br /&gt;
	return ( string.gsub( pattern_str, &amp;quot;[%(%)%.%%%+%-%*%?%[%^%$%]]&amp;quot;, &amp;quot;%%%0&amp;quot; ) )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return str&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=Module:Check_for_unknown_parameters&amp;diff=137</id>
		<title>Module:Check for unknown parameters</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=Module:Check_for_unknown_parameters&amp;diff=137"/>
		<updated>2026-04-15T05:27:51Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- This module may be used to compare the arguments passed to the parent&lt;br /&gt;
-- with a list of arguments, returning a specified result if an argument is&lt;br /&gt;
-- not on the list&lt;br /&gt;
&lt;br /&gt;
require (&#039;strict&#039;);&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
local mapframe_params = {&lt;br /&gt;
	&#039;coord&#039;,&lt;br /&gt;
	&#039;coordinates&#039;,&lt;br /&gt;
	&#039;id&#039;,&lt;br /&gt;
	&#039;qid&#039;,&lt;br /&gt;
	&#039;mapframe&#039;,&lt;br /&gt;
	&#039;mapframe-area_km2&#039;,&lt;br /&gt;
	&#039;mapframe-area_mi2&#039;,&lt;br /&gt;
	&#039;mapframe-caption&#039;,&lt;br /&gt;
	&#039;mapframe-coord&#039;,&lt;br /&gt;
	&#039;mapframe-coordinates&#039;,&lt;br /&gt;
	&#039;mapframe-custom&#039;,&lt;br /&gt;
	&#039;mapframe-frame-coord&#039;,&lt;br /&gt;
	&#039;mapframe-frame-coordinates&#039;,&lt;br /&gt;
	&#039;mapframe-frame-height&#039;,&lt;br /&gt;
	&#039;mapframe-frame-width&#039;,&lt;br /&gt;
	&#039;mapframe-geomask&#039;,&lt;br /&gt;
	&#039;mapframe-geomask-fill&#039;,&lt;br /&gt;
	&#039;mapframe-geomask-fill-opacity&#039;,&lt;br /&gt;
	&#039;mapframe-geomask-stroke-color&#039;,&lt;br /&gt;
	&#039;mapframe-geomask-stroke-colour&#039;,&lt;br /&gt;
	&#039;mapframe-geomask-stroke-width&#039;,&lt;br /&gt;
	&#039;mapframe-height&#039;,&lt;br /&gt;
	&#039;mapframe-id&#039;,&lt;br /&gt;
	&#039;mapframe-length_km&#039;,&lt;br /&gt;
	&#039;mapframe-length_mi&#039;,&lt;br /&gt;
	&#039;mapframe-line&#039;,&lt;br /&gt;
	&#039;mapframe-line-stroke-color&#039;,&lt;br /&gt;
	&#039;mapframe-line-stroke-colour&#039;,&lt;br /&gt;
	&#039;mapframe-marker&#039;,&lt;br /&gt;
	&#039;mapframe-marker-color&#039;,&lt;br /&gt;
	&#039;mapframe-marker-colour&#039;,&lt;br /&gt;
	&#039;mapframe-point&#039;,&lt;br /&gt;
	&#039;mapframe-population&#039;,&lt;br /&gt;
	&#039;mapframe-shape&#039;,&lt;br /&gt;
	&#039;mapframe-shape-fill&#039;,&lt;br /&gt;
	&#039;mapframe-shape-fill-opacity&#039;,&lt;br /&gt;
	&#039;mapframe-shape-stroke-color&#039;,&lt;br /&gt;
	&#039;mapframe-shape-stroke-colour&#039;,&lt;br /&gt;
	&#039;mapframe-stroke-color&#039;,&lt;br /&gt;
	&#039;mapframe-stroke-colour&#039;,&lt;br /&gt;
	&#039;mapframe-stroke-width&#039;,&lt;br /&gt;
	&#039;mapframe-switcher&#039;,&lt;br /&gt;
	&#039;mapframe-type&#039;,&lt;br /&gt;
	&#039;mapframe-width&#039;,&lt;br /&gt;
	&#039;mapframe-wikidata&#039;,&lt;br /&gt;
	&#039;mapframe-zoom&#039;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
local function trim(s)&lt;br /&gt;
	return s:match(&#039;^%s*(.-)%s*$&#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function isnotempty(s)&lt;br /&gt;
	return s and s:match(&#039;%S&#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function clean(text)&lt;br /&gt;
	-- Return text cleaned for display and truncated if too long.&lt;br /&gt;
	-- Strip markers are replaced with dummy text representing the original wikitext.&lt;br /&gt;
	local pos, truncated&lt;br /&gt;
	local function truncate(text)&lt;br /&gt;
		if truncated then&lt;br /&gt;
			return &#039;&#039;&lt;br /&gt;
		end&lt;br /&gt;
		if mw.ustring.len(text) &amp;gt; 25 then&lt;br /&gt;
			truncated = true&lt;br /&gt;
			text = mw.ustring.sub(text, 1, 25) .. &#039;...&#039;&lt;br /&gt;
		end&lt;br /&gt;
		return mw.text.nowiki(text)&lt;br /&gt;
	end&lt;br /&gt;
	local parts = {}&lt;br /&gt;
	for before, tag, remainder in text:gmatch(&#039;([^\127]*)\127[^\127]*%-(%l+)%-[^\127]*\127()&#039;) do&lt;br /&gt;
		pos = remainder&lt;br /&gt;
		table.insert(parts, truncate(before) .. &#039;&amp;amp;lt;&#039; .. tag .. &#039;&amp;amp;gt;...&amp;amp;lt;/&#039; .. tag .. &#039;&amp;amp;gt;&#039;)&lt;br /&gt;
	end&lt;br /&gt;
	table.insert(parts, truncate(text:sub(pos or 1)))&lt;br /&gt;
	return table.concat(parts)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p._check(args, pargs)&lt;br /&gt;
	if type(args) ~= &amp;quot;table&amp;quot; or type(pargs) ~= &amp;quot;table&amp;quot; then&lt;br /&gt;
		-- TODO: error handling&lt;br /&gt;
		return&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- create the list of known args, regular expressions, and the return string&lt;br /&gt;
	local knownargs = {}&lt;br /&gt;
	&lt;br /&gt;
	if isnotempty(args[&#039;mapframe_args&#039;]) then&lt;br /&gt;
		for _, v in ipairs(mapframe_params) do&lt;br /&gt;
    		knownargs[v] = 1&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local regexps = {}&lt;br /&gt;
	for k, v in pairs(args) do&lt;br /&gt;
		if type(k) == &#039;number&#039; then&lt;br /&gt;
			v = trim(v)&lt;br /&gt;
			knownargs[v] = 1&lt;br /&gt;
		elseif k:find(&#039;^regexp[1-9][0-9]*$&#039;) then&lt;br /&gt;
			table.insert(regexps, &#039;^&#039; .. v .. &#039;$&#039;)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- loop over the parent args, and make sure they are on the list&lt;br /&gt;
	local ignoreblank = isnotempty(args[&#039;ignoreblank&#039;])&lt;br /&gt;
	local showblankpos = isnotempty(args[&#039;showblankpositional&#039;])&lt;br /&gt;
	local values = {}&lt;br /&gt;
	for k, v in pairs(pargs) do&lt;br /&gt;
		if type(k) == &#039;string&#039; and knownargs[k] == nil then&lt;br /&gt;
			local knownflag = false&lt;br /&gt;
			for _, regexp in ipairs(regexps) do&lt;br /&gt;
				if mw.ustring.match(k, regexp) then&lt;br /&gt;
					knownflag = true&lt;br /&gt;
					break&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
			if not knownflag and ( not ignoreblank or isnotempty(v) )  then&lt;br /&gt;
				table.insert(values, clean(k))&lt;br /&gt;
			end&lt;br /&gt;
		elseif type(k) == &#039;number&#039; and knownargs[tostring(k)] == nil then&lt;br /&gt;
			local knownflag = false&lt;br /&gt;
			for _, regexp in ipairs(regexps) do&lt;br /&gt;
				if mw.ustring.match(tostring(k), regexp) then&lt;br /&gt;
					knownflag = true&lt;br /&gt;
					break&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
			if not knownflag and ( showblankpos or isnotempty(v) ) then&lt;br /&gt;
				table.insert(values, k .. &#039; = &#039; .. clean(v))&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- add results to the output tables&lt;br /&gt;
	local res = {}&lt;br /&gt;
	if #values &amp;gt; 0 then&lt;br /&gt;
		local unknown_text = args[&#039;unknown&#039;] or &#039;Found _VALUE_, &#039;&lt;br /&gt;
&lt;br /&gt;
		if mw.getCurrentFrame():preprocess( &amp;quot;{{REVISIONID}}&amp;quot; ) == &amp;quot;&amp;quot; then&lt;br /&gt;
			local preview_text = args[&#039;preview&#039;]&lt;br /&gt;
			if isnotempty(preview_text) then&lt;br /&gt;
				preview_text = require(&#039;Module:If preview&#039;)._warning({preview_text})&lt;br /&gt;
			elseif preview_text == nil then&lt;br /&gt;
				preview_text = unknown_text&lt;br /&gt;
			end&lt;br /&gt;
			unknown_text = preview_text&lt;br /&gt;
		end&lt;br /&gt;
		for _, v in pairs(values) do&lt;br /&gt;
			-- Fix odd bug for | = which gets stripped to the empty string and&lt;br /&gt;
			-- breaks category links&lt;br /&gt;
			if v == &#039;&#039; then v = &#039; &#039; end&lt;br /&gt;
&lt;br /&gt;
			-- avoid error with v = &#039;example%2&#039; (&amp;quot;invalid capture index&amp;quot;)&lt;br /&gt;
			local r = unknown_text:gsub(&#039;_VALUE_&#039;, {_VALUE_ = v})&lt;br /&gt;
			table.insert(res, r)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return table.concat(res)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.check(frame)&lt;br /&gt;
	local args = frame.args&lt;br /&gt;
	local pargs = frame:getParent().args&lt;br /&gt;
	return p._check(args, pargs)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=Template:Main_other&amp;diff=135</id>
		<title>Template:Main other</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=Template:Main_other&amp;diff=135"/>
		<updated>2026-04-15T05:27:48Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{safesubst:&amp;lt;noinclude/&amp;gt;#switch:&lt;br /&gt;
  &amp;lt;noinclude&amp;gt;&amp;lt;!-- If no or empty &amp;quot;demospace&amp;quot; parameter then detect namespace --&amp;gt;&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
  {{safesubst:&amp;lt;noinclude/&amp;gt;#if:{{{demospace|}}} &lt;br /&gt;
  | {{safesubst:&amp;lt;noinclude/&amp;gt;lc: {{{demospace}}} }}    &amp;lt;noinclude&amp;gt;&amp;lt;!-- Use lower case &amp;quot;demospace&amp;quot; --&amp;gt;&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
  | {{safesubst:&amp;lt;noinclude/&amp;gt;#ifeq:{{safesubst:&amp;lt;noinclude/&amp;gt;NAMESPACE}}|{{safesubst:&amp;lt;noinclude/&amp;gt;ns:0}}&lt;br /&gt;
    | main&lt;br /&gt;
    | other&lt;br /&gt;
    }} &lt;br /&gt;
  }}&lt;br /&gt;
| main     = {{{1|}}}&lt;br /&gt;
| other&lt;br /&gt;
| #default = {{{2|}}}&lt;br /&gt;
}}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{documentation}}&lt;br /&gt;
&amp;lt;!-- Add categories to the /doc subpage; interwikis go to Wikidata, thank you! --&amp;gt;&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=Template:Yesno&amp;diff=133</id>
		<title>Template:Yesno</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=Template:Yesno&amp;diff=133"/>
		<updated>2026-04-15T05:27:48Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{&amp;lt;includeonly&amp;gt;safesubst:&amp;lt;/includeonly&amp;gt;#switch: {{&amp;lt;includeonly&amp;gt;safesubst:&amp;lt;/includeonly&amp;gt;lc: {{{1|¬}}} }}&lt;br /&gt;
 |no&lt;br /&gt;
 |n&lt;br /&gt;
 |f&lt;br /&gt;
 |false&lt;br /&gt;
 |off&lt;br /&gt;
 |0        = {{{no|}}}&lt;br /&gt;
 |         = {{{blank|{{{no|}}}}}}&lt;br /&gt;
 |¬        = {{{¬|}}}&lt;br /&gt;
 |yes&lt;br /&gt;
 |y&lt;br /&gt;
 |t&lt;br /&gt;
 |true&lt;br /&gt;
 |on&lt;br /&gt;
 |1        = {{{yes|yes}}}&lt;br /&gt;
 |#default = {{{def|{{{yes|yes}}}}}}&lt;br /&gt;
}}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{Documentation}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=Module:Unsubst&amp;diff=131</id>
		<title>Module:Unsubst</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=Module:Unsubst&amp;diff=131"/>
		<updated>2026-04-15T05:27:47Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;local checkType = require(&#039;libraryUtil&#039;).checkType&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
local BODY_PARAM = &#039;$B&#039;&lt;br /&gt;
&lt;br /&gt;
local specialParams = {&lt;br /&gt;
	[&#039;$params&#039;] = &#039;parameter list&#039;,&lt;br /&gt;
	[&#039;$aliases&#039;] = &#039;parameter aliases&#039;,&lt;br /&gt;
	[&#039;$flags&#039;] = &#039;flags&#039;,&lt;br /&gt;
	[&#039;$B&#039;] = &#039;template content&#039;,&lt;br /&gt;
	[&#039;$template-name&#039;] = &#039;template invocation name override&#039;,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function p.main(frame, body)&lt;br /&gt;
	-- If we are substing, this function returns a template invocation, and if&lt;br /&gt;
	-- not, it returns the template body. The template body can be specified in&lt;br /&gt;
	-- the body parameter, or in the template parameter defined in the&lt;br /&gt;
	-- BODY_PARAM variable. This function can be called from Lua or from&lt;br /&gt;
	-- #invoke.&lt;br /&gt;
&lt;br /&gt;
	-- Return the template body if we aren&#039;t substing.&lt;br /&gt;
	if not mw.isSubsting() then&lt;br /&gt;
		if body ~= nil then&lt;br /&gt;
			return body&lt;br /&gt;
		elseif frame.args[BODY_PARAM] ~= nil then&lt;br /&gt;
			return frame.args[BODY_PARAM]&lt;br /&gt;
		else&lt;br /&gt;
			error(string.format(&lt;br /&gt;
				&amp;quot;no template content specified (use parameter &#039;%s&#039; from #invoke)&amp;quot;,&lt;br /&gt;
				BODY_PARAM&lt;br /&gt;
			), 2)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Sanity check for the frame object.&lt;br /&gt;
	if type(frame) ~= &#039;table&#039;&lt;br /&gt;
		or type(frame.getParent) ~= &#039;function&#039;&lt;br /&gt;
		or not frame:getParent()&lt;br /&gt;
	then&lt;br /&gt;
		error(&lt;br /&gt;
			&amp;quot;argument #1 to &#039;main&#039; must be a frame object with a parent &amp;quot; ..&lt;br /&gt;
			&amp;quot;frame available&amp;quot;,&lt;br /&gt;
			2&lt;br /&gt;
		)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Find the invocation name.&lt;br /&gt;
	local mTemplateInvocation = require(&#039;Module:Template invocation&#039;)&lt;br /&gt;
	local name&lt;br /&gt;
&lt;br /&gt;
	if frame.args[&#039;$template-name&#039;] and &#039;&#039; ~= frame.args[&#039;$template-name&#039;] then&lt;br /&gt;
		name = frame.args[&#039;$template-name&#039;]										-- override whatever the template name is with this name&lt;br /&gt;
	else&lt;br /&gt;
		name = mTemplateInvocation.name(frame:getParent():getTitle())&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Combine passed args with passed defaults&lt;br /&gt;
	local args = {}&lt;br /&gt;
	if string.find( &#039;,&#039;..(frame.args[&#039;$flags&#039;] or &#039;&#039;)..&#039;,&#039;, &#039;,%s*override%s*,&#039; ) then&lt;br /&gt;
		for k, v in pairs( frame:getParent().args ) do&lt;br /&gt;
			args[k] = v&lt;br /&gt;
		end&lt;br /&gt;
		for k, v in pairs( frame.args ) do&lt;br /&gt;
			if not specialParams[k] then&lt;br /&gt;
				if v == &#039;__DATE__&#039; then&lt;br /&gt;
					v = mw.getContentLanguage():formatDate( &#039;F Y&#039; )&lt;br /&gt;
				end&lt;br /&gt;
				args[k] = v&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		for k, v in pairs( frame.args ) do&lt;br /&gt;
			if not specialParams[k] then&lt;br /&gt;
				if v == &#039;__DATE__&#039; then&lt;br /&gt;
					v = mw.getContentLanguage():formatDate( &#039;F Y&#039; )&lt;br /&gt;
				end&lt;br /&gt;
				args[k] = v&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		for k, v in pairs( frame:getParent().args ) do&lt;br /&gt;
			args[k] = v&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Trim parameters, if not specified otherwise&lt;br /&gt;
	if not string.find( &#039;,&#039;..(frame.args[&#039;$flags&#039;] or &#039;&#039;)..&#039;,&#039;, &#039;,%s*keep%-whitespace%s*,&#039; ) then&lt;br /&gt;
		for k, v in pairs( args ) do args[k] = mw.ustring.match(v, &#039;^%s*(.*)%s*$&#039;) or &#039;&#039; end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Pull information from parameter aliases&lt;br /&gt;
	local aliases = {}&lt;br /&gt;
	if frame.args[&#039;$aliases&#039;] then&lt;br /&gt;
		local list = mw.text.split( frame.args[&#039;$aliases&#039;], &#039;%s*,%s*&#039; )&lt;br /&gt;
		for k, v in ipairs( list ) do&lt;br /&gt;
			local tmp = mw.text.split( v, &#039;%s*&amp;gt;%s*&#039; )&lt;br /&gt;
			aliases[tonumber(mw.ustring.match(tmp[1], &#039;^[1-9][0-9]*$&#039;)) or tmp[1]] = ((tonumber(mw.ustring.match(tmp[2], &#039;^[1-9][0-9]*$&#039;))) or tmp[2])&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	for k, v in pairs( aliases ) do&lt;br /&gt;
		if args[k] and ( not args[v] or args[v] == &#039;&#039; ) then&lt;br /&gt;
			args[v] = args[k]&lt;br /&gt;
		end&lt;br /&gt;
		args[k] = nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Remove empty parameters, if specified&lt;br /&gt;
	if string.find( &#039;,&#039;..(frame.args[&#039;$flags&#039;] or &#039;&#039;)..&#039;,&#039;, &#039;,%s*remove%-empty%s*,&#039; ) then&lt;br /&gt;
		local tmp = 0&lt;br /&gt;
		for k, v in ipairs( args ) do&lt;br /&gt;
			if v ~= &#039;&#039; or ( args[k+1] and args[k+1] ~= &#039;&#039; ) or ( args[k+2] and args[k+2] ~= &#039;&#039; ) then&lt;br /&gt;
				tmp = k&lt;br /&gt;
			else&lt;br /&gt;
				break&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		for k, v in pairs( args ) do&lt;br /&gt;
			if v == &#039;&#039; then&lt;br /&gt;
				if not (type(k) == &#039;number&#039; and k &amp;lt; tmp) then args[k] = nil end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Order parameters&lt;br /&gt;
	if frame.args[&#039;$params&#039;] then&lt;br /&gt;
		local params, tmp = mw.text.split( frame.args[&#039;$params&#039;], &#039;%s*,%s*&#039; ), {}&lt;br /&gt;
		for k, v in ipairs(params) do&lt;br /&gt;
			v = tonumber(mw.ustring.match(v, &#039;^[1-9][0-9]*$&#039;)) or v&lt;br /&gt;
			if args[v] then tmp[v], args[v] = args[v], nil end&lt;br /&gt;
		end&lt;br /&gt;
		for k, v in pairs(args) do tmp[k], args[k] = args[k], nil end&lt;br /&gt;
		args = tmp&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return mTemplateInvocation.invocation(name, args)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
p[&#039;&#039;] = p.main -- For backwards compatibility&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=Template:Ifsubst&amp;diff=129</id>
		<title>Template:Ifsubst</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=Template:Ifsubst&amp;diff=129"/>
		<updated>2026-04-15T05:27:44Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ safesubst:&amp;lt;noinclude/&amp;gt;#if:{{{demo|}}}&lt;br /&gt;
|{{ safesubst:&amp;lt;noinclude/&amp;gt;#ifeq:{{{demo}}} |no&lt;br /&gt;
 |{{{no|{{{2|}}}}}}&lt;br /&gt;
 |{{{yes|{{{1|}}}}}}&lt;br /&gt;
}}&lt;br /&gt;
|{{ safesubst:&amp;lt;noinclude/&amp;gt;#ifeq:{{ safesubst:&amp;lt;noinclude/&amp;gt;NAMESPACE}}|{{NAMESPACE}}&lt;br /&gt;
 |{{{no|{{{2|}}}}}}&lt;br /&gt;
 |{{{yes|{{{1|}}}}}}&lt;br /&gt;
}}}}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{Documentation}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
	<entry>
		<id>https://cardbot.wiki/index.php?title=Module:Redirect&amp;diff=127</id>
		<title>Module:Redirect</title>
		<link rel="alternate" type="text/html" href="https://cardbot.wiki/index.php?title=Module:Redirect&amp;diff=127"/>
		<updated>2026-04-15T05:27:43Z</updated>

		<summary type="html">&lt;p&gt;Cabalex: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- This module provides functions for getting the target of a redirect page.&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
-- Gets a mw.title object, using pcall to avoid generating script errors if we&lt;br /&gt;
-- are over the expensive function count limit (among other possible causes).&lt;br /&gt;
local function getTitle(...)&lt;br /&gt;
	local success, titleObj = pcall(mw.title.new, ...)&lt;br /&gt;
	if success then&lt;br /&gt;
		return titleObj&lt;br /&gt;
	else&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Gets the name of a page that a redirect leads to, or nil if it isn&#039;t a&lt;br /&gt;
-- redirect.&lt;br /&gt;
function p.getTargetFromText(text)&lt;br /&gt;
	local target = string.match(&lt;br /&gt;
		text,&lt;br /&gt;
		&amp;quot;^%s*#[Rr][Ee][Dd][Ii][Rr][Ee][Cc][Tt]%s*:?%s*%[%[([^%[%]|]-)%]%]&amp;quot;&lt;br /&gt;
	) or string.match(&lt;br /&gt;
		text,&lt;br /&gt;
		&amp;quot;^%s*#[Rr][Ee][Dd][Ii][Rr][Ee][Cc][Tt]%s*:?%s*%[%[([^%[%]|]-)|[^%[%]]-%]%]&amp;quot;&lt;br /&gt;
	)&lt;br /&gt;
	return target and mw.uri.decode(target, &#039;PATH&#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Gets the target of a redirect. If the page specified is not a redirect,&lt;br /&gt;
-- returns nil.&lt;br /&gt;
function p.getTarget(page, fulltext)&lt;br /&gt;
	-- Get the title object. Both page names and title objects are allowed&lt;br /&gt;
	-- as input.&lt;br /&gt;
	local titleObj&lt;br /&gt;
	if type(page) == &#039;string&#039; or type(page) == &#039;number&#039; then&lt;br /&gt;
		titleObj = getTitle(page)&lt;br /&gt;
	elseif type(page) == &#039;table&#039; and type(page.getContent) == &#039;function&#039; then&lt;br /&gt;
		titleObj = page&lt;br /&gt;
	else&lt;br /&gt;
		error(string.format(&lt;br /&gt;
			&amp;quot;bad argument #1 to &#039;getTarget&#039;&amp;quot;&lt;br /&gt;
				.. &amp;quot; (string, number, or title object expected, got %s)&amp;quot;,&lt;br /&gt;
			type(page)&lt;br /&gt;
		), 2)&lt;br /&gt;
	end&lt;br /&gt;
	if not titleObj then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	local targetTitle = titleObj.redirectTarget&lt;br /&gt;
	if targetTitle then&lt;br /&gt;
		if fulltext then&lt;br /&gt;
			return targetTitle.fullText&lt;br /&gt;
		else&lt;br /&gt;
			return targetTitle.prefixedText&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
-- Given a single page name determines what page it redirects to and returns the&lt;br /&gt;
-- target page name, or the passed page name when not a redirect. The passed&lt;br /&gt;
-- page name can be given as plain text or as a page link.&lt;br /&gt;
--&lt;br /&gt;
-- Returns page name as plain text, or when the bracket parameter is given, as a&lt;br /&gt;
-- page link. Returns an error message when page does not exist or the redirect&lt;br /&gt;
-- target cannot be determined for some reason.&lt;br /&gt;
--]]&lt;br /&gt;
function p.luaMain(rname, bracket, fulltext)&lt;br /&gt;
	if type(rname) ~= &amp;quot;string&amp;quot; or not rname:find(&amp;quot;%S&amp;quot;) then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	bracket = bracket and &amp;quot;[[%s]]&amp;quot; or &amp;quot;%s&amp;quot;&lt;br /&gt;
	rname = rname:match(&amp;quot;%[%[(.+)%]%]&amp;quot;) or rname&lt;br /&gt;
	local target = p.getTarget(rname, fulltext)&lt;br /&gt;
	local ret = target or rname&lt;br /&gt;
	ret = getTitle(ret)&lt;br /&gt;
	if ret then&lt;br /&gt;
		if fulltext then&lt;br /&gt;
			ret = ret.fullText&lt;br /&gt;
		else&lt;br /&gt;
			ret = ret.prefixedText&lt;br /&gt;
		end&lt;br /&gt;
		return bracket:format(ret)&lt;br /&gt;
	else&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Provides access to the luaMain function from wikitext.&lt;br /&gt;
function p.main(frame)&lt;br /&gt;
	local args = require(&#039;Module:Arguments&#039;).getArgs(frame, {frameOnly = true})&lt;br /&gt;
	return p.luaMain(args[1], args.bracket, args.fulltext) or &#039;&#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Returns true if the specified page is a redirect, and false otherwise.&lt;br /&gt;
function p.luaIsRedirect(page)&lt;br /&gt;
	local titleObj = getTitle(page)&lt;br /&gt;
	if not titleObj then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	if titleObj.isRedirect then&lt;br /&gt;
		return true&lt;br /&gt;
	else&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Provides access to the luaIsRedirect function from wikitext, returning &#039;yes&#039;&lt;br /&gt;
-- if the specified page is a redirect, and the blank string otherwise.&lt;br /&gt;
function p.isRedirect(frame)&lt;br /&gt;
	local args = require(&#039;Module:Arguments&#039;).getArgs(frame, {frameOnly = true})&lt;br /&gt;
	if p.luaIsRedirect(args[1]) then&lt;br /&gt;
		return &#039;yes&#039;&lt;br /&gt;
	else&lt;br /&gt;
		return &#039;&#039;&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Cabalex</name></author>
	</entry>
</feed>