<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://noaverse.erina.moe/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Erina</id>
	<title>Noaverse - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://noaverse.erina.moe/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Erina"/>
	<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php/Special:Contributions/Erina"/>
	<updated>2026-07-10T17:03:50Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.44.0</generator>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=Noa_(Prime)&amp;diff=92</id>
		<title>Noa (Prime)</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=Noa_(Prime)&amp;diff=92"/>
		<updated>2025-12-10T10:33:23Z</updated>

		<summary type="html">&lt;p&gt;Erina: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox&lt;br /&gt;
&lt;br /&gt;
|image=[[File:Noa Prime.png|200px]]&lt;br /&gt;
&lt;br /&gt;
|title=Noa&lt;br /&gt;
|caption=&#039;&#039;Illustration by kan_mirai&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|header10=Profile&lt;br /&gt;
|label12=Height&lt;br /&gt;
|label13=Weight&lt;br /&gt;
&lt;br /&gt;
|data12=165cm&lt;br /&gt;
|data13=55kg&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
The main Noa. Aside from the [[Noa (Code Vein)|Code Vein version]], they all have diverted from this one.&lt;br /&gt;
&lt;br /&gt;
==Design==&lt;br /&gt;
&lt;br /&gt;
{{Stub|section}}{{Messagebox|To self: try to describe the design with a bit more prose. Backstory maybe for some elements?}}&lt;br /&gt;
&lt;br /&gt;
* Stars on face: derived from WACCA Lily&lt;br /&gt;
* Scar on face: battle injury (derived from Code Vein customization)&lt;br /&gt;
* Choker with padlock: derived from Black Rock Shooter&lt;br /&gt;
* Witch hat: derived from Halloween&lt;br /&gt;
* Outfit design: designed by artist SEA_ICE_CREAM on Twitter&lt;br /&gt;
* Heterochromatic eyes: looks cool&lt;br /&gt;
&lt;br /&gt;
==Abilities==&lt;br /&gt;
&lt;br /&gt;
{{Stub|section}}&lt;br /&gt;
&lt;br /&gt;
===Ideas===&lt;br /&gt;
{{Messagebox|Most of these here are ideas. Nothing really fleshed out or balanced, just ideas that I thought sounded nice. They are gathered here for further reference.}}&lt;br /&gt;
&lt;br /&gt;
==== Heterochromatic eyes ====&lt;br /&gt;
Her left eye stays mainly blue, but her right eye shifts from cyan to straight up green. Inspired by wife&#039;s universe, eye colors could deviate from standard (blue/cyan) when focusing on specific abilities:&lt;br /&gt;
&lt;br /&gt;
* Right eye (default: cyan) could shift to green when focusing on a psychic ability&lt;br /&gt;
* Left eye (default: blue) could shift/sparkle when focusing on a physical ability&lt;br /&gt;
&lt;br /&gt;
[[Category:Noa]]&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=Noa_(Prime)&amp;diff=91</id>
		<title>Noa (Prime)</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=Noa_(Prime)&amp;diff=91"/>
		<updated>2025-12-10T10:26:49Z</updated>

		<summary type="html">&lt;p&gt;Erina: /* Abilities */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox&lt;br /&gt;
&lt;br /&gt;
|image=[[File:Noa Prime.png|200px]]&lt;br /&gt;
&lt;br /&gt;
|title=Noa&lt;br /&gt;
|caption=&#039;&#039;Illustration by kan_mirai&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|header10=Profile&lt;br /&gt;
|label12=Height&lt;br /&gt;
|label13=Weight&lt;br /&gt;
&lt;br /&gt;
|data12=165cm&lt;br /&gt;
|data13=55kg&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
The main Noa. Aside from the [[Noa (Code Vein)|Code Vein version]], they all have diverted from this one.&lt;br /&gt;
&lt;br /&gt;
==Design==&lt;br /&gt;
&lt;br /&gt;
{{Stub|section}}&lt;br /&gt;
&lt;br /&gt;
==Abilities==&lt;br /&gt;
&lt;br /&gt;
{{Stub|section}}&lt;br /&gt;
&lt;br /&gt;
===Ideas===&lt;br /&gt;
{{Messagebox|Most of these here are ideas. Nothing really fleshed out or balanced, just ideas that I thought sounded nice. They are gathered here for further reference.}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Noa]]&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=Template:Messagebox&amp;diff=90</id>
		<title>Template:Messagebox</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=Template:Messagebox&amp;diff=90"/>
		<updated>2025-12-10T10:26:04Z</updated>

		<summary type="html">&lt;p&gt;Erina: Created page with &amp;quot;&amp;lt;div class=&amp;quot;mbox&amp;quot; role=&amp;quot;presentation&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;mbox-title&amp;quot;&amp;gt;{{{1|something}}}&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;templatestyles src=&amp;quot;Module:Mbox/styles.css&amp;quot; /&amp;gt;&amp;lt;includeonly&amp;gt;Category:Article stubs&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt; {{/doc}}&amp;lt;/noinclude&amp;gt;&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&amp;quot;mbox&amp;quot; role=&amp;quot;presentation&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;mbox-title&amp;quot;&amp;gt;{{{1|something}}}&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;templatestyles src=&amp;quot;Module:Mbox/styles.css&amp;quot; /&amp;gt;&amp;lt;includeonly&amp;gt;[[Category:Article stubs]]&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{/doc}}&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=Noa_(Code_Vein)&amp;diff=89</id>
		<title>Noa (Code Vein)</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=Noa_(Code_Vein)&amp;diff=89"/>
		<updated>2025-09-28T21:07:31Z</updated>

		<summary type="html">&lt;p&gt;Erina: Correct body type&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox&lt;br /&gt;
|title=Noa&lt;br /&gt;
|image=[[File:Noa_Code_Vein_Bust.png|300px]]&lt;br /&gt;
&lt;br /&gt;
|header10=Profile&lt;br /&gt;
&lt;br /&gt;
|label11=Height&lt;br /&gt;
|data11=approx. 181cm&lt;br /&gt;
&lt;br /&gt;
|header50=Code Vein Physique settings&lt;br /&gt;
&lt;br /&gt;
|label51=Gender&lt;br /&gt;
|label52=Height&lt;br /&gt;
|label53=Body Type&lt;br /&gt;
|label54=Overall Balance&lt;br /&gt;
|label55=Head Size&lt;br /&gt;
&lt;br /&gt;
|data51=Female&lt;br /&gt;
|data52=1.020&lt;br /&gt;
|data53=C&lt;br /&gt;
|data54=5&lt;br /&gt;
|data55=0&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
The original. She has seen the most variants over time, most of which are lost to time. Still, this page will do its best (in due time) to retell her design tale.&lt;br /&gt;
&lt;br /&gt;
== Current design ==&lt;br /&gt;
{{Stub|part}}&lt;br /&gt;
&lt;br /&gt;
== Design history ==&lt;br /&gt;
&lt;br /&gt;
=== 2019 ===&lt;br /&gt;
&lt;br /&gt;
[[File:Noa Code Vein (2019).png|160x160px|left|This is the only remaining screenshot of the time.]]&lt;br /&gt;
&lt;br /&gt;
In 2019, Noa looked quite a bit different than what she does now. She had plain blue hair, slightly longer on the back, and had red and blue heterochromatic eyes. &lt;br /&gt;
&lt;br /&gt;
She didn&#039;t get to be iterated much on, because I did not play Code Vein for long at the time.&lt;br /&gt;
&lt;br /&gt;
=== 2021 ===&lt;br /&gt;
[[File:Noa Code Vein (early 2021).jpg|thumb|200x200px|Noa in early 2021.]]&lt;br /&gt;
I picked Code Vein up again in 2021, and spent time in the character creator again.&lt;br /&gt;
&lt;br /&gt;
She retained her bangs but now has shorter hair. Her hair is also now dark blue, with hints of purple at the tips. Her eyes are now cyan and blue. She retained the metallic clothing (metallic blue t-shirt, metallic red skirt).&lt;br /&gt;
[[File:Noa Code Vein (late 2021).jpg|thumb|200x200px|Noa in late 2021.]]&lt;br /&gt;
As time went on however, the hint of purple turned into more and more red at her tips, reaching a point where it&#039;s a simple blue to red gradient. &lt;br /&gt;
&lt;br /&gt;
Inspired by Black Rock Shooter, she got a choker with a padlock (visible on the early 2022 screenshot).&lt;br /&gt;
&lt;br /&gt;
She also got a brand new golden hat, in time for Halloween 2021. &lt;br /&gt;
&lt;br /&gt;
=== 2022 ===&lt;br /&gt;
[[File:Noa Code Vein (Late 2022).jpg|left|thumb|200x200px|Noa in late 2022.]]&lt;br /&gt;
Early in the year, she has gotten a scar, representative of her close quarters combat style. &lt;br /&gt;
&lt;br /&gt;
She also has gotten a pair of stars under her right eye, for no particular reason. (That was inspired by Lily from WACCA, one of my favorite rhythm games.)&lt;br /&gt;
&lt;br /&gt;
Her hair also progressively got redder and redder, indicating a shift in which of the two is my favorite color. (I like both.)&lt;br /&gt;
&lt;br /&gt;
== Abilities ==&lt;br /&gt;
{{Stub|part also}}&lt;br /&gt;
[[Category:Noa]]&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=Noa_(Train)&amp;diff=88</id>
		<title>Noa (Train)</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=Noa_(Train)&amp;diff=88"/>
		<updated>2025-09-21T22:26:51Z</updated>

		<summary type="html">&lt;p&gt;Erina: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox&lt;br /&gt;
&lt;br /&gt;
|title=623XL &amp;quot;Noa&amp;quot;&lt;br /&gt;
&lt;br /&gt;
|header10=Profile&lt;br /&gt;
&lt;br /&gt;
|label11=Height&lt;br /&gt;
|label12=Weight&lt;br /&gt;
&lt;br /&gt;
|data11=135.37m&lt;br /&gt;
|data12=322 tons&lt;br /&gt;
&lt;br /&gt;
|header19=Unit information&lt;br /&gt;
|label20=Class&lt;br /&gt;
|label21=Set&lt;br /&gt;
|label22=Power cars&lt;br /&gt;
|label23=Maximum speed&lt;br /&gt;
|label24=Capacity&lt;br /&gt;
&lt;br /&gt;
|data20=SNCF Class Z 56600 &amp;quot;Omneo Premium&amp;quot;&lt;br /&gt;
|data21=623XL&lt;br /&gt;
|data22=Z56645, Z56646&lt;br /&gt;
|data23=200 km/h&lt;br /&gt;
|data24=First class: 59 seats&amp;lt;br&amp;gt;Standard class: 446 seats &lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Choo choo. SNCF Class Z 56600 unit 623XL (power car 56645)&lt;br /&gt;
&lt;br /&gt;
[[Category:Noa]]&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=Noa_(Code_Vein)&amp;diff=87</id>
		<title>Noa (Code Vein)</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=Noa_(Code_Vein)&amp;diff=87"/>
		<updated>2025-09-21T21:51:50Z</updated>

		<summary type="html">&lt;p&gt;Erina: design history&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox&lt;br /&gt;
|title=Noa&lt;br /&gt;
|image=[[File:Noa_Code_Vein_Bust.png|300px]]&lt;br /&gt;
&lt;br /&gt;
|header10=Profile&lt;br /&gt;
&lt;br /&gt;
|label11=Height&lt;br /&gt;
|data11=approx. 181cm&lt;br /&gt;
&lt;br /&gt;
|header50=Code Vein Physique settings&lt;br /&gt;
&lt;br /&gt;
|label51=Gender&lt;br /&gt;
|label52=Height&lt;br /&gt;
|label53=Body Type&lt;br /&gt;
|label54=Overall Balance&lt;br /&gt;
|label55=Head Size&lt;br /&gt;
&lt;br /&gt;
|data51=Female&lt;br /&gt;
|data52=1.020&lt;br /&gt;
|data53=A&lt;br /&gt;
|data54=5&lt;br /&gt;
|data55=0&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
The original. She has seen the most variants over time, most of which are lost to time. Still, this page will do its best (in due time) to retell her design tale.&lt;br /&gt;
&lt;br /&gt;
== Current design ==&lt;br /&gt;
{{Stub|part}}&lt;br /&gt;
&lt;br /&gt;
== Design history ==&lt;br /&gt;
&lt;br /&gt;
=== 2019 ===&lt;br /&gt;
&lt;br /&gt;
[[File:Noa Code Vein (2019).png|160x160px|left|This is the only remaining screenshot of the time.]]&lt;br /&gt;
&lt;br /&gt;
In 2019, Noa looked quite a bit different than what she does now. She had plain blue hair, slightly longer on the back, and had red and blue heterochromatic eyes. &lt;br /&gt;
&lt;br /&gt;
She didn&#039;t get to be iterated much on, because I did not play Code Vein for long at the time.&lt;br /&gt;
&lt;br /&gt;
=== 2021 ===&lt;br /&gt;
[[File:Noa Code Vein (early 2021).jpg|thumb|200x200px|Noa in early 2021.]]&lt;br /&gt;
I picked Code Vein up again in 2021, and spent time in the character creator again.&lt;br /&gt;
&lt;br /&gt;
She retained her bangs but now has shorter hair. Her hair is also now dark blue, with hints of purple at the tips. Her eyes are now cyan and blue. She retained the metallic clothing (metallic blue t-shirt, metallic red skirt).&lt;br /&gt;
[[File:Noa Code Vein (late 2021).jpg|thumb|200x200px|Noa in late 2021.]]&lt;br /&gt;
As time went on however, the hint of purple turned into more and more red at her tips, reaching a point where it&#039;s a simple blue to red gradient. &lt;br /&gt;
&lt;br /&gt;
Inspired by Black Rock Shooter, she got a choker with a padlock (visible on the early 2022 screenshot).&lt;br /&gt;
&lt;br /&gt;
She also got a brand new golden hat, in time for Halloween 2021. &lt;br /&gt;
&lt;br /&gt;
=== 2022 ===&lt;br /&gt;
[[File:Noa Code Vein (Late 2022).jpg|left|thumb|200x200px|Noa in late 2022.]]&lt;br /&gt;
Early in the year, she has gotten a scar, representative of her close quarters combat style. &lt;br /&gt;
&lt;br /&gt;
She also has gotten a pair of stars under her right eye, for no particular reason. (That was inspired by Lily from WACCA, one of my favorite rhythm games.)&lt;br /&gt;
&lt;br /&gt;
Her hair also progressively got redder and redder, indicating a shift in which of the two is my favorite color. (I like both.)&lt;br /&gt;
&lt;br /&gt;
== Abilities ==&lt;br /&gt;
{{Stub|part also}}&lt;br /&gt;
[[Category:Noa]]&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=File:Noa_Code_Vein_(Late_2022).jpg&amp;diff=86</id>
		<title>File:Noa Code Vein (Late 2022).jpg</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=File:Noa_Code_Vein_(Late_2022).jpg&amp;diff=86"/>
		<updated>2025-09-21T21:41:47Z</updated>

		<summary type="html">&lt;p&gt;Erina: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Noa in late 2022&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=File:Noa_Code_Vein_(early_2022).jpg&amp;diff=85</id>
		<title>File:Noa Code Vein (early 2022).jpg</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=File:Noa_Code_Vein_(early_2022).jpg&amp;diff=85"/>
		<updated>2025-09-21T21:38:23Z</updated>

		<summary type="html">&lt;p&gt;Erina: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Noa in early 2022.&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=File:Noa_Code_Vein_(late_2021).jpg&amp;diff=84</id>
		<title>File:Noa Code Vein (late 2021).jpg</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=File:Noa_Code_Vein_(late_2021).jpg&amp;diff=84"/>
		<updated>2025-09-21T21:36:01Z</updated>

		<summary type="html">&lt;p&gt;Erina: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Noa as featured in Code Vein in late 2021.&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=File:Noa_Code_Vein_(early_2021).jpg&amp;diff=83</id>
		<title>File:Noa Code Vein (early 2021).jpg</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=File:Noa_Code_Vein_(early_2021).jpg&amp;diff=83"/>
		<updated>2025-09-21T21:26:28Z</updated>

		<summary type="html">&lt;p&gt;Erina: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Noa as she appeared in Code Vein in early 2021.&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=File:Noa_Code_Vein_(2019).png&amp;diff=82</id>
		<title>File:Noa Code Vein (2019).png</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=File:Noa_Code_Vein_(2019).png&amp;diff=82"/>
		<updated>2025-09-21T21:18:58Z</updated>

		<summary type="html">&lt;p&gt;Erina: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Noa as she was designed in 2019&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=Noa_(Code_Vein)&amp;diff=81</id>
		<title>Noa (Code Vein)</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=Noa_(Code_Vein)&amp;diff=81"/>
		<updated>2025-09-21T18:47:00Z</updated>

		<summary type="html">&lt;p&gt;Erina: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox&lt;br /&gt;
|title=Noa&lt;br /&gt;
|image=[[File:Noa_Code_Vein_Bust.png|300px]]&lt;br /&gt;
&lt;br /&gt;
|header10=Profile&lt;br /&gt;
&lt;br /&gt;
|label11=Height&lt;br /&gt;
|data11=approx. 181cm&lt;br /&gt;
&lt;br /&gt;
|header50=Code Vein Physique settings&lt;br /&gt;
&lt;br /&gt;
|label51=Gender&lt;br /&gt;
|label52=Height&lt;br /&gt;
|label53=Body Type&lt;br /&gt;
|label54=Overall Balance&lt;br /&gt;
|label55=Head Size&lt;br /&gt;
&lt;br /&gt;
|data51=Female&lt;br /&gt;
|data52=1.020&lt;br /&gt;
|data53=A&lt;br /&gt;
|data54=5&lt;br /&gt;
|data55=0&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
The original. She has seen the most variants over time, most of which are lost to time. Still, this page will do its best (in due time) to retell her design tale.&lt;br /&gt;
&lt;br /&gt;
[[Category:Noa]]&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=Noa_(Code_Vein)&amp;diff=80</id>
		<title>Noa (Code Vein)</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=Noa_(Code_Vein)&amp;diff=80"/>
		<updated>2025-09-21T18:46:39Z</updated>

		<summary type="html">&lt;p&gt;Erina: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox&lt;br /&gt;
|title=Noa&lt;br /&gt;
|image=[[File:Noa_Code_Vein_Bust.png|300px]]&lt;br /&gt;
&lt;br /&gt;
|header10=Profile&lt;br /&gt;
&lt;br /&gt;
|label11=Height&lt;br /&gt;
|data11=approx. 181cm&lt;br /&gt;
&lt;br /&gt;
|header50=Code Vein settings&lt;br /&gt;
&lt;br /&gt;
|label51=Gender&lt;br /&gt;
|label52=Height&lt;br /&gt;
|label53=Body Type&lt;br /&gt;
|label54=Overall Balance&lt;br /&gt;
|label55=Head Size&lt;br /&gt;
&lt;br /&gt;
|data51=Female&lt;br /&gt;
|data52=1.020&lt;br /&gt;
|data53=A&lt;br /&gt;
|data54=5&lt;br /&gt;
|data55=0&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
The original. She has seen the most variants over time, most of which are lost to time. Still, this page will do its best (in due time) to retell her design tale.&lt;br /&gt;
&lt;br /&gt;
[[Category:Noa]]&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=File:Noa_Code_Vein_Bust.png&amp;diff=79</id>
		<title>File:Noa Code Vein Bust.png</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=File:Noa_Code_Vein_Bust.png&amp;diff=79"/>
		<updated>2025-09-21T18:06:47Z</updated>

		<summary type="html">&lt;p&gt;Erina: Noa as seen in Code Vein.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Summary ==&lt;br /&gt;
Noa as seen in Code Vein.&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=Noa_(Prime)&amp;diff=78</id>
		<title>Noa (Prime)</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=Noa_(Prime)&amp;diff=78"/>
		<updated>2025-09-21T15:57:58Z</updated>

		<summary type="html">&lt;p&gt;Erina: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox&lt;br /&gt;
