<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.852r.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Jasper</id>
	<title>Hongkongggag Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.852r.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Jasper"/>
	<link rel="alternate" type="text/html" href="https://wiki.852r.org/index.php/Special:Contributions/Jasper"/>
	<updated>2026-08-06T21:00:38Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.42.1</generator>
	<entry>
		<id>https://wiki.852r.org/index.php?title=History_of_Hongkongggag&amp;diff=3925</id>
		<title>History of Hongkongggag</title>
		<link rel="alternate" type="text/html" href="https://wiki.852r.org/index.php?title=History_of_Hongkongggag&amp;diff=3925"/>
		<updated>2026-08-06T10:47:22Z</updated>

		<summary type="html">&lt;p&gt;Jasper: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Very long}}&lt;br /&gt;
This is the history of [[Hongkongggag]] from its creation in 2018 to the present day. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Please note that this is a work in progress at all times.&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Pre-Community Era (July 2018-June 2019)==&lt;br /&gt;
For a long time, [[Card0]] had been disappointed at how few Hong Kong meme pages there were, many of them had resulted to simply posting advertisments instead of actually posting memes.  &lt;br /&gt;
&lt;br /&gt;
Sometime during July 2018, [[Card0]] posted an Instagram poll on his personal account out of boredom, asking friends whether he should make a Hong Kong-themed meme page out of boredom. After significant support, he made the page &amp;quot;hongkonggag&amp;quot; (with 2 gs) on July 18th, 2018, however he would only post funny images of Hong Kong, rather than actual memes. Though from September onwards, he began posting actual memes wich started garnering a small following. During this period, hongkonggag received advocacy from other content creators, most notably [[memes.hk]]. They gave hongkonggag several shoutouts, each boosting the page by 50 to 100 followers. In early 2019, the page hit the 1000 follower milestone. &lt;br /&gt;
&lt;br /&gt;
At some point, [[flutters]], a follower of the page for some time, was promoted to Admin after asking Card0.&lt;br /&gt;
&lt;br /&gt;
==Resurgence Era (June 2019-March 2021)==&lt;br /&gt;
This Resurgence Era was immediately marked by both rapid growth and deep internal crises. This is also when the page&#039;s identity was really forged, with the Satirical Maps series starting in August 2020, offset by a decline in morale, follower counts, and staff retention, leading to a leadership crisis that forced Card0 to democratize some of his authority through the March 2021 Reforms and the establishment of the rank of Founder.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Staff during this period:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Admins: Card0, Salmon, Flutters, Drea, Nissay, Deni, Vista&lt;br /&gt;
&lt;br /&gt;
Moderators: Tolmo, Anidiot, aaronforce1, Sayonara, Cassandra&lt;br /&gt;
&lt;br /&gt;
Resignations: Nissay (June 2020), Cassandra (September 2020), Tolmo (December 2020), Deni (February 2021), Vista (March 2023)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Notable members who joined during this era:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [[Salmon]]&lt;br /&gt;
* [[Drea]]&lt;br /&gt;
* [[Nissay]]&lt;br /&gt;
* [[Deni]]&lt;br /&gt;
* [[Vista]]&lt;br /&gt;
* [[Crosby]]&lt;br /&gt;
* [[HikikomoriGod]]&lt;br /&gt;
* [[Christie]]&lt;br /&gt;
* [[Tolmo]]&lt;br /&gt;
* [[Anidiot]]&lt;br /&gt;
* [[KarpiG]]&lt;br /&gt;
* [[aaronforce1]]&lt;br /&gt;
* [[Blep]]&lt;br /&gt;
* [[Ky3653]]&lt;br /&gt;
* [[Vartesh]]&lt;br /&gt;
* [[Aditya]]&lt;br /&gt;
* [[Meltham]]&lt;br /&gt;
* [[Chief Kweef]]&lt;br /&gt;
* [[herro]]&lt;br /&gt;
* [[Cassandra]]&lt;br /&gt;
* [[HeyGuysItzSatan]]&lt;br /&gt;
* [[James Collins]]&lt;br /&gt;
* [[DepressedSteggy]]&lt;br /&gt;
* [[Kap26]]&lt;br /&gt;
* [[Lemontea]]&lt;br /&gt;
* [[Livie]]&lt;br /&gt;
* [[DarthMew]]&lt;br /&gt;
* [[king ronak]]&lt;br /&gt;
* [[NICORE]] (Discord only)&lt;br /&gt;
* [[Hill]] (Discord only)&lt;br /&gt;
* [[Jamiewg19]]&lt;br /&gt;
* [[Sayonara]]&lt;br /&gt;
* [[Cobbz289]]&lt;br /&gt;
* [[Celia]]&lt;br /&gt;
* [[Boba]]&lt;br /&gt;
* [[Wsdu]]&lt;br /&gt;
* [[Salami]]&lt;br /&gt;
* [[Andy 1987]]&lt;br /&gt;
* [[Darren]]&lt;br /&gt;
* [[Lieutenant Quattro]]&lt;br /&gt;
* [[AquaEclipse324]] (Discord Only)&lt;br /&gt;
&lt;br /&gt;
=== The Beginnings of [[The Resurgence]]===&lt;br /&gt;
Card0 and flutters feared that the extradition law would put the page in danger. As a result, procedures were enacted to delete the Instagram page and move the follower base underground into a WhatsApp group chat.  &lt;br /&gt;
&lt;br /&gt;
Initially named Hongkongggag Resurgence, the group chat was created on June 11, 2019. Members who joined on the first day include [[Crosby]], [[Drea]], [[HikikomoriGod]], [[Salmon]] and [[Vista]]. During this time, 30 to 40 people had joined the group chat, with most joining on the first few days. There was a lot of concern for the future of Hong Kong during this time, as there were rumours spreading around on what the government would do, and whether the PLA would intervene in Hong Kong with a real fear that there would be a Tiananmen-style crackdown in the city. [[Christie]] was also promoted in this period after asking Card0. However, she and flutters had constant disagreements which led Card0 to have to mediate frequently.&lt;br /&gt;
&lt;br /&gt;
=== Impact of the Protests ===&lt;br /&gt;
The 2019-20 protests had a profound impact on the community and page, especially during the Summer. Activity in the group chat was strong, with most discussion topics being related to the [https://en.wikipedia.org/wiki/2019%E2%80%932020_Hong_Kong_protests 2019 Hong Kong Protests]. After the [https://en.wikipedia.org/wiki/2019_Yuen_Long_attack 721 incident], many members also provided news and updates for [[Card0]] to post on hongkonggag, as the page began posting news. Some people would also ask Card0 if they could be Admin, however Card0 declined their offers, mostly due to the fact that he didn&#039;t think they were capable enough. Naturally, the community was very pan-democracy and were full of yellow ribbons (pan-democracy supporters). Due to the emphasis of unity throughout the movement as well as the size of The Resurgence, there was little drama in the early stages of the community. However, later on there were also questions over the future of the movement, as well as the issue of pro-trump localists.&lt;br /&gt;
&lt;br /&gt;
===Christie Incident===&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&#039;&#039;Main Article: [[Christie Incident]]&#039;&#039;&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On the night of September 14, 2019, Christie revealed that she was a blue ribbon and took over the page. Despite constant demands to confess her actions and give back the page, she refused. Some members such as [[Vista]] tried to help Card0, with some reporting the page in the process.  In the aftermath, hongkonggag was taken down and deleted from Instagram the following afternoon, forcing Card0 to restart over. Card0 was stressed by the incident and took it seriously. &lt;br /&gt;
&lt;br /&gt;
===Hongkonggag to Hongkongggag===&lt;br /&gt;
After the Christie incident, [[Card0]] attempted to rebuild the page despite his reluctance. One of the first decisions he made during this era was promoting [[Salmon]] to Admin for assistance in reconstruction. The page was then renamed to &amp;quot;hongkonggagrebirth&amp;quot;, which was later changed to [[Hongkongggag|&amp;quot;hongkongggag&amp;quot;]].&lt;br /&gt;
&lt;br /&gt;
In Early October, [[Deni]], [[Drea]], [[Nissay]] and [[Vista]] were promoted to Admin in an impromptu administrative action when Card0 noticed that the protests were about to escalate to a new level. Throughout this time, Deni Justin and Vista were the admins aside from Card0 making the news updates on the page&#039;s story. As the protests continued, some feared for Card0&#039;s safety, and even he himself was scared that he would get arrested. Nevertheless, no harm came to him personally although according to him, at least one member of the group chat was detained during the protests.  &lt;br /&gt;
&lt;br /&gt;
The community remained primarily protest-focused, though non-political topics were a regular occurence, this lasted until the outbreak of the Covid-19 pandemic.  &lt;br /&gt;
&lt;br /&gt;
===Early Community Issues ===&lt;br /&gt;
Around Early January, multiple members of The Resurgence, including [[Salmon]], got heavily engaged in an argument over Kobe Bryant&#039;s death as well as his past as a supposed rapist. As such, the admins talked to every member involved to get a clearer idea of the situation. Punishments were issued as a result in order to warn people not to engage in this type of behavior. This was one of, if not the first major argument in the community. &lt;br /&gt;
&lt;br /&gt;
=== Impact of the Covid-19 Pandemic ===&lt;br /&gt;
With the Covid-19 Pandemic beginning, Card0 decided to start doing Covid-19 updates about Hong Kong on his Instagram story on Hongkongggag. This also led to increased activity in the group chat.&lt;br /&gt;
&lt;br /&gt;
===U13 Crisis===&lt;br /&gt;
From January to February of 2020, two members: [[DepressedSteggy]] and [[Pumpkin]] misbehaved, often getting into trouble with the Staff Team. As they were under 13 years old (U13), many members were concerned whether [[The Resurgence]] was appropriate for them. Calls for a solution were heard, leading to the creation of a chat for U13 members. However, this chat disbanded a couple of months after its inception due to low activity. &lt;br /&gt;
&lt;br /&gt;
===[[Kaden Crisis]]===&lt;br /&gt;
In February of 2020, [[Ky3653]], who had a history of inappropriate behaviour and punishments, was banned by the Admins after several unsuccessful attempts at reasoning with him. Ky3653, also known as Kaden, was restricted from participating in The Resurgence, although he was allowed to follow the Instagram page and interact with Admins.&lt;br /&gt;
&lt;br /&gt;
Kaden remained as a conversation topic for several months, drawing criticism from some. &lt;br /&gt;
===[[May 2020 Porn Incursion|Varteshian Incursion]]===&lt;br /&gt;
Between April and May of 2020, a member known as [[Vartesh]] joined, getting along with most people at first. Vartesh invited his friends to join a trivia session one night who behaved badly, Staff were concerned but did not take further action.&lt;br /&gt;
&lt;br /&gt;
A couple of minutes into trivia, Vartesh&#039;s friends began spamming explicit stickers repeatedly, leading [[Card0]], [[Vista]] and [[Justin]] to shut the chat down multiple times. They were soon banned with Vartesh denying any involvement. &lt;br /&gt;
&lt;br /&gt;
This led to the creation of Moderators, then called Chat Mods. [[Tolmo]], [[Aaronforce1]] and [[Anidiot]] were promoted to this position soon after.&lt;br /&gt;
&lt;br /&gt;
=== Head Admin Demotion ===&lt;br /&gt;
In early June, due to posting a controversial opinion on &#039;&#039;Black Lives Matter&#039;&#039;, [[Card0]] received criticism and requests for him to step down from the Head Admin position, effectively making his permissions equal as other Admins. Following a vote in [[Resurgence Elite]], the Head Admin role was scrapped. Despite this, Card0&#039;s activity implied very little change in his actual permissions.&lt;br /&gt;
&lt;br /&gt;
===Impact of the National Security Law===&lt;br /&gt;
The National Security Law came into effect in Hong Kong on July 1, 2020. Fearing for a worst-case scenario, Hongkongggag staff privated the page and all associated platforms on July 4, 2020. There were emergency plans to take down the page if need be, with [[Vista]] urging that the community migrate to Signal as soon as possible. However, the page was never taken down and a Signal group chat was created much later.  &lt;br /&gt;
=== Start of [[Satirical Maps]]===&lt;br /&gt;
On August 26, 2020, [[Card0]] began the First Season of Satirical Maps, starting with Wan Chai and ending with Sha Tau Kok, on August 31, 2020. [[[https://www.instagram.com/p/CEWlVraJ52F/ |A satirical map of Wan Chai District ]]][[[https://www.instagram.com/p/CEjSXmcJb37/ | The final map! Sha Tau Kok. Thanks for all the support!]]] Satirical Maps was well-received and helped boost the page.&lt;br /&gt;
&lt;br /&gt;
At the time, Card0 had no plans for a second season.&lt;br /&gt;
&lt;br /&gt;
=== September Religious Debates ===&lt;br /&gt;
On September 26, 2020, a heated debate between [[Salmon]], [[Tolmo]] and [[anidiot]] occurred. This led all three staff members to be put on probation albeit for a short period of time. &lt;br /&gt;
&lt;br /&gt;
After the debate, [[Cassandra]] resigned, leaving the group without explanation and returned a few weeks later. It is not known whether this was a direct result of the religious discussion that occurred at the time. &lt;br /&gt;
&lt;br /&gt;
[[Vista]] also announced a break, calling the group an echo chamber and criticizing the community&#039;s lack security.  &lt;br /&gt;
===Gradual Reopening===&lt;br /&gt;
Around late September of 2020, [[Card0]] decided that it was adequate to reopen the page to the public. However, [[The Resurgence]] remained a private communications group chat.&lt;br /&gt;
&lt;br /&gt;
=== Great Decline ===&lt;br /&gt;
From September 2020 to January 2021, the page experienced a massive decline, as well as drama in the community.&lt;br /&gt;
&lt;br /&gt;
===December 2020 Controversies ===&lt;br /&gt;
Controversies and questions about the administrative process of [[The Resurgence]] were often raised by [[Aditya]] and [[Tolmo]], leading to conflict between them and [[Card0]]. The tense situation led [[Cassandra]] to resign for a second time.&lt;br /&gt;
&lt;br /&gt;
On December 27, 2020, Tolmo voluntarily resigned from his position as Chat Mod due to a joke made in poor taste, fulfilling a pact he made prior to resign if he made a severe mistake.&lt;br /&gt;
&lt;br /&gt;
Follower growth dropped also during this period, often going into the negatives. Card0 has often claimed this month as the worst month to be in this community. Yet at the same time, the discord server began to grow slightly, with signs that it would overtake the WhatsApp GC as the main community platform going forward.  &lt;br /&gt;
&lt;br /&gt;
===Satirical Maps Season 3 ===&lt;br /&gt;
On January 8, 2021, [[Card0]] started Satirical Maps Season 3 in an attempt to boost the page.&amp;lt;ref&amp;gt;[https://www.instagram.com/p/CJwvR3iswSU/ hongkongggag: Satirical Maps Season 3 premieres today! Let me know what areas you want me to make satirical maps of!]&amp;lt;/ref&amp;gt; While not as successful as Season 2, it oversaw immense follower growth, By the end of the season, hongkongggag had amassed over 9000 followers, largely coming from satirical maps.&lt;br /&gt;
&lt;br /&gt;
Satirical Maps Season 3 ended on February 8, 2021. &amp;lt;ref&amp;gt;[https://www.instagram.com/p/CK_fMPCpnqr/ hongkongggag: Satirical Maps Season 3 Finale Part 3! Thank you for supporting the series. Season 4 will come in June-July but look out for some stand alone maps to be posted]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Partnership with WaterOmelette===&lt;br /&gt;
In February 2021, [[852 Resurgence]] became partnered with the [[Wateromelette Discord server|wateromelette Discord Server]].  As a result, members from WaterOmelette&#039;s server, such as [[Bossuuu]], [[Hill]] and [[ImMcNutty]], joined 852 Resurgence. When wateromelette became inactive, her server&#039;s members started settling in 852 Resurgence, increasing their participation and activity in the server. This was the first server partnership in the community&#039;s history, laying the benchmark for future partnerships.&lt;br /&gt;
&lt;br /&gt;
=== Discord Reforms ===&lt;br /&gt;
In face of 852 Resurgence&#039;s increasing interest, a rank revamp was implemented on the server. Ranks were renamed to Citizen, Trustee, Councillor, Senator, Governor and Prestige.&amp;lt;ref name=&amp;quot;identifier&amp;quot;&amp;gt;&#039;&#039; Trustee, Councillor, Governor renamed to Attache, Dignitary and Vice in later months. Prepare new section for them&#039;&#039;&amp;lt;/ref&amp;gt; Some of these rank names were inspired by the [[MRT Server|MRT Server&#039;]]&amp;lt;nowiki/&amp;gt;s ranks, however as time went on some of their names would be changed. Trustee, Councillor and Governor were renamed to Attache, Dignitary and Vice respectively. Later on, roles for affiliates and ambassadors were introduced on the discord server.&lt;br /&gt;
===[[Vista]]&#039;s Resignation and the Election===&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&#039;&#039;See Also: [[March 2021 Moderator Elections]]&#039;&#039;&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
Since November 2020, three staff members had resigned: [[Cassandra]], [[Tolmo]] and [[Deni]] (who had left in February 2021). This inevitably had an effect on Card0 and the rest of Staff, as they became more pessimistic towards the community&#039;s future. However, Card0 didn&#039;t believe the situation was volatile for drastic action just yet, hence the lack of reforms for the community.   &lt;br /&gt;
&lt;br /&gt;
On March 9, 2021. [[Vista]] resigned. Vista reiterated many of the concerns he expressed in his statement from September and left the community soon after. Following this, The [[Resurgence Bot]] was taken down permanently. According to Card0,he was under the impression that Vista would return after his exams were over, and was very surprised by the announcement.  &lt;br /&gt;
&lt;br /&gt;
Due to a rapidly shrinking staff team, [[Card0]] called the [[March 2021 Moderator Elections]]. Running from March 20 to 21, 2021, polls were held on both Discord and Instagram. [[lemontea]] and [[zo.loft]] became Moderators afterwards. The other three candidates: [[Salami]], [[Lieutenant Quattro]] and [[Chief Kweef]] were not promoted though two of the members (Salami and Quattro), became Staff members later on. &lt;br /&gt;
&lt;br /&gt;
===[[March 2021 Incident]] and the [[March Reforms]]===&lt;br /&gt;
A week after resigning, Vista published a statement detailing the reason for his resignation and proposed changes for the community, as he believed there were significant shortcomings present at the time. This sparked a debate between [[Card0]], [[Aditya]] and [[Tolmo]] in the [[Core Community]]. Many members such as [[Boba]] and [[Salami]] tried to mediate the conversation. &lt;br /&gt;
&lt;br /&gt;
At some point, Card0 backed down shortly after Tolmo had taken a step back. Despite this, Aditya continued criticizing the community especially Card0&#039;s leadership,  even though other members tried to calm him down. This aroused concern, leading to a meeting on Discord that night, with 10 to 12 people attending. Meanwhile, Card0 talked with various members about the best way forward for the community itself. One of these members was KarpiG, who Card0 had a long conversation with on how the community should proceed.&lt;br /&gt;
&lt;br /&gt;
A document entailing modifications towards the community&#039;s leadership was drafted by [[Card0]] and [[KarpiG]]. including: &lt;br /&gt;
&lt;br /&gt;
* The establishment of [[Mediator|Mediators]], staff members that acted as a second opinion and opposing voice for the community, tasked with eliminating the presence of an echo chamber, and &lt;br /&gt;
* Substitution of &amp;quot;Head Admin&amp;quot; with the [[Founder]] role. This was meant to solidify Card0&#039;s position and to ensure transparency on the Staff team&#039;s structure.&lt;br /&gt;
&lt;br /&gt;
[[Wsdu]] and [[Boba]] were nominated by [[Darren]], becoming the first Mediators. Other issues such as the reform of Core Community were also discussed and approved. &lt;br /&gt;
&lt;br /&gt;
==Reform &amp;amp; Expansion Era (March 2021-May 2022)==&lt;br /&gt;
The Reform Era marked significant reforms in the community, not just the shift from WhatsApp to Discord but in the community&#039;s standards and purpose. The transition to Discord became complete, and new members flooded in. his era saw the implementation of new staff nomination systems and the first partnerships with other servers, bringing in influential new members. However, this expansion was continuously punctuated by incidents and drama.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Staff during this period:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Founder: Card0&lt;br /&gt;
&lt;br /&gt;
Admins: flutters, Salmon, Lemontea, Andi&lt;br /&gt;
&lt;br /&gt;
Moderators: Anidiot, aaronforce1, Sayonara, zo.loft, Bossuuu, Syntax, Lieutenant.Quattro, Sage&lt;br /&gt;
&lt;br /&gt;
Mediators: Boba, Wsdu, Salami&lt;br /&gt;
&lt;br /&gt;
Technicians; Sleepy, Tolmo&lt;br /&gt;
&lt;br /&gt;
Promotions: Zo.loft, Lemontea, Boba, Wsdu (March 2021), Salami (May 2021), Bossuuu (July 2021), Syntax (September 2021), Lieutenant Quattro, Andi (December 2021), Sleepy (January 2022), Tolmo (December 2021 as Moderator, January 2022 as Technician), Sage (February 2022)&lt;br /&gt;
&lt;br /&gt;
Resignations: Drea (July 2021), Anidiot (March 2022)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Notable members who joined during this era:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [[Bossuuu]]&lt;br /&gt;
* [[Andi]]&lt;br /&gt;
* [[Sleepy]]&lt;br /&gt;
* [[Greentea]]&lt;br /&gt;
* [[Syntax]]&lt;br /&gt;
* [[Soviзт Коммissaя]]&lt;br /&gt;
* [[Sage]]&lt;br /&gt;
* [[aman.kumar_s]] &lt;br /&gt;
* [[Joyce]]&lt;br /&gt;
* [[AvianStupid]]&lt;br /&gt;
* [[Sushi]]&lt;br /&gt;
* [[Gorou]]&lt;br /&gt;
* [[ImMcNutty]]&lt;br /&gt;
* [[Simpus Olympus]]&lt;br /&gt;
* [[Ballsy]]&lt;br /&gt;
* [[Messu]]&lt;br /&gt;
* [[XxAlexX]]&lt;br /&gt;
* [[PrivateJoker]]&lt;br /&gt;
* [[Chris]]&lt;br /&gt;
* [[Coom]]&lt;br /&gt;
* [[Masaki]]&lt;br /&gt;
* [[Hanappe]]&lt;br /&gt;
* [[Emperor Time]]&lt;br /&gt;
* [[Astra]]&lt;br /&gt;
* [[Aqua]]&lt;br /&gt;
* [[friedchilli]]&lt;br /&gt;
* [[Mys]]&lt;br /&gt;
* [[Frogggggg]]&lt;br /&gt;
* [[Pie]]&lt;br /&gt;
* [[TrinaLydia]]&lt;br /&gt;
* [[rd19822019]]&lt;br /&gt;
* [[manbythenameofsanti]]&lt;br /&gt;
* [[NoodleCupKKv]]&lt;br /&gt;
* [[cursedcitrus]] &lt;br /&gt;
* [[Starvelk]]&lt;br /&gt;
* [[Frosty Foobar10]]&lt;br /&gt;
* [[Ash]]&lt;br /&gt;
* [[varunn]]&lt;br /&gt;
* [[frog_0922]]&lt;br /&gt;
* [[AirplaneNiner]]&lt;br /&gt;
* [[Cado]]&lt;br /&gt;
&lt;br /&gt;
=== Shift to Discord===&lt;br /&gt;
After the March reforms, the community gradually transitioned from the [[The Resurgence|WhatsApp group]] to [[852 Resurgence]], as interest in Discord grew. From early to mid 2021, there was an increasing proportion of new members entering the Discord server over the WhatsApp group, and activity of Staff on the former piqued. It should be noted that the Discord server had begun growing in importance prior to the March reforms around February, however the reforms were seen as a key turning point for the community&#039;s choice of platform&lt;br /&gt;
&lt;br /&gt;
Sometime during April-May 2021, the Signal and WhatsApp groups went completely private due to a lack of new members and security concerns.&lt;br /&gt;
&lt;br /&gt;
===New System, New Staff===&lt;br /&gt;
A new system for new moderators was put in place. Known colloquially as the &amp;quot;nomination system&amp;quot;, this saw candidates being nominated by members every month before being voted on by the Staff privately.&lt;br /&gt;
&lt;br /&gt;
[[Bossuuu]] was the only member to be promoted via this system. [[Simpus Olympus]] went through a modified version but was denied.  Later, the system became more publicised before being partially scrapped in October for a system that favoured popular votes.&lt;br /&gt;
&lt;br /&gt;
With the situation in Hong Kong becoming more unstable, Card0 promoted lemontea, a moderator who joined in 2019 residing in the United States to Admin. Around the same time, [[Drea]] resigned from her position as Admin due to inactivity.  &lt;br /&gt;
&lt;br /&gt;
===Minecraft Server===&lt;br /&gt;
In summer of 2021, [[Syntax]] offered to run a Minecraft server for the community. The server ran from July 23rd to September of the same year, when Syn7ax became occupied with immigration. &lt;br /&gt;
&lt;br /&gt;
Syn7ax&#039;s work with the server earned him a promotion to Moderator.&lt;br /&gt;
&lt;br /&gt;
===September Decline===&lt;br /&gt;
[[852 Resurgence]] and [[hongkongggag]] saw a decline in September. As most members were returning to school, Card0 did nothing to try and increase growth, instead waiting for a later date to boost the community&#039;s numbers.  &lt;br /&gt;
&lt;br /&gt;
===Big Boom===&lt;br /&gt;
On October 1, 2021,  [[Salmon]], who had not made a post on [[hongkongggag]] since September 2019, posted several &amp;quot;relatable&amp;quot; memes. His posts were extremely well-received. On one occasion, the page gained 1315 followers in a single day, the most the page had received at the time. &lt;br /&gt;
&lt;br /&gt;
In hindsight of his work, [[Card0]] capitalized on the trend, making several &amp;quot;relatable&amp;quot; memes for audience appeal. He also made school-specific memes, using both local and international schools as a basis for content, including universities and community colleges. While he had done this before, they were more popular this time around. &lt;br /&gt;
&lt;br /&gt;
The boost in popularity affected [[852 Resurgence]], growing the server from 400 to 600 members in a short period of time. Notable members who joined during the Big Boom include [[Sleepy]], [[Bakasta]] and [[E Man]].&lt;br /&gt;
&lt;br /&gt;
===Ban of [[NICORE]]===&lt;br /&gt;
On October 9, 2021, staff held a meeting to discuss various issues of the community,  including the sudden surge of [[Hongkongggag|hongkongggag&#039;s]] popularity. One of the issues discussed was NICORE and his suboptimal behaviour on the [[852 Resurgence|Discord server]]. Staff decided to issue a Level 6 Warning to him on the same day.&lt;br /&gt;
&lt;br /&gt;
NICORE went on to make extremely disrespectful comments to another affiliate, resulting in an indefinite ban the following day. &lt;br /&gt;
&lt;br /&gt;
===Satirical Maps Season 5===&lt;br /&gt;
Card0 had teased Season 5 for a long time, despite Season 4 not doing well. He started making satirical maps throughout October and November, taking in requests while also making maps of his own. This, alongside the aforementioned &amp;quot;relatable&amp;quot; and school specific memes boosted the page from 13 thousand followers at the start of October to 20 thousand by the end of November. This season was also supported by flutters, making satirical maps for South Horizons, Tseung Kwan O, Ap Lei Chau and Pok Fu Lam. &lt;br /&gt;
&lt;br /&gt;
While less successful than other seasons, the page was boosted during its runtime.&lt;br /&gt;
&lt;br /&gt;
=== Further Democratization ===&lt;br /&gt;
Card0 considered more democratic reforms for the community but was hesitant to do so. He asked via a poll if more community decisions (rule changes, new channels etc.) should be chosen through popular vote, to which a majority agreed.As a result, Card0 put up multiple polls asking people to vote on various community affairs, such as the creation of new Discord channels or rule modification. He also withdrew several sanctions, believing that he had made an incorrect decision issuing them. These reforms led to more democratization in regards to the moderator promotion process.&lt;br /&gt;
=== McNutty Spam Attack===&lt;br /&gt;
In late November, [[ImMcNutty]] and some of his friends sent spam accounts asking [[Bossuuu|Bosssuu]] for her SnapChat. &lt;br /&gt;
&lt;br /&gt;
This action caused [[Card0]] to interrogate ImMcNutty and his friends. Although they denied it, Card0 received incriminating evidence pointing towards McNutty. As a result, Level 2 warnings were issued to McNutty, [[SKully]] and [[Nizzy]]. &lt;br /&gt;
&lt;br /&gt;
A Level 1 warning as well as a harsh verbal warning were issued towards [[Hill]] and [[Sakii]] respectively for being complacent in the attacks.  Afterward, Card0 locked down the server temporarily for a couple of hours.  &lt;br /&gt;
&lt;br /&gt;
[[andi]] was partially promoted due to this incident. &lt;br /&gt;
&lt;br /&gt;
=== Creation of the [[Hongkongggag Study Server]] ===&lt;br /&gt;
While study channels existed on 852 Resurgence, they were rarely used. To have a more centralized place for study resources, Card0 and flutters decided to create the [[Hongkongggag Study Server]].&lt;br /&gt;
&lt;br /&gt;
While all 852R staff members got automatic staff powers on the study server, [[sleepy]], a member at the time, was also given powers on the server due to her technical knowledge. &lt;br /&gt;
&lt;br /&gt;
===CJ&#039;s Minecraft Server Incident===&lt;br /&gt;
in the face of the Hongkongggag Minecraft Server still being offline, [[CJ]] suggested running an unofficial Minecraft Server. He set up a Discord for his Minecraft server and gave administrative permissions to all existing members of 852 Resurgence staff. &lt;br /&gt;
&lt;br /&gt;
On CJ&#039;s Discord server, a member: [[Trickster]] spammed racial slurs, including on an alt account, causing Card0 to temporarily ban them. Card0&#039;s actions led [[Wesley]] to call him out for overextension and abuse of power on an auxiliary server.  Wesley was then banned by Card0 from CJ&#039;s server after revealing his political stance of being pro-Beijing, as per 852 Resurgence standards. Card0 was swiftly met with sharp criticism from CJ, claiming that he was abusing his authority on a foreign server. Eventually, both servers broke off relations.&lt;br /&gt;
&lt;br /&gt;
Card0 believed that the situation needed to be addressed transparently, resulting in an emergency community meeting concerning his involvement.  As many members held negative opinions towards Card0&#039;s actions, he took some time away from the community to reflect and calm down.&lt;br /&gt;
&lt;br /&gt;
=== Rise of the Cults===&lt;br /&gt;
On December 17, 2021, Card0 accidentally said 19371 as the answer to a question during a trivia game. As a result, [[flutters]] prompted everyone to change their names to include [[19371 Cult|19371]] at the start.  &lt;br /&gt;
&lt;br /&gt;
On December 19, 2021, the [[Cult|#cults]] channel was invented. Other than adding the existing cults like the Moyai Cult, Bossuuu Cult and the YUU Cult; flutters went on to create many cults not so long after the last. The [[Ms Chan Cult]], [[Sushi Cult]], [[Honey Cult]], [[≤4 Cult|&amp;lt;4 Cult]], [[Lia&#039;s BBs Cult|Lia&#039;s BB Cult]], [[French Cult]] and the [[Everest Cult]] were all made by flutters within a week. Not even when the French Cult and the Everest Cult was created, flutters was told that they needed to transfer all but one cult as they had a cult monopoly. flutter&#039;s chosen cult to keep was 19371. The cults are ever so expanding with new ones appearing at least every 48 hours. &lt;br /&gt;
&lt;br /&gt;
=== Hongkongggag Community Awards 2021===&lt;br /&gt;
On December 18, 2021, the first [[Hongkongggag Community Awards]] were held. Awards were given to multiple members associated with Hongkongggag, including those outside the Discord and WhatsApp groups. Over 20 people were given awards.&lt;br /&gt;
&lt;br /&gt;
The ceremony was hosted by flutters and Card0, lasting roughly 40 minutes. &lt;br /&gt;
&lt;br /&gt;
===Tolmo&#039;s Second Resignation===&lt;br /&gt;
On December 19, 2021, Tolmo, who was promoted to Mod a few weeks ago, posted a study concerning the connection between homosexuality and pedophillia in the debate channel on [[852 Resurgence]], enquiring about its validity. The study was removed from the channel by [[Card0]].&lt;br /&gt;
&lt;br /&gt;
After a back-and-forth argument about his actions, Tolmo resigned from his position as Moderator. in his resignation statement,&amp;lt;ref&amp;gt;[[:File:Tolmo resignation 21-12-19.png|Tolmo&#039;s resignation statement]]&amp;lt;/ref&amp;gt; he expressed his disagreement with the staff team&#039;s methodology of running the debates channel and server. &lt;br /&gt;
&lt;br /&gt;
Later that week, the debates channel was reformed to only allow members who opted-in via  a message. &lt;br /&gt;
&lt;br /&gt;
===Ban and Unban of [[ImMcNutty]]===&lt;br /&gt;
On December 21, 2021, Card0 announced that he had indefinitely banned ImMcNutty for harassment against another member.  This sparked outrage in the community, feeling that McNutty&#039;s side of the story was not properly told. This response led Card0 to unban ImMcNutty 4 hours later, supplemented by a verbal apology in Voice Chat. &lt;br /&gt;
&lt;br /&gt;
Following this, Card0 banned [[CJ]]: who was a friend of ImMcNutty, for confidential and unrelated reasons. &lt;br /&gt;
&lt;br /&gt;
===January 2022 Controversies===&lt;br /&gt;
&amp;lt;blockquote&amp;gt; &#039;&#039;See More: [[January Controversies]]&#039;&#039;&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
==== Technician Crisis ====&lt;br /&gt;
In the first couple days of the new year, Card0 suggested the idea of a new staff rank known as [[Technician]]. Technicians would be ranked below Mediators and have some Staff powers but would mainly focus on the &amp;quot;tech-aspect&amp;quot; of the community including bot and wikia management.&lt;br /&gt;
&lt;br /&gt;
A heated debate between [[Card0]], [[flutters]] and [[Tolmo]] began in #discussion-forum on January 9 2021. &lt;br /&gt;
====Grooming Allegations ====&lt;br /&gt;
At some point during the argument, [[Senpaii]] and [[SKully]] accused flutters of grooming Sleepy with little supporting evidence. Under the old warnings system, they, along with other associates, were temporarily banned.&lt;br /&gt;
&lt;br /&gt;
Eventually, the Technicians proposal was approved, with Sleepy and Tolmo being promoted to the rank.&lt;br /&gt;
&lt;br /&gt;
=== Warning System Reform ===&lt;br /&gt;
flutters proposed a new warning system, stating that the old one was unnecessarily long. Following brief opposition by Card0, the system was implemented in favour of its simplicity.&lt;br /&gt;
&lt;br /&gt;
=== flutters&#039; Probation ===&lt;br /&gt;
flutters was put on probation for a few days due to bad behavior in late December of 2021. However, their impudent attitude acting rasher and harsher towards Card0 and other members. After a series of incidents including Tolmo&#039;s promotion to Technician, Card0 decided to issue a month-long probation to flutters on January 17, 2022.&lt;br /&gt;
&lt;br /&gt;
flutters went on several breaks due to their mental health between mid-January and early February 2022. &lt;br /&gt;
&lt;br /&gt;
=== flutters&#039; Resignation ===&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&#039;&#039;Main Article: [[Admin Controversy|Admin Controversy]]&#039;&#039;&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
Throughout most of January, tensions between Card0 and flutters remained high. flutters proposed to make the Founder role more equal with Admins. After heated debate with Card0 on February 9, 2022, flutters resigned from their Admin position but remained a Mod.&lt;br /&gt;
&lt;br /&gt;
=== Satirical Maps Season 6 ===&lt;br /&gt;
On February 10 2022, the sixth season of Satirical Maps was issued. However, not only did this season not meet Card0&#039;s expectations in terms of reception, but accroding to him, the behavior and attitudes of other Hong Kong meme pages began affecting his enjoyment.&lt;br /&gt;
&lt;br /&gt;
He announced an early cancellation of the season, posting a total of 17 satirical maps. Following the end of the season, Card0 announced that Season 7 was unlikely given recent responses.&lt;br /&gt;
&lt;br /&gt;
=== Intervention in [[Charlie Jackson&#039;s Server]] ===&lt;br /&gt;
[[Frosty]], also known as Charlie Jackson, had set up his own server. He reached out to Card0 for advice who agreed to help him while also offering a partnership between 852R and this new server.  &lt;br /&gt;
&lt;br /&gt;
The partnership became official on February 12, 2022. However, the server was fraught with issues ranging from trolls to staff members. This led to Frosty asking Card0 for help from his Staff team, of which 2 members: [[Tolmo]] and [[flutters]], became staff members on the server in order to improve the experience of it. &lt;br /&gt;
&lt;br /&gt;
=== March 8 Incident ===&lt;br /&gt;
At around 8pm HKT (GMT+8) on March 8, 2022, Card0 posted a new meme, criticising the government&#039;s decision to have an early &amp;quot;summer break&amp;quot; for local schools, which had started earlier that week. A while after posting, some people allegedly from international schools posted comments that seemingly poked fun at those that had the so called summer break. &lt;br /&gt;
&lt;br /&gt;
Some of those people from local schools would then fire back at them, calling them out on their entitledness and privilege. The heated situation would lead Card0 to make a post on the page&#039;s story, asking for those involved to calm down. However, the situation remained tense and as such, Card0 archived the post after waking up the next day. This was one of the few times where a meme was genuinely controversial, rather than being &amp;quot;drama-free&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Lilshotanekoboi Controversy ===&lt;br /&gt;
In early March, [[lilshotanekoboi]] shared a concept drawing of him as Piper Perri in the meme format &amp;quot;1 girl 5 guys&amp;quot; popped up in #art. The context behind the meme was sexual&amp;lt;ref&amp;gt;https://knowyourmeme.com/memes/piper-perri-surrounded&amp;lt;/ref&amp;gt; The community&#039;s response towards the drawing was very conflicted with most of the members being against him. Later on, he would repost a more finalised piece of the art which spurred staff to hold a trial.&lt;br /&gt;
&lt;br /&gt;
lilshotanekoboi was allowed to have a jury and trial to justify his actions. The thread, now deleted, consisted of the same points of how unethical the drawing was. Lilshota argued that he put a cake with the number 18 on it, using it as defence that the boy in the drawing was 18. However others pointed out that in the original draft, there was no cake and was added after. He then tried to defend himself again, claiming that it was underneath the layers, something that the jury and the rest of the public couldn’t see. Despite not all jury members being present for the trial itself, both [[Andi]] and flutters decided to issue an indefinite ban, with approval from [[Card0]].&lt;br /&gt;
&lt;br /&gt;
=== March-April 2022 Community Crisis  ===&lt;br /&gt;
Between mid March and early April 2022, 852 Resurgence experienced a rise in toxicity and increased inactivity. Several members such as [[Hill]] (who later rejoined), [[emperor time]], and [[Simpus Olympus]] (who shortly rejoined and left) would leave the server as a result.&lt;br /&gt;
==== Nyan’s Ban ====&lt;br /&gt;
On March 16 2022, flutters created the #lgbtqia-plus channel, over a week later, Andi would create a similar channel for positivity. However, both channels had the opposite effect as Staff noticed that some people were being toxic to each other. In addition, Staff also received reports about toxicity in the community. As such, Card0 announced on March 27, 2022, Staff would officially take a harder stance against toxicity, especially in the venting channels. This would lead to sanctions issued to several members due to this new stance.&lt;br /&gt;
&lt;br /&gt;
One member: [[Nyan]], posted anti-LGBTQ+ comments in the #lgbtqia-plus channel and was issued a L1 warning by Card0. However, he would then continue his homophobic behavior with multiple staff members in DMs, leading to a temporary 1 month ban. This would further escalate as Nyan would use his Instagram account to play the victim, daring staff to permanently ban him. As a result, he would later be permanently banned. Shortly after, Nyan would use the Instagram page of an e-sports team he was a part of, to paint the staff of 852R in a bad light, accusing them of &amp;quot;indoctrinating future generations&amp;quot;. Some members would then call him out on his behavior. &lt;br /&gt;
==== Toto Controversy ==== &lt;br /&gt;
On March 30 2022, [[Toto523]] was temporarily banned for 2 weeks for spamming in several channels, including the venting channels. &lt;br /&gt;
&lt;br /&gt;
However shortly after on April 1, 2022, Staff received word that Toto was planning a raid via 4Chan. Seeing this, [[Andi]] quickly upgraded Toto’s ban to a permanent one. Toto would be upset with this, sending a long piece of text in the Moyai Cult server criticising the staff, especially [[Card0]]. The rant accused the staff of being entitled simply because they went to international schools (which was inaccurate), as well as making other irrational takes. Card0, and other members of the community, denounced the statement. &lt;br /&gt;
&lt;br /&gt;
==== End of the Crisis  ====&lt;br /&gt;
On April 2, 2022, Card0 decided to ask the members of the server what they thought the main issues were, what they thought about staff and what should be done to help make the server a better place. The response was mostly limited with most members having at most, minor issues with how the server was run. Card0 would also decide to start promoting the server more via server events on the page&#039;s story, and look into offering privileges for those of higher ranks, in order to help boost the server&#039;s activity.  &lt;br /&gt;
&lt;br /&gt;
Eventually, other events would lead the crisis to a close, ending a stressful time in the server&#039;s history.  &lt;br /&gt;
&lt;br /&gt;
=== The impact of r/place ===&lt;br /&gt;
On March 30, 2022, a member known as [[HKGAFD]] joined the server and promoted his project: to create the Black Bauhinia flag onto r/place 2. Card0 offered them a server partnership between 852R and their server to which they accepted. Over the course of r/place, the amount of members in the r/place HK server increased to 1600 at its peak. HKGAFD would also be given a special role: Black Bauhinia Leader. &lt;br /&gt;
&lt;br /&gt;
However, HKGAFD had plans to archive the server after the event was over and as such, Card0 decided to promote 852R to members on the other server who wished to continue talking. Some of these members included [[Bricky]] and [[MrTup]]. Shortly after on April 6, 2022, HKGAFD would cancel the archival and work to create a community server, though the staff team would still archive the server later on due to a continued lack of interest.&lt;br /&gt;
&lt;br /&gt;
=== The new [[852RSMP]] ===&lt;br /&gt;
After several delays, [[Sleepy]] decided to help host the Hongkongggag Minecraft Server on a new seed instead of Syn7ax. New rules were written up by [[Card0]] and Sleepy and a rudimentary spawn area was built by Card0. &lt;br /&gt;
&lt;br /&gt;
The server opened on April 12, 2022. While there were issues among different factions, the server was very popular in its first few days of opening. Furthermore, Staff were allowed to &amp;quot;admin abuse&amp;quot; to a certain capacity provided they didn&#039;t ruin the fun of the server.&lt;br /&gt;
&lt;br /&gt;
=== Mythguy Incident ===&lt;br /&gt;
On April 15 2022, [[Card0]] decided to play a prank by teleporting [[Mythguy1314]] to a pit and then dropping him into it, causing his death. This angered Myth as his levels were also gone. However, Card0 defended himself citing that &amp;quot;it was just a game&amp;quot; and that he would compensate.  While some members sympathised with Myth, they soon asked him to stop as he was making things worse. &lt;br /&gt;
&lt;br /&gt;
Myth would then ask Card0 for Flint and Steel to which Card0 gave it to him, he would then proceed to grief parts of Card0&#039;s base in the [[Mutualist Republic of New Estonia]] which would lead him to be banned for 1 week and warned. This would be upgraded to a 2 week ban and an indefinite ban from the SMP as he threatened to grief the SMP as a whole once he was unbanned.&lt;br /&gt;
&lt;br /&gt;
=== The Road to 40K ===&lt;br /&gt;
On April 14 2022, [[Card0]] began a new series, making fun of various international schools in different memes by generalising students from those schools. Seeing the immense success, he would decide to continue the series but with local schools, further increasing the page&#039;s popularity. Many followers began to ask for specific schools to which Card0 tried to fufill their wishes. Soon, people weren&#039;t just excited for the accuracy, but also the mention of their school on the page as the schools chosen became more and more lesser known. On one occasion on April 17, 2110 new people followed the page, the most the page has seen since.&lt;br /&gt;
&lt;br /&gt;
Furthermore, it would lead to an increase in members in [[852 Resurgence]] such as [[Jasper]] and [[Hcone]]. This would also see a slight boost in the popularity of the SMP which, despite the resumption of face-to-face classes in Hong Kong on April 19, remained popular. While growth would slow down after April 19, 2022, the page still saw accelerated growth as Card0 shifted to making &amp;quot;why don&#039;t you join&amp;quot; memes of universities while still continuing the students memes for a while.  &lt;br /&gt;
&lt;br /&gt;
On April 22, 2022, the page would finally reach 40 thousand followers. Following this, the page&#039;s growth would slow down even more although it remained fairly high compared to before. &lt;br /&gt;
&lt;br /&gt;
=== Imposter Situation ===&lt;br /&gt;
On April 19, 2022,  a page known as hongkongggag_v2 was discovered by Card0, who was impersonating the original page. Almost immediately, Card0 called upon members of the discord as well as the page&#039;s followers to report the page immediately. A few members did point out that as the page claimed to be &amp;quot;stolen content&amp;quot;, he had no right to take action though Card0 argued that it was using the page&#039;s brand regardless. Others argued that the page was small and as such, Card0 should not pay as much attention to it.  &lt;br /&gt;
&lt;br /&gt;
=== Wutty Incident ===&lt;br /&gt;
On May 1, 2022, a member called [[Wutty]] joined the server, accusing Card0 of silencing free speech for blocking him as a blue ribbon. This of course, led Card0 to ban him indefintely. &lt;br /&gt;
&lt;br /&gt;
A day later on May 2, 2022, a new member known as [[Farhan.xkhan]] reported that Wutty was planning a raid. As such, Card0 immediately decided to shut down the server and set it to private. As Wutty&#039;s threats increased in terms of severity, Card0 even put the page on private for a few hours, the first time since the Underground Era.&lt;br /&gt;
&lt;br /&gt;
The lockdown lasted until the morning of May 3, 2022 when the server was re-opened again. As a result of the raid threat, Card0 purged about 20+ members while also enhancing the server&#039;s security.&lt;br /&gt;
&lt;br /&gt;
=== End of the Hype ===&lt;br /&gt;
Shortly after getting 44 thousand followers in Early May, the page&#039;s growth began to stunt severely until Hongkongggag would only see less than 30 new followers daily. This bought an end to the 3rd era of hype.&lt;br /&gt;
==Great Era of Hype (May 2022-January 2023)==&lt;br /&gt;
The Great Era of Hype was called as such due to the immense amount of follower and server member growth in this period, compared to most periods in Hongkongggag&#039;s history. This era also saw new intiatives such as the revival of the SMP, the creation of Asianggag, the new Pokemon project and Tsz Kong&#039;s revival. The era would also cement Hongkongggag&#039;s pan-democratic left-wing identity, concluding on a high note with the 2023 Community Awards.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Staff during this period:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Founder: Card0&lt;br /&gt;
&lt;br /&gt;
Admins: flutters, Lemontea, Salmon, Andi, Bossuuu&lt;br /&gt;
&lt;br /&gt;
Moderators: Lieutenant.Quattro, Sayonara, zo.loft, Sage, Greentea, zt&lt;br /&gt;
&lt;br /&gt;
Mediators: Boba, Salami, Livie, Chris&lt;br /&gt;
&lt;br /&gt;
Technicians: Sleepy, Tolmo, aaronforce1&lt;br /&gt;
&lt;br /&gt;
Promotions: Greentea, Livie (September 2022), Chris, Zt (October 2022)&lt;br /&gt;
&lt;br /&gt;
Resignations: Syntax (August 2022)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Notable members who joined during this era:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [[Felix-ashe]]&lt;br /&gt;
* [[beeeeeeeluga]]&lt;br /&gt;
* [[Cole Park]]&lt;br /&gt;
* [[Thoth]]&lt;br /&gt;
* [[Zt]]&lt;br /&gt;
* [[Skydust_Mario]]&lt;br /&gt;
* [[Asianbarb]]&lt;br /&gt;
* [[ozzzkar]]&lt;br /&gt;
* [[Kingsnake1]]&lt;br /&gt;
* [[Deerbro]]&lt;br /&gt;
* [[Krispies]]&lt;br /&gt;
* [[rl34_]]&lt;br /&gt;
* [[Rsburuu]]&lt;br /&gt;
* [[Kevinovich]]&lt;br /&gt;
* [[Casio fx-gx 50]]&lt;br /&gt;
* [[Ame]]&lt;br /&gt;
* [[Nox]]&lt;br /&gt;
* [[Kix Kiefer]]&lt;br /&gt;
* [[Nax]]&lt;br /&gt;
* [[Allurim]]&lt;br /&gt;
* [[zuiyunyue]]&lt;br /&gt;
* [[Farhan]]&lt;br /&gt;
* [[goosy]]&lt;br /&gt;
* [[DDaniii]]&lt;br /&gt;
* [[Helia]]&lt;br /&gt;
* [[rena]]&lt;br /&gt;
* [[Lammielord]]&lt;br /&gt;
* [[jasmine]]&lt;br /&gt;
* [[Rin]]&lt;br /&gt;
* [[ConstanceTheBAKA]]&lt;br /&gt;
* [[Katra]]&lt;br /&gt;
* [[dawn]]&lt;br /&gt;
* [[aleishes]]&lt;br /&gt;
* [[Coxmic]]&lt;br /&gt;
* [[MeisterBurgerBurgerMeister]]&lt;br /&gt;
* [[Jasper]]&lt;br /&gt;
* [[clout]]&lt;br /&gt;
* [[JFK]]&lt;br /&gt;
* [[thatharpgirl]]&lt;br /&gt;
* [[Polaris]]&lt;br /&gt;
* [[StormNinja25]]&lt;br /&gt;
* [[lilylily4011]]&lt;br /&gt;
* [[Qin]]&lt;br /&gt;
* [[Yosh]]&lt;br /&gt;
* [[Worrski]]&lt;br /&gt;
* [[curiosityyyyy]]&lt;br /&gt;
* [[SecurityInnit]]&lt;br /&gt;
* [[Stars88]]&lt;br /&gt;
* [[Murvon]]&lt;br /&gt;
* [[Lowiczanka]]&lt;br /&gt;
* [[Tuck]]&lt;br /&gt;
&lt;br /&gt;
===Wsdu&#039;s Resignation===&lt;br /&gt;
Following a heated debate in #debates on June 2, 2022, [[Wsdu]] was put on probation for a week due to his actions. Despite Card0 giving him a chance to think over his actions, Wsdu would then promptly resign effective from June 4, 2022, initially only staying to purge his messages. Later, Wsdu apologized for his behavior in #debates and announced that he would remain active in the server as a regular member until he left the server in December, later rejoining on May 17, 2023.&lt;br /&gt;
&lt;br /&gt;
=== Creation of Asianggag ===&lt;br /&gt;
On June 21, Card0 asked the community on what should be done with the inactive backup page: hongkonggag2. He gave the community three ideas: the second being to make Asian memes. This option was by far the most popular and as a result, the backup page was rebranded to [[Asianggag]] later that day.&lt;br /&gt;
&lt;br /&gt;
=== Withdrawal from the Hong Kong Inter-Page Alliance ===&lt;br /&gt;
On June 22, Card0 asked the community if the page should leave the Hong Kong Inter-Page Alliance: a group of Hong Kong pro-democracy independent news pages that Card0 founded back in 2019. However, he realised that some of the people in the group became too sensationalist and often exaggerated the truth. As a result, the page withdrew from the alliance after a discussion with the community. This decision was not controversial and the members who responded to Card0 largely agreed/trusted him. &lt;br /&gt;
===Operation British and the Revival of the SMP===&lt;br /&gt;
In Early July, [[Zeon]] commenced Operation British on the 852R SMP, destroying Yuutopia. This was based off an off hand comment by YUUtopia&#039;s main leader: [[Zoe]], that she didn&#039;t care about the faction anymore. However upon discovering Operation British, Zoe would get mad at Zeon and as a result, Card0 would de-op Zeon&#039;s leader: [[Lieutenant Quattro]], for 1 week on the SMP.&lt;br /&gt;
&lt;br /&gt;
Card0 would then help Zoe as well as [[Aqua]] to rebuild Yuutopia, even granting them Creative mode on occasion. [[Nax]] and [[Luminous]] would also help rebuild the faction. The new design would reflect New L&#039;Manberg from the Dream SMP. This whole affair would also revive interest in the server for a short while.&lt;br /&gt;
&lt;br /&gt;
=== Tsz Kong Revival ===&lt;br /&gt;
Having remained inactive since April, Card0 revived the sim on July 4th 2022 with new members such as [[Kevinovich]] joining the sim. [[Farhan.xkhan]] would win the elections under the Nationalist Party held just a few days later. However, he would be ousted after acting unconstitutionally leading to Card0 to call new elections. In these new elections, Kevinovich would win under the Social Democratic Worker&#039;s Party (SDWP), though activity and interest in Tsz Kong would slow down for the latter half of his term until the August Elections.&lt;br /&gt;
&lt;br /&gt;
===[[MRT Controversy]]===&lt;br /&gt;
In July, some members began to join the MRT Server, a server some members in 852R had come from due to Card0 playing on the server as well. As some members began to bring in 852R jokes on a more prominent level, the MRT&#039;s owner: Frumple: clamped down, targetting members from 852R while ignoring other inside jokes on the server. This sparked outrage among both those who hadn&#039;t played on the MRT previously and those that had. &lt;br /&gt;
&lt;br /&gt;
Card0 would make a statement on the situation, with past incidents of Frumple&#039;s emotional manipulation influencing the statement.&amp;lt;ref&amp;gt;[https://docs.google.com/document/u/1/d/1QgiRa7HZ8U55sY_BW3gpJvRwMCFZOC4dyTf0rv2YIo4/edit A Statement]&amp;lt;/ref&amp;gt; However, the response to it on the MRT was lukewarm with largely those that sided with Frumple calling out Card0 while others who disagreed with Frumple remained silent. Since then, Frumple has become a meme on the server, with one of Frumple&#039;s messages becoming a sticker in the server.. Furthermore, when Card0 would be banned for jokingly calling Zoe &amp;quot;fuck you&amp;quot; in late November, his ban message would also become a sticker though it would later be removed.&lt;br /&gt;
&lt;br /&gt;
===4th Anniversary===&lt;br /&gt;
On July 18, the community as well as the page celebrated 4 years of the page. Card0 made a speech, posting it both on Discord and Instagram, thanking everyone and reflecting on the last 4 years of running the page. During celebrations that night, he would read an abridged version of the speech. Other members such as [[Tolmo]], [[Aqua]] and [[Joyce]] would also read short speeches or type them out in #general.&lt;br /&gt;
&lt;br /&gt;
Some old members would also return to the server, most notably former admin [[Vista]] as well as [[Rei]], both of whom left in 2021 (though the latter would leave soon after). Other new members also joined the server for the first time due to heavy promotion on the page.&lt;br /&gt;
&lt;br /&gt;
Throughout the month of July, several events would be hosted to celebrate the 4th anniversary.&lt;br /&gt;
&lt;br /&gt;
=== Peak of Demotivation  (July 2022-August 2022) ===&lt;br /&gt;
Throughout July and August, hongkongggag, as well as many other Hong Kong meme pages both English and Cantonese speaking experiences drops in follower growth. The page was sitting around 47 thousand followers. However, daily growth rarely exceeded 15-20 new people. &lt;br /&gt;
&lt;br /&gt;
This was largely was due to Instagram’s new reel based algorithm as well as other incidents in the Hong Kong meme space most notably the fallout of the Mirror “We Are” Concert incident. Additionally, Card0 claimed that due to the high number of new HK meme pages, content had become saturated possibly leading to this drought. &lt;br /&gt;
&lt;br /&gt;
Card0 would post a few statements in early August while also asking the page’s followers on what could be done. However he was left with not a lot of options besides waiting. This would end with Card0 finally began posting reel-type memes, with the same style and design as the other non-reel memes. These would be well received, boosting the page&#039;s growth. &lt;br /&gt;
&lt;br /&gt;
=== Tsz Kong August Election Controversy ===&lt;br /&gt;
The August Tsz Kong Elections were held on August 16th, with candidates declaring their participation a few days earlier. While [[Kevinovich]] declined to run again, the previous president: [[Farhan.xkhan]] ran again. A new party: the Ronak Libertarian Party, led by [[sid]], was formed.&lt;br /&gt;
&lt;br /&gt;
However, Farhan was accused of vote rigging by inviting his friends just to vote for him. Both of these known friends also had profile pics of a Nazi and Saddam Hussein respectively. Card0 would ban both and give Farhan a deadline to list those names. While Farhan did eventually give Card0 his names, his initial attempt to lie about it led Card0 to disqualify Farhan anyways. &lt;br /&gt;
&lt;br /&gt;
Meanwhile in the political sim, the disqualification of the Nationalists meant that [[Lieutenant Quattro]] of the Zeonist Party, won the election, returning to the post once again.  &lt;br /&gt;
&lt;br /&gt;
=== Trial of Farhan ===&lt;br /&gt;
Following the incident, Card0 would then discuss with Staff on holding a trial for Farhan, to which Staff agreed, partially due to Farhan having controversies in the main server as well. The trial would be held just a day later. The jury consisted of [[Kevinovich]], [[sid]], [[Salami]] and [[Citric Acid]]. Other members of the community including those not involved in Tsz Kong were also present. Farhan asked [[Speedbird001]] to be his &amp;quot;defense attorney&amp;quot;, however in the end the jury, and later the public, decided on an indefinite ban.&lt;br /&gt;
&lt;br /&gt;
As part of the punishment, Farhan was also removed from the [[HK Meme Page Alliance]] which was seen as controversial by some members in the group. In addition, Card0 also questioned Farhan&#039;s claims of Wutty&#039;s raid, having theories that Farhan faked the raid threat in order to gain more power and trust in the community.&lt;br /&gt;
&lt;br /&gt;
=== Relaxation of the [[Anti-Blue Ribbon Policy]]===&lt;br /&gt;
On August 20, 2022, a member of the server: [[Yosh]] revealed in a debate that he was a blue ribbon. However, his past messages as well as more information revealed by himself seemed to indicate he had more neutral views. Card0, who had asked Yosh these questions, had decided after a few calls notably from [[Tolmo]] and [[Sleepy]] within Staff, to review the anti-blue ribbon policy. &lt;br /&gt;
&lt;br /&gt;
Card0 asked the community for their opinions and while many were concerned, others believed some relaxation was needed. Later on, a poll was held which gave the community 3 options: do nothing and treat Yosh as a special case, relax the policy or remove it entirely. Most of the people who voted opted for the 2nd option, which would be implemented the next day. &lt;br /&gt;
&lt;br /&gt;
=== [[Satirical Maps]] Season 7 ===&lt;br /&gt;
On August 23rd, Card0 teased a 7th season of Satirical Maps. The season would begin a few weeks later on September 3rd with a satirical map of Singapore. It ended on October 23rd. The season was special as it frequently featured maps of other cities, notably those with a sizable Hong Kong Diaspora such as London and Vancouver. A New York City map was planned and even made but Card0 would decide not to post it due to him believing it was lacking in its information and humour. &lt;br /&gt;
===The Reopening of Mod Nominations and the Simpus Nomination Incident===&lt;br /&gt;
With Mod Nominations having been closed for a couple of months, Card0 decided to reopen nominations as the server had grown since then following a poll held on September 8th. Card0 himself would also nominate two people: [[Crimsion Ghost|Crimson Ghost]] and [[Citric Acid]] though both members declined the position before the polls ended.&lt;br /&gt;
&lt;br /&gt;
On September 11, 2022, [[flutters]] (as well as [[Chilis]] later on) would nominate [[Zoe]] for Mod, this was approved by Card0. Shortly after, [[Lieutenant Quattro]] would nominate [[Simpus Olympus]] for the position as well. However, Card0 would deny this citing maturity concerns. This sparked outrage from Quattro as well as [[Ballsy]] and [[Hill]] who accused Card0 of being immature himself, bringing up past incidents to discredit him. This caused Card0 to lock Discussion Forum for a while and announce that he was stepping back from most Staff responsibilities for a while. Zoe would later be promoted the next day. Hill would be issued a Level 2 warning after Card0 came back a week later on the 18th. &lt;br /&gt;
&lt;br /&gt;
=== Bootlicker Meme Controversy ===&lt;br /&gt;
On September 16, 2022, Card0 posted a meme to the page indicating Hong Kongers who defended the British Monarchy (or the British colonial era of Hong Kong), were bootlickers. Although Card0 expected the meme to be at least somewhat controversial, he did not expect such an extreme response, with many making personal attacks towards Card0.  Some of this backlash was also due to the fact that it was posted just a couple days after the Queen&#039;s death. This led Card0 to turn off comments for the meme then later archive it. He would then unarchive it and turn comments back on the next day.&lt;br /&gt;
&lt;br /&gt;
The meme, according to Card0, led to around 100 people unfollowing the page in less than 48 hours. Card0 would also make a few more anti-colonial memes, though only posting them on the Discord in fear of backlash. Thankfully, no active members of the community were upset by the meme, with some even defending Card0 most notably those based in the UK such as Andi. &lt;br /&gt;
&lt;br /&gt;
===Death of Hanappe===&lt;br /&gt;
[[File:Screenshot 2022-10-25 181347.png|thumb|400px|flutters announcing Hanappe&#039;s death.]]&lt;br /&gt;
On the afternoon of October 15, 2022, it was announced that [[Hanappe]] passed away due to suicide.&amp;lt;ref&amp;gt;[https://discord.com/channels/567308609411612674/588692075676172298/1030752877574107166 https://discord.com/channels/567308609411612674/588692075676172298/1030752877574107166]&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;[https://www.hk01.com/%E7%AA%81%E7%99%BC/825532/%E6%B2%99%E9%A0%AD%E8%A7%92%E5%9C%8B%E9%9A%9B%E5%AD%B8%E6%A0%A115%E6%AD%B2%E5%A5%B3%E5%AD%B8%E7%94%9F%E4%B8%8A%E5%90%8A-%E7%95%99%E9%86%AB3%E6%97%A5%E4%B8%8D%E6%B2%BB 沙頭角國際學校15歲女學生上吊　留醫3日不治 ]&amp;lt;/ref&amp;gt; After the announcement, the 852 Resurgence server icon and banner were changed to black and white artwork drawn by Hanappe before her death, with several members posting their condolences.  &lt;br /&gt;
&lt;br /&gt;
The response to her death was overwhelming, many expressed profound statements of grief and sorrow, including many who hadn&#039;t interacted with Hanappe a lot or even at all.  &lt;br /&gt;
&lt;br /&gt;
A memorial service was held a week later on October 22, with Card0 and other members making statements, followed by a moment of silence. A few days after the service, the server icon and banner were changed to colorised versions of Hanappe&#039;s art for an indefinite time.  &lt;br /&gt;
&lt;br /&gt;
===Introduction of Meme Submission Sundays===&lt;br /&gt;
[[File:Kix.png|thumb|400px|The meme submitted by Kix.]]&lt;br /&gt;
On October 22, 2022, [[Zt|zt]] suggested a new event called Meme Submission Sunday, where members can submit memes to Hongkongggag following a specified but optional theme. This was approved by Card0, who opened a #meme-submissions channel. The first theme the next day on October 23 was dim sum, with a meme submitted by [[Kix Kiefer]] being chosen by Card0 and posted the next day.&amp;lt;ref&amp;gt;[https://www.instagram.com/p/CkF5NH1v9CV/?igshid=YmMyMTA2M2Y= hongkongggag: This is a sin and you shall be punished by our judgement]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Double-staff Promotion ===&lt;br /&gt;
On October 26, two current staff members, zt and Thoth, were nominated as Moderator and Mediator respectively. The next day they both were promoted.&lt;br /&gt;
&lt;br /&gt;
=== October 31st Instagram Purge ===&lt;br /&gt;
On October 31st, Instagram would remove inactive accounts across the platform, this caused panic among many &amp;quot;influencers&amp;quot; on Instagram including Hongkongggag. Card0 posted announcements in both discord and on the page&#039;s story pleading for people to follow the page back.&lt;br /&gt;
&lt;br /&gt;
Thankfully Instagram reversed the change and in a surprise twist, the page gained more followers as a result of this decision. &lt;br /&gt;
&lt;br /&gt;
=== Anti-Xenophobia Movement ===&lt;br /&gt;
On November 15th, Card0 silently and unofficially began an indirect purge of Hongkongggag&#039;s followers. Rather than manually removing followers, Card0 instead posted certain memes that called out monarchy-bootlicking, Homophobia and Xenophobia in order to get people who supported those ideals to unfollow the page, therefore making the page more of a safe and tolerant page. This &amp;quot;purge&amp;quot; ended on November 18th.&lt;br /&gt;
&lt;br /&gt;
==== Calling out Oneaguy ====&lt;br /&gt;
For a while, Card0 had been openly calling out Oneaguy (一個人, also known in English as Hong Kong Guy), a xenophobic cartoonist who posted stick figure comics greatly exaggerating the situation in Hong Kong on Instagram. He went on to post a call-out post on November 21st with help from other members. While most reacted to the post postively, with many saying that they had feelings of animosity towards Oneaguy, many called out Card0 instead, even making personal attacks. This led to Card0 blocking many accounts. As result of the post, the page lost about 100 followers, which Card0 presumed were those that were either sympathetic towards, or fans of Oneaguy.&lt;br /&gt;
&lt;br /&gt;
In Late December, Card0 found out that some people on LIHKG had smeared the page&#039;s post, calling the page a &amp;quot;leftard&amp;quot; and claiming that Hong Kongers supporting democracy should hate Mainlanders. However, some also noticed that many on the forum didn&#039;t really like Oneaguy either.&lt;br /&gt;
&lt;br /&gt;
==== Impact of the Chinese Protests ====&lt;br /&gt;
While the indirect purge would end on the 18th, it started up again on the 26th. This was due to the sudden protests against the CCP in China and as a result, Card0 decided to combat and call out xenophobia by calling it out. While most people supported him, some also unfollowed the page due to believing that the mainland protests had nothing to do with the pro-democracy movement. This also marked a shift in the page&#039;s stance, as it began to connect with mainland-based pro-democracy pages, as well as critiquing the localist factions of the movement as a whole. Since then, Hongkongggag has greatly distanced itself from said localist groups.&lt;br /&gt;
&lt;br /&gt;
=== The beginning of Pokémon Canary and Azure: a 852R Pokémon World ===&lt;br /&gt;
On the 22nd of November, 2022, zt was bored in their social studies class, and made a crack idea saying they&#039;d make 852R into a Pokémon world. Card0 agreed with the idea, and together, along with a.few other members, started the 852R joint project of Pokémon Canary and Azure. This was a success and as such, a second project was created shortly after Canary and Azure was largely completed, Card0 hosted a poll on December 3rd 2022 asking members to choose which shall be the next region the Pokemon fans of the server shall create. The winner was the Phillipines and as a result, the Pokemon Flux and Stasis project began shortly after, which lasted until early-mid 2023.&lt;br /&gt;
&lt;br /&gt;
=== The 2022 Community Awards ===&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&#039;&#039;Main Article: [[Hongkongggag Community Awards]]&#039;&#039;&amp;lt;/blockquote&amp;gt;Similar to 2021, a community awards ceremony was hosted on December 23rd 2022. However this time, the awards of Best Mascot, Best Staff and Best Member were open to voting from the public, with members voting in a poll hosted by flutters. The winner of the Best Staff Award was Zt while Best Member went to flutters. Several other members would win awards that night, many of them having either joined the community in 2022, or became active in 2022. Card0 and Andi would host the awards as flutters was busy that day. Around 35 people attended, exceeding the audience number of 2021&#039;s award show.&lt;br /&gt;
&lt;br /&gt;
=== Vision 2023 ===&lt;br /&gt;
On December 28th 2022: Card0 unveiled the plan for both the page and the community for the coming year: Vision 2023. The plan included both major and minor changes for the server, raging from the creation of a lgbt-memes channel, school memes on the page to be released in batches, and an overhaul of the Admin and Discord Admin ranks. Some of these changes, like the aforementioned Admin reform, were put up to polls on the first day of the new year, with most of these changes passing. Furthermore, Tolmo would be promoted to Moderator on New Year&#039;s Day as well, with Card0 saying that he may promote him to Admin in the next 1-2 months.&lt;br /&gt;
&lt;br /&gt;
=== January 2023 Lockdown ===&lt;br /&gt;
On January 10th 2023, the server was put on private due to a raid threat from another server who wanted to destroy 852R and Hongkongggag. Despite the threat being baseless in retrospect, all invite links were revoked during this time. The lockdown was lifted the next day.&lt;br /&gt;
&lt;br /&gt;
=== Second Tsz Kong Revival ===&lt;br /&gt;
Throughout most of late 2022, the Tsz Kong Political Sim had been more inactive. While bills were being passed, these often happened only once every week. With only 3 parties confirming participation in the next elections (one of them would be later removed), on January 17th 2023, Card0 made an urgent plea in the server urging people to join the sim. He referred to it as the &amp;quot;black sheep of hkgag&amp;quot;, due to its lack of growth and activity compared to 852R and the page. As a result, many people would join the sim and create parties, just before the elections began the next day. New parties included the Ocean Party and the .He would also promote it on the page though by the time most people from there started joining the elections had started. Nevertheless, this led to a very diverse parliament for the next term,&lt;br /&gt;
&lt;br /&gt;
=== Removal of 30 Day Ban ===&lt;br /&gt;
On January 19th 2023, Card0 and Andi announced that the 30 day ban warning (L3 Warning) had been removed due to it being obsolete, as most people got L1, L2 or L4 warnings instead, with some getting L5 (permanent ban).&lt;br /&gt;
&lt;br /&gt;
=== Creation of hongkongislandgag ===&lt;br /&gt;
In late January, Card0 publicly bought up the ideas of new &amp;quot;sister pages&amp;quot; to Hongkongggag, beyond asianggag. While he mentioned collaborating with Herro on a potential &amp;quot;australiagag&amp;quot; or &amp;quot;sydneygag&amp;quot;, Kix Kiefer would create hongkongislandgag, the first true sister page to the original page. The page got 271 followers less than 4 days after its creation. However, the page is currently inactive at the time of writing. &lt;br /&gt;
&lt;br /&gt;
== Frontier Era (February 2023-February 2024) ==&lt;br /&gt;
The Frontier Era is to referred to as the page and community explored new opportunities, leading to new ideas coming about. However, this era also experienced some stagnation both in terms of the page and server, as well as issues with the immaturity of certain members. By its end, activity dipped, and Card0 publicly mused about stepping back from the server, but not from the page.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Staff during this period:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Founder: Card0&lt;br /&gt;
&lt;br /&gt;
Admins: flutters, Lemontea, Salmon, Andi, Bossuuu, Tolmo&lt;br /&gt;
&lt;br /&gt;
Moderators: Lieutenant.Quattro, Sayonara, Sage, Greentea, zt, Astra, Polaris, Sumii, Ame, Jasper&lt;br /&gt;
&lt;br /&gt;
Mediators: Boba, Salami, Livie, Chris, Thoth, Ame&lt;br /&gt;
&lt;br /&gt;
Technicians: aaronforce1, Sleepy, Tuck&lt;br /&gt;
&lt;br /&gt;
Promotions: Thoth, Astra, Polaris (April 2023), Tuck (May 2023), Sumii, Ame (June 2023), Jasper (August 2023)&lt;br /&gt;
&lt;br /&gt;
Resignations: zo.loft (April 2023)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Notable members who joined during this era:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [[Nigel]]&lt;br /&gt;
* [[Noknok05]]&lt;br /&gt;
* [[Saera]]&lt;br /&gt;
* [[Ceadz]]&lt;br /&gt;
* [[elio_ch]]&lt;br /&gt;
* [[Medic_Bear]]&lt;br /&gt;
* [[Moj]]&lt;br /&gt;
* [[Rtvan7459]]&lt;br /&gt;
* [[SpaceFaucer]]&lt;br /&gt;
* [[Hoch]]&lt;br /&gt;
* [[Slater]]&lt;br /&gt;
* [[pinho]]&lt;br /&gt;
* [[Expired potato]]&lt;br /&gt;
* [[Catgirlmutant]]&lt;br /&gt;
* [[sionnachuighim]]&lt;br /&gt;
* [[Cubex]]&lt;br /&gt;
* [[Tend]]&lt;br /&gt;
* [[Ocean]]&lt;br /&gt;
* [[Syncretism]]&lt;br /&gt;
* [[J4CKI]]&lt;br /&gt;
* [[Alexip718]]&lt;br /&gt;
* [[vin100 Kotlin Learner]]&lt;br /&gt;
* [[Chel]]&lt;br /&gt;
* [[MegaNoodle852]]&lt;br /&gt;
* [[Orangeychip]]&lt;br /&gt;
* [[th07045]]&lt;br /&gt;
* [[Starcubed]]&lt;br /&gt;
* [[Astolfo]]&lt;br /&gt;
* [[rdk]]&lt;br /&gt;
* [[fourfiveeightthree]]&lt;br /&gt;
* [[Bluber]]&lt;br /&gt;
* [[Kedah]]&lt;br /&gt;
* [[Jonoo]]&lt;br /&gt;
* [[Zy]]&lt;br /&gt;
* [[Pixel]]&lt;br /&gt;
* [[DetectiveAnoose]]&lt;br /&gt;
&lt;br /&gt;
=== Meme the News ===&lt;br /&gt;
In early February, Card0 officially revealed that his memes would be a part of an exhibition at the Hong Kong Foreign Correspondents&#039; Club in Central, alongside a few other Hong Kong meme pages. The response to the news was overwhelmingly positive, albeit also very sarcastic which Card0 responded as &amp;quot;people going too far&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Meister&#039;s Trial ===&lt;br /&gt;
For several months, [[MeisterBurgerBurgerMeister]] had been issued several warnings for borderline homophobia and transphobia. Irritated by Meister&#039;s actions in General, the Staff decided to hold a trial on the night of February 12th 2023. The trial lasted for around an hour with a jury of 3 members, who decided that Meister should be permanently banned. Before being banned, Meister made a speech mocking the staff and the LGBT community which quickly became a server-wide meme:&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
Yeah. I did a lot of trolling, and it was worth it. I thought you’d just outright ban me; I couldn’t have expected a trial, and a rigged one at that. Guess I got too silly for y’all. Some folx just can’t handle the smoke, and it clear that you can’t. A safe space. Psh what a joke. That’s funny. I say, it was quite fun to subtly clown on Cardold. And I ain’t gonna learn. The world is a harsh and unforgiving place, and it’s getting worse for people, rebels, like me. I oppose the new world order and globalism. I meant all of what I said. Nothing was ever misinterpreted.&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
Following his ban, while Meister&#039;s friends were saddened by his ban, most of the other members present in the trial, including Card0 celebrated. Shortly after, cup, Meister&#039;s de-facto defense attorney, was banned for similiar comments against the LGBT community.&lt;br /&gt;
&lt;br /&gt;
=== Farhan&#039;s Trial ===&lt;br /&gt;
The trial of Farhan in 17th February 2023  was held after his 6 month ban was expired. The trial lasted for 30 mins and Farhan was unbanned  from 852r and Tsz Kong. &lt;br /&gt;
=== Creation of [[Sydneygag]] ===&lt;br /&gt;
Sydneygag was finally created in February 2023, after [[Herro]] and Card0 had discussed it for months. The page is also assisted by [[Livie]] and [[Megan chan]] who helped out with ideas.&lt;br /&gt;
&lt;br /&gt;
=== House Memes ===&lt;br /&gt;
In late March, Card0 began making house memes on the page, giving stereotypes of different school houses. This gave the page a lot of followers as Card0 began to also make university faculty memes.&lt;br /&gt;
&lt;br /&gt;
=== The Immaturity Issue ===&lt;br /&gt;
Throughout February and March 2023, members of the public began noticing a rise in immaturity, something many members of Staff were concerned about. As such, staff decided to take a harsher stance against it from March onwards, giving out more warnings, both verbal and formal, to people deemed immature, as well as a community forum post to address the issue.  &lt;br /&gt;
&lt;br /&gt;
=== Zy&#039;s Demotion ===&lt;br /&gt;
Due to his passive aggressiveness, [[Zy]] was deposed from President in Tsz Kong, alongside Pixel, who was his fellow MP, on April 2nd 2023. The two had been called out for their passive aggressiveness for a longtime and things reached a peak on the 2nd. Following this, Card0 made another plea in the main server to get more people in Tsz Kong, leading to a few new parties being formed. An election was held on the 4th which Farhan, having been unbanned from TK politics, won with his new party.&lt;br /&gt;
&lt;br /&gt;
=== Surpassing Hkmehmeh ===&lt;br /&gt;
For months, Hongkongggag was rapidly approaching Hkmehmeh in terms of follower count. On April 9th 2023, the page officially surpassed hkmehmeh with 64.4K followers compared to hkmehmeh&#039;s 64.3K. This was announced by Card0 in 852R, celebrating it as a huge milestone for Hongkongggag with it finally becoming the largest English meme page in Hong Kong, an achievement that he has continously touted when talking about the page&#039;s success.&lt;br /&gt;
&lt;br /&gt;
=== New Mods ===&lt;br /&gt;
On April 11th 2023, nominations for Moderator and Mediator were reopened. The same day, [[Citric Acid]] and [[Polaris]] were nominated and promoted the next day. This came after zo.loft resigned due to inactivity around the same time. Citric was nominated by Card0 in the past, but he declined though he changed his mind for his second nomination. &lt;br /&gt;
&lt;br /&gt;
=== Creation of the [[Inter Server Co-Operation Organization]] ===&lt;br /&gt;
On April 24th 2023, Card0 announced the creation of the Inter Server Co-Operation Organization, a forum for servers to meet and discuss ideas to improve their servers while also providing useful information that could help each other. The organization had 9 founding members though a few other servers would join shortly after its founding. &lt;br /&gt;
&lt;br /&gt;
=== [[852R SMP V2]] ===&lt;br /&gt;
Discussions of transferring the SMP to a paid host to boost activity began ages ago however it wasn&#039;t until April 26th 2023 when a poll asking people if they would play on a paid host (that would not require manually turning the server on and off). The results was an absolute majority however due to the old SMP&#039;s size, it was archived though not deleted. The new SMP went live at night the following day and was proven to be more popular than its predecessor.&lt;br /&gt;
&lt;br /&gt;
=== Ban of StormNinja25 ===&lt;br /&gt;
On the night of May 11th, following several discussions within staff and with Storm, Card0 annnounced that Storm would be banned from the server, though she would still be allowed to join the SMP. Storm had been banned for immaturity, hyper activity (as she was spamming to get higher on the MEE6 Leaderboard) and bothering others. To many, Storm was the main culprit of the server&#039;s general decline in maturity. Although some would defend Storm, many on both sides of the argument understood why staff had to ban Storm. &lt;br /&gt;
&lt;br /&gt;
Storm later rejoined the server on June 15, using her alt celestial_being#2425 (also known as 19371 uranus blep &amp;lt;4). Suspicious behavior, such as her nickname and trying to quickly earn back MEE6 levels, caused many to suspect celestial_being#2425 of being a Storm alt, confirmed by an independent investigation by Quattro and Hill. As a result, Storm was permenantly banned on June 19, 2023. &lt;br /&gt;
&lt;br /&gt;
On June 22, Storm&#039;s ban was officially downgraded to an indefinite ban with an additional 6 months when it was revealed that she was manipulated by Hoch into attempting to dox the server. She was also blocked from editing the wiki on June 24, in response to her creating pages for Hoch and Uranus and writing long rants on these pages, as well adding spam to other pages, the previous day.&lt;br /&gt;
&lt;br /&gt;
However, a month later, on July 22, Storm was permanently banned for the last time after attempting to dox flutters using their LinkedIn page. Since thetn, Storm has continued to harrass the server on multiple occasions such as spreading misinformation and having alts in the server/sympathetic members, though this has declined recently.&lt;br /&gt;
=== Hoch&#039;s Campaign and Ban ===&lt;br /&gt;
On June 2, 2023, [[Hoch]] posted his campaign for Mod in 852r-forum, encouraging others to show their support. Others also wrote official nominations for Hoch, which were accepted by Card0, who started a poll for Hoch&#039;s promotion on June 3. Despite most people voting in the poll approving of his promotion, many others also voted against, including many Staff members, which led Card0 (whose position was neutral on the issue of Hoch being mod), to extend the poll by 24 hours. &lt;br /&gt;
&lt;br /&gt;
Coincidentally, the June 4th Tiananmen Square vigil was held just hours before Hoch&#039;s poll ended. However, Card0 noticed that Hoch was getting into a heated argument with other members, such as [[Noknok05]], about US-China relations. This led to Card0 vetoing him for his behaviour. He later stressed that this was not due to Hoch&#039;s views, but more how he presented it, especially at a vigil for the Tiananmen massarce. Many agreed with this decision, largely due to the server&#039;s population being primarily pro-democracy. &lt;br /&gt;
&lt;br /&gt;
Despite this incident, Hoch continued to be an active member for a few weeks. Campaigns for staff positions were later banned by a poll, ensuring that a similar situation would not happen in the future.  &lt;br /&gt;
&lt;br /&gt;
On June 18, a debate was started in #debates about allowing transgender women to compete in biological women&#039;s sports. This debate quickly spiraled out of control, with Hoch making comments viewed by many as borderline transphobic. Because of this, he was issued a level 1 warning, leading to a 2 week ban, as he previously had another warning for insensitive comments. However, this was later raised to an indefinite ban, with Card0 stating that &amp;quot;Transphobia is not tolerated in 852r.&amp;quot; Hoch&#039;s Discord server was also unpartnered and removed from the ISCO.&lt;br /&gt;
&lt;br /&gt;
As a result of the transgender debate, LGBT-related topics were immediately banned from #debates, with flutters stating that &amp;quot;there is virtually nothing to debate&amp;quot; and that &amp;quot;we should not be defending and debating the existence of us.&amp;quot; This was later scrapped due to its unpopularity and some perceiving that it made no difference with Florida’s “Don’t say gay” law . &lt;br /&gt;
&lt;br /&gt;
Hoch&#039;s ban was upgraded to a permanent ban on June 22 when it was revealed that he manipulated Storm into attempting to dox Card0.&lt;br /&gt;
&lt;br /&gt;
=== New Prestiges ===&lt;br /&gt;
At 10pm HKT on June 11, 2023, a celebration was held for the 4th anniversary of 852 Resurgence. During the event, several former Vices were promoted to Prestige by Card0:&lt;br /&gt;
* [[Aqua]]&lt;br /&gt;
* [[Asianbarb]]&lt;br /&gt;
* [[AquaEclipse324]]&lt;br /&gt;
* [[Kix Kiefer]]&lt;br /&gt;
* [[Drotoch]]&lt;br /&gt;
* [[Hill]]&lt;br /&gt;
* [[Helia]]&lt;br /&gt;
* [[Celia]]&lt;br /&gt;
* [[Soviзт_Коммissaя]]&lt;br /&gt;
* [[NoodleCupKKv]]&lt;br /&gt;
* [[Sumii]]&lt;br /&gt;
* [[Coom]]&lt;br /&gt;
* [[Friedchilli]]&lt;br /&gt;
* [[Yosh]]&lt;br /&gt;
=== [[5th Anniversary]] ===&lt;br /&gt;
Compared to previous anniversary events, the 5th anniversary was planned to be larger in scale, with events being held across July with the main celebrations on the founding date of July 18th. Initially however, events saw low participation due to some members being on vacation. The server&#039;s activity also took a big dip, though things gradually improved just in time for the anniversary day.&lt;br /&gt;
&lt;br /&gt;
On the anniversary, many members made speeches congratulating the server, the page and [[Card0]], as the celebrations were meant to celebrate both the server and the page. The anniversary event was also streamed on Instagram, via Card0&#039;s phone though the quality was dubious. According to him, over 1000 people joined the stream on Instagram in total, leading him to deem the event an overall success despite the initial inactivity of early July.&lt;br /&gt;
&lt;br /&gt;
=== Boost in SMP Activity ===&lt;br /&gt;
The SMP was updated to 1.20 on July 21st 2023. Combined with promotion on Instagram, the server saw a boost in activity and members who only came for the SMP, much to Card0&#039;s surprise and delight. However, this would end once the summer holidays were over.&lt;br /&gt;
&lt;br /&gt;
=== New Wiki ===&lt;br /&gt;
On August 14th 2023, the wiki was transferred from its old host on Fandom to a new host on Mediawiki by [[Jasper]]. This was due to Jasper&#039;s offer to Card0, as well as Fandom becoming a less sustainable place to host a wiki.&lt;br /&gt;
&lt;br /&gt;
=== [[HKGAG Music Festival]] ===&lt;br /&gt;
Around late June 2023, [[Drotoch]] suggested a music festival to Card0, who agreed to host it in July. Sadly, due to a lack of participants confirming their participation before the deadline, this was pushed to August 23rd. Thankfully however, several musicians and singers joined with around 10 participants, including Drotoch, taking part.&lt;br /&gt;
&lt;br /&gt;
The event was an astounding success, with around 20-35 people viewing the event in total, including half of the musicians who had either showed up or sent one of their members to attend. Many of the members were blown away at the quality of the music, as some members thought that most of the songs would be memes, and not that serious. As a result, Card0 would hint that a smaller-scale Christmas event may be held later in the year, as well as a second one next year. [[flutters]] would also announce a film festival to be held later that year, though this was cancelled due to low interest. &lt;br /&gt;
&lt;br /&gt;
=== Creation of [[Singaporeggag]] ===&lt;br /&gt;
On August 26th 2023, [[Card0]] and a few of his close Singaporean associates via [[Hongkongggag]] launched [[Singaporeggag]], the fourth sister page in the page&#039;s history, fifth including [[Flutters]]&#039;s page: hkg.flutters. &lt;br /&gt;
&lt;br /&gt;
=== [[Hanappe]] 1 Year Anniversary Vigil ===&lt;br /&gt;
On October 14th 2023, a vigil was held in commemoration of Hanappe, who had died exactly 1 year before. Members such as Card0, Drotoch and asianbarb made speeches commemorating her life.&lt;br /&gt;
&lt;br /&gt;
=== [[Hongkongggag Creative Writing Contest]] ===&lt;br /&gt;
On December 3rd 2023, Card0 announced a creative writing contest for people to submit stories to. He would receive a grand total of 14 submissions, which were then judged by 3 of Card0&#039;s real life friends throughout January and February. The winners were announced on February 28th 2024.&lt;br /&gt;
&lt;br /&gt;
== Era of Strife (Februrary 2024-November 2024) ==&lt;br /&gt;
From April 2024, and increasingly from July-August 2024 onwards, several reforms and new ideas were put forward in regards to the community and page. However, this era would mark some drama in the server, especially among the Staff team as significant disagreements became commonplace. Initial reforms, as well as new ideas, were soon overshadowed by conflict within the Staff team. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Staff during this period:&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
Founder: Card0&lt;br /&gt;
&lt;br /&gt;
Admins: flutters, Lemontea, Salmon, Andi, Bossuuu, Tolmo, Jasper&lt;br /&gt;
&lt;br /&gt;
Moderators: Lieutenant.Quattro, Sayonara, Sage, Greentea, zt, Astra, Polaris, Sumii, Ame, Saera, Boba, Salami, Livie, Chris, Thoth, Ame, aaronforce1, Sleepy, Tuck&lt;br /&gt;
&lt;br /&gt;
Promotions: Saera (July 2024)&lt;br /&gt;
&lt;br /&gt;
Resignations: aaronforce1, Andi, flutters (November 2024)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Notable members who joined during this era:&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
* [[Eris]]&lt;br /&gt;
* [[kyli3_3]]&lt;br /&gt;
* [[Caine Park]]&lt;br /&gt;
* [[charlottew]]&lt;br /&gt;
* [[callmeken0.0]]&lt;br /&gt;
* [[bighands_punchyou]]&lt;br /&gt;
* [[Toaster]]&lt;br /&gt;
* [[OJ]]&lt;br /&gt;
* [[Morse.dot.bao]]&lt;br /&gt;
* [[tribal]]&lt;br /&gt;
* [[Joohj]]&lt;br /&gt;
* [[aaronjaegar_]]&lt;br /&gt;
* [[Aqua Marine]]&lt;br /&gt;
* [[Scummyprincessathena]]&lt;br /&gt;
* [[Ramajaya81]]&lt;br /&gt;
* [[Number 21]]&lt;br /&gt;
* [[Yoshipie]]&lt;br /&gt;
* [[Victorian]]&lt;br /&gt;
* [[Rafale915]]&lt;br /&gt;
* [[smallping]]&lt;br /&gt;
* [[Ari]]&lt;br /&gt;
* [[nonsense_man]]&lt;br /&gt;
* [[Mag]]&lt;br /&gt;
* [[_Typical]]&lt;br /&gt;
&lt;br /&gt;
=== Tuck Diarrhea Bussy Incident ===&lt;br /&gt;
On February 6th 2024, [[Andi]] pinged @here in funny-quotes with the following message:&lt;br /&gt;
&lt;br /&gt;
&amp;quot;give me that diarrhea bussy - @Tuck to @Card0&lt;br /&gt;
@here&amp;quot;&lt;br /&gt;
This caused mass confusion amongst those who were pinged, with some expressing fear at the incident, which included Card0 himself.&lt;br /&gt;
=== February 18th 2024 Vandal Incident ===&lt;br /&gt;
On February 18th 2024, a suspected quadruple Storm Alt attack occurred on the wiki&lt;br /&gt;
&lt;br /&gt;
At 10:54 GMT+8, a user of &amp;quot;Youknowwhatyoudid&amp;quot; registered, and replaced the whole [[852 Resurgence]] page with the following quote:&amp;lt;blockquote&amp;gt;&#039;&#039;&amp;quot;Corruption. Stupidity. You know what you did. You will pay for this.&amp;quot;&#039;&#039;&amp;lt;/blockquote&amp;gt;The edits were swiftly reverted and the user was banned not even 5 minutes after the incident. Another alt registered on the same day at 15:50 GMT+8 called &amp;quot;Littlebitch&amp;quot; where the alt replaced the introductory line to [[Zt]]&#039;s page &amp;quot;zt, or Hazel is a member of 852 Resurgence.&amp;quot; with:&amp;lt;blockquote&amp;gt;&#039;&#039;&amp;quot;zt, or Hazel is a bitch.&amp;quot;&#039;&#039;&amp;lt;/blockquote&amp;gt;Within 10 minutes, the content was reverted and the alt was banned. But at 16:03pm HKT , a user named Rigged registered to the wiki, where 3 edits were made to [[Hongkongggag Community Awards]]. The first was adding the word &#039;Rigged&#039; at the start of the wiki page, the second was adding a second &#039;Rigged&#039; to make &#039; RiggedRigged&#039; before blanking the page completely. At 16:27pm the page was reverted and they were promptly banned.&lt;br /&gt;
&lt;br /&gt;
An hour later at 17:42pm, a user of Theoriginaldoxxer was registered, but a London IP Address changed the content of [[Luminous|lumi]]&#039;s page to allegations of them being a doxxer, alongside death threats. Then, a the user Theoriginaldoxxer added a rickroll to the page. The changes were reverted ASAP. Some members speculated that this was [[Hoch]], though evidence was limited in terms of his guilt.&lt;br /&gt;
&lt;br /&gt;
=== Channel &amp;amp; Role Reform ===&lt;br /&gt;
With new Discord updates, [[flutters]] configured and announced that the role selection menu had been moved in light of Discord&#039;s new role selection feature, while also allowing members to pick and choose which channels they can see in the server.&lt;br /&gt;
&lt;br /&gt;
=== New Ambassadors ===&lt;br /&gt;
On March 12th 2024, Card0 promoted the following affiliates to ambassadors, marking the largest bulk promotion of affiliates up to that point.&lt;br /&gt;
&lt;br /&gt;
The following affiliates were promoted:&lt;br /&gt;
&lt;br /&gt;
* [[Nox]]: Ambassador for Clearwater Bay&lt;br /&gt;
* [[Saera]]: Ambassador for Fu Tung&lt;br /&gt;
* [[Drotoch]]: Ambassador for Sai Kung North&lt;br /&gt;
* [[Cursedcitrus]]: Ambassador for Lam Tin&lt;br /&gt;
* [[Katra]]: Ambassador for NAIS&lt;br /&gt;
* [[AvianStupid]]: Ambassador for Po Lam&lt;br /&gt;
* [[Nigel]]: Ambassador for VTC&lt;br /&gt;
&lt;br /&gt;
=== Continued Wiki Vandalisms ===&lt;br /&gt;
Throughout the end of February and the start of March, the wiki was vandalised multiple times by random trolls, leading to a restriction on account creation for the Wiki on March 13th 2024 by Jasper. This would be lifted a few months later.&lt;br /&gt;
&lt;br /&gt;
=== Ballsdex and Inactivity ===&lt;br /&gt;
On January 9th 2024, Card0 introduced the Ballsdex bot to the server: a bot that spawned random countryballs for members to catch. While initially liked, a few members wanted them in another server leading to a poll being held by flutters on January 15th. However as the poll was very close, Ballsdex continued to spawn in #general. [[Ceadz]] would also introduce a HK version of it: [[hkdex]] to the server around the same time.&lt;br /&gt;
&lt;br /&gt;
With inactivity rising throughout March, Card0 would make a post on March 16th 2024, asking why inactivity was an issue as of late, especially with good follower growth at the time. While some people pointed out that they were busy with exams and assessments, a few mentioned that because of Ballsdex spam, they have been less motivated to speak as it would often cut into conversations. As such, Card0 made a poll that same day asking if the bot should be moved, which saw a majority vote in favour. Card0 would then end the poll early and move both Ballsdex and hkdex to #minigames-bots. However, ballsdex&#039; removal did not increase activity, as activity levels remained low due to many members having exams.&lt;br /&gt;
&lt;br /&gt;
=== Impact of Article 23 ===&lt;br /&gt;
On March 19th 2024, Article 23 was passed in Hong Kong, marking the further encroachment of China on Hong Kong and an expansion of the national security law introduced in 2020. As such, many across the server and following the page were concerned for the page&#039;s future, as well as Card0&#039;s safety as the man behind the page. In response, Card0 made a statement advising for calm, while also encouraging members to be hopeful that one day the city would be free, and in the meantime to enjoy as much of Hong Kong as they can if they were still in the city. This statement was published on Tuesday morning, a couple hours before the law was passed in LegCo, before being posted on the Instagram story later that day.&lt;br /&gt;
&lt;br /&gt;
Responses to the statement were supportive across both the server and instagram page, with many expressing their continued support for Card0 and Hongkongggag. Unlike the NSL in 2020, Card0 had no plans concerning setting the page or server to private, though he reiterated to many people that several precautions had been put in place in regards to his safety, and the page&#039;s longevity. &lt;br /&gt;
&lt;br /&gt;
=== ISCO Expansion ===&lt;br /&gt;
During May and early June of 2024, the [[Inter Server Co-Operation Organization]] expanded, seeing new members added in order to better connect 852R&#039;s different partnered servers, many of which had owners who were on good terms with Card0. In addition, the HK Meme Page Alliance saw some expansion during April-May, though this was more minor and not as drastic.&lt;br /&gt;
&lt;br /&gt;
=== Support of br0wnhub and humourofhk ===&lt;br /&gt;
Following [[br0wnhub]]&#039;s return to activity, and the revival of [[humourofhk]], the latter of which had been mysteriously taken down by Instagram. Hongkongggag would greatly support both pages by collaborating with them on memes, while also tying the three pages closer, something that had been done before with Memes of HK.&lt;br /&gt;
&lt;br /&gt;
=== Announcing Card0&#039;s Stepback ===&lt;br /&gt;
For a while, Card0 had briefly thought about retiring from the server, something he mused he would do in 2025/2026. However, he had not made any concrete plans until June 2024, when he announced at the community anniversary that he planned to step back in late 2025 at the earliest, with 2026 as a more realistic date, in favour of [[flutters]] who would be designated as his official successor. While the announcement was made in June, he had already begun thinking about in April-May, though he decided to announce it early so that it wouldn&#039;t be too surprising. He also announced his plan to promote [[Astra]] and [[Greentea]] to Admin to help flutters, while also elaborating that he felt that a disconnect had grown between him and some members, as well as his real life circumstances with him saying that he had been spending more time with friends post-pandemic compared to pre-pandemic and during the pandemic. He also mentioned that previous incidents also influenced his decision, believing that for the sake of his mental health it was better for other staff members to deal with them in the future. Despite this, he stressed that he would still be around and would help approve staff decisions, just that he wouldn&#039;t want to deal with everything.  &lt;br /&gt;
&lt;br /&gt;
Most people reacted with little surprise, as some people had expected such an announcement would come sooner or later. However, this plan would change somewhat, with the plan being changed to a &amp;quot;collective leadership led by flutters&amp;quot;, before the plan was scrapped after flutters was resigned for pure collective leadership, at least amongst the admins. &lt;br /&gt;
&lt;br /&gt;
=== [[852MUN]] ===&lt;br /&gt;
Although announced in April 2024, the event would be hosted by [[Saera]], [[Sleepy]] and [[Hill]] on July 20th 2024, seeing around 30-45 people attending, representing different countries.&lt;br /&gt;
&lt;br /&gt;
=== Patreon and Sponsorships ===&lt;br /&gt;
On July 9th 2024, Card0 announced the creation of a Hongkongggag Patreon, which would have some exclusive contents in the form of memes, while also guaranteeing patreons a monthly shoutout. However, it did not receive much attention or popularity, with only two people subscribing, with the Patreon shutting down in October. &lt;br /&gt;
&lt;br /&gt;
Later on in July, Card0 made a poll on his story, asking his followers on whether they would be okay with sponsorships, with around 55% voting in favour. The first sponsored, with the Aero-Thai Flying School, went live the other day.&lt;br /&gt;
&lt;br /&gt;
=== Staff Rank Reforms ===&lt;br /&gt;
On July 26th 2024, Card0 announced special staff roles for specific members of Staff that focused on the expansion of the community and page. Not long after this, on August 12th 2024, Card0 announced a proposal to reform it so that all Mediators would gain Moderator ranks, due to the former&#039;s ambigious role. [[Andi]] would also put forward a similar proposal but for technicians. Both saw unanimous approval in polls, as all existing Mediators and Technicians became Moderators the next day.&lt;br /&gt;
&lt;br /&gt;
=== [[2024 HKGAG Music Festival]] ===&lt;br /&gt;
A second HKGAG Music Fesitval was hosted by Card0 and [[Drotoch]] on August 23rd 2024, which saw 13 musicians submitting songs for the festival, including 3 bands. Some singers, like [[Fxith]] and [[The Lemon Ones]] would re-submit, while others such as [[Issah]] were newcomers. &lt;br /&gt;
&lt;br /&gt;
While the event didn&#039;t see as many people join as the previous festival, around 20-25 people still joined the event, leading to Card0 to deem it a sucess.&lt;br /&gt;
&lt;br /&gt;
=== [[2024 August-September Reforms]] ===&lt;br /&gt;
Several staff would promote server reforms throughout August and September. Card0 would approve this and suggest making discussion about a rules revamp public, which led to an open discussion about server reforms throughout August and September. During this time, the rules would be clarified, while other associated reforms occured, such as the introduction of specified staff roles such as Affiliate Recruiter, and the return of [[Sleepy]]&#039;s bots which had been down for some time, having been improved with new code from [[Jasper]]. A [[Marketing Council]], led by [[Joyce]] was also created. The page also saw an influx of new affiliates. The new rules would finally be implemented after a poll, on September 26th. &lt;br /&gt;
&lt;br /&gt;
=== Hongkongggag Census 2024 ===&lt;br /&gt;
A second census was published on September 15th 2024, as the first one in 2023 was a success. The census was like the first time, published in both the server and page, with most people responding to it believing that while the page was still good, it had slightly gone down in terms of quality, though some in the census believed that this was part of a general trend. Despite this, Card0 began to change course with both the server and the page, focusing on improving the quality and creativity of the memes.&lt;br /&gt;
&lt;br /&gt;
=== Overseas Events ===&lt;br /&gt;
During September and October, [[Ame]] and [[Andi]] spearheaded the idea of overseas events, specifically in the Pacific and British timezones respectively, in hopes that this would attract members of the page living in other timezones. While these events saw some success, ultimately they were quietly discontinued as attendance was lower than expected.&lt;br /&gt;
&lt;br /&gt;
=== October-November Warnings ===&lt;br /&gt;
Throughout October and November, several members, mainly new members but also some established members, would be warned or banned depending on the severity of what they did, most of whom would be warned for their behaviour in discussions. As such, some in the Staff team became disillusioned with the server, and fears began to grow amongst certain staff members over the future of the server.&lt;br /&gt;
&lt;br /&gt;
=== November Follower Crash ===&lt;br /&gt;
In the leadup to the 2024 US elections, there were many debates on whether Trump or Harris would win, with some members even watching the coverage live. However, as it became more obvious that Trump would win, Card0 would prepare for damage control, while also writing a statement of hope and inspiration to both the server and page. &lt;br /&gt;
&lt;br /&gt;
Around 6pm HKT, 3 hours after Trump was all but confirmed as the victor, Card0 posted the statement on both platforms. While the reception to the statement was largely positive, the same could not be said for the page as many pro-Trump followers commented on the page, though several anti-Trump followers would share the post and like it. The post quickly reached thousands of comments and hundreds of likes, while also leading to 597 people unfollowing the page in one single day, the most in the page&#039;s history. However, Card0 later saw this as a victory, believing that with significantly less pro-Trump followers, the page would be further committed to progressive and left-wing ideals.&lt;br /&gt;
&lt;br /&gt;
=== [[October-November Staff Crisis]] ===&lt;br /&gt;
For years, there had been disagreements between Card0, [[flutters]] and [[Andi]] on the direction of the server, with flutteres and Andi often criticising Card0 on many of his decisions, sometimes joined by other Staff. On many occassions, Card0 would back down or come to a compromise, with things usually being resolved relatively quickly. It should be noted that the latter two staff were some of the most influential Staff, even more than the other Admins, so they held more sway over the direction of the server. Despite their disagreements, when Card0 announced his stepback, he would designate flutters as his de-facto successor, with the plan for them to lead day to day operations of the server.&lt;br /&gt;
&lt;br /&gt;
However, this would change in October as within Staff, a concern had been raised by [[Boba]] on the status of underage moderators in the university-graduated channel. While that channel was not a 18+ NSFW channel, the nature of having minors in a channel designated for adults made Boba uncomfortable, who pitched it to Card0 IRL who sent it in Staff. This then caused a heated debate between flutters and Andi, with both members clashing over the status of minors, with [[Thoth]] agreeing with the proposed change, while [[Saera]] disagreed. As Boba initially raised the concern due to Saera texting in the channel for uni advice, flutters would threaten Saera with demotion if she continued to use the channel, which led to Andi clamping back hard, forcing other Staff like [[Zt]] to step in and calm the situation. At the time, Card0 was outside so he didn&#039;t see the message sent by flutters, and simply urged a message of calm before going back to what he was doing in real life. In the end, no poll was made in regards to the proposed change. &lt;br /&gt;
&lt;br /&gt;
After the incident, Andi, with Card0 still upholding flutters as his designated successor (not helped by the fact that Card0 had not made it too clear on the exact arrangements of his step back), began to become more dissatisfied with his leadership. Saera would also come to agree, having aligned more with Andi over the course of her term as mod. &lt;br /&gt;
&lt;br /&gt;
While the situation in Staff may have remained cool in other times, October-November also marked a shift for the page and server with multiple warnings as well as a shift in the server&#039;s activity, though for the latter this had been a trend for a few months. On November 16th, following another argument between flutters and Andi, Andi and Saera began to believ e that the server simply wasn&#039;t growing, and that massive reform was needed, which included better disciplinary communications, clearer moderation guidelines, as well as less bias overall. There were also discussions about thinking about how big the server needed to be, with Andi and Saera thinking that the server had grown too big with some Staff feeling alienated from some members in the community. Another reform, later included, involved stricter citizen entry requirements. With Andi and Saera seeing that only older members remained the most active, three proposals were later made:&lt;br /&gt;
&lt;br /&gt;
# Reform the server and make it appeal to a wider range of people.&lt;br /&gt;
# Define an age group to target and appeal to them only.&lt;br /&gt;
# Make the server into a smaller close friends server&lt;br /&gt;
&lt;br /&gt;
Although most Staff including Card0 agreed with the first option and the bulk of the reforms, the second option was seen as more controversial, with the third being immediately vetoed by Card0 as a no-go, though Saera and Andi did propose minimising the server significantly if the member growth of the server continued to decline. This caused a lot of arguing between the two, with many other Staff on the sidelines, with Card0 criticising the over-formality of the reforms, while Andi and to an extent, Saera, criticising Card0&#039;s leadership as holding the server back. Andi also increasingly believed Card0 should move on from the server, which was somewhat echoed by Saera. Other Staff also voiced their views, with [[Tuck]] agreeing with most of the reforms save for the formal language, while [[Zt]] pointed out that the server had an issue with cliques, and [[Salami]] arguing that while the reforms were a step in the right direction, the over-formality was not ideal. Boba would later comment on the reforms, agreeing with Salami on the concepts, but also pointing out how many of the reforms were too formal.&lt;br /&gt;
&lt;br /&gt;
In the end, some of the proposed reforms were never carried out due to the resignation of Andi, and later flutters (Saera would be promoted to temporary Admin until her own resignation in January). Any proposal to downsize the server or priotise older members was never carried out. However reforms to #introductions as well as later reforms in 2025 by Salami over the rules would be passed. As Andi had announced his resignation in late November alongside flutters shortly after, Card0 would dm and seek the consent of [[Astra]] and [[Greentea]] to be promoted to Admin. In addition, he also talked with Syntax, Nigel and Joyce to promote them to Moderator.&lt;br /&gt;
&lt;br /&gt;
=== Transition in Leadership ===&lt;br /&gt;
On December 1st, 2024, Andi and flutters stepped down, after announcing their resignations a few days earlier, having also announced it to the Staff teams days earlier. On November 29th 2024 at 8:04am HKT, Andi released his statement.     &lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
Dear 852 Resurgence community, &lt;br /&gt;
&lt;br /&gt;
It has been a tumultuous three years being a member of 852 Resurgence, with most of them spent as a staff member for which I am very honoured to have served as. &lt;br /&gt;
&lt;br /&gt;
Since beginning a full-time 9-to-5 job here in the UK, and with recent developments at my company promising a significant increase in my workload, I&#039;ve found a need to make more time for myself to prioritise my mental health and wellbeing. I also recognise that my job has disconnected me from the most active times of this server. &lt;br /&gt;
&lt;br /&gt;
In addition, in my role as a Mod, Senior Mod and now Admin I have had to deal with behind-the-scenes drama within the staff team as well - I won’t go into any details, or discuss them with anyone outside the staff team since these have now been reconciled with agreement from all parties.&lt;br /&gt;
&lt;br /&gt;
It is therefore with a heavy heart that I hereby announce that I will be resigning my position as a staff member of this server, effective from 00:00 GMT on Sunday 1 December 2024. &lt;br /&gt;
&lt;br /&gt;
I’ll still be around in the server as a friendly face, sharing my experiences and knowledge with people here.&lt;br /&gt;
&lt;br /&gt;
It has been a genuine pleasure to serve the 852 Resurgence community as a staff member, and I wish all other staff members the best in guiding the community forwards.&lt;br /&gt;
&lt;br /&gt;
Remember, if you see something that doesn’t look right, speak to a staff member, or use the #⁠reports channel. They’ll sort it. See it. Say it. Sorted.&lt;br /&gt;
&lt;br /&gt;
Yours sincerely,&lt;br /&gt;
&lt;br /&gt;
Andi&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
Similarly, flutters made a similar statement hours later at 3:17pm HKT. &lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
hey all, &lt;br /&gt;
&lt;br /&gt;
yes yes... i am also retiring...&lt;br /&gt;
&lt;br /&gt;
i&#039;ve been here since 2019 on hongkongggag and 852r as an admin and i think its time for me to go...&lt;br /&gt;
&lt;br /&gt;
my contributions to the community slowly declined and i&#039;ve felt a little disconnect between the community, the instagram page and myself. this is most likely due to the lack of time spent to university and mental health. &lt;br /&gt;
&lt;br /&gt;
i may remain at 852r but i will no longer act as administrator.&lt;br /&gt;
&lt;br /&gt;
i wish everyone a merry christmas in advance and i will be making christmas hats on pfps still ;)&lt;br /&gt;
&lt;br /&gt;
happy holidays,&lt;br /&gt;
flutters&lt;br /&gt;
&lt;br /&gt;
Instagram @hkg.flutters&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In addition, [[Aaronforce1]], a long-standing Staff member while also having been inactive for months, would be demoted.  &lt;br /&gt;
&lt;br /&gt;
At the same time, the community welcomed fresh leadership: [[Astra]] and [[Greentea]] were promoted to Admin, while Nigel, Joyce, and Syntax were promoted to Moderator, all chosen through community polls two days earlier. All 3 moderators had qualities that they bought to the Staff team: [[Nigel]] was a trusted Ambassador despite having joined recently in 2023; Joyce was another Ambassador and head of the [[Marketing Council]] who had been active in the server since 2021; and Syntax was a former Mod who had resigned in 2021. Their promotions weren’t just about filling gaps but reshaping the server’s future, giving a new sense of leadership to the server. This was especially important as in the few months leading up to their resignations, there had been not only concerns about the direction the server was going in with warnings, but also conflict within the Staff team. Moreover, [[Saera]] would take on the role of Admin temporarily, though she would resign on January 11th 2025. &lt;br /&gt;
&lt;br /&gt;
December 1st also marked a transition into a new era for the server, with Nigel in particular semi-humorously describing the promotions as &amp;quot;the next generation of leaders&amp;quot;, something Card0 supported, while also drawing comparisons ironically between the Staff Team and the CCP Politburo.&lt;br /&gt;
&lt;br /&gt;
== Hongkongggag Renaissance (December 2024-December 2025) ==&lt;br /&gt;
With a transition in leadership, new reforms, more new citizens in the server, as well as increasing follower numbers in 2025, Card0 would officially announce on March 18th 2025 that a new era had (retroactively) begun: the Hongkongggag Renaissance. The new era was characterized by structural and creative innovation, including the 18 District Miku Project,  the creation of the International Queer Initiative, and Card0’s formal step back from daily operations, a transition he had planned for years. The year ended with the community rallying to provide aid after the Tai Po fires and the fifth Community Awards.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Staff during this period:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Founder: Card0&lt;br /&gt;
&lt;br /&gt;
Admins: Lemontea, Salmon, Tolmo, Bossuuu, Jasper, Astra, Greentea, Salami, Joyce&lt;br /&gt;
&lt;br /&gt;
Moderators: Lieutenant.Quattro, zt, Polaris, Sumii, Ame, Saera, Boba, Livie, Chris,  Sleepy, Tuck, Nigel, Syntax, Expired Potato, Asianbarb&lt;br /&gt;
&lt;br /&gt;
Promotions: Nigel, Syntax, Joyce (December 2024), Expired Potato (May 2025), Asianbarb (July 2025)&lt;br /&gt;
&lt;br /&gt;
Resignations/Demotions: Saera (January 2025), Thoth (February 2025), Sage (May 2025), Sayonara (July 2025)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Notable members who joined during this era:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [[GravityDuke]]&lt;br /&gt;
* [[Blue]]&lt;br /&gt;
* [[Yuma]]&lt;br /&gt;
* [[Vespera/MV3 no.1 fan]]&lt;br /&gt;
* [[Thunderstruck]]&lt;br /&gt;
* [[bleu]]&lt;br /&gt;
* [[g.l.a.c.e]]&lt;br /&gt;
* [[d8vids]]&lt;br /&gt;
* [[leleafy767]]&lt;br /&gt;
* [[PresidentLee]]&lt;br /&gt;
* [[Diffusion]]&lt;br /&gt;
* [[Sleepy (woke)]]&lt;br /&gt;
* [[Tingaling]]&lt;br /&gt;
* [[Brob]]&lt;br /&gt;
* [[Unyleeyu]]&lt;br /&gt;
* [[Del]]&lt;br /&gt;
* [[everosely]]&lt;br /&gt;
* [[Natello 27848]]&lt;br /&gt;
* [[Aurelia]]&lt;br /&gt;
* [[TearCea]]&lt;br /&gt;
* [[Darwin]]&lt;br /&gt;
* [[Chzvii]]&lt;br /&gt;
* [[Tank]]&lt;br /&gt;
* [[mrchatbubble]]&lt;br /&gt;
* [[Daniel]]&lt;br /&gt;
* [[Pentl]]&lt;br /&gt;
* [[Adri@n]]&lt;br /&gt;
* [[Raymond]]&lt;br /&gt;
* [[Saltedline]]&lt;br /&gt;
* [[Tobyistheguy]]&lt;br /&gt;
* [[Geom]]&lt;br /&gt;
* [[black_cat0201]]&lt;br /&gt;
* [[SaltHatter]]&lt;br /&gt;
* [[Cel]]&lt;br /&gt;
* [[Cardigan Paradeau]]&lt;br /&gt;
* [[Ks. .5331]]&lt;br /&gt;
&lt;br /&gt;
=== 2024 Community Awards ===&lt;br /&gt;
The Fourth [[Hongkongggag Community Awards]] were hosted on December 12th 2024, which marked the first awards ceremony to not be co-hosted or co-planned by [[flutters]]. The event was hosted by Card0 as well as some other Staff members like Astra, Syntax and Zt. Around 30 people received awards, with around 30 people in total attending, though only around 20 people were in the VC at any given time. In addition, several categories were open for public voting, including the Member of Impact Award, which was awarded to [[Nigel]].&lt;br /&gt;
&lt;br /&gt;
=== Expanding Page Access ===&lt;br /&gt;
On January 25th 2025, after weeks of deliberation, Card0 announced he was, for the first time in years, expanding page access to 2 admins, those being the newly promoted [[Astra]] and [[greentea]]. These two Admins were also the first Admins with access to the page that didn’t come from the old WhatsApp group, with [[Lemontea]] and [[Salmon]] having page access from during the early period of the page. &lt;br /&gt;
&lt;br /&gt;
=== Follower Boom ===&lt;br /&gt;
February marked a pivotal moment for Hongkongggag as the page experienced a sudden surge in followers, riding a wave of renewed interest that swept across Hong Kong’s meme scene. New formats like viral starter packs roasting local schools and neighborhoods that resonated with people, while new reels capitalized on trending audio clips. Collaborations with pages like br0wnhub, majorcantotraits, chaoshongkong, and thehkobserver amplified reach, increasing the follower count of the page. &lt;br /&gt;
&lt;br /&gt;
Behind the numbers, though, was a shift in creative energy, accompanied by a shift in the energy of the Staff team. Memes became sharper, more self-aware, and unapologetically local, with a return to more community participation in helping make memes, something that had been lost during late 2024. With this, the community realised that the vibe of the page was shifting, especially as Hongkongggag became more dominant in the Hong Kong English meme page sphere, regaining more of its influence that had been dormant for a while. &lt;br /&gt;
&lt;br /&gt;
=== Creation of the [[Advisory Groups]] ===&lt;br /&gt;
To help with improving tier lists, as well as a new format: bingo card templates, Card0 would create two new advisory groups: the [[Tier List Advisory Group]] and the [[Bingo Card Advisory Group]]. These groups helped improve the quality of bingo cards and tier lists. He would later create the [[Shenzhen Memes Advisory Group]].&lt;br /&gt;
&lt;br /&gt;
=== [[18 District Miku Project]] ===&lt;br /&gt;
Although this project had begun in September 2024, the project was completed on March 9th 2025: Miku Day, following several delays. Initially, while Card0 wanted the project to be done in December, this was scrapped. Card0 had organised this alongside [[Rena]] and [[TearCea]], who and 16 additional artists helped create a Hatsune Miku OC for every district in Hong Kong. Despite difficulties, the project was deemed a relative success by its organizers. &lt;br /&gt;
&lt;br /&gt;
=== Technological Reforms ===&lt;br /&gt;
Throughout March, a few reforms were created in the server to help streamline the process for new members in the server. Specifically, the new introduction system was fixed by [[Syntax]] to make it so brand new people joining the server had to send an introduction, with no texting access to any other channel at all, before they could be given the citizen rank. More importantly, [[Jasper]] implemented automatic ranks that were given through Arcane levels, making the system automatic for the first time.&lt;br /&gt;
&lt;br /&gt;
=== International Queer Initiative ===&lt;br /&gt;
After a few months of planning, following its proposal by Card0 in Vision 2025, the [[International Queer Initiative]] was announced to the public on March 27th 2025, with a few LGBT+ pages, most of them based in Hong Kong as its first members. The group aimed to spread LGBT awareness and co-share news/petitions/resources together.&lt;br /&gt;
&lt;br /&gt;
=== Spring Follower Boom ===&lt;br /&gt;
For the first time in a while, Hongkongggag had experienced a major follower boom, in the sense that the page would go from 86K to 90K in the span of a week. Although follower growth had been fairly positive since late 2024, things would improve drastically in March as well as April, with a few posts going semi-viral. This continued into May, with school starter packs, as well as other semi-viral memes.&lt;br /&gt;
&lt;br /&gt;
=== [[Pokemon TCG Pocket Tournament]] ===&lt;br /&gt;
With the popularity of Pokemon TCG Pocket, Card0, alongside [[Joyce]] decided to co-host a Pokemon TCG Pocket Tournament, with over 20 players taking part. The winner, decided by coin toss as a result of the other person being suddenly unreachable, was [[Renee]].&lt;br /&gt;
&lt;br /&gt;
=== Hitting 100K ===&lt;br /&gt;
Thanks to a surge in followers, fueled by a string of semi-viral memes, the page’s growth skyrocketed throughout early 2025. By May, hitting 100K followers wasn’t just a hopeful milestone; it was practically inevitable. Card0, [[Tolmo]] and [[Polaris]] had initially guessed it would happen before July, but as engagement kept climbing, the timeline shifted. By May 10th, the numbers were rising so fast that reaching the goal by the end of the month seemed almost certain, if not within the week.  &lt;br /&gt;
&lt;br /&gt;
On the night May 12th 2025, with the follower count being so close, an impromptu watch party, which saw around 25 people join, was held in the server as Card0 implored everyone he knew to get others to follow. And at around 10:12pm, the page hit 100K, though the number fluctuated slightly for 15 minutes. This was marked by celebration in the voice call, as well as reactions in the server and page at large. &lt;br /&gt;
&lt;br /&gt;
=== Card0&#039;s Step Back ===&lt;br /&gt;
From June/July onwards, [[Card0]] formally stepped back from his server responsibilities. While he remained semi-active to active within the community, he no longer handled the day-to-day administrative tasks, which included managing smaller server operations like issuing punishments or dealing with problematic members. In addition, other staff members began to take a more active role in the server. He also encouraged non-staff members to host more events in the server. &lt;br /&gt;
&lt;br /&gt;
In addition, this period also saw the promotion of new Staff to the team, with [[Expired potato]] promoted on May 30th 2025, and [[Asianbarb]] on July 11th 2025. In addition, both [[Salami]] and [[Joyce]] to the role of Admin on May 25th 2025 also solidified the leadership transition of December 2024, with Joyce gaining page access as well. Inactive moderators [[Sage]] and [[Sayonara]] would be demoted around the same time as well.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note: [[Thoth]] resigned in January 2025 as well, due to real life reasons.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
=== [[Blood on the Clocktower]] ===&lt;br /&gt;
Throughout the summer, [[Number_21]] would host a variety of sessions of Blood on the Clocktower biweekly, a social deduction game similar to Mafia/Werewolf. This event was also promoted on the page, and saw considerable popularity. &lt;br /&gt;
&lt;br /&gt;
=== [[2025 HKGAG Music Festival]] ===&lt;br /&gt;
With the success of the previous two Music Festivals in [[2023 HKGAG Music Festival|2023]] and [[2024 HKGAG Music Festival|2024]] respectively, a third MusicFest was announced in June 2025, with the submission deadline set to August 12th. However, this time the competition was slightly changed as it would include a competition format, in which artists would be given a score out of 10 by [[Boba]] who was serving as the Judge, and the winner being the one with the highest score. This also marked the first MusicFest to not include [[Drotoch]], who was unable to host the event. In addition, the event was pushed to August 16th for a few days, before it was delayed back to its original date of August 17th.&lt;br /&gt;
&lt;br /&gt;
During the event, over 25-30 people joined the event, though there were also technical difficulties on Card0&#039;s side. This also marked the longest MusicFest in terms of time with the event lasting for 2 hours. The winner was [[The Lemon Ones]], with [[Ombré]] coming in 2nd place, and [[Marcus Pangregrew]] in 3rd.&lt;br /&gt;
&lt;br /&gt;
=== TearCea Incident ===&lt;br /&gt;
On October 12th 2025, Card0 made an announcement in the Affiliates group chat on Instagram, asking that he would be accepting new applications for Ambassador, in the hopes that a new round of affiliates can be promoted, the first in over a year. [[TearCea]], having helped Card0 a lot on the [[18 District Miku Project]] as well as other advisory groups, applied to join, however Card0 vetoed him on the grounds that he was too passive-aggressive, while also trusting misinformation from banned members before even clarifying with Card0. Shortly after, TearCea accused Card0 of covering up incidents in the server, despite counter-arguments by Card0 and [[Nigel]], he then proceeded to send a screenshot of staff-chat, which he didn&#039;t elaborate on how he found it. As staff-chat was obviously supposed to be private, Card0 tried to get him to explain where the screenshot came from, but TearCea would then leave both the server and chat.&lt;br /&gt;
&lt;br /&gt;
Shortly after, TearCea was formally demoted from both Affiliate, and his role in the advisory chats (Card0 had already told him he would be demoted after sharing misinformation about covering up incidents). &lt;br /&gt;
&lt;br /&gt;
=== Password Crisis ===&lt;br /&gt;
Around 11pm HKT on November 2nd 2025, Card0 reported that someone had sent an odd message on the account in the Tier List Advisory Group, as none of the Admins who had access to the account said that they sent it, Card0 thought that this was a security breach, with someone somehow gaining access to the page. He the resetted the password, however upon sending it to the other Admins with page access, they said that they couldn&#039;t login, with Card0 being unable to login on other devices. Later that night, Card0 would make an announcement in the vice-and-above channel asking for help, with [[catgirlmutant]] providing most of the advice alongside other Staff such as [[Astra]] and [[Polaris]]&lt;br /&gt;
&lt;br /&gt;
The next morning, at 10:37am, Card0 would make a plea to the community, both on the discord server and the page, asking for anyone who might know the issue. Later that day, Tier List Advisory Group member [[Chzvii]] said that they had been the one to sent the message, but the conversation made it seem like it was being sent from the Hongkongggag account, causing a mass panic. However, the issue with the password persisted, until around 6:30pm, when [[Cardigan Pardeau]] helped [[Astra]] to solve it while Card0 was busy. For some reason, the password reset worked on his end, and soon all access to the page was restored for all Admins with page access. &lt;br /&gt;
&lt;br /&gt;
=== New Ambassadors &amp;amp; Functional Affiliates ===&lt;br /&gt;
After more than a year with no new Ambassadors, Card0 would promote the following Affiliates to Ambassador on November 7th 2025.&lt;br /&gt;
&lt;br /&gt;
* [[Celia]], Ambassador for PolyU SHTM (formerly Choi Hung)&lt;br /&gt;
* [[Theajverse|Rsburuu]], Ambassador for Sai Wan Ho&lt;br /&gt;
* [[meandrelee]], Ambassador for Mong Kok&lt;br /&gt;
* [[Poisonviper376]], Ambassador for HKU Med&lt;br /&gt;
* [[Alisonwong.|Alisonwong]], Ambassador for Pak Shek Kok&lt;br /&gt;
Shortly after on November 14th 2025, Card0 would introduce the idea of Functional Affiliates, which would be just like regular affiliates except that they represented a specific professional community or passionate interest group (eg: music, engineering), similar to Hong Kong&#039;s real life functional constituencies. The first Functional Affiliates were [[AquaEclipse324]] for Science, [[GravityDuke]] for Chemistry, and [[Polaris]] for Medicine.&lt;br /&gt;
&lt;br /&gt;
=== Aftermath of Tai Po Fires ===&lt;br /&gt;
On November 26th 2025, a catastrophic fire broke out in Wang Fuk Court in Tai Po, which lead to Card0 turning the server and page into a resource sharing page, sharing updates and how volunteers can go and help. Many Tai Po-based followers, as well as those who lived near the area, would join the server to help out, such as [[Yuma]] and [[Vespera/MV3 no.1 fan]] helping coordinate. As the server also made pings about important updates regarding the fire, many new members joined as well, as [[Jasper]] waived the introduction requirement for new members if they wanted ot get Citizen. This also put a pause on memes and regular content, which only resumed the following Monday. Several fundraisers were also posted on the page, with multiple artists collaborating with Hongkongggag in order to post art fundraisers to raise funds for those affected by the fires.&lt;br /&gt;
&lt;br /&gt;
=== 2025 Community Awards ===&lt;br /&gt;
For the fifth time, the [[Hongkongggag Community Awards]] were held once again, on December 17th 2025, with around 28 people winning, with the competition lasting for around 40-45 minutes. Several categories were open for voting, but because of many people filling in answers that didn&#039;t make sense, Card0 said that next year&#039;s awards will feature only multiple choice pre-set answers. [[Lieutenant Quattro]] won Member of Impact. &lt;br /&gt;
&lt;br /&gt;
== Outreach Era (January 2026-Present) ==&lt;br /&gt;
Hongkongggag during this era has so far, experienced notable changes to the interactions with the page, as well as ways of boosting community activity. Reforms continued with relaxed meetup rules for adults and the introduction of a seventh rank, Luminary, signaling an evolving hierarchy. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Staff during this period:&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
Founder: Card0&lt;br /&gt;
&lt;br /&gt;
Admins: Lemontea, Salmon, Tolmo, Bossuuu, Jasper, Astra, Salami, Joyce, Boba&lt;br /&gt;
&lt;br /&gt;
Moderators: zt, Polaris, Sumii, Ame, Chris, Sleepy, Tuck, Syntax, Expired Potato, Asianbarb, Blep, Hill, Aurelia, Sugar, Raymond&lt;br /&gt;
&lt;br /&gt;
Promotions: Blep (March 2026), Hill, Aurelia (April 2026), Sugar (May 2026), Raymond (June 2026)&lt;br /&gt;
&lt;br /&gt;
Resignations/Demotions: Livie, Greentea (March 2026), Nigel (April 2026), Lieutenant Quattro (June 2026)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Notable members who joined during this era:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* [[Saltysugarr]]&lt;br /&gt;
* [[Wallstreet Noose]]&lt;br /&gt;
* [[Cl4rity]]&lt;br /&gt;
&lt;br /&gt;
* [[That Hong Kong Guy]]&lt;br /&gt;
* [[Selin]]&lt;br /&gt;
* [[ryku.5000.2]]&lt;br /&gt;
* [[dunkleosteus_fan_2.0_59404]]&lt;br /&gt;
* [[Pengyou]]&lt;br /&gt;
* [[Isabelle]]&lt;br /&gt;
* [[fake]]&lt;br /&gt;
* [[uych_620]]&lt;br /&gt;
* [[snowflake__playz]]&lt;br /&gt;
* [[Fallen]]&lt;br /&gt;
* [[Wowim]]&lt;br /&gt;
* [[callieacting2019]]&lt;br /&gt;
* [[cairobaby]]&lt;br /&gt;
* [[mosarball]]&lt;br /&gt;
&lt;br /&gt;
=== Scheduled Events Policy ===&lt;br /&gt;
As part of Vision 2026, one of Card0&#039;s main goals was to &amp;quot;have at least 2 scheduled events per month&amp;quot;, something that was put into action by him and other staff members, especially [[Expired potato]] and [[Greentea]]. This increased over the course of 2026 with more and more scheduled events, with at least 3 scheduled events being held each month.&lt;br /&gt;
&lt;br /&gt;
=== Revival of Satirical Maps ===&lt;br /&gt;
In early January, Card0 asked on the page story on whether people would want to see a revival of [[Satirical Maps]], with most saying they would. The first of these would go live on January 8th 2026, depicting Tsim Sha Tsui. This time however, the maps were branded as &amp;quot;honest maps&amp;quot;, and they would become a semi-regular occurence rather than being seasonal, though they would be posted more infrequently.; &lt;br /&gt;
&lt;br /&gt;
=== New Advisory Groups ===&lt;br /&gt;
On January 23rd 2026, Card0 announced the creation of new university advisory groups in a similar vein to the tier list, bingo card and Shenzhen meme advisory groups, with the universities covered being HKU, CU, UST, CityU, PolyU and EDU. A few days later, he would revamp the Shenzhen meme advisory group by purging people who didn&#039;t contribute, leaving only 4 members left in the group. &lt;br /&gt;
&lt;br /&gt;
=== Anti-MLM Campaign ===&lt;br /&gt;
In Early February, Card0 announced an anti-MLM (Multi-Level Marketing) campaign, which included an awareness infographic posted on the page, as well as an event educating people on how to spot and avoid MLMs. &lt;br /&gt;
&lt;br /&gt;
=== [[Bauhinia Rising Political Sim]] ===&lt;br /&gt;
While there were previous discussions of another polsim after Tsz Kong, none came to fruition until Card0 decided to host a new one, this time set in Hong Kong in a timeline where the 2019 protests didn&#039;t happen. The sim began with 6 players, each representing the Democratic, Civic, DAB, FTU, PP-LSD and Demosisto parties respectively, with more members joining later. The sim ended on July 19th 2026 after low activity, though a Taiwan sim was proposed.&lt;br /&gt;
&lt;br /&gt;
=== Channel Reorganisation ===&lt;br /&gt;
Throughout February and March, some channels were moved around or deleted to avoid clutter, with the school-specific channels being moved to their own category, while the interests channel was split, with the latter being done after a discussion on how to increase the usage of lesser used interest channels. Moreover, the driving-motoring and general-hobbies channels would be retired, with the latter replaced with a forum for specific hobbies that were too niche to deserve their own channel. This inadvertedly had the effect of improving member retention as with less clutter, more members were keen to stay and chat.&lt;br /&gt;
&lt;br /&gt;
=== Shadowban Crisis, New Moderators ===&lt;br /&gt;
On March 28th 2026, the page found itself hit with the worst shadowban in its recent history, while followers decreased over the weekend at a rapid rate. Initially Card0 only decided to ask the Staff, Ambassadors and Affiliates to help, however seeing that many members were too busy or ghosted him, he called on the entire community to help, where reception was initially limited but soon intensified as people began to help. &lt;br /&gt;
&lt;br /&gt;
The issue would gradually recover from Monday onwards with a new meme that went semi-viral, giving the page a follower boost. Around the same time, [[Greentea]] would resign from Admin, while [[Boba]] would be promoted at the same time.&amp;lt;blockquote&amp;gt;hello all. zoe here. i think some of yall probably don&#039;t know me since i never talk anymore. therefore i am retiring after 4 yrs effective immediately. i can finally be free from this godforsaken hellhole&lt;br /&gt;
&lt;br /&gt;
jk this server is amazing. ive been here since 2021 which holy shit five years. for a long time it was a big part of my life, maybe even one of the most important things. ive made a lot of really happy memories here and met a lot of amazing people here. special thanks to @zt because im probably closest to you; im very happy to have found a friend this great through here. hopefully now that im gone cardo lets u take my place as admin.  but it has been four years and this server has watched me grow a lot, move to two countries, and ive outgrown being active here although i still very much treasure this place. &lt;br /&gt;
&lt;br /&gt;
this will probably be the only time you ever hear me say this so listen up but you should appreciate card0 more. as the self proclaimed #1 cardo hater ik its rly fun to hate on him but he&#039;s done, obviously, an insane amount for this server. he&#039;s created a lgbtq friendly pandem english hk space, and he&#039;s put a lot of work into doing it. &lt;br /&gt;
&lt;br /&gt;
its sad that i wont be able to fulfill my plan of taking over the server when cardo dies of stress bcs of us in a few years but honestly, this place is a shithole i ain&#039;t want it obviously i won&#039;t be leaving so if there&#039;s any events fun enough i will join. hit me up if u play val on hk servers or watch vct. thanks to staff and everyone for a very, very good four years. glory to yuutopia.&amp;lt;/blockquote&amp;gt;In addition, reforms to the mod nomination process were passed with members now allowed to self-nominate, so long as they had backing from two members. [[Aurelia]] and [[Hill]] would also be promoted around the same time albeit under the old system, while [[Blep]] was promoted a month earlier. [[Salami]] would also be given page access around the same time, marking the first time since 2020 that 7 people had access to the page. &lt;br /&gt;
&lt;br /&gt;
=== Reform of Meetup Rules ===&lt;br /&gt;
While the server had a history of new members looking to meetup in real life, this was restricted due to previous incidents. However after some discussions within Staff suggested by [[Boba]], reforms were put out for the community to vote on April 7th 2026 to relax the rules for 18+ members. The poll passed, and a hangout thread was created in the university-graduated channel to help organize hangouts. &lt;br /&gt;
&lt;br /&gt;
=== Resignation of [[Nigel]] ===&lt;br /&gt;
On Aprl 21st 2026, [[Card0]] made a sudden announcement in the morning (HKT) shortly after Nigel left the discord server during the early morrning.&amp;lt;blockquote&amp;gt;Hi guys, Nigel has resigned from Moderator and left the server due to private reasons&amp;lt;/blockquote&amp;gt;He also mentioned that Nigel also resigned from Ambassador. As Nigel was a popular moderator and member of the server, many people speculated on what happened, with a few being insensitive, making fun of the situation. A day later, he put forward a second statement:&amp;lt;blockquote&amp;gt;sorry for the ping but with all the discussion that happened with Nigel&#039;s resignation, as well as people being very insensitive, I think its important to disclose the fact that he committed many inappropriate actions that crossed many physical boundaries that affected members of Staff and others in this community in real life. As such he resigned due to these reasons. &lt;br /&gt;
&lt;br /&gt;
We advise you to cut off ties with Nigel because of this, and not to joke around about this. While we acknowledge that Nigel has done a lot of good for the community, this does not erase the severity of his actions, which affected several people, including me personally. &lt;br /&gt;
&lt;br /&gt;
I apologise for not elaborating more yesterday, as I was still shaken by what had happened and I didn&#039;t know what I could share. But I feel like now is the time to be more transparent about this. I hope the community can heal and move on from this &lt;br /&gt;
&lt;br /&gt;
For obvious reasons, please dont contact me or staff for any further personal questions&amp;lt;/blockquote&amp;gt;This was met with some shock, with a few members also privately messaging Card0 to express their condolences for what happened.&lt;br /&gt;
&lt;br /&gt;
=== The Seventh Rank ===&lt;br /&gt;
For the first time since early 2021, 852R would see the introduction of a new rank to the six rank system: Luminary, which was created after a poll on April 21st-22nd 2026. This new rank, colored poppy blue, would be ranked above Prestige, be appointed ad-hoc, while Vice would made into a rank that members could achieve via the YUU rewards system.&lt;br /&gt;
&lt;br /&gt;
=== Diaspora Advisory Groups ===&lt;br /&gt;
In May, Card0 created new diaspora advisory groups for the Canadian, British and American Hong Kong diasporas respectively, while the pre-existing Sydneyggag chat was rennamed into the Australian diaspora advisory group. The British group in particular, was a de-facto successor of the resurgence-era Bureau of British Affairs. &lt;br /&gt;
&lt;br /&gt;
Later, on July 11th 2026, a Singaporean group was created.&lt;br /&gt;
&lt;br /&gt;
=== More New Moderators ===&lt;br /&gt;
Following the trend set earlier that year, two new members were promoted to Moderator, [[Saltysugarr]] on May 3th 2026, and [[Raymond]] on June 4th 2026. Interestingly, Sugar was the fastest person to go from Citizen to Moderator since 2022, having joined only in March 2026.&lt;br /&gt;
&lt;br /&gt;
=== Follower Loss &amp;amp; Backrooms Collaboration ===&lt;br /&gt;
In late May, Instagram began removing bot accounts and inactive followers, leading to Hongkongggag to experience almost daily follower losses for nearly two weeks, bringing the follower count down below 120K for two days. However, at the same time the page also collaborated with Movie Movie to promote the Backrooms movie: Hongkongggag&#039;s largest collaboration ever. Aside from a sponsored meme post ranking liminal spaces in Hong Kong, a ticket giveaway went live on June 3rd 2026, with 20 tickets up for grabs. This helped gradually restore the page&#039;s followers, bringing it back up to 120K, before the follower count dropped drastically again.&lt;br /&gt;
&lt;br /&gt;
=== PresidentLee Controversy ===&lt;br /&gt;
[[PresidentLee]], a prominent and active member, had garnered a lot of dislike from other members due to his actions that were seen as annoying or ragebaity, while also saying insensitive messages to try and &amp;quot;trigger&amp;quot; other people. Although he was temporarily banned for a month when he made light of the fallout of Nigel&#039;s resignation, he would return not long after his ban expired. While at first most members didn&#039;t have any serious concerns, these soon escalated. As a final warning, Lee was told that if he didn&#039;t change his behavior, Staff would issue an indefinite ban. With more and more concerns rising from other members, and Lee ignoring this warning, Staff banned him on June 19th 2026 which many active members celebrated.&lt;br /&gt;
&lt;br /&gt;
=== [[University Info Night]] ===&lt;br /&gt;
On July 16th 2026, [[Polaris]] hosted a uni info night with several members, both existing and new members, presenting on local and international universities. The event saw good attendance, and even overran due to how many speakers there were. [[Card0]] also livestreamed the event on the page, the first example of streaming from his laptop.&lt;br /&gt;
&lt;br /&gt;
=== [[Hongkongggag Medium]] ===&lt;br /&gt;
Card0 began to publish articles about Hong Kong and other similar issues on Medium, a site he had used for one article back in 2021, but forgot about it. These issues came from a progressive/left-leaning viewpoint.&lt;br /&gt;
&lt;br /&gt;
==References ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:History]]&lt;/div&gt;</summary>
		<author><name>Jasper</name></author>
	</entry>
	<entry>
		<id>https://wiki.852r.org/index.php?title=Module:Pagetype/rfd&amp;diff=3924</id>
		<title>Module:Pagetype/rfd</title>
		<link rel="alternate" type="text/html" href="https://wiki.852r.org/index.php?title=Module:Pagetype/rfd&amp;diff=3924"/>
		<updated>2026-08-06T10:46:20Z</updated>

		<summary type="html">&lt;p&gt;Jasper: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- This page contains a table of all RfD templates and their&lt;br /&gt;
-- redirects. Templates names are capitalized, and the Template: prefix is&lt;br /&gt;
-- removed. Templates are grouped with the main template first, followed by&lt;br /&gt;
-- its redirects.&lt;br /&gt;
&lt;br /&gt;
return {&lt;br /&gt;
	-- Template forms (these should be substituted so we should rarely see these)&lt;br /&gt;
	[&amp;quot;Redirect for discussion&amp;quot;] = true,&lt;br /&gt;
		[&amp;quot;RFD&amp;quot;] = true,&lt;br /&gt;
		[&amp;quot;RfD&amp;quot;] = true,&lt;br /&gt;
		[&amp;quot;Rfd1&amp;quot;] = true,&lt;br /&gt;
		[&amp;quot;Rfd-t&amp;quot;] = true,&lt;br /&gt;
		[&amp;quot;Rfd&amp;quot;] = true,&lt;br /&gt;
		[&amp;quot;Rfd-NPF&amp;quot;] = true,&lt;br /&gt;
		[&amp;quot;Rfd-NPF/core&amp;quot;] = true,&lt;br /&gt;
	-- Module forms&lt;br /&gt;
	[&amp;quot;#invoke:RfD&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;&amp;lt;includeonly&amp;gt;safesubst:&amp;lt;/includeonly&amp;gt;#invoke:RfD&amp;quot;] = true, -- The form made by substituting RfD&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Jasper</name></author>
	</entry>
	<entry>
		<id>https://wiki.852r.org/index.php?title=Module:Pagetype/softredirect&amp;diff=3922</id>
		<title>Module:Pagetype/softredirect</title>
		<link rel="alternate" type="text/html" href="https://wiki.852r.org/index.php?title=Module:Pagetype/softredirect&amp;diff=3922"/>
		<updated>2026-08-06T10:46:20Z</updated>

		<summary type="html">&lt;p&gt;Jasper: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- This page contains a table of all soft redirect templates and their&lt;br /&gt;
-- redirects. Templates names are capitalized, and the Template: prefix is&lt;br /&gt;
-- removed. Templates are grouped with the main template first, followed by&lt;br /&gt;
-- its redirects.&lt;br /&gt;
&lt;br /&gt;
return {&lt;br /&gt;
	[&amp;quot;R from category navigation&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Redirect from category navigation&amp;quot;] = true,&lt;br /&gt;
&lt;br /&gt;
	[&amp;quot;Category redirect&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Cat move&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Cat red&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Cat redir&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Cat redirect&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Category move&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Category Redirect&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Categoryredirect&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Catr&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Catred&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Catredir&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Catredirect&amp;quot;] = true,&lt;br /&gt;
&lt;br /&gt;
	[&amp;quot;R from template-generated category&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Redirect from template-generated category&amp;quot;] = true,&lt;br /&gt;
&lt;br /&gt;
	[&amp;quot;Portal soft redirect&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Portal Redirect&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Portal redirect&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Portal Soft Redirect&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Portalredirect&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Portalsoftredirect&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;PortRed&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Portred&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Portsoftred&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;PSR&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Psr&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Soft portal redirect&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Soft redirect portal&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;SPR&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Spr&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;SRP&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Srp&amp;quot;] = true,&lt;br /&gt;
&lt;br /&gt;
	[&amp;quot;Salted redirect&amp;quot;] = true,&lt;br /&gt;
&lt;br /&gt;
	[&amp;quot;Soft redirect&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Interwiki redirect&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Plain soft redirect&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Soft&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Soft link&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Soft redir&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Soft Redirect&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Softr&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Softredir&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;SoftRedirect&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Softredirect&amp;quot;] = true,&lt;br /&gt;
&lt;br /&gt;
	[&amp;quot;Userrename&amp;quot;] = true,&lt;br /&gt;
&lt;br /&gt;
	[&amp;quot;Wikibooks redirect&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;WBOOK&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Wbook&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Wikibook redirect&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Wikibooks Redirect&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;WikibooksRedirect&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Wikibooksredirect&amp;quot;] = true,&lt;br /&gt;
&lt;br /&gt;
	[&amp;quot;Wikimedia Commons redirect&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;COMM&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Comm&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Commons Redirect&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Commons redirect&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;CommonsRedirect&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Commonsredirect&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Wikimedia commons redirect&amp;quot;] = true,&lt;br /&gt;
&lt;br /&gt;
	[&amp;quot;Wikiquote redirect&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Wq&amp;quot;] = true,&lt;br /&gt;
&lt;br /&gt;
	[&amp;quot;Wikisource redirect&amp;quot;] = true,&lt;br /&gt;
&lt;br /&gt;
	[&amp;quot;Wikispecies redirect&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Wikispecies Redirect&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;WikispeciesRedirect&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Wikispeciesredirect&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;WSPEC&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Wspec&amp;quot;] = true,&lt;br /&gt;
&lt;br /&gt;
	[&amp;quot;Wikivoyage redirect&amp;quot;] = true,&lt;br /&gt;
&lt;br /&gt;
	[&amp;quot;Wiktionary redirect&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Moved to Wiktionary&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;RedirecttoWiktionary&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Wi&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Wikt red&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Wikt redirect&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Wiktionary Redirect&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Wiktionary-redirect&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;WiktionaryRedirect&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Wiktionaryredirect&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Wiktr&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Wiktred&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Wiktredir&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Wtr&amp;quot;] = true,&lt;br /&gt;
	[&amp;quot;Wtsr&amp;quot;] = true,&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Jasper</name></author>
	</entry>
	<entry>
		<id>https://wiki.852r.org/index.php?title=Module:Wikitext_Parsing&amp;diff=3920</id>
		<title>Module:Wikitext Parsing</title>
		<link rel="alternate" type="text/html" href="https://wiki.852r.org/index.php?title=Module:Wikitext_Parsing&amp;diff=3920"/>
		<updated>2026-08-06T10:46:20Z</updated>

		<summary type="html">&lt;p&gt;Jasper: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;require(&amp;quot;strict&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
-- We&#039;re calling up to thousands of string methods each time we run, so&lt;br /&gt;
-- do this very simple micro optimisation to help a tiny bit&lt;br /&gt;
local string = string&lt;br /&gt;
&lt;br /&gt;
-- Helper functions for PrepareText --&lt;br /&gt;
local function endswith(text, subtext)&lt;br /&gt;
	return string.sub(text, -#subtext, -1) == subtext&lt;br /&gt;
end&lt;br /&gt;
local function allcases(s)&lt;br /&gt;
	return string.gsub(s, &amp;quot;%a&amp;quot;, function(c)&lt;br /&gt;
		return &amp;quot;[&amp;quot;..string.upper(c)..string.lower(c)..&amp;quot;]&amp;quot;&lt;br /&gt;
	end)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[=[ Implementation notes&lt;br /&gt;
---- NORMAL HTML TAGS ----&lt;br /&gt;
Tags are very strict on how they want to start, but loose on how they end.&lt;br /&gt;
The start must strictly follow &amp;lt;[tAgNaMe](%s|&amp;gt;) with no room for whitespace in&lt;br /&gt;
the tag&#039;s name, but may then flow as they want afterwards, making&lt;br /&gt;
&amp;lt;div\nclass\n=\n&amp;quot;\nerror\n&amp;quot;\n&amp;gt; valid. If a tag has no end, it will consume all&lt;br /&gt;
text instead of not processing.&lt;br /&gt;
&lt;br /&gt;
There&#039;s no sense of escaping &amp;lt; or &amp;gt;&lt;br /&gt;
E.g.&lt;br /&gt;
 &amp;lt;div class=&amp;quot;error\&amp;gt;&amp;quot;&amp;gt; will end at \&amp;gt; despite it being inside a quote&lt;br /&gt;
 &amp;lt;div class=&amp;quot;&amp;lt;span class=&amp;quot;error&amp;quot;&amp;gt;error&amp;lt;/span&amp;gt;&amp;quot;&amp;gt; will not process the larger div&lt;br /&gt;
&lt;br /&gt;
---- NOPROCESSING TAGS (nowiki, pre, syntaxhighlight, source, etc.) ----&lt;br /&gt;
(Note: &amp;lt;source&amp;gt; is the deprecated version of &amp;lt;syntaxhighlight&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
No-processing tags have some differences to the above rules. Specifically, their&lt;br /&gt;
syntax is a lot stricter. While an opening tag follows the same set of rules, A&lt;br /&gt;
closing tag can&#039;t have any sort of extra formatting. &amp;lt;/div a/a&amp;gt; is valid,&lt;br /&gt;
&amp;lt;/nowiki a/a&amp;gt; is not. Only newlines and spaces/tabs are allowed in closing tags.&lt;br /&gt;
Note that, even though tags may cause a visual change without an ending tag like&lt;br /&gt;
&amp;lt;pre&amp;gt;, one is required for the no-processing effects.&lt;br /&gt;
&lt;br /&gt;
Both the content inside the tag pair and the text in the tags will not be&lt;br /&gt;
processed. E.g. &amp;lt;nowiki |}}&amp;gt;|}}&amp;lt;/nowiki&amp;gt; would have both of the |}} escaped.&lt;br /&gt;
&lt;br /&gt;
Since we only care about these no-processing tags, we can ignore the idea of an&lt;br /&gt;
intercepting tag messing us up, and just go for the first ending we can find. If&lt;br /&gt;
there is no ending, the tag will NOT consume the rest of the text. Even if there&lt;br /&gt;
is no ending tag, the content inside the opening tag will still be unprocessed,&lt;br /&gt;
meaning {{X20|&amp;lt;nowiki }}&amp;gt;}} wouldn&#039;t end at the first }} despite there being no&lt;br /&gt;
ending tag.&lt;br /&gt;
&lt;br /&gt;
There are some tags, like &amp;lt;math&amp;gt;, which also function like &amp;lt;nowiki&amp;gt; for our&lt;br /&gt;
purposes, and are handled here. Some other tags, like &amp;lt;ref&amp;gt;, have more complex&lt;br /&gt;
behaviour that can&#039;t be reasonably implemented in this, and so are ignored. I&lt;br /&gt;
suspect that every tag listed in [[Special:Version]] may behave somewhat like&lt;br /&gt;
this, but that&#039;s far too many cases worth checking for rarely used tags that may&lt;br /&gt;
not even have a good reason to contain {{ or }} anyways, so we leave them alone.&lt;br /&gt;
&lt;br /&gt;
---- INCLUDEONLY ----&lt;br /&gt;
While includeonly tags do technically serve the same purpose as a nowiki tag for&lt;br /&gt;
what this module does, contextually they don&#039;t always make sense to escape, and&lt;br /&gt;
as such are ignored by this module entirely.&lt;br /&gt;
--]=]&lt;br /&gt;
-- This function expects the string to start with the tag&lt;br /&gt;
local validtags = {nowiki=1, pre=1, syntaxhighlight=1, source=1, math=1}&lt;br /&gt;
local function TestForNowikiTag(text, scanPosition)&lt;br /&gt;
	local tagName = string.match(text, &amp;quot;^&amp;lt;([^\n /&amp;gt;]+)&amp;quot;, scanPosition)&lt;br /&gt;
	if not tagName or not validtags[string.lower(tagName)] then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	local nextOpener = string.find(text, &amp;quot;&amp;lt;&amp;quot;, scanPosition+1, true)&lt;br /&gt;
	local nextCloser = string.find(text, &amp;quot;&amp;gt;&amp;quot;, scanPosition+1, true)&lt;br /&gt;
	if nextCloser and (not nextOpener or nextCloser &amp;lt; nextOpener) then&lt;br /&gt;
		local startingTag = string.sub(text, scanPosition, nextCloser)&lt;br /&gt;
		-- We have our starting tag (E.g. &#039;&amp;lt;pre style=&amp;quot;color:red&amp;quot;&amp;gt;&#039;)&lt;br /&gt;
		-- Now find our ending...&lt;br /&gt;
		if endswith(startingTag, &amp;quot;/&amp;gt;&amp;quot;) then -- self-closing tag (we are our own ending)&lt;br /&gt;
			return {&lt;br /&gt;
				Tag = tagName,&lt;br /&gt;
				Start = startingTag,&lt;br /&gt;
				Content = &amp;quot;&amp;quot;, End = &amp;quot;&amp;quot;,&lt;br /&gt;
				Length = #startingTag&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
		else&lt;br /&gt;
			local endingTagStart, endingTagEnd = string.find(text, &amp;quot;&amp;lt;/&amp;quot;..allcases(tagName)..&amp;quot;[ \t\n]*&amp;gt;&amp;quot;, scanPosition)&lt;br /&gt;
			if endingTagStart then --Regular tag formation&lt;br /&gt;
				local endingTag = string.sub(text, endingTagStart, endingTagEnd)&lt;br /&gt;
				local tagContent = string.sub(text, nextCloser+1, endingTagStart-1)&lt;br /&gt;
				return {&lt;br /&gt;
					Tag = tagName,&lt;br /&gt;
					Start = startingTag,&lt;br /&gt;
					Content = tagContent,&lt;br /&gt;
					End = endingTag,&lt;br /&gt;
					Length = #startingTag + #tagContent + #endingTag&lt;br /&gt;
				}&lt;br /&gt;
&lt;br /&gt;
			else -- Content inside still needs escaping (also linter error!)&lt;br /&gt;
				return {&lt;br /&gt;
					Tag = tagName,&lt;br /&gt;
					Start = startingTag,&lt;br /&gt;
					Content = &amp;quot;&amp;quot;, End = &amp;quot;&amp;quot;,&lt;br /&gt;
					Length = #startingTag&lt;br /&gt;
				}&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return nil&lt;br /&gt;
end&lt;br /&gt;
--[=[ Implementation Notes&lt;br /&gt;
HTML Comments are about as basic as it gets. Start at &amp;lt;!--, end at --&amp;gt;, no extra&lt;br /&gt;
conditions. If a comment has no end, it will eat all the text ahead.&lt;br /&gt;
--]=]&lt;br /&gt;
local function TestForComment(text, scanPosition)&lt;br /&gt;
	if string.match(text, &amp;quot;^&amp;lt;!%-%-&amp;quot;, scanPosition) then&lt;br /&gt;
		local commentEnd = string.find(text, &amp;quot;--&amp;gt;&amp;quot;, scanPosition+4, true)&lt;br /&gt;
		if commentEnd then&lt;br /&gt;
			return {&lt;br /&gt;
				Start = &amp;quot;&amp;lt;!--&amp;quot;, End = &amp;quot;--&amp;gt;&amp;quot;,&lt;br /&gt;
				Content = string.sub(text, scanPosition+4, commentEnd-1),&lt;br /&gt;
				Length = commentEnd-scanPosition+3&lt;br /&gt;
			}&lt;br /&gt;
		else -- Consumes all text if not given an ending&lt;br /&gt;
			return {&lt;br /&gt;
				Start = &amp;quot;&amp;lt;!--&amp;quot;, End = &amp;quot;&amp;quot;,&lt;br /&gt;
				Content = string.sub(text, scanPosition+4),&lt;br /&gt;
				Length = #text-scanPosition+1&lt;br /&gt;
			}&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return nil&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--[[ Implementation notes&lt;br /&gt;
The goal of this function is to escape all text that wouldn&#039;t be parsed if it&lt;br /&gt;
was preprocessed (see above implementation notes).&lt;br /&gt;
&lt;br /&gt;
Using keepComments will keep all HTML comments instead of removing them. They&lt;br /&gt;
will still be escaped regardless.&lt;br /&gt;
--]]&lt;br /&gt;
local function PrepareText(text, keepComments)&lt;br /&gt;
	local newtext = {}&lt;br /&gt;
	local scanPosition = 1&lt;br /&gt;
	local textPosition = 1&lt;br /&gt;
	while true do&lt;br /&gt;
		local nextCheck = string.find(text, &amp;quot;&amp;lt;&amp;quot;, scanPosition, true) -- Advance to the next potential tag we care about&lt;br /&gt;
		if not nextCheck then -- Done&lt;br /&gt;
			newtext[#newtext+1] = string.sub(text, textPosition)&lt;br /&gt;
			break&lt;br /&gt;
		end&lt;br /&gt;
		scanPosition = nextCheck&lt;br /&gt;
		local Comment = TestForComment(text, scanPosition)&lt;br /&gt;
		if Comment then&lt;br /&gt;
			newtext[#newtext+1] = string.sub(text, textPosition, nextCheck-1)&lt;br /&gt;
			if keepComments then&lt;br /&gt;
				newtext[#newtext+1] = Comment.Start .. mw.text.nowiki(Comment.Content) .. Comment.End&lt;br /&gt;
			end&lt;br /&gt;
			scanPosition = scanPosition + Comment.Length&lt;br /&gt;
			textPosition = scanPosition&lt;br /&gt;
		else&lt;br /&gt;
			local Tag = TestForNowikiTag(text, scanPosition)&lt;br /&gt;
			if Tag then&lt;br /&gt;
				newtext[#newtext+1] = string.sub(text, textPosition, nextCheck-1)&lt;br /&gt;
				local newTagStart = &amp;quot;&amp;lt;&amp;quot; .. mw.text.nowiki(string.sub(Tag.Start, 2, -2)) .. &amp;quot;&amp;gt;&amp;quot;&lt;br /&gt;
				local newTagEnd =&lt;br /&gt;
					Tag.End == &amp;quot;&amp;quot; and &amp;quot;&amp;quot; or -- Respect no tag ending&lt;br /&gt;
					&amp;quot;&amp;lt;/&amp;quot; .. mw.text.nowiki(string.sub(Tag.End, 3, -2)) .. &amp;quot;&amp;gt;&amp;quot;&lt;br /&gt;
				local newContent = mw.text.nowiki(Tag.Content)&lt;br /&gt;
				newtext[#newtext+1] = newTagStart .. newContent .. newTagEnd&lt;br /&gt;
				scanPosition = scanPosition + Tag.Length&lt;br /&gt;
				textPosition = scanPosition&lt;br /&gt;
			else -- Nothing special, move on...&lt;br /&gt;
				scanPosition = scanPosition + 1&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return table.concat(newtext, &amp;quot;&amp;quot;)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
--Main entry points&lt;br /&gt;
p.PrepareText = PrepareText&lt;br /&gt;
--Extra entry points, not really required&lt;br /&gt;
p.TestForNowikiTag = TestForNowikiTag&lt;br /&gt;
p.TestForComment = TestForComment&lt;br /&gt;
&lt;br /&gt;
return p&lt;br /&gt;
&lt;br /&gt;
--[==[ console tests&lt;br /&gt;
&lt;br /&gt;
local s = [=[Hey!{{Text|&amp;lt;nowiki | ||&amp;gt;&lt;br /&gt;
Hey! }}&lt;br /&gt;
A&amp;lt;/nowiki&amp;gt;|&amp;lt;!--AAAAA|AAA--&amp;gt;Should see|Shouldn&#039;t see}}]=]&lt;br /&gt;
local out = p.PrepareText(s)&lt;br /&gt;
mw.logObject(out)&lt;br /&gt;
&lt;br /&gt;
local s = [=[B&amp;lt;!--&lt;br /&gt;
Hey!&lt;br /&gt;
--&amp;gt;A]=]&lt;br /&gt;
local out = p.TestForComment(s, 2)&lt;br /&gt;
mw.logObject(out); mw.log(string.sub(s, 2, out.Length))&lt;br /&gt;
&lt;br /&gt;
]==]&lt;/div&gt;</summary>
		<author><name>Jasper</name></author>
	</entry>
	<entry>
		<id>https://wiki.852r.org/index.php?title=Module:Shortcut/styles.css&amp;diff=3918</id>
		<title>Module:Shortcut/styles.css</title>
		<link rel="alternate" type="text/html" href="https://wiki.852r.org/index.php?title=Module:Shortcut/styles.css&amp;diff=3918"/>
		<updated>2026-08-06T10:46:20Z</updated>

		<summary type="html">&lt;p&gt;Jasper: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* {{pp-template}} */&lt;br /&gt;
.module-shortcutboxplain {&lt;br /&gt;
	float: right;&lt;br /&gt;
	margin: 0 0 0 1em;&lt;br /&gt;
	border: 1px solid var(--border-color-base, #a2a9b1);&lt;br /&gt;
	background-color: var(--background-color-base, #fff);&lt;br /&gt;
	padding: 0.3em 0.6em 0.2em 0.6em;&lt;br /&gt;
	text-align: center;&lt;br /&gt;
	font-size: 85%;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.module-shortcutboxleft {&lt;br /&gt;
	float: left;&lt;br /&gt;
	margin: 0 1em 0 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.module-shortcutlist {&lt;br /&gt;
	display: inline-block;&lt;br /&gt;
	border-bottom: 1px solid var(--border-color-base, #a2a9b1);&lt;br /&gt;
	margin-bottom: 0.2em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.module-shortcutboxplain ul {&lt;br /&gt;
	font-weight: bold;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.module-shortcutanchordiv {&lt;br /&gt;
	position: relative;&lt;br /&gt;
	top: -3em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
li .module-shortcutanchordiv {&lt;br /&gt;
	float: right; /* IE/Edge in list items */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.mbox-imageright .module-shortcutboxplain {&lt;br /&gt;
	padding: 0.4em 1em;&lt;br /&gt;
	line-height: 1.3;&lt;br /&gt;
	margin: 0;&lt;br /&gt;
	float: initial;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Jasper</name></author>
	</entry>
	<entry>
		<id>https://wiki.852r.org/index.php?title=Template:Plainlist/styles.css&amp;diff=3916</id>
		<title>Template:Plainlist/styles.css</title>
		<link rel="alternate" type="text/html" href="https://wiki.852r.org/index.php?title=Template:Plainlist/styles.css&amp;diff=3916"/>
		<updated>2026-08-06T10:46:20Z</updated>

		<summary type="html">&lt;p&gt;Jasper: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* {{pp-template|small=yes}} */&lt;br /&gt;
.plainlist ol,&lt;br /&gt;
.plainlist ul {&lt;br /&gt;
	line-height: inherit;&lt;br /&gt;
	list-style: none;&lt;br /&gt;
	margin: 0;&lt;br /&gt;
	padding: 0; /* Reset Minerva default */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.plainlist ol li,&lt;br /&gt;
.plainlist ul li {&lt;br /&gt;
	margin-bottom: 0;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Jasper</name></author>
	</entry>
	<entry>
		<id>https://wiki.852r.org/index.php?title=Module:Message_box/ambox.css&amp;diff=3914</id>
		<title>Module:Message box/ambox.css</title>
		<link rel="alternate" type="text/html" href="https://wiki.852r.org/index.php?title=Module:Message_box/ambox.css&amp;diff=3914"/>
		<updated>2026-08-06T10:46:20Z</updated>

		<summary type="html">&lt;p&gt;Jasper: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* {{pp|small=y}} */&lt;br /&gt;
.ambox {&lt;br /&gt;
	border: 1px solid #a2a9b1;&lt;br /&gt;
	/* @noflip */&lt;br /&gt;
	border-left: 10px solid #36c;  /* Default &amp;quot;notice&amp;quot; blue */&lt;br /&gt;
	background-color: #fbfbfb;&lt;br /&gt;
	box-sizing: border-box;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Single border between stacked boxes.&lt;br /&gt;
 * category and TemplateStyles are wrapped in an &amp;quot;empty&amp;quot; span [[phab:T378906]]&lt;br /&gt;
 * [[phab:T200206]] may be relevant at a later date&lt;br /&gt;
 */&lt;br /&gt;
.ambox + .mw-empty-elt + .ambox,&lt;br /&gt;
.ambox + .mw-empty-elt + .mw-empty-elt + .ambox,&lt;br /&gt;
/*&lt;br /&gt;
 * and Template:Dated maintenance category. we can probably remove this flavor&lt;br /&gt;
 * when T200206 is fixed&lt;br /&gt;
 */&lt;br /&gt;
.ambox + .mw-empty-elt + .mw-empty-elt + .mw-empty-elt + .ambox {&lt;br /&gt;
	margin-top: -1px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* For the &amp;quot;small=left&amp;quot; option. */&lt;br /&gt;
/* must override .ambox + .ambox styles above */&lt;br /&gt;
html body.mediawiki .ambox.mbox-small-left {&lt;br /&gt;
	/* @noflip */&lt;br /&gt;
	margin: 4px 1em 4px 0;&lt;br /&gt;
	overflow: hidden;&lt;br /&gt;
	width: 238px;&lt;br /&gt;
	border-collapse: collapse;&lt;br /&gt;
	font-size: 88%;&lt;br /&gt;
	line-height: 1.25em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.ambox-speedy {&lt;br /&gt;
	/* @noflip */&lt;br /&gt;
	border-left: 10px solid #b32424;    /* Red */&lt;br /&gt;
	background-color: #fee7e6;          /* Pink */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.ambox-delete {&lt;br /&gt;
	/* @noflip */&lt;br /&gt;
	border-left: 10px solid #b32424;    /* Red */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.ambox-content {&lt;br /&gt;
	/* @noflip */&lt;br /&gt;
	border-left: 10px solid #f28500;    /* Orange */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.ambox-style {&lt;br /&gt;
	/* @noflip */&lt;br /&gt;
	border-left: 10px solid #fc3;       /* Yellow */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.ambox-move {&lt;br /&gt;
	/* @noflip */&lt;br /&gt;
	border-left: 10px solid #9932cc;    /* Purple */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.ambox-protection {&lt;br /&gt;
	/* @noflip */&lt;br /&gt;
	border-left: 10px solid #a2a9b1;    /* Gray-gold */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.ambox .mbox-text {&lt;br /&gt;
	border: none;&lt;br /&gt;
	/* @noflip */&lt;br /&gt;
	padding: 0.25em 0.5em;&lt;br /&gt;
	width: 100%;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.ambox .mbox-image {&lt;br /&gt;
	border: none;&lt;br /&gt;
	/* @noflip */&lt;br /&gt;
	padding: 2px 0 2px 0.5em;&lt;br /&gt;
	text-align: center;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.ambox .mbox-imageright {&lt;br /&gt;
	border: none;&lt;br /&gt;
	/* @noflip */&lt;br /&gt;
	padding: 2px 0.5em 2px 0;&lt;br /&gt;
	text-align: center;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* An empty narrow cell */&lt;br /&gt;
.ambox .mbox-empty-cell {&lt;br /&gt;
	border: none;&lt;br /&gt;
	padding: 0;&lt;br /&gt;
	width: 1px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.ambox .mbox-image-div {&lt;br /&gt;
	width: 52px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
@media (min-width: 720px) {&lt;br /&gt;
	.ambox {&lt;br /&gt;
		margin: 0 10%; /* 10% = Will not overlap with other elements */&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
@media print {&lt;br /&gt;
	body.ns-0 .ambox {&lt;br /&gt;
		display: none !important;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Jasper</name></author>
	</entry>
	<entry>
		<id>https://wiki.852r.org/index.php?title=Template:Very_long/doc&amp;diff=3912</id>
		<title>Template:Very long/doc</title>
		<link rel="alternate" type="text/html" href="https://wiki.852r.org/index.php?title=Template:Very_long/doc&amp;diff=3912"/>
		<updated>2026-08-06T10:46:20Z</updated>

		<summary type="html">&lt;p&gt;Jasper: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Documentation subpage}}&lt;br /&gt;
&amp;lt;!-- Please place categories where indicated at the bottom of this page and interwikis at Wikidata (see [[Wikipedia:Wikidata]]) --&amp;gt;&lt;br /&gt;
{{Twinkle standard installation}}&lt;br /&gt;
{{Template shortcut|Long|Toobig|Toolong|Too-long|Too long|VeryLong}}&lt;br /&gt;
&lt;br /&gt;
See [[Wikipedia:Article size]] for more information on this topic.&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
Add {{Tlx|Very long|date{{=}}{{CURRENTMONTHNAME}} {{CURRENTYEAR}}}} to the top of the article, below any [[WP:HAT|hatnotes]].&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;code&amp;gt;small&amp;lt;/code&amp;gt; parameter&lt;br /&gt;
: {{Tlx|Very long|small{{=}}left|date{{=}}{{CURRENTMONTHNAME}} {{CURRENTYEAR}}}} generates the following smaller-sized template, a left-size box instead of a banner (which is usually only of use with {{para|section}}, below): {{Very long|small=left|date={{CURRENTMONTHNAME}} {{CURRENTYEAR}}}}&lt;br /&gt;
; Section-specific use&lt;br /&gt;
: If just a particular section of an article is getting long, it can be tagged by adding the {{para|section}} parameter, or using the {{tlx|Very long section}} template variant:&lt;br /&gt;
: {{Tlx|Very long section}} and {{Tlx|Very long|section|small{{=}}left|date{{=}}{{CURRENTMONTHNAME}} {{CURRENTYEAR}}}} both render: {{Very long section}}&lt;br /&gt;
; Readable prose size (in words)&lt;br /&gt;
: The readable prose size in words, calculated with the help of tools like [[User:Dr pda/prosesize|Prosesize]] or [[User:Shubinator/DYKcheck|Shubinator&#039;s DYK tool]], can be added manually to the template:&lt;br /&gt;
: {{Tlx|Very long|words{{=}}7,000}} generates the following template: {{Very long|words=7,000}}&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;code&amp;gt;nosplit&amp;lt;/code&amp;gt; parameter&lt;br /&gt;
: Adding {{para|nosplit|yes}} (or any other value for that parameter, such as &amp;lt;kbd&amp;gt;y&amp;lt;/kbd&amp;gt; or &amp;lt;kbd&amp;gt;true&amp;lt;/kbd&amp;gt;) will suppress mention of splitting the material to new sub-articles, since not all content is suitable for splitting (usually because it would fail [[WP:Notability]] as a stand-alone article).&lt;br /&gt;
&lt;br /&gt;
; Reason parameter&lt;br /&gt;
: Adding {{para|reason|your reason here}} will add a new second sentence to the banner reading: &lt;br /&gt;
:: {{xt|The specific problem is: &#039;&#039;&#039;your reason here&#039;&#039;&#039;}}. &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &#039;&#039;(bolded, as shown)&#039;&#039;&lt;br /&gt;
: Final punctuation is provided, you do not need to include it.&lt;br /&gt;
&lt;br /&gt;
; Categorization&lt;br /&gt;
: This template adds tagged articles to [[:Category:Articles that may be too long]], or one of its dated subcategories.&lt;br /&gt;
&lt;br /&gt;
{{Wikipedia:Template messages/Splitting/List|noheading=yes}}{{Wikipedia:Template messages/Merging/List|noheading=yes}}&lt;br /&gt;
&lt;br /&gt;
== TemplateData ==&lt;br /&gt;
{{TemplateData header}}&lt;br /&gt;
&amp;lt;templatedata&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;description&amp;quot;: &amp;quot;Use this cleanup template to indicate that an article may be too long to read and navigate comfortably.&amp;quot;,&lt;br /&gt;
	&amp;quot;format&amp;quot;: &amp;quot;inline&amp;quot;,&lt;br /&gt;
	&amp;quot;params&amp;quot;: {&lt;br /&gt;
		&amp;quot;1&amp;quot;: {&lt;br /&gt;
			&amp;quot;label&amp;quot;: &amp;quot;Affected area&amp;quot;,&lt;br /&gt;
			&amp;quot;description&amp;quot;: &amp;quot;Text to replace the word \&amp;quot;article\&amp;quot;, usually \&amp;quot;section\&amp;quot;&amp;quot;,&lt;br /&gt;
			&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;,&lt;br /&gt;
			&amp;quot;autovalue&amp;quot;: &amp;quot;section&amp;quot;,&lt;br /&gt;
			&amp;quot;example&amp;quot;: &amp;quot;section&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
		&amp;quot;date&amp;quot;: {&lt;br /&gt;
			&amp;quot;label&amp;quot;: &amp;quot;Month and year&amp;quot;,&lt;br /&gt;
			&amp;quot;description&amp;quot;: &amp;quot;The month and year that the template was placed (in full). \&amp;quot;{{subst:CURRENTMONTHNAME}} {{subst:CURRENTYEAR}}\&amp;quot; inserts the current month and year automatically.&amp;quot;,&lt;br /&gt;
			&amp;quot;type&amp;quot;: &amp;quot;line&amp;quot;,&lt;br /&gt;
			&amp;quot;autovalue&amp;quot;: &amp;quot;{{subst:CURRENTMONTHNAME}} {{subst:CURRENTYEAR}}&amp;quot;,&lt;br /&gt;
			&amp;quot;example&amp;quot;: &amp;quot;January 2013&amp;quot;,&lt;br /&gt;
			&amp;quot;suggested&amp;quot;: true&lt;br /&gt;
		},&lt;br /&gt;
		&amp;quot;nosplit&amp;quot;: {&lt;br /&gt;
			&amp;quot;label&amp;quot;: &amp;quot;Don&#039;t suggest splitting&amp;quot;,&lt;br /&gt;
			&amp;quot;description&amp;quot;: &amp;quot;Enter any text here to remove \&amp;quot;splitting content into sub-articles\&amp;quot; from the suggested fix, if the content would not be suitable for splitting (usually because it would fail WP:NOTABILITY as a standalone article).&amp;quot;,&lt;br /&gt;
			&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;,&lt;br /&gt;
			&amp;quot;autovalue&amp;quot;: &amp;quot;y&amp;quot;,&lt;br /&gt;
			&amp;quot;example&amp;quot;: &amp;quot;y&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
		&amp;quot;fix&amp;quot;: {&lt;br /&gt;
			&amp;quot;label&amp;quot;: &amp;quot;Suggested fix&amp;quot;,&lt;br /&gt;
			&amp;quot;description&amp;quot;: &amp;quot;Text to replace the suggested fix (\&amp;quot;Consider splitting content into sub-articles, condensing it, or adding subheadings.\&amp;quot;)&amp;quot;,&lt;br /&gt;
			&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;,&lt;br /&gt;
			&amp;quot;example&amp;quot;: &amp;quot;Consider splitting content into a history sub-article and condensing the geography section.&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
		&amp;quot;small&amp;quot;: {&lt;br /&gt;
			&amp;quot;label&amp;quot;: &amp;quot;Make template small&amp;quot;,&lt;br /&gt;
			&amp;quot;description&amp;quot;: &amp;quot;Enter \&amp;quot;left\&amp;quot; here to make the template box small and aligned to the left. This also condenses the text and replaces \&amp;quot;article\&amp;quot; with \&amp;quot;section\&amp;quot;.&amp;quot;,&lt;br /&gt;
			&amp;quot;type&amp;quot;: &amp;quot;string&amp;quot;,&lt;br /&gt;
			&amp;quot;autovalue&amp;quot;: &amp;quot;left&amp;quot;,&lt;br /&gt;
			&amp;quot;example&amp;quot;: &amp;quot;left&amp;quot;&lt;br /&gt;
		},&lt;br /&gt;
		&amp;quot;words&amp;quot;: {&lt;br /&gt;
			&amp;quot;label&amp;quot;: &amp;quot;Word count&amp;quot;,&lt;br /&gt;
			&amp;quot;description&amp;quot;: &amp;quot;The present word count of the article&amp;quot;,&lt;br /&gt;
			&amp;quot;example&amp;quot;: &amp;quot;15,000&amp;quot;,&lt;br /&gt;
			&amp;quot;type&amp;quot;: &amp;quot;number&amp;quot;&lt;br /&gt;
		}&lt;br /&gt;
	},&lt;br /&gt;
	&amp;quot;paramOrder&amp;quot;: [&lt;br /&gt;
		&amp;quot;date&amp;quot;,&lt;br /&gt;
		&amp;quot;nosplit&amp;quot;,&lt;br /&gt;
		&amp;quot;fix&amp;quot;,&lt;br /&gt;
		&amp;quot;1&amp;quot;,&lt;br /&gt;
		&amp;quot;small&amp;quot;,&lt;br /&gt;
		&amp;quot;words&amp;quot;&lt;br /&gt;
	]&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/templatedata&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== See also ==&lt;br /&gt;
* A list of related [[Wikipedia:Cleanup|cleanup]] templates at [[Wikipedia:Template index/Cleanup]]&lt;br /&gt;
* {{Tl|Lead too long}}&lt;br /&gt;
* {{Tl|Long plot}}&lt;br /&gt;
* {{Tl|Sections}}&lt;br /&gt;
* {{Tl|Subsections}}&lt;br /&gt;
* {{Tl|Summarize section}}&lt;br /&gt;
* {{Tl|Overly detailed}}&lt;br /&gt;
* {{Tl|Too many see alsos}}&lt;br /&gt;
* {{Tl|Very long section}}&lt;br /&gt;
* {{tl|Archive request}} – a template for long talk pages&lt;br /&gt;
&lt;br /&gt;
==Tracking categories==&lt;br /&gt;
* {{clc|Pages using Very long with unknown parameters}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;includeonly&amp;gt;{{Sandbox other||&lt;br /&gt;
&amp;lt;!-- Categories below this line, please; interwikis at Wikidata --&amp;gt;&lt;br /&gt;
[[Category:Cleanup templates]]&lt;br /&gt;
[[Category:Coherency templates]]&lt;br /&gt;
&lt;br /&gt;
}}&amp;lt;/includeonly&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jasper</name></author>
	</entry>
	<entry>
		<id>https://wiki.852r.org/index.php?title=Template:Parameter&amp;diff=3910</id>
		<title>Template:Parameter</title>
		<link rel="alternate" type="text/html" href="https://wiki.852r.org/index.php?title=Template:Parameter&amp;diff=3910"/>
		<updated>2026-08-06T10:46:20Z</updated>

		<summary type="html">&lt;p&gt;Jasper: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{safesubst:&amp;lt;noinclude /&amp;gt;#if:{{{plain|}}}{{{mxt|}}}{{{green|}}}{{{!mxt|}}}{{{red|}}}{{{color|}}}&lt;br /&gt;
	| &amp;lt;code class=&amp;quot;tpl-para&amp;quot; style=&amp;quot;word-break:break-word;{{safesubst:&amp;lt;noinclude /&amp;gt;#if:{{{plain|}}}&lt;br /&gt;
		| border: none; background-color: inherit;&lt;br /&gt;
	}} {{safesubst:&amp;lt;noinclude /&amp;gt;#if:{{{color|}}}&lt;br /&gt;
		| color: {{{color}}};&lt;br /&gt;
		| {{safesubst:&amp;lt;noinclude /&amp;gt;#if:{{{mxt|}}}{{{green|}}}&lt;br /&gt;
			| color: #006400;&lt;br /&gt;
			| {{safesubst:&amp;lt;noinclude /&amp;gt;#if:{{{!mxt|}}}{{{red|}}}&lt;br /&gt;
				| color: #8B0000;&lt;br /&gt;
				| color: inherit;&lt;br /&gt;
			}}&lt;br /&gt;
		}}&lt;br /&gt;
	}} {{safesubst:&amp;lt;noinclude /&amp;gt;#if:{{{style|}}}|{{{style}}}}}&amp;quot;&amp;gt;&amp;amp;#124;{{safesubst:&amp;lt;noinclude /&amp;gt;#if:{{{1|}}}&lt;br /&gt;
		| {{{1}}}&amp;amp;#61;&lt;br /&gt;
	}}{{{2|}}}&amp;lt;/code&amp;gt;&lt;br /&gt;
	| &amp;lt;syntaxhighlight lang=&amp;quot;wikitext&amp;quot; inline style=&amp;quot;display: none;&amp;quot; /&amp;gt;&amp;lt;!-- required to fetch syntaxhighlight&#039;s css --&amp;gt;&amp;lt;code class=&amp;quot;mw-highlight&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;p&amp;quot;&amp;gt;&amp;amp;#124;&amp;lt;/span&amp;gt;{{safesubst:&amp;lt;noinclude /&amp;gt;#if:{{{1|}}}&lt;br /&gt;
		| &amp;lt;span class=&amp;quot;nl&amp;quot;&amp;gt;{{{1}}}&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;o&amp;quot;&amp;gt;=&amp;lt;/span&amp;gt;&lt;br /&gt;
	}}{{{2|}}}&amp;lt;/code&amp;gt;&lt;br /&gt;
}}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{Documentation}}&lt;br /&gt;
&amp;lt;!-- Categories go near the bottom of the /doc subpage – interwikis go to Wikidata, thank you! --&amp;gt;&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jasper</name></author>
	</entry>
	<entry>
		<id>https://wiki.852r.org/index.php?title=Module:Message_box/ombox.css&amp;diff=3908</id>
		<title>Module:Message box/ombox.css</title>
		<link rel="alternate" type="text/html" href="https://wiki.852r.org/index.php?title=Module:Message_box/ombox.css&amp;diff=3908"/>
		<updated>2026-08-06T10:46:20Z</updated>

		<summary type="html">&lt;p&gt;Jasper: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* {{pp|small=y}} */&lt;br /&gt;
.ombox {&lt;br /&gt;
	margin: 4px 0;&lt;br /&gt;
	border-collapse: collapse;&lt;br /&gt;
	border: 1px solid #a2a9b1;    /* Default &amp;quot;notice&amp;quot; gray */&lt;br /&gt;
	background-color: var(--background-color-neutral-subtle, #f8f9fa);&lt;br /&gt;
	box-sizing: border-box;&lt;br /&gt;
    color: var(--color-base, #202122);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* For the &amp;quot;small=yes&amp;quot; option. */&lt;br /&gt;
.ombox.mbox-small {&lt;br /&gt;
	font-size: 88%;&lt;br /&gt;
	line-height: 1.25em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.ombox-speedy {&lt;br /&gt;
	border: 2px solid #b32424;    /* Red */&lt;br /&gt;
	background-color: #fee7e6;    /* Pink */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.ombox-delete {&lt;br /&gt;
	border: 2px solid #b32424;    /* Red */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.ombox-content {&lt;br /&gt;
	border: 1px solid #f28500;    /* Orange */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.ombox-style {&lt;br /&gt;
	border: 1px solid #fc3;       /* Yellow */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.ombox-move {&lt;br /&gt;
	border: 1px solid #9932cc;    /* Purple */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.ombox-protection {&lt;br /&gt;
	border: 2px solid #a2a9b1;    /* Gray-gold */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.ombox .mbox-text {&lt;br /&gt;
	border: none;&lt;br /&gt;
	/* @noflip */&lt;br /&gt;
	padding: 0.25em 0.9em;&lt;br /&gt;
	width: 100%;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.ombox .mbox-image {&lt;br /&gt;
	border: none;&lt;br /&gt;
	/* @noflip */&lt;br /&gt;
	padding: 2px 0 2px 0.9em;&lt;br /&gt;
	text-align: center;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.ombox .mbox-imageright {&lt;br /&gt;
	border: none;&lt;br /&gt;
	/* @noflip */&lt;br /&gt;
	padding: 2px 0.9em 2px 0;&lt;br /&gt;
	text-align: center;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* An empty narrow cell */&lt;br /&gt;
.ombox .mbox-empty-cell {&lt;br /&gt;
	border: none;&lt;br /&gt;
	padding: 0;&lt;br /&gt;
	width: 1px;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* keep synced with each other type of message box as this isn&#039;t qualified */&lt;br /&gt;
.mbox-invalid-type {&lt;br /&gt;
	text-align: center;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
@media (min-width: 720px) {&lt;br /&gt;
	.ombox {&lt;br /&gt;
		margin: 4px 10%;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	.ombox.mbox-small {&lt;br /&gt;
		/* @noflip */&lt;br /&gt;
		clear: right;&lt;br /&gt;
		/* @noflip */&lt;br /&gt;
		float: right;&lt;br /&gt;
		/* @noflip */&lt;br /&gt;
		margin: 4px 0 4px 1em;&lt;br /&gt;
		width: 238px;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/** T367463 */&lt;br /&gt;
body.skin--responsive table.ombox img {&lt;br /&gt;
	max-width: none !important;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
@media screen {&lt;br /&gt;
	html.skin-theme-clientpref-night .ombox-speedy {&lt;br /&gt;
		background-color: #310402;    /* Dark red, same hue/saturation as light */&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
@media screen and (prefers-color-scheme: dark) {&lt;br /&gt;
	html.skin-theme-clientpref-os .ombox-speedy {&lt;br /&gt;
		background-color: #310402; /* Dark red, same hue/saturation as light */&lt;br /&gt;
	}&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Jasper</name></author>
	</entry>
	<entry>
		<id>https://wiki.852r.org/index.php?title=Template:Example_text&amp;diff=3906</id>
		<title>Template:Example text</title>
		<link rel="alternate" type="text/html" href="https://wiki.852r.org/index.php?title=Template:Example_text&amp;diff=3906"/>
		<updated>2026-08-06T10:46:20Z</updated>

		<summary type="html">&lt;p&gt;Jasper: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#ifeq:{{NAMESPACE}}|{{ns:0}}|{{FormattingError|[[:{{safesubst:&amp;lt;noinclude/&amp;gt;#invoke:TEMPLATENAME|main}}]] is only for examples of style and formatting. Do not use it in actual articles.}}|&amp;lt;span class=&amp;quot;example&amp;quot; style=&amp;quot;font-family: Georgia, &#039;DejaVu Serif&#039;, serif; color: var(--color-content-added, #006400);&amp;quot; {{#if:{{{title|}}}|title=&amp;quot;{{{title}}}&amp;quot;}}&amp;gt;{{{1|Example text}}}&amp;lt;/span&amp;gt;}}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{Documentation}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jasper</name></author>
	</entry>
	<entry>
		<id>https://wiki.852r.org/index.php?title=Hongkongggag_Wiki:Template_messages/Splitting/List&amp;diff=3904</id>
		<title>Hongkongggag Wiki:Template messages/Splitting/List</title>
		<link rel="alternate" type="text/html" href="https://wiki.852r.org/index.php?title=Hongkongggag_Wiki:Template_messages/Splitting/List&amp;diff=3904"/>
		<updated>2026-08-06T10:46:20Z</updated>

		<summary type="html">&lt;p&gt;Jasper: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Wikipedia:Template index/Splitting/List]]&lt;br /&gt;
&lt;br /&gt;
{{Redirect category shell|&lt;br /&gt;
{{R from move}}&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Jasper</name></author>
	</entry>
	<entry>
		<id>https://wiki.852r.org/index.php?title=Hongkongggag_Wiki:Template_messages/Merging/List&amp;diff=3902</id>
		<title>Hongkongggag Wiki:Template messages/Merging/List</title>
		<link rel="alternate" type="text/html" href="https://wiki.852r.org/index.php?title=Hongkongggag_Wiki:Template_messages/Merging/List&amp;diff=3902"/>
		<updated>2026-08-06T10:46:20Z</updated>

		<summary type="html">&lt;p&gt;Jasper: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Wikipedia:Template index/Merging/List]]&lt;br /&gt;
&lt;br /&gt;
{{Redirect category shell|&lt;br /&gt;
{{R from move}}&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Jasper</name></author>
	</entry>
	<entry>
		<id>https://wiki.852r.org/index.php?title=Hongkongggag_Wiki:Template_index/Splitting/List&amp;diff=3900</id>
		<title>Hongkongggag Wiki:Template index/Splitting/List</title>
		<link rel="alternate" type="text/html" href="https://wiki.852r.org/index.php?title=Hongkongggag_Wiki:Template_index/Splitting/List&amp;diff=3900"/>
		<updated>2026-08-06T10:46:20Z</updated>

		<summary type="html">&lt;p&gt;Jasper: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Short description|Wikimedia project page}}&lt;br /&gt;
&amp;lt;noinclude&amp;gt;;This page is utilized as a sub-template :which is called and is common to the usage sections of the split templates it lists. &lt;br /&gt;
:It does nothing more than list these links and self-categorize itself.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;{{#if:{{{noheading|}}}||&amp;lt;h2&amp;gt;See also&amp;lt;/h2&amp;gt;&lt;br /&gt;
{{further2|[[Wikipedia:Splitting]]|[[Wikipedia:Merging]]|[[Wikipedia:Section move]]}}&lt;br /&gt;
}}{{#if:{{{only split|}}}||&lt;br /&gt;
&amp;lt;h3&amp;gt;Splitting&amp;lt;/h3&amp;gt;&lt;br /&gt;
}}{{div col|colwidth=15em}}&lt;br /&gt;
* {{tl|Split}}&lt;br /&gt;
* {{tl|Being split}}&lt;br /&gt;
* {{tl|Split section}}&lt;br /&gt;
* {{tl|Split sections}}&lt;br /&gt;
* {{tl|Split portions}}&lt;br /&gt;
* {{tl|Split section portions}}&lt;br /&gt;
* {{tl|Cleanup split}}&lt;br /&gt;
* {{tl|Copied}}&lt;br /&gt;
* {{tl|Split dab}}&lt;br /&gt;
* {{tl|Split and dab}}&lt;br /&gt;
* {{tl|Split article}}&lt;br /&gt;
* {{tl|Very long}}&lt;br /&gt;
{{div col end}}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
[[Category:Documentation see also templates|Splitting]]&lt;br /&gt;
[[Category:Wikipedia template administration]]&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jasper</name></author>
	</entry>
	<entry>
		<id>https://wiki.852r.org/index.php?title=Hongkongggag_Wiki:Template_index/Merging/List&amp;diff=3898</id>
		<title>Hongkongggag Wiki:Template index/Merging/List</title>
		<link rel="alternate" type="text/html" href="https://wiki.852r.org/index.php?title=Hongkongggag_Wiki:Template_index/Merging/List&amp;diff=3898"/>
		<updated>2026-08-06T10:46:20Z</updated>

		<summary type="html">&lt;p&gt;Jasper: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;noinclude&amp;gt;;This page is utilized as a sub-template :which is called and is common to the usage sections of the merge templates it lists. &lt;br /&gt;
:It does nothing more than list these links and self-categorize itself.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;{{#if:{{{noheading|}}}||&amp;lt;h2&amp;gt;See also&amp;lt;/h2&amp;gt;&lt;br /&gt;
{{further|Wikipedia:Splitting|Wikipedia:Merging}}&lt;br /&gt;
}}{{#if:{{{only merge|}}}||&lt;br /&gt;
&amp;lt;h3&amp;gt;Merging&amp;lt;/h3&amp;gt;&lt;br /&gt;
}}{{div col|colwidth=15em}}&lt;br /&gt;
* {{tl|Merge}} - DEPRECATED&lt;br /&gt;
* {{tl|Merge to}} - DEPRECATED&lt;br /&gt;
* {{tl|Merge from}} - new discussions use &amp;quot;afd&amp;quot; parameter&lt;br /&gt;
* {{tl|AfDM}} - replaces &amp;quot;Merge to&amp;quot; for new discussions&lt;br /&gt;
* {{tl|Afd-merge to}} - merges with consensus that have not been implemented yet, in the new system&lt;br /&gt;
* {{tl|Being merged}}&lt;br /&gt;
* {{tl|Merge portions from}}&lt;br /&gt;
* {{tl|Cleanup merge}}&lt;br /&gt;
* {{tl|Copied}}&lt;br /&gt;
* {{tl|Merged-to}}&lt;br /&gt;
* {{tl|Merged-from}}&lt;br /&gt;
* {{tl|Old merge}}&lt;br /&gt;
* {{tl|Duplication}}&lt;br /&gt;
{{div col end|}}&lt;br /&gt;
{{#if:{{{only merge|}}}||&lt;br /&gt;
===Section moving===&lt;br /&gt;
{{div col|colwidth=15em}}&lt;br /&gt;
* {{tl|Section move from}}&lt;br /&gt;
* {{tl|Section move to}}&lt;br /&gt;
{{div col end|}}}}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
[[Category:Documentation see also templates|Merging]]&lt;br /&gt;
[[Category:Wikipedia template administration]]&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jasper</name></author>
	</entry>
	<entry>
		<id>https://wiki.852r.org/index.php?title=Template:Template_shortcut&amp;diff=3896</id>
		<title>Template:Template shortcut</title>
		<link rel="alternate" type="text/html" href="https://wiki.852r.org/index.php?title=Template:Template_shortcut&amp;diff=3896"/>
		<updated>2026-08-06T10:46:19Z</updated>

		<summary type="html">&lt;p&gt;Jasper: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;{{#invoke:Shortcut|main|template=yes}}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;{{Documentation}}&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jasper</name></author>
	</entry>
	<entry>
		<id>https://wiki.852r.org/index.php?title=Template:Clc&amp;diff=3894</id>
		<title>Template:Clc</title>
		<link rel="alternate" type="text/html" href="https://wiki.852r.org/index.php?title=Template:Clc&amp;diff=3894"/>
		<updated>2026-08-06T10:46:19Z</updated>

		<summary type="html">&lt;p&gt;Jasper: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Template:Category link with count]]&lt;/div&gt;</summary>
		<author><name>Jasper</name></author>
	</entry>
	<entry>
		<id>https://wiki.852r.org/index.php?title=Template:Template_parameter_usage&amp;diff=3892</id>
		<title>Template:Template parameter usage</title>
		<link rel="alternate" type="text/html" href="https://wiki.852r.org/index.php?title=Template:Template_parameter_usage&amp;diff=3892"/>
		<updated>2026-08-06T10:46:19Z</updated>

		<summary type="html">&lt;p&gt;Jasper: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#switch:{{{label|}}}&lt;br /&gt;
 |=[https://bambots.brucemyers.com/TemplateParam.php?wiki=enwiki&amp;amp;template={{Urlencode:{{#if:{{{1|}}}|{{ROOTPAGENAME:{{{1|}}}}}|{{ROOTPAGENAME}}}}}} {{#ifeq:{{yesno-no|{{{lc}}}}}|no|S|s}}ee a monthly parameter usage report] for {{#if:{{{1|}}}|[[Template:{{ROOTPAGENAME:{{{1|}}}}}]]|this template}} in articles{{#ifeq:{{yesno-no|{{{based}}}}}|yes|&amp;amp;#32;based on {{#if:{{{1|}}}|its|this}} TemplateData}}.&lt;br /&gt;
 |None|none=[https://bambots.brucemyers.com/TemplateParam.php?wiki=enwiki&amp;amp;template={{Urlencode:{{#if:{{{1|}}}|{{ROOTPAGENAME:{{{1|}}}}}|{{ROOTPAGENAME}}}}}} {{#ifeq:{{yesno-no|{{{lc}}}}}|no|P|p}}arameter usage report]{{#ifeq:{{yesno-no|{{{based}}}}}|yes|&amp;amp;#32;based on {{#if:{{{1|}}}|its|this}} TemplateData}}&lt;br /&gt;
 |for|For=[https://bambots.brucemyers.com/TemplateParam.php?wiki=enwiki&amp;amp;template={{Urlencode:{{#if:{{{1|}}}|{{ROOTPAGENAME:{{{1|}}}}}|{{ROOTPAGENAME}}}}}} {{#ifeq:{{yesno-no|{{{lc}}}}}|no|P|p}}arameter usage report] for {{#if:{{{1|}}}|[[Template:{{ROOTPAGENAME:{{{1|}}}}}]]|[[Template:{{ROOTPAGENAME}}]]}}{{#ifeq:{{yesno-no|{{{based}}}}}|yes|&amp;amp;#32;based on {{#if:{{{1|}}}|its|this}} TemplateData}}.&lt;br /&gt;
 |#default=[https://bambots.brucemyers.com/TemplateParam.php?wiki=enwiki&amp;amp;template={{Urlencode:{{#if:{{{1|}}}|{{ROOTPAGENAME:{{{1|}}}}}|{{ROOTPAGENAME}}}}}} {{{label|}}}]{{#ifeq:{{yesno-no|{{{based}}}}}|yes|&amp;amp;#32;based on {{#if:{{{1|}}}|its|this}} TemplateData}}&lt;br /&gt;
}}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{documentation}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jasper</name></author>
	</entry>
	<entry>
		<id>https://wiki.852r.org/index.php?title=Template:TemplateData_header&amp;diff=3890</id>
		<title>Template:TemplateData header</title>
		<link rel="alternate" type="text/html" href="https://wiki.852r.org/index.php?title=Template:TemplateData_header&amp;diff=3890"/>
		<updated>2026-08-06T10:46:19Z</updated>

		<summary type="html">&lt;p&gt;Jasper: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div class=&amp;quot;templatedata-header&amp;quot;&amp;gt;{{#if:{{{noheader|}}}|&amp;lt;!--&lt;br /&gt;
 noheader:&lt;br /&gt;
--&amp;gt;{{Template parameter usage|{{{1|{{BASEPAGENAME}}}}}|based=y}}|&amp;lt;!--&lt;br /&gt;
 +header:&lt;br /&gt;
--&amp;gt;This is the {{#if:{{{nolink|}}}|&amp;lt;!--&lt;br /&gt;
  +header, nolink TD&lt;br /&gt;
  --&amp;gt;TemplateData|&amp;lt;!--&lt;br /&gt;
  +header,  +link [[TD]]; DEFAULT:&lt;br /&gt;
--&amp;gt;[[Wikipedia:TemplateData|TemplateData]]}}&amp;lt;!--&lt;br /&gt;
   e.o. #if:nolink; DEFAULT:&lt;br /&gt;
--&amp;gt; for this template used by [[mw:Extension:TemplateWizard|TemplateWizard]], [[Wikipedia:VisualEditor|VisualEditor]] and other tools. {{Template parameter usage|{{{1|{{BASEPAGENAME}}}}}|based=y}}&amp;lt;!--&lt;br /&gt;
   e.o. #if:noheader&lt;br /&gt;
--&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TemplateData for {{{1|{{BASEPAGENAME}}}}}&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;/div&amp;gt;&amp;lt;includeonly&amp;gt;&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
 check parameters&lt;br /&gt;
--&amp;gt;{{#invoke:Check for unknown parameters|check&lt;br /&gt;
|unknown={{template other|1=[[Category:Pages using TemplateData header with unknown parameters|_VALUE_]]}}&lt;br /&gt;
|template=Template:TemplateData header&lt;br /&gt;
|1 |nolink |noheader&lt;br /&gt;
|preview=&amp;lt;div class=&amp;quot;error&amp;quot; style=&amp;quot;font-weight:normal&amp;quot;&amp;gt;Unknown parameter &#039;_VALUE_&#039; in [[Template:TemplateData header]].&amp;lt;/div&amp;gt;&lt;br /&gt;
}}&amp;lt;!--&lt;br /&gt;
--&amp;gt;{{template other|{{sandbox other||&lt;br /&gt;
[[Category:Templates using TemplateData]]&lt;br /&gt;
&lt;br /&gt;
}}}}&amp;lt;/includeonly&amp;gt;&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
--&amp;gt;&amp;lt;noinclude&amp;gt;{{Documentation}}&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jasper</name></author>
	</entry>
	<entry>
		<id>https://wiki.852r.org/index.php?title=Template:Twinkle_standard_installation&amp;diff=3888</id>
		<title>Template:Twinkle standard installation</title>
		<link rel="alternate" type="text/html" href="https://wiki.852r.org/index.php?title=Template:Twinkle_standard_installation&amp;diff=3888"/>
		<updated>2026-08-06T10:46:19Z</updated>

		<summary type="html">&lt;p&gt;Jasper: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Mbox&lt;br /&gt;
| image = [[File:Twinkle logo.svg|50x40px|alt=Logo of Twinkle|link=]]&lt;br /&gt;
| text = Any [[Template:Twinkle standard installation#&amp;quot;Breaking changes&amp;quot;|breaking changes]] to this template, including moving it or nominating it for deletion, {{strong|must be communicated in advance}} to [[Wikipedia:Twinkle|Twinkle]]&#039;s users and maintainers at [[Wikipedia talk:Twinkle]]. The standard installation of Twinkle relies on this template. Thank you.{{#if:{{{1|}}}|&amp;lt;br&amp;gt;&lt;br /&gt;
{{{1}}}}}}}&amp;lt;includeonly&amp;gt;{{#if:{{{nocat|}}}||{{#ifeq:{{PAGENAME}}|{{BASEPAGENAME}}|[[Category:Templates used by Twinkle|{{PAGENAME}}]]}}}}&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{Documentation}}&amp;lt;!-- Add categories and interwikis to the /doc subpage, not here! --&amp;gt;&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jasper</name></author>
	</entry>
	<entry>
		<id>https://wiki.852r.org/index.php?title=Template:Very_long_section&amp;diff=3886</id>
		<title>Template:Very long section</title>
		<link rel="alternate" type="text/html" href="https://wiki.852r.org/index.php?title=Template:Very_long_section&amp;diff=3886"/>
		<updated>2026-08-06T10:46:19Z</updated>

		<summary type="html">&lt;p&gt;Jasper: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{ {{{|safesubst:}}}#invoke:Unsubst||date=__DATE__ |$B=&lt;br /&gt;
{{Very long&lt;br /&gt;
|name=Very long section&lt;br /&gt;
|subst=&amp;lt;includeonly&amp;gt;{{subst:&amp;lt;/includeonly&amp;gt;&amp;lt;includeonly&amp;gt;substcheck}}&amp;lt;/includeonly&amp;gt;&lt;br /&gt;
|1=section&lt;br /&gt;
|date={{{date|}}}&lt;br /&gt;
|nosplit={{{nosplit|}}}&lt;br /&gt;
}}&lt;br /&gt;
}}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{documentation}}&amp;lt;!--Please add this template&#039;s categories to the /doc subpage, interwikis to Wikidata, not here - thanks!--&amp;gt;&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jasper</name></author>
	</entry>
	<entry>
		<id>https://wiki.852r.org/index.php?title=Module:Shortcut/config&amp;diff=3884</id>
		<title>Module:Shortcut/config</title>
		<link rel="alternate" type="text/html" href="https://wiki.852r.org/index.php?title=Module:Shortcut/config&amp;diff=3884"/>
		<updated>2026-08-06T10:46:19Z</updated>

		<summary type="html">&lt;p&gt;Jasper: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- This module holds configuration data for [[Module:Shortcut]].&lt;br /&gt;
&lt;br /&gt;
return {&lt;br /&gt;
&lt;br /&gt;
-- The heading at the top of the shortcut box. It accepts the following parameter:&lt;br /&gt;
-- $1 - the total number of shortcuts. (required)&lt;br /&gt;
[&#039;shortcut-heading&#039;] = &#039;[[Wikipedia:Shortcut|{{PLURAL:$1|Shortcut|Shortcuts}}]]&#039;,&lt;br /&gt;
&lt;br /&gt;
-- The heading when |redirect=yes is given. It accepts the following parameter:&lt;br /&gt;
-- $1 - the total number of shortcuts. (required)&lt;br /&gt;
[&#039;redirect-heading&#039;] = &#039;[[Wikipedia:Redirect|{{PLURAL:$1|Redirect|Redirects}}]]&#039;,&lt;br /&gt;
&lt;br /&gt;
-- The error message to display when a shortcut is invalid (is not a string, or&lt;br /&gt;
-- is the blank string). It accepts the following parameter:&lt;br /&gt;
-- $1 - the number of the shortcut in the argument list. (required)&lt;br /&gt;
[&#039;invalid-shortcut-error&#039;] = &#039;shortcut #$1 was invalid (shortcuts must be &#039; ..&lt;br /&gt;
	&#039;strings of at least one character in length)&#039;,&lt;br /&gt;
&lt;br /&gt;
-- The error message to display when no shortcuts or other displayable content&lt;br /&gt;
-- were specified. (required)&lt;br /&gt;
[&#039;no-content-error&#039;] = &#039;Error: no shortcuts were specified and the &#039; ..&lt;br /&gt;
	mw.text.nowiki(&#039;|msg=&#039;) ..&lt;br /&gt;
	&#039; parameter was not set.&#039;,&lt;br /&gt;
&lt;br /&gt;
-- A category to add when the no-content-error message is displayed. (optional)&lt;br /&gt;
[&#039;no-content-error-category&#039;] = &#039;Shortcut templates with missing parameters&#039;,&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Jasper</name></author>
	</entry>
	<entry>
		<id>https://wiki.852r.org/index.php?title=Module:Shortcut&amp;diff=3882</id>
		<title>Module:Shortcut</title>
		<link rel="alternate" type="text/html" href="https://wiki.852r.org/index.php?title=Module:Shortcut&amp;diff=3882"/>
		<updated>2026-08-06T10:46:19Z</updated>

		<summary type="html">&lt;p&gt;Jasper: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- This module implements {{shortcut}}.&lt;br /&gt;
&lt;br /&gt;
-- Set constants&lt;br /&gt;
local CONFIG_MODULE = &#039;Module:Shortcut/config&#039;&lt;br /&gt;
&lt;br /&gt;
-- Load required modules&lt;br /&gt;
local checkType = require(&#039;libraryUtil&#039;).checkType&lt;br /&gt;
local yesno = require(&#039;Module:Yesno&#039;)&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
local function message(msg, ...)&lt;br /&gt;
	return mw.message.newRawMessage(msg, ...):plain()&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function makeCategoryLink(cat)&lt;br /&gt;
	return string.format(&#039;[[%s:%s]]&#039;, mw.site.namespaces[14].name, cat)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p._main(shortcuts, options, frame, cfg)&lt;br /&gt;
	checkType(&#039;_main&#039;, 1, shortcuts, &#039;table&#039;)&lt;br /&gt;
	checkType(&#039;_main&#039;, 2, options, &#039;table&#039;, true)&lt;br /&gt;
	options = options or {}&lt;br /&gt;
	frame = frame or mw.getCurrentFrame()&lt;br /&gt;
	cfg = cfg or mw.loadData(CONFIG_MODULE)&lt;br /&gt;
	local templateMode = options.template and yesno(options.template)&lt;br /&gt;
	local redirectMode = options.redirect and yesno(options.redirect)&lt;br /&gt;
	local isCategorized = not options.category or yesno(options.category) ~= false&lt;br /&gt;
&lt;br /&gt;
	-- Validate shortcuts&lt;br /&gt;
	for i, shortcut in ipairs(shortcuts) do&lt;br /&gt;
		if type(shortcut) ~= &#039;string&#039; or #shortcut &amp;lt; 1 then&lt;br /&gt;
			error(message(cfg[&#039;invalid-shortcut-error&#039;], i), 2)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Make the list items. These are the shortcuts plus any extra lines such&lt;br /&gt;
	-- as options.msg.&lt;br /&gt;
	local listItems = {}&lt;br /&gt;
	for i, shortcut in ipairs(shortcuts) do&lt;br /&gt;
		local templatePath, prefix&lt;br /&gt;
		if templateMode then&lt;br /&gt;
			-- Namespace detection&lt;br /&gt;
			local titleObj = mw.title.new(shortcut, 10)&lt;br /&gt;
			if titleObj.namespace == 10 then&lt;br /&gt;
				templatePath = titleObj.fullText&lt;br /&gt;
			else&lt;br /&gt;
				templatePath = shortcut&lt;br /&gt;
			end&lt;br /&gt;
			prefix = options[&#039;pre&#039; .. i] or options.pre or &#039;&#039;&lt;br /&gt;
		end&lt;br /&gt;
		if options.target and yesno(options.target) then&lt;br /&gt;
			listItems[i] = templateMode&lt;br /&gt;
				and string.format(&amp;quot;&amp;amp;#123;&amp;amp;#123;%s[[%s|%s]]&amp;amp;#125;&amp;amp;#125;&amp;quot;, prefix, templatePath, shortcut)&lt;br /&gt;
				or string.format(&amp;quot;[[%s]]&amp;quot;, shortcut)&lt;br /&gt;
		else&lt;br /&gt;
			listItems[i] = frame:expandTemplate{&lt;br /&gt;
				title = &#039;No redirect&#039;,&lt;br /&gt;
				args = templateMode and {templatePath, shortcut} or {shortcut, shortcut}&lt;br /&gt;
			}&lt;br /&gt;
			if templateMode then&lt;br /&gt;
				listItems[i] = string.format(&amp;quot;&amp;amp;#123;&amp;amp;#123;%s%s&amp;amp;#125;&amp;amp;#125;&amp;quot;, prefix, listItems[i])&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	table.insert(listItems, options.msg)&lt;br /&gt;
&lt;br /&gt;
	-- Return an error if we have nothing to display&lt;br /&gt;
	if #listItems &amp;lt; 1 then&lt;br /&gt;
		local msg = cfg[&#039;no-content-error&#039;]&lt;br /&gt;
		msg = string.format(&#039;&amp;lt;strong class=&amp;quot;error&amp;quot;&amp;gt;%s&amp;lt;/strong&amp;gt;&#039;, msg)&lt;br /&gt;
		if isCategorized and cfg[&#039;no-content-error-category&#039;] then&lt;br /&gt;
			msg = msg .. makeCategoryLink(cfg[&#039;no-content-error-category&#039;])&lt;br /&gt;
		end&lt;br /&gt;
		return msg&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local root = mw.html.create()&lt;br /&gt;
	root:wikitext(frame:extensionTag{ name = &#039;templatestyles&#039;, args = { src = &#039;Module:Shortcut/styles.css&#039;} })&lt;br /&gt;
	-- Anchors&lt;br /&gt;
	local anchorDiv = root&lt;br /&gt;
		:tag(&#039;div&#039;)&lt;br /&gt;
			:addClass(&#039;module-shortcutanchordiv&#039;)&lt;br /&gt;
	for i, shortcut in ipairs(shortcuts) do&lt;br /&gt;
		local anchor = mw.uri.anchorEncode(shortcut)&lt;br /&gt;
		anchorDiv:tag(&#039;span&#039;):attr(&#039;id&#039;, anchor)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Shortcut heading&lt;br /&gt;
	local shortcutHeading&lt;br /&gt;
	do&lt;br /&gt;
		local nShortcuts = #shortcuts&lt;br /&gt;
		if nShortcuts &amp;gt; 0 then&lt;br /&gt;
			local headingMsg = options[&#039;shortcut-heading&#039;] or&lt;br /&gt;
				redirectMode and cfg[&#039;redirect-heading&#039;] or&lt;br /&gt;
				cfg[&#039;shortcut-heading&#039;]&lt;br /&gt;
			shortcutHeading = message(headingMsg, nShortcuts)&lt;br /&gt;
			shortcutHeading = frame:preprocess(shortcutHeading)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Shortcut box&lt;br /&gt;
	local shortcutList = root&lt;br /&gt;
		:tag(&#039;div&#039;)&lt;br /&gt;
			:addClass(&#039;module-shortcutboxplain noprint&#039;)&lt;br /&gt;
			:attr(&#039;role&#039;, &#039;note&#039;)&lt;br /&gt;
	if options.float and options.float:lower() == &#039;left&#039; then&lt;br /&gt;
		shortcutList:addClass(&#039;module-shortcutboxleft&#039;)&lt;br /&gt;
	end&lt;br /&gt;
	if options.clear and options.clear ~= &#039;&#039; then&lt;br /&gt;
		shortcutList:css(&#039;clear&#039;, options.clear)&lt;br /&gt;
	end&lt;br /&gt;
	if shortcutHeading then&lt;br /&gt;
		shortcutList&lt;br /&gt;
			:tag(&#039;div&#039;)&lt;br /&gt;
				:addClass(&#039;module-shortcutlist&#039;)&lt;br /&gt;
				:wikitext(shortcutHeading)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local ubl = require(&#039;Module:List&#039;).unbulleted(listItems)&lt;br /&gt;
	shortcutList:wikitext(ubl)&lt;br /&gt;
	return tostring(root)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.main(frame)&lt;br /&gt;
	local args = require(&#039;Module:Arguments&#039;).getArgs(frame)&lt;br /&gt;
&lt;br /&gt;
	-- Separate shortcuts from options&lt;br /&gt;
	local shortcuts, options = {}, {}&lt;br /&gt;
	for k, v in pairs(args) do&lt;br /&gt;
		if type(k) == &#039;number&#039; then&lt;br /&gt;
			shortcuts[k] = v&lt;br /&gt;
		else&lt;br /&gt;
			options[k] = v&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Compress the shortcut array, which may contain nils.&lt;br /&gt;
	local function compressArray(t)&lt;br /&gt;
		local nums, ret = {}, {}&lt;br /&gt;
		for k in pairs(t) do&lt;br /&gt;
			nums[#nums + 1] = k&lt;br /&gt;
		end&lt;br /&gt;
		table.sort(nums)&lt;br /&gt;
		for i, num in ipairs(nums) do&lt;br /&gt;
			ret[i] = t[num]&lt;br /&gt;
		end&lt;br /&gt;
		return ret&lt;br /&gt;
	end&lt;br /&gt;
	shortcuts = compressArray(shortcuts)&lt;br /&gt;
&lt;br /&gt;
	return p._main(shortcuts, options, frame)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Jasper</name></author>
	</entry>
	<entry>
		<id>https://wiki.852r.org/index.php?title=Template:Documentation_subpage&amp;diff=3880</id>
		<title>Template:Documentation subpage</title>
		<link rel="alternate" type="text/html" href="https://wiki.852r.org/index.php?title=Template:Documentation_subpage&amp;diff=3880"/>
		<updated>2026-08-06T10:46:19Z</updated>

		<summary type="html">&lt;p&gt;Jasper: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&amp;lt;!--&lt;br /&gt;
 --&amp;gt;{{#ifeq:{{lc:{{SUBPAGENAME}}}} |{{{override|doc}}}&lt;br /&gt;
     | &amp;lt;!--(this template has been transcluded on a /doc or /{{{override}}} page)--&amp;gt;&lt;br /&gt;
&amp;lt;/includeonly&amp;gt;&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
      --&amp;gt;{{#ifeq:{{{doc-notice|show}}} |show&lt;br /&gt;
          | {{Mbox&lt;br /&gt;
             | type = notice&lt;br /&gt;
             | style = margin-bottom:1.0em;&lt;br /&gt;
             | image = [[File:Edit-copy green.svg|40px|alt=icon]]&lt;br /&gt;
             | text =&lt;br /&gt;
{{strong|This is a [[Wikipedia:Template documentation|documentation subpage]]}} for {{terminate sentence|{{{1|[[:{{SUBJECTSPACE}}:{{BASEPAGENAME}}]]}}}}}&amp;lt;br /&amp;gt;It may contain usage information, [[Wikipedia:Categorization|categories]] and other content that is not part of the original {{#if:{{{text2|}}} |{{{text2}}} |{{#if:{{{text1|}}} |{{{text1}}} |{{#ifeq:{{SUBJECTSPACE}} |{{ns:User}} |{{lc:{{SUBJECTSPACE}}}} template page |{{#if:{{SUBJECTSPACE}} |{{lc:{{SUBJECTSPACE}}}} page|article}}}}}}}}. &lt;br /&gt;
            }}&lt;br /&gt;
         }}&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
      --&amp;gt;{{DEFAULTSORT:{{{defaultsort|{{PAGENAME}}}}}}}&amp;lt;!--&lt;br /&gt;
      &lt;br /&gt;
      --&amp;gt;&amp;lt;includeonly&amp;gt;__EXPECTED_UNCONNECTED_PAGE__&amp;lt;/includeonly&amp;gt;&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
      --&amp;gt;{{#if:{{{nocat|}}}{{{inhibit|}}}|&amp;lt;!--(don&#039;t categorize)--&amp;gt;&lt;br /&gt;
          |&amp;lt;includeonly&amp;gt;&amp;lt;!--&lt;br /&gt;
               --&amp;gt;{{#ifexist:{{NAMESPACE}}:{{BASEPAGENAME}}&lt;br /&gt;
                   | [[Category:{{#switch:{{SUBJECTSPACE}} |Template=Template |Module=Module |User=User |#default=Wikipedia}} documentation pages]]&lt;br /&gt;
                   | [[Category:Documentation subpages without corresponding pages]]&lt;br /&gt;
                  }}&amp;lt;!--&lt;br /&gt;
           --&amp;gt;&amp;lt;/includeonly&amp;gt;&lt;br /&gt;
         }}&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
(completing initial #ifeq: at start of template:)&lt;br /&gt;
--&amp;gt;&amp;lt;includeonly&amp;gt;&lt;br /&gt;
     | &amp;lt;!--(this template has not been transcluded on a /doc or /{{{override}}} page)--&amp;gt;&lt;br /&gt;
    }}&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;{{Documentation}}&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jasper</name></author>
	</entry>
	<entry>
		<id>https://wiki.852r.org/index.php?title=Template:Sandbox_other&amp;diff=3878</id>
		<title>Template:Sandbox other</title>
		<link rel="alternate" type="text/html" href="https://wiki.852r.org/index.php?title=Template:Sandbox_other&amp;diff=3878"/>
		<updated>2026-08-06T10:46:19Z</updated>

		<summary type="html">&lt;p&gt;Jasper: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;onlyinclude&amp;gt;{{safesubst:&amp;lt;noinclude/&amp;gt;#if:{{safesubst:&amp;lt;noinclude/&amp;gt;#ifeq:{{safesubst:&amp;lt;noinclude/&amp;gt;#invoke:String|sublength|s={{safesubst:&amp;lt;noinclude/&amp;gt;SUBPAGENAME}}|i=0|len=7}}|sandbox|1}}{{safesubst:&amp;lt;noinclude/&amp;gt;#ifeq:{{safesubst:&amp;lt;noinclude/&amp;gt;SUBPAGENAME}}|doc|1}}{{safesubst:&amp;lt;noinclude/&amp;gt;#invoke:String|match|{{safesubst:&amp;lt;noinclude/&amp;gt;PAGENAME}}|/sandbox/styles.css$|plain=false|nomatch=}}|{{{1|}}}|{{{2|}}}}}&amp;lt;/onlyinclude&amp;gt;&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
--&amp;gt;{{documentation}}&lt;/div&gt;</summary>
		<author><name>Jasper</name></author>
	</entry>
	<entry>
		<id>https://wiki.852r.org/index.php?title=Module:Documentation/styles.css&amp;diff=3876</id>
		<title>Module:Documentation/styles.css</title>
		<link rel="alternate" type="text/html" href="https://wiki.852r.org/index.php?title=Module:Documentation/styles.css&amp;diff=3876"/>
		<updated>2026-08-06T10:46:19Z</updated>

		<summary type="html">&lt;p&gt;Jasper: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* {{pp|small=yes}} */&lt;br /&gt;
.documentation,&lt;br /&gt;
.documentation-metadata {&lt;br /&gt;
	border: 1px solid var( --border-color-base, #a2a9b1 );&lt;br /&gt;
	background-color: #ecfcf4;&lt;br /&gt;
	color:inherit;&lt;br /&gt;
	clear: both;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.documentation {&lt;br /&gt;
	margin: 1em 0 0 0;&lt;br /&gt;
	padding: 1em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.documentation-metadata {&lt;br /&gt;
	margin: 0.2em 0; /* same margin left-right as .documentation */&lt;br /&gt;
    font-style: italic;&lt;br /&gt;
    padding: 0.4em 1em; /* same padding left-right as .documentation */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.documentation-startbox {&lt;br /&gt;
	padding-bottom: 3px;&lt;br /&gt;
	border-bottom: 1px solid var( --border-color-base, #a2a9b1 );&lt;br /&gt;
	margin-bottom: 1ex;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.documentation-heading {&lt;br /&gt;
	font-weight: bold;&lt;br /&gt;
	font-size: 125%;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
body.skin-minerva .documentation-startbox .mw-editsection-like a,&lt;br /&gt;
body.skin-timeless .documentation-startbox .mw-editsection-like a {&lt;br /&gt;
	display: inline-block;&lt;br /&gt;
	margin-left: 0.3em;&lt;br /&gt;
	margin-right: 0.3em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.documentation-clear { /* Don&#039;t want things to stick out where they shouldn&#039;t. */&lt;br /&gt;
	clear: both;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.documentation-toolbar {&lt;br /&gt;
	font-style: normal;&lt;br /&gt;
	font-size: 85%;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
@media screen {&lt;br /&gt;
    html.skin-theme-clientpref-night .documentation,&lt;br /&gt;
	html.skin-theme-clientpref-night .documentation-metadata {&lt;br /&gt;
	    background-color: #0b1e1c;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
@media screen and ( prefers-color-scheme: dark ) {&lt;br /&gt;
    html.skin-theme-clientpref-os .documentation,&lt;br /&gt;
    html.skin-theme-clientpref-os .documentation-metadata {&lt;br /&gt;
        background-color: #0b1e1c;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Jasper</name></author>
	</entry>
	<entry>
		<id>https://wiki.852r.org/index.php?title=Module:Documentation/config&amp;diff=3874</id>
		<title>Module:Documentation/config</title>
		<link rel="alternate" type="text/html" href="https://wiki.852r.org/index.php?title=Module:Documentation/config&amp;diff=3874"/>
		<updated>2026-08-06T10:46:19Z</updated>

		<summary type="html">&lt;p&gt;Jasper: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;----------------------------------------------------------------------------------------------------&lt;br /&gt;
--&lt;br /&gt;
--                               Configuration for Module:Documentation&lt;br /&gt;
--&lt;br /&gt;
-- Here you can set the values of the parameters and messages used in Module:Documentation to&lt;br /&gt;
-- localise it to your wiki and your language. Unless specified otherwise, values given here&lt;br /&gt;
-- should be string values.&lt;br /&gt;
----------------------------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local cfg = {} -- Do not edit this line.&lt;br /&gt;
&lt;br /&gt;
----------------------------------------------------------------------------------------------------&lt;br /&gt;
-- Protection template configuration&lt;br /&gt;
----------------------------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;protection-reason-edit&#039;]&lt;br /&gt;
-- The protection reason for edit-protected templates to pass to&lt;br /&gt;
-- [[Module:Protection banner]].&lt;br /&gt;
cfg[&#039;protection-reason-edit&#039;] = &#039;template&#039;&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
----------------------------------------------------------------------------------------------------&lt;br /&gt;
-- Sandbox notice configuration&lt;br /&gt;
--&lt;br /&gt;
-- On sandbox pages the module can display a template notifying users that the current page is a&lt;br /&gt;
-- sandbox, and the location of test cases pages, etc. The module decides whether the page is a&lt;br /&gt;
-- sandbox or not based on the value of cfg[&#039;sandbox-subpage&#039;]. The following settings configure the&lt;br /&gt;
-- messages that the notices contains.&lt;br /&gt;
----------------------------------------------------------------------------------------------------&lt;br /&gt;
--]]&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;sandbox-notice-image&#039;]&lt;br /&gt;
-- The image displayed in the sandbox notice.&lt;br /&gt;
cfg[&#039;sandbox-notice-image&#039;] = &#039;[[File:Edit In Sandbox Icon - Color.svg|50px|alt=|link=]]&#039;&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
-- cfg[&#039;sandbox-notice-pagetype-template&#039;]&lt;br /&gt;
-- cfg[&#039;sandbox-notice-pagetype-module&#039;]&lt;br /&gt;
-- cfg[&#039;sandbox-notice-pagetype-other&#039;]&lt;br /&gt;
-- The page type of the sandbox page. The message that is displayed depends on the current subject&lt;br /&gt;
-- namespace. This message is used in either cfg[&#039;sandbox-notice-blurb&#039;] or&lt;br /&gt;
-- cfg[&#039;sandbox-notice-diff-blurb&#039;].&lt;br /&gt;
--]]&lt;br /&gt;
cfg[&#039;sandbox-notice-pagetype-template&#039;] = &#039;[[Wikipedia:Template test cases|template sandbox]] page&#039;&lt;br /&gt;
cfg[&#039;sandbox-notice-pagetype-module&#039;] = &#039;[[Wikipedia:Template test cases|module sandbox]] page&#039;&lt;br /&gt;
cfg[&#039;sandbox-notice-pagetype-other&#039;] = &#039;sandbox page&#039;&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
-- cfg[&#039;sandbox-notice-blurb&#039;]&lt;br /&gt;
-- cfg[&#039;sandbox-notice-diff-blurb&#039;]&lt;br /&gt;
-- cfg[&#039;sandbox-notice-diff-display&#039;]&lt;br /&gt;
-- Either cfg[&#039;sandbox-notice-blurb&#039;] or cfg[&#039;sandbox-notice-diff-blurb&#039;] is the opening sentence&lt;br /&gt;
-- of the sandbox notice. The latter has a diff link, but the former does not. $1 is the page&lt;br /&gt;
-- type, which is either cfg[&#039;sandbox-notice-pagetype-template&#039;],&lt;br /&gt;
-- cfg[&#039;sandbox-notice-pagetype-module&#039;] or cfg[&#039;sandbox-notice-pagetype-other&#039;] depending what&lt;br /&gt;
-- namespace we are in. $2 is a link to the main template page, and $3 is a diff link between&lt;br /&gt;
-- the sandbox and the main template. The display value of the diff link is set by &lt;br /&gt;
-- cfg[&#039;sandbox-notice-compare-link-display&#039;].&lt;br /&gt;
--]]&lt;br /&gt;
cfg[&#039;sandbox-notice-blurb&#039;] = &#039;This is the $1 for $2.&#039;&lt;br /&gt;
cfg[&#039;sandbox-notice-diff-blurb&#039;] = &#039;This is the $1 for $2 ($3).&#039;&lt;br /&gt;
cfg[&#039;sandbox-notice-compare-link-display&#039;] = &#039;diff&#039;&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
-- cfg[&#039;sandbox-notice-testcases-blurb&#039;]&lt;br /&gt;
-- cfg[&#039;sandbox-notice-testcases-link-display&#039;]&lt;br /&gt;
-- cfg[&#039;sandbox-notice-testcases-run-blurb&#039;]&lt;br /&gt;
-- cfg[&#039;sandbox-notice-testcases-run-link-display&#039;]&lt;br /&gt;
-- cfg[&#039;sandbox-notice-testcases-blurb&#039;] is a sentence notifying the user that there is a test cases page&lt;br /&gt;
-- corresponding to this sandbox that they can edit. $1 is a link to the test cases page.&lt;br /&gt;
-- cfg[&#039;sandbox-notice-testcases-link-display&#039;] is the display value for that link.&lt;br /&gt;
-- cfg[&#039;sandbox-notice-testcases-run-blurb&#039;] is a sentence notifying the user that there is a test cases page&lt;br /&gt;
-- corresponding to this sandbox that they can edit, along with a link to run it. $1 is a link to the test&lt;br /&gt;
-- cases page, and $2 is a link to the page to run it.&lt;br /&gt;
-- cfg[&#039;sandbox-notice-testcases-run-link-display&#039;] is the display value for the link to run the test&lt;br /&gt;
-- cases.&lt;br /&gt;
--]]&lt;br /&gt;
cfg[&#039;sandbox-notice-testcases-blurb&#039;] = &#039;See also the companion subpage for $1.&#039;&lt;br /&gt;
cfg[&#039;sandbox-notice-testcases-link-display&#039;] = &#039;test cases&#039;&lt;br /&gt;
cfg[&#039;sandbox-notice-testcases-run-blurb&#039;] = &#039;See also the companion subpage for $1 ($2).&#039;&lt;br /&gt;
cfg[&#039;sandbox-notice-testcases-run-link-display&#039;] = &#039;run&#039;&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;sandbox-category&#039;] - A category to add to all template sandboxes.&lt;br /&gt;
-- cfg[&#039;module-sandbox-category&#039;] - A category to add to all module sandboxes.&lt;br /&gt;
-- cfg[&#039;module-sandbox-category&#039;] - A category to add to all sandboxe not in templates or modules.&lt;br /&gt;
cfg[&#039;sandbox-category&#039;] = &#039;Template sandboxes&#039;&lt;br /&gt;
cfg[&#039;module-sandbox-category&#039;] = &#039;Module sandboxes&#039;&lt;br /&gt;
cfg[&#039;other-sandbox-category&#039;] = &#039;Sandboxes outside of template or module namespace&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----------------------------------------------------------------------------------------------------&lt;br /&gt;
-- Start box configuration&lt;br /&gt;
----------------------------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;documentation-icon-wikitext&#039;]&lt;br /&gt;
-- The wikitext for the icon shown at the top of the template.&lt;br /&gt;
cfg[&#039;documentation-icon-wikitext&#039;] = &#039;[[File:Test Template Info-Icon - Version (2).svg|50px|link=|alt=]]&#039;&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;template-namespace-heading&#039;]&lt;br /&gt;
-- The heading shown in the template namespace.&lt;br /&gt;
cfg[&#039;template-namespace-heading&#039;] = &#039;Template documentation&#039;&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;module-namespace-heading&#039;]&lt;br /&gt;
-- The heading shown in the module namespace.&lt;br /&gt;
cfg[&#039;module-namespace-heading&#039;] = &#039;Module documentation&#039;&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;file-namespace-heading&#039;]&lt;br /&gt;
-- The heading shown in the file namespace.&lt;br /&gt;
cfg[&#039;file-namespace-heading&#039;] = &#039;Summary&#039;&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;other-namespaces-heading&#039;]&lt;br /&gt;
-- The heading shown in other namespaces.&lt;br /&gt;
cfg[&#039;other-namespaces-heading&#039;] = &#039;Documentation&#039;&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;view-link-display&#039;]&lt;br /&gt;
-- The text to display for &amp;quot;view&amp;quot; links.&lt;br /&gt;
cfg[&#039;view-link-display&#039;] = &#039;view&#039;&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;edit-link-display&#039;]&lt;br /&gt;
-- The text to display for &amp;quot;edit&amp;quot; links.&lt;br /&gt;
cfg[&#039;edit-link-display&#039;] = &#039;edit&#039;&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;history-link-display&#039;]&lt;br /&gt;
-- The text to display for &amp;quot;history&amp;quot; links.&lt;br /&gt;
cfg[&#039;history-link-display&#039;] = &#039;history&#039;&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;purge-link-display&#039;]&lt;br /&gt;
-- The text to display for &amp;quot;purge&amp;quot; links.&lt;br /&gt;
cfg[&#039;purge-link-display&#039;] = &#039;purge&#039;&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;create-link-display&#039;]&lt;br /&gt;
-- The text to display for &amp;quot;create&amp;quot; links.&lt;br /&gt;
cfg[&#039;create-link-display&#039;] = &#039;create&#039;&lt;br /&gt;
&lt;br /&gt;
----------------------------------------------------------------------------------------------------&lt;br /&gt;
-- Link box (end box) configuration&lt;br /&gt;
----------------------------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;transcluded-from-blurb&#039;]&lt;br /&gt;
-- Notice displayed when the docs are transcluded from another page. $1 is a wikilink to that page.&lt;br /&gt;
cfg[&#039;transcluded-from-blurb&#039;] = &#039;The above [[Wikipedia:Template documentation|documentation]] is [[Help:Transclusion|transcluded]] from $1.&#039;&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
-- cfg[&#039;create-module-doc-blurb&#039;]&lt;br /&gt;
-- Notice displayed in the module namespace when the documentation subpage does not exist.&lt;br /&gt;
-- $1 is a link to create the documentation page with the preload cfg[&#039;module-preload&#039;] and the&lt;br /&gt;
-- display cfg[&#039;create-link-display&#039;].&lt;br /&gt;
--]]&lt;br /&gt;
cfg[&#039;create-module-doc-blurb&#039;] = &#039;You might want to $1 a documentation page for this [[Wikipedia:Lua|Scribunto module]].&#039;&lt;br /&gt;
&lt;br /&gt;
----------------------------------------------------------------------------------------------------&lt;br /&gt;
-- Experiment blurb configuration&lt;br /&gt;
----------------------------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
-- cfg[&#039;experiment-blurb-template&#039;]&lt;br /&gt;
-- cfg[&#039;experiment-blurb-module&#039;]&lt;br /&gt;
-- The experiment blurb is the text inviting editors to experiment in sandbox and test cases pages.&lt;br /&gt;
-- It is only shown in the template and module namespaces. With the default English settings, it&lt;br /&gt;
-- might look like this:&lt;br /&gt;
--&lt;br /&gt;
-- Editors can experiment in this template&#039;s sandbox (edit | diff) and testcases (edit) pages.&lt;br /&gt;
--&lt;br /&gt;
-- In this example, &amp;quot;sandbox&amp;quot;, &amp;quot;edit&amp;quot;, &amp;quot;diff&amp;quot;, &amp;quot;testcases&amp;quot;, and &amp;quot;edit&amp;quot; would all be links.&lt;br /&gt;
--&lt;br /&gt;
-- There are two versions, cfg[&#039;experiment-blurb-template&#039;] and cfg[&#039;experiment-blurb-module&#039;], depending&lt;br /&gt;
-- on what namespace we are in.&lt;br /&gt;
-- &lt;br /&gt;
-- Parameters:&lt;br /&gt;
--&lt;br /&gt;
-- $1 is a link to the sandbox page. If the sandbox exists, it is in the following format:&lt;br /&gt;
--&lt;br /&gt;
--     cfg[&#039;sandbox-link-display&#039;] (cfg[&#039;sandbox-edit-link-display&#039;] | cfg[&#039;compare-link-display&#039;])&lt;br /&gt;
-- &lt;br /&gt;
-- If the sandbox doesn&#039;t exist, it is in the format:&lt;br /&gt;
--&lt;br /&gt;
--     cfg[&#039;sandbox-link-display&#039;] (cfg[&#039;sandbox-create-link-display&#039;] | cfg[&#039;mirror-link-display&#039;])&lt;br /&gt;
-- &lt;br /&gt;
-- The link for cfg[&#039;sandbox-create-link-display&#039;] link preloads the page with cfg[&#039;template-sandbox-preload&#039;]&lt;br /&gt;
-- or cfg[&#039;module-sandbox-preload&#039;], depending on the current namespace. The link for cfg[&#039;mirror-link-display&#039;]&lt;br /&gt;
-- loads a default edit summary of cfg[&#039;mirror-edit-summary&#039;].&lt;br /&gt;
--&lt;br /&gt;
-- $2 is a link to the test cases page. If the test cases page exists, it is in the following format:&lt;br /&gt;
--&lt;br /&gt;
--     cfg[&#039;testcases-link-display&#039;] (cfg[&#039;testcases-edit-link-display&#039;] | cfg[&#039;testcases-run-link-display&#039;])&lt;br /&gt;
--&lt;br /&gt;
-- If the test cases page doesn&#039;t exist, it is in the format:&lt;br /&gt;
-- &lt;br /&gt;
--     cfg[&#039;testcases-link-display&#039;] (cfg[&#039;testcases-create-link-display&#039;])&lt;br /&gt;
--&lt;br /&gt;
-- If the test cases page doesn&#039;t exist, the link for cfg[&#039;testcases-create-link-display&#039;] preloads the&lt;br /&gt;
-- page with cfg[&#039;template-testcases-preload&#039;] or cfg[&#039;module-testcases-preload&#039;], depending on the current&lt;br /&gt;
-- namespace.&lt;br /&gt;
--]]&lt;br /&gt;
cfg[&#039;experiment-blurb-template&#039;] = &amp;quot;Editors can experiment in this template&#039;s $1 and $2 pages.&amp;quot;&lt;br /&gt;
cfg[&#039;experiment-blurb-module&#039;] = &amp;quot;Editors can experiment in this module&#039;s $1 and $2 pages.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
----------------------------------------------------------------------------------------------------&lt;br /&gt;
-- Sandbox link configuration&lt;br /&gt;
----------------------------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;sandbox-subpage&#039;]&lt;br /&gt;
-- The name of the template subpage typically used for sandboxes.&lt;br /&gt;
cfg[&#039;sandbox-subpage&#039;] = &#039;sandbox&#039;&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;template-sandbox-preload&#039;]&lt;br /&gt;
-- Preload file for template sandbox pages.&lt;br /&gt;
cfg[&#039;template-sandbox-preload&#039;] = &#039;Template:Documentation/preload-sandbox&#039;&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;module-sandbox-preload&#039;]&lt;br /&gt;
-- Preload file for Lua module sandbox pages.&lt;br /&gt;
cfg[&#039;module-sandbox-preload&#039;] = &#039;Template:Documentation/preload-module-sandbox&#039;&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;sandbox-link-display&#039;]&lt;br /&gt;
-- The text to display for &amp;quot;sandbox&amp;quot; links.&lt;br /&gt;
cfg[&#039;sandbox-link-display&#039;] = &#039;sandbox&#039;&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;sandbox-edit-link-display&#039;]&lt;br /&gt;
-- The text to display for sandbox &amp;quot;edit&amp;quot; links.&lt;br /&gt;
cfg[&#039;sandbox-edit-link-display&#039;] = &#039;edit&#039;&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;sandbox-create-link-display&#039;]&lt;br /&gt;
-- The text to display for sandbox &amp;quot;create&amp;quot; links.&lt;br /&gt;
cfg[&#039;sandbox-create-link-display&#039;] = &#039;create&#039;&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;compare-link-display&#039;]&lt;br /&gt;
-- The text to display for &amp;quot;compare&amp;quot; links.&lt;br /&gt;
cfg[&#039;compare-link-display&#039;] = &#039;diff&#039;&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;mirror-edit-summary&#039;]&lt;br /&gt;
-- The default edit summary to use when a user clicks the &amp;quot;mirror&amp;quot; link. $1 is a wikilink to the&lt;br /&gt;
-- template page.&lt;br /&gt;
cfg[&#039;mirror-edit-summary&#039;] = &#039;Create sandbox version of $1&#039;&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;mirror-link-display&#039;]&lt;br /&gt;
-- The text to display for &amp;quot;mirror&amp;quot; links.&lt;br /&gt;
cfg[&#039;mirror-link-display&#039;] = &#039;mirror&#039;&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;mirror-link-preload&#039;]&lt;br /&gt;
-- The page to preload when a user clicks the &amp;quot;mirror&amp;quot; link.&lt;br /&gt;
cfg[&#039;mirror-link-preload&#039;] = &#039;Template:Documentation/mirror&#039;&lt;br /&gt;
&lt;br /&gt;
----------------------------------------------------------------------------------------------------&lt;br /&gt;
-- Test cases link configuration&lt;br /&gt;
----------------------------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;testcases-subpage&#039;]&lt;br /&gt;
-- The name of the template subpage typically used for test cases.&lt;br /&gt;
cfg[&#039;testcases-subpage&#039;] = &#039;testcases&#039;&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;template-testcases-preload&#039;]&lt;br /&gt;
-- Preload file for template test cases pages.&lt;br /&gt;
cfg[&#039;template-testcases-preload&#039;] = &#039;Template:Documentation/preload-testcases&#039;&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;module-testcases-preload&#039;]&lt;br /&gt;
-- Preload file for Lua module test cases pages.&lt;br /&gt;
cfg[&#039;module-testcases-preload&#039;] = &#039;Template:Documentation/preload-module-testcases&#039;&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;testcases-link-display&#039;]&lt;br /&gt;
-- The text to display for &amp;quot;testcases&amp;quot; links.&lt;br /&gt;
cfg[&#039;testcases-link-display&#039;] = &#039;testcases&#039;&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;testcases-edit-link-display&#039;]&lt;br /&gt;
-- The text to display for test cases &amp;quot;edit&amp;quot; links.&lt;br /&gt;
cfg[&#039;testcases-edit-link-display&#039;] = &#039;edit&#039;&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;testcases-run-link-display&#039;]&lt;br /&gt;
-- The text to display for test cases &amp;quot;run&amp;quot; links.&lt;br /&gt;
cfg[&#039;testcases-run-link-display&#039;] = &#039;run&#039;&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;testcases-create-link-display&#039;]&lt;br /&gt;
-- The text to display for test cases &amp;quot;create&amp;quot; links.&lt;br /&gt;
cfg[&#039;testcases-create-link-display&#039;] = &#039;create&#039;&lt;br /&gt;
&lt;br /&gt;
----------------------------------------------------------------------------------------------------&lt;br /&gt;
-- Add categories blurb configuration&lt;br /&gt;
----------------------------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
-- cfg[&#039;add-categories-blurb&#039;]&lt;br /&gt;
-- Text to direct users to add categories to the /doc subpage. Not used if the &amp;quot;content&amp;quot; or&lt;br /&gt;
-- &amp;quot;docname fed&amp;quot; arguments are set, as then it is not clear where to add the categories. $1 is a&lt;br /&gt;
-- link to the /doc subpage with a display value of cfg[&#039;doc-link-display&#039;].&lt;br /&gt;
--]]&lt;br /&gt;
cfg[&#039;add-categories-blurb&#039;] = &#039;Add categories to the $1 subpage.&#039;&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;doc-link-display&#039;]&lt;br /&gt;
-- The text to display when linking to the /doc subpage.&lt;br /&gt;
cfg[&#039;doc-link-display&#039;] = &#039;/doc&#039;&lt;br /&gt;
&lt;br /&gt;
----------------------------------------------------------------------------------------------------&lt;br /&gt;
-- Subpages link configuration&lt;br /&gt;
----------------------------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
-- cfg[&#039;subpages-blurb&#039;]&lt;br /&gt;
-- The &amp;quot;Subpages of this template&amp;quot; blurb. $1 is a link to the main template&#039;s subpages with a&lt;br /&gt;
-- display value of cfg[&#039;subpages-link-display&#039;]. In the English version this blurb is simply&lt;br /&gt;
-- the link followed by a period, and the link display provides the actual text.&lt;br /&gt;
--]]&lt;br /&gt;
cfg[&#039;subpages-blurb&#039;] = &#039;$1.&#039;&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
-- cfg[&#039;subpages-link-display&#039;]&lt;br /&gt;
-- The text to display for the &amp;quot;subpages of this page&amp;quot; link. $1 is cfg[&#039;template-pagetype&#039;],&lt;br /&gt;
-- cfg[&#039;module-pagetype&#039;] or cfg[&#039;default-pagetype&#039;], depending on whether the current page is in&lt;br /&gt;
-- the template namespace, the module namespace, or another namespace.&lt;br /&gt;
--]]&lt;br /&gt;
cfg[&#039;subpages-link-display&#039;] = &#039;Subpages of this $1&#039;&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;template-pagetype&#039;]&lt;br /&gt;
-- The pagetype to display for template pages.&lt;br /&gt;
cfg[&#039;template-pagetype&#039;] = &#039;template&#039;&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;module-pagetype&#039;]&lt;br /&gt;
-- The pagetype to display for Lua module pages.&lt;br /&gt;
cfg[&#039;module-pagetype&#039;] = &#039;module&#039;&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;default-pagetype&#039;]&lt;br /&gt;
-- The pagetype to display for pages other than templates or Lua modules.&lt;br /&gt;
cfg[&#039;default-pagetype&#039;] = &#039;page&#039;&lt;br /&gt;
&lt;br /&gt;
----------------------------------------------------------------------------------------------------&lt;br /&gt;
-- Doc link configuration&lt;br /&gt;
----------------------------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;doc-subpage&#039;]&lt;br /&gt;
-- The name of the subpage typically used for documentation pages.&lt;br /&gt;
cfg[&#039;doc-subpage&#039;] = &#039;doc&#039;&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;docpage-preload&#039;]&lt;br /&gt;
-- Preload file for template documentation pages in all namespaces.&lt;br /&gt;
cfg[&#039;docpage-preload&#039;] = &#039;Template:Documentation/preload&#039;&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;module-preload&#039;]&lt;br /&gt;
-- Preload file for Lua module documentation pages.&lt;br /&gt;
cfg[&#039;module-preload&#039;] = &#039;Template:Documentation/preload-module-doc&#039;&lt;br /&gt;
&lt;br /&gt;
----------------------------------------------------------------------------------------------------&lt;br /&gt;
-- HTML and CSS configuration&lt;br /&gt;
----------------------------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;templatestyles&#039;]&lt;br /&gt;
-- The name of the TemplateStyles page where CSS is kept.&lt;br /&gt;
-- Sandbox CSS will be at Module:Documentation/sandbox/styles.css when needed.&lt;br /&gt;
cfg[&#039;templatestyles&#039;] = &#039;Module:Documentation/styles.css&#039;&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;container&#039;]&lt;br /&gt;
-- Class which can be used to set flex or grid CSS on the&lt;br /&gt;
-- two child divs documentation and documentation-metadata&lt;br /&gt;
cfg[&#039;container&#039;] = &#039;documentation-container&#039;&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;main-div-classes&#039;]&lt;br /&gt;
-- Classes added to the main HTML &amp;quot;div&amp;quot; tag.&lt;br /&gt;
cfg[&#039;main-div-classes&#039;] = &#039;documentation&#039;&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;main-div-heading-class&#039;]&lt;br /&gt;
-- Class for the main heading for templates and modules and assoc. talk spaces&lt;br /&gt;
cfg[&#039;main-div-heading-class&#039;] = &#039;documentation-heading&#039;&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;start-box-class&#039;]&lt;br /&gt;
-- Class for the start box&lt;br /&gt;
cfg[&#039;start-box-class&#039;] = &#039;documentation-startbox&#039;&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;start-box-link-classes&#039;]&lt;br /&gt;
-- Classes used for the [view][edit][history] or [create] links in the start box.&lt;br /&gt;
-- mw-editsection-like is per [[Wikipedia:Village pump (technical)/Archive 117]]&lt;br /&gt;
cfg[&#039;start-box-link-classes&#039;] = &#039;mw-editsection-like plainlinks&#039;&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;end-box-class&#039;]&lt;br /&gt;
-- Class for the end box.&lt;br /&gt;
cfg[&#039;end-box-class&#039;] = &#039;documentation-metadata&#039;&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;end-box-plainlinks&#039;]&lt;br /&gt;
-- Plainlinks&lt;br /&gt;
cfg[&#039;end-box-plainlinks&#039;] = &#039;plainlinks&#039;&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;toolbar-class&#039;]&lt;br /&gt;
-- Class added for toolbar links.&lt;br /&gt;
cfg[&#039;toolbar-class&#039;] = &#039;documentation-toolbar&#039;&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;clear&#039;]&lt;br /&gt;
-- Just used to clear things.&lt;br /&gt;
cfg[&#039;clear&#039;] = &#039;documentation-clear&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----------------------------------------------------------------------------------------------------&lt;br /&gt;
-- Tracking category configuration&lt;br /&gt;
----------------------------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;display-strange-usage-category&#039;]&lt;br /&gt;
-- Set to true to enable output of cfg[&#039;strange-usage-category&#039;] if the module is used on a /doc subpage&lt;br /&gt;
-- or a /testcases subpage. This should be a boolean value (either true or false).&lt;br /&gt;
cfg[&#039;display-strange-usage-category&#039;] = true&lt;br /&gt;
&lt;br /&gt;
-- cfg[&#039;strange-usage-category&#039;]&lt;br /&gt;
-- Category to output if cfg[&#039;display-strange-usage-category&#039;] is set to true and the module is used on a&lt;br /&gt;
-- /doc subpage or a /testcases subpage.&lt;br /&gt;
cfg[&#039;strange-usage-category&#039;] = &#039;Wikipedia pages with strange ((documentation)) usage&#039;&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
----------------------------------------------------------------------------------------------------&lt;br /&gt;
-- End configuration&lt;br /&gt;
--&lt;br /&gt;
-- Don&#039;t edit anything below this line.&lt;br /&gt;
----------------------------------------------------------------------------------------------------&lt;br /&gt;
--]]&lt;br /&gt;
&lt;br /&gt;
return cfg&lt;/div&gt;</summary>
		<author><name>Jasper</name></author>
	</entry>
	<entry>
		<id>https://wiki.852r.org/index.php?title=Module:Documentation&amp;diff=3872</id>
		<title>Module:Documentation</title>
		<link rel="alternate" type="text/html" href="https://wiki.852r.org/index.php?title=Module:Documentation&amp;diff=3872"/>
		<updated>2026-08-06T10:46:19Z</updated>

		<summary type="html">&lt;p&gt;Jasper: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- This module implements {{documentation}}.&lt;br /&gt;
&lt;br /&gt;
-- Get required modules.&lt;br /&gt;
local getArgs = require(&#039;Module:Arguments&#039;).getArgs&lt;br /&gt;
&lt;br /&gt;
-- Get the config table.&lt;br /&gt;
local cfg = mw.loadData(&#039;Module:Documentation/config&#039;)&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
-- Often-used functions.&lt;br /&gt;
local ugsub = mw.ustring.gsub&lt;br /&gt;
local format = mw.ustring.format&lt;br /&gt;
&lt;br /&gt;
----------------------------------------------------------------------------&lt;br /&gt;
-- Helper functions&lt;br /&gt;
--&lt;br /&gt;
-- These are defined as local functions, but are made available in the p&lt;br /&gt;
-- table for testing purposes.&lt;br /&gt;
----------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local function message(cfgKey, valArray, expectType)&lt;br /&gt;
	--[[&lt;br /&gt;
	-- Gets a message from the cfg table and formats it if appropriate.&lt;br /&gt;
	-- The function raises an error if the value from the cfg table is not&lt;br /&gt;
	-- of the type expectType. The default type for expectType is &#039;string&#039;.&lt;br /&gt;
	-- If the table valArray is present, strings such as $1, $2 etc. in the&lt;br /&gt;
	-- message are substituted with values from the table keys [1], [2] etc.&lt;br /&gt;
	-- For example, if the message &amp;quot;foo-message&amp;quot; had the value &#039;Foo $2 bar $1.&#039;,&lt;br /&gt;
	-- message(&#039;foo-message&#039;, {&#039;baz&#039;, &#039;qux&#039;}) would return &amp;quot;Foo qux bar baz.&amp;quot;&lt;br /&gt;
	--]]&lt;br /&gt;
	local msg = cfg[cfgKey]&lt;br /&gt;
	expectType = expectType or &#039;string&#039;&lt;br /&gt;
	if type(msg) ~= expectType then&lt;br /&gt;
		error(&#039;message: type error in message cfg.&#039; .. cfgKey .. &#039; (&#039; .. expectType .. &#039; expected, got &#039; .. type(msg) .. &#039;)&#039;, 2)&lt;br /&gt;
	end&lt;br /&gt;
	if not valArray then&lt;br /&gt;
		return msg&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local function getMessageVal(match)&lt;br /&gt;
		match = tonumber(match)&lt;br /&gt;
		return valArray[match] or error(&#039;message: no value found for key $&#039; .. match .. &#039; in message cfg.&#039; .. cfgKey, 4)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	return ugsub(msg, &#039;$([1-9][0-9]*)&#039;, getMessageVal)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
p.message = message&lt;br /&gt;
&lt;br /&gt;
local function makeWikilink(page, display)&lt;br /&gt;
	if display then&lt;br /&gt;
		return format(&#039;[[%s|%s]]&#039;, page, display)&lt;br /&gt;
	else&lt;br /&gt;
		return format(&#039;[[%s]]&#039;, page)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
p.makeWikilink = makeWikilink&lt;br /&gt;
&lt;br /&gt;
local function makeCategoryLink(cat, sort)&lt;br /&gt;
	local catns = mw.site.namespaces[14].name&lt;br /&gt;
	return makeWikilink(catns .. &#039;:&#039; .. cat, sort)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
p.makeCategoryLink = makeCategoryLink&lt;br /&gt;
&lt;br /&gt;
local function makeUrlLink(url, display)&lt;br /&gt;
	return format(&#039;[%s %s]&#039;, url, display)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
p.makeUrlLink = makeUrlLink&lt;br /&gt;
&lt;br /&gt;
local function makeToolbar(...)&lt;br /&gt;
	local ret = {}&lt;br /&gt;
	local lim = select(&#039;#&#039;, ...)&lt;br /&gt;
	if lim &amp;lt; 1 then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	for i = 1, lim do&lt;br /&gt;
		ret[#ret + 1] = select(i, ...)&lt;br /&gt;
	end&lt;br /&gt;
	-- &#039;documentation-toolbar&#039;&lt;br /&gt;
	return format(&lt;br /&gt;
		&#039;&amp;lt;span class=&amp;quot;%s&amp;quot;&amp;gt;(%s)&amp;lt;/span&amp;gt;&#039;,&lt;br /&gt;
		message(&#039;toolbar-class&#039;),&lt;br /&gt;
		table.concat(ret, &#039; &amp;amp;#124; &#039;)&lt;br /&gt;
	)&lt;br /&gt;
end	&lt;br /&gt;
&lt;br /&gt;
p.makeToolbar = makeToolbar&lt;br /&gt;
&lt;br /&gt;
----------------------------------------------------------------------------&lt;br /&gt;
-- Argument processing&lt;br /&gt;
----------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local function makeInvokeFunc(funcName)&lt;br /&gt;
	return function (frame)&lt;br /&gt;
		local args = getArgs(frame, {&lt;br /&gt;
			valueFunc = function (key, value)&lt;br /&gt;
				if type(value) == &#039;string&#039; then&lt;br /&gt;
					value = value:match(&#039;^%s*(.-)%s*$&#039;) -- Remove whitespace.&lt;br /&gt;
					if key == &#039;heading&#039; or value ~= &#039;&#039; then&lt;br /&gt;
						return value&lt;br /&gt;
					else&lt;br /&gt;
						return nil&lt;br /&gt;
					end&lt;br /&gt;
				else&lt;br /&gt;
					return value&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		})&lt;br /&gt;
		return p[funcName](args)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
----------------------------------------------------------------------------&lt;br /&gt;
-- Entry points&lt;br /&gt;
----------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
function p.nonexistent(frame)&lt;br /&gt;
	if mw.title.getCurrentTitle().subpageText == &#039;testcases&#039; then&lt;br /&gt;
		return frame:expandTemplate{title = &#039;module test cases notice&#039;}&lt;br /&gt;
	else&lt;br /&gt;
		return p.main(frame)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
p.main = makeInvokeFunc(&#039;_main&#039;)&lt;br /&gt;
&lt;br /&gt;
function p._main(args)&lt;br /&gt;
	--[[&lt;br /&gt;
	-- This function defines logic flow for the module.&lt;br /&gt;
	-- @args - table of arguments passed by the user&lt;br /&gt;
	--]]&lt;br /&gt;
	local env = p.getEnvironment(args)&lt;br /&gt;
	local root = mw.html.create()&lt;br /&gt;
	root&lt;br /&gt;
		:wikitext(p._getModuleWikitext(args, env))&lt;br /&gt;
		:wikitext(p.protectionTemplate(env))&lt;br /&gt;
		:wikitext(p.sandboxNotice(args, env))&lt;br /&gt;
		:tag(&#039;div&#039;)&lt;br /&gt;
			-- &#039;documentation-container&#039;&lt;br /&gt;
			:addClass(message(&#039;container&#039;))&lt;br /&gt;
			:attr(&#039;role&#039;, &#039;complementary&#039;)&lt;br /&gt;
			:attr(&#039;aria-labelledby&#039;, args.heading ~= &#039;&#039; and &#039;documentation-heading&#039; or nil)&lt;br /&gt;
			:attr(&#039;aria-label&#039;, args.heading == &#039;&#039; and &#039;Documentation&#039; or nil)&lt;br /&gt;
			:newline()&lt;br /&gt;
			:tag(&#039;div&#039;)&lt;br /&gt;
				-- &#039;documentation&#039;&lt;br /&gt;
				:addClass(message(&#039;main-div-classes&#039;))&lt;br /&gt;
				:newline()&lt;br /&gt;
				:wikitext(p._startBox(args, env))&lt;br /&gt;
				:wikitext(p._content(args, env))&lt;br /&gt;
				:tag(&#039;div&#039;)&lt;br /&gt;
					-- &#039;documentation-clear&#039;&lt;br /&gt;
					:addClass(message(&#039;clear&#039;))&lt;br /&gt;
					:done()&lt;br /&gt;
				:newline()&lt;br /&gt;
				:done()&lt;br /&gt;
			:wikitext(p._endBox(args, env))&lt;br /&gt;
			:done()&lt;br /&gt;
		:wikitext(p.addTrackingCategories(env))&lt;br /&gt;
	-- &#039;Module:Documentation/styles.css&#039;&lt;br /&gt;
	return mw.getCurrentFrame():extensionTag (&lt;br /&gt;
		&#039;templatestyles&#039;, &#039;&#039;, {src=cfg[&#039;templatestyles&#039;]&lt;br /&gt;
	}) .. tostring(root)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
----------------------------------------------------------------------------&lt;br /&gt;
-- Environment settings&lt;br /&gt;
----------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
function p.getEnvironment(args)&lt;br /&gt;
	--[[&lt;br /&gt;
	-- Returns a table with information about the environment, including title&lt;br /&gt;
	-- objects and other namespace- or path-related data.&lt;br /&gt;
	-- @args - table of arguments passed by the user&lt;br /&gt;
	--&lt;br /&gt;
	-- Title objects include:&lt;br /&gt;
	-- env.title - the page we are making documentation for (usually the current title)&lt;br /&gt;
	-- env.templateTitle - the template (or module, file, etc.)&lt;br /&gt;
	-- env.docTitle - the /doc subpage.&lt;br /&gt;
	-- env.sandboxTitle - the /sandbox subpage.&lt;br /&gt;
	-- env.testcasesTitle - the /testcases subpage.&lt;br /&gt;
	--&lt;br /&gt;
	-- Data includes:&lt;br /&gt;
	-- env.protectionLevels - the protection levels table of the title object.&lt;br /&gt;
	-- env.subjectSpace - the number of the title&#039;s subject namespace.&lt;br /&gt;
	-- env.docSpace - the number of the namespace the title puts its documentation in.&lt;br /&gt;
	-- env.docpageBase - the text of the base page of the /doc, /sandbox and /testcases pages, with namespace.&lt;br /&gt;
	-- env.compareUrl - URL of the Special:ComparePages page comparing the sandbox with the template.&lt;br /&gt;
	-- &lt;br /&gt;
	-- All table lookups are passed through pcall so that errors are caught. If an error occurs, the value&lt;br /&gt;
	-- returned will be nil.&lt;br /&gt;
	--]]&lt;br /&gt;
	&lt;br /&gt;
	local env, envFuncs = {}, {}&lt;br /&gt;
&lt;br /&gt;
	-- Set up the metatable. If triggered we call the corresponding function in the envFuncs table. The value&lt;br /&gt;
	-- returned by that function is memoized in the env table so that we don&#039;t call any of the functions&lt;br /&gt;
	-- more than once. (Nils won&#039;t be memoized.)&lt;br /&gt;
	setmetatable(env, {&lt;br /&gt;
		__index = function (t, key)&lt;br /&gt;
			local envFunc = envFuncs[key]&lt;br /&gt;
			if envFunc then&lt;br /&gt;
				local success, val = pcall(envFunc)&lt;br /&gt;
				if success then&lt;br /&gt;
					env[key] = val -- Memoise the value.&lt;br /&gt;
					return val&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
			return nil&lt;br /&gt;
		end&lt;br /&gt;
	})	&lt;br /&gt;
&lt;br /&gt;
	function envFuncs.title()&lt;br /&gt;
		-- The title object for the current page, or a test page passed with args.page.&lt;br /&gt;
		local title&lt;br /&gt;
		local titleArg = args.page&lt;br /&gt;
		if titleArg then&lt;br /&gt;
			title = mw.title.new(titleArg)&lt;br /&gt;
		else&lt;br /&gt;
			title = mw.title.getCurrentTitle()&lt;br /&gt;
		end&lt;br /&gt;
		return title&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	function envFuncs.templateTitle()&lt;br /&gt;
		--[[&lt;br /&gt;
		-- The template (or module, etc.) title object.&lt;br /&gt;
		-- Messages:&lt;br /&gt;
		-- &#039;sandbox-subpage&#039; --&amp;gt; &#039;sandbox&#039;&lt;br /&gt;
		-- &#039;testcases-subpage&#039; --&amp;gt; &#039;testcases&#039;&lt;br /&gt;
		--]]&lt;br /&gt;
		local subjectSpace = env.subjectSpace&lt;br /&gt;
		local title = env.title&lt;br /&gt;
		local subpage = title.subpageText&lt;br /&gt;
		if subpage == message(&#039;sandbox-subpage&#039;) or subpage == message(&#039;testcases-subpage&#039;) or (subpage == message(&#039;doc-subpage&#039;) and mw.title.getCurrentTitle().namespace == env.docSpace) then&lt;br /&gt;
			return mw.title.makeTitle(subjectSpace, title.baseText)&lt;br /&gt;
		else&lt;br /&gt;
			return mw.title.makeTitle(subjectSpace, title.text)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	function envFuncs.docTitle()&lt;br /&gt;
		--[[&lt;br /&gt;
		-- Title object of the /doc subpage.&lt;br /&gt;
		-- Messages:&lt;br /&gt;
		-- &#039;doc-subpage&#039; --&amp;gt; &#039;doc&#039;&lt;br /&gt;
		--]]&lt;br /&gt;
		local title = env.title&lt;br /&gt;
		local docname = args[1] -- User-specified doc page.&lt;br /&gt;
		local docpage&lt;br /&gt;
		if docname then&lt;br /&gt;
			docpage = docname&lt;br /&gt;
		else&lt;br /&gt;
			docpage = env.docpageBase .. &#039;/&#039; .. message(&#039;doc-subpage&#039;)&lt;br /&gt;
		end&lt;br /&gt;
		return mw.title.new(docpage)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	function envFuncs.sandboxTitle()&lt;br /&gt;
		--[[&lt;br /&gt;
		-- Title object for the /sandbox subpage.&lt;br /&gt;
		-- Messages:&lt;br /&gt;
		-- &#039;sandbox-subpage&#039; --&amp;gt; &#039;sandbox&#039;&lt;br /&gt;
		--]]&lt;br /&gt;
		return mw.title.new(env.docpageBase .. &#039;/&#039; .. message(&#039;sandbox-subpage&#039;))&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	function envFuncs.testcasesTitle()&lt;br /&gt;
		--[[&lt;br /&gt;
		-- Title object for the /testcases subpage.&lt;br /&gt;
		-- Messages:&lt;br /&gt;
		-- &#039;testcases-subpage&#039; --&amp;gt; &#039;testcases&#039;&lt;br /&gt;
		--]]&lt;br /&gt;
		return mw.title.new(env.docpageBase .. &#039;/&#039; .. message(&#039;testcases-subpage&#039;))&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	function envFuncs.protectionLevels()&lt;br /&gt;
		-- The protection levels table of the title object.&lt;br /&gt;
		return env.title.protectionLevels&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	function envFuncs.subjectSpace()&lt;br /&gt;
		-- The subject namespace number.&lt;br /&gt;
		return mw.site.namespaces[env.title.namespace].subject.id&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	function envFuncs.docSpace()&lt;br /&gt;
		-- The documentation namespace number. For most namespaces this is the&lt;br /&gt;
		-- same as the subject namespace. However, pages in the Article, File,&lt;br /&gt;
		-- MediaWiki or Category namespaces must have their /doc, /sandbox and&lt;br /&gt;
		-- /testcases pages in talk space.&lt;br /&gt;
		local subjectSpace = env.subjectSpace&lt;br /&gt;
		if subjectSpace == 0 or subjectSpace == 6 or subjectSpace == 8 or subjectSpace == 14 then&lt;br /&gt;
			return subjectSpace + 1&lt;br /&gt;
		else&lt;br /&gt;
			return subjectSpace&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	function envFuncs.docpageBase()&lt;br /&gt;
		-- The base page of the /doc, /sandbox, and /testcases subpages.&lt;br /&gt;
		-- For some namespaces this is the talk page, rather than the template page.&lt;br /&gt;
		local templateTitle = env.templateTitle&lt;br /&gt;
		local docSpace = env.docSpace&lt;br /&gt;
		local docSpaceText = mw.site.namespaces[docSpace].name&lt;br /&gt;
		-- Assemble the link. docSpace is never the main namespace, so we can hardcode the colon.&lt;br /&gt;
		return docSpaceText .. &#039;:&#039; .. templateTitle.text&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	function envFuncs.compareUrl()&lt;br /&gt;
		-- Diff link between the sandbox and the main template using [[Special:ComparePages]].&lt;br /&gt;
		local templateTitle = env.templateTitle&lt;br /&gt;
		local sandboxTitle = env.sandboxTitle&lt;br /&gt;
		if templateTitle.exists and sandboxTitle.exists then&lt;br /&gt;
			local compareUrl = mw.uri.canonicalUrl(&lt;br /&gt;
				&#039;Special:ComparePages&#039;,&lt;br /&gt;
				{ page1 = templateTitle.prefixedText, page2 = sandboxTitle.prefixedText}&lt;br /&gt;
			)&lt;br /&gt;
			return tostring(compareUrl)&lt;br /&gt;
		else&lt;br /&gt;
			return nil&lt;br /&gt;
		end&lt;br /&gt;
	end		&lt;br /&gt;
&lt;br /&gt;
	return env&lt;br /&gt;
end	&lt;br /&gt;
&lt;br /&gt;
----------------------------------------------------------------------------&lt;br /&gt;
-- Auxiliary templates&lt;br /&gt;
----------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
p.getModuleWikitext = makeInvokeFunc(&#039;_getModuleWikitext&#039;)&lt;br /&gt;
&lt;br /&gt;
function p._getModuleWikitext(args, env)&lt;br /&gt;
	local currentTitle = mw.title.getCurrentTitle()&lt;br /&gt;
	if currentTitle.contentModel ~= &#039;Scribunto&#039; then return end&lt;br /&gt;
	pcall(require, currentTitle.prefixedText) -- if it fails, we don&#039;t care&lt;br /&gt;
	local moduleWikitext =  package.loaded[&amp;quot;Module:Module wikitext&amp;quot;]&lt;br /&gt;
	if moduleWikitext then&lt;br /&gt;
		return moduleWikitext.main()&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.sandboxNotice(args, env)&lt;br /&gt;
	--[=[&lt;br /&gt;
	-- Generates a sandbox notice for display above sandbox pages.&lt;br /&gt;
	-- @args - a table of arguments passed by the user&lt;br /&gt;
	-- @env - environment table containing title objects, etc., generated with p.getEnvironment&lt;br /&gt;
	-- &lt;br /&gt;
	-- Messages:&lt;br /&gt;
	-- &#039;sandbox-notice-image&#039; --&amp;gt; &#039;[[File:Sandbox.svg|50px|alt=|link=]]&#039;&lt;br /&gt;
	-- &#039;sandbox-notice-blurb&#039; --&amp;gt; &#039;This is the $1 for $2.&#039;&lt;br /&gt;
	-- &#039;sandbox-notice-diff-blurb&#039; --&amp;gt; &#039;This is the $1 for $2 ($3).&#039;&lt;br /&gt;
	-- &#039;sandbox-notice-pagetype-template&#039; --&amp;gt; &#039;[[Wikipedia:Template test cases|template sandbox]] page&#039;&lt;br /&gt;
	-- &#039;sandbox-notice-pagetype-module&#039; --&amp;gt; &#039;[[Wikipedia:Template test cases|module sandbox]] page&#039;&lt;br /&gt;
	-- &#039;sandbox-notice-pagetype-other&#039; --&amp;gt; &#039;sandbox page&#039;&lt;br /&gt;
	-- &#039;sandbox-notice-compare-link-display&#039; --&amp;gt; &#039;diff&#039;&lt;br /&gt;
	-- &#039;sandbox-notice-testcases-blurb&#039; --&amp;gt; &#039;See also the companion subpage for $1.&#039;&lt;br /&gt;
	-- &#039;sandbox-notice-testcases-link-display&#039; --&amp;gt; &#039;test cases&#039;&lt;br /&gt;
	-- &#039;sandbox-category&#039; --&amp;gt; &#039;Template sandboxes&#039;&lt;br /&gt;
	-- &#039;module-sandbox-category&#039; --&amp;gt; &#039;Module sandboxes&#039;&lt;br /&gt;
	-- &#039;other-sandbox-category&#039; --&amp;gt; &#039;Sandboxes outside of template or module namespace&#039;&lt;br /&gt;
	--]=]&lt;br /&gt;
	local title = env.title&lt;br /&gt;
	local sandboxTitle = env.sandboxTitle&lt;br /&gt;
	local templateTitle = env.templateTitle&lt;br /&gt;
	local subjectSpace = env.subjectSpace&lt;br /&gt;
	if not (subjectSpace and title and sandboxTitle and templateTitle&lt;br /&gt;
		and mw.title.equals(title, sandboxTitle)) then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	-- Build the table of arguments to pass to {{ombox}}. We need just two fields, &amp;quot;image&amp;quot; and &amp;quot;text&amp;quot;.&lt;br /&gt;
	local omargs = {}&lt;br /&gt;
	omargs.image = message(&#039;sandbox-notice-image&#039;)&lt;br /&gt;
	-- Get the text. We start with the opening blurb, which is something like&lt;br /&gt;
	-- &amp;quot;This is the template sandbox for [[Template:Foo]] (diff).&amp;quot;&lt;br /&gt;
	local text = &#039;__EXPECTUNUSEDTEMPLATE__&#039;&lt;br /&gt;
	local pagetype, sandboxCat&lt;br /&gt;
	if subjectSpace == 10 then&lt;br /&gt;
		pagetype = message(&#039;sandbox-notice-pagetype-template&#039;)&lt;br /&gt;
		sandboxCat = message(&#039;sandbox-category&#039;)&lt;br /&gt;
	elseif subjectSpace == 828 then&lt;br /&gt;
		pagetype = message(&#039;sandbox-notice-pagetype-module&#039;)&lt;br /&gt;
		sandboxCat = message(&#039;module-sandbox-category&#039;)&lt;br /&gt;
	else&lt;br /&gt;
		pagetype = message(&#039;sandbox-notice-pagetype-other&#039;)&lt;br /&gt;
		sandboxCat = message(&#039;other-sandbox-category&#039;)&lt;br /&gt;
	end&lt;br /&gt;
	local templateLink = makeWikilink(templateTitle.prefixedText)&lt;br /&gt;
	local compareUrl = env.compareUrl&lt;br /&gt;
	if compareUrl then&lt;br /&gt;
		local compareDisplay = message(&#039;sandbox-notice-compare-link-display&#039;)&lt;br /&gt;
		local compareLink = makeUrlLink(compareUrl, compareDisplay)&lt;br /&gt;
		text = text .. message(&#039;sandbox-notice-diff-blurb&#039;, {pagetype, templateLink, compareLink})&lt;br /&gt;
	else&lt;br /&gt;
		text = text .. message(&#039;sandbox-notice-blurb&#039;, {pagetype, templateLink})&lt;br /&gt;
	end&lt;br /&gt;
	-- Get the test cases page blurb if the page exists. This is something like&lt;br /&gt;
	-- &amp;quot;See also the companion subpage for [[Template:Foo/testcases|test cases]].&amp;quot;&lt;br /&gt;
	local testcasesTitle = env.testcasesTitle&lt;br /&gt;
	if testcasesTitle and testcasesTitle.exists then&lt;br /&gt;
		if testcasesTitle.contentModel == &amp;quot;Scribunto&amp;quot; then&lt;br /&gt;
			local testcasesLinkDisplay = message(&#039;sandbox-notice-testcases-link-display&#039;)&lt;br /&gt;
			local testcasesRunLinkDisplay = message(&#039;sandbox-notice-testcases-run-link-display&#039;)&lt;br /&gt;
			local testcasesLink = makeWikilink(testcasesTitle.prefixedText, testcasesLinkDisplay)&lt;br /&gt;
			local testcasesRunLink = makeWikilink(testcasesTitle.talkPageTitle.prefixedText, testcasesRunLinkDisplay)&lt;br /&gt;
			text = text .. &#039;&amp;lt;br /&amp;gt;&#039; .. message(&#039;sandbox-notice-testcases-run-blurb&#039;, {testcasesLink, testcasesRunLink})&lt;br /&gt;
		else&lt;br /&gt;
			local testcasesLinkDisplay = message(&#039;sandbox-notice-testcases-link-display&#039;)&lt;br /&gt;
			local testcasesLink = makeWikilink(testcasesTitle.prefixedText, testcasesLinkDisplay)&lt;br /&gt;
			text = text .. &#039;&amp;lt;br /&amp;gt;&#039; .. message(&#039;sandbox-notice-testcases-blurb&#039;, {testcasesLink})&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Add the sandbox to the sandbox category.&lt;br /&gt;
	omargs.text = text .. makeCategoryLink(sandboxCat)&lt;br /&gt;
&lt;br /&gt;
	-- &#039;documentation-clear&#039;&lt;br /&gt;
	return &#039;&amp;lt;div class=&amp;quot;&#039; .. message(&#039;clear&#039;) .. &#039;&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
		.. require(&#039;Module:Message box&#039;).main(&#039;ombox&#039;, omargs)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.protectionTemplate(env)&lt;br /&gt;
	-- Generates the padlock icon in the top right.&lt;br /&gt;
	-- @env - environment table containing title objects, etc., generated with p.getEnvironment&lt;br /&gt;
	-- Messages:&lt;br /&gt;
	-- &#039;protection-template&#039; --&amp;gt; &#039;pp-template&#039;&lt;br /&gt;
	-- &#039;protection-template-args&#039; --&amp;gt; {docusage = &#039;yes&#039;}&lt;br /&gt;
	local protectionLevels = env.protectionLevels&lt;br /&gt;
	if not protectionLevels then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	local editProt = protectionLevels.edit and protectionLevels.edit[1]&lt;br /&gt;
	local moveProt = protectionLevels.move and protectionLevels.move[1]&lt;br /&gt;
	if editProt then&lt;br /&gt;
		-- The page is edit-protected.&lt;br /&gt;
		return require(&#039;Module:Protection banner&#039;)._main{&lt;br /&gt;
			message(&#039;protection-reason-edit&#039;), small = true&lt;br /&gt;
		}&lt;br /&gt;
	elseif moveProt and moveProt ~= &#039;autoconfirmed&#039; then&lt;br /&gt;
		-- The page is move-protected but not edit-protected. Exclude move&lt;br /&gt;
		-- protection with the level &amp;quot;autoconfirmed&amp;quot;, as this is equivalent to&lt;br /&gt;
		-- no move protection at all.&lt;br /&gt;
		return require(&#039;Module:Protection banner&#039;)._main{&lt;br /&gt;
			action = &#039;move&#039;, small = true&lt;br /&gt;
		}&lt;br /&gt;
	else&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
----------------------------------------------------------------------------&lt;br /&gt;
-- Start box&lt;br /&gt;
----------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
p.startBox = makeInvokeFunc(&#039;_startBox&#039;)&lt;br /&gt;
&lt;br /&gt;
function p._startBox(args, env)&lt;br /&gt;
	--[[&lt;br /&gt;
	-- This function generates the start box.&lt;br /&gt;
	-- @args - a table of arguments passed by the user&lt;br /&gt;
	-- @env - environment table containing title objects, etc., generated with p.getEnvironment&lt;br /&gt;
	-- &lt;br /&gt;
	-- The actual work is done by p.makeStartBoxLinksData and p.renderStartBoxLinks which make&lt;br /&gt;
	-- the [view] [edit] [history] [purge] links, and by p.makeStartBoxData and p.renderStartBox&lt;br /&gt;
	-- which generate the box HTML.&lt;br /&gt;
	--]]&lt;br /&gt;
	env = env or p.getEnvironment(args)&lt;br /&gt;
	local links&lt;br /&gt;
	local content = args.content&lt;br /&gt;
	if not content or args[1] then&lt;br /&gt;
		-- No need to include the links if the documentation is on the template page itself.&lt;br /&gt;
		local linksData = p.makeStartBoxLinksData(args, env)&lt;br /&gt;
		if linksData then&lt;br /&gt;
			links = p.renderStartBoxLinks(linksData)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	-- Generate the start box html.&lt;br /&gt;
	local data = p.makeStartBoxData(args, env, links)&lt;br /&gt;
	if data then&lt;br /&gt;
		return p.renderStartBox(data)&lt;br /&gt;
	else&lt;br /&gt;
		-- User specified no heading.&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.makeStartBoxLinksData(args, env)&lt;br /&gt;
	--[[&lt;br /&gt;
	-- Does initial processing of data to make the [view] [edit] [history] [purge] links.&lt;br /&gt;
	-- @args - a table of arguments passed by the user&lt;br /&gt;
	-- @env - environment table containing title objects, etc., generated with p.getEnvironment&lt;br /&gt;
	-- &lt;br /&gt;
	-- Messages:&lt;br /&gt;
	-- &#039;view-link-display&#039; --&amp;gt; &#039;view&#039;&lt;br /&gt;
	-- &#039;edit-link-display&#039; --&amp;gt; &#039;edit&#039;&lt;br /&gt;
	-- &#039;history-link-display&#039; --&amp;gt; &#039;history&#039;&lt;br /&gt;
	-- &#039;purge-link-display&#039; --&amp;gt; &#039;purge&#039;&lt;br /&gt;
	-- &#039;module-preload&#039; --&amp;gt; &#039;Template:Documentation/preload-module-doc&#039;&lt;br /&gt;
	-- &#039;docpage-preload&#039; --&amp;gt; &#039;Template:Documentation/preload&#039;&lt;br /&gt;
	-- &#039;create-link-display&#039; --&amp;gt; &#039;create&#039;&lt;br /&gt;
	--]]&lt;br /&gt;
	local subjectSpace = env.subjectSpace&lt;br /&gt;
	local title = env.title&lt;br /&gt;
	local docTitle = env.docTitle&lt;br /&gt;
	if not title or not docTitle then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	if docTitle.isRedirect then &lt;br /&gt;
		docTitle = docTitle.redirectTarget&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Create link if /doc doesn&#039;t exist.&lt;br /&gt;
	local preload = args.preload&lt;br /&gt;
	if not preload then&lt;br /&gt;
		if subjectSpace == 828 then -- Module namespace&lt;br /&gt;
			preload = message(&#039;module-preload&#039;)&lt;br /&gt;
		else&lt;br /&gt;
			preload = message(&#039;docpage-preload&#039;)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return {&lt;br /&gt;
		title = title,&lt;br /&gt;
		docTitle = docTitle,&lt;br /&gt;
		-- View, display, edit, and purge links if /doc exists.&lt;br /&gt;
		viewLinkDisplay = message(&#039;view-link-display&#039;),&lt;br /&gt;
		editLinkDisplay = message(&#039;edit-link-display&#039;),&lt;br /&gt;
		historyLinkDisplay = message(&#039;history-link-display&#039;),&lt;br /&gt;
		purgeLinkDisplay = message(&#039;purge-link-display&#039;),&lt;br /&gt;
		preload = preload,&lt;br /&gt;
		createLinkDisplay = message(&#039;create-link-display&#039;)&lt;br /&gt;
	}&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.renderStartBoxLinks(data)&lt;br /&gt;
	--[[&lt;br /&gt;
	-- Generates the [view][edit][history][purge] or [create][purge] links from the data table.&lt;br /&gt;
	-- @data - a table of data generated by p.makeStartBoxLinksData&lt;br /&gt;
	--]]&lt;br /&gt;
	local docTitle = data.docTitle&lt;br /&gt;
	-- yes, we do intend to purge the template page on which the documentation appears&lt;br /&gt;
	local purgeLink = makeWikilink(&amp;quot;Special:Purge/&amp;quot; .. data.title.prefixedText, data.purgeLinkDisplay)&lt;br /&gt;
	&lt;br /&gt;
	if docTitle.exists then&lt;br /&gt;
		local viewLink = makeWikilink(docTitle.prefixedText, data.viewLinkDisplay)&lt;br /&gt;
		local editLink = makeWikilink(&amp;quot;Special:EditPage/&amp;quot; .. docTitle.prefixedText, data.editLinkDisplay)&lt;br /&gt;
		local historyLink = makeWikilink(&amp;quot;Special:PageHistory/&amp;quot; .. docTitle.prefixedText, data.historyLinkDisplay)&lt;br /&gt;
		return viewLink .. editLink .. historyLink .. purgeLink&lt;br /&gt;
	else&lt;br /&gt;
		local createLink = makeUrlLink(docTitle:canonicalUrl{action = &#039;edit&#039;, preload = data.preload}, data.createLinkDisplay)&lt;br /&gt;
		return createLink .. purgeLink&lt;br /&gt;
	end&lt;br /&gt;
	return ret&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.makeStartBoxData(args, env, links)&lt;br /&gt;
	--[=[&lt;br /&gt;
	-- Does initial processing of data to pass to the start-box render function, p.renderStartBox.&lt;br /&gt;
	-- @args - a table of arguments passed by the user&lt;br /&gt;
	-- @env - environment table containing title objects, etc., generated with p.getEnvironment&lt;br /&gt;
	-- @links - a string containing the [view][edit][history][purge] links - could be nil if there&#039;s an error.&lt;br /&gt;
	--&lt;br /&gt;
	-- Messages:&lt;br /&gt;
	-- &#039;documentation-icon-wikitext&#039; --&amp;gt; &#039;[[File:Test Template Info-Icon - Version (2).svg|50px|link=|alt=]]&#039;&lt;br /&gt;
	-- &#039;template-namespace-heading&#039; --&amp;gt; &#039;Template documentation&#039;&lt;br /&gt;
	-- &#039;module-namespace-heading&#039; --&amp;gt; &#039;Module documentation&#039;&lt;br /&gt;
	-- &#039;file-namespace-heading&#039; --&amp;gt; &#039;Summary&#039;&lt;br /&gt;
	-- &#039;other-namespaces-heading&#039; --&amp;gt; &#039;Documentation&#039;&lt;br /&gt;
	-- &#039;testcases-create-link-display&#039; --&amp;gt; &#039;create&#039;&lt;br /&gt;
	--]=]&lt;br /&gt;
	local subjectSpace = env.subjectSpace&lt;br /&gt;
	if not subjectSpace then&lt;br /&gt;
		-- Default to an &amp;quot;other namespaces&amp;quot; namespace, so that we get at least some output&lt;br /&gt;
		-- if an error occurs.&lt;br /&gt;
		subjectSpace = 2&lt;br /&gt;
	end&lt;br /&gt;
	local data = {}&lt;br /&gt;
	&lt;br /&gt;
	-- Heading&lt;br /&gt;
	local heading = args.heading -- Blank values are not removed.&lt;br /&gt;
	if heading == &#039;&#039; then&lt;br /&gt;
		-- Don&#039;t display the start box if the heading arg is defined but blank.&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	if heading then&lt;br /&gt;
		data.heading = heading&lt;br /&gt;
	elseif subjectSpace == 10 then -- Template namespace&lt;br /&gt;
		data.heading = message(&#039;documentation-icon-wikitext&#039;) .. &#039; &#039; .. message(&#039;template-namespace-heading&#039;)&lt;br /&gt;
	elseif subjectSpace == 828 then -- Module namespace&lt;br /&gt;
		data.heading = message(&#039;documentation-icon-wikitext&#039;) .. &#039; &#039; .. message(&#039;module-namespace-heading&#039;)&lt;br /&gt;
	elseif subjectSpace == 6 then -- File namespace&lt;br /&gt;
		data.heading = message(&#039;file-namespace-heading&#039;)&lt;br /&gt;
	else&lt;br /&gt;
		data.heading = message(&#039;other-namespaces-heading&#039;)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Heading CSS&lt;br /&gt;
	local headingStyle = args[&#039;heading-style&#039;]&lt;br /&gt;
	if headingStyle then&lt;br /&gt;
		data.headingStyleText = headingStyle&lt;br /&gt;
	else&lt;br /&gt;
		-- &#039;documentation-heading&#039;&lt;br /&gt;
		data.headingClass = message(&#039;main-div-heading-class&#039;)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Data for the [view][edit][history][purge] or [create] links.&lt;br /&gt;
	if links then&lt;br /&gt;
		-- &#039;mw-editsection-like plainlinks&#039;&lt;br /&gt;
		data.linksClass = message(&#039;start-box-link-classes&#039;)&lt;br /&gt;
		data.links = links&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return data&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.renderStartBox(data)&lt;br /&gt;
	-- Renders the start box html.&lt;br /&gt;
	-- @data - a table of data generated by p.makeStartBoxData.&lt;br /&gt;
	local sbox = mw.html.create(&#039;div&#039;)&lt;br /&gt;
	sbox&lt;br /&gt;
		-- &#039;documentation-startbox&#039;&lt;br /&gt;
		:addClass(message(&#039;start-box-class&#039;))&lt;br /&gt;
		:newline()&lt;br /&gt;
		:tag(&#039;span&#039;)&lt;br /&gt;
			:addClass(data.headingClass)&lt;br /&gt;
			:attr(&#039;id&#039;, &#039;documentation-heading&#039;)&lt;br /&gt;
			:cssText(data.headingStyleText)&lt;br /&gt;
			:wikitext(data.heading)&lt;br /&gt;
	local links = data.links&lt;br /&gt;
	if links then&lt;br /&gt;
		sbox:tag(&#039;span&#039;)&lt;br /&gt;
			:addClass(data.linksClass)&lt;br /&gt;
			:attr(&#039;id&#039;, data.linksId)&lt;br /&gt;
			:wikitext(links)&lt;br /&gt;
	end&lt;br /&gt;
	return tostring(sbox)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
----------------------------------------------------------------------------&lt;br /&gt;
-- Documentation content&lt;br /&gt;
----------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
p.content = makeInvokeFunc(&#039;_content&#039;)&lt;br /&gt;
&lt;br /&gt;
function p._content(args, env)&lt;br /&gt;
	-- Displays the documentation contents&lt;br /&gt;
	-- @args - a table of arguments passed by the user&lt;br /&gt;
	-- @env - environment table containing title objects, etc., generated with p.getEnvironment&lt;br /&gt;
	env = env or p.getEnvironment(args)&lt;br /&gt;
	local docTitle = env.docTitle&lt;br /&gt;
	local content = args.content&lt;br /&gt;
	if not content and docTitle and docTitle.exists then&lt;br /&gt;
		content = args._content or mw.getCurrentFrame():expandTemplate{title = docTitle.prefixedText}&lt;br /&gt;
	end&lt;br /&gt;
	-- The line breaks below are necessary so that &amp;quot;=== Headings ===&amp;quot; at the start and end&lt;br /&gt;
	-- of docs are interpreted correctly.&lt;br /&gt;
	return &#039;\n&#039; .. (content or &#039;&#039;) .. &#039;\n&#039; &lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
p.contentTitle = makeInvokeFunc(&#039;_contentTitle&#039;)&lt;br /&gt;
&lt;br /&gt;
function p._contentTitle(args, env)&lt;br /&gt;
	env = env or p.getEnvironment(args)&lt;br /&gt;
	local docTitle = env.docTitle&lt;br /&gt;
	if not args.content and docTitle and docTitle.exists then&lt;br /&gt;
		return docTitle.prefixedText&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;
-- End box&lt;br /&gt;
----------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
p.endBox = makeInvokeFunc(&#039;_endBox&#039;)&lt;br /&gt;
&lt;br /&gt;
function p._endBox(args, env)&lt;br /&gt;
	--[=[&lt;br /&gt;
	-- This function generates the end box (also known as the link box).&lt;br /&gt;
	-- @args - a table of arguments passed by the user&lt;br /&gt;
	-- @env - environment table containing title objects, etc., generated with p.getEnvironment&lt;br /&gt;
	-- &lt;br /&gt;
	--]=]&lt;br /&gt;
	&lt;br /&gt;
	-- Get environment data.&lt;br /&gt;
	env = env or p.getEnvironment(args)&lt;br /&gt;
	local subjectSpace = env.subjectSpace&lt;br /&gt;
	local docTitle = env.docTitle&lt;br /&gt;
	if not subjectSpace or not docTitle then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
		&lt;br /&gt;
	-- Check whether we should output the end box at all. Add the end&lt;br /&gt;
	-- box by default if the documentation exists or if we are in the&lt;br /&gt;
	-- user, module or template namespaces.&lt;br /&gt;
	local linkBox = args[&#039;link box&#039;]&lt;br /&gt;
	if linkBox == &#039;off&#039;&lt;br /&gt;
		or not (&lt;br /&gt;
			docTitle.exists&lt;br /&gt;
			or subjectSpace == 2&lt;br /&gt;
			or subjectSpace == 828&lt;br /&gt;
			or subjectSpace == 10&lt;br /&gt;
		)&lt;br /&gt;
	then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Assemble the link box.&lt;br /&gt;
	local text = &#039;&#039;&lt;br /&gt;
	if linkBox then&lt;br /&gt;
		text = text .. linkBox&lt;br /&gt;
	else&lt;br /&gt;
		text = text .. (p.makeDocPageBlurb(args, env) or &#039;&#039;) -- &amp;quot;This documentation is transcluded from [[Foo]].&amp;quot; &lt;br /&gt;
		if subjectSpace == 2 or subjectSpace == 10 or subjectSpace == 828 then&lt;br /&gt;
			-- We are in the user, template or module namespaces.&lt;br /&gt;
			-- Add sandbox and testcases links.&lt;br /&gt;
			-- &amp;quot;Editors can experiment in this template&#039;s sandbox and testcases pages.&amp;quot;&lt;br /&gt;
			text = text .. (p.makeExperimentBlurb(args, env) or &#039;&#039;) .. &#039;&amp;lt;br /&amp;gt;&#039;&lt;br /&gt;
			if not args.content and not args[1] then&lt;br /&gt;
				-- &amp;quot;Please add categories to the /doc subpage.&amp;quot;&lt;br /&gt;
				-- Don&#039;t show this message with inline docs or with an explicitly specified doc page,&lt;br /&gt;
				-- as then it is unclear where to add the categories.&lt;br /&gt;
				text = text .. (p.makeCategoriesBlurb(args, env) or &#039;&#039;)&lt;br /&gt;
			end&lt;br /&gt;
			text = text .. &#039; &#039; .. (p.makeSubpagesBlurb(args, env) or &#039;&#039;) --&amp;quot;Subpages of this template&amp;quot;&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	local box = mw.html.create(&#039;div&#039;)&lt;br /&gt;
	-- &#039;documentation-metadata&#039;&lt;br /&gt;
	box:attr(&#039;role&#039;, &#039;note&#039;)&lt;br /&gt;
		:addClass(message(&#039;end-box-class&#039;))&lt;br /&gt;
		-- &#039;plainlinks&#039;&lt;br /&gt;
		:addClass(message(&#039;end-box-plainlinks&#039;))&lt;br /&gt;
		:wikitext(text)&lt;br /&gt;
		:done()&lt;br /&gt;
&lt;br /&gt;
	return &#039;\n&#039; .. tostring(box)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.makeDocPageBlurb(args, env)&lt;br /&gt;
	--[=[&lt;br /&gt;
	-- Makes the blurb &amp;quot;This documentation is transcluded from [[Template:Foo]] (edit, history)&amp;quot;.&lt;br /&gt;
	-- @args - a table of arguments passed by the user&lt;br /&gt;
	-- @env - environment table containing title objects, etc., generated with p.getEnvironment&lt;br /&gt;
	-- &lt;br /&gt;
	-- Messages:&lt;br /&gt;
	-- &#039;edit-link-display&#039; --&amp;gt; &#039;edit&#039;&lt;br /&gt;
	-- &#039;history-link-display&#039; --&amp;gt; &#039;history&#039;&lt;br /&gt;
	-- &#039;transcluded-from-blurb&#039; --&amp;gt; &lt;br /&gt;
	-- &#039;The above [[Wikipedia:Template documentation|documentation]] &lt;br /&gt;
	-- is [[Help:Transclusion|transcluded]] from $1.&#039;&lt;br /&gt;
	-- &#039;module-preload&#039; --&amp;gt; &#039;Template:Documentation/preload-module-doc&#039;&lt;br /&gt;
	-- &#039;create-link-display&#039; --&amp;gt; &#039;create&#039;&lt;br /&gt;
	-- &#039;create-module-doc-blurb&#039; --&amp;gt;&lt;br /&gt;
	-- &#039;You might want to $1 a documentation page for this [[Wikipedia:Lua|Scribunto module]].&#039;&lt;br /&gt;
	--]=]&lt;br /&gt;
	local docTitle = env.docTitle&lt;br /&gt;
	if not docTitle then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	if docTitle.exists then&lt;br /&gt;
		-- /doc exists; link to it.&lt;br /&gt;
		local docLink = makeWikilink(docTitle.prefixedText)&lt;br /&gt;
		local editDisplay = message(&#039;edit-link-display&#039;)&lt;br /&gt;
		local editLink = makeWikilink(&amp;quot;Special:EditPage/&amp;quot; .. docTitle.prefixedText, editDisplay)&lt;br /&gt;
		local historyDisplay = message(&#039;history-link-display&#039;)&lt;br /&gt;
		local historyLink = makeWikilink(&amp;quot;Special:PageHistory/&amp;quot; .. docTitle.prefixedText, historyDisplay)&lt;br /&gt;
		return message(&#039;transcluded-from-blurb&#039;, {docLink})&lt;br /&gt;
			.. &#039; &#039;&lt;br /&gt;
			.. makeToolbar(editLink, historyLink)&lt;br /&gt;
			.. &#039;&amp;lt;br /&amp;gt;&#039;&lt;br /&gt;
	elseif env.subjectSpace == 828 then&lt;br /&gt;
		-- /doc does not exist; ask to create it.&lt;br /&gt;
		local createUrl = docTitle:canonicalUrl{action = &#039;edit&#039;, preload = message(&#039;module-preload&#039;)}&lt;br /&gt;
		local createDisplay = message(&#039;create-link-display&#039;)&lt;br /&gt;
		local createLink = makeUrlLink(createUrl, createDisplay)&lt;br /&gt;
		return message(&#039;create-module-doc-blurb&#039;, {createLink})&lt;br /&gt;
			.. &#039;&amp;lt;br /&amp;gt;&#039;&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.makeExperimentBlurb(args, env)&lt;br /&gt;
	--[[&lt;br /&gt;
	-- Renders the text &amp;quot;Editors can experiment in this template&#039;s sandbox (edit | diff) and testcases (edit) pages.&amp;quot;&lt;br /&gt;
	-- @args - a table of arguments passed by the user&lt;br /&gt;
	-- @env - environment table containing title objects, etc., generated with p.getEnvironment&lt;br /&gt;
	-- &lt;br /&gt;
	-- Messages:&lt;br /&gt;
	-- &#039;sandbox-link-display&#039; --&amp;gt; &#039;sandbox&#039;&lt;br /&gt;
	-- &#039;sandbox-edit-link-display&#039; --&amp;gt; &#039;edit&#039;&lt;br /&gt;
	-- &#039;compare-link-display&#039; --&amp;gt; &#039;diff&#039;&lt;br /&gt;
	-- &#039;module-sandbox-preload&#039; --&amp;gt; &#039;Template:Documentation/preload-module-sandbox&#039;&lt;br /&gt;
	-- &#039;template-sandbox-preload&#039; --&amp;gt; &#039;Template:Documentation/preload-sandbox&#039;&lt;br /&gt;
	-- &#039;sandbox-create-link-display&#039; --&amp;gt; &#039;create&#039;&lt;br /&gt;
	-- &#039;mirror-edit-summary&#039; --&amp;gt; &#039;Create sandbox version of $1&#039;&lt;br /&gt;
	-- &#039;mirror-link-display&#039; --&amp;gt; &#039;mirror&#039;&lt;br /&gt;
	-- &#039;mirror-link-preload&#039; --&amp;gt; &#039;Template:Documentation/mirror&#039;&lt;br /&gt;
	-- &#039;sandbox-link-display&#039; --&amp;gt; &#039;sandbox&#039;&lt;br /&gt;
	-- &#039;testcases-link-display&#039; --&amp;gt; &#039;testcases&#039;&lt;br /&gt;
	-- &#039;testcases-edit-link-display&#039;--&amp;gt; &#039;edit&#039;&lt;br /&gt;
	-- &#039;template-sandbox-preload&#039; --&amp;gt; &#039;Template:Documentation/preload-sandbox&#039;&lt;br /&gt;
	-- &#039;testcases-create-link-display&#039; --&amp;gt; &#039;create&#039;&lt;br /&gt;
	-- &#039;testcases-link-display&#039; --&amp;gt; &#039;testcases&#039;&lt;br /&gt;
	-- &#039;testcases-edit-link-display&#039; --&amp;gt; &#039;edit&#039;&lt;br /&gt;
	-- &#039;module-testcases-preload&#039; --&amp;gt; &#039;Template:Documentation/preload-module-testcases&#039;&lt;br /&gt;
	-- &#039;template-testcases-preload&#039; --&amp;gt; &#039;Template:Documentation/preload-testcases&#039;&lt;br /&gt;
	-- &#039;experiment-blurb-module&#039; --&amp;gt; &#039;Editors can experiment in this module&#039;s $1 and $2 pages.&#039;&lt;br /&gt;
	-- &#039;experiment-blurb-template&#039; --&amp;gt; &#039;Editors can experiment in this template&#039;s $1 and $2 pages.&#039;&lt;br /&gt;
	--]]&lt;br /&gt;
	local subjectSpace = env.subjectSpace&lt;br /&gt;
	local templateTitle = env.templateTitle&lt;br /&gt;
	local sandboxTitle = env.sandboxTitle&lt;br /&gt;
	local testcasesTitle = env.testcasesTitle&lt;br /&gt;
	local templatePage = templateTitle.prefixedText&lt;br /&gt;
	if not subjectSpace or not templateTitle or not sandboxTitle or not testcasesTitle then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	-- Make links.&lt;br /&gt;
	local sandboxLinks, testcasesLinks&lt;br /&gt;
	if sandboxTitle.exists then&lt;br /&gt;
		local sandboxPage = sandboxTitle.prefixedText&lt;br /&gt;
		local sandboxDisplay = message(&#039;sandbox-link-display&#039;)&lt;br /&gt;
		local sandboxLink = makeWikilink(sandboxPage, sandboxDisplay)&lt;br /&gt;
		local sandboxEditDisplay = message(&#039;sandbox-edit-link-display&#039;)&lt;br /&gt;
		local sandboxEditLink = makeWikilink(&amp;quot;Special:EditPage/&amp;quot; .. sandboxPage, sandboxEditDisplay)&lt;br /&gt;
		local compareUrl = env.compareUrl&lt;br /&gt;
		local compareLink&lt;br /&gt;
		if compareUrl then&lt;br /&gt;
			local compareDisplay = message(&#039;compare-link-display&#039;)&lt;br /&gt;
			compareLink = makeUrlLink(compareUrl, compareDisplay)&lt;br /&gt;
		end&lt;br /&gt;
		sandboxLinks = sandboxLink .. &#039; &#039; .. makeToolbar(sandboxEditLink, compareLink)&lt;br /&gt;
	else&lt;br /&gt;
		local sandboxPreload&lt;br /&gt;
		if subjectSpace == 828 then&lt;br /&gt;
			sandboxPreload = message(&#039;module-sandbox-preload&#039;)&lt;br /&gt;
		else&lt;br /&gt;
			sandboxPreload = message(&#039;template-sandbox-preload&#039;)&lt;br /&gt;
		end&lt;br /&gt;
		local sandboxCreateUrl = sandboxTitle:canonicalUrl{action = &#039;edit&#039;, preload = sandboxPreload}&lt;br /&gt;
		local sandboxCreateDisplay = message(&#039;sandbox-create-link-display&#039;)&lt;br /&gt;
		local sandboxCreateLink = makeUrlLink(sandboxCreateUrl, sandboxCreateDisplay)&lt;br /&gt;
		local mirrorSummary = message(&#039;mirror-edit-summary&#039;, {makeWikilink(templatePage)})&lt;br /&gt;
		local mirrorPreload = message(&#039;mirror-link-preload&#039;)&lt;br /&gt;
		local mirrorUrl = sandboxTitle:canonicalUrl{action = &#039;edit&#039;, preload = mirrorPreload, summary = mirrorSummary}&lt;br /&gt;
		if subjectSpace == 828 then&lt;br /&gt;
			mirrorUrl = sandboxTitle:canonicalUrl{action = &#039;edit&#039;, preload = templateTitle.prefixedText, summary = mirrorSummary}&lt;br /&gt;
		end&lt;br /&gt;
		local mirrorDisplay = message(&#039;mirror-link-display&#039;)&lt;br /&gt;
		local mirrorLink = makeUrlLink(mirrorUrl, mirrorDisplay)&lt;br /&gt;
		sandboxLinks = message(&#039;sandbox-link-display&#039;) .. &#039; &#039; .. makeToolbar(sandboxCreateLink, mirrorLink)&lt;br /&gt;
	end&lt;br /&gt;
	if testcasesTitle.exists then&lt;br /&gt;
		local testcasesPage = testcasesTitle.prefixedText&lt;br /&gt;
		local testcasesDisplay = message(&#039;testcases-link-display&#039;)&lt;br /&gt;
		local testcasesLink = makeWikilink(testcasesPage, testcasesDisplay)&lt;br /&gt;
		local testcasesEditUrl = testcasesTitle:canonicalUrl{action = &#039;edit&#039;}&lt;br /&gt;
		local testcasesEditDisplay = message(&#039;testcases-edit-link-display&#039;)&lt;br /&gt;
		local testcasesEditLink = makeWikilink(&amp;quot;Special:EditPage/&amp;quot; .. testcasesPage, testcasesEditDisplay)&lt;br /&gt;
		-- for Modules, add testcases run link if exists&lt;br /&gt;
		if testcasesTitle.contentModel == &amp;quot;Scribunto&amp;quot;  and testcasesTitle.talkPageTitle and testcasesTitle.talkPageTitle.exists then&lt;br /&gt;
			local testcasesRunLinkDisplay = message(&#039;testcases-run-link-display&#039;)&lt;br /&gt;
			local testcasesRunLink = makeWikilink(testcasesTitle.talkPageTitle.prefixedText, testcasesRunLinkDisplay)&lt;br /&gt;
			testcasesLinks = testcasesLink .. &#039; &#039; .. makeToolbar(testcasesEditLink, testcasesRunLink)&lt;br /&gt;
		else&lt;br /&gt;
			testcasesLinks = testcasesLink .. &#039; &#039; .. makeToolbar(testcasesEditLink)&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		local testcasesPreload&lt;br /&gt;
		if subjectSpace == 828 then&lt;br /&gt;
			testcasesPreload = message(&#039;module-testcases-preload&#039;)&lt;br /&gt;
		else&lt;br /&gt;
			testcasesPreload = message(&#039;template-testcases-preload&#039;)&lt;br /&gt;
		end&lt;br /&gt;
		local testcasesCreateUrl = testcasesTitle:canonicalUrl{action = &#039;edit&#039;, preload = testcasesPreload}&lt;br /&gt;
		local testcasesCreateDisplay = message(&#039;testcases-create-link-display&#039;)&lt;br /&gt;
		local testcasesCreateLink = makeUrlLink(testcasesCreateUrl, testcasesCreateDisplay)&lt;br /&gt;
		testcasesLinks = message(&#039;testcases-link-display&#039;) .. &#039; &#039; .. makeToolbar(testcasesCreateLink)&lt;br /&gt;
	end&lt;br /&gt;
	local messageName&lt;br /&gt;
	if subjectSpace == 828 then&lt;br /&gt;
		messageName = &#039;experiment-blurb-module&#039;&lt;br /&gt;
	else&lt;br /&gt;
		messageName = &#039;experiment-blurb-template&#039;&lt;br /&gt;
	end&lt;br /&gt;
	return message(messageName, {sandboxLinks, testcasesLinks})&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.makeCategoriesBlurb(args, env)&lt;br /&gt;
	--[[&lt;br /&gt;
	-- Generates the text &amp;quot;Please add categories to the /doc subpage.&amp;quot;&lt;br /&gt;
	-- @args - a table of arguments passed by the user&lt;br /&gt;
	-- @env - environment table containing title objects, etc., generated with p.getEnvironment&lt;br /&gt;
	-- Messages:&lt;br /&gt;
	-- &#039;doc-link-display&#039; --&amp;gt; &#039;/doc&#039;&lt;br /&gt;
	-- &#039;add-categories-blurb&#039; --&amp;gt; &#039;Please add categories to the $1 subpage.&#039;&lt;br /&gt;
	--]]&lt;br /&gt;
	local docTitle = env.docTitle&lt;br /&gt;
	if not docTitle then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	local docPathLink = makeWikilink(docTitle.prefixedText, message(&#039;doc-link-display&#039;))&lt;br /&gt;
	return message(&#039;add-categories-blurb&#039;, {docPathLink})&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.makeSubpagesBlurb(args, env)&lt;br /&gt;
	--[[&lt;br /&gt;
	-- Generates the &amp;quot;Subpages of this template&amp;quot; link.&lt;br /&gt;
	-- @args - a table of arguments passed by the user&lt;br /&gt;
	-- @env - environment table containing title objects, etc., generated with p.getEnvironment&lt;br /&gt;
	&lt;br /&gt;
	-- Messages:&lt;br /&gt;
	-- &#039;template-pagetype&#039; --&amp;gt; &#039;template&#039;&lt;br /&gt;
	-- &#039;module-pagetype&#039; --&amp;gt; &#039;module&#039;&lt;br /&gt;
	-- &#039;default-pagetype&#039; --&amp;gt; &#039;page&#039;&lt;br /&gt;
	-- &#039;subpages-link-display&#039; --&amp;gt; &#039;Subpages of this $1&#039;&lt;br /&gt;
	--]]&lt;br /&gt;
	local subjectSpace = env.subjectSpace&lt;br /&gt;
	local templateTitle = env.templateTitle&lt;br /&gt;
	if not subjectSpace or not templateTitle then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	local pagetype&lt;br /&gt;
	if subjectSpace == 10 then&lt;br /&gt;
		pagetype = message(&#039;template-pagetype&#039;)&lt;br /&gt;
	elseif subjectSpace == 828 then&lt;br /&gt;
		pagetype = message(&#039;module-pagetype&#039;)&lt;br /&gt;
	else&lt;br /&gt;
		pagetype = message(&#039;default-pagetype&#039;)&lt;br /&gt;
	end&lt;br /&gt;
	local subpagesLink = makeWikilink(&lt;br /&gt;
		&#039;Special:PrefixIndex/&#039; .. templateTitle.prefixedText .. &#039;/&#039;,&lt;br /&gt;
		message(&#039;subpages-link-display&#039;, {pagetype})&lt;br /&gt;
	)&lt;br /&gt;
	return message(&#039;subpages-blurb&#039;, {subpagesLink})&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
----------------------------------------------------------------------------&lt;br /&gt;
-- Tracking categories&lt;br /&gt;
----------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
function p.addTrackingCategories(env)&lt;br /&gt;
	--[[&lt;br /&gt;
	-- Check if {{documentation}} is transcluded on a /doc or /testcases page.&lt;br /&gt;
	-- @env - environment table containing title objects, etc., generated with p.getEnvironment&lt;br /&gt;
	&lt;br /&gt;
	-- Messages:&lt;br /&gt;
	-- &#039;display-strange-usage-category&#039; --&amp;gt; true&lt;br /&gt;
	-- &#039;doc-subpage&#039; --&amp;gt; &#039;doc&#039;&lt;br /&gt;
	-- &#039;testcases-subpage&#039; --&amp;gt; &#039;testcases&#039;&lt;br /&gt;
	-- &#039;strange-usage-category&#039; --&amp;gt; &#039;Wikipedia pages with strange ((documentation)) usage&#039;&lt;br /&gt;
	-- &lt;br /&gt;
	-- /testcases pages in the module namespace are not categorised, as they may have&lt;br /&gt;
	-- {{documentation}} transcluded automatically.&lt;br /&gt;
	--]]&lt;br /&gt;
	local title = env.title&lt;br /&gt;
	local subjectSpace = env.subjectSpace&lt;br /&gt;
	if not title or not subjectSpace then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	local subpage = title.subpageText&lt;br /&gt;
	if message(&#039;display-strange-usage-category&#039;, nil, &#039;boolean&#039;)&lt;br /&gt;
		and (&lt;br /&gt;
			subpage == message(&#039;doc-subpage&#039;)&lt;br /&gt;
			or subjectSpace ~= 828 and subpage == message(&#039;testcases-subpage&#039;)&lt;br /&gt;
		)&lt;br /&gt;
	then&lt;br /&gt;
		return makeCategoryLink(message(&#039;strange-usage-category&#039;))&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;&#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Jasper</name></author>
	</entry>
	<entry>
		<id>https://wiki.852r.org/index.php?title=Template:No_redirect&amp;diff=3870</id>
		<title>Template:No redirect</title>
		<link rel="alternate" type="text/html" href="https://wiki.852r.org/index.php?title=Template:No_redirect&amp;diff=3870"/>
		<updated>2026-08-06T10:46:19Z</updated>

		<summary type="html">&lt;p&gt;Jasper: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{safesubst:&amp;lt;noinclude/&amp;gt;#if: {{safesubst:&amp;lt;noinclude/&amp;gt;#invoke:Redirect|isRedirect|{{{1}}}}}&lt;br /&gt;
| &amp;lt;span class=&amp;quot;plainlinks&amp;quot;&amp;gt;[{{safesubst:&amp;lt;noinclude/&amp;gt;fullurl:{{{1}}}|redirect=no}} {{{2|{{{1}}}}}}]&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;display: none&amp;quot;&amp;gt;[[:{{{1}}}]]&amp;lt;/span&amp;gt;&lt;br /&gt;
| [[:{{safesubst:&amp;lt;noinclude/&amp;gt;FULLPAGENAME:{{{1}}}}}|{{{2|{{{1}}}}}}]]&lt;br /&gt;
}}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{documentation}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jasper</name></author>
	</entry>
	<entry>
		<id>https://wiki.852r.org/index.php?title=Template:Para&amp;diff=3868</id>
		<title>Template:Para</title>
		<link rel="alternate" type="text/html" href="https://wiki.852r.org/index.php?title=Template:Para&amp;diff=3868"/>
		<updated>2026-08-06T10:46:18Z</updated>

		<summary type="html">&lt;p&gt;Jasper: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Template:Parameter]]&lt;br /&gt;
&lt;br /&gt;
{{Rcat shell|&lt;br /&gt;
{{R from move}}&lt;br /&gt;
{{R from template shortcut}}&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Jasper</name></author>
	</entry>
	<entry>
		<id>https://wiki.852r.org/index.php?title=Template:Strong&amp;diff=3866</id>
		<title>Template:Strong</title>
		<link rel="alternate" type="text/html" href="https://wiki.852r.org/index.php?title=Template:Strong&amp;diff=3866"/>
		<updated>2026-08-06T10:46:18Z</updated>

		<summary type="html">&lt;p&gt;Jasper: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;strong {{#if:{{{role|}}}|role=&amp;quot;{{{role}}}&amp;quot;}} {{#if:{{{class|}}}|class=&amp;quot;{{{class}}}&amp;quot;}} {{#if:{{{id|}}}|id=&amp;quot;{{{id}}}&amp;quot;}} {{#if:{{{style|}}}|style=&amp;quot;{{{style}}}&amp;quot;}} {{#if:{{{title|}}}|title=&amp;quot;{{{title}}}&amp;quot;}}&amp;gt;{{{1}}}&amp;lt;/strong&amp;gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{documentation}}&lt;br /&gt;
&amp;lt;!-- Add cats and interwikis to the /doc subpage, not here! --&amp;gt;&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jasper</name></author>
	</entry>
	<entry>
		<id>https://wiki.852r.org/index.php?title=Template:Div_col_end&amp;diff=3864</id>
		<title>Template:Div col end</title>
		<link rel="alternate" type="text/html" href="https://wiki.852r.org/index.php?title=Template:Div_col_end&amp;diff=3864"/>
		<updated>2026-08-06T10:46:18Z</updated>

		<summary type="html">&lt;p&gt;Jasper: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{Documentation|Template:Div col/doc}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jasper</name></author>
	</entry>
	<entry>
		<id>https://wiki.852r.org/index.php?title=Template:Div_col/styles.css&amp;diff=3862</id>
		<title>Template:Div col/styles.css</title>
		<link rel="alternate" type="text/html" href="https://wiki.852r.org/index.php?title=Template:Div_col/styles.css&amp;diff=3862"/>
		<updated>2026-08-06T10:46:18Z</updated>

		<summary type="html">&lt;p&gt;Jasper: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* {{pp|small=yes}} */&lt;br /&gt;
.div-col {&lt;br /&gt;
	margin-top: 0.3em;&lt;br /&gt;
	column-width: 30em;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.div-col-small {&lt;br /&gt;
	font-size: 90%;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
.div-col-rules {&lt;br /&gt;
	column-rule: 1px solid #aaa;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Reset top margin for lists in div col */&lt;br /&gt;
.div-col dl,&lt;br /&gt;
.div-col ol,&lt;br /&gt;
.div-col ul {&lt;br /&gt;
	margin-top: 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Avoid elements breaking between columns&lt;br /&gt;
   See also Template:No col break */&lt;br /&gt;
.div-col li,&lt;br /&gt;
.div-col dd {&lt;br /&gt;
	page-break-inside: avoid; /* Removed from CSS in favor of break-inside c. 2020 */&lt;br /&gt;
	break-inside: avoid-column;&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Jasper</name></author>
	</entry>
	<entry>
		<id>https://wiki.852r.org/index.php?title=Module:Protection_banner/config&amp;diff=3860</id>
		<title>Module:Protection banner/config</title>
		<link rel="alternate" type="text/html" href="https://wiki.852r.org/index.php?title=Module:Protection_banner/config&amp;diff=3860"/>
		<updated>2026-08-06T10:46:18Z</updated>

		<summary type="html">&lt;p&gt;Jasper: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- This module provides configuration data for [[Module:Protection banner]].&lt;br /&gt;
&lt;br /&gt;
return {&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
--&lt;br /&gt;
--                                BANNER DATA&lt;br /&gt;
--&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
-- Banner data consists of six fields:&lt;br /&gt;
-- * text - the main protection text that appears at the top of protection&lt;br /&gt;
--   banners.&lt;br /&gt;
-- * explanation - the text that appears below the main protection text, used&lt;br /&gt;
--   to explain the details of the protection.&lt;br /&gt;
-- * tooltip - the tooltip text you see when you move the mouse over a small&lt;br /&gt;
--   padlock icon.&lt;br /&gt;
-- * link - the page that the small padlock icon links to.&lt;br /&gt;
-- * alt - the alt text for the small padlock icon. This is also used as tooltip&lt;br /&gt;
--   text for the large protection banners.&lt;br /&gt;
-- * image - the padlock image used in both protection banners and small padlock&lt;br /&gt;
--   icons.&lt;br /&gt;
--&lt;br /&gt;
-- The module checks in three separate tables to find a value for each field.&lt;br /&gt;
-- First it checks the banners table, which has values specific to the reason&lt;br /&gt;
-- for the page being protected. Then the module checks the defaultBanners&lt;br /&gt;
-- table, which has values specific to each protection level. Finally, the&lt;br /&gt;
-- module checks the masterBanner table, which holds data for protection&lt;br /&gt;
-- templates to use if no data has been found in the previous two tables.&lt;br /&gt;
--&lt;br /&gt;
-- The values in the banner data can take parameters. These are specified&lt;br /&gt;
-- using ${TEXTLIKETHIS} (a dollar sign preceding a parameter name&lt;br /&gt;
-- enclosed in curly braces).&lt;br /&gt;
--&lt;br /&gt;
--                          Available parameters:&lt;br /&gt;
--&lt;br /&gt;
-- ${CURRENTVERSION} - a link to the page history or the move log, with the&lt;br /&gt;
-- display message &amp;quot;current-version-edit-display&amp;quot; or&lt;br /&gt;
-- &amp;quot;current-version-move-display&amp;quot;.&lt;br /&gt;
--&lt;br /&gt;
-- ${EDITREQUEST} - a link to create an edit request for the current page.&lt;br /&gt;
--&lt;br /&gt;
-- ${EXPLANATIONBLURB} - an explanation blurb, e.g. &amp;quot;Please discuss any changes&lt;br /&gt;
-- on the talk page; you may submit a request to ask an administrator to make&lt;br /&gt;
-- an edit if it is minor or supported by consensus.&amp;quot;&lt;br /&gt;
--&lt;br /&gt;
-- ${IMAGELINK} - a link to set the image to, depending on the protection&lt;br /&gt;
-- action and protection level.&lt;br /&gt;
--&lt;br /&gt;
-- ${INTROBLURB} - the PROTECTIONBLURB parameter, plus the expiry if an expiry&lt;br /&gt;
-- is set. E.g. &amp;quot;Editing of this page by new or unregistered users is currently &lt;br /&gt;
-- disabled until dd Month YYYY.&amp;quot;&lt;br /&gt;
--&lt;br /&gt;
-- ${INTROFRAGMENT} - the same as ${INTROBLURB}, but without final punctuation&lt;br /&gt;
-- so that it can be used in run-on sentences.&lt;br /&gt;
--&lt;br /&gt;
-- ${PAGETYPE} - the type of the page, e.g. &amp;quot;article&amp;quot; or &amp;quot;template&amp;quot;.&lt;br /&gt;
-- Defined in the cfg.pagetypes table.&lt;br /&gt;
--&lt;br /&gt;
-- ${PROTECTIONBLURB} - a blurb explaining the protection level of the page, e.g.&lt;br /&gt;
-- &amp;quot;Editing of this page by new or unregistered users is currently disabled&amp;quot;&lt;br /&gt;
--&lt;br /&gt;
-- ${PROTECTIONDATE} - the protection date, if it has been supplied to the&lt;br /&gt;
-- template.&lt;br /&gt;
--&lt;br /&gt;
-- ${PROTECTIONLEVEL} - the protection level, e.g. &amp;quot;fully protected&amp;quot; or&lt;br /&gt;
-- &amp;quot;semi-protected&amp;quot;.&lt;br /&gt;
--&lt;br /&gt;
-- ${PROTECTIONLOG} - a link to the protection log or the pending changes log,&lt;br /&gt;
-- depending on the protection action.&lt;br /&gt;
--&lt;br /&gt;
-- ${TALKPAGE} - a link to the talk page. If a section is specified, links&lt;br /&gt;
-- straight to that talk page section.&lt;br /&gt;
--&lt;br /&gt;
-- ${TOOLTIPBLURB} - uses the PAGETYPE, PROTECTIONTYPE and EXPIRY parameters to&lt;br /&gt;
-- create a blurb like &amp;quot;This template is semi-protected&amp;quot;, or &amp;quot;This article is&lt;br /&gt;
-- move-protected until DD Month YYYY&amp;quot;.&lt;br /&gt;
--&lt;br /&gt;
-- ${VANDAL} - links for the specified username (or the root page name)&lt;br /&gt;
-- using Module:Vandal-m.&lt;br /&gt;
--&lt;br /&gt;
--                                 Functions&lt;br /&gt;
--&lt;br /&gt;
-- For advanced users, it is possible to use Lua functions instead of strings&lt;br /&gt;
-- in the banner config tables. Using functions gives flexibility that is not&lt;br /&gt;
-- possible just by using parameters. Functions take two arguments, the&lt;br /&gt;
-- protection object and the template arguments, and they must output a string.&lt;br /&gt;
--&lt;br /&gt;
-- For example:&lt;br /&gt;
--&lt;br /&gt;
-- text = function (protectionObj, args)&lt;br /&gt;
--     if protectionObj.level == &#039;autoconfirmed&#039; then&lt;br /&gt;
--         return &#039;foo&#039;&lt;br /&gt;
--     else&lt;br /&gt;
--         return &#039;bar&#039;&lt;br /&gt;
--     end&lt;br /&gt;
-- end&lt;br /&gt;
--&lt;br /&gt;
-- Some protection object properties and methods that may be useful:&lt;br /&gt;
-- protectionObj.action - the protection action&lt;br /&gt;
-- protectionObj.level - the protection level&lt;br /&gt;
-- protectionObj.reason - the protection reason&lt;br /&gt;
-- protectionObj.expiry - the expiry. Nil if unset, the string &amp;quot;indef&amp;quot; if set&lt;br /&gt;
--     to indefinite, and the protection time in unix time if temporary.&lt;br /&gt;
-- protectionObj.protectionDate - the protection date in unix time, or nil if&lt;br /&gt;
--     unspecified.&lt;br /&gt;
-- protectionObj.bannerConfig - the banner config found by the module. Beware&lt;br /&gt;
--     of editing the config field used by the function, as it could create an&lt;br /&gt;
--     infinite loop.&lt;br /&gt;
-- protectionObj:isProtected - returns a boolean showing whether the page is&lt;br /&gt;
--     protected.&lt;br /&gt;
-- protectionObj:isTemporary - returns a boolean showing whether the expiry is&lt;br /&gt;
--     temporary.&lt;br /&gt;
-- protectionObj:isIncorrect - returns a boolean showing whether the protection&lt;br /&gt;
--     template is incorrect.&lt;br /&gt;
--]]&lt;br /&gt;
&lt;br /&gt;
-- The master banner data, used if no values have been found in banners or&lt;br /&gt;
-- defaultBanners.&lt;br /&gt;
masterBanner = {&lt;br /&gt;
	text = &#039;${INTROBLURB}&#039;,&lt;br /&gt;
	explanation = &#039;${EXPLANATIONBLURB}&#039;,&lt;br /&gt;
	tooltip = &#039;${TOOLTIPBLURB}&#039;,&lt;br /&gt;
	link = &#039;${IMAGELINK}&#039;,&lt;br /&gt;
	alt = &#039;Page ${PROTECTIONLEVEL}&#039;&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
-- The default banner data. This holds banner data for different protection&lt;br /&gt;
-- levels.&lt;br /&gt;
-- *required* - this table needs edit, move, autoreview and upload subtables.&lt;br /&gt;
defaultBanners = {&lt;br /&gt;
	edit = {},&lt;br /&gt;
	move = {},&lt;br /&gt;
	autoreview = {&lt;br /&gt;
		default = {&lt;br /&gt;
			alt = &#039;Page protected with pending changes&#039;,&lt;br /&gt;
			tooltip = &#039;All edits by unregistered and new users are subject to review prior to becoming visible to unregistered users&#039;,&lt;br /&gt;
			image = &#039;Pending-protection-shackle.svg&#039;&lt;br /&gt;
		}&lt;br /&gt;
	},&lt;br /&gt;
	upload = {}&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
-- The banner data. This holds banner data for different protection reasons.&lt;br /&gt;
-- In fact, the reasons specified in this table control which reasons are&lt;br /&gt;
-- valid inputs to the first positional parameter.&lt;br /&gt;
--&lt;br /&gt;
-- There is also a non-standard &amp;quot;description&amp;quot; field that can be used for items&lt;br /&gt;
-- in this table. This is a description of the protection reason for use in the&lt;br /&gt;
-- module documentation.&lt;br /&gt;
--&lt;br /&gt;
-- *required* - this table needs edit, move, autoreview and upload subtables.&lt;br /&gt;
banners = {&lt;br /&gt;
	edit = {&lt;br /&gt;
		blp = {&lt;br /&gt;
			description = &#039;For pages protected to promote compliance with the&#039;&lt;br /&gt;
				.. &#039; [[Wikipedia:Biographies of living persons&#039;&lt;br /&gt;
				.. &#039;|biographies of living persons]] policy&#039;,&lt;br /&gt;
			text = &#039;${INTROFRAGMENT} to promote compliance with&#039;&lt;br /&gt;
				.. &#039; [[Wikipedia:Biographies of living persons&#039;&lt;br /&gt;
				.. &amp;quot;|Wikipedia&#039;s&amp;amp;nbsp;policy on&amp;amp;nbsp;the&amp;amp;nbsp;biographies&amp;quot;&lt;br /&gt;
				.. &#039; of&amp;amp;nbsp;living&amp;amp;nbsp;people]].&#039;,&lt;br /&gt;
			tooltip = &#039;${TOOLTIPFRAGMENT} to promote compliance with the policy on&#039;&lt;br /&gt;
				.. &#039; biographies of living persons&#039;,&lt;br /&gt;
		},&lt;br /&gt;
		deceased = {&lt;br /&gt;
			description = &#039;For user pages of Wikipedia users who are deceased&#039;,&lt;br /&gt;
			text = &#039;${INTROFRAGMENT} to prevent vandalism of a deceased&#039;&lt;br /&gt;
				.. &#039; Wikipedian\&#039;s user page.&#039;&lt;br /&gt;
				.. &#039; A family member who wishes to edit this user page can use this&#039;&lt;br /&gt;
				.. &#039; user\&#039;s ${TALKPAGE} or submit a request to [[Wikipedia:VRT|the&#039;&lt;br /&gt;
				.. &#039; Volunteer Response Team]].&#039;,&lt;br /&gt;
			tooltip = &#039;${TOOLTIPFRAGMENT} because this Wikipedian is deceased&#039;&lt;br /&gt;
		},&lt;br /&gt;
		dmca = {&lt;br /&gt;
			description = &#039;For pages protected by the Wikimedia Foundation&#039;&lt;br /&gt;
				.. &#039; due to [[Digital Millennium Copyright Act]] takedown requests&#039;,&lt;br /&gt;
			explanation = function (protectionObj, args)&lt;br /&gt;
				local ret = &#039;Pursuant to a rights owner notice under the Digital&#039;&lt;br /&gt;
					.. &#039; Millennium Copyright Act (DMCA) regarding some content&#039;&lt;br /&gt;
					.. &#039; in this article, the Wikimedia Foundation acted under&#039;&lt;br /&gt;
					.. &#039; applicable law and took down and restricted the content&#039;&lt;br /&gt;
					.. &#039; in question.&#039;&lt;br /&gt;
				if args.notice then&lt;br /&gt;
					ret = ret .. &#039; A copy of the received notice can be found here: &#039;&lt;br /&gt;
						.. args.notice .. &#039;.&#039;&lt;br /&gt;
				end&lt;br /&gt;
				ret = ret .. &#039; For more information, including websites discussing&#039;&lt;br /&gt;
					.. &#039; how to file a counter-notice, please see&#039;&lt;br /&gt;
					.. &amp;quot; [[Wikipedia:Office actions]] and the article&#039;s ${TALKPAGE}.&amp;quot;&lt;br /&gt;
					.. &amp;quot;&#039;&#039;&#039;Do not remove this template from the article until the&amp;quot;&lt;br /&gt;
					.. &amp;quot; restrictions are withdrawn&#039;&#039;&#039;.&amp;quot;&lt;br /&gt;
				return ret&lt;br /&gt;
			end,&lt;br /&gt;
			image = &#039;Office-protection-shackle.svg&#039;,&lt;br /&gt;
			link = &#039;Wikipedia:Protection policy#office&#039;,&lt;br /&gt;
		},&lt;br /&gt;
		dispute = {&lt;br /&gt;
			description = &#039;For pages protected due to editing disputes&#039;,&lt;br /&gt;
			text = function (protectionObj, args)&lt;br /&gt;
				-- Find the value of &amp;quot;disputes&amp;quot;.&lt;br /&gt;
				local display = &#039;disputes&#039;&lt;br /&gt;
				local disputes&lt;br /&gt;
				if args.section then&lt;br /&gt;
					disputes = string.format(&lt;br /&gt;
						&#039;[[%s:%s#%s|%s]]&#039;,&lt;br /&gt;
						mw.site.namespaces[protectionObj.title.namespace].talk.name,&lt;br /&gt;
						protectionObj.title.text,&lt;br /&gt;
						args.section,&lt;br /&gt;
						display&lt;br /&gt;
					)&lt;br /&gt;
				else&lt;br /&gt;
					disputes = display&lt;br /&gt;
				end&lt;br /&gt;
&lt;br /&gt;
				-- Make the blurb, depending on the expiry.&lt;br /&gt;
				local msg&lt;br /&gt;
				if type(protectionObj.expiry) == &#039;number&#039; then&lt;br /&gt;
					msg = &#039;${INTROFRAGMENT} or until editing %s have been resolved.&#039;&lt;br /&gt;
				else&lt;br /&gt;
					msg = &#039;${INTROFRAGMENT} until editing %s have been resolved.&#039;&lt;br /&gt;
				end&lt;br /&gt;
				return string.format(msg, disputes)&lt;br /&gt;
			end,&lt;br /&gt;
			explanation = &amp;quot;This protection is &#039;&#039;&#039;not&#039;&#039;&#039; an endorsement of the&amp;quot;&lt;br /&gt;
				.. &#039; ${CURRENTVERSION}. ${EXPLANATIONBLURB}&#039;,&lt;br /&gt;
			tooltip = &#039;${TOOLTIPFRAGMENT} due to editing disputes&#039;,&lt;br /&gt;
		},&lt;br /&gt;
		ecp = {&lt;br /&gt;
			description = &#039;For articles in topic areas authorized by&#039;&lt;br /&gt;
				.. &#039; [[Wikipedia:Arbitration Committee|ArbCom]] or&#039;&lt;br /&gt;
				.. &#039; meets the criteria for community use&#039;,&lt;br /&gt;
			alt = &#039;Extended-protected ${PAGETYPE}&#039;,&lt;br /&gt;
		},&lt;br /&gt;
		mainpage = {&lt;br /&gt;
			description = &#039;For pages protected for being displayed on the [[Main Page]]&#039;,&lt;br /&gt;
			text = &#039;This file is currently&#039;&lt;br /&gt;
				.. &#039; [[Wikipedia:This page is protected|protected]] from&#039;&lt;br /&gt;
				.. &#039; editing because it is currently or will soon be displayed&#039;&lt;br /&gt;
				.. &#039; on the [[Main Page]].&#039;,&lt;br /&gt;
			explanation = &#039;Images on the Main Page are protected due to their high&#039;&lt;br /&gt;
				.. &#039; visibility. Please discuss any necessary changes on the ${TALKPAGE}.&#039;&lt;br /&gt;
				.. &#039;&amp;lt;br /&amp;gt;&amp;lt;span style=&amp;quot;font-size:90%;&amp;quot;&amp;gt;&#039;&lt;br /&gt;
				.. &amp;quot;&#039;&#039;&#039;Administrators:&#039;&#039;&#039; Once this image is definitely off the Main Page,&amp;quot;&lt;br /&gt;
				.. &#039; please unprotect this file, or reduce to semi-protection,&#039;&lt;br /&gt;
				.. &#039; as appropriate.&amp;lt;/span&amp;gt;&#039;,&lt;br /&gt;
		},&lt;br /&gt;
		office = {&lt;br /&gt;
			description = &#039;For pages protected by the Wikimedia Foundation&#039;,&lt;br /&gt;
			text = function (protectionObj, args)&lt;br /&gt;
				local ret = &#039;This ${PAGETYPE} is currently under the&#039;&lt;br /&gt;
					.. &#039; scrutiny of the&#039;&lt;br /&gt;
					.. &#039; [[Wikipedia:Office actions|Wikimedia Foundation Office]]&#039;&lt;br /&gt;
					.. &#039; and is protected.&#039;&lt;br /&gt;
				if protectionObj.protectionDate then&lt;br /&gt;
					ret = ret .. &#039; It has been protected since ${PROTECTIONDATE}.&#039;&lt;br /&gt;
				end&lt;br /&gt;
				return ret&lt;br /&gt;
			end,&lt;br /&gt;
			explanation = &amp;quot;If you can edit this page, please discuss all changes and&amp;quot;&lt;br /&gt;
				.. &amp;quot; additions on the ${TALKPAGE} first. &#039;&#039;&#039;Do not remove protection from this&amp;quot;&lt;br /&gt;
				.. &amp;quot; page unless you are authorized by the Wikimedia Foundation to do&amp;quot;&lt;br /&gt;
				.. &amp;quot; so.&#039;&#039;&#039;&amp;quot;,&lt;br /&gt;
			image = &#039;Office-protection-shackle.svg&#039;,&lt;br /&gt;
			link = &#039;Wikipedia:Protection policy#office&#039;,&lt;br /&gt;
		},&lt;br /&gt;
		reset = {&lt;br /&gt;
			description = &#039;For pages protected by the Wikimedia Foundation and&#039;&lt;br /&gt;
				.. &#039; &amp;quot;reset&amp;quot; to a bare-bones version&#039;,&lt;br /&gt;
 			text = &#039;This ${PAGETYPE} is currently under the&#039;&lt;br /&gt;
					.. &#039; scrutiny of the&#039;&lt;br /&gt;
					.. &#039; [[Wikipedia:Office actions|Wikimedia Foundation Office]]&#039;&lt;br /&gt;
					.. &#039; and is protected.&#039;,&lt;br /&gt;
			explanation = function (protectionObj, args)&lt;br /&gt;
				local ret = &#039;&#039;&lt;br /&gt;
				if protectionObj.protectionDate then&lt;br /&gt;
					ret = ret .. &#039;On ${PROTECTIONDATE} this ${PAGETYPE} was&#039;&lt;br /&gt;
				else&lt;br /&gt;
					ret = ret .. &#039;This ${PAGETYPE} has been&#039;&lt;br /&gt;
				end&lt;br /&gt;
				ret = ret .. &#039; reduced to a&#039;&lt;br /&gt;
				.. &#039; simplified, &amp;quot;bare bones&amp;quot; version so that it may be completely&#039;&lt;br /&gt;
				.. &#039; rewritten to ensure it meets the policies of&#039;&lt;br /&gt;
				.. &#039; [[WP:NPOV|Neutral Point of View]] and [[WP:V|Verifiability]].&#039;&lt;br /&gt;
				.. &#039; Standard Wikipedia policies will apply to its rewriting—which&#039;&lt;br /&gt;
				.. &#039; will eventually be open to all editors—and will be strictly&#039;&lt;br /&gt;
				.. &#039; enforced. The ${PAGETYPE} has been ${PROTECTIONLEVEL} while&#039;&lt;br /&gt;
				.. &#039; it is being rebuilt.\n\n&#039;&lt;br /&gt;
				.. &#039;Any insertion of material directly from&#039;&lt;br /&gt;
				.. &#039; pre-protection revisions of the ${PAGETYPE} will be removed, as&#039;&lt;br /&gt;
				.. &#039; will any material added to the ${PAGETYPE} that is not properly&#039;&lt;br /&gt;
				.. &#039; sourced. The associated talk page(s) were also cleared on the&#039;&lt;br /&gt;
				.. &amp;quot; same date.\n\n&amp;quot;&lt;br /&gt;
				.. &amp;quot;If you can edit this page, please discuss all changes and&amp;quot;&lt;br /&gt;
				.. &amp;quot; additions on the ${TALKPAGE} first. &#039;&#039;&#039;Do not override&amp;quot;&lt;br /&gt;
				.. &amp;quot; this action, and do not remove protection from this page,&amp;quot;&lt;br /&gt;
				.. &amp;quot; unless you are authorized by the Wikimedia Foundation&amp;quot;&lt;br /&gt;
				.. &amp;quot; to do so. No editor may remove this notice.&#039;&#039;&#039;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
				return ret&lt;br /&gt;
			end,&lt;br /&gt;
			image = &#039;Office-protection-shackle.svg&#039;,&lt;br /&gt;
			link = &#039;Wikipedia:Protection policy#office&#039;,&lt;br /&gt;
		},&lt;br /&gt;
		sock = {&lt;br /&gt;
			description = &#039;For pages protected due to&#039;&lt;br /&gt;
				.. &#039; [[Wikipedia:Sock puppetry|sock puppetry]]&#039;,&lt;br /&gt;
			text = &#039;${INTROFRAGMENT} to prevent [[Wikipedia:Sock puppetry|sock puppets]] of&#039;&lt;br /&gt;
				.. &#039; [[Wikipedia:Blocking policy|blocked]] or&#039;&lt;br /&gt;
				.. &#039; [[Wikipedia:Banning policy|banned users]]&#039;&lt;br /&gt;
				.. &#039; from editing it.&#039;,&lt;br /&gt;
			tooltip = &#039;${TOOLTIPFRAGMENT} to prevent sock puppets of blocked or banned users from&#039;&lt;br /&gt;
				.. &#039; editing it&#039;,&lt;br /&gt;
		},&lt;br /&gt;
		template = {&lt;br /&gt;
			description = &#039;For [[Wikipedia:High-risk templates|high-risk]]&#039;&lt;br /&gt;
				.. &#039; templates and Lua modules&#039;,&lt;br /&gt;
			text = &#039;This is a permanently [[Wikipedia:Protection policy|protected]] ${PAGETYPE},&#039;&lt;br /&gt;
				.. &#039; as it is [[Wikipedia:High-risk templates|high-risk]].&#039;,&lt;br /&gt;
			explanation = &#039;Please discuss any changes on the ${TALKPAGE}; you may&#039;&lt;br /&gt;
				.. &#039; ${EDITREQUEST} to ask an&#039;&lt;br /&gt;
				.. &#039; [[Wikipedia:Administrators|administrator]] or&#039;&lt;br /&gt;
				.. &#039; [[Wikipedia:Template editor|template editor]] to make an edit if&#039;&lt;br /&gt;
				.. &#039; it is [[Help:Minor edit#When to mark an edit as a minor edit&#039;&lt;br /&gt;
				.. &#039;|uncontroversial]] or supported by&#039;&lt;br /&gt;
				.. &#039; [[Wikipedia:Consensus|consensus]]. You can also&#039;&lt;br /&gt;
				.. &#039; [[Wikipedia:Requests for page protection|request]] that the page be&#039;&lt;br /&gt;
				.. &#039; unprotected.&#039;,&lt;br /&gt;
			tooltip = &#039;This high-risk ${PAGETYPE} is permanently ${PROTECTIONLEVEL}&#039;&lt;br /&gt;
				.. &#039; to prevent vandalism&#039;,&lt;br /&gt;
			alt = &#039;Permanently protected ${PAGETYPE}&#039;,&lt;br /&gt;
		},&lt;br /&gt;
		usertalk = {&lt;br /&gt;
			description = &#039;For pages protected against disruptive edits by a&#039;&lt;br /&gt;
				.. &#039; particular user&#039;,&lt;br /&gt;
			text = &#039;${INTROFRAGMENT} to prevent ${VANDAL} from using it to make disruptive edits,&#039;&lt;br /&gt;
				.. &#039; such as abusing the&#039;&lt;br /&gt;
				.. &#039; &amp;amp;#123;&amp;amp;#123;[[Template:unblock|unblock]]&amp;amp;#125;&amp;amp;#125; template.&#039;,&lt;br /&gt;
			explanation = &#039;If you cannot edit this user talk page and you need to&#039;&lt;br /&gt;
				.. &#039; make a change or leave a message, you can&#039;&lt;br /&gt;
				.. &#039; [[Wikipedia:Requests for page protection&#039;&lt;br /&gt;
				.. &#039;#Current requests for edits to a protected page&#039;&lt;br /&gt;
				.. &#039;|request an edit]],&#039;&lt;br /&gt;
				.. &#039; [[Wikipedia:Requests for page protection&#039;&lt;br /&gt;
				.. &#039;#Current requests for reduction in protection level&#039;&lt;br /&gt;
				.. &#039;|request unprotection]],&#039;&lt;br /&gt;
				.. &#039; [[Special:Userlogin|log in]],&#039;&lt;br /&gt;
				.. &#039; or [[Special:UserLogin/signup|create an account]].&#039;,&lt;br /&gt;
		},&lt;br /&gt;
		vandalism = {&lt;br /&gt;
			description = &#039;For pages protected against&#039;&lt;br /&gt;
				.. &#039; [[Wikipedia:Vandalism|vandalism]]&#039;,&lt;br /&gt;
			text = &#039;${INTROFRAGMENT} due to [[Wikipedia:Vandalism|vandalism]].&#039;,&lt;br /&gt;
			explanation = function (protectionObj, args)&lt;br /&gt;
				local ret = &#039;&#039;&lt;br /&gt;
				if protectionObj.level == &#039;sysop&#039; then&lt;br /&gt;
					ret = ret .. &amp;quot;This protection is &#039;&#039;&#039;not&#039;&#039;&#039; an endorsement of the&amp;quot;&lt;br /&gt;
						.. &#039; ${CURRENTVERSION}. &#039;&lt;br /&gt;
				end&lt;br /&gt;
				return ret .. &#039;${EXPLANATIONBLURB}&#039;&lt;br /&gt;
			end,&lt;br /&gt;
			tooltip = &#039;${TOOLTIPFRAGMENT} due to vandalism&#039;,&lt;br /&gt;
		}&lt;br /&gt;
	},&lt;br /&gt;
	move = {&lt;br /&gt;
		dispute = {&lt;br /&gt;
			description = &#039;For pages protected against page moves due to&#039;&lt;br /&gt;
				.. &#039; disputes over the page title&#039;,&lt;br /&gt;
			explanation = &amp;quot;This protection is &#039;&#039;&#039;not&#039;&#039;&#039; an endorsement of the&amp;quot;&lt;br /&gt;
				.. &#039; ${CURRENTVERSION}. ${EXPLANATIONBLURB}&#039;,&lt;br /&gt;
			image = &#039;Move-protection-shackle.svg&#039;&lt;br /&gt;
		},&lt;br /&gt;
		vandalism = {&lt;br /&gt;
			description = &#039;For pages protected against&#039;&lt;br /&gt;
				.. &#039; [[Wikipedia:Vandalism#Page-move vandalism&#039;&lt;br /&gt;
				.. &#039; |page-move vandalism]]&#039;&lt;br /&gt;
		}&lt;br /&gt;
	},&lt;br /&gt;
	autoreview = {},&lt;br /&gt;
	upload = {}&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
--&lt;br /&gt;
--                            GENERAL DATA TABLES&lt;br /&gt;
--&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Protection blurbs&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- This table produces the protection blurbs available with the&lt;br /&gt;
-- ${PROTECTIONBLURB} parameter. It is sorted by protection action and&lt;br /&gt;
-- protection level, and is checked by the module in the following order:&lt;br /&gt;
-- 1. page&#039;s protection action, page&#039;s protection level&lt;br /&gt;
-- 2. page&#039;s protection action, default protection level&lt;br /&gt;
-- 3. &amp;quot;edit&amp;quot; protection action, default protection level&lt;br /&gt;
--&lt;br /&gt;
-- It is possible to use banner parameters inside this table.&lt;br /&gt;
-- *required* - this table needs edit, move, autoreview and upload subtables.&lt;br /&gt;
protectionBlurbs = {&lt;br /&gt;
	edit = {&lt;br /&gt;
		default = &#039;This ${PAGETYPE} is currently [[Wikipedia:Protection policy#full|&#039;&lt;br /&gt;
			.. &#039;protected]] from editing&#039;,&lt;br /&gt;
		templateeditor = &#039;This ${PAGETYPE} is currently [[Wikipedia:Protection policy#template&#039;&lt;br /&gt;
			.. &#039;|protected]] from editing&#039;,&lt;br /&gt;
		autoconfirmed = &#039;Editing of this ${PAGETYPE} by [[Wikipedia:User access&#039;&lt;br /&gt;
			.. &#039; levels#New users|new]] or [[Wikipedia:User access levels#Unregistered&#039;&lt;br /&gt;
			.. &#039; users|unregistered]] users is currently [[Wikipedia:Protection&#039;&lt;br /&gt;
			.. &#039; policy#semi|disabled]]&#039;,&lt;br /&gt;
		extendedconfirmed = &#039;This ${PAGETYPE} is currently under [[Wikipedia:Protection&#039;&lt;br /&gt;
			.. &#039; policy#extended|extended confirmed protection]]&#039;,&lt;br /&gt;
	},&lt;br /&gt;
	move = {&lt;br /&gt;
		default = &#039;This ${PAGETYPE} is currently [[Wikipedia:Protection policy#Move&#039;&lt;br /&gt;
			.. &#039; protection|protected]] from [[Help:Moving a page|page moves]]&#039;&lt;br /&gt;
	},&lt;br /&gt;
	autoreview = {&lt;br /&gt;
		default = &#039;All edits made to this ${PAGETYPE} by&#039;&lt;br /&gt;
			.. &#039; [[Wikipedia:User access levels#New users|new]] or&#039;&lt;br /&gt;
			.. &#039; [[Wikipedia:User access levels#Unregistered users|unregistered]]&#039;&lt;br /&gt;
			.. &#039; users are currently&#039;&lt;br /&gt;
			.. &#039; [[Wikipedia:Pending changes|subject to review]]&#039;&lt;br /&gt;
	},&lt;br /&gt;
	upload = {&lt;br /&gt;
		default = &#039;Uploading new versions of this ${PAGETYPE} is currently disabled&#039;&lt;br /&gt;
	}&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Explanation blurbs&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- This table produces the explanation blurbs available with the&lt;br /&gt;
-- ${EXPLANATIONBLURB} parameter. It is sorted by protection action,&lt;br /&gt;
-- protection level, and whether the page is a talk page or not. If the page is&lt;br /&gt;
-- a talk page it will have a talk key of &amp;quot;talk&amp;quot;; otherwise it will have a talk&lt;br /&gt;
-- key of &amp;quot;subject&amp;quot;. The table is checked in the following order:&lt;br /&gt;
-- 1. page&#039;s protection action, page&#039;s protection level, page&#039;s talk key&lt;br /&gt;
-- 2. page&#039;s protection action, page&#039;s protection level, default talk key&lt;br /&gt;
-- 3. page&#039;s protection action, default protection level, page&#039;s talk key&lt;br /&gt;
-- 4. page&#039;s protection action, default protection level, default talk key&lt;br /&gt;
--&lt;br /&gt;
-- It is possible to use banner parameters inside this table.&lt;br /&gt;
-- *required* - this table needs edit, move, autoreview and upload subtables.&lt;br /&gt;
explanationBlurbs = {&lt;br /&gt;
	edit = {&lt;br /&gt;
		autoconfirmed = {&lt;br /&gt;
			subject = &#039;See the [[Wikipedia:Protection policy|&#039;&lt;br /&gt;
				.. &#039;protection policy]] and ${PROTECTIONLOG} for more details. If you&#039;&lt;br /&gt;
				.. &#039; cannot edit this ${PAGETYPE} and you wish to make a change, you can&#039;&lt;br /&gt;
				.. &#039; ${EDITREQUEST}, discuss changes on the ${TALKPAGE},&#039;&lt;br /&gt;
				.. &#039; [[Wikipedia:Requests for page protection&#039;&lt;br /&gt;
				.. &#039;#Current requests for reduction in protection level&#039;&lt;br /&gt;
				.. &#039;|request unprotection]], [[Special:Userlogin|log in]], or&#039;&lt;br /&gt;
				.. &#039; [[Special:UserLogin/signup|create an account]].&#039;,&lt;br /&gt;
			default = &#039;See the [[Wikipedia:Protection policy|&#039;&lt;br /&gt;
				.. &#039;protection policy]] and ${PROTECTIONLOG} for more details. If you&#039;&lt;br /&gt;
				.. &#039; cannot edit this ${PAGETYPE} and you wish to make a change, you can&#039;&lt;br /&gt;
				.. &#039; [[Wikipedia:Requests for page protection&#039;&lt;br /&gt;
				.. &#039;#Current requests for reduction in protection level&#039;&lt;br /&gt;
				.. &#039;|request unprotection]], [[Special:Userlogin|log in]], or&#039;&lt;br /&gt;
				.. &#039; [[Special:UserLogin/signup|create an account]].&#039;,&lt;br /&gt;
		},&lt;br /&gt;
		extendedconfirmed = {&lt;br /&gt;
			default = &#039;Extended confirmed protection prevents edits from all unregistered editors&#039;&lt;br /&gt;
				.. &#039; and registered users with fewer than 30 days tenure and 500 edits.&#039;&lt;br /&gt;
				.. &#039; The [[Wikipedia:Protection policy#extended|policy on community use]]&#039;&lt;br /&gt;
				.. &#039; specifies that extended confirmed protection can be applied to combat&#039;&lt;br /&gt;
				.. &#039; disruption, if semi-protection has proven to be ineffective.&#039;&lt;br /&gt;
				.. &#039; Extended confirmed protection may also be applied to enforce&#039;&lt;br /&gt;
				.. &#039; [[Wikipedia:Arbitration Committee|arbitration sanctions]].&#039;&lt;br /&gt;
				.. &#039; Please discuss any changes on the ${TALKPAGE}; you may&#039;&lt;br /&gt;
				.. &#039; ${EDITREQUEST} to ask for uncontroversial changes supported by&#039;&lt;br /&gt;
				.. &#039; [[Wikipedia:Consensus|consensus]].&#039;&lt;br /&gt;
		},&lt;br /&gt;
		default = {&lt;br /&gt;
			subject = &#039;See the [[Wikipedia:Protection policy|&#039;&lt;br /&gt;
				.. &#039;protection policy]] and ${PROTECTIONLOG} for more details.&#039;&lt;br /&gt;
				.. &#039; Please discuss any changes on the ${TALKPAGE}; you&#039;&lt;br /&gt;
				.. &#039; may ${EDITREQUEST} to ask an&#039;&lt;br /&gt;
				.. &#039; [[Wikipedia:Administrators|administrator]] to make an edit if it&#039;&lt;br /&gt;
				.. &#039; is [[Help:Minor edit#When to mark an edit as a minor edit&#039;&lt;br /&gt;
				.. &#039;|uncontroversial]] or supported by [[Wikipedia:Consensus&#039;&lt;br /&gt;
				.. &#039;|consensus]]. You may also [[Wikipedia:Requests for&#039;&lt;br /&gt;
				.. &#039; page protection#Current requests for reduction in protection level&#039;&lt;br /&gt;
				.. &#039;|request]] that this page be unprotected.&#039;,&lt;br /&gt;
			default = &#039;See the [[Wikipedia:Protection policy|&#039;&lt;br /&gt;
				.. &#039;protection policy]] and ${PROTECTIONLOG} for more details.&#039;&lt;br /&gt;
				.. &#039; You may [[Wikipedia:Requests for page&#039;&lt;br /&gt;
				.. &#039; protection#Current requests for edits to a protected page|request an&#039;&lt;br /&gt;
				.. &#039; edit]] to this page, or [[Wikipedia:Requests for&#039;&lt;br /&gt;
				.. &#039; page protection#Current requests for reduction in protection level&#039;&lt;br /&gt;
				.. &#039;|ask]] for it to be unprotected.&#039;&lt;br /&gt;
		}&lt;br /&gt;
	},&lt;br /&gt;
	move = {&lt;br /&gt;
		default = {&lt;br /&gt;
			subject = &#039;See the [[Wikipedia:Protection policy|&#039;&lt;br /&gt;
				.. &#039;protection policy]] and ${PROTECTIONLOG} for more details.&#039;&lt;br /&gt;
				.. &#039; The page may still be edited but cannot be moved&#039;&lt;br /&gt;
				.. &#039; until unprotected. Please discuss any suggested moves on the&#039;&lt;br /&gt;
				.. &#039; ${TALKPAGE} or at [[Wikipedia:Requested moves]]. You can also&#039;&lt;br /&gt;
				.. &#039; [[Wikipedia:Requests for page protection|request]] that the page be&#039;&lt;br /&gt;
				.. &#039; unprotected.&#039;,&lt;br /&gt;
			default = &#039;See the [[Wikipedia:Protection policy|&#039;&lt;br /&gt;
				.. &#039;protection policy]] and ${PROTECTIONLOG} for more details.&#039;&lt;br /&gt;
				.. &#039; The page may still be edited but cannot be moved&#039;&lt;br /&gt;
				.. &#039; until unprotected. Please discuss any suggested moves at&#039;&lt;br /&gt;
				.. &#039; [[Wikipedia:Requested moves]]. You can also&#039;&lt;br /&gt;
				.. &#039; [[Wikipedia:Requests for page protection|request]] that the page be&#039;&lt;br /&gt;
				.. &#039; unprotected.&#039;&lt;br /&gt;
		}&lt;br /&gt;
	},&lt;br /&gt;
	autoreview = {&lt;br /&gt;
		default = {&lt;br /&gt;
			default = &#039;See the [[Wikipedia:Protection policy|&#039;&lt;br /&gt;
				.. &#039;protection policy]] and ${PROTECTIONLOG} for more details.&#039;&lt;br /&gt;
				.. &#039; Edits to this ${PAGETYPE} by new and unregistered users&#039;&lt;br /&gt;
				.. &#039; will not be visible to readers until they are accepted by&#039;&lt;br /&gt;
				.. &#039; a reviewer. To avoid the need for your edits to be&#039;&lt;br /&gt;
				.. &#039; reviewed, you may&#039;&lt;br /&gt;
				.. &#039; [[Wikipedia:Requests for page protection&#039;&lt;br /&gt;
				.. &#039;#Current requests for reduction in protection level&#039;&lt;br /&gt;
				.. &#039;|request unprotection]], [[Special:Userlogin|log in]], or&#039;&lt;br /&gt;
				.. &#039; [[Special:UserLogin/signup|create an account]].&#039;&lt;br /&gt;
		},&lt;br /&gt;
	},&lt;br /&gt;
	upload = {&lt;br /&gt;
		default = {&lt;br /&gt;
			default = &#039;See the [[Wikipedia:Protection policy|&#039;&lt;br /&gt;
				.. &#039;protection policy]] and ${PROTECTIONLOG} for more details.&#039;&lt;br /&gt;
				.. &#039; The page may still be edited but new versions of the file&#039;&lt;br /&gt;
				.. &#039; cannot be uploaded until it is unprotected. You can&#039;&lt;br /&gt;
				.. &#039; request that a new version be uploaded by using a&#039;&lt;br /&gt;
				.. &#039; [[Wikipedia:Edit requests|protected edit request]], or you&#039;&lt;br /&gt;
				.. &#039; can  [[Wikipedia:Requests for page protection|request]]&#039;&lt;br /&gt;
				.. &#039; that the file be unprotected.&#039;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Protection levels&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- This table provides the data for the ${PROTECTIONLEVEL} parameter, which&lt;br /&gt;
-- produces a short label for different protection levels. It is sorted by&lt;br /&gt;
-- protection action and protection level, and is checked in the following&lt;br /&gt;
-- order:&lt;br /&gt;
-- 1. page&#039;s protection action, page&#039;s protection level&lt;br /&gt;
-- 2. page&#039;s protection action, default protection level&lt;br /&gt;
-- 3. &amp;quot;edit&amp;quot; protection action, default protection level&lt;br /&gt;
--&lt;br /&gt;
-- It is possible to use banner parameters inside this table.&lt;br /&gt;
-- *required* - this table needs edit, move, autoreview and upload subtables.&lt;br /&gt;
protectionLevels = {&lt;br /&gt;
	edit = {&lt;br /&gt;
		default = &#039;protected&#039;,&lt;br /&gt;
		templateeditor = &#039;template-protected&#039;,&lt;br /&gt;
		extendedconfirmed = &#039;extended-confirmed-protected&#039;,&lt;br /&gt;
		autoconfirmed = &#039;semi-protected&#039;,&lt;br /&gt;
	},&lt;br /&gt;
	move = {&lt;br /&gt;
		default = &#039;move-protected&#039;&lt;br /&gt;
	},&lt;br /&gt;
	autoreview = {&lt;br /&gt;
	},&lt;br /&gt;
	upload = {&lt;br /&gt;
		default = &#039;upload-protected&#039;&lt;br /&gt;
	}&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Images&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- This table lists different padlock images for each protection action and&lt;br /&gt;
-- protection level. It is used if an image is not specified in any of the&lt;br /&gt;
-- banner data tables, and if the page does not satisfy the conditions for using&lt;br /&gt;
-- the [&#039;image-filename-indef&#039;] image. It is checked in the following order:&lt;br /&gt;
-- 1. page&#039;s protection action, page&#039;s protection level&lt;br /&gt;
-- 2. page&#039;s protection action, default protection level&lt;br /&gt;
images = {&lt;br /&gt;
	edit = {&lt;br /&gt;
		default = &#039;Full-protection-shackle.svg&#039;,&lt;br /&gt;
		templateeditor = &#039;Template-protection-shackle.svg&#039;,&lt;br /&gt;
		extendedconfirmed = &#039;Extended-protection-shackle.svg&#039;,&lt;br /&gt;
		autoconfirmed = &#039;Semi-protection-shackle.svg&#039;&lt;br /&gt;
	},&lt;br /&gt;
	move = {&lt;br /&gt;
		default = &#039;Move-protection-shackle.svg&#039;,&lt;br /&gt;
	},&lt;br /&gt;
	autoreview = {&lt;br /&gt;
		default = &#039;Pending-protection-shackle.svg&#039;&lt;br /&gt;
	},&lt;br /&gt;
	upload = {&lt;br /&gt;
		default = &#039;Upload-protection-shackle.svg&#039;&lt;br /&gt;
	}&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
-- Pages with a reason specified in this table will show the special &amp;quot;indef&amp;quot;&lt;br /&gt;
-- padlock, defined in the &#039;image-filename-indef&#039; message, if no expiry is set.&lt;br /&gt;
indefImageReasons = {&lt;br /&gt;
	template = true&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Image links&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- This table provides the data for the ${IMAGELINK} parameter, which gets&lt;br /&gt;
-- the image link for small padlock icons based on the page&#039;s protection action&lt;br /&gt;
-- and protection level. It is checked in the following order:&lt;br /&gt;
-- 1. page&#039;s protection action, page&#039;s protection level&lt;br /&gt;
-- 2. page&#039;s protection action, default protection level&lt;br /&gt;
-- 3. &amp;quot;edit&amp;quot; protection action, default protection level&lt;br /&gt;
--&lt;br /&gt;
-- It is possible to use banner parameters inside this table.&lt;br /&gt;
-- *required* - this table needs edit, move, autoreview and upload subtables.&lt;br /&gt;
imageLinks = {&lt;br /&gt;
	edit = {&lt;br /&gt;
		default = &#039;Wikipedia:Protection policy#full&#039;,&lt;br /&gt;
		templateeditor = &#039;Wikipedia:Protection policy#template&#039;,&lt;br /&gt;
		extendedconfirmed = &#039;Wikipedia:Protection policy#extended&#039;,&lt;br /&gt;
		autoconfirmed = &#039;Wikipedia:Protection policy#semi&#039;&lt;br /&gt;
	},&lt;br /&gt;
	move = {&lt;br /&gt;
		default = &#039;Wikipedia:Protection policy#move&#039;&lt;br /&gt;
	},&lt;br /&gt;
	autoreview = {&lt;br /&gt;
		default = &#039;Wikipedia:Protection policy#pending&#039;&lt;br /&gt;
	},&lt;br /&gt;
	upload = {&lt;br /&gt;
		default = &#039;Wikipedia:Protection policy#upload&#039;&lt;br /&gt;
	}&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Padlock indicator names&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- This table provides the &amp;quot;name&amp;quot; attribute for the &amp;lt;indicator&amp;gt; extension tag&lt;br /&gt;
-- with which small padlock icons are generated. All indicator tags on a page&lt;br /&gt;
-- are displayed in alphabetical order based on this attribute, and with&lt;br /&gt;
-- indicator tags with duplicate names, the last tag on the page wins.&lt;br /&gt;
-- The attribute is chosen based on the protection action; table keys must be a&lt;br /&gt;
-- protection action name or the string &amp;quot;default&amp;quot;.&lt;br /&gt;
padlockIndicatorNames = {&lt;br /&gt;
	autoreview = &#039;pp-autoreview&#039;,&lt;br /&gt;
	default = &#039;pp-default&#039;&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Protection categories&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
--[[&lt;br /&gt;
-- The protection categories are stored in the protectionCategories table.&lt;br /&gt;
-- Keys to this table are made up of the following strings:&lt;br /&gt;
--&lt;br /&gt;
-- 1. the expiry date&lt;br /&gt;
-- 2. the namespace&lt;br /&gt;
-- 3. the protection reason (e.g. &amp;quot;dispute&amp;quot; or &amp;quot;vandalism&amp;quot;)&lt;br /&gt;
-- 4. the protection level (e.g. &amp;quot;sysop&amp;quot; or &amp;quot;autoconfirmed&amp;quot;)&lt;br /&gt;
-- 5. the action (e.g. &amp;quot;edit&amp;quot; or &amp;quot;move&amp;quot;)&lt;br /&gt;
-- &lt;br /&gt;
-- When the module looks up a category in the table, first it will will check to&lt;br /&gt;
-- see a key exists that corresponds to all five parameters. For example, a&lt;br /&gt;
-- user page semi-protected from vandalism for two weeks would have the key&lt;br /&gt;
-- &amp;quot;temp-user-vandalism-autoconfirmed-edit&amp;quot;. If no match is found, the module&lt;br /&gt;
-- changes the first part of the key to &amp;quot;all&amp;quot; and checks the table again. It&lt;br /&gt;
-- keeps checking increasingly generic key combinations until it finds the&lt;br /&gt;
-- field, or until it reaches the key &amp;quot;all-all-all-all-all&amp;quot;.&lt;br /&gt;
--&lt;br /&gt;
-- The module uses a binary matrix to determine the order in which to search.&lt;br /&gt;
-- This is best demonstrated by a table. In this table, the &amp;quot;0&amp;quot; values&lt;br /&gt;
-- represent &amp;quot;all&amp;quot;, and the &amp;quot;1&amp;quot; values represent the original data (e.g.&lt;br /&gt;
-- &amp;quot;indef&amp;quot; or &amp;quot;file&amp;quot; or &amp;quot;vandalism&amp;quot;).&lt;br /&gt;
--&lt;br /&gt;
--        expiry    namespace reason   level     action&lt;br /&gt;
-- order&lt;br /&gt;
-- 1      1         1         1        1         1&lt;br /&gt;
-- 2      0         1         1        1         1&lt;br /&gt;
-- 3      1         0         1        1         1&lt;br /&gt;
-- 4      0         0         1        1         1&lt;br /&gt;
-- 5      1         1         0        1         1&lt;br /&gt;
-- 6      0         1         0        1         1&lt;br /&gt;
-- 7      1         0         0        1         1&lt;br /&gt;
-- 8      0         0         0        1         1&lt;br /&gt;
-- 9      1         1         1        0         1&lt;br /&gt;
-- 10     0         1         1        0         1&lt;br /&gt;
-- 11     1         0         1        0         1&lt;br /&gt;
-- 12     0         0         1        0         1&lt;br /&gt;
-- 13     1         1         0        0         1&lt;br /&gt;
-- 14     0         1         0        0         1&lt;br /&gt;
-- 15     1         0         0        0         1&lt;br /&gt;
-- 16     0         0         0        0         1&lt;br /&gt;
-- 17     1         1         1        1         0&lt;br /&gt;
-- 18     0         1         1        1         0&lt;br /&gt;
-- 19     1         0         1        1         0&lt;br /&gt;
-- 20     0         0         1        1         0&lt;br /&gt;
-- 21     1         1         0        1         0&lt;br /&gt;
-- 22     0         1         0        1         0&lt;br /&gt;
-- 23     1         0         0        1         0&lt;br /&gt;
-- 24     0         0         0        1         0&lt;br /&gt;
-- 25     1         1         1        0         0&lt;br /&gt;
-- 26     0         1         1        0         0&lt;br /&gt;
-- 27     1         0         1        0         0&lt;br /&gt;
-- 28     0         0         1        0         0&lt;br /&gt;
-- 29     1         1         0        0         0&lt;br /&gt;
-- 30     0         1         0        0         0&lt;br /&gt;
-- 31     1         0         0        0         0&lt;br /&gt;
-- 32     0         0         0        0         0&lt;br /&gt;
--&lt;br /&gt;
-- In this scheme the action has the highest priority, as it is the last&lt;br /&gt;
-- to change, and the expiry has the least priority, as it changes the most.&lt;br /&gt;
-- The priorities of the expiry, the protection level and the action are&lt;br /&gt;
-- fixed, but the priorities of the reason and the namespace can be swapped&lt;br /&gt;
-- through the use of the cfg.bannerDataNamespaceHasPriority table.&lt;br /&gt;
--]]&lt;br /&gt;
&lt;br /&gt;
-- If the reason specified to the template is listed in this table,&lt;br /&gt;
-- namespace data will take priority over reason data in the protectionCategories&lt;br /&gt;
-- table.&lt;br /&gt;
reasonsWithNamespacePriority = {&lt;br /&gt;
	vandalism = true,&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
-- The string to use as a namespace key for the protectionCategories table for each&lt;br /&gt;
-- namespace number.&lt;br /&gt;
categoryNamespaceKeys = {&lt;br /&gt;
	[  2] = &#039;user&#039;,&lt;br /&gt;
	[  3] = &#039;user&#039;,&lt;br /&gt;
	[  4] = &#039;project&#039;,&lt;br /&gt;
	[  6] = &#039;file&#039;,&lt;br /&gt;
	[  8] = &#039;mediawiki&#039;,&lt;br /&gt;
	[ 10] = &#039;template&#039;,&lt;br /&gt;
	[ 12] = &#039;project&#039;,&lt;br /&gt;
	[ 14] = &#039;category&#039;,&lt;br /&gt;
	[100] = &#039;portal&#039;,&lt;br /&gt;
	[828] = &#039;module&#039;,&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
protectionCategories = {&lt;br /&gt;
	[&#039;all|all|all|all|all&#039;]                     = &#039;Wikipedia fully protected pages&#039;,&lt;br /&gt;
	[&#039;all|all|office|all|all&#039;]                  = &#039;Wikipedia Office-protected pages&#039;,&lt;br /&gt;
	[&#039;all|all|reset|all|all&#039;]                   = &#039;Wikipedia Office-protected pages&#039;,&lt;br /&gt;
	[&#039;all|all|dmca|all|all&#039;]                    = &#039;Wikipedia Office-protected pages&#039;,&lt;br /&gt;
	[&#039;all|all|mainpage|all|all&#039;]                = &#039;Wikipedia fully protected main page files&#039;,&lt;br /&gt;
	[&#039;all|all|all|extendedconfirmed|all&#039;]       = &#039;Wikipedia extended-confirmed-protected pages&#039;,&lt;br /&gt;
	[&#039;all|all|ecp|extendedconfirmed|all&#039;]       = &#039;Wikipedia extended-confirmed-protected pages&#039;,&lt;br /&gt;
	[&#039;all|template|all|all|edit&#039;]               = &#039;Wikipedia fully protected templates&#039;,&lt;br /&gt;
	[&#039;all|all|all|autoconfirmed|edit&#039;]          = &#039;Wikipedia semi-protected pages&#039;,&lt;br /&gt;
	[&#039;indef|all|all|autoconfirmed|edit&#039;]        = &#039;Wikipedia indefinitely semi-protected pages&#039;,&lt;br /&gt;
	[&#039;all|all|blp|autoconfirmed|edit&#039;]          = &#039;Wikipedia indefinitely semi-protected biographies of living people&#039;,&lt;br /&gt;
	[&#039;temp|all|blp|autoconfirmed|edit&#039;]         = &#039;Wikipedia temporarily semi-protected biographies of living people&#039;,&lt;br /&gt;
	[&#039;all|all|dispute|autoconfirmed|edit&#039;]      = &#039;Wikipedia pages semi-protected due to dispute&#039;,&lt;br /&gt;
	[&#039;all|all|sock|autoconfirmed|edit&#039;]         = &#039;Wikipedia pages semi-protected from banned users&#039;,&lt;br /&gt;
	[&#039;all|all|vandalism|autoconfirmed|edit&#039;]    = &#039;Wikipedia pages semi-protected against vandalism&#039;,&lt;br /&gt;
	[&#039;all|category|all|autoconfirmed|edit&#039;]     = &#039;Wikipedia semi-protected categories&#039;,&lt;br /&gt;
	[&#039;all|file|all|autoconfirmed|edit&#039;]         = &#039;Wikipedia semi-protected files&#039;,&lt;br /&gt;
	[&#039;all|portal|all|autoconfirmed|edit&#039;]       = &#039;Wikipedia semi-protected portals&#039;,&lt;br /&gt;
	[&#039;all|project|all|autoconfirmed|edit&#039;]      = &#039;Wikipedia semi-protected project pages&#039;,&lt;br /&gt;
	[&#039;all|talk|all|autoconfirmed|edit&#039;]         = &#039;Wikipedia semi-protected talk pages&#039;,&lt;br /&gt;
	[&#039;all|template|all|autoconfirmed|edit&#039;]     = &#039;Wikipedia semi-protected templates&#039;,&lt;br /&gt;
	[&#039;all|user|all|autoconfirmed|edit&#039;]         = &#039;Wikipedia semi-protected user and user talk pages&#039;,&lt;br /&gt;
	[&#039;all|all|all|templateeditor|move&#039;]         = &#039;Wikipedia template-protected pages other than templates and modules&#039;,&lt;br /&gt;
	[&#039;all|all|all|templateeditor|edit&#039;]         = &#039;Wikipedia template-protected pages other than templates and modules&#039;,&lt;br /&gt;
	[&#039;all|template|all|templateeditor|edit&#039;]    = &#039;Wikipedia template-protected templates&#039;,&lt;br /&gt;
	[&#039;all|template|all|templateeditor|move&#039;]    = &#039;Wikipedia template-protected templates&#039;, -- move-protected templates&lt;br /&gt;
	[&#039;all|all|blp|sysop|edit&#039;]                  = &#039;Wikipedia indefinitely protected biographies of living people&#039;,&lt;br /&gt;
	[&#039;temp|all|blp|sysop|edit&#039;]                 = &#039;Wikipedia temporarily protected biographies of living people&#039;,&lt;br /&gt;
	[&#039;all|all|dispute|sysop|edit&#039;]              = &#039;Wikipedia pages protected due to dispute&#039;,&lt;br /&gt;
	[&#039;all|all|sock|sysop|edit&#039;]                 = &#039;Wikipedia pages protected from banned users&#039;,&lt;br /&gt;
	[&#039;all|all|vandalism|sysop|edit&#039;]            = &#039;Wikipedia pages protected against vandalism&#039;,&lt;br /&gt;
	[&#039;all|category|all|sysop|edit&#039;]             = &#039;Wikipedia fully protected categories&#039;,&lt;br /&gt;
	[&#039;all|file|all|sysop|edit&#039;]                 = &#039;Wikipedia fully protected files&#039;,&lt;br /&gt;
	[&#039;all|project|all|sysop|edit&#039;]              = &#039;Wikipedia fully protected project pages&#039;,&lt;br /&gt;
	[&#039;all|talk|all|sysop|edit&#039;]                 = &#039;Wikipedia fully protected talk pages&#039;,&lt;br /&gt;
	[&#039;all|template|all|extendedconfirmed|edit&#039;] = &#039;Wikipedia extended-confirmed-protected templates&#039;,&lt;br /&gt;
	[&#039;all|template|all|extendedconfirmed|move&#039;] = &#039;Wikipedia extended-confirmed-protected templates&#039;,&lt;br /&gt;
	[&#039;all|template|all|sysop|edit&#039;]             = &#039;Wikipedia fully protected templates&#039;,&lt;br /&gt;
	[&#039;all|user|all|sysop|edit&#039;]                 = &#039;Wikipedia fully protected user and user talk pages&#039;,&lt;br /&gt;
	[&#039;all|module|all|all|edit&#039;]                 = &#039;Wikipedia fully protected modules&#039;,&lt;br /&gt;
	[&#039;all|module|all|templateeditor|edit&#039;]      = &#039;Wikipedia template-protected modules&#039;,&lt;br /&gt;
	[&#039;all|module|all|extendedconfirmed|edit&#039;]   = &#039;Wikipedia extended-confirmed-protected modules&#039;,&lt;br /&gt;
	[&#039;all|module|all|autoconfirmed|edit&#039;]       = &#039;Wikipedia semi-protected modules&#039;,&lt;br /&gt;
	[&#039;all|all|all|sysop|move&#039;]                  = &#039;Wikipedia move-protected pages&#039;,&lt;br /&gt;
	[&#039;indef|all|all|sysop|move&#039;]                = &#039;Wikipedia indefinitely move-protected pages&#039;,&lt;br /&gt;
	[&#039;all|all|dispute|sysop|move&#039;]              = &#039;Wikipedia pages move-protected due to dispute&#039;,&lt;br /&gt;
	[&#039;all|all|vandalism|sysop|move&#039;]            = &#039;Wikipedia pages move-protected due to vandalism&#039;,&lt;br /&gt;
	[&#039;all|portal|all|sysop|move&#039;]               = &#039;Wikipedia move-protected portals&#039;,&lt;br /&gt;
	[&#039;all|project|all|sysop|move&#039;]              = &#039;Wikipedia move-protected project pages&#039;,&lt;br /&gt;
	[&#039;all|talk|all|sysop|move&#039;]                 = &#039;Wikipedia move-protected talk pages&#039;,&lt;br /&gt;
	[&#039;all|template|all|sysop|move&#039;]             = &#039;Wikipedia move-protected templates&#039;,&lt;br /&gt;
	[&#039;all|user|all|sysop|move&#039;]                 = &#039;Wikipedia move-protected user and user talk pages&#039;,&lt;br /&gt;
	[&#039;all|all|all|autoconfirmed|autoreview&#039;]    = &#039;Wikipedia pending changes protected pages&#039;,&lt;br /&gt;
	[&#039;all|file|all|all|upload&#039;]                 = &#039;Wikipedia upload-protected files&#039;,&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Expiry category config&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- This table configures the expiry category behaviour for each protection&lt;br /&gt;
-- action.&lt;br /&gt;
-- * If set to true, setting that action will always categorise the page if&lt;br /&gt;
--   an expiry parameter is not set.&lt;br /&gt;
-- * If set to false, setting that action will never categorise the page.&lt;br /&gt;
-- * If set to nil, the module will categorise the page if:&lt;br /&gt;
--   1) an expiry parameter is not set, and&lt;br /&gt;
--   2) a reason is provided, and&lt;br /&gt;
--   3) the specified reason is not blacklisted in the reasonsWithoutExpiryCheck&lt;br /&gt;
--      table.&lt;br /&gt;
&lt;br /&gt;
expiryCheckActions = {&lt;br /&gt;
	edit = nil,&lt;br /&gt;
	move = false,&lt;br /&gt;
	autoreview = true,&lt;br /&gt;
	upload = false&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
reasonsWithoutExpiryCheck = {&lt;br /&gt;
	blp = true,&lt;br /&gt;
	template = true,&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Pagetypes&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- This table produces the page types available with the ${PAGETYPE} parameter.&lt;br /&gt;
-- Keys are namespace numbers, or the string &amp;quot;default&amp;quot; for the default value.&lt;br /&gt;
pagetypes = {&lt;br /&gt;
	[0] = &#039;article&#039;,&lt;br /&gt;
	[6] = &#039;file&#039;,&lt;br /&gt;
	[10] = &#039;template&#039;,&lt;br /&gt;
	[14] = &#039;category&#039;,&lt;br /&gt;
	[828] = &#039;module&#039;,&lt;br /&gt;
	default = &#039;page&#039;&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Strings marking indefinite protection&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- This table contains values passed to the expiry parameter that mean the page&lt;br /&gt;
-- is protected indefinitely.&lt;br /&gt;
indefStrings = {&lt;br /&gt;
	[&#039;indef&#039;] = true,&lt;br /&gt;
	[&#039;indefinite&#039;] = true,&lt;br /&gt;
	[&#039;indefinitely&#039;] = true,&lt;br /&gt;
	[&#039;infinite&#039;] = true,&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Group hierarchy&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- This table maps each group to all groups that have a superset of the original&lt;br /&gt;
-- group&#039;s page editing permissions.&lt;br /&gt;
hierarchy = {&lt;br /&gt;
	sysop = {},&lt;br /&gt;
	reviewer = {&#039;sysop&#039;},&lt;br /&gt;
	filemover = {&#039;sysop&#039;},&lt;br /&gt;
	templateeditor = {&#039;sysop&#039;},&lt;br /&gt;
	extendedconfirmed = {&#039;sysop&#039;},&lt;br /&gt;
	autoconfirmed = {&#039;reviewer&#039;, &#039;filemover&#039;, &#039;templateeditor&#039;, &#039;extendedconfirmed&#039;},&lt;br /&gt;
	user = {&#039;autoconfirmed&#039;},&lt;br /&gt;
	[&#039;*&#039;] = {&#039;user&#039;}&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Wrapper templates and their default arguments&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- This table contains wrapper templates used with the module, and their&lt;br /&gt;
-- default arguments. Templates specified in this table should contain the&lt;br /&gt;
-- following invocation, and no other template content:&lt;br /&gt;
--&lt;br /&gt;
-- {{#invoke:Protection banner|main}}&lt;br /&gt;
--&lt;br /&gt;
-- If other content is desired, it can be added between&lt;br /&gt;
-- &amp;lt;noinclude&amp;gt;...&amp;lt;/noinclude&amp;gt; tags.&lt;br /&gt;
--&lt;br /&gt;
-- When a user calls one of these wrapper templates, they will use the&lt;br /&gt;
-- default arguments automatically. However, users can override any of the&lt;br /&gt;
-- arguments.&lt;br /&gt;
wrappers = {&lt;br /&gt;
	[&#039;Template:Pp&#039;]                         = {},&lt;br /&gt;
	[&#039;Template:Protection padlock&#039;]         = {},&lt;br /&gt;
	[&#039;Template:Pp-extended&#039;]                = {&#039;ecp&#039;},&lt;br /&gt;
	[&#039;Template:Pp-blp&#039;]                     = {&#039;blp&#039;},&lt;br /&gt;
	-- we don&#039;t need Template:Pp-create&lt;br /&gt;
	[&#039;Template:Pp-dispute&#039;]                 = {&#039;dispute&#039;},&lt;br /&gt;
	[&#039;Template:Pp-main-page&#039;]               = {&#039;mainpage&#039;},&lt;br /&gt;
	[&#039;Template:Pp-move&#039;]                    = {action = &#039;move&#039;, catonly = &#039;yes&#039;},&lt;br /&gt;
	[&#039;Template:Pp-move-dispute&#039;]            = {&#039;dispute&#039;, action = &#039;move&#039;, catonly = &#039;yes&#039;},&lt;br /&gt;
	-- we don&#039;t need Template:Pp-move-indef&lt;br /&gt;
	[&#039;Template:Pp-move-vandalism&#039;]          = {&#039;vandalism&#039;, action = &#039;move&#039;, catonly = &#039;yes&#039;},&lt;br /&gt;
	[&#039;Template:Pp-office&#039;]                  = {&#039;office&#039;},&lt;br /&gt;
	[&#039;Template:Pp-office-dmca&#039;]             = {&#039;dmca&#039;},&lt;br /&gt;
	[&#039;Template:Pp-pc&#039;]                      = {action = &#039;autoreview&#039;, small = true},&lt;br /&gt;
	[&#039;Template:Pp-pc1&#039;]                     = {action = &#039;autoreview&#039;, small = true},&lt;br /&gt;
	[&#039;Template:Pp-reset&#039;]                   = {&#039;reset&#039;},&lt;br /&gt;
	[&#039;Template:Pp-semi-indef&#039;]              = {small = true},&lt;br /&gt;
	[&#039;Template:Pp-sock&#039;]                    = {&#039;sock&#039;},&lt;br /&gt;
	[&#039;Template:Pp-template&#039;]                = {&#039;template&#039;, small = true},&lt;br /&gt;
	[&#039;Template:Pp-upload&#039;]                  = {action = &#039;upload&#039;},&lt;br /&gt;
	[&#039;Template:Pp-usertalk&#039;]                = {&#039;usertalk&#039;},&lt;br /&gt;
	[&#039;Template:Pp-vandalism&#039;]               = {&#039;vandalism&#039;},&lt;br /&gt;
},&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- &lt;br /&gt;
--                                 MESSAGES&lt;br /&gt;
-- &lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
msg = {&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Intro blurb and intro fragment&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- These messages specify what is produced by the ${INTROBLURB} and&lt;br /&gt;
-- ${INTROFRAGMENT} parameters. If the protection is temporary they use the&lt;br /&gt;
-- intro-blurb-expiry or intro-fragment-expiry, and if not they use&lt;br /&gt;
-- intro-blurb-noexpiry or intro-fragment-noexpiry.&lt;br /&gt;
-- It is possible to use banner parameters in these messages.&lt;br /&gt;
[&#039;intro-blurb-expiry&#039;] = &#039;${PROTECTIONBLURB} until ${EXPIRY}.&#039;,&lt;br /&gt;
[&#039;intro-blurb-noexpiry&#039;] = &#039;${PROTECTIONBLURB}.&#039;,&lt;br /&gt;
[&#039;intro-fragment-expiry&#039;] = &#039;${PROTECTIONBLURB} until ${EXPIRY},&#039;,&lt;br /&gt;
[&#039;intro-fragment-noexpiry&#039;] = &#039;${PROTECTIONBLURB}&#039;,&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Tooltip blurb&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- These messages specify what is produced by the ${TOOLTIPBLURB} parameter.&lt;br /&gt;
-- If the protection is temporary the tooltip-blurb-expiry message is used, and&lt;br /&gt;
-- if not the tooltip-blurb-noexpiry message is used.&lt;br /&gt;
-- It is possible to use banner parameters in these messages.&lt;br /&gt;
[&#039;tooltip-blurb-expiry&#039;] = &#039;This ${PAGETYPE} is ${PROTECTIONLEVEL} until ${EXPIRY}.&#039;,&lt;br /&gt;
[&#039;tooltip-blurb-noexpiry&#039;] = &#039;This ${PAGETYPE} is ${PROTECTIONLEVEL}.&#039;,&lt;br /&gt;
[&#039;tooltip-fragment-expiry&#039;] = &#039;This ${PAGETYPE} is ${PROTECTIONLEVEL} until ${EXPIRY},&#039;,&lt;br /&gt;
[&#039;tooltip-fragment-noexpiry&#039;] = &#039;This ${PAGETYPE} is ${PROTECTIONLEVEL}&#039;,&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Special explanation blurb&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- An explanation blurb for pages that cannot be unprotected, e.g. for pages&lt;br /&gt;
-- in the MediaWiki namespace.&lt;br /&gt;
-- It is possible to use banner parameters in this message.&lt;br /&gt;
[&#039;explanation-blurb-nounprotect&#039;] = &#039;See the [[Wikipedia:Protection policy|&#039;&lt;br /&gt;
	.. &#039;protection policy]] and ${PROTECTIONLOG} for more details.&#039;&lt;br /&gt;
	.. &#039; Please discuss any changes on the ${TALKPAGE}; you&#039;&lt;br /&gt;
	.. &#039; may ${EDITREQUEST} to ask an&#039;&lt;br /&gt;
	.. &#039; [[Wikipedia:Administrators|administrator]] to make an edit if it&#039;&lt;br /&gt;
	.. &#039; is [[Help:Minor edit#When to mark an edit as a minor edit&#039;&lt;br /&gt;
	.. &#039;|uncontroversial]] or supported by [[Wikipedia:Consensus&#039;&lt;br /&gt;
	.. &#039;|consensus]].&#039;,&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Protection log display values&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- These messages determine the display values for the protection log link&lt;br /&gt;
-- or the pending changes log link produced by the ${PROTECTIONLOG} parameter.&lt;br /&gt;
-- It is possible to use banner parameters in these messages.&lt;br /&gt;
[&#039;protection-log-display&#039;] = &#039;protection log&#039;,&lt;br /&gt;
[&#039;pc-log-display&#039;] = &#039;pending changes log&#039;,&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Current version display values&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- These messages determine the display values for the page history link&lt;br /&gt;
-- or the move log link produced by the ${CURRENTVERSION} parameter.&lt;br /&gt;
-- It is possible to use banner parameters in these messages.&lt;br /&gt;
[&#039;current-version-move-display&#039;] = &#039;current title&#039;,&lt;br /&gt;
[&#039;current-version-edit-display&#039;] = &#039;current version&#039;,&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Talk page&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- This message determines the display value of the talk page link produced&lt;br /&gt;
-- with the ${TALKPAGE} parameter.&lt;br /&gt;
-- It is possible to use banner parameters in this message.&lt;br /&gt;
[&#039;talk-page-link-display&#039;] = &#039;talk page&#039;,&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Edit requests&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- This message determines the display value of the edit request link produced&lt;br /&gt;
-- with the ${EDITREQUEST} parameter.&lt;br /&gt;
-- It is possible to use banner parameters in this message.&lt;br /&gt;
[&#039;edit-request-display&#039;] = &#039;submit an edit request&#039;,&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Expiry date format&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- This is the format for the blurb expiry date. It should be valid input for&lt;br /&gt;
-- the first parameter of the #time parser function.&lt;br /&gt;
[&#039;expiry-date-format&#039;] = &#039;F j, Y &amp;quot;at&amp;quot; H:i e&#039;,&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Tracking categories&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- These messages determine which tracking categories the module outputs.&lt;br /&gt;
[&#039;tracking-category-incorrect&#039;] = &#039;Wikipedia pages with incorrect protection templates&#039;,&lt;br /&gt;
[&#039;tracking-category-template&#039;] = &#039;Wikipedia template-protected pages other than templates and modules&#039;,&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Images&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- These are images that are not defined by their protection action and protection level.&lt;br /&gt;
[&#039;image-filename-indef&#039;] = &#039;Full-protection-shackle.svg&#039;,&lt;br /&gt;
[&#039;image-filename-default&#039;] = &#039;Transparent.gif&#039;,&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- End messages&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- End configuration&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Jasper</name></author>
	</entry>
	<entry>
		<id>https://wiki.852r.org/index.php?title=Module:Protection_banner&amp;diff=3858</id>
		<title>Module:Protection banner</title>
		<link rel="alternate" type="text/html" href="https://wiki.852r.org/index.php?title=Module:Protection_banner&amp;diff=3858"/>
		<updated>2026-08-06T10:46:18Z</updated>

		<summary type="html">&lt;p&gt;Jasper: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- This module implements {{pp-meta}} and its daughter templates such as&lt;br /&gt;
-- {{pp-dispute}}, {{pp-vandalism}} and {{pp-sock}}.&lt;br /&gt;
&lt;br /&gt;
-- Initialise necessary modules.&lt;br /&gt;
require(&#039;strict&#039;)&lt;br /&gt;
local makeFileLink = require(&#039;Module:File link&#039;)._main&lt;br /&gt;
local effectiveProtectionLevel = require(&#039;Module:Effective protection level&#039;)._main&lt;br /&gt;
local effectiveProtectionExpiry = require(&#039;Module:Effective protection expiry&#039;)._main&lt;br /&gt;
local yesno = require(&#039;Module:Yesno&#039;)&lt;br /&gt;
&lt;br /&gt;
-- Lazily initialise modules and objects we don&#039;t always need.&lt;br /&gt;
local getArgs, makeMessageBox, lang&lt;br /&gt;
&lt;br /&gt;
-- Set constants.&lt;br /&gt;
local CONFIG_MODULE = &#039;Module:Protection banner/config&#039;&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Helper functions&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local function makeCategoryLink(cat, sort)&lt;br /&gt;
	if cat then&lt;br /&gt;
		return string.format(&lt;br /&gt;
			&#039;[[%s:%s|%s]]&#039;,&lt;br /&gt;
			mw.site.namespaces[14].name,&lt;br /&gt;
			cat,&lt;br /&gt;
			sort&lt;br /&gt;
		)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Validation function for the expiry and the protection date&lt;br /&gt;
local function validateDate(dateString, dateType)&lt;br /&gt;
	if not lang then&lt;br /&gt;
		lang = mw.language.getContentLanguage()&lt;br /&gt;
	end&lt;br /&gt;
	local success, result = pcall(lang.formatDate, lang, &#039;U&#039;, dateString)&lt;br /&gt;
	if success then&lt;br /&gt;
		result = tonumber(result)&lt;br /&gt;
		if result then&lt;br /&gt;
			return result&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	error(string.format(&lt;br /&gt;
		&#039;invalid %s: %s&#039;,&lt;br /&gt;
		dateType,&lt;br /&gt;
		tostring(dateString)&lt;br /&gt;
	), 4)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function makeFullUrl(page, query, display)&lt;br /&gt;
	return string.format(&lt;br /&gt;
		&#039;[%s %s]&#039;,&lt;br /&gt;
		tostring(mw.uri.fullUrl(page, query)),&lt;br /&gt;
		display&lt;br /&gt;
	)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Given a directed graph formatted as node -&amp;gt; table of direct successors,&lt;br /&gt;
-- get a table of all nodes reachable from a given node (though always&lt;br /&gt;
-- including the given node).&lt;br /&gt;
local function getReachableNodes(graph, start)&lt;br /&gt;
	local toWalk, retval = {[start] = true}, {}&lt;br /&gt;
	while true do&lt;br /&gt;
		-- Can&#039;t use pairs() since we&#039;re adding and removing things as we&#039;re iterating&lt;br /&gt;
		local k = next(toWalk) -- This always gets the &amp;quot;first&amp;quot; key&lt;br /&gt;
		if k == nil then&lt;br /&gt;
			return retval&lt;br /&gt;
		end&lt;br /&gt;
		toWalk[k] = nil&lt;br /&gt;
		retval[k] = true&lt;br /&gt;
		for _,v in ipairs(graph[k]) do&lt;br /&gt;
			if not retval[v] then&lt;br /&gt;
				toWalk[v] = true&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Protection class&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local Protection = {}&lt;br /&gt;
Protection.__index = Protection&lt;br /&gt;
&lt;br /&gt;
Protection.supportedActions = {&lt;br /&gt;
	edit = true,&lt;br /&gt;
	move = true,&lt;br /&gt;
	autoreview = true,&lt;br /&gt;
	upload = true&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Protection.bannerConfigFields = {&lt;br /&gt;
	&#039;text&#039;,&lt;br /&gt;
	&#039;explanation&#039;,&lt;br /&gt;
	&#039;tooltip&#039;,&lt;br /&gt;
	&#039;alt&#039;,&lt;br /&gt;
	&#039;link&#039;,&lt;br /&gt;
	&#039;image&#039;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function Protection.new(args, cfg, title)&lt;br /&gt;
	local obj = {}&lt;br /&gt;
	obj._cfg = cfg&lt;br /&gt;
	obj.title = title or mw.title.getCurrentTitle()&lt;br /&gt;
&lt;br /&gt;
	-- Set action&lt;br /&gt;
	if not args.action then&lt;br /&gt;
		obj.action = &#039;edit&#039;&lt;br /&gt;
	elseif Protection.supportedActions[args.action] then&lt;br /&gt;
		obj.action = args.action&lt;br /&gt;
	else&lt;br /&gt;
		error(string.format(&lt;br /&gt;
			&#039;invalid action: %s&#039;,&lt;br /&gt;
			tostring(args.action)&lt;br /&gt;
		), 3)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Set level&lt;br /&gt;
	obj.level = args.demolevel or effectiveProtectionLevel(obj.action, obj.title)&lt;br /&gt;
	if not obj.level or (obj.action == &#039;move&#039; and obj.level == &#039;autoconfirmed&#039;) then&lt;br /&gt;
		-- Users need to be autoconfirmed to move pages anyway, so treat&lt;br /&gt;
		-- semi-move-protected pages as unprotected.&lt;br /&gt;
		obj.level = &#039;*&#039;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Set expiry&lt;br /&gt;
	local effectiveExpiry = effectiveProtectionExpiry(obj.action, obj.title)&lt;br /&gt;
	if effectiveExpiry == &#039;infinity&#039; then&lt;br /&gt;
		obj.expiry = &#039;indef&#039;&lt;br /&gt;
	elseif effectiveExpiry ~= &#039;unknown&#039; then&lt;br /&gt;
		obj.expiry = validateDate(effectiveExpiry, &#039;expiry date&#039;)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Set reason&lt;br /&gt;
	if args[1] then&lt;br /&gt;
		obj.reason = mw.ustring.lower(args[1])&lt;br /&gt;
		if obj.reason:find(&#039;|&#039;) then&lt;br /&gt;
			error(&#039;reasons cannot contain the pipe character (&amp;quot;|&amp;quot;)&#039;, 3)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Set protection date&lt;br /&gt;
	if args.date then&lt;br /&gt;
		obj.protectionDate = validateDate(args.date, &#039;protection date&#039;)&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- Set banner config&lt;br /&gt;
	do&lt;br /&gt;
		obj.bannerConfig = {}&lt;br /&gt;
		local configTables = {}&lt;br /&gt;
		if cfg.banners[obj.action] then&lt;br /&gt;
			configTables[#configTables + 1] = cfg.banners[obj.action][obj.reason]&lt;br /&gt;
		end&lt;br /&gt;
		if cfg.defaultBanners[obj.action] then&lt;br /&gt;
			configTables[#configTables + 1] = cfg.defaultBanners[obj.action][obj.level]&lt;br /&gt;
			configTables[#configTables + 1] = cfg.defaultBanners[obj.action].default&lt;br /&gt;
		end&lt;br /&gt;
		configTables[#configTables + 1] = cfg.masterBanner&lt;br /&gt;
		for i, field in ipairs(Protection.bannerConfigFields) do&lt;br /&gt;
			for j, t in ipairs(configTables) do&lt;br /&gt;
				if t[field] then&lt;br /&gt;
					obj.bannerConfig[field] = t[field]&lt;br /&gt;
					break&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return setmetatable(obj, Protection)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Protection:isUserScript()&lt;br /&gt;
	-- Whether the page is a user JavaScript or CSS page.&lt;br /&gt;
	local title = self.title&lt;br /&gt;
	return title.namespace == 2 and (&lt;br /&gt;
		title.contentModel == &#039;javascript&#039; or title.contentModel == &#039;css&#039;&lt;br /&gt;
	)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Protection:isProtected()&lt;br /&gt;
	return self.level ~= &#039;*&#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Protection:shouldShowLock()&lt;br /&gt;
	-- Whether we should output a banner/padlock&lt;br /&gt;
	return self:isProtected() and not self:isUserScript()&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Whether this page needs a protection category.&lt;br /&gt;
Protection.shouldHaveProtectionCategory = Protection.shouldShowLock&lt;br /&gt;
&lt;br /&gt;
function Protection:isTemporary()&lt;br /&gt;
	return type(self.expiry) == &#039;number&#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Protection:makeProtectionCategory()&lt;br /&gt;
	if not self:shouldHaveProtectionCategory() then&lt;br /&gt;
		return &#039;&#039;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	local cfg = self._cfg&lt;br /&gt;
	local title = self.title&lt;br /&gt;
	&lt;br /&gt;
	-- Get the expiry key fragment.&lt;br /&gt;
	local expiryFragment&lt;br /&gt;
	if self.expiry == &#039;indef&#039; then&lt;br /&gt;
		expiryFragment = self.expiry&lt;br /&gt;
	elseif type(self.expiry) == &#039;number&#039; then&lt;br /&gt;
		expiryFragment = &#039;temp&#039;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Get the namespace key fragment.&lt;br /&gt;
	local namespaceFragment = cfg.categoryNamespaceKeys[title.namespace]&lt;br /&gt;
	if not namespaceFragment and title.namespace % 2 == 1 then&lt;br /&gt;
			namespaceFragment = &#039;talk&#039;&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Define the order that key fragments are tested in. This is done with an&lt;br /&gt;
	-- array of tables containing the value to be tested, along with its&lt;br /&gt;
	-- position in the cfg.protectionCategories table.&lt;br /&gt;
	local order = {&lt;br /&gt;
		{val = expiryFragment,    keypos = 1},&lt;br /&gt;
		{val = namespaceFragment, keypos = 2},&lt;br /&gt;
		{val = self.reason,       keypos = 3},&lt;br /&gt;
		{val = self.level,        keypos = 4},&lt;br /&gt;
		{val = self.action,       keypos = 5}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	--[[&lt;br /&gt;
	-- The old protection templates used an ad-hoc protection category system,&lt;br /&gt;
	-- with some templates prioritising namespaces in their categories, and&lt;br /&gt;
	-- others prioritising the protection reason. To emulate this in this module&lt;br /&gt;
	-- we use the config table cfg.reasonsWithNamespacePriority to set the&lt;br /&gt;
	-- reasons for which namespaces have priority over protection reason.&lt;br /&gt;
	-- If we are dealing with one of those reasons, move the namespace table to&lt;br /&gt;
	-- the end of the order table, i.e. give it highest priority. If not, the&lt;br /&gt;
	-- reason should have highest priority, so move that to the end of the table&lt;br /&gt;
	-- instead.&lt;br /&gt;
	--]]&lt;br /&gt;
	table.insert(order, table.remove(order, self.reason and cfg.reasonsWithNamespacePriority[self.reason] and 2 or 3))&lt;br /&gt;
 &lt;br /&gt;
	--[[&lt;br /&gt;
	-- Define the attempt order. Inactive subtables (subtables with nil &amp;quot;value&amp;quot;&lt;br /&gt;
	-- fields) are moved to the end, where they will later be given the key&lt;br /&gt;
	-- &amp;quot;all&amp;quot;. This is to cut down on the number of table lookups in&lt;br /&gt;
	-- cfg.protectionCategories, which grows exponentially with the number of&lt;br /&gt;
	-- non-nil keys. We keep track of the number of active subtables with the&lt;br /&gt;
	-- noActive parameter.&lt;br /&gt;
	--]]&lt;br /&gt;
	local noActive, attemptOrder&lt;br /&gt;
	do&lt;br /&gt;
		local active, inactive = {}, {}&lt;br /&gt;
		for i, t in ipairs(order) do&lt;br /&gt;
			if t.val then&lt;br /&gt;
				active[#active + 1] = t&lt;br /&gt;
			else&lt;br /&gt;
				inactive[#inactive + 1] = t&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		noActive = #active&lt;br /&gt;
		attemptOrder = active&lt;br /&gt;
		for i, t in ipairs(inactive) do&lt;br /&gt;
			attemptOrder[#attemptOrder + 1] = t&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
 &lt;br /&gt;
	--[[&lt;br /&gt;
	-- Check increasingly generic key combinations until we find a match. If a&lt;br /&gt;
	-- specific category exists for the combination of key fragments we are&lt;br /&gt;
	-- given, that match will be found first. If not, we keep trying different&lt;br /&gt;
	-- key fragment combinations until we match using the key&lt;br /&gt;
	-- &amp;quot;all-all-all-all-all&amp;quot;.&lt;br /&gt;
	--&lt;br /&gt;
	-- To generate the keys, we index the key subtables using a binary matrix&lt;br /&gt;
	-- with indexes i and j. j is only calculated up to the number of active&lt;br /&gt;
	-- subtables. For example, if there were three active subtables, the matrix&lt;br /&gt;
	-- would look like this, with 0 corresponding to the key fragment &amp;quot;all&amp;quot;, and&lt;br /&gt;
	-- 1 corresponding to other key fragments.&lt;br /&gt;
	-- &lt;br /&gt;
	--   j 1  2  3&lt;br /&gt;
	-- i  &lt;br /&gt;
	-- 1   1  1  1&lt;br /&gt;
	-- 2   0  1  1&lt;br /&gt;
	-- 3   1  0  1&lt;br /&gt;
	-- 4   0  0  1&lt;br /&gt;
	-- 5   1  1  0&lt;br /&gt;
	-- 6   0  1  0&lt;br /&gt;
	-- 7   1  0  0&lt;br /&gt;
	-- 8   0  0  0&lt;br /&gt;
	-- &lt;br /&gt;
	-- Values of j higher than the number of active subtables are set&lt;br /&gt;
	-- to the string &amp;quot;all&amp;quot;.&lt;br /&gt;
	--&lt;br /&gt;
	-- A key for cfg.protectionCategories is constructed for each value of i.&lt;br /&gt;
	-- The position of the value in the key is determined by the keypos field in&lt;br /&gt;
	-- each subtable.&lt;br /&gt;
	--]]&lt;br /&gt;
	local cats = cfg.protectionCategories&lt;br /&gt;
	for i = 1, 2^noActive do&lt;br /&gt;
		local key = {}&lt;br /&gt;
		for j, t in ipairs(attemptOrder) do&lt;br /&gt;
			if j &amp;gt; noActive then&lt;br /&gt;
				key[t.keypos] = &#039;all&#039;&lt;br /&gt;
			else&lt;br /&gt;
				local quotient = i / 2 ^ (j - 1)&lt;br /&gt;
				quotient = math.ceil(quotient)&lt;br /&gt;
				if quotient % 2 == 1 then&lt;br /&gt;
					key[t.keypos] = t.val&lt;br /&gt;
				else&lt;br /&gt;
					key[t.keypos] = &#039;all&#039;&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		key = table.concat(key, &#039;|&#039;)&lt;br /&gt;
		local attempt = cats[key]&lt;br /&gt;
		if attempt then&lt;br /&gt;
			return makeCategoryLink(attempt, title.text)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return &#039;&#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Protection:isIncorrect()&lt;br /&gt;
	if not self:shouldHaveProtectionCategory() then&lt;br /&gt;
		return true&lt;br /&gt;
	end&lt;br /&gt;
	if type(self.expiry) ~= &#039;number&#039; then&lt;br /&gt;
		return false&lt;br /&gt;
	end&lt;br /&gt;
	local expiry = os.date(&#039;*t&#039;, self.expiry)&lt;br /&gt;
	-- Avoid checking today.day or os.time(), unless close. https://phabricator.wikimedia.org/T416616&lt;br /&gt;
	local today = os.date(&#039;*t&#039;)&lt;br /&gt;
	return (expiry.year &amp;lt; today.year)&lt;br /&gt;
		or (expiry.year == today.year and expiry.month &amp;lt; today.month)&lt;br /&gt;
		or (expiry.year == today.year and expiry.month == today.month and expiry.day &amp;lt; today.day)&lt;br /&gt;
		or (expiry.year == today.year and expiry.month == today.month and expiry.day == today.day and self.expiry &amp;lt; os.time())&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Protection:isTemplateProtectedNonTemplate()&lt;br /&gt;
	local action, namespace = self.action, self.title.namespace&lt;br /&gt;
	return self.level == &#039;templateeditor&#039;&lt;br /&gt;
		and (&lt;br /&gt;
			(action ~= &#039;edit&#039; and action ~= &#039;move&#039;)&lt;br /&gt;
			or (namespace ~= 10 and namespace ~= 828)&lt;br /&gt;
		)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Protection:makeCategoryLinks()&lt;br /&gt;
	local msg = self._cfg.msg&lt;br /&gt;
	local ret = {self:makeProtectionCategory()}&lt;br /&gt;
	if self:isIncorrect() then&lt;br /&gt;
		ret[#ret + 1] = makeCategoryLink(&lt;br /&gt;
			msg[&#039;tracking-category-incorrect&#039;],&lt;br /&gt;
			self.title.text&lt;br /&gt;
		)&lt;br /&gt;
	end&lt;br /&gt;
	if self:isTemplateProtectedNonTemplate() then&lt;br /&gt;
		ret[#ret + 1] = makeCategoryLink(&lt;br /&gt;
			msg[&#039;tracking-category-template&#039;],&lt;br /&gt;
			self.title.text&lt;br /&gt;
		)&lt;br /&gt;
	end&lt;br /&gt;
	return table.concat(ret)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Blurb class&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local Blurb = {}&lt;br /&gt;
Blurb.__index = Blurb&lt;br /&gt;
&lt;br /&gt;
Blurb.bannerTextFields = {&lt;br /&gt;
	text = true,&lt;br /&gt;
	explanation = true,&lt;br /&gt;
	tooltip = true,&lt;br /&gt;
	alt = true,&lt;br /&gt;
	link = true&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function Blurb.new(protectionObj, args, cfg)&lt;br /&gt;
	return setmetatable({&lt;br /&gt;
		_cfg = cfg,&lt;br /&gt;
		_protectionObj = protectionObj,&lt;br /&gt;
		_args = args&lt;br /&gt;
	}, Blurb)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Private methods --&lt;br /&gt;
&lt;br /&gt;
function Blurb:_formatDate(num)&lt;br /&gt;
	-- Formats a Unix timestamp into dd Month, YYYY format.&lt;br /&gt;
	lang = lang or mw.language.getContentLanguage()&lt;br /&gt;
	local success, date = pcall(&lt;br /&gt;
		lang.formatDate,&lt;br /&gt;
		lang,&lt;br /&gt;
		self._cfg.msg[&#039;expiry-date-format&#039;] or &#039;j F Y&#039;,&lt;br /&gt;
		&#039;@&#039; .. tostring(num)&lt;br /&gt;
	)&lt;br /&gt;
	if success then&lt;br /&gt;
		return date&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Blurb:_getExpandedMessage(msgKey)&lt;br /&gt;
	return self:_substituteParameters(self._cfg.msg[msgKey])&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Blurb:_substituteParameters(msg)&lt;br /&gt;
	if not self._params then&lt;br /&gt;
		local parameterFuncs = {}&lt;br /&gt;
&lt;br /&gt;
		parameterFuncs.CURRENTVERSION     = self._makeCurrentVersionParameter&lt;br /&gt;
		parameterFuncs.EDITREQUEST        = self._makeEditRequestParameter&lt;br /&gt;
		parameterFuncs.EXPIRY             = self._makeExpiryParameter&lt;br /&gt;
		parameterFuncs.EXPLANATIONBLURB   = self._makeExplanationBlurbParameter&lt;br /&gt;
		parameterFuncs.IMAGELINK          = self._makeImageLinkParameter&lt;br /&gt;
		parameterFuncs.INTROBLURB         = self._makeIntroBlurbParameter&lt;br /&gt;
		parameterFuncs.INTROFRAGMENT      = self._makeIntroFragmentParameter&lt;br /&gt;
		parameterFuncs.PAGETYPE           = self._makePagetypeParameter&lt;br /&gt;
		parameterFuncs.PROTECTIONBLURB    = self._makeProtectionBlurbParameter&lt;br /&gt;
		parameterFuncs.PROTECTIONDATE     = self._makeProtectionDateParameter&lt;br /&gt;
		parameterFuncs.PROTECTIONLEVEL    = self._makeProtectionLevelParameter&lt;br /&gt;
		parameterFuncs.PROTECTIONLOG      = self._makeProtectionLogParameter&lt;br /&gt;
		parameterFuncs.TALKPAGE           = self._makeTalkPageParameter&lt;br /&gt;
		parameterFuncs.TOOLTIPBLURB       = self._makeTooltipBlurbParameter&lt;br /&gt;
		parameterFuncs.TOOLTIPFRAGMENT    = self._makeTooltipFragmentParameter&lt;br /&gt;
		parameterFuncs.VANDAL             = self._makeVandalTemplateParameter&lt;br /&gt;
		&lt;br /&gt;
		self._params = setmetatable({}, {&lt;br /&gt;
			__index = function (t, k)&lt;br /&gt;
				local param&lt;br /&gt;
				if parameterFuncs[k] then&lt;br /&gt;
					param = parameterFuncs[k](self)&lt;br /&gt;
				end&lt;br /&gt;
				param = param or &#039;&#039;&lt;br /&gt;
				t[k] = param&lt;br /&gt;
				return param&lt;br /&gt;
			end&lt;br /&gt;
		})&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	msg = msg:gsub(&#039;${(%u+)}&#039;, self._params)&lt;br /&gt;
	return msg&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Blurb:_makeCurrentVersionParameter()&lt;br /&gt;
	-- A link to the page history or the move log, depending on the kind of&lt;br /&gt;
	-- protection.&lt;br /&gt;
	local pagename = self._protectionObj.title.prefixedText&lt;br /&gt;
	if self._protectionObj.action == &#039;move&#039; then&lt;br /&gt;
		-- We need the move log link.&lt;br /&gt;
		return makeFullUrl(&lt;br /&gt;
			&#039;Special:Log&#039;,&lt;br /&gt;
			{type = &#039;move&#039;, page = pagename},&lt;br /&gt;
			self:_getExpandedMessage(&#039;current-version-move-display&#039;)&lt;br /&gt;
		)&lt;br /&gt;
	else&lt;br /&gt;
		-- We need the history link.&lt;br /&gt;
		return makeFullUrl(&lt;br /&gt;
			pagename,&lt;br /&gt;
			{action = &#039;history&#039;},&lt;br /&gt;
			self:_getExpandedMessage(&#039;current-version-edit-display&#039;)&lt;br /&gt;
		)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Blurb:_makeEditRequestParameter()&lt;br /&gt;
	local mEditRequest = require(&#039;Module:Submit an edit request&#039;)&lt;br /&gt;
	local action = self._protectionObj.action&lt;br /&gt;
	local level = self._protectionObj.level&lt;br /&gt;
	&lt;br /&gt;
	-- Get the edit request type.&lt;br /&gt;
	local requestType&lt;br /&gt;
	if action == &#039;edit&#039; then&lt;br /&gt;
		if level == &#039;autoconfirmed&#039; then&lt;br /&gt;
			requestType = &#039;semi&#039;&lt;br /&gt;
		elseif level == &#039;extendedconfirmed&#039; then&lt;br /&gt;
			requestType = &#039;extended&#039;&lt;br /&gt;
		elseif level == &#039;templateeditor&#039; then&lt;br /&gt;
			requestType = &#039;template&#039;&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	requestType = requestType or &#039;full&#039;&lt;br /&gt;
	&lt;br /&gt;
	-- Get the display value.&lt;br /&gt;
	local display = self:_getExpandedMessage(&#039;edit-request-display&#039;)&lt;br /&gt;
&lt;br /&gt;
	return mEditRequest._link{type = requestType, display = display}&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Blurb:_makeExpiryParameter()&lt;br /&gt;
	local expiry = self._protectionObj.expiry&lt;br /&gt;
	if type(expiry) == &#039;number&#039; then&lt;br /&gt;
		return self:_formatDate(expiry)&lt;br /&gt;
	else&lt;br /&gt;
		return expiry&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Blurb:_makeExplanationBlurbParameter()&lt;br /&gt;
	-- Cover special cases first.&lt;br /&gt;
	if self._protectionObj.title.namespace == 8 then&lt;br /&gt;
		-- MediaWiki namespace&lt;br /&gt;
		return self:_getExpandedMessage(&#039;explanation-blurb-nounprotect&#039;)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Get explanation blurb table keys&lt;br /&gt;
	local action = self._protectionObj.action&lt;br /&gt;
	local level = self._protectionObj.level&lt;br /&gt;
	local talkKey = self._protectionObj.title.isTalkPage and &#039;talk&#039; or &#039;subject&#039;&lt;br /&gt;
&lt;br /&gt;
	-- Find the message in the explanation blurb table and substitute any&lt;br /&gt;
	-- parameters.&lt;br /&gt;
	local explanations = self._cfg.explanationBlurbs&lt;br /&gt;
	local msg&lt;br /&gt;
	if explanations[action][level] and explanations[action][level][talkKey] then&lt;br /&gt;
		msg = explanations[action][level][talkKey]&lt;br /&gt;
	elseif explanations[action][level] and explanations[action][level].default then&lt;br /&gt;
		msg = explanations[action][level].default&lt;br /&gt;
	elseif explanations[action].default and explanations[action].default[talkKey] then&lt;br /&gt;
		msg = explanations[action].default[talkKey]&lt;br /&gt;
	elseif explanations[action].default and explanations[action].default.default then&lt;br /&gt;
		msg = explanations[action].default.default&lt;br /&gt;
	else&lt;br /&gt;
		error(string.format(&lt;br /&gt;
			&#039;could not find explanation blurb for action &amp;quot;%s&amp;quot;, level &amp;quot;%s&amp;quot; and talk key &amp;quot;%s&amp;quot;&#039;,&lt;br /&gt;
			action,&lt;br /&gt;
			level,&lt;br /&gt;
			talkKey&lt;br /&gt;
		), 8)&lt;br /&gt;
	end&lt;br /&gt;
	return self:_substituteParameters(msg)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Blurb:_makeImageLinkParameter()&lt;br /&gt;
	local imageLinks = self._cfg.imageLinks&lt;br /&gt;
	local action = self._protectionObj.action&lt;br /&gt;
	local level = self._protectionObj.level&lt;br /&gt;
	local msg&lt;br /&gt;
	if imageLinks[action][level] then&lt;br /&gt;
		msg = imageLinks[action][level]&lt;br /&gt;
	elseif imageLinks[action].default then&lt;br /&gt;
		msg = imageLinks[action].default&lt;br /&gt;
	else&lt;br /&gt;
		msg = imageLinks.edit.default&lt;br /&gt;
	end&lt;br /&gt;
	return self:_substituteParameters(msg)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Blurb:_makeIntroBlurbParameter()&lt;br /&gt;
	if self._protectionObj:isTemporary() then&lt;br /&gt;
		return self:_getExpandedMessage(&#039;intro-blurb-expiry&#039;)&lt;br /&gt;
	else&lt;br /&gt;
		return self:_getExpandedMessage(&#039;intro-blurb-noexpiry&#039;)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Blurb:_makeIntroFragmentParameter()&lt;br /&gt;
	if self._protectionObj:isTemporary() then&lt;br /&gt;
		return self:_getExpandedMessage(&#039;intro-fragment-expiry&#039;)&lt;br /&gt;
	else&lt;br /&gt;
		return self:_getExpandedMessage(&#039;intro-fragment-noexpiry&#039;)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Blurb:_makePagetypeParameter()&lt;br /&gt;
	local pagetypes = self._cfg.pagetypes&lt;br /&gt;
	return pagetypes[self._protectionObj.title.namespace]&lt;br /&gt;
		or pagetypes.default&lt;br /&gt;
		or error(&#039;no default pagetype defined&#039;, 8)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Blurb:_makeProtectionBlurbParameter()&lt;br /&gt;
	local protectionBlurbs = self._cfg.protectionBlurbs&lt;br /&gt;
	local action = self._protectionObj.action&lt;br /&gt;
	local level = self._protectionObj.level&lt;br /&gt;
	local msg&lt;br /&gt;
	if protectionBlurbs[action][level] then&lt;br /&gt;
		msg = protectionBlurbs[action][level]&lt;br /&gt;
	elseif protectionBlurbs[action].default then&lt;br /&gt;
		msg = protectionBlurbs[action].default&lt;br /&gt;
	elseif protectionBlurbs.edit.default then&lt;br /&gt;
		msg = protectionBlurbs.edit.default&lt;br /&gt;
	else&lt;br /&gt;
		error(&#039;no protection blurb defined for protectionBlurbs.edit.default&#039;, 8)&lt;br /&gt;
	end&lt;br /&gt;
	return self:_substituteParameters(msg)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Blurb:_makeProtectionDateParameter()&lt;br /&gt;
	local protectionDate = self._protectionObj.protectionDate&lt;br /&gt;
	if type(protectionDate) == &#039;number&#039; then&lt;br /&gt;
		return self:_formatDate(protectionDate)&lt;br /&gt;
	else&lt;br /&gt;
		return protectionDate&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Blurb:_makeProtectionLevelParameter()&lt;br /&gt;
	local protectionLevels = self._cfg.protectionLevels&lt;br /&gt;
	local action = self._protectionObj.action&lt;br /&gt;
	local level = self._protectionObj.level&lt;br /&gt;
	local msg&lt;br /&gt;
	if protectionLevels[action][level] then&lt;br /&gt;
		msg = protectionLevels[action][level]&lt;br /&gt;
	elseif protectionLevels[action].default then&lt;br /&gt;
		msg = protectionLevels[action].default&lt;br /&gt;
	elseif protectionLevels.edit.default then&lt;br /&gt;
		msg = protectionLevels.edit.default&lt;br /&gt;
	else&lt;br /&gt;
		error(&#039;no protection level defined for protectionLevels.edit.default&#039;, 8)&lt;br /&gt;
	end&lt;br /&gt;
	return self:_substituteParameters(msg)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Blurb:_makeProtectionLogParameter()&lt;br /&gt;
	local pagename = self._protectionObj.title.prefixedText&lt;br /&gt;
	if self._protectionObj.action == &#039;autoreview&#039; then&lt;br /&gt;
		-- We need the pending changes log.&lt;br /&gt;
		return makeFullUrl(&lt;br /&gt;
			&#039;Special:Log&#039;,&lt;br /&gt;
			{type = &#039;stable&#039;, page = pagename},&lt;br /&gt;
			self:_getExpandedMessage(&#039;pc-log-display&#039;)&lt;br /&gt;
		)&lt;br /&gt;
	else&lt;br /&gt;
		-- We need the protection log.&lt;br /&gt;
		return makeFullUrl(&lt;br /&gt;
			&#039;Special:Log&#039;,&lt;br /&gt;
			{type = &#039;protect&#039;, page = pagename},&lt;br /&gt;
			self:_getExpandedMessage(&#039;protection-log-display&#039;)&lt;br /&gt;
		)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Blurb:_makeTalkPageParameter()&lt;br /&gt;
	return string.format(&lt;br /&gt;
		&#039;[[%s:%s#%s|%s]]&#039;,&lt;br /&gt;
		mw.site.namespaces[self._protectionObj.title.namespace].talk.name,&lt;br /&gt;
		self._protectionObj.title.text,&lt;br /&gt;
		self._args.section or &#039;top&#039;,&lt;br /&gt;
		self:_getExpandedMessage(&#039;talk-page-link-display&#039;)&lt;br /&gt;
	)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Blurb:_makeTooltipBlurbParameter()&lt;br /&gt;
	if self._protectionObj:isTemporary() then&lt;br /&gt;
		return self:_getExpandedMessage(&#039;tooltip-blurb-expiry&#039;)&lt;br /&gt;
	else&lt;br /&gt;
		return self:_getExpandedMessage(&#039;tooltip-blurb-noexpiry&#039;)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Blurb:_makeTooltipFragmentParameter()&lt;br /&gt;
	if self._protectionObj:isTemporary() then&lt;br /&gt;
		return self:_getExpandedMessage(&#039;tooltip-fragment-expiry&#039;)&lt;br /&gt;
	else&lt;br /&gt;
		return self:_getExpandedMessage(&#039;tooltip-fragment-noexpiry&#039;)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Blurb:_makeVandalTemplateParameter()&lt;br /&gt;
	return mw.getCurrentFrame():expandTemplate{&lt;br /&gt;
		title=&amp;quot;vandal-m&amp;quot;,&lt;br /&gt;
		args={self._args.user or self._protectionObj.title.baseText}&lt;br /&gt;
	}&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
-- Public methods --&lt;br /&gt;
&lt;br /&gt;
function Blurb:makeBannerText(key)&lt;br /&gt;
	-- Validate input.&lt;br /&gt;
	if not key or not Blurb.bannerTextFields[key] then&lt;br /&gt;
		error(string.format(&lt;br /&gt;
			&#039;&amp;quot;%s&amp;quot; is not a valid banner config field&#039;,&lt;br /&gt;
			tostring(key)&lt;br /&gt;
		), 2)&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Generate the text.&lt;br /&gt;
	local msg = self._protectionObj.bannerConfig[key]&lt;br /&gt;
	if type(msg) == &#039;string&#039; then&lt;br /&gt;
		return self:_substituteParameters(msg)&lt;br /&gt;
	elseif type(msg) == &#039;function&#039; then&lt;br /&gt;
		msg = msg(self._protectionObj, self._args)&lt;br /&gt;
		if type(msg) ~= &#039;string&#039; then&lt;br /&gt;
			error(string.format(&lt;br /&gt;
				&#039;bad output from banner config function with key &amp;quot;%s&amp;quot;&#039;&lt;br /&gt;
					.. &#039; (expected string, got %s)&#039;,&lt;br /&gt;
				tostring(key),&lt;br /&gt;
				type(msg)&lt;br /&gt;
			), 4)&lt;br /&gt;
		end&lt;br /&gt;
		return self:_substituteParameters(msg)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- BannerTemplate class&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local BannerTemplate = {}&lt;br /&gt;
BannerTemplate.__index = BannerTemplate&lt;br /&gt;
&lt;br /&gt;
function BannerTemplate.new(protectionObj, cfg)&lt;br /&gt;
	local obj = {}&lt;br /&gt;
	obj._cfg = cfg&lt;br /&gt;
&lt;br /&gt;
	-- Set the image filename.&lt;br /&gt;
	local imageFilename = protectionObj.bannerConfig.image&lt;br /&gt;
	if imageFilename then&lt;br /&gt;
		obj._imageFilename = imageFilename&lt;br /&gt;
	else&lt;br /&gt;
		-- If an image filename isn&#039;t specified explicitly in the banner config,&lt;br /&gt;
		-- generate it from the protection status and the namespace.&lt;br /&gt;
		local action = protectionObj.action&lt;br /&gt;
		local level = protectionObj.level&lt;br /&gt;
		local namespace = protectionObj.title.namespace&lt;br /&gt;
		local reason = protectionObj.reason&lt;br /&gt;
		&lt;br /&gt;
		-- Deal with special cases first.&lt;br /&gt;
		if (&lt;br /&gt;
			namespace == 10&lt;br /&gt;
			or namespace == 828&lt;br /&gt;
			or reason and obj._cfg.indefImageReasons[reason]&lt;br /&gt;
			)&lt;br /&gt;
			and action == &#039;edit&#039;&lt;br /&gt;
			and level == &#039;sysop&#039;&lt;br /&gt;
			and not protectionObj:isTemporary()&lt;br /&gt;
		then&lt;br /&gt;
			-- Fully protected modules and templates get the special red &amp;quot;indef&amp;quot;&lt;br /&gt;
			-- padlock.&lt;br /&gt;
			obj._imageFilename = obj._cfg.msg[&#039;image-filename-indef&#039;]&lt;br /&gt;
		else&lt;br /&gt;
			-- Deal with regular protection types.&lt;br /&gt;
			local images = obj._cfg.images&lt;br /&gt;
			if images[action] then&lt;br /&gt;
				if images[action][level] then&lt;br /&gt;
					obj._imageFilename = images[action][level]&lt;br /&gt;
				elseif images[action].default then&lt;br /&gt;
					obj._imageFilename = images[action].default&lt;br /&gt;
				end&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	return setmetatable(obj, BannerTemplate)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function BannerTemplate:renderImage()&lt;br /&gt;
	local filename = self._imageFilename&lt;br /&gt;
		or self._cfg.msg[&#039;image-filename-default&#039;]&lt;br /&gt;
		or &#039;Transparent.gif&#039;&lt;br /&gt;
	return makeFileLink{&lt;br /&gt;
		file = filename,&lt;br /&gt;
		size = (self.imageWidth or 20) .. &#039;px&#039;,&lt;br /&gt;
		alt = self._imageAlt,&lt;br /&gt;
		link = self._imageLink,&lt;br /&gt;
		caption = self.imageCaption&lt;br /&gt;
	}&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Banner class&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local Banner = setmetatable({}, BannerTemplate)&lt;br /&gt;
Banner.__index = Banner&lt;br /&gt;
&lt;br /&gt;
function Banner.new(protectionObj, blurbObj, cfg)&lt;br /&gt;
	local obj = BannerTemplate.new(protectionObj, cfg) -- This doesn&#039;t need the blurb.&lt;br /&gt;
	obj.imageWidth = 40&lt;br /&gt;
	obj.imageCaption = blurbObj:makeBannerText(&#039;alt&#039;) -- Large banners use the alt text for the tooltip.&lt;br /&gt;
	obj._reasonText = blurbObj:makeBannerText(&#039;text&#039;)&lt;br /&gt;
	obj._explanationText = blurbObj:makeBannerText(&#039;explanation&#039;)&lt;br /&gt;
	obj._page = protectionObj.title.prefixedText -- Only makes a difference in testing.&lt;br /&gt;
	return setmetatable(obj, Banner)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Banner:__tostring()&lt;br /&gt;
	-- Renders the banner.&lt;br /&gt;
	makeMessageBox = makeMessageBox or require(&#039;Module:Message box&#039;).main&lt;br /&gt;
	local reasonText = self._reasonText or error(&#039;no reason text set&#039;, 2)&lt;br /&gt;
	local explanationText = self._explanationText&lt;br /&gt;
	local mbargs = {&lt;br /&gt;
		page = self._page,&lt;br /&gt;
		type = &#039;protection&#039;,&lt;br /&gt;
		image = self:renderImage(),&lt;br /&gt;
		text = string.format(&lt;br /&gt;
			&amp;quot;&#039;&#039;&#039;%s&#039;&#039;&#039;%s&amp;quot;,&lt;br /&gt;
			reasonText,&lt;br /&gt;
			explanationText and &#039;&amp;lt;br /&amp;gt;&#039; .. explanationText or &#039;&#039;&lt;br /&gt;
		)&lt;br /&gt;
	}&lt;br /&gt;
	return makeMessageBox(&#039;mbox&#039;, mbargs)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Padlock class&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local Padlock = setmetatable({}, BannerTemplate)&lt;br /&gt;
Padlock.__index = Padlock&lt;br /&gt;
&lt;br /&gt;
function Padlock.new(protectionObj, blurbObj, cfg)&lt;br /&gt;
	local obj = BannerTemplate.new(protectionObj, cfg) -- This doesn&#039;t need the blurb.&lt;br /&gt;
	obj.imageWidth = 20&lt;br /&gt;
	obj.imageCaption = blurbObj:makeBannerText(&#039;tooltip&#039;)&lt;br /&gt;
	obj._imageAlt = blurbObj:makeBannerText(&#039;alt&#039;)&lt;br /&gt;
	obj._imageLink = blurbObj:makeBannerText(&#039;link&#039;)&lt;br /&gt;
	obj._indicatorName = cfg.padlockIndicatorNames[protectionObj.action]&lt;br /&gt;
		or cfg.padlockIndicatorNames.default&lt;br /&gt;
		or &#039;pp-default&#039;&lt;br /&gt;
	return setmetatable(obj, Padlock)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function Padlock:__tostring()&lt;br /&gt;
	local frame = mw.getCurrentFrame()&lt;br /&gt;
	-- The nowiki tag helps prevent whitespace at the top of articles.&lt;br /&gt;
	return frame:extensionTag{name = &#039;nowiki&#039;} .. frame:extensionTag{&lt;br /&gt;
		name = &#039;indicator&#039;,&lt;br /&gt;
		args = {name = self._indicatorName},&lt;br /&gt;
		content = self:renderImage()&lt;br /&gt;
	}&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Exports&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
function p._exportClasses()&lt;br /&gt;
	-- This is used for testing purposes.&lt;br /&gt;
	return {&lt;br /&gt;
		Protection = Protection,&lt;br /&gt;
		Blurb = Blurb,&lt;br /&gt;
		BannerTemplate = BannerTemplate,&lt;br /&gt;
		Banner = Banner,&lt;br /&gt;
		Padlock = Padlock,&lt;br /&gt;
	}&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p._main(args, cfg, title)&lt;br /&gt;
	args = args or {}&lt;br /&gt;
	cfg = cfg or require(CONFIG_MODULE)&lt;br /&gt;
&lt;br /&gt;
	local protectionObj = Protection.new(args, cfg, title)&lt;br /&gt;
&lt;br /&gt;
	local ret = {}&lt;br /&gt;
&lt;br /&gt;
	-- If a page&#039;s edit protection is equally or more restrictive than its&lt;br /&gt;
	-- protection from some other action, then don&#039;t bother displaying anything&lt;br /&gt;
	-- for the other action (except categories).&lt;br /&gt;
	if not yesno(args.catonly) and (protectionObj.action == &#039;edit&#039; or&lt;br /&gt;
		args.demolevel or&lt;br /&gt;
		not getReachableNodes(&lt;br /&gt;
			cfg.hierarchy,&lt;br /&gt;
			protectionObj.level&lt;br /&gt;
		)[effectiveProtectionLevel(&#039;edit&#039;, protectionObj.title)])&lt;br /&gt;
	then&lt;br /&gt;
		-- Initialise the blurb object&lt;br /&gt;
		local blurbObj = Blurb.new(protectionObj, args, cfg)&lt;br /&gt;
	&lt;br /&gt;
		-- Render the banner&lt;br /&gt;
		if protectionObj:shouldShowLock() then&lt;br /&gt;
			ret[#ret + 1] = tostring(&lt;br /&gt;
				(yesno(args.small) and Padlock or Banner)&lt;br /&gt;
				.new(protectionObj, blurbObj, cfg)&lt;br /&gt;
			)&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Render the categories&lt;br /&gt;
	if yesno(args.category) ~= false then&lt;br /&gt;
		ret[#ret + 1] = protectionObj:makeCategoryLinks()&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	-- For arbitration enforcement, flagging [[WP:PIA]] pages to enable [[Special:AbuseFilter/1339]] to flag edits to them&lt;br /&gt;
	if protectionObj.level == &amp;quot;extendedconfirmed&amp;quot; then&lt;br /&gt;
		if require(&amp;quot;Module:TableTools&amp;quot;).inArray(protectionObj.title.talkPageTitle.categories, &amp;quot;Wikipedia pages subject to the extended confirmed restriction related to the Arab-Israeli conflict&amp;quot;) then&lt;br /&gt;
			ret[#ret + 1] = &amp;quot;&amp;lt;p class=&#039;PIA-flag&#039; style=&#039;display:none; visibility:hidden;&#039; title=&#039;This page is subject to the extended confirmed restriction related to the Arab-Israeli conflict.&#039;&amp;gt;&amp;lt;/p&amp;gt;&amp;quot;&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	&lt;br /&gt;
	return table.concat(ret)	&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.main(frame, cfg)&lt;br /&gt;
	cfg = cfg or require(CONFIG_MODULE)&lt;br /&gt;
&lt;br /&gt;
	-- Find default args, if any.&lt;br /&gt;
	local parent = frame.getParent and frame:getParent()&lt;br /&gt;
	local defaultArgs = parent and cfg.wrappers[parent:getTitle():gsub(&#039;/sandbox$&#039;, &#039;&#039;)]&lt;br /&gt;
&lt;br /&gt;
	-- Find user args, and use the parent frame if we are being called from a&lt;br /&gt;
	-- wrapper template.&lt;br /&gt;
	getArgs = getArgs or require(&#039;Module:Arguments&#039;).getArgs&lt;br /&gt;
	local userArgs = getArgs(frame, {&lt;br /&gt;
		parentOnly = defaultArgs,&lt;br /&gt;
		frameOnly = not defaultArgs&lt;br /&gt;
	})&lt;br /&gt;
&lt;br /&gt;
	-- Build the args table. User-specified args overwrite default args.&lt;br /&gt;
	local args = {}&lt;br /&gt;
	for k, v in pairs(defaultArgs or {}) do&lt;br /&gt;
		args[k] = v&lt;br /&gt;
	end&lt;br /&gt;
	for k, v in pairs(userArgs) do&lt;br /&gt;
		args[k] = v&lt;br /&gt;
	end&lt;br /&gt;
	return p._main(args, cfg)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Jasper</name></author>
	</entry>
	<entry>
		<id>https://wiki.852r.org/index.php?title=Module:Effective_protection_level&amp;diff=3856</id>
		<title>Module:Effective protection level</title>
		<link rel="alternate" type="text/html" href="https://wiki.852r.org/index.php?title=Module:Effective_protection_level&amp;diff=3856"/>
		<updated>2026-08-06T10:46:18Z</updated>

		<summary type="html">&lt;p&gt;Jasper: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;local p = {}&lt;br /&gt;
-- Returns the permission required to perform a given action on a given title.&lt;br /&gt;
-- If no title is specified, the title of the page being displayed is used.&lt;br /&gt;
function p._main(action, pagename)&lt;br /&gt;
	local title&lt;br /&gt;
	if type(pagename) == &#039;table&#039; and pagename.prefixedText then&lt;br /&gt;
		title = pagename&lt;br /&gt;
	elseif pagename then&lt;br /&gt;
		title = mw.title.new(pagename)&lt;br /&gt;
	else&lt;br /&gt;
		title = mw.title.getCurrentTitle()&lt;br /&gt;
	end&lt;br /&gt;
	pagename = title.prefixedText&lt;br /&gt;
	if action == &#039;autoreview&#039; then&lt;br /&gt;
		local level = mw.ext.FlaggedRevs.getStabilitySettings(title)&lt;br /&gt;
		level = level and level.autoreview&lt;br /&gt;
		if level == &#039;review&#039; then&lt;br /&gt;
			return &#039;reviewer&#039;&lt;br /&gt;
		elseif level ~= &#039;&#039; then&lt;br /&gt;
			return level&lt;br /&gt;
		else&lt;br /&gt;
			return nil -- not &#039;*&#039;. a page not being PC-protected is distinct from it being PC-protected with anyone able to review. also not &#039;&#039;, as that would mean PC-protected but nobody can review&lt;br /&gt;
		end&lt;br /&gt;
	elseif action ~= &#039;edit&#039; and action ~= &#039;move&#039; and action ~= &#039;create&#039; and action ~= &#039;upload&#039; and action ~= &#039;undelete&#039; then&lt;br /&gt;
		error( &#039;First parameter must be one of edit, move, create, upload, undelete, autoreview&#039;, 2 )&lt;br /&gt;
	end&lt;br /&gt;
	if title.namespace == 8 then -- MediaWiki namespace&lt;br /&gt;
		if title.text:sub(-3) == &#039;.js&#039; or title.text:sub(-4) == &#039;.css&#039; or title.contentModel == &#039;javascript&#039; or title.contentModel == &#039;css&#039; then -- site JS or CSS page&lt;br /&gt;
			return &#039;interfaceadmin&#039;&lt;br /&gt;
		elseif title.baseText == &amp;quot;Gadgets-definition&amp;quot; then&lt;br /&gt;
			return &#039;interfaceadmin&#039;&lt;br /&gt;
		else -- any non-JS/CSS MediaWiki page&lt;br /&gt;
			return &#039;sysop&#039;&lt;br /&gt;
		end&lt;br /&gt;
	elseif title.namespace == 2 and title.isSubpage then&lt;br /&gt;
		if title.contentModel == &#039;javascript&#039; or title.contentModel == &#039;css&#039; then -- user JS or CSS page&lt;br /&gt;
			return &#039;interfaceadmin&#039;&lt;br /&gt;
		elseif title.contentModel == &#039;json&#039; then -- user JSON page&lt;br /&gt;
			return &#039;sysop&#039;&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if action == &#039;undelete&#039; then&lt;br /&gt;
		return &#039;sysop&#039;&lt;br /&gt;
	end&lt;br /&gt;
	local level = title.protectionLevels[action] and title.protectionLevels[action][1]&lt;br /&gt;
	if level == &#039;sysop&#039; or level == &#039;editprotected&#039; then&lt;br /&gt;
		return &#039;sysop&#039;&lt;br /&gt;
	elseif title.cascadingProtection.restrictions[action] and title.cascadingProtection.restrictions[action][1] then -- used by a cascading-protected page&lt;br /&gt;
		return &#039;sysop&#039;&lt;br /&gt;
	elseif level == &#039;templateeditor&#039; then&lt;br /&gt;
		return &#039;templateeditor&#039;&lt;br /&gt;
	elseif action == &#039;move&#039; then&lt;br /&gt;
		local blacklistentry = mw.ext.TitleBlacklist.test(&#039;edit&#039;, pagename) -- Testing action edit is correct, since this is for the source page. The target page name gets tested with action move.&lt;br /&gt;
		if blacklistentry and not blacklistentry.params.autoconfirmed then&lt;br /&gt;
			return &#039;templateeditor&#039;&lt;br /&gt;
		elseif title.namespace == 6 then&lt;br /&gt;
			return &#039;filemover&#039;&lt;br /&gt;
		elseif level == &#039;extendedconfirmed&#039; then&lt;br /&gt;
			return &#039;extendedconfirmed&#039;&lt;br /&gt;
		else&lt;br /&gt;
			return &#039;autoconfirmed&#039;&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	local blacklistentry = mw.ext.TitleBlacklist.test(action, pagename)&lt;br /&gt;
	if blacklistentry then&lt;br /&gt;
		if not blacklistentry.params.autoconfirmed then&lt;br /&gt;
			return &#039;templateeditor&#039;&lt;br /&gt;
		elseif level == &#039;extendedconfirmed&#039; then&lt;br /&gt;
			return &#039;extendedconfirmed&#039;&lt;br /&gt;
		else&lt;br /&gt;
			return &#039;autoconfirmed&#039;&lt;br /&gt;
		end&lt;br /&gt;
	elseif level == &#039;editsemiprotected&#039; then -- create-semiprotected pages return this for some reason&lt;br /&gt;
		return &#039;autoconfirmed&#039;&lt;br /&gt;
	elseif level then&lt;br /&gt;
		return level&lt;br /&gt;
	elseif action == &#039;upload&#039; then&lt;br /&gt;
		return &#039;autoconfirmed&#039;&lt;br /&gt;
	elseif action == &#039;create&#039; and title.namespace % 2 == 0 and title.namespace ~= 118 then -- You need to be registered, but not autoconfirmed, to create non-talk pages other than drafts&lt;br /&gt;
		if title.namespace == 0 then&lt;br /&gt;
			return &#039;autoconfirmed&#039; -- Per [[WP:ACPERM]], you need to be autoconfirmed to create pages in mainspace&lt;br /&gt;
		end&lt;br /&gt;
		return &#039;user&#039;&lt;br /&gt;
	else&lt;br /&gt;
		return &#039;*&#039;&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
setmetatable(p, { __index = function(t, k)&lt;br /&gt;
	return function(frame)&lt;br /&gt;
		return t._main(k, frame.args[1])&lt;br /&gt;
	end&lt;br /&gt;
end })&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Jasper</name></author>
	</entry>
	<entry>
		<id>https://wiki.852r.org/index.php?title=Template:Xt&amp;diff=3854</id>
		<title>Template:Xt</title>
		<link rel="alternate" type="text/html" href="https://wiki.852r.org/index.php?title=Template:Xt&amp;diff=3854"/>
		<updated>2026-08-06T10:46:18Z</updated>

		<summary type="html">&lt;p&gt;Jasper: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Template:Example text]]&lt;br /&gt;
&lt;br /&gt;
{{Redirect category shell|&lt;br /&gt;
{{R from move}}&lt;br /&gt;
}}&lt;/div&gt;</summary>
		<author><name>Jasper</name></author>
	</entry>
	<entry>
		<id>https://wiki.852r.org/index.php?title=Module:Template_link_general&amp;diff=3852</id>
		<title>Module:Template link general</title>
		<link rel="alternate" type="text/html" href="https://wiki.852r.org/index.php?title=Module:Template_link_general&amp;diff=3852"/>
		<updated>2026-08-06T10:46:18Z</updated>

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

		<summary type="html">&lt;p&gt;Jasper: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- This module contains the blacklist used by [[Module:Category handler]].&lt;br /&gt;
-- Pages that match Lua patterns in this list will not be categorised unless&lt;br /&gt;
-- categorisation is explicitly requested.&lt;br /&gt;
&lt;br /&gt;
return {&lt;br /&gt;
	&#039;^Main Page$&#039;, -- don&#039;t categorise the main page.&lt;br /&gt;
&lt;br /&gt;
	-- Don&#039;t categorise the following pages or their subpages.&lt;br /&gt;
	-- &amp;quot;%f[/\0]&amp;quot; matches if the next character is &amp;quot;/&amp;quot; or the end of the string.&lt;br /&gt;
	&#039;^Wikipedia:Cascade%-protected items%f[/\0]&#039;,&lt;br /&gt;
	&#039;^User:UBX%f[/\0]&#039;, -- The userbox &amp;quot;template&amp;quot; space.&lt;br /&gt;
	&#039;^User talk:UBX%f[/\0]&#039;,&lt;br /&gt;
&lt;br /&gt;
	-- Don&#039;t categorise subpages of these pages, but allow&lt;br /&gt;
	-- categorisation of the base page.&lt;br /&gt;
	&#039;^Wikipedia:Template index/.*$&#039;,&lt;br /&gt;
&lt;br /&gt;
	-- Don&#039;t categorise archives.&lt;br /&gt;
	&#039;/[aA]rchive&#039;,&lt;br /&gt;
	&amp;quot;^Wikipedia:Administrators&#039; noticeboard/IncidentArchive%d+$&amp;quot;,&lt;br /&gt;
}&lt;/div&gt;</summary>
		<author><name>Jasper</name></author>
	</entry>
	<entry>
		<id>https://wiki.852r.org/index.php?title=Module:Category_handler/shared&amp;diff=3848</id>
		<title>Module:Category handler/shared</title>
		<link rel="alternate" type="text/html" href="https://wiki.852r.org/index.php?title=Module:Category_handler/shared&amp;diff=3848"/>
		<updated>2026-08-06T10:46:18Z</updated>

		<summary type="html">&lt;p&gt;Jasper: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- This module contains shared functions used by [[Module:Category handler]]&lt;br /&gt;
-- and its submodules.&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
function p.matchesBlacklist(page, blacklist)&lt;br /&gt;
	for i, pattern in ipairs(blacklist) do&lt;br /&gt;
		local match = mw.ustring.match(page, pattern)&lt;br /&gt;
		if match 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;
function p.getParamMappings(useLoadData)&lt;br /&gt;
	local dataPage = &#039;Module:Namespace detect/data&#039;&lt;br /&gt;
	if useLoadData then&lt;br /&gt;
		return mw.loadData(dataPage).mappings&lt;br /&gt;
	else&lt;br /&gt;
		return require(dataPage).mappings&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.getNamespaceParameters(titleObj, mappings)&lt;br /&gt;
	-- We don&#039;t use title.nsText for the namespace name because it adds&lt;br /&gt;
	-- underscores.&lt;br /&gt;
	local mappingsKey&lt;br /&gt;
	if titleObj.isTalkPage then&lt;br /&gt;
		mappingsKey = &#039;talk&#039;&lt;br /&gt;
	else&lt;br /&gt;
		mappingsKey = mw.site.namespaces[titleObj.namespace].name&lt;br /&gt;
	end&lt;br /&gt;
	mappingsKey = mw.ustring.lower(mappingsKey)&lt;br /&gt;
	return mappings[mappingsKey] or {}&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Jasper</name></author>
	</entry>
	<entry>
		<id>https://wiki.852r.org/index.php?title=Module:Category_handler/config&amp;diff=3846</id>
		<title>Module:Category handler/config</title>
		<link rel="alternate" type="text/html" href="https://wiki.852r.org/index.php?title=Module:Category_handler/config&amp;diff=3846"/>
		<updated>2026-08-06T10:46:18Z</updated>

		<summary type="html">&lt;p&gt;Jasper: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;--------------------------------------------------------------------------------&lt;br /&gt;
--            [[Module:Category handler]] configuration data                  --&lt;br /&gt;
--       Language-specific parameter names and values can be set here.        --&lt;br /&gt;
--       For blacklist config, see [[Module:Category handler/blacklist]].     --&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local cfg = {} -- Don&#039;t edit this line.&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
--                       Start configuration data                             --&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
--                              Parameter names                               --&lt;br /&gt;
-- These configuration items specify custom parameter names.                  --&lt;br /&gt;
-- To add one extra name, you can use this format:                            --&lt;br /&gt;
--                                                                            --&lt;br /&gt;
-- foo = &#039;parameter name&#039;,                                                    --&lt;br /&gt;
--                                                                            --&lt;br /&gt;
-- To add multiple names, you can use this format:                            --&lt;br /&gt;
--                                                                            --&lt;br /&gt;
-- foo = {&#039;parameter name 1&#039;, &#039;parameter name 2&#039;, &#039;parameter name 3&#039;},        --&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
cfg.parameters = {&lt;br /&gt;
	&lt;br /&gt;
	-- The nocat and categories parameter suppress&lt;br /&gt;
	-- categorisation. They are used with Module:Yesno, and work as follows:&lt;br /&gt;
	--&lt;br /&gt;
	-- cfg.nocat:&lt;br /&gt;
	-- Result of yesno()                        Effect&lt;br /&gt;
	-- true                                     Categorisation is suppressed&lt;br /&gt;
	-- false                                    Categorisation is allowed, and&lt;br /&gt;
	--                                          the blacklist check is skipped&lt;br /&gt;
	-- nil                                      Categorisation is allowed&lt;br /&gt;
	--&lt;br /&gt;
	-- cfg.categories:&lt;br /&gt;
	-- Result of yesno()                        Effect&lt;br /&gt;
	-- true                                     Categorisation is allowed, and&lt;br /&gt;
	--                                          the blacklist check is skipped&lt;br /&gt;
	-- false                                    Categorisation is suppressed&lt;br /&gt;
	-- nil                                      Categorisation is allowed&lt;br /&gt;
	nocat = &#039;nocat&#039;,&lt;br /&gt;
	categories = &#039;categories&#039;,&lt;br /&gt;
	&lt;br /&gt;
	-- The parameter name for the legacy &amp;quot;category2&amp;quot; parameter. This skips the&lt;br /&gt;
	-- blacklist if set to the cfg.category2Yes value, and suppresses&lt;br /&gt;
	-- categorisation if present but equal to anything other than&lt;br /&gt;
	-- cfg.category2Yes or cfg.category2Negative.&lt;br /&gt;
	category2 = &#039;category2&#039;,&lt;br /&gt;
	&lt;br /&gt;
	-- cfg.subpage is the parameter name to specify how to behave on subpages.&lt;br /&gt;
	subpage = &#039;subpage&#039;,&lt;br /&gt;
	&lt;br /&gt;
	-- The parameter for data to return in all namespaces.&lt;br /&gt;
	all = &#039;all&#039;,&lt;br /&gt;
	&lt;br /&gt;
	-- The parameter name for data to return if no data is specified for the&lt;br /&gt;
	-- namespace that is detected.&lt;br /&gt;
	other = &#039;other&#039;,&lt;br /&gt;
	&lt;br /&gt;
	-- The parameter name used to specify a page other than the current page;&lt;br /&gt;
	-- used for testing and demonstration.&lt;br /&gt;
	demopage = &#039;page&#039;,&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
--                              Parameter values                              --&lt;br /&gt;
-- These are set values that can be used with certain parameters. Only one    --&lt;br /&gt;
-- value can be specified, like this:                                         --&lt;br /&gt;
--                                                                            --&lt;br /&gt;
-- cfg.foo = &#039;value name&#039;                                                     --                                               --&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- The following settings are used with the cfg.category2 parameter. Setting&lt;br /&gt;
-- cfg.category2 to cfg.category2Yes skips the blacklist, and if cfg.category2&lt;br /&gt;
-- is present but equal to anything other than cfg.category2Yes or&lt;br /&gt;
-- cfg.category2Negative then it supresses cateogrisation.&lt;br /&gt;
cfg.category2Yes = &#039;yes&#039;&lt;br /&gt;
cfg.category2Negative = &#039;¬&#039;&lt;br /&gt;
&lt;br /&gt;
-- The following settings are used with the cfg.subpage parameter.&lt;br /&gt;
-- cfg.subpageNo is the value to specify to not categorise on subpages;&lt;br /&gt;
-- cfg.subpageOnly is the value to specify to only categorise on subpages.&lt;br /&gt;
cfg.subpageNo = &#039;no&#039;&lt;br /&gt;
cfg.subpageOnly = &#039;only&#039;&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
--                           Default namespaces                               --&lt;br /&gt;
-- This is a table of namespaces to categorise by default. The keys are the   --&lt;br /&gt;
-- namespace numbers.                                                         --&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
cfg.defaultNamespaces = {&lt;br /&gt;
	[  0] = true, -- main&lt;br /&gt;
	[  6] = true, -- file&lt;br /&gt;
	[ 12] = true, -- help&lt;br /&gt;
	[ 14] = true, -- category&lt;br /&gt;
	[100] = true, -- portal&lt;br /&gt;
	[108] = true, -- book&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
--                                Wrappers                                    --&lt;br /&gt;
-- This is a wrapper template or a list of wrapper templates to be passed to  --&lt;br /&gt;
-- [[Module:Arguments]].                                                      --&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
cfg.wrappers = &#039;Template:Category handler&#039;&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
--                           End configuration data                           --&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
return cfg -- Don&#039;t edit this line.&lt;/div&gt;</summary>
		<author><name>Jasper</name></author>
	</entry>
	<entry>
		<id>https://wiki.852r.org/index.php?title=Module:Category_handler/data&amp;diff=3844</id>
		<title>Module:Category handler/data</title>
		<link rel="alternate" type="text/html" href="https://wiki.852r.org/index.php?title=Module:Category_handler/data&amp;diff=3844"/>
		<updated>2026-08-06T10:46:18Z</updated>

		<summary type="html">&lt;p&gt;Jasper: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;-- This module assembles data to be passed to [[Module:Category handler]] using&lt;br /&gt;
-- mw.loadData. This includes the configuration data and whether the current&lt;br /&gt;
-- page matches the title blacklist.&lt;br /&gt;
&lt;br /&gt;
local data = require(&#039;Module:Category handler/config&#039;)&lt;br /&gt;
local mShared = require(&#039;Module:Category handler/shared&#039;)&lt;br /&gt;
local blacklist = require(&#039;Module:Category handler/blacklist&#039;)&lt;br /&gt;
local title = mw.title.getCurrentTitle()&lt;br /&gt;
&lt;br /&gt;
data.currentTitleMatchesBlacklist = mShared.matchesBlacklist(&lt;br /&gt;
	title.prefixedText,&lt;br /&gt;
	blacklist&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
data.currentTitleNamespaceParameters = mShared.getNamespaceParameters(&lt;br /&gt;
	title,&lt;br /&gt;
	mShared.getParamMappings()&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
return data&lt;/div&gt;</summary>
		<author><name>Jasper</name></author>
	</entry>
	<entry>
		<id>https://wiki.852r.org/index.php?title=Module:Category_handler&amp;diff=3842</id>
		<title>Module:Category handler</title>
		<link rel="alternate" type="text/html" href="https://wiki.852r.org/index.php?title=Module:Category_handler&amp;diff=3842"/>
		<updated>2026-08-06T10:46:18Z</updated>

		<summary type="html">&lt;p&gt;Jasper: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;--------------------------------------------------------------------------------&lt;br /&gt;
--                                                                            --&lt;br /&gt;
--                              CATEGORY HANDLER                              --&lt;br /&gt;
--                                                                            --&lt;br /&gt;
--      This module implements the {{category handler}} template in Lua,      --&lt;br /&gt;
--      with a few improvements: all namespaces and all namespace aliases     --&lt;br /&gt;
--      are supported, and namespace names are detected automatically for     --&lt;br /&gt;
--      the local wiki. This module requires [[Module:Namespace detect]]      --&lt;br /&gt;
--      and [[Module:Yesno]] to be available on the local wiki. It can be     --&lt;br /&gt;
--      configured for different wikis by altering the values in              --&lt;br /&gt;
--      [[Module:Category handler/config]], and pages can be blacklisted      --&lt;br /&gt;
--      from categorisation by using [[Module:Category handler/blacklist]].   --&lt;br /&gt;
--                                                                            --&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
-- Load required modules&lt;br /&gt;
local yesno = require(&#039;Module:Yesno&#039;)&lt;br /&gt;
&lt;br /&gt;
-- Lazily load things we don&#039;t always need&lt;br /&gt;
local mShared, mappings&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 trimWhitespace(s, removeBlanks)&lt;br /&gt;
	if type(s) ~= &#039;string&#039; then&lt;br /&gt;
		return s&lt;br /&gt;
	end&lt;br /&gt;
	s = s:match(&#039;^%s*(.-)%s*$&#039;)&lt;br /&gt;
	if removeBlanks then&lt;br /&gt;
		if s ~= &#039;&#039; then&lt;br /&gt;
			return s&lt;br /&gt;
		else&lt;br /&gt;
			return nil&lt;br /&gt;
		end&lt;br /&gt;
	else&lt;br /&gt;
		return s&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- CategoryHandler class&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local CategoryHandler = {}&lt;br /&gt;
CategoryHandler.__index = CategoryHandler&lt;br /&gt;
&lt;br /&gt;
function CategoryHandler.new(data, args)&lt;br /&gt;
	local obj = setmetatable({ _data = data, _args = args }, CategoryHandler)&lt;br /&gt;
	&lt;br /&gt;
	-- Set the title object&lt;br /&gt;
	do&lt;br /&gt;
		local pagename = obj:parameter(&#039;demopage&#039;)&lt;br /&gt;
		local success, titleObj&lt;br /&gt;
		if pagename then&lt;br /&gt;
			success, titleObj = pcall(mw.title.new, pagename)&lt;br /&gt;
		end&lt;br /&gt;
		if success and titleObj then&lt;br /&gt;
			obj.title = titleObj&lt;br /&gt;
			if titleObj == mw.title.getCurrentTitle() then&lt;br /&gt;
				obj._usesCurrentTitle = true&lt;br /&gt;
			end&lt;br /&gt;
		else&lt;br /&gt;
			obj.title = mw.title.getCurrentTitle()&lt;br /&gt;
			obj._usesCurrentTitle = true&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
&lt;br /&gt;
	-- Set suppression parameter values&lt;br /&gt;
	for _, key in ipairs{&#039;nocat&#039;, &#039;categories&#039;} do&lt;br /&gt;
		local value = obj:parameter(key)&lt;br /&gt;
		value = trimWhitespace(value, true)&lt;br /&gt;
		obj[&#039;_&#039; .. key] = yesno(value)&lt;br /&gt;
	end&lt;br /&gt;
	do&lt;br /&gt;
		local subpage = obj:parameter(&#039;subpage&#039;)&lt;br /&gt;
		local category2 = obj:parameter(&#039;category2&#039;)&lt;br /&gt;
		if type(subpage) == &#039;string&#039; then&lt;br /&gt;
			subpage = mw.ustring.lower(subpage)&lt;br /&gt;
		end&lt;br /&gt;
		if type(category2) == &#039;string&#039; then&lt;br /&gt;
			subpage = mw.ustring.lower(category2)&lt;br /&gt;
		end&lt;br /&gt;
		obj._subpage = trimWhitespace(subpage, true)&lt;br /&gt;
		obj._category2 = trimWhitespace(category2) -- don&#039;t remove blank values&lt;br /&gt;
	end&lt;br /&gt;
	return obj&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function CategoryHandler:parameter(key)&lt;br /&gt;
	local parameterNames = self._data.parameters[key]&lt;br /&gt;
	local pntype = type(parameterNames)&lt;br /&gt;
	if pntype == &#039;string&#039; or pntype == &#039;number&#039; then&lt;br /&gt;
		return self._args[parameterNames]&lt;br /&gt;
	elseif pntype == &#039;table&#039; then&lt;br /&gt;
		for _, name in ipairs(parameterNames) do&lt;br /&gt;
			local value = self._args[name]&lt;br /&gt;
			if value ~= nil then&lt;br /&gt;
				return value&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
		return nil&lt;br /&gt;
	else&lt;br /&gt;
		error(string.format(&lt;br /&gt;
			&#039;invalid config key &amp;quot;%s&amp;quot;&#039;,&lt;br /&gt;
			tostring(key)&lt;br /&gt;
		), 2)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function CategoryHandler:isSuppressedByArguments()&lt;br /&gt;
	return&lt;br /&gt;
		-- See if a category suppression argument has been set.&lt;br /&gt;
		self._nocat == true&lt;br /&gt;
		or self._categories == false&lt;br /&gt;
		or (&lt;br /&gt;
			self._category2&lt;br /&gt;
			and self._category2 ~= self._data.category2Yes&lt;br /&gt;
			and self._category2 ~= self._data.category2Negative&lt;br /&gt;
		)&lt;br /&gt;
&lt;br /&gt;
		-- Check whether we are on a subpage, and see if categories are&lt;br /&gt;
		-- suppressed based on our subpage status.&lt;br /&gt;
		or self._subpage == self._data.subpageNo and self.title.isSubpage&lt;br /&gt;
		or self._subpage == self._data.subpageOnly and not self.title.isSubpage&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function CategoryHandler:shouldSkipBlacklistCheck()&lt;br /&gt;
	-- Check whether the category suppression arguments indicate we&lt;br /&gt;
	-- should skip the blacklist check.&lt;br /&gt;
	return self._nocat == false&lt;br /&gt;
		or self._categories == true&lt;br /&gt;
		or self._category2 == self._data.category2Yes&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function CategoryHandler:matchesBlacklist()&lt;br /&gt;
	if self._usesCurrentTitle then&lt;br /&gt;
		return self._data.currentTitleMatchesBlacklist&lt;br /&gt;
	else&lt;br /&gt;
		mShared = mShared or require(&#039;Module:Category handler/shared&#039;)&lt;br /&gt;
		return mShared.matchesBlacklist(&lt;br /&gt;
			self.title.prefixedText,&lt;br /&gt;
			mw.loadData(&#039;Module:Category handler/blacklist&#039;)&lt;br /&gt;
		)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function CategoryHandler:isSuppressed()&lt;br /&gt;
	-- Find if categories are suppressed by either the arguments or by&lt;br /&gt;
	-- matching the blacklist.&lt;br /&gt;
	return self:isSuppressedByArguments()&lt;br /&gt;
		or not self:shouldSkipBlacklistCheck() and self:matchesBlacklist()&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function CategoryHandler:getNamespaceParameters()&lt;br /&gt;
	if self._usesCurrentTitle then&lt;br /&gt;
		return self._data.currentTitleNamespaceParameters&lt;br /&gt;
	else&lt;br /&gt;
		if not mappings then&lt;br /&gt;
			mShared = mShared or require(&#039;Module:Category handler/shared&#039;)&lt;br /&gt;
			mappings = mShared.getParamMappings(true) -- gets mappings with mw.loadData&lt;br /&gt;
		end&lt;br /&gt;
		return mShared.getNamespaceParameters(&lt;br /&gt;
			self.title,&lt;br /&gt;
			mappings&lt;br /&gt;
		)&lt;br /&gt;
	end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function CategoryHandler:namespaceParametersExist()&lt;br /&gt;
	-- Find whether any namespace parameters have been specified.&lt;br /&gt;
	-- We use the order &amp;quot;all&amp;quot; --&amp;gt; namespace params --&amp;gt; &amp;quot;other&amp;quot; as this is what&lt;br /&gt;
	-- the old template did.&lt;br /&gt;
	if self:parameter(&#039;all&#039;) then&lt;br /&gt;
		return true&lt;br /&gt;
	end&lt;br /&gt;
	if not mappings then&lt;br /&gt;
		mShared = mShared or require(&#039;Module:Category handler/shared&#039;)&lt;br /&gt;
		mappings = mShared.getParamMappings(true) -- gets mappings with mw.loadData&lt;br /&gt;
	end&lt;br /&gt;
	for ns, params in pairs(mappings) do&lt;br /&gt;
		for i, param in ipairs(params) do&lt;br /&gt;
			if self._args[param] then&lt;br /&gt;
				return true&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if self:parameter(&#039;other&#039;) then&lt;br /&gt;
		return true&lt;br /&gt;
	end&lt;br /&gt;
	return false&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function CategoryHandler:getCategories()&lt;br /&gt;
	local params = self:getNamespaceParameters()&lt;br /&gt;
	local nsCategory&lt;br /&gt;
	for i, param in ipairs(params) do&lt;br /&gt;
		local value = self._args[param]&lt;br /&gt;
		if value ~= nil then&lt;br /&gt;
			nsCategory = value&lt;br /&gt;
			break&lt;br /&gt;
		end&lt;br /&gt;
	end&lt;br /&gt;
	if nsCategory ~= nil or self:namespaceParametersExist() then&lt;br /&gt;
		-- Namespace parameters exist - advanced usage.&lt;br /&gt;
		if nsCategory == nil then&lt;br /&gt;
			nsCategory = self:parameter(&#039;other&#039;)&lt;br /&gt;
		end&lt;br /&gt;
		local ret = {self:parameter(&#039;all&#039;)}&lt;br /&gt;
		local numParam = tonumber(nsCategory)&lt;br /&gt;
		if numParam and numParam &amp;gt;= 1 and math.floor(numParam) == numParam then&lt;br /&gt;
			-- nsCategory is an integer&lt;br /&gt;
			ret[#ret + 1] = self._args[numParam]&lt;br /&gt;
		else&lt;br /&gt;
			ret[#ret + 1] = nsCategory&lt;br /&gt;
		end&lt;br /&gt;
		if #ret &amp;lt; 1 then&lt;br /&gt;
			return nil&lt;br /&gt;
		else&lt;br /&gt;
			return table.concat(ret)&lt;br /&gt;
		end&lt;br /&gt;
	elseif self._data.defaultNamespaces[self.title.namespace] then&lt;br /&gt;
		-- Namespace parameters don&#039;t exist, simple usage.&lt;br /&gt;
		return self._args[1]&lt;br /&gt;
	end&lt;br /&gt;
	return nil&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
-- Exports&lt;br /&gt;
--------------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
local p = {}&lt;br /&gt;
&lt;br /&gt;
function p._exportClasses()&lt;br /&gt;
	-- Used for testing purposes.&lt;br /&gt;
	return {&lt;br /&gt;
		CategoryHandler = CategoryHandler&lt;br /&gt;
	}&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p._main(args, data)&lt;br /&gt;
	data = data or mw.loadData(&#039;Module:Category handler/data&#039;)&lt;br /&gt;
	local handler = CategoryHandler.new(data, args)&lt;br /&gt;
	if handler:isSuppressed() then&lt;br /&gt;
		return nil&lt;br /&gt;
	end&lt;br /&gt;
	return handler:getCategories()&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
function p.main(frame, data)&lt;br /&gt;
	data = data or mw.loadData(&#039;Module:Category handler/data&#039;)&lt;br /&gt;
	local args = require(&#039;Module:Arguments&#039;).getArgs(frame, {&lt;br /&gt;
		wrappers = data.wrappers,&lt;br /&gt;
		valueFunc = function (k, v)&lt;br /&gt;
			v = trimWhitespace(v)&lt;br /&gt;
			if type(k) == &#039;number&#039; then&lt;br /&gt;
				if v ~= &#039;&#039; then&lt;br /&gt;
					return v&lt;br /&gt;
				else&lt;br /&gt;
					return nil&lt;br /&gt;
				end&lt;br /&gt;
			else&lt;br /&gt;
				return v&lt;br /&gt;
			end&lt;br /&gt;
		end&lt;br /&gt;
	})&lt;br /&gt;
	return p._main(args, data)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return p&lt;/div&gt;</summary>
		<author><name>Jasper</name></author>
	</entry>
	<entry>
		<id>https://wiki.852r.org/index.php?title=Module:TableTools&amp;diff=3840</id>
		<title>Module:TableTools</title>
		<link rel="alternate" type="text/html" href="https://wiki.852r.org/index.php?title=Module:TableTools&amp;diff=3840"/>
		<updated>2026-08-06T10:46:18Z</updated>

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

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

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

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

		<summary type="html">&lt;p&gt;Jasper: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#ifeq:&amp;lt;!--test first character for lower-case letter--&amp;gt;{{#invoke:string|find|1={{{1|}}}|2=^%l|plain=false}}|1&lt;br /&gt;
|&amp;lt;!-- first character is a lower case letter; test against whitelist&lt;br /&gt;
--&amp;gt;{{#switch: {{First word|{{{1|}}}}}&amp;lt;!--begin whitelist--&amp;gt;&lt;br /&gt;
|c. &amp;lt;!--for circa--&amp;gt;&lt;br /&gt;
|gTLD&lt;br /&gt;
|iMac&lt;br /&gt;
|iOS&lt;br /&gt;
|iOS,&lt;br /&gt;
|iPad&lt;br /&gt;
|iPhone&lt;br /&gt;
|iTunes&lt;br /&gt;
|macOS&lt;br /&gt;
|none&lt;br /&gt;
|pH&lt;br /&gt;
|pH-dependent=&amp;lt;!-- end whitelist; short description starts with an allowed lower-case string; whitelist matched; do nothing --&amp;gt; &lt;br /&gt;
|#default=&amp;lt;!-- apply category to track lower-case short descriptions --&amp;gt;{{main other|[[Category:Pages with lower-case short description|{{trim|{{{1|}}}}}]]}}{{Testcases other|{{red|CATEGORY APPLIED}}}}&amp;lt;!-- end whitelist test --&amp;gt;}}&lt;br /&gt;
|&amp;lt;!-- short description does not start with lower-case letter; do nothing; end lower-case test --&amp;gt;&lt;br /&gt;
}}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{documentation}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jasper</name></author>
	</entry>
	<entry>
		<id>https://wiki.852r.org/index.php?title=Template:Main_other&amp;diff=3830</id>
		<title>Template:Main other</title>
		<link rel="alternate" type="text/html" href="https://wiki.852r.org/index.php?title=Template:Main_other&amp;diff=3830"/>
		<updated>2026-08-06T10:46:17Z</updated>

		<summary type="html">&lt;p&gt;Jasper: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{safesubst:&amp;lt;noinclude/&amp;gt;#switch:&lt;br /&gt;
  &amp;lt;noinclude&amp;gt;&amp;lt;!-- If no or empty &amp;quot;demospace&amp;quot; parameter then detect namespace --&amp;gt;&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
  {{safesubst:&amp;lt;noinclude/&amp;gt;#if:{{{demospace|}}} &lt;br /&gt;
  | {{safesubst:&amp;lt;noinclude/&amp;gt;lc: {{{demospace}}} }}    &amp;lt;noinclude&amp;gt;&amp;lt;!-- Use lower case &amp;quot;demospace&amp;quot; --&amp;gt;&amp;lt;/noinclude&amp;gt;&lt;br /&gt;
  | {{safesubst:&amp;lt;noinclude/&amp;gt;#ifeq:{{safesubst:&amp;lt;noinclude/&amp;gt;NAMESPACE}}|{{safesubst:&amp;lt;noinclude/&amp;gt;ns:0}}&lt;br /&gt;
    | main&lt;br /&gt;
    | other&lt;br /&gt;
    }} &lt;br /&gt;
  }}&lt;br /&gt;
| main     = {{{1|}}}&lt;br /&gt;
| other&lt;br /&gt;
| #default = {{{2|}}}&lt;br /&gt;
}}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{documentation}}&lt;br /&gt;
&amp;lt;!-- Add categories to the /doc subpage; interwikis go to Wikidata, thank you! --&amp;gt;&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jasper</name></author>
	</entry>
	<entry>
		<id>https://wiki.852r.org/index.php?title=Template:Short_description&amp;diff=3828</id>
		<title>Template:Short description</title>
		<link rel="alternate" type="text/html" href="https://wiki.852r.org/index.php?title=Template:Short_description&amp;diff=3828"/>
		<updated>2026-08-06T10:46:17Z</updated>

		<summary type="html">&lt;p&gt;Jasper: 1 revision imported&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{#ifeq:{{lc:{{{1|}}}}}|none|{{SHORTDESC:|{{{2|}}}}}&amp;lt;nowiki/&amp;gt;&amp;lt;!--Prevents whitespace issues when used with adjacent newlines--&amp;gt;|&amp;lt;div class=&amp;quot;shortdescription nomobile noexcerpt noprint searchaux&amp;quot; style=&amp;quot;display:none&amp;quot;&amp;gt;{{{1|}}}{{SHORTDESC:{{{1|}}}|{{{2|}}}}}&amp;lt;/div&amp;gt;}}&amp;lt;includeonly&amp;gt;{{#ifeq:{{{pagetype}}}|Disambiguation pages||{{#ifeq:{{pagetype |defaultns = all |user=exclude}}|exclude||{{#ifeq:{{#switch: {{NAMESPACENUMBER}} | 2 | 3 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | 13 | 14 | 15 | 100 | 101 | 118 | 119 | 828 | 829 | = exclude|#default=}}|exclude||[[Category:{{{pagetype|{{pagetype |defaultns = extended |plural=y}}}}} with short description]]}}}}}}&amp;lt;/includeonly&amp;gt;&amp;lt;!-- Start tracking&lt;br /&gt;
--&amp;gt;{{#invoke:Check for unknown parameters|check|unknown={{Main other|[[Category:Pages using short description with unknown parameters|_VALUE_{{PAGENAME}}]]}}|preview=Page using [[Template:Short description]] with unknown parameter &amp;quot;_VALUE_&amp;quot;|ignoreblank=y| 1 | 2 | pagetype | bot |plural }}&amp;lt;!--&lt;br /&gt;
--&amp;gt;{{#ifexpr: {{#invoke:String|len|{{{1|}}}}}&amp;gt;100 | [[Category:{{{pagetype|{{pagetype |defaultns = extended |plural=y}}}}} with long short description]]}}&amp;lt;!--&lt;br /&gt;
--&amp;gt;&amp;lt;includeonly&amp;gt;{{#if:{{{1|}}}||[[Category:Pages with empty short description]]}}&amp;lt;/includeonly&amp;gt;&amp;lt;!--&lt;br /&gt;
--&amp;gt;{{Short description/lowercasecheck|{{{1|}}}}}&amp;lt;!-- &lt;br /&gt;
--&amp;gt;{{Main other |{{SDcat |sd={{{1|}}} }} }}&amp;lt;noinclude&amp;gt;&lt;br /&gt;
{{Documentation}}&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Jasper</name></author>
	</entry>
</feed>