<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://eurovision.jobogamer.xyz/index.php?action=history&amp;feed=atom&amp;title=MediaWiki%3AGadget-Twinkle.js</id>
	<title>MediaWiki:Gadget-Twinkle.js - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://eurovision.jobogamer.xyz/index.php?action=history&amp;feed=atom&amp;title=MediaWiki%3AGadget-Twinkle.js"/>
	<link rel="alternate" type="text/html" href="https://eurovision.jobogamer.xyz/index.php?title=MediaWiki:Gadget-Twinkle.js&amp;action=history"/>
	<updated>2026-05-20T20:45:43Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.45.3</generator>
	<entry>
		<id>https://eurovision.jobogamer.xyz/index.php?title=MediaWiki:Gadget-Twinkle.js&amp;diff=31&amp;oldid=prev</id>
		<title>Alfie: 1 revision imported</title>
		<link rel="alternate" type="text/html" href="https://eurovision.jobogamer.xyz/index.php?title=MediaWiki:Gadget-Twinkle.js&amp;diff=31&amp;oldid=prev"/>
		<updated>2026-03-19T09:58:24Z</updated>

		<summary type="html">&lt;p&gt;1 revision imported&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 05:58, 19 March 2026&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-notice&quot; lang=&quot;en&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(No difference)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;</summary>
		<author><name>Alfie</name></author>
	</entry>
	<entry>
		<id>https://eurovision.jobogamer.xyz/index.php?title=MediaWiki:Gadget-Twinkle.js&amp;diff=30&amp;oldid=prev</id>
		<title>en&gt;SD0001: Repo at fe45acb: Improve caching of Twinkle preferences (#2322)</title>
		<link rel="alternate" type="text/html" href="https://eurovision.jobogamer.xyz/index.php?title=MediaWiki:Gadget-Twinkle.js&amp;diff=30&amp;oldid=prev"/>
		<updated>2026-02-25T17:01:21Z</updated>

		<summary type="html">&lt;p&gt;Repo at fe45acb: Improve caching of Twinkle preferences (#2322)&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;/**&lt;br /&gt;
 * +-------------------------------------------------------------------------+&lt;br /&gt;
 * |                  === WARNING: GLOBAL GADGET FILE ===                    |&lt;br /&gt;
 * |                Changes to this page affect many users.                  |&lt;br /&gt;
 * |           Please discuss changes at [[WT:TW]] before editing.           |&lt;br /&gt;
 * +-------------------------------------------------------------------------+&lt;br /&gt;
 *&lt;br /&gt;
 * Imported from github [https://github.com/wikimedia-gadgets/twinkle].&lt;br /&gt;
 * All changes should be made in the repository, otherwise they will be lost.&lt;br /&gt;
 *&lt;br /&gt;
 * ----------&lt;br /&gt;
 *&lt;br /&gt;
 * This is AzaToth&amp;#039;s Twinkle, the popular script sidekick for newbies, admins, and&lt;br /&gt;
 * every Wikipedian in between. Visit [[WP:TW]] for more information.&lt;br /&gt;
 */&lt;br /&gt;
// &amp;lt;nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* global Morebits */&lt;br /&gt;
&lt;br /&gt;
(function() {&lt;br /&gt;
&lt;br /&gt;
// Check if account is experienced enough to use Twinkle&lt;br /&gt;
if (!Morebits.userIsInGroup(&amp;#039;autoconfirmed&amp;#039;) &amp;amp;&amp;amp; !Morebits.userIsInGroup(&amp;#039;confirmed&amp;#039;)) {&lt;br /&gt;
	return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
const Twinkle = {};&lt;br /&gt;
window.Twinkle = Twinkle; // allow global access&lt;br /&gt;
&lt;br /&gt;
Twinkle.initCallbacks = [];&lt;br /&gt;
/**&lt;br /&gt;
 * Adds a callback to execute when Twinkle has loaded.&lt;br /&gt;
 *&lt;br /&gt;
 * @param {Function} func&lt;br /&gt;
 * @param {string} [name] - name of module used to check if is disabled.&lt;br /&gt;
 * If name is not given, module is loaded unconditionally.&lt;br /&gt;
 */&lt;br /&gt;
Twinkle.addInitCallback = function twinkleAddInitCallback(func, name) {&lt;br /&gt;
	Twinkle.initCallbacks.push({ func: func, name: name });&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
Twinkle.defaultConfig = {};&lt;br /&gt;
/**&lt;br /&gt;
 * This holds the default set of preferences used by Twinkle.&lt;br /&gt;
 * It is important that all new preferences added here, especially admin-only ones, are also added to&lt;br /&gt;
 * |Twinkle.config.sections| in twinkleconfig.js, so they are configurable via the Twinkle preferences panel.&lt;br /&gt;
 * For help on the actual preferences, see the comments in twinkleconfig.js.&lt;br /&gt;
 */&lt;br /&gt;
Twinkle.defaultConfig = {&lt;br /&gt;
	// General&lt;br /&gt;
	userTalkPageMode: &amp;#039;tab&amp;#039;,&lt;br /&gt;
	dialogLargeFont: false,&lt;br /&gt;
	disabledModules: [],&lt;br /&gt;
	disabledSysopModules: [],&lt;br /&gt;
&lt;br /&gt;
	// ARV&lt;br /&gt;
	spiWatchReport: &amp;#039;yes&amp;#039;,&lt;br /&gt;
&lt;br /&gt;
	// Block&lt;br /&gt;
	defaultToBlock64: false,&lt;br /&gt;
	defaultToPartialBlocks: false,&lt;br /&gt;
	blankTalkpageOnIndefBlock: false,&lt;br /&gt;
&lt;br /&gt;
	// Rollback&lt;br /&gt;
	autoMenuAfterRollback: false,&lt;br /&gt;
	openTalkPage: [ &amp;#039;agf&amp;#039;, &amp;#039;norm&amp;#039;, &amp;#039;vand&amp;#039; ],&lt;br /&gt;
	openTalkPageOnAutoRevert: false,&lt;br /&gt;
	rollbackInPlace: false,&lt;br /&gt;
	markRevertedPagesAsMinor: [ &amp;#039;vand&amp;#039; ],&lt;br /&gt;
	watchRevertedPages: [ &amp;#039;agf&amp;#039;, &amp;#039;norm&amp;#039;, &amp;#039;vand&amp;#039;, &amp;#039;torev&amp;#039; ],&lt;br /&gt;
	watchRevertedExpiry: &amp;#039;1 month&amp;#039;,&lt;br /&gt;
	offerReasonOnNormalRevert: true,&lt;br /&gt;
	confirmOnRollback: false,&lt;br /&gt;
	confirmOnMobileRollback: true,&lt;br /&gt;
	showRollbackLinks: [ &amp;#039;diff&amp;#039;, &amp;#039;others&amp;#039; ],&lt;br /&gt;
&lt;br /&gt;
	// DI (twinkleimage)&lt;br /&gt;
	notifyUserOnDeli: true,&lt;br /&gt;
	deliWatchPage: &amp;#039;1 month&amp;#039;,&lt;br /&gt;
	deliWatchUser: &amp;#039;1 month&amp;#039;,&lt;br /&gt;
&lt;br /&gt;
	// Protect&lt;br /&gt;
	watchRequestedPages: &amp;#039;yes&amp;#039;,&lt;br /&gt;
	watchPPTaggedPages: &amp;#039;default&amp;#039;,&lt;br /&gt;
	watchProtectedPages: &amp;#039;default&amp;#039;,&lt;br /&gt;
&lt;br /&gt;
	// PROD&lt;br /&gt;
	watchProdPages: &amp;#039;1 month&amp;#039;,&lt;br /&gt;
	markProdPagesAsPatrolled: false,&lt;br /&gt;
	prodReasonDefault: &amp;#039;&amp;#039;,&lt;br /&gt;
	logProdPages: false,&lt;br /&gt;
	prodLogPageName: &amp;#039;PROD log&amp;#039;,&lt;br /&gt;
&lt;br /&gt;
	// CSD&lt;br /&gt;
	speedySelectionStyle: &amp;#039;buttonClick&amp;#039;,&lt;br /&gt;
	watchSpeedyPages: [ &amp;#039;g3&amp;#039;, &amp;#039;g5&amp;#039;, &amp;#039;g10&amp;#039;, &amp;#039;g11&amp;#039;, &amp;#039;g12&amp;#039; ],&lt;br /&gt;
	watchSpeedyExpiry: &amp;#039;1 month&amp;#039;,&lt;br /&gt;
	markSpeedyPagesAsPatrolled: false,&lt;br /&gt;
	watchSpeedyUser: &amp;#039;1 month&amp;#039;,&lt;br /&gt;
&lt;br /&gt;
	// these next two should probably be identical by default&lt;br /&gt;
	welcomeUserOnSpeedyDeletionNotification: [ &amp;#039;db&amp;#039;, &amp;#039;g1&amp;#039;, &amp;#039;g2&amp;#039;, &amp;#039;g3&amp;#039;, &amp;#039;g4&amp;#039;, &amp;#039;g5&amp;#039;, &amp;#039;g6&amp;#039;, &amp;#039;g10&amp;#039;, &amp;#039;g11&amp;#039;, &amp;#039;g12&amp;#039;, &amp;#039;g13&amp;#039;, &amp;#039;g14&amp;#039;, &amp;#039;g15&amp;#039;, &amp;#039;a1&amp;#039;, &amp;#039;a2&amp;#039;, &amp;#039;a3&amp;#039;, &amp;#039;a7&amp;#039;, &amp;#039;a9&amp;#039;, &amp;#039;a10&amp;#039;, &amp;#039;a11&amp;#039;, &amp;#039;c1&amp;#039;, &amp;#039;f1&amp;#039;, &amp;#039;f2&amp;#039;, &amp;#039;f3&amp;#039;, &amp;#039;f7&amp;#039;, &amp;#039;f9&amp;#039;, &amp;#039;r3&amp;#039;, &amp;#039;u6&amp;#039;, &amp;#039;u7&amp;#039; ],&lt;br /&gt;
	notifyUserOnSpeedyDeletionNomination: [ &amp;#039;db&amp;#039;, &amp;#039;g1&amp;#039;, &amp;#039;g2&amp;#039;, &amp;#039;g3&amp;#039;, &amp;#039;g4&amp;#039;, &amp;#039;g5&amp;#039;, &amp;#039;g6&amp;#039;, &amp;#039;g10&amp;#039;, &amp;#039;g11&amp;#039;, &amp;#039;g12&amp;#039;, &amp;#039;g13&amp;#039;, &amp;#039;g14&amp;#039;, &amp;#039;g15&amp;#039;, &amp;#039;a1&amp;#039;, &amp;#039;a2&amp;#039;, &amp;#039;a3&amp;#039;, &amp;#039;a7&amp;#039;, &amp;#039;a9&amp;#039;, &amp;#039;a10&amp;#039;, &amp;#039;a11&amp;#039;, &amp;#039;c1&amp;#039;, &amp;#039;f1&amp;#039;, &amp;#039;f2&amp;#039;, &amp;#039;f3&amp;#039;, &amp;#039;f7&amp;#039;, &amp;#039;f9&amp;#039;, &amp;#039;r3&amp;#039;, &amp;#039;u6&amp;#039;, &amp;#039;u7&amp;#039; ],&lt;br /&gt;
	warnUserOnSpeedyDelete: [ &amp;#039;db&amp;#039;, &amp;#039;g1&amp;#039;, &amp;#039;g2&amp;#039;, &amp;#039;g3&amp;#039;, &amp;#039;g4&amp;#039;, &amp;#039;g5&amp;#039;, &amp;#039;g6&amp;#039;, &amp;#039;g10&amp;#039;, &amp;#039;g11&amp;#039;, &amp;#039;g12&amp;#039;, &amp;#039;g13&amp;#039;, &amp;#039;g14&amp;#039;, &amp;#039;g15&amp;#039;, &amp;#039;a1&amp;#039;, &amp;#039;a2&amp;#039;, &amp;#039;a3&amp;#039;, &amp;#039;a7&amp;#039;, &amp;#039;a9&amp;#039;, &amp;#039;a10&amp;#039;, &amp;#039;a11&amp;#039;, &amp;#039;c1&amp;#039;, &amp;#039;f1&amp;#039;, &amp;#039;f2&amp;#039;, &amp;#039;f3&amp;#039;, &amp;#039;f7&amp;#039;, &amp;#039;f9&amp;#039;, &amp;#039;r3&amp;#039;, &amp;#039;u6&amp;#039;, &amp;#039;u7&amp;#039; ],&lt;br /&gt;
	promptForSpeedyDeletionSummary: [],&lt;br /&gt;
	deleteTalkPageOnDelete: true,&lt;br /&gt;
	deleteRedirectsOnDelete: true,&lt;br /&gt;
	deleteSysopDefaultToDelete: false,&lt;br /&gt;
	speedyWindowHeight: 500,&lt;br /&gt;
	speedyWindowWidth: 800,&lt;br /&gt;
	logSpeedyNominations: false,&lt;br /&gt;
	speedyLogPageName: &amp;#039;CSD log&amp;#039;,&lt;br /&gt;
	noLogOnSpeedyNomination: [ &amp;#039;u1&amp;#039; ],&lt;br /&gt;
&lt;br /&gt;
	// Unlink&lt;br /&gt;
	unlinkNamespaces: [ &amp;#039;0&amp;#039;, &amp;#039;10&amp;#039;, &amp;#039;100&amp;#039;, &amp;#039;118&amp;#039; ],&lt;br /&gt;
&lt;br /&gt;
	// Warn&lt;br /&gt;
	defaultWarningGroup: &amp;#039;10&amp;#039;,&lt;br /&gt;
	combinedSingletMenus: false,&lt;br /&gt;
	watchWarnings: &amp;#039;1 month&amp;#039;,&lt;br /&gt;
	oldSelect: false,&lt;br /&gt;
	customWarningList: [],&lt;br /&gt;
&lt;br /&gt;
	// XfD&lt;br /&gt;
	logXfdNominations: false,&lt;br /&gt;
	xfdLogPageName: &amp;#039;XfD log&amp;#039;,&lt;br /&gt;
	noLogOnXfdNomination: [],&lt;br /&gt;
	xfdWatchDiscussion: &amp;#039;default&amp;#039;,&lt;br /&gt;
	xfdWatchList: &amp;#039;no&amp;#039;,&lt;br /&gt;
	xfdWatchPage: &amp;#039;1 month&amp;#039;,&lt;br /&gt;
	xfdWatchUser: &amp;#039;1 month&amp;#039;,&lt;br /&gt;
	xfdWatchRelated: &amp;#039;1 month&amp;#039;,&lt;br /&gt;
	markXfdPagesAsPatrolled: true,&lt;br /&gt;
&lt;br /&gt;
	// Hidden preferences&lt;br /&gt;
	autolevelStaleDays: 3, // Huggle is 3, CBNG is 2&lt;br /&gt;
	revertMaxRevisions: 50, // intentionally limited&lt;br /&gt;
	batchMax: 5000,&lt;br /&gt;
	batchChunks: 50,&lt;br /&gt;
&lt;br /&gt;
	// Deprecated options, as a fallback for add-on scripts/modules&lt;br /&gt;
	summaryAd: &amp;#039; ([[WP:TW|TW]])&amp;#039;,&lt;br /&gt;
	deletionSummaryAd: &amp;#039; ([[WP:TW|TW]])&amp;#039;,&lt;br /&gt;
	protectionSummaryAd: &amp;#039; ([[WP:TW|TW]])&amp;#039;,&lt;br /&gt;
&lt;br /&gt;
	// Tag&lt;br /&gt;
	groupByDefault: true,&lt;br /&gt;
	watchTaggedVenues: [&amp;#039;articles&amp;#039;, &amp;#039;drafts&amp;#039;, &amp;#039;redirects&amp;#039;, &amp;#039;files&amp;#039;],&lt;br /&gt;
	watchTaggedPages: &amp;#039;1 month&amp;#039;,&lt;br /&gt;
	watchMergeDiscussions: &amp;#039;1 month&amp;#039;,&lt;br /&gt;
	markTaggedPagesAsMinor: false,&lt;br /&gt;
	markTaggedPagesAsPatrolled: false,&lt;br /&gt;
	tagArticleSortOrder: &amp;#039;cat&amp;#039;,&lt;br /&gt;
	customTagList: [],&lt;br /&gt;
	customFileTagList: [],&lt;br /&gt;
	customRedirectTagList: [],&lt;br /&gt;
&lt;br /&gt;
	// Welcome&lt;br /&gt;
	topWelcomes: false,&lt;br /&gt;
	watchWelcomes: &amp;#039;3 months&amp;#039;,&lt;br /&gt;
	insertUsername: true,&lt;br /&gt;
	quickWelcomeMode: &amp;#039;norm&amp;#039;,&lt;br /&gt;
	quickWelcomeTemplate: &amp;#039;welcome&amp;#039;,&lt;br /&gt;
	customWelcomeList: [],&lt;br /&gt;
	customWelcomeSignature: true,&lt;br /&gt;
&lt;br /&gt;
	// Talkback&lt;br /&gt;
	markTalkbackAsMinor: false,&lt;br /&gt;
	insertTalkbackSignature: true, // always sign talkback templates&lt;br /&gt;
	talkbackHeading: &amp;#039;New message from &amp;#039; + mw.config.get(&amp;#039;wgUserName&amp;#039;),&lt;br /&gt;
	mailHeading: &amp;quot;You&amp;#039;ve got mail!&amp;quot;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
Twinkle.getPref = function twinkleGetPref(name) {&lt;br /&gt;
	if (typeof Twinkle.prefs === &amp;#039;object&amp;#039; &amp;amp;&amp;amp; Twinkle.prefs[name] !== undefined) {&lt;br /&gt;
		return Twinkle.prefs[name];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Old preferences format, used before twinkleoptions.js was a thing&lt;br /&gt;
	if (typeof window.TwinkleConfig === &amp;#039;object&amp;#039; &amp;amp;&amp;amp; window.TwinkleConfig[name] !== undefined) {&lt;br /&gt;
		return window.TwinkleConfig[name];&lt;br /&gt;
	}&lt;br /&gt;
	if (typeof window.FriendlyConfig === &amp;#039;object&amp;#039; &amp;amp;&amp;amp; window.FriendlyConfig[name] !== undefined) {&lt;br /&gt;
		return window.FriendlyConfig[name];&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Backwards compatibility code because we renamed confirmOnFluff to confirmOnRollback, and confirmOnMobileFluff to confirmOnMobileRollback&lt;br /&gt;
	if (name === &amp;#039;confirmOnRollback&amp;#039; &amp;amp;&amp;amp; typeof Twinkle.prefs === &amp;#039;object&amp;#039; &amp;amp;&amp;amp; Twinkle.prefs.confirmOnFluff !== undefined) {&lt;br /&gt;
		return Twinkle.prefs.confirmOnFluff;&lt;br /&gt;
	} else if (name === &amp;#039;confirmOnMobileRollback&amp;#039; &amp;amp;&amp;amp; typeof Twinkle.prefs === &amp;#039;object&amp;#039; &amp;amp;&amp;amp; Twinkle.prefs.confirmOnMobileFluff !== undefined) {&lt;br /&gt;
		return Twinkle.prefs.confirmOnMobileFluff;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return Twinkle.defaultConfig[name];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Adds a portlet menu to one of the navigation areas on the page.&lt;br /&gt;
 *&lt;br /&gt;
 * @return {string} portletId&lt;br /&gt;
 */&lt;br /&gt;
Twinkle.addPortlet = function() {&lt;br /&gt;
	/** @type {string} id of the target navigation area (skin dependent, on vector either of &amp;quot;#left-navigation&amp;quot;, &amp;quot;#right-navigation&amp;quot;, or &amp;quot;#mw-panel&amp;quot;) */&lt;br /&gt;
	let navigation;&lt;br /&gt;
&lt;br /&gt;
	/** @type {string} id of the portlet menu to create, preferably start with &amp;quot;p-&amp;quot;. */&lt;br /&gt;
	let id;&lt;br /&gt;
&lt;br /&gt;
	/** @type {string} name of the portlet menu to create. Visibility depends on the class used. */&lt;br /&gt;
	let text;&lt;br /&gt;
&lt;br /&gt;
	/** @type {Node} the id of the node before which the new item should be added, should be another item in the same list, or undefined to place it at the end. */&lt;br /&gt;
	let nextnodeid;&lt;br /&gt;
&lt;br /&gt;
	switch (mw.config.get(&amp;#039;skin&amp;#039;)) {&lt;br /&gt;
		case &amp;#039;vector&amp;#039;:&lt;br /&gt;
		case &amp;#039;vector-2022&amp;#039;:&lt;br /&gt;
			navigation = &amp;#039;#right-navigation&amp;#039;;&lt;br /&gt;
			id = &amp;#039;p-twinkle&amp;#039;;&lt;br /&gt;
			text = &amp;#039;TW&amp;#039;;&lt;br /&gt;
			// In order to get mw.util.addPortlet to generate a dropdown menu in vector and vector-2022, the nextnodeid must be p-cactions. Any other nextnodeid will generate a non-dropdown portlet instead.&lt;br /&gt;
			nextnodeid = &amp;#039;p-cactions&amp;#039;;&lt;br /&gt;
			break;&lt;br /&gt;
		case &amp;#039;timeless&amp;#039;:&lt;br /&gt;
			navigation = &amp;#039;#page-tools .sidebar-inner&amp;#039;;&lt;br /&gt;
			id = &amp;#039;p-twinkle&amp;#039;;&lt;br /&gt;
			text = &amp;#039;Twinkle&amp;#039;;&lt;br /&gt;
			nextnodeid = &amp;#039;p-userpagetools&amp;#039;;&lt;br /&gt;
			break;&lt;br /&gt;
		default:&lt;br /&gt;
			navigation = null;&lt;br /&gt;
			id = &amp;#039;p-cactions&amp;#039;;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (navigation === null) {&lt;br /&gt;
		return id;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// make sure navigation is a valid CSS selector&lt;br /&gt;
	const root = document.querySelector(navigation);&lt;br /&gt;
	if (!root) {&lt;br /&gt;
		return id;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// if we already created the portlet, return early. we don&amp;#039;t want to create it again.&lt;br /&gt;
	const item = document.getElementById(id);&lt;br /&gt;
	if (item) {&lt;br /&gt;
		return id;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	mw.util.addPortlet(id, text, &amp;#039;#&amp;#039; + nextnodeid);&lt;br /&gt;
&lt;br /&gt;
	// The Twinkle dropdown menu has been added to the left of p-cactions, since that is the only spot that will create a dropdown menu. But we want it on the right. Move it to the right.&lt;br /&gt;
	if (mw.config.get(&amp;#039;skin&amp;#039;) === &amp;#039;vector&amp;#039;) {&lt;br /&gt;
		$(&amp;#039;#p-twinkle&amp;#039;).insertAfter(&amp;#039;#p-cactions&amp;#039;);&lt;br /&gt;
	} else if (mw.config.get(&amp;#039;skin&amp;#039;) === &amp;#039;vector-2022&amp;#039;) {&lt;br /&gt;
		const $landmark = $(&amp;#039;#right-navigation &amp;gt; .vector-page-tools-landmark&amp;#039;);&lt;br /&gt;
		$(&amp;#039;#p-twinkle-dropdown&amp;#039;).insertAfter($landmark);&lt;br /&gt;
&lt;br /&gt;
		// .vector-page-tools-landmark is unstable and could change. If so, log it to console, to hopefully get someone&amp;#039;s attention.&lt;br /&gt;
		if (!$landmark) {&lt;br /&gt;
			mw.log.warn(&amp;#039;Unexpected change in DOM&amp;#039;);&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return id;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Builds a portlet menu if it doesn&amp;#039;t exist yet, and adds a portlet link. This function runs at the top of every Twinkle module, ensuring that the first module to be loaded adds the portlet, and that every module can add a link to itself to the portlet.&lt;br /&gt;
 *&lt;br /&gt;
 * @param {string|Function} task Either a URL for the portlet link or a function to execute.&lt;br /&gt;
 */&lt;br /&gt;
Twinkle.addPortletLink = function(task, text, id, tooltip) {&lt;br /&gt;
	// Create a portlet to hold all the portlet links (if not created already). And get the portletId.&lt;br /&gt;
	const portletId = Twinkle.addPortlet();&lt;br /&gt;
&lt;br /&gt;
	// Create a portlet link and add it to the portlet.&lt;br /&gt;
	const link = mw.util.addPortletLink(portletId, typeof task === &amp;#039;string&amp;#039; ? task : &amp;#039;#&amp;#039;, text, id, tooltip);&lt;br /&gt;
&lt;br /&gt;
	// Related to the hidden peer gadget that prevents jumpiness when the page first loads&lt;br /&gt;
	$(&amp;#039;.client-js .skin-vector #p-cactions&amp;#039;).css(&amp;#039;margin-right&amp;#039;, &amp;#039;initial&amp;#039;);&lt;br /&gt;
&lt;br /&gt;
	// Add a click listener for the portlet link&lt;br /&gt;
	if (typeof task === &amp;#039;function&amp;#039;) {&lt;br /&gt;
		$(link).on(&amp;#039;click&amp;#039;, (ev) =&amp;gt; {&lt;br /&gt;
			task();&lt;br /&gt;
			ev.preventDefault();&lt;br /&gt;
		});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// $.collapsibleTabs is a feature of Vector 2010&lt;br /&gt;
	if ($.collapsibleTabs) {&lt;br /&gt;
		// Manually trigger a recalculation of what tabs to put where. This is to account for the space that the TW menu we just added is taking up.&lt;br /&gt;
		$.collapsibleTabs.handleResize();&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	return link;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * **************** General initialization code ****************&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
// Retrieve the user&amp;#039;s Twinkle preferences&lt;br /&gt;
Morebits.wiki.getCachedPage(`User:${mw.config.get(&amp;#039;wgUserName&amp;#039;)}/twinkleoptions.js`)&lt;br /&gt;
	.then((optionsText) =&amp;gt; {&lt;br /&gt;
		if (!optionsText) {&lt;br /&gt;
			// User has no options&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		// Twinkle options are basically a JSON object with some comments. Strip those:&lt;br /&gt;
		optionsText = optionsText.replace(/(?:^(?:\/\/[^\n]*\n)*\n*|(?:\/\/[^\n]*(?:\n|$))*$)/g, &amp;#039;&amp;#039;);&lt;br /&gt;
&lt;br /&gt;
		// First version of options had some boilerplate code to make it eval-able -- strip that too. This part may become obsolete down the line.&lt;br /&gt;
		if (optionsText.lastIndexOf(&amp;#039;window.Twinkle.prefs = &amp;#039;, 0) === 0) {&lt;br /&gt;
			optionsText = optionsText.replace(/(?:^window.Twinkle.prefs = |;\n*$)/g, &amp;#039;&amp;#039;);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		try {&lt;br /&gt;
			const options = JSON.parse(optionsText);&lt;br /&gt;
			if (options) {&lt;br /&gt;
				if (options.twinkle || options.friendly) { // Old preferences format&lt;br /&gt;
					Twinkle.prefs = $.extend(options.twinkle, options.friendly);&lt;br /&gt;
				} else {&lt;br /&gt;
					Twinkle.prefs = options;&lt;br /&gt;
				}&lt;br /&gt;
				// v2 established after unification of Twinkle/Friendly objects&lt;br /&gt;
				Twinkle.prefs.optionsVersion = Twinkle.prefs.optionsVersion || 1;&lt;br /&gt;
			}&lt;br /&gt;
		} catch (e) {&lt;br /&gt;
			mw.notify(&amp;#039;Could not parse your Twinkle preferences&amp;#039;, {type: &amp;#039;error&amp;#039;});&lt;br /&gt;
		}&lt;br /&gt;
	})&lt;br /&gt;
	.catch(() =&amp;gt; {&lt;br /&gt;
		console.log(&amp;#039;Could not load your Twinkle preferences, resorting to default preferences&amp;#039;); // eslint-disable-line no-console&lt;br /&gt;
	})&lt;br /&gt;
	.always(() =&amp;gt; {&lt;br /&gt;
		$(Twinkle.load);&lt;br /&gt;
	});&lt;br /&gt;
&lt;br /&gt;
// Developers: you can import custom Twinkle modules here&lt;br /&gt;
// For example, mw.loader.load(scriptpathbefore + &amp;quot;User:UncleDouggie/morebits-test.js&amp;quot; + scriptpathafter);&lt;br /&gt;
&lt;br /&gt;
Twinkle.load = function () {&lt;br /&gt;
	// Don&amp;#039;t activate on special pages other than those listed here, so&lt;br /&gt;
	// that others load faster, especially the watchlist.&lt;br /&gt;
	let activeSpecialPageList = [ &amp;#039;Block&amp;#039;, &amp;#039;Contributions&amp;#039;, &amp;#039;IPContributions&amp;#039;, &amp;#039;Recentchanges&amp;#039;, &amp;#039;Recentchangeslinked&amp;#039; ]; // wgRelevantUserName defined for non-sysops on Special:Block&lt;br /&gt;
	if (Morebits.userIsSysop) {&lt;br /&gt;
		activeSpecialPageList = activeSpecialPageList.concat([ &amp;#039;DeletedContributions&amp;#039;, &amp;#039;Prefixindex&amp;#039; ]);&lt;br /&gt;
	}&lt;br /&gt;
	if (mw.config.get(&amp;#039;wgNamespaceNumber&amp;#039;) === -1 &amp;amp;&amp;amp;&lt;br /&gt;
		!activeSpecialPageList.includes(mw.config.get(&amp;#039;wgCanonicalSpecialPageName&amp;#039;))) {&lt;br /&gt;
		return;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Prevent clickjacking&lt;br /&gt;
	if (window.top !== window.self) {&lt;br /&gt;
		return;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Set custom Api-User-Agent header, for server-side logging purposes&lt;br /&gt;
	Morebits.wiki.Api.setApiUserAgent(&amp;#039;Twinkle (&amp;#039; + mw.config.get(&amp;#039;wgWikiID&amp;#039;) + &amp;#039;)&amp;#039;);&lt;br /&gt;
&lt;br /&gt;
	Twinkle.disabledModules = Twinkle.getPref(&amp;#039;disabledModules&amp;#039;).concat(Twinkle.getPref(&amp;#039;disabledSysopModules&amp;#039;));&lt;br /&gt;
&lt;br /&gt;
	// Redefine addInitCallback so that any modules being loaded now on are directly&lt;br /&gt;
	// initialised rather than added to initCallbacks array&lt;br /&gt;
	Twinkle.addInitCallback = function(func, name) {&lt;br /&gt;
		if (!name || !Twinkle.disabledModules.includes(name)) {&lt;br /&gt;
			func();&lt;br /&gt;
		}&lt;br /&gt;
	};&lt;br /&gt;
	// Initialise modules that were saved in initCallbacks array&lt;br /&gt;
	Twinkle.initCallbacks.forEach((module) =&amp;gt; {&lt;br /&gt;
		Twinkle.addInitCallback(module.func, module.name);&lt;br /&gt;
	});&lt;br /&gt;
&lt;br /&gt;
	// Increases text size in Twinkle dialogs, if so configured&lt;br /&gt;
	if (Twinkle.getPref(&amp;#039;dialogLargeFont&amp;#039;)) {&lt;br /&gt;
		mw.util.addCSS(&amp;#039;.morebits-dialog-content, .morebits-dialog-footerlinks { font-size: 100% !important; } &amp;#039; +&lt;br /&gt;
			&amp;#039;.morebits-dialog input, .morebits-dialog select, .morebits-dialog-content button { font-size: inherit !important; }&amp;#039;);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// Hide the lingering space if the TW menu is empty&lt;br /&gt;
	const isVector = mw.config.get(&amp;#039;skin&amp;#039;) === &amp;#039;vector&amp;#039; || mw.config.get(&amp;#039;skin&amp;#039;) === &amp;#039;vector-2022&amp;#039;;&lt;br /&gt;
	if (isVector &amp;amp;&amp;amp; Twinkle.getPref(&amp;#039;portletType&amp;#039;) === &amp;#039;menu&amp;#039; &amp;amp;&amp;amp; $(&amp;#039;#p-twinkle&amp;#039;).length === 0) {&lt;br /&gt;
		$(&amp;#039;#p-cactions&amp;#039;).css(&amp;#039;margin-right&amp;#039;, &amp;#039;initial&amp;#039;);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	// If using a skin with space for lots of modules, display a link to Twinkle Preferences&lt;br /&gt;
	const usingSkinWithDropDownMenu = mw.config.get(&amp;#039;skin&amp;#039;) === &amp;#039;vector&amp;#039; || mw.config.get(&amp;#039;skin&amp;#039;) === &amp;#039;vector-2022&amp;#039; || mw.config.get(&amp;#039;skin&amp;#039;) === &amp;#039;timeless&amp;#039;;&lt;br /&gt;
	if (usingSkinWithDropDownMenu) {&lt;br /&gt;
		Twinkle.addPortletLink(mw.util.getUrl(&amp;#039;Wikipedia:Twinkle/Preferences&amp;#039;), &amp;#039;Config&amp;#039;, &amp;#039;tw-config&amp;#039;, &amp;#039;Open Twinkle preferences page&amp;#039;);&lt;br /&gt;
	}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Twinkle-specific data shared by multiple modules&lt;br /&gt;
 * Likely customized per installation&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
// Custom change tag(s) to be applied to all Twinkle actions, create at Special:Tags&lt;br /&gt;
Twinkle.changeTags = &amp;#039;twinkle&amp;#039;;&lt;br /&gt;
// Available for actions that don&amp;#039;t (yet) support tags&lt;br /&gt;
// currently: FlaggedRevs and PageTriage&lt;br /&gt;
Twinkle.summaryAd = &amp;#039; ([[WP:TW|TW]])&amp;#039;;&lt;br /&gt;
&lt;br /&gt;
// Various hatnote templates, used when tagging (csd/xfd/tag/prod/protect) to&lt;br /&gt;
// ensure MOS:ORDER&lt;br /&gt;
Twinkle.hatnoteRegex = &amp;#039;short description|hatnote|main|correct title|dablink|distinguish|for|further|selfref|year dab|similar names|highway detail hatnote|broader|about(?:-distinguish| other people)?|other\\s?(?:hurricane(?: use)?s|people|persons|places|ships|uses(?: of)?)|redirect(?:-(?:distinguish|synonym|multi))?|see\\s?(?:wiktionary|also(?: if exists)?)&amp;#039;;&lt;br /&gt;
&lt;br /&gt;
/* Twinkle-specific utility functions shared by multiple modules */&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * When performing rollbacks with [rollback] links, then visiting a user talk page, some data such as page name can be prefilled into Wel/AIV/Warn. Twinkle calls this a &amp;quot;prefill&amp;quot;. This method gets a prefill, either from URL parameters (e.g. &amp;amp;vanarticle=Test) or from data previously stored using Twinkle.setPrefill()&lt;br /&gt;
 */&lt;br /&gt;
Twinkle.getPrefill = function (key) {&lt;br /&gt;
	Twinkle.prefill = Twinkle.prefill || {};&lt;br /&gt;
	if (!Object.prototype.hasOwnProperty.call(Twinkle.prefill, key)) {&lt;br /&gt;
		Twinkle.prefill[key] = mw.util.getParamValue(key);&lt;br /&gt;
	}&lt;br /&gt;
	return Twinkle.prefill[key];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * When performing rollbacks with [rollback] links, then visiting a user talk page, some data such as page name can be prefilled into Wel/AIV/Warn. Twinkle calls this a &amp;quot;prefill&amp;quot;. This method sets a prefill. This data will be lost if the page is refreshed, unless it is added to the URL as a parameter.&lt;br /&gt;
 */&lt;br /&gt;
Twinkle.setPrefill = function (key, value) {&lt;br /&gt;
	Twinkle.prefill = Twinkle.prefill || {};&lt;br /&gt;
	Twinkle.prefill[key] = value;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Used in XFD and PROD&lt;br /&gt;
 */&lt;br /&gt;
Twinkle.makeFindSourcesDiv = function makeSourcesDiv(divID) {&lt;br /&gt;
	if (!$(divID).length) {&lt;br /&gt;
		return;&lt;br /&gt;
	}&lt;br /&gt;
	if (!Twinkle.findSources) {&lt;br /&gt;
		const parser = new Morebits.wiki.Preview($(divID)[0]);&lt;br /&gt;
		parser.beginRender(&amp;#039;({{Find sources|&amp;#039; + Morebits.pageNameNorm + &amp;#039;}})&amp;#039;, &amp;#039;WP:AFD&amp;#039;).then(() =&amp;gt; {&lt;br /&gt;
			// Save for second-time around&lt;br /&gt;
			Twinkle.findSources = parser.previewbox.innerHTML;&lt;br /&gt;
			$(divID).removeClass(&amp;#039;morebits-previewbox&amp;#039;);&lt;br /&gt;
		});&lt;br /&gt;
	} else {&lt;br /&gt;
		$(divID).html(Twinkle.findSources);&lt;br /&gt;
	}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Used in batch, unlink, and deprod to sort pages by namespace, as&lt;br /&gt;
 * json formatversion=2 sorts by pageid instead (#1251)&lt;br /&gt;
 */&lt;br /&gt;
Twinkle.sortByNamespace = function(first, second) {&lt;br /&gt;
	return first.ns - second.ns || (first.title &amp;gt; second.title ? 1 : -1);&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Used in batch listings to link to the page in question with &amp;gt;&lt;br /&gt;
 */&lt;br /&gt;
Twinkle.generateArrowLinks = function (checkbox) {&lt;br /&gt;
	const link = Morebits.htmlNode(&amp;#039;a&amp;#039;, &amp;#039; &amp;gt;&amp;#039;);&lt;br /&gt;
	link.setAttribute(&amp;#039;class&amp;#039;, &amp;#039;tw-arrowpage-link&amp;#039;);&lt;br /&gt;
	link.setAttribute(&amp;#039;href&amp;#039;, mw.util.getUrl(checkbox.value));&lt;br /&gt;
	link.setAttribute(&amp;#039;target&amp;#039;, &amp;#039;_blank&amp;#039;);&lt;br /&gt;
	checkbox.nextElementSibling.append(link);&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * Used in deprod and unlink listings to link the page title&lt;br /&gt;
 */&lt;br /&gt;
Twinkle.generateBatchPageLinks = function (checkbox) {&lt;br /&gt;
	const $checkbox = $(checkbox);&lt;br /&gt;
	const link = Morebits.htmlNode(&amp;#039;a&amp;#039;, $checkbox.val());&lt;br /&gt;
	link.setAttribute(&amp;#039;class&amp;#039;, &amp;#039;tw-batchpage-link&amp;#039;);&lt;br /&gt;
	link.setAttribute(&amp;#039;href&amp;#039;, mw.util.getUrl($checkbox.val()));&lt;br /&gt;
	link.setAttribute(&amp;#039;target&amp;#039;, &amp;#039;_blank&amp;#039;);&lt;br /&gt;
	$checkbox.next().prepend([link, &amp;#039; &amp;#039;]);&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/**&lt;br /&gt;
 * remove &amp;quot;move to Commons&amp;quot; tag - deletion-tagged files cannot be moved to Commons&lt;br /&gt;
 */&lt;br /&gt;
Twinkle.removeMoveToCommonsTagsFromWikicode = ( wikicode ) =&amp;gt; wikicode.replace(/\{\{(mtc|(copy |move )?to ?commons|move to wikimedia commons|copy to wikimedia commons)(?!( in))[^}]*\}\}/gi, &amp;#039;&amp;#039;);&lt;br /&gt;
&lt;br /&gt;
}());&lt;br /&gt;
&lt;br /&gt;
// &amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>en&gt;SD0001</name></author>
	</entry>
</feed>