_ _    _ _____  ___   __                       
 __      _(_) | _(_)___ / ( _ ) / /_   ___ ___  _ __ ___  
 \ \ /\ / / | |/ / | |_ \ / _ \| '_ \ / __/ _ \| '_ ` _ \ 
  \ V  V /| |   <| |___) | (_) | (_) | (_| (_) | | | | | |
   \_/\_/ |_|_|\_\_|____/ \___/ \___(_)___\___/|_| |_| |_|

MediaWiki:Gadget-replylinks.js

W dzisiejszym świecie MediaWiki:Gadget-replylinks.js zyskał niespotykane dotąd znaczenie. Niezależnie od tego, czy chodzi o naukę, kulturę, rozrywkę czy politykę, MediaWiki:Gadget-replylinks.js stał się podstawowym tematem dyskusji i analiz. Jego wpływ przekroczył granice i wywołał wielką debatę we współczesnym społeczeństwie. Aby zrozumieć jego znaczenie i implikacje, konieczne jest przeprowadzenie głębokich i szczegółowych badań, które pozwolą nam zagłębić się we wszystkie jego wymiary. W tym artykule zbadamy różne aspekty związane z MediaWiki:Gadget-replylinks.js, od jego pochodzenia po wpływ na dzisiejszy świat, w celu rzucenia światła na ten temat, który jest dziś tak istotny.
/**
	@file Odpowiedzi z linkami (Reply links with backtrack links)
	v1.11.1

	Opis (pl):
		- http://pl.wikipedia.orghttps://wiki386.com/pl/Wikipedia:Narz%C4%99dzia/Odpowiedzi_z_linkami

    Main functions:
		- adding reply links near user links
		- inserting text given in newsectionname (as PHP param in the location string of the page)

    Copyright:  ©2006-2024 Maciej Jaros (pl:User:Nux, en:User:EcceNux)
     Licencja:  GNU General Public License v2
                http://opensource.org/licenses/gpl-license.php

	@note Please keep MW 1.16 compatible (i.e. do not use mw.config directly)
	@note jQuery is required though
	
	@note Dev version: http://pl.wikipedia.orghttps://wiki386.com/pl/Wikipedysta:Nux/replylinks.dev.js
	@note Prod version: https://pl.wikipedia.orghttps://wiki386.com/pl/MediaWiki:Gadget-replylinks.js

	@note Repo, bugz, pull requests: https://github.com/Eccenux/wiki-replylinks/
*/
// <nowiki>
/* -=-=-=-=-=-=-=-=-=-=-=-
	Object init
 -=-=-=-=-=-=-=-=-=-=-=- */
if (typeof(window.oRepLinks) != 'undefined')
{
	throw ("oRepLinks already used");
}
var oRepLinks = {};
window.oRepLinks = oRepLinks;

/* -=-=-=-=-=-=-=-=-=-=-=-
	Version
 -=-=-=-=-=-=-=-=-=-=-=- */
oRepLinks.version = oRepLinks.ver = '1.11.1';

/* -=-=-=-=-=-=-=-=-=-=-=-
	Preferences
 -=-=-=-=-=-=-=-=-=-=-=- */
// i18n
oRepLinks.i18n = {'':''
	,'en' : {'':''
		,'std prefix'        : 'Re:'   // standard prefix to a reply
		,'no section prefix' : 'Ad:'   // prefix shown when a section header was not found
		,'reply link text'   : 'reply'
	}
	,'pl' : {'':''
		,'std prefix'        : 'Odp:'
		,'no section prefix' : 'Ad:'
		,'reply link text'   : 'odp'
	}
};
// IP will be added to the end to create a working link
oRepLinks.hrefOnlineIPwhois = 'https://whois.toolforge.org/gateway.py?lookup=true&ip=';

/* -=-=-=-=-=-=-=-=-=-=-=-
	Gadget code
	$G = oRepLinks
 -=-=-=-=-=-=-=-=-=-=-=- */
(function($G){
/**
	@brief get MediaWiki configuration variable
	
	MW 1.16 and 1.17+ compatible
*/
$G.getMediaWikiConfig = function(variableName)
{
	if (typeof(mw) === 'object' && 'config' in mw) {
		return mw.config.get(variableName);
	}
	return window;
};

//
// i18n setup
//
$G.Lang = "en";
if ($G.getMediaWikiConfig('wgUserLanguage') in $G.i18n)
{
	$G.Lang = $G.getMediaWikiConfig('wgUserLanguage');
}
$G.i18n = $G.i18n;

/** Configurable by users (and default when `gConfig` is not available). */
$G.options = {
	boolAddSignature: true,
};

/**
 * Prepare options from user config.
 * @param {UserConfig} userConfig 
 */
$G.prepareConfig = async function (userConfig) {
	await userConfig.register();

	const userOptions = [
		'boolAddSignature',
	];
	for (const option of userOptions) {
		let value = userConfig.get(option);
		this.options = value;
	}
	mw.hook('userjs.replylinks.configReady').fire();
},

/**
	@brief get all alternative namespaces for given \a namespaceNumber.

	@return array of namespace names (including alternative names)
*/
$G.getNamespaceNames = function(namespaceNumber, encodingFunction)
{
	var found = ;
	var namespacesIds = $G.getMediaWikiConfig('wgNamespaceIds');
	for (var id in namespacesIds)
	{
		if (namespacesIds == namespaceNumber)
		{
			if (encodingFunction)
			{
				id = encodingFunction(id);
			}
			found.push(id);
		}
	}
	return found;
};

//
// Technical Settings
//
//! @warning avoid using catching parenthesis by adding "?:"
// 'http://...https://wiki386.com/pl/User:';
$G.strReHrefBase          = $G.getMediaWikiConfig('wgServer') + $G.getMediaWikiConfig('wgArticlePath').replace('$1',  '(?:' + $G.getNamespaceNames(2, encodeURIComponent).join('|') + ')') + ':';
// 'http://.../w/index.php\\?title=User:';
$G.strReHrefNewBase       = $G.getMediaWikiConfig('wgServer') + $G.getMediaWikiConfig('wgScript') + '\\?title=' + '(?:' + $G.getNamespaceNames(2, encodeURIComponent).join('|') + ')' + ':';
// 'http://...https://wiki386.com/pl/Specjal:Contributions';
$G.strReHrefAnonimBase    = $G.getMediaWikiConfig('wgServer') + $G.getMediaWikiConfig('wgArticlePath').replace('$1', encodeURIComponent($G.getMediaWikiConfig('wgFormattedNamespaces'))) + ':(?:Contributions|Wk%C5%82ad)/';
// 'http://...https://wiki386.com/pl/User_talk:';
$G.strBaseUserTalkURL     = $G.getMediaWikiConfig('wgServer') + $G.getMediaWikiConfig('wgArticlePath').replace('$1', encodeURIComponent($G.getMediaWikiConfig('wgFormattedNamespaces'))) + ':';

/*
	The bot:owner map.
	oBotToOwner update via script:
	https://github.com/Eccenux/wiki-replylinks/blob/main/botToOwnerGen.js

	The `window.oRepLinksCustomB2O` object is a "hook" for other wikis (non-plwiki).
*/
$G.oBotToOwner = window.oRepLinksCustomB2O || {'':''
,'.anacondabot':'.anaconda'
,'A.bot':'A.'
,'Ab.awbot':'Abronikowski'
,'Adas_bot':'Adziura'
,'AkBot':'Ankry'
,'AlohaBOT':'Patrol110'
,'AndrzeiBOT':'Andrzei111'
,'Andrzej94.bot':'Andrzej94'
,'AutoBot':'WarX'
,'AutoPur':'Pur'
,'BOTiczelli':'ABX'
,'Beau.bot':'Beau'
,'Beau.bot.admin':'Beau'
,'BlackBot':'Blackfish'
,'Bluebot~plwiki':'Blueshade'
,'Bocianski.bot':'Bocianski'
,'BossBot':'The_boss'
,'BotOks':'Skalee'
,'BuddBot':'Budd_Le_Toux'
,'Bugbot':'Lcamtuf'
,'BzBot':'Be%C5%BBet'
,'ClueBot~plwiki':'Mathel'
,'Cookie.bot':'Jwitos'
,'DodekBot':'Dodek'
,'DonnerJack.bot':'ABach'
,'Du%C5%A1an_Krehe%C4%BE_(bot)':'Du%C5%A1an_Krehe%C4%BE'
,'EgonBOT':'Egon~plwiki'
,'EinsBot':'Einsbor'
,'EmptyBot':'Emptywords'
,'EquadusBot~plwiki':'Equadus'
,'Erwin-Bot':'Ejdzej'
,'Escarbot':'Vargenau'
,'Faxebot':'Faxe'
,'G.bot':'Gregul'
,'Geonidiuszbot':'Geonidiusz'
,'Halibott':'Halibutt'
,'Holek.Bot':'Holek'
,'JarektBot':'Jarekt'
,'Jaszczurobot':'Jaszczurocz%C5%82ek'
,'Jozef-k.bot':'Jozef-k'
,'K.J.Bot':'Krzysiu_Jarzyna'
,'KamikazeBot':'Karol007'
,'Kamil-bBOT':'Kamil-b'
,'KangelBot':'Kangel'
,'Kbot':'Kb'
,'Kotbot':'Kotniski'
,'LA2-bot':'LA2'
,'Lambot':'Lampak'
,'LeafBot':'Leafnode'
,'LeonardoRob0t':'LeonardoGregianin'
,'MBot':'Maikking'
,'MagulBot':'Magul'
,'MalarzBOT':'Malarz_pl'
,'MalarzBOT.admin':'Malarz_pl'
,'MarciBOT':'Marcimon'
,'Margosbot':'Margos'
,'MastiBot':'Masti'
,'MastiBot.admin':'Masti'
,'Matbot':'Matusz'
,'Mateusz.bot':'Mateusz.ns'
,'Mathieu_Mars_.bot':'Mathieu_Mars'
,'MatmaBot':'Matma_Rex'
,'McBot~plwiki':'McMonster'
,'Merdis.bot':'Merdis'
,'Miner':'Saper'
,'MiszaBot':'Misza13'
,'Mr%C3%B3wka':'Matma_Rex'
,'NickyBot':'Wojciech_P%C4%99dzich'
,'NuxBot':'Nux'
,'OdderBot':'Odder'
,'Ohtnim':'Mintho'
,'Olafbot':'Olaf'
,'OpenBOT':'Openbk'
,'PBbot':'Peter_Bowman'
,'PL_Przemek.bot':'PL_Przemek'
,'Pacynka_malarza':'Malarz_pl'
,'Pawe%C5%82_Ziemian_BOT':'Pawe%C5%82_Ziemian'
,'PowerBot':'Powerek38'
,'Powiadomienia_ZB':'Matma_Rex'
,'PrzemuBot':'Przemub'
,'Pszcz%C3%B3%C5%82ka':'Therud'
,'PtjackBOT':'Ptjackyll'
,'Putorobot':'Putoro'
,'PwlBOT':'Polskawliczbach'
,'RavpawliszBot':'Ravpawlisz'
,'Rebot~plwiki':'Jagger'
,'RewersBot':'Nostrix'
,'RooBot':'Roo72'
,'RzuwigBot':'Rzuwig'
,'StankoBot':'Stanko'
,'Staszek_Jest_Jeszcze_Szybszy':'Staszek_Szybki_Jest'
,'Stv.bot':'Stv'
,'Sunridin.bot':'Sunridin'
,'Szczepan.bot':'Szczepan1990'
,'Szoltys-bot':'Szoltys'
,'TAMMBot':'TAMM'
,'TarBot':'Tar_L%C3%B3cesilion'
,'Tawbot':'Taw'
,'The_Polish_Bot':'The_Polish'
,'ToBot':'ToSter'
,'Trivelt.bot':'Trivelt'
,'Tsca.bot':'Tsca'
,'Ty221_bot':'Ty221'
,'UlvarBOT':'Ulv80'
,'Ver-bot':'Verwolff'
,'VindiBot':'Vindicator'
,'Vinne2.bot':'Vinne2'
,'WarXboT':'WarX'
,'Wargo32.exe':'Wargo'
,'WebmajstrBot':'Webmajstr'
,'WikitanvirBot':'Wikitanvir'
,'WiktorynBot':'Wiktoryn'
,'YarluBot':'Yarl'
};

/**
 * Helper class for gConfig.
 */
// eslint-disable-next-line no-unused-vars
class UserConfig {
	constructor(gConfig) {
		this.gConfig = gConfig;
		/** gConfig key/tag. */
		this.configKey = 'replylinks';
		/** Base info. */
		this.gadgetInfo = {
			name: 'Odpowiedzi z linkami',
			descriptionPage: 'Wikipedia:Narz%C4%99dzia/Odpowiedzi_z_linkami' 
		};
	}

	/** Get user option. */
	get(option) {
		let value = this.gConfig.get(this.configKey, option);
		// bool is mapped to '' or '1'
		if (option.startsWith('bool')) {
			value = value == '1';
		}
		return value;
	}

	/** Register messages. */
	async register() {
		// https://pl.wikipedia.orghttps://wiki386.com/pl/MediaWiki:Gadget-gConfig.js#L-147
		let options = ;
		options.push({
			name: `boolAddSignature`,
			desc: `Dodaj podpis.`,
			type: 'boolean',
			deflt: true,
		});

		// https://pl.wikipedia.orghttps://wiki386.com/pl/MediaWiki:Gadget-gConfig.js#L-147
		this.gConfig.register(this.configKey, this.gadgetInfo, options);
	}
}


/**
 * Get data "sent" from previous page.
 * 
 * (data from url param)
 * @private
 */
$G.autoNewSectionData = function()
{
	var data = {
		title: '',
		content: '',
	};
	var reParam = new RegExp ("&newsectionname=(*)", "i");	// ignoring lettercase
	var matches = reParam.exec(location.search);
	var sectxt;
	// append to input if all OK
	if (matches)
	{
		sectxt = decodeURIComponent(matches);
		data.content = ';'+sectxt+'\n\n';
	}

	//
	// Add some summary
	matches = /(.*)\]/.exec(sectxt);
	// append to input if all OK
	if (matches)
	{
		data.title = decodeURIComponent(matches);
	}

	return data;
};

/**
	@brief Inserting new section name and some info from the location string param.

	@note newsectionname url param used
*/
$G.autoNewSectionInit = function()
{
	var data = $G.autoNewSectionData();
	if (data.content.length <= 0)
	{
		return;
	}

	//
	// Standard new-section form
	//
	var elInput = document.getElementById('wpTextbox1');
	if (elInput)
	{
		// section content (link)
		if (data.content.length > 0)
		{
			let content = (this.options.boolAddSignature) ? data.content + '\n--'+'~'+'~'+'~'+'~' : data.content;
			// link + signature
			$(elInput).textSelection('setContents', content);
		}

		// setup post-save action(s)
		$G.setupPostSave(elInput);

		// section title
		elInput = document.getElementById('wpSummary');
		if (elInput)
		{
			if (data.title.length > 0)
			{
				elInput.value = data.title;
			}
		}
	}
};

/** @private Setup form for post-save action(s) like subscription. */
$G.setupPostSave = function(textbox)
{
	textbox = document.getElementById('wpTextbox1');
	var summary = document.querySelector('#wpSummary');
	if (!textbox || !summary) {
		console.error('', 'setupPostSave failed');
		return;
	}
	textbox.form.addEventListener('submit', function(){
		// auto-subscriptions: https://github.com/Eccenux/wiki-replylinks/issues/2
		$G.prepareSub(summary);
	});
};

/** @private Prepare for subscription. */
$G.prepareSub = function(summary)
{
	var state = {};
	// save state before submit: title, with time
	state.title = summary.value;
	state.time = (new Date()).getTime();
	// also save "relevant" user name
	state.user = $G.getMediaWikiConfig('wgRelevantUserName');
	$G.saveState(state);
};

/**
 * Max deltaT between submit and load .
 */
$G.maxValidTime = 60;

/** @private Check to make a subscription. */
$G.checkSub = function()
{
	var state = $G.readState();
	// basic state validation
	if (!(state && typeof state === 'object' && state.title)) {
		return;
	}
	// check for subscription data
	var sub = $G.findSub();
	if (!sub) {
		return;
	}
	// after submit check user is the same
	var user = $G.getMediaWikiConfig('wgRelevantUserName');
	if (user !== state.user) {
		return;
	}
	// if now()-time > maxtime => remove state
	var now = (new Date()).getTime();
	var deltaT = Math.round((now - state.time) / 1000);
	if (deltaT > $G.maxValidTime) {
		$G.removeState();
		console.warn(' stale state: now()-time: %d ', deltaT);
		return;
	}
	// if OK => subscribe; remove state
	$G.addSub(sub.pageTitle, sub.sectionTitle, sub.commentname);
	$G.removeState();
};

/** @private Find subscription data. */
$G.findSub = function()
{
	// check for subscription links first (or sub placeholders)
	var els = document.querySelectorAll('.ext-discussiontools-init-section-subscribeButton');
	if (!els.length) {
		return false;
	}
	// we could just get href from above, but sadly href is not avilable right after save...
	//var sub = new URL(el.querySelector('a').href);
	// so instead...

	// I hate this but it works 🙃
	var section = Array.from(document.querySelectorAll('.ext-discussiontools-init-section')).pop();
	if (!section) {
		return false;
	}
	var h = section.querySelector('.mw-headline');
	if (!h) {
		return false;
	}
	var pageTitle = mw.config.get('wgRelevantPageName');
	var sectionTitle = h.id;
	// convert thread-id to subscriptions format... sadly not the same :-/
	var commentname = h.getAttribute('data-mw-thread-id').replace(h.id, mw.config.get('wgUserName'));
	return {pageTitle:pageTitle, sectionTitle:sectionTitle, commentname:commentname};
};

/** @private Add subscription. */
/**
 * 
 * @param {String} pageTitle 
 * @param {String} sectionTitle Not encoded. E.g. "Odp:Próba wiadoma 3"
 * @param {String} commentname 
 */
$G.addSub = function(pageTitle, sectionTitle, commentname)
{
	new mw.Api().postWithEditToken( {
		action: 'discussiontoolssubscribe',
		formatversion : '2',
		page : pageTitle + '#' + sectionTitle,
		commentname : commentname,
		subscribe : 'true',
	} );
};

// on load
if ($G.getMediaWikiConfig('wgAction')=='view'
	&& $G.getMediaWikiConfig('wgCanonicalNamespace')=='User_talk')
{
	$(function(){
		setTimeout(function () {
			$G.checkSub();
		}, 100);
	});
}

// temporary subscription storage
$G._stateKey = 'userjs.replylinks.sub';

/** @private Save post-form state. */
$G.saveState = function(state)
{
	console.log('', 'saveState', state);
	localStorage.setItem($G._stateKey, JSON.stringify(state));
};
/** @private Read post-form state. */
$G.readState = function()
{
	var rawState = localStorage.getItem($G._stateKey);
	var state = JSON.parse(rawState);
	console.log('', 'readState', state);
	return state;
};
/** @private Clear post-form state. */
$G.removeState = function()
{
	localStorage.removeItem($G._stateKey);
};

/**
	@brief Adding reply links near user links.
*/
$G.addReplyLinks = function()
{
	//
	// When to run this...
	//
	// if (!document.getElementById('t-permalink') && !document.getElementById('t-ispermalink') )	// almost always
	if ($G.getMediaWikiConfig('wgCurRevisionId')==0)	// no versioning available
	{
		return;
	}

	//
	// Get viewed page version link (may be something in history)
	//
	var hrefPermalink;
	// this one means it is a perma link (comparing versions, showing one specfic version and such)
	if (document.location.href.indexOf('&oldid=')!=-1)
	{
		hrefPermalink = document.location.href.replace(/#.+$/,'');
	}
	// get latest
	else
	{
		hrefPermalink = '{{fullurl:' + $G.getMediaWikiConfig('wgPageName') + '|oldid=' + $G.getMediaWikiConfig('wgCurRevisionId') + '}}';
	}

	//
	// Find user pages links and put links into them
	//

	//
	// create regexpes for user links
	var reHref = new RegExp ($G.strReHrefBase + "(*)$", "i");	// with ignore case
	var reHrefNew = new RegExp ($G.strReHrefNewBase + "(*)", "i");	// with ignore case
	var reHrefAnonim = new RegExp ($G.strReHrefAnonimBase + "(*|*:+)$", 'i');

	//
	// main container for content (also for diff meta-data, history listing)
	var bodyContent = document.querySelector('#bodyContent,#mw_contentholder');
	if (!bodyContent)
	{
		console.warn('', 'bodyContent not found, skipping');
		return;
	}

	//
	// first header as a default section
	var secAbove = {
		'id' : bodyContent.id,	// for link hash
		'text' : $G.parseSectionText($G.getMediaWikiConfig('wgPageName')).replace(/_/g, ' ')	// for display
	};
	var secReplyText = $G.i18n;
	//
	// in search for links... and section headers
	//var a = $G.getElementsByTagNames ('A,SPAN', bodyContent);
	var a = Array.from(bodyContent.querySelectorAll(':is(h1,h2,h3,h4),a'));
	for (var i = 0; i < a.length; i++)
	{
		var nodeName = a.nodeName.toLowerCase();
		var currentNode = a;
		
		//
		// section setup
		if (nodeName.indexOf('h') === 0) // hX
		{
			secAbove.id = currentNode.id;
			// sometimes there could be a link in the header (maybe some more)
			secAbove.text = $G.stripSectionNumbering($G.parseSectionText(currentNode.innerHTML), secAbove.id);
			continue;
		}
		
		//
		// add a reply if this is a user link (also adds whois link to anons)
		if (nodeName == 'a' && a.href != '' && a.getAttribute('href').indexOf('#')==-1)
		{
			var anonimous = false;
			var matches = (a.className.indexOf('new')>=0) ? reHrefNew.exec(a.href) : reHref.exec(a.href);
			if (!matches)
			{
				matches = reHrefAnonim.exec(a.href);
				anonimous = true;
			}
			// botname translation due to match with nonanonimous link
			else if ($G.oBotToOwner] != undefined)
			{
				matches = $G.oBotToOwner];
			}

			if (matches)
			{
				//
				// creating reply href
				// var userName = matches;
				var hrefReply = $G.strBaseUserTalkURL + matches + '?action=edit&section=new';
				//
				// and now to create and add data for the new reply section name
				var newSectionName = '';
				hrefReply += '&dtenable=0';	// disable dicussion tools
				hrefReply += '&newsectionname=' + encodeURIComponent(newSectionName);
				var newEl = document.createElement('small');
				var newA = document.createElement('a');
				newA.className = 'gadget-replylinks-reply';
				newA.setAttribute('href', hrefReply);
				newA.setAttribute('title', $G.i18n+secAbove.text);
				newA.appendChild(document.createTextNode('+']'));
				newEl.appendChild(newA);
				$G.insertAfterGivenElement(a,newEl);

				// Anonimous whois checker
				if (anonimous)
				{
					newA = document.createElement('a');
					newA.className = 'gadget-replylinks-whois';
					newA.setAttribute('href', $G.hrefOnlineIPwhois+matches);
					newA.setAttribute('title', 'IP whois');
					newA.setAttribute('target', '_blank');
					newA.setAttribute('rel', 'noopener noreferrer');
					newA.appendChild(document.createTextNode(''));
					newEl.appendChild(newA); // appending to previously created
					//i++;	// a is a dynamic list
				}
			}
		}

	}
};

/**
	@brief Inserting \a newEl element after given \a el element.

	@param el
		Element object to insert after
	@param newEl
		(new) element object to insert
\* ===================================================== */
$G.insertAfterGivenElement = function (el, newEl)
{
	if (el.nextSibling)
	{
		el.parentNode.insertBefore(newEl, el.nextSibling);
	}
	else
	{
		el.parentNode.appendChild(newEl);
	}
};

/**
	@brief Parses Section HTML to Text

	Stripping HTML tags from the HTML text and cleansing of some wikicode

	@param html
		The html string
	@returns Stripped text
*/
$G.parseSectionText = function (html)
{
	// with global match (all will be replaced)
	html = html.replace(/<\S*>/g, '');
	// replace cut anything in brackets  (editing sections links and such)
	html = html.replace(/\]*\]/,'');
	// replace wiki stuff with null
	html = html.replace(//g,'');
	// trim (right,left)
	html =  html.replace(/*$/,'').replace(/^*/,'');
	return html;
};

/**
	@brief Strips section numbering if present.

	@param sectionText Text of the section.
	@param sectionId Id of the section.
	@returns Stripped text
*/
$G.stripSectionNumbering= function (sectionText, sectionId)
{
	// strip section numering
	if (sectionText.search(/^+ /) > -1)
	{
		var isNumbered = true;
		if (sectionId.search(/^+_/) > -1)
		{
			if (sectionText.replace(/^(+) .*/, '$1').length == sectionId.replace(/^(+)_.*/, '$1').length)
			{
				isNumbered = false;
			}
		}
		if (isNumbered)
		{
			sectionText = sectionText.replace(/^+ (.*)/, '$1');
		}
	}
	return sectionText;
};


// gConfig init
mw.hook('userjs.gConfig.ready').add(function (gConfig) {
	let userConfig = new UserConfig(gConfig);
	$G.prepareConfig(userConfig); // fires 'userjs.replylinks.configReady'
});

//
// Init
//
// add text to textbox
// if ($G.getMediaWikiConfig('wgAction')=='edit' 
// 	&& $G.getMediaWikiConfig('wgCanonicalNamespace')=='User_talk')
// note, wgAction=view for dynamic new-section
if (location.search.indexOf('newsectionname=') > 0 
	&& $G.getMediaWikiConfig('wgCanonicalNamespace')=='User_talk')
{
	$.when($.ready, mw.loader.using('jquery.textSelection')).done(function () {
		// init after config if gConfig is available
		if (mw.loader.getState('ext.gadget.gConfig') !== null) {
			mw.hook('userjs.replylinks.configReady').add(function(){
				$G.autoNewSectionInit();
			});
		// init directly using default config
		} else {
			$G.autoNewSectionInit();
		}
	});
}
// add links
if ($G.getMediaWikiConfig('wgAction')!='edit' 
	&& $G.getMediaWikiConfig('wgAction')!='submit')
{
	$($G.addReplyLinks);
}

/* -=-=-=-=-=-=-=-=-=-=-=-
	Gadget code : END
 -=-=-=-=-=-=-=-=-=-=-=- */
// </nowiki>
})(oRepLinks);