&lt;br /&gt;
|image=[[File:Noa Prime.png|200px]]&lt;br /&gt;
&lt;br /&gt;
|title=Noa&lt;br /&gt;
|caption=&#039;&#039;Illustration by kan_mirai&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|header10=Profile&lt;br /&gt;
|label12=Height&lt;br /&gt;
|label13=Weight&lt;br /&gt;
&lt;br /&gt;
|data12=165cm&lt;br /&gt;
|data13=55kg&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
The main Noa. Aside from the [[Noa (Code Vein)|Code Vein version]], they all have diverted from this one.&lt;br /&gt;
&lt;br /&gt;
==Design==&lt;br /&gt;
&lt;br /&gt;
{{Stub|section}}&lt;br /&gt;
&lt;br /&gt;
==Abilities==&lt;br /&gt;
&lt;br /&gt;
{{Stub|section}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Noa]]&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=Module:Mbox/styles.css&amp;diff=77</id>
		<title>Module:Mbox/styles.css</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=Module:Mbox/styles.css&amp;diff=77"/>
		<updated>2025-09-21T15:57:01Z</updated>

		<summary type="html">&lt;p&gt;Erina: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;.mbox {&lt;br /&gt;
	position: relative;&lt;br /&gt;
	display: flex;&lt;br /&gt;
	flex-direction: column;&lt;br /&gt;
	margin-block: var(--space-md);&lt;br /&gt;
	background-color: var(--color-surface-1);&lt;br /&gt;
	border: var(--border-base);&lt;br /&gt;
	border-radius: var(--border-radius-medium);&lt;br /&gt;
	font-size: var(--font-size-small);&lt;br /&gt;
	line-height: var(--line-height-xx-small);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.mbox.mbox-high {&lt;br /&gt;
	background-color: var(--background-color-destructive-subtle);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.mbox.mbox-med {&lt;br /&gt;
	background-color: var(--background-color-warning-subtle);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.mbox-title,&lt;br /&gt;
.mbox-text {&lt;br /&gt;
	padding: var(--space-sm) var(--space-md);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.mbox-title {&lt;br /&gt;
	display: flex;&lt;br /&gt;
	align-items: center;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.mbox-icon img {&lt;br /&gt;
	display: block;&lt;br /&gt;
	width: var(--font-size-small);&lt;br /&gt;
	height: auto;&lt;br /&gt;
	margin-right: var(--space-xs);&lt;br /&gt;
	opacity: var(--opacity-icon-base);&lt;br /&gt;
	filter: var(--filter-invert);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.mbox-text {&lt;br /&gt;
	position: absolute;&lt;br /&gt;
	top: 100%;&lt;br /&gt;
	left: 0;&lt;br /&gt;
	right: 0;&lt;br /&gt;
	z-index: 10;&lt;br /&gt;
	margin-inline: -1px;&lt;br /&gt;
	box-sizing: border-box;&lt;br /&gt;
	background-color: var(--color-surface-1);&lt;br /&gt;
	border-inline: var(--border-base);&lt;br /&gt;
	border-bottom: var(--border-base);&lt;br /&gt;
	border-bottom-left-radius: var(--border-radius-medium);&lt;br /&gt;
	border-bottom-right-radius: var(--border-radius-medium);&lt;br /&gt;
	box-shadow: var(--box-shadow-drop-xx-large);&lt;br /&gt;
	opacity: 0;&lt;br /&gt;
	visibility: hidden;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.mbox-text::before {&lt;br /&gt;
	content: &#039;&#039;;&lt;br /&gt;
	display: block;&lt;br /&gt;
	position: absolute;&lt;br /&gt;
	top: 0;&lt;br /&gt;
	left: var(--space-md);&lt;br /&gt;
	right: var(--space-md);&lt;br /&gt;
	height: var(--border-width-base);&lt;br /&gt;
	background: var(--border-color-subtle);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
&lt;br /&gt;
.mbox:hover {&lt;br /&gt;
	/* Merge with popup * /&lt;br /&gt;
	border-bottom-left-radius: 0;&lt;br /&gt;
	border-bottom-right-radius: 0;&lt;br /&gt;
	box-shadow: var(--box-shadow-drop-xx-large);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.mbox:hover .mbox-text {&lt;br /&gt;
	opacity: 1;&lt;br /&gt;
	visibility: visible;&lt;br /&gt;
}&lt;br /&gt;
*/&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=Template:Stub&amp;diff=76</id>
		<title>Template:Stub</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=Template:Stub&amp;diff=76"/>
		<updated>2025-09-21T15:56:33Z</updated>

		<summary type="html">&lt;p&gt;Erina: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&amp;quot;mbox&amp;quot; role=&amp;quot;presentation&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;mbox-title&amp;quot;&amp;gt;This {{{1|article}}} needs more yap.&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;templatestyles src=&amp;quot;Module:Mbox/styles.css&amp;quot; /&amp;gt;&amp;lt;includeonly&amp;gt;[[Category:Article stubs]]&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{/doc}}&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=Noa_(Prime)&amp;diff=75</id>
		<title>Noa (Prime)</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=Noa_(Prime)&amp;diff=75"/>
		<updated>2025-09-21T15:14:00Z</updated>

		<summary type="html">&lt;p&gt;Erina: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Infobox&lt;br /&gt;
&lt;br /&gt;
|image=[[File:Noa Prime.png|200px]]&lt;br /&gt;
&lt;br /&gt;
|title=Noa&lt;br /&gt;
|caption=&#039;&#039;Illustration by kan_mirai&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
|header10=Profile&lt;br /&gt;
|label12=Height&lt;br /&gt;
|label13=Weight&lt;br /&gt;
&lt;br /&gt;
|data12=165cm&lt;br /&gt;
|data13=55kg&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
The main Noa. Aside from the [[Noa (Code Vein)|Code Vein version]], they all have diverted from this one.&lt;br /&gt;
&lt;br /&gt;
==Design==&lt;br /&gt;
&lt;br /&gt;
stub&lt;br /&gt;
&lt;br /&gt;
==Abilities==&lt;br /&gt;
&lt;br /&gt;
stub&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Noa]]&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=Module:I18n/category/en.json&amp;diff=74</id>
		<title>Module:I18n/category/en.json</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=Module:I18n/category/en.json&amp;diff=74"/>
		<updated>2025-09-21T15:10:41Z</updated>

		<summary type="html">&lt;p&gt;Erina: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{&lt;br /&gt;
	&amp;quot;category_documentation&amp;quot;: &amp;quot;%s documentation&amp;quot;,&lt;br /&gt;
	&amp;quot;category_error_item_missing_manufacturer&amp;quot;: &amp;quot;Items missing manufacturer&amp;quot;,&lt;br /&gt;
	&amp;quot;category_error_item_missing_uuid&amp;quot;: &amp;quot;Items missing UUID&amp;quot;,&lt;br /&gt;
	&amp;quot;category_error_pages_with_script_errors&amp;quot;: &amp;quot;Pages with script errors&amp;quot;,&lt;br /&gt;
	&amp;quot;category_error_item_missing_type_label&amp;quot;: &amp;quot;Items missing type label&amp;quot;,&lt;br /&gt;
	&amp;quot;category_error_item_missing_type_category&amp;quot;: &amp;quot;Items missing type category&amp;quot;,&lt;br /&gt;
	&amp;quot;category_ground_vehicle&amp;quot;: &amp;quot;Ground vehicles&amp;quot;,&lt;br /&gt;
	&amp;quot;category_ground_vehicle_pledge&amp;quot;: &amp;quot;Pledge vehicles&amp;quot;,&lt;br /&gt;
	&amp;quot;category_ground_vehicle_size&amp;quot;: &amp;quot;%s vehicles&amp;quot;,&lt;br /&gt;
	&amp;quot;category_ground_vehicles&amp;quot;: &amp;quot;ground vehicles&amp;quot;,&lt;br /&gt;
	&amp;quot;category_imported_from_wikipedia&amp;quot;: &amp;quot;%ss imported from Wikipedia&amp;quot;,&lt;br /&gt;
	&amp;quot;category_infobox_using_placeholder_image&amp;quot;: &amp;quot;Infoboxes using placeholder image&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_bomb&amp;quot;: &amp;quot;Bombs&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_bomb.utility&amp;quot;: &amp;quot;Bombs&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_bomblauncher.bombrack&amp;quot;: &amp;quot;Bomb racks&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_cargo.cargo&amp;quot;: &amp;quot;Commodities&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_cargo.small&amp;quot;: &amp;quot;Commodities&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_char_accessory_eyes&amp;quot;: &amp;quot;Eyewear&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_char_armor_arms.heavy&amp;quot;: &amp;quot;Arms armor&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_char_armor_arms.light&amp;quot;: &amp;quot;Arms armor&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_char_armor_arms.medium&amp;quot;: &amp;quot;Arms armor&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_char_armor_backpack&amp;quot;: &amp;quot;Backpacks&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_char_armor_backpack.personal&amp;quot;: &amp;quot;Backpacks&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_char_armor_backpack.medium&amp;quot;: &amp;quot;Backpacks&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_char_armor_helmet&amp;quot;: &amp;quot;Helmets&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_char_armor_helmet.heavy&amp;quot;: &amp;quot;Helmets&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_char_armor_helmet.light&amp;quot;: &amp;quot;Helmets&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_char_armor_helmet.medium&amp;quot;: &amp;quot;Helmets&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_char_armor_legs.heavy&amp;quot;: &amp;quot;Legs armor&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_char_armor_legs.light&amp;quot;: &amp;quot;Legs armor&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_char_armor_legs.medium&amp;quot;: &amp;quot;Legs armor&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_char_armor_torso.heavy&amp;quot;: &amp;quot;Torso armor&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_char_armor_torso.light&amp;quot;: &amp;quot;Torso armor&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_char_armor_torso.medium&amp;quot;: &amp;quot;Torso armor&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_char_armor_undersuit&amp;quot;: &amp;quot;Undersuits&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_char_armor_undersuit.heavy&amp;quot;: &amp;quot;Undersuits&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_char_clothing_feet&amp;quot;: &amp;quot;Footwear&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_char_clothing_hands&amp;quot;: &amp;quot;Gloves&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_char_clothing_hat&amp;quot;: &amp;quot;Headgears&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_char_clothing_hat.heavy&amp;quot;: &amp;quot;Headgears&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_char_clothing_hat.light&amp;quot;: &amp;quot;Headgears&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_char_clothing_hat.medium&amp;quot;: &amp;quot;Headgears&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_char_clothing_legs&amp;quot;: &amp;quot;Legwear&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_char_clothing_legs.heavy&amp;quot;: &amp;quot;Legwear&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_char_clothing_legs.light&amp;quot;: &amp;quot;Legwear&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_char_clothing_legs.medium&amp;quot;: &amp;quot;Legwear&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_char_clothing_torso_0&amp;quot;: &amp;quot;Shirts&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_char_clothing_torso_1&amp;quot;: &amp;quot;Outerwear&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_char_clothing_torso_1.heavy&amp;quot;: &amp;quot;Outerwear&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_char_clothing_torso_1.light&amp;quot;: &amp;quot;Outerwear&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_char_clothing_torso_1.medium&amp;quot;: &amp;quot;Outerwear&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_container.cargo&amp;quot;: &amp;quot;Cargo pods&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_cooler&amp;quot;: &amp;quot;Coolers&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_dockingcollar&amp;quot;: &amp;quot;Fuel nozzles&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_drink.bottle&amp;quot;: &amp;quot;Drinks&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_drink.can&amp;quot;: &amp;quot;Drinks&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_emp&amp;quot;: &amp;quot;EMP generators&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_externalfueltank&amp;quot;: &amp;quot;Fuel pods&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_flair_cockpit.flair_static&amp;quot;: &amp;quot;Cockpit flairs&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_flightcontroller&amp;quot;: &amp;quot;Flight blades&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_food.bar&amp;quot;: &amp;quot;Food&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_food.box&amp;quot;: &amp;quot;Food&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_food.consumable&amp;quot;: &amp;quot;Food&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_food.harvestable&amp;quot;: &amp;quot;Food&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_food.junk&amp;quot;: &amp;quot;Food&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_food.plant&amp;quot;: &amp;quot;Food&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_food.sachet&amp;quot;: &amp;quot;Food&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_food.tin&amp;quot;: &amp;quot;Food&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_fps_consumable&amp;quot;: &amp;quot;Consumable&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_fps_consumable.hacking&amp;quot;: &amp;quot;Cryptokeys&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_fps_consumable.medical&amp;quot;: &amp;quot;Medical consumables&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_fps_consumable.medpack&amp;quot;: &amp;quot;Medical consumables&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_fps_consumable.oxygencap&amp;quot;: &amp;quot;Medical consumables&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_gadget.gadget&amp;quot;: &amp;quot;Gadgets&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_inventorycontainer.cargo&amp;quot;: &amp;quot;Containers&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_jumpdrive&amp;quot;: &amp;quot;Jump modules&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_jumpdrive.jumpdrive&amp;quot;: &amp;quot;Jump modules&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_lifesupportgenerator&amp;quot;: &amp;quot;Life support generators&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_miningmodifier.gun&amp;quot;: &amp;quot;Mining modules&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_misc&amp;quot;: &amp;quot;Miscellaneous items&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_misc.harvestable&amp;quot;: &amp;quot;Harvestable items&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_missile.missile&amp;quot;: &amp;quot;Missiles&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_missile.torpedo&amp;quot;: &amp;quot;Torpedoes&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_missilelauncher.missilerack&amp;quot;: &amp;quot;Missile racks&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_mobiglas.personal&amp;quot;: &amp;quot;mobiGlas&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_module&amp;quot;: &amp;quot;Vehicle modules&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_powerplant.power&amp;quot;: &amp;quot;Power plants&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_quantumdrive&amp;quot;: &amp;quot;Quantum drives&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_quantuminterdictiongenerator&amp;quot;: &amp;quot;Quantum enforcement devices&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_radar.midrangeradar&amp;quot;: &amp;quot;Radars&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_salvagehead&amp;quot;: &amp;quot;Salvage heads&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_salvagemodifier&amp;quot;: &amp;quot;Scraper modules&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_salvagemodifier.salvagemodifier_tractorbeam&amp;quot;: &amp;quot;Tractor beams&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_shield&amp;quot;: &amp;quot;Shield generators&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_towingbeam&amp;quot;: &amp;quot;Towing beams&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_tractorbeam&amp;quot;: &amp;quot;Tractor beams&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_turret.ballturret&amp;quot;: &amp;quot;Weapon mounts&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_turret.canardturret&amp;quot;: &amp;quot;Weapon mounts&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_turret.gunturret&amp;quot;: &amp;quot;Weapon mounts&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_turret.nosemounted&amp;quot;: &amp;quot;Weapon mounts&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_turret.pdcturret&amp;quot;: &amp;quot;PDCs&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_turretbase.mannedturret&amp;quot;: &amp;quot;Manned turrets&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_weaponattachment.barrel&amp;quot;: &amp;quot;Barrel attachments&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_weaponattachment.bottomattachment&amp;quot;: &amp;quot;Underbarrel attachments&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_weaponattachment.ironsight&amp;quot;: &amp;quot;Optics attachments&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_weaponattachment.magazine&amp;quot;: &amp;quot;Magazines&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_weaponattachment.utility&amp;quot;: &amp;quot;Multi-Tool attachments&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_weapongun.gun&amp;quot;: &amp;quot;Guns&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_weapongun.nosemounted&amp;quot;: &amp;quot;Guns&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_weapongun.rocket&amp;quot;: &amp;quot;Rocket pods&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_weaponmining.gun&amp;quot;: &amp;quot;Mining lasers&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_weaponpersonal.gadget&amp;quot;: &amp;quot;Gadgets&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_weaponpersonal.grenade&amp;quot;: &amp;quot;Grenades&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_weaponpersonal.knife&amp;quot;: &amp;quot;Knives&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_weaponpersonal.large&amp;quot;: &amp;quot;Shouldered weapons&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_weaponpersonal.medium&amp;quot;: &amp;quot;Stocked weapons&amp;quot;,&lt;br /&gt;
	&amp;quot;category_itemtype_weaponpersonal.small&amp;quot;: &amp;quot;Sidearm weapons&amp;quot;,&lt;br /&gt;
	&amp;quot;category_lua_based_template&amp;quot;: &amp;quot;Lua-based templates&amp;quot;,&lt;br /&gt;
	&amp;quot;category_module&amp;quot;: &amp;quot;Modules&amp;quot;,&lt;br /&gt;
	&amp;quot;category_module_data&amp;quot;: &amp;quot;Module data&amp;quot;,&lt;br /&gt;
	&amp;quot;category_modules_required_by_modules&amp;quot;: &amp;quot;Modules required by modules&amp;quot;,&lt;br /&gt;
	&amp;quot;category_modules_using_data&amp;quot;: &amp;quot;Modules using data&amp;quot;,&lt;br /&gt;
	&amp;quot;category_series&amp;quot;: &amp;quot;%s series&amp;quot;,&lt;br /&gt;
	&amp;quot;category_shared_by_the_star_citizen_wikis&amp;quot;: &amp;quot;%ss shared by the Star Citizen Wikis&amp;quot;,&lt;br /&gt;
	&amp;quot;category_ship&amp;quot;: &amp;quot;Ships&amp;quot;,&lt;br /&gt;
	&amp;quot;category_ship_pledge&amp;quot;: &amp;quot;Pledge ships&amp;quot;,&lt;br /&gt;
	&amp;quot;category_ship_size&amp;quot;: &amp;quot;%s ships&amp;quot;,&lt;br /&gt;
	&amp;quot;category_ships&amp;quot;: &amp;quot;ships&amp;quot;,&lt;br /&gt;
	&amp;quot;category_strict_mode_modules&amp;quot;: &amp;quot;Strict mode modules&amp;quot;,&lt;br /&gt;
	&amp;quot;category_template_invoked_modules&amp;quot;: &amp;quot;Template invoked modules&amp;quot;,&lt;br /&gt;
	&amp;quot;category_unused_module&amp;quot;: &amp;quot;Unused modules&amp;quot;,&lt;br /&gt;
	&amp;quot;category_weaponpersonal_assault_rifle&amp;quot;: &amp;quot;Assault rifles&amp;quot;,&lt;br /&gt;
	&amp;quot;category_weaponpersonal_frag_pistol&amp;quot;: &amp;quot;Frag pistols&amp;quot;,&lt;br /&gt;
	&amp;quot;category_weaponpersonal_fire_extinguisher&amp;quot;: &amp;quot;Fire extinguishers&amp;quot;,&lt;br /&gt;
	&amp;quot;category_weaponpersonal_grenade_launcher&amp;quot;: &amp;quot;Grenade launchers&amp;quot;,&lt;br /&gt;
	&amp;quot;category_weaponpersonal_lmg&amp;quot;: &amp;quot;LMGs&amp;quot;,&lt;br /&gt;
	&amp;quot;category_weaponpersonal_missile_launcher&amp;quot;: &amp;quot;Missile launchers&amp;quot;,&lt;br /&gt;
	&amp;quot;category_weaponpersonal_pistol&amp;quot;: &amp;quot;Pistols&amp;quot;,&lt;br /&gt;
	&amp;quot;category_weaponpersonal_railgun&amp;quot;: &amp;quot;Railguns&amp;quot;,&lt;br /&gt;
	&amp;quot;category_weaponpersonal_shotgun&amp;quot;: &amp;quot;Shotguns&amp;quot;,&lt;br /&gt;
	&amp;quot;category_weaponpersonal_smg&amp;quot;: &amp;quot;SMGs&amp;quot;,&lt;br /&gt;
	&amp;quot;category_weaponpersonal_sniper_rifle&amp;quot;: &amp;quot;Sniper rifles&amp;quot;,&lt;br /&gt;
	&amp;quot;category_weaponpersonal_toy_pistol&amp;quot;: &amp;quot;Toy pistols&amp;quot;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=Module:I18n&amp;diff=72</id>
		<title>Module:I18n</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=Module:I18n&amp;diff=72"/>
		<updated>2025-09-21T15:10:41Z</updated>

		<summary type="html">&lt;p&gt;Erina: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;require( &#039;strict&#039; )&lt;br /&gt;
&lt;br /&gt;
local i18n = {}&lt;br /&gt;
&lt;br /&gt;
local metatable = {}&lt;br /&gt;
local methodtable = {}&lt;br /&gt;
&lt;br /&gt;
metatable.__index = methodtable&lt;br /&gt;
&lt;br /&gt;
local libraryUtil = require( &#039;libraryUtil&#039; )&lt;br /&gt;
local checkType = libraryUtil.checkType&lt;br /&gt;
&lt;br /&gt;
--- Cache table containing i18n data&lt;br /&gt;
--- e.g. cache[&#039;en&#039;][&#039;SMW&#039;] will get you the SMW table in English&lt;br /&gt;
local cache = {}&lt;br /&gt;
&lt;br /&gt;
--- Cache language codes for reuse&lt;br /&gt;
local languages = {}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--- Retrieve dataset namespace from key prefix&lt;br /&gt;
---&lt;br /&gt;
--- @param key string The translation key&lt;br /&gt;
--- @return string&lt;br /&gt;
local function getNamespace( key )&lt;br /&gt;
    local namespace = string.match( key, &#039;([^_]*)&#039; )&lt;br /&gt;
    return namespace&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--- Retrieve a list of applicable language codes&lt;br /&gt;
---&lt;br /&gt;
--- @return table&lt;br /&gt;
local function getLanguageCodes()&lt;br /&gt;
    if #languages &amp;gt; 0 then return languages end&lt;br /&gt;
    local mwlang = mw.language.getContentLanguage()&lt;br /&gt;
    local langCodes = { mwlang:getCode() }&lt;br /&gt;
&lt;br /&gt;
    local fallbackLangCodes = mwlang:getFallbackLanguages()&lt;br /&gt;
    if next( fallbackLangCodes ) ~= nil then&lt;br /&gt;
        for _, fallbackLangCode in pairs( fallbackLangCodes ) do&lt;br /&gt;
            table.insert( langCodes, fallbackLangCode )&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    --mw.log( string.format( &#039;🌐 [i18n] Setting language chain: %s&#039;, table.concat( langCodes, &#039;→&#039; ) ) )&lt;br /&gt;
    return langCodes&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--- Loads a dataset and saves it to the cache&lt;br /&gt;
---&lt;br /&gt;
--- @param lang string&lt;br /&gt;
--- @param namespace string&lt;br /&gt;
--- @return table|nil { data = &amp;quot;The dataset&amp;quot;, keys = &amp;quot;Translation key mapped to index&amp;quot; }&lt;br /&gt;
local function load( lang, namespace )&lt;br /&gt;
    -- Init language cache if it does not exist&lt;br /&gt;
    if cache[ lang ] == nil then&lt;br /&gt;
        cache[ lang ] = {}&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if cache[ lang ][ namespace ] then&lt;br /&gt;
        return cache[ lang ][ namespace ]&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local datasetName = string.format( &#039;Module:i18n/%s/%s.json&#039;, namespace, lang )&lt;br /&gt;
    local success, data = pcall( mw.loadJsonData, datasetName )&lt;br /&gt;
&lt;br /&gt;
    if not success then&lt;br /&gt;
        --mw.log( string.format( &#039;🚨 [i18n] Loading dataset[%s][%s]: %s not found on wiki&#039;, lang, namespace, datasetName ) )&lt;br /&gt;
        -- Cache the empty result so we do not run mw.loadJsonData again&lt;br /&gt;
        cache[ lang ][ namespace ] = {}&lt;br /&gt;
        return&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    cache[ lang ][ namespace ] = data&lt;br /&gt;
    --mw.log( string.format( &#039;⌛ [i18n] Loading dataset[%s][%s]: %s&#039;, lang, namespace, datasetName ) )&lt;br /&gt;
&lt;br /&gt;
    return cache[ lang ][ namespace ]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--- Returns translated message (or key if returnKey is enabled)&lt;br /&gt;
---&lt;br /&gt;
--- @param key string The translation key&lt;br /&gt;
--- @param options table|nil Optional options&lt;br /&gt;
--- @return string|nil&lt;br /&gt;
function methodtable.translate( self, key, options )&lt;br /&gt;
    options = options or {&lt;br /&gt;
        [&#039;returnKey&#039;] = true&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    checkType( &#039;Module:i18n.translate&#039;, 1, self, &#039;table&#039; )&lt;br /&gt;
    checkType( &#039;Module:i18n.translate&#039;, 2, key, &#039;string&#039; )&lt;br /&gt;
    checkType( &#039;Module:i18n.translate&#039;, 3, options, &#039;table&#039; )&lt;br /&gt;
&lt;br /&gt;
    --mw.log( string.format( &#039;🔍 [i18n] Looking for message: %s&#039;, key ) )&lt;br /&gt;
&lt;br /&gt;
    local namespace = getNamespace( key )&lt;br /&gt;
    if namespace == nil then&lt;br /&gt;
        -- No namespace found error&lt;br /&gt;
        --mw.log( string.format( &#039;❌ [i18n] Namespace cannot be found from: %s&#039;, key ) )&lt;br /&gt;
        if options[&#039;returnKey&#039;] == true then&lt;br /&gt;
            return key&lt;br /&gt;
        else&lt;br /&gt;
            return&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    languages = getLanguageCodes()&lt;br /&gt;
&lt;br /&gt;
    local message&lt;br /&gt;
    local i = 1&lt;br /&gt;
&lt;br /&gt;
    while ( message == nil and i &amp;lt;= #languages ) do&lt;br /&gt;
        local dataset = load( languages[ i ], namespace )&lt;br /&gt;
        if dataset then&lt;br /&gt;
            local match = dataset[ key ]&lt;br /&gt;
            if match then&lt;br /&gt;
                message = match&lt;br /&gt;
                --mw.log( string.format( &#039;✅ [i18n] Found message: %s&#039;, message ) )&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
        i = i + 1&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if message == nil then&lt;br /&gt;
        --mw.log( string.format( &#039;❌ [i18n] Could not found message: %s&#039;, key ) )&lt;br /&gt;
        if options[&#039;returnKey&#039;] == true then&lt;br /&gt;
            message = key&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return message&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--- Normalize a string to be used as an i18n key by converting whitespace to underscores and making all characters lowercase&lt;br /&gt;
---&lt;br /&gt;
--- @param str string The string to normalize&lt;br /&gt;
--- @return string&lt;br /&gt;
function methodtable.normalizeKey( self, str )&lt;br /&gt;
    checkType( &#039;Module:i18n.normalizeKey&#039;, 1, self, &#039;table&#039; )&lt;br /&gt;
    checkType( &#039;Module:i18n.normalizeKey&#039;, 2, str, &#039;string&#039; )&lt;br /&gt;
&lt;br /&gt;
    return string.lower( string.gsub( str, &#039;%s+&#039;, &#039;_&#039; ) )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--- New Instance&lt;br /&gt;
---&lt;br /&gt;
--- @return table i18n&lt;br /&gt;
function i18n.new( self )&lt;br /&gt;
    local instance = {}&lt;br /&gt;
&lt;br /&gt;
    setmetatable( instance, metatable )&lt;br /&gt;
&lt;br /&gt;
    return instance&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
return i18n&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=Module:DependencyList/i18n.json&amp;diff=70</id>
		<title>Module:DependencyList/i18n.json</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=Module:DependencyList/i18n.json&amp;diff=70"/>
		<updated>2025-09-21T15:10:41Z</updated>

		<summary type="html">&lt;p&gt;Erina: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{&lt;br /&gt;
	&amp;quot;license&amp;quot;: &amp;quot;CC0-1.0&amp;quot;,&lt;br /&gt;
	&amp;quot;description&amp;quot;: {&lt;br /&gt;
		&amp;quot;en&amp;quot;: &amp;quot;Translation table for the Module:DependencyList&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
	&amp;quot;schema&amp;quot;: {&lt;br /&gt;
		&amp;quot;fields&amp;quot;: [&lt;br /&gt;
			{&lt;br /&gt;
				&amp;quot;name&amp;quot;: &amp;quot;id&amp;quot;,&lt;br /&gt;
				&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;&lt;br /&gt;
			},&lt;br /&gt;
			{&lt;br /&gt;
				&amp;quot;name&amp;quot;: &amp;quot;message&amp;quot;,&lt;br /&gt;
				&amp;quot;type&amp;quot;: &amp;quot;localized&amp;quot;&lt;br /&gt;
			}&lt;br /&gt;
		]&lt;br /&gt;
	},&lt;br /&gt;
	&amp;quot;data&amp;quot;: [&lt;br /&gt;
		[&lt;br /&gt;
			&amp;quot;message_unused_module_title&amp;quot;,&lt;br /&gt;
			{&lt;br /&gt;
				&amp;quot;de&amp;quot;: &amp;quot;Dieses Modul wird nicht verwendet.&amp;quot;,&lt;br /&gt;
				&amp;quot;en&amp;quot;: &amp;quot;This module is unused.&amp;quot;&lt;br /&gt;
			}&lt;br /&gt;
		],&lt;br /&gt;
		[&lt;br /&gt;
			&amp;quot;message_unused_module_desc&amp;quot;,&lt;br /&gt;
			{&lt;br /&gt;
				&amp;quot;de&amp;quot;: &amp;quot;Dieses Modul wird weder von einer Vorlage aufgerufen noch von einem anderen Modul benötigt/geladen. Wenn dies ein Fehler ist, stelle bitte sicher, dass \u003Ccode\u003E{{[[Vorlage:Dokumentation|Dokumentation]]}}\u003C/code\u003E/\u003Ccode\u003E{{[[Vorlage:Keine Dokumentation|Keine\u0026nbsp;Dokumentation]]}}\u003C/code\u003E auf der Dokumentationsseite der Vorlage oder des Moduls eingebunden ist.&amp;quot;,&lt;br /&gt;
				&amp;quot;en&amp;quot;: &amp;quot;This module is neither invoked by a template nor required/loaded by another module. If this is in error, make sure to add \u003Ccode\u003E{{[[Template:Documentation|Documentation]]}}\u003C/code\u003E/\u003Ccode\u003E{{[[Template:No documentation|No\u0026nbsp;documentation]]}}\u003C/code\u003E to the calling template&#039;s or parent&#039;s module documentation.&amp;quot;&lt;br /&gt;
			}&lt;br /&gt;
		],&lt;br /&gt;
		[&lt;br /&gt;
			&amp;quot;message_not_exists&amp;quot;,&lt;br /&gt;
			{&lt;br /&gt;
				&amp;quot;de&amp;quot;: &amp;quot;$1 existiert nicht.&amp;quot;,&lt;br /&gt;
				&amp;quot;en&amp;quot;: &amp;quot;$1 does not exist.&amp;quot;&lt;br /&gt;
			}&lt;br /&gt;
		],&lt;br /&gt;
		[&lt;br /&gt;
			&amp;quot;message_invokes_function&amp;quot;,&lt;br /&gt;
			{&lt;br /&gt;
				&amp;quot;de&amp;quot;: &amp;quot;&#039;&#039;&#039;$1&#039;&#039;&#039; verwendet die Funktion &#039;&#039;&#039;$2&#039;&#039;&#039; in [[$3]] durch [[Star Citizen:Lua|Lua]].&amp;quot;,&lt;br /&gt;
				&amp;quot;en&amp;quot;: &amp;quot;&#039;&#039;&#039;$1&#039;&#039;&#039; invokes function &#039;&#039;&#039;$2&#039;&#039;&#039; in [[$3]] using [[Star Citizen:Lua|Lua]].&amp;quot;&lt;br /&gt;
			}&lt;br /&gt;
		],&lt;br /&gt;
		[&lt;br /&gt;
			&amp;quot;message_module_functions_invoked_by&amp;quot;,&lt;br /&gt;
			{&lt;br /&gt;
				&amp;quot;de&amp;quot;: &amp;quot;&#039;&#039;&#039;$1&#039;&#039;&#039;&#039;s functions wird aufgerufen von $2.&amp;quot;,&lt;br /&gt;
				&amp;quot;en&amp;quot;: &amp;quot;&#039;&#039;&#039;$1&#039;&#039;&#039;&#039;s functions are invoked by $2.&amp;quot;&lt;br /&gt;
			}&lt;br /&gt;
		],&lt;br /&gt;
		[&lt;br /&gt;
			&amp;quot;message_function_invoked_by&amp;quot;,&lt;br /&gt;
			{&lt;br /&gt;
				&amp;quot;de&amp;quot;: &amp;quot;$2 (function &#039;&#039;&#039;$1&#039;&#039;&#039;)&amp;quot;,&lt;br /&gt;
				&amp;quot;en&amp;quot;: &amp;quot;$2 (function &#039;&#039;&#039;$1&#039;&#039;&#039;)&amp;quot;&lt;br /&gt;
			}&lt;br /&gt;
		],&lt;br /&gt;
		[&lt;br /&gt;
			&amp;quot;message_required_by&amp;quot;,&lt;br /&gt;
			{&lt;br /&gt;
				&amp;quot;de&amp;quot;: &amp;quot;&#039;&#039;&#039;$1&#039;&#039;&#039; wird benötigt von $2.&amp;quot;,&lt;br /&gt;
				&amp;quot;en&amp;quot;: &amp;quot;&#039;&#039;&#039;$1&#039;&#039;&#039; is required by $2.&amp;quot;&lt;br /&gt;
			}&lt;br /&gt;
		],&lt;br /&gt;
		[&lt;br /&gt;
			&amp;quot;message_loaded_by&amp;quot;,&lt;br /&gt;
			{&lt;br /&gt;
				&amp;quot;de&amp;quot;: &amp;quot;&#039;&#039;&#039;$1&#039;&#039;&#039; geladen von $2.&amp;quot;,&lt;br /&gt;
				&amp;quot;en&amp;quot;: &amp;quot;&#039;&#039;&#039;$1&#039;&#039;&#039; loaded by $2.&amp;quot;&lt;br /&gt;
			}&lt;br /&gt;
		],&lt;br /&gt;
		[&lt;br /&gt;
			&amp;quot;message_loads_data_from&amp;quot;,&lt;br /&gt;
			{&lt;br /&gt;
				&amp;quot;de&amp;quot;: &amp;quot;&#039;&#039;&#039;$1&#039;&#039;&#039; lädt Daten von $2.&amp;quot;,&lt;br /&gt;
				&amp;quot;en&amp;quot;: &amp;quot;&#039;&#039;&#039;$1&#039;&#039;&#039; loads data from $2.&amp;quot;&lt;br /&gt;
			}&lt;br /&gt;
		],&lt;br /&gt;
		[&lt;br /&gt;
			&amp;quot;message_transcludes&amp;quot;,&lt;br /&gt;
			{&lt;br /&gt;
				&amp;quot;de&amp;quot;: &amp;quot;&#039;&#039;&#039;$1&#039;&#039;&#039; bindet $2 ein, durch \u003Csamp\u003Eframe:preprocess()\u003C/samp\u003E.&amp;quot;,&lt;br /&gt;
				&amp;quot;en&amp;quot;: &amp;quot;&#039;&#039;&#039;$1&#039;&#039;&#039; transcludes $2 using \u003Csamp\u003Eframe:preprocess()\u003C/samp\u003E.&amp;quot;&lt;br /&gt;
			}&lt;br /&gt;
		],&lt;br /&gt;
		[&lt;br /&gt;
			&amp;quot;message_requires&amp;quot;,&lt;br /&gt;
			{&lt;br /&gt;
				&amp;quot;de&amp;quot;: &amp;quot;&#039;&#039;&#039;$1&#039;&#039;&#039; benötigt $2.&amp;quot;,&lt;br /&gt;
				&amp;quot;en&amp;quot;: &amp;quot;&#039;&#039;&#039;$1&#039;&#039;&#039; requires $2.&amp;quot;&lt;br /&gt;
			}&lt;br /&gt;
		],&lt;br /&gt;
		[&lt;br /&gt;
			&amp;quot;list_type_modules&amp;quot;,&lt;br /&gt;
			{&lt;br /&gt;
				&amp;quot;de&amp;quot;: &amp;quot;Module&amp;quot;,&lt;br /&gt;
				&amp;quot;en&amp;quot;: &amp;quot;modules&amp;quot;&lt;br /&gt;
			}&lt;br /&gt;
		],&lt;br /&gt;
		[&lt;br /&gt;
			&amp;quot;list_type_templates&amp;quot;,&lt;br /&gt;
			{&lt;br /&gt;
				&amp;quot;de&amp;quot;: &amp;quot;Vorlagen&amp;quot;,&lt;br /&gt;
				&amp;quot;en&amp;quot;: &amp;quot;templates&amp;quot;&lt;br /&gt;
			}&lt;br /&gt;
		]&lt;br /&gt;
	]&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=Module:Documentation/i18n.json&amp;diff=68</id>
		<title>Module:Documentation/i18n.json</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=Module:Documentation/i18n.json&amp;diff=68"/>
		<updated>2025-09-21T15:10:41Z</updated>

		<summary type="html">&lt;p&gt;Erina: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{&lt;br /&gt;
	&amp;quot;license&amp;quot;: &amp;quot;CC0-1.0&amp;quot;,&lt;br /&gt;
	&amp;quot;description&amp;quot;: {&lt;br /&gt;
		&amp;quot;en&amp;quot;: &amp;quot;Translation table for the Module:Documentation&amp;quot;&lt;br /&gt;
	},&lt;br /&gt;
	&amp;quot;schema&amp;quot;: {&lt;br /&gt;
		&amp;quot;fields&amp;quot;: [&lt;br /&gt;
			{&lt;br /&gt;
				&amp;quot;name&amp;quot;: &amp;quot;id&amp;quot;,&lt;br /&gt;
				&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;&lt;br /&gt;
			},&lt;br /&gt;
			{&lt;br /&gt;
				&amp;quot;name&amp;quot;: &amp;quot;message&amp;quot;,&lt;br /&gt;
				&amp;quot;type&amp;quot;: &amp;quot;localized&amp;quot;&lt;br /&gt;
			}&lt;br /&gt;
		]&lt;br /&gt;
	},&lt;br /&gt;
	&amp;quot;data&amp;quot;: [&lt;br /&gt;
		[&lt;br /&gt;
			&amp;quot;module&amp;quot;,&lt;br /&gt;
			{&lt;br /&gt;
				&amp;quot;de&amp;quot;: &amp;quot;Modul&amp;quot;,&lt;br /&gt;
				&amp;quot;en&amp;quot;: &amp;quot;module&amp;quot;&lt;br /&gt;
			}&lt;br /&gt;
		],&lt;br /&gt;
		[&lt;br /&gt;
			&amp;quot;template&amp;quot;,&lt;br /&gt;
			{&lt;br /&gt;
				&amp;quot;de&amp;quot;: &amp;quot;Vorlage&amp;quot;,&lt;br /&gt;
				&amp;quot;en&amp;quot;: &amp;quot;template&amp;quot;&lt;br /&gt;
			}&lt;br /&gt;
		],&lt;br /&gt;
		[&lt;br /&gt;
			&amp;quot;message_subpage_title&amp;quot;,&lt;br /&gt;
			{&lt;br /&gt;
				&amp;quot;de&amp;quot;: &amp;quot;Dies ist die Dokumentationsseite für &#039;$1&#039;.&amp;quot;,&lt;br /&gt;
				&amp;quot;en&amp;quot;: &amp;quot;This is a documentation subpage for &#039;$1&#039;.&amp;quot;&lt;br /&gt;
			}&lt;br /&gt;
		],&lt;br /&gt;
		[&lt;br /&gt;
			&amp;quot;message_subpage_desc&amp;quot;,&lt;br /&gt;
			{&lt;br /&gt;
				&amp;quot;de&amp;quot;: &amp;quot;Es enthält Nutzungsinformationen, Kategorien und andere Inhalte, die nicht Teil der [[$1|Original $2-Seite]] sind.&amp;quot;,&lt;br /&gt;
				&amp;quot;en&amp;quot;: &amp;quot;It contains usage information, categories, and other content that is not part of the [[$1|original $2 page]].&amp;quot;&lt;br /&gt;
			}&lt;br /&gt;
		],&lt;br /&gt;
		[&lt;br /&gt;
			&amp;quot;message_documentation_title&amp;quot;,&lt;br /&gt;
			{&lt;br /&gt;
				&amp;quot;de&amp;quot;: &amp;quot;$1 Dokumentation&amp;quot;,&lt;br /&gt;
				&amp;quot;en&amp;quot;: &amp;quot;$1 documentation&amp;quot;&lt;br /&gt;
			}&lt;br /&gt;
		],&lt;br /&gt;
		[&lt;br /&gt;
			&amp;quot;message_transclude_desc&amp;quot;,&lt;br /&gt;
			{&lt;br /&gt;
				&amp;quot;de&amp;quot;: &amp;quot;Diese Dokumentation wird von [[$1/doc]] aus übernommen. Änderungen können auf der Diskussionsseite vorgeschlagen werden.&amp;quot;,&lt;br /&gt;
				&amp;quot;en&amp;quot;: &amp;quot;This documentation is transcluded from [[$1/doc]]. Changes can be proposed in the talk page.&amp;quot;&lt;br /&gt;
			}&lt;br /&gt;
		],&lt;br /&gt;
		[&lt;br /&gt;
			&amp;quot;message_shared_across&amp;quot;,&lt;br /&gt;
			{&lt;br /&gt;
				&amp;quot;de&amp;quot;: &amp;quot;&#039;&#039;&#039;$1&#039;&#039;&#039; wird von den [https://github.com/The-Star-Citizen-Wikis/SharedModules/tree/master/$2 Star Citizen Wikis] verwendet.&amp;quot;,&lt;br /&gt;
				&amp;quot;en&amp;quot;: &amp;quot;&#039;&#039;&#039;$1&#039;&#039;&#039; is [https://github.com/The-Star-Citizen-Wikis/SharedModules/tree/master/$2 shared across] the Star Citizen Wikis.&amp;quot;&lt;br /&gt;
			}&lt;br /&gt;
		],&lt;br /&gt;
		[&lt;br /&gt;
			&amp;quot;message_shared_across_subtext&amp;quot;,&lt;br /&gt;
			{&lt;br /&gt;
				&amp;quot;de&amp;quot;: &amp;quot;Dieses $1 wird über die Star Citizen Wikis geteilt. Alle Änderungen sollten auch an das GitHub-Repository weitergeleitet werden.&amp;quot;,&lt;br /&gt;
				&amp;quot;en&amp;quot;: &amp;quot;This $1 is shared across the Star Citizen Wikis. Any changes should also be relayed to the GitHub repository.&amp;quot;&lt;br /&gt;
			}&lt;br /&gt;
		],&lt;br /&gt;
		[&lt;br /&gt;
			&amp;quot;message_from_wikipedia&amp;quot;,&lt;br /&gt;
			{&lt;br /&gt;
				&amp;quot;de&amp;quot;: &amp;quot;&#039;&#039;&#039;$1&#039;&#039;&#039; wird von [https://en.wikipedia.org/wiki/$2 $3] Wikipedia importiert.&amp;quot;,&lt;br /&gt;
				&amp;quot;en&amp;quot;: &amp;quot;&#039;&#039;&#039;$1&#039;&#039;&#039; is imported from [https://en.wikipedia.org/wiki/$2 $3] on Wikipedia.&amp;quot;&lt;br /&gt;
			}&lt;br /&gt;
		],&lt;br /&gt;
		[&lt;br /&gt;
			&amp;quot;message_from_wikipedia_subtext&amp;quot;,&lt;br /&gt;
			{&lt;br /&gt;
				&amp;quot;de&amp;quot;: &amp;quot;Dieses $1 wurde aus der englischen Wikipedia importiert. Obwohl das visuelle Erscheinungsbild unterschiedlich sein kann, ist die Funktionalität identisch. Eine ausführliche Dokumentation finden Sie auf der Wikipedia-Seite.&amp;quot;,&lt;br /&gt;
				&amp;quot;en&amp;quot;: &amp;quot;This $1 is imported from the English Wikipedia. Although the visual appearance might be different, the functionality is identical. Please refer to the Wikipedia page for detailed documentation.&amp;quot;&lt;br /&gt;
			}&lt;br /&gt;
		],&lt;br /&gt;
		[&lt;br /&gt;
			&amp;quot;message_module_configuration&amp;quot;,&lt;br /&gt;
			{&lt;br /&gt;
				&amp;quot;de&amp;quot;: &amp;quot;&#039;&#039;&#039;$1&#039;&#039;&#039; lädt Konfiguration von [[$1/config.json]].&amp;quot;,&lt;br /&gt;
				&amp;quot;en&amp;quot;: &amp;quot;&#039;&#039;&#039;$1&#039;&#039;&#039; loads configuration from [[$1/config.json]].&amp;quot;&lt;br /&gt;
			}&lt;br /&gt;
		],&lt;br /&gt;
		[&lt;br /&gt;
			&amp;quot;message_module_configuration_subtext&amp;quot;,&lt;br /&gt;
			{&lt;br /&gt;
				&amp;quot;de&amp;quot;: &amp;quot;Dieses Modul kann über die Unterseite config.json konfiguriert werden.&amp;quot;,&lt;br /&gt;
				&amp;quot;en&amp;quot;: &amp;quot;This module can be configurated from the config.json subpage.&amp;quot;&lt;br /&gt;
			}&lt;br /&gt;
		],&lt;br /&gt;
		[&lt;br /&gt;
			&amp;quot;message_module_i18n&amp;quot;,&lt;br /&gt;
			{&lt;br /&gt;
				&amp;quot;de&amp;quot;: &amp;quot;&#039;&#039;&#039;$1&#039;&#039;&#039; lädt Sprachen von [[$2/i18n.json]].&amp;quot;,&lt;br /&gt;
				&amp;quot;en&amp;quot;: &amp;quot;&#039;&#039;&#039;$1&#039;&#039;&#039; loads messages from [[$2/i18n.json]].&amp;quot;&lt;br /&gt;
			}&lt;br /&gt;
		],&lt;br /&gt;
		[&lt;br /&gt;
			&amp;quot;message_module_i18n_subtext&amp;quot;,&lt;br /&gt;
			{&lt;br /&gt;
				&amp;quot;de&amp;quot;: &amp;quot;Dieses Modul ist sprachneutral konzipiert. Alle Meldungen werden auf der Unterseite i18n.json gespeichert.&amp;quot;,&lt;br /&gt;
				&amp;quot;en&amp;quot;: &amp;quot;This module is designed to be language-neutral. All of the messages are saved in the i18n.json subpage.&amp;quot;&lt;br /&gt;
			}&lt;br /&gt;
		],&lt;br /&gt;
		[&lt;br /&gt;
			&amp;quot;message_module_tests&amp;quot;,&lt;br /&gt;
			{&lt;br /&gt;
				&amp;quot;de&amp;quot;: &amp;quot;Dies ist die Seite mit Testfällen für das Modul [[Modul:$1]].&amp;quot;,&lt;br /&gt;
				&amp;quot;en&amp;quot;: &amp;quot;This is the test cases page for the module [[Module:$1]].&amp;quot;&lt;br /&gt;
			}&lt;br /&gt;
		],&lt;br /&gt;
		[&lt;br /&gt;
			&amp;quot;message_styles&amp;quot;,&lt;br /&gt;
			{&lt;br /&gt;
				&amp;quot;de&amp;quot;: &amp;quot;&#039;&#039;&#039;$1&#039;&#039;&#039; lädt Styles aus [[$2/styles.css]].&amp;quot;,&lt;br /&gt;
				&amp;quot;en&amp;quot;: &amp;quot;&#039;&#039;&#039;$1&#039;&#039;&#039; loads styles from [[$2/styles.css]].&amp;quot;&lt;br /&gt;
			}&lt;br /&gt;
		]&lt;br /&gt;
	]&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=Module:Documentation/styles.css&amp;diff=66</id>
		<title>Module:Documentation/styles.css</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=Module:Documentation/styles.css&amp;diff=66"/>
		<updated>2025-09-21T15:10:41Z</updated>

		<summary type="html">&lt;p&gt;Erina: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;.documentation {&lt;br /&gt;
    margin-top: var( --space-md );&lt;br /&gt;
    padding-top: var( --space-md );&lt;br /&gt;
    border-top: var( --border-base );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.documentation-header {&lt;br /&gt;
    display: flex;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    justify-content: space-between;&lt;br /&gt;
    flex-wrap: wrap;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.documentation-header,&lt;br /&gt;
.documentation-subheader {&lt;br /&gt;
    line-height: 1.25;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.documentation-title {&lt;br /&gt;
    color: var( --color-emphasized );&lt;br /&gt;
    font-size: var( --font-size-large );&lt;br /&gt;
    font-weight: var( --font-weight-semi-bold );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.documentation-links {&lt;br /&gt;
    font-family: var( --font-family-monospace );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.documentation-subheader {&lt;br /&gt;
    color: var( --color-subtle );&lt;br /&gt;
    font-size: var( --font-size-small );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.documentation-content {&lt;br /&gt;
    margin-top: var( --space-xl );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.documentation-modulestats {&lt;br /&gt;
    padding: var( --space-xxs );&lt;br /&gt;
    background: var( --color-surface-1 );&lt;br /&gt;
    border-radius: var( --border-radius-medium );&lt;br /&gt;
    display: flex;&lt;br /&gt;
    align-items: center;&lt;br /&gt;
    justify-content: space-between;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.documentation-modulestats &amp;gt; * {&lt;br /&gt;
    margin: 0 !important;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=Module:Translate&amp;diff=64</id>
		<title>Module:Translate</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=Module:Translate&amp;diff=64"/>
		<updated>2025-09-21T15:10:41Z</updated>

		<summary type="html">&lt;p&gt;Erina: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;require( &#039;strict&#039; )&lt;br /&gt;
&lt;br /&gt;
local Translate = {}&lt;br /&gt;
&lt;br /&gt;
local metatable = {}&lt;br /&gt;
local methodtable = {}&lt;br /&gt;
&lt;br /&gt;
metatable.__index = methodtable&lt;br /&gt;
&lt;br /&gt;
local libraryUtil = require( &#039;libraryUtil&#039; )&lt;br /&gt;
local checkType = libraryUtil.checkType&lt;br /&gt;
local i18n = require( &#039;Module:i18n&#039; ):new()&lt;br /&gt;
&lt;br /&gt;
--- Cache table containing i18n data at the &#039;data&#039; key, and a key map at the &#039;keys&#039; key&lt;br /&gt;
--- The table is keyed by the i18n.json module name&lt;br /&gt;
local cache = {}&lt;br /&gt;
local i18nDataset = &#039;Module:Translate/i18n.json&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--- Uses the current title as the base and appends &#039;/i18n.json&#039;&lt;br /&gt;
---&lt;br /&gt;
--- @param dataset table&lt;br /&gt;
--- @return string|nil&lt;br /&gt;
local function guessDataset( dataset )&lt;br /&gt;
    if string.find( dataset, &#039;:&#039;, 1, true ) then&lt;br /&gt;
        return dataset&lt;br /&gt;
    elseif type( dataset ) == &#039;string&#039; then&lt;br /&gt;
        return string.format( &#039;Module:%s/i18n.json&#039;, dataset )&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return nil&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--- Loads a dataset and saves it to the cache&lt;br /&gt;
---&lt;br /&gt;
--- @param dataset string&lt;br /&gt;
--- @return table { data = &amp;quot;The dataset&amp;quot;, keys = &amp;quot;Translation key mapped to index&amp;quot; }&lt;br /&gt;
local function load( dataset )&lt;br /&gt;
    if cache[ dataset ] ~= nil then&lt;br /&gt;
        return cache[ dataset ]&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local data = mw.loadJsonData( dataset )&lt;br /&gt;
    local keys = {}&lt;br /&gt;
    for index, row in ipairs( data.data ) do&lt;br /&gt;
        keys[ row[ 1 ] ] = index&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    cache[ dataset ] = {&lt;br /&gt;
        data = data,&lt;br /&gt;
        keys = keys&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return cache[ dataset ]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--- Retrieves a message from a dataset and formats it according to parameters and language&lt;br /&gt;
---&lt;br /&gt;
--- @param dataset string&lt;br /&gt;
--- @param key string&lt;br /&gt;
--- @param params table&lt;br /&gt;
--- @param lang string&lt;br /&gt;
local function formatMessage( dataset, key, params, lang )&lt;br /&gt;
    local data = load( dataset )&lt;br /&gt;
&lt;br /&gt;
    if data.keys[ key ] == nil then&lt;br /&gt;
        error( formatMessage( i18nDataset, &#039;error_bad_msgkey&#039;, { key, dataset }, mw.getContentLanguage():getCode() ) )&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local msg = data.data.data[ data.keys[ key ] ][ 2 ]&lt;br /&gt;
&lt;br /&gt;
    if msg == nil then&lt;br /&gt;
        error( formatMessage( i18nDataset, &#039;error_bad_msgkey&#039;, { key, dataset }, mw.getContentLanguage():getCode() ) )&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    msg = msg[ lang ] or error( string.format( &#039;Language &amp;quot;%s&amp;quot; not found for key &amp;quot;%s&amp;quot;&#039;, lang, key ) )&lt;br /&gt;
&lt;br /&gt;
    local result = mw.message.newRawMessage( msg, unpack( params or {} ) )&lt;br /&gt;
&lt;br /&gt;
    return result:plain()&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--- Translates a message&lt;br /&gt;
---&lt;br /&gt;
--- @param dataset string&lt;br /&gt;
--- @param key string&lt;br /&gt;
--- @return string&lt;br /&gt;
function methodtable.format( dataset, key, ... )&lt;br /&gt;
    dataset = guessDataset( dataset )&lt;br /&gt;
&lt;br /&gt;
    checkType(&#039;format&#039;, 1, dataset, &#039;string&#039;)&lt;br /&gt;
    checkType(&#039;format&#039;, 2, key, &#039;string&#039;)&lt;br /&gt;
&lt;br /&gt;
    local lang = mw.getContentLanguage():getCode()&lt;br /&gt;
&lt;br /&gt;
    return formatMessage( dataset, key, {...}, lang )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--- Translates a message in a given language&lt;br /&gt;
---&lt;br /&gt;
--- @param lang string&lt;br /&gt;
--- @param dataset string&lt;br /&gt;
--- @param key string&lt;br /&gt;
--- @return string&lt;br /&gt;
function methodtable.formatInLanguage( lang, dataset, key, ... )&lt;br /&gt;
    dataset = guessDataset( dataset )&lt;br /&gt;
&lt;br /&gt;
    checkType(&#039;formatInLanguage&#039;, 1, lang, &#039;string&#039;)&lt;br /&gt;
    checkType(&#039;formatInLanguage&#039;, 2, dataset, &#039;string&#039;)&lt;br /&gt;
    checkType(&#039;formatInLanguage&#039;, 3, key, &#039;string&#039;)&lt;br /&gt;
&lt;br /&gt;
    return formatMessage( dataset, key, {...}, lang )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--- Wrapper function for Translate.getTemplateData that wraps the output in a &amp;lt;templatedata&amp;gt; tag&lt;br /&gt;
---&lt;br /&gt;
--- @param frame table Current MW Frame&lt;br /&gt;
--- @return string&lt;br /&gt;
function Translate.doc( frame )&lt;br /&gt;
    local dataset = frame.args[ 1 ] or frame.args[ &#039;dataset&#039; ] or ( mw.title.getCurrentTitle().prefixedText .. &#039;/i18n.json&#039; )&lt;br /&gt;
&lt;br /&gt;
    return frame:extensionTag( &#039;templatedata&#039;, Translate.getTemplateData( dataset ) )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--- Base logic taken from Module:TNT&lt;br /&gt;
--- Iterates through all user settable arguments and outputs json usable in a &amp;lt;templatedata&amp;gt; tag&lt;br /&gt;
---&lt;br /&gt;
--- @param dataset string The data.json page from which the arguments are taken&lt;br /&gt;
--- @return string Json&lt;br /&gt;
function Translate.getTemplateData( dataset )&lt;br /&gt;
    local data = load( guessDataset( dataset ) )&lt;br /&gt;
    local instance = Translate:new( dataset )&lt;br /&gt;
&lt;br /&gt;
    local names = {}&lt;br /&gt;
    for _, field in ipairs( data.data.schema.fields ) do&lt;br /&gt;
        table.insert( names, field.name )&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local numOnly = true&lt;br /&gt;
    local params = {}&lt;br /&gt;
    local paramOrder = {}&lt;br /&gt;
&lt;br /&gt;
    for _, row in ipairs( data.data.data ) do&lt;br /&gt;
        local newVal = {}&lt;br /&gt;
        local name&lt;br /&gt;
&lt;br /&gt;
        if row[ 1 ]:sub( 1, 3 ) == &#039;ARG&#039; then&lt;br /&gt;
            for pos, columnName in ipairs( names ) do&lt;br /&gt;
                if columnName == &#039;id&#039; then&lt;br /&gt;
                    name = instance.format( dataset, row[ pos ] )&lt;br /&gt;
                elseif columnName ~= &#039;message&#039; then&lt;br /&gt;
                    newVal[ columnName ] = row[ pos ]&lt;br /&gt;
&lt;br /&gt;
                    -- Allow to share examples and label&lt;br /&gt;
                    if ( columnName == &#039;example&#039; or columnName == &#039;label&#039; ) and type( row[ pos ] ) == &#039;string&#039; then&lt;br /&gt;
                        newVal[ columnName ] = {&lt;br /&gt;
                            de = row[ pos ],&lt;br /&gt;
                            en = row[ pos ],&lt;br /&gt;
                        }&lt;br /&gt;
                    end&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
&lt;br /&gt;
            if name and newVal[ &#039;type&#039; ] ~= nil then&lt;br /&gt;
                if type( name ) ~= &amp;quot;number&amp;quot; and ( type( name ) ~= &amp;quot;string&amp;quot; or not string.match( name, &amp;quot;^%d+$&amp;quot; ) ) then&lt;br /&gt;
                    numOnly = false&lt;br /&gt;
                end&lt;br /&gt;
&lt;br /&gt;
                params[ name ] = newVal&lt;br /&gt;
&lt;br /&gt;
                table.insert( paramOrder, name )&lt;br /&gt;
&lt;br /&gt;
                -- TODO: Limit this to a specified subset of url args&lt;br /&gt;
                if row[ 1 ]:sub( -3 ) == &#039;Url&#039; then&lt;br /&gt;
                    for i = 1, 4 do&lt;br /&gt;
                        local tmp = {}&lt;br /&gt;
                        for k, v in pairs( newVal ) do&lt;br /&gt;
                            if type( v ) == &#039;table&#039; then&lt;br /&gt;
                                tmp[ k ] = {}&lt;br /&gt;
                                for k1, v1 in pairs( v ) do&lt;br /&gt;
                                    tmp[ k ][ k1 ] = v1&lt;br /&gt;
                                end&lt;br /&gt;
                            else&lt;br /&gt;
                                tmp[ k ] = v&lt;br /&gt;
                            end&lt;br /&gt;
                        end&lt;br /&gt;
&lt;br /&gt;
                        local nameI = name .. tostring( i )&lt;br /&gt;
                        tmp[ &#039;required&#039; ] = false&lt;br /&gt;
                        tmp[ &#039;suggested&#039; ] = false&lt;br /&gt;
                        params[ nameI ] = tmp&lt;br /&gt;
&lt;br /&gt;
                        table.insert( paramOrder, nameI )&lt;br /&gt;
                    end&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- Work around json encoding treating {&amp;quot;1&amp;quot;:{...}} as an [{...}]&lt;br /&gt;
    if numOnly then&lt;br /&gt;
        params[&#039;zzz123&#039;]=&#039;&#039;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local json = mw.text.jsonEncode({&lt;br /&gt;
        params = params,&lt;br /&gt;
        paramOrder = paramOrder,&lt;br /&gt;
        description = data.template_description,&lt;br /&gt;
    })&lt;br /&gt;
&lt;br /&gt;
    if numOnly then&lt;br /&gt;
        json = string.gsub( json,&#039;&amp;quot;zzz123&amp;quot;:&amp;quot;&amp;quot;,?&#039;, &amp;quot;&amp;quot; )&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return json&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--- Calls TNT with the given key&lt;br /&gt;
---&lt;br /&gt;
--- @param dataset string The i18n.json page&lt;br /&gt;
--- @param config table The calling module&#039;s config&lt;br /&gt;
--- @param key string The translation key&lt;br /&gt;
--- @param addSuffix boolean|nil Adds a language suffix if config.smw_multilingual_text is true&lt;br /&gt;
--- @return string If the key was not found in the .tab page, the key is returned&lt;br /&gt;
function methodtable.translate( self, dataset, config, key, addSuffix, ... )&lt;br /&gt;
    checkType( &#039;Module:Translate.translate&#039;, 1, self, &#039;table&#039; )&lt;br /&gt;
    checkType( &#039;Module:Translate.translate&#039;, 2, dataset, &#039;string&#039; )&lt;br /&gt;
    checkType( &#039;Module:Translate.translate&#039;, 3, config, &#039;table&#039; )&lt;br /&gt;
    checkType( &#039;Module:Translate.translate&#039;, 4, key, &#039;string&#039; )&lt;br /&gt;
    checkType( &#039;Module:Translate.translate&#039;, 5, addSuffix, &#039;boolean&#039;, true )&lt;br /&gt;
&lt;br /&gt;
    -- Temporary fallback function&lt;br /&gt;
	local prefix = string.match( key, &#039;([^_]*)&#039; )&lt;br /&gt;
	if prefix == &#039;SMW&#039; or prefix == &#039;label&#039; or prefix == &#039;message&#039; or prefix == &#039;category&#039; then&lt;br /&gt;
		return i18n:translate( key )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	addSuffix = addSuffix or false&lt;br /&gt;
	local success, translation&lt;br /&gt;
&lt;br /&gt;
	local function multilingualIfActive( input )&lt;br /&gt;
		if addSuffix and config.smw_multilingual_text == true then&lt;br /&gt;
			return string.format( &#039;%s@%s&#039;, input, config.module_lang or mw.getContentLanguage():getCode() )&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		return input&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if config.module_lang ~= nil then&lt;br /&gt;
		success, translation = pcall( self.formatInLanguage, config.module_lang, dataset, key or &#039;&#039;, ... )&lt;br /&gt;
	else&lt;br /&gt;
		success, translation = pcall( self.format, dataset, key or &#039;&#039;, ... )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if not success or translation == nil then&lt;br /&gt;
        local title = mw.title.new( guessDataset( dataset ) )&lt;br /&gt;
&lt;br /&gt;
        if not title.exists then&lt;br /&gt;
            error( string.format( &#039;I18N table &amp;quot;%s&amp;quot; does not exist!&#039;, dataset ), 3 )&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return multilingualIfActive( translation )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--- New Instance&lt;br /&gt;
---&lt;br /&gt;
--- @return table Translate&lt;br /&gt;
function Translate.new( self, dataset )&lt;br /&gt;
    local instance = {&lt;br /&gt;
        dataset = dataset or nil&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    setmetatable( instance, metatable )&lt;br /&gt;
&lt;br /&gt;
    return instance&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
return Translate&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=Module:Mbox/styles.css&amp;diff=62</id>
		<title>Module:Mbox/styles.css</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=Module:Mbox/styles.css&amp;diff=62"/>
		<updated>2025-09-21T15:10:41Z</updated>

		<summary type="html">&lt;p&gt;Erina: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;.mbox {&lt;br /&gt;
	position: relative;&lt;br /&gt;
	display: flex;&lt;br /&gt;
	flex-direction: column;&lt;br /&gt;
	margin-block: var(--space-md);&lt;br /&gt;
	background-color: var(--color-surface-1);&lt;br /&gt;
	border: var(--border-base);&lt;br /&gt;
	border-radius: var(--border-radius-medium);&lt;br /&gt;
	font-size: var(--font-size-small);&lt;br /&gt;
	line-height: var(--line-height-xx-small);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.mbox.mbox-high {&lt;br /&gt;
	background-color: var(--background-color-destructive-subtle);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.mbox.mbox-med {&lt;br /&gt;
	background-color: var(--background-color-warning-subtle);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.mbox-title,&lt;br /&gt;
.mbox-text {&lt;br /&gt;
	padding: var(--space-sm) var(--space-md);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.mbox-title {&lt;br /&gt;
	display: flex;&lt;br /&gt;
	align-items: center;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.mbox-icon img {&lt;br /&gt;
	display: block;&lt;br /&gt;
	width: var(--font-size-small);&lt;br /&gt;
	height: auto;&lt;br /&gt;
	margin-right: var(--space-xs);&lt;br /&gt;
	opacity: var(--opacity-icon-base);&lt;br /&gt;
	filter: var(--filter-invert);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.mbox-text {&lt;br /&gt;
	position: absolute;&lt;br /&gt;
	top: 100%;&lt;br /&gt;
	left: 0;&lt;br /&gt;
	right: 0;&lt;br /&gt;
	z-index: 10;&lt;br /&gt;
	margin-inline: -1px;&lt;br /&gt;
	box-sizing: border-box;&lt;br /&gt;
	background-color: var(--color-surface-1);&lt;br /&gt;
	border-inline: var(--border-base);&lt;br /&gt;
	border-bottom: var(--border-base);&lt;br /&gt;
	border-bottom-left-radius: var(--border-radius-medium);&lt;br /&gt;
	border-bottom-right-radius: var(--border-radius-medium);&lt;br /&gt;
	box-shadow: var(--box-shadow-drop-xx-large);&lt;br /&gt;
	opacity: 0;&lt;br /&gt;
	visibility: hidden;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.mbox-text::before {&lt;br /&gt;
	content: &#039;&#039;;&lt;br /&gt;
	display: block;&lt;br /&gt;
	position: absolute;&lt;br /&gt;
	top: 0;&lt;br /&gt;
	left: var(--space-md);&lt;br /&gt;
	right: var(--space-md);&lt;br /&gt;
	height: var(--border-width-base);&lt;br /&gt;
	background: var(--border-color-subtle);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.mbox:hover {&lt;br /&gt;
	/* Merge with popup */&lt;br /&gt;
	border-bottom-left-radius: 0;&lt;br /&gt;
	border-bottom-right-radius: 0;&lt;br /&gt;
	box-shadow: var(--box-shadow-drop-xx-large);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.mbox:hover .mbox-text {&lt;br /&gt;
	opacity: 1;&lt;br /&gt;
	visibility: visible;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=Module:Mbox&amp;diff=60</id>
		<title>Module:Mbox</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=Module:Mbox&amp;diff=60"/>
		<updated>2025-09-21T15:10:41Z</updated>

		<summary type="html">&lt;p&gt;Erina: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;local libraryUtil = require( &#039;libraryUtil&#039; )&lt;br /&gt;
local checkType = libraryUtil.checkType&lt;br /&gt;
local mArguments -- lazily initialise [[Module:Arguments]]&lt;br /&gt;
local mError     -- lazily initialise [[Module:Error]]&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
--- Helper function to throw error&lt;br /&gt;
--&lt;br /&gt;
-- @param msg string - Error message&lt;br /&gt;
--&lt;br /&gt;
-- @return string - Formatted error message in wikitext&lt;br /&gt;
local function makeWikitextError( msg )&lt;br /&gt;
	mError = require( &#039;Module:Error&#039; )&lt;br /&gt;
	return mError.error {&lt;br /&gt;
		message = &#039;Error: &#039; .. msg .. &#039;.&#039;&lt;br /&gt;
	}&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.mbox( frame )&lt;br /&gt;
	mArguments = require( &#039;Module:Arguments&#039; )&lt;br /&gt;
	local args = mArguments.getArgs( frame )&lt;br /&gt;
	local title = args[ 1 ] or args[ &#039;title&#039; ]&lt;br /&gt;
	local text = args[ 2 ] or args[ &#039;text&#039; ]&lt;br /&gt;
	if not title or not text then&lt;br /&gt;
		return makeWikitextError(&lt;br /&gt;
			&#039;no title or text specified&#039;&lt;br /&gt;
		)&lt;br /&gt;
	end&lt;br /&gt;
	return p._mbox( title, text, {&lt;br /&gt;
		extraclasses = args.extraclasses,&lt;br /&gt;
		icon = args.icon&lt;br /&gt;
	} )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p._mbox( title, text, options )&lt;br /&gt;
	checkType( &#039;_mbox&#039;, 1, title, &#039;string&#039; )&lt;br /&gt;
	checkType( &#039;_mbox&#039;, 2, text, &#039;string&#039; )&lt;br /&gt;
	checkType( &#039;_mbox&#039;, 3, options, &#039;table&#039;, true )&lt;br /&gt;
&lt;br /&gt;
	options = options or {}&lt;br /&gt;
	local mbox = mw.html.create( &#039;div&#039; )&lt;br /&gt;
	local extraclasses&lt;br /&gt;
	if type( options.extraclasses ) == &#039;string&#039; then&lt;br /&gt;
		extraclasses = options.extraclasses&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	mbox&lt;br /&gt;
		:attr( &#039;role&#039;, &#039;presentation&#039; )&lt;br /&gt;
		:addClass( &#039;mbox&#039; )&lt;br /&gt;
		:addClass( extraclasses )&lt;br /&gt;
&lt;br /&gt;
	local mboxTitle = mbox:tag( &#039;div&#039; ):addClass( &#039;mbox-title&#039; )&lt;br /&gt;
&lt;br /&gt;
	if options.icon and type( options.icon ) == &#039;string&#039; then&lt;br /&gt;
		mboxTitle:tag( &#039;div&#039; )&lt;br /&gt;
			:addClass( &#039;mbox-icon metadata&#039; )&lt;br /&gt;
			:wikitext( &#039;[[File:&#039; .. options.icon .. &#039;|14px|link=]]&#039; )&lt;br /&gt;
			:done()&lt;br /&gt;
			:tag( &#039;div&#039; )&lt;br /&gt;
			:wikitext( title )&lt;br /&gt;
	else&lt;br /&gt;
		mboxTitle:wikitext( title )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	mbox:tag( &#039;div&#039; )&lt;br /&gt;
		:addClass( &#039;mbox-text&#039; )&lt;br /&gt;
		:wikitext( text )&lt;br /&gt;
&lt;br /&gt;
	return mw.getCurrentFrame():extensionTag {&lt;br /&gt;
		name = &#039;templatestyles&#039;, args = { src = &#039;Module:Mbox/styles.css&#039; }&lt;br /&gt;
	} .. tostring( mbox )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=Module:User_error&amp;diff=58</id>
		<title>Module:User error</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=Module:User_error&amp;diff=58"/>
		<updated>2025-09-21T15:10:41Z</updated>

		<summary type="html">&lt;p&gt;Erina: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;--------------------------------------------------------------------------------&lt;br /&gt;
-- A less intimidating version of the built-in &amp;quot;error()&amp;quot; function, to help&lt;br /&gt;
-- editors fix their mistakes when transcluding a template.&lt;br /&gt;
--&lt;br /&gt;
-- @see [[wikia:w:c:Dev:Module:User error]] for a similar module.&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local checkType = require(&amp;quot;libraryUtil&amp;quot;).checkType;&lt;br /&gt;
&lt;br /&gt;
return function (message, ...)&lt;br /&gt;
	checkType(&amp;quot;Module:User error&amp;quot;, 1, message, &amp;quot;string&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	local result = mw.text.tag(&lt;br /&gt;
		&amp;quot;strong&amp;quot;,&lt;br /&gt;
		{ class=&amp;quot;error&amp;quot; },&lt;br /&gt;
		&amp;quot;Error: &amp;quot; .. message&lt;br /&gt;
	);&lt;br /&gt;
&lt;br /&gt;
	local categories = {};&lt;br /&gt;
	for i = 1, select(&amp;quot;#&amp;quot;, ...) do&lt;br /&gt;
		local category = select(i, ...);&lt;br /&gt;
		checkType(&amp;quot;Module:User error&amp;quot;, 1 + i, category, &amp;quot;string&amp;quot;, true);&lt;br /&gt;
&lt;br /&gt;
		if (category and category ~= &amp;quot;&amp;quot;) then&lt;br /&gt;
			table.insert(categories, &amp;quot;[[Category:&amp;quot; .. category .. &amp;quot;]]&amp;quot;);&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return result .. table.concat(categories);&lt;br /&gt;
end;&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=Module:Format_link&amp;diff=56</id>
		<title>Module:Format link</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=Module:Format_link&amp;diff=56"/>
		<updated>2025-09-21T15:10:41Z</updated>

		<summary type="html">&lt;p&gt;Erina: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- Imported from: https://en.wikipedia.org/wiki/Module:Format_link&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Format link&lt;br /&gt;
--&lt;br /&gt;
-- Makes a wikilink from the given link and display values. Links are escaped&lt;br /&gt;
-- with colons if necessary, and links to sections are detected and displayed&lt;br /&gt;
-- with &amp;quot; § &amp;quot; as a separator rather than the standard MediaWiki &amp;quot;#&amp;quot;. Used in&lt;br /&gt;
-- the {{format link}} template.&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
local libraryUtil = require(&#039;libraryUtil&#039;)&lt;br /&gt;
local checkType = libraryUtil.checkType&lt;br /&gt;
local checkTypeForNamedArg = libraryUtil.checkTypeForNamedArg&lt;br /&gt;
local mArguments -- lazily initialise [[Module:Arguments]]&lt;br /&gt;
local mError -- lazily initialise [[Module:Error]]&lt;br /&gt;
local yesno -- lazily initialise [[Module:Yesno]]&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Helper functions&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local function getArgs(frame)&lt;br /&gt;
	-- Fetches the arguments from the parent frame. Whitespace is trimmed and&lt;br /&gt;
	-- blanks are removed.&lt;br /&gt;
	mArguments = require(&#039;Module:Arguments&#039;)&lt;br /&gt;
	return mArguments.getArgs(frame, {parentOnly = true})&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function removeInitialColon(s)&lt;br /&gt;
	-- Removes the initial colon from a string, if present.&lt;br /&gt;
	return s:match(&#039;^:?(.*)&#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function maybeItalicize(s, shouldItalicize)&lt;br /&gt;
	-- Italicize s if s is a string and the shouldItalicize parameter is true.&lt;br /&gt;
	if s and shouldItalicize then&lt;br /&gt;
		return &#039;&amp;lt;i&amp;gt;&#039; .. s .. &#039;&amp;lt;/i&amp;gt;&#039;&lt;br /&gt;
	else&lt;br /&gt;
		return s&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function parseLink(link)&lt;br /&gt;
	-- Parse a link and return a table with the link&#039;s components.&lt;br /&gt;
	-- These components are:&lt;br /&gt;
	-- - link: the link, stripped of any initial colon (always present)&lt;br /&gt;
	-- - page: the page name (always present)&lt;br /&gt;
	-- - section: the page name (may be nil)&lt;br /&gt;
	-- - display: the display text, if manually entered after a pipe (may be nil)&lt;br /&gt;
	link = removeInitialColon(link)&lt;br /&gt;
&lt;br /&gt;
	-- Find whether a faux display value has been added with the {{!}} magic&lt;br /&gt;
	-- word.&lt;br /&gt;
	local prePipe, display = link:match(&#039;^(.-)|(.*)$&#039;)&lt;br /&gt;
	link = prePipe or link&lt;br /&gt;
&lt;br /&gt;
	-- Find the page, if it exists.&lt;br /&gt;
	-- For links like [[#Bar]], the page will be nil.&lt;br /&gt;
	local preHash, postHash = link:match(&#039;^(.-)#(.*)$&#039;)&lt;br /&gt;
	local page&lt;br /&gt;
	if not preHash then&lt;br /&gt;
		-- We have a link like [[Foo]].&lt;br /&gt;
		page = link&lt;br /&gt;
	elseif preHash ~= &#039;&#039; then&lt;br /&gt;
		-- We have a link like [[Foo#Bar]].&lt;br /&gt;
		page = preHash&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Find the section, if it exists.&lt;br /&gt;
	local section&lt;br /&gt;
	if postHash and postHash ~= &#039;&#039; then&lt;br /&gt;
		section = postHash&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return {&lt;br /&gt;
		link = link,&lt;br /&gt;
		page = page,&lt;br /&gt;
		section = section,&lt;br /&gt;
		display = display,&lt;br /&gt;
	}&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function formatDisplay(parsed, options)&lt;br /&gt;
	-- Formats a display string based on a parsed link table (matching the&lt;br /&gt;
	-- output of parseLink) and an options table (matching the input options for&lt;br /&gt;
	-- _formatLink).&lt;br /&gt;
	local page = maybeItalicize(parsed.page, options.italicizePage)&lt;br /&gt;
	local section = maybeItalicize(parsed.section, options.italicizeSection)&lt;br /&gt;
	if (not section) then&lt;br /&gt;
		return page&lt;br /&gt;
	elseif (not page) then&lt;br /&gt;
		return string.format(&#039;§&amp;amp;nbsp;%s&#039;, section)&lt;br /&gt;
	else&lt;br /&gt;
		return string.format(&#039;%s §&amp;amp;nbsp;%s&#039;, page, section)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function missingArgError(target)&lt;br /&gt;
	mError = require(&#039;Module:Error&#039;)&lt;br /&gt;
	return mError.error{message =&lt;br /&gt;
		&#039;Error: no link or target specified! ([[&#039; .. target .. &#039;#Errors|help]])&#039;&lt;br /&gt;
	}&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Main functions&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
function p.formatLink(frame)&lt;br /&gt;
	-- The formatLink export function, for use in templates.&lt;br /&gt;
	yesno = require(&#039;Module:Yesno&#039;)&lt;br /&gt;
	local args = getArgs(frame)&lt;br /&gt;
	local link = args[1] or args.link&lt;br /&gt;
	local target = args[3] or args.target&lt;br /&gt;
	if not (link or target) then&lt;br /&gt;
		return missingArgError(&#039;Template:Format link&#039;)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return p._formatLink{&lt;br /&gt;
		link = link,&lt;br /&gt;
		display = args[2] or args.display,&lt;br /&gt;
		target = target,&lt;br /&gt;
		italicizePage = yesno(args.italicizepage),&lt;br /&gt;
		italicizeSection = yesno(args.italicizesection),&lt;br /&gt;
		categorizeMissing = args.categorizemissing&lt;br /&gt;
	}&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p._formatLink(options)&lt;br /&gt;
	-- The formatLink export function, for use in modules.&lt;br /&gt;
	checkType(&#039;_formatLink&#039;, 1, options, &#039;table&#039;)&lt;br /&gt;
	local function check(key, expectedType) --for brevity&lt;br /&gt;
		checkTypeForNamedArg(&lt;br /&gt;
			&#039;_formatLink&#039;, key, options[key], expectedType or &#039;string&#039;, true&lt;br /&gt;
		)&lt;br /&gt;
	end&lt;br /&gt;
	check(&#039;link&#039;)&lt;br /&gt;
	check(&#039;display&#039;)&lt;br /&gt;
	check(&#039;target&#039;)&lt;br /&gt;
	check(&#039;italicizePage&#039;, &#039;boolean&#039;)&lt;br /&gt;
	check(&#039;italicizeSection&#039;, &#039;boolean&#039;)&lt;br /&gt;
	check(&#039;categorizeMissing&#039;)&lt;br /&gt;
&lt;br /&gt;
	-- Normalize link and target and check that at least one is present&lt;br /&gt;
	if options.link == &#039;&#039; then options.link = nil end&lt;br /&gt;
	if options.target == &#039;&#039; then options.target = nil end&lt;br /&gt;
	if not (options.link or options.target) then&lt;br /&gt;
		return missingArgError(&#039;Module:Format link&#039;)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local parsed = parseLink(options.link)&lt;br /&gt;
	local display = options.display or parsed.display&lt;br /&gt;
	local catMissing = options.categorizeMissing&lt;br /&gt;
	local category = &#039;&#039;&lt;br /&gt;
&lt;br /&gt;
	-- Find the display text&lt;br /&gt;
	if not display then display = formatDisplay(parsed, options) end&lt;br /&gt;
&lt;br /&gt;
	-- Handle the target option if present&lt;br /&gt;
	if options.target then&lt;br /&gt;
		local parsedTarget = parseLink(options.target)&lt;br /&gt;
		parsed.link = parsedTarget.link&lt;br /&gt;
		parsed.page = parsedTarget.page&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Test if page exists if a diagnostic category is specified&lt;br /&gt;
	if catMissing and (string.len(catMissing) &amp;gt; 0) then&lt;br /&gt;
		local title = nil&lt;br /&gt;
		if parsed.page then title = mw.title.new(parsed.page) end&lt;br /&gt;
		if title and (not title.isExternal) then&lt;br /&gt;
			local success, exists = pcall(function() return title.exists end)&lt;br /&gt;
			if success and not exists then&lt;br /&gt;
				category = string.format(&#039;[[Category:%s]]&#039;, catMissing)&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Format the result as a link&lt;br /&gt;
	if parsed.link == display then&lt;br /&gt;
		return string.format(&#039;[[:%s]]%s&#039;, parsed.link, category)&lt;br /&gt;
	else&lt;br /&gt;
		return string.format(&#039;[[:%s|%s]]%s&#039;, parsed.link, display, category)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Derived convenience functions&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
function p.formatPages(options, pages)&lt;br /&gt;
	-- Formats an array of pages using formatLink and the given options table,&lt;br /&gt;
	-- and returns it as an array. Nil values are not allowed.&lt;br /&gt;
	local ret = {}&lt;br /&gt;
	for i, page in ipairs(pages) do&lt;br /&gt;
		ret[i] = p._formatLink{&lt;br /&gt;
			link = page,&lt;br /&gt;
			categorizeMissing = options.categorizeMissing,&lt;br /&gt;
			italicizePage = options.italicizePage,&lt;br /&gt;
			italicizeSection = options.italicizeSection&lt;br /&gt;
		}&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=Module:Array&amp;diff=54</id>
		<title>Module:Array</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=Module:Array&amp;diff=54"/>
		<updated>2025-09-21T15:10:40Z</updated>

		<summary type="html">&lt;p&gt;Erina: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- Imported from: https://runescape.wiki/w/Module:Array&lt;br /&gt;
&lt;br /&gt;
local libraryUtil = require(&#039;libraryUtil&#039;)&lt;br /&gt;
local checkType = libraryUtil.checkType&lt;br /&gt;
local checkTypeMulti = libraryUtil.checkTypeMulti&lt;br /&gt;
&lt;br /&gt;
---@class Array&lt;br /&gt;
---@operator call(any[]): Array&lt;br /&gt;
---@operator concat(any[]): Array&lt;br /&gt;
---@operator concat(number|string|function): string&lt;br /&gt;
---@operator unm: Array&lt;br /&gt;
---@operator add(number|number[]|Array): Array&lt;br /&gt;
---@operator sub(number|number[]|Array): Array&lt;br /&gt;
---@operator mul(number|number[]|Array): Array&lt;br /&gt;
---@operator div(number|number[]|Array): Array&lt;br /&gt;
---@operator pow(number|number[]|Array): Array&lt;br /&gt;
local Array = {&lt;br /&gt;
	pop = table.remove&lt;br /&gt;
}&lt;br /&gt;
Array.__index = Array&lt;br /&gt;
&lt;br /&gt;
setmetatable(Array, {&lt;br /&gt;
	__index = table,&lt;br /&gt;
	__call = function (_, arr)&lt;br /&gt;
		return Array.new(arr)&lt;br /&gt;
	end&lt;br /&gt;
})&lt;br /&gt;
&lt;br /&gt;
-- function Array.__tostring(arr)&lt;br /&gt;
-- 	-- local dumpObject = require(&#039;Module:Logger&#039;).dumpObject&lt;br /&gt;
-- 	require &#039;log&#039;&lt;br /&gt;
-- 	local dumpObject = dumpObject&lt;br /&gt;
-- 	local mt = getmetatable(arr)&lt;br /&gt;
-- 	setmetatable(arr, nil)&lt;br /&gt;
-- 	local str = dumpObject(arr, {clean=true, collapseLimit=100})&lt;br /&gt;
-- 	setmetatable(arr, mt)&lt;br /&gt;
-- 	return str&lt;br /&gt;
-- end&lt;br /&gt;
&lt;br /&gt;
function Array.__concat(lhs, rhs)&lt;br /&gt;
	if type(lhs) == &#039;table&#039; and type(rhs) == &#039;table&#039; then&lt;br /&gt;
		local res = {}&lt;br /&gt;
		for i = 1, #lhs do&lt;br /&gt;
			res[i] = lhs[i]&lt;br /&gt;
		end&lt;br /&gt;
		local l = #lhs&lt;br /&gt;
		for i = 1, #rhs do&lt;br /&gt;
			res[i + l] = rhs[i]&lt;br /&gt;
		end&lt;br /&gt;
		return setmetatable(res, getmetatable(lhs) or getmetatable(rhs))&lt;br /&gt;
	else&lt;br /&gt;
		return tostring(lhs) .. tostring(rhs)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Array.__unm(arr)&lt;br /&gt;
	return Array.map(arr, function(x) return -x end)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---@param lhs number|number[]|Array&lt;br /&gt;
---@param rhs number|number[]|Array&lt;br /&gt;
---@param funName string&lt;br /&gt;
---@param opName string&lt;br /&gt;
---@param fun fun(lhs: number, rhs: number): number&lt;br /&gt;
---@return Array&lt;br /&gt;
local function mathTemplate(lhs, rhs, funName, opName, fun)&lt;br /&gt;
	checkTypeMulti(&#039;Module:Array.&#039; .. funName, 1, lhs, {&#039;number&#039;, &#039;table&#039;})&lt;br /&gt;
	checkTypeMulti(&#039;Module:Array.&#039; .. funName, 2, rhs, {&#039;number&#039;, &#039;table&#039;})&lt;br /&gt;
	local res = {}&lt;br /&gt;
&lt;br /&gt;
	if type(lhs) == &#039;number&#039; then&lt;br /&gt;
		for i = 1, #rhs do&lt;br /&gt;
			res[i] = fun(lhs, rhs[i])&lt;br /&gt;
		end&lt;br /&gt;
	elseif type(rhs) == &#039;number&#039; then&lt;br /&gt;
		for i = 1, #lhs do&lt;br /&gt;
			res[i] = fun(lhs[i], rhs)&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		assert(#lhs == #rhs, string.format(&#039;Elementwise %s failed because arrays have different sizes (left: %d, right: %d)&#039;, opName, #lhs, #rhs))&lt;br /&gt;
		for i = 1, #lhs do&lt;br /&gt;
			res[i] = fun(lhs[i], rhs[i])&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return setmetatable(res, getmetatable(lhs) or getmetatable(rhs))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Array.__add(lhs, rhs)&lt;br /&gt;
	return mathTemplate(lhs, rhs, &#039;__add&#039;, &#039;addition&#039;, function(x, y) return x + y end)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Array.__sub(lhs, rhs)&lt;br /&gt;
	return mathTemplate(lhs, rhs, &#039;__sub&#039;, &#039;substraction&#039;, function(x, y) return x - y end)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Array.__mul(lhs, rhs)&lt;br /&gt;
	return mathTemplate(lhs, rhs, &#039;__mul&#039;, &#039;multiplication&#039;, function(x, y) return x * y end)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Array.__div(lhs, rhs)&lt;br /&gt;
	return mathTemplate(lhs, rhs, &#039;__div&#039;, &#039;division&#039;, function(x, y) return x / y end)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Array.__pow(lhs, rhs)&lt;br /&gt;
	return mathTemplate(lhs, rhs, &#039;__pow&#039;, &#039;exponentiation&#039;, function(x, y) return x ^ y end)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Array.__eq(lhs, rhs)&lt;br /&gt;
	if #lhs ~= #rhs then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	for i = 1, #lhs do&lt;br /&gt;
		if lhs[i] ~= rhs[i] 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;
---Behaviour depends on the value of `fn`:&lt;br /&gt;
---* `nil` - Checks that the array doesn&#039;t contain any **false** elements.&lt;br /&gt;
---* `fun(elem: any, i?: integer): boolean` - Returns **true** if `fn` returns **true** for every element.&lt;br /&gt;
---* `number` | `table` | `boolean` - Checks that all elements in `arr` are equal to this value.&lt;br /&gt;
---@param arr any[]&lt;br /&gt;
---@param fn? any&lt;br /&gt;
---@return boolean&lt;br /&gt;
function Array.all(arr, fn)&lt;br /&gt;
	checkType(&#039;Module:Array.all&#039;, 1, arr, &#039;table&#039;)&lt;br /&gt;
	if fn == nil then fn = function(item) return item end end&lt;br /&gt;
	if type(fn) ~= &#039;function&#039; then&lt;br /&gt;
		local val = fn&lt;br /&gt;
		fn = function(item) return item == val end&lt;br /&gt;
	end&lt;br /&gt;
	local i = 1&lt;br /&gt;
	while arr[i] ~= nil do&lt;br /&gt;
		---@diagnostic disable-next-line: redundant-parameter&lt;br /&gt;
		if not fn(arr[i], i) then&lt;br /&gt;
			return false&lt;br /&gt;
		end&lt;br /&gt;
		i = i + 1&lt;br /&gt;
	end&lt;br /&gt;
	return true&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---Behaviour depends on the value of `fn`:&lt;br /&gt;
---* `nil` - Checks that the array contains at least one non **false** element.&lt;br /&gt;
---* `fun(elem: any, i?: integer): boolean` - Returns **true** if `fn` returns **true** for at least one element.&lt;br /&gt;
---* `number` | `table` | `boolean` - Checks that `arr` contains this value.&lt;br /&gt;
---@param arr any[]&lt;br /&gt;
---@param fn? any&lt;br /&gt;
---@return boolean&lt;br /&gt;
function Array.any(arr, fn)&lt;br /&gt;
	checkType(&#039;Module:Array.any&#039;, 1, arr, &#039;table&#039;)&lt;br /&gt;
	if fn == nil then fn = function(item) return item end end&lt;br /&gt;
	if type(fn) ~= &#039;function&#039; then&lt;br /&gt;
		local val = fn&lt;br /&gt;
		fn = function(item) return item == val end&lt;br /&gt;
	end&lt;br /&gt;
	local i = 1&lt;br /&gt;
	while arr[i] ~= nil do&lt;br /&gt;
		---@diagnostic disable-next-line: redundant-parameter&lt;br /&gt;
		if fn(arr[i], i) then&lt;br /&gt;
			return true&lt;br /&gt;
		end&lt;br /&gt;
		i = i + 1&lt;br /&gt;
	end&lt;br /&gt;
	return false&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---Recursively removes all metatables.&lt;br /&gt;
---@param arr any[]&lt;br /&gt;
---@return any[]&lt;br /&gt;
function Array.clean(arr)&lt;br /&gt;
	checkType(&#039;Module:Array.clean&#039;, 1, arr, &#039;table&#039;)&lt;br /&gt;
	for i = 1, #arr do&lt;br /&gt;
		if type(arr[i]) == &#039;table&#039; then&lt;br /&gt;
			Array.clean(arr[i])&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	setmetatable(arr, nil)&lt;br /&gt;
	return arr&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---Make a copy of the input table. Preserves metatables.&lt;br /&gt;
---@generic T: any[]&lt;br /&gt;
---@param arr T&lt;br /&gt;
---@param deep? boolean # Recursively clone subtables if **true**.&lt;br /&gt;
---@return T&lt;br /&gt;
function Array.clone(arr, deep)&lt;br /&gt;
	checkType(&#039;Module:Array.clone&#039;, 1, arr, &#039;table&#039;)&lt;br /&gt;
	checkType(&#039;Module:Array.clone&#039;, 2, deep, &#039;boolean&#039;, true)&lt;br /&gt;
	local res = {}&lt;br /&gt;
	for i = 1, #arr do&lt;br /&gt;
		if deep == true and type(arr[i]) == &#039;table&#039; then&lt;br /&gt;
			res[i] = Array.clone(arr[i], true)&lt;br /&gt;
		else&lt;br /&gt;
			res[i] = arr[i]&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return setmetatable(res, getmetatable(arr))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---Check if `arr` contains `val`.&lt;br /&gt;
---@param arr any[]&lt;br /&gt;
---@param val any&lt;br /&gt;
---@return boolean&lt;br /&gt;
function Array.contains(arr, val)&lt;br /&gt;
	checkType(&#039;Module:Array.contains&#039;, 1, arr, &#039;table&#039;)&lt;br /&gt;
	for i = 1, #arr do&lt;br /&gt;
		if arr[i] == val then&lt;br /&gt;
			return true&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return false&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---Check if `arr` contains any of the values in the table `t`.&lt;br /&gt;
---@param arr any[]&lt;br /&gt;
---@param t any[]&lt;br /&gt;
---@return boolean&lt;br /&gt;
function Array.containsAny(arr, t)&lt;br /&gt;
	checkType(&#039;Module:Array.containsAny&#039;, 1, arr, &#039;table&#039;)&lt;br /&gt;
	checkType(&#039;Module:Array.containsAny&#039;, 2, t, &#039;table&#039;)&lt;br /&gt;
	local lookupTbl = {}&lt;br /&gt;
	for i = 1, #t do&lt;br /&gt;
		lookupTbl[t[i]] = true&lt;br /&gt;
	end&lt;br /&gt;
	for i = 1, #arr do&lt;br /&gt;
		if lookupTbl[arr[i]] then&lt;br /&gt;
			return true&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return false&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---Check if `arr` contains all values in the table `t`.&lt;br /&gt;
---@param arr any[]&lt;br /&gt;
---@param t any[]&lt;br /&gt;
---@return boolean&lt;br /&gt;
function Array.containsAll(arr, t)&lt;br /&gt;
	checkType(&#039;Module:Array.containsAll&#039;, 1, arr, &#039;table&#039;)&lt;br /&gt;
	checkType(&#039;Module:Array.containsAll&#039;, 2, t, &#039;table&#039;)&lt;br /&gt;
	local lookupTbl = {}&lt;br /&gt;
	local l = #t&lt;br /&gt;
	local trueCount = 0&lt;br /&gt;
	for i = 1, l do&lt;br /&gt;
		lookupTbl[t[i]] = false&lt;br /&gt;
	end&lt;br /&gt;
	for i = 1, #arr do&lt;br /&gt;
		if lookupTbl[arr[i]] == false then&lt;br /&gt;
			lookupTbl[arr[i]] = true&lt;br /&gt;
			trueCount = trueCount + 1&lt;br /&gt;
		end&lt;br /&gt;
		if trueCount == l then&lt;br /&gt;
			return true&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return false&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---Convolute two number arrays.&lt;br /&gt;
---@generic T: number[]&lt;br /&gt;
---@param x T&lt;br /&gt;
---@param y T&lt;br /&gt;
---@return T&lt;br /&gt;
function Array.convolve(x, y)&lt;br /&gt;
	checkType(&#039;Module:Array.convolve&#039;, 1, x, &#039;table&#039;)&lt;br /&gt;
	checkType(&#039;Module:Array.convolve&#039;, 2, y, &#039;table&#039;)&lt;br /&gt;
	local z = {}&lt;br /&gt;
    local xLen, yLen = #x, #y&lt;br /&gt;
    for j = 1, (xLen + yLen - 1) do&lt;br /&gt;
        local sum = 0&lt;br /&gt;
        for k = math.max(1, j - yLen + 1), math.min(xLen, j) do&lt;br /&gt;
            sum = sum + x[k] * y[j-k+1]&lt;br /&gt;
        end&lt;br /&gt;
        z[j] = sum&lt;br /&gt;
    end&lt;br /&gt;
    return setmetatable(z, getmetatable(x) or getmetatable(y))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---Remove **nil** values from `arr` while preserving order.&lt;br /&gt;
---@generic T: any[]&lt;br /&gt;
---@param arr T&lt;br /&gt;
---@return T&lt;br /&gt;
function Array.condenseSparse(arr)&lt;br /&gt;
	checkType(&#039;Module:Array.condenseSparse&#039;, 1, arr, &#039;table&#039;)&lt;br /&gt;
	local keys = {}&lt;br /&gt;
	local res = {}&lt;br /&gt;
	local l = 0&lt;br /&gt;
	for k in pairs(arr) do&lt;br /&gt;
		l = l + 1&lt;br /&gt;
		keys[l] = k&lt;br /&gt;
	end&lt;br /&gt;
	table.sort(keys)&lt;br /&gt;
	for i =  1, l do&lt;br /&gt;
		res[i] = arr[keys[i]]&lt;br /&gt;
	end&lt;br /&gt;
	return setmetatable(res, getmetatable(arr))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---Behaviour depends on value of `val`:&lt;br /&gt;
---* `nil` - Counts the number of non **false** elements.&lt;br /&gt;
---* `fun(elem: any): boolean` - Count the number of times the function returned **true**.&lt;br /&gt;
---* `boolean` | `number` | `table` - Counts the number of times this value occurs in `arr`.&lt;br /&gt;
---@param arr any[]&lt;br /&gt;
---@param val? any&lt;br /&gt;
---@return integer&lt;br /&gt;
function Array.count(arr, val)&lt;br /&gt;
	checkType(&#039;Module:Array.count&#039;, 1, arr, &#039;table&#039;)&lt;br /&gt;
	if val == nil then val = function(item) return item end end&lt;br /&gt;
	if type(val) ~= &#039;function&#039; then&lt;br /&gt;
		local _val = val&lt;br /&gt;
		val = function(item) return item == _val end&lt;br /&gt;
	end&lt;br /&gt;
	local count = 0&lt;br /&gt;
	for i = 1, #arr do&lt;br /&gt;
		if val(arr[i]) then&lt;br /&gt;
			count = count + 1&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return count&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---Differentiate the array&lt;br /&gt;
---@generic T: number[]&lt;br /&gt;
---@param arr T&lt;br /&gt;
---@param order number? # Oder of the differentiation. Default is 1.&lt;br /&gt;
---@return T # Length is `#arr - order`&lt;br /&gt;
function Array.diff(arr, order)&lt;br /&gt;
	checkType(&#039;Module:Array.diff&#039;, 1, arr, &#039;table&#039;)&lt;br /&gt;
	checkType(&#039;Module:Array.diff&#039;, 2, order, &#039;number&#039;, true)&lt;br /&gt;
	local res = {}&lt;br /&gt;
	for i = 1, #arr - 1 do&lt;br /&gt;
		res[i] = arr[i+1] - arr[i]&lt;br /&gt;
	end&lt;br /&gt;
	if order and order &amp;gt; 1 then&lt;br /&gt;
		return Array.diff(res, order - 1)&lt;br /&gt;
	end&lt;br /&gt;
	return setmetatable(res, getmetatable(arr))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---Loops over `arr` and passes each element as the first argument to `fn`. This function returns nothing.&lt;br /&gt;
---@param arr any[]&lt;br /&gt;
---@param fn fun(elem: any, i?: integer)&lt;br /&gt;
function Array.each(arr, fn)&lt;br /&gt;
	checkType(&#039;Module:Array.each&#039;, 1, arr, &#039;table&#039;)&lt;br /&gt;
	checkType(&#039;Module:Array.each&#039;, 2, fn, &#039;function&#039;)&lt;br /&gt;
	local i = 1&lt;br /&gt;
	while arr[i] ~= nil do&lt;br /&gt;
		fn(arr[i], i)&lt;br /&gt;
		i = i + 1&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---Makes a copy of `arr` with only elements for which `fn` returned **true**.&lt;br /&gt;
---@generic T: any[]&lt;br /&gt;
---@param arr T&lt;br /&gt;
---@param fn fun(elem: any, i?: integer): boolean&lt;br /&gt;
---@return T&lt;br /&gt;
function Array.filter(arr, fn)&lt;br /&gt;
	checkType(&#039;Module:Array.filter&#039;, 1, arr, &#039;table&#039;)&lt;br /&gt;
	checkType(&#039;Module:Array.filter&#039;, 2, fn, &#039;function&#039;)&lt;br /&gt;
	local r = {}&lt;br /&gt;
	local len = 0&lt;br /&gt;
	local i = 1&lt;br /&gt;
	while arr[i] ~= nil do&lt;br /&gt;
		if fn(arr[i], i) then&lt;br /&gt;
			len = len + 1&lt;br /&gt;
			r[len] = arr[i]&lt;br /&gt;
		end&lt;br /&gt;
		i = i + 1&lt;br /&gt;
	end&lt;br /&gt;
	return setmetatable(r, getmetatable(arr))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---Find the first elements for which `fn` returns **true**.&lt;br /&gt;
---@param arr any[]&lt;br /&gt;
---@param fn any # A value to look for or a function of the form `fun(elem: any, i?: integer): boolean`.&lt;br /&gt;
---@param default? any # Value to return if no element passes the test.&lt;br /&gt;
---@return any? elem # The first element that passed the test.&lt;br /&gt;
---@return integer? i # The index of the item that passed the test.&lt;br /&gt;
function Array.find(arr, fn, default)&lt;br /&gt;
	checkType(&#039;Module:Array.find&#039;, 1, arr, &#039;table&#039;)&lt;br /&gt;
	checkTypeMulti(&#039;Module:Array.find_index&#039;, 2, fn, {&#039;function&#039;, &#039;table&#039;, &#039;number&#039;, &#039;boolean&#039;})&lt;br /&gt;
	if type(fn) ~= &#039;function&#039; then&lt;br /&gt;
		local _val = fn&lt;br /&gt;
		fn = function(item) return item == _val end&lt;br /&gt;
	end&lt;br /&gt;
	local i = 1&lt;br /&gt;
	while arr[i] ~= nil do&lt;br /&gt;
		---@diagnostic disable-next-line: redundant-parameter&lt;br /&gt;
		if fn(arr[i], i) then&lt;br /&gt;
			return arr[i], i&lt;br /&gt;
		end&lt;br /&gt;
		i = i + 1&lt;br /&gt;
	end&lt;br /&gt;
	return default, nil&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---Find the index of `val`.&lt;br /&gt;
---@param arr any[]&lt;br /&gt;
---@param val any # A value to look for or a function of the form `fun(elem: any, i?: integer): boolean`.&lt;br /&gt;
---@param default? any # Value to return if no element passes the test.&lt;br /&gt;
---@return integer?&lt;br /&gt;
function Array.find_index(arr, val, default)&lt;br /&gt;
	checkType(&#039;Module:Array.find_index&#039;, 1, arr, &#039;table&#039;)&lt;br /&gt;
	checkTypeMulti(&#039;Module:Array.find_index&#039;, 2, val, {&#039;function&#039;, &#039;table&#039;, &#039;number&#039;, &#039;boolean&#039;})&lt;br /&gt;
	if type(val) ~= &#039;function&#039; then&lt;br /&gt;
		local _val = val&lt;br /&gt;
		val = function(item) return item == _val end&lt;br /&gt;
	end&lt;br /&gt;
	local i = 1&lt;br /&gt;
	while arr[i] ~= nil do&lt;br /&gt;
		---@diagnostic disable-next-line: redundant-parameter&lt;br /&gt;
		if val(arr[i], i) then&lt;br /&gt;
			return i&lt;br /&gt;
		end&lt;br /&gt;
		i = i + 1&lt;br /&gt;
	end&lt;br /&gt;
	return default&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---Extracts a subset of `arr`.&lt;br /&gt;
---@generic T: any[]&lt;br /&gt;
---@param arr T&lt;br /&gt;
---@param indexes integer|integer[] # Indexes of the elements.&lt;br /&gt;
---@return T&lt;br /&gt;
function Array.get(arr, indexes)&lt;br /&gt;
	checkType(&#039;Module:Array.set&#039;, 1, arr, &#039;table&#039;)&lt;br /&gt;
	checkTypeMulti(&#039;Module:Array.set&#039;, 2, indexes, {&#039;table&#039;, &#039;number&#039;})&lt;br /&gt;
	if type(indexes) == &#039;number&#039; then&lt;br /&gt;
		indexes = {indexes}&lt;br /&gt;
	end&lt;br /&gt;
	local res = {}&lt;br /&gt;
	for i = 1, #indexes do&lt;br /&gt;
		 res[i] = arr[indexes[i]]&lt;br /&gt;
	end&lt;br /&gt;
	return setmetatable(res, getmetatable(arr))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---Integrates the array. Effectively does $\left\{\sum^{n}_{start}{arr[n]} \,\Bigg|\, n \in [start, stop]\right\}$.&lt;br /&gt;
---@generic T: number[]&lt;br /&gt;
---@param arr T # number[]&lt;br /&gt;
---@param start? integer # Index where to start the summation. Defaults to 1.&lt;br /&gt;
---@param stop? integer # Index where to stop the summation. Defaults to #arr.&lt;br /&gt;
---@return T&lt;br /&gt;
function Array.int(arr, start, stop)&lt;br /&gt;
	checkType(&#039;Module:Array.int&#039;, 1, arr, &#039;table&#039;)&lt;br /&gt;
	checkType(&#039;Module:Array.int&#039;, 2, start, &#039;number&#039;, true)&lt;br /&gt;
	checkType(&#039;Module:Array.int&#039;, 3, stop, &#039;number&#039;, true)&lt;br /&gt;
	local res = {}&lt;br /&gt;
	start = start or 1&lt;br /&gt;
	stop = stop or #arr&lt;br /&gt;
	res[1] = arr[start]&lt;br /&gt;
	for i = 1, stop - start do&lt;br /&gt;
		res[i+1] = res[i] + arr[start + i]&lt;br /&gt;
	end&lt;br /&gt;
	return setmetatable(res, getmetatable(arr))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---Returns an array with elements that are present in both tables.&lt;br /&gt;
---@generic T: any[]&lt;br /&gt;
---@param arr1 T&lt;br /&gt;
---@param arr2 T&lt;br /&gt;
---@return T&lt;br /&gt;
function Array.intersect(arr1, arr2)&lt;br /&gt;
	checkType(&#039;Module:Array.intersect&#039;, 1, arr1, &#039;table&#039;)&lt;br /&gt;
	checkType(&#039;Module:Array.intersect&#039;, 2, arr2, &#039;table&#039;)&lt;br /&gt;
	local arr2Elements = {}&lt;br /&gt;
	local res = {}&lt;br /&gt;
	local len = 0&lt;br /&gt;
	Array.each(arr2, function(item) arr2Elements[item] = true end)&lt;br /&gt;
	Array.each(arr1, function(item)&lt;br /&gt;
		if arr2Elements[item] then&lt;br /&gt;
			len = len + 1&lt;br /&gt;
			res[len] = item&lt;br /&gt;
		end&lt;br /&gt;
	end)&lt;br /&gt;
	return setmetatable(res, getmetatable(arr1) or getmetatable(arr2))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---Checks if the two inputs have at least one element in common.&lt;br /&gt;
---@param arr1 any[]&lt;br /&gt;
---@param arr2 any[]&lt;br /&gt;
---@return boolean&lt;br /&gt;
function Array.intersects(arr1, arr2)&lt;br /&gt;
	checkType(&#039;Module:Array.intersects&#039;, 1, arr1, &#039;table&#039;)&lt;br /&gt;
	checkType(&#039;Module:Array.intersects&#039;, 2, arr2, &#039;table&#039;)&lt;br /&gt;
	local small = {}&lt;br /&gt;
	local large&lt;br /&gt;
	if #arr1 &amp;lt;= #arr2 then&lt;br /&gt;
		Array.each(arr1, function(item) small[item] = true end)&lt;br /&gt;
		large = arr2&lt;br /&gt;
	else&lt;br /&gt;
		Array.each(arr2, function(item) small[item] = true end)&lt;br /&gt;
		large = arr1&lt;br /&gt;
	end&lt;br /&gt;
	return Array.any(large, function(item) return small[item] end)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---Inserts values into `arr`.&lt;br /&gt;
---@generic T: any[]&lt;br /&gt;
---@param arr T&lt;br /&gt;
---@param val any # If `val` is an array and `unpackVal` is **true** then the individual elements of `val` are inserted.&lt;br /&gt;
---@param index? integer # Location to start the insertion. Default is at the end of `arr`.&lt;br /&gt;
---@param unpackVal? boolean # Default is **false**.&lt;br /&gt;
---@return T&lt;br /&gt;
---@overload fun(arr: T, val: any, unpackVal: boolean): T&lt;br /&gt;
function Array.insert(arr, val, index, unpackVal)&lt;br /&gt;
	checkType(&#039;Module:Array.insert&#039;, 1, arr, &#039;table&#039;)&lt;br /&gt;
	checkTypeMulti(&#039;Module:Array.insert&#039;, 3, index, {&#039;number&#039;, &#039;boolean&#039;, &#039;nil&#039;})&lt;br /&gt;
	checkType(&#039;Module:Array.insert&#039;, 4, unpackVal, &#039;boolean&#039;, true)&lt;br /&gt;
	if type(index) == &#039;boolean&#039;  then&lt;br /&gt;
		unpackVal, index = index, nil&lt;br /&gt;
	end&lt;br /&gt;
	local len = #arr&lt;br /&gt;
	index = index or (len + 1)&lt;br /&gt;
	local mt = getmetatable(arr)&lt;br /&gt;
	setmetatable(arr, nil)&lt;br /&gt;
&lt;br /&gt;
	if type(val) == &#039;table&#039; and unpackVal then&lt;br /&gt;
		local len2 = #val&lt;br /&gt;
		for i = 0, len - index do&lt;br /&gt;
			arr[len + len2 - i] = arr[len - i]&lt;br /&gt;
		end&lt;br /&gt;
		for i = 0, len2 - 1 do&lt;br /&gt;
			arr[index + i] = val[i + 1]&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		table.insert(arr, index, val)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return setmetatable(arr, mt)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---Returns the last element of `arr`.&lt;br /&gt;
---@param arr any[]&lt;br /&gt;
---@param offset? integer&lt;br /&gt;
---@return any&lt;br /&gt;
function Array.last(arr, offset)&lt;br /&gt;
	checkType(&#039;Module:Array.last&#039;, 1, arr, &#039;table&#039;)&lt;br /&gt;
	checkType(&#039;Module:Array.last&#039;, 2, offset, &#039;number&#039;, true)&lt;br /&gt;
	return arr[#arr + offset]&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---Returns a new table were each element of `arr` is modified by `fn`.&lt;br /&gt;
---@generic T: any[]&lt;br /&gt;
---@param arr T&lt;br /&gt;
---@param fn fun(elem: any, i?: integer): any # First argument is the current element, the second argument is the index of the current element.&lt;br /&gt;
---@return T&lt;br /&gt;
function Array.map(arr, fn)&lt;br /&gt;
	checkType(&#039;Module:Array.map&#039;, 1, arr, &#039;table&#039;)&lt;br /&gt;
	checkType(&#039;Module:Array.map&#039;, 2, fn, &#039;function&#039;)&lt;br /&gt;
	local len = 0&lt;br /&gt;
	local r = {}&lt;br /&gt;
	local i = 1&lt;br /&gt;
	while arr[i] ~= nil do&lt;br /&gt;
		local tmp = fn(arr[i], i)&lt;br /&gt;
		if tmp ~= nil then&lt;br /&gt;
			len = len + 1&lt;br /&gt;
			r[len] = tmp&lt;br /&gt;
		end&lt;br /&gt;
		i = i + 1&lt;br /&gt;
	end&lt;br /&gt;
	return setmetatable(r, getmetatable(arr))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---Find the element for which `fn` returned the largest value.&lt;br /&gt;
---@param arr any[]&lt;br /&gt;
---@param fn fun(elem: any): any # The returned value needs to be comparable using the `&amp;lt;` operator.&lt;br /&gt;
---@return any elem # The element with the largest `fn` value.&lt;br /&gt;
---@return integer i # The index of this element.&lt;br /&gt;
function Array.max_by(arr, fn)&lt;br /&gt;
	checkType(&#039;Module:Array.max_by&#039;, 1, arr, &#039;table&#039;)&lt;br /&gt;
	checkType(&#039;Module:Array.max_by&#039;, 2, fn, &#039;function&#039;)&lt;br /&gt;
	return unpack(Array.reduce(arr, function(new, old, i)&lt;br /&gt;
		local y = fn(new)&lt;br /&gt;
		return y &amp;gt; old[2] and {new, y, i} or old&lt;br /&gt;
	end, {nil, -math.huge}))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---Find the largest value in the array.&lt;br /&gt;
---@param arr any[] # The values need to be comparable using the `&amp;lt;` operator.&lt;br /&gt;
---@return any elem&lt;br /&gt;
---@return integer i # The index of the largest value.&lt;br /&gt;
function Array.max(arr)&lt;br /&gt;
	checkType(&#039;Module:Array.max&#039;, 1, arr, &#039;table&#039;)&lt;br /&gt;
	local val, _, i = Array.max_by(arr, function(x) return x end)&lt;br /&gt;
	return val, i&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---Find the smallest value in the array.&lt;br /&gt;
---@param arr any[] # The values need to be comparable using the `&amp;lt;` operator.&lt;br /&gt;
---@return any elem&lt;br /&gt;
---@return integer i # The index of the smallest value.&lt;br /&gt;
function Array.min(arr)&lt;br /&gt;
	checkType(&#039;Module:Array.min&#039;, 1, arr, &#039;table&#039;)&lt;br /&gt;
	local val, _, i = Array.max_by(arr, function(x) return -x end)&lt;br /&gt;
	return val, i&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---Turn the input table into an Array. This makes it possible to use the colon `:` operator to access the Array methods.&lt;br /&gt;
---&lt;br /&gt;
---It also enables the use of math operators with the array.&lt;br /&gt;
---```&lt;br /&gt;
---local x = arr.new{ 1, 2, 3 }&lt;br /&gt;
---local y = arr{ 4, 5, 6 } -- Alternative notation&lt;br /&gt;
---&lt;br /&gt;
---print( -x ) --&amp;gt; { -1, -2, -3 }&lt;br /&gt;
---print( x + 2 ) --&amp;gt; { 3, 4, 5 }&lt;br /&gt;
---print( x - 2 ) --&amp;gt; { -1, 0, 1 }&lt;br /&gt;
---print( x * 2 ) --&amp;gt; { 2, 4, 6 }&lt;br /&gt;
---print( x / 2 ) --&amp;gt; { 0.5, 1, 1.5 }&lt;br /&gt;
---print( x ^ 2 ) --&amp;gt; { 1, 4, 9 }&lt;br /&gt;
---&lt;br /&gt;
---print( x + y ) --&amp;gt; { 5, 7, 9 }&lt;br /&gt;
---print( x .. y ) --&amp;gt; { 1, 2, 3, 4, 5, 6 }&lt;br /&gt;
---print( (x .. y):reject{3, 4, 5} ) --&amp;gt; { 1, 2, 6 }&lt;br /&gt;
---print( x:sum() ) --&amp;gt; 6&lt;br /&gt;
---&lt;br /&gt;
---print( x:update( {1, 3}, y:get{2, 3} * 2 ) ) --&amp;gt; { 10, 2, 12 }&lt;br /&gt;
---```&lt;br /&gt;
---@param arr? any[]&lt;br /&gt;
---@return Array&lt;br /&gt;
function Array.new(arr)&lt;br /&gt;
	local obj = arr or {}&lt;br /&gt;
	for _, v in pairs(obj) do&lt;br /&gt;
		if type(v) == &#039;table&#039; then&lt;br /&gt;
			Array.new(v)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if getmetatable(obj) == nil then&lt;br /&gt;
		setmetatable(obj, Array)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return obj&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---Creates an object that returns a value that is `step` higher than the previous value each time it gets called.&lt;br /&gt;
---&lt;br /&gt;
---The stored value can be read without incrementing by reading the `val` field.&lt;br /&gt;
---&lt;br /&gt;
---A new stored value can be set through the `val` field.&lt;br /&gt;
---&lt;br /&gt;
---A new step size can be set through the `step` field.&lt;br /&gt;
---```&lt;br /&gt;
---local inc = arr.newIncrementor(10, 5)&lt;br /&gt;
---print( inc() ) --&amp;gt; 10&lt;br /&gt;
---print( inc() ) --&amp;gt; 15&lt;br /&gt;
---print( inc.val ) --&amp;gt; 15&lt;br /&gt;
---inc.val = 100&lt;br /&gt;
---inc.step = 20&lt;br /&gt;
---print( inc.val ) --&amp;gt; 100&lt;br /&gt;
---print( inc() ) --&amp;gt; 120&lt;br /&gt;
---```&lt;br /&gt;
---@param start? number # Default is 1.&lt;br /&gt;
---@param step? number # Default is 1.&lt;br /&gt;
---@return Incrementor&lt;br /&gt;
function Array.newIncrementor(start, step)&lt;br /&gt;
	checkType(&#039;Module:Array.newIncrementor&#039;, 1, start, &#039;number&#039;, true)&lt;br /&gt;
	checkType(&#039;Module:Array.newIncrementor&#039;, 2, step, &#039;number&#039;, true)&lt;br /&gt;
	step = step or 1&lt;br /&gt;
	local n = (start or 1) - step&lt;br /&gt;
	---@class Incrementor&lt;br /&gt;
	local obj = {}&lt;br /&gt;
	return setmetatable(obj, {&lt;br /&gt;
		__call = function() n = n + step return n end,&lt;br /&gt;
		__tostring = function() return n end,&lt;br /&gt;
		__index = function() return n end,&lt;br /&gt;
		__newindex = function(self, k, v)&lt;br /&gt;
			if k == &#039;step&#039; and type(v) == &#039;number&#039; then&lt;br /&gt;
				step = v&lt;br /&gt;
			elseif type(v) == &#039;number&#039; then&lt;br /&gt;
				n = v&lt;br /&gt;
			end&lt;br /&gt;
		end,&lt;br /&gt;
		__concat = function(x, y) return tostring(x) .. tostring(y) end&lt;br /&gt;
	})&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---Returns a range of numbers.&lt;br /&gt;
---@param start number # Start value inclusive.&lt;br /&gt;
---@param stop number # Stop value inclusive for integers, exclusive for floats.&lt;br /&gt;
---@param step? number # Default is 1.&lt;br /&gt;
---@return Array&lt;br /&gt;
---@overload fun(stop: number): Array&lt;br /&gt;
function Array.range(start, stop, step)&lt;br /&gt;
	checkType(&#039;Module:Array.range&#039;, 1, start, &#039;number&#039;)&lt;br /&gt;
	checkType(&#039;Module:Array.range&#039;, 2, stop, &#039;number&#039;, true)&lt;br /&gt;
	checkType(&#039;Module:Array.range&#039;, 3, step, &#039;number&#039;, true)&lt;br /&gt;
	local arr = {}&lt;br /&gt;
	local len = 0&lt;br /&gt;
	if not stop then&lt;br /&gt;
		stop = start&lt;br /&gt;
		start = 1&lt;br /&gt;
	end&lt;br /&gt;
	for i = start, stop, step or 1 do&lt;br /&gt;
		len = len + 1&lt;br /&gt;
		arr[len] = i&lt;br /&gt;
	end&lt;br /&gt;
	return setmetatable(arr, Array)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---Condenses the array into a single value.&lt;br /&gt;
---&lt;br /&gt;
---For each element `fn` is called with the current element, the current accumulator, and the current element index. The returned value of `fn` becomes the accumulator for the next element.&lt;br /&gt;
---&lt;br /&gt;
---If no `accumulator` value is given at the start then the first element off `arr` becomes the accumulator and the iteration starts from the second element.&lt;br /&gt;
---```&lt;br /&gt;
---local t = { 1, 2, 3, 4 }&lt;br /&gt;
---local sum = arr.reduce( t, function(elem, acc) return acc + elem end ) -- sum == 10&lt;br /&gt;
---```&lt;br /&gt;
---@param arr any[]&lt;br /&gt;
---@param fn fun(elem: any, acc: any, i?: integer): any # The result of this function becomes the `acc` for the next element.&lt;br /&gt;
---@param accumulator? any&lt;br /&gt;
---@return any # This is the last accumulator value.&lt;br /&gt;
function Array.reduce(arr, fn, accumulator)&lt;br /&gt;
	checkType(&#039;Module:Array.reduce&#039;, 1, arr, &#039;table&#039;)&lt;br /&gt;
	checkType(&#039;Module:Array.reduce&#039;, 2, fn, &#039;function&#039;)&lt;br /&gt;
	local acc = accumulator&lt;br /&gt;
	local i = 1&lt;br /&gt;
	if acc == nil then&lt;br /&gt;
		acc = arr[1]&lt;br /&gt;
		i = 2&lt;br /&gt;
	end&lt;br /&gt;
	while arr[i] ~= nil do&lt;br /&gt;
		acc = fn(arr[i], acc, i)&lt;br /&gt;
		i = i + 1&lt;br /&gt;
	end&lt;br /&gt;
	return acc&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---Make a copy off `arr` with certain values removed.&lt;br /&gt;
---&lt;br /&gt;
---Behaviour for different values of `val`:&lt;br /&gt;
---* `boolean` | `number` - Remove values equal to this.&lt;br /&gt;
---* `table` - Remove all values in this table.&lt;br /&gt;
---* `fun(elem: any, i?: integer): boolean` - Remove elements for which the functions returns **true**.&lt;br /&gt;
---@generic T: any[]&lt;br /&gt;
---@param arr T&lt;br /&gt;
---@param val table|function|number|boolean&lt;br /&gt;
---@return T&lt;br /&gt;
function Array.reject(arr, val)&lt;br /&gt;
	checkType(&#039;Module:Array.reject&#039;, 1, arr, &#039;table&#039;)&lt;br /&gt;
	checkTypeMulti(&#039;Module:Array.reject&#039;, 2, val, {&#039;function&#039;, &#039;table&#039;, &#039;number&#039;, &#039;boolean&#039;})&lt;br /&gt;
	if type(val) ~= &#039;function&#039; and type(val) ~= &#039;table&#039; then&lt;br /&gt;
		val = {val}&lt;br /&gt;
	end&lt;br /&gt;
	local r = {}&lt;br /&gt;
	local len = 0&lt;br /&gt;
	if type(val) == &#039;function&#039; then&lt;br /&gt;
		local i = 1&lt;br /&gt;
		while arr[i] ~= nil do&lt;br /&gt;
			if not val(arr[i], i) then&lt;br /&gt;
				len = len + 1&lt;br /&gt;
				r[len] = arr[i]&lt;br /&gt;
			end&lt;br /&gt;
			i = i + 1&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		local rejectMap = {}&lt;br /&gt;
		Array.each(val --[[@as any[] ]], function(item) rejectMap[item] = true end)&lt;br /&gt;
		local i = 1&lt;br /&gt;
		while arr[i] ~= nil do&lt;br /&gt;
			if not rejectMap[arr[i]] then&lt;br /&gt;
				len = len + 1&lt;br /&gt;
				r[len] = arr[i]&lt;br /&gt;
			end&lt;br /&gt;
			i = i + 1&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return setmetatable(r, getmetatable(arr))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---Returns an Array with `val` repeated `n` times.&lt;br /&gt;
---@param val any&lt;br /&gt;
---@param n integer&lt;br /&gt;
---@return Array&lt;br /&gt;
function Array.rep(val, n)&lt;br /&gt;
	checkType(&#039;Module:Array.rep&#039;, 2, n, &#039;number&#039;)&lt;br /&gt;
	local r = {}&lt;br /&gt;
	for i = 1, n do&lt;br /&gt;
		r[i] = val&lt;br /&gt;
	end&lt;br /&gt;
	return setmetatable(r, Array)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---Condenses the array into a single value while saving every accumulator value.&lt;br /&gt;
---&lt;br /&gt;
---For each element `fn` is called with the current element, the current accumulator, and the current element index. The returned value of `fn` becomes the accumulator for the next element.&lt;br /&gt;
---&lt;br /&gt;
---If no `accumulator` value is given at the start then the first element off `arr` becomes the accumulator and the iteration starts from the second element.&lt;br /&gt;
---```&lt;br /&gt;
---local t = { 1, 2, 3, 4 }&lt;br /&gt;
---local x = arr.scan( t, function(elem, acc) return acc + elem end ) -- x = { 1, 3, 6, 10 }&lt;br /&gt;
---```&lt;br /&gt;
---@generic T: any[]&lt;br /&gt;
---@param arr T&lt;br /&gt;
---@param fn fun(elem: any, acc: any, i?: integer): any # Returned value becomes the accumulator for the next element.&lt;br /&gt;
---@param accumulator? any&lt;br /&gt;
---@return T&lt;br /&gt;
function Array.scan(arr, fn, accumulator)&lt;br /&gt;
	checkType(&#039;Module:Array.scan&#039;, 1, arr, &#039;table&#039;)&lt;br /&gt;
	checkType(&#039;Module:Array.scan&#039;, 2, fn, &#039;function&#039;)&lt;br /&gt;
	local acc = accumulator&lt;br /&gt;
	local r = {}&lt;br /&gt;
	local i = 1&lt;br /&gt;
	while arr[i] ~= nil do&lt;br /&gt;
		if i == 1 and not accumulator then&lt;br /&gt;
			acc = arr[i]&lt;br /&gt;
		else&lt;br /&gt;
			acc = fn(arr[i], acc, i)&lt;br /&gt;
		end&lt;br /&gt;
		r[i] = acc&lt;br /&gt;
		i = i + 1&lt;br /&gt;
	end&lt;br /&gt;
	return setmetatable(r, getmetatable(arr))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---Update a range of index with a range of values.&lt;br /&gt;
---&lt;br /&gt;
---If if only one value is given but multiple indexes than that value is set for all those indexes.&lt;br /&gt;
---&lt;br /&gt;
---If `values` is a table then it must of the same length as `indexes`.&lt;br /&gt;
---@generic T: any[]&lt;br /&gt;
---@param arr T&lt;br /&gt;
---@param indexes integer|integer[]&lt;br /&gt;
---@param values any|any[]&lt;br /&gt;
---@return T&lt;br /&gt;
function Array.set(arr, indexes, values)&lt;br /&gt;
	checkType(&#039;Module:Array.set&#039;, 1, arr, &#039;table&#039;)&lt;br /&gt;
	checkTypeMulti(&#039;Module:Array.set&#039;, 2, indexes, {&#039;table&#039;, &#039;number&#039;})&lt;br /&gt;
	local mt = getmetatable(arr)&lt;br /&gt;
	setmetatable(arr, nil)&lt;br /&gt;
	if type(indexes) == &#039;number&#039; then&lt;br /&gt;
		indexes = {indexes}&lt;br /&gt;
	end&lt;br /&gt;
	if type(values) == &#039;table&#039; then&lt;br /&gt;
		assert(#indexes == #values, string.format(&amp;quot;Module:Array.set: &#039;indexes&#039; and &#039;values&#039; arrays are not equal length (#indexes = %d, #values = %d)&amp;quot;, #indexes, #values))&lt;br /&gt;
		for i = 1, #indexes do&lt;br /&gt;
			arr[indexes[i]] = values[i]&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		for i = 1, #indexes do&lt;br /&gt;
			arr[indexes[i]] = values&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return setmetatable(arr, mt)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---Extract a subtable from `arr`.&lt;br /&gt;
---@generic T: any[]&lt;br /&gt;
---@param arr T&lt;br /&gt;
---@param start integer # Start index. Use negative values to count form the end of the array.&lt;br /&gt;
---@param stop integer # Stop index. Use negative values to count form the end of the array.&lt;br /&gt;
---@return T&lt;br /&gt;
---@overload fun(arr: T, stop: integer): T&lt;br /&gt;
function Array.slice(arr, start, stop)&lt;br /&gt;
	checkType(&#039;Module:Array.slice&#039;, 1, arr, &#039;table&#039;)&lt;br /&gt;
	checkType(&#039;Module:Array.slice&#039;, 2, start, &#039;number&#039;, true)&lt;br /&gt;
	checkType(&#039;Module:Array.slice&#039;, 3, stop, &#039;number&#039;, true)&lt;br /&gt;
	start = start or #arr&lt;br /&gt;
	if start &amp;lt; 0 then&lt;br /&gt;
		start = #arr + start&lt;br /&gt;
	end&lt;br /&gt;
	if stop == nil then&lt;br /&gt;
		stop = start&lt;br /&gt;
		start = 1&lt;br /&gt;
	end&lt;br /&gt;
	if stop &amp;lt; 0 then&lt;br /&gt;
		stop = #arr + stop&lt;br /&gt;
	end&lt;br /&gt;
	local r = {}&lt;br /&gt;
	local len = 0&lt;br /&gt;
	for i = start, stop do&lt;br /&gt;
		len = len + 1&lt;br /&gt;
		r[len] = arr[i]&lt;br /&gt;
	end&lt;br /&gt;
	return setmetatable(r, getmetatable(arr))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---Split `arr` into two arrays.&lt;br /&gt;
---@generic T: any[]&lt;br /&gt;
---@param arr T&lt;br /&gt;
---@param index integer # Index to split on.&lt;br /&gt;
---@return T x # [1, index]&lt;br /&gt;
---@return T y # [index + 1, #arr]&lt;br /&gt;
function Array.split(arr, index)&lt;br /&gt;
	checkType(&#039;Module:Array.split&#039;, 1, arr, &#039;table&#039;)&lt;br /&gt;
	checkType(&#039;Module:Array.split&#039;, 2, index, &#039;number&#039;)&lt;br /&gt;
	local x = {}&lt;br /&gt;
	local y = {}&lt;br /&gt;
	for i = 1, #arr do&lt;br /&gt;
		table.insert(i &amp;lt;= index and x or y, arr[i])&lt;br /&gt;
	end&lt;br /&gt;
	return setmetatable(x, getmetatable(arr)), setmetatable(y, getmetatable(arr))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---Returns the sum of all elements of `arr`.&lt;br /&gt;
---@param arr number[]&lt;br /&gt;
---@return number&lt;br /&gt;
function Array.sum(arr)&lt;br /&gt;
	checkType(&#039;Module:Array.sum&#039;, 1, arr, &#039;table&#039;)&lt;br /&gt;
	local res = 0&lt;br /&gt;
	for i = 1, #arr do&lt;br /&gt;
		res = res + arr[i]&lt;br /&gt;
	end&lt;br /&gt;
	return res&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---Extract a subtable from `arr`.&lt;br /&gt;
---@generic T: any[]&lt;br /&gt;
---@param arr T&lt;br /&gt;
---@param count integer # Length of the subtable.&lt;br /&gt;
---@param start? integer # Start index. Default is 1.&lt;br /&gt;
---@return T&lt;br /&gt;
function Array.take(arr, count, start)&lt;br /&gt;
	checkType(&#039;Module:Array.take&#039;, 1, arr, &#039;table&#039;)&lt;br /&gt;
	checkType(&#039;Module:Array.take&#039;, 2, count, &#039;number&#039;)&lt;br /&gt;
	checkType(&#039;Module:Array.take&#039;, 3, start, &#039;number&#039;, true)&lt;br /&gt;
	local x = {}&lt;br /&gt;
	start = start or 1&lt;br /&gt;
	for i = start, math.min(#arr, count + start - 1) do&lt;br /&gt;
		table.insert(x, arr[i])&lt;br /&gt;
	end&lt;br /&gt;
	return setmetatable(x, getmetatable(arr))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---Extract a subtable from `arr`.&lt;br /&gt;
---```&lt;br /&gt;
---local t = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }&lt;br /&gt;
---local x = arr.take_every( t, 2 )       --&amp;gt; x = { 1, 3, 5, 7, 9 }&lt;br /&gt;
---local x = arr.take_every( t, 2, 3 )    --&amp;gt; x = { 1, 3, 5 }&lt;br /&gt;
---local x = arr.take_every( t, 2, 3, 2 ) --&amp;gt; x = { 2, 4, 6 }&lt;br /&gt;
--- ```&lt;br /&gt;
---@generic T: any[]&lt;br /&gt;
---@param arr T&lt;br /&gt;
---@param n integer # Step size.&lt;br /&gt;
---@param start? integer # Start index.&lt;br /&gt;
---@param count? integer # Max amount of elements to get.&lt;br /&gt;
---@return T&lt;br /&gt;
function Array.take_every(arr, n, start, count)&lt;br /&gt;
	checkType(&#039;Module:Array.take_every&#039;, 1, arr, &#039;table&#039;)&lt;br /&gt;
	checkType(&#039;Module:Array.take_every&#039;, 2, n, &#039;number&#039;)&lt;br /&gt;
	checkType(&#039;Module:Array.take_every&#039;, 3, start, &#039;number&#039;, true)&lt;br /&gt;
	checkType(&#039;Module:Array.take_every&#039;, 4, count, &#039;number&#039;, true)&lt;br /&gt;
	count = count or #arr&lt;br /&gt;
	local r = {}&lt;br /&gt;
	local len = 0&lt;br /&gt;
	local i = start or 1&lt;br /&gt;
	while arr[i] ~= nil and len &amp;lt; count do&lt;br /&gt;
		len = len + 1&lt;br /&gt;
		r[len] = arr[i]&lt;br /&gt;
		i = i + n&lt;br /&gt;
	end&lt;br /&gt;
	return setmetatable(r, getmetatable(arr))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---Return a new table with all duplicates removed.&lt;br /&gt;
---@generic T: any[]&lt;br /&gt;
---@param arr T&lt;br /&gt;
---@param fn? fun(elem: any): any # Function to generate an id for each element. The result will then contain elements that generated unique ids.&lt;br /&gt;
---@return T&lt;br /&gt;
function Array.unique(arr, fn)&lt;br /&gt;
	checkType(&#039;Module:Array.unique&#039;, 1, arr, &#039;table&#039;)&lt;br /&gt;
	checkType(&#039;Module:Array.unique&#039;, 2, fn, &#039;function&#039;, true)&lt;br /&gt;
	fn = fn or function(item) return item end&lt;br /&gt;
	local r = {}&lt;br /&gt;
	local len = 0&lt;br /&gt;
	local hash = {}&lt;br /&gt;
	local i = 1&lt;br /&gt;
	while arr[i] ~= nil do&lt;br /&gt;
		local id = fn(arr[i])&lt;br /&gt;
		if not hash[id] then&lt;br /&gt;
			len = len + 1&lt;br /&gt;
			r[len] = arr[i]&lt;br /&gt;
			hash[id] = true&lt;br /&gt;
		end&lt;br /&gt;
		i = i + 1&lt;br /&gt;
	end&lt;br /&gt;
	return setmetatable(r, getmetatable(arr))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---Combine elements with the same index from multiple arrays.&lt;br /&gt;
---```&lt;br /&gt;
---local x = {1, 2, 3}&lt;br /&gt;
---local y = {4, 5, 6, 7}&lt;br /&gt;
---local z = arr.zip( x, y ) --&amp;gt; z = { { 1, 4 }, { 2, 5 }, { 3, 6 }, { 7 } }&lt;br /&gt;
---```&lt;br /&gt;
---@param ... any[]&lt;br /&gt;
---@return Array&lt;br /&gt;
function Array.zip(...)&lt;br /&gt;
	local arrs = { ... }&lt;br /&gt;
	checkType(&#039;Module:Array.zip&#039;, 1, arrs[1], &#039;table&#039;)&lt;br /&gt;
	local r = {}&lt;br /&gt;
	local _, longest = Array.max_by(arrs, function(arr) return #arr end)&lt;br /&gt;
	for i = 1, longest do&lt;br /&gt;
		local q = {}&lt;br /&gt;
		for j = 1, #arrs do&lt;br /&gt;
			table.insert(q, arrs[j][i])&lt;br /&gt;
		end&lt;br /&gt;
		table.insert(r, setmetatable(q, Array))&lt;br /&gt;
	end&lt;br /&gt;
	return setmetatable(r, Array)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Range indexing has a performance impact so this is placed in a separate subclass&lt;br /&gt;
Array.RI_mt = {}&lt;br /&gt;
for k, v in pairs(Array) do&lt;br /&gt;
	Array.RI_mt[k] = v&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Array.RI_mt.__index(t, k)&lt;br /&gt;
	if type(k) == &#039;table&#039; then&lt;br /&gt;
		local res = {}&lt;br /&gt;
		for i = 1, #k do&lt;br /&gt;
			res[i] = t[k[i]]&lt;br /&gt;
		end&lt;br /&gt;
		return setmetatable(res, Array)&lt;br /&gt;
	else&lt;br /&gt;
		return Array[k]&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Array.RI_mt.__newindex(t, k, v)&lt;br /&gt;
	if type(k) == &#039;table&#039; then&lt;br /&gt;
		if type(v) == &#039;table&#039; then&lt;br /&gt;
			for i = 1, #k do&lt;br /&gt;
				t[k[i]] = v[i]&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			for i = 1, #k do&lt;br /&gt;
				t[k[i]] = v&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		rawset(t, k, v)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---Enable range indexing on the input array.&lt;br /&gt;
---&lt;br /&gt;
---This has a performance impact on reads and writes to the table.&lt;br /&gt;
---```&lt;br /&gt;
---local t = arr{10, 11, 12, 13, 14, 15}:ri()&lt;br /&gt;
---print( t[{2, 3}] ) --&amp;gt; { 11, 12 }&lt;br /&gt;
---```&lt;br /&gt;
---@param arr any[]&lt;br /&gt;
---@param recursive? boolean # Default is false.&lt;br /&gt;
---@return Array&lt;br /&gt;
function Array.ri(arr, recursive)&lt;br /&gt;
	checkType(&#039;Module:Array.ri&#039;, 1, arr, &#039;table&#039;)&lt;br /&gt;
	checkType(&#039;Module:Array.ri&#039;, 2, recursive, &#039;boolean&#039;, true)&lt;br /&gt;
	arr = arr or {}&lt;br /&gt;
	if recursive then&lt;br /&gt;
		for _, v in pairs(arr) do&lt;br /&gt;
			if type(v) == &#039;table&#039; then&lt;br /&gt;
				Array.ri(v, true)&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if getmetatable(arr) == nil or getmetatable(arr) == Array then&lt;br /&gt;
		setmetatable(arr, Array.RI_mt)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return arr&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---Globally enable range indexing on all Array objects by default.&lt;br /&gt;
---@param set boolean&lt;br /&gt;
function Array.allwaysAllowRangeIndexing(set)&lt;br /&gt;
	checkType(&#039;Module:Array.allwaysAllowRangeIndexing&#039;, 1, set, &#039;boolean&#039;)&lt;br /&gt;
	if set then&lt;br /&gt;
		Array.__index = Array.RI_mt.__index&lt;br /&gt;
		Array.__newindex = Array.RI_mt.__newindex&lt;br /&gt;
	else&lt;br /&gt;
		Array.__index = Array&lt;br /&gt;
		Array.__newindex = nil&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return Array&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=Template:Stub/doc&amp;diff=52</id>
		<title>Template:Stub/doc</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=Template:Stub/doc&amp;diff=52"/>
		<updated>2025-09-21T15:10:40Z</updated>

		<summary type="html">&lt;p&gt;Erina: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Documentation}}&lt;br /&gt;
{{t|Stub}} will categorize articles that include it into [[:Category:Article stubs]], and mark it with a stub template.&lt;br /&gt;
== Usage ==&lt;br /&gt;
Type &amp;lt;code&amp;gt;{{t|stub}}&amp;lt;/code&amp;gt; at the end of an article.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;includeonly&amp;gt;[[Category:Maintenance templates|{{PAGENAME}}]]&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=Template:T/piece&amp;diff=50</id>
		<title>Template:T/piece</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=Template:T/piece&amp;diff=50"/>
		<updated>2025-09-21T15:10:40Z</updated>

		<summary type="html">&lt;p&gt;Erina: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#ifeq: {{{1|---}}}|---||&amp;amp;#124;&amp;lt;font color=&amp;quot;gray&amp;quot;&amp;gt;&#039;&#039;&amp;amp;lt;{{{1}}}&amp;amp;gt;&#039;&#039;&amp;lt;/font&amp;gt;}}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{/doc}}&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=Template:T&amp;diff=48</id>
		<title>Template:T</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=Template:T&amp;diff=48"/>
		<updated>2025-09-21T15:10:40Z</updated>

		<summary type="html">&lt;p&gt;Erina: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&amp;lt;nowiki&amp;gt;{{&amp;lt;/nowiki&amp;gt;[[Template:{{{1}}}|{{{1}}}]]{{t/piece|{{{2|---}}}}}{{t/piece|{{{3|---}}}}}{{t/piece|{{{4|---}}}}}{{t/piece|{{{5|---}}}}}{{t/piece|{{{6|---}}}}}{{t/piece|{{{7|---}}}}}{{t/piece|{{{8|---}}}}}{{t/piece|{{{9|---}}}}}{{t/piece|{{{10|---}}}}}{{t/piece|{{{11|---}}}}}{{t/piece|{{{12|---}}}}}{{t/piece|{{{13|---}}}}}{{t/piece|{{{14|---}}}}}{{t/piece|{{{15|---}}}}}{{t/piece|{{{16|---}}}}}{{t/piece|{{{17|---}}}}}{{t/piece|{{{18|---}}}}}{{t/piece|{{{19|---}}}}}{{t/piece|{{{20|---}}}}}{{t/piece|{{{21|---}}}}}&amp;lt;nowiki&amp;gt;}}&amp;lt;/nowiki&amp;gt;&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{documentation}}&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=Module:Paramtest&amp;diff=46</id>
		<title>Module:Paramtest</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=Module:Paramtest&amp;diff=46"/>
		<updated>2025-09-21T15:10:40Z</updated>

		<summary type="html">&lt;p&gt;Erina: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- Imported from: https://runescape.wiki/w/Module:Paramtest&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
{{Helper module&lt;br /&gt;
|name=Paramtest&lt;br /&gt;
|fname1 = is_empty(arg)&lt;br /&gt;
|ftype1 = String&lt;br /&gt;
|fuse1 = Returns true if arg is not defined or contains only whitespace&lt;br /&gt;
|fname2 = has_content(arg)&lt;br /&gt;
|ftype2 = String&lt;br /&gt;
|fuse2 = Returns true if arg exists and does not only contain whitespace&lt;br /&gt;
|fname3 = default_to(arg1,arg2)&lt;br /&gt;
|ftype3 = String, Any value&lt;br /&gt;
|fuse3 = If arg1 exists and does not only contain whitespace, the function returns arg1, otherwise returns arg2&lt;br /&gt;
|fname4 = defaults{ {arg1,arg2},...}&lt;br /&gt;
|ftype4 = {String, Any value}...&lt;br /&gt;
|fuse4 = Does the same as &amp;lt;code&amp;gt;default_to()&amp;lt;/code&amp;gt; run over every table passed&lt;br /&gt;
|fname5 = table_is_empty(arg)&lt;br /&gt;
|ftype5 = Table&lt;br /&gt;
|fuse5 = Returns true if the table has no content, it does not check if the content of the table contains anything&lt;br /&gt;
|fname6 = table_has_content(arg)&lt;br /&gt;
|ftype6 = Table&lt;br /&gt;
|fuse6 = returns true if the table has content, it does not check if the content of the table contains anything&lt;br /&gt;
}}&lt;br /&gt;
--]]&lt;br /&gt;
&lt;br /&gt;
local checkType, checkTypeForNamedArg&lt;br /&gt;
do&lt;br /&gt;
	local _libraryUtil = require(&amp;quot;libraryUtil&amp;quot;);&lt;br /&gt;
	checkType = _libraryUtil.checkType;&lt;br /&gt;
	checkTypeForNamedArg = _libraryUtil.checkTypeForNamedArg;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--&lt;br /&gt;
-- Tests basic properties of parameters&lt;br /&gt;
--&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
--&lt;br /&gt;
-- Tests if the parameter is empty, all white space, or undefined&lt;br /&gt;
--&lt;br /&gt;
&lt;br /&gt;
function p.is_empty(arg)&lt;br /&gt;
	return not string.find(arg or &#039;&#039;, &#039;%S&#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--&lt;br /&gt;
-- Tests if the table parameter is empty&lt;br /&gt;
--&lt;br /&gt;
&lt;br /&gt;
function p.table_is_empty(arg)&lt;br /&gt;
	for _, _ in pairs(arg) do&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	return true&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--&lt;br /&gt;
-- Returns the parameter if it has any content, the default (2nd param)&lt;br /&gt;
--&lt;br /&gt;
&lt;br /&gt;
function p.default_to(arg, default)&lt;br /&gt;
	if string.find(arg or &#039;&#039;, &#039;%S&#039;) then&lt;br /&gt;
		return arg&lt;br /&gt;
	else&lt;br /&gt;
		return default&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--&lt;br /&gt;
-- Returns a list of paramaters if it has any content, or the default&lt;br /&gt;
--&lt;br /&gt;
function p.defaults(args)&lt;br /&gt;
	checkType(&amp;quot;defaults&amp;quot;, 1, args, &amp;quot;table&amp;quot;);&lt;br /&gt;
	local ret = {}&lt;br /&gt;
	for i, v in ipairs(args) do&lt;br /&gt;
		checkTypeForNamedArg(&amp;quot;defaults&amp;quot;, i, v, &amp;quot;table&amp;quot;);&lt;br /&gt;
		ret[i] = p.default_to(v[1], v[2]);&lt;br /&gt;
	end&lt;br /&gt;
	return unpack(ret, 1, #args);&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--&lt;br /&gt;
-- Tests if the parameter has content&lt;br /&gt;
-- The same as !is_empty, but this is more readily clear&lt;br /&gt;
--&lt;br /&gt;
&lt;br /&gt;
function p.has_content(arg)&lt;br /&gt;
	return string.find(arg or &#039;&#039;, &#039;%S&#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--&lt;br /&gt;
-- Tests if the table parameter has content&lt;br /&gt;
-- The same as !table_is_empty, but this is more readily clear&lt;br /&gt;
--&lt;br /&gt;
&lt;br /&gt;
function p.table_has_content(arg)&lt;br /&gt;
	for _, _ in pairs(arg) do&lt;br /&gt;
		return true&lt;br /&gt;
	end&lt;br /&gt;
	return false&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--&lt;br /&gt;
-- uppercases first letter&lt;br /&gt;
--&lt;br /&gt;
&lt;br /&gt;
function p.ucfirst(arg)&lt;br /&gt;
	if not arg or arg:len() == 0 then&lt;br /&gt;
		return nil&lt;br /&gt;
	elseif arg:len() == 1 then&lt;br /&gt;
		return arg:upper()&lt;br /&gt;
	else&lt;br /&gt;
		return arg:sub(1,1):upper() .. arg:sub(2)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--&lt;br /&gt;
-- uppercases first letter, lowercases everything else&lt;br /&gt;
--&lt;br /&gt;
&lt;br /&gt;
function p.ucflc(arg)&lt;br /&gt;
	if not arg or arg:len() == 0 then&lt;br /&gt;
		return nil&lt;br /&gt;
	elseif arg:len() == 1 then&lt;br /&gt;
		return arg:upper()&lt;br /&gt;
	else&lt;br /&gt;
		return arg:sub(1,1):upper() .. arg:sub(2):lower()&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=Module:Documentation&amp;diff=44</id>
		<title>Module:Documentation</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=Module:Documentation&amp;diff=44"/>
		<updated>2025-09-21T15:10:40Z</updated>

		<summary type="html">&lt;p&gt;Erina: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- &amp;lt;nowiki&amp;gt;&lt;br /&gt;
local dependencyList = require( &#039;Module:DependencyList&#039; )&lt;br /&gt;
local hatnote = require( &#039;Module:Hatnote&#039; )._hatnote&lt;br /&gt;
local mbox = require( &#039;Module:Mbox&#039; )._mbox&lt;br /&gt;
local i18n = require( &#039;Module:i18n&#039; ):new()&lt;br /&gt;
local TNT = require( &#039;Module:Translate&#039; ):new()&lt;br /&gt;
local lang = mw.getContentLanguage()&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--- Wrapper function for Module:i18n.translate&lt;br /&gt;
---&lt;br /&gt;
--- @param key string The translation key&lt;br /&gt;
--- @return string If the key was not found, the key is returned&lt;br /&gt;
local function t( key )&lt;br /&gt;
	return i18n:translate( key )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--- FIXME: This should go to somewhere else, like Module:Common&lt;br /&gt;
--- Calls TNT with the given key&lt;br /&gt;
---&lt;br /&gt;
--- @param key string The translation key&lt;br /&gt;
--- @return string If the key was not found in the .tab page, the key is returned&lt;br /&gt;
local function translate( key, ... )&lt;br /&gt;
	local success, translation = pcall( TNT.format, &#039;Module:Documentation/i18n.json&#039;, key or &#039;&#039;, ... )&lt;br /&gt;
&lt;br /&gt;
	if not success or translation == nil then&lt;br /&gt;
		return key&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return translation&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
function p.doc( frame )&lt;br /&gt;
    local title = mw.title.getCurrentTitle()&lt;br /&gt;
    local args = frame:getParent().args&lt;br /&gt;
    local page = args[1] or string.gsub( title.fullText, &#039;/[Dd]o[ck]u?$&#039;, &#039;&#039; )&lt;br /&gt;
    local ret, cats, ret1, ret2, ret3&lt;br /&gt;
    local pageType = title.namespace == 828 and &#039;module&#039; or &#039;template&#039;&lt;br /&gt;
&lt;br /&gt;
    -- subpage header&lt;br /&gt;
    if title.subpageText == &#039;doc&#039; then&lt;br /&gt;
		ret = mbox(&lt;br /&gt;
			translate( &#039;message_subpage_title&#039;, page ),&lt;br /&gt;
			translate( &#039;message_subpage_desc&#039;, page, translate( pageType ) ),&lt;br /&gt;
			{ icon = &#039;WikimediaUI-Notice.svg&#039; }&lt;br /&gt;
    	)&lt;br /&gt;
&lt;br /&gt;
        if title.namespace == 10 then -- Template namespace&lt;br /&gt;
            cats = &#039;[[Category:&#039; .. string.format( t( &#039;category_documentation&#039; ), t( &#039;category_&#039; .. pageType ) ) .. &#039;|&#039; .. title.baseText .. &#039;]]&#039;&lt;br /&gt;
            ret2 = dependencyList._main()&lt;br /&gt;
        elseif title.namespace == 828 then -- Module namespace&lt;br /&gt;
            cats = &#039;[[Category:&#039; .. string.format( t( &#039;category_documentation&#039; ), t( &#039;category_&#039; .. pageType ) ) .. &#039;|&#039; .. title.baseText .. &#039;]]&#039;&lt;br /&gt;
            ret2 = dependencyList._main()&lt;br /&gt;
            ret2 = ret2 .. require(&#039;Module:Module toc&#039;).main()&lt;br /&gt;
        else&lt;br /&gt;
            cats = &#039;&#039;&lt;br /&gt;
            ret2 = &#039;&#039;&lt;br /&gt;
        end&lt;br /&gt;
&lt;br /&gt;
        return tostring( ret ) .. ret2 .. cats&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    -- template header&lt;br /&gt;
    -- don&#039;t use mw.html as we aren&#039;t closing the main div tag&lt;br /&gt;
    ret1 = &#039;&amp;lt;div class=&amp;quot;documentation&amp;quot;&amp;gt;&#039;&lt;br /&gt;
&lt;br /&gt;
    ret2 = mw.html.create( nil )&lt;br /&gt;
        :tag( &#039;div&#039; )&lt;br /&gt;
            :addClass( &#039;documentation-header&#039; )&lt;br /&gt;
            :tag( &#039;span&#039; )&lt;br /&gt;
                :addClass( &#039;documentation-title&#039; )&lt;br /&gt;
                :wikitext( lang:ucfirst( translate(&#039;message_documentation_title&#039;, pageType ) ) )&lt;br /&gt;
                :done()&lt;br /&gt;
            :tag( &#039;span&#039; )&lt;br /&gt;
                :addClass( &#039;documentation-links plainlinks&#039; )&lt;br /&gt;
                :wikitext(&lt;br /&gt;
                    &#039;[[&#039; .. tostring( mw.uri.fullUrl( page .. &#039;/doc&#039;, {action=&#039;view&#039;} ) ) .. &#039; view]]&#039; ..&lt;br /&gt;
                    &#039;[[&#039; .. tostring( mw.uri.fullUrl( page .. &#039;/doc&#039;, {action=&#039;edit&#039;} ) ) .. &#039; edit]]&#039; ..&lt;br /&gt;
                    &#039;[[&#039; .. tostring( mw.uri.fullUrl( page .. &#039;/doc&#039;, {action=&#039;history&#039;} ) ) .. &#039; history]]&#039; ..&lt;br /&gt;
                    &#039;[&amp;lt;span class=&amp;quot;jsPurgeLink&amp;quot;&amp;gt;[&#039; .. tostring( mw.uri.fullUrl( title.fullText, { action = &#039;purge&#039; } ) ) .. &#039; purge]&amp;lt;/span&amp;gt;]&#039;&lt;br /&gt;
                )&lt;br /&gt;
                :done()&lt;br /&gt;
            :done()&lt;br /&gt;
        :tag( &#039;div&#039; )&lt;br /&gt;
            :addClass( &#039;documentation-subheader&#039; )&lt;br /&gt;
            :tag( &#039;span&#039; )&lt;br /&gt;
                :addClass( &#039;documentation-documentation&#039; )&lt;br /&gt;
                :wikitext( translate( &#039;message_transclude_desc&#039;, page ) )&lt;br /&gt;
                :done()&lt;br /&gt;
            :wikitext( frame:extensionTag{ name = &#039;templatestyles&#039;, args = { src = &#039;Module:Documentation/styles.css&#039;} } )&lt;br /&gt;
            :done()&lt;br /&gt;
&lt;br /&gt;
    ret3 = {}&lt;br /&gt;
&lt;br /&gt;
    if args.scwShared then&lt;br /&gt;
    	--- Message box&lt;br /&gt;
    	table.insert( ret3,&lt;br /&gt;
    		mbox(&lt;br /&gt;
	    		translate(&lt;br /&gt;
					&#039;message_shared_across&#039;,&lt;br /&gt;
					title.fullText,&lt;br /&gt;
					mw.uri.encode( title.text, &#039;PATH&#039; )&lt;br /&gt;
				),&lt;br /&gt;
				translate(&lt;br /&gt;
					&#039;message_shared_across_subtext&#039;,&lt;br /&gt;
					pageType&lt;br /&gt;
				),&lt;br /&gt;
				{ icon = &#039;WikimediaUI-ArticleDisambiguation-ltr.svg&#039; }&lt;br /&gt;
			)&lt;br /&gt;
	   )&lt;br /&gt;
	   --- Set category&lt;br /&gt;
	   table.insert( ret3, &#039;[[Category:&#039; .. string.format( t( &#039;category_shared_by_the_star_citizen_wikis&#039; ), lang:ucfirst( pageType ) ) .. &#039;]]&#039; )&lt;br /&gt;
		--- Interlanguage link&lt;br /&gt;
		--- TODO: Make this into a for loop when there are more wikis&lt;br /&gt;
		for _, code in pairs{ &#039;de&#039;, &#039;en&#039; } do&lt;br /&gt;
			if lang:getCode() ~= code then&lt;br /&gt;
	    		table.insert( ret3, string.format( &#039;[[%s:%s]]&#039;, code, title.fullText ) )&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if args.fromWikipedia then&lt;br /&gt;
    	table.insert( ret3,&lt;br /&gt;
    		mbox(&lt;br /&gt;
	    		translate(&lt;br /&gt;
					&#039;message_from_wikipedia&#039;,&lt;br /&gt;
					title.fullText,&lt;br /&gt;
					mw.uri.encode( page, &#039;WIKI&#039; ),&lt;br /&gt;
					page&lt;br /&gt;
				),&lt;br /&gt;
				translate(&lt;br /&gt;
					&#039;message_from_wikipedia_subtext&#039;,&lt;br /&gt;
					pageType&lt;br /&gt;
				),&lt;br /&gt;
				{ icon = &#039;WikimediaUI-Logo-Wikipedia.svg&#039; }&lt;br /&gt;
			)&lt;br /&gt;
	   )&lt;br /&gt;
	   --- Set category&lt;br /&gt;
	   table.insert( ret3, &#039;[[Category:&#039; .. string.format( t( &#039;category_imported_from_wikipedia&#039; ), lang:ucfirst( pageType ) ) .. &#039;]]&#039; )&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if title.namespace == 828 then&lt;br /&gt;
    	-- Has config&lt;br /&gt;
    	if mw.title.new( title.fullText .. &#039;/config.json&#039;, &#039;Module&#039; ).exists then&lt;br /&gt;
			table.insert( ret3,&lt;br /&gt;
				mbox(&lt;br /&gt;
		    		translate(&lt;br /&gt;
		    			&#039;message_module_configuration&#039;,&lt;br /&gt;
		    			title.fullText,&lt;br /&gt;
		    			title.fullText&lt;br /&gt;
		    		),&lt;br /&gt;
		    		translate( &#039;message_module_configuration_subtext&#039; ),&lt;br /&gt;
		    		{ icon = &#039;WikimediaUI-Settings.svg&#039; }&lt;br /&gt;
		    	)&lt;br /&gt;
			)&lt;br /&gt;
    	end&lt;br /&gt;
&lt;br /&gt;
    	-- Has localization&lt;br /&gt;
    	if mw.title.new( title.fullText .. &#039;/i18n.json&#039;, &#039;Module&#039; ).exists then&lt;br /&gt;
			table.insert( ret3,&lt;br /&gt;
				mbox(&lt;br /&gt;
		    		translate(&lt;br /&gt;
		    			&#039;message_module_i18n&#039;,&lt;br /&gt;
		    			title.fullText,&lt;br /&gt;
		    			title.fullText&lt;br /&gt;
		    		),&lt;br /&gt;
		    		translate( &#039;message_module_i18n_subtext&#039; ),&lt;br /&gt;
		    		{ icon = &#039;WikimediaUI-Language.svg&#039; }&lt;br /&gt;
		    	)&lt;br /&gt;
			)&lt;br /&gt;
    	end&lt;br /&gt;
&lt;br /&gt;
    	-- Testcase page&lt;br /&gt;
    	if title.subpageText == &#039;testcases&#039; then&lt;br /&gt;
    		table.insert( ret3,&lt;br /&gt;
		    	hatnote(&lt;br /&gt;
		    		translate( &#039;message_module_tests&#039;, title.baseText ),&lt;br /&gt;
		    		{ icon = &#039;WikimediaUI-LabFlask.svg&#039; }&lt;br /&gt;
		    	)&lt;br /&gt;
		    )&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		table.insert( ret3, string.format( &#039;[[Category:%s]]&#039;, t( &#039;category_module&#039; ) ) )&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    --- Dependency list&lt;br /&gt;
    table.insert( ret3, dependencyList._main( nil, args.category, args.isUsed ) )&lt;br /&gt;
&lt;br /&gt;
    -- Has templatestyles&lt;br /&gt;
	if mw.title.new( title.fullText .. &#039;/styles.css&#039; ).exists then&lt;br /&gt;
		table.insert( ret3,&lt;br /&gt;
			hatnote(&lt;br /&gt;
	    		translate( &#039;message_styles&#039;, title.fullText, title.fullText ),&lt;br /&gt;
	    		{ icon = &#039;WikimediaUI-Palette.svg&#039; }&lt;br /&gt;
	    	)&lt;br /&gt;
		)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
    --- Module stats bar&lt;br /&gt;
    if title.namespace == 828 then&lt;br /&gt;
		table.insert( ret3, &#039;&amp;lt;div class=&amp;quot;documentation-modulestats&amp;quot;&amp;gt;&#039; )&lt;br /&gt;
&lt;br /&gt;
		-- Function list&lt;br /&gt;
		table.insert( ret3, require( &#039;Module:Module toc&#039; ).main() )&lt;br /&gt;
&lt;br /&gt;
		-- Unit tests&lt;br /&gt;
		local testcaseTitle = title.baseText .. &#039;/testcases&#039;&lt;br /&gt;
		if mw.title.new( testcaseTitle, &#039;Module&#039; ).exists then&lt;br /&gt;
			-- There is probably a better way :P&lt;br /&gt;
			table.insert( ret3, frame:preprocess( &#039;{{#invoke:&#039; .. testcaseTitle .. &#039;|run}}&#039; ) )&lt;br /&gt;
    	end&lt;br /&gt;
&lt;br /&gt;
    	table.insert( ret3, &#039;&amp;lt;/div&amp;gt;&#039; )&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return ret1 .. tostring( ret2 ) .. &#039;&amp;lt;div class=&amp;quot;documentation-content&amp;quot;&amp;gt;&#039; .. table.concat( ret3 )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;br /&gt;
&lt;br /&gt;
-- &amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=Module:DependencyList&amp;diff=42</id>
		<title>Module:DependencyList</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=Module:DependencyList&amp;diff=42"/>
		<updated>2025-09-21T15:10:39Z</updated>

		<summary type="html">&lt;p&gt;Erina: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;--- Based on Module:DependencyList from RuneScape Wiki&lt;br /&gt;
--- Modified to use SMW instead of DPL&lt;br /&gt;
--- @see https://runescape.wiki/w/Module:DependencyList&lt;br /&gt;
&lt;br /&gt;
require( &#039;strict&#039; )&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
local libraryUtil = require( &#039;libraryUtil&#039; )&lt;br /&gt;
local arr = require( &#039;Module:Array&#039; )&lt;br /&gt;
local yn = require( &#039;Module:Yesno&#039; )&lt;br /&gt;
local param = require( &#039;Module:Paramtest&#039; )&lt;br /&gt;
local userError = require( &#039;Module:User error&#039; )&lt;br /&gt;
local hatnote = require( &#039;Module:Hatnote&#039; )._hatnote&lt;br /&gt;
local mHatlist = require( &#039;Module:Hatnote list&#039; )&lt;br /&gt;
local mbox = require( &#039;Module:Mbox&#039; )._mbox&lt;br /&gt;
local i18n = require( &#039;Module:i18n&#039; ):new()&lt;br /&gt;
local TNT = require( &#039;Module:Translate&#039; ):new()&lt;br /&gt;
&lt;br /&gt;
local dpl -- Lazy load DPL&lt;br /&gt;
&lt;br /&gt;
-- Toggle query mode between SemanticMediaWiki (smw) and DynamicPageList3 (dpl)&lt;br /&gt;
-- For SMW, you will need the SemanticExtraSpecialProperties extension and enable the &#039;Links to&#039; property&lt;br /&gt;
local QUERY_MODE = &#039;dpl&#039;&lt;br /&gt;
local MAX_DYNAMIC_REQUIRE_LIST_LENGTH = 30&lt;br /&gt;
&lt;br /&gt;
local moduleIsUsed = false&lt;br /&gt;
local shouldAddCategories = false&lt;br /&gt;
local COLLAPSE_LIST_LENGTH_THRESHOLD = 5&lt;br /&gt;
local dynamicRequireListQueryCache = {}&lt;br /&gt;
&lt;br /&gt;
local NS_MODULE_NAME = mw.site.namespaces[828].name&lt;br /&gt;
local NS_TEMPLATE_NAME = mw.site.namespaces[10].name&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--- Wrapper function for Module:i18n.translate&lt;br /&gt;
---&lt;br /&gt;
--- @param key string The translation key&lt;br /&gt;
--- @return string If the key was not found, the key is returned&lt;br /&gt;
local function t( key )&lt;br /&gt;
    return i18n:translate( key )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--- FIXME: This should go to somewhere else, like Module:Common&lt;br /&gt;
--- Calls TNT with the given key&lt;br /&gt;
---&lt;br /&gt;
--- @param key string The translation key&lt;br /&gt;
--- @return string If the key was not found in the .tab page, the key is returned&lt;br /&gt;
local function translate( key, ... )&lt;br /&gt;
    local success, translation = pcall( TNT.format, &#039;Module:DependencyList/i18n.json&#039;, key or &#039;&#039;, ... )&lt;br /&gt;
&lt;br /&gt;
    if not success or translation == nil then&lt;br /&gt;
        return key&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return translation&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
local builtins = {&lt;br /&gt;
    [&#039;libraryUtil&#039;] = {&lt;br /&gt;
        link = &#039;mw:Special:MyLanguage/Extension:Scribunto/Lua reference manual#libraryUtil&#039;,&lt;br /&gt;
        categories = {},&lt;br /&gt;
    },&lt;br /&gt;
    [&#039;strict&#039;] = {&lt;br /&gt;
        link = &#039;mw:Special:MyLanguage/Extension:Scribunto/Lua reference manual#strict&#039;,&lt;br /&gt;
        categories = { t( &#039;category_strict_mode_modules&#039; ) },&lt;br /&gt;
    },&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--- Used in case &#039;require( varName )&#039; is found. Attempts to find a string value stored in &#039;varName&#039;.&lt;br /&gt;
---@param content string    The content of the module to search in&lt;br /&gt;
---@param varName string&lt;br /&gt;
---@return string&lt;br /&gt;
local function substVarValue( content, varName )&lt;br /&gt;
    local res = content:match( varName .. &#039;%s*=%s*(%b&amp;quot;&amp;quot;%s-%.*)&#039; ) or content:match( varName .. &amp;quot;%s*=%s*(%b&#039;&#039;%s-%.*)&amp;quot; ) or&lt;br /&gt;
        &#039;&#039;&lt;br /&gt;
    if res:find( &#039;^([&amp;quot;\&#039;])[Mm]odule?:[%S]+%1&#039; ) and not res:find( &#039;%.%.&#039; ) and not res:find( &#039;%%%a&#039; ) then&lt;br /&gt;
        return mw.text.trim( res )&lt;br /&gt;
    else&lt;br /&gt;
        return &#039;&#039;&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
---@param capture string&lt;br /&gt;
---@param content string    The content of the module to search in&lt;br /&gt;
---@return string&lt;br /&gt;
local function extractModuleName( capture, content )&lt;br /&gt;
    capture = capture:gsub( &#039;^%(%s*(.-)%s*%)$&#039;, &#039;%1&#039; )&lt;br /&gt;
&lt;br /&gt;
    if capture:find( &#039;^([&amp;quot;\&#039;]).-%1$&#039; ) then     -- Check if it is already a pure string&lt;br /&gt;
        return capture&lt;br /&gt;
    elseif capture:find( &#039;^[%a_][%w_]*$&#039; ) then -- Check if if is a single variable&lt;br /&gt;
        return substVarValue( content, capture )&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return capture&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
---@param str string&lt;br /&gt;
---@return string&lt;br /&gt;
local function formatPageName( str )&lt;br /&gt;
    local name = mw.text.trim( str )&lt;br /&gt;
        :gsub( &#039;^([\&#039;\&amp;quot;])(.-)%1$&#039;, function ( _, x ) return x end ) -- Only remove quotes at start and end of string if both are the same type&lt;br /&gt;
        :gsub( &#039;_&#039;, &#039; &#039; )&lt;br /&gt;
        :gsub( &#039;^.&#039;, string.upper )&lt;br /&gt;
        :gsub( &#039;:.&#039;, string.upper )&lt;br /&gt;
&lt;br /&gt;
    return name&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
---@param str string&lt;br /&gt;
---@param allowBuiltins? boolean&lt;br /&gt;
---@return string&lt;br /&gt;
local function formatModuleName( str, allowBuiltins )&lt;br /&gt;
    if allowBuiltins then&lt;br /&gt;
        local name = mw.text.trim( str )&lt;br /&gt;
            -- Only remove quotes at start and end of string if both are the same type&lt;br /&gt;
            :gsub( [[^([&#039;&amp;quot;])(.-)%1$]], &#039;%2&#039; )&lt;br /&gt;
&lt;br /&gt;
        if builtins[name] then&lt;br /&gt;
            return name&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local module = formatPageName( str )&lt;br /&gt;
&lt;br /&gt;
    if not string.find( module, &#039;^[Mm]odule?:&#039; ) then&lt;br /&gt;
        module = NS_MODULE_NAME .. &#039;:&#039; .. module&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return module&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
local function dualGmatch( str, pat1, pat2 )&lt;br /&gt;
    local f1 = string.gmatch( str, pat1 )&lt;br /&gt;
    if pat2 then&lt;br /&gt;
        local f2 = string.gmatch( str, pat2 )&lt;br /&gt;
        return function ()&lt;br /&gt;
            return f1() or f2()&lt;br /&gt;
        end&lt;br /&gt;
    else&lt;br /&gt;
        return f1&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function isDynamicPath( str )&lt;br /&gt;
    return string.find( str, &#039;%.%.&#039; ) or string.find( str, &#039;%%%a&#039; )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--- Used in case a construct like &#039;require( &amp;quot;Module:wowee/&amp;quot; .. isTheBest )&#039; is found.&lt;br /&gt;
--- Will return a list of pages which satisfy this pattern where &#039;isTheBest&#039; can take any value.&lt;br /&gt;
---@param query string&lt;br /&gt;
---@return string[]&lt;br /&gt;
local function getDynamicRequireList( query )&lt;br /&gt;
    if query:find( &#039;%.%.&#039; ) then&lt;br /&gt;
        query = mw.text.split( query, &#039;..&#039;, true )&lt;br /&gt;
        query = arr.map( query, function ( x ) return mw.text.trim( x ) end )&lt;br /&gt;
        query = arr.map( query, function ( x ) return (x:match( &#039;^[\&#039;\&amp;quot;](.-)[\&#039;\&amp;quot;]$&#039; ) or &#039;%&#039;) end )&lt;br /&gt;
        query = table.concat( query )&lt;br /&gt;
    else&lt;br /&gt;
        local _, _query = query:match( &#039;([&amp;quot;\&#039;])(.-)%1&#039; )&lt;br /&gt;
        query = _query:gsub( &#039;%%%a&#039;, &#039;%%&#039; )&lt;br /&gt;
    end&lt;br /&gt;
    query = query:gsub( &#039;^[Mm]odule:&#039;, &#039;&#039; )&lt;br /&gt;
&lt;br /&gt;
    if dynamicRequireListQueryCache[query] then&lt;br /&gt;
        return dynamicRequireListQueryCache[query]&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local list = {}&lt;br /&gt;
&lt;br /&gt;
    if QUERY_MODE == &#039;smw&#039; then&lt;br /&gt;
        --  TODO: Implement SMW query&lt;br /&gt;
    elseif QUERY_MODE == &#039;dpl&#039; then&lt;br /&gt;
        list = dpl.ask( {&lt;br /&gt;
            namespace = NS_MODULE_NAME,&lt;br /&gt;
            titlematch = query,&lt;br /&gt;
            nottitlematch = &#039;%/doc|&#039; .. query .. &#039;/%&#039;,&lt;br /&gt;
            distinct = &#039;strict&#039;,&lt;br /&gt;
            ignorecase = true,&lt;br /&gt;
            ordermethod = &#039;title&#039;,&lt;br /&gt;
            count = MAX_DYNAMIC_REQUIRE_LIST_LENGTH + 1,&lt;br /&gt;
            skipthispage = &#039;no&#039;,&lt;br /&gt;
            allowcachedresults = true,&lt;br /&gt;
            cacheperiod = 604800 -- One week&lt;br /&gt;
        } )&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if #list &amp;gt; MAX_DYNAMIC_REQUIRE_LIST_LENGTH then&lt;br /&gt;
        list = { &#039;Module:&#039; .. query }&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    dynamicRequireListQueryCache[query] = list&lt;br /&gt;
&lt;br /&gt;
    return list&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--- Returns a list of modules loaded and required by module &#039;moduleName&#039;.&lt;br /&gt;
---@param moduleName string&lt;br /&gt;
---@param searchForUsedTemplates boolean|nil&lt;br /&gt;
---@return table&amp;lt;string, string[]&amp;gt;&lt;br /&gt;
local function getRequireList( moduleName, searchForUsedTemplates )&lt;br /&gt;
    local content = mw.title.new( moduleName ):getContent()&lt;br /&gt;
    local requireList = arr {}&lt;br /&gt;
    local loadDataList = arr {}&lt;br /&gt;
    local loadJsonDataList = arr {}&lt;br /&gt;
    local usedTemplateList = arr {}&lt;br /&gt;
    local dynamicRequirelist = arr {}&lt;br /&gt;
    local dynamicLoadDataList = arr {}&lt;br /&gt;
    local dynamicLoadJsonDataList = arr {}&lt;br /&gt;
    local extraCategories = arr {}&lt;br /&gt;
&lt;br /&gt;
    if content == nil then&lt;br /&gt;
        --assert( content ~= nil, translate( &#039;message_not_exists&#039;, moduleName ) )&lt;br /&gt;
        return {&lt;br /&gt;
            requireList = requireList,&lt;br /&gt;
            loadDataList = loadDataList,&lt;br /&gt;
            loadJsonDataList = loadJsonDataList,&lt;br /&gt;
            usedTemplateList = usedTemplateList,&lt;br /&gt;
            extraCategories = extraCategories&lt;br /&gt;
        }&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    content = content:gsub( &#039;%-%-%[(=-)%[.-%]%1%]&#039;, &#039;&#039; ):gsub( &#039;%-%-[^\n]*&#039;, &#039;&#039; ) -- Strip comments&lt;br /&gt;
&lt;br /&gt;
    local function getList( pat1, pat2, list, dynList )&lt;br /&gt;
        for match in dualGmatch( content, pat1, pat2 ) do&lt;br /&gt;
            match = mw.text.trim( match )&lt;br /&gt;
            local name = extractModuleName( match, content )&lt;br /&gt;
&lt;br /&gt;
            if isDynamicPath( name ) then&lt;br /&gt;
                dynList:insert( getDynamicRequireList( name ), true )&lt;br /&gt;
            elseif name ~= &#039;&#039; then&lt;br /&gt;
                name = formatModuleName( name, true )&lt;br /&gt;
                table.insert( list, name )&lt;br /&gt;
&lt;br /&gt;
                if builtins[name] then&lt;br /&gt;
                    extraCategories = extraCategories:insert( builtins[name].categories, true )&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    getList( &#039;require%s*(%b())&#039;, &#039;require%s*(([&amp;quot;\&#039;])%s*[Mm]odule:.-%2)&#039;, requireList, dynamicRequirelist )&lt;br /&gt;
    getList( &#039;mw%.loadData%s*(%b())&#039;, &#039;mw%.loadData%s*(([&amp;quot;\&#039;])%s*[Mm]odule:.-%2)&#039;, loadDataList, dynamicLoadDataList )&lt;br /&gt;
    getList( &#039;mw%.loadJsonData%s*(%b())&#039;, &#039;mw%.loadJsonData%s*(([&amp;quot;\&#039;])%s*[Mm]odule:.-%2)&#039;, loadJsonDataList,&lt;br /&gt;
        dynamicLoadJsonDataList )&lt;br /&gt;
    getList( &#039;pcall%s*%(%s*require%s*,([^%),]+)&#039;, nil, requireList, dynamicRequirelist )&lt;br /&gt;
    getList( &#039;pcall%s*%(%s*mw%.loadData%s*,([^%),]+)&#039;, nil, loadDataList, dynamicLoadDataList )&lt;br /&gt;
    getList( &#039;pcall%s*%(%s*mw%.loadJsonData%s*,([^%),]+)&#039;, nil, loadJsonDataList, dynamicLoadJsonDataList )&lt;br /&gt;
&lt;br /&gt;
    if searchForUsedTemplates then&lt;br /&gt;
        for preprocess in string.gmatch( content, &#039;:preprocess%s*(%b())&#039; ) do&lt;br /&gt;
            local function recursiveGMatch( str, pat )&lt;br /&gt;
                local list = {}&lt;br /&gt;
                local i = 0&lt;br /&gt;
&lt;br /&gt;
                repeat&lt;br /&gt;
                    for match in string.gmatch( list[i] or str, pat ) do&lt;br /&gt;
                        table.insert( list, match )&lt;br /&gt;
                    end&lt;br /&gt;
                    i = i + 1&lt;br /&gt;
                until i &amp;gt; #list or i &amp;gt; 100&lt;br /&gt;
&lt;br /&gt;
                i = 0&lt;br /&gt;
                return function ()&lt;br /&gt;
                    i = i + 1&lt;br /&gt;
                    return list[i]&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
&lt;br /&gt;
            for template in recursiveGMatch( preprocess, &#039;{(%b{})}&#039; ) do&lt;br /&gt;
                local name = string.match( template, &#039;{(.-)[|{}]&#039; )&lt;br /&gt;
                if name ~= &#039;&#039; then&lt;br /&gt;
                    if name:find( &#039;:&#039; ) then&lt;br /&gt;
                        local ns = name:match( &#039;^(.-):&#039; )&lt;br /&gt;
                        if arr.contains( { &#039;&#039;, &#039;template&#039;, &#039;user&#039; }, ns:lower() ) then&lt;br /&gt;
                            table.insert( usedTemplateList, name )&lt;br /&gt;
                        elseif ns == ns:upper() then&lt;br /&gt;
                            table.insert( usedTemplateList, ns ) -- Probably a magic word&lt;br /&gt;
                        end&lt;br /&gt;
                    else&lt;br /&gt;
                        if name:match( &#039;^%u+$&#039; ) or name == &#039;!&#039; then&lt;br /&gt;
                            table.insert( usedTemplateList, name ) -- Probably a magic word&lt;br /&gt;
                        else&lt;br /&gt;
                            table.insert( usedTemplateList, &#039;Template:&#039; .. name )&lt;br /&gt;
                        end&lt;br /&gt;
                    end&lt;br /&gt;
                end&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    requireList = requireList .. dynamicRequirelist&lt;br /&gt;
    requireList = requireList:unique()&lt;br /&gt;
    loadDataList = loadDataList .. dynamicLoadDataList&lt;br /&gt;
    loadDataList = loadDataList:unique()&lt;br /&gt;
    loadJsonDataList = loadJsonDataList .. dynamicLoadJsonDataList&lt;br /&gt;
    loadJsonDataList = loadJsonDataList:unique()&lt;br /&gt;
    usedTemplateList = usedTemplateList:unique()&lt;br /&gt;
    extraCategories = extraCategories:unique()&lt;br /&gt;
    table.sort( extraCategories )&lt;br /&gt;
&lt;br /&gt;
    return {&lt;br /&gt;
        requireList = requireList,&lt;br /&gt;
        loadDataList = loadDataList,&lt;br /&gt;
        loadJsonDataList = loadJsonDataList,&lt;br /&gt;
        usedTemplateList = usedTemplateList,&lt;br /&gt;
        extraCategories = extraCategories&lt;br /&gt;
    }&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--- Returns a list with module and function names used in all &#039;{{#Invoke:moduleName|funcName}}&#039; found on page &#039;templateName&#039;.&lt;br /&gt;
---@param templateName string&lt;br /&gt;
---@return table&amp;lt;string, string&amp;gt;[]&lt;br /&gt;
local function getInvokeCallList( templateName )&lt;br /&gt;
    local content = mw.title.new( templateName ):getContent()&lt;br /&gt;
    local invokeList = {}&lt;br /&gt;
&lt;br /&gt;
    assert( content ~= nil, translate( &#039;message_not_exists&#039;, templateName ) )&lt;br /&gt;
&lt;br /&gt;
    for moduleName, funcName in string.gmatch( content, &#039;{{[{|safeubt:}]-#[Ii]nvoke:([^|]+)|([^}|]+)[^}]*}}&#039; ) do&lt;br /&gt;
        moduleName = formatModuleName( moduleName )&lt;br /&gt;
        funcName = mw.text.trim( funcName )&lt;br /&gt;
        if string.find( funcName, &#039;^{{{&#039; ) then&lt;br /&gt;
            funcName = funcName .. &#039;}}}&#039;&lt;br /&gt;
        end&lt;br /&gt;
        table.insert( invokeList, { moduleName = moduleName, funcName = funcName } )&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    invokeList = arr.unique( invokeList, function ( x ) return x.moduleName .. x.funcName end )&lt;br /&gt;
    table.sort( invokeList, function ( x, y ) return x.moduleName .. x.funcName &amp;lt; y.moduleName .. y.funcName end )&lt;br /&gt;
&lt;br /&gt;
    return invokeList&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---@return string&lt;br /&gt;
local function messageBoxUnused()&lt;br /&gt;
    local category = shouldAddCategories and &#039;[[Category:&#039; .. t( &#039;category_unused_module&#039; ) .. &#039;]]&#039; or &#039;&#039;&lt;br /&gt;
&lt;br /&gt;
    return mbox(&lt;br /&gt;
        translate( &#039;message_unused_module_title&#039; ),&lt;br /&gt;
        translate( &#039;message_unused_module_desc&#039; ),&lt;br /&gt;
        { icon = &#039;WikimediaUI-Alert.svg&#039; }&lt;br /&gt;
    ) .. category&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Returns the wikitext for the message template (mbox/hatnote)&lt;br /&gt;
---@param msgKey string message key in /i18n.json&lt;br /&gt;
---@param pageName string page name used for the message&lt;br /&gt;
---@param list table&lt;br /&gt;
---@param listType string type of the page list used for the message&lt;br /&gt;
---@return string&lt;br /&gt;
local function getDependencyListWikitext( msgKey, pageName, list, listType )&lt;br /&gt;
    local listLabel = string.format( &#039;%d %s&#039;, #list, listType )&lt;br /&gt;
    local listContent = mHatlist.andList( list, false )&lt;br /&gt;
&lt;br /&gt;
    --- Return mbox&lt;br /&gt;
    if #list &amp;gt; COLLAPSE_LIST_LENGTH_THRESHOLD then&lt;br /&gt;
        return mbox(&lt;br /&gt;
            translate( msgKey, pageName, listLabel ),&lt;br /&gt;
            listContent,&lt;br /&gt;
            { icon = &#039;WikimediaUI-Code.svg&#039; }&lt;br /&gt;
        )&lt;br /&gt;
        --- Return hatnote&lt;br /&gt;
    else&lt;br /&gt;
        return hatnote(&lt;br /&gt;
            translate( msgKey, pageName, listContent ),&lt;br /&gt;
            { icon = &#039;WikimediaUI-Code.svg&#039; }&lt;br /&gt;
        )&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--- Creates a link to [[Special:Search]] showing all pages found by getDynamicRequireList() in case it found more than MAX_DYNAMIC_REQUIRE_LIST_LENGTH pages.&lt;br /&gt;
---@param query string      @This will be in a format like &#039;Module:Wowee/%&#039; or &#039;Module:Wowee/%/data&#039;&lt;br /&gt;
---@return string&lt;br /&gt;
local function formatDynamicQueryLink( query )&lt;br /&gt;
    local prefix = query:match( &#039;^([^/]+)&#039; )&lt;br /&gt;
    local linkText = query:gsub( &#039;%%&#039;, &#039;&amp;amp;lt; ... &amp;amp;gt;&#039; )&lt;br /&gt;
&lt;br /&gt;
    query = query:gsub( &#039;^Module?:&#039;, &#039;&#039; )&lt;br /&gt;
&lt;br /&gt;
    query = query:gsub( &#039;([^/]+)/?&#039;, function ( match )&lt;br /&gt;
        if match == &#039;%&#039; then&lt;br /&gt;
            return &#039;\\/[^\\/]+&#039;&lt;br /&gt;
        else&lt;br /&gt;
            return &#039;\\/&amp;quot;&#039; .. match .. &#039;&amp;quot;&#039;&lt;br /&gt;
        end&lt;br /&gt;
    end )&lt;br /&gt;
&lt;br /&gt;
    query = query:gsub( &#039;^\\/&#039;, &#039;&#039; )&lt;br /&gt;
&lt;br /&gt;
    query = string.format(&lt;br /&gt;
        &#039;intitle:/%s%s/i -intitle:/%s\\/&amp;quot;&amp;quot;/i -intitle:doc prefix:&amp;quot;%s&amp;quot;&#039;,&lt;br /&gt;
        query,&lt;br /&gt;
        query:find( &#039;&amp;quot;$&#039; ) and &#039;&#039; or &#039;&amp;quot;&amp;quot;&#039;,&lt;br /&gt;
        query,&lt;br /&gt;
        prefix&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    return string.format( &#039;&amp;lt;span class=&amp;quot;plainlinks&amp;quot;&amp;gt;[%s %s]&amp;lt;/span&amp;gt;&#039;,&lt;br /&gt;
        tostring( mw.uri.fullUrl( &#039;Special:Search&#039;, {&lt;br /&gt;
            search = query&lt;br /&gt;
        } ) ), linkText )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--- Helper function to return the wikitext of the templates and categories&lt;br /&gt;
---@param currentPageName string&lt;br /&gt;
---@param pageList table|nil&lt;br /&gt;
---@param pageType string&lt;br /&gt;
---@param message string&lt;br /&gt;
---@param category string|nil&lt;br /&gt;
---@return string&lt;br /&gt;
local function formatDependencyList( currentPageName, pageList, pageType, message, category )&lt;br /&gt;
    local res = {}&lt;br /&gt;
&lt;br /&gt;
    if type( pageList ) == &#039;table&#039; and #pageList &amp;gt; 0 then&lt;br /&gt;
        table.sort( pageList )&lt;br /&gt;
        table.insert( res, getDependencyListWikitext( message, currentPageName, pageList, pageType ) )&lt;br /&gt;
&lt;br /&gt;
        if shouldAddCategories and category then&lt;br /&gt;
            table.insert( res, string.format( &#039;[[Category:%s]]&#039;, category ) )&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;
&lt;br /&gt;
---@param templateName string&lt;br /&gt;
---@param invokeList table&amp;lt;string, string&amp;gt;[]    @This is the list returned by getInvokeCallList()&lt;br /&gt;
---@return string&lt;br /&gt;
local function formatInvokeCallList( templateName, invokeList )&lt;br /&gt;
    local category = shouldAddCategories and &#039;[[Category:&#039; .. t( &#039;category_lua_based_template&#039; ) .. &#039;]]&#039; or &#039;&#039;&lt;br /&gt;
    local res = {}&lt;br /&gt;
&lt;br /&gt;
    for _, item in ipairs( invokeList ) do&lt;br /&gt;
        local msg = translate(&lt;br /&gt;
            &#039;message_invokes_function&#039;,&lt;br /&gt;
            templateName,&lt;br /&gt;
            item.funcName,&lt;br /&gt;
            item.moduleName&lt;br /&gt;
        )&lt;br /&gt;
        table.insert( res, hatnote( msg, { icon = &#039;WikimediaUI-Code.svg&#039; } ) )&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if #invokeList &amp;gt; 0 then&lt;br /&gt;
        table.insert( res, category )&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return table.concat( res )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
---@param moduleName string&lt;br /&gt;
---@param whatLinksHere table    @A list generated by a dpl of pages in the Template namespace which link to moduleName.&lt;br /&gt;
---@return string&lt;br /&gt;
local function formatInvokedByList( moduleName, whatLinksHere )&lt;br /&gt;
    local function lcfirst( str )&lt;br /&gt;
        return string.gsub( str, &#039;^[Mm]odule?:.&#039;, string.lower )&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local templateData = arr.map( whatLinksHere,&lt;br /&gt;
        function ( x )&lt;br /&gt;
            return {&lt;br /&gt;
                templateName = x,&lt;br /&gt;
                invokeList = getInvokeCallList( x )&lt;br /&gt;
            }&lt;br /&gt;
        end )&lt;br /&gt;
    templateData = arr.filter( templateData, function ( x )&lt;br /&gt;
        return arr.any( x.invokeList, function ( y )&lt;br /&gt;
            return lcfirst( y.moduleName ) == lcfirst( moduleName )&lt;br /&gt;
        end )&lt;br /&gt;
    end )&lt;br /&gt;
&lt;br /&gt;
    local invokedByList = {}&lt;br /&gt;
&lt;br /&gt;
    for _, template in ipairs( templateData ) do&lt;br /&gt;
        for _, invoke in ipairs( template.invokeList ) do&lt;br /&gt;
            --- NOTE: Somehow only templates aren&#039;t linked properly, not sure why&lt;br /&gt;
            table.insert( invokedByList,&lt;br /&gt;
                translate( &#039;message_function_invoked_by&#039;, invoke.funcName, &#039;[[&#039; .. template.templateName .. &#039;]]&#039; ) )&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if #invokedByList &amp;gt; 0 then&lt;br /&gt;
        moduleIsUsed = true&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return formatDependencyList(&lt;br /&gt;
        moduleName,&lt;br /&gt;
        invokedByList,&lt;br /&gt;
        translate( &#039;list_type_templates&#039; ),&lt;br /&gt;
        &#039;message_module_functions_invoked_by&#039;,&lt;br /&gt;
        t( &#039;category_template_invoked_modules&#039; )&lt;br /&gt;
    )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
---@param moduleName string&lt;br /&gt;
---@param whatLinksHere table      @A list generated by a dpl of pages in the Module namespace which link to moduleName.&lt;br /&gt;
---@return string&lt;br /&gt;
local function formatRequiredByList( moduleName, whatLinksHere )&lt;br /&gt;
    local childModuleData = arr.map( whatLinksHere, function ( title )&lt;br /&gt;
        local lists = getRequireList( title )&lt;br /&gt;
        return {&lt;br /&gt;
            name = title,&lt;br /&gt;
            requireList = lists.requireList,&lt;br /&gt;
            loadDataList = lists.loadDataList .. lists.loadJsonDataList&lt;br /&gt;
        }&lt;br /&gt;
    end )&lt;br /&gt;
&lt;br /&gt;
    local requiredByList = arr.map( childModuleData, function ( item )&lt;br /&gt;
        if arr.any( item.requireList, function ( x ) return x:lower() == moduleName:lower() end ) then&lt;br /&gt;
            if item.name:find( &#039;%%&#039; ) then&lt;br /&gt;
                return formatDynamicQueryLink( item.name )&lt;br /&gt;
            else&lt;br /&gt;
                return &#039;[[&#039; .. item.name .. &#039;]]&#039;&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end )&lt;br /&gt;
&lt;br /&gt;
    local loadedByList = arr.map( childModuleData, function ( item )&lt;br /&gt;
        if arr.any( item.loadDataList, function ( x ) return x:lower() == moduleName:lower() end ) then&lt;br /&gt;
            if item.name:find( &#039;%%&#039; ) then&lt;br /&gt;
                return formatDynamicQueryLink( item.name )&lt;br /&gt;
            else&lt;br /&gt;
                return &#039;[[&#039; .. item.name .. &#039;]]&#039;&lt;br /&gt;
            end&lt;br /&gt;
        end&lt;br /&gt;
    end )&lt;br /&gt;
&lt;br /&gt;
    if #requiredByList &amp;gt; 0 or #loadedByList &amp;gt; 0 then&lt;br /&gt;
        moduleIsUsed = true&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local res = {}&lt;br /&gt;
&lt;br /&gt;
    table.insert( res,&lt;br /&gt;
        formatDependencyList(&lt;br /&gt;
            moduleName,&lt;br /&gt;
            requiredByList,&lt;br /&gt;
            translate( &#039;list_type_modules&#039; ),&lt;br /&gt;
            &#039;message_required_by&#039;,&lt;br /&gt;
            t( &#039;category_modules_required_by_modules&#039; )&lt;br /&gt;
        )&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    table.insert( res,&lt;br /&gt;
        formatDependencyList(&lt;br /&gt;
            moduleName,&lt;br /&gt;
            loadedByList,&lt;br /&gt;
            translate( &#039;list_type_modules&#039; ),&lt;br /&gt;
            &#039;message_loaded_by&#039;,&lt;br /&gt;
            t( &#039;category_module_data&#039; )&lt;br /&gt;
        )&lt;br /&gt;
    )&lt;br /&gt;
&lt;br /&gt;
    return table.concat( res )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
local function cleanFrom( from )&lt;br /&gt;
    from = from or &#039;&#039;&lt;br /&gt;
    local parts = mw.text.split( from, &#039;|&#039;, true )&lt;br /&gt;
&lt;br /&gt;
    if #parts == 2 then&lt;br /&gt;
        local name = string.gsub( parts[1], &#039;%[%[:&#039;, &#039;&#039; )&lt;br /&gt;
        name = string.gsub( name, &#039;/[Dd]o[ck]u?&#039;, &#039;&#039; )&lt;br /&gt;
&lt;br /&gt;
        return name&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return nil&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
---@param pageName string&lt;br /&gt;
---@return table&lt;br /&gt;
local function getWhatLinksHere( pageName, namespace, options )&lt;br /&gt;
    options = options or {}&lt;br /&gt;
    local whatLinksHere = {}&lt;br /&gt;
&lt;br /&gt;
    if QUERY_MODE == &#039;smw&#039; then&lt;br /&gt;
        local res = mw.smw.ask( {&lt;br /&gt;
            &#039;[[Links to::&#039; .. pageName .. &#039;]]&#039;,&lt;br /&gt;
            &#039;[[&#039; .. namespace .. &#039;:+]]&#039;,&lt;br /&gt;
            &#039;sort=Links to&#039;,&lt;br /&gt;
            &#039;order=asc&#039;,&lt;br /&gt;
            &#039;mainlabel=from&#039;&lt;br /&gt;
        } ) or {}&lt;br /&gt;
&lt;br /&gt;
        whatLinksHere = arr.new( arr.condenseSparse( arr.map( res, function ( link )&lt;br /&gt;
            return cleanFrom( link[&#039;from&#039;] )&lt;br /&gt;
        end ) ) ):unique()&lt;br /&gt;
&lt;br /&gt;
        if options.smw_reject_self then&lt;br /&gt;
            whatLinksHere = whatLinksHere:reject( { pageName } )&lt;br /&gt;
        end&lt;br /&gt;
    elseif QUERY_MODE == &#039;dpl&#039; then&lt;br /&gt;
        whatLinksHere = dpl.ask( {&lt;br /&gt;
            namespace = namespace,&lt;br /&gt;
            linksto = pageName,&lt;br /&gt;
            distinct = &#039;strict&#039;,&lt;br /&gt;
            ignorecase = true,&lt;br /&gt;
            ordermethod = &#039;title&#039;,&lt;br /&gt;
            allowcachedresults = true,&lt;br /&gt;
            cacheperiod = 604800 -- One week&lt;br /&gt;
        } )&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return whatLinksHere&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---@param pageName string&lt;br /&gt;
---@return table&lt;br /&gt;
function p.getWhatTemplatesLinkHere( pageName )&lt;br /&gt;
    return getWhatLinksHere( pageName, NS_TEMPLATE_NAME )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---@param pageName string&lt;br /&gt;
---@return table&lt;br /&gt;
function p.getWhatModulesLinkHere( pageName )&lt;br /&gt;
    return getWhatLinksHere( pageName, NS_MODULE_NAME, { smw_reject_self = true } )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.main( frame )&lt;br /&gt;
    local args = frame:getParent().args&lt;br /&gt;
    return p._main( args[1], args.category, args.isUsed )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
---@param currentPageName string|nil&lt;br /&gt;
---@param addCategories boolean|string|nil&lt;br /&gt;
---@return string&lt;br /&gt;
function p._main( currentPageName, addCategories, isUsed )&lt;br /&gt;
    libraryUtil.checkType( &#039;Module:RequireList._main&#039;, 1, currentPageName, &#039;string&#039;, true )&lt;br /&gt;
    libraryUtil.checkTypeMulti( &#039;Module:RequireList._main&#039;, 2, addCategories, { &#039;boolean&#039;, &#039;string&#039;, &#039;nil&#039; } )&lt;br /&gt;
    libraryUtil.checkTypeMulti( &#039;Module:RequireList._main&#039;, 3, isUsed, { &#039;boolean&#039;, &#039;string&#039;, &#039;nil&#039; } )&lt;br /&gt;
&lt;br /&gt;
    local title = mw.title.getCurrentTitle()&lt;br /&gt;
&lt;br /&gt;
    -- Leave early if not in module or template namespace&lt;br /&gt;
    if param.is_empty( currentPageName ) and&lt;br /&gt;
        (not arr.contains( { NS_MODULE_NAME, NS_TEMPLATE_NAME }, title.nsText )) then&lt;br /&gt;
        return &#039;&#039;&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    currentPageName = param.default_to( currentPageName, title.fullText )&lt;br /&gt;
    currentPageName = string.gsub( currentPageName, &#039;/[Dd]o[ck]u?$&#039;, &#039;&#039; )&lt;br /&gt;
    currentPageName = formatPageName( currentPageName )&lt;br /&gt;
    moduleIsUsed = yn( param.default_to( isUsed, false ) )&lt;br /&gt;
    shouldAddCategories = yn( param.default_to( addCategories, title.subpageText ~= &#039;doc&#039; ) )&lt;br /&gt;
&lt;br /&gt;
    -- Don&#039;t show sandbox and testcases modules as unused&lt;br /&gt;
    if title.text:lower():find( &#039;sandbox&#039; ) or title.text:lower():find( &#039;testcases&#039; ) then&lt;br /&gt;
        moduleIsUsed = true&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if QUERY_MODE == &#039;dpl&#039; then&lt;br /&gt;
        dpl = require( &#039;Module:DPLlua&#039; )&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if currentPageName:find( &#039;^&#039; .. NS_TEMPLATE_NAME .. &#039;:&#039; ) then&lt;br /&gt;
        local ok, invokeList = pcall( getInvokeCallList, currentPageName )&lt;br /&gt;
        if ok then&lt;br /&gt;
            return formatInvokeCallList( currentPageName, invokeList )&lt;br /&gt;
        else&lt;br /&gt;
            return userError( invokeList )&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local ok, lists = pcall( getRequireList, currentPageName, true )&lt;br /&gt;
    if not ok then&lt;br /&gt;
        return userError( lists )&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local requireList = arr.map( lists.requireList, function ( moduleName )&lt;br /&gt;
        if moduleName:find( &#039;%%&#039; ) then&lt;br /&gt;
            return formatDynamicQueryLink( moduleName )&lt;br /&gt;
        elseif builtins[moduleName] then&lt;br /&gt;
            return &#039;[[&#039; .. builtins[moduleName].link .. &#039;|&#039; .. moduleName .. &#039;]]&#039;&lt;br /&gt;
        else&lt;br /&gt;
            return &#039;[[&#039; .. moduleName .. &#039;]]&#039;&lt;br /&gt;
        end&lt;br /&gt;
    end )&lt;br /&gt;
&lt;br /&gt;
    local loadDataList = arr.map( lists.loadDataList, function ( moduleName )&lt;br /&gt;
        if moduleName:find( &#039;%%&#039; ) then&lt;br /&gt;
            return formatDynamicQueryLink( moduleName )&lt;br /&gt;
        else&lt;br /&gt;
            return &#039;[[&#039; .. moduleName .. &#039;]]&#039;&lt;br /&gt;
        end&lt;br /&gt;
    end )&lt;br /&gt;
&lt;br /&gt;
    local loadJsonDataList = arr.map( lists.loadJsonDataList, function ( moduleName )&lt;br /&gt;
        if moduleName:find( &#039;%%&#039; ) then&lt;br /&gt;
            return formatDynamicQueryLink( moduleName )&lt;br /&gt;
        else&lt;br /&gt;
            return &#039;[[&#039; .. moduleName .. &#039;]]&#039;&lt;br /&gt;
        end&lt;br /&gt;
    end )&lt;br /&gt;
&lt;br /&gt;
    local usedTemplateList = arr.map( lists.usedTemplateList, function ( templateName )&lt;br /&gt;
        if string.find( templateName, &#039;:&#039; ) then -- Real templates are prefixed by a namespace, magic words are not&lt;br /&gt;
            return &#039;[[&#039; .. templateName .. &#039;]]&#039;&lt;br /&gt;
        else&lt;br /&gt;
            return &amp;quot;&#039;&#039;&#039;&amp;amp;#123;&amp;amp;#123;&amp;quot; ..&lt;br /&gt;
                templateName ..&lt;br /&gt;
                &amp;quot;&amp;amp;#125;&amp;amp;#125;&#039;&#039;&#039;&amp;quot; -- Magic words don&#039;t have a page so make them bold instead&lt;br /&gt;
        end&lt;br /&gt;
    end )&lt;br /&gt;
&lt;br /&gt;
    local res = {}&lt;br /&gt;
&lt;br /&gt;
    table.insert( res, formatInvokedByList( currentPageName, p.getWhatTemplatesLinkHere( currentPageName ) ) )&lt;br /&gt;
    table.insert( res,&lt;br /&gt;
        formatDependencyList( currentPageName, requireList, translate( &#039;list_type_modules&#039; ), &#039;message_requires&#039;,&lt;br /&gt;
            t( &#039;category_modules_required_by_modules&#039; ) ) )&lt;br /&gt;
    table.insert( res,&lt;br /&gt;
        formatDependencyList( currentPageName, loadDataList, translate( &#039;list_type_modules&#039; ), &#039;message_loads_data_from&#039;,&lt;br /&gt;
            t( &#039;category_modules_using_data&#039; ) ) )&lt;br /&gt;
    table.insert( res,&lt;br /&gt;
        formatDependencyList( currentPageName, loadJsonDataList, translate( &#039;list_type_modules&#039; ),&lt;br /&gt;
            &#039;message_loads_data_from&#039;, t( &#039;category_modules_using_data&#039; ) ) )&lt;br /&gt;
    table.insert( res,&lt;br /&gt;
        formatDependencyList( currentPageName, usedTemplateList, translate( &#039;list_type_templates&#039; ),&lt;br /&gt;
            &#039;message_transcludes&#039;, nil ) )&lt;br /&gt;
    table.insert( res, formatRequiredByList( currentPageName, p.getWhatModulesLinkHere( currentPageName ) ) )&lt;br /&gt;
&lt;br /&gt;
    if shouldAddCategories then&lt;br /&gt;
        local extraCategories = arr.map( lists.extraCategories, function ( categoryName )&lt;br /&gt;
            return &#039;[[Category:&#039; .. categoryName .. &#039;]]&#039;&lt;br /&gt;
        end )&lt;br /&gt;
&lt;br /&gt;
        table.insert( res, table.concat( extraCategories ) )&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    if not moduleIsUsed then&lt;br /&gt;
        table.insert( res, 1, messageBoxUnused() )&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    return table.concat( res )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;br /&gt;
-- &amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=Module:DPLlua&amp;diff=40</id>
		<title>Module:DPLlua</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=Module:DPLlua&amp;diff=40"/>
		<updated>2025-09-21T15:10:39Z</updated>

		<summary type="html">&lt;p&gt;Erina: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- &amp;lt;nowiki&amp;gt;&lt;br /&gt;
local dpl = {}&lt;br /&gt;
local libraryUtil = require(&#039;libraryUtil&#039;)&lt;br /&gt;
local hasContent = require(&#039;Module:Paramtest&#039;).has_content&lt;br /&gt;
local checkType = libraryUtil.checkType&lt;br /&gt;
local checkTypeForNamedArg = libraryUtil.checkTypeForNamedArg&lt;br /&gt;
&lt;br /&gt;
dpl.pipe = &#039;¦&#039;&lt;br /&gt;
local dataContentMarker = &#039;`#@@#`&#039;&lt;br /&gt;
local allIncludedParamNames = {}&lt;br /&gt;
&lt;br /&gt;
-- Custom function for splitting a string because mw.text.split() is waaay too slow&lt;br /&gt;
local function split( str, pattern, plain )&lt;br /&gt;
	local res = {}&lt;br /&gt;
	local continue = true&lt;br /&gt;
	local startIndex = 1&lt;br /&gt;
&lt;br /&gt;
	while continue do&lt;br /&gt;
		local i, j = string.find( str, pattern, startIndex, plain )&lt;br /&gt;
		if i then&lt;br /&gt;
			table.insert( res, string.sub( str, startIndex, i-1 ) )&lt;br /&gt;
			startIndex = j + 1&lt;br /&gt;
		else&lt;br /&gt;
			table.insert( res, string.sub( str, startIndex ) )&lt;br /&gt;
			continue = false&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return res&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Also custom function for speed&lt;br /&gt;
local function trim( str )&lt;br /&gt;
	return (string.gsub( str, &#039;^%s+&#039;, &#039;&#039; ):gsub( &#039;%s+$&#039;, &#039;&#039; ))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function mergeItem( tbl, key, item )&lt;br /&gt;
	if type( tbl[key] ) == &#039;table&#039; and type( item ) == &#039;table&#039; then&lt;br /&gt;
		for k in pairs( tbl[key] ) do&lt;br /&gt;
			mergeItem( tbl[key], k, item[k] )&lt;br /&gt;
		end&lt;br /&gt;
	elseif type( tbl[key] ) == &#039;table&#039; then&lt;br /&gt;
		table.insert( tbl[key], item )&lt;br /&gt;
	else&lt;br /&gt;
		tbl[key] = { tbl[key], item }&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local escapeChars = {&lt;br /&gt;
	[&#039;{&#039;] = &#039;&amp;amp;#123;&#039;,&lt;br /&gt;
	[&#039;}&#039;] = &#039;&amp;amp;#125;&#039;,&lt;br /&gt;
	[&#039;[&#039;] = &#039;&amp;amp;#91;&#039;,&lt;br /&gt;
	[&#039;]&#039;] = &#039;&amp;amp;#93;&#039;,&lt;br /&gt;
	[&#039;|&#039;] = &#039;&amp;amp;#124;&#039;,&lt;br /&gt;
	[&#039;-&#039;] = &#039;&amp;amp;#8208;&#039;&lt;br /&gt;
}&lt;br /&gt;
local function escape( str )&lt;br /&gt;
	return (string.gsub( str, &#039;[{}%[%]|%-]&#039;, escapeChars ))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local unEscapeChars = {&lt;br /&gt;
	[&#039;&amp;amp;#123;&#039;] = &#039;{&#039;,&lt;br /&gt;
	[&#039;&amp;amp;#125;&#039;] = &#039;}&#039;,&lt;br /&gt;
	[&#039;&amp;amp;#91;&#039;] = &#039;[&#039;,&lt;br /&gt;
	[&#039;&amp;amp;#93;&#039;] = &#039;]&#039;,&lt;br /&gt;
	[&#039;&amp;amp;#124;&#039;] = &#039;|&#039;,&lt;br /&gt;
	[&#039;&amp;amp;#8208;&#039;] = &#039;-&#039;&lt;br /&gt;
}&lt;br /&gt;
local function unEscape( str )&lt;br /&gt;
	return (string.gsub( str, &#039;&amp;amp;#%d+;&#039;, unEscapeChars ))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function fixCurlyBrackets( str )&lt;br /&gt;
	-- the \226\157\180\181 are used to match ❴ (U+2774) and ❵ (U+2775) wich are 3 bytes long (UTF-8) so&lt;br /&gt;
	-- we can&#039;t use them directly inside [] patterns. Ustring would fix this but it&#039;s way too slow.&lt;br /&gt;
	return (string.gsub( str, &#039;\226\157[\180\181]&#039;, { [&#039;❴&#039;] = &#039;{&#039;, [&#039;❵&#039;] = &#039;}&#039; } ))&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function removeFormattingSettings( query )&lt;br /&gt;
	local toRemove = {&lt;br /&gt;
		&#039;mode&#039;,&lt;br /&gt;
		&#039;table&#039;,&lt;br /&gt;
		&#039;tablerow&#039;,&lt;br /&gt;
		&#039;tablesortcol&#039;,&lt;br /&gt;
		&#039;headingmode&#039;,&lt;br /&gt;
		&#039;headingcount&#039;,&lt;br /&gt;
		&#039;listattr&#039;,&lt;br /&gt;
		&#039;itemattr&#039;,&lt;br /&gt;
		&#039;hlistattr&#039;,&lt;br /&gt;
		&#039;hitemattr&#039;,&lt;br /&gt;
		&#039;userdateformat&#039;,&lt;br /&gt;
		&#039;shownamespace&#039;,&lt;br /&gt;
		&#039;escapelinks&#039;,&lt;br /&gt;
		&#039;titlemaxlength&#039;,&lt;br /&gt;
		&#039;replaceintitle&#039;,&lt;br /&gt;
		&#039;columns&#039;,&lt;br /&gt;
		&#039;rows&#039;,&lt;br /&gt;
		&#039;rowsize&#039;,&lt;br /&gt;
		&#039;rowcolformat&#039;,&lt;br /&gt;
		&#039;resultsheader&#039;,&lt;br /&gt;
		&#039;resultsfooter&#039;,&lt;br /&gt;
		&#039;oneresultheader&#039;,&lt;br /&gt;
		&#039;oneresultfooter&#039;,&lt;br /&gt;
		&#039;noresultsheader&#039;,&lt;br /&gt;
		&#039;suppresserrors&#039;,&lt;br /&gt;
		&#039;noresultsfooter&#039;,&lt;br /&gt;
		&#039;format&#039;,&lt;br /&gt;
		&#039;groupMultiTemplateResults&#039;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	for _, k in ipairs( toRemove ) do&lt;br /&gt;
		query[k] = nil&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function formatInclude( query )&lt;br /&gt;
	checkTypeForNamedArg( &#039;Module:DPLlua.ask&#039;, &#039;include&#039;, query, &#039;string&#039; )&lt;br /&gt;
	query = split( query, &#039;,&#039;, true )&lt;br /&gt;
	local includedParamNames = {}&lt;br /&gt;
	local sectionAttributes = {}&lt;br /&gt;
&lt;br /&gt;
	for i = 1, #query do&lt;br /&gt;
		if query[i]:match( &#039;%b{}&#039; ) then -- Check if we are including a template&lt;br /&gt;
			local templateName, extra = query[i]:match( &#039;{(.-)[¦|}](.*)&#039; )&lt;br /&gt;
			if hasContent( extra ) then&lt;br /&gt;
				local phantomTemplateName = extra:match( &#039;^(.-)}&#039; ) or extra:match( &#039;^[./].+&#039; )&lt;br /&gt;
				local phantomTemplatePrefix = extra:match( &#039;^(.-)}&#039; ) and &#039;&#039; or templateName&lt;br /&gt;
				local params = extra:gsub( &#039;^.-}&#039;, &#039;&#039; ):gsub( &#039;^[./].+&#039;, &#039;&#039; ):gsub( &#039;:%-&#039;, &#039;&#039; )&lt;br /&gt;
				local sur = hasContent( phantomTemplateName ) and (&#039;¦&#039; .. phantomTemplatePrefix .. phantomTemplateName) or &#039;&#039;&lt;br /&gt;
				query[i] = string.format( &#039;{%s%s}%s&#039;, templateName, sur, params )&lt;br /&gt;
&lt;br /&gt;
				if hasContent( phantomTemplateName ) then&lt;br /&gt;
					table.insert( includedParamNames, { name=phantomTemplatePrefix..phantomTemplateName, isTemplate=true, hasPhantomTemplate=true } )&lt;br /&gt;
					table.insert( sectionAttributes, { hasPhantomTemplate=true } )&lt;br /&gt;
				else&lt;br /&gt;
					for param in params:gmatch( &#039;:([^:]*)&#039; ) do&lt;br /&gt;
						param = trim( param )&lt;br /&gt;
						table.insert( includedParamNames, { name=templateName, isTemplate=true, param=param } )&lt;br /&gt;
					end&lt;br /&gt;
					table.insert( sectionAttributes, { hasPhantomTemplate=false } )&lt;br /&gt;
				end&lt;br /&gt;
			else&lt;br /&gt;
				query[i] = string.format( &#039;{%s¦DPLlua helper}&#039;, templateName ) -- Use a helper template to get all the parameters of our included template&lt;br /&gt;
				table.insert( includedParamNames, { name=templateName, isTemplate=true, includeAll=true } )&lt;br /&gt;
				table.insert( sectionAttributes, { hasPhantomTemplate=false } )&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			table.insert( includedParamNames, { name=trim( query[i] ) } )&lt;br /&gt;
			table.insert( sectionAttributes, { hasPhantomTemplate=false } )&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return table.concat( query, &#039;,&#039; ), includedParamNames, sectionAttributes&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function formatDpl( query )&lt;br /&gt;
	local queries = {}&lt;br /&gt;
	local count = query.count or 500&lt;br /&gt;
	local offset = query.offset or 0&lt;br /&gt;
	local usesInclude = false&lt;br /&gt;
	local includedParamNames = {}&lt;br /&gt;
	local sectionAttributes&lt;br /&gt;
	query.count = nil&lt;br /&gt;
	query.offset = nil&lt;br /&gt;
&lt;br /&gt;
	-- Use table format so we can place dataContentMarkers around each included parameter. The secseparator&lt;br /&gt;
	-- is needed to add dataContentMarkers when a phantom template is used&lt;br /&gt;
	local dplStringInclude =&lt;br /&gt;
[=[&lt;br /&gt;
{{#dpl:&lt;br /&gt;
|noresultsheader=@@&lt;br /&gt;
|count=%s&lt;br /&gt;
|offset=%s&lt;br /&gt;
|%s&lt;br /&gt;
|table=,&lt;br /&gt;
|listseparators=,\n¦-\n¦[[%%PAGE%%¦]],,&lt;br /&gt;
|tablerow=%s&lt;br /&gt;
|secseparators=%s&lt;br /&gt;
}}]=]&lt;br /&gt;
&lt;br /&gt;
	-- Table format requires an include statement so we use format instead.&lt;br /&gt;
	-- This is also a lot faster than adding an empty include statement&lt;br /&gt;
	local dplStringNoInclude =&lt;br /&gt;
[=[&lt;br /&gt;
{{#dpl:&lt;br /&gt;
|noresultsheader=@@&lt;br /&gt;
|count=%s&lt;br /&gt;
|offset=%s&lt;br /&gt;
|%s&lt;br /&gt;
|format=,¦-¦[[%%PAGE%%¦]],,&lt;br /&gt;
}}]=]&lt;br /&gt;
&lt;br /&gt;
	-- Auto generate more than one dpl if count &amp;gt; 500&lt;br /&gt;
	-- The results of these are later combined&lt;br /&gt;
	for i = 1, math.ceil( count / 500 ) do&lt;br /&gt;
		local params = {}&lt;br /&gt;
&lt;br /&gt;
		for k, v in pairs( query ) do&lt;br /&gt;
			if k == &#039;include&#039; then&lt;br /&gt;
				v, includedParamNames, sectionAttributes = formatInclude( v )&lt;br /&gt;
				usesInclude =  true&lt;br /&gt;
			end&lt;br /&gt;
&lt;br /&gt;
			if type( v ) == &#039;table&#039; then&lt;br /&gt;
				for _, x in ipairs( v ) do&lt;br /&gt;
					table.insert( params, k .. &#039;=&#039; .. tostring( x ):gsub( &#039;|&#039;, &#039;¦&#039; ) )&lt;br /&gt;
				end&lt;br /&gt;
			else&lt;br /&gt;
				table.insert( params, k .. &#039;=&#039; .. tostring( v ):gsub( &#039;|&#039;, &#039;¦&#039; ) )&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		if usesInclude then&lt;br /&gt;
			local secseparators = &#039;&#039;&lt;br /&gt;
			for _, v in ipairs( sectionAttributes ) do&lt;br /&gt;
				if v.hasPhantomTemplate then&lt;br /&gt;
					-- Phantom templates need this because they ignore tablerow formatting&lt;br /&gt;
					secseparators = secseparators .. &#039;¶¦&#039; .. dataContentMarker .. &#039;,&#039; .. dataContentMarker .. &#039;,&#039;&lt;br /&gt;
				else&lt;br /&gt;
					secseparators = secseparators .. &#039;¶¦,,&#039;&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
&lt;br /&gt;
			table.insert( queries, string.format(&lt;br /&gt;
				dplStringInclude,&lt;br /&gt;
				count &amp;gt; 500 and 500 or count,&lt;br /&gt;
				offset,&lt;br /&gt;
				table.concat( params, &#039;\n|&#039; ),&lt;br /&gt;
				string.rep( dataContentMarker..&#039;%%&#039;..dataContentMarker..&#039;,&#039;, #includedParamNames ),&lt;br /&gt;
				secseparators&lt;br /&gt;
			) )&lt;br /&gt;
		else&lt;br /&gt;
			table.insert( queries, string.format(&lt;br /&gt;
				dplStringNoInclude,&lt;br /&gt;
				count &amp;gt; 500 and 500 or count,&lt;br /&gt;
				offset,&lt;br /&gt;
				table.concat( params, &#039;\n|&#039; )&lt;br /&gt;
			) )&lt;br /&gt;
		end&lt;br /&gt;
&lt;br /&gt;
		count = count - 500&lt;br /&gt;
		offset = offset + 500&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	table.insert( allIncludedParamNames, includedParamNames )&lt;br /&gt;
	return table.concat( queries )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function toTable( query, groupMultiTemplateResults )&lt;br /&gt;
	local includedParamNames = table.remove( allIncludedParamNames, 1 )&lt;br /&gt;
	local usesInclude = #includedParamNames &amp;gt; 0&lt;br /&gt;
	local res = {}&lt;br /&gt;
&lt;br /&gt;
	query = query:gsub( &#039;&amp;lt;p&amp;gt;Extension:DynamicPageList .-&amp;lt;/p&amp;gt;&#039;, function(item) res.error = item; return &#039;&#039; end )&lt;br /&gt;
&lt;br /&gt;
	if query:find( &#039;^@@&#039; ) then -- @@ is used when no result is found&lt;br /&gt;
		return res&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	if usesInclude then&lt;br /&gt;
		query = query:gsub( dataContentMarker..&#039;(.-)&#039;..dataContentMarker, escape )&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	query = trim( query )&lt;br /&gt;
	query = split( query, &#039;|-&#039;, true ) -- Results of the returned pages are separated by |-&lt;br /&gt;
&lt;br /&gt;
	for _, v in ipairs( query ) do&lt;br /&gt;
		if hasContent( v ) and not v:find( &#039;^@@&#039; ) then&lt;br /&gt;
			v = trim( v )&lt;br /&gt;
			local title = v:match( &#039;^|%[%[(.-)|&#039; )&lt;br /&gt;
			local rawDataList = v:match( &#039;^|.-|.-|(.*)&#039; ) -- This is everything after the title&lt;br /&gt;
&lt;br /&gt;
			if not usesInclude then&lt;br /&gt;
				if title and title ~= &#039;&#039; then&lt;br /&gt;
					table.insert( res, title )&lt;br /&gt;
				end&lt;br /&gt;
			else&lt;br /&gt;
				-- When multiple includes are used (e.g. include={Template1},{Template2} or include={Template}:1:2) their results are separated by a pipe&lt;br /&gt;
				rawDataList = split( rawDataList, &#039;|&#039;, true )&lt;br /&gt;
				local cleanedDataList = {}&lt;br /&gt;
&lt;br /&gt;
				for _incIndex, dataItem in ipairs( rawDataList ) do&lt;br /&gt;
					local incIndex = ((_incIndex - 1) % #includedParamNames) + 1 -- Needed in case the same template appears multiple times on the same page&lt;br /&gt;
					dataItem = unEscape( dataItem )&lt;br /&gt;
					dataItem = trim( dataItem )&lt;br /&gt;
&lt;br /&gt;
					if includedParamNames[ incIndex ].isTemplate and includedParamNames[ incIndex ].includeAll then -- Check if we included a full template&lt;br /&gt;
						-- When we include an entire template we use the %ARGS% parameter supplied by dpl.&lt;br /&gt;
						-- However all | characters are repaced with §, e.g.:&lt;br /&gt;
						-- §namelessParam&lt;br /&gt;
						-- §param = text [[wowee§link text]]&lt;br /&gt;
						-- §param2 = text {{something§something else}}&lt;br /&gt;
						dataItem = dataItem:gsub( &#039;\127\&#039;&amp;quot;`UNIQ%-%-nowiki%-%x+%-QINU`&amp;quot;\&#039;\127&#039;, function(item) return &#039;&amp;lt;nowiki&amp;gt;&#039; .. item .. &#039;&amp;lt;/nowiki&amp;gt;&#039; end )&lt;br /&gt;
						dataItem = mw.text.unstripNoWiki( dataItem ) -- Unstrip nowiki so we can clean their content&lt;br /&gt;
						dataItem = fixCurlyBrackets( dataItem ) -- When using the %ARGS% dpl parameter, curly brackets are replaced with ❴ (U+2774) and ❵ (U+2775)&lt;br /&gt;
						dataItem = dataItem:gsub( &#039;%b{}&#039;, function(x) return x:gsub( &#039;§&#039;, &#039;|&#039; ) end ) -- Restore pipe characters inside links and templates&lt;br /&gt;
						dataItem = dataItem:gsub( &#039;%b[]&#039;, function(x) return x:gsub( &#039;§&#039;, &#039;|&#039; ) end )&lt;br /&gt;
						dataItem = dataItem:gsub( &#039;&amp;lt;nowiki&amp;gt;(.-)&amp;lt;/nowiki&amp;gt;&#039;, function(x) return mw.getCurrentFrame():extensionTag( &#039;nowiki&#039;, x ) end ) -- Restrip nowiki&lt;br /&gt;
						local _dataItem = {}&lt;br /&gt;
&lt;br /&gt;
						if dataItem ~= &#039;&#039; then&lt;br /&gt;
							dataItem = split( dataItem:sub( 3 ), &#039;§&#039; ) -- The sub(3) removes the first § at the start. § is 2 bytes wide so start at index 3&lt;br /&gt;
&lt;br /&gt;
							for i, item in ipairs( dataItem ) do&lt;br /&gt;
								if item:find( &#039;=&#039; ) then -- Check if the parameter is named or unnamed&lt;br /&gt;
									local param, value = item:match( &#039;^%s*(.-)%s*=%s*(.-)%s*$&#039; )&lt;br /&gt;
									_dataItem[ param ] = value&lt;br /&gt;
								else&lt;br /&gt;
									table.insert( _dataItem, trim( item ) )&lt;br /&gt;
								end&lt;br /&gt;
							end&lt;br /&gt;
						end&lt;br /&gt;
&lt;br /&gt;
						dataItem = _dataItem&lt;br /&gt;
					end&lt;br /&gt;
&lt;br /&gt;
					local dataListIndex = groupMultiTemplateResults and 1 or math.ceil( _incIndex / #includedParamNames )&lt;br /&gt;
					if&lt;br /&gt;
						includedParamNames[ incIndex ].isTemplate and&lt;br /&gt;
						not includedParamNames[ incIndex ].includeAll and&lt;br /&gt;
						not includedParamNames[ incIndex ].hasPhantomTemplate&lt;br /&gt;
					then -- This means there was an include in the form &#039;include = {template}:param&#039;&lt;br /&gt;
						local templateName = includedParamNames[ incIndex ].name&lt;br /&gt;
						local paramName = includedParamNames[ incIndex ].param&lt;br /&gt;
						paramName = tonumber( paramName ) or paramName -- Keep as string if tonumber fails&lt;br /&gt;
						cleanedDataList[ dataListIndex ] = cleanedDataList[ dataListIndex ] or {}&lt;br /&gt;
						cleanedDataList[ dataListIndex ][ templateName ] = cleanedDataList[ dataListIndex ][ templateName ] or {}&lt;br /&gt;
						&lt;br /&gt;
						if groupMultiTemplateResults and _incIndex &amp;gt; #includedParamNames then&lt;br /&gt;
							mergeItem( cleanedDataList[ dataListIndex ][ templateName ], paramName, dataItem )&lt;br /&gt;
						else&lt;br /&gt;
							cleanedDataList[ dataListIndex ][ templateName ][ paramName ] = dataItem&lt;br /&gt;
						end&lt;br /&gt;
					else&lt;br /&gt;
						local templateName = includedParamNames[ incIndex ].name&lt;br /&gt;
						cleanedDataList[ dataListIndex ] = cleanedDataList[ dataListIndex ] or {}&lt;br /&gt;
						&lt;br /&gt;
						if groupMultiTemplateResults and _incIndex &amp;gt; #includedParamNames then&lt;br /&gt;
							mergeItem( cleanedDataList[ dataListIndex ], templateName, dataItem )&lt;br /&gt;
						else&lt;br /&gt;
							cleanedDataList[ dataListIndex ][ templateName ] = dataItem&lt;br /&gt;
						end&lt;br /&gt;
					end&lt;br /&gt;
				end&lt;br /&gt;
&lt;br /&gt;
				if title and title ~= &#039;&#039; then&lt;br /&gt;
					for _, v in ipairs( cleanedDataList ) do&lt;br /&gt;
						table.insert( res, { title=title, include=v } )&lt;br /&gt;
					end&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return res&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Accepts a series of tables each containig the settings for a dpl query.&lt;br /&gt;
-- Combinig multiple dpl queries yields better performance than doing them sequentially&lt;br /&gt;
function dpl.ask( ... )&lt;br /&gt;
	local formatTime = os.clock()&lt;br /&gt;
	local queries = { ... }&lt;br /&gt;
	local wantsGrouping = {}&lt;br /&gt;
&lt;br /&gt;
	for i = 1, #queries do&lt;br /&gt;
		checkType( &#039;Module:DPLlua.ask&#039;, i, queries[i], &#039;table&#039; )&lt;br /&gt;
		table.insert( wantsGrouping, queries[i].groupMultiTemplateResults or false )&lt;br /&gt;
		removeFormattingSettings( queries[i] )&lt;br /&gt;
		queries[i] = formatDpl( queries[i] )&lt;br /&gt;
	end&lt;br /&gt;
	formatTime = os.clock() - formatTime&lt;br /&gt;
&lt;br /&gt;
	local DPLtime = os.clock()&lt;br /&gt;
	queries = table.concat( queries, &#039;$@µ@$&#039; )&lt;br /&gt;
	queries = mw.getCurrentFrame():preprocess( queries )&lt;br /&gt;
	queries = split( queries, &#039;$@µ@$&#039;, true )&lt;br /&gt;
	DPLtime = os.clock() - DPLtime&lt;br /&gt;
&lt;br /&gt;
	for i = 1, #queries do&lt;br /&gt;
		local parseTime = os.clock()&lt;br /&gt;
		queries[i] = toTable( queries[i], wantsGrouping[i] )&lt;br /&gt;
		parseTime = os.clock() - parseTime&lt;br /&gt;
		queries[i][&#039;DPL time&#039;] = DPLtime&lt;br /&gt;
		queries[i][&#039;Parse time&#039;] = math.floor( (formatTime + parseTime) * 1e5 ) / 1e5 -- os.clock() has a resolution of 10µs&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return unpack( queries )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- function dpl.test()&lt;br /&gt;
-- 	local time = os.clock()&lt;br /&gt;
&lt;br /&gt;
	-- local a, b = dpl.ask({&lt;br /&gt;
	--     namespace = &#039;Module&#039;,&lt;br /&gt;
	--     linksto = &#039;Module:Chart data&#039;,&lt;br /&gt;
	--     distinct = &#039;strict&#039;,&lt;br /&gt;
	--     ordermethod = &#039;title&#039;,&lt;br /&gt;
	--     nottitlematch = &#039;%/doc¦%sandbox%¦Exchange/%¦Exchange historical/%¦Chart data&#039;,&lt;br /&gt;
	-- 	ignorecase = &#039;true&#039;,&lt;br /&gt;
	-- 	allowcachedresults = false&lt;br /&gt;
	-- },{&lt;br /&gt;
	--     namespace = &#039;Module&#039;,&lt;br /&gt;
	--     linksto = &#039;Module:Enum&#039;,&lt;br /&gt;
	--     distinct = &#039;strict&#039;,&lt;br /&gt;
	--     ordermethod = &#039;title&#039;,&lt;br /&gt;
	-- 	nottitlematch = &#039;%/doc¦%sandbox%¦Exchange/%¦Exchange historical/%¦Enum&#039;,&lt;br /&gt;
	--     ignorecase = &#039;true&#039;,&lt;br /&gt;
	-- 	allowcachedresults = false&lt;br /&gt;
	-- })&lt;br /&gt;
	-- mw.logObject(a)&lt;br /&gt;
	-- mw.logObject(b)&lt;br /&gt;
&lt;br /&gt;
	-- local a, b = dpl.ask({&lt;br /&gt;
	--     namespace = &#039;Module&#039;,&lt;br /&gt;
	--     linksto = &#039;Module:Chart data&#039;,&lt;br /&gt;
	--     distinct = &#039;strict&#039;,&lt;br /&gt;
	--     ordermethod = &#039;title&#039;,&lt;br /&gt;
	--     nottitlematch = &#039;%/doc¦%sandbox%¦Exchange/%¦Exchange historical/%¦Chart data&#039;,&lt;br /&gt;
	--     ignorecase = &#039;true&#039;,&lt;br /&gt;
	-- 	allowcachedresults = false&lt;br /&gt;
	-- },{&lt;br /&gt;
	-- 	namespace = &#039;&#039;,&lt;br /&gt;
	-- 	ignorecase = &#039;true&#039;,&lt;br /&gt;
	-- 	uses = &#039;Template:Infobox Recipe&#039;,&lt;br /&gt;
	-- 	count = 50,&lt;br /&gt;
	-- 	include = &#039;{Infobox Recipe},{Infobox Item}&#039;,&lt;br /&gt;
	-- 	allowcachedresults = false&lt;br /&gt;
	-- })&lt;br /&gt;
	-- mw.logObject(a)&lt;br /&gt;
	-- mw.logObject(b)&lt;br /&gt;
&lt;br /&gt;
	-- local a = dpl.ask{&lt;br /&gt;
	-- 	namespace = &#039;&#039;,&lt;br /&gt;
	-- 	uses = &#039;Template:Infobox Recipe&#039;,&lt;br /&gt;
	-- 	include = &#039;{Infobox Recipe}:skill:name,{Infobox Item}:update,{Infobox Item|test}&#039;,&lt;br /&gt;
	-- 	count = 50,&lt;br /&gt;
	-- 	ordermethod = &#039;title&#039;,&lt;br /&gt;
	-- }&lt;br /&gt;
	-- mw.logObject(a)&lt;br /&gt;
&lt;br /&gt;
	-- local q = dpl.ask{&lt;br /&gt;
	-- 	uses = &amp;quot;Template:Collections table&amp;quot;,&lt;br /&gt;
	-- 	category = &amp;quot;Archaeology collections&amp;quot;,&lt;br /&gt;
	-- 	-- include = &amp;quot;{Infobox collection}:reward,{Collections table}:1:2:3:4:5:6:7:8:9:10:11:12:13:14:15&amp;quot;,&lt;br /&gt;
	-- 	include = &amp;quot;{Infobox collection}:reward,{Collections table}&amp;quot;,&lt;br /&gt;
	-- 	count = 100&lt;br /&gt;
	-- }&lt;br /&gt;
	-- mw.logObject(q)&lt;br /&gt;
	&lt;br /&gt;
	-- local q = dpl.ask{&lt;br /&gt;
	-- 	namespace = &amp;quot;&amp;quot;,&lt;br /&gt;
	-- 	uses = &amp;quot;Template:Infobox spell&amp;quot;,&lt;br /&gt;
	-- 	notcategory = {&amp;quot;Removed content&amp;quot;, &amp;quot;Removed spells&amp;quot;},&lt;br /&gt;
	-- 	nottitlematch = {&amp;quot;Enchant Crossbow Bolt&amp;quot;, &amp;quot;Storm of Armadyl&amp;quot;},&lt;br /&gt;
	-- 	include = &amp;quot;{Infobox spell}&amp;quot;,&lt;br /&gt;
	-- }&lt;br /&gt;
	-- mw.logObject(q)&lt;br /&gt;
&lt;br /&gt;
-- 	local list = dpl.ask{&lt;br /&gt;
-- 		namespace = &#039;Template&#039;,&lt;br /&gt;
-- 		uses = &#039;Template:Navbox&#039;,&lt;br /&gt;
-- 		ordermethod = &#039;title&#039;,&lt;br /&gt;
-- 		include = &#039;{Navbox}:gtitle1:gtitle2&#039;,&lt;br /&gt;
-- 		count = 1,&lt;br /&gt;
-- 		offset = 3&lt;br /&gt;
-- 	}&lt;br /&gt;
-- 	mw.logObject(list)&lt;br /&gt;
&lt;br /&gt;
-- 	local list = dpl.ask{&lt;br /&gt;
-- 		namespace = &#039;User&#039;,&lt;br /&gt;
-- 		titlematch = &#039;CephHunter/Sandbox/test1&#039;,&lt;br /&gt;
-- 		include = &#039;{User:CephHunter/Sandbox/test2|User:CephHunter/Sandbox/test3},{User:CephHunter/Sandbox/test3}:1&#039;,&lt;br /&gt;
-- 	}&lt;br /&gt;
-- 	mw.logObject(list)&lt;br /&gt;
&lt;br /&gt;
-- 	mw.logObject(dpl.ask{&lt;br /&gt;
-- 		namespace = &#039;User&#039;,&lt;br /&gt;
-- 		ignorecase = &#039;true&#039;,&lt;br /&gt;
-- 		titlematch = &#039;CephHunter/Sandbox/test1&#039;,&lt;br /&gt;
-- 		include = &#039;{User:CephHunter/Sandbox/test2}&#039;&lt;br /&gt;
-- 	})&lt;br /&gt;
&lt;br /&gt;
-- 	mw.logObject(dpl.ask{&lt;br /&gt;
-- 		namespace = &#039;Module&#039;,&lt;br /&gt;
-- 		uses = &#039;Template:Helper module&#039;,&lt;br /&gt;
-- 		titlematch = &#039;%/doc&#039;,&lt;br /&gt;
-- 		nottitlematch = &#039;Exchange/%|Exchange historical/%|Sandbox/%&#039;,&lt;br /&gt;
-- 		ordermethod = &#039;title&#039;,&lt;br /&gt;
-- 		include = &#039;{Helper module}, {Helper module}:example&#039;,&lt;br /&gt;
-- 		count = 1,&lt;br /&gt;
-- 		offset = 13&lt;br /&gt;
-- 	})&lt;br /&gt;
&lt;br /&gt;
-- 	mw.logObject(dpl.ask{&lt;br /&gt;
--         namespace = &#039;Module&#039;,&lt;br /&gt;
--         titlematch = &#039;Chart data|Absorbative calculator&#039;,&lt;br /&gt;
--         nottitlematch = &#039;Exchange/%|Exchange historical/%|Sandbox/%|%/doc|DPLlua%&#039;,&lt;br /&gt;
--         ordermethod = &#039;title&#039;,&lt;br /&gt;
--         include = &#039;%0&#039;&lt;br /&gt;
-- 	})&lt;br /&gt;
&lt;br /&gt;
-- 	mw.logObject(dpl.ask{&lt;br /&gt;
--         uses = &#039;Template:Collections table&#039;,&lt;br /&gt;
--         include = &#039;{Collections table}&#039;,&lt;br /&gt;
--         count = 5&lt;br /&gt;
-- 	})&lt;br /&gt;
&lt;br /&gt;
-- 	mw.log(os.clock()-time)&lt;br /&gt;
-- end&lt;br /&gt;
&lt;br /&gt;
return dpl&lt;br /&gt;
-- &amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=Template:Documentation&amp;diff=38</id>
		<title>Template:Documentation</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=Template:Documentation&amp;diff=38"/>
		<updated>2025-09-21T15:10:39Z</updated>

		<summary type="html">&lt;p&gt;Erina: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;{{#invoke:Documentation|doc}}__NOEDITSECTION__{{#seo:&lt;br /&gt;
|type			= website&lt;br /&gt;
|description	= {{FULLPAGENAME}} is a template page used on the Star Citizen Wiki. Templates are pages that are embedded (transcluded) into other pages to allow for the repetition of information.&lt;br /&gt;
|site_name		= Star Citizen Wiki&lt;br /&gt;
|locale			= {{PAGELANGUAGE}}&lt;br /&gt;
}}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;{{/doc}}&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=Module:Yesno&amp;diff=36</id>
		<title>Module:Yesno</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=Module:Yesno&amp;diff=36"/>
		<updated>2025-09-21T15:10:39Z</updated>

		<summary type="html">&lt;p&gt;Erina: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- Imported from: https://en.wikipedia.org/wiki/Module:Yesno&lt;br /&gt;
&lt;br /&gt;
-- Function allowing for consistent treatment of boolean-like wikitext input.&lt;br /&gt;
-- It works similarly to the template {{yesno}}.&lt;br /&gt;
&lt;br /&gt;
return function (val, default)&lt;br /&gt;
    -- If your wiki uses non-ascii characters for any of &amp;quot;yes&amp;quot;, &amp;quot;no&amp;quot;, etc., you&lt;br /&gt;
    -- should replace &amp;quot;val:lower()&amp;quot; with &amp;quot;string.lower(val)&amp;quot; in the&lt;br /&gt;
    -- following line.&lt;br /&gt;
    val = type(val) == &#039;string&#039; and val:lower() or val&lt;br /&gt;
    if val == nil then&lt;br /&gt;
        return nil&lt;br /&gt;
    elseif val == true&lt;br /&gt;
            or val == &#039;yes&#039;&lt;br /&gt;
            or val == &#039;y&#039;&lt;br /&gt;
            or val == &#039;true&#039;&lt;br /&gt;
            or val == &#039;t&#039;&lt;br /&gt;
            or val == &#039;on&#039;&lt;br /&gt;
            or val == &#039;ja&#039;&lt;br /&gt;
            or tonumber(val) == 1&lt;br /&gt;
    then&lt;br /&gt;
        return true&lt;br /&gt;
    elseif val == false&lt;br /&gt;
            or val == &#039;no&#039;&lt;br /&gt;
            or val == &#039;n&#039;&lt;br /&gt;
            or val == &#039;false&#039;&lt;br /&gt;
            or val == &#039;f&#039;&lt;br /&gt;
            or val == &#039;off&#039;&lt;br /&gt;
            or val == &#039;nein&#039;&lt;br /&gt;
            or tonumber(val) == 0&lt;br /&gt;
    then&lt;br /&gt;
        return false&lt;br /&gt;
    else&lt;br /&gt;
        return default&lt;br /&gt;
    end&lt;br /&gt;
end&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=Module:Hatnote_list&amp;diff=34</id>
		<title>Module:Hatnote list</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=Module:Hatnote_list&amp;diff=34"/>
		<updated>2025-09-21T15:10:39Z</updated>

		<summary type="html">&lt;p&gt;Erina: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;--------------------------------------------------------------------------------&lt;br /&gt;
--                           Module:Hatnote list                              --&lt;br /&gt;
--                                                                            --&lt;br /&gt;
-- This module produces and formats lists for use in hatnotes. In particular, --&lt;br /&gt;
-- it implements the for-see list, i.e. lists of &amp;quot;For X, see Y&amp;quot; statements,   --&lt;br /&gt;
-- as used in {{about}}, {{redirect}}, and their variants. Also introduced    --&lt;br /&gt;
-- are andList &amp;amp; orList helpers for formatting lists with those conjunctions. --&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local mArguments --initialize lazily&lt;br /&gt;
local mFormatLink = require(&#039;Module:Format link&#039;)&lt;br /&gt;
local mHatnote = require(&#039;Module:Hatnote&#039;)&lt;br /&gt;
local libraryUtil = require(&#039;libraryUtil&#039;)&lt;br /&gt;
local checkType = libraryUtil.checkType&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- List stringification helper functions&lt;br /&gt;
--&lt;br /&gt;
-- These functions are used for stringifying lists, usually page lists inside&lt;br /&gt;
-- the &amp;quot;Y&amp;quot; portion of &amp;quot;For X, see Y&amp;quot; for-see items.&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
--default options table used across the list stringification functions&lt;br /&gt;
local stringifyListDefaultOptions = {&lt;br /&gt;
    conjunction = &amp;quot;and&amp;quot;,&lt;br /&gt;
    separator = &amp;quot;,&amp;quot;,&lt;br /&gt;
    altSeparator = &amp;quot;;&amp;quot;,&lt;br /&gt;
    space = &amp;quot; &amp;quot;,&lt;br /&gt;
    formatted = false&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
--Searches display text only&lt;br /&gt;
local function searchDisp(haystack, needle)&lt;br /&gt;
    return string.find(&lt;br /&gt;
            string.sub(haystack, (string.find(haystack, &#039;|&#039;) or 0) + 1), needle&lt;br /&gt;
    )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Stringifies a list generically; probably shouldn&#039;t be used directly&lt;br /&gt;
local function stringifyList(list, options)&lt;br /&gt;
    -- Type-checks, defaults, and a shortcut&lt;br /&gt;
    checkType(&amp;quot;stringifyList&amp;quot;, 1, list, &amp;quot;table&amp;quot;)&lt;br /&gt;
    if #list == 0 then return nil end&lt;br /&gt;
    checkType(&amp;quot;stringifyList&amp;quot;, 2, options, &amp;quot;table&amp;quot;, true)&lt;br /&gt;
    options = options or {}&lt;br /&gt;
    for k, v in pairs(stringifyListDefaultOptions) do&lt;br /&gt;
        if options[k] == nil then options[k] = v end&lt;br /&gt;
    end&lt;br /&gt;
    local s = options.space&lt;br /&gt;
    -- Format the list if requested&lt;br /&gt;
    if options.formatted then&lt;br /&gt;
        list = mFormatLink.formatPages(&lt;br /&gt;
                {categorizeMissing = mHatnote.missingTargetCat}, list&lt;br /&gt;
        )&lt;br /&gt;
    end&lt;br /&gt;
    -- Set the separator; if any item contains it, use the alternate separator&lt;br /&gt;
    local separator = options.separator&lt;br /&gt;
    for k, v in pairs(list) do&lt;br /&gt;
        if searchDisp(v, separator) then&lt;br /&gt;
            separator = options.altSeparator&lt;br /&gt;
            break&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    -- Set the conjunction, apply Oxford comma, and force a comma if #1 has &amp;quot;§&amp;quot;&lt;br /&gt;
    local conjunction = s .. options.conjunction .. s&lt;br /&gt;
    if #list == 2 and searchDisp(list[1], &amp;quot;§&amp;quot;) or #list &amp;gt; 2 then&lt;br /&gt;
        conjunction = separator .. conjunction&lt;br /&gt;
    end&lt;br /&gt;
    -- Return the formatted string&lt;br /&gt;
    return mw.text.listToText(list, separator .. s, conjunction)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--DRY function&lt;br /&gt;
function p.conjList (conj, list, fmt)&lt;br /&gt;
    return stringifyList(list, {conjunction = conj, formatted = fmt})&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Stringifies lists with &amp;quot;and&amp;quot; or &amp;quot;or&amp;quot;&lt;br /&gt;
function p.andList (...) return p.conjList(&amp;quot;and&amp;quot;, ...) end&lt;br /&gt;
function p.orList (...) return p.conjList(&amp;quot;or&amp;quot;, ...) end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- For see&lt;br /&gt;
--&lt;br /&gt;
-- Makes a &amp;quot;For X, see [[Y]].&amp;quot; list from raw parameters. Intended for the&lt;br /&gt;
-- {{about}} and {{redirect}} templates and their variants.&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
--default options table used across the forSee family of functions&lt;br /&gt;
local forSeeDefaultOptions = {&lt;br /&gt;
    andKeyword = &#039;and&#039;,&lt;br /&gt;
    title = mw.title.getCurrentTitle().text,&lt;br /&gt;
    otherText = &#039;other uses&#039;,&lt;br /&gt;
    forSeeForm = &#039;For %s, see %s.&#039;,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
--Collapses duplicate punctuation&lt;br /&gt;
local function punctuationCollapse (text)&lt;br /&gt;
    local replacements = {&lt;br /&gt;
        [&amp;quot;%.%.$&amp;quot;] = &amp;quot;.&amp;quot;,&lt;br /&gt;
        [&amp;quot;%?%.$&amp;quot;] = &amp;quot;?&amp;quot;,&lt;br /&gt;
        [&amp;quot;%!%.$&amp;quot;] = &amp;quot;!&amp;quot;,&lt;br /&gt;
        [&amp;quot;%.%]%]%.$&amp;quot;] = &amp;quot;.]]&amp;quot;,&lt;br /&gt;
        [&amp;quot;%?%]%]%.$&amp;quot;] = &amp;quot;?]]&amp;quot;,&lt;br /&gt;
        [&amp;quot;%!%]%]%.$&amp;quot;] = &amp;quot;!]]&amp;quot;&lt;br /&gt;
    }&lt;br /&gt;
    for k, v in pairs(replacements) do text = string.gsub(text, k, v) end&lt;br /&gt;
    return text&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Structures arguments into a table for stringification, &amp;amp; options&lt;br /&gt;
function p.forSeeArgsToTable (args, from, options)&lt;br /&gt;
    -- Type-checks and defaults&lt;br /&gt;
    checkType(&amp;quot;forSeeArgsToTable&amp;quot;, 1, args, &#039;table&#039;)&lt;br /&gt;
    checkType(&amp;quot;forSeeArgsToTable&amp;quot;, 2, from, &#039;number&#039;, true)&lt;br /&gt;
    from = from or 1&lt;br /&gt;
    checkType(&amp;quot;forSeeArgsToTable&amp;quot;, 3, options, &#039;table&#039;, true)&lt;br /&gt;
    options = options or {}&lt;br /&gt;
    for k, v in pairs(forSeeDefaultOptions) do&lt;br /&gt;
        if options[k] == nil then options[k] = v end&lt;br /&gt;
    end&lt;br /&gt;
    -- maxArg&#039;s gotten manually because getArgs() and table.maxn aren&#039;t friends&lt;br /&gt;
    local maxArg = 0&lt;br /&gt;
    for k, v in pairs(args) do&lt;br /&gt;
        if type(k) == &#039;number&#039; and k &amp;gt; maxArg then maxArg = k end&lt;br /&gt;
    end&lt;br /&gt;
    -- Structure the data out from the parameter list:&lt;br /&gt;
    -- * forTable is the wrapper table, with forRow rows&lt;br /&gt;
    -- * Rows are tables of a &amp;quot;use&amp;quot; string &amp;amp; a &amp;quot;pages&amp;quot; table of pagename strings&lt;br /&gt;
    -- * Blanks are left empty for defaulting elsewhere, but can terminate list&lt;br /&gt;
    local forTable = {}&lt;br /&gt;
    local i = from&lt;br /&gt;
    local terminated = false&lt;br /&gt;
    -- If there is extra text, and no arguments are given, give nil value&lt;br /&gt;
    -- to not produce default of &amp;quot;For other uses, see foo (disambiguation)&amp;quot;&lt;br /&gt;
    if options.extratext and i &amp;gt; maxArg then return nil end&lt;br /&gt;
    -- Loop to generate rows&lt;br /&gt;
    repeat&lt;br /&gt;
        -- New empty row&lt;br /&gt;
        local forRow = {}&lt;br /&gt;
        -- On blank use, assume list&#039;s ended &amp;amp; break at end of this loop&lt;br /&gt;
        forRow.use = args[i]&lt;br /&gt;
        if not args[i] then terminated = true end&lt;br /&gt;
        -- New empty list of pages&lt;br /&gt;
        forRow.pages = {}&lt;br /&gt;
        -- Insert first pages item if present&lt;br /&gt;
        table.insert(forRow.pages, args[i + 1])&lt;br /&gt;
        -- If the param after next is &amp;quot;and&amp;quot;, do inner loop to collect params&lt;br /&gt;
        -- until the &amp;quot;and&amp;quot;&#039;s stop. Blanks are ignored: &amp;quot;1|and||and|3&amp;quot; → {1, 3}&lt;br /&gt;
        while args[i + 2] == options.andKeyword do&lt;br /&gt;
            if args[i + 3] then&lt;br /&gt;
                table.insert(forRow.pages, args[i + 3])&lt;br /&gt;
            end&lt;br /&gt;
            -- Increment to next &amp;quot;and&amp;quot;&lt;br /&gt;
            i = i + 2&lt;br /&gt;
        end&lt;br /&gt;
        -- Increment to next use&lt;br /&gt;
        i = i + 2&lt;br /&gt;
        -- Append the row&lt;br /&gt;
        table.insert(forTable, forRow)&lt;br /&gt;
    until terminated or i &amp;gt; maxArg&lt;br /&gt;
&lt;br /&gt;
    return forTable&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Stringifies a table as formatted by forSeeArgsToTable&lt;br /&gt;
function p.forSeeTableToString (forSeeTable, options)&lt;br /&gt;
    -- Type-checks and defaults&lt;br /&gt;
    checkType(&amp;quot;forSeeTableToString&amp;quot;, 1, forSeeTable, &amp;quot;table&amp;quot;, true)&lt;br /&gt;
    checkType(&amp;quot;forSeeTableToString&amp;quot;, 2, options, &amp;quot;table&amp;quot;, true)&lt;br /&gt;
    options = options or {}&lt;br /&gt;
    for k, v in pairs(forSeeDefaultOptions) do&lt;br /&gt;
        if options[k] == nil then options[k] = v end&lt;br /&gt;
    end&lt;br /&gt;
    -- Stringify each for-see item into a list&lt;br /&gt;
    local strList = {}&lt;br /&gt;
    if forSeeTable then&lt;br /&gt;
        for k, v in pairs(forSeeTable) do&lt;br /&gt;
            local useStr = v.use or options.otherText&lt;br /&gt;
            local pagesStr =&lt;br /&gt;
            p.andList(v.pages, true) or&lt;br /&gt;
                    mFormatLink._formatLink{&lt;br /&gt;
                        categorizeMissing = mHatnote.missingTargetCat,&lt;br /&gt;
                        link = mHatnote.disambiguate(options.title)&lt;br /&gt;
                    }&lt;br /&gt;
            local forSeeStr = string.format(options.forSeeForm, useStr, pagesStr)&lt;br /&gt;
            forSeeStr = punctuationCollapse(forSeeStr)&lt;br /&gt;
            table.insert(strList, forSeeStr)&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    if options.extratext then table.insert(strList, punctuationCollapse(options.extratext..&#039;.&#039;)) end&lt;br /&gt;
    -- Return the concatenated list&lt;br /&gt;
    return table.concat(strList, &#039; &#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Produces a &amp;quot;For X, see [[Y]]&amp;quot; string from arguments. Expects index gaps&lt;br /&gt;
-- but not blank/whitespace values. Ignores named args and args &amp;lt; &amp;quot;from&amp;quot;.&lt;br /&gt;
function p._forSee (args, from, options)&lt;br /&gt;
    local forSeeTable = p.forSeeArgsToTable(args, from, options)&lt;br /&gt;
    return p.forSeeTableToString(forSeeTable, options)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- As _forSee, but uses the frame.&lt;br /&gt;
function p.forSee (frame, from, options)&lt;br /&gt;
    mArguments = require(&#039;Module:Arguments&#039;)&lt;br /&gt;
    return p._forSee(mArguments.getArgs(frame), from, options)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=Module:Hatnote&amp;diff=32</id>
		<title>Module:Hatnote</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=Module:Hatnote&amp;diff=32"/>
		<updated>2025-09-21T15:10:39Z</updated>

		<summary type="html">&lt;p&gt;Erina: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;--------------------------------------------------------------------------------&lt;br /&gt;
--                              Module:Hatnote                                --&lt;br /&gt;
--                                                                            --&lt;br /&gt;
-- This module produces hatnote links and links to related articles. It       --&lt;br /&gt;
-- implements the {{hatnote}} and {{format link}} meta-templates and includes --&lt;br /&gt;
-- helper functions for other Lua hatnote modules.                            --&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local libraryUtil = require(&#039;libraryUtil&#039;)&lt;br /&gt;
local checkType = libraryUtil.checkType&lt;br /&gt;
local mArguments -- lazily initialise [[Module:Arguments]]&lt;br /&gt;
local yesno -- lazily initialise [[Module:Yesno]]&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Helper functions&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local function getArgs(frame)&lt;br /&gt;
    -- Fetches the arguments from the parent frame. Whitespace is trimmed and&lt;br /&gt;
    -- blanks are removed.&lt;br /&gt;
    mArguments = require(&#039;Module:Arguments&#039;)&lt;br /&gt;
    return mArguments.getArgs(frame, {parentOnly = true})&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function removeInitialColon(s)&lt;br /&gt;
    -- Removes the initial colon from a string, if present.&lt;br /&gt;
    return s:match(&#039;^:?(.*)&#039;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.defaultClasses(inline)&lt;br /&gt;
    -- Provides the default hatnote classes as a space-separated string; useful&lt;br /&gt;
    -- for hatnote-manipulation modules like [[Module:Hatnote group]].&lt;br /&gt;
    return&lt;br /&gt;
    (inline == 1 and &#039;hatnote-inline&#039; or &#039;hatnote&#039;) .. &#039; &#039; ..&lt;br /&gt;
            &#039;navigation-not-searchable&#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.disambiguate(page, disambiguator)&lt;br /&gt;
    -- Formats a page title with a disambiguation parenthetical,&lt;br /&gt;
    -- i.e. &amp;quot;Example&amp;quot; → &amp;quot;Example (disambiguation)&amp;quot;.&lt;br /&gt;
    checkType(&#039;disambiguate&#039;, 1, page, &#039;string&#039;)&lt;br /&gt;
    checkType(&#039;disambiguate&#039;, 2, disambiguator, &#039;string&#039;, true)&lt;br /&gt;
    disambiguator = disambiguator or &#039;disambiguation&#039;&lt;br /&gt;
    return string.format(&#039;%s (%s)&#039;, page, disambiguator)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.findNamespaceId(link, removeColon)&lt;br /&gt;
    -- Finds the namespace id (namespace number) of a link or a pagename. This&lt;br /&gt;
    -- function will not work if the link is enclosed in double brackets. Colons&lt;br /&gt;
    -- are trimmed from the start of the link by default. To skip colon&lt;br /&gt;
    -- trimming, set the removeColon parameter to false.&lt;br /&gt;
    checkType(&#039;findNamespaceId&#039;, 1, link, &#039;string&#039;)&lt;br /&gt;
    checkType(&#039;findNamespaceId&#039;, 2, removeColon, &#039;boolean&#039;, true)&lt;br /&gt;
    if removeColon ~= false then&lt;br /&gt;
        link = removeInitialColon(link)&lt;br /&gt;
    end&lt;br /&gt;
    local namespace = link:match(&#039;^(.-):&#039;)&lt;br /&gt;
    if namespace then&lt;br /&gt;
        local nsTable = mw.site.namespaces[namespace]&lt;br /&gt;
        if nsTable then&lt;br /&gt;
            return nsTable.id&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return 0&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.makeWikitextError(msg, helpLink, addTrackingCategory, title)&lt;br /&gt;
    -- Formats an error message to be returned to wikitext. If&lt;br /&gt;
    -- addTrackingCategory is not false after being returned from&lt;br /&gt;
    -- [[Module:Yesno]], and if we are not on a talk page, a tracking category&lt;br /&gt;
    -- is added.&lt;br /&gt;
    checkType(&#039;makeWikitextError&#039;, 1, msg, &#039;string&#039;)&lt;br /&gt;
    checkType(&#039;makeWikitextError&#039;, 2, helpLink, &#039;string&#039;, true)&lt;br /&gt;
    yesno = require(&#039;Module:Yesno&#039;)&lt;br /&gt;
    title = title or mw.title.getCurrentTitle()&lt;br /&gt;
    -- Make the help link text.&lt;br /&gt;
    local helpText&lt;br /&gt;
    if helpLink then&lt;br /&gt;
        helpText = &#039; ([[&#039; .. helpLink .. &#039;|help]])&#039;&lt;br /&gt;
    else&lt;br /&gt;
        helpText = &#039;&#039;&lt;br /&gt;
    end&lt;br /&gt;
    -- Make the category text.&lt;br /&gt;
    local category&lt;br /&gt;
    if not title.isTalkPage -- Don&#039;t categorise talk pages&lt;br /&gt;
            and title.namespace ~= 2 -- Don&#039;t categorise userspace&lt;br /&gt;
            and yesno(addTrackingCategory) ~= false -- Allow opting out&lt;br /&gt;
    then&lt;br /&gt;
        category = &#039;Hatnote templates with errors&#039;&lt;br /&gt;
        category = string.format(&lt;br /&gt;
                &#039;[[%s:%s]]&#039;,&lt;br /&gt;
                mw.site.namespaces[14].name,&lt;br /&gt;
                category&lt;br /&gt;
        )&lt;br /&gt;
    else&lt;br /&gt;
        category = &#039;&#039;&lt;br /&gt;
    end&lt;br /&gt;
    return string.format(&lt;br /&gt;
            &#039;&amp;lt;strong class=&amp;quot;error&amp;quot;&amp;gt;Error: %s%s.&amp;lt;/strong&amp;gt;%s&#039;,&lt;br /&gt;
            msg,&lt;br /&gt;
            helpText,&lt;br /&gt;
            category&lt;br /&gt;
    )&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local curNs = mw.title.getCurrentTitle().namespace&lt;br /&gt;
p.missingTargetCat =&lt;br /&gt;
--Default missing target category, exported for use in related modules&lt;br /&gt;
((curNs ==  0) or (curNs == 14)) and&lt;br /&gt;
        &#039;Articles with hatnote templates targeting a nonexistent page&#039; or nil&lt;br /&gt;
&lt;br /&gt;
function p.quote(title)&lt;br /&gt;
    --Wraps titles in quotation marks. If the title starts/ends with a quotation&lt;br /&gt;
    --mark, kerns that side as with {{-&#039;}}&lt;br /&gt;
    local quotationMarks = {&lt;br /&gt;
        [&amp;quot;&#039;&amp;quot;]=true, [&#039;&amp;quot;&#039;]=true, [&#039;“&#039;]=true, [&amp;quot;‘&amp;quot;]=true, [&#039;”&#039;]=true, [&amp;quot;’&amp;quot;]=true&lt;br /&gt;
    }&lt;br /&gt;
    local quoteLeft, quoteRight = -- Test if start/end are quotation marks&lt;br /&gt;
    quotationMarks[string.sub(title,  1,  1)],&lt;br /&gt;
    quotationMarks[string.sub(title, -1, -1)]&lt;br /&gt;
    if quoteLeft or quoteRight then&lt;br /&gt;
        title = mw.html.create(&amp;quot;span&amp;quot;):wikitext(title)&lt;br /&gt;
    end&lt;br /&gt;
    if quoteLeft  then title:css(&amp;quot;padding-left&amp;quot;,  &amp;quot;0.15em&amp;quot;) end&lt;br /&gt;
    if quoteRight then title:css(&amp;quot;padding-right&amp;quot;, &amp;quot;0.15em&amp;quot;) end&lt;br /&gt;
    return &#039;&amp;quot;&#039; .. tostring(title) .. &#039;&amp;quot;&#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Hatnote&lt;br /&gt;
--&lt;br /&gt;
-- Produces standard hatnote text. Implements the {{hatnote}} template.&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local function decorateHatnote(hatnote, options)&lt;br /&gt;
    local function getIcon(filename)&lt;br /&gt;
        local html = &#039;&#039;&lt;br /&gt;
        if type(filename) == &#039;string&#039; then&lt;br /&gt;
            local icon = mw.html.create(&#039;span&#039;)&lt;br /&gt;
            icon&lt;br /&gt;
                    :addClass(&#039;hatnote-icon&#039;)&lt;br /&gt;
                    :addClass(&#039;metadata&#039;)&lt;br /&gt;
                    :wikitext(&#039;[[File:&#039; .. filename .. &#039;|14px|link=]]&#039;)&lt;br /&gt;
                    :done()&lt;br /&gt;
            html = tostring(icon)&lt;br /&gt;
        end&lt;br /&gt;
        return html&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    local container = mw.html.create(&#039;div&#039;)&lt;br /&gt;
    container&lt;br /&gt;
            :addClass(&#039;hatnote-container&#039;)&lt;br /&gt;
            :wikitext(getIcon(options.icon))&lt;br /&gt;
            :wikitext(tostring(hatnote))&lt;br /&gt;
            :done()&lt;br /&gt;
    return container&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.hatnote(frame)&lt;br /&gt;
    local args = getArgs(frame)&lt;br /&gt;
    local s = args[1]&lt;br /&gt;
    if not s then&lt;br /&gt;
        return p.makeWikitextError(&lt;br /&gt;
                &#039;no text specified&#039;,&lt;br /&gt;
                &#039;Template:Hatnote#Errors&#039;,&lt;br /&gt;
                args.category&lt;br /&gt;
        )&lt;br /&gt;
    end&lt;br /&gt;
    return p._hatnote(s, {&lt;br /&gt;
        extraclasses = args.extraclasses,&lt;br /&gt;
        selfref = args.selfref&lt;br /&gt;
    })&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p._hatnote(s, options)&lt;br /&gt;
    checkType(&#039;_hatnote&#039;, 1, s, &#039;string&#039;)&lt;br /&gt;
    checkType(&#039;_hatnote&#039;, 2, options, &#039;table&#039;, true)&lt;br /&gt;
    options = options or {}&lt;br /&gt;
    local inline = options.inline&lt;br /&gt;
    local hatnote = mw.html.create(inline == 1 and &#039;span&#039; or &#039;div&#039;)&lt;br /&gt;
    local extraclasses&lt;br /&gt;
    if type(options.extraclasses) == &#039;string&#039; then&lt;br /&gt;
        extraclasses = options.extraclasses&lt;br /&gt;
    end&lt;br /&gt;
&lt;br /&gt;
    hatnote&lt;br /&gt;
            :attr(&#039;role&#039;, &#039;note&#039;)&lt;br /&gt;
            :addClass(p.defaultClasses(inline))&lt;br /&gt;
            :addClass(extraclasses)&lt;br /&gt;
            :addClass(options.selfref and &#039;selfref&#039; or nil)&lt;br /&gt;
            :wikitext(s)&lt;br /&gt;
&lt;br /&gt;
    -- Decorate WP hatnote to SCW standard&lt;br /&gt;
    hatnote = decorateHatnote(hatnote, options)&lt;br /&gt;
&lt;br /&gt;
    return mw.getCurrentFrame():extensionTag{&lt;br /&gt;
        name = &#039;templatestyles&#039;, args = { src = &#039;Module:Hatnote/styles.css&#039; }&lt;br /&gt;
    } .. tostring(hatnote)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=Template:Stub&amp;diff=30</id>
		<title>Template:Stub</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=Template:Stub&amp;diff=30"/>
		<updated>2025-09-21T15:10:39Z</updated>

		<summary type="html">&lt;p&gt;Erina: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&amp;quot;mbox mbox-med mbox-stub&amp;quot; role=&amp;quot;presentation&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;mbox-title&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;mbox-icon metadata&amp;quot;&amp;gt;[[File:WikimediaUI-Notice.svg|14px|link=]]&amp;lt;/span&amp;gt;This article is a stub.&amp;lt;/span&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;mbox-text&amp;quot;&amp;gt;This article needs some ❤️! You can help the Star Citizen Wiki by  &amp;lt;span class=&amp;quot;plainlinks&amp;quot;&amp;gt;[{{fullurl:{{FULLPAGENAME}}|action=edit}} expanding it]&amp;lt;/span&amp;gt;. See [[:Category:Article stubs]] for other pages that needs expansion.&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;templatestyles src=&amp;quot;Module:Mbox/styles.css&amp;quot; /&amp;gt;&amp;lt;includeonly&amp;gt;[[Category:Article stubs]]&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{/doc}}&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=File:Noa_Prime.png&amp;diff=28</id>
		<title>File:Noa Prime.png</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=File:Noa_Prime.png&amp;diff=28"/>
		<updated>2025-09-21T14:09:22Z</updated>

		<summary type="html">&lt;p&gt;Erina: Illustrated by https://twitter.com/kan_mirai&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Summary ==&lt;br /&gt;
Illustrated by https://twitter.com/kan_mirai&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=Template:Template_other&amp;diff=27</id>
		<title>Template:Template other</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=Template:Template_other&amp;diff=27"/>
		<updated>2025-09-21T13:23:15Z</updated>

		<summary type="html">&lt;p&gt;Erina: Created page with &amp;quot;{{#switch:   &amp;lt;!--If no or empty &amp;quot;demospace&amp;quot; parameter then detect namespace--&amp;gt;   {{#if:{{{demospace|}}}   | {{lc: {{{demospace}}} }}    &amp;lt;!--Use lower case &amp;quot;demospace&amp;quot;--&amp;gt;   | {{#ifeq:{{NAMESPACE}}|{{ns:Template}}     | template     | other     }}   }} | template = {{{1|}}} | other | #default = {{{2|}}} }}&amp;lt;!--End switch--&amp;gt;&amp;lt;noinclude&amp;gt;  {{documentation}} &amp;lt;!-- Add categories and interwikis to the /doc subpage, not here! --&amp;gt; &amp;lt;/noinclude&amp;gt;&amp;quot;&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>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=MediaWiki:Citizen-footer-desc&amp;diff=26</id>
		<title>MediaWiki:Citizen-footer-desc</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=MediaWiki:Citizen-footer-desc&amp;diff=26"/>
		<updated>2025-09-19T22:38:57Z</updated>

		<summary type="html">&lt;p&gt;Erina: Created page with &amp;quot;footer footer footer&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[MediaWiki:Citizen-footer-desc|footer footer footer]]&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=MediaWiki:Citizen-footer-tagline&amp;diff=25</id>
		<title>MediaWiki:Citizen-footer-tagline</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=MediaWiki:Citizen-footer-tagline&amp;diff=25"/>
		<updated>2025-09-19T22:38:35Z</updated>

		<summary type="html">&lt;p&gt;Erina: Created page with &amp;quot;tagline tagline tagline&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[MediaWiki:Citizen-footer-tagline|tagline tagline tagline]]&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=Main_Page&amp;diff=24</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=Main_Page&amp;diff=24"/>
		<updated>2025-09-19T22:26:53Z</updated>

		<summary type="html">&lt;p&gt;Erina: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[:Category:Noa|Noa is love, Noa is life]]&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=Template:REDACTED&amp;diff=23</id>
		<title>Template:REDACTED</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=Template:REDACTED&amp;diff=23"/>
		<updated>2025-09-19T20:28:22Z</updated>

		<summary type="html">&lt;p&gt;Erina: Created page with &amp;quot;&amp;lt;includeonly&amp;gt;{{#invoke:String|replace|source={{{1}}}|%S|█|plain=0}}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;12345 67890 -&amp;gt; {{REDACTED|12345 67890}}&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;{{#invoke:String|replace|source={{{1}}}|%S|█|plain=0}}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;12345 67890 -&amp;gt; {{REDACTED|12345 67890}}&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=Template:Infobox/styles.css&amp;diff=22</id>
		<title>Template:Infobox/styles.css</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=Template:Infobox/styles.css&amp;diff=22"/>
		<updated>2025-09-19T20:28:00Z</updated>

		<summary type="html">&lt;p&gt;Erina: Created page with &amp;quot;.infobox { 	display: table; 	border: 1px solid #a2a9b1; 	border-spacing: 3px; 	background-color: #f8f9fa; 	color: black; 	/* @noflip */ 	margin: 0.5em 0 0.5em 1em; 	padding: 0.2em; 	/* @noflip */ 	float: right; 	/* @noflip */ 	clear: right; 	font-size: 88%; 	line-height: 1.5em; }  .infobox caption { 	font-size: 125%; 	font-weight: bold; 	padding: 0.2em; 	text-align: center; }  .infobox td, .infobox th { 	vertical-align: top; 	/* @noflip */ 	text-align: left; }  .infobox...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;.infobox {&lt;br /&gt;
	display: table;&lt;br /&gt;
	border: 1px solid #a2a9b1;&lt;br /&gt;
	border-spacing: 3px;&lt;br /&gt;
	background-color: #f8f9fa;&lt;br /&gt;
	color: black;&lt;br /&gt;
	/* @noflip */&lt;br /&gt;
	margin: 0.5em 0 0.5em 1em;&lt;br /&gt;
	padding: 0.2em;&lt;br /&gt;
	/* @noflip */&lt;br /&gt;
	float: right;&lt;br /&gt;
	/* @noflip */&lt;br /&gt;
	clear: right;&lt;br /&gt;
	font-size: 88%;&lt;br /&gt;
	line-height: 1.5em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.infobox caption {&lt;br /&gt;
	font-size: 125%;&lt;br /&gt;
	font-weight: bold;&lt;br /&gt;
	padding: 0.2em;&lt;br /&gt;
	text-align: center;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.infobox td,&lt;br /&gt;
.infobox th {&lt;br /&gt;
	vertical-align: top;&lt;br /&gt;
	/* @noflip */&lt;br /&gt;
	text-align: left;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.infobox .infobox-above {&lt;br /&gt;
	text-align: center;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.infobox.bordered {&lt;br /&gt;
	border-collapse: collapse;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.infobox.bordered td,&lt;br /&gt;
.infobox.bordered th {&lt;br /&gt;
	border: 1px solid #a2a9b1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.infobox.bordered .borderless td,&lt;br /&gt;
.infobox.bordered .borderless th {&lt;br /&gt;
	border: 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.infobox.sisterproject {&lt;br /&gt;
	width: 20em;&lt;br /&gt;
	font-size: 90%;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.infobox.standard-talk {&lt;br /&gt;
	border: 1px solid #c0c090;&lt;br /&gt;
	background-color: #f8eaba;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.infobox.standard-talk.bordered td,&lt;br /&gt;
.infobox.standard-talk.bordered th {&lt;br /&gt;
	border: 1px solid #c0c090;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* styles for bordered infobox with merged rows */&lt;br /&gt;
.infobox.bordered .mergedtoprow td,&lt;br /&gt;
.infobox.bordered .mergedtoprow th {&lt;br /&gt;
	border: 0;&lt;br /&gt;
	border-top: 1px solid #a2a9b1;&lt;br /&gt;
	/* @noflip */&lt;br /&gt;
	border-right: 1px solid #a2a9b1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.infobox.bordered .mergedrow td,&lt;br /&gt;
.infobox.bordered .mergedrow th {&lt;br /&gt;
	border: 0;&lt;br /&gt;
	/* @noflip */&lt;br /&gt;
	border-right: 1px solid #a2a9b1;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.infobox .infobox-header,&lt;br /&gt;
.infobox .infobox-subheader {&lt;br /&gt;
	color: unset;&lt;br /&gt;
	background-color: #00aaff50;&lt;br /&gt;
	text-align: center;&lt;br /&gt;
	padding: 0 0.75em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.infobox .infobox-header {&lt;br /&gt;
	font-size: 1.15em;&lt;br /&gt;
	line-height: 1.5em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.infobox .infobox-image {&lt;br /&gt;
	text-align: center;&lt;br /&gt;
	padding: 0em 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.infobox .spacer-cell {&lt;br /&gt;
	width: calc(100% / 30);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.infobox .navbar {&lt;br /&gt;
	display: block;&lt;br /&gt;
	text-align: center;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.infobox .tabber {&lt;br /&gt;
	margin-top: -1em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.infobox .tabber__header {&lt;br /&gt;
	margin-bottom: 1em;&lt;br /&gt;
	justify-content: center;&lt;br /&gt;
	box-shadow: none;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.infobox td ul {&lt;br /&gt;
	margin-left: 0.8rem;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Different screen sizes&lt;br /&gt;
 */&lt;br /&gt;
@media only screen and (max-width: 576px) {&lt;br /&gt;
	.infobox {&lt;br /&gt;
		float: none;&lt;br /&gt;
		margin-left: auto;&lt;br /&gt;
		margin-right: auto;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Vector skin&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Citizen skin&lt;br /&gt;
 */&lt;br /&gt;
body.skin-citizen .infobox {&lt;br /&gt;
	border-color: var(--border-color-base);&lt;br /&gt;
	background-color: var(--background-color-framed);&lt;br /&gt;
	border-radius: var(--border-radius--small);&lt;br /&gt;
	color: inherit;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=Template:Infobox&amp;diff=21</id>
		<title>Template:Infobox</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=Template:Infobox&amp;diff=21"/>
		<updated>2025-09-19T20:27:46Z</updated>

		<summary type="html">&lt;p&gt;Erina: Created page with &amp;quot;&amp;lt;templatestyles src=&amp;quot;Infobox/styles.css&amp;quot;/&amp;gt; {{#invoke:Infobox|infobox}}&amp;lt;includeonly&amp;gt;{{template other|{{#ifeq:{{PAGENAME}}|Infobox||{{#ifeq:{{str left|{{SUBPAGENAME}}|7}}|Infobox|{{SUBPAGENAME}}}}}}}}|}}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt; &amp;lt;!-- Categories go in the /doc subpage, and interwikis go in Wikidata. --&amp;gt; &amp;lt;/noinclude&amp;gt;&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;templatestyles src=&amp;quot;Infobox/styles.css&amp;quot;/&amp;gt;&lt;br /&gt;
{{#invoke:Infobox|infobox}}&amp;lt;includeonly&amp;gt;{{template other|{{#ifeq:{{PAGENAME}}|Infobox||{{#ifeq:{{str left|{{SUBPAGENAME}}|7}}|Infobox|[[Category:Infobox templates|{{remove first word|{{SUBPAGENAME}}}}]]}}}}|}}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
&amp;lt;!-- Categories go in the /doc subpage, and interwikis go in Wikidata. --&amp;gt;&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
	<entry>
		<id>https://noaverse.erina.moe/index.php?title=Category:Noa&amp;diff=20</id>
		<title>Category:Noa</title>
		<link rel="alternate" type="text/html" href="https://noaverse.erina.moe/index.php?title=Category:Noa&amp;diff=20"/>
		<updated>2025-09-19T14:56:55Z</updated>

		<summary type="html">&lt;p&gt;Erina: Created page with &amp;quot;All of the Noas.&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;All of the Noas.&lt;/div&gt;</summary>
		<author><name>Erina</name></author>
	</entry>
</feed>