//Bawl[https://en.wikipedia.org/wiki/User:Alexis_Jazz/Bawl] is a userscript to add comments to discussions and edit pages in general with more features and options than usual. Report issues on the talk page. If you see short garbage variable names you are reading the compact version of this script.
/*globals $:false,mw:false,OO:false*/
if ( typeof window.Bawl == 'undefined' || typeof window.Bawl.nodeName != 'undefined' ) { //window.Bawl could also exist if there's a section named "Bawl"
window.Bawl = {};
var Bawl = window.Bawl;
Bawl.fyi = 'Bawl is public domain, irrevocably released as WTFPL Version 2[www.wtfpl.net/about/] by its author, Alexis Jazz. If you don\'t like that or think it\'s invalid where you live you may use this under CC BY-SA 3.0, CC BY 2.5 or CC BY 4.0 instead. Your choice.';
Bawl.run = function(){
'use strict';
var BawlBasicmsgsObj = {};
var BawlWikiMsgsObj = {};
var BawlmsgsObj = {};
Bawl.timestampInit = new Date().getTime();
Bawl.semiRandom = Bawl.timestampInit.toString().slice(-4); //last 4 digits of current timestamp. Won't change as long as you don't leave the page. Used in regular expressions for temporary placeholders (see Bawl.safeText) so you can discuss the actual placeholders without them getting replaced
Bawl.openingFormInProgressDelay = 1500; //how many ms it may take to open a form. It's usually only 1 or 2, but if oojs-ui-core isn't available yet and your device is very old, maybe longer. This value is used to throw an error if the form didn't open in time.
Bawl.purpleBGJoker = $('.BawlPurpleBG').length; //if some joker decides to post an element with the "BawlPurpleBG" class (which otherwise indicates an ongoing or stuck process), Bawl won't break as we subtract those
Bawl.VERSIONDATE = '22:25, 9 June 2022 (UTC)';
Bawl.nowikiOpen = '<nowiki>';//not used anywhere but this way the minifier won't remove it. needed because MediaWiki parses JS pages as wikitext, sometimes resulting in maintenance categories
Bawl.nowikiTagName = 'nowiki';//to avoid entering nowiki tags in replacements
Bawl.userName = mw.config.get('wgUserName');
Bawl.userLang = mw.config.get('wgUserLanguage');
if ( Bawl.userName ) {
	Bawl.userNameUnderscore = Bawl.userName.replace(/ /g, '_');
}
Bawl.userNSLinkRegExpPart = 'User:|User_talk:';
Bawl.userNSWikitextRegExpPart = '[Uu]ser:|[Uu]ser[ _]talk:';
for (Bawl.userNSInt=0;Bawl.userNSInt<Object.values(mw.config.get('wgNamespaceIds')).length;Bawl.userNSInt++) { //some wikis have multiple names for the same namespace (like gendered namespaces), nobody knows what will be used in links or wikitext
	if ( [2,3].includes(Object.values(mw.config.get('wgNamespaceIds'))[Bawl.userNSInt]) && ! ['user','user_talk'].includes(Object.keys(mw.config.get('wgNamespaceIds'))[Bawl.userNSInt]) ) {
		Bawl.userNSLinkRegExpPart = Bawl.userNSLinkRegExpPart + '|' + encodeURIComponent(Object.keys(mw.config.get('wgNamespaceIds'))[Bawl.userNSInt].slice(0,1).toUpperCase()) + mw.util.escapeRegExp(encodeURIComponent(Object.keys(mw.config.get('wgNamespaceIds'))[Bawl.userNSInt].slice(1))) + ':';
		Bawl.userNSWikitextRegExpPart = Bawl.userNSWikitextRegExpPart + '|[' + Object.keys(mw.config.get('wgNamespaceIds'))[Bawl.userNSInt].slice(0,1).toUpperCase() + Object.keys(mw.config.get('wgNamespaceIds'))[Bawl.userNSInt].slice(0,1) + ']' + mw.util.escapeRegExp(Object.keys(mw.config.get('wgNamespaceIds'))[Bawl.userNSInt].slice(1)).replace(/_/g,'[ _]') + ':';
	}
}
if ( mw.config.get('wgServer').match('http') ) {
	Bawl.serverName = mw.config.get('wgServer'); //beta cluster
} else {
	Bawl.serverName = 'https:' + mw.config.get('wgServer');
}
Bawl.projectIsSULWiki = window.location.hostname.match(/\.(wikipedia|wmflabs|wiktionary|wikiquote|wikinews|wikisource|wikibooks|wikiversity|wikivoyage|wikidata|wikimedia)\.org$/);
if ( window.location.hostname.match(/wikitech/) ) {//wikitech.wikimedia.org is NOT a SUL wiki
	Bawl.projectIsSULWiki = false;
}
Bawl.modules = {}; //creating empty object for modules to store their things to avoid conflicts
Bawl.msgsObj = {};
Bawl.basicmsgsObj = {};
Bawl.wikiMsgsObj = {};
var api = new mw.Api();
Bawl.kittehStuck = '<a href="https://commons.wikimedia.org/wiki/File:Kitten_stuck_on_top_of_a_tree_trunk.jpg"><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/6/69/Kitten_stuck_on_top_of_a_tree_trunk.jpg/480px-Kitten_stuck_on_top_of_a_tree_trunk.jpg"/><br/><small>CC BY 2.0 / Guyon Morée</small></a>';
Bawl.summaryCredit = ' [[[w:en:User:Alexis Jazz/Bawl|Bawl!]]]';
Bawl.summaryCreditDE = ' [[[w:de:Benutzer:Alexis Jazz/Bawl|Bawl!]]]';
Bawl.wikiMsgsObj.mul = { //multilingual and default texts. Messages that end up in wikitext or edit summaries. Selected using wgPageContentLanguage
	'difflinkname':' (DIFF $8)',
	'difflinknamebare':'DIFF $5',
	'difflinknameprevnext':' (DIFF ~$9)',
	'pageHistoryLinkName':'$5 (HISTORY)',
	'postCommentSummaryPost':'replying to USER' + Bawl.summaryCredit,
	'postSubsectionSummaryPost':'new subsection: [[#SUBSECTION|SUBSECTION]]' + Bawl.summaryCredit,
	'postCommentSummaryNewSection':'/* NEWSECTION */ new sectionSUMMARY' + Bawl.summaryCredit,
	'postCommentSummaryMovedSection':'Moved section from SOURCE to TARGET' + Bawl.summaryCredit,
	'editCommentSummary':'editing commentUSER' + Bawl.summaryCredit,
	'summaryCredit':Bawl.summaryCredit,
	'quoteOpen':'<q>', //only used if there is no talk quote inline template
	'quoteClose':'</q>',
	'refOpen':'<ref name="REFNAME">',
	'refClose':'</ref>'
};
Bawl.wikiMsgsObj.nl = {
	'postCommentSummaryPost':'reactie op USER' + Bawl.summaryCredit,
	'postSubsectionSummaryPost':'nieuwe subsectie: [[#SUBSECTION|SUBSECTION]]' + Bawl.summaryCredit,
	'postCommentSummaryNewSection':'/* NEWSECTION */ nieuw onderwerpSUMMARY' + Bawl.summaryCredit,
	'postCommentSummaryMovedSection':'Sectie verplaatst van SOURCE naar TARGET' + Bawl.summaryCredit,
	'editCommentSummary':'wijzig reactieUSER' + Bawl.summaryCredit,
};
Bawl.wikiMsgsObj.de = {
	'postCommentSummaryPost':'Antwort an USER' + Bawl.summaryCreditDE,
	'postSubsectionSummaryPost':'neuen Teilabschnitt: [[#SUBSECTION|SUBSECTION]]' + Bawl.summaryCreditDE,
	'postCommentSummaryNewSection':'/* NEWSECTION */ neuen AbschnittSUMMARY' + Bawl.summaryCreditDE,
	'postCommentSummaryMovedSection':'Abschnitt verschiebt von SOURCE nach TARGET' + Bawl.summaryCredit,
	'editCommentSummary':'Kommentar bearbeitenUSER' + Bawl.summaryCreditDE,
	'summaryCredit':Bawl.summaryCreditDE
};
if ( typeof BawlWikiMsgsObj != 'undefined' && BawlWikiMsgsObj[ mw.config.get('wgPageContentLanguage') ] ) { // BawlwikiMsgsObj could be specified in common.js before Bawl is loaded
	Bawl.wikiMsgs = Object.assign(Bawl.wikiMsgsObj.mul, BawlWikiMsgsObj[ mw.config.get('wgPageContentLanguage') ]);
} else if ( Bawl.wikiMsgsObj[ mw.config.get('wgPageContentLanguage') ] ) {
	Bawl.wikiMsgs = Object.assign(Bawl.wikiMsgsObj.mul, Bawl.wikiMsgsObj[ mw.config.get('wgPageContentLanguage') ]);
} else {
	Bawl.wikiMsgs = Bawl.wikiMsgsObj.mul;
}
Bawl.msgsObj.mul = { //multilingual and default texts, selected using wgUserLanguage. Messages that are used beyond the initial opening of the form.
	'UILabelLoad':'Load',
	'editLinks':'Insert links to edit my comments',
	'replySecLink':'Add extra reply button for the section starter to the bottom of the section if there are >3 commenters',
	'nSecLink':'Insert link to add a new section',
	'nSecBottomLink':'Insert link to add a new section at the end of the page',
	'secLinks':'Insert links to add subsections',
	'sectionIsNewTO':'Take over URLs containing section=new',
	'inputBoxTO':'Take over <a href="https://www.mediawiki.org/wiki/Extension:InputBox" target="_new">InputBoxes</a>',
	'mwuibuttonTO':'Take over new section buttons with .mw-ui-button and .oo-ui-buttonElement-button class',
	'hideArchived':'Hide links within elements with the "archived" or "boilerplate" class',
	'editFullPage':'Enable full page editing',
	'editFullSection':'Enable full section editing',
	'dateLinksIconSection':'Add link/permalink generator icon for sections',
	'dateLinksIconSectExtra':'Also provide non-permalink',
	'dateLinksIcon':'Permalink generator for comments',
	'dateLinksIconAlt':'When the reply form is open, use comment link icons in the same section to insert anchored links to those comments',
	'thankLink':'',
	'reverseSectionOrder':'Reverse section order',
	'collapsible':'Collapsible sections',
	'autoCollapse':'Automatically collapse sections that contain no new comments since your last visit',
	'collapArticle':'Collapsible sections on non-talk pages', //T306660 is pretty cool. Bawl had a head start to implement it quickly.
	'collapArticleDefault':'Collapse all non-talk page sections by default',
	'collapArticleDefaultFloatingToC':'Floating ToC',
	'collapArticleDefaultNoToC':'Hide ToC',
	'dateLinksLocalTime':'Display signature dates in local time',
	'dateLinksLocalTimeUserOptTZ':'Use timezone from account preferences',
	'dateLinksLocalTimeRelative':'Show relative date (15 days ago)',
	'dateLinksLocalTimeAbsolute':'Show actual date (1 May 2022)',
	'dateLinksLocalTime12H':'Use 12-hour clock (7:15 PM)',
	'dateLinksLocalTimeNumMonth':'Show months as a number',
	'dateLinksLocalTimeLongMonth':'Show full month name (December)',
	'dateLinksLocalTimeWeekday':'Show abbreviated weekday (Tue)',
	'dateLinksLocalTimeWeekdayFull':'Show full weekday (Tuesday)',
	'cureDTBlueStreak':'Automatically fade out comment highlighting by DiscussionTools',
	'UILabelInterface':'Interface',
	'tosNag':'Annoy me with the ToS all the time (you can disable this!)',
	'markup':'Enable basic markup toolbar',
	'pingDropDown':'Drop-down menu to add user mentions',
	'pingDropDownAt':'Open user mentions menu by entering @',
	'onetimetools':'Add icon for search and replace, section moving and other advanced tools',
	'clearEditFullPage':'Hide page content when editing full page',
	'editNotice':'Display <a href="https://en.wikipedia.org/wiki/Wikipedia:Editnotice" target="_new">editnotices</a>',
	'wrongUI':'Put buttons on the wrong side like <a href="' + mw.config.get('wgServer') + mw.config.get('wgArticlePath').replace('$1', 'm:Special:MyLanguage/Talk_pages_project/Feature_summary') + '" target="_new">DiscussionTools</a>',
	'previewAboveFull':'Render preview above form instead of below when editing a full page/section',
	'previewAboveOther':'Render preview above form instead of below in other situations',
	'checkNewComments':'Check for new comments when opening form/preview',
	'limitWidth':'Limit interface width',
	'warnExit':'Warn before leaving the page with an entered comment',
	'UIfontSize':'Interface size:',
	'customSummary':'Field to add your own message to the edit summary and checkbox to mark edits as minor',
	'customBackground':'Custom background URL',
	'bgicon':'Put speech balloon on form background when commenting and marker when editing a comment',
	'UILabelEditing':'Editing',
	'livePreview':'Live preview',
	'bracketToForm':'Move to link insertion form when typing [[ or ((',
	'autoPing':'Auto-mention',
	'quoteSelect':'Include highlighted/selected text as quote with mention',
	'AWBtypos':'Automatically apply <a href="https://www.wikidata.org/wiki/Q6585066">AutoWikiBrowser RegExTypoFix</a>',
	'AWBtypoPreview':'Also enable RegExTypoFix on preview',
	'AWBtyposCustomTitle':'Page title for RegExTypoFix (not needed on WMF wikis)',
	'enableCI':'Enable custom inserts',
	'enableCIThatRunCmt':'Enable custom regular expressions that are applied to comments only',
	'enableCIThatRun':'Enable custom regular expressions that are automatically applied on preview/publish',
	'monospace':'Use monospace font in editing window by default (switch with ctrl+alt+m)',
	'markdown':'Convert <a href="https://en.wikipedia.org/wiki/Markdown" target="_new">Markdown</a> markup language (partial implementation)',
	'bbcode':'Convert <a href="https://en.wikipedia.org/wiki/BBCode" target="_new">BBCode</a> markup language',
	'outdent':'Automatically outdent when exceeding level:',
	'sumSnippet':'Automatically add a snippet of your comment to the edit summary',
	'saveDraft':'Try to recover unsent comments of >100 characters after unexpected exit',
	'pingText':'Mention text:',
	'pingTextInSection':'Mention text when pressing a speech balloon within the same section:',
	'rewritun':'Rewrite external URLs to internal ones where possible, clean internal links',
	'rewriteOnBlur':'Rewrite external URLs and apply regular expressions when the main text input loses focus',
	'rewritunOther':'CSS selector for other elements to rewrite URLs for (on blur):',
	'runCIOther':'CSS selector for other elements to apply regular expressions to (on blur):',
	'AWBtyposOther':'CSS selector for other elements to apply AutoWikiBrowser RegExTypoFix to (on blur):',
	'UILabelSubscribe':'Subscriptions (WIP)',
	'stalkAddSubLinks':'Add icons to subscribe to sections',
	'stalkMaxSubs':'Maximum page subscriptions (subscriptions to multiple sections on one page count as one page subscription)',
	'stalkAutoSub':'Automatically subscribe when replying',
	'stalkSyncToPrefs':'Synchronize subscriptions to account preferences. Takes a little extra bandwidth. Subscriptions object will be limited to 65535 bytes. Allows your subscriptions to be shared across multiple devices/browsers.',
	'markNewCmts':'Mark timestamps of new comments since your last visit to the page',
	'markNewCmtsSubbed':'Mark timestamps of new comments in sections you subscribed to since your last visit to the page',
	'markNewCmtsBorder':'Add one-sided border to new comments since your last visit to the page',
	'stalkAddCycleBtn':'Button to scroll to the next unread comment on a page',
	'stalkAddCycleBtnSubbed':'Button to scroll to the next unread comment on a page in sections you subscribed to',
	'stalkMarkReadScroll':'Mark comments as read when you scroll them into view',
	'stalkWatchListCmts':'[WIP] Show unread comments from subscribed sections on watchlist',
	'stalkTackOnEcho':'Notify me about new comments in the general notification area',
	'stalkInterval':'Outside the watchlist, check for new comments no more than every:',
	'UILabelAdvanced':'Advanced',
	'showRisky':'Show expert settings',
	'shortcuts':'Enable keyboard shortcuts',
	'submitShortcut':'Use ctrl+enter to submit form, ctrl+shift+enter to mark edit as minor and submit form',
	'hideDT':'Hide reply links from DiscussionTools',
	'hideDTSub':'Hide subscription links from DiscussionTools if Bawl subscription links are enabled',
	'hideAdvFE':'Hide/take over reply tools from advanced mobile mode',
	'loadMinervaD':'Load links on Minerva (desktop)',
	'loadMinervaM':'Load links on Minerva (mobile)',
	'methodLocator':'Detect comments by Bawl locator',
	'methodLegacy':'Detect comments by legacy method (essential, do not disable this)',
	'extendedSigDetect':'Slighty improve detection rate of legacy signatures at the cost of slightly more CPU-time',
	'useLocator':'Add invisible comment locator to my comments (recommended setting: enabled)',
	'enableOnDiffOldId':'Enable Bawl on diffs/old revisions. Terrible idea. Don\'t do it.',
	'theStranger':'Add edit links to comments by others. Expect funky shit',
	'ninjaLoader':'Load links within page content only after pressing a section header',
	'addLinkTS':'Only add reply link for the first comment of each section',
	'killswitch':'If adding links takes more than 8 seconds stop adding links',
	'debug':'Enable test/debug mode',
	'dbgLimit':'Maximum debug messages to log to console:',
	'afterPost':'After posting:',
	'afterPostReload':'Never re-parse the page, just reload instead',
	'watchlist':'Watchlist setting:',
	'watchlistexpiry':'Watchlist expiration: ',
	'editor':'Default editor:',
	'editorSwitch':'Enable switching between editors',
	'RLmasq':'Masquerade as reply-link',
	'grayscale':'Grayscale icons',
	'saveTo':'Save/erase settings to/from:',
	'prefLabelBrowser':' (browser)',
	'prefLabelAccountPrefs':' (account preferences)',
	'prefLabelGlobalPrefs':' (global preferences)',
	'watchlistexpirydays':'DAYS days',
	'watchlistexpiryplusdays':'+DAYS days',
	'BawlCustomInsertPlaceholder':'foo[BAWLCRT]barNUM:<<[AUTOPOST[CMT|NONCMT]]bar>>',
	'BawlCustomInsertThatRunPlaceholder':'/[Ff]ooNUM/bar/g',
	'pingTextPlaceholder':'Yo [[User:PINGUSER|PINGUSER]],',
	'pingTextInSectionPlaceholder':'[[CMTLINK|^]] [[User:PINGUSER|PINGUSER]],',
	'UIfontSize0875em':'0.875em',
	'UIfontSizeTiny':'Tiny!',
	'UIfontSizeSmall':'Small',
	'UIfontSizeMedium':'Medium',
	'UIfontSizeLarge':'Large',
	'UIfontSizeHuge':'Huge',
	'linkafter':'Just show a link (fastest)',
	'parse':'Parse comments and new sections in place (fast)',
	'parsecmtonly':'Parse comments in place (fast)',
	'parsepage':'Re-parse page without reloading (slower)',
	'reloadafter':'Reload the page (slowest)',
	'saveToAccountPrefs':'Account preferences',
	'saveToGlobalPrefs':'Global preferences',
	'saveToBrowser':'This browser',
	'resetPreferencesButtonUnlock':'Unlock',
	'resetLocalStorBawlSubs':'Erase subscriptions',
	'resetPreferencesButtonLocalStor':'Erase other localStorage items',
	'editorSource':'Source',
	'editorVisualLight':'VisualLight',
	'commentDone':'Done!',
	'commentPostedThankYou':' Thank you for using <a href="https://en.wikipedia.org/wiki/User:Alexis_Jazz/Bawl" target="_new">Bawl!</a>',
	'nopingNotify':'This user doesn\'t want their username to be linked.',
	'replyToTitle':'USER',
	'newSectionTitle':'Add section',
	'editFullSectionTitle':'Edit section',
	'editTitle':'Change comment',
	'restoredDraft':'Restored draft',
	'removeDraft':'Deleted draft',
	'insertLinkLink':'https://www.example.com/lorem/ or article title',
	'insertLinkName':'Link name (optional)',
	'bawl':'Bawl!',
	'messedUp1':'Awwww shit.',
	'messedUp2':'I deeply apologize, something has gone terribly wrong.',
	'messedUp3':'Please file this pre-filled out error report.',
	'messedUp4':'If you can\'t edit English Wikipedia you can file the report on META or [[NLWIKT|Dutch Wiktionary]] instead.',
	'cITSbuttonMenu':'@',
	'replaceButton':'Replace',
	'replaceAllButton':'Replace all',
	'AWBtyposButton':'AWB RegExTypoFix',
	'genBulletedList':'Generate bulleted list of links',
	'genNumberedList':'Generate numbered list of links',
	'moveContentToPage':'Move content to page',
	'allowPageCreation':'Allow page creation when moving',
	'archiveSection':'Wrap section in closed/archived block',
	'subsHeader':'Section subscriptions',
	'subsSeenIt':'Seen it!',
	'readYaCmts':'There are unread comments waiting for you.',
	'sectionTitleNotUnique':'A section with that title already exists',
	'reportBug':'bug?',
	'tackOnNewCmt':'New comment in "SECTION"',
	'newLines':'The page has been changed since you loaded it. The following lines were added or changed:',
	'matchedRETF':'Matched <code>REGEXP</code> (WORD)',
	'rewritunOtherPlaceholder':'#wpSummary,.morebits-dialog textarea',
	'nevermind':'Never mind that, it\'s fine!',
	'refbutton':'Insert as reference',
};
Bawl.basicmsgsObj.mul = { //multilingual and default texts, selected using wgUserLanguage. Messages that are required to load the script and open the form
	'htmlform-submit':'  📢  ', //regular spaces are stripped, figure spaces are not
	'preview':'  👁  ',
	'showdiff':'Diff',
	'cancel':'  🗑️  ',
	'saveprefs':'Save',
	'restoreprefs':'Restore all default settings',
	'mw-widgets-copytextlayout-copy-success':'Copied to clipboard.',
	'mw-widgets-copytextlayout-copy-fail':'Failed to copy to clipboard.',
	'tooltip-summary':'Edit summary',
	'actionfailed':'Action failed',
	'revid':'revision $5',
	'diff-empty':'(no differences)',
	'anoneditwarning':'Unless you <a href="' + mw.config.get('wgArticlePath').replace('$1', 'Special:UserLogin') + '?returnto=' + encodeURIComponent(mw.config.get('wgPageName')) + '">log in</a> or <a href="' + mw.config.get('wgArticlePath').replace('$1', 'Special:CreateAccount') + '?returnto=' + encodeURIComponent(mw.config.get('wgPageName')) + '">sign up</a> your IP address will be publicly visible if you post a message!',
	'subject':'',
	'newsection':'New section',
	'bold':' B ',
	'italic':' I ',
	'strike':'xyz',
	'specialcontribs':'Special:Contributions',
	'specialdiff':'Special:Diff',
	'specialpermalink':'Special:PermanentLink',
	'thankLink':'Icon to thank for comments',
	'flow-thanks-confirmation-special':'Do you want to publicly send thanks for this comment?',
	'editsectionhint':'Edit section: $1',
	'tooltip-ca-addsection':'Start a new section',
	'AWBtyposTitle':'',//AWB RETF page title
	'newline':'',//name of template that transcludes a pure newline
	'smiley':'',//Template:Smiley title
	'atops':'',//Archive top substitution template
	'abots':'',//Archive bottom substitution template
	'tq':'',//Talk quote inline template or its most common redirect
	'citemap':'',//local JSON with template map and parameter map for citation templates
	'lockicon':'',//is Twemoji2 1f512.svg available on this wiki?
	'notification-timestamp-ago-seconds':'((PLURAL:$1|$1s))',
	'notification-timestamp-ago-minutes':'((PLURAL:$1|$1m))',
	'notification-timestamp-ago-hours':'((PLURAL:$1|$1h))',
	'notification-timestamp-ago-days':'((PLURAL:$1|$1d))',
	'feedback-back':'Back',
	'editingold':'<strong>You are editing an old revision of this page.</strong> If you save it, changes that are newer than this revision will be lost.',
	'history_small':'history',
	'minoreditletter':'m',
	'tooltip-minoredit':'This is a minor edit',
	'ipbemailban':'Sending email',
	'ipb-disableusertalk':'Editing their own talk page',
	'log-action-filter-block-reblock':'Block modification',
	'unblock':'Unblock user',
	'block':'Block user',
	'ipboptions':'2 hours:2 hours,1 day:1 day,3 days:3 days,1 week:1 week,2 weeks:2 weeks,1 month:1 month,3 months:3 months,6 months:6 months,1 year:1 year,indefinite:infinite',
	'ipbother':'Other time:',//for non-English the translation includes a note sometimes that the entered value must be in English
	'TZ':'UTC',
	'tosNagText':'By submitting your input you agree to release your work under the license of this project and to comply with all applicable terms and conditions of this site. (if you are reading this the proper disclaimer failed to load)',
	'wikimedia-mobile-license-links':'<a href="https://creativecommons.org/licenses/by-sa/3.0/" title="Definition of the Creative Commons Attribution-ShareAlike License" target="_blank">CC BY-SA 3.0</a>+<a href="https://www.gnu.org/licenses/fdl.html" title="Definition of the GFDL" target="_blank">GFDL</a>',
	'wikimedia-copyright':'<a href="https://foundation.wikimedia.org/wiki/Terms_of_Use">Terms of Use</a>',//not the full msg as we only extract the ToU link from this
	'unblocked':'[[user]] has been unblocked.',
	'blockedtitle':'User is blocked',
	'English':'English',//to inform the block period must be entered in English
	'action-edit':'Edit this page',
	'today-at':'$1',
	'yesterday-at':'Yesterday at $1',
	'days':'((PLURAL:$1|$1 day|$1 days))',
	'months':'((PLURAL:$1|$1 month|$1 months))',
	'years':'((PLURAL:$1|$1 year|$1 years))',
	'ago':'$1 ago',
	'tag-filter-submit':'Filter'
};
Bawl.testValidJSON = function (string) {
		if ( string == null ) {
			Bawl.debug('you didn\'t think null would be a valid JSON, did you?');
			return false;
		}
		try {JSON.parse(string);} catch (e) {return false;}
		return true;
};
Bawl.basicmsgs = Bawl.basicmsgsObj.mul; //just in case everything goes to shit
if ( typeof BawlBasicmsgsObj != 'undefined' && BawlBasicmsgsObj[ Bawl.userLang ] ) { // BawlBasicmsgsObj could be specified in common.js before Bawl is loaded
	Bawl.basicmsgs = Object.assign(Bawl.basicmsgsObj.mul, BawlBasicmsgsObj[ Bawl.userLang ]);
	Bawl.wikiTimezone = Bawl.basicmsgs.TZ;
} else if ( window.localStorage.BawlBasicLang && Bawl.testValidJSON(window.localStorage.BawlBasicLang) && JSON.parse(window.localStorage.BawlBasicLang)[Bawl.userLang] && JSON.parse(window.localStorage.BawlBasicLang)[Bawl.userLang].version == Bawl.VERSIONDATE ) {
	Bawl.basicmsgs = Object.assign(Bawl.basicmsgsObj.mul, JSON.parse(window.localStorage.BawlBasicLang)[Bawl.userLang]);
	Bawl.wikiTimezone = Bawl.basicmsgs.TZ;
} else {
	Bawl.basicLangKeys = ['#timel:e','#special:Contributions','#special:Permalink','#special:Diff','#special:PageHistory','#language:en','#expr:2/2','#ifexist:Template:truenewline|truenewline','#ifexist:Template:smiley|smiley','#ifexist:Project:RETF|Project:RETF','#ifexist:Template:atops|atops','#ifexist:Template:abots|abots','#ifexist:Template:tq|tq','#ifexist:Media:Twemoji2 1f512.svg|Twemoji2 1f512.svg','MediaWiki:revid','htmlform-submit','preview','showdiff','cancel','saveprefs','restoreprefs','mw-widgets-copytextlayout-copy-success','mw-widgets-copytextlayout-copy-fail','tooltip-summary','actionfailed','diff-empty','anoneditwarning','subject','newsection','thanks-desc','flow-thanks-confirmation-special','thanks-submit','editsectionhint','tooltip-ca-addsection','notification-timestamp-ago-seconds','notification-timestamp-ago-minutes','notification-timestamp-ago-hours','notification-timestamp-ago-days','feedback-back','editingold','history_small','minoreditletter','tooltip-minoredit','actioncomplete','ipbemailban','ipb-disableusertalk','log-action-filter-block-reblock','unblock','block','blockedtitle','unblocked','ipboptions','ipbother','checkbox-none','wikimedia-mobile-license-links','wikimedia-copyright','MediaWiki:Copyrightwarning','action-edit','today-at','yesterday-at','days','months','years','ago','tag-filter-submit'];
	Bawl.basicMsgsWikiText = '';
	for (Bawl.basicLangKeysInt=0;Bawl.basicLangKeysInt<Bawl.basicLangKeys.length;Bawl.basicLangKeysInt++){
		if ( Bawl.basicLangKeys[Bawl.basicLangKeysInt].match(/^[a-z\-_]*$/) ) {
			Bawl.basicMsgsWikiTextPre = 'int:';
		} else {
			Bawl.basicMsgsWikiTextPre = '';
		}
		Bawl.basicMsgsWikiText = Bawl.basicMsgsWikiText + '<div class="BAWLTRANS">((' + Bawl.basicMsgsWikiTextPre + Bawl.basicLangKeys[Bawl.basicLangKeysInt] + '))</div>';
	}
	Bawl.basicMsgsWikiText = Bawl.basicMsgsWikiText + '<div class="BAWLTRANS"></div>';
	api.post( {format: 'json', contentmodel:'wikitext', action: 'parse', disablelimitreport: true, uselang: Bawl.userLang, text: Bawl.basicMsgsWikiText} ).then( function ( data ) {
		Bawl.basicMsgsArrayRegExp = new RegExp('(?:<div class="BAWLTRANS">)(([^<]|<(?!\/div><div class="BAWLTRANS">))*)(?:<\/div>)', 'g');
		Bawl.basicMsgsArray = data.parse.text['*'].match(Bawl.basicMsgsArrayRegExp);
		if ( Bawl.basicMsgsArray ) {
			Bawl.basicmsgsObj[Bawl.userLang] = {};
			Bawl.basicmsgsObjKeys = {0:'TZ',1:'specialcontribs',2:'specialpermalink',3:'specialdiff',4:'specialhistory',5:'English',6:'PF',7:'newline',8:'smiley',9:'AWBtyposTitle',10:'atops',11:'abots',12:'tq',13:'lockicon','thanks-desc':'thankLink','MediaWiki:revid':'revid','MediaWiki:Copyrightwarning':'tosNagText'};
			for (Bawl.basicLangKeysInt=0;Bawl.basicLangKeysInt<Bawl.basicLangKeys.length;Bawl.basicLangKeysInt++){
				if ( Bawl.basicmsgsObjKeys[Bawl.basicLangKeysInt] ) {
					Bawl.basicmsgsObjKey = Bawl.basicmsgsObjKeys[Bawl.basicLangKeysInt];
				} else if ( Bawl.basicmsgsObjKeys[Bawl.basicLangKeys[Bawl.basicLangKeysInt]] ) {
					Bawl.basicmsgsObjKey = Bawl.basicmsgsObjKeys[Bawl.basicLangKeys[Bawl.basicLangKeysInt]];
				} else if ( Bawl.basicLangKeys[Bawl.basicLangKeysInt].match(/^[a-z\-_]*$/) ) {
					Bawl.basicmsgsObjKey = Bawl.basicLangKeys[Bawl.basicLangKeysInt];
				}
				if ( ! Bawl.basicMsgsArray[Bawl.basicLangKeysInt].match('⧼') ) { //if it does match ⧼ it's probably a message that doesn't exist on this MediaWiki installation, it should fallback to the message in Bawl.basicmsgsObj.mul
					Bawl.basicmsgsObj[Bawl.userLang][Bawl.basicmsgsObjKey] = Bawl.basicMsgsArray[Bawl.basicLangKeysInt].replace(Bawl.basicMsgsArrayRegExp,'$1');
				}
				if ( Bawl.basicmsgsObjKey == 'revid' ) {
					Bawl.basicmsgsObj[Bawl.userLang][Bawl.basicmsgsObjKey] = Bawl.basicmsgsObj[Bawl.userLang][Bawl.basicmsgsObjKey].replace('$1','$5');
				} else if ( Bawl.basicmsgsObjKey == 'anoneditwarning' ) {
					Bawl.basicmsgsObj[Bawl.userLang][Bawl.basicmsgsObjKey] = Bawl.basicmsgsObj[Bawl.userLang][Bawl.basicmsgsObjKey].replace(/\[\$1 ([^\]]*)\]/,'<a href="' + mw.config.get('wgArticlePath').replace('$1', 'Special:UserLogin') + '?returnto=' + encodeURIComponent(mw.config.get('wgPageName')) + '">$1</a>').replace(/\[\$2 ([^\]]*)\]/, '<a href="' + mw.config.get('wgArticlePath').replace('$1', 'Special:CreateAccount') + '?returnto=' + encodeURIComponent(mw.config.get('wgPageName')) + '">$1</a>');
				} else if ( Bawl.basicmsgsObjKey == 'subject' ) {
					Bawl.basicmsgsObj[Bawl.userLang][Bawl.basicmsgsObjKey] = Bawl.basicmsgsObj[Bawl.userLang][Bawl.basicmsgsObjKey].replace(/(\&\#160;|:)/g,'');
				}
			}
			Bawl.basicmsgsObj[Bawl.userLang].difflinkname = Bawl.wikiMsgs.difflinkname.replace('DIFF',Bawl.basicmsgsObj[Bawl.userLang].specialdiff.replace(/.*:/,''));
			Bawl.basicmsgsObj[Bawl.userLang].difflinknamebare = Bawl.wikiMsgs.difflinknamebare.replace('DIFF',Bawl.basicmsgsObj[Bawl.userLang].specialdiff.replace(/.*:/,''));
			Bawl.basicmsgsObj[Bawl.userLang].difflinknameprevnext = Bawl.wikiMsgs.difflinknameprevnext.replace('DIFF',Bawl.basicmsgsObj[Bawl.userLang].specialdiff.replace(/.*:/,''));
			Bawl.basicmsgsObj[Bawl.userLang].pageHistoryLinkName = Bawl.wikiMsgs.pageHistoryLinkName.replace('HISTORY',Bawl.basicmsgsObj[Bawl.userLang].history_small);
			Bawl.basicmsgsObj[Bawl.userLang].revid = Bawl.basicmsgsObj[Bawl.userLang].revid.replace('$1','$7');
			Bawl.basicmsgsObj[Bawl.userLang].version = Bawl.VERSIONDATE;
			Bawl.localBold = {'de':'F','sv':'F','fr':'G','it':'G','es':'N','pt':'N','ru':'ж','uk':'ж'}; //ja, pl, vi, zh use B/I
			Bawl.localItalic = {'de':'K','es':'K','sv':'K','it':'C','ru':'к','uk':'к'};
			if ( Bawl.localBold[Bawl.userLang] ) {
				Bawl.basicmsgsObj[Bawl.userLang].bold = Bawl.localBold[Bawl.userLang];
			}
			if ( Bawl.localItalic[Bawl.userLang] ) {
				Bawl.basicmsgsObj[Bawl.userLang].italic = Bawl.localItalic[Bawl.userLang];
			}
			Bawl.basicLangString = {};
			if ( window.localStorage.BawlBasicLang && Bawl.testValidJSON(window.localStorage.BawlBasicLang) && window.localStorage.BawlBasicLang.length < 100000) {
				Bawl.basicLangString = JSON.parse(window.localStorage.BawlBasicLang); //in case you have other languages already in our localStorage, we don't want them to get lost. Unless it has already exceeded 100K (you'd need to load a site in ~20 languages to achieve that) in which case bye-bye
			}
			if ( Bawl.basicmsgsObj[Bawl.userLang].PF != '1' ) {
				Bawl.debug('ParserFunctions is not available on your wiki. Some of the parsed output is garbage..');
				Bawl.basicmsgsObj[Bawl.userLang].PF = '0';
				Bawl.basicmsgsObj[Bawl.userLang].newline = '';
				Bawl.basicmsgsObj[Bawl.userLang].smiley = '';
				Bawl.basicmsgsObj[Bawl.userLang].AWBtyposTitle = '';
				Bawl.basicmsgsObj[Bawl.userLang].atops = '';
				Bawl.basicmsgsObj[Bawl.userLang].abots = '';
				Bawl.basicmsgsObj[Bawl.userLang].tq = '';
				Bawl.basicmsgsObj[Bawl.userLang].lockicon = '';
				Bawl.dbg('get wiki timezone from API');
				api.get( {
					format: 'json', action: 'query', meta: 'siteinfo', siprop: 'general'
				} ).done( function ( data ) {
					Bawl.TZObj = JSON.stringify({'version':Bawl.versionDate,'timezone':data.query.general.timezone});
					Bawl.basicmsgsObj[Bawl.userLang].TZ = data.query.general.timezone;
					Bawl.basicLangString[Bawl.userLang] = Bawl.basicmsgsObj[Bawl.userLang];
					Bawl.basicLangStringified = JSON.stringify(Bawl.basicLangString);
					Bawl.basicmsgs = Object.assign(Bawl.basicmsgsObj.mul, Bawl.basicmsgsObj[Bawl.userLang]);
					window.localStorage.setItem('BawlBasicLang', Bawl.basicLangStringified);
				} );
			}
			Bawl.basicLangString[Bawl.userLang] = Bawl.basicmsgsObj[Bawl.userLang];
			Bawl.basicLangStringified = JSON.stringify(Bawl.basicLangString);
			window.localStorage.setItem('BawlBasicLang', Bawl.basicLangStringified);
			Bawl.basicmsgs = Object.assign(Bawl.basicmsgsObj.mul, Bawl.basicmsgsObj[Bawl.userLang]);
			Bawl.wikiTimezone = Bawl.basicmsgs.TZ;
			if ( Bawl.projectIsSULWiki[0] == '.wmflabs.org' ) {
				Bawl.wikiDataApi = 'https://wikidata.beta.wmflabs.org/w/api.php';
				Bawl.wikiDataRETF = '';
				Bawl.wikiDataNewLine = 'Q609020';
				Bawl.wikiDataSmiley = '';
				Bawl.wikiDataAtops = '';
				Bawl.wikiDataAbots = '';
				Bawl.wikiDataCitemap = '';
				Bawl.wikiDataTq = '';
				Bawl.wikiDataTqRedir = '';
				Bawl.wikiDataIDs = [Bawl.wikiDataNewLine];
			} else {
				Bawl.wikiDataApi = 'https://www.wikidata.org/w/api.php';
				Bawl.wikiDataRETF = 'Q6585066';
				Bawl.wikiDataNewLine = 'Q111996190';
				Bawl.wikiDataSmiley = 'Q6021960';
				Bawl.wikiDataAtops = 'Q112108086';
				Bawl.wikiDataAbots = 'Q112108089';
				Bawl.wikiDataCitemap = 'Q112131235';
				Bawl.wikiDataTq = 'Q11394737';
				Bawl.wikiDataTqRedir = 'Q112199474';
				Bawl.wikiDataIDs = [Bawl.wikiDataRETF,Bawl.wikiDataNewLine,Bawl.wikiDataSmiley,Bawl.wikiDataAtops,Bawl.wikiDataAbots,Bawl.wikiDataCitemap,Bawl.wikiDataTq,Bawl.wikiDataTqRedir];
			}
			if ( Bawl.projectIsSULWiki ) {
				Bawl.debug('you are on a Wikimedia SUL wiki, get names for some templates Bawl can use');
				mw.loader.using(['mediawiki.ForeignApi'], function(){
					var apiWikidata = new mw.ForeignApi(Bawl.wikiDataApi,{anonymous:true});
					apiWikidata.get({format:'json',action:'wbgetentities',props:'sitelinks',ids:Bawl.wikiDataIDs}).then(function(data){
						Bawl.debug('got template names from Wikidata');
						if ( data.entities[Bawl.wikiDataRETF] && data.entities[Bawl.wikiDataRETF].sitelinks[mw.config.get('wgWikiID')] ) {
							Bawl.basicmsgsObj[Bawl.userLang].AWBtyposTitle = data.entities[Bawl.wikiDataRETF].sitelinks[mw.config.get('wgWikiID')].title;
						}
						if ( data.entities[Bawl.wikiDataNewLine] && data.entities[Bawl.wikiDataNewLine].sitelinks[mw.config.get('wgWikiID')] ) {
							Bawl.basicmsgsObj[Bawl.userLang].newline = data.entities[Bawl.wikiDataNewLine].sitelinks[mw.config.get('wgWikiID')].title.replace(/[^:]*:/,'');
						}
						if ( data.entities[Bawl.wikiDataSmiley] && data.entities[Bawl.wikiDataSmiley].sitelinks[mw.config.get('wgWikiID')] ) {
							Bawl.basicmsgsObj[Bawl.userLang].smiley = data.entities[Bawl.wikiDataSmiley].sitelinks[mw.config.get('wgWikiID')].title.replace(/[^:]*:/,'');
						}
						if ( data.entities[Bawl.wikiDataAtops] && data.entities[Bawl.wikiDataAtops].sitelinks[mw.config.get('wgWikiID')] ) {
							Bawl.basicmsgsObj[Bawl.userLang].atops = data.entities[Bawl.wikiDataAtops].sitelinks[mw.config.get('wgWikiID')].title.replace(/[^:]*:/,'');
						}
						if ( data.entities[Bawl.wikiDataAbots] && data.entities[Bawl.wikiDataAbots].sitelinks[mw.config.get('wgWikiID')] ) {
							Bawl.basicmsgsObj[Bawl.userLang].abots = data.entities[Bawl.wikiDataAbots].sitelinks[mw.config.get('wgWikiID')].title.replace(/[^:]*:/,'');
						}
						if ( data.entities[Bawl.wikiDataCitemap] && data.entities[Bawl.wikiDataCitemap].sitelinks[mw.config.get('wgWikiID')] ) {
							Bawl.basicmsgsObj[Bawl.userLang].citemap = data.entities[Bawl.wikiDataCitemap].sitelinks[mw.config.get('wgWikiID')].title;
						}
						if ( data.entities[Bawl.wikiDataTq] && data.entities[Bawl.wikiDataTq].sitelinks[mw.config.get('wgWikiID')] ) {
							Bawl.basicmsgsObj[Bawl.userLang].tq = data.entities[Bawl.wikiDataTq].sitelinks[mw.config.get('wgWikiID')].title.replace(/[^:]*:/,'');
						}
						if ( data.entities[Bawl.wikiDataTqRedir] && data.entities[Bawl.wikiDataTqRedir].sitelinks[mw.config.get('wgWikiID')] ) { //don't care where tq actually is. if there's a common shortcut, use that instead
							Bawl.basicmsgsObj[Bawl.userLang].tq = data.entities[Bawl.wikiDataTqRedir].sitelinks[mw.config.get('wgWikiID')].title.replace(/[^:]*:/,'');
						}
						Bawl.basicLangString[Bawl.userLang] = Bawl.basicmsgsObj[Bawl.userLang];
						Bawl.basicLangStringified = JSON.stringify(Bawl.basicLangString);
						Bawl.basicmsgs = Object.assign(Bawl.basicmsgsObj.mul, Bawl.basicmsgsObj[Bawl.userLang]);
						window.localStorage.setItem('BawlBasicLang', Bawl.basicLangStringified);
						Bawl.searchNodeContentsLoop();
					}, function ( code, data ) { Bawl.APIError(code, data, 'Possible cross-origin configuration error.');
					});
				});
			} else {
				Bawl.searchNodeContentsLoop(); //loading links before the translation is loaded may be unsafe, especially if the UI isn't English
			}
		}
	} );
}
if ( typeof window.BawlExtraFileLocation != "undefined" ) {
	Bawl.extraFileLocation = window.BawlExtraFileLocation;
} else {
	Bawl.extraFileLocation = 'User:Alexis_Jazz/Bawl-extra.js';
}
Bawl.loadXtra = function() {
	Bawl.msgsObjKeyName = 'msgsObj';//as this key is shared with Bawl-extra.js it needs protection from AJSJSMangler
	Bawl.loadXtraLang = function(){
		Bawl[Bawl.msgsObjKeyName][mw.config.get('wgUserLanguage')].date = Bawl.VERSIONDATE;
		Bawl.msgs = Object.assign(Bawl.msgsObj.mul, Bawl[Bawl.msgsObjKeyName][ mw.config.get('wgUserLanguage') ]);
		Bawl.newLocalStorageObj = {};
		if ( window.localStorage.BawlLang ) {
			Bawl.newLocalStorageObj = JSON.parse(window.localStorage.BawlLang);
		}
		Bawl.newLocalStorageObj[mw.config.get('wgUserLanguage')] = Bawl.msgsObj[ mw.config.get('wgUserLanguage') ];
		window.localStorage.setItem('BawlLang', JSON.stringify(Bawl.newLocalStorageObj));
	};
	if ( typeof Bawl.xtraJSDL == 'undefined' ) {
		Bawl.xtraFileLocation = mw.config.get('wgScript') + '?title=MediaWiki:Gadget-Bawl.js/Bawl-extra.js&action=raw&ctype=text/javascript';
		mw.loader.getScript(Bawl.xtraFileLocation).then(
		function() {
			if ( typeof Bawl[Bawl.msgsObjKeyName].de == 'object' ) {
				console.log('Bawl: loaded Bawl-extra.js from MediaWiki: namespace successfully');
				Bawl.loadXtraLang();
			} else {
				console.log('Bawl: no local copy, load Bawl-extra.js from English Wikipedia');
				mw.loader.getScript('https://en.wikipedia.org/w/index.php?title=User:Alexis_Jazz/Bawl-extra.js&action=raw&ctype=text/javascript').then(
				function() {
					if ( typeof Bawl[Bawl.msgsObjKeyName].de == 'object' ) {
						console.log('Bawl: loaded Bawl-extra.js from enwiki userspace successfully');
						Bawl.loadXtraLang();
					}
				});
			}
		}, function ( errorExtra ) {
				console.log( 'Bawl: could not load Bawl-extra.js: ' + errorExtra.message );
		});
	}
	Bawl.xtraJSDL = true;
};
Bawl.smoothScroll = {behavior: 'smooth',block: 'center',inline: 'nearest'};
Bawl.debugMsgCount = 0;Bawl.resetDbg=function(skipturnon){if(!skipturnon){Bawl.settings.debug=true;}Bawl.debugMsgCount = 0;Bawl.debugMsgCountReported = false;return 'reset, '+Bawl.settings.dbgLimit+' debug messages left';};
Bawl.debug=function(errortext){
	if(Bawl.settings&&Bawl.settings.debug==true&&Bawl.debugMsgCount<Bawl.settings.dbgLimit){
		Bawl.debugMsgCount++;if(typeof errortext=="string"){
			console.log('Bawl: '+errortext);//Bawl.debug
		}else{//Bawl.debug
			console.log(errortext);//Bawl.debug
		}//Bawl.debug
	}else if(Bawl.settings&&typeof Bawl.debugMsgCountReported == 'undefined' && Bawl.debugMsgCount==Bawl.settings.dbgLimit){
		Bawl.debugMsgCountReported=true;
		mw.notify('Exceeded ' + Bawl.settings.dbgLimit + ' debug messages, see console.');//Bawl.debug
		console.log('exceeded ' + Bawl.settings.dbgLimit + ' debug messages, reporting halted. Raise limit in settings and/or enter Bawl.resetDbg() to reset counter.');//Bawl.debug
	}//Bawl.debug
};//Bawl.debug
if ( BawlmsgsObj[ Bawl.userLang ] ) { // BawlmsgsObj could be specified in common.js before Bawl is loaded
	Bawl.msgs = Object.assign(Bawl.msgsObj.mul, BawlmsgsObj[ Bawl.userLang ]);
} else if ( Bawl.testValidJSON(window.localStorage.BawlLang) && JSON.parse(window.localStorage.BawlLang)[Bawl.userLang] && JSON.parse(window.localStorage.BawlLang)[Bawl.userLang].date == Bawl.VERSIONDATE ) {
	Bawl.msgs = Object.assign(Bawl.msgsObj.mul, JSON.parse(window.localStorage.BawlLang)[Bawl.userLang] );
} else {
	Bawl.msgs = Bawl.msgsObj.mul;
	if ( ['nl','de'].indexOf(Bawl.userLang) != -1 ) { //array of full translations available in Bawl-extra.js
		Bawl.loadXtra();
	}
}
//default wiki config
Bawl.pingText = '[[' + mw.config.get('wgFormattedNamespaces')[2] + ':PINGUSER|]], ';
Bawl.pingTextInSection = '[[' + mw.config.get('wgFormattedNamespaces')[2] + ':PINGUSER|]], '; //[[CMTLINK|^]] is supported, but not so sure it's sensible by default
Bawl.pingTextAnon = '[[' + mw.config.get('wgFormattedNamespaces')[-1] + ':Contributions/PINGUSER|PINGUSER]], ';
Bawl.commentTextIndentWikiDefault = ':';
Bawl.monthNames = mw.config.get('wgMonthNames'); // months as found in signatures
Bawl.timestampFormat = '$6$7$8:$9$10$11'; //just the time without date as date is unpredictable, could cause problems if there are multiple comments at the same time by the same user on the same page, recommended to configure for your wiki. Use "MONTHNAME" to insert the name of the month. Processed by /(0?)([1-3]?)([0-9])\/([0-1][0-9])\/([0-9]{4}), (0?)([1-2]?)([0-9])\:(0?)([0-9]?)([0-9])/
Bawl.endOfCommentLocator = '<span id="USERTIME" class="BawlCmt">INNERCONTENT</span>';
if ( mw.config.get('wgDBname') == 'enwiki' ) { //overwrite config where needed
	Bawl.timestampFormat = '$6$7$8:$9$10$11, $2$3 MONTHNAME $5';
} else if ( mw.config.get('wgDBname') == 'dewiki' ) {
	Bawl.monthNames = {1:'Jan.',2:'Feb.',3:'Mär.',4:'Apr.',5:'Mai',6:'Jun.',7:'Jul.',8:'Aug.',9:'Sep.',10:'Okt.',11:'Nov.',12:'Dez.'};
	Bawl.timestampFormat = '$6$7$8:$9$10$11, $2$3. MONTHNAME $5';
} else if ( mw.config.get('wgDBname') == 'nlwiktionary' || mw.config.get('wgDBname') == 'nlwiki' ) {
	Bawl.monthNames = {1:'jan',2:'feb',3:'mrt',4:'apr',5:'mei',6:'jun',7:'jul',8:'aug',9:'sep',10:'okt',11:'nov',12:'dec'};
	Bawl.timestampFormat = '$2$3 MONTHNAME $5 $6$7$8:$9$10$11';
} else if ( [ 'thwikibooks', 'thwiki', 'thwikisource', 'thwiktionary', 'thwikiquote' ].indexOf(mw.config.get('wgDBname')) != -1 ) {
	Bawl.timestampFormat = '$6$7$8:$9$10$11, $2$3 MONTHNAME'; //Thai solar calendar. Who needs to know what year it is anyway
}
Bawl.pageLoadTimeStamp = new Date().toISOString(); //to detect new comments since loading the page
Bawl.editConflictRetries = 3;
Bawl.defaultSettings = { //default settings
	'UILabelLoad':'TAB',
	'editLinks':true,
	'replySecLink':false,
	'nSecLink':true,
	'nSecBottomLink':true,
	'secLinks':false,
	'sectionIsNewTO':true,
	'inputBoxTO':true,
	'mwuibuttonTO':true,
	'hideArchived':true,
	'editFullPage':false,
	'editFullSection':false,
	'dateLinksIconSection':false,
	'dateLinksIconSectExtra':false,
	'dateLinksIcon':false,
	'dateLinksIconAlt':true,
	'thankLink':false,
	'reverseSectionOrder':false,
	'collapsible':false,
	'autoCollapse':false,
	'collapArticle':false,
	'collapArticleDefault':false,
	'collapArticleDefaultFloatingToC':false,
	'collapArticleDefaultNoToC':false,
	'dateLinksLocalTime':false,
	'dateLinksLocalTimeUserOptTZ':true,
	'dateLinksLocalTimeRelative':false,
	'dateLinksLocalTimeAbsolute':true,
	'dateLinksLocalTime12H':false,
	'dateLinksLocalTimeNumMonth':false,
	'dateLinksLocalTimeLongMonth':false,
	'dateLinksLocalTimeWeekday':false,
	'dateLinksLocalTimeWeekdayFull':false,
	'cureDTBlueStreak':true,
	'UILabelInterface':'TAB',
	'tosNag':true,
	'markup':true,
	'pingDropDown':false,
	'pingDropDownAt':true,
	'onetimetools':true,
	'clearEditFullPage':true,
	'editNotice':true,
	'wrongUI':false,
	'previewAboveFull':false,
	'previewAboveOther':false,
	'checkNewComments':true,
	'limitWidth':false,
	'warnExit':true,
	'UIfontSize':'small',
	'customSummary':false,
	'customBackground':'',
	'bgicon':false,
	'UILabelEditing':'TAB',
	'livePreview':false,
	'bracketToForm':false,
	'autoPing':true,
	'quoteSelect':false,
	'AWBtypos':false,
	'AWBtypoPreview':true,
	'AWBtyposCustomTitle':'',
	'enableCI':true,
	'enableCIThatRun':true,
	'enableCIThatRunCmt':true,
	'cI':{}, //examples: /youtu\.be(.)/youtube.com$1watch\?/, '''Keep''', ((AIV|chk)), ((subst:AfC invite))
	'cIThatRun':{}, //regexp that get automatically executed
	'cIThatRunCmt':{}, //regexp that get automatically executed but only on comments
	'monospace':false,
	'markdown':false,
	'bbcode':false,
	'outdent':8,
	'sumSnippet':true,
	'saveDraft':true,
	'pingText':Bawl.pingText,
	'pingTextInSection':Bawl.pingTextInSection,
	'rewritun':true,
	'rewriteOnBlur':true,
	'rewritunOther':'',
	'runCIOther':'',
	'AWBtyposOther':'',
	'UILabelSubscribe':'TAB',
	'stalkAddSubLinks':false,
	'stalkMaxSubs':200,
	'stalkAutoSub':false,
	'stalkSyncToPrefs':false,
	'markNewCmts':true,
	'stalkAddCycleBtn':false,
	'markNewCmtsSubbed':true,
	'stalkAddCycleBtnSubbed':false,
	'markNewCmtsBorder':false,
	'stalkMarkReadScroll':false,
	'stalkWatchListCmts':false,
	'stalkTackOnEcho':false,
	'stalkInterval':10,
	'UILabelAdvanced':'TAB',
	'showRisky':false,
	'shortcuts':true,
	'submitShortcut':false,
	'hideDT':true,
	'hideDTSub':true,
	'hideAdvFE':true,
	'loadMinervaD':true,
	'loadMinervaM':true,
	'methodLocator':true,
	'methodLegacy':true,
	'extendedSigDetect':false,
	'useLocator':true,
	'enableOnDiffOldId':false,
	'theStranger':false,
	'ninjaLoader':false,
	'addLinkTS':false,
	'killswitch':true,
	'debug':false,
	'dbgLimit':3000,
	'afterPost':'parse', //link, reload, parsepage, parse, parsecmtonly
	'afterPostReload':false,
	'watchlist':'watch',
	'watchlistexpiry':'+30 days',
	'editor':'source',
	'editorSwitch':false,
	'RLmasq':false,
	'grayscale':false,
	'saveTo':'browser',
	'resetPrefsButtonBar':'BUTTONBAR',
};
Bawl.settings = $.extend( true, {}, Bawl.defaultSettings ); // copy as = only creates a shortcut
Bawl.tosNagContainer = document.createElement('div');
Bawl.tosNagContainer.id = 'BawltosNagContainer';
Bawl.loadSettings = function() {
	Bawl.customizedSettings = '';
	if ( window.localStorage.Bawl && Bawl.testValidJSON(window.localStorage.Bawl) ) {
		Bawl.debug('load settings from localStorage');
		Bawl.customizedSettings = JSON.parse(window.localStorage.Bawl);
		Bawl.settings = Object.assign(Bawl.settings, Bawl.customizedSettings);
	} else if ( Bawl.testValidJSON(mw.user.options.get('userjs-Bawl')) ) {
		Bawl.settings = Object.assign(Bawl.settings, JSON.parse(mw.user.options.get('userjs-Bawl')));
		Bawl.customizedSettings = JSON.parse(mw.user.options.get('userjs-Bawl'));
	}
};
Bawl.loadSettings();
Bawl.reloadForm = function() {
	Bawl.loadSettings();
	Bawl.cancelReply(); //clear form entirely
	Bawl.reloaded = true;
	Bawl.openReplyForm(Bawl.replyLinkParamsOpened, 'reload'); //force reloading everything
};
Bawl.disableForm = function(setDisableForm) {
	Bawl.UITextInputTitle.setReadOnly(setDisableForm);
	Bawl.UITextInput.setReadOnly(setDisableForm);
	Bawl.UIReplyButton.setDisabled(setDisableForm);
	Bawl.UIPreviewButton.setDisabled(setDisableForm);
	Bawl.UICancelButton.setDisabled(setDisableForm);
	if ( Bawl.UIDiffButton ) {
		Bawl.UIDiffButton.setDisabled(setDisableForm);
	}
};
Bawl.getWikitextFromExport = function(text) {
	if ( text.match(/[^]*<text bytes[^>]*>([^]*)<\/text>[^]*/) ) {
		return text.replace(/[^]*<text bytes[^>]*>([^]*)<\/text>[^]*/, '$1').replace(/\&lt\;/g, '<').replace(/\&gt\;/g, '>').replace(/\&amp\;/g, '&');
	} else {
		return '';
	}
};
Bawl.deleteSubsFromPrefs = function() {
	api.postWithEditToken( {format: 'json', action: 'options', change:['userjs-BawlSubs='] } ).then( function ( data ) {
		Bawl.debug(data);
		if ( data.options == 'success' ) {
			Bawl.debug('removed subscriptions from account preferences');
			mw.user.options.set({'userjs-BawlSubs':undefined});
		}
	}, function ( code, data ) { Bawl.APIError(code, data);
	});
};
Bawl.changePreferences = function(actionToPerform, type) {
	if ( type == 'accountprefs' && Bawl.projectIsSULWiki ) {
		Bawl.prefsParamsAction = 'globalpreferenceoverrides'; //also works as a regular preference, even if the local preference isn't set
	} else if ( type == 'accountprefs' ) {
		Bawl.prefsParamsAction = 'options'; //for non-SUL wikis
	} else if ( type == 'globalprefs' ) {
		Bawl.prefsParamsAction = 'globalpreferences';
	}
	if ( actionToPerform == 'delete' ) {
		Bawl.prefsParamsSettings = '';
	} else {
		Bawl.prefsParamsSettings = Bawl.encodedPrefs;
	}
	api.postWithEditToken( {format: 'json', action: Bawl.prefsParamsAction, change:['userjs-Bawl=' + Bawl.prefsParamsSettings] } ).then( function ( data ) { // do not use alternative multiple-value separator for change parameter: T306319
		Bawl.debug(data);
		if ( data.globalpreferences == 'success' || data.options == 'success' || data.globalpreferenceoverrides == 'success' ) {
			Bawl.debug('changed prefences in ' + Bawl.prefsParamsAction + ' successfully');
			mw.user.options.set({'userjs-Bawl':Bawl.prefsParamsSettings});//this changes the value in mw.user.options (non-persistent) so we don't have to reload the page to apply the settings
			Bawl.reloadForm();
		}
	}, function ( code, data ) { Bawl.APIError(code, data);
	});
};
Bawl.saveSettings = function() {
	Bawl.disableForm(true); //disable buttons so you can't double click
	$(document.getElementById('saveSettingsButton')).addClass('BawlPendingBlink');
	Bawl.debug('Saving settings..');
	Bawl.prefCount = Object.keys(Bawl.defaultSettings).length;
	for (Bawl.prefint = 0; Bawl.prefint < Bawl.prefCount; Bawl.prefint++) {
		Bawl.processKey = Object.keys(Bawl.defaultSettings)[Bawl.prefint];
		Bawl.debug('process element for saving ' + (Bawl.prefint + 1) + '/' + Bawl.prefCount + ': ' + Bawl.processKey);
		if ( Bawl.settingElement[ Bawl.processKey ] && typeof Bawl.settingElement[ Bawl.processKey ].isSelected == 'function' ) {
			Bawl.settings[ Bawl.processKey ] = Bawl.settingElement[ Bawl.processKey ].isSelected();
		} else if ( Bawl.settingElement[ Bawl.processKey ] && typeof Bawl.settingElement[ Bawl.processKey ].getValue == 'function' ) {
			Bawl.settings[ Bawl.processKey ] = Bawl.settingElement[ Bawl.processKey ].getValue();
		}
	}
	if ( Bawl.settings.pingText == '' ) {
		Bawl.settings.pingText = Bawl.pingText;
	}
	if ( ! Bawl.settings.editNotice && window.localStorage.BawlEditNotices ) {
		Bawl.debug('dumping edit notices');
		window.localStorage.removeItem('BawlEditNotices');
	}
	if ( ! Bawl.settings.saveDraft && window.localStorage.BawlDrafts ) {
		window.localStorage.removeItem('BawlDrafts');
	}
	for (Bawl.int = 0; Bawl.int < 50; Bawl.int++) {
		if ( Bawl.customInsertTextInput[Bawl.int].getValue() != '' ) {
			Bawl.settings.cI[Bawl.int] = encodeURIComponent(Bawl.customInsertTextInput[Bawl.int].getValue());
		} else {
			delete Bawl.settings.cI[Bawl.int];
		}
		if ( Bawl.customInsertThatRunTextInput[Bawl.int].getValue() != '' ) {
			Bawl.settings.cIThatRun[Bawl.int] = encodeURIComponent(Bawl.customInsertThatRunTextInput[Bawl.int].getValue());
		} else {
			delete Bawl.settings.cIThatRun[Bawl.int];
		}
		if ( Bawl.customInsertThatRunCmtTextInput[Bawl.int].getValue() != '' ) {
			Bawl.settings.cIThatRunCmt[Bawl.int] = encodeURIComponent(Bawl.customInsertThatRunCmtTextInput[Bawl.int].getValue());
		} else {
			delete Bawl.settings.cIThatRunCmt[Bawl.int];
		}
	}
	if ( window.BawlGlobalPrefs ) {window.BawlGlobalPrefs = Bawl.settingsToSave;} //refreshing this would otherwise require a page reload
	if ( window.BawlPrefs ) { window.BawlPrefs = Bawl.settingsToSave; }
	if ( ! Bawl.settings.stalkSyncToPrefs && Bawl.testValidJSON(mw.user.options.get('userjs-BawlSubs')) ) {
		Bawl.debug('removing BawlSubs from account preferences');
		Bawl.deleteSubsFromPrefs();
	}
	Bawl.prefCount = Object.keys(Bawl.defaultSettings).length;
	Bawl.settingsToSave = $.extend( true, {}, Bawl.settings );
	Bawl.debug('compacting preferences');
	for (Bawl.prefint = 0; Bawl.prefint < Bawl.prefCount; Bawl.prefint++) { //compacting settings by removing values that match defaults
		Bawl.processKey = Object.keys(Bawl.defaultSettings)[Bawl.prefint];
		Bawl.debug('checking ' + Bawl.prefint + '/' + Bawl.prefCount + ': ' + Bawl.processKey);
		if ( ( typeof Bawl.settingsToSave[Bawl.processKey] == "boolean" || typeof Bawl.settingsToSave[Bawl.processKey] == "string" ) && Bawl.settingsToSave[Bawl.processKey] == Bawl.defaultSettings[Bawl.processKey] ) {
			Bawl.debug('removing ' + Bawl.processKey + ' from settings to save, same as default');
			delete Bawl.settingsToSave[Bawl.processKey];
		} else {
			Bawl.debug(Bawl.processKey + ': ' + Bawl.settingsToSave[Bawl.processKey] + ' does not match ' + Bawl.defaultSettings[Bawl.processKey]);
		}
	}
	Bawl.debug('finished compacting preferences');
	Bawl.encodedPrefs = JSON.stringify(Bawl.settingsToSave); //store object as a base64 encoded JSON. encodeURIComponent because btoa only supports Latin1
	if ( Bawl.settings.saveTo == 'browser' ) {
		Bawl.debug('saving settings to localStorage.Bawl');
		window.localStorage.setItem('Bawl', Bawl.encodedPrefs);
		Bawl.reloadForm();
	} else { //saving to accountprefs or globalprefs
		Bawl.debug('saving settings to ' + Bawl.settings.saveTo);
		Bawl.resetPreferences('browser'); //removing localStorage so that won't override accountprefs
		Bawl.changePreferences('save',Bawl.settings.saveTo);
	}
};
Bawl.resetPreferences = function(prefType) {
	if ( ! prefType ) { // the reset/delete preferences button was pressed
		Bawl.disableForm(true);
		$(document.getElementById('resetPreferencesButton')).addClass('BawlPendingBlink');
	}
	if ( (prefType && prefType == 'browser') || ( ! prefType && Bawl.settingElement.saveTo.getValue() == 'browser' )) {
		window.localStorage.removeItem('Bawl');
		if ( ! prefType ) {
			Bawl.reloadForm();
		}
	} else if ( (prefType && prefType == 'accountprefs') || ( ! prefType && Bawl.settingElement.saveTo.getValue() == 'accountprefs' )) {
		Bawl.debug('removing settings from account preferences');
		Bawl.changePreferences('delete','accountprefs');
	} else if ( (prefType && prefType == 'globalprefs') || ( ! prefType && Bawl.settingElement.saveTo.getValue() == 'globalprefs' )) {
		Bawl.debug('removing settings from global preferences');
		Bawl.changePreferences('delete','globalprefs');
	}
};
Bawl.clearLocalStorage = function(a) {
	window.localStorage.removeItem('BawlBasicLang');
	window.localStorage.removeItem('BawlLang');
	window.localStorage.removeItem('BawlEditNotices');
	window.localStorage.removeItem('BawlDrafts');
	window.localStorage.removeItem('BawlThanks');
	mw.notify(Bawl.basicmsgs.actioncomplete);
	Bawl.debug('bye localStorage items');
};
Bawl.addScrewedLink = function(errorDescription,moreInfo) {
	Bawl.debug('WELL NOW YOU\'VE DONE IT.');
	Bawl.debug('Description: ' + errorDescription + ', moreInfo: ' + moreInfo);
	$(document).ready(function() {
		var DelayedScrew = setInterval(function () { //sometimes errors seem to happen BECAUSE we're leaving the page (which probably causes http requests to get canceled)
			clearInterval(DelayedScrew);
			if ( $('.BawlScrewed')[0] ) { Bawl.debug('there\'s already an open warning.');return;}
			if ( typeof Bawl.processElementArray == 'object' ) {
				Bawl.addScrewedProcessLength = Bawl.processElementArray.length;
				Bawl.addScrewedProcessTypesArray = [];
				Bawl.addScrewedProcessTypes = '';
				for(Bawl.addScrewedInt=0;Bawl.addScrewedInt<Bawl.processElementArray.length;Bawl.addScrewedInt++){ //collect HTML element types that are present in the processElementArray. If case of some gadget or script conflict you may see something missing here.
					if ( Bawl.processElementArray[Bawl.addScrewedInt] && ! Bawl.addScrewedProcessTypesArray.includes(Bawl.processElementArray[Bawl.addScrewedInt].nodeName) ) {
						Bawl.addScrewedProcessTypesArray.push(Bawl.processElementArray[Bawl.addScrewedInt].nodeName);
						Bawl.addScrewedProcessTypes = Bawl.addScrewedProcessTypes + Bawl.processElementArray[Bawl.addScrewedInt].nodeName + ', ';
					}
				}
				Bawl.addScrewedProcessTypes = Bawl.addScrewedProcessTypes.replace(/, $/,'');
			} else {
				Bawl.addScrewedProcessLength = -1;
				Bawl.addScrewedProcessTypes = 'none';
			}
			if ( $('.BawlLinks')[0] ) {
				Bawl.addScrewedRLCount = $('.BawlLinks').length;
			} else {
				Bawl.addScrewedRLCount = 0;
			}
			Bawl.screwedUrlParamRLP = 'n%2Fa';
			if ( Bawl.replyLinkParamsOpened ) {
				Bawl.screwedUrlParamRLP = encodeURIComponent(JSON.stringify(Bawl.replyLinkParamsOpened));
			}
			Bawl.failURL = 'index.php?title=User_talk:Alexis_Jazz/Bawl&action=edit&section=new&loadBawl=0&preloadtitle=You%20messed%20up!%20(' + encodeURIComponent(errorDescription) + ')&preload=User_talk%3AAlexis%20Jazz/Bawl/preload&preloadparams%5b%5d=' + Bawl.screwedUrlParamRLP + '&preloadparams%5b%5d=' + encodeURIComponent(new Date().toLocaleString('en-GB',{timeZone:'UTC'})) + '%20UTC&preloadparams%5b%5d=' + encodeURIComponent(JSON.stringify(Bawl.customizedSettings)) + '&preloadparams%5b%5d=' + encodeURIComponent(moreInfo) + '&preloadparams%5b%5d=' + mw.config.get('skin') + '&preloadparams%5b%5d=' + encodeURIComponent(new Date(Bawl.timestampInit).toLocaleString('en-GB',{timeZone:'UTC'})) + '&preloadparams%5b%5d=' + encodeURIComponent(Bawl.addScrewedProcessLength) + '&preloadparams%5b%5d=' + encodeURIComponent(Bawl.addScrewedProcessTypes) + '&preloadparams%5b%5d=' + Bawl.addScrewedRLCount + '&preloadparams%5b%5d=' + encodeURIComponent(mw.config.get('wgPageName')) + '&preloadparams%5b%5d=' + mw.config.get('wgWikiID');
			Bawl.failMsg = '<h1>' + Bawl.msgs.messedUp1 + '</h1>' + Bawl.kittehStuck + '<p><b>' + Bawl.msgs.messedUp2 + '</b><br/><br/><a href="https://en.wikipedia.org/w/' + Bawl.failURL + '"><big><b>' + Bawl.msgs.messedUp3 + '</b></big></a><br/><br/>' + Bawl.msgs.messedUp4.replace('META','<a href="https://meta.wikimedia.org/w/' + Bawl.failURL + '">Meta-Wiki</a>').replace(/\[\[NLWIKT\|([^\]]*)\]\]/,'<a href="https://nl.wiktionary.org/w/' + Bawl.failURL.replace('You%20messed%20up!','Je%20hebt%20het%20verprutst!') + '">$1</a>') + '<br/><br/>' + moreInfo + '<br/><a style="font-weight:bold" onclick="$(\'.BawlScrewed\').remove()">' + Bawl.basicmsgs['feedback-back'] + '</a></p>';
			Bawl.failMsgDiv = document.createElement('div');
			Bawl.failMsgDiv.className = 'BawlWarning BawlScrewed';
			Bawl.failMsgDiv.innerHTML = Bawl.failMsg;
			if ( Bawl.replyLinkParamsOpened && document.getElementById('bawlForm-'+Bawl.replyLinkParamsOpened.id) ) {
				document.getElementById('bawlForm-'+Bawl.replyLinkParamsOpened.id).prepend(Bawl.failMsgDiv);
			} else {
				$('#content').prepend(Bawl.failMsgDiv);
			}
			$(document).ready(function() {
				$('.BawlWarning')[0].scrollIntoView({'behavior':'smooth'});
			});
			var DelayedScrew2 = setInterval(function () { //SCROLL DAMN YOU AND DON'T STOP UNTIL YOU'RE THERE
				clearInterval(DelayedScrew2);
				$('.BawlWarning')[0].scrollIntoView({'behavior':'smooth'});
			}, 250);
		}, 500);
	});
};
Bawl.insertToSnag = function() {
	$('#BawltosNagContainer')[0].innerHTML = '';
	$('#BawltosNagContainer').append(Bawl.basicmsgs.tosNagText.replace('$2',Bawl.escapeReplacement(Bawl.basicmsgs['wikimedia-mobile-license-links'])).replace('$1',Bawl.escapeReplacement(Bawl.basicmsgs['wikimedia-copyright'].replace(/<[\/]?a[^>]*>/g,'').replace(/&gt;/g,'>').replace(/&lt;/g,'<').match(/<a[^>\n]*href="[^"\n]*Terms[^"\n]*">[^<]*<\/a>/)[0])));
};
Bawl.toggleTosNag = function() {
	if ( ! document.getElementById('BawlToSNag') && Bawl.settingElement.tosNag.isSelected() ) {
		Bawl.insertToSnag();
	} else if ( Bawl.settingElement.tosNag.isSelected() == true ) {
		$('#BawlToSNag').removeClass('BawlNoDisplay');
	} else if ( Bawl.settingElement.tosNag.isSelected() == false ){
		$('#BawlToSNag').addClass('BawlNoDisplay');
	}
};
//ensure a concistent look, icons are own work
Bawl.svgHeader = '<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" ';
Bawl.svgBawlIcon = 'width="1080px" height="720px" viewBox="0 0 1080 720"><defs><mask id="cut"><rect fill="#FFF" x="0" y="0" width="720" height="720"/><ellipse fill="#000" cx="870" cy="370" rx="300" ry="400"/></mask><mask id="cut2"><rect fill="#0ff" x="665" y="260" width="640" height="480"/></mask></defs><ellipse fill="#8af" cx="700" cy="420" rx="450" ry="280" mask="url(#cut)"/><ellipse fill="#8af" cx="360" cy="310" rx="340" ry="280"/>';
Bawl.svgBawlIconNewSectionData = 'data:image/svg+xml,' + encodeURIComponent(Bawl.svgHeader + Bawl.svgBawlIcon + '<rect fill="#000" x="820" y="0" width="60" height="320"/><rect fill="#000" x="680" y="130" width="320" height="60"/></svg>');
Bawl.svgBawlIconData = 'data:image/svg+xml,' + encodeURIComponent(Bawl.svgHeader + Bawl.svgBawlIcon.replace(/1080/g,'720').replace(/<mask id="cut2">.*<\/mas>/,'') + '</svg>');
Bawl.svgBawlIconFirstReplyData = Bawl.svgBawlIconData.replace(/8af/g,'68d');
Bawl.svgBawlIconEditData = 'data:image/svg+xml,' + encodeURIComponent(Bawl.svgHeader + 'width="720px" height="720px" viewBox="0 0 720 720"><g transform="rotate(40)"><g transform="translate(530 200) scale(1 1.5) rotate(45)"><rect fill="#8bf" x="0" y="0" width="127" height="127"/></g><rect fill="#8af" x="440" y="-365" width="180" height="700"/><rect fill="#79e" x="460" y="-230" width="40" height="520"/><rect fill="#67e" x="440" y="-365" width="180" height="100"/></g></svg>');
Bawl.svgBawlIconLinkData = 'data:image/svg+xml,' + encodeURIComponent(Bawl.svgHeader + 'width="720px" height="720px" viewBox="0 0 720 720"><defs><mask id="c1"><rect x="0" width="720" height="360" fill="#fff"/><rect x="0" width="240" height="720" fill="#fff"/><circle cx="440" cy="360" r="30" fill="#fff"/><circle cx="240" cy="510" r="30" fill="#fff"/></mask></defs><g mask="url(#c1)"><ellipse cx="240" cy="360" rx="200" ry="150" stroke="#556" stroke-width="60" fill="none"/></g><g mask="url(#c1)" transform="rotate(180) translate(-720,-720)"><ellipse cx="240" cy="360" rx="200" ry="150" stroke="#556" stroke-width="60" fill="none"/></g></svg>');
Bawl.svgBawlIconSettingsData = 'data:image/svg+xml,' + encodeURIComponent(Bawl.svgHeader + 'width="720px" height="720px" viewBox="0 0 720 720"><defs><clipPath id="cut1"><rect fill="#f0f" width="220" height="720"/><rect fill="#f0f" x="500" width="220" height="720"/><rect fill="#f0f" width="720" height="220"/><rect fill="#f0f" y="500" width="720" height="220"/></clipPath><clipPath id="cut"><circle fill="#333" cx="360" cy="360" r="355"/></clipPath></defs><g clip-path="url(#cut)"><rect fill="#333" x="300" y="0" width="120" height="720" clip-path="url(#cut1)"/><rect fill="#333" x="0" y="300" width="720" height="120" clip-path="url(#cut1)"/></g><g clip-path="url(#cut)"><g clip-path="url(#cut1)"><g transform="translate(360,-277)"><g transform="rotate(45)"><rect fill="#333" x="390" y="0" width="120" height="900"/><rect fill="#333" x="0" y="390" width="900" height="120"/></g></g></g></g><circle cx="360" cy="360" r="180" fill="none" stroke="#333" stroke-width="120"/></svg>');
Bawl.svgBawlIconLinkBlack = '<img style="height:2.5em !important" src="' + Bawl.svgBawlIconLinkData.replace(/\%23778/g, '%23333') + '">';
Bawl.svgBawlIconSettings = '<img style="height:1.75em !important" src="' + Bawl.svgBawlIconSettingsData + '">';
Bawl.svgMagnifierData = 'data:image/svg+xml,' + encodeURIComponent(Bawl.svgHeader + 'width="720px" height="720px" viewBox="0 0 720 720"><circle cx="290" cy="290" r="260" stroke="#333" stroke-width="60" fill="none"/><rect transform="rotate(-45)" fill="#333" x="-50" y="650" width="100" height="300"/></svg>');
Bawl.svgMagnifier = '<img style="height:1.75em !important" src="' + Bawl.svgMagnifierData + '">';
Bawl.svgBawlIconBell = 'width="720px" height="720px" viewBox="0 0 720 720"><defs><mask id="c1"><rect fill="#fff" width="720" height="560"/></mask></defs><g mask="url(#c1)"><ellipse fill="#8af" cx="360" cy="460" rx="200" ry="440"/><ellipse fill="#8af" cx="360" cy="600" rx="280" ry="380"/></g><circle cx="360" cy="650" r="70" fill="#8af"/>';
Bawl.svgBawlIconBellData = 'data:image/svg+xml,' + encodeURIComponent(Bawl.svgHeader + Bawl.svgBawlIconBell + '</svg>');
Bawl.svgBawlIconBellStruckData = 'data:image/svg+xml,' + encodeURIComponent(Bawl.svgHeader + Bawl.svgBawlIconBell + '<rect transform="rotate(45)" fill="#444" x="450" y="-440" width="100" height="880"/></svg>');
Bawl.svgBawlHeartIconData = 'data:image/svg+xml,' + encodeURIComponent(Bawl.svgHeader + 'width="720px" height="720px" viewBox="0 0 720 720"><g transform="translate(360,120) scale(1.00,0.95) rotate(45)"><rect fill="#8af" x="0" y="0" width="420" height="420"/><circle cx="0" cy="210" r="210" fill="#8af"/><circle cx="210" cy="0" r="210" fill="#8af"/></g></svg>');
Bawl.svgBawlHeartRedIconData = Bawl.svgBawlHeartIconData.replace(/8af/g,'f44');
Bawl.svgBawlChevronIconData = 'data:image/svg+xml,' + encodeURIComponent(Bawl.svgHeader + 'width="720px" height="720px" viewBox="0 0 720 720"><g transform="translate(360,720) rotate(-135)"><rect fill="#444" x="120" y="120" width="480" height="60"/><rect fill="#444" x="120" y="120" width="60" height="480"/></g></svg>');
Bawl.svgBawlCopyIconData = '<img style="height:1.5em !important" src="data:image/svg+xml,' + encodeURIComponent(Bawl.svgHeader + 'width="720px" height="720px" viewBox="0 0 720 720"><defs><mask id="r1"><rect x="510" width="210" height="720" fill="#fff"/><rect y="510" width="720" height="210" fill="#fff"/></mask></defs><rect x="40" y="40" width="470" height="470" fill="none" stroke="#fff" stroke-width="60"/><g mask="url(#r1)"><rect x="210" y="210" width="470" height="470" fill="none" stroke="#fff" stroke-width="60"/></g></svg>')+'">';
Bawl.svgBawlCancelIconData = '<img style="height:1.5em !important" src="data:image/svg+xml,' + encodeURIComponent(Bawl.svgHeader + 'width="720px" height="720px" viewBox="0 0 720 720"><g transform="translate(360 -150) rotate(45)"><circle cx="360" cy="360" r="320" fill="none" stroke="#fff" stroke-width="60"/><rect x="30" y="320" width="660" height="80" fill="#fff"/></g></svg>')+'">';
if ( Bawl.settings.grayscale ) {
	Bawl.svgBawlIconData = Bawl.svgBawlIconData.replace(/8af/g,'bbb');
	Bawl.svgBawlIconNewSectionData = Bawl.svgBawlIconNewSectionData.replace(/8af/g,'bbb');
	Bawl.svgBawlIconEditData = Bawl.svgBawlIconEditData.replace(/8af/g,'bbb').replace(/8bf/g,'c1c1c1').replace(/79e/g,'aaa').replace(/67e/g,'999');
	Bawl.svgBawlIconBellData = Bawl.svgBawlIconBellData.replace(/8af/g,'000');
	Bawl.svgBawlIconBellStruckData = Bawl.svgBawlIconBellStruckData.replace(/8af/g,'000');
	Bawl.svgBawlHeartIconData = Bawl.svgBawlHeartIconData.replace(/8af/g,'aaa');
	Bawl.svgBawlHeartRedIconData = Bawl.svgBawlHeartIconData.replace(/8af/g,'666');
}
if ( $('#mw-content-text')[0].attributes && $('#mw-content-text')[0].attributes.dir && $('#mw-content-text')[0].attributes.dir.value == 'rtl' ) {
	Bawl.CSSDirectionR = 'left';
	Bawl.CSSDirectionL = 'right';
	Bawl.CSSRot = '-90';
} else {
	Bawl.CSSDirectionR = 'right';
	Bawl.CSSDirectionL = 'left';
	Bawl.CSSRot = '90';
}
mw.util.addCSS(
'.BawlReplyLink:hover{text-decoration:none;background-color:#EEEEFF;cursor:pointer;}'+
'.BawlReplyLink:active{text-decoration:none;background-color:#EEEEFF;}'+
'.BawlSVG{background-repeat:no-repeat;background-position:center;height:1em;display:inline-block;vertical-align:middle;margin-bottom:0.1em;}'+
'.BawlSVGLinkIcon{background-image:url("'+Bawl.svgBawlIconLinkData+'");background-size:1.6em;padding:0 1.5em 0 1.6em;}'+
'.BawlSVGIcon{background-image:url("'+Bawl.svgBawlIconData+'");background-size:1em;padding:0 1em 0 1em;}'+
'.BawlSVGLargeIcon{background-repeat:no-repeat;background-position:center;height:2em;display:inline-block;background-image:url("'+Bawl.svgBawlIconData+'");background-size:2em;padding:0 1em 0 1em;}'+
'.BawlSVGFirstReplyIcon{background-image:url("'+Bawl.svgBawlIconFirstReplyData+'");background-size:1em;padding:0 1em 0 1em;}'+
'.BawlSVGEditIcon{background-image:url("'+Bawl.svgBawlIconEditData+'");background-size:1em;padding:0 1em 0 1em;}'+
'.BawlSVGNewSectionIcon{background-image:url("'+Bawl.svgBawlIconNewSectionData+'");background-size:1.5em;padding:0 1.3em 0 1.2em;}'+
'.BawlSVGBellIcon{background-image:url("'+Bawl.svgBawlIconBellData+'");background-size:1em;padding:0 1.5em 0 1.5em;}'+
'.BawlSVGBellStruckIcon{background-image:url("'+Bawl.svgBawlIconBellStruckData+'");background-size:1em;padding:0 1.5em 0 1.5em;}'+
'.BawlSVGHeartIcon{background-image:url("'+Bawl.svgBawlHeartIconData+'");background-size:1em;padding:0 1.5em 0 1.5em;}'+
'.BawlSVGHeartRedIcon{background-image:url("'+Bawl.svgBawlHeartRedIconData+'");background-size:1em;padding:0 1.5em 0 1.5em;}'+
'.BawlSVGChevronIcon{background-image:url("'+Bawl.svgBawlChevronIconData+'");background-size:1em;padding:0 1.5em 0 1.5em;}'+
'.BawlSVGChevronIconRot{transform:rotate(' + Bawl.CSSRot + 'deg)}'+
'.BawlCommentBG{background-image:url("'+Bawl.svgBawlIconData+'");background-size:contain;background-position:'+Bawl.CSSDirectionR+';background-repeat:no-repeat}'+
'.BawlEditBG{background-image:url("'+Bawl.svgBawlIconEditData+'");background-size:contain;background-position:'+Bawl.CSSDirectionR+';background-repeat:no-repeat}'+
'.BawlCustomBG{background-repeat:no-repeat;background-size:100% 100%;padding:1em}'+
'.BawlNoDisplay{display:none !important}'+
'.BawlYesDisplay{display:inline !important}'+
'.BawlMarginHalfEm{margin-bottom:0.5em}'+
'.BawlMarginHalfEmTop{margin-top:0.5em;}'+
'.BawlPreviewBox{padding:0.1em 1em 0.1em 1em;border:thin dashed gray;word-wrap:break-word;}'+
'.BawlNewLinesBox{padding:0.1em 1em 0.1em 1em;border:thin dashed gray;word-wrap:break-word;background-color:rgba(0, 70, 255, 0.05);}'+
'.BawlFloatRight{float:' + Bawl.CSSDirectionR + ';}'+
'.BawlForm{font-style:normal;text-align:initial;transition:all .5s ease-in;padding:0.5em 0.5em 0em 0.5em;font-size:' + Bawl.settings.UIfontSize + ';font-family:sans-serif;font-weight:normal;min-width:50em;}'+
'.BawlMonoSpace{font-family:monospace; !important}'+
'.BawlLimitWidth{max-width:50em;}'+
'.BawlUnsetLimitWidth{max-width:unset !important;}'+
'.BawlSettings{background:#FEFEFF;padding:0.1em 0.5em 0.1em 0.5em;border:thin solid lightgray;}'+
'.BawlSettingTabs{padding:0.5em 0.5em 0 0.5em !important;}'+
'.BawlDropDownMenu{max-width:35em;}'+
'.BawlOOuiFieldLayout{margin-top:0.5em !important;margin-bottom:0.75em;}'+
'.BawlOOuiFieldLayout::after{clear:none;}'+
'.BawlShakeIt{animation:shake 0.12s;animation-iteration-count:3;} @keyframes shake{0%{margin:-0.1em 0em 0.6em 0em;} 9%{margin:-0.2em 0em 0.7em 0em;} 18%{margin:-0.3em 0em 0.8em 0em;} 27%{margin:-0.2em 0em 0.7em 0em;} 36%{margin:-0.1em 0em 0.6em 0em;} 45%{margin:0em 0em 0.5em 0em;} 54%{margin:0.1em 0em 0.4em 0em;} 63%{margin:0.2em 0em 0.3em 0em;} 72%{margin:0.3em 0em 0.2em 0em;} 81%{margin:0.2em 0em 0.3em 0em;} 90%{margin:0.1em 0em 0.4em 0em;} 100%{margin:0em 0em 0.5em 0em;))'+
'.BawlSmallerText{font-size:70%;}'+
'.BawlEditNoticeDiv{max-height:12em;padding:0;margin:0 0 1em 0;overflow:auto;border:0.1em solid #bbb;}'+
'.BawlEditNoticeDismiss{background:GhostWhite;text-align:right;padding:0.5em;border-bottom:0.1em solid #bbb;clear:both;}'+
'@keyframes BawlBlinker{50%{opacity:0.5;))'+
'.BawlPendingBlink{animation:BawlBlinker 1s linear infinite;}'+
'.BawlLeftRightMargin{margin-left:0.6em;margin-right:0.6em;}'+
'.BawlLeftRightMarginWide{margin-left:2.5em;margin-right:2.5em;}'+
'.BawlLeftRightMarginWider{margin-left:5em;margin-right:5em;}'+
'.BawlMarkupBold{font-weight:bold;font-size:large;}'+
'.BawlMarkupItalic{font-weight:normal;font-style:italic;font-size:large;}'+
'.BawlPreviewAfterPost{transition:all .5s ease-in;margin-left:0;font-family:sans-serif;font-weight:normal;}'+
'.BawlFirstReply{display:block !important;text-align:center;margin:-0.6em 0 -0.5em 0;height:1em;}'+
'.BawlNoMaxWidth{max-width:none;}'+
'.BawlInsertLinkForm{transition:all .5s ease-in;width:96%;background:#EEEEFF;padding:1em;border:0.2em solid #CCC;}'+
'.BawlInsertLinkForm:focus{border:0.2em solid #69F;}'+
'.BawlPurpleBG{background-color:rgba(170, 70, 255, 0.2) !important;}'+
'.BawlEaseIn{transition:all 1s ease-in;}'+
'.BawlDiffPlusBig{font-weight:bold;color:#006400;}'+
'.BawlDiffPlus{color:#006400;}'+
'.BawlDiffMinBig{font-weight:bold;color:#8b0000;}'+
'.BawlDiffMin{color:#8b0000;}'+
'.BawlVisualLight{transition:all .5s ease-in;padding:0.5em;margin:0.5em 0.5em 0.5em 0;border:0.2em solid #CCC;width:98%;height:10em;word-wrap:break-word;overflow:auto;outline:none;}'+
'.BawlVisualLight:focus{border:0.2em solid #69F;}'+
'.BawlEditorSwitch{font-weight:bold;font-size:large;font-family:mono;}'+
'.BawlHalfOpacity{opacity:0.5;}'+
'.BawlWarning{background:#FFBBBB;padding:1em;text-align:center;}'+
'.BawlpermaLinkText{width:25em;}'+
'.BawlCreditTop{position:absolute;'+Bawl.CSSDirectionR+':1.5em;}'+
'.BawlSearchSettingsInput input{width:15em !important;}'+
'.BawlSearchSettingsInput {width:15em !important;margin:0 auto 0 auto !important;}'+
'.BawlCounterUL{margin-left:-1.6em;}'+
'.BawlIndented{margin-'+Bawl.CSSDirectionL+':1.5em;}'+
'.Bawlonetimetools{background-color:rgba(0,0,0, 0.05);padding:1em;}'+
'.BawlSubsDiv{background-color:rgba(0,0,0, 0.02);padding:1em;margin:0.5em;}'+
'.BawlRedBG{background-color:rgba(255,0,0,0.1) !important;}'+
'.BawlCycleBtnsFixed{cursor:pointer;position:fixed;top:50%;background-color:#eee;z-index:3;' + Bawl.CSSDirectionL + ':0%;border-' + Bawl.CSSDirectionR + ':0.1em solid #777;border-top:0.1em solid #777;border-bottom:0.1em solid #777}'+
'.BawlNewCmt{background-color:rgba(0,255,0, 0.1);}'+
'.BawlNewCmtSubscribed{background-color:rgba(0,150,0, 0.3);}'+
'.BawlNewCmtBorder{border-' + Bawl.CSSDirectionL + ':0.1em solid rgba(0,255,0, 0.6);padding-' + Bawl.CSSDirectionL + ':0.5em;}'+
'.BawlNewCmtSubscribedBorder{border-' + Bawl.CSSDirectionL + ':0.1em solid rgba(0,150,0, 0.6);padding-' + Bawl.CSSDirectionL + ':0.5em;}'+
'.BawlLinks{display:inline-block}'+
'.skin-timeless .mw-editsection .BawlLinks{font-size:larger}.mw-editsection .BawlSubscribe{padding:0 1.5em 0 1.5em !important}'+//".mw-editsection a" applies padding 0.5em 0 0.25em. no idea why
'.skin-minerva H1 .mw-editsection .BawlLinks,.skin-minerva H2 .mw-editsection .BawlLinks{font-size:smaller}'+
'.skin-minerva .mw-editsection .BawlLinks{vertical-align:bottom}'+
'.skin-minerva .mw-editsection .BawlSVG{padding-top:0.75em}'+
'.skin-minerva .BawlSVGChevronIcon{padding-top:0.5em;margin-bottom:-0.5em}'+
'.BawlFlexLayout{display:flex}'+
'.client-js .ns-0 .BawlPreviewBox ol>li>ul {display: unset !important;}'+ //hack to show collapsed quotations on English Wiktionary, which they themselves collapsed with what amounts to a hack. Should have been possible to use mw-collapsible (for personal reference: mw.loader.using('jquery.makeCollapsible').then( function () {$($('.mw-collapsible')[0]).makeCollapsible()}) ) or better yet DON'T collapse quotations but nooooooo
'.BawlFloatingToC{'+Bawl.CSSDirectionR+':0;bottom:0;position:fixed;overflow:auto;display:block;max-height:60%;}'
);
Bawl.makeCollapsible = function() {
	mw.loader.using('jquery.makeCollapsible').then( function () {
		for ( Bawl.previewCollapsibleInt=0;Bawl.previewCollapsibleInt<$('.BawlPreviewAfterPost .mw-collapsible,#BawlPreviewBox .mw-collapsible').length;Bawl.previewCollapsibleInt++){
			$($('.BawlPreviewAfterPost .mw-collapsible,#BawlPreviewBox .mw-collapsible')[Bawl.previewCollapsibleInt]).makeCollapsible();
		}
	});
};
Bawl.pageRevisionSinceLastCheck = {};
Bawl.pageRevisionIDSinceLastCheck = {};
Bawl.doAPICall = function( params, mode, callback ) {
	Bawl.debug('called doAPICall with mode ' + mode + ', params:');
	Bawl.debug(params);
	Bawl.apiTimeStart = new Date().getTime();//Bawl.debug
	if ( params.action == 'parse' ) {
		Bawl.doAPICallMethod = 'post';
	} else {
		Bawl.doAPICallMethod = 'postWithEditToken';
	}
	api[Bawl.doAPICallMethod]( params ).then( function ( apiResponse ) {
		Bawl.apiTimeEnd = new Date().getTime();//Bawl.debug
		if (params.action == 'parse' && mode == 'previewposted' ) {
			Bawl.debug('Got parsed comment:' + apiResponse.parse.text);
			if ( Bawl.replyLinkParamsOpened.type == 'newsection' && Bawl.settings.nSecBottomLink ) {
				$('#mw-content-text').append($('#BawlnSecBottom')[0].parentElement);
			}
			Bawl.postedCommentParsed = apiResponse.parse.text.replace(/^<div class=\"mw-parser-output\">([^]*)<\/div>$/, '$1').replace(/^<p>([^]*)<\/p>[\s]*/,'$1').replace(/<span data\-mw\-comment[^>]*>(<span data\-mw\-comment\-[^>]*><\/span>)*<\/span>/,'');//get rid of P tags that would otherwise break up comment and signature when editing an existing comment
			if ( Bawl.replyLinkParamsOpened.freshindent && Bawl.replyLinkParamsOpened.type == 'edit' ) {
				Bawl.bawlFormNegativeMargin = (Bawl.replyLinkParamsOpened.freshindent * 1.6);
			} else if ( Bawl.replyLinkParamsOpened.freshcomment && Bawl.replyLinkParamsOpened.type == 'comment' ) {
				Bawl.debug('you\'re replying to your own comment that was rendered with parse-in-place, set margin to 1.6em. This isn\'t really perfect but it should at least be right for the first reply to yourself. It\'s rare to reply more than once to yourself without reloading the page in between.');
				Bawl.bawlFormNegativeMargin = ( Bawl.replyLinkParamsOpened.freshindent * 1.6);
				if ( Bawl.commentTextIndent.match(/┌/) ) {
					Bawl.bawlFormNegativeMargin = (Bawl.cmtIndentHTML * -1.6);
				}
			}
			Bawl.previewAfterParseBox = '<div id="PreviewAfterPost" style="margin-' + Bawl.CSSDirectionL + ':' + Bawl.bawlFormNegativeMargin + 'em" class="BawlPreviewAfterPost BawlPurpleBG">' + Bawl.postedCommentParsed;
			Bawl.previewHasHeaderRegExp = new RegExp('^(<h1[ >][^]*<\/h1>|<h2[ >][^]*<\/h2>|<h3[ >][^]*<\/h3>|<h4[ >][^]*<\/h4>|<h5[ >][^]*<\/h5>|<h6[ >][^]*<\/h6>)');
			Bawl.previewHasHeader = Bawl.postedCommentParsed.match(Bawl.previewHasHeaderRegExp);
			if ( Bawl.previewHasHeader ) {
				Bawl.debug('preview starts with a section header. Moving section header outside the previewAfterParseBox so editing the comment right after posting won\'t destroy the header');
				Bawl.previewAfterParseBox = Bawl.previewHasHeader[0] + '<div id="PreviewAfterPost" class="BawlPreviewAfterPost BawlPurpleBG mw-parser-output">' + Bawl.postedCommentParsed.replace(Bawl.previewHasHeaderRegExp,''); //mw-parser-output is added to allow templatestyles to work
			}
			if ( ['comment','BCL','newsection','newheading'].indexOf(Bawl.replyLinkParamsOpened.type) != -1 || ( Bawl.replyLinkParamsOpened.type == 'edit' && document.getElementById('PreviewAfterPost-' + Bawl.replyLinkParamsOpened.id) ) ) {
				if ( Bawl.previewAfterParseBox.match(/span id="([^"]*:[0-9]{13,14}:[^"]*)" class="BawlCmt"/) ) {
					Bawl.wrongLocatorID = Bawl.previewAfterParseBox.match(/span id="([^"]*:[0-9]{13,14}:[^"]*)" class="BawlCmt"/)[1];
					Bawl.debug('recorded wrong locator ID for preview: ' + Bawl.wrongLocatorID + ', this will be replaced when we get confirmation from the server with the correct timestamp');
				} else {
					Bawl.debug('could not find locator!');
					Bawl.wrongLocatorID = '';
				}
			}
			if ( Bawl.replyLinkParamsOpened.type == 'edit' && document.getElementById('PreviewAfterPost-' + Bawl.replyLinkParamsOpened.id) ) {
				Bawl.debug('preview for comment edited from preview');
				document.getElementById('PreviewAfterPost-' + Bawl.replyLinkParamsOpened.id).outerHTML = Bawl.previewAfterParseBox + '</div>';
				$('.BawlPreviewAfterPost .ext-discussiontools-init-replylink-buttons').remove();//taking out the trash. not like these could have ever worked like this..
			} else if ( Bawl.replyLinkParamsOpened.type == 'edit' ) {
				Bawl.debug('editing a comment, not from the preview after posting');
				Bawl.cancelReply();
				Bawl.locatorInHTMLRegExp = new RegExp('([^]*)(<span id="' + Bawl.escapeRegExp(Bawl.replyLinkParamsOpened.id) + '" class="[^"]*">)(([^<]|<(?![\/]?span>|<span([^<]|<(?!\/span>))*)*)*<\/span>)');
				if ( document.getElementById('bawlLink-' + Bawl.escapeHTML(Bawl.replyLinkParamsOpened.id)).parentElement.parentElement.innerHTML.match(Bawl.locatorInHTMLRegExp) ) {
					document.getElementById('bawlLink-' + Bawl.escapeHTML(Bawl.replyLinkParamsOpened.id)).parentElement.parentElement.innerHTML = document.getElementById('bawlLink-' + Bawl.escapeHTML(Bawl.replyLinkParamsOpened.id)).parentElement.parentElement.innerHTML.replace(Bawl.locatorInHTMLRegExp, Bawl.previewAfterParseBox + '$2$3' + '</div>');
					Bawl.processElementArray[Bawl.replyLinkParamsOpened.int] = document.getElementById('bawlLink-' + Bawl.escapeHTML(Bawl.replyLinkParamsOpened.id)).parentElement; //the replacement above means the .BawlCmt from processElementArray is no longer attached to the DOM. We update it in case you want to reply to yourself.
				} else {
					Bawl.debug('locator not found in wikitext, you are probably editing some comment without one. This is incompatible with parse-in-place');
					$('#content').addClass('BawlEaseIn BawlPurpleBG'); //can't open new reply forms
					Bawl.mustReload = true; //but we can't until we have edit confirmation
				}
			} else if ( document.getElementById('bawlForm-' + Bawl.replyLinkParamsOpened.id) ) {
				Bawl.debug('preview for new comment');
				Bawl.previewBoxExtraMargin = '';
				if ( Bawl.counterUL ) {
					Bawl.previewBoxExtraMargin = ' BawlCounterUL';
				}
				Bawl.previewAfterParseBoxDiv = document.createElement('div');
				document.getElementById('bawlForm-' + Bawl.replyLinkParamsOpened.id).parentElement.insertBefore(Bawl.previewAfterParseBoxDiv,document.getElementById('bawlForm-' + Bawl.replyLinkParamsOpened.id));
				Bawl.previewAfterParseBoxDiv.outerHTML = Bawl.previewAfterParseBox.replace('BawlPreviewAfterPost BawlPurpleBG','BawlPreviewAfterPost BawlPurpleBG' + Bawl.previewBoxExtraMargin) + '</div>';
				if ( document.getElementById('bawlForm-' + Bawl.replyLinkParamsOpened.id).querySelectorAll('.BawlScrewed')[0] ) {
					Bawl.debug('there\'s a big error attached to the reply form, not removing it');
				} else {
					document.getElementById('bawlForm-' + Bawl.replyLinkParamsOpened.id).remove();
				}
			}
			if ( Bawl.postCommentSuccess == true && Bawl.wrongLocatorID != '' && Bawl.newCommentID != '#' ) {
				Bawl.debug('preview parsing took longer than editing (this is rare), patch up preview');
				if ( Bawl.replyLinkParamsOpened.type != 'edit' && document.getElementById(Bawl.wrongLocatorID) ) {
					Bawl.debug('preview for fresh comment, fixing ID');
					document.getElementById(Bawl.wrongLocatorID).id = decodeURIComponent(Bawl.newCommentID.slice(1));
					document.getElementById('PreviewAfterPost').id = 'PreviewAfterPost-' + decodeURIComponent(Bawl.newCommentID.slice(1)); //keep IDs unique if a user posts multiple comments without reloading
				}
				$('.BawlPurpleBG').removeClass('BawlPurpleBG');
				Bawl.addReplyLinkTo(Bawl.previewPostedParams); //adds edit link
				$('.BawlLinks').removeClass('BawlNoDisplay');
			}
			if ( apiResponse.parse.text.match('mw-collapsible') ) {
				Bawl.makeCollapsible();
			}
		} else if (params.action == 'parse' && (mode == 'preview' || mode == 'livepreview' || mode == 'diff') ) {
			Bawl.debug('Loading preview');
			Bawl.UIPreviewButton.setDisabled(false);
			$(document.getElementsByClassName('BawlPreviewBox'))[0].innerHTML = apiResponse.parse.text.replace(/<span data\-mw\-comment[^>]*>(<span data\-mw\-comment\-[^>]*><\/span>)*<\/span>/,'');
			if ( apiResponse.parse.text.match('mw-collapsible') ) {
				Bawl.makeCollapsible();
			}
			Bawl.debug('server answered with preview in ' + ( Bawl.apiTimeEnd - Bawl.apiTimeStart ) + 'ms');
		} else if ( ( apiResponse.error && apiResponse.error.code == 'editconflict' ) || ( typeof apiResponse.edit != 'undefined' && apiResponse.edit.result == 'Success' && ! apiResponse.edit.newtimestamp ) ) { //that nonsense second condition is a workaround for T299809
			Bawl.editConflictRetries = Bawl.editConflictRetries - 1;
			if ( apiResponse.edit.result == 'Success' && ! apiResponse.edit.newtimestamp && Bawl.editConflictRetries > 0 ) { //damage control in case there is a legit situation that triggers this
				Bawl.editConflictRetries = 1;
			}
			if ( apiResponse.edit.result == 'Success' && ! apiResponse.edit.newtimestamp ) {
				Bawl.debug('encountered either an edit conflict or Bawl is performing null edits. (which it never should) So which is it? Can somebody PLEASE look at T299809? ' + Bawl.editConflictRetries + ' tries left.');
			 } else {
				Bawl.debug('encountered edit conflict. ' + Bawl.editConflictRetries + ' tries left.');
			 }
			if ( Bawl.editConflictRetries >= 1 ) {
				Bawl.postReply1(Bawl.replyLinkParamsOpened,'editconflict');
			} else {
				Bawl.debug('giving up');
			}
		} else if (params.action == 'edit' && apiResponse.edit.result == 'Success' ) {
			Bawl.debug('page edit succeeded:');
			Bawl.postReplyInProgress = new Date().getTime();
			Bawl.debug(apiResponse);
			if ( Bawl.replyLinkParamsOpened.redirect ) {
				window.location = mw.config.get('wgArticlePath').replace('$1',mw.config.get('wgPageName'))+'#'+Bawl.flattenWikiText(Bawl.UITextInputTitle.getValue()).replace(/ /g,'_');
				return;
			}
			if ( Bawl.replyLinkParamsOpened.forcepurge || Bawl.replyLinkParamsOpened.pageTitle.replace(/ /g,'_') != mw.config.get('wgPageName') ) {
				Bawl.purgeParams = {'action':'purge','format':'json','titles':[mw.config.get('wgPageName')]};
				api.post(Bawl.purgeParams).then(function(data) {
					Bawl.debug('purged cache of ' + Bawl.replyLinkParamsOpened.pageTitle);
					Bawl.debug(data); 
				}, function ( code, data ) {
					Bawl.debug('purging of ' + Bawl.replyLinkParamsOpened.pageTitle + ' failed:' + code);
					Bawl.debug(data);
				});
			}
			if ( Bawl.oneTimeTools && Bawl.oneTimeTools.blockMod && Bawl.oneTimeTools.blockMod.getValue() != '' ) {
				Bawl.oneTimeTools.blockModSummarySpace = '';
				if ( Bawl.UITextInputSummary.getValue().trim() != '' ) {
					Bawl.oneTimeTools.blockModSummarySpace = ' ';
				}
				Bawl.oneTimeTools.blockModSummary = Bawl.UITextInputSummary.getValue().trim() + Bawl.oneTimeTools.blockModSummarySpace + '[[' + Bawl.basicmsgs.specialdiff + '/' + apiResponse.edit.newrevid + ']]';
				Bawl.blockModParams = {format:'json',user:mw.config.get('wgRelevantUserName'),reason:Bawl.oneTimeTools.blockModSummary,autoblock:true,nocreate:true};
				if ( Bawl.oneTimeTools.blockMod.getValue() == 'unblock' ) {
					Bawl.blockModParams.action = 'unblock';
				} else {
					Bawl.blockModParams.action = 'block';
					Bawl.blockModParams.expiry = Bawl.oneTimeTools.blockMod.getValue();
					Bawl.blockModParams.noemail = Bawl.oneTimeTools.blockModmail.isSelected();
					if ( ! Bawl.oneTimeTools.blockModtalk.isSelected() ) {
						Bawl.blockModParams.allowusertalk = true;
					}
					Bawl.blockModParams.reblock = true;
				}
				api.postWithEditToken( Bawl.blockModParams ).then( function ( apiResponse ) {
					if (apiResponse.block) {
						mw.notify(Bawl.basicmsgs.blockedtitle,{autoHide:false});
					} else if (apiResponse.unblock) {
						mw.notify($(Bawl.basicmsgs.unblocked.replace(/\$1/g,encodeURIComponent(Bawl.blockModParams.user.replace(/ /g,'_')))+'<span></span>'),{autoHide:false});
					}
				}, function ( code, data ) { Bawl.APIError(code, data);});
			}
			if ( Bawl.settings.saveDraft ) {
					Bawl.saveDraft(Bawl.replyLinkParamsOpened, 'remove');
			}
			delete Bawl.newCommentID;
			if ( Bawl.settings.useLocator && ['comment','BCL','newsection','newheading'].indexOf(Bawl.replyLinkParamsOpened.type) != -1 ) {
				Bawl.newCommentTimestamp = new Date(apiResponse.edit.newtimestamp).getTime().toFixed().slice(0,-3);
				if ( typeof Bawl.locatorID != 'undefined' && Bawl.locatorID.match(/((subst:#time:xNU))/) ) {
					Bawl.newCommentID = '#' + Bawl.locatorID.replace('((subst:#time:xNU))', Bawl.newCommentTimestamp);
				}
			} else if ( Bawl.settings.useLocator && Bawl.replyLinkParamsOpened.type == 'edit' ) {
				if ( document.getElementById(Bawl.replyLinkParamsOpened.id) ) {
					Bawl.newCommentID = '#' + encodeURIComponent(Bawl.replyLinkParamsOpened.id);
				} else if ( document.getElementById('bawlLink-' + Bawl.escapeHTML(Bawl.replyLinkParamsOpened.id)) ){
					Bawl.newCommentID = '#' + encodeURIComponent('bawlLink-' + Bawl.escapeHTML(Bawl.replyLinkParamsOpened.id));
				}
			} else if ( Bawl.replyLinkParamsOpened.type == 'heading' && Bawl.replyLinkParamsOpened.subtype == 'edit' ) {
				Bawl.newCommentID = '#' + Bawl.replyLinkParamsOpened.sectionTitle.replace(/ /g,'_');
			} else {
				Bawl.newCommentID = '';
			}
			if ( Bawl.replyLinkParamsOpened.freshindent && Bawl.commentTextIndent && ! Bawl.commentTextIndent.match(/┌/) ) {
				Bawl.freshindent = Bawl.replyLinkParamsOpened.freshindent +1;
			} else if ( Bawl.commentTextIndent && Bawl.commentTextIndent.match(/┌/) ) {
				Bawl.freshindent = (1 - Bawl.cmtIndentHTML);
			} else {
				Bawl.freshindent = 1;
			}
			if ( Bawl.highestRLPInt ) {
				Bawl.highestRLPInt++;
			} else if ( Bawl.replyLinkParams ) {
				Bawl.highestRLPInt = Number(Object.keys(Bawl.replyLinkParams)[Object.keys(Bawl.replyLinkParams).length-1]) +1;
			} else {
				Bawl.replyLinkParams = {};
				Bawl.highestRLPInt = 0;
			}
			if ( Bawl.replyLinkParamsOpened.type == 'edit' ) {
				Bawl.newOrigTimestamp = Bawl.replyLinkParamsOpened.origTimestamp;
			} else {
				Bawl.newOrigTimestamp = Bawl.newCommentTimestamp + Bawl.commentMilliseconds;
			}
			Bawl.previewPostedParams = {
				'int': Bawl.highestRLPInt,
				'type':'comment',
				'subtype':'locator',
				'id': decodeURIComponent(Bawl.newCommentID.slice(1)),
				'origid': Bawl.replyLinkParamsOpened.id,
				'pageTitle': Bawl.replyLinkParamsOpened.pageTitle,
				'origReplyTo': Bawl.userName,
				'origTimestamp': Bawl.newOrigTimestamp,
				'sectionTitle': Bawl.replyLinkParamsOpened.sectionTitle,
				'seq':0,
				'sectionseq':Bawl.replyLinkParamsOpened.sectionseq,
				'freshcomment':true,
				'freshindent':Bawl.freshindent
			};
			Bawl.replyLinkParams[Bawl.previewPostedParams.int] = Bawl.previewPostedParams; //registering the new comment in the internal administration
			if ( Bawl.newCommentID.slice(1) != '' ) {
				Bawl.processElementArray[Bawl.previewPostedParams.int] = document.getElementById(decodeURIComponent(Bawl.newCommentID.slice(1))); //associating a DOM element with the new comment
			}
			if ( Bawl.settings.stalkAutoSub && Bawl.signatureAdded && Bawl.previewPostedParams.origid != 'Bawl-comment-link' ) {
				Bawl.stalkSubscribe(Bawl.previewPostedParams);
			}
			if ( ['link','reload'].includes(Bawl.settings.afterPost) ) {
				document.getElementById('bawlForm-' + Bawl.replyLinkParamsOpened.id).outerHTML = document.getElementById('bawlForm-' + Bawl.replyLinkParamsOpened.id).outerHTML + '<span id="thanksForUsing"><a href="?' + Math.floor(Math.random()*100000) + Bawl.newCommentID + '">' + Bawl.msgs.commentDone + '</a>' + Bawl.msgs.commentPostedThankYou + '</span>'; // the ? forces page reload, # provides anchor to the comment that was commented on
			}
			Bawl.cancelReply(); //closes the reply form
			if ( Bawl.mustReload == true || ['reload','parsepage'].includes(Bawl.settings.afterPost) || (! ['comment','edit','newsection','newheading'].includes(Bawl.replyLinkParamsOpened.type) && Bawl.settings.afterPost != 'link' ) || ['newsection','newheading'].includes(Bawl.replyLinkParamsOpened.type) && Bawl.settings.afterPost == 'parsecmtonly' ) {
				if ( Bawl.newCommentID != '' ) {
					window.location = Bawl.newCommentID;
				}
				if ( Bawl.settings.afterPost == 'reload' ) {
					if(Bawl.settings.debug){OO.ui.confirm('Reload?').done(function(a){if(a){location.reload();)));}else{//Bawl.debug
						var DelayedReload = setInterval(function(){clearInterval(DelayedReload); location.reload();}, 2000); //if we reload immediately we may not get served the most recent revision with our comment
					}//Bawl.debug
				} else {
					Bawl.parsePageInPlace();
				}
			} else if ( ['parse','parsecmtonly'].includes(Bawl.settings.afterPost) ) {
				Bawl.debug('previewPostedParams:');
				Bawl.debug(Bawl.previewPostedParams);
				Bawl.postCommentSuccess = true;
				$('.BawlPurpleBG').removeClass('BawlPurpleBG'); //it clears all the purple
				if ( Bawl.postedCommentParsed && document.getElementById(Bawl.wrongLocatorID) && Bawl.newCommentID != '#' ) {
					Bawl.debug('editing took longer than preview parsing (this is common), patch up preview');
					document.getElementById(Bawl.wrongLocatorID).id = Bawl.escapeHTML(decodeURIComponent(Bawl.newCommentID.slice(1)));
					document.getElementById('PreviewAfterPost').id = 'PreviewAfterPost-' + Bawl.escapeHTML(decodeURIComponent(Bawl.newCommentID.slice(1))); //keep IDs unique if a user posts multiple comments without reloading
					Bawl.addReplyLinkTo(Bawl.previewPostedParams); //adds edit link
				}
			}
			if ( $('.BawlForm')[0] ) {
				Bawl.debug('the form hadn\'t been removed, possibly due to some "awww shit", possibly triggered by a timeout. Removing the form now, including any attached "awww shit" as apparently the edit came through after all.');
				$('.BawlForm')[0].remove();
				mw.notify(Bawl.msgs.nevermind);
			}
			Bawl.debug('edit succeeded, empty input fields');
			Bawl.UITextInput.setValue('');
			Bawl.UITextInputTitle.setValue('');
		}
	}, function ( code, data ) { Bawl.APIError(code, data);
	});
};
Bawl.APIError = function(code,data,extra) {
	Bawl.debug(code);
	Bawl.debug(data);
	if ( typeof data != 'undefined' && typeof data.error != 'undefined' ) {
		Bawl.addScrewedLink(data.error.code,'API: "' + data.error.info + '"');
	} else {
		Bawl.APIErrorExtra = '';
		if(extra){Bawl.APIErrorExtra = ' '+extra;}
		Bawl.addScrewedLink('no_response','Received no response from API. Is your internet plugged in?'+Bawl.APIErrorExtra);
	}
};
Bawl.escapeRegExp = function(text) {
	if ( text ) {
		return mw.util.escapeRegExp(text);
	} else {
		return '';
	}
};
Bawl.escapeReplacement = function(text) {
	return text.replace(/\$/g, '$$$$');
};
Bawl.escapeHTML = function(text) {
Bawl.debug('escaping HTML for "' + text + '"');
	if ( typeof text == 'undefined' ) {
		return '';
	} else if ( typeof text != 'string' ) {
		text = text.toString();
	}
	return text.replace(/\&/g, '&amp;').replace(/\'/g, '&apos;').replace(/\"/g, '&quot;').replace(/</g, '&lt;').replace(/\>/g, '&gt;');
};
Bawl.copyToClipBoard = function(text,permaLinkInt,mode) {
	if (document.queryCommandSupported && document.queryCommandSupported("copy")) {
		try {
			if ( mode == 'nonPerma' ) {
				Bawl.nonPermaLinkText[permaLinkInt].select();
			} else {
				Bawl.permaLinkText[permaLinkInt].select();
			}
			document.execCommand("copy");
			$('#BawlpermaLink-' + permaLinkInt).remove();
			$('#genLink-' + permaLinkInt).removeClass('BawlNoDisplay');
		} catch (fubar) {
			mw.notify(Bawl.basicmsgs['mw-widgets-copytextlayout-copy-fail'] + fubar,{type:'error'});
			Bawl.debug('could not copy ' + Bawl.permaLink + ' to clipboard: ' + fubar);
		}
	}
};
Bawl.permaLinkIDs = {};
Bawl.permaLinkText = {};
Bawl.permaLinkCutButton = {};
Bawl.permaLinkCancel = {};
Bawl.permaLinkLayout = {};
Bawl.nonPermaLinkText = {};
Bawl.nonPermaLinkCutButton = {};
Bawl.nonPermaLinkLayout = {};
Bawl.genPermaLink = function(replyLinkParams,mode) {
	Bawl.debug('get ID for permalink or to give thanks');
	Bawl.debug(replyLinkParams);
	replyLinkParams = Bawl.addPageAndSectionTitleToRPL(replyLinkParams);
	delete Bawl.permaLink;
	if ( mode == 'link' && $('.BawlForm')[0] && Bawl.settings.dateLinksIconAlt && replyLinkParams.pageTitle == Bawl.replyLinkParamsOpened.pageTitle && replyLinkParams.sectionTitle == Bawl.replyLinkParamsOpened.sectionTitle && replyLinkParams.sectionseq == Bawl.replyLinkParamsOpened.sectionseq ) {
		Bawl.addAnchorTimestamp = Bawl.sigDateToMachineReadable(replyLinkParams.origTimestamp,true);
		Bawl.addAnchorCmtLink = Bawl.unixTimeToFlatDate(Bawl.addAnchorTimestamp) + '_' + replyLinkParams.origReplyTo.replace(/ /g,'_');
		Bawl.insertMarkup('cI','','[[#' + Bawl.addAnchorCmtLink + ']]','');
		return;
	}
	if ( replyLinkParams.subtype == 'legacy' || mode == 'thanks' ) {
		if ( replyLinkParams.subtype == 'legacy' ) {
			Bawl.debug('timestamp from legacy: ' + replyLinkParams.origTimestamp);
			Bawl.rvStartPermaLink = new Date(Bawl.sigDateToMachineReadable(replyLinkParams.origTimestamp)).toISOString();
		} else if ( replyLinkParams.subtype == 'locator' ) {//locator permalink is oldid. locator thanks requires, just like legacy, a diff id
			Bawl.debug('timestamp from locator: ' + replyLinkParams.origTimestamp);
			Bawl.rvStartPermaLink = new Date(Number(replyLinkParams.origTimestamp)).toISOString();
		}
		Bawl.currentPageTextParams = {'action':'query','format':'json','titles': replyLinkParams.pageTitle,'prop':'revisions','rvstart':Bawl.rvStartPermaLink,'rvlimit':1,'rvdir':'newer'};
	} else if ( typeof Bawl.permaLinkIDs[replyLinkParams.pageTitle] == 'number' ) {
		Bawl.permaLinkID = Bawl.permaLinkIDs[replyLinkParams.pageTitle];
		Bawl.insertPermaLinkForm(replyLinkParams,mode,Bawl.permaLinkID);
		return;
	} else if ( replyLinkParams.pageTitle != mw.config.get('wgPageName').replace(/_/g,' ') ) {
		Bawl.currentPageTextParams = {'action':'query','format':'json','titles': replyLinkParams.pageTitle,'prop':'revisions'};
	} else {
		Bawl.permaLinkID = mw.config.get('wgCurRevisionId');
		Bawl.insertPermaLinkForm(replyLinkParams,mode,Bawl.permaLinkID);
		return;
	}
	api.get(Bawl.currentPageTextParams).then(function(currentPageRevID) {
		Bawl.debug(currentPageRevID);
		if ( ! currentPageRevID.query.pages[-1] ) {
			Bawl.debug('got revision info to create permalink');
			Bawl.permaLinkID = currentPageRevID.query.pages[ Object.keys(currentPageRevID.query.pages)[0] ].revisions[0].revid;
			Bawl.debug('permaLinkID is '+Bawl.permaLinkID);
			Bawl.permaLinkIDs[replyLinkParams.pageTitle] = Bawl.permaLinkID;
			if ( mode == 'thanks' ) {
				Bawl.thankParams = {'action':'thank','format':'json','rev':Bawl.permaLinkID,'source':'Bawl!'};
				$('#' + Bawl.confirmThanksLink.id).remove();
				api.postWithEditToken(Bawl.thankParams).then(function(data) {
					$('#thankLink-' + replyLinkParams.int + ' span').removeClass('BawlSVGHeartIcon').addClass('BawlSVGHeartRedIcon');
					$('#thankLink-' + replyLinkParams.int).removeClass('BawlNoDisplay').removeClass('BawlLeftRightMarginWide');
					if ( window.localStorage.BawlThanks && Bawl.testValidJSON(window.localStorage.BawlThanks) ) {
						Bawl.thankedComments = JSON.parse(window.localStorage.BawlThanks);
					} else {
						Bawl.thankedComments = {};
					}
					if ( Object.keys(Bawl.thankedComments).length > 500 ) {//remove the two oldest thanks given, only the last 500 thanked edits are remembered so localStorage can't overflow
						delete Bawl.thankedComments[ Object.keys(Bawl.thankedComments).sort()[0] ];
						delete Bawl.thankedComments[ Object.keys(Bawl.thankedComments).sort()[1] ];
					}
					Bawl.debug('add ' + replyLinkParams.id + ' to localStorage.BawlThanks');
					Bawl.thankTimestamp = new Date().getTime();
					Bawl.thankedComments[Bawl.thankTimestamp] = replyLinkParams.id;
					Bawl.debug('set localStorage item');
					window.localStorage.setItem('BawlThanks',JSON.stringify(Bawl.thankedComments));
				}, function ( code, data ) {
					if ( data.error && data.error.info ) {
						$('#thankLink-' + replyLinkParams.int).removeClass('BawlNoDisplay').removeClass('BawlLeftRightMarginWide');
						mw.notify(data.error.info); //it's just thanks, doesn't compromise the reliability of this script if it doesn't work, so no big "awww shit" here
					}
				});
				return;
			} else {
				Bawl.insertPermaLinkForm(replyLinkParams,mode,Bawl.permaLinkID);
			}
		} else {
			mw.notify(Bawl.basicmsgs.actionfailed,{type:'error'});
		}
	}, function ( code, data ) { Bawl.APIError(code, data);
	});
};
Bawl.insertPermaLinkForm = function(replyLinkParams,mode,permaLinkID) {
			if ( replyLinkParams.subtype == 'locator' ) {
				Bawl.permaLinkAnchor = replyLinkParams.id.replace(/ /g, '_');
			} else if ( replyLinkParams.type == 'newheading' ) {
				Bawl.permaLinkAnchor = replyLinkParams.sectionTitle;
				if ( replyLinkParams.sectionseq > 0 ) {
					Bawl.permaLinkAnchor = Bawl.permaLinkAnchor + '_' + ( replyLinkParams.sectionseq + 1);
				}
			}
			if ( replyLinkParams.subtype == 'legacy' ) {
				Bawl.permaLink = Bawl.serverName + mw.config.get('wgArticlePath').replace('$1',Bawl.basicmsgs.specialdiff + '/' + permaLinkID);
			} else {// section permalinks are "ugly" (not using Special:Permalink) because the "ugly" variant includes the page title which Bawl can use while rewriting.
				Bawl.permaLink = Bawl.serverName + mw.config.get('wgScriptPath') + '/index.php?title=' + encodeURIComponent(replyLinkParams.pageTitle.replace(/ /g, '_')) + '&oldid=' + permaLinkID + '#' + Bawl.permaLinkAnchor.replace(/ /g,'_');
				Bawl.nonPermaLink = Bawl.serverName + mw.config.get('wgArticlePath').replace('$1',encodeURIComponent(replyLinkParams.pageTitle.replace(/ /g, '_'))) + '#' + Bawl.permaLinkAnchor.replace(/ /g,'_');
			}
			mw.loader.using( [ 'oojs-ui-core' ] ).then( function () {
				Bawl.permaLinkText[replyLinkParams.int] = new OO.ui.TextInputWidget( {
					value: Bawl.permaLink,
					classes: ['BawlpermaLinkText'],
					readOnly: true
				} );
				Bawl.permaLinkCutButton[replyLinkParams.int] = new OO.ui.ButtonWidget( {
					label:new OO.ui.HtmlSnippet('  '+Bawl.svgBawlCopyIconData+'  '),
					flags:['progressive','primary']
				} );
				Bawl.permaLinkCutButton[replyLinkParams.int].on('click', function() { Bawl.copyToClipBoard(Bawl.permaLink,replyLinkParams.int); });
				Bawl.permaLinkCancel[replyLinkParams.int] = new OO.ui.ButtonWidget( {
					label:new OO.ui.HtmlSnippet('  '+Bawl.svgBawlCancelIconData+'  '),
					flags:['progressive','primary']
				} );
				Bawl.permaLinkCancel[replyLinkParams.int].on('click', function() { Bawl.permaLinkLayout[replyLinkParams.int].toggle(false);$('#genLink-' + replyLinkParams.int).removeClass('BawlNoDisplay'); });
				Bawl.permaLinkLayout[replyLinkParams.int] = new OO.ui.HorizontalLayout( {
					items: [Bawl.permaLinkText[replyLinkParams.int],Bawl.permaLinkCutButton[replyLinkParams.int],Bawl.permaLinkCancel[replyLinkParams.int]],
					id: 'BawlpermaLink-' + replyLinkParams.int,
					classes: ['BawlLinks','BawlLeftRightMargin']
				} );
				Bawl.debug('add field with permalink to processElementArray #' + replyLinkParams.int + ' with ID bawlLink-' + Bawl.escapeHTML(replyLinkParams.id).replace(/([\-\.:%\/\(\)\!\?])/g,'\\$1'));
				if ( replyLinkParams.type == 'newheading' ) {
					document.getElementById('bawlLink-' + Bawl.escapeHTML(replyLinkParams.id)).prepend(Bawl.permaLinkLayout[replyLinkParams.int].$element[0]);
				} else {
					Bawl.appendToFirstBlockParent(document.getElementById('bawlLink-' + Bawl.escapeHTML(replyLinkParams.id)),Bawl.permaLinkLayout[replyLinkParams.int].$element[0],'permalink');
				}
				if ( Bawl.settings.dateLinksIconSectExtra && replyLinkParams.type == 'newheading' ) {
					Bawl.nonPermaLinkText[replyLinkParams.int] = new OO.ui.TextInputWidget( {
						value: Bawl.nonPermaLink,
						classes: ['BawlpermaLinkText'],
						readOnly: true
					} );
					Bawl.nonPermaLinkCutButton[replyLinkParams.int] = new OO.ui.ButtonWidget( {
						label:new OO.ui.HtmlSnippet('  '+Bawl.svgBawlCopyIconData+'  '),
						flags:['progressive','primary']
					} );
					Bawl.nonPermaLinkCutButton[replyLinkParams.int].on('click', function() { Bawl.copyToClipBoard(Bawl.nonPermaLink,replyLinkParams.int,'nonPerma'); });
					Bawl.nonPermaLinkLayout[replyLinkParams.int] = new OO.ui.HorizontalLayout( {
						items: [Bawl.nonPermaLinkText[replyLinkParams.int],Bawl.nonPermaLinkCutButton[replyLinkParams.int]],
					} );
					$('#BawlpermaLink-' + replyLinkParams.int).append('<br />');
					$('#BawlpermaLink-' + replyLinkParams.int).append(Bawl.nonPermaLinkLayout[replyLinkParams.int].$element);
				}
				$('#genLink-' + replyLinkParams.int).addClass('BawlNoDisplay');
				Bawl.permaLinkText[replyLinkParams.int].select();
			});
};
Bawl.giveThanks = function(replyLinkParams) {
	Bawl.debug('create thank confirmation/cancel link');
	Bawl.confirmThanksLink = document.createElement('span');
	Bawl.confirmThanksLink.id = 'submitThanksLink-' + replyLinkParams.int;
	Bawl.confirmThanksLink.classList.add('BawlLeftRightMarginWide');
	Bawl.submitThanksLink = document.createElement('a');
	Bawl.submitThanksLink.onclick = function(){Bawl.genPermaLink(replyLinkParams,'thanks');};
	Bawl.submitThanksLink.innerText = Bawl.basicmsgs['flow-thanks-confirmation-special'];
	Bawl.confirmThanksLink.append(Bawl.submitThanksLink);
	Bawl.confirmThanksLink.append(' / ');
	Bawl.cancelThanksLink = document.createElement('a');
	Bawl.cancelThanksLink.innerText = Bawl.basicmsgs.cancel;
	Bawl.cancelThanksLink.onclick = function(){$('#' + Bawl.confirmThanksLink.id).remove();$('#thankLink-' + replyLinkParams.int).removeClass('BawlNoDisplay');$('#thankLink-' + replyLinkParams.int).removeClass('BawlLeftRightMarginWide');};
	Bawl.confirmThanksLink.append(Bawl.cancelThanksLink);
	if ( typeof $('#' + Bawl.confirmThanksLink.id)[0] == 'undefined' ) {
		$('#thankLink-' + replyLinkParams.int).addClass('BawlLeftRightMarginWide');
		$('#thankLink-' + replyLinkParams.int).addClass('BawlNoDisplay');
		$('#thankLink-' + replyLinkParams.int)[0].parentElement.insertBefore(Bawl.confirmThanksLink,$('#thankLink-' + replyLinkParams.int)[0]);
	}
};
Bawl.rewritunUrUrlz = function(text,mode,linkname) {
	if ( mw.config.get('wgPageContentModel') != 'wikitext' && mode != 'contentmove' && mode != 'addRewritunToOther' ) {
		Bawl.debug('this ain\'t no wikitext page! write your own urls! mode ' + mode);
		return text;
	}
	Bawl.debug('rewritun ur urlz');
	Bawl.rewritunUrUrlz2=text;
	Bawl.debug('rewritun externalLinkRegExp');
	Bawl.rewritunRegExps = {
		'phabpage':'/([^\[\}\|"\']|^)https\\:\\/\\/phabricator\.wikimedia\.org\\/(([^\\n\\.\\,\\?\\& ]|[\\.\\,\\?][^$ \\n])*)/$1[[:phab:$2]]/g',//https://phabricator.wikimedia.org/T306737
		'page':'/([^\[\}\|"\']|^)https\\:\\/\\/([a-z\-]{0,10})(\.m)?\.(wikipedia|wikimedia|mediawiki|wikidata|wikibooks|wiktionary|wikinews|wikiquote|wikisource|wikiversity|wikivoyage)\.org\\/wiki\\/(([^\\n\\.\\,\\?\\& ]|[\\.\\,][^$ \\n])*)([\\.\\, \\n]|\\?($| |\\n)|$)/$1[[INTERWIKI:$2.$4:$5]]$7/g',//https://en.wikipedia.org/wiki/Main_Page, https://www.wikidata.org/wiki/Wikidata:Main_Page
		'diffbare':'/([^\[\}\|"\']|^)https\\:\\/\\/([a-z\-]{0,10})(\.m)?\.(wikipedia|wikimedia|mediawiki|wikidata|wikibooks|wiktionary|wikinews|wikiquote|wikisource|wikiversity|wikivoyage)\.org\\/w\\/index\.php\\?diff\=([0-9]+)(\\&oldid\=[0-9]*)?([\\.\\, \\n]|\\?($| |\\n)|$)/$1[[INTERWIKI:$2.$4:' + Bawl.basicmsgs.specialdiff + 'SLASHCHAR$5|$3' + Bawl.basicmsgs.difflinknamebare + ']]$7/g',//https://en.wikipedia.org/w/index.php?diff=1 (you'd get this from your address bar after following a Special:Diff/1 link)
		'oldidbare':'/([^\[\}\|"\']|^)https\\:\\/\\/([a-z\-]{0,10})(\.m)?\.(wikipedia|wikimedia|mediawiki|wikidata|wikibooks|wiktionary|wikinews|wikiquote|wikisource|wikiversity|wikivoyage)\.org\\/w\\/index\.php\\?oldid\=([0-9]*)(#([^ \\n,\?\!]|[\.\?\!][^$\s])*)?([\\.\\, \\n]|\\?($| |\\n)|$)/$1[[INTERWIKI:$2.$4:' + Bawl.basicmsgs.specialpermalink + 'SLASHCHAR$5|' + Bawl.basicmsgs.revid + ']]$8/g',//https://en.wikipedia.org/w/index.php?oldid=1085167190 (you'd get this from your address bar after following a Special:Permalink/1 link)
		'diff':'/([^\[\}\|"\']|^)https\\:\\/\\/([a-z\-]{0,10})(\.m)?\.(wikipedia|wikimedia|mediawiki|wikidata|wikibooks|wiktionary|wikinews|wikiquote|wikisource|wikiversity|wikivoyage)\.org\\/w\\/index\.php\\?(title\=(([^\\n\\.\\,\\?\\& ]|[\\.\\,\\?][^$ \\n])*)\\&)?diff\=([0-9]+)\\&oldid\=[0-9]*([\\.\\, \\n]|\\?($| |\\n)|$)/$1[[INTERWIKI:$2.$4:' + Bawl.basicmsgs.specialdiff + 'SLASHCHAR$8|$6' + Bawl.basicmsgs.difflinkname + ']]$9/g',//https://en.wikipedia.org/w/index.php?title=Main_Page&diff=1085170884&oldid=1085167190
		'diffprevnext':'/([^\[\}\|"\']|^)https\\:\\/\\/([a-z\-]{0,10})(\.m)?\.(wikipedia|wikimedia|mediawiki|wikidata|wikibooks|wiktionary|wikinews|wikiquote|wikisource|wikiversity|wikivoyage)\.org\\/w\\/index\.php\\?(title\=(([^\\n\\.\\,\\?\\& ]|[\\.\\,\\?][^$ \\n])*)\\&)?diff\=(next|prev)\\&oldid\=([0-9]*)([\\.\\, \\n]|\\?($| |\\n)|$)/$1[[INTERWIKI:$2.$4:' + Bawl.basicmsgs.specialdiff + 'SLASHCHAR$9SLASHCHAR$8|$6' + Bawl.basicmsgs.difflinknameprevnext + ']]$10/g',//https://en.wikipedia.org/w/index.php?title=Main_Page&diff=next&oldid=1085167190
		'spaceremoval':'/(Special\:Diff.[0-9]*)(\\/)?(prev|next)?. /$1$2$3|/g',
		'oldid':'/([^\[\}\|"\']|^)https\\:\\/\\/([a-z\-]{0,10})(\.m)?\.(wikipedia|wikimedia|mediawiki|wikidata|wikibooks|wiktionary|wikinews|wikiquote|wikisource|wikiversity|wikivoyage)\.org\\/w\\/index\.php\\?title\=(([^\\n\\.\\,\\?\\& ]|[\\.\\,\\?][^$ \\n])*)\\&oldid\=([0-9]*)(#([^ \\n,\?\!]|[\.\?\!][^$\s])*)?([\\.\\, \\n]|\\?($| |\\n)|$)/$1[[INTERWIKI:$2.$4:' + Bawl.basicmsgs.specialpermalink + 'SLASHCHAR$7$8|$5 (' + Bawl.basicmsgs.revid.replace('$5','$7') + ')]]$10/g',//https://en.wikipedia.org/w/index.php?title=Main_Page&oldid=1085167190
		'redlink':'/([^\[\}\|"\']|^)https\\:\\/\\/([a-z\-]{0,10})(\.m)?\.(wikipedia|wikimedia|mediawiki|wikidata|wikibooks|wiktionary|wikinews|wikiquote|wikisource|wikiversity|wikivoyage)\.org\\/w\\/index\\.php\\?title=([^\\&\\n]*)\\&action=edit\\&redlink=1([\\.\\, \\n]|\\?($| |\\n)|$)/$1[[INTERWIKI:$2.$4:$5]]$6/g',//https://en.wikipedia.org/w/index.php?title=Page_does_not_exist_yet&action=edit&redlink=1
		'history':'/([^\[\}\|"\']|^)https\\:\\/\\/([a-z\-]{0,10})(\.m)?\.(wikipedia|wikimedia|mediawiki|wikidata|wikibooks|wiktionary|wikinews|wikiquote|wikisource|wikiversity|wikivoyage)\.org\\/w\\/index\\.php\\?title=([^\\&\\n]*)\\&action=history([\\.\\, \\n]|\\?($| |\\n)|$)/$1[[INTERWIKI:$2.$4:' + Bawl.basicmsgs.specialhistory + 'SLASHCHAR$5|' + Bawl.basicmsgs.pageHistoryLinkName + ']]$6/g',//https://en.wikipedia.org/w/index.php?title=Main_Page&action=history
		'pagetitle':'/([^\[\}\|"\']|^)https\\:\\/\\/([a-z\-]{0,10})(\.m)?\.(wikipedia|wikimedia|mediawiki|wikidata|wikibooks|wiktionary|wikinews|wikiquote|wikisource|wikiversity|wikivoyage)\.org\\/w\\/index\.php\\?(title\=(([^\\n\\.\\,\\?\\!\\& ]|[\\.\\,\\?\\!][^$ \\n])*))([\\.\\, \\n]|\\?($| |\\n)|$)/$1[[INTERWIKI:$2.$4:$6]]$8/g',//https://en.wikipedia.org/w/index.php?title=Main_Page
		'localwiki':'/\\[\\[INTERWIKI:' + Bawl.escapeRegExp(mw.config.get('wgServer').replace(/\/\/([^\/]*)\.org.*/, '$1')) + '/INTERWIKI[[/g',
		'nonlocalwikidiff':'/(\\[\\[INTERWIKI:[a-z][a-z:\.\-]*(?!Special:Diff)\/)(' + Bawl.escapeRegExp(Bawl.basicmsgs.specialdiff) + ')/$1Special:Diff/g',//for interwiki links the special page names are rewritten back to English. Those work everywhere. I could store or request the localized name for diff/permalink/history, but frankly, my dear, I don't give a damn
		'nonlocalwikipermalink':'/(\\[\\[INTERWIKI[^\\[][a-z:\.\-]*(?!Special:PermaLink)\/)(' + Bawl.escapeRegExp(Bawl.basicmsgs.specialpermalink) + ')/$1Special:PermaLink/g',
		'nonlocalwikihistory':'/(\\[\\[INTERWIKI[^\\[][[a-z:\.\-]*(?!Special:History)\/)(' + Bawl.escapeRegExp(Bawl.basicmsgs.specialhistory) + ')/$1Special:PageHistory/g',
		'testwiki':'/\\[\\[INTERWIKI:test\\.wikipedia/INTERWIKI[[:testwiki/g',
		'commons':'/\\[\\[INTERWIKI:commons\\.wikimedia/INTERWIKI[[:c/g',
		'meta':'/\\[\\[INTERWIKI:meta\\.wikimedia/INTERWIKI[[:m/g',
		'mediawiki':'/\\[\\[INTERWIKI:www\\.mediawiki/INTERWIKI[[:mw/g',
		'foundation':'/\\[\\[INTERWIKI:foundation\\.wikimedia/INTERWIKI[[:foundation/g',
		'species':'/\\[\\[INTERWIKI:species\\.wikimedia/INTERWIKI[[:species/g',
		'wikitech':'/\\[\\[INTERWIKI:wikitech\\.wikimedia/INTERWIKI[[:wikitech/g',
		'wikidata':'/\\[\\[INTERWIKI:www\\.wikidata/INTERWIKI[[:d/g',
		'wikipedia':'/\\[\\[INTERWIKI:([a-z\-]{0,10})\\.wikipedia/INTERWIKI[[:w:$1/g',
		'wikibooks':'/\\[\\[INTERWIKI:([a-z\-]{0,10})\\.wikibooks/INTERWIKI[[:b:$1/g',
		'wiktionary':'/\\[\\[INTERWIKI:([a-z\-]{0,10})\\.wiktionary/INTERWIKI[[:wikt:$1/g',
		'wikinews':'/\\[\\[INTERWIKI:([a-z\-]{0,10})\\.wikinews/INTERWIKI[[:n:$1/g',
		'wikiquote':'/\\[\\[INTERWIKI:([a-z\-]{0,10})\\.wikiquote/INTERWIKI[[:q:$1/g',
		'wikisource':'/\\[\\[INTERWIKI:([a-z\-]{0,10})\\.wikisource/INTERWIKI[[:s:$1/g',
		'wikiversity':'/\\[\\[INTERWIKI:([a-z\-]{0,10})\\.wikiversity/INTERWIKI[[:v:$1/g',
		'wikivoyage':'/\\[\\[INTERWIKI:([a-z\-]{0,10})\\.wikivoyage/INTERWIKI[[:voy:$1/g',
	};
	for (Bawl.int = 0; Bawl.int < Object.keys(Bawl.rewritunRegExps).length; Bawl.int++) {
		Bawl.rewritunReg = Bawl.rewritunRegExps[Object.keys(Bawl.rewritunRegExps)[Bawl.int]].replace(/^\/(.*[^\\])\/(.*[^\\])\/(.*[^\\])/, '$1');
		Bawl.rewritunFlags = Bawl.rewritunRegExps[Object.keys(Bawl.rewritunRegExps)[Bawl.int]].replace(/^\/(.*[^\\])\/(.*[^\\])\/(.*[^\\])/, '$3');
		Bawl.rewritunReplacement = Bawl.rewritunRegExps[Object.keys(Bawl.rewritunRegExps)[Bawl.int]].replace(/^\/(.*[^\\])\/(.*[^\\])\/(.*[^\\])/, '$2');
		Bawl.debug('Expression #' + Bawl.int + ': ' + Bawl.rewritunReg + ', flags: ' + Bawl.rewritunFlags + ', replacement: ' + Bawl.rewritunReplacement);
		Bawl.rewritunRegExp = new RegExp(Bawl.rewritunReg, Bawl.rewritunFlags);
		//We select the preceding character to ensure we're not replacing links that aren't bare. We select the trailing character to ensure we found the end of the URL. If two links that are caught by the same RegExp (e.g. two history links) have only one character between them (like a space or newline) they can't both match, so we run the RegExp twice.
		Bawl.rewritunUrUrlz2 = Bawl.rewritunUrUrlz2.replace(Bawl.rewritunRegExp, Bawl.rewritunReplacement).replace(Bawl.rewritunRegExp, Bawl.rewritunReplacement).replace(/SLASHCHAR/g, '/');
	}
	Bawl.rewritunMatchDiffs = Bawl.rewritunUrUrlz2.match(/Special:Diff\/([0-9]+)\|([^\]]*) \([^\)]*[0-9]+[^\)]*\)/g);
	if ( Bawl.rewritunMatchDiffs ) {
		for (Bawl.int = 0; Bawl.int < Bawl.rewritunMatchDiffs.length; Bawl.int++) {
			Bawl.rewritunUrUrlz2 = Bawl.rewritunUrUrlz2.replace(Bawl.rewritunMatchDiffs[Bawl.int], decodeURIComponent(Bawl.rewritunMatchDiffs[Bawl.int].replace(/%(?![0-9A-Fa-f][0-9A-Fa-f])/g,'%25').replace(/_/g, ' ')));
		}
	}
	Bawl.debug('Rewritten urls: ' + Bawl.rewritunUrUrlz2);
	Bawl.debug('rewritun youtu.be');
	Bawl.rewritunUrUrlz2 = Bawl.rewritunUrUrlz2.replace(/\/\/youtu\.be\/([^\?]*)\?\//g, '\/\/www.youtube.com\/watch\?$1&').replace(/\/\/youtu\.be\//g, '\/\/www.youtube.com\/watch\?'); //rewrite youtu.be shortened urls (these are blacklisted)
	Bawl.rewritunUrUrlz3 = Bawl.rewritunUrUrlz2;
	Bawl.int=0;
	while ( ( Bawl.rewritunUrUrlz2 != Bawl.rewritunUrUrlz3 && Bawl.int < 1000 ) || Bawl.int == 0 ) {
		Bawl.rewritunUrUrlz2 = Bawl.rewritunUrUrlz3;
		Bawl.rewritunUrUrlz3 = Bawl.rewritunUrUrlz3.replace(/\[\[([^_\]\n]{0,1000})_(.*\]\])/g, '[[$1 $2'); //replace underscores in internal links with spaces
		Bawl.int = Bawl.int + 1;
		Bawl.debug('rewritun #' + Bawl.int + ' (' + Bawl.rewritunUrUrlz2 + ' to ' + Bawl.rewritunUrUrlz3 + ')' );
	}
	Bawl.internalLinks = Bawl.rewritunUrUrlz3.match(/INTERWIKI\[\[(([^\]]*|\][^\]])*[\]])/g);
	if ( Bawl.internalLinks ) {
		Bawl.debug('remove percent encoding from internal links');
		for ( Bawl.internalLinksInt = 0;Bawl.internalLinksInt < Bawl.internalLinks.length;Bawl.internalLinksInt++) {
			Bawl.rewritunUrUrlz3 = Bawl.rewritunUrUrlz3.replace(Bawl.internalLinks[Bawl.internalLinksInt],decodeURIComponent(Bawl.internalLinks[Bawl.internalLinksInt].replace(/%(?![0-9A-Fa-f][0-9A-Fa-f])/g,'%25'))).replace(/INTERWIKI\[\[/,'[[');
		}
	}
	Bawl.debug(Bawl.internalLinks);
	Bawl.rewritunUrUrlz4 = Bawl.rewritunUrUrlz3;
	Bawl.rewritunUrUrlz4RegExp = new RegExp('(\\[\\[[^\\]\n\%]*\%[^\\]\n]*\\]\\])', 'g');
	Bawl.rewritunUrUrlz4match = Bawl.rewritunUrUrlz4.match(Bawl.rewritunUrUrlz4RegExp);
	if ( Bawl.rewritunUrUrlz4match ) {
		for (Bawl.int = 0; Bawl.int < Bawl.rewritunUrUrlz4match.length; Bawl.int++) {
			Bawl.debug('rewritun #' + Bawl.int + ', '+ Bawl.rewritunUrUrlz4match[Bawl.int] + ' with ' + decodeURIComponent(Bawl.rewritunUrUrlz4match[Bawl.int].replace(/%(?![0-9A-Fa-f][0-9A-Fa-f])/g,'%25')));
			Bawl.rewritunUrUrlz4 = Bawl.rewritunUrUrlz4.replace(Bawl.rewritunUrUrlz4match[Bawl.int], decodeURIComponent(Bawl.rewritunUrUrlz4match[Bawl.int].replace(/%(?![0-9A-Fa-f][0-9A-Fa-f])/g,'%25')));
		}
	}
	if ( mode == 'insertlink' && linkname != '' ) {
		Bawl.rewritunUrUrlz4 = Bawl.rewritunUrUrlz4.replace(/^([a-z0-9]*:\/\/[^ ]*$)/,'[$1 ' + linkname + ']').replace(/(\[[a-z0-9]*:\/\/[^ ]*) .+\]$/,'$1 ' + linkname + ']').replace(/^(\[\[[^\|]*\|)(.*\]\])$/,'$1' + linkname + ']]').replace(/^(\[\[[^\|]*)\]\]$/, '$1|' + linkname + '\]\]');
	}
	Bawl.debug('finished rewritun');
	return Bawl.rewritunUrUrlz4;
};
Bawl.rewritunOther = function() {
	this.value = Bawl.rewritunUrUrlz(this.value,'addRewritunToOther');//"this" is the <input> element that triggered the event that called rewritunOther
};
Bawl.addRewritunToOther = function() {
	$(document).ready(function() {
		for(Bawl.addRewritunToOtherInt=0;Bawl.addRewritunToOtherInt<$(Bawl.settings.rewritunOther).length;Bawl.addRewritunToOtherInt++){
			if ( ['text','textarea'].includes($(Bawl.settings.rewritunOther)[Bawl.addRewritunToOtherInt].type) && ( ! $(Bawl.settings.rewritunOther)[Bawl.addRewritunToOtherInt].classList || ! $(Bawl.settings.rewritunOther)[Bawl.addRewritunToOtherInt].classList.contains('BawlRewritun') ) ) {
				$(Bawl.settings.rewritunOther)[Bawl.addRewritunToOtherInt].classList.add('BawlRewritun');
				$(Bawl.settings.rewritunOther)[Bawl.addRewritunToOtherInt].addEventListener('blur',Bawl.rewritunOther);
			}
		}
	});
};
if ( Bawl.settings.rewritunOther != '' ) {
	$('body').on('click',function() { Bawl.addRewritunToOther(); });//the reason we don't simply do this on load is that input fields that need rewriting may not exist yet, for example if you haven't opened Twinkle yet, so we check on every click.
}
Bawl.runCIOther = function() {
	this.value = Bawl.runCI(this.value,'runCIOther');
};
Bawl.addrunCIToOther = function() {
	$(document).ready(function() {
		for(Bawl.addrunCIToOtherInt=0;Bawl.addrunCIToOtherInt<$(Bawl.settings.runCIOther).length;Bawl.addrunCIToOtherInt++){
			if ( ['text','textarea'].includes($(Bawl.settings.runCIOther)[Bawl.addrunCIToOtherInt].type) && ( ! $(Bawl.settings.runCIOther)[Bawl.addrunCIToOtherInt].classList || ! $(Bawl.settings.runCIOther)[Bawl.addrunCIToOtherInt].classList.contains('BawlrunCI') ) ) {
				$(Bawl.settings.runCIOther)[Bawl.addrunCIToOtherInt].classList.add('BawlrunCI');
				$(Bawl.settings.runCIOther)[Bawl.addrunCIToOtherInt].addEventListener('blur',Bawl.runCIOther);
			}
		}
	});
};
if ( Bawl.settings.runCIOther != '' ) {
	$('body').on('click',function() { Bawl.addrunCIToOther(); });
}
Bawl.AWBtyposOther = function() {
	Bawl.RETF(this.value,'AWBtyposOther',this); //we pass the element in question to RETF as RETF will just call itself after downloading the list the first time it runs. It needs to know to which element to apply the stuff when it calls itself
};
Bawl.addAWBtyposToOther = function() {
	$(document).ready(function() {
		for(Bawl.addrunCIToOtherInt=0;Bawl.addrunCIToOtherInt<$(Bawl.settings.AWBtyposOther).length;Bawl.addrunCIToOtherInt++){
			if ( ['text','textarea'].includes($(Bawl.settings.AWBtyposOther)[Bawl.addrunCIToOtherInt].type) && ( ! $(Bawl.settings.AWBtyposOther)[Bawl.addrunCIToOtherInt].classList || ! $(Bawl.settings.AWBtyposOther)[Bawl.addrunCIToOtherInt].classList.contains('BawlrunCI') ) ) {
				$(Bawl.settings.AWBtyposOther)[Bawl.addrunCIToOtherInt].classList.add('BawlrunCI');
				$(Bawl.settings.AWBtyposOther)[Bawl.addrunCIToOtherInt].addEventListener('blur',Bawl.AWBtyposOther);
			}
		}
	});
};
if ( Bawl.settings.AWBtyposOther != '' ) {
	$('body').on('click',function() { Bawl.addAWBtyposToOther(); });//the reason we don't simply do this on load is that input fields that need rewriting may not exist yet, for example if you haven't opened Twinkle yet, so we check on every click.
}
Bawl.safeText = function(text,mode,skiplinks) {
	Bawl.safeTextStart = new Date().getTime();//Bawl.debug
	Bawl.safedMarker = 'BAWLSAFED'+Bawl.semiRandom;
	if ( mode == 'unsafe' ) {
		Bawl.debug('safeText: return text to original form');
		Bawl.safeTextPlaceholders = ['LINK','WIKILINK','L6TEMPLATE','L5TEMPLATE','L4TEMPLATE','L3TEMPLATE','L2TEMPLATE','L1TEMPLATE','L0TEMPLATE','CODE','STL','REF','HTMLCOMMENT','PRE','NOWIKI']; //THE ORDER MUST BE THE REVERSE OF THE REPLACEMENTS!!
		for (Bawl.safeTextPlaceholdersInt=0;Bawl.safeTextPlaceholdersInt<Bawl.safeTextPlaceholders.length;Bawl.safeTextPlaceholdersInt++){
			if ( Bawl['RETFEscapeMatched' + Bawl.safeTextPlaceholders[Bawl.safeTextPlaceholdersInt]] ) {
				Bawl.debug('safeText: replace placeholder "'+Bawl.safedMarker+Bawl.safeTextPlaceholders[Bawl.safeTextPlaceholdersInt] + ' with original content');
				for ( Bawl.RETFEscapeInt=0;Bawl.RETFEscapeInt<Bawl['RETFEscapeMatched' + Bawl.safeTextPlaceholders[Bawl.safeTextPlaceholdersInt]].length;Bawl.RETFEscapeInt++) {
					text = text.replace(new RegExp(Bawl.safedMarker + Bawl.safeTextPlaceholders[Bawl.safeTextPlaceholdersInt]),Bawl.escapeReplacement(Bawl['RETFEscapeMatched' + Bawl.safeTextPlaceholders[Bawl.safeTextPlaceholdersInt]][Bawl.RETFEscapeInt]));
				}
			}
		}
		Bawl.debug('restored text in ' + (new Date().getTime() - Bawl.safeTextStart) + 'ms');
		return text;
	} else if ( ! text.match(new RegExp(Bawl.safedMarker)) ) {
		Bawl.debug('safeText: replace tags/links etc with placeholders to stop replacements from matching'); //A note on the order here. It's best to safe items that may contain other items first. So safe ref tags first as they may contain templates. Safe templates before links as they may contain links. A template or link that was already safed as part of something bigger doesn't need to be safed individually, which makes the process faster.
		Bawl.RETFEscapeNew = text;
		Bawl.debug('safeText: safing nowiki tags..');
		Bawl.RETFEscapeMatchedNOWIKIRegExp = new RegExp('<([Nn]o[Ww]iki|NOWIKI)>(([^\^<]|<(?!\/([Nn]o[Ww]iki>|NOWIKI>)))*)<\/([Nn]o[Ww]iki|NOWIKI)>','g');
		Bawl.RETFEscapeMatchedNOWIKI = Bawl.RETFEscapeNew.match(Bawl.RETFEscapeMatchedNOWIKIRegExp);
		Bawl.RETFEscapeNew = Bawl.RETFEscapeNew.replace(Bawl.RETFEscapeMatchedNOWIKIRegExp,Bawl.safedMarker+'NOWIKI');
		Bawl.debug('safeText: safing pre tags..');
		Bawl.RETFEscapeMatchedPRERegExp = new RegExp('<([Pp]re|PRE)>(([^\^<]|<(?!\/([Pp]re>|PRE>)))*)<\/([Pp]re|PRE)>','g');
		Bawl.RETFEscapeMatchedPRE = Bawl.RETFEscapeNew.match(Bawl.RETFEscapeMatchedPRERegExp);
		Bawl.RETFEscapeNew = Bawl.RETFEscapeNew.replace(Bawl.RETFEscapeMatchedPRERegExp,Bawl.safedMarker+'PRE');
		Bawl.debug('safeText: safing HTML comments..');
		Bawl.RETFEscapeMatchedHTMLCOMMENTRegExp = new RegExp('<\!--[ ]*(([^-d]|-(?!->)|d(?!ummy)){0,3000})-->','g');
		Bawl.RETFEscapeMatchedHTMLCOMMENT = Bawl.RETFEscapeNew.match(Bawl.RETFEscapeMatchedHTMLCOMMENTRegExp);
		Bawl.RETFEscapeNew = Bawl.RETFEscapeNew.replace(Bawl.RETFEscapeMatchedHTMLCOMMENTRegExp,Bawl.safedMarker+'HTMLCOMMENT');
		Bawl.debug('safeText: safing ref tags..');
		Bawl.RETFEscapeMatchedREFRegExp = new RegExp('<([Rr]ef|REF)>(([^\^<]|<(?!\/([Rr]ef>|REF>)))*)<\/([Rr]ef|REF)>','g');
		Bawl.RETFEscapeMatchedREF = Bawl.RETFEscapeNew.match(Bawl.RETFEscapeMatchedREFRegExp);
		Bawl.RETFEscapeNew = Bawl.RETFEscapeNew.replace(Bawl.RETFEscapeMatchedREFRegExp,Bawl.safedMarker+'REF');
		Bawl.debug('safeText: safing syntaxhighlight tags..');
		Bawl.RETFEscapeMatchedSTLRegExp = new RegExp('<([Ss]yntax[Hh]igh[Ll]ight[^>]*|SYNTAXHIGHLIGHT[^>]*)>(([^\^<]|<(?!\/([Ss]yntax[Hh]igh[Ll]ight>|SYNTAXHIGHLIGHT>)))*)<\/([Ss]yntax[Hh]igh[Ll]ight|SYNTAXHIGHLIGHT)>','g');
		Bawl.RETFEscapeMatchedSTL = Bawl.RETFEscapeNew.match(Bawl.RETFEscapeMatchedSTLRegExp);
		Bawl.RETFEscapeNew = Bawl.RETFEscapeNew.replace(Bawl.RETFEscapeMatchedSTLRegExp,Bawl.safedMarker+'STL');
		Bawl.debug('safeText: safing code tags..');
		Bawl.RETFEscapeMatchedCODERegExp = new RegExp('<([Cc]ode|CODE)>(([^\^<]|<(?!\/([Cc]ode>|CODE>)))*)<\/([Cc]ode|CODE)>','g');
		Bawl.RETFEscapeMatchedCODE = Bawl.RETFEscapeNew.match(Bawl.RETFEscapeMatchedCODERegExp);
		Bawl.RETFEscapeNew = Bawl.RETFEscapeNew.replace(Bawl.RETFEscapeMatchedCODERegExp,Bawl.safedMarker+'CODE');
		Bawl.debug('safeText: safing templates..');
		Bawl.RETFEscapeMatchedSingleTemplateRegExp = new RegExp('\{\{(([^\{\}]|\{[^\{]|\}[^\}])*)\}\}','g');
		for(Bawl.RETFTemplateSafeInt=0;Bawl.RETFTemplateSafeInt<7;Bawl.RETFTemplateSafeInt++){
			Bawl.debug('safeText: safing templates (nesting level '+Bawl.RETFTemplateSafeInt);
			Bawl['RETFEscapeMatchedL'+Bawl.RETFTemplateSafeInt+'TEMPLATE'] = Bawl.RETFEscapeNew.match(Bawl.RETFEscapeMatchedSingleTemplateRegExp);
			Bawl.RETFEscapeNew = Bawl.RETFEscapeNew.replace(Bawl.RETFEscapeMatchedSingleTemplateRegExp,Bawl.safedMarker+'L'+Bawl.RETFTemplateSafeInt+'TEMPLATE');
		}
		if ( ! skiplinks ) {
			if ( Bawl.settings.rewritun && mode == 'rewritun' ) { //we rewrite URLs here because links in HTML comments etc have already been safed here but links haven't been safed yet.
				Bawl.RETFEscapeNew = Bawl.rewritunUrUrlz(Bawl.RETFEscapeNew);
			}
			Bawl.debug('safeText: safing wikilinks..');
			Bawl.RETFEscapeMatchedWIKILINKRegExp = new RegExp('\\[\\[([^\\]\n]|\\](?![^\\]]))*\\]\\]','g');
			Bawl.RETFEscapeMatchedWIKILINK = Bawl.RETFEscapeNew.match(Bawl.RETFEscapeMatchedWIKILINKRegExp);
			Bawl.RETFEscapeNew = Bawl.RETFEscapeNew.replace(Bawl.RETFEscapeMatchedWIKILINKRegExp,Bawl.safedMarker+'WIKILINK');
			Bawl.debug('safeText: safing external links..');
			Bawl.RETFEscapeMatchedLINKRegExp = new RegExp(':\/\/([^ \n\]\|])*','g');
			Bawl.RETFEscapeMatchedLINK = Bawl.RETFEscapeNew.match(Bawl.RETFEscapeMatchedLINKRegExp);
			Bawl.RETFEscapeNew = Bawl.RETFEscapeNew.replace(Bawl.RETFEscapeMatchedLINKRegExp,Bawl.safedMarker+'LINK');
		}
		Bawl.debug('safed text in ' + (new Date().getTime() - Bawl.safeTextStart) + 'ms');
		return Bawl.RETFEscapeNew;
	} else {
		Bawl.debug('text seems to already have been made safe');
		return text;
	}
};
Bawl.RETFBlacklist = []; //e.g. '-XXX(ed/er/ing/ive)'
Bawl.RETF = function(text,mode,AWBtyposOtherElement) {
	if ( mode == 'onetime' ) {
		Bawl.UITextInput.setReadOnly(true);
	}
	if ( ( Bawl.basicmsgs.AWBtyposTitle != '' || Bawl.settings.AWBtyposCustomTitle != '' ) && mw.config.get('wgPageContentModel') == 'wikitext' ) {
		Bawl.debug('AWB RegExTypoFix');
		if ( typeof Bawl.RETFTypoRegEx == 'undefined' ) {
			Bawl.RETFTypoRegEx = [];
			Bawl.RETFTypoReplacement = [];
			Bawl.RETFTypoRegExWord = [];
			Bawl.debug('obtain ' + Bawl.basicmsgs.AWBtyposTitle + ' to extract regular expressions from');
			if ( Bawl.settings.AWBtyposCustomTitle != '' ) {
				Bawl.AWBtyposTitle = Bawl.settings.AWBtyposCustomTitle;
			} else if ( Bawl.basicmsgs.AWBtyposTitle != '' ) {
				Bawl.AWBtyposTitle = Bawl.basicmsgs.AWBtyposTitle;
			}
			api.get( {'action':'query','format':'json','export':'true','titles': Bawl.AWBtyposTitle} ).then( function ( data ) {
				Bawl.debug(data);
				Bawl.RETFRegExpText = Bawl.getWikitextFromExport(data.query.export['*']).replace(/&lt;/g,'<').replace(/&gt;/g,'>');
				Bawl.RETFRegExpGlobal = new RegExp('<Typo word="(.*)" find="(.*)" replace="(.*)"[ ]?\/>','g');
				Bawl.RETFRegExpGroups = new RegExp(Bawl.RETFRegExpGlobal.source);
				Bawl.RETFRegExpArr = Bawl.RETFRegExpText.match(Bawl.RETFRegExpGlobal);
				for (Bawl.RETFRegExpInt=0;Bawl.RETFRegExpInt<Bawl.RETFRegExpArr.length;Bawl.RETFRegExpInt++) {
					Bawl.RETFTypoRegEx.push(Bawl.RETFRegExpArr[Bawl.RETFRegExpInt].match(Bawl.RETFRegExpGroups)[2]);
					Bawl.RETFTypoReplacement.push(Bawl.RETFRegExpArr[Bawl.RETFRegExpInt].match(Bawl.RETFRegExpGroups)[3]);
					Bawl.RETFTypoRegExWord.push(Bawl.RETFRegExpArr[Bawl.RETFRegExpInt].match(Bawl.RETFRegExpGroups)[1]);
				}
				if ( mode == 'onetime' ) {
					Bawl.debug('running AWB typos just this once');
					Bawl.RETF(text,'onetime');
				} else if ( mode == 'AWBtyposOther' ) {
					Bawl.debug('apply RETF to some field');
					Bawl.RETF(text,mode,AWBtyposOtherElement);
				}
			}, function ( code, data ) { Bawl.RETFRegExp = '';Bawl.APIError(code, data);
			});
			return;
		}
		if ( mode != 'init' ) {
			Bawl.debug('Regular expressions are available, applying them now');
			text = Bawl.safeText(text);
			if ( mode == 'onetime' ) {
				$('#BawlMatchedRETF')[0].innerHTML = '';
			}
			for (Bawl.RETFRegExpInt=0;Bawl.RETFRegExpInt<Bawl.RETFTypoRegEx.length;Bawl.RETFRegExpInt++) {
				Bawl.validRETFRegExp = true;
				try {
					RegExp(Bawl.RETFTypoRegEx[Bawl.RETFRegExpInt]);
				} catch(e) {
					Bawl.validRETFRegExp = false;
				}
				if ( Bawl.validRETFRegExp && Bawl.RETFBlacklist.indexOf(Bawl.RETFTypoRegExWord[Bawl.RETFRegExpInt]) == -1 ) {
					Bawl.RETFnewText = text;
					delete Bawl.RETFoldText;
					Bawl.RETFescapeInt=0;
					while ( Bawl.RETFnewText != Bawl.RETFoldText && Bawl.RETFescapeInt<10000 ) {
						Bawl.RETFoldText = Bawl.RETFnewText;
						Bawl.RETFnewText = Bawl.RETFnewText.replace(new RegExp(Bawl.RETFTypoRegEx[Bawl.RETFRegExpInt]),Bawl.RETFTypoReplacement[Bawl.RETFRegExpInt]);
					}
					if ( Bawl.settings.debug && Bawl.RETFnewText != text ) { Bawl.debug('input text matched ' + Bawl.RETFTypoRegEx[Bawl.RETFRegExpInt]); }
					if ( Bawl.RETFnewText != text && mode == 'onetime' ) {
						$('#BawlMatchedRETF').append(Bawl.msgs.matchedRETF.replace('REGEXP',Bawl.RETFTypoRegEx[Bawl.RETFRegExpInt]).replace('WORD',Bawl.RETFTypoRegExWord[Bawl.RETFRegExpInt]) + '<br/>');
						if ( ! Bawl.RETFsummary.match(new RegExp(', ' + Bawl.escapeRegExp(Bawl.RETFTypoRegExWord[Bawl.RETFRegExpInt]) + '($|,)')) ) {
							Bawl.RETFsummary = ', ' + Bawl.RETFsummary + Bawl.RETFTypoRegExWord[Bawl.RETFRegExpInt];
						}
					}
					text = Bawl.RETFnewText;
				} else if ( Bawl.RETFBlacklist.indexOf(Bawl.RETFTypoRegExWord[Bawl.RETFRegExpInt]) != -1 ) { //Bawl.debug
					Bawl.debug('the replacement for ' + Bawl.RETFTypoRegExWord[Bawl.RETFRegExpInt] + ' is blacklisted');
				}
			}
			if ( mode != 'AWBtyposOther' ) {
				Bawl.RETFsummary = Bawl.RETFsummary.replace(/^, (.*)/,'[[[' + Bawl.basicmsgs.AWBtyposTitle + '|$1]]]');
			}
			text = Bawl.safeText(text,'unsafe');
			if ( mode == 'onetime' ) {
				Bawl.UITextInput.setValue(text);
				Bawl.UITextInput.setReadOnly(false);
				Bawl.focusInput();
			}
			if ( AWBtyposOtherElement ) {
				Bawl.debug('RETF was loaded, now applying it to some field determined by your custom CSS selector');
				AWBtyposOtherElement.value = text;
				return;
			}
			return text;
		}
	} else if ( Bawl.basicmsgs.AWBtyposTitle == '' ) {
		Bawl.debug('Wikidata (Q6585066) has no associated page for AWB RETF for this project and you didn\'t configure a page to use either');
		Bawl.UITextInput.setReadOnly(false);
		return text;
	} else if ( mw.config.get('wgPageContentModel') != 'wikitext' ) {
		Bawl.debug('Do not run AWB RETF on pages that are not wikitext');
		Bawl.UITextInput.setReadOnly(false);
		return text;
	}
};
Bawl.applyMarkdown = function(text) {
	Bawl.debug('Applying Markdown markup');
	return text.replace(/_([^_]*)_/g,'<i>$1</i>').replace(/`([^`]*)`/g, '<code>$1</code>').replace(/(^|\n)---($|\n)/, '$1----$2');
	//todo: lists, links, images, maybe headers.
};
Bawl.applyBBCode = function(text) {
	Bawl.debug('applying BBCode');
	if ( Bawl.basicmsgs.smiley != '' ) {
		text = text.replace(/(^| |\n)(:-\)|;-\)\|:-\()([^a-zA-Z0-9]|$)/g, '$1((' + Bawl.basicmsgs.smiley + '|$2))$3');
	}
	return text.replace(/\[\/?[Bb]\]/g, '\'\'\'').replace(/\[\/?[Ii]\]/g, '\'\'').replace(/\[(\/)?[Uu]\]/g, '<$1u>').replace(/\[(\/)?[Ss]\]/g, '<$1s>').replace(/\[url\](http)?(s?)(:\/\/)?([^\/\[]*)([^\[]*)\[\/url\]/gi, '[http$2://$4$5 ' + '$4' + ']').replace(/\[url="?(http)?(s?)(:\/\/)?([^\/\[]*)([^\[]*)"?\]([^\[]*)\[\/url\]/gi, '[http$2://$4$5 ' + '$6' + ']').replace(/\[img\]([^:\[]*:)?([^\[]*)\[\/img\]/g, '[[' + mw.config.get('wgFormattedNamespaces')[6] + ':$2|thumb]]').replace(/\[(\/)?[Cc]ode\]/g, '<$1code>').replace(/\[[Ss]tyle size="?([0-9]*)"?\]([^\[]*)\[\/(style)?\]/g, '<span style="font-size: $1pt">$2</span>').replace(/\[[Ss]tyle size="?([^"\]]*)"?\]([^\[]*)\[\/(style)?\]/g, '<span style="font-size: $1">$2</span>').replace(/\[([Ss]tyle )?color="?([0-9A-Fa-z]*)"?\]([^\[]*)\[\/(style|color)?\]/g, '<span style="color: $2">$3</span>').replace(/\[\*\] ?([^\n\[]*)\s*/gm, '<li>$1</li>').replace(/\[[Ll]ist\]\s*([^]*)\[\/[Ll]ist\]/gm, '<ul>$1</ul>').replace(/\s*<\/(ul|li)>/g, '</$1>').replace(/\[[Qq](uote)?\]([^\[]*)\[\/[Qq](uote)?\]/g, '<blockquote><p>$2</p></blockquote>').replace(/\[[Qq](uote)?=?"?([^"\]]*)"?\]([^\[]*)\[\/[Qq](uote)?\]/g, '<blockquote><p>$3</p>—$2</blockquote>').replace(/\s*\[(\/)?(td|tr)\]\s*/g, '<$1$2>').replace(/\[[Tt]able\]/g, '<table class="wikitable">').replace(/\[\/[Tt]able\]/g, '</table>');
};
Bawl.insertIsRegExpRegExp = new RegExp('^\/((?:[^\\/]|[\\\\][\/])*)\/((?:[^\\/]|[\\\\][\/])*)\/([gmi]{0,3})$');
Bawl.runCI = function(text,mode) {
	Bawl.debug('start to process automatically applied custom inserts that are regular expressions');
	for (Bawl.int = 0; Bawl.int < 50; Bawl.int++) {
		if ( Bawl.settings.enableCIThatRun && Bawl.settings.cIThatRun && Bawl.settings.cIThatRun[Bawl.int] && Bawl.settings.cIThatRun[Bawl.int] != "" ) { //non-empty insert found
			Bawl.debug('found non-empty regexp to be applied automatically ' + (Bawl.int + 1) + '/50');
			if ( decodeURIComponent(Bawl.settings.cIThatRun[Bawl.int]).match(Bawl.insertIsRegExpRegExp) ) {
				Bawl.customInsertRegExpNowParts = decodeURIComponent(Bawl.settings.cIThatRun[Bawl.int]).match(Bawl.insertIsRegExpRegExp);
				Bawl.customInsertRegExpNow = new RegExp(Bawl.customInsertRegExpNowParts[1], Bawl.customInsertRegExpNowParts[3]);
				text = text.replace(Bawl.customInsertRegExpNow, Bawl.customInsertRegExpNowParts[2].replace(/\\\//g,'/').replace(/[\\]n/g,'\n'));
				if (mode != 'runCIOther') {
					Bawl.UITextInput.setValue(text);
				}
				Bawl.debug('replaced ' + Bawl.customInsertRegExpNow + ' with ' + Bawl.customInsertRegExpNowParts[2]);
			}
		}
		if ( Bawl.settings.enableCIThatRunCmt && Bawl.settings.cIThatRunCmt && Bawl.settings.cIThatRunCmt[Bawl.int] && Bawl.settings.cIThatRunCmt[Bawl.int] != "" && ! text.match(/NOSIGN$/) && Bawl.replyLinkParamsOpened.type != 'editFullPage' && ! (Bawl.replyLinkParamsOpened.type == 'heading' && Bawl.replyLinkParamsOpened.subtype == 'edit') && mode != 'runCIOther' ) {
			Bawl.debug('found non-empty regexp to be applied automatically and you\'re not editing a full page or section ' + (Bawl.int + 1) + '/50');
			if ( decodeURIComponent(Bawl.settings.cIThatRunCmt[Bawl.int]).match(Bawl.insertIsRegExpRegExp) ) {
				Bawl.customInsertRegExpNowParts = decodeURIComponent(Bawl.settings.cIThatRunCmt[Bawl.int]).match(Bawl.insertIsRegExpRegExp);
				Bawl.customInsertRegExpNow = new RegExp(Bawl.customInsertRegExpNowParts[1], Bawl.customInsertRegExpNowParts[3]);
				text = text.replace(Bawl.customInsertRegExpNow, Bawl.customInsertRegExpNowParts[2].replace(/\\\//g,'/').replace(/[\\]n/g,'\n'));
				if (!['livepreview','runCIOther'].includes(mode)){
					Bawl.UITextInput.setValue(text);
				}
				Bawl.debug('replaced ' + Bawl.customInsertRegExpNow + ' with ' + Bawl.customInsertRegExpNowParts[2]);
			}
		}
	}
	return text;
};
Bawl.convertToOneLineCmt = function(text) {
	if ( Bawl.basicmsgs.newline == '' && ( ( Bawl.replyLinkParamsOpened.type == 'newheading' && Bawl.replyLinkParamsOpened.subtype == 'heading' ) || Bawl.replyLinkParamsOpened.type == 'newsection' ) && ( text.match(/\n(([^<\n]|<(?![Pp]re|PRE))*)<\/([Pp]re|PRE)>/) || text.match(/\n(([^<\n]|<(?![Nn]o[Ww]iki|NOWIKI))*)<\/([Nn]o[Ww]iki|NOWIKI)>/) || text.match(/\n(([^<\n]|<(?![Ss]yntax[Hh]igh[Ll]ight|SYNTAXHIGHLIGHT))*)<\/([Ss]yntax[Hh]igh[Ll]ight|SYNTAXHIGHLIGHT)>/) ) ) {
		Bawl.debug('a newline template is not known AND you\'re posting a new (sub)section which is unindented AND your message appears to contains some multiline pre/nowiki/syntaxhighlight. At the cost being unable to edit your whole comment (you could still edit the whole section of course), we\'ll skip the conversion to a single line for this comment.');
		return text;
	}
	Bawl.debug('converting comment to a single line');
	Bawl.multilineText1 = ' \n \n' + text;
	Bawl.multilineText2 = '';
	Bawl.listInt = 0;
	Bawl.multilineText1 = Bawl.multilineText1.replace(/<([\/])?([Ss]yntax[Hh]igh[Ll]ight|SYNTAXHIGHLIGHT)([^>\n]*)>/g,'<$1syntaxhighlight$3>');
	Bawl.multilineText1 = Bawl.multilineText1.replace(/<([\/])?([Gg]allery|GALLERY)([^>\n]*)>/g,'<$1gallery$3>');
	while ( Bawl.multilineText1 != Bawl.multilineText2 && Bawl.listInt < 1000 ) {
		Bawl.listInt = Bawl.listInt + 1;
		Bawl.multilineText2 = Bawl.multilineText1;
		Bawl.multilineText1 = Bawl.multilineText1.replace(/\{\{(([^\{\}\n]|\{[^\{\n]|\}[^\}\n]|\{\{[^\{\}\n]*\}\})*)\n(((([^\{\}]|\{[^\{]|\}[^\}]|\{\{[^\{\}]*\}\})*)\n)*)([^\}]*)\}\}/g,'(($1$3))'); //This removes one newline from multiline templates. Only one, so it has to be applied as many times as the number of lines a template takes up. In SOME cases the result is possibly not desirable, but in those cases whatever you were trying to do probably wasn't going to work in an indented comment anyway. Note: you can only nest one level. So ((x(newline)|((y)))) would work, but ((x(newline)|((y|((z)))))) wouldn't.
		Bawl.multilineText1 = Bawl.multilineText1.replace(/(\n[^\#].*\n)(\#[ ]*)/g, '$1' + Bawl.listInt + '. ');
		Bawl.multilineText1 = Bawl.multilineText1.replace(/<([Pp]re|PRE)([^>\n]*)>(([^<\n]|<(?![\/]?[Pp]re))*)\n(([^<]|<(?![\/]?[Pp]re))*)<\/[Pp]re>/g,'<syntaxhighlight lang=text>$5</syntaxhighlight>'); //pre with at least one newline in it
		Bawl.multilineText1 = Bawl.multilineText1.replace(/<([Nn]o[Ww]iki|NOWIKI)>(([^<\n]|<(?!\/([Nn]o[Ww]iki|NOWIKI)>))*)\n/g,'<' + Bawl.nowikiTagName + '>$2</' + Bawl.nowikiTagName + '> <' + Bawl.nowikiTagName + '>');
		Bawl.multilineText1 = Bawl.multilineText1.replace(/<(syntaxhighlight)([^>\n]*)>\n/g,'<$1$2>').replace(/<(syntaxhighlight)([^>\n]*)>(([^<\n]|<(?![\/]?syntaxhighlight))*)(PARSEWIKITAGNEWLINE.*)?\n(([^<]|<(?![\/]?syntaxhighlight))*<\/(syntaxhighlight)>)/g,'<$1$2>$3$5PARSEWIKITAGNEWLINE $6');
		Bawl.multilineText1 = Bawl.multilineText1.replace(/<(gallery)([^>\n]*)>\n/g,'<$1$2>').replace(/<(gallery)([^>\n]*)>(([^<\n]|<(?![\/]?gallery))*)(PARSEWIKITAGNEWLINE.*)?\n(([^<]|<(?![\/]?gallery))*<\/(gallery)>)/g,'<$1$2>$3$5PARSEWIKITAGNEWLINE $6');
	}
	if ( Bawl.basicmsgs.newline == '' ) {
		Bawl.multilineText1 = Bawl.multilineText1.replace(/PARSEWIKITAGNEWLINE/g,'');
	} else {
		Bawl.multilineText1 = Bawl.multilineText1.replace(new RegExp('\{\{' + Bawl.escapeRegExp(Bawl.basicmsgs.newline) + '\}\} BWLNEWLINE','g'),'(('+Bawl.basicmsgs.newline+'))').replace(new RegExp('<\/pre>\{\{' + Bawl.escapeRegExp(Bawl.basicmsgs.newline) + '\}\}<pre>','g'), '((' + Bawl.basicmsgs.newline + '))');
		Bawl.multilineText1 = Bawl.multilineText1.replace(new RegExp('<(syntaxhighlight|gallery)[ ]?([^>\n]*)>((([^<]|<(?!\/[Ss]yntax[Hh]igh[Ll]ight|\/SYNTAXHIGHLIGHT)))*PARSEWIKITAGNEWLINE)(([^<]|<(?!\/syntaxhighlight|\/gallery))*)<\/(syntaxhighlight|gallery)>','g'),'((#tag:$1|$3$6SYNTAXHLEND|SYNTAXHLPARAMSSTART$2SYNTAXHLPARAMSEND))');
		for(Bawl.tagParamsInt=0;Bawl.tagParamsInt<10;Bawl.tagParamsInt++){
			Bawl.multilineText1 = Bawl.multilineText1.replace(/(SYNTAXHLPARAMSSTART[^=]+="[^"]*")[ ](.*SYNTAXHLPARAMSEND)/g,'$1|$2');
		}
		Bawl.listInt = 0;
		while ( Bawl.multilineText1 != Bawl.multilineText2 && Bawl.listInt < 1000 ) {
			Bawl.listInt = Bawl.listInt + 1;
			Bawl.multilineText2 = Bawl.multilineText1;
			Bawl.multilineText1 = Bawl.multilineText1.replace(/(\{\{#tag:(syntaxhighlight|pre)(([^S]|S(?!YNTAXHLEND))*))(?!SYNTAXHLNOWIKIOPEN)([\{\}])(?!SYNTAXHLNOWIKICLOSE)/g,'$1SYNTAXHLNOWIKIOPEN$5SYNTAXHLNOWIKICLOSE');
		}
		Bawl.multilineText1 = Bawl.multilineText1.replace(/SYNTAXHLNOWIKIOPEN(.)SYNTAXHLNOWIKICLOSE/g,'<' + Bawl.nowikiTagName + '>$1</' + Bawl.nowikiTagName + '>').replace(/PARSEWIKITAGNEWLINE /g,'((' + Bawl.basicmsgs.newline + '))').replace(/SYNTAXHL(PARAMS)?(START|END)/g,'');
	}
	Bawl.multilineText1 = Bawl.multilineText1.replace(/<[n]owiki><\/[n]owiki>[ ]?/g,'');
	return Bawl.multilineText1.replace(/^[\s]*/, '').replace(/(^|\n)[\*]{3}[\s]*(.*)/gm, '<li style="margin-left:3em;">$2</li>').replace(/(^|\n)[\*]{2}[\s]*(([^\*]|\*[^\*])*)(\n|$)/gm, '<li style="margin-left:2em;">$2</li>').replace(/(^|\n)[\*][\s]*(([^\*\n]|\*[^\*\n])*)(\n|$)/gm, '<li>$2</li>$4').replace(/[\n]?(<li( style="margin-left:[1-2]em;")?>(([^<]|<(?!\/li>))*)<\/li>)[\n]?/g, '$1').replace(/((<li( style="margin-left:[2-4]em;")?>(([^<]|<(?!\/li>))*)<\/li>)+)/g, '<ul>$1</ul>').replace(/\n\n/gm,'<br style="margin-bottom:0.5em"/>').replace( /\n/gm,'<br/>');
};
Bawl.addSignature = function(text) {
	if ( text.match(/NOSIGN$/) || Bawl.replyLinkParamsOpened.type == 'edit' || ! $('#ca-addsection,.minerva-talk-add-button,.BawlCmt,.LegacyCmt')[0] ) {
		Bawl.debug('found NOSIGN or this is an edit of an existing comment, skipping signature');
		Bawl.detectedNOSIGN = true;
		return text.replace(/[ ]*NOSIGN$/,'');
	} else {
		Bawl.debug('adding signature');
		Bawl.signatureAdded = true;
		Bawl.addSigSeparator = ' ';
		if ( text.trim().match(/(&nbsp;|<\/([Pp]re|PRE|[Ss]yntax[Hh]igh[Ll]ight|SYNTAXHIGHLIGHT)>|\}\})$/) ) {
			Bawl.addSigSeparator = '';
		}
		if ( Bawl.settings.useLocator ) {
			if ( ! Bawl.userName ) {
				Bawl.userName = '';
			}
			Bawl.locatorID = Bawl.escapeHTML(Bawl.userName) + ':((subst:#time:xNU))' + Bawl.commentMilliseconds + ':' + Bawl.escapeHTML(Bawl.replyLinkParamsOpened.pageTitle.replace(/:/g, 'BWLCLN'));
			Bawl.locatorID = Bawl.locatorID.replace(/ /g, '_');
			return text.replace(/[ ]?~~~~$/,'') + Bawl.addSigSeparator + Bawl.endOfCommentLocator.replace(/INNERCONTENT/g, '~~~~').replace(/USERTIME/g, Bawl.locatorID);
		} else {
			return text.replace(/[ ]?~~~~$/,'') + Bawl.addSigSeparator + '~~~~';
		}
	}
};
Bawl.cancelReply = function(trigger) {
	Bawl.openingFormInProgress = new Date().getTime();
	Bawl.debug('check if there\'s a reply form to remove');
	if ( document.getElementById('bawlForm-' + Bawl.replyLinkParamsOpened.id) ) {
		if ( document.getElementById('bawlForm-' + Bawl.replyLinkParamsOpened.id).querySelectorAll('.BawlScrewed')[0] ) {
			Bawl.debug('there\'s a big error attached to the reply form. Not closing.');
			return;
		}
		document.getElementById('bawlForm-' + Bawl.replyLinkParamsOpened.id).outerHTML = '';
		Bawl.debug('there is, removed it');
		if ( Bawl.UITextInput.getValue().length < 40 ) {
			Bawl.UITextInput.setValue('');
		}
	}
	if ( trigger == 'user' ) {
		Bawl.saveDraft(Bawl.replyLinkParamsOpened, 'remove', 'user');
		Bawl.UITextInput.setValue('');
		if ( mw.config.get('wgAction') == 'edit' && mw.util.getParamValue('section') == 'new' ) {
			$('#editform,#wikiPreview').removeClass('BawlNoDisplay');
		}
	}
	$('#mw-content-text').removeClass('BawlNoDisplay'); //full page editing can hide page content
	$('#BawlnSecBottom').removeClass('BawlNoDisplay');
};
Bawl.processComment = function(text, mode) {
	Bawl.processCommentStart = new Date().getTime();//Bawl.debug
	if ( mode != 'toVisual' && Bawl.activeEditor == 'visualLight' ) {
		Bawl.debug('sync to source before processing comment');
		Bawl.syncToSource();
	}
	text = text.replace(/^[\s]*/, '');
	if ( !['preview','livepreview','toVisual'].includes(mode) ) {
		text = text.replace(/[\s]*$/, '');
	}
	text = Bawl.applyModules('processComment',text);
	if ( Bawl.settings.enableCIThatRun || Bawl.settings.enableCIThatRunCmt ) {
		Bawl.debug('applying your regular expressions');
		text = Bawl.runCI(text,mode);
	}
	if ( mw.config.get('wgPageContentModel') == 'wikitext' ) {
		text = Bawl.safeText(text,'rewritun'); //rewritun is done inside safing as rewritun can't be done after safing (when the URLs are safed) but is preferably done after HTML comments etc have been safed
		if ( Bawl.settings.AWBtypos && mode != 'toVisual' && (mode != 'preview' || Bawl.settings.AWBtypoPreview) ) { //in preview mode doPreview has already applied RETF
			text = Bawl.RETF(text);
		}
		if ( Bawl.settings.bbcode ) {
			text = Bawl.applyBBCode(text);
		}
		if ( Bawl.settings.markdown ) {
			text = Bawl.applyMarkdown(text);
		}
		text = text.replace(/\*\*(([^\*\n]|\*[^\*])*)\*\*/g, 'BAWLBOLDTAGOPEN$1BAWLBOLDTAGCLOSE').replace(/(^|[^:"'\[])\/\/(([^\/\:]|\:..|\/[^\/])*)(?![:"'\[])\/\/($|[^\/])/g, '$1BAWLITALICTAGOPEN$2BAWLITALICTAGCLOSE$4');//the :.. allows a URL within italicized text
		text = Bawl.safeText(text,'unsafe');
		if(mode!='livepreview'){
			Bawl.UITextInput.setValue(text.replace(/BAWLBOLDTAGOPEN(([^B]|B(?!AWLBOLDTAGCLOSE))*)BAWLBOLDTAGCLOSE/g,'**$1**').replace(/BAWLITALICTAGOPEN(([^B]|B(?!AWLITALICTAGCLOSE))*)BAWLITALICTAGCLOSE/g,'//$1//'));
		}
		text = text.replace(/BAWLBOLDTAGOPEN(([^B]|B(?!AWLBOLDTAGCLOSE))*)BAWLBOLDTAGCLOSE/g,'<b>$1</b>').replace(/BAWLITALICTAGOPEN(([^B]|B(?!AWLITALICTAGCLOSE))*)BAWLITALICTAGCLOSE/g,'<i>$1</i>');
	}
	Bawl.signatureAdded = false;
	if ( Bawl.replyLinkParamsOpened.type == 'editFullPage' || ( Bawl.replyLinkParamsOpened.type == 'heading' && Bawl.replyLinkParamsOpened.subtype == 'edit' ) ) {
		Bawl.debug('return processed text for full page/section edit');
		Bawl.processCommentEnd = new Date().getTime();//Bawl.debug
		Bawl.debug('processed comment in ' + (Bawl.processCommentEnd - Bawl.processCommentStart)+'ms');
		return text.replace(/[ ]*NOSIGN$/,'');//if there's NOSIGN here the user added it erroneously
	} else if ( mode == 'toVisual' ) {
		Bawl.debug('return processed text for toVisual');
		text = Bawl.convertToOneLineCmt(text);
		Bawl.processCommentEnd = new Date().getTime();//Bawl.debug
		Bawl.debug('processed comment in ' + (Bawl.processCommentEnd - Bawl.processCommentStart)+'ms');
		return text;
	} else {
		Bawl.detectedNOSIGN = false;
		text = Bawl.addSignature(text);
		if ( Bawl.replyLinkParamsOpened.type == 'edit' ) {
			Bawl.debug('return processed text for comment edit');
			text = Bawl.convertToOneLineCmt(text).replace(/[\s]*$/, '');
			Bawl.processCommentEnd = new Date().getTime();//Bawl.debug
			Bawl.debug('processed comment in ' + (Bawl.processCommentEnd - Bawl.processCommentStart)+'ms');
			return text;
		} else if ( Bawl.detectedNOSIGN ) {
			Bawl.debug('found NOSIGN, no signature added, will not convert comment to one line');
			Bawl.processCommentEnd = new Date().getTime();//Bawl.debug
			Bawl.debug('processed comment in ' + (Bawl.processCommentEnd - Bawl.processCommentStart)+'ms');
			return text;
		} else {
			Bawl.debug('return processed and signed text');
			text = Bawl.convertToOneLineCmt(text);
			Bawl.processCommentEnd = new Date().getTime();//Bawl.debug
			Bawl.debug('processed comment in ' + (Bawl.processCommentEnd - Bawl.processCommentStart)+'ms');
			return text;
		}
	}
};
Bawl.parsePageInPlace = function(){ // learned a great deal from w:enUser:BrandonXLF/QuickEdit.js for this, thanks BrandonXLF!
	if ( Bawl.settings.afterPostReload ) {
		Bawl.debug('you\'d rather just have the page reloaded than reparsed, so let\'s do that.');
		if(Bawl.settings.debug){OO.ui.confirm('Reload?').done(function(a){if(a){location.reload();)));}else{//Bawl.debug
			var DelayedReload = setInterval(function () {
				clearInterval(DelayedReload); location.reload(); //if we reload immediately we may not get served the most recent revision with our comment
			}, 2000);
		}//Bawl.debug
		return;
	}
	Bawl.debug('parsePageInPlace: obtain parsed version of this page and replace current contents');
	api.get({action:'parse',page:mw.config.get('wgPageName'),format:'json',disablelimitreport:true,prop:['text','categorieshtml']}).then(function(data){
		Bawl.debug('parsePageInPlace: got parsed page:');
		Bawl.debug(data);
		Bawl.pageContentElement = $('#mw-content-text');
		Bawl.pageCategoriesElement = $('#catlinks');
		Bawl.pageContentElement[0].querySelectorAll('.mw-parser-output')[0].outerHTML = data.parse.text['*'];
		Bawl.pageCategoriesElement[0].outerHTML = data.parse.categorieshtml['*'];
		mw.hook('wikipage.content').fire(Bawl.pageContentElement);
		mw.hook('wikipage.categories').fire(Bawl.pageCategoriesElement);
		if ( Bawl.settings.collapArticleDefaultFloatingToC ) {
			Bawl.debug('parsePageInPlace: refloat the ToC');
			$('.BawlFloatingToC').remove();
			Bawl.floatTheTOC();
		}
		delete Bawl.legacyCommentCount;
		delete Bawl.mwHeadLineArray;
		Bawl.replyLinkParams = {};
		Bawl.finishedAddingLinks = false;
		Bawl.searchNodeContentsLoop();
	}, function ( code, data ) { mw.notify(code,{type:'error'});
	});
};
Bawl.doDiff = function(replyLinkParams) {
	Bawl.UIDiffButton.setDisabled(true);
	if ( ! Bawl.diffCSSloaded ) {
		mw.loader.load('/w/load.php?lang='+mw.config.get('wgUserLanguage')+'&modules=mediawiki.diff.styles&only=styles&skin=' + mw.config.get('skin'),'text/css');
		Bawl.diffCSSloaded = true;
	}
	if ( Bawl.activeEditor == 'visualLight' ) {
		Bawl.syncToSource();
	}
	Bawl.processedComment = Bawl.processComment(Bawl.UITextInput.getValue(),'preview');
	Bawl.diffParams = { action:'compare',toslots:'main',prop:'diff|size','fromcontentmodel-main':'wikitext','tocontentmodel-main':'wikitext' };
	if ( replyLinkParams.type == 'editFullPage' ) {
		Bawl.diffParams.fromtitle = replyLinkParams.pageTitle;
		Bawl.diffParams['totext-main'] = Bawl.processedComment;
	} else if ( replyLinkParams.type == 'heading' && Bawl.replyLinkParamsOpened.subtype == 'edit' ) {
		Bawl.diffParams.fromslots = 'main';
		if ( typeof Bawl.sectionTextForPreload == 'undefined' ) {
			api.get( {action: 'query', export: 'true', format: 'json', titles: replyLinkParams.pageTitle} ).then( function ( data ) {
				Bawl.debug(data);
				Bawl.wikiTextForEdit = Bawl.getWikitextFromExport(data.query.export["*"]);
				Bawl.debug('preload section wikitext');
				Bawl.sectionTextForPreload = Bawl.getInsertionPointSection(Bawl.replyLinkParamsOpened, Bawl.wikiTextForEdit).sectiontext;
				if ( Bawl.sectionTextForPreload == null ) {
					Bawl.debug('section not found, try preloading text by section number instead'); //this happens on sections like "== ((int:license-header)) ==" as they don't contain the innerText "Licensing"
					Bawl.sectionNumFromLink = Number(Bawl.processElementArray[Bawl.replyLinkParamsOpened.int].querySelectorAll('A')[0].href.match(/section=(T\-)?([0-9]*)/)[2]);
					Bawl.sectionTextForPreload = Bawl.getSectionByNum(Bawl.wikiTextForEdit,Bawl.sectionNumFromLink);
				}
				Bawl.doDiff(replyLinkParams);
				return;
			}, function ( code, data ) { Bawl.APIError(code, data);
			});
			return;
		}
		Bawl.diffParams['fromtext-main'] = Bawl.sectionTextForPreload;
		Bawl.diffParams['totext-main'] = Bawl.processedComment;
	} else if ( replyLinkParams.type == 'edit' ) {
		Bawl.diffParams.fromslots = 'main';
		Bawl.diffParams['fromtext-main'] = Bawl.wikiTextForEditCommentStripped;
		Bawl.diffParams['totext-main'] = Bawl.processedComment;
	}
	api.post( Bawl.diffParams ).then( function ( data ) {
		Bawl.UIDiffButton.setDisabled(false);
		$('#BawlPreviewBox')[0].innerHTML = '';
		$('#BawlPreviewBox').removeClass('BawlNoDisplay');
		Bawl.debug('got diff HTML:');
		Bawl.debug(data.compare['*']);
		if ( ! data.compare['*'] ) {
			Bawl.diffHTML = '<div style="width:100%;text-align:center">' + Bawl.basicmsgs['diff-empty'] + '</div>';
		} else {
			Bawl.diffHTML = '<table class="diff diff-contentalign-left diff-editfont-monospace"><colgroup><col class="diff-marker"><col class="diff-content"><col class="diff-marker"><col class="diff-content"></colgroup>' + data.compare['*'] + '</table>';
		}
		$('#BawlPreviewBox').append(Bawl.diffHTML);
		if ( data.compare.fromsize ) {
			Bawl.diffOldSize = data.compare.fromsize;
		} else if ( replyLinkParams.type == 'heading' && replyLinkParams.subtype == 'edit' ) {
			Bawl.diffOldSize = new Blob([Bawl.sectionTextForPreload]).size;
		} else if ( replyLinkParams.type == 'edit' ) {
			Bawl.diffOldSize = new Blob([Bawl.wikiTextForEditComment]).size;
		}
		Bawl.diffNewSize = new Blob([Bawl.UITextInput.getValue()]).size;
		if ( Bawl.diffNewSize >= Bawl.diffOldSize ) {
			Bawl.diffSize = Bawl.diffNewSize - Bawl.diffOldSize;
			Bawl.diffPlusMin = '+';
			if ( Bawl.diffSize > 200 ) {
				Bawl.diffSizeClass = "BawlDiffPlusBig";
			} else {
				Bawl.diffSizeClass = "BawlDiffPlus";
			}
		} else {
			Bawl.diffSize = Bawl.diffOldSize - Bawl.diffNewSize;
			Bawl.diffPlusMin = '-';
			if ( Bawl.diffSize > 200 ) {
				Bawl.diffSizeClass = "BawlDiffMinBig";
			} else {
				Bawl.diffSizeClass = "BawlDiffMin";
			}
		}
		Bawl.UIdiffSize.setLabel(new OO.ui.HtmlSnippet('<span class="' + Bawl.diffSizeClass + '">' + Bawl.diffPlusMin + Bawl.diffSize + '</span>'));
	}, function ( code, data ) { Bawl.UIDiffButton.setDisabled(false);Bawl.APIError(code, data);
	});
};
Bawl.doPreview = function(mode, replyLinkParams) {
	Bawl.debug('preview');
	if ( mode == 'preview' ) {
		Bawl.UIPreviewButton.setDisabled(true);
		var DelayMarkUnlockPreviewButton = setInterval(function () { //just in case the preview parsing times out or something
			clearInterval(DelayMarkUnlockPreviewButton);
			Bawl.UIPreviewButton.setDisabled(false);
		},10000);
	}
	if ( ! Bawl.syntaxHighlightCSSloaded && Bawl.UITextInput.getValue().match(/<\/syntaxhighlight>/i) ) {
		mw.loader.load('/w/load.php?lang='+mw.config.get('wgUserLanguage')+'&modules=ext.pygments&only=styles&skin=' + mw.config.get('skin'),'text/css');
		Bawl.syntaxHighlightCSSloaded = true;
	}
	if ( ! Bawl.galleryCSSloaded && Bawl.UITextInput.getValue().match(/<\/gallery>/i) ) {
		mw.loader.load('/w/load.php?lang='+mw.config.get('wgUserLanguage')+'&modules=mediawiki.page.gallery.styles&only=styles&skin=' + mw.config.get('skin'),'text/css');
		Bawl.galleryCSSloaded = true;
	}
	if ( mode != 'previewposted' ) {
		$(document.getElementsByClassName('BawlPreviewBox')).removeClass('BawlNoDisplay');
		if ( Bawl.settings.checkNewComments && mw.config.get('wgArticleId') != 0 ) {
			Bawl.checkForNewComments(Bawl.replyLinkParamsOpened, 'preview');
		}
	}
	if ( mode != 'livepreview' && (Bawl.settings.rewritun || Bawl.settings.AWBtypos) ) {
		Bawl.UITextInput.setReadOnly(true);
		if ( Bawl.settings.rewritun ) {
			Bawl.UITextInput.setValue(Bawl.rewritunUrUrlz(Bawl.UITextInput.getValue()));
		}
		if ( Bawl.settings.AWBtypos && Bawl.settings.AWBtypoPreview ) {
			Bawl.UITextInput.setValue(Bawl.RETF(Bawl.UITextInput.getValue()));
		}
		Bawl.UITextInput.setReadOnly(false);
	}
	if ( Bawl.activeEditor == 'visualLight' ) {
		Bawl.syncToSource();
	}
	Bawl.processedComment = Bawl.processComment(Bawl.UITextInput.getValue(),mode);
	if ( mode == 'previewposted' && Bawl.commentTextIndent && ( replyLinkParams.type != 'edit' || ( replyLinkParams.type == 'edit' && replyLinkParams.freshcomment == true ) ) ) {
			Bawl.debug('add the last character+space from the indentation so preview renders properly with its indentation');
			if ( ! Bawl.commentTextIndent.match('┌') ) {
				Bawl.processedComment = Bawl.commentTextIndent.slice(-1) + Bawl.processedComment + Bawl.repairTagImbalance(Bawl.processedComment);
			} else {
				Bawl.debug('adjust preview for automatic outdent');
				Bawl.processedComment = Bawl.commentTextIndent + Bawl.processedComment + Bawl.repairTagImbalance(Bawl.processedComment);
				Bawl.bawlFormNegativeMargin = Bawl.origCmtIndent * -1.6;
			}
	}
	if ( mode == 'previewposted' && replyLinkParams.type == 'newsection' ) {
		Bawl.processedComment = '==' + Bawl.UITextInputTitle.getValue() + '==\n' + Bawl.processedComment;
	}
	if ( mode == 'previewposted' && replyLinkParams.type == 'newheading' ) {
		Bawl.processedComment = Bawl.newSectionLevel + Bawl.UITextInputTitle.getValue() + Bawl.newSectionLevel + '\n' + Bawl.processedComment;
	}
	if ( replyLinkParams.type == 'edit' ) {
		Bawl.processedComment = Bawl.processedComment + Bawl.wikiTextForEditSigForPreview;
		Bawl.processedComment = Bawl.processedComment + Bawl.repairTagImbalance(Bawl.processedComment);
	}
	Bawl.previewCommentParams = {
		format: 'json',
		action: 'parse',
		disablelimitreport: true,
		title: Bawl.replyLinkParamsOpened.pageTitle,
		pst: '1',
		prop: 'text',
		formatversion: '2',
		text: Bawl.processedComment,
	};
	if ( Bawl.replyLinkParamsOpened.type != 'editFullPage' ) {
		Bawl.previewCommentParams.disableeditsection = true;
	}
	Bawl.doAPICall(Bawl.previewCommentParams, mode);
};
Bawl.compareRevisionsToCheckForComments = function(replyLinkParams,mode,wikitextFromPostReply,revidFromPostReply,getWikiText) {
	if ( getWikiText != true && mode != 'postreply' ) {
		api.get( {
			action: 'query', prop: 'revisions', format: 'json', titles: replyLinkParams.pageTitle, rvlimit: 1, rvprop: 'ids', rvslots: '*',
		} ).then( function ( data ) {
			if ( ! data.query.pages[-1] && data.query.pages[ Object.keys(data.query.pages)[0] ].revisions[0].revid != Bawl.pageRevisionIDSinceLastCheck[replyLinkParams.pageTitle] ) {
				Bawl.debug('the current revision is different from the last one we checked');
				Bawl.pageRevisionIDSinceLastCheck[replyLinkParams.pageTitle] = data.query.pages[ Object.keys(data.query.pages)[0] ].revisions[0].revid;
				Bawl.compareRevisionsToCheckForComments(replyLinkParams,mode,wikitextFromPostReply,revidFromPostReply,true);
			} else { Bawl.debug('no new revisions since the last time we checked');
			}
		}, function ( code, data ) { Bawl.APIError(code, data);
		});
	} else {
		Bawl.debug('compare wikitext of current revision to revision since last check');
		Bawl.compareRevisionsToCheckForCommentsProcessing = function(replyLinkParams,mode,wikitextFromPostReply,revidFromPostReply) {
			if ( replyLinkParams.type == 'comment' ) {
				Bawl.insertionPointThrowAway = Bawl.getInsertionPointComment(replyLinkParams, Bawl.pageRevisionCurrentText); //we don't do anything with this, but it triggers an error if the comment has vanished
			}
			Bawl.pageRevisionCurrentText = Bawl.getInsertionPointSection(replyLinkParams, Bawl.pageRevisionCurrentText).sectiontext;
			Bawl.pageRevisionSinceLastCheckText = Bawl.getInsertionPointSection(replyLinkParams, Bawl.pageRevisionSinceLastCheck[replyLinkParams.pageTitle]).sectiontext;
			if ( Bawl.pageRevisionCurrentText != Bawl.pageRevisionSinceLastCheckText ){
				Bawl.pageRevisionCurrentSplit = Bawl.pageRevisionCurrentText.split('\n');
				Bawl.linesSinceLastCheck = '';
				for (Bawl.commentCheckInt = 0; Bawl.commentCheckInt < Bawl.pageRevisionCurrentSplit.length; Bawl.commentCheckInt++) {
					if ( Bawl.pageRevisionSinceLastCheckText.split('\n').indexOf(Bawl.pageRevisionCurrentSplit[Bawl.commentCheckInt]) == -1 ) {
						Bawl.debug('line not found in the old revision of this page: ' + Bawl.pageRevisionCurrentSplit[Bawl.commentCheckInt]);
						Bawl.newLineUserLinks = Bawl.pageRevisionCurrentSplit[Bawl.commentCheckInt].match(new RegExp('(?:' + Bawl.userNSWikitextRegExpPart + ')([^\\|\\]]*)','g'));
						Bawl.newLineLastUser = '';
						if ( Bawl.newLineUserLinks ) {
							Bawl.newLineLastUser = Bawl.newLineUserLinks[Bawl.newLineUserLinks.length -1].replace(new RegExp('(' + Bawl.userNSWikitextRegExpPart + ')'),'').replace(/_/g,' ');
						}
						if ( ! ( Bawl.newLineLastUser == mw.config.get('wgUserName') && Bawl.pageRevisionCurrentSplit[Bawl.commentCheckInt].match(Bawl.signDateRegExpLocalMonths) ) ) {
							Bawl.linesSinceLastCheck = Bawl.linesSinceLastCheck + Bawl.pageRevisionCurrentSplit[Bawl.commentCheckInt] + '\n';
						}
						else { Bawl.debug('changed line appears to be a comment by you, presumably you already know about that'); }
					}
				}
				if ( Bawl.linesSinceLastCheck == '' ) {
					Bawl.debug('there\'s a new revision but no new lines you need to know of');
					Bawl.disableForm(false); //re-enable form
					$(document.getElementById('BawlUIReplyButton')).removeClass('BawlPendingBlink');
					if ( mode == 'postreply' ) {
						Bawl.postReply2(replyLinkParams, wikitextFromPostReply, revidFromPostReply);
					}
					return;
				}
				api.post( {
					action: 'parse', format: 'json', disablelimitreport: true, disableeditsection: true, title: mw.config.get('wgPageName'), pst: '1', prop: 'text', formatversion: '2', text: Bawl.linesSinceLastCheck
				} ).then( function ( data ) {
					$('#showNewLines')[0].innerHTML = '<b>' + Bawl.msgs.newLines + '</b><br />' + data.parse.text;
					$('#showNewLines').removeClass('BawlNoDisplay');
					$('#showNewLines').addClass('BawlEaseIn BawlPurpleBG');
					$('#showNewLines')[0].scrollIntoView(Bawl.smoothScroll);
					var DelayMarkAsReadButton = setInterval(function () {
						clearInterval(DelayMarkAsReadButton);
						$('#showNewLines').removeClass('BawlPurpleBG');
						Bawl.disableForm(false); //re-enable form
						$(document.getElementById('BawlUIReplyButton')).removeClass('BawlPendingBlink');
					},500);
					}, function ( code, data ) { Bawl.APIError(code, data);
				});
			} else if ( mode == 'postreply' ) {
				Bawl.debug('current revision and revision as of the last check are identical (for this section, at least)');
				Bawl.postReply2(replyLinkParams,wikitextFromPostReply,revidFromPostReply);
			}
		};
		if ( mode == 'postreply' ) {
			Bawl.debug('already have the current wikitext from postReply1');
			Bawl.pageRevisionCurrentText = wikitextFromPostReply;
			Bawl.compareRevisionsToCheckForCommentsProcessing(replyLinkParams,mode,wikitextFromPostReply,revidFromPostReply);
			Bawl.pageRevisionSinceLastCheck[replyLinkParams.pageTitle] = wikitextFromPostReply;
			Bawl.pageRevisionIDSinceLastCheck[replyLinkParams.pageTitle] = revidFromPostReply;
		}	else {
			api.get( {
				action: 'query', prop: 'revisions', format: 'json', titles: replyLinkParams.pageTitle, rvlimit: 1, rvprop: 'timestamp|content|ids', rvslots: '*',
			} ).then( function ( data ) {
				Bawl.debug('page content now:');
				Bawl.debug(data);
				if ( data.query && data.query.pages && data.query.pages[ Object.keys(data.query.pages)[0] ] && data.query.pages[ Object.keys(data.query.pages)[0] ].revisions && data.query.pages[ Object.keys(data.query.pages)[0] ].revisions[0] ) {
					Bawl.pageRevisionCurrentText = data.query.pages[ Object.keys(data.query.pages)[0] ].revisions[0].slots.main['*'];
				} else {
					Bawl.pageRevisionCurrentText = '';
				}
				Bawl.compareRevisionsToCheckForCommentsProcessing(replyLinkParams,mode,Bawl.pageRevisionCurrentText,revidFromPostReply);
				if ( data.query && data.query.pages && data.query.pages[ Object.keys(data.query.pages)[0] ] && data.query.pages[ Object.keys(data.query.pages)[0] ].revisions && data.query.pages[ Object.keys(data.query.pages)[0] ].revisions[0] ) {
					Bawl.pageRevisionSinceLastCheck[replyLinkParams.pageTitle] = data.query.pages[ Object.keys(data.query.pages)[0] ].revisions[0].slots.main['*'];
					Bawl.pageRevisionIDSinceLastCheck[replyLinkParams.pageTitle] = data.query.pages[ Object.keys(data.query.pages)[0] ].revisions[0].revid;
				} else {
					Bawl.addScrewedLink('no_revision_API','No revision data found in API response.');
				}
			}, function ( code, data ) { Bawl.APIError(code, data);
			});
		}
	}
};
Bawl.lastCheckedForNewComments = 0;
Bawl.checkForNewComments = function(replyLinkParams, mode, wikitextFromPostReply, revidFromPostReply) {
	if ( ! replyLinkParams.pageTitle ) {
		Bawl.addPageAndSectionTitleToRPL(replyLinkParams);
	}
	if ( mode != 'postreply' && ( Bawl.lastCheckedForNewComments + 30000 ) > new Date().getTime() && Bawl.lastCheckedID == replyLinkParams.id ) {
		Bawl.debug('checkForNewComments, already checked for new comments in the past 30 seconds, skipping');
	} else {
		Bawl.debug('checkForNewComments, check for new comments');
		if ( Bawl.pageRevisionSinceLastCheck[replyLinkParams.pageTitle] ) {
			Bawl.debug('already have a version that was checked against');
			Bawl.compareRevisionsToCheckForComments(replyLinkParams,mode,wikitextFromPostReply,revidFromPostReply);
		} else {
			Bawl.debug('first time we check, obtain wikitext of the page as it was when the page was loaded');
			Bawl.initialRevisionCheckParams = { 'action': 'query', 'prop': 'revisions|info', 'format': 'json', 'titles': replyLinkParams.pageTitle, 'rvlimit': 1, 'rvprop': 'timestamp|content|ids', 'rvslots': '*', 'rvstart': Bawl.pageLoadTimeStamp, 'inprop':'watched', 'intestactions':'edit'};
			api.get( Bawl.initialRevisionCheckParams ).then( function ( data ) {
				Bawl.debug('page content as it was when loading the page:');
				Bawl.debug(data);
				if ( typeof data.query.pages[ Object.keys(data.query.pages)[0] ].actions.edit != 'string' ) {
					Bawl.showProtectedWarning();
				}
				if ( data.query.pages[-1] ) {
					Bawl.debug('page doesn\'t seem to exist.');
					if ( mode == 'postreply' ) {
						Bawl.postReply2(replyLinkParams,wikitextFromPostReply,revidFromPostReply);
					}
					return;
				}
				if ( typeof data.query.pages[ Object.keys(data.query.pages)[0] ].watched == 'string' ) {
					if ( typeof data.query.pages[ Object.keys(data.query.pages)[0] ].watchlistexpiry == 'string' ) {
						Bawl.watchlistexpiry = new Date(data.query.pages[ Object.keys(data.query.pages)[0] ].watchlistexpiry).getTime();
					}
				}
				if ( data.query && data.query.pages && data.query.pages[ Object.keys(data.query.pages)[0] ] && data.query.pages[ Object.keys(data.query.pages)[0] ].revisions && data.query.pages[ Object.keys(data.query.pages)[0] ].revisions[0] ) {
					Bawl.pageRevisionSinceLastCheck[replyLinkParams.pageTitle] = data.query.pages[ Object.keys(data.query.pages)[0] ].revisions[0].slots.main['*'];
					Bawl.pageRevisionIDSinceLastCheck[replyLinkParams.pageTitle] = data.query.pages[ Object.keys(data.query.pages)[0] ].revisions[0].revid;
				} else {
					Bawl.pageRevisionSinceLastCheck[replyLinkParams.pageTitle] = '';
					Bawl.pageRevisionIDSinceLastCheck[replyLinkParams.pageTitle] = 0;
				}
				Bawl.compareRevisionsToCheckForComments(replyLinkParams,mode,wikitextFromPostReply,revidFromPostReply);
			}, function ( code, data ) { Bawl.APIError(code, data);
			});
		}
	}
	Bawl.lastCheckedForNewComments = new Date().getTime();
	Bawl.lastCheckedID = replyLinkParams.id;
};
Bawl.saveDraftEvery = function() {
	var SaveDraftEvery = setInterval(function () {
		if ( $('#BawlReplyForm')[0] ) {
			Bawl.saveDraft(Bawl.replyLinkParamsOpened,false,'scheduled');
			Bawl.saveDraftEvery();
		}
	clearInterval(SaveDraftEvery);
	}, 20000);
};
Bawl.saveDraft = function(replyLinkParams, removeDraft, trigger) {
	Bawl.debug('should we save a draft? trigger: ' + trigger);
	if ( ! $('#BawlReplyForm')[0] && trigger != 'user' && removeDraft != 'remove' ) {
		Bawl.debug('there is no open reply form and you didn\'t press cancel');
	} else {
		if ( window.localStorage.BawlDrafts && Bawl.testValidJSON(window.localStorage.BawlDrafts) ) {
			Bawl.debug('found existing drafts in localStorage');
			Bawl.savedDrafts = JSON.parse(window.localStorage.BawlDrafts);
			if ( removeDraft != 'remove' && Bawl.savedDrafts[encodeURIComponent(replyLinkParams.id)] && ( Bawl.savedDrafts[encodeURIComponent(replyLinkParams.id)].text == Bawl.UITextInput.getValue() ) ) {
				Bawl.draftUnchanged = true;
			} else {
				delete Bawl.draftUnchanged;
			}
		} else {
			Bawl.debug('no existing drafts found');
			Bawl.savedDrafts = {};
			delete Bawl.draftUnchanged;
		}
		Bawl.timestampNowDraft = new Date().getTime();
		Bawl.timestampNowDraftLastWeek = Bawl.timestampNowDraft - 604800000;
		for (Bawl.BawlDraftInt = 0; Bawl.BawlDraftInt < Bawl.savedDrafts.length; Bawl.BawlDraftInt++) {
			Bawl.debug(Bawl.processDraftKey);
			Bawl.processDraftKey = Object.keys(Bawl.savedDrafts)[Bawl.prefint];
			if ( Bawl.savedDrafts[Bawl.processDraftKey].time < Bawl.timestampNowDraftLastWeek ) {
				Bawl.debug('draft ' + Bawl.processDraftKey + ' is over a week old, removing it');
				delete Bawl.savedDrafts[Bawl.processDraftKey];
			}
		}
		if ( Bawl.UITextInput.getValue().length > 100 && ! removeDraft ) {
			Bawl.savedDrafts[encodeURIComponent(replyLinkParams.id)] = {'time':Bawl.timestampNowDraft,'text':Bawl.UITextInput.getValue()};
		} else if ( Bawl.savedDrafts[encodeURIComponent(replyLinkParams.id)] ) {
			Bawl.debug('too short or deletion requested, removing draft ' + encodeURIComponent(replyLinkParams.id) + ', trigger: ' + trigger);
			if ( trigger == 'user' && Bawl.UITextInput.getValue() > 100 ) {
				mw.notify(Bawl.msgs.removeDraft);
			}
			delete Bawl.savedDrafts[encodeURIComponent(replyLinkParams.id)];
		} else {
			Bawl.debug('no change to drafts found');
			Bawl.draftUnchanged = true;
		}
		if ( ! Bawl.draftUnchanged || trigger == 'user' ) {
			Bawl.debug('save drafts to localStorage, trigger: ' + trigger);
			window.localStorage.setItem('BawlDrafts',JSON.stringify(Bawl.savedDrafts));
		} else {
			Bawl.debug('no change, skipped saving');
		}
	}
};
Bawl.closeSettings = function() {
	$(document.getElementsByClassName('BawlSettings')).addClass('BawlNoDisplay');
	window.BawlUITextInput.scrollIntoView(Bawl.smoothScroll);
};
Bawl.unixTimeToFlatDate = function(timestamp) { //in: 1649799410000 out: 202204132136
	Bawl.unixTimeToFlatDateYear = new Date(new Date(timestamp).toLocaleString('en',{timeZone:Bawl.wikiTimezone})).getFullYear();
	Bawl.unixTimeToFlatDateMonth = (new Date(new Date(timestamp).toLocaleString('en',{timeZone:Bawl.wikiTimezone})).getMonth()) + 1;
	if ( Bawl.unixTimeToFlatDateMonth < 10 ) {
		Bawl.unixTimeToFlatDateMonth = '0' + Bawl.unixTimeToFlatDateMonth;
	}
	Bawl.unixTimeToFlatDateDay = (new Date(new Date(timestamp).toLocaleString('en',{timeZone:Bawl.wikiTimezone})).getDate());
	if ( Bawl.unixTimeToFlatDateDay < 10 ) {
		Bawl.unixTimeToFlatDateDay = '0' + Bawl.unixTimeToFlatDateDay;
	}
	Bawl.unixTimeToFlatDateHours = new Date(new Date(timestamp).toLocaleString('en',{timeZone:Bawl.wikiTimezone})).getHours();
	if ( Bawl.unixTimeToFlatDateHours < 10 ) {
		Bawl.unixTimeToFlatDateHours = '0' + Bawl.unixTimeToFlatDateHours;
	}
	Bawl.unixTimeToFlatDateMinutes = new Date(new Date(timestamp).toLocaleString('en',{timeZone:Bawl.wikiTimezone})).getMinutes();
	if ( Bawl.unixTimeToFlatDateMinutes < 10 ) {
		Bawl.unixTimeToFlatDateMinutes = '0' + Bawl.unixTimeToFlatDateMinutes;
	}
	return Bawl.unixTimeToFlatDateYear + Bawl.unixTimeToFlatDateMonth + Bawl.unixTimeToFlatDateDay + Bawl.unixTimeToFlatDateHours + Bawl.unixTimeToFlatDateMinutes;
};
Bawl.createPingText = function(replyLinkParams,mode) {
	Bawl.debug('create ping text');
	if ( replyLinkParams.origReplyTo == '' ) {
		return;
	}
	Bawl.recipientIsAnon = replyLinkParams.origReplyTo.match(/(^anon$|^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$|\:)/); //IPv4 or contains a colon as in IPv6 which is disallowed in usernames. Will need adjustment after IP anonimization
	Bawl.checkHtmlForNoping = Bawl.processElementArray[replyLinkParams.int].parentElement.innerHTML;
	Bawl.checkLessHtmlForNopingRegExp = new RegExp('Bawl.escapeRegExp(replyLinkParams.origReplyTo).*NOPING.*' + Bawl.escapeRegExp(replyLinkParams.origTimestamp));
	Bawl.checkLessHtmlForNoping = '';
	if ( Bawl.checkHtmlForNoping.match(Bawl.checkLessHtmlForNopingRegExp) ) {
		Bawl.checkLessHtmlForNoping = Bawl.checkHtmlForNoping.match(Bawl.checkLessHtmlForNopingRegExp)[0];
	}
	Bawl.userHatesPingRegExp = new RegExp('(' + Bawl.escapeRegExp(replyLinkParams.origReplyTo) + '.*)NOPING(\:[^\:<\>\"]{0,120})?(\:[^\:<\>\"]{0,120})?(\:[^\:<\>\"]{0,120})?(\:[^\:<\>\"]{0,120})?(\:[^\:<\>\"]{0,120})?(.{0,100}' + Bawl.escapeRegExp(replyLinkParams.origTimestamp) + '.*)');
	Bawl.userHatesPing = Bawl.checkLessHtmlForNoping.match(Bawl.userHatesPingRegExp);
	replyLinkParams = Bawl.addPageAndSectionTitleToRPL(replyLinkParams);
	if ( mode == 'addping' && replyLinkParams.pageTitle.replace(/_/g,' ') == Bawl.replyLinkParamsOpened.pageTitle.replace(/_/g,' ') && replyLinkParams.sectionTitle.replace(/_/g,' ') == Bawl.replyLinkParamsOpened.sectionTitle.replace(/_/g,' ') && replyLinkParams.sectionseq == Bawl.replyLinkParamsOpened.sectionseq ) {
		Bawl.debug('you pressed a speech balloon in the same section where you are adding a comment');
		Bawl.createdPingText = Bawl.settings.pingTextInSection.replace(/PINGUSER/g, Bawl.escapeReplacement(replyLinkParams.origReplyTo.replace(/_/g,' ')));
		if ( replyLinkParams.subtype == 'locator' ) {
			Bawl.createdPingText = Bawl.createdPingText.replace(/CMTLINK/g, '#' + Bawl.escapeReplacement(replyLinkParams.id));
		} else if ( replyLinkParams.subtype == 'legacy' ) {
			Bawl.addAnchorTimestamp = Bawl.sigDateToMachineReadable(replyLinkParams.origTimestamp);
			Bawl.addAnchorCmtLink = Bawl.unixTimeToFlatDate(Bawl.addAnchorTimestamp) + '_' + replyLinkParams.origReplyTo.replace(/ /g,'_');
			Bawl.createdPingText = Bawl.createdPingText.replace(/CMTLINK/g, '#' + Bawl.escapeReplacement(Bawl.addAnchorCmtLink));
		}
	} else {
		Bawl.createdPingText = Bawl.settings.pingText.replace(/PINGUSER/g, Bawl.escapeReplacement(replyLinkParams.origReplyTo.replace(/_/g,' ')));
	}
	if ( Bawl.settings.quoteSelect && Bawl.selectedText && Bawl.selectedText != '' ) {
		if ( Bawl.basicmsgs.tq != '' ) {
			Bawl.quoteSelect = '(('+Bawl.basicmsgs.tq+'|1='+Bawl.selectedText+')) ';
		} else {
			Bawl.quoteSelect = Bawl.wikiMsgs.quoteOpen+Bawl.selectedText+Bawl.wikiMsgs.quoteClose+' ';
		}
		Bawl.createdPingText = Bawl.createdPingText + Bawl.quoteSelect;
		Bawl.pingTextAnon = Bawl.pingTextAnon + Bawl.quoteSelect;
	} else {
		Bawl.quoteSelect = '';
	}
	if ( Bawl.recipientIsAnon != null ) {
		Bawl.debug('anon user found');
		return Bawl.pingTextAnon.replace(/PINGUSER/g, Bawl.escapeReplacement(replyLinkParams.origReplyTo));
	} else if ( Bawl.userHatesPing && Bawl.userName ) {
		Bawl.debug('user hates pings and you are logged in');
		Bawl.userNemesis = Bawl.checkLessHtmlForNoping.replace(Bawl.userHatesPingRegExp, '$2$3$4$5$6').replace(/_/g, ' ');
		if ( Bawl.userNemesis == '' || Bawl.userNemesis.match(':' + Bawl.userName + ':') ) {
			Bawl.debug(replyLinkParams.origReplyTo + ' doesn\'t want to be pinged');
			if ( Bawl.userNemesis.match(':' + Bawl.userName + ':') ) {
				Bawl.debug('BY YOU.');
			}
			mw.notify(Bawl.msgs.nopingNotify,{type:'error'});
			return replyLinkParams.origReplyTo + ', '+Bawl.quoteSelect;
		} else {
			Bawl.debug('this user has enemies, but you aren\'t one of them. adding ping');
			return Bawl.createdPingText;
		}
	} else if ( replyLinkParams.origReplyTo.replace(/_/g,' ') == Bawl.userName ) {
		Bawl.debug('you talking to yourself?');
	} else if ( replyLinkParams.origReplyTo.replace(/_/g,' ') == mw.config.get('wgRelevantUserName') && ! mw.config.get('wgRelevantPageName').match('/') ) {
		Bawl.debug('not pinging user on their own talk page');
	} else {
		return Bawl.createdPingText;
	}
};
Bawl.listToRaw = function(text) {
	return text.replace(/<[\/]?ul>/g, '').replace(/<\/li>([^<])/g, '</li>\n$1').replace(/<li>(([^<]|<(?!\/li>))*)<\/li>/g, '\n*$1').replace(/<li style="margin\-left:2em;">(([^<]|<(?!\/li>))*)<\/li>/g, '\n**$1').replace(/<li style="margin\-left:3em;">(([^<]|<(?!\/li>))*)<\/li>/g, '\n***$1');
};
Bawl.syncToVisual = function() {
	if ( Bawl.syncBackToVisual == false ) {
		Bawl.debug('skip syncing back to visual');
		Bawl.syncBackToVisual = true;
	} else if ( Bawl.activeEditor == 'visualLight' ) {
		Bawl.debug('sync to visual');
		Bawl.visualComment = Bawl.processComment(Bawl.UITextInput.getValue(), 'toVisual');
		Bawl.visualComment = Bawl.visualComment.replace(/\*\*([^\*\n]+)\*\*/g, '<b>$1</b>').replace(/(^|[^:"'])\/\/(([^\/]|:\/|\/[^\/])*[^:"'])\/\/($|[^\/])/g, '$1<i>$2</i>$4').replace(/(^|[^'])'''(([^']|'[^']|''[^'])*)'''([^'])/g, '$1<b>$2</b>$4').replace(/(^|[^'])''([^']([^']|'''|[^']'[^'])*)''([^'])/g, '$1<i>$2</i>$4').replace(/\[([A-Za-z0-9]*):\/\/([^ \]]*)\]/g, '<a class="external" href="$1://$2">[1]</a>').replace(/\[([A-Za-z0-9]*):\/\/([^ \]]*) ([^\]]*)\]/g, '<a class="external" href="$1://$2">$3</a>').replace(/\[\[(([^\]\|]|\][^\]])*)\|\]\]/g, '<a class="BawlUnnamedPipeTrickInternalLink" href="/wiki/$1">$1</a>').replace(/\[\[(([^\]\|]|\][^\]])*)\]\]/g, '<a class="BawlUnnamedInternalLink" href="/wiki/$1">$1</a>').replace(/\[\[([^\|]*)\|(([^\]]|\][^\]])*)\]\]/g, '<a class="BawlNamedInternalLink" href="/wiki/$1">$2</a>').replace(/(<a class="BawlUnnamedInternalLink" href="[^"]*">):/, '$1');
		Bawl.UIVisual.innerHTML = Bawl.visualComment;
	}
};
Bawl.syncToSource = function(syncBackToVisual,origin) {
	if ( Bawl.activeEditor == 'visualLight' ) {
		if ( origin != 'livePreview' ) {Bawl.debug('sync to source');}
		Bawl.sourceComment = Bawl.UIVisual.innerHTML.replace(/<i>(([^<]|<(?!\/i>))*)<\/i>/g,'//$1//').replace(/<b>(([^<]|<(?!\/b>))*)<\/b>/g,'**$1**').replace(/<div>(([^<]|<(?!\/div>))*)<\/div>/g, '<br />' + '$1').replace(/(<br( \/)?>)+/g, '\n').replace(/<a class="BawlUnnamedPipeTrickInternalLink" href="\/wiki\/([^"]*)">(([^<]|<(?!\/a>))*)<\/a>/g, '[[$1|]]').replace(/<a class="BawlUnnamedInternalLink" href="\/wiki\/([^"]*)">(([^<]|<(?!\/a>))*)<\/a>/g, '[[$1]]').replace(/<a class="BawlNamedInternalLink" href="\/wiki\/([^"]*)">(([^<]|<(?!\/a>))*)<\/a>/g, '[[$1|$2]]').replace(/<a class="external" href="([^"]*)">[1]<\/a>/g, '[$1]').replace(/<a class="external" href="([^"]*)">(([^<]|<(?!\/a>))*)<\/a>/g, '[$1 $2]');
		if ( syncBackToVisual == false ) {
			Bawl.syncBackToVisual = false;
		}
		Bawl.UITextInput.setValue(Bawl.listToRaw(Bawl.sourceComment).replace(/(\n)+/g, '\n'));
		delete Bawl.sourceComment;
	}
};
Bawl.focusInput = function(start) {
	if ( Bawl.activeEditor == 'visualLight' ) {
		document.getSelection().collapse(Bawl.UIVisual,Bawl.UIVisual.childNodes.length);
	} else if ( Bawl.activeEditor == 'source' && start == 'start' ) {
		Bawl.UITextInput.moveCursorToStart();
	} else if ( Bawl.activeEditor == 'source' ) {
		Bawl.UITextInput.focus();
	}
};
Bawl.insertMarkup = function(type, content, markUpStart, markUpEnd, focusNodeMP, focusOffsetMP, anchorNodeMP, anchorOffsetMP) {
	Bawl.markUpStart = { 'italic':'//','bold':'**','struck':'<s>','superscript':'<sup>','subscript':'<sub>','code':'<code>','underline':'<u>','h1':'= ','h2':'== ','h3':'=== ','h4':'==== ','h5':'===== ','h6':'====== ','blockquote':'<blockquote>','PingDropDown':content,'cI':markUpStart};
	Bawl.markUpEnd = { 'italic':'BAWLCRT//','bold':'BAWLCRT**','struck':'BAWLCRT</s>','superscript':'BAWLCRT</sup>','subscript':'BAWLCRT</sub>','code':'BAWLCRT</code>','underline':'BAWLCRT</u>','h1':'BAWLCRT =','h2':'BAWLCRT ==','h3':'BAWLCRT ===','h4':'BAWLCRT ====','h5':'BAWLCRT =====','h6':'BAWLCRT ======','blockquote':'BAWLCRT</blockquote>','PingDropDown':'BAWLCRT','cI':'BAWLCRT' + markUpEnd};
	if ( type == 'link' ) {
		if ( Bawl.UIinsertLinkLink.getValue().match(/^(www\.|[A-Za-z0-9]+:\/\/)/) ) {
			Bawl.debug('looks like an external link you\'re trying to insert');
			if ( Bawl.UIinsertLinkLink.getValue().match(/^www\./) ) {
				Bawl.linkToInsert = 'http://' + Bawl.UIinsertLinkLink.getValue();
			} else {
				Bawl.linkToInsert = Bawl.UIinsertLinkLink.getValue();
			}
			if ( Bawl.UIinsertLinkName.getValue() != '' ) {
				Bawl.useLinkName = Bawl.UIinsertLinkName.getValue();
			} else {
				Bawl.useLinkName = '';
			}
			Bawl.markUpStart.link = '[' + Bawl.linkToInsert + ' ';
			Bawl.markUpEnd.link = Bawl.useLinkName + ']BAWLCRT';
			Bawl.linkToInsertInternalCheck = Bawl.rewritunUrUrlz(Bawl.linkToInsert,'insertlink',Bawl.useLinkName);
			if ( Bawl.linkToInsertInternalCheck != Bawl.linkToInsert ) {
				Bawl.markUpStart.link = Bawl.linkToInsertInternalCheck.replace(/(.*[^\]])([\]]+)$/,'$1');
				Bawl.markUpEnd.link = Bawl.linkToInsertInternalCheck.replace(/(.*[^\]])([\]]+)$/,'$2') + 'BAWLCRT';
			} else {
				Bawl.insertLinkStart = 'BAWLINSERTEDLINKLINK ' + Bawl.linkToInsert;
				Bawl.insertLinkEnd = ' BAWLINSERTEDLINKNAMESTART-' + Bawl.UIinsertLinkName.getValue() + '-BAWLINSERTEDLINKNAMEEND';
			}
		} else {
			Bawl.debug('I\'m guessing article/template title.');
			Bawl.pipedLink = '';
			Bawl.linkOpenBrackets = '[[';
			Bawl.linkCloseBrackets = ']]';
			Bawl.linkValue = Bawl.UIinsertLinkLink.getValue();
			if ( Bawl.checkLinkInsertingTemplate ) {
				Bawl.checkForTemplateNSRegExp = new RegExp('^' + Bawl.escapeRegExp(mw.config.get('wgFormattedNamespaces')[10]) + ':');
				Bawl.linkOpenBrackets = '((';
				if ( Bawl.linkValue.match(Bawl.checkForTemplateNSRegExp) ) {
					Bawl.linkValue = Bawl.linkValue.replace(Bawl.checkForTemplateNSRegExp,'');
				}
				Bawl.linkCloseBrackets = '))';
				if ( Bawl.UIinsertLinkName.getValue() != '' ) {
					Bawl.pipedLink = '|';
				}
			} else if ( Bawl.linkValue.match(/:/) || Bawl.UIinsertLinkName.getValue() != '' && ! Bawl.checkLinkInsertingTemplate ) {
				Bawl.pipedLink = '|';
				Bawl.linkOpenBrackets = '[[';
				Bawl.linkCloseBrackets = ']]';
			}
			Bawl.markUpStart.link = Bawl.linkOpenBrackets + Bawl.linkValue + Bawl.pipedLink;
			Bawl.markUpEnd.link = Bawl.UIinsertLinkName.getValue() + Bawl.linkCloseBrackets + 'BAWLCRT';
		}
	}
	if ( Bawl.activeEditor == 'visualLight' ) {
		if ( focusNodeMP != anchorNodeMP ) {
			focusNodeMP.textContent = focusNodeMP.textContent.slice(0,focusOffsetMP) + 'BAWLINSERTMARKUP' + focusNodeMP.textContent.slice(focusOffsetMP);
			anchorNodeMP.textContent = anchorNodeMP.textContent.slice(0,anchorOffsetMP) + 'BAWLINSERTMARKUP' + anchorNodeMP.textContent.slice(anchorOffsetMP);
		} else {
			if ( focusOffsetMP == anchorOffsetMP ) {
				focusNodeMP.textContent = focusNodeMP.textContent.slice(0,focusOffsetMP) + 'BAWLINSERTMARKUPBAWLINSERTMARKUP' + focusNodeMP.textContent.slice(focusOffsetMP);
			} else if ( focusOffsetMP > anchorOffsetMP ) {
				focusNodeMP.textContent = focusNodeMP.textContent.slice(0,anchorOffsetMP) + 'BAWLINSERTMARKUP' + focusNodeMP.textContent.slice(anchorOffsetMP,focusOffsetMP) + 'BAWLINSERTMARKUP' + focusNodeMP.textContent.slice(focusOffsetMP);
			} else {
				focusNodeMP.textContent = focusNodeMP.textContent.slice(0,focusOffsetMP) + 'BAWLINSERTMARKUP' + focusNodeMP.textContent.slice(focusOffsetMP,anchorOffsetMP) + 'BAWLINSERTMARKUP' + focusNodeMP.textContent.slice(anchorOffsetMP);
			}
		}
		Bawl.syncToSource(); //in visual we insert those generic "BAWLINSERTMARKUP" markers, then we sync to source. These markers allow us to find the corresponding offset in source for the anchorNodeMP and focusNodeMP. The generic markers are replaced with the desired content IN SOURCE, the source change triggers a sync to visual.
		Bawl.MarkUpStartOffset = Bawl.UITextInput.getValue().split('BAWLINSERTMARKUP')[0].length;
		if ( Bawl.UITextInput.getValue().split('BAWLINSERTMARKUP')[1] ) {
			Bawl.MarkUpEndOffset = Bawl.UITextInput.getValue().split('BAWLINSERTMARKUP')[0].length + Bawl.UITextInput.getValue().split('BAWLINSERTMARKUP')[1].length;
		} else {
			Bawl.MarkUpEndOffset = Bawl.MarkUpStartOffset;
		}
		Bawl.UITextInput.setValue(Bawl.UITextInput.getValue().replace(/BAWLINSERTMARKUP/g,'').replace(/BAWLINSERTMARKUP/g,''));
		Bawl.UITextInput.selectRange(Bawl.MarkUpStartOffset,Bawl.MarkUpEndOffset);
	}
	Bawl.UITextInput.encapsulateContent(Bawl.markUpStart[type], Bawl.markUpEnd[type]);
	if ( Bawl.activeEditor == 'visualLight' ) {
		Bawl.UIVisualAllElements = $('#BawlVisualLight *,#BawlVisualLight');
		Bawl.UIVisualFoundCaret = false;
		for (Bawl.UIVisualAllElementsInt=0;Bawl.UIVisualAllElementsInt<Bawl.UIVisualAllElements.length;Bawl.UIVisualAllElementsInt++){
			for (Bawl.UIVisualAllElementsChildrenInt=0;Bawl.UIVisualAllElementsChildrenInt<Bawl.UIVisualAllElements[Bawl.UIVisualAllElementsInt].childNodes.length;Bawl.UIVisualAllElementsChildrenInt++){
				if ( Bawl.UIVisualAllElements[Bawl.UIVisualAllElementsInt].childNodes[Bawl.UIVisualAllElementsChildrenInt].nodeName == '#text' && Bawl.UIVisualAllElements[Bawl.UIVisualAllElementsInt].childNodes[Bawl.UIVisualAllElementsChildrenInt].textContent.match('BAWLCRT') ) {
					Bawl.debug('found caret textnode');
					Bawl.UIVisualFoundCaret = true;
					Bawl.UIVisualCaretNode = Bawl.UIVisualAllElements[Bawl.UIVisualAllElementsInt].childNodes[Bawl.UIVisualAllElementsChildrenInt];
					Bawl.UIVisualCaretOffset = Bawl.UIVisualCaretNode.textContent.split('BAWLCRT')[0].length;
					Bawl.UIVisualCaretNode.textContent = Bawl.UIVisualCaretNode.textContent.replace('BAWLCRT','');
					break;
				}
			}
			if ( Bawl.UIVisualFoundCaret ) {
				Bawl.debug('found caret element');
				Bawl.UIVisualFoundCaret = true;
				break;
			}
		}
		Bawl.debug('focus visualLight input');
		document.getSelection().collapse(Bawl.UIVisualCaretNode,Bawl.UIVisualCaretOffset);
	} else if ( Bawl.activeEditor == 'source' ) {
		Bawl.sourceFocusOffset = Bawl.UITextInput.getValue().split('BAWLCRT')[0].length;
		Bawl.UITextInput.setValue(Bawl.UITextInput.getValue().replace(/BAWLCRT/,''));
		Bawl.UITextInput.selectRange(Bawl.sourceFocusOffset);
	}
};
Bawl.checkLinkSwitch = function() {
	if ( ['[[','(('].includes(Bawl.UITextInput.getValue().slice(Bawl.UITextInput.getRange().to -2,Bawl.UITextInput.getRange().to)) ) { //todo: visualLight
		Bawl.insertLink('linkSwitch');
	}
};
Bawl.linkFieldChange = function(mode) {
	if ( mode == 'link' && Bawl.basicmsgs.citemap != '' && Bawl.UIinsertLinkLink.getValue().match(/:\/\//) ) {
		Bawl.UIinsertLinkWeb2Cit.toggle(true);
		$('#Web2CitLink')[0].href = 'https://web2cit.toolforge.org/' + encodeURIComponent(Bawl.UIinsertLinkLink.getValue());
	} else if ( Bawl.UIinsertLinkWeb2Cit ) {
		Bawl.UIinsertLinkWeb2Cit.toggle(false);
	}
	Bawl.debug('get page title suggestions');
	if ( mode == 'link' && [']]','))'].includes(Bawl.UIinsertLinkLink.getValue().slice(-2)) ) {
		Bawl.submitInsertedLink('linkField');
		return;
	}
	if ( mode == 'contentmove' ) {
		if ( Bawl.oneTimeTools.moveContentToPage.getValue() != '' ) {
			Bawl.oneTimeTools.allowPageCreation.setDisabled(false);
		} else {
			Bawl.oneTimeTools.allowPageCreation.setDisabled(true);
			Bawl.oneTimeTools.allowPageCreation.setSelected(false);
		}
		if ( Bawl.oneTimeTools.allowPageCreation.isSelected() ) {
			Bawl.oneTimeTools.moveContentToPage.setOptions([]);
			return;
		}
		Bawl.linkFieldSearchTerm = Bawl.oneTimeTools.moveContentToPage.getValue();
	} else {
		Bawl.linkFieldSearchTerm = Bawl.UIinsertLinkLink.getValue();
	}
	if ( mode == 'contentmove' || ( Bawl.UIinsertLinkLink && ! Bawl.UIinsertLinkLink.getValue().match(/^(.*:\/\/|www\.)/) ) ) { //external links are not article titles so don't bother looking for suggestions
		api.get({'action':'opensearch','format':'json','formatversion': 2,'search':Bawl.linkFieldSearchTerm,'namespace':[0,2,3,4,5],'limit':6}).then(function(suggestedTitles) {
			Bawl.suggestedTitles = [];
			for(Bawl.suggestedTitlesInt=0;Bawl.suggestedTitlesInt<suggestedTitles[1].length;Bawl.suggestedTitlesInt++){
				Bawl.suggestedTitles.push({data:suggestedTitles[1][Bawl.suggestedTitlesInt]});
			}
			if ( mode == 'contentmove' ) {
				Bawl.oneTimeTools.moveContentToPage.setOptions(Bawl.suggestedTitles);
			} else {
				Bawl.UIinsertLinkLink.setOptions(Bawl.suggestedTitles);
			}
		});
	} else if ( mode == 'link' ) {
		Bawl.UIinsertLinkLink.setOptions([]);
	} else {
		Bawl.oneTimeTools.moveContentToPage.setOptions([]);
	}
};
Bawl.insertLink = function(focusNode,focusOffset,anchorNode,anchorOffset) {
	Bawl.checkLinkInsertingTemplate = false;
	if ( $('#UIinsertLinkForm')[0] ) {
		Bawl.debug('link form was opened previously, empty fields and make it visible again');
		Bawl.UIinsertLinkLink.setValue('');
		Bawl.UIinsertLinkName.setValue('');
		Bawl.UIinsertLinkForm.toggle(true);
		Bawl.UIinsertLinkLink.focus();
	} else {
		Bawl.UIinsertLinkLink = new OO.ui.ComboBoxInputWidget( {
			classes: [ 'BawlMarginHalfEm',Bawl.BawlUITextInputTitleClass ],
			placeholder: Bawl.msgs.insertLinkLink,
			options: [],//{data:'Option 1',label: 'Option One'}
			spellcheck: false,
			menu: {filterFromInput: true}
		} );
		Bawl.UIinsertLinkName = new OO.ui.TextInputWidget( {
			classes: [ 'BawlMarginHalfEm',Bawl.BawlUITextInputTitleClass ],
			placeholder: Bawl.msgs.insertLinkName,
		} );
		Bawl.UIinsertLinkButton = new OO.ui.ButtonWidget( {
			label: Bawl.basicmsgs['htmlform-submit'],
			flags: [ 'primary', 'progressive' ],
			classes: [ Bawl.buttonOnTheWrongSideClass, 'BawlWideButton' ]
		} );
		Bawl.submitInsertedLink = function(origin) {
			if ( origin == 'linkField' && Bawl.UIinsertLinkLink.getValue().slice(-2) == '))' ) {
				Bawl.checkLinkInsertingTemplate = true;
			}
			if ( origin == 'linkField' ) {
				Bawl.UIinsertLinkLink.setValue(Bawl.UIinsertLinkLink.getValue().slice(0,Bawl.UIinsertLinkLink.getValue().length -2));
			}
			Bawl.insertMarkup('link','','','',focusNode,focusOffset,anchorNode,anchorOffset);
			Bawl.UIinsertLinkForm.toggle(false);
		};
		Bawl.UIinsertLinkButton.on('click', function() { Bawl.submitInsertedLink('button'); });
		Bawl.UIinsertRefButton = new OO.ui.ButtonWidget( {
			id: 'BawlUIInsertRefButton',
			label: Bawl.msgs.refbutton,
			flags: [ 'primary', 'progressive' ],
			classes: [ Bawl.buttonOnTheWrongSideClass, 'BawlWideButton' ]
		} );
		if ( Bawl.basicmsgs.citemap == '' ) {
			Bawl.debug('no citemap available for your wiki!! GO CREATE IT!! https://www.wikidata.org/wiki/Q112131235');
			Bawl.UIinsertRefButton.toggle(false);
		}
		Bawl.UIinsertRefButton.on('click', function() {Bawl.insertRef();});
		Bawl.insertRef = function() {
			Bawl.UIinsertRefButton.setDisabled(true);
			$('#BawlUIInsertRefButton').addClass('BawlPendingBlink');
			if ( ! Bawl.templateMapLoaded ) {
				Bawl.debug('loading template/parameter map for cites');
				$.getJSON( mw.util.wikiScript('api'),{format:'json',action:'query',titles:Bawl.basicmsgs.citemap,prop:'revisions',rvprop:'content'} ).done( function ( data ) {
					Bawl.templateMapLoaded = true;
					Bawl.templateMap = JSON.parse(data.query.pages[Object.keys(data.query.pages)[0]].revisions[0]['*']);
					Bawl.debug('template/parameter map for cites loaded');
					Bawl.insertRef();
				});
				return;
			}
			Bawl.debug('get stuff from web2cit for reference..');
			Bawl.web2CitUrl = 'https://web2cit.toolforge.org/translate/';
			Bawl.web2CitData = {'url':Bawl.UIinsertLinkLink.getValue(),'format':'mediawiki','citoid':'false'};
			Bawl.getRefData = function(params,callback,handleError,doCall) {
				callback = function ( jqXHR, textStatus, errorThrown ) {
					Bawl.debug('got the requested stuff from web2cit');
					Bawl.debug(jqXHR);
					Bawl.refDataObj = jqXHR[0];
					Bawl.linkCiteTemplateType = Bawl.templateMap.templateTypeMap[Bawl.refDataObj.itemType];
					Bawl.linkCiteTemplateParamsMap = Bawl.templateMap[Bawl.templateMap.templateParamMap[Bawl.linkCiteTemplateType]];
					Bawl.refDataString = Bawl.linkCiteTemplateType;
					for (Bawl.refDataObjInt=0;Bawl.refDataObjInt<Object.keys(Bawl.refDataObj).length;Bawl.refDataObjInt++){
						if (typeof Bawl.linkCiteTemplateParamsMap[Object.keys(Bawl.refDataObj)[Bawl.refDataObjInt]]!='undefined'){
							Bawl.refDataString = Bawl.refDataString + '|' + Bawl.linkCiteTemplateParamsMap[Object.keys(Bawl.refDataObj)[Bawl.refDataObjInt]]+'='+Bawl.refDataObj[Object.keys(Bawl.refDataObj)[Bawl.refDataObjInt]];
						}
					}
					Bawl.refTagName = '';
					if ( Bawl.refDataObj.publicationTitle ) {
						Bawl.refTagName = Bawl.refDataObj.publicationTitle;
					} else if ( Bawl.refDataObj.url && Bawl.refDataObj.url.match(/:\/\/([^\/]*)\//)){
						Bawl.refTagName = Bawl.refDataObj.url.match(/:\/\/([^\/]*)\//)[1].replace(/www\./,'');
					}
					if ( Bawl.refDataObj.date ) {
						if ( Bawl.refTagName != '' ) {
							Bawl.refTagName = Bawl.refTagName + '_';
						}
						Bawl.refTagName = Bawl.refTagName + Bawl.refDataObj.date;
					}
					if ( Bawl.UIinsertLinkName.getValue() != '' ) {
						Bawl.refTagName = Bawl.UIinsertLinkName.getValue();
					}
					Bawl.refString = Bawl.wikiMsgs.refOpen.replace(/REFNAME/g,Bawl.refTagName) + '(('+Bawl.refDataString+'))' + Bawl.wikiMsgs.refClose;
					Bawl.insertMarkup('cI','',Bawl.refString,'',focusNode,focusOffset,anchorNode,anchorOffset);
					$('#BawlUIInsertRefButton').removeClass('BawlPendingBlink');
					Bawl.UIinsertRefButton.setDisabled(false);
					Bawl.UIinsertLinkForm.toggle(false);
				};
				handleError = function ( jqXHR, textStatus, errorThrown ) {
					Bawl.debug('didn\'t get the requested stuff from web2cit');
					Bawl.debug(jqXHR);
					Bawl.debug(textStatus);
					Bawl.debug(errorThrown);
				};
				doCall = function () {
					$.ajax( {	url: Bawl.web2CitUrl, dataType: 'json', data: Bawl.web2CitData, type: 'GET', success: callback, error: handleError } );
				};
				doCall();
			};
			Bawl.getRefData();
		};
		Bawl.UIinsertLinkLink.on('enter', function() { Bawl.submitInsertedLink('button'); });
		Bawl.UIinsertLinkName.on('enter', function() { Bawl.submitInsertedLink('button'); });
		Bawl.UIinsertLinkLink.on('change',function() { Bawl.linkFieldChange('link'); });
		Bawl.UIinsertLinkCancel = new OO.ui.ButtonWidget( {
			label: Bawl.basicmsgs.cancel,
			flags: [ 'primary', 'destructive' ],
			classes: [ Bawl.buttonOnTheWrongSideClass, 'BawlWideButton' ]
		} );
		Bawl.UIinsertLinkCancel.on('click', function() { Bawl.UIinsertLinkForm.toggle(false); });
		Bawl.UIinsertLinkWeb2Cit = new OO.ui.LabelWidget( {
			label: new OO.ui.HtmlSnippet('<a id="Web2CitLink" target="_new" href="https://web2cit.toolforge.org/">Web2Cit</a>'),
		} );
		Bawl.UIinsertLinkWeb2Cit.toggle(false);
		Bawl.UIinsertLinkButtonBar = new OO.ui.HorizontalLayout( {
			items: [
				Bawl.UIinsertLinkButton,
				Bawl.UIinsertRefButton,
				Bawl.UIinsertLinkCancel,
				Bawl.UIinsertLinkWeb2Cit
			],
			classes: ['BawlLeftRightMargin']
		} );
		Bawl.UIinsertLinkForm = new OO.ui.FormLayout( {
			items: [
				Bawl.UIinsertLinkLink,
				Bawl.UIinsertLinkName,
				Bawl.UIinsertLinkButtonBar
			],
			id: 'UIinsertLinkForm',
			classes: ['BawlInsertLinkForm'],
		} );
		$('#BawlMainButtonBar').prepend(Bawl.UIinsertLinkForm.$element);
		$('#UIinsertLinkForm .oo-ui-comboBoxInputWidget-dropdownButton').remove();
		$('#UIinsertLinkForm .oo-ui-comboBoxInputWidget').removeClass('oo-ui-comboBoxInputWidget');
		Bawl.UIinsertLinkLink.focus();
	}
	if ( Bawl.UITextInput.getValue().slice(Bawl.UITextInput.getRange().to -2,Bawl.UITextInput.getRange().to) == '((' ) {
		Bawl.checkLinkInsertingTemplate = true;
	}
	if ( focusNode == 'linkSwitch' ) {
		Bawl.linkSwitchRange = Bawl.UITextInput.getRange().to;
		Bawl.UITextInput.setValue(Bawl.UITextInput.getValue().slice(0,Bawl.UITextInput.getRange().to -2) + Bawl.UITextInput.getValue().slice(Bawl.UITextInput.getRange().to));
		Bawl.UITextInput.selectRange(Bawl.linkSwitchRange -2);
		Bawl.UIinsertLinkLink.focus();
	}
	if ( Bawl.checkLinkInsertingTemplate ) {
		Bawl.UIinsertLinkLink.setValue(mw.config.get('wgFormattedNamespaces')[10] + ':');
	}
};
Bawl.initVisualLight = function() {
	Bawl.UIVisual = document.createElement('div');
	Bawl.UIVisual.contentEditable = true;
	Bawl.UIVisual.className = 'BawlVisualLight';
	Bawl.UIVisual.id = 'BawlVisualLight';
	Bawl.UITextInput.on('change', function() { Bawl.syncToVisual(); });
	$('body').bind("mouseup keyup touchend", function() {
		Bawl.focusNode = window.getSelection().focusNode;
		Bawl.anchorNode = window.getSelection().anchorNode;
		Bawl.caretIndex = window.getSelection();
		Bawl.anchorOffset = window.getSelection().anchorOffset;
		Bawl.focusOffset = window.getSelection().focusOffset;
		Bawl.selectionType = window.getSelection().type;
	});
	if ( Bawl.settings.pingDropDownAt ) {
		Bawl.UIVisual.oninput = function(){ Bawl.showPingDropDown(); };
	}
	if ( Bawl.activeEditor == 'source' && ! Bawl.settings.debug ) {//user enabled editorSwitch but kept source default
		Bawl.debug('initialized visualLight, hiding it as your activeEditor is source');
		Bawl.UIVisual.classList.add('BawlNoDisplay');
	}
};
if ( Bawl.settings.quoteSelect ) {
	$('#mw-content-text').bind("mouseup keyup touchend", function() {
		if ( window.getSelection().toString() != '' ) {
			Bawl.selectedText = window.getSelection().toString();
		} else {
			var DelayedOpenFormCheck = setInterval(function () {
				clearInterval(DelayedOpenFormCheck);
				if ( ! Bawl.openingFormInProgress || (Bawl.openingFormInProgress+100) < new Date().getTime() ) { //no form was opened, or a form was opened more than 100ms ago
					Bawl.selectedText = '';
				}
			},50);
		}
	});
}
Bawl.loadWikiEditor = function(a){
	if ( ! $('#BawlUITextInput .wikiEditor-ui')[0] ) {
		mw.loader.using(['ext.wikiEditor']).then(function() {
			mw.addWikiEditor(Bawl.UITextInput.$input);
			if ( a == 'ace' ) {
				Bawl.AceUpMySleeve('loadWikiEditor');
			}
		});
	}
};
Bawl.AceUpMySleeve = function(a){
			$('#BawlUITextInput', '#content').attr({
				name: 'wpTextbox1-temp',
				id: 'wpTextbox1-temp'
			});
	if ( ! $('#BawlUITextInput .wikiEditor-ui')[0] && a != 'loadWikiEditor' ) {
		Bawl.loadWikiEditor('ace');
		return;
	}
	//$('#BawlReplyForm #mw-editbutton-codemirror a')[0].click()
	//$('#BawlReplyForm .group-codeeditor-main a')[0].click()
	Bawl.UITextInput.$input.attr('id', 'wpTextbox1');
	mw.config.set('wgCodeEditorCurrentLanguage', mw.config.get('wgPageContentModel'));

	if (mw.loader.getState('ext.codeEditor') == 'ready') {
		mw.loader.state({'ext.codeEditor': 'loaded'});
	}

	//if (mw.loader.getState('ext.codeMirror') == 'ready') {
	//	mw.loader.state({'ext.codeMirror': 'loaded'});
	//}

	mw.loader.using(['ext.CodeMirror'], function() {
	});

	mw.loader.using(['ext.codeEditor'], function() {

				window.QFNcodeEditorloaded = true;
				// Loaded. Now return my id.
				$('body').one('mouseover', function() {
					if (window.QFNcodeEditorloaded) {
						$('#wpTextbox1', '#qfn-dialog').attr('id', 'qfn-code').removeAttr('name');
						$('#wpTextbox1-temp[name="wpTextbox1-temp"]').attr({
							name: 'wpTextbox1',
							id: 'wpTextbox1'
						});
						delete window.QFNcodeEditorloaded;
					}
				});
/*
		$('#wpTextbox1', '#qfn-dialog').attr('id', 'qfn-code').removeAttr('name');

		$('#wpTextbox1-temp[name="wpTextbox1-temp"]').attr({
			name: 'wpTextbox1',
			id: 'wpTextbox1'
		});
*/

	});
};
Bawl.toggleEditor = function() {
	if ( Bawl.activeEditor == 'source' ) {
		if ( mw.config.get('wgPageContentModel') != 'wikitext' ) {
			//Bawl.AceUpMySleeve();
		} else {
			Bawl.UITextInput.toggle(false);
			if ( ! Bawl.UIVisual.id ) {
				Bawl.initVisualLight();
			}
			$('#BawlUISwitchEditorButton').addClass('BawlHalfOpacity');
			Bawl.UIVisual.classList.remove('BawlNoDisplay');
			Bawl.activeEditor = 'visualLight';
			Bawl.syncToVisual();
		}
	} else if ( Bawl.activeEditor == 'visualLight' ) {
		Bawl.UITextInput.toggle(true);
		Bawl.UIVisual.classList.add('BawlNoDisplay');
		$('#BawlUISwitchEditorButton').removeClass('BawlHalfOpacity');
		Bawl.syncToSource();
		Bawl.activeEditor = 'source';
	}
	Bawl.focusInput();
};
Bawl.loadEditNotice = function(dismiss) {
	Bawl.debug('Loading editnotice');
	Bawl.cachedEditNotices = {};
	Bawl.dismissNoticeElement = '<div class="BawlEditNoticeDismiss"><a>[X]</a></div>';
	if ( window.localStorage.BawlEditNotices && Bawl.testValidJSON(window.localStorage.BawlEditNotices) && typeof Bawl.replyLinkParamsOpened.editintro == 'undefined' ) {
		Bawl.cachedEditNotices = JSON.parse(window.localStorage.BawlEditNotices);
		for (Bawl.editNoticeNum = 0; Bawl.editNoticeNum < Bawl.cachedEditNotices.length; Bawl.editNoticeNum++) {
			if ( Bawl.cachedEditNotices[(Object.keys(Bawl.cachedEditNotices)[Bawl.editNoticeNum])].time < (Bawl.timestampInit - 345600000 ) ) {
				Bawl.debug('removing old cached editnotice ' + Object.keys(Bawl.cachedEditNotices)[Bawl.editNoticeNum] + ' from window.localStorage');
				delete Bawl.cachedEditNotices[(Object.keys(Bawl.cachedEditNotices)[Bawl.editNoticeNum])];
			}
		}
		delete Bawl.editNoticeNum;
		if ( Bawl.cachedEditNotices[Bawl.replyLinkParamsOpened.pageTitle] && ! dismiss ) {
			Bawl.cachedEditNotices[Bawl.replyLinkParamsOpened.pageTitle] = {'time':Bawl.timestampInit,'text':Bawl.cachedEditNotices[Bawl.replyLinkParamsOpened.pageTitle].text}; //refresh cache time
			if ( Bawl.cachedEditNotices[Bawl.replyLinkParamsOpened.pageTitle].text.replace(/<[^<>]*>/g, '').replace(/^[ ]*$/, '') != '' ) {
				$('#BawlEditNotice').append(Bawl.dismissNoticeElement + '<div style="padding:0.5em">' + Bawl.cachedEditNotices[Bawl.replyLinkParamsOpened.pageTitle].text + '</div>');
				$('#BawlEditNotice').removeClass('BawlNoDisplay');
				$('.BawlEditNoticeDismiss').on('click',function(){Bawl.loadEditNotice('dismissed');});
			}
		} else if ( dismiss ) {
			Bawl.cachedEditNotices[Bawl.replyLinkParamsOpened.pageTitle] = {'time':Bawl.timestampInit,'text':''};
			$('#BawlEditNotice').addClass('BawlNoDisplay');
		}
		if ( JSON.parse(window.localStorage.BawlEditNotices) != Bawl.cachedEditNotices ) {
			Bawl.debug('saving editnotices');
			window.localStorage.setItem('BawlEditNotices',JSON.stringify(Bawl.cachedEditNotices));
		}
	}
	if ( ! Bawl.cachedEditNotices[Bawl.replyLinkParamsOpened.pageTitle] && ! dismiss ) {
		Bawl.editNoticeWikitext = '((#ifexist:MediaWiki:Editnotice-((NAMESPACENUMBER))-((#invoke:String|replace|((PAGENAME))|/|-))|((MediaWiki:Editnotice-((NAMESPACENUMBER))-((#invoke:String|replace|((PAGENAME))|/|-))))|((#ifexist:MediaWiki:Editnotice-((NAMESPACENUMBER))|((MediaWiki:Editnotice-((NAMESPACENUMBER))))))))';
		if ( Bawl.replyLinkParamsOpened.editintro ) {
			Bawl.editNoticeWikitext = '((' + Bawl.replyLinkParamsOpened.editintro + '))';
		}
		Bawl.editNoticeParams = {
			format: 'json',
			action: 'parse',
			disablelimitreport: true,
			title: Bawl.replyLinkParamsOpened.pageTitle,
			pst: '1',
			prop: 'text',
			formatversion: '2',
			uselang: Bawl.userLang,
			text: '<div id="BawlNotice">' + Bawl.editNoticeWikitext + '<span id="BawlNoticeEnd">end</span></div>',
		};
		if ( Bawl.replyLinkParamsOpened.editIntro ) {
			Bawl.editNoticeParams.text = '((:' + Bawl.replyLinkParamsOpened.editIntro + '))';
		}
		api.post( Bawl.editNoticeParams ).then( function ( data ) {
			if ( data.parse ) {
				Bawl.debug('Got editnotice, inserting and saving to localStorage');
				Bawl.editNoticeExtracted = data.parse.text.replace(/[^]*<div id="BawlNotice">(([^])*)<span id="BawlNoticeEnd"[^]*/,'$1');
				if ( Bawl.flattenWikiText(Bawl.editNoticeExtracted).trim() != '' ) {
					$('#BawlEditNotice').append(Bawl.dismissNoticeElement + '<div style="padding:0.5em">' + Bawl.editNoticeExtracted + '</div>');
					$('#BawlEditNotice').removeClass('BawlNoDisplay');
					$('.BawlEditNoticeDismiss').on('click',function(){Bawl.loadEditNotice('dismissed');});
				} else {
					Bawl.editNoticeExtracted = ''; //the edit notice is empty or essentially empty. On metawiki in the User talk: namespace you get some empty divs for example
				}
				if ( typeof Bawl.replyLinkParamsOpened.editintro == 'undefined' ) {
					Bawl.cachedEditNotices[Bawl.replyLinkParamsOpened.pageTitle] = {'time':Bawl.timestampInit,'text':Bawl.editNoticeExtracted};
					window.localStorage.setItem('BawlEditNotices',JSON.stringify(Bawl.cachedEditNotices));
				}
			}
		}, function ( code, data ) { Bawl.APIError(code, data);
		});
	}
};
Bawl.setCustomBackground = function() {
	if ( Bawl.settings.bgicon && Bawl.replyLinkParamsOpened.type == 'comment' ) {
		$('#BawlUITextInput textarea')[0].style.opacity = '0.95';
		$('#BawlReplyForm:eq(0)').addClass('BawlCommentBG');
	} else if ( Bawl.settings.bgicon && Bawl.replyLinkParamsOpened.type == 'edit' ) {
		$('#BawlUITextInput textarea')[0].style.opacity = '0.95';
		$('#BawlReplyForm:eq(0)').addClass('BawlEditBG');
	} else if ( Bawl.settings.customBackground != '' ) {
		$('#BawlUITextInput textarea')[0].style.opacity = '0.95';
		$('#BawlReplyForm')[0].style['background-image'] = 'url("'+Bawl.settings.customBackground+'")';
		$('#BawlReplyForm:eq(0)').addClass('BawlCustomBG');
	}
};
Bawl.editSummaryPipeTrick = function() {
	$('#BawlUITextInputSummary input').blur(function() { Bawl.UITextInputSummary.setValue(Bawl.rewritunUrUrlz(Bawl.UITextInputSummary.getValue().replace(/\[\[(.*):([^:]*)\|\]\]/,'[[$1:$2|$2]]'),'contentmove'));});
};
Bawl.showProtectedWarning = function(title) {
	if ( ! $('#BawlProtectedWarning')[0] ) {
		Bawl.protectionLevelText = '((MediaWiki:Protectedpagetext|((subst:#switch:((subst:PROTECTIONLEVEL:edit))|sysop=editprotected|((subst:PROTECTIONLEVEL:edit))))))'; //WHY is MediaWiki:Protectedpagetext called with a parameter like "editprotected" to indicate admin-only protection? WHY??
		api.get( {format: 'json', 'pst':1, 'formatversion':2, contentmodel:'wikitext', title: title, action: 'parse', disablelimitreport: true, uselang: Bawl.userLang, text: Bawl.protectionLevelText} ).then( function ( data ) {
			if ( ! $('#BawlProtectedWarning')[0] ) {//when called in quick succession the warning from the first request could be here now
				$('#BawlReplyForm').prepend('<div id="BawlProtectedWarning" class="BawlWarning" style="text-align:unset">' + data.parse.text + '</div>');
			}
		} );
	}
};
Bawl.getInnerTextTitles = function() {
	Bawl.titleElementsArray = Array.from($('#mw-content-text .mw-headline'));
	Bawl.innerTextTitles = [];
	for (Bawl.innerTextTitlesInt=0;Bawl.innerTextTitlesInt<Bawl.titleElementsArray.length;Bawl.innerTextTitlesInt++) {
		Bawl.innerTextTitles.push(Bawl.titleElementsArray[Bawl.innerTextTitlesInt].innerText);
	}
	return Bawl.innerTextTitles;
};
Bawl.checkIfTitleUnique = function() {
	if ( typeof Bawl.innerTextTitles == 'undefined' ) {
		Bawl.getInnerTextTitles();
	}
	if ( Bawl.innerTextTitles.indexOf(Bawl.flattenWikiText(Bawl.UITextInputTitle.getValue())) != -1 ) {
		$('#BawlUITextInputTitle input').addClass('BawlRedBG');
		Bawl.UITextInputTitle.setLabel(Bawl.msgs.sectionTitleNotUnique);
	} else {
		$('#BawlUITextInputTitle input').removeClass('BawlRedBG');
		Bawl.UITextInputTitle.setLabel('');
	}
};
Bawl.appendToFirstBlockParent = function(targetelement,formelement,mode) {
	Bawl.debug('find first block parent for element:');
	Bawl.debug(targetelement);
	if ( mw.config.get('skin') == 'minerva' && $('.talk-overlay.visible .BawlLinks')[0] ) {
		Bawl.testParentDisplay = targetelement;
		for(Bawl.testDisplay=0;Bawl.testDisplay<10;Bawl.testDisplayInt++){
			if ( typeof Bawl.testParentDisplay == 'object' && getComputedStyle(Bawl.testParentDisplay).display == 'none' ) {
				Bawl.debug('element associated with this Bawl icon is not currently visible. You\'re viewing a thread which was internally copied into an overlay. Multiple elements with the same ID?? Funky advanced mobile mode Minerva shit.');
				targetelement = $('.talk-overlay.visible')[0];//fallback if the next loop finds nothing
				for(Bawl.findCloneInt=0;Bawl.findCloneInt<$('.talk-overlay.visible .BawlLinks').length;Bawl.findCloneInt++){
					Bawl.debug('test element #' + Bawl.findCloneInt);
					if ($('.talk-overlay .BawlLinks')[Bawl.findCloneInt].id.match(Bawl.escapeRegExp(Bawl.replyLinkParamsOpened.id))){
						Bawl.debug('found cloned Bawl icon for this comment');
						targetelement = $('.talk-overlay .BawlLinks')[Bawl.findCloneInt];
						Bawl.debug(targetelement);
					}
				}
				break;
			}
			Bawl.testParentDisplay = Bawl.testParentDisplay.parentElement;
		}
	}
	Bawl.appendToFirstBlockParentTypes = ['block'];
	if ( mode == 'permalink' ) {
		Bawl.appendToFirstBlockParentTypes.push('inline-block');
	}
	while ( typeof targetelement == 'object' && ! Bawl.appendToFirstBlockParentTypes.includes(getComputedStyle(targetelement).display) && ! targetelement.classList.contains('mw-parser-output') ) {
		Bawl.debug(targetelement);
		Bawl.debug('..NOPE.');
		targetelement = targetelement.parentElement;
	}
	if ( mode == 'permalink' ) {
		targetelement.prepend(formelement);
	} else {
		targetelement.append(formelement);
	}
};
Bawl.applyFunctionToSelection = function(a){//a=function()
	Bawl.UITextInput.encapsulateContent('BAWLAPPLYFUNC','BAWLAPPLYFUNC');
	Bawl.extractedSelectedText = Bawl.UITextInput.getValue().match(/BAWLAPPLYFUNC([^]*)BAWLAPPLYFUNC/)[1];
	Bawl.processedExtractedSelectedText = a(Bawl.extractedSelectedText);
	Bawl.UITextInput.setValue(Bawl.UITextInput.getValue().replace(/BAWLAPPLYFUNC[^]*BAWLAPPLYFUNC/,Bawl.processedExtractedSelectedText));
};
Bawl.insertModuleButton = function(moduleNum,b) {
	if ( b == 'generic' ) {
		Bawl.moduleButtons[moduleNum].on('click', function(){Bawl.loadedModules[moduleNum].buttonFunc();});
	} else if ( b == 'selection' ) {
		Bawl.moduleButtons[moduleNum].on('click', function(){Bawl.applyFunctionToSelection(Bawl.loadedModules[moduleNum].selectionFunc);});
	}
};
Bawl.applyModules = function(a,processText){
	Bawl.moduleProcessedText = processText;
	if ( ( ! Bawl.loadedModules && window.BawlModules ) || Bawl.loadedModules && window.BawlModules && Bawl.loadedModules.length != window.BawlModules.length ) {
		Bawl.loadedModules = window.BawlModules;
		Bawl.loadedModulesLength = Bawl.loadedModules.length;
	}
	if ( typeof Bawl.loadedModules == 'object' && Bawl.loadedModulesLength>0 ) {
		Bawl.moduleButtons = {};
		for(Bawl.loadedModulesInt=0;Bawl.loadedModulesInt<Bawl.loadedModulesLength;Bawl.loadedModulesInt++){
			Bawl.debug('applyModules: check module #' + Bawl.loadedModulesInt);
			if ( Bawl.loadedModules[Bawl.loadedModulesInt].load.includes(a) ) { //execute some function contained within the module
				Bawl.debug('applyModules: module includes "'+a+'" loadtype');
				if ( typeof Bawl.loadedModules[Bawl.loadedModulesInt][a+'Func'] == 'function' ) {
					Bawl.debug('applyModules: run function from module with type '+a);
					Bawl.loadedModules[Bawl.loadedModulesInt][a+'Func']();
				}
			}
			if ( a == 'afterOpenForm' && Bawl.loadedModules[Bawl.loadedModulesInt].load.includes('afterOpenForm') ) {
				if ( typeof Bawl.loadedModules[Bawl.loadedModulesInt].extraUI == 'object' ) {
					$('#BawlCustomInserts').removeClass('BawlNoDisplay');
					$('#BawlCustomInserts').prepend(Bawl.loadedModules[Bawl.loadedModulesInt].extraUI.$element);
				}
				if ( typeof Bawl.loadedModules[Bawl.loadedModulesInt].buttonLabel == 'string' ) {
					$('#BawlCustomInserts').removeClass('BawlNoDisplay');
					Bawl.moduleButtons[Bawl.loadedModulesInt] = new OO.ui.ButtonWidget( {
						label:Bawl.loadedModules[Bawl.loadedModulesInt].buttonLabel,
						classes:['BawlMarginHalfEm',Bawl.buttonOnTheWrongSideClass,'BawlModuleButton'+Bawl.loadedModules[Bawl.loadedModulesInt].buttonLabel]
					} );
					if ( typeof Bawl.loadedModules[Bawl.loadedModulesInt].buttonFunc == 'function' ) {
						Bawl.debug('add event to button #' + Bawl.loadedModulesInt);
						Bawl.insertModuleButton(Bawl.loadedModulesInt,'generic');
					}
					if ( typeof Bawl.loadedModules[Bawl.loadedModulesInt].selectionFunc == 'function' ) {
						Bawl.insertModuleButton(Bawl.loadedModulesInt,'selection');
					}
					$('#BawlCustomInserts').prepend(Bawl.moduleButtons[Bawl.loadedModulesInt].$element);
				}
			} else if ( a == 'processComment' && Bawl.loadedModules[Bawl.loadedModulesInt].load.includes('processComment') && typeof Bawl.loadedModules[Bawl.loadedModulesInt].processCommentFunc == 'function' ) {
				Bawl.debug('applyModules: module includes "processComment" loadtype');
				Bawl.moduleProcessedText = Bawl.loadedModules[Bawl.loadedModulesInt].processCommentFunc(Bawl.moduleProcessedText);
				continue;
			}
		}
	} else { Bawl.debug('applyModules: no modules found');
	}
	if ( a == 'processComment' ) {
		return Bawl.moduleProcessedText;
	}
};
Bawl.openReplyForm = function(replyLinkParams, trigger) {
	Bawl.loadSettings();
	Bawl.applyModules('beforeOpenForm');
	delete Bawl.watched;
	delete Bawl.watchlistexpiry;
	delete Bawl.sectionNumFromLink;
	if ( Bawl.testValidJSON(decodeURIComponent(replyLinkParams)) ) {
		Bawl.debug('decode and parse replyLinkParams');
		replyLinkParams = JSON.parse(decodeURIComponent(replyLinkParams.replace(/\%27/g, '\'')));
	}
	Bawl.postCommentSuccess = false;
	if ( Bawl.settings.warnExit ) {
		window.onbeforeunload = function() { if ( Bawl.UITextInput.getValue().length > 30 && document.getElementById('BawlReplyForm') ) { return ''; } };
	}
	Bawl.debug(replyLinkParams);
	Bawl.debug('openReplyForm');
	if ( replyLinkParams.type != 'edit' && document.getElementById('BawlUITextInput') != null && replyLinkParams.type == 'comment' ) { //there is already a reply form open, add a ping instead
		Bawl.debug('form already open, adding ping');
		if ( Bawl.UITextInput.getValue().slice(Bawl.UITextInput.getValue().length - 1, Bawl.UITextInput.getValue().length) != " " ) {
			Bawl.spaceBeforePing = " ";
		} else {
			Bawl.spaceBeforePing = "";
		}
		Bawl.userPingText = Bawl.createPingText(replyLinkParams,'addping');
		if ( Bawl.userPingText && Bawl.UITextInput.getValue().match(Bawl.escapeRegExp(Bawl.userPingText)) ) {
			Bawl.debug('this user has already been mentioned. I\'ll scroll Bawl into view so you can see');
			Bawl.UITextInput.scrollElementIntoView();
			Bawl.UIReplyButton.scrollElementIntoView();
			Bawl.focusInput();
		} else if ( Bawl.userPingText ) {
			Bawl.debug('insert user ' + Bawl.userPingText);
			//Bawl.UITextInput.encapsulateContent() is the easier way to do this, but that will always focus the input field and scroll it into view. the focus isn't the issue, the scrolling can be if you are adding multiple names from elsewhere in the discussion
			Bawl.cursorPos = Bawl.UITextInput.getRange().from;
			Bawl.pingLength = Bawl.spaceBeforePing.length + Bawl.userPingText.length;
			Bawl.UITextInput.setValue(Bawl.UITextInput.getValue().slice(0, Bawl.cursorPos) + Bawl.spaceBeforePing + Bawl.userPingText + Bawl.UITextInput.getValue().slice(Bawl.cursorPos));
			$('#BawlUITextInput textarea')[0].selectionStart = Bawl.cursorPos + Bawl.pingLength;
			$('#BawlUITextInput textarea')[0].selectionEnd = Bawl.cursorPos + Bawl.pingLength;
		}
	} else if ( document.getElementById('BawlUITextInput') != null && replyLinkParams.type != 'comment' && replyLinkParams.type != 'edit' ) {
		Bawl.debug('not adding a mention for not-comment icons');
		Bawl.UITextInput.scrollElementIntoView();
		Bawl.UIReplyButton.scrollElementIntoView();
	} else if ( ! $('#BawlUITextInput')[0] ) {
		Bawl.openingFormInProgress = new Date().getTime();
		var DelayedSuccessCheck = setInterval(function () {
			clearInterval(DelayedSuccessCheck);
			if ( ! $('#BawlUITextInput')[0] && Bawl.openingFormInProgress < new Date().getTime()-Bawl.openingFormInProgressDelay+20 ) {
				Bawl.addScrewedLink('open form failed','Could not open form.');
			}
		},Bawl.openingFormInProgressDelay);
		if ( typeof Bawl.RETFTypoRegEx == 'undefined' && ( Bawl.basicmsgs.AWBtyposTitle || Bawl.settings.AWBtyposCustomTitle )&& Bawl.settings.AWBtypos ) {
			Bawl.RETF('','init'); //load AWB's RegExTypoFix now so it'll be ready when the comment is previewed/posted
		}
		mw.loader.using( [ 'oojs-ui-core' ] ).then( function () {
		if ( replyLinkParams.type == 'editFullPage' ) {
			Bawl.activeEditor = 'source';
		} else {
			Bawl.activeEditor = Bawl.settings.editor;
		}
		Bawl.debug('there is no reply form yet, let\'s create one');
		if ( ( $('.BawlPurpleBG').length - Bawl.purpleBGJoker ) > 0 ) {
			Bawl.debug('there\'s an element with the BawlPurpleBG class, either an edit that hasn\'t finished yet in which case it\'s advisable to wait, or one that failed in which case it may not be safe to proceed in this state');
			mw.notify(Bawl.basicmsgs.actionfailed,{type:'error'});
			Bawl.openingFormInProgress = new Date().getTime();
			return;
		}
		Bawl.replyLinkParamsOpened = replyLinkParams;
		if ( Bawl.oneTimeTools ) { //if the block status or section move/archive setting was changed in oneTimeTools when the form was opened previously, reset it
			delete Bawl.oneTimeTools;
		}
		delete Bawl.commentTextIndent;//if an indented comment is posted followed by a new (sub)section the indentation of the previous comment shouldn't be reused for the preview
		Bawl.bawlFormHTML = document.createElement('div');
		Bawl.bawlFormHTML.id = 'bawlForm-' + replyLinkParams.id;
		Bawl.bawlFormHTML.classList = [ 'BawlNoDisplay BawlForm' ];
		Bawl.counterUL = false;
		Bawl.bawlFormNegativeMargin = 0;
		Bawl.RETFsummary = '';
		if ( replyLinkParams.type == 'comment' ) {
			Bawl.debug('create form to add comment');
			Bawl.origCmtIndent = Bawl.getIndentationFromHTML(replyLinkParams.int);
			Bawl.cmtIndentHTML = Bawl.origCmtIndent;
			Bawl.relevantCmtElement = Bawl.processElementArray[replyLinkParams.int];
			Bawl.relevantCmtElementInt = replyLinkParams.int;
			Bawl.debug('HTMLindent: find element to insert form below for RLP #' + replyLinkParams.int + ' with indentation level ' + Bawl.origCmtIndent);
			for(Bawl.trueIndentInSectionHTMLInt=replyLinkParams.int+1;Bawl.trueIndentInSectionHTMLInt<=Number(Object.keys(Bawl.replyLinkParams)[Object.keys(Bawl.replyLinkParams).length -1]);Bawl.trueIndentInSectionHTMLInt++){
				if ( Bawl.replyLinkParams[Bawl.trueIndentInSectionHTMLInt] && Bawl.replyLinkParams[Bawl.trueIndentInSectionHTMLInt].type == 'newheading' ) {
					Bawl.debug('HTMLindent: ran into next section while looking for form insertion point in HTML');
					break;
				} else if ( Bawl.replyLinkParams[Bawl.trueIndentInSectionHTMLInt] && ! Bawl.replyLinkParams[Bawl.trueIndentInSectionHTMLInt].freshcomment ) {
					Bawl.testCmtIndentHTML = Bawl.getIndentationFromHTML(Number(Bawl.trueIndentInSectionHTMLInt));
					if ( Bawl.testCmtIndentHTML <= Bawl.origCmtIndent ) {
						Bawl.debug('HTMLindent: indentation of #' + Bawl.trueIndentInSectionHTMLInt + ' is ' + Bawl.testCmtIndentHTML + ', this is what we were looking for');
						break;
					} else {
						Bawl.relevantCmtElement = Bawl.processElementArray[Number(Bawl.trueIndentInSectionHTMLInt)];
						Bawl.relevantCmtElementInt = Number(Bawl.trueIndentInSectionHTMLInt);
						Bawl.cmtIndentHTML = Bawl.testCmtIndentHTML;
						Bawl.debug('HTMLindent: indentation of #' + Bawl.trueIndentInSectionHTMLInt + ' is ' + Bawl.cmtIndentHTML + ', too high');
					}
				}
			}
			Bawl.debug('HTMLindent: final relevantCmtElement ID: ' + Bawl.relevantCmtElementInt);
			Bawl.bawlFormNegativeMargin = ( Bawl.origCmtIndent - Bawl.cmtIndentHTML ) * 1.6;
			Bawl.debug('HTMLindent: margin: ' + Bawl.bawlFormNegativeMargin + 'em');
			Bawl.bawlFormHTML.style = 'margin-' + Bawl.CSSDirectionL + ':' + ( Bawl.bawlFormNegativeMargin + 1.6 ) + 'em';
			Bawl.appendToFirstBlockParent(Bawl.relevantCmtElement,Bawl.bawlFormHTML);
		} else if ( replyLinkParams.type == 'edit' && document.getElementById('bawlLink-' + Bawl.escapeHTML(replyLinkParams.id)) ) {
			Bawl.debug('edit type, appending form to:');
			Bawl.debug(document.getElementById('bawlLink-' + Bawl.escapeHTML(replyLinkParams.id)));
			Bawl.appendToFirstBlockParent(document.getElementById('bawlLink-' + Bawl.escapeHTML(replyLinkParams.id)),Bawl.bawlFormHTML);
		} else if ( ( replyLinkParams.type == 'newheading' || replyLinkParams.type == 'heading' ) && replyLinkParams.section != 0 ) {
			Bawl.processHeaderElementArray = Array.from($('#mw-content-text H1,#mw-content-text H2,#mw-content-text H3,#mw-content-text H4,#mw-content-text H5,#mw-content-text H6'));
			Bawl.findNextHeader = false;
			Bawl.nodeNameLevel = Bawl.processElementArray[replyLinkParams.int].parentElement.nodeName.slice(-1);
			delete Bawl.relevantCmtElement;
			for (Bawl.intHeaderElement = 0; Bawl.intHeaderElement < Bawl.processHeaderElementArray.length; Bawl.intHeaderElement++) {
				if ( Bawl.processHeaderElementArray[Bawl.intHeaderElement] == Bawl.processElementArray[replyLinkParams.int].parentElement ) {
					Bawl.findNextHeader = true;
				} else if ( Bawl.findNextHeader && Bawl.processHeaderElementArray[Bawl.intHeaderElement].nodeName.slice(-1) <= Bawl.nodeNameLevel ) {
					Bawl.relevantCmtElement = Bawl.processHeaderElementArray[Bawl.intHeaderElement];
					break;
				}
			}
			if ( Bawl.relevantCmtElement ) {
				Bawl.debug('newheading, inserting form in parentElement of this element, before this element:');
				Bawl.debug(Bawl.relevantCmtElement);
				Bawl.relevantCmtElement.parentElement.insertBefore(Bawl.bawlFormHTML,Bawl.relevantCmtElement);
			} else {
				Bawl.debug('no relevantCmtElement found, appending form to form to #mw-content-text');
				$('#mw-content-text').append(Bawl.bawlFormHTML);
				$('#BawlnSecBottom').addClass('BawlNoDisplay');
			}
		} else if ( replyLinkParams.type == 'BCL' ) {
			Bawl.debug('BCL, appending form to processElementArray #' + replyLinkParams.int);
			Bawl.appendToFirstBlockParent(Bawl.processElementArray[replyLinkParams.int],Bawl.bawlFormHTML);
		} else if ( replyLinkParams.type == 'editFullPage' || ( replyLinkParams.type == 'heading' && replyLinkParams.subtype == 'edit' && replyLinkParams.section == 0 ) ) {
			if ( Bawl.settings.clearEditFullPage ) {
				Bawl.debug('hiding page content, appending for mto #content');
				$('#mw-content-text').addClass('BawlNoDisplay');
				$('#content').append(Bawl.bawlFormHTML);
			} else {
				Bawl.debug('appending form to #mw-content-text');
				$('#mw-content-text').prepend(Bawl.bawlFormHTML);
			}
		} else if ( replyLinkParams.type == 'newsection' ) {
			if ( Bawl.settings.reverseSectionOrder && $('.BawlH1SectionsContainer')[0] ) {
				Bawl.debug('newsection with section reversal enabled and H1 section found, prepending to:');
				Bawl.debug($('.BawlH1SectionsContainer')[0]);
				$('.BawlH1SectionsContainer')[0].prepend(Bawl.bawlFormHTML);
			} else if ( Bawl.settings.reverseSectionOrder && $('.BawlH2SectionsContainer')[0] ) {
				Bawl.debug('newsection with section reversal enabled and H2 (but no H1) section found, prepending to:');
				Bawl.debug($('.BawlH2SectionsContainer')[0]);
				$('.BawlH2SectionsContainer')[0].prepend(Bawl.bawlFormHTML);
			} else {
				Bawl.debug('newsection, appending to #mw-content-text');
				$('#mw-content-text').append(Bawl.bawlFormHTML);
			}
		}
		if ( Bawl.UITextInput && Bawl.UITextInput.getValue() != '' ) {
			Bawl.debug('form was opened previously, reload last input');
			Bawl.preloadText = Bawl.UITextInput.getValue();
		} else if ( replyLinkParams.origReplyTo != 'NO-VALUE-PLEASE-IGNORE' && Bawl.settings.autoPing && replyLinkParams.type == "comment" && replyLinkParams.origReplyTo != Bawl.userName && !( replyLinkParams.origReplyTo == mw.config.get('wgTitle') && mw.config.get('wgNamespaceNumber') == 3 ) ) { //don't ping yourself and don't ping the recipient on their own talk page
			Bawl.debug('preloading auto-mention');
			Bawl.preloadText = Bawl.createPingText(replyLinkParams,'preload');
		} else {
			Bawl.debug('skipping auto-mention');
			Bawl.preloadText = '';
		}
		if ( Bawl.UITextInputTitle ) { Bawl.preloadTitle = Bawl.UITextInputTitle.getValue(); } else { Bawl.preloadTitle = ''; }
		if ( Bawl.settings.limitWidth == false ) {
			Bawl.BawlUITextInputTitleClass = 'BawlNoMaxWidth';
		} else {
			Bawl.BawlUITextInputTitleClass = '';
		}
		Bawl.UITextInputTitle = new OO.ui.TextInputWidget( {
			id: 'BawlUITextInputTitle',
			classes: [ 'BawlMarginHalfEm',Bawl.BawlUITextInputTitleClass ],
			value: Bawl.preloadTitle,
			placeholder: Bawl.basicmsgs.subject,
		} );
		if ( replyLinkParams.type == 'editFullPage' ) {
			Bawl.UITextInputRows = 25;
		} else if ( ['heading','newsection'].includes(replyLinkParams.type) ) {
			Bawl.UITextInputRows = 15;
		} else {
			Bawl.UITextInputRows = 6;
		}
		Bawl.UITextInput = new OO.ui.MultilineTextInputWidget( {
			id: 'BawlUITextInput',
			name: 'wpTextbox1', // Go ask codeEditor for reason.
			rows: Bawl.UITextInputRows,
			classes: [ 'BawlMarginHalfEm', 'BawlUnsetLimitWidth' ],
			spellcheck: ( mw.config.get('wgPageContentModel') == 'wikitext' ),
			value: Bawl.preloadText,
		} );
		Bawl.UIVisual = document.createElement('div');
		if ( Bawl.settings.debug == false ) {//Bawl.debug
			Bawl.UIVisual.className = 'BawlNoDisplay';
		}//Bawl.debug
		if ( (Bawl.activeEditor == 'visualLight' || Bawl.settings.editorSwitch) && ( replyLinkParams.type != 'editFullPage' && !( replyLinkParams.type == 'heading' && replyLinkParams.subtype == 'edit' ) ) ) {
			Bawl.initVisualLight();
		}
		if ( Bawl.settings.editor == 'visualLight' ) {
			Bawl.UITextInput.toggle(false);
		}
		if ( Bawl.settings.editor == 'visualLight' && Bawl.settings.debug ) {Bawl.UIVisual.style = 'background:#FBFFFF';Bawl.UITextInput.toggle(true);}//Bawl.debug
		Bawl.checkIfLivePreviewShouldBeRendered = function(oldTextInputValue) {
			if ( oldTextInputValue == Bawl.UITextInput.getValue() ) {
				Bawl.debug('input unchanged, skipping preview');
			} else if ( Bawl.activeEditor == 'visualLight' ) {
				Bawl.debug('VisualLight is active, skip live preview as this combination causes too many problems (mostly focusnode reset and removal of newlines at the end of the text');
			} else {
				Bawl.debug('input has changed, render preview');
				Bawl.doPreview('livepreview',replyLinkParams);
			}
			Bawl.oldTextInputValue = Bawl.UITextInput.getValue();
			Bawl.livePreviewInterval = 1000;
			if ( Bawl.settings.offlinepreview ) {
				Bawl.livePreviewInterval = 100;
			}
			var DelayedPreview = setInterval(function () { // only parse preview once a second
				clearInterval(DelayedPreview);
				if ( Bawl.UIReplyButton.isElementAttached() ) {
					Bawl.checkIfLivePreviewShouldBeRendered(Bawl.oldTextInputValue);
				}
			}, Bawl.livePreviewInterval);
		};
		if ( Bawl.settings.livePreview ) {
			Bawl.checkIfLivePreviewShouldBeRendered();
		}
		if ( Bawl.settings.saveDraft && replyLinkParams.type != 'edit' ) {
			Bawl.saveDraftEvery();
		}
		Bawl.buttonOnTheWrongSideClass = '';
		if ( Bawl.settings.wrongUI ) {
			Bawl.buttonOnTheWrongSideClass = 'BawlFloatRight';
		}
		if ( ! Bawl.userName ) {
			$(document.getElementById('bawlForm-' + Bawl.escapeHTML(replyLinkParams.id))).append('<div class="BawlWarning">' + Bawl.basicmsgs.anoneditwarning + '</div>');
		}
		if ( ( mw.config.get('wgCurRevisionId') != mw.config.get('wgRevisionId') ) && replyLinkParams.type == 'editFullPage' && mw.config.get('wgRevisionId') ) {
			$(document.getElementById('bawlForm-' + Bawl.escapeHTML(replyLinkParams.id))).append('<div class="BawlWarning">' + Bawl.basicmsgs.editingold + '</div>');
		}
		Bawl.UIReplyButton = new OO.ui.ButtonWidget( {
			id: 'BawlUIReplyButton',
			label: Bawl.basicmsgs['htmlform-submit'],
			flags: [ 'primary', 'progressive' ],
			classes: [ Bawl.buttonOnTheWrongSideClass ]
		} );
		Bawl.UIReplyButton.on('click', function() { Bawl.postReply1(replyLinkParams,'button'); });
		Bawl.UIDryRunButton = new OO.ui.ButtonWidget( {
			id: 'BawlUIDryRunButton',
			label: 'Dry run',
			flags: [ 'primary', 'destructive' ],
			classes: [ Bawl.buttonOnTheWrongSideClass ]
		} );
		Bawl.UIDryRunButton.on('click', function() { Bawl.dryRunOnce = true;Bawl.postReply1(replyLinkParams,'dryrunbutton'); });
		Bawl.UIPreviewButton = new OO.ui.ButtonWidget( {
			id: 'BawlUIPreviewButton',
			label: Bawl.basicmsgs.preview,
			flags: [ 'primary' ],
			classes: [ Bawl.buttonOnTheWrongSideClass ]
		} );
		Bawl.UIPreviewButton.on('click', function() { Bawl.doPreview('preview',replyLinkParams); });
		Bawl.UIDiffButton = new OO.ui.ButtonWidget( {
			id: 'BawlUIDiffButton',
			label: Bawl.basicmsgs.showdiff,
			flags: [ 'primary' ],
			classes: [ Bawl.buttonOnTheWrongSideClass ]
		} );
		Bawl.UIDiffButton.on('click', function() { Bawl.doDiff(replyLinkParams); });
		Bawl.UIDiffButton.toggle(false);
		Bawl.UICancelButton = new OO.ui.ButtonWidget( {
			id: 'BawlUICancelButton',
			label: Bawl.basicmsgs.cancel,
			classes: [ Bawl.buttonOnTheWrongSideClass ]
		} );
		Bawl.UIdiffSize = new OO.ui.LabelWidget( {
		} );
		Bawl.UISettingsButtonIcon = new OO.ui.HtmlSnippet(Bawl.svgBawlIconSettings);
		Bawl.UISettingsButton = new OO.ui.ButtonWidget( {
			id: 'BawlUISettingsButton',
			label: Bawl.UISettingsButtonIcon,
			classes: ['BawlFloatRight','mw-no-invert'],
			framed: false,
		} );
		if ( Bawl.activeEditor == 'visualLight' ) {
			Bawl.switchEditorClass = 'BawlHalfOpacity';
		} else {
			Bawl.switchEditorClass = '';
		}
		Bawl.UISwitchEditorButton = new OO.ui.ButtonWidget( {
			id: 'BawlUISwitchEditorButton',
			label: '</>',
			framed: false,
			classes: ['BawlLeftRightMargin','BawlEditorSwitch','BawlFloatRight',Bawl.switchEditorClass]
		} );
		Bawl.UISwitchEditorButton.on('click', function() { Bawl.toggleEditor(); } );
		if ( Bawl.settings.editorSwitch == false ) {
			Bawl.UISwitchEditorButton.toggle(false);
		}
		Bawl.UICancelButton.on('click', function() { Bawl.cancelReply('user'); } );
		Bawl.UIMarkupBoldButton = new OO.ui.ButtonWidget( {
			id: 'BawlUIMarkupBoldButton',
			label: Bawl.basicmsgs.bold,
			framed: false,
			classes: ['BawlLeftRightMargin', 'BawlMarkupBold']
		} );
		Bawl.UIMarkupItalicButton = new OO.ui.ButtonWidget( {
			id: 'BawlUIMarkupItalicButton',
			label: Bawl.basicmsgs.italic,
			framed: false,
			classes: ['BawlLeftRightMargin', 'BawlMarkupItalic']
		} );
		Bawl.UIMarkupStrikeButton = new OO.ui.ButtonWidget( {
			id: 'BawlUIMarkupStrikeButton',
			label: new OO.ui.HtmlSnippet('<span style="text-decoration:line-through;font-size:large;font-weight: normal">' + Bawl.basicmsgs.strike + '</span>'),
			framed: false,
			classes: ['BawlLeftRightMargin', 'BawlMarkupStrike']
		} );
		Bawl.UIMarkupLinkButtonIcon = new OO.ui.HtmlSnippet(Bawl.svgBawlIconLinkBlack);
		Bawl.UIMarkupLinkButton = new OO.ui.ButtonWidget( {
			id: 'BawlUIMarkupLinkButton',
			label: Bawl.UIMarkupLinkButtonIcon,
			framed: false,
			classes: ['BawlLeftRightMargin','mw-no-invert']
		} );
		Bawl.UIoneTimeToolsButton = new OO.ui.ButtonWidget( {
			label: new OO.ui.HtmlSnippet(Bawl.svgMagnifier),
			framed: false,
			classes: ['BawlLeftRightMargin','BawlFloatRight','mw-no-invert']
		} );
		Bawl.UIMarkupBoldButton.on('click', function() { Bawl.insertMarkup('bold','','','',Bawl.focusNode,Bawl.focusOffset,Bawl.anchorNode,Bawl.anchorOffset); } );
		Bawl.UIMarkupItalicButton.on('click', function() { Bawl.insertMarkup('italic','','','',Bawl.focusNode,Bawl.focusOffset,Bawl.anchorNode,Bawl.anchorOffset); } );
		Bawl.UIMarkupStrikeButton.on('click', function() { Bawl.insertMarkup('struck','','','',Bawl.focusNode,Bawl.focusOffset,Bawl.anchorNode,Bawl.anchorOffset); } );
		Bawl.UIMarkupLinkButton.on('click', function() { Bawl.insertLink(Bawl.focusNode, Bawl.focusOffset, Bawl.anchorNode, Bawl.anchorOffset); } );
		Bawl.UIoneTimeToolsButton.on('click', function() { Bawl.oneTimeToolsOpen(); } );
		if ( ! Bawl.settings.onetimetools ) {
			Bawl.UIoneTimeToolsButton.toggle(false);
		}
		if ( Bawl.settings.markup ) {
			Bawl.MarkupButtonBar = new OO.ui.HorizontalLayout( {
				items: [
					Bawl.UIMarkupBoldButton,
					Bawl.UIMarkupItalicButton,
					Bawl.UIMarkupStrikeButton,
					Bawl.UIMarkupLinkButton,
				],
				id: 'BawlMarkupButtonBar',
				classes: ['BawlLeftRightMargin']
			} );
		} else {
			Bawl.MarkupButtonBar = new OO.ui.HorizontalLayout( {} );
		}
		if ( Bawl.settings.pingDropDownAt ) {
			Bawl.showPingDropDown = function() {
				if ( $('#BawlcITSbuttonMenu')[0] && ( Bawl.activeEditor == 'source' && Bawl.UITextInput.getValue().slice(Bawl.UITextInput.getRange().to -1,Bawl.UITextInput.getRange().to) == '@' ) || ( Bawl.activeEditor == 'visualLight' && typeof Bawl.focusNode != 'undefined' && typeof Bawl.focusNode.data == 'string' && (Bawl.focusNode.data.length -1) == Bawl.focusOffset && Bawl.focusNode.data.slice(-1) == '@' ) || ( Bawl.activeEditor == 'visualLight' && typeof Bawl.focusNode != 'undefined' && typeof Bawl.focusNode.innerText == 'string' && (Bawl.focusNode.innerText.length - Bawl.focusOffset) < 3 && Bawl.focusNode.innerText.slice(-2).match('@') ) ) {
					Bawl.cITSbuttonMenu.toggle(true);
					Bawl.cITSbuttonMenu.getMenu().toggle(true);
					Bawl.cITSbuttonMenu.focus();
				} else if ( $('#BawlcITSbuttonMenu')[0] ) {
					Bawl.cITSbuttonMenu.getMenu().toggle(false);
					if ( ! Bawl.settings.pingDropDown && Bawl.cITSbuttonMenu.isVisible() == true ) {
						Bawl.cITSbuttonMenu.toggle(false);
					}
				}
			};
			Bawl.UITextInput.on('change', function() { Bawl.showPingDropDown(); });
		}
		Bawl.replyFormElements = [];
		if ( Bawl.settings.pingDropDown || Bawl.settings.pingDropDownAt ) {
			Bawl.debug('add ping dropdown');
			Bawl.commentersInThisSection = Bawl.commentersInSectionBySection[Bawl.replyLinkParamsOpened.pageTitleInt];
			Bawl.cITSmenuItemsObj = {};
			Bawl.cITSmenuItems = [];
			if ( typeof Bawl.commentersInThisSection != 'undefined' ) {
				for (Bawl.cITSint = 0; Bawl.cITSint < Bawl.commentersInThisSection.length; Bawl.cITSint++) {
					Bawl.cITSmenuItemsObj[Bawl.cITSint] = new OO.ui.MenuOptionWidget( { data:Bawl.commentersInThisSection[Bawl.cITSint],label:Bawl.commentersInThisSection[Bawl.cITSint] } );
					Bawl.cITSmenuItems.push(Bawl.cITSmenuItemsObj[Bawl.cITSint]);
				}
				delete Bawl.cITSint;
				if ( Bawl.cITSmenuItems.length > 0 ) {
					Bawl.cITSbuttonMenu = new OO.ui.ButtonMenuSelectWidget( {
						id:'BawlcITSbuttonMenu',
						menu: { items: Bawl.cITSmenuItems },
						label: Bawl.msgs.cITSbuttonMenu,
					});
					Bawl.replyFormElements.push(Bawl.cITSbuttonMenu);
					Bawl.cITSbuttonMenu.getMenu().on( 'choose', function ( menuOption ) {
						Bawl.debug( menuOption.getData() );
						Bawl.insertMarkup('PingDropDown',Bawl.settings.pingText.replace(/PINGUSER/g, Bawl.escapeReplacement(menuOption.getData().replace(/_/g,' '))),Bawl.focusNode,Bawl.focusOffset,Bawl.anchorNode,Bawl.anchorOffset);
					} );
					if ( ! Bawl.settings.pingDropDown ) {
						Bawl.cITSbuttonMenu.toggle(false);
					}
				}
			}
		}
		if ( Bawl.settings.wrongUI == false ) {
			Bawl.ButtonBarItems = [
					Bawl.UIReplyButton,
					Bawl.UIPreviewButton,
					Bawl.UICancelButton,
					Bawl.UIDiffButton,
					Bawl.UIdiffSize,
					Bawl.UIDryRunButton,
					Bawl.MarkupButtonBar,
					Bawl.UISettingsButton,
					Bawl.UISwitchEditorButton,
					Bawl.UIoneTimeToolsButton
				];
		} else {
			Bawl.ButtonBarItems = [
					Bawl.UIReplyButton,
					Bawl.UIPreviewButton,
					Bawl.UICancelButton,
					Bawl.UIDiffButton,
					Bawl.UIDryRunButton,
					Bawl.UISettingsButton,
					Bawl.UISwitchEditorButton,
					Bawl.UIoneTimeToolsButton,
					Bawl.MarkupButtonBar,
				];
		}
		if ( Bawl.settings.debug != true ) {Bawl.UIDryRunButton.toggle(false);}//Bawl.debug
		if ( mw.config.get('wgCurRevisionId') && (replyLinkParams.type == 'editFullPage' || replyLinkParams.type == 'edit' || (replyLinkParams.type == 'heading' && replyLinkParams.subtype == 'edit') ) ) {
			Bawl.UIDiffButton.toggle(true);
		}
		Bawl.ButtonBar = new OO.ui.HorizontalLayout( {
			items: Bawl.ButtonBarItems,
			id: 'BawlMainButtonBar',
		} );
		Bawl.editNoticeAndCIAutoPostDiv = '<div id="BawlEditNotice" class="BawlNoDisplay BawlForm BawlEditNoticeDiv"></div><div id="BawlCustomInsertsAutoPost" class="BawlMarginHalfEm BawlNoDisplay"></div>';
		Bawl.summaryMaxLengthSectionTitle = 0;
		if ( replyLinkParams.sectionTitle ) {
			Bawl.summaryMaxLengthSectionTitle = replyLinkParams.sectionTitle.length + 6;
		}
		Bawl.summaryMaxLength = 500 - Bawl.wikiMsgs.summaryCredit.length - Bawl.summaryMaxLengthSectionTitle - 200;//on Wikimedia up to 500 seems to be allowed. The 200 is for stuff that's difficult to predict at this point like RETF, sumsnippet but also the templated summaries. It might not always be enough still.
		Bawl.UITextInputSummary = new OO.ui.TextInputWidget( {
			id: 'BawlUITextInputSummary',
			classes: [ 'BawlMarginHalfEm',Bawl.BawlUITextInputTitleClass ],
			value: '',
			maxLength:Bawl.summaryMaxLength,
			placeholder: Bawl.basicmsgs['tooltip-summary'],
		} );
		Bawl.UIMinorCheck = new OO.ui.CheckboxInputWidget( {
			title:Bawl.basicmsgs['tooltip-minoredit']
		} );
		Bawl.UITextInputSummaryMinorLabel = new OO.ui.LabelWidget( {
			label: new OO.ui.HtmlSnippet('<b>' + Bawl.basicmsgs.minoreditletter + '</b>'),
			title:Bawl.basicmsgs['tooltip-minoredit']
		} );
		Bawl.UITextInputSummaryMinorLayout = new OO.ui.HorizontalLayout( {
			items: [
				Bawl.UITextInputSummary,
				Bawl.UIMinorCheck,
				Bawl.UITextInputSummaryMinorLabel
			],
			classes:['BawlFlexLayout']
		} );
		Bawl.UIVisualElement = new OO.ui.FormLayout( {
			id:'BawlUIVisualContainer',
		} );
		Bawl.replyFormElements.push(Bawl.UITextInputTitle,Bawl.UITextInput,Bawl.UIVisualElement);
		if ( Bawl.settings.customSummary || replyLinkParams.type == 'editFullPage' || ( replyLinkParams.type == 'heading' && replyLinkParams.subtype == 'edit' ) ) {
			Bawl.replyFormElements.push(Bawl.UITextInputSummaryMinorLayout);
		}
		Bawl.replyFormElements.push(Bawl.ButtonBar);
		Bawl.ReplyForm = new OO.ui.FormLayout( {
			items: Bawl.replyFormElements,
			id: 'BawlReplyForm',
			classes: ['BawlReplyForm'],
		} );
		$(document.getElementById('bawlForm-' + replyLinkParams.id)).removeClass('BawlNoDisplay');
		$(document.getElementById('bawlForm-' + replyLinkParams.id)).append(Bawl.editNoticeAndCIAutoPostDiv).append(Bawl.ReplyForm.$element);
		Bawl.setCustomBackground();
		$('#BawlUIVisualContainer').prepend(Bawl.UIVisual);
		if ( Bawl.settings.shortcuts ) {
			$('#BawlUITextInput').keydown(function(event){
				Bawl.fullPageOrSectionEdit = ( Bawl.replyLinkParamsOpened.type == 'editFullPage' || ( Bawl.replyLinkParamsOpened.type == 'heading' && Bawl.replyLinkParamsOpened.subtype == 'edit') );
				if ( event.which == 16 ) {//pressed shift
					event.preventDefault();
					Bawl.pressedShift = true;
				} else if ( event.which == 17 ) {//pressed control
					event.preventDefault();
					Bawl.pressedControl = true;
				} else if ( event.which == 18 ) {//pressed alt
					event.preventDefault();
					Bawl.pressedAlt = true;
				} else if ( event.which == 27 ) {//pressed escape
					event.preventDefault();
					Bawl.cancelReply();
				} else if ( Bawl.pressedControl && Bawl.pressedAlt && event.which == 77 ) {//pressed escape
					event.preventDefault();
					if ( $('#BawlUITextInput').hasClass('BawlMonoSpace') ) {
						$('#BawlUITextInput').removeClass('BawlMonoSpace mw-editfont-monospace');
					} else {
						$('#BawlUITextInput').addClass('BawlMonoSpace mw-editfont-monospace');
					}
				} else if ( ! Bawl.UIReplyButton.isDisabled() && ( Bawl.pressedControl && Bawl.pressedShift && event.which == 13 && Bawl.settings.submitShortcut ) ) {//pressed ctrl+shift+enter
					event.preventDefault();
					if ( ! Bawl.UIMinorCheck.isElementAttached() ) {
						Bawl.summaryAndMinorDiv = document.createElement('div');
						Bawl.summaryAndMinorDiv.id = 'summaryAndMinorDiv';
						$('#BawlMainButtonBar')[0].parentElement.insertBefore(Bawl.summaryAndMinorDiv,$('#BawlMainButtonBar')[0]);
						$('#summaryAndMinorDiv').append(Bawl.UITextInputSummaryMinorLayout.$element);
					}
					Bawl.UIMinorCheck.setSelected(true);
					Bawl.postReply1(replyLinkParams,'button');
				} else if ( ! Bawl.UIReplyButton.isDisabled() && ( ( Bawl.pressedControl && event.which == 13 && Bawl.settings.submitShortcut ) || ( Bawl.pressedAlt && Bawl.pressedShift && event.which == 83 ) ) ) {//pressed enter or alt+shift+s
					event.preventDefault();
					Bawl.postReply1(replyLinkParams,'button');
				} else if ( Bawl.pressedControl && event.which == 75 ) {//pressed k. what follows are keyboard shortcuts that also exist in VE
					event.preventDefault();
					Bawl.insertLink(Bawl.focusNode, Bawl.focusOffset, Bawl.anchorNode, Bawl.anchorOffset);
				} else if ( Bawl.pressedControl && event.which == 66 ) {//pressed b
					event.preventDefault();
					Bawl.insertMarkup('bold','','','',Bawl.focusNode,Bawl.focusOffset,Bawl.anchorNode,Bawl.anchorOffset);
				} else if ( Bawl.pressedControl && event.which == 73 ) {//pressed i
					event.preventDefault();
					Bawl.insertMarkup('italic','','','',Bawl.focusNode,Bawl.focusOffset,Bawl.anchorNode,Bawl.anchorOffset);
				} else if ( Bawl.pressedControl && event.which == 49 && Bawl.fullPageOrSectionEdit ) {//pressed 1
					event.preventDefault();
					Bawl.insertMarkup('h1','','','',Bawl.focusNode,Bawl.focusOffset,Bawl.anchorNode,Bawl.anchorOffset);
				} else if ( Bawl.pressedControl && event.which == 50 && Bawl.fullPageOrSectionEdit ) {//pressed 2
					event.preventDefault();
					Bawl.insertMarkup('h2','','','',Bawl.focusNode,Bawl.focusOffset,Bawl.anchorNode,Bawl.anchorOffset);
				} else if ( Bawl.pressedControl && event.which == 51 && Bawl.fullPageOrSectionEdit ) {//pressed 3
					event.preventDefault();
					Bawl.insertMarkup('h3','','','',Bawl.focusNode,Bawl.focusOffset,Bawl.anchorNode,Bawl.anchorOffset);
				} else if ( Bawl.pressedControl && event.which == 52 && Bawl.fullPageOrSectionEdit ) {//pressed 4
					event.preventDefault();
					Bawl.insertMarkup('h4','','','',Bawl.focusNode,Bawl.focusOffset,Bawl.anchorNode,Bawl.anchorOffset);
				} else if ( Bawl.pressedControl && event.which == 53 && Bawl.fullPageOrSectionEdit ) {//pressed 5
					event.preventDefault();
					Bawl.insertMarkup('h5','','','',Bawl.focusNode,Bawl.focusOffset,Bawl.anchorNode,Bawl.anchorOffset);
				} else if ( Bawl.pressedControl && event.which == 54 && Bawl.fullPageOrSectionEdit ) {//pressed 6
					event.preventDefault();
					Bawl.insertMarkup('h6','','','',Bawl.focusNode,Bawl.focusOffset,Bawl.anchorNode,Bawl.anchorOffset);
				} else if ( Bawl.pressedControl && event.which == 56 ) {//pressed 8
					event.preventDefault();
					Bawl.insertMarkup('blockquote','','','',Bawl.focusNode,Bawl.focusOffset,Bawl.anchorNode,Bawl.anchorOffset);
				} else if ( Bawl.pressedAlt && Bawl.pressedShift && event.which == 86 && Bawl.fullPageOrSectionEdit ) {//pressed v
					event.preventDefault();
					Bawl.doDiff(Bawl.replyLinkParamsOpened);
				} else if ( Bawl.pressedAlt && Bawl.pressedShift && event.which == 73 ) {//pressed i
					if ( ! Bawl.UIMinorCheck.isElementAttached() ) {
						Bawl.summaryAndMinorDiv = document.createElement('div');
						Bawl.summaryAndMinorDiv.id = 'summaryAndMinorDiv';
						$('#BawlMainButtonBar')[0].parentElement.insertBefore(Bawl.summaryAndMinorDiv,$('#BawlMainButtonBar')[0]);
						$('#summaryAndMinorDiv').append(Bawl.UITextInputSummaryMinorLayout.$element);
					}
					Bawl.UIMinorCheck.setSelected(!Bawl.UIMinorCheck.isSelected());
				} else if ( Bawl.pressedControl && Bawl.pressedShift && event.which == 53 ) {//pressed 5
					event.preventDefault();
					Bawl.insertMarkup('struck','','','',Bawl.focusNode,Bawl.focusOffset,Bawl.anchorNode,Bawl.anchorOffset);
				} else if ( Bawl.pressedControl && Bawl.pressedShift && event.which == 54 ) {//pressed 6
					event.preventDefault();
					Bawl.insertMarkup('code','','','',Bawl.focusNode,Bawl.focusOffset,Bawl.anchorNode,Bawl.anchorOffset);
				} else if ( Bawl.pressedControl && event.which == 85 ) {//pressed u
					event.preventDefault();
					Bawl.insertMarkup('underline','','','',Bawl.focusNode,Bawl.focusOffset,Bawl.anchorNode,Bawl.anchorOffset);
				} else if ( Bawl.pressedControl && event.which == 188 ) {//pressed ,
					event.preventDefault();
					Bawl.insertMarkup('subscript','','','',Bawl.focusNode,Bawl.focusOffset,Bawl.anchorNode,Bawl.anchorOffset);
				} else if ( Bawl.pressedControl && event.which == 190 ) {//pressed .
					event.preventDefault();
					Bawl.insertMarkup('superscript','','','',Bawl.focusNode,Bawl.focusOffset,Bawl.anchorNode,Bawl.anchorOffset);
				}
			});
			$('#BawlUITextInput').keyup(function(event){
				Bawl.pressedShift = false;
				Bawl.pressedControl = false;
				Bawl.pressedAlt = false;
			});
		}
		if (['javascript','css','json'].includes(mw.config.get('wgPageContentModel')) || Bawl.settings.monospace){
			$('#BawlUITextInput').addClass('BawlMonoSpace mw-editfont-monospace');
		}
		if ( Bawl.replyFormElements.indexOf(Bawl.UITextInputSummaryMinorLayout) != -1 ) {
			Bawl.editSummaryPipeTrick();
			Bawl.UITextInputSummary.on('enter', function() { Bawl.UITextInputSummary.blur();Bawl.postReply1(replyLinkParams,'summarybutton'); });
		}
		if ( Bawl.settings.bracketToForm ) {
			Bawl.UITextInput.on('change',function(){Bawl.checkLinkSwitch();});
		}
		if ( Bawl.settings.rewriteOnBlur && mw.config.get('wgPageContentModel') == 'wikitext' ) {
			$('#BawlUITextInput textarea').on('blur', function(){
				Bawl.debug('main input lost focus, applying rewritun and regular expressions');
				Bawl.textUpdatedOnBlur = Bawl.UITextInput.getValue();
				Bawl.textUpdatedOnBlur = Bawl.safeText(Bawl.textUpdatedOnBlur,'rewritun');
				Bawl.textUpdatedOnBlur = Bawl.safeText(Bawl.textUpdatedOnBlur,'unsafe');
				if ( Bawl.settings.enableCIThatRun || Bawl.settings.enableCIThatRunCmt ) {
					Bawl.runCI(Bawl.textUpdatedOnBlur);
				}
			});
		}
		if ( window.localStorage.BawlDrafts && Bawl.testValidJSON(window.localStorage.BawlDrafts) ) {
			Bawl.loadedDrafts = JSON.parse(window.localStorage.BawlDrafts);
		}
		if ( ! Bawl.reloaded && replyLinkParams.type != 'edit' && Bawl.settings.saveDraft && Bawl.loadedDrafts && Bawl.loadedDrafts[encodeURIComponent(replyLinkParams.id)] && Bawl.loadedDrafts[encodeURIComponent(replyLinkParams.id)].time > (new Date().getTime() - 604800000) ) {
			Bawl.debug('load draft from localStorage');
			Bawl.UITextInput.setValue(Bawl.loadedDrafts[encodeURIComponent(replyLinkParams.id)].text);
			mw.notify(Bawl.msgs.restoredDraft);
		} else if ( ( mw.config.get('wgRevisionId') || mw.config.get('wgCurRevisionId') ) && ! Bawl.reloaded && ( replyLinkParams.type == 'edit' || replyLinkParams.type == 'editFullPage' || ( replyLinkParams.type == 'heading' && replyLinkParams.subtype == 'edit' ) ) ) {
			Bawl.debug('preload comment or section or full page to edit');
			replyLinkParams = Bawl.addPageAndSectionTitleToRPL(replyLinkParams);
			Bawl.disableForm(true); //disable form until preload is done
			Bawl.UIReplyButton.setLabel(Bawl.basicmsgs['htmlform-submit']);
			Bawl.getWikiTextParams = {action: 'query', prop: 'revisions', format: 'json', rvprop:'content',rvslots:'*'};
			if ( replyLinkParams.type == 'editFullPage' ) {
				if ( mw.config.get('wgRevisionId') ) {
					Bawl.getWikiTextParams.revids = mw.config.get('wgRevisionId');//editing an old revision
				} else if ( mw.config.get('wgCurRevisionId') ) {
					Bawl.getWikiTextParams.revids = mw.config.get('wgCurRevisionId');
				}
			} else {
				Bawl.getWikiTextParams.titles = replyLinkParams.pageTitle;
			}
			api.get( Bawl.getWikiTextParams ).then( function ( data ) {
				Bawl.debug(data);
				Bawl.wikiTextForEdit = data.query.pages[Object.keys(data.query.pages)[0]].revisions[0].slots.main['*'];
				if ( replyLinkParams.type == 'editFullPage' ) {
					Bawl.UITextInput.setValue(Bawl.wikiTextForEdit);
					Bawl.disableForm(false);
					Bawl.focusInput('start');
					Bawl.openingFormInProgress = new Date().getTime();
					return;
				}
				if ( replyLinkParams.type == 'heading' && replyLinkParams.subtype == 'edit' ) {
					Bawl.debug('preload section wikitext');
					Bawl.sectionTextForPreload = Bawl.getInsertionPointSection(Bawl.replyLinkParamsOpened, Bawl.wikiTextForEdit).sectiontext;
					if ( Bawl.sectionTextForPreload == null ) {
						Bawl.debug('section not found, try preloading text by section number instead'); //this happens on sections like "== ((int:license-header)) ==" as they don't contain the innerText "Licensing". You might be wondering why not always do this? Because section numbers are not permanent, if sections are added/removed after you loaded the page (hello ArchiverBot!), they break. This is very much a MediaWiki problem and Bawl works around it by determining the sectionnum from wikitext.
						Bawl.sectionNumFromLink = Number(Bawl.processElementArray[Bawl.replyLinkParamsOpened.int].querySelectorAll('A')[0].href.match(/section=(T\-)?([0-9]*)/)[2]);
						Bawl.sectionTextForPreload = Bawl.getSectionByNum(Bawl.wikiTextForEdit,Bawl.sectionNumFromLink);
					}
					Bawl.UITextInput.setValue(Bawl.sectionTextForPreload);
					Bawl.disableForm(false);
					Bawl.focusInput('start');
					Bawl.openingFormInProgress = new Date().getTime();
					return;
				}
				Bawl.debug('preloading existing comment');
				Bawl.endOfCommentLocatorRegExp = new RegExp(' *<span id="[^"]*" class="BawlCmt".*');
				Bawl.restoreNewlineRegExp = new RegExp(Bawl.escapeRegExp('<br/>'), 'g');
				Bawl.restoreDoubleNewlineRegExp = new RegExp(Bawl.escapeRegExp('<br style="margin-bottom:0.5em"/>'), 'g');
				Bawl.wikiTextForEditComment = Bawl.getInsertionPointComment(replyLinkParams, Bawl.wikiTextForEdit).relevantComment.replace(/^[\*\:\# ]*/, '');
				Bawl.wikiTextForEditSigForPreview = Bawl.wikiTextForEditComment.match(Bawl.endOfCommentLocatorRegExp);
				if ( Bawl.wikiTextForEditSigForPreview ) {
					Bawl.wikiTextForEditSigForPreview = Bawl.wikiTextForEditComment.match(Bawl.endOfCommentLocatorRegExp)[0];
				} else {
					Bawl.wikiTextForEditSigForPreview = '';
				}
				Bawl.wikiTextForEditCommentStripped = Bawl.wikiTextForEditComment.replace(Bawl.endOfCommentLocatorRegExp, '');
				Bawl.wikiTextForEditCommentMultiline = Bawl.wikiTextForEditCommentStripped.replace( Bawl.restoreNewlineRegExp, '\n' ).replace(Bawl.restoreDoubleNewlineRegExp,'\n\n');
				Bawl.wikiTextForEditCommentMultilineRawList = Bawl.listToRaw(Bawl.wikiTextForEditCommentMultiline);
				Bawl.wikiTextForEditSTLOld = '';
				Bawl.wikiTextForEditSTLNew = Bawl.wikiTextForEditCommentMultilineRawList;
				//todo: this regex CAN BECOME A RUNAWAY REGEX. (it did when it was applied to whole sections) It needs to be improved/replaced. (https://en.wikipedia.org/w/index.php?title=Wikipedia:Village_pump_(technical)&oldid=1090343769#How_to_give_labels_to_specific_objects_in_template?)
				Bawl.RETFEscapeMatchedTEMPLATERegExp = new RegExp('\\{\\{(([^\\{\\}]|\\{[^\\{]|\\}[^\\}]|\\{\\{(([^\\{\\}]|\\{[^\\{|\\}[^\\}])*)\\}\\}|\\{\\{(([^\\{\\}]|\\{[^\\{|\\}[^\\}]|\\{\\{(([^\\{\\}]|\\{[^\\{|\\}[^\\}])*)\\}\\})*)\\}\\})*)\\}\\}','g'); //catches up to two level of nested templates like ((template1|((template2|template3))))))
				Bawl.wikiTextForEditSTLRegExp = new RegExp('(\\{\\{#tag:syntaxhighlight\\|(([^\n\\{\\}]|\\}[^\\}]|' + Bawl.RETFEscapeMatchedTEMPLATERegExp.source + ')*))\\{\\{' + Bawl.basicmsgs.newline + '\\}\\}','g');
				while ( Bawl.wikiTextForEditSTLOld != Bawl.wikiTextForEditSTLNew ) {
					Bawl.wikiTextForEditSTLOld = Bawl.wikiTextForEditSTLNew;
					Bawl.wikiTextForEditSTLNew = Bawl.wikiTextForEditSTLNew.replace(Bawl.wikiTextForEditSTLRegExp,'$1\n');
				}
				Bawl.wikiTextForEditSTLTagRegExp = new RegExp('(\\{\\{#tag:syntaxhighlight\\|(([^\\{\\}\\|]|\\}[^\\}]|' + Bawl.RETFEscapeMatchedTEMPLATERegExp.source + ')*))(\\|[^\\}\n\\\\|]+)?(\\|[^\\}\n\\\\|]+)?(\\|[^\\}\n\\\\|]+)?(\\|[^\\}\n\\\\|]+)?\\}\\}','g');
				Bawl.wikiTextForEditSTLNew = Bawl.wikiTextForEditSTLNew.replace(Bawl.wikiTextForEditSTLTagRegExp,'<syntaxhighlight $12 $13 $14 $15>\n$2</syntaxhighlight>');
				for(Bawl.wikiTextForEditSTLSpaceCleanInt=0;Bawl.wikiTextForEditSTLSpaceCleanInt<4;Bawl.wikiTextForEditSTLSpaceCleanInt++){
					Bawl.wikiTextForEditSTLNew = Bawl.wikiTextForEditSTLNew.replace(/(<syntaxhighlight)([ ]?\|)/g,'$1 ').replace(/(<syntaxhighlight)([^>\|\n]*[ ]?\|)/g,'$1 ').replace(/(<syntaxhighlight)([^>\|\n]*[ ]?\|)/g,'$1 ').replace(/(<syntaxhighlight)([^>\|\n]*[ ]?\|)/g,'$1 ');
				}
				Bawl.wikiTextForEditSTLNew = Bawl.wikiTextForEditSTLNew.replace(/(<syntaxhighlight(([^>\n])*))([^ ])[ ]*>/,'$1$4>').replace(/<syntaxhighlight lang=text[ ]*>[\n]*(([^<]|<(?![\/]?syntaxhighlight>))*)<\/syntaxhighlight>/g,'<pre>\n$1</pre>');
				Bawl.UITextInput.setValue(Bawl.wikiTextForEditSTLNew);
				Bawl.disableForm(false);
				Bawl.debug('edit preload done, focus text input');
				Bawl.focusInput();
			}, function ( code, data ) { Bawl.APIError(code, data);
			});
		} else if ( ! Bawl.reloaded && (replyLinkParams.preload || replyLinkParams.preloadtitle) && Bawl.UITextInput.getValue() == '' && Bawl.UITextInputTitle.getValue() == '' ) { //InputBox/Bawl-comment-link preload
			if ( Bawl.replyLinkParamsnSec.subtype != 'InputBox' ) { //this would happen on section=new pages where no actual InputBox could exist, parameters are extracted from the URL there
				Bawl.debug('get title from InputBox. Wasn\'t known on page load as the user hadn\'t entered it yet');
				for (Bawl.intInputBoxPreload = 0; Bawl.intInputBoxPreload < Bawl.processElementArray[replyLinkParams.int].children.length; Bawl.intInputBoxPreload++) {
					Bawl.debug('process child element #' + Bawl.intInputBoxPreload + '/' + Bawl.processElementArray[replyLinkParams.int].children.length + ' for element #' + Bawl.int);
					if ( Bawl.processElementArray[replyLinkParams.int].children[Bawl.intInputBoxPreload].name == 'preloadtitle' ) {
						replyLinkParams.preloadtitle = Bawl.processElementArray[replyLinkParams.int].children[Bawl.intInputBoxPreload].value;
					}
				}
			}
			if ( replyLinkParams.preloadtitle ) {
				Bawl.debug('preloading title');
				Bawl.UITextInputTitle.setValue(replyLinkParams.preloadtitle);
			}
			if ( replyLinkParams.preload ) {
				Bawl.disableForm(true); //disable form until preload is done
				Bawl.debug('preloading page specified by InputBox');
					api.get( {
						action: 'query', export: 'true', format: 'json', titles: replyLinkParams.preload,
					} ).then( function ( data ) {
						Bawl.debug(data);
						Bawl.wikiTextForEdit = Bawl.getWikitextFromExport(data.query.export["*"]);
						if ( Bawl.testValidJSON(replyLinkParams.preloadparams) ) {
							replyLinkParams.preloadparams = JSON.parse(decodeURIComponent(replyLinkParams.preloadparams).replace(/\&quot\;/g, '"'));
						}
						for (Bawl.intInputBoxPreloadParams = 0; Bawl.intInputBoxPreloadParams < replyLinkParams.preloadparams.length; Bawl.intInputBoxPreloadParams++) {
							Bawl.debug('replacing preloadparam ' + (Bawl.intInputBoxPreloadParams + 1));
							Bawl.replacePreloadVar = new RegExp('\\$' + ( Bawl.intInputBoxPreloadParams + 1) + '([^0-9]|$)', 'g');
							Bawl.wikiTextForEdit = Bawl.wikiTextForEdit.replace(Bawl.replacePreloadVar, replyLinkParams.preloadparams[Bawl.intInputBoxPreloadParams] + '$1');
						}
						Bawl.wikiTextForEdit = Bawl.wikiTextForEdit.replace(/<noinclude>(([^<]|<(?!\/noinclude>))*)<\/noinclude>/g,'').replace(/[\s]*~~~~[\s]*/,'');
						Bawl.UITextInput.setValue(Bawl.wikiTextForEdit);
						Bawl.disableForm(false);
						if ( Bawl.UITextInputTitle.isVisible() == false ) {
							Bawl.debug('loaded requested preload page, focus input field');
							Bawl.focusInput();
						}
					}, function ( code, data ) { Bawl.APIError(code, data);
					});
			}
		}
		delete Bawl.reloaded;
		if ( replyLinkParams.type == 'newsection' ) {
			window.BawlUITextInputTitle.scrollIntoView(Bawl.smoothScroll);
		}
		$('#BawlReplyForm').append(Bawl.tosNagContainer);
		if ( Bawl.settings.tosNag && ! document.getElementById('BawlToSNag') ) {
			Bawl.insertToSnag();
		}
		Bawl.extraDivs = '<div id="BawlCustomInserts" class="BawlCustomInserts BawlMarginHalfEm BawlNoDisplay"></div><div id="onetimetools" class="Bawlonetimetools BawlNoDisplay"></div><div id="showNewLines" class="BawlNewLinesBox BawlNoDisplay"></div><div id="BawlPreviewBox" class="BawlPreviewBox BawlMarginHalfEm BawlNoDisplay"></div><div id="BawlSettings" class="BawlSettings BawlMarginHalfEm BawlNoDisplay"><div id="BawlSettingsTop"></div></div>';
		$(document.getElementById('bawlForm-' + replyLinkParams.id)).append(Bawl.extraDivs);
		if ( ( Bawl.settings.previewAboveFull && (replyLinkParams.type == 'editFullPage' || (replyLinkParams.type == 'heading' && replyLinkParams.type == 'edit') ) ) || ( Bawl.settings.previewAboveOther && replyLinkParams.type != 'editFullPage' && ! (replyLinkParams.type == 'heading' && replyLinkParams.type == 'edit') ) ) {
			$('.BawlForm')[0].insertBefore($('#BawlPreviewBox')[0],$('#BawlReplyForm')[0]);
		}
		Bawl.customInsertButton = {};
		for (Bawl.int = 0; Bawl.int < 50; Bawl.int++) {
			Bawl.debug('process custom inserts');
			if ( Bawl.settings.cI && Bawl.settings.cI[Bawl.int] && Bawl.settings.cI[Bawl.int] != "" ) { //non-empty insert found
				Bawl.debug('adding button for custom insert #' + Bawl.int);
				Bawl.CIbuttonFlags = [];
				if ( decodeURIComponent(Bawl.settings.cI[Bawl.int]).match(/\:<<([^\>]*)\>\>/) ) {
					Bawl.cILabel = decodeURIComponent(Bawl.settings.cI[Bawl.int]).replace(/.*\:<<([^\>]*)\>\>/, '$1');
					if ( ( Bawl.replyLinkParamsOpened.type == 'comment' && Bawl.cILabel.match(/^AUTOPOSTCMT/) ) || ( Bawl.replyLinkParamsOpened.type != 'comment' && Bawl.cILabel.match(/^AUTOPOSTNONCMT/) ) || Bawl.cILabel.match(/^AUTOPOST(?!CMT|NONCMT)/) ) {
						Bawl.debug('found a custom insert with AUTOPOST, triggers postReply1 after insertion');
						Bawl.cILabel = Bawl.cILabel.replace(/^AUTOPOST(CMT|NONCMT)?/,'');
						Bawl.CIbuttonFlags = ['progressive'];
					} else if ( Bawl.cILabel.match(/^AUTOPOST/) ) {
						Bawl.cILabel = '';
					}
				} else if ( decodeURIComponent(Bawl.settings.cI[Bawl.int]).length > 14 ) {
					Bawl.cILabel = decodeURIComponent(Bawl.settings.cI[Bawl.int]).slice(0,10) + '..';
				} else {
					Bawl.cILabel = decodeURIComponent(Bawl.settings.cI[Bawl.int]);
				}
				Bawl.customInsertButton[Bawl.int] = new OO.ui.ButtonWidget( {
					label: Bawl.cILabel,
					classes: [ 'BawlMarginHalfEm' ],
					flags: Bawl.CIbuttonFlags
				});
				if ( Bawl.CIbuttonFlags[0] == 'progressive' && Bawl.cILabel != '' ) {
					$('#BawlCustomInsertsAutoPost').removeClass('BawlNoDisplay');
					$('#BawlCustomInsertsAutoPost').append(Bawl.customInsertButton[Bawl.int].$element);
				} else if ( Bawl.cILabel != '' ) {
					$('#BawlCustomInserts').removeClass('BawlNoDisplay');
					$('#BawlCustomInserts').append(Bawl.customInsertButton[Bawl.int].$element);
				}
			} //end non-empty insert found
		} //end for
		Bawl.insertCustomInsert = function(num) {
			Bawl.debug('insert custom insert #' + num);
			Bawl.activatedCustomInsert = decodeURIComponent(Bawl.settings.cI[num]).replace(/\:<<[^\>]*\>\>$/, '');
			if ( Bawl.activatedCustomInsert.match(Bawl.insertIsRegExpRegExp) ) {
				Bawl.customInsertRegExpNowParts = Bawl.activatedCustomInsert.match(Bawl.insertIsRegExpRegExp);
				Bawl.customInsertRegExpNow = new RegExp(Bawl.customInsertRegExpNowParts[1], Bawl.customInsertRegExpNowParts[3]);
				Bawl.UITextInput.setValue(Bawl.UITextInput.getValue().replace(Bawl.customInsertRegExpNow, Bawl.customInsertRegExpNowParts[2].replace(/\\\//g,'/')));
			} else {
				if ( Bawl.activatedCustomInsert.match('BAWLCRT') ) {
					Bawl.activatedCustomInsertStart = Bawl.activatedCustomInsert.split('BAWLCRT')[0].replace(/[\\]n/g,'\n');
					Bawl.activatedCustomInsertEnd = Bawl.activatedCustomInsert.split('BAWLCRT')[1].replace(/[\\]n/g,'\n');
				} else {
					Bawl.activatedCustomInsertStart = Bawl.activatedCustomInsert.replace(/[\\]n/g,'\n');
					Bawl.activatedCustomInsertEnd = '';
				}
				Bawl.insertMarkup('cI', '', Bawl.activatedCustomInsertStart, Bawl.activatedCustomInsertEnd,Bawl.focusNode,Bawl.focusOffset,Bawl.anchorNode,Bawl.anchorOffset);
			}
			if ( decodeURIComponent(Bawl.settings.cI[num]).match(/\:<<AUTOPOST[^\>]*\>\>$/) ) {
				Bawl.debug('AUTOPOST activated');
				Bawl.postReply1(Bawl.replyLinkParamsOpened,'autopost');
			}
		};
		Bawl.insBtn = function(insNum) {
			Bawl.customInsertButton[insNum].on('click', function() { Bawl.insertCustomInsert(insNum); });
		};
		for (Bawl.CIButtonInt = 0; Bawl.CIButtonInt < 50; Bawl.CIButtonInt++) {
			if ( typeof Bawl.customInsertButton[Bawl.CIButtonInt] == 'object' ) {
				Bawl.insBtn(Bawl.CIButtonInt);
			}
		}
		if ( Bawl.settings.limitWidth ) {
			$('.BawlForm').addClass('BawlLimitWidth');
			Bawl.UIVisual.classList.add('BawlLimitWidth');
			$('BawlUITextInput').removeClass('BawlUnsetLimitWidth');
			$('BawlUITextInput').addClass('BawlLimitWidth');
		}
		if ( replyLinkParams.type == 'comment' || replyLinkParams.type == 'edit' || replyLinkParams.type == 'BCL' || replyLinkParams.type == 'editFullPage' || ( replyLinkParams.type == 'heading' && replyLinkParams.subtype == 'edit' ) ) {
			Bawl.debug('hide title input and make it read-only');
			Bawl.UITextInputTitle.setValue('');
			Bawl.UITextInputTitle.setReadOnly(true);
			Bawl.UITextInputTitle.toggle(false);
		}
		replyLinkParams = Bawl.addPageAndSectionTitleToRPL(replyLinkParams);
		if ( replyLinkParams.pageTitle == mw.config.get('wgPageName') && mw.config.get('wgIsProbablyEditable') == false ) {
			Bawl.showProtectedWarning(replyLinkParams.pageTitle);
			Bawl.disableForm(true);
			Bawl.UICancelButton.setDisabled(false);
		}
		if ( ( Bawl.settings.editNotice || replyLinkParams.editIntro ) && mw.config.get('wgPageContentModel') == 'wikitext' ) { // load editnotice. if there isn't any it'll just be blank
			Bawl.loadEditNotice();
		}
		if ( Bawl.settings.checkNewComments && mw.config.get('wgArticleId') != 0 && Bawl.replyLinkParamsOpened.type == 'comment' ) {
			if ( Bawl.sectionToCheckForComments != replyLinkParams.sectionTitle + replyLinkParams.sectionseq ){
				Bawl.debug('first form you opened since loading the page or section differs from the section in which the last form was opened');
				Bawl.sectionToCheckForComments = replyLinkParams.sectionTitle + replyLinkParams.sectionseq;
				Bawl.lastCheckedForNewComments = 0;
				delete Bawl.pageRevisionSinceLastCheck[replyLinkParams.pageTitle];
				delete Bawl.pageRevisionIDSinceLastCheck[replyLinkParams.pageTitle];
			}
			Bawl.checkForNewComments(replyLinkParams, 'openform');
		}
		Bawl.debug('scroll reply button into view');
		Bawl.UIReplyButton.scrollElementIntoView();
		if ( replyLinkParams.type == 'newsection' || replyLinkParams.type == 'newheading' ) {
			Bawl.debug('focus input title and scroll it into view');
			Bawl.UITextInputTitle.focus();
			Bawl.UITextInputTitle.scrollElementIntoView();
			Bawl.UITextInputTitle.on('change',function() { Bawl.checkIfTitleUnique(); });
		} else {
			Bawl.debug('focus text input');
			Bawl.focusInput();
		}
		Bawl.UISettingsButton.on('click', Bawl.openSettings);
		if ( trigger == 'reload' ) {
			Bawl.debug('form opened by Bawl.reloadForm, scroll BawlUITextInput into view');
			window.BawlUITextInput.scrollIntoView(Bawl.smoothScroll);
		}
		if ( Bawl.UIReplyButton.isElementAttached() && mw.config.get('wgAction') == 'edit' && mw.util.getParamValue('section') == 'new' ) {
			$('#editform,#wikiPreview').addClass('BawlNoDisplay');
		}
		Bawl.syncToVisual();
		Bawl.openingFormInProgress = new Date().getTime();
		Bawl.applyModules('afterOpenForm');
	}); //end mw.loader.using
	} //end there is no reply form yet, create one
}; //end openReplyForm
Bawl.keyOpenReplyForm = Object.keys(Bawl)[Object.values(Bawl).indexOf(Bawl.openReplyForm)]; //used for insertion in onclick stuff, so the key mangler (AJSJSM) won't break that
Bawl.cIValue = {};
Bawl.cIThatRunValue = {};
Bawl.cIThatRunCmtValue = {};
Bawl.openSettings = function(openClose) {
	mw.loader.using( [ 'oojs-ui-core','oojs-ui-widgets' ] ).then( function () {
		Bawl.UISettingsButton.blur();
		if ( document.getElementById('saveSettingsButton') && ! $(document.getElementsByClassName('BawlSettings')).hasClass('BawlNoDisplay') && openClose != 'open' ) {
			Bawl.debug('settings are already opened. hiding them');
			Bawl.closeSettings();
			return;
		} else if ( document.getElementById('saveSettingsButton') && $(document.getElementsByClassName('BawlSettings')).hasClass('BawlNoDisplay') ) {
			Bawl.debug('settings were opened previously but currently hidden. unhiding them');
			$('#BawlPreviewBox').addClass('BawlNoDisplay');
			$(document.getElementsByClassName('BawlSettings')).removeClass('BawlNoDisplay');
			return;
		}
		$('#BawlPreviewBox').addClass('BawlNoDisplay');
		$(document.getElementsByClassName('BawlSettings')).removeClass('BawlNoDisplay');
		Bawl.settingElement = {};
		Bawl.settingElement.stalkMaxSubs = new OO.ui.TextInputWidget( {
			value: Bawl.settings.stalkMaxSubs,
			classes: [ 'BawlMarginHalfEmTop', 'BawlMarginHalfEm', 'BawlpermaLinkText' ],
		} );
		Bawl.settingElement.stalkMaxSubsFieldLayout = new OO.ui.FieldLayout( Bawl.settingElement.stalkMaxSubs, { label: Bawl.msgs.stalkMaxSubs, align: 'inline', classes: [ 'BawlOOuiFieldLayout' ] } );
		Bawl.settingElement.dbgLimit = new OO.ui.TextInputWidget( {
			value: Bawl.settings.dbgLimit,
			classes: [ 'BawlMarginHalfEmTop', 'BawlMarginHalfEm', 'BawlpermaLinkText' ],
		} );
		Bawl.settingElement.dbgLimitFieldLayout = new OO.ui.FieldLayout( Bawl.settingElement.dbgLimit, { label: Bawl.msgs.dbgLimit, align: 'inline', classes: [ 'BawlOOuiFieldLayout' ] } );
		Bawl.settingElement.outdent = new OO.ui.DropdownInputWidget( {
			options: [{data:5},{data:6},{data:7},{data:8},{data:9},{data:10},{data:15},{data:20},{data:30}],
			value: Bawl.settings.outdent,
			classes: [ 'BawlDropDownMenu' ],
		} );
		Bawl.settingElement.outdentFieldLayout = new OO.ui.FieldLayout( Bawl.settingElement.outdent, { label: Bawl.msgs.outdent, align: 'inline', classes: [ 'BawlOOuiFieldLayout' ] } );
		Bawl.settingElement.editor = new OO.ui.DropdownInputWidget( {
			options: [
				{ data: 'source', label: Bawl.msgs.editorSource },
				{ data: 'visualLight', label: Bawl.msgs.editorVisualLight },
				],
			value: Bawl.settings.editor,
			classes: [ 'BawlDropDownMenu' ],
		} );
		Bawl.settingElement.editorFieldLayout = new OO.ui.FieldLayout( Bawl.settingElement.editor, { label: Bawl.msgs.editor, align: 'inline', classes: [ 'BawlOOuiFieldLayout' ] } );
		Bawl.settingElement.watchlist = new OO.ui.DropdownInputWidget( {
			options: [
				{ data: 'nochange', label: Bawl.msgs.watchlistexpirynochange },
				{ data: 'preferences', label: Bawl.msgs.watchlistexpirypreferences },
				{ data: 'unwatch', label: Bawl.msgs.watchlistexpiryunwatch },
				{ data: 'watch', label: Bawl.msgs.watchlistexpirywatch },
				],
			value: Bawl.settings.watchlist,
			id: 'UIwatchlist',
			classes: [ 'BawlDropDownMenu' ],
		} );
		Bawl.settingElement.watchlistFieldLayout = new OO.ui.FieldLayout( Bawl.settingElement.watchlist, { label: Bawl.msgs.watchlist, align: 'inline', classes: [ 'BawlOOuiFieldLayout' ] } );
		Bawl.expireLabel = function(days) {
			if ( days.slice(0,1) == '+' ) {
				return Bawl.msgs.watchlistexpiryplusdays.replace('DAYS', days.slice(1));
			} else {
				return Bawl.msgs.watchlistexpirydays.replace('DAYS', days);
			}
		};
		Bawl.settingElement.watchlistexpiry = new OO.ui.DropdownInputWidget( {
			options: [
				{ data: '+7 days', label: Bawl.expireLabel('+7') },
				{ data: '+14 days', label: Bawl.expireLabel('+14') },
				{ data: '+30 days', label: Bawl.expireLabel('+30') },
				{ data: '+90 days', label: Bawl.expireLabel('+90') },
				{ data: '14 days', label: Bawl.expireLabel('14') },
				{ data: '30 days', label: Bawl.expireLabel('30') },
				{ data: '90 days', label: Bawl.expireLabel('90') },
				{ data: '180 days', label: Bawl.expireLabel('180') },
				{ data: 'indefinite', label: Bawl.expireLabel('∞') },
				],
			value: Bawl.settings.watchlistexpiry,
			id: 'UIwatchlistexpiry',
			classes: [ 'BawlDropDownMenu' ],
		} );
		Bawl.settingElement.watchlistexpiryFieldLayout = new OO.ui.FieldLayout( Bawl.settingElement.watchlistexpiry, { label: Bawl.msgs.watchlistexpiry, align: 'inline', classes: [ 'BawlOOuiFieldLayout' ] } );
		Bawl.stalkInterLabel = function(days) {
			return Bawl.basicmsgs['notification-timestamp-ago-minutes'].replace(/\{\{PLURAL:\$1\|(.*)\}\}$/,'$1').replace('$1', days);
		};
		Bawl.settingElement.stalkInterval = new OO.ui.DropdownInputWidget( {
			options: [
				{ data: 0, label: Bawl.stalkInterLabel(0) },
				{ data: 2, label: Bawl.stalkInterLabel(2) },
				{ data: 5, label: Bawl.stalkInterLabel(5) },
				{ data: 10, label: Bawl.stalkInterLabel(10) },
				{ data: 20, label: Bawl.stalkInterLabel(20) },
				{ data: 30, label: Bawl.stalkInterLabel(30) },
				{ data: 60, label: Bawl.stalkInterLabel(60) },
				{ data: 120, label: Bawl.stalkInterLabel(120) },
				],
			value: Bawl.settings.stalkInterval,
			id: 'UIstalkInterval',
			classes: [ 'BawlDropDownMenu' ],
		} );
		Bawl.settingElement.stalkIntervalFieldLayout = new OO.ui.FieldLayout( Bawl.settingElement.stalkInterval, { label: Bawl.msgs.stalkInterval, align: 'inline', classes: [ 'BawlOOuiFieldLayout' ] } );
		Bawl.settingElement.UIfontSize = new OO.ui.DropdownInputWidget( {
			options: [
				{ data: '0.875em', label: Bawl.msgs.UIfontSize0875em },
				{ data: 'x-small', label: Bawl.msgs.UIfontSizeTiny },
				{ data: 'small', label: Bawl.msgs.UIfontSizeSmall },
				{ data: 'medium' , label: Bawl.msgs.UIfontSizeMedium },
				{ data: 'large' , label: Bawl.msgs.UIfontSizeLarge },
				{ data: 'x-large', label: Bawl.msgs.UIfontSizeHuge },
				],
			value: Bawl.settings.UIfontSize,
			id: 'UIfontSize',
			classes: [ 'BawlDropDownMenu' ],
		} );
		Bawl.settingElement.UIfontSizeFieldLayout = new OO.ui.FieldLayout( Bawl.settingElement.UIfontSize, { label: Bawl.msgs.UIfontSize, align: 'inline', classes: [ 'BawlOOuiFieldLayout' ] } );
		Bawl.settingElement.afterPost = new OO.ui.DropdownInputWidget( {
			options: [
				{ data: 'reload', label: Bawl.msgs.reloadafter },
				{ data: 'parsepage', label: Bawl.msgs.parsepage },
				{ data: 'parsecmtonly', label: Bawl.msgs.parsecmtonly },
				{ data: 'parse', label: Bawl.msgs.parse },
				{ data: 'link', label: Bawl.msgs.linkafter },
				],
			value: Bawl.settings.afterPost,
			id: 'BawlAfterPost',
			classes: [ 'BawlDropDownMenu' ],
		} );
		Bawl.settingElement.afterPostFieldLayout = new OO.ui.FieldLayout( Bawl.settingElement.afterPost, { label: Bawl.msgs.afterPost, align: 'inline', classes: [ 'BawlOOuiFieldLayout' ] } );
		Bawl.settingElement.saveOptionsList = [ { data: 'browser', label: Bawl.msgs.saveToBrowser }, { data: 'accountprefs', label: Bawl.msgs.saveToAccountPrefs } ];
		if ( Bawl.projectIsSULWiki ) {
			Bawl.debug('This appears to be a Wikimedia SUL wiki. Add option to save preferences in global preferences');
			Bawl.settingElement.saveOptionsList.push({ data: 'globalprefs', label: Bawl.msgs.saveToGlobalPrefs });
		}
		if ( Bawl.userName == null ) { //anon can't save to account preferences
			Bawl.settingElement.saveOptionsList[1].disabled = true;
			Bawl.settingElement.saveOptionsList[2].disabled = true;
		}
		Bawl.settingElement.saveTo = new OO.ui.DropdownInputWidget( {
			options: Bawl.settingElement.saveOptionsList,
			value: Bawl.settings.saveTo,
			id: 'BawlSaveTo',
			classes: [ 'BawlDropDownMenu' ],
		} );
		Bawl.settingElement.saveToFieldLayout = new OO.ui.FieldLayout( Bawl.settingElement.saveTo, { label: Bawl.msgs.saveTo, align: 'inline', classes: [ 'BawlOOuiFieldLayout' ] } );
		Bawl.settingElement.pingText = new OO.ui.TextInputWidget( {
			value: Bawl.settings.pingText,
			placeholder: Bawl.msgs.pingTextPlaceholder,
			classes: [ 'BawlMarginHalfEmTop', 'BawlMarginHalfEm' ],
		} );
		Bawl.settingElement.pingTextFieldLayout = new OO.ui.FieldLayout( Bawl.settingElement.pingText, { label: Bawl.msgs.pingText, align: 'inline', classes: [ 'BawlOOuiFieldLayout' ] } );
		Bawl.settingElement.pingTextInSection = new OO.ui.TextInputWidget( {
			value: Bawl.settings.pingTextInSection,
			placeholder: Bawl.msgs.pingTextInSectionPlaceholder,
			classes: [ 'BawlMarginHalfEmTop', 'BawlMarginHalfEm' ],
		} );
		Bawl.settingElement.pingTextInSectionFieldLayout = new OO.ui.FieldLayout( Bawl.settingElement.pingTextInSection, { label: Bawl.msgs.pingTextInSection, align: 'inline', classes: [ 'BawlOOuiFieldLayout' ] } );
		Bawl.settingElement.customBackground = new OO.ui.TextInputWidget( {
			value: Bawl.settings.customBackground,
			placeholder: Bawl.msgs.customBackground,
			classes: [ 'BawlMarginHalfEmTop', 'BawlMarginHalfEm' ],
		} );
		Bawl.settingElement.customBackgroundFieldLayout = new OO.ui.FieldLayout( Bawl.settingElement.customBackground, { align: 'inline', classes: [ 'BawlOOuiFieldLayout' ] } );
		Bawl.settingElement.rewritunOther = new OO.ui.TextInputWidget( {
			value: Bawl.settings.rewritunOther,
			placeholder: Bawl.msgs.rewritunOtherPlaceholder,
			classes: [ 'BawlMarginHalfEmTop', 'BawlMarginHalfEm' ],
		} );
		Bawl.settingElement.rewritunOtherFieldLayout = new OO.ui.FieldLayout( Bawl.settingElement.rewritunOther, { label: Bawl.msgs.rewritunOther, align: 'inline', classes: [ 'BawlOOuiFieldLayout' ] } );
		Bawl.settingElement.runCIOther = new OO.ui.TextInputWidget( {
			value: Bawl.settings.runCIOther,
			placeholder: Bawl.msgs.rewritunOtherPlaceholder,
			classes: [ 'BawlMarginHalfEmTop', 'BawlMarginHalfEm' ],
		} );
		Bawl.settingElement.runCIOtherFieldLayout = new OO.ui.FieldLayout( Bawl.settingElement.runCIOther, { label: Bawl.msgs.runCIOther, align: 'inline', classes: [ 'BawlOOuiFieldLayout' ] } );
		Bawl.settingElement.AWBtyposOther = new OO.ui.TextInputWidget( {
			value: Bawl.settings.AWBtyposOther,
			placeholder: Bawl.msgs.rewritunOtherPlaceholder,
			classes: [ 'BawlMarginHalfEmTop', 'BawlMarginHalfEm' ],
		} );
		Bawl.settingElement.AWBtyposOtherFieldLayout = new OO.ui.FieldLayout( Bawl.settingElement.AWBtyposOther, { label: Bawl.msgs.AWBtyposOther, align: 'inline', classes: [ 'BawlOOuiFieldLayout' ] } );
		Bawl.settingElement.AWBtyposCustomTitle = new OO.ui.TextInputWidget( {
			placeholder: Bawl.msgs.AWBtyposCustomTitle,
			value: Bawl.settings.AWBtyposCustomTitle,
			classes: [ 'BawlMarginHalfEmTop', 'BawlMarginHalfEm' ],
		} );
		Bawl.settingElement.AWBtyposCustomTitleFieldLayout = new OO.ui.FieldLayout( Bawl.settingElement.AWBtyposCustomTitle, { align: 'inline', classes: [ 'BawlOOuiFieldLayout' ] } );
		Bawl.UIversionDateLabel = new OO.ui.HtmlSnippet(Bawl.VERSIONDATE + ' (' + (Bawl.timestampInitEnd - Bawl.timestampInit) + 'ms init/' + Bawl.loadTimeTotal + Bawl.maybeSkullNBones + 'ms total/<a class="triggerBugLink">' + Bawl.msgs.reportBug + '</a>)');
		Bawl.settingElement.UIversionDate = new OO.ui.LabelWidget( {
			label: Bawl.UIversionDateLabel,
			classes: [ 'BawlFloatRight', 'BawlSmallerText' ]
		} );
		Bawl.settingElement.saveSettingsButton = new OO.ui.ButtonWidget( {
			id: 'saveSettingsButton',
			flags: [ 'primary', 'progressive' ],
		} );
		Bawl.settingElement.resetPreferencesButtonUnlock = new OO.ui.ButtonWidget( {
			label: Bawl.msgs.resetPreferencesButtonUnlock,
			flags: [ 'primary', 'destructive' ],
		} );
		Bawl.settingElement.resetBawlSubs = new OO.ui.ButtonWidget( {
			label: Bawl.msgs.resetLocalStorBawlSubs,
			flags: [ 'primary', 'destructive' ],
			disabled: true
		} );
		Bawl.settingElement.resetBawlSubs.on('click', function() { window.localStorage.removeItem('BawlSubs');Bawl.deleteSubsFromPrefs();mw.notify(Bawl.basicmsgs.actioncomplete); });
		Bawl.settingElement.resetPreferencesButtonLocalStor = new OO.ui.ButtonWidget( {
			label: Bawl.msgs.resetPreferencesButtonLocalStor,
			flags: [ 'primary', 'destructive' ],
			disabled: true
		} );
		Bawl.settingElement.resetPreferencesButtonLocalStor.on('click', function() { Bawl.clearLocalStorage(); });
		Bawl.settingElement.resetPreferencesButton = new OO.ui.ButtonWidget( {
			flags: [ 'primary', 'destructive' ],
			disabled: true
		} );
		Bawl.settingElement.resetPreferencesButtonUnlock.on('click', function() { Bawl.settingElement.resetPreferencesButtonLocalStor.setDisabled(false);Bawl.settingElement.resetBawlSubs.setDisabled(false);Bawl.settingElement.resetPreferencesButton.setDisabled(false);Bawl.settingElement.resetPreferencesButtonUnlock.setDisabled(true);});
		Bawl.settingElement.resetPrefsButtonBar = new OO.ui.HorizontalLayout( {
			items: [
				Bawl.settingElement.resetBawlSubs,
				Bawl.settingElement.resetPreferencesButtonLocalStor,
				Bawl.settingElement.resetPreferencesButton,
				Bawl.settingElement.resetPreferencesButtonUnlock,
			],
			classes: [ 'BawlMarginHalfEmTop' ],
		} );
		Bawl.settingElement.resetPrefsButtonBarFieldLayout = Bawl.settingElement.resetPrefsButtonBar;//so loop picks it up
		Bawl.togglePrefButtonLabel = function() {
			if ( Bawl.settingElement.saveTo.getValue() == 'browser' ) {
				Bawl.settingElement.resetPreferencesButton.setLabel(Bawl.basicmsgs.restoreprefs + Bawl.msgs.prefLabelBrowser);
				Bawl.settingElement.saveSettingsButton.setLabel(Bawl.basicmsgs.saveprefs + Bawl.msgs.prefLabelBrowser);
			} else if ( Bawl.settingElement.saveTo.getValue() == 'accountprefs' ) {
				Bawl.settingElement.resetPreferencesButton.setLabel(Bawl.basicmsgs.restoreprefs + Bawl.msgs.prefLabelAccountPrefs);
				Bawl.settingElement.saveSettingsButton.setLabel(Bawl.basicmsgs.saveprefs + Bawl.msgs.prefLabelAccountPrefs);
			} else if ( Bawl.settingElement.saveTo.getValue() == 'globalprefs' ) {
				Bawl.settingElement.resetPreferencesButton.setLabel(Bawl.basicmsgs.restoreprefs + Bawl.msgs.prefLabelGlobalPrefs);
				Bawl.settingElement.saveSettingsButton.setLabel(Bawl.basicmsgs.saveprefs + Bawl.msgs.prefLabelGlobalPrefs);
			}
		};
		Bawl.togglePrefButtonLabel();
		Bawl.settingElement.saveTo.on('change', Bawl.togglePrefButtonLabel );
		Bawl.settingElement.cancelSettingsButton = new OO.ui.ButtonWidget( {
			id: 'cancelSettingsButton',
			label: Bawl.basicmsgs.cancel,
		} );
		Bawl.settingElement.saveSettingsButton.on('click', Bawl.saveSettings );
		Bawl.settingElement.resetPreferencesButton.on('click', Bawl.resetPreferences );
		Bawl.settingElement.cancelSettingsButton.on('click', Bawl.closeSettings );
		Bawl.settingElement.SettingsButtonBar = new OO.ui.HorizontalLayout( {
			items: [
				Bawl.settingElement.saveSettingsButton,
				Bawl.settingElement.cancelSettingsButton,
				Bawl.settingElement.UIversionDate
			],
			classes: [ 'BawlMarginHalfEmTop' ],
		} );
		Bawl.settingTabs = new OO.ui.IndexLayout({
			classes: ['BawlSettingTabs'],
			framed: false,
			expanded: false,
			autoFocus:false
		});
		Bawl.prefCount = Object.keys(Bawl.defaultSettings).length;
		Bawl.tabs = {};
		for (Bawl.prefint = 0; Bawl.prefint < Bawl.prefCount; Bawl.prefint++) {
			Bawl.processKey = Object.keys(Bawl.defaultSettings)[Bawl.prefint];
			Bawl.debug('process/create element ' + (Bawl.prefint + 1) + '/' + Bawl.prefCount + ': ' + Bawl.processKey);
			if ( typeof Bawl.settings[ Bawl.processKey ] == 'string' && Bawl.settings[ Bawl.processKey ] == 'TAB' ) {
				Bawl.debug('make new tab');
				Bawl.processingTab = Bawl.processKey;
				Bawl.tabs[Bawl.processingTab + 'Tab'] = new OO.ui.TabPanelLayout( Bawl.processingTab, { label: Bawl.msgs[ Bawl.processKey ], expanded:false,classes:['BawlSettingTabs'] } );
				Bawl.settingTabs.addTabPanels( [ Bawl.tabs[Bawl.processingTab + 'Tab'] ] );
			} else if ( typeof Bawl.settings[ Bawl.processKey ] != 'object' ) { //do not process the CI/runCI objects
				if ( ! Bawl.settingElement[ Bawl.processKey ] ) {
					Bawl.debug('make checkbox');
					if ( typeof Bawl.basicmsgs[ Bawl.processKey ] == 'string' ) { //for messages imported from MediaWiki which are stored in a different object
						Bawl.msgs[ Bawl.processKey ] = Bawl.basicmsgs[ Bawl.processKey ];
					}
					if ( typeof Bawl.msgs[ Bawl.processKey ] == 'string' && Bawl.msgs[ Bawl.processKey ].match(/<a/) ) {
						Bawl.msgs[ Bawl.processKey ] = new OO.ui.HtmlSnippet(Bawl.msgs[ Bawl.processKey ]);
					}
					Bawl.settingElement[ Bawl.processKey ] = new OO.ui.CheckboxInputWidget( {
						id: 'BawlPref' + Bawl.processKey,
						selected: Bawl.settings[ Bawl.processKey ],
						classes: [ 'BawlMarginHalfEm' ],
					} );
					Bawl.settingElement[ Bawl.processKey + 'FieldLayout' ] = new OO.ui.FieldLayout( Bawl.settingElement[ Bawl.processKey ], { id: 'BawlPref' + Bawl.processKey + 'FieldLayout', label: Bawl.msgs[ Bawl.processKey ], align: 'inline', classes: [ 'BawlOOuiFieldLayout' ] } );
					if ( Bawl.processKey.match(/(stalkAddCycle|dateLinksIconAlt|dateLinksIconSectExtra|dateLinksLocalTime.|collapArticle|autoCollapse|submitShortcut)/) || Bawl.processKey == 'AWBtypoPreview' ) {
						Bawl.settingElement[ Bawl.processKey + 'FieldLayout' ].$element.addClass('BawlIndented');
					}
				}
			}
			if ( Bawl.settingElement[ Bawl.processKey + 'FieldLayout' ] ) {
				Bawl.tabs[Bawl.processingTab + 'Tab'].$element.append(Bawl.settingElement[ Bawl.processKey + 'FieldLayout' ].$element);
			}
		}
		if ( Bawl.userName == null ) { //anon can't save to account preferences
			Bawl.settingElement.stalkSyncToPrefs.setSelected(false);
			Bawl.settingElement.stalkSyncToPrefs.setDisabled(true);
		}
		Bawl.toggleExtraOptions = function() {
			if (Bawl.settingElement.enableCI.isSelected()) {
				$('.BawlCustomInsertTextInput').removeClass('BawlNoDisplay');
			} else {
				$('.BawlCustomInsertTextInput').addClass('BawlNoDisplay');
			}
			if (Bawl.settingElement.enableCIThatRun.isSelected()) {
				$('.BawlCustomInsertThatRunTextInput').removeClass('BawlNoDisplay');
			} else {
				$('.BawlCustomInsertThatRunTextInput').addClass('BawlNoDisplay');
			}
			if (Bawl.settingElement.enableCIThatRunCmt.isSelected()) {
				$('.BawlCustomInsertThatRunCmtTextInput').removeClass('BawlNoDisplay');
			} else {
				$('.BawlCustomInsertThatRunCmtTextInput').addClass('BawlNoDisplay');
			}
			if ( ! Bawl.settingElement.collapsible.isSelected() ) {
				Bawl.settingElement.autoCollapse.setSelected(false);
				Bawl.settingElement.collapArticle.setSelected(false);
				Bawl.settingElement.collapArticleDefault.setSelected(false);
			}
			Bawl.settingElement.markNewCmtsBorder.setDisabled(! Bawl.settingElement.markNewCmts.isSelected() && ! Bawl.settingElement.markNewCmtsSubbed.isSelected());
			Bawl.settingElement.stalkMarkReadScroll.setDisabled(! Bawl.settingElement.markNewCmts.isSelected() && ! Bawl.settingElement.markNewCmtsSubbed.isSelected());
			if ( Bawl.settingElement.markNewCmtsBorder.isDisabled() ) {
				Bawl.settingElement.markNewCmtsBorder.setSelected(false);
				Bawl.settingElement.stalkMarkReadScroll.setSelected(false);
			}
			Bawl.settingElementsToToggle = {'dateLinksLocalTimeUserOptTZFieldLayout':'dateLinksLocalTime','dateLinksLocalTimeRelativeFieldLayout':'dateLinksLocalTime','dateLinksLocalTimeAbsoluteFieldLayout':'dateLinksLocalTime','dateLinksLocalTime12HFieldLayout':'dateLinksLocalTime','dateLinksLocalTimeNumMonthFieldLayout':'dateLinksLocalTime','dateLinksLocalTimeLongMonthFieldLayout':'dateLinksLocalTime','dateLinksLocalTimeWeekdayFieldLayout':'dateLinksLocalTime','dateLinksLocalTimeWeekdayFullFieldLayout':'dateLinksLocalTime','AWBtypoPreviewFieldLayout':'AWBtypos','dateLinksIconAltFieldLayout':'dateLinksIcon','dateLinksIconSectExtraFieldLayout':'dateLinksIconSection','stalkAddCycleBtnFieldLayout':'markNewCmts','stalkAddCycleBtnSubbedFieldLayout':'markNewCmtsSubbed','collapArticleDefaultFloatingToCFieldLayout':'collapsible','collapArticleDefaultNoToCFieldLayout':'collapsible','autoCollapseFieldLayout':'collapsible','collapArticleFieldLayout':'collapsible','collapArticleDefaultFieldLayout':'collapsible','submitShortcutFieldLayout':'shortcuts','hideDTFieldLayout':'showRisky','hideDTSubFieldLayout':'showRisky','methodLegacyFieldLayout':'showRisky','methodLocatorFieldLayout':'showRisky','useLocatorFieldLayout':'showRisky','enableOnDiffOldIdFieldLayout':'showRisky','theStrangerFieldLayout':'showRisky','ninjaLoaderFieldLayout':'showRisky','addLinkTSFieldLayout':'showRisky','killswitchFieldLayout':'showRisky','afterPostFieldLayout':'showRisky','afterPostReloadFieldLayout':'showRisky','watchlistFieldLayout':'showRisky','inputBoxTOFieldLayout':'showRisky','mwuibuttonTOFieldLayout':'showRisky','hideArchivedFieldLayout':'showRisky','cureDTBlueStreakFieldLayout':'showRisky','onetimetoolsFieldLayout':'showRisky','clearEditFullPageFieldLayout':'showRisky','limitWidthFieldLayout':'showRisky','warnExitFieldLayout':'showRisky','customBackgroundFieldLayout':'showRisky','markdownFieldLayout':'showRisky','sumSnippetFieldLayout':'showRisky','pingTextInSectionFieldLayout':'showRisky','rewritunFieldLayout':'showRisky','rewritunOtherFieldLayout':'showRisky','runCIOtherFieldLayout':'showRisky','AWBtyposOtherFieldLayout':'showRisky','markNewCmtsBorderFieldLayout':'showRisky','stalkWatchListCmtsFieldLayout':'showRisky','hideAdvFEFieldLayout':'showRisky','loadMinervaDFieldLayout':'showRisky','loadMinervaMFieldLayout':'showRisky','extendedSigDetectFieldLayout':'showRisky','RLmasqFieldLayout':'showRisky','outdent':'showRisky'};
			Bawl.settingElementsToToggle.debugFieldLayout = 'showRisky';//Bawl.debug
			Bawl.settingElementsToToggle.dbgLimitFieldLayout = 'showRisky';//Bawl.debug
			for(Bawl.settingToggleInt=0;Bawl.settingToggleInt<Object.keys(Bawl.settingElementsToToggle).length;Bawl.settingToggleInt++){
				Bawl.settingElement[Object.keys(Bawl.settingElementsToToggle)[Bawl.settingToggleInt]].toggle(Bawl.settingElement[Object.values(Bawl.settingElementsToToggle)[Bawl.settingToggleInt]].isSelected()); //hide option that can't be used without its parent from view
				if ( Object.keys(Bawl.settingElementsToToggle)[Bawl.settingToggleInt].match(/FieldLayout/) ){ //disable option that can't be used without its parent so it'll show when filtering options but won't be enabled
					Bawl.settingElement[Object.keys(Bawl.settingElementsToToggle)[Bawl.settingToggleInt].replace(/FieldLayout/,'')].setDisabled(!Bawl.settingElement[Object.values(Bawl.settingElementsToToggle)[Bawl.settingToggleInt]].isSelected());
				}
			}
		};
		Bawl.toggleExtraOptArray = ['dateLinksLocalTime','AWBtypos','showRisky','enableCI','enableCIThatRun','enableCIThatRunCmt','rewritun','dateLinksIcon','dateLinksIconSection','markNewCmts','markNewCmtsSubbed','collapArticleDefault','collapsible','shortcuts'];
		for(Bawl.toggleExtraInt=0;Bawl.toggleExtraInt<Bawl.toggleExtraOptArray.length;Bawl.toggleExtraInt++){
			Bawl.settingElement[Bawl.toggleExtraOptArray[Bawl.toggleExtraInt]].on('change', Bawl.toggleExtraOptions);
		}
		Bawl.debug('add settings button bar');
		Bawl.settingElement.tosNag.on('change', Bawl.toggleTosNag );
		$('#BawlSettings').append(Bawl.settingTabs.$element);
		$('#BawlSettings').append(Bawl.settingElement.SettingsButtonBar.$element);
		Bawl.toggleExtraOptions();
		Bawl.customInsertTextInput = {};
		Bawl.customInsertThatRunTextInput = {};
		Bawl.customInsertThatRunCmtTextInput = {};
		Bawl.hideFurtherCIInputFields = false;
		Bawl.hideFurtherCIThatRunInputFields = false;
		Bawl.filterSettingsInput = new OO.ui.TextInputWidget({id:'BawlFilterSettings',placeholder:Bawl.basicmsgs['tag-filter-submit'],maxLength:20,classes:['BawlSearchSettingsInput']});
		$('#BawlSettingsTop').prepend(Bawl.filterSettingsInput.$element);
		Bawl.BawlCreditTop = document.createElement('span');
		Bawl.BawlCreditTop.classList = ['BawlCreditTop'];
		Bawl.BawlCreditTop.innerHTML = '<a id="BawlCreditLink" href="https://en.wikipedia.org/wiki/User:Alexis_Jazz/Bawl" style="font-weight: bold">Bawl!</a> (early access) <a class="triggerBugLink">bug?</a>';
		$('#BawlSettings').prepend(Bawl.BawlCreditTop);
		$('.triggerBugLink').on('click',function(){Bawl.addScrewedLink('I AM ERROR','Error triggered by user.');});
		Bawl.filterSettingsInput.on('change',function(){Bawl.filterSettings();});
		Bawl.filterSettings = function() {
			if ( Bawl.filterSettingsInput.getValue().length == 0 ) {
				Bawl.debug('filterSettings: restore settings to original display');
				for (Bawl.restoreTabsInt=0;Bawl.restoreTabsInt<Object.keys(Bawl.tabs).length;Bawl.restoreTabsInt++){
					Bawl.tabs[Object.keys(Bawl.tabs)[Bawl.restoreTabsInt]].toggle(Bawl.tabs[Object.keys(Bawl.tabs)[Bawl.restoreTabsInt]].isActive());
				}
				for (Bawl.toggleAllInt=0;Bawl.toggleAllInt<Object.keys(Bawl.settingElement).length;Bawl.toggleAllInt++){
					if ( Object.keys(Bawl.settingElement)[Bawl.toggleAllInt].match(/FieldLayout/) ) {
						Bawl.settingElement[Object.keys(Bawl.settingElement)[Bawl.toggleAllInt]].toggle(true);
					}
				}
				Bawl.toggleExtraOptions();
			} else {
				Bawl.debug('filterSettings: toggle all tabs to true');
				for (Bawl.restoreTabsInt=0;Bawl.restoreTabsInt<Object.keys(Bawl.tabs).length;Bawl.restoreTabsInt++){
					Bawl.tabs[Object.keys(Bawl.tabs)[Bawl.restoreTabsInt]].toggle(true);
				}
				for (Bawl.toggleAllInt=0;Bawl.toggleAllInt<Object.keys(Bawl.settingElement).length;Bawl.toggleAllInt++){
					Bawl.debug('filterSettings: process '+Object.keys(Bawl.settingElement)[Bawl.toggleAllInt]);
					Bawl.elementToToggleFL = Bawl.settingElement[Object.keys(Bawl.settingElement)[Bawl.toggleAllInt]];
					Bawl.elementToToggle = Bawl.settingElement[Object.keys(Bawl.settingElement)[Bawl.toggleAllInt].replace(/FieldLayout/,'')];
					if ( Object.keys(Bawl.settingElement)[Bawl.toggleAllInt].match(/FieldLayout/) ) {
						if ( Bawl.elementToToggleFL.getLabel && typeof Bawl.elementToToggleFL.getLabel() == 'string' && Bawl.elementToToggleFL.getLabel().match(new RegExp(Bawl.escapeRegExp(Bawl.filterSettingsInput.getValue()),'i')) ) {
							Bawl.elementToToggleFL.toggle(true);
							if(Bawl.settingElementsToToggle[Object.keys(Bawl.settingElement)[Bawl.toggleAllInt]]){
								Bawl.settingElementParent = Object.values(Bawl.settingElementsToToggle)[Object.keys(Bawl.settingElementsToToggle).indexOf(Object.keys(Bawl.settingElement)[Bawl.toggleAllInt])];
								Bawl.settingElement[Bawl.settingElementParent+'FieldLayout'].toggle(true);
							}
						} else if ( Bawl.elementToToggle && Bawl.elementToToggle.getInputId && typeof Bawl.elementToToggle.getInputId() == 'string' && $('#'+Bawl.elementToToggle.getInputId())[0].attributes.placeholder && $('#'+Bawl.elementToToggle.getInputId())[0].attributes.placeholder.textContent.match(new RegExp(Bawl.escapeRegExp(Bawl.filterSettingsInput.getValue()),'i')) ) {
							Bawl.elementToToggleFL.toggle(true);
						} else {
							Bawl.elementToToggleFL.toggle(false);
						}
					}
				}
			}
		};
		for (Bawl.int = 0; Bawl.int < 50; Bawl.int++) {
			Bawl.debug('process custom inserts');
			Bawl.placeholderIntPlusOne = Bawl.int + 1;
			if ( typeof Bawl.settings.cI[Bawl.int] != 'undefined' ) {
				Bawl.cIValue[Bawl.int] = Bawl.settings.cI[Bawl.int].replace(/SLASHCHAR/g,'/');
			} else {
				Bawl.cIValue[Bawl.int] = '';
			}
			Bawl.customInsertTextInput[Bawl.int] = new OO.ui.TextInputWidget( {
				value: decodeURIComponent(Bawl.cIValue[Bawl.int]),
				id: 'BawlCustomInsert_' + Bawl.int,
				placeholder: Bawl.msgs.BawlCustomInsertPlaceholder.replace(/NUM/g, Bawl.placeholderIntPlusOne),
				classes: [ 'BawlMarginHalfEm', 'BawlCustomInsertTextInput' ],
			} );
			Bawl.customInsertTextInput[Bawl.int].on('change', Bawl.unhidecIField );
			if ( typeof Bawl.settings.cIThatRun[Bawl.int] != 'undefined' ) {
				Bawl.cIThatRunValue[Bawl.int] = decodeURIComponent(Bawl.settings.cIThatRun[Bawl.int]);
			} else {
				Bawl.cIThatRunValue[Bawl.int] = '';
			}
			Bawl.customInsertThatRunTextInput[Bawl.int] = new OO.ui.TextInputWidget( {
				value: Bawl.cIThatRunValue[Bawl.int],
				id: 'BawlCustomInsertThatRun_' + Bawl.int,
				placeholder: Bawl.msgs.BawlCustomInsertThatRunPlaceholder.replace('NUM', Bawl.placeholderIntPlusOne),
				classes: [ 'BawlMarginHalfEm', 'BawlCustomInsertThatRunTextInput' ],
			} );
			Bawl.customInsertThatRunTextInput[Bawl.int].on('change', Bawl.unhidecIField );
			if ( typeof Bawl.settings.cIThatRunCmt[Bawl.int] != 'undefined' ) {
				Bawl.cIThatRunCmtValue[Bawl.int] = decodeURIComponent(Bawl.settings.cIThatRunCmt[Bawl.int]);
			} else {
				Bawl.cIThatRunCmtValue[Bawl.int] = '';
			}
			Bawl.customInsertThatRunCmtTextInput[Bawl.int] = new OO.ui.TextInputWidget( {
				value: Bawl.cIThatRunCmtValue[Bawl.int],
				id: 'BawlCustomInsertThatRunCmt_' + Bawl.int,
				placeholder: Bawl.msgs.BawlCustomInsertThatRunPlaceholder.replace('NUM', Bawl.placeholderIntPlusOne),
				classes: [ 'BawlMarginHalfEm', 'BawlCustomInsertThatRunCmtTextInput' ],
			} );
			Bawl.customInsertThatRunCmtTextInput[Bawl.int].on('change', Bawl.unhidecIField );
			if ( Bawl.int == 0 || Bawl.settings.cI[Bawl.int] || Bawl.lastAddedcI == Bawl.int -1 ) {
				$('#BawlPrefenableCIFieldLayout').append(Bawl.customInsertTextInput[Bawl.int].$element);
				if ( Bawl.settings.cI[Bawl.int] ) {
					Bawl.lastAddedcI = Bawl.int;
				}
			}
			if ( Bawl.int == 0 || Bawl.settings.cIThatRun[Bawl.int] || Bawl.lastAddedcIThatRun == Bawl.int -1 ) {
				$('#BawlPrefenableCIThatRunFieldLayout').append(Bawl.customInsertThatRunTextInput[Bawl.int].$element);
				if ( Bawl.settings.cIThatRun[Bawl.int] ) {
					Bawl.lastAddedcIThatRun = Bawl.int;
				}
			}
			if ( Bawl.int == 0 || Bawl.settings.cIThatRunCmt[Bawl.int] || Bawl.lastAddedcIThatRunCmt == Bawl.int -1 ) {
				$('#BawlPrefenableCIThatRunCmtFieldLayout').append(Bawl.customInsertThatRunCmtTextInput[Bawl.int].$element);
				if ( Bawl.settings.cIThatRunCmt[Bawl.int] ) {
					Bawl.lastAddedcIThatRunCmt = Bawl.int;
				}
			}
		} //end for loop
		clearInterval(DelayJump);$('#BawlCreditLink')[0].scrollIntoView({behavior:'smooth'});//BawlCreditLink is at the top of the settings window
	});
}; //end function opensettings
Bawl.unhidecIField = function() {
	if ( document.activeElement.parentElement && document.activeElement.parentElement.id && document.activeElement.parentElement.id.match(/_[0-9]*$/) ) {
		Bawl.nextcIElementNum = Number(document.activeElement.parentElement.id.replace(/.*_/,'')) +1;
		Bawl.nextcIElement = document.activeElement.parentElement.id.replace(/[0-9]*$/,'') + Bawl.nextcIElementNum.toString();
		if ( ! $('#' + Bawl.nextcIElement)[0] && Bawl.nextcIElementNum < 50 ) {
			Bawl.debug('there is no element with ID ' + Bawl.nextcIElement + ' so let\'s append it');
			if ( Bawl.nextcIElement.replace(/_[0-9]*/,'') == 'BawlCustomInsert' ) {
				$('#BawlPrefenableCIFieldLayout').append(Bawl.customInsertTextInput[Bawl.nextcIElementNum].$element);
			} else if ( Bawl.nextcIElement.replace(/_[0-9]*/,'') == 'BawlCustomInsertThatRun' ) {
				$('#BawlPrefenableCIThatRunFieldLayout').append(Bawl.customInsertThatRunTextInput[Bawl.nextcIElementNum].$element);
			} else if ( Bawl.nextcIElement.replace(/_[0-9]*/,'') == 'BawlCustomInsertThatRunCmt' ) {
				$('#BawlPrefenableCIThatRunCmtFieldLayout').append(Bawl.customInsertThatRunCmtTextInput[Bawl.nextcIElementNum].$element);
			}
		}
	}
};
Bawl.oneTimeToolsOpen = function() {
	if ( $('#onetimetools')[0] && $('#onetimetools')[0].classList.contains('BawlTools') && $('#onetimetools')[0].classList.contains('BawlNoDisplay') ) {
		$('#onetimetools').removeClass('BawlNoDisplay');
		Bawl.oneTimeTools.replaceThis.focus();
		return;
	} else if ( $('#onetimetools')[0] && $('#onetimetools')[0].classList.contains('BawlTools') ) {
		$('#onetimetools').addClass('BawlNoDisplay');
		Bawl.focusInput();
		return;
	}
	$('#onetimetools').addClass('BawlTools').removeClass('BawlNoDisplay');
	Bawl.oneTimeTools = {};
	Bawl.oneTimeTools.replaceThis = new OO.ui.TextInputWidget( {
		placeholder: 'Lorem | /([Ll])orem/g',
		classes: [ 'BawlMarginHalfEmTop', 'BawlMarginHalfEm' ],
	} );
	Bawl.oneTimeTools.replaceWith = new OO.ui.TextInputWidget( {
		placeholder: 'Ipsum | $1psum',
		classes: [ 'BawlMarginHalfEmTop', 'BawlMarginHalfEm' ],
	} );
	Bawl.oneTimeTools.replaceButton = new OO.ui.ButtonWidget( {
		label: Bawl.msgs.replaceButton,
		flags: [ 'primary' ],
	} );
	Bawl.oneTimeTools.replaceAllButton = new OO.ui.ButtonWidget( {
		label: Bawl.msgs.replaceAllButton,
		flags: [ 'primary' ],
	} );
	Bawl.oneTimeTools.AWBtyposButton = new OO.ui.ButtonWidget( {
		label: Bawl.msgs.AWBtyposButton,
		flags: [ 'primary' ],
	} );
	Bawl.oneTimeTools.replaceButtonBar = new OO.ui.HorizontalLayout( {
		items: [Bawl.oneTimeTools.replaceButton,Bawl.oneTimeTools.replaceAllButton,Bawl.oneTimeTools.AWBtyposButton],
		id: 'BawlReplaceButtonBar',
		classes: [ 'BawlMarginHalfEmTop' ],
	} );
	Bawl.searchAndReplace = function(mode) {
		if ( Bawl.oneTimeTools.replaceThis.getValue().match(/^\/.*\/[gmi]{0,3}$/) ) {
			Bawl.oneTimeTools.replaceThisVal = new RegExp(Bawl.oneTimeTools.replaceThis.getValue().match(/^\/(.*)\/([gmi]{0,3})$/)[1],Bawl.oneTimeTools.replaceThis.getValue().match(/^\/(.*)\/([gmi]{0,3})$/)[2]);
			Bawl.oneTimeTools.replaceWithVal = Bawl.oneTimeTools.replaceWith.getValue();
		} else if ( mode == 'all' ) {
			Bawl.oneTimeTools.replaceThisVal = new RegExp(Bawl.escapeRegExp(Bawl.oneTimeTools.replaceThis.getValue()), 'g');
			Bawl.oneTimeTools.replaceWithVal = Bawl.escapeReplacement(Bawl.oneTimeTools.replaceWith.getValue());
		} else {
			Bawl.oneTimeTools.replaceThisVal = Bawl.oneTimeTools.replaceThis.getValue();
			Bawl.oneTimeTools.replaceWithVal = Bawl.escapeReplacement(Bawl.oneTimeTools.replaceWith.getValue());
		}
		Bawl.UITextInput.setValue(Bawl.UITextInput.getValue().replace(Bawl.oneTimeTools.replaceThisVal,Bawl.oneTimeTools.replaceWithVal));
	};
	Bawl.oneTimeTools.replaceButton.on('click',function() { Bawl.searchAndReplace();});
	Bawl.oneTimeTools.replaceAllButton.on('click',function() { Bawl.searchAndReplace('all');});
	Bawl.oneTimeTools.AWBtyposButton.on('click',function() { Bawl.RETF(Bawl.UITextInput.getValue(),'onetime');});
	Bawl.genLinksList = function(listType) {
		if ( $('.mw-changeslist-diff')[0] ) {//todo: some special pages need another selector
			Bawl.genLinksListElements = $('.mw-changeslist-diff');
			Bawl.genLinksPageType = 'contribs';
		} else {
			Bawl.genLinksListElements = $('#mw-content-text a:not(.external,.new,.ext-discussiontools-init-section-subscribe-link)');
			Bawl.genLinksPageType = 'generic';
		}
		Bawl.genLinksListCode = '\n';
		Bawl.genLinksListArray = [];
		for (Bawl.genLinksListElementsInt=0;Bawl.genLinksListElementsInt<Bawl.genLinksListElements.length;Bawl.genLinksListElementsInt++) {
			delete Bawl.genLinksProcessLink;
			if ( Bawl.genLinksPageType == 'contribs' ) {
				Bawl.genLinksProcessLink = Bawl.genLinksListElements[Bawl.genLinksListElementsInt].href;
			} else if ( Bawl.genLinksListElements[Bawl.genLinksListElementsInt].href.match(mw.config.get('wgArticlePath').replace('$1','')) ) {
				Bawl.genLinksProcessLink = '[[' + Bawl.genLinksListElements[Bawl.genLinksListElementsInt].title + ']]';
			}
			if ( Bawl.genLinksProcessLink && Bawl.genLinksProcessLink != '[[]]' && Bawl.genLinksListArray.indexOf(Bawl.genLinksProcessLink) == -1 ) {
				Bawl.debug('adding ' + Bawl.genLinksProcessLink + ' to list');
				Bawl.genLinksListArray.push(Bawl.genLinksProcessLink);
				Bawl.genLinksListCode = Bawl.genLinksListCode + '\n' + listType + Bawl.genLinksProcessLink;
			}
		}
		if ( Bawl.genLinksPageType == 'contribs' ) {
			Bawl.genLinksListCode = Bawl.rewritunUrUrlz(Bawl.genLinksListCode).replace(/#.*/,'');
		}
		if ( Bawl.genLinksListElements.length > 0 ) {
			Bawl.UITextInput.setValue(Bawl.UITextInput.getValue() + Bawl.genLinksListCode);
		}
	};
	Bawl.oneTimeTools.bulletedListButton = new OO.ui.ButtonWidget( {
		label: Bawl.msgs.genBulletedList,
		flags: [ 'primary' ],
	} );
	Bawl.oneTimeTools.numberedListButton = new OO.ui.ButtonWidget( {
		label: Bawl.msgs.genNumberedList,
		flags: [ 'primary' ],
	} );
	Bawl.oneTimeTools.bulletedListButton.on('click',function() { Bawl.genLinksList('*');});
	Bawl.oneTimeTools.numberedListButton.on('click',function() { Bawl.genLinksList('#');});
	Bawl.oneTimeTools.genListButtonBar = new OO.ui.HorizontalLayout( {
		items: [Bawl.oneTimeTools.bulletedListButton,Bawl.oneTimeTools.numberedListButton],
		classes: [ 'BawlMarginHalfEmTop' ],
	} );
	Bawl.oneTimeTools.moveContentToPage = new OO.ui.ComboBoxInputWidget( {
		id:'BawlMoveToPage',
		options: [],//{data:'Option 1',label: 'Option One'}
		placeholder: Bawl.msgs.moveContentToPage,
		spellcheck: false,
		menu: {filterFromInput: true},
		classes: [ 'BawlMarginHalfEm' ],
	} );
	Bawl.oneTimeTools.moveContentToPage.on('change',function() { Bawl.linkFieldChange('contentmove'); });
	Bawl.oneTimeTools.allowPageCreation = new OO.ui.CheckboxInputWidget({ disabled:true });
	Bawl.oneTimeTools.allowPageCreationFieldLayout = new OO.ui.FieldLayout( Bawl.oneTimeTools.allowPageCreation, { label: Bawl.msgs.allowPageCreation, align: 'inline'} );
	Bawl.oneTimeTools.moveContentToPageHorizontalLayout = new OO.ui.HorizontalLayout( {
		items: [Bawl.oneTimeTools.moveContentToPage,Bawl.oneTimeTools.allowPageCreationFieldLayout],
		classes: [ 'BawlMarginHalfEmTop' ],
	} );
	Bawl.oneTimeTools.moveContentToPageHorizontalLayout.toggle(false);
	Bawl.oneTimeTools.archiveSection = new OO.ui.CheckboxInputWidget({});
	Bawl.oneTimeTools.archiveSectionFieldLayout = new OO.ui.FieldLayout( Bawl.oneTimeTools.archiveSection, { label: Bawl.msgs.archiveSection, align: 'inline', classes: [ 'BawlOOuiFieldLayout' ] } );
	Bawl.oneTimeToolsFormArray = [Bawl.oneTimeTools.replaceThis,Bawl.oneTimeTools.replaceWith,Bawl.oneTimeTools.replaceButtonBar,Bawl.oneTimeTools.genListButtonBar,Bawl.oneTimeTools.moveContentToPageHorizontalLayout,Bawl.oneTimeTools.archiveSectionFieldLayout];
	if ( ! Bawl.UITextInputSummaryMinorLayout.isElementAttached() ) {
		Bawl.oneTimeToolsFormArray.push(Bawl.UITextInputSummaryMinorLayout);
	}
	if ( mw.config.get('wgRelevantUserName') && mw.config.get('wgRelevantUserName') != Bawl.userName && mw.config.get('wgCanonicalNamespace') == 'User_talk' && mw.config.get('wgTitle') == mw.config.get('wgRelevantUserName') && ( Bawl.settings.debug || mw.config.get('wgUserGroups').includes('sysop') ) ) {
		Bawl.oneTimeTools.blockModoptions = [];
		Bawl.oneTimeTools.blockModipboptions = JSON.parse('{"' + Bawl.basicmsgs.ipboptions.replace(/:([^,]*),/g,'":"$1","').replace(/:([^,]*)$/,'":"$1"}').replace(/ /g,'\ '));
		for(Bawl.blockModperiodInt=0;Bawl.blockModperiodInt<Object.keys(Bawl.oneTimeTools.blockModipboptions).length;Bawl.blockModperiodInt++){
			Bawl.oneTimeTools.blockModoptions.push({data:Object.values(Bawl.oneTimeTools.blockModipboptions)[Bawl.blockModperiodInt],label:Object.keys(Bawl.oneTimeTools.blockModipboptions)[Bawl.blockModperiodInt]});
		}
		Bawl.oneTimeTools.blockModoptions.push({data:'unblock',label:Bawl.basicmsgs.unblock},{data:'',label:Bawl.basicmsgs['checkbox-none']});
		Bawl.oneTimeTools.blockMod = new OO.ui.ComboBoxInputWidget( {
			classes: [ 'BawlMarginHalfEm','BawlpermaLinkText'],
			placeholder: Bawl.basicmsgs['log-action-filter-block-reblock'] + ' (' + Bawl.basicmsgs.English + ')',
			options: Bawl.oneTimeTools.blockModoptions,//{data:'Option 1',label: 'Option One'}
			spellcheck: false,
		} );
		Bawl.oneTimeTools.blockModWarn = function() {
			if ( Bawl.oneTimeTools.blockMod.getValue() != '' && Bawl.oneTimeTools.blockMod.getValue() != 'unblock' ) {
				Bawl.UIReplyButton.clearFlags();Bawl.UIReplyButton.setFlags(['primary','destructive']);
				$('.BawlForm').addClass('BawlRedBG');
				Bawl.oneTimeTools.blockModmail.setDisabled(false);
				Bawl.oneTimeTools.blockModtalk.setDisabled(false);
				Bawl.UIReplyButton.setLabel(Bawl.basicmsgs['htmlform-submit'] + ' + ' + Bawl.basicmsgs.block + ' (' + mw.config.get('wgRelevantUserName') + ')');
			} else {
				Bawl.UIReplyButton.clearFlags();Bawl.UIReplyButton.setFlags(['primary','progressive']);
				$('.BawlForm').removeClass('BawlRedBG');
				Bawl.oneTimeTools.blockModmail.setDisabled(true);
				Bawl.oneTimeTools.blockModtalk.setDisabled(true);
				Bawl.UIReplyButton.setLabel(Bawl.basicmsgs['htmlform-submit']);
			}
			if ( Bawl.oneTimeTools.blockMod.getValue() == 'unblock' ) {
				Bawl.UIReplyButton.setLabel(Bawl.basicmsgs['htmlform-submit'] + ' + ' + Bawl.basicmsgs.unblock + ' (' + mw.config.get('wgRelevantUserName') + ')');
			}
		};
		Bawl.oneTimeTools.blockMod.on('change',Bawl.oneTimeTools.blockModWarn);
		Bawl.oneTimeTools.blockModmail = new OO.ui.CheckboxInputWidget({disabled:true});
		Bawl.oneTimeTools.blockModmailFieldLayout = new OO.ui.FieldLayout( Bawl.oneTimeTools.blockModmail, { label: Bawl.basicmsgs.ipbemailban, align: 'inline' } );
		Bawl.oneTimeTools.blockModtalk = new OO.ui.CheckboxInputWidget({disabled:true});
		Bawl.oneTimeTools.blockModtalkFieldLayout = new OO.ui.FieldLayout( Bawl.oneTimeTools.blockModtalk, { label: Bawl.basicmsgs['ipb-disableusertalk'], align: 'inline' } );
		Bawl.oneTimeTools.blockModhorizontal = new OO.ui.HorizontalLayout( {
			items: [Bawl.oneTimeTools.blockMod,Bawl.oneTimeTools.blockModmailFieldLayout,Bawl.oneTimeTools.blockModtalkFieldLayout],
			classes: [ 'BawlMarginHalfEmTop' ],
		} );
		Bawl.oneTimeToolsFormArray.push(Bawl.oneTimeTools.blockModhorizontal);
	}
	Bawl.oneTimeToolsForm = new OO.ui.FormLayout( {
		items: Bawl.oneTimeToolsFormArray,
		id: 'oneTimeToolsForm',
		classes: ['BawlReplyForm'],
	} );
	$('#onetimetools').append(Bawl.oneTimeToolsForm.$element);
	$('#BawlReplaceButtonBar').append('<div id="BawlMatchedRETF"></div>');
	Bawl.oneTimeTools.replaceThis.focus();
	$('#BawlMoveToPage input').blur(function() { if ( Bawl.oneTimeTools.moveContentToPage.getValue() != '' ) { Bawl.disableForm(false);Bawl.oneTimeTools.allowPageCreation.setDisabled(false);Bawl.oneTimeTools.moveContentToPage.setValue(Bawl.rewritunUrUrlz(Bawl.oneTimeTools.moveContentToPage.getValue(),'contentmove').replace(/^\[\[(:)?(.*)\]\]$/,'$2'));Bawl.UIReplyButton.setLabel(Bawl.basicmsgs['htmlform-submit'] + ' → ' + Bawl.oneTimeTools.moveContentToPage.getValue()); } });
	Bawl.editSummaryPipeTrick();
	if ( Bawl.replyLinkParamsOpened.type == 'editFullPage' || ( typeof Bawl.replyLinkParamsOpened.sectionTitle == 'string' && Bawl.replyLinkParamsOpened.sectionTitle != '' ) ) {
		Bawl.oneTimeTools.moveContentToPageHorizontalLayout.toggle(true);
	}
};
Bawl.getSectionByNum = function(wikiTextSectByNum, num) {
	Bawl.debug('get section #' + num);
	if ( Bawl.safedMarker && wikiTextSectByNum.match(new RegExp(Bawl.safedMarker)) ) {
		Bawl.debug('wikitext has already been safed, skip safing');
		Bawl.wikiTextSectByNumSafed = wikiTextSectByNum;
	} else {
		Bawl.debug('wikitext has not been safed yet, safing now');
		Bawl.wikiTextSectByNumSafed = Bawl.safeText(wikiTextSectByNum,undefined,'skiplinks');
	}
	Bawl.sectionByNum = Bawl.wikiTextSectByNumSafed.replace(/(^|\n)=/g,'$1BAWLSECTION=');
	Bawl.sectionByNumRegExp = new RegExp('BAWLSECTION=.+=[ ]*(?:$|\n)','g');
	Bawl.sectionByNumSplit = Bawl.sectionByNum.split(Bawl.sectionByNumRegExp);
	Bawl.sectionByNumMatch = Bawl.sectionByNum.match(Bawl.sectionByNumRegExp);
	Bawl.sectionByNumMatch.unshift(''); //the lede has no section so we add an empty element at the start to sync these up
	if ( Bawl.sectionByNumSplit[num] ) {
		Bawl.sectionByNumHeaderLevel = Bawl.sectionByNumMatch[num].trim().match(/BAWLSECTION([\=]*)/)[1].length;
		Bawl.sectionByNumWikiText = Bawl.sectionByNumMatch[num] + Bawl.sectionByNumSplit[num];
		for (Bawl.int = 0; Bawl.int < Bawl.sectionByNumMatch.length; Bawl.int++) {
			if ( Bawl.int >= num && Bawl.sectionByNumMatch[Bawl.int].trim().match(/BAWLSECTION([\=]*)/)[1].length > Bawl.sectionByNumHeaderLevel ) {
				Bawl.debug('add subsection #' + Bawl.int);
				Bawl.sectionByNumWikiText = Bawl.sectionByNumWikiText + Bawl.sectionByNumMatch[Bawl.int] + Bawl.sectionByNumSplit[Bawl.int];
			} else if ( Bawl.int > num && Bawl.sectionByNumMatch[Bawl.int].trim().match(/BAWLSECTION([\=]*)/)[1].length <= Bawl.sectionByNumHeaderLevel ) {
				break;
			}
		}
		Bawl.sectionByNumWikiTextTrim = Bawl.sectionByNumWikiText.trim();
		Bawl.wikiTextSectByNumSafedMarked = Bawl.sectionByNum.replace(Bawl.sectionByNumWikiTextTrim,'BAWLGETSECTIONBYNUMSTART'+Bawl.semiRandom+Bawl.sectionByNumWikiTextTrim+'BAWLGETSECTIONBYNUMSTART'+Bawl.semiRandom);
		Bawl.wikiTextSectByNumUnsafeRegExp = new RegExp('BAWLGETSECTIONBYNUMSTART'+Bawl.semiRandom+'([^]*)'+'BAWLGETSECTIONBYNUMSTART'+Bawl.semiRandom);
		Bawl.wikiTextSectByNumUnsafe = Bawl.safeText(Bawl.wikiTextSectByNumSafedMarked,'unsafe').match(Bawl.wikiTextSectByNumUnsafeRegExp)[1];
		return Bawl.wikiTextSectByNumUnsafe.replace(/BAWLSECTION=/g,'=');
	} else {
		return null;
	}
};
Bawl.repairWikiText = function(text) {
	Bawl.debug('look for a time (like 12:00) followed by more than one newline followed by an indented message and reduce the number of newlines to one. Otherwise replies to that first post will go right under that post which is strictly speaking correct behavior (which is why I refuse to correct THAT), but not desired. Also: fuck you DiscussionTools.');
	return text.replace(/([0-9]{1,2}:[0-5][0-9].*)[\n]{2,}([\\:\\*\\#])/g, '$1\n$2');
};
Bawl.extractUsernames = function(text) {
	Bawl.extractUsernamesPingTextRegExp = new RegExp('(' + Bawl.escapeRegExp(Bawl.pingText).replace('PINGUSER', '([^\\]\\}]*)') + '|\\[\\[User:[^\\|\\]]*|\\[\\[' + mw.config.get('wgFormattedNamespaces')[2] + ':[^\\|\\]]*|\{\{[Pp]ing\\|[^}]*|\{\{[Rr]eply to\\|[^}]*)', 'g');
	Bawl.extractedUsernames = text.match(Bawl.extractUsernamesPingTextRegExp);
	Bawl.extractedUsernamesClean = [];
	if ( Bawl.extractedUsernames ) {
		for (Bawl.int = 0; Bawl.int < Bawl.extractedUsernames.length; Bawl.int++) {
			Bawl.cleanUserPing = new RegExp('(\\[\\[:?[Uu]ser:|\\[\\[:?' + mw.config.get('wgFormattedNamespaces')[2] + ':|\{\{[Pp]ing\\||\{\{[Rr]eply to\\||\\|\\]\\])', 'g');
			Bawl.extractedUsernamesClean[Bawl.int] = Bawl.extractedUsernames[Bawl.int].replace(Bawl.cleanUserPing, '');
		}
	}
	return Bawl.extractedUsernamesClean;
};
Bawl.pingFix = function(origText,newText) {
	Bawl.debug('getting usernames mentioned in this comment (WP:PINGFIX)');
	Bawl.usernamesInEditedComment = Bawl.extractUsernames(origText);
	Bawl.usernamesInUneditedComment = Bawl.extractUsernames(newText);
	Bawl.userMentionInSummary = '';
	for (Bawl.int = 0; Bawl.int < Bawl.usernamesInEditedComment.length; Bawl.int++) {
		Bawl.debug('checking ' + Bawl.usernamesInEditedComment[Bawl.int]);
		if ( Bawl.usernamesInEditedComment[Bawl.int] && Bawl.usernamesInUneditedComment.indexOf(Bawl.usernamesInEditedComment[Bawl.int]) == -1 && ! Bawl.userMentionInSummary.match(Bawl.usernamesInEditedComment[Bawl.int] + '\\|') ) {
			Bawl.userMentionInSummary = Bawl.userMentionInSummary + ', [[' + mw.config.get('wgFormattedNamespaces')[2] + ':' + Bawl.usernamesInEditedComment[Bawl.int] + '|' + Bawl.usernamesInEditedComment[Bawl.int] + ']]';
		}
	}
	return Bawl.userMentionInSummary;
};
Bawl.repairTagImbalance = function(text) {
	Bawl.debug('check for unbalanced \'\', \'\'\', <i>, <b>, <s> and <span> and return an appropriate set of closing tags.');
	if ( text && Bawl.replyLinkParamsOpened.type != 'edit' ) {
		Bawl.balancingTags = '';
		Bawl.balancingTextCleaned = text.replace(/<[n]owiki\>[^]*<\/[n]owiki\>/gm, '').replace(/\{\{([^\{\}]|[\{\}][^\{\}])*\}\}/gm, '').replace(/\{\{([^\{\}]|[\{\}][^\{\}])*\}\}/gm, '').replace(/\{\{([^\{\}]|[\{\}][^\{\}])*\}\}/gm, '').replace(/\{\{([^\{\}]|[\{\}][^\{\}])*\}\}/gm, '').replace(/\{\{([^\{\}]|[\{\}][^\{\}])*\}\}/gm, '');
		for (Bawl.int = 0; Bawl.int < 10; Bawl.int++) { //removing complete tag combinations in the right order. times 10 to also catch nested tags
			Bawl.balancingTextCleaned = Bawl.balancingTextCleaned.replace(/<(?![\/]?[bis]\>|[\/]?span( [^>]*)?)/g, '').replace(/<span( [^\>]*)?\>([^<]|<[\/]?[bis]\>)*<\/span\>/gmi, '$2').replace(/<b( [^\>]*)?\>([^<]*|<[\/]?span[^\>]*\>|<[\/]?[is]\>)*<\/b\>/gmi, '$2').replace(/<i( [^\>]*)?\>([^<]*|<[\/]?[bs]\>|<[\/]?span[^\>]*\>)*<\/i\>/gmi, '$2').replace(/<s( [^\>]*)?\>([^<]*|<[\/]?[bi]\>|<[\/]?span[^\>]*\>)*<\/s\>/gmi, '$2');
		}
		Bawl.debug('text that will be checked for unbalanced tags:\n' + Bawl.balancingTextCleaned);
		Bawl.balancingOperations = 0; //prevent infinite loops in case something is screwed up
		Bawl.balancingTextTwoSingleQuotes = Bawl.balancingTextCleaned.match(/(^|[^\'])\'\'($|[^\'])/g);
		if ( Bawl.balancingTextTwoSingleQuotes ) {Bawl.balancingTextTwoSingleQuotes = Bawl.balancingTextTwoSingleQuotes.length;}
		Bawl.balancingTextThreeSingleQuotes = Bawl.balancingTextCleaned.match(/(^|[^\'])\'\'\'($|[^\'])/g);
		if ( Bawl.balancingTextThreeSingleQuotes ) {Bawl.balancingTextThreeSingleQuotes = Bawl.balancingTextThreeSingleQuotes.length;}
		if ( Bawl.balancingTextTwoSingleQuotes / 2 != (Bawl.balancingTextTwoSingleQuotes / 2).toFixed() ) {
			Bawl.balancingOperations = Bawl.balancingOperations + 1;
			Bawl.debug('adding closing \'\' tag (' + Bawl.balancingOperations + ' tags added)');
			Bawl.balancingTags = Bawl.balancingTags + '\'\'';
		}
		if ( Bawl.balancingTextThreeSingleQuotes / 2 != (Bawl.balancingTextThreeSingleQuotes / 2).toFixed() ) {
			Bawl.balancingOperations = Bawl.balancingOperations + 1;
			Bawl.debug('adding closing \'\'\' tag (' + Bawl.balancingOperations + ' tags added)');
			Bawl.balancingTags = Bawl.balancingTags + '\'\'\'';
		}
		Bawl.balancingTextOpenSpan = Bawl.balancingTextCleaned.match(/<span( [^\>]*)?\>/gi);
		Bawl.balancingTextOpenB = Bawl.balancingTextCleaned.match(/<b( [^\>]*)?\>/gi);
		Bawl.balancingTextOpenI = Bawl.balancingTextCleaned.match(/<i( [^\>]*)?\>/gi);
		Bawl.balancingTextOpenS = Bawl.balancingTextCleaned.match(/<s( [^\>]*)?\>/gi);
		if ( Bawl.balancingTextOpenSpan ) {Bawl.balancingTextOpenSpan = Bawl.balancingTextOpenSpan.length;}
		if ( Bawl.balancingTextOpenB ) {Bawl.balancingTextOpenB = Bawl.balancingTextOpenB.length;}
		if ( Bawl.balancingTextOpenI ) {Bawl.balancingTextOpenI = Bawl.balancingTextOpenI.length;}
		if ( Bawl.balancingTextOpenS ) {Bawl.balancingTextOpenS = Bawl.balancingTextOpenS.length;}
		while ( Bawl.balancingOperations < 100 && 0+Bawl.balancingTextOpenSpan > 0 ) {
			Bawl.balancingOperations = Bawl.balancingOperations + 1;
			Bawl.debug('adding closing span tag (' + Bawl.balancingOperations + ' tags added)');
			Bawl.balancingTextOpenSpan = Bawl.balancingTextOpenSpan - 1;
			Bawl.balancingTags = Bawl.balancingTags + '</span>';
		}
		while ( Bawl.balancingOperations < 100 && 0+Bawl.balancingTextOpenB > 0 ) {
			Bawl.balancingOperations = Bawl.balancingOperations + 1;
			Bawl.debug('adding closing B tag (' + Bawl.balancingOperations + ' tags added)');
			Bawl.balancingTextOpenB = Bawl.balancingTextOpenB - 1;
			Bawl.balancingTags = Bawl.balancingTags + '</b>';
		}
		while ( Bawl.balancingOperations < 100 && 0+Bawl.balancingTextOpenI > 0 ) {
			Bawl.balancingOperations = Bawl.balancingOperations + 1;
			Bawl.debug('adding closing I tag (' + Bawl.balancingOperations + ' tags added)');
			Bawl.balancingTextOpenI = Bawl.balancingTextOpenI - 1;
			Bawl.balancingTags = Bawl.balancingTags + '</i>';
		}
		while ( Bawl.balancingOperations < 100 && 0+Bawl.balancingTextOpenS > 0 ) {
			Bawl.balancingOperations = Bawl.balancingOperations + 1;
			Bawl.debug('adding closing S tag (' + Bawl.balancingOperations + ' tags added)');
			Bawl.balancingTextOpenS = Bawl.balancingTextOpenS - 1;
			Bawl.balancingTags = Bawl.balancingTags + '</s>';
		}
		Bawl.debug(Bawl.balancingOperations +	' balancing tags added');
		return Bawl.balancingTags;
	} else {
		Bawl.debug('no text input to balance');
		return '';
	}
};
Bawl.getMostPopularIndent = function(fullPageText, sectionTextGetIndent) {
	if ( $('#useindenttype')[0] && typeof $('#useindenttype')[0].innerText != 'undefined' && $('#useindenttype')[0].innerText.match(/^[\\:\\*\\#$]/) && Bawl.replyLinkParamsOpened.pageTitle == mw.config.get('wgPageName').replace(/ /g,'_') ) {
		Bawl.debug('set indentation type by template #useindenttype');
		return $('#useindenttype')[0].innerText;
	}
	if ( sectionTextGetIndent ) {
		Bawl.textSearchIndentation = sectionTextGetIndent;
	} else {
		Bawl.textSearchIndentation = fullPageText;
	}
	Bawl.debug('find the most popular indentation type');
	Bawl.countHashtagsRegExp = new RegExp('^\#.*' + Bawl.signDateRegExpLocalMonths.source, 'gm');
	Bawl.countColonsRegExp = new RegExp('^\:.*' + Bawl.signDateRegExpLocalMonths.source, 'gm');
	Bawl.countAsterisksColonsRegExp = new RegExp('^[\\*].*' + Bawl.signDateRegExpLocalMonths.source, 'gm');
	if ( Bawl.textSearchIndentation.match(Bawl.countHashtagsRegExp) ) { Bawl.countHashtags = Bawl.textSearchIndentation.match(Bawl.countHashtagsRegExp).length; } else { Bawl.countHashtags = 0; }
	if ( Bawl.textSearchIndentation.match(Bawl.countColonsRegExp) ) { Bawl.countColons = Bawl.textSearchIndentation.match(Bawl.countColonsRegExp).length; } else { Bawl.countColons = 0; }
	if ( Bawl.textSearchIndentation.match(Bawl.countAsterisksColonsRegExp) ) { Bawl.countAsterisks = Bawl.textSearchIndentation.match(Bawl.countAsterisksColonsRegExp).length; } else { Bawl.countAsterisks = 0; }
	Bawl.countCombined = Bawl.countHashtags + Bawl.countColons + Bawl.countAsterisks;
	Bawl.debug('total: ' + Bawl.countCombined + ', hashtags: ' + Bawl.countHashtags + ', colons: ' + Bawl.countColons + ', asterisks: ' + Bawl.countAsterisks);
	if ( Bawl.countAsterisks >= Bawl.countColons && Bawl.countAsterisks >= Bawl.countHashtags && Bawl.countCombined > 0 ) {
		Bawl.debug('the asterisks have it');
		return '*';
	} else if ( Bawl.countColons >= Bawl.countAsterisks && Bawl.countColons >= Bawl.countHashtags && Bawl.countCombined > 0 ) {
		Bawl.debug('the colons have it');
		return ':';
	} else if ( Bawl.countHashtags > Bawl.countColons || Bawl.countHashtags > Bawl.countAsterisks && Bawl.countCombined > 0 ) {
		Bawl.debug('the hashtags have it');
		return '#';
	} else if ( sectionTextGetIndent ) {
		Bawl.debug('unable to determine indendation for section. try full page.');
		return Bawl.getMostPopularIndent(fullPageText);
	} else {
		return Bawl.commentTextIndentWikiDefault;
	}
};
Bawl.stalkUnsubscribe = function(replyLinkParams,mode) {
	if ( Bawl.testValidJSON(window.localStorage.BawlSubs) ) {
		Bawl.currentSubs = JSON.parse(window.localStorage.BawlSubs);
		if ( Bawl.currentSubs[replyLinkParams.pageTitle.replace(/_/g,' ')] && Bawl.currentSubs[replyLinkParams.pageTitle.replace(/_/g,' ')].subs && Bawl.currentSubs[replyLinkParams.pageTitle.replace(/_/g,' ')].subs[replyLinkParams.sectionTitle.replace(/_/g,' ')] ) {
			Bawl.debug('unsubscribing from ' + replyLinkParams.sectionTitle);
			delete Bawl.currentSubs[replyLinkParams.pageTitle.replace(/_/g,' ')].subs[replyLinkParams.sectionTitle.replace(/_/g,' ')];
			window.localStorage.setItem('BawlSubs',JSON.stringify(Bawl.currentSubs));
			if ( Bawl.settings.stalkSyncToPrefs ) {
				Bawl.stalkSyncToPrefs();
			}
			if ( mode == 'bellicon' ) {
				Bawl.processElementArray[Object.keys(Bawl.processElementArray)[replyLinkParams.int]].querySelectorAll('.BawlSVGBellStruckIcon')[0].classList.add('BawlSVGBellIcon');
				Bawl.processElementArray[Object.keys(Bawl.processElementArray)[replyLinkParams.int]].querySelectorAll('.BawlSVGBellStruckIcon')[0].classList.remove('BawlSVGBellStruckIcon');
				Bawl.processElementArray[Object.keys(Bawl.processElementArray)[replyLinkParams.int]].querySelectorAll('.BawlSVGBellIcon')[0].attributes.onclick.nodeValue = 'Bawl.' + Bawl.keyStalkSubscribe + '(Bawl.' + Bawl.keyReplyLinkParams + '[' + replyLinkParams.int + '],\'bellicon\',null,event)';
			}
		}
	}
};
Bawl.keyStalkUnsubscribe = Object.keys(Bawl)[Object.values(Bawl).indexOf(Bawl.stalkUnsubscribe)];
Bawl.stalkSyncToLocalStorage = function() {//this function should only be called directly after loading the page or if userjs-BawlSubs is synced from the server first
	if ( (mw.user.options.get('userjs-BawlSubs') && mw.user.options.get('userjs-BawlSubs').match('"lastviewed"')) || ( window.localStorage.BawlSubs && window.localStorage.BawlSubs.match('"lastviewed"')) ) { //todo: remove this after a few days
		mw.notify('Please reset your Bawl subscriptions');
		return;
	}
	if ( Bawl.testValidJSON(mw.user.options.get('userjs-BawlSubs')) ) {
		Bawl.debug('stalkSyncToLocalStorage: sync subs from preferences to localStorage');
		Bawl.currentPrefSubs = JSON.parse(mw.user.options.get('userjs-BawlSubs'));
		if ( Bawl.testValidJSON(window.localStorage.BawlSubs) ) {
			Bawl.currentSubs = JSON.parse(window.localStorage.BawlSubs);
		} else {
			Bawl.currentSubs = {};
		}
		Bawl.prefSubsKeys = Object.keys(Bawl.currentPrefSubs);
		for (Bawl.prefSubsKeysInt=0;Bawl.prefSubsKeysInt<Bawl.prefSubsKeys.length;Bawl.prefSubsKeysInt++){
			Bawl.debug('stalkSyncToLocalStorage: process subscriptions for page "' + Bawl.prefSubsKeys[Bawl.prefSubsKeysInt] + '"');
			if ( ! Bawl.currentSubs[Bawl.prefSubsKeys[Bawl.prefSubsKeysInt]] ) {
				Bawl.debug('stalkSyncToLocalStorage: found a page title in subs from prefs that isn\'t in your localStorage subs. Could be something you subscribed to on another device, adding to localStorage subs');
				Bawl.currentSubs[Bawl.prefSubsKeys[Bawl.prefSubsKeysInt]] = Bawl.currentPrefSubs[Bawl.prefSubsKeys[Bawl.prefSubsKeysInt]];
			}
			Bawl.prefSubsPageSubs = Bawl.currentPrefSubs[Bawl.prefSubsKeys[Bawl.prefSubsKeysInt]].subs;
			if ( ! Bawl.prefSubsPageSubs ) {
				Bawl.debug('stalkSyncToLocalStorage: there shouldn\'t be pages without subscriptions in your subs in preferences, skipping ' + Bawl.prefSubsKeys[Bawl.prefSubsKeysInt] + '..');
				continue;//skip this iteration in the loop, there are no subscriptions to process for this page title
			}
			Bawl.prefSubsPageSubsKeys = Object.keys(Bawl.prefSubsPageSubs);
			for (Bawl.prefSubsPageSubsKeysInt=0;Bawl.prefSubsPageSubsKeysInt<Bawl.prefSubsPageSubsKeys.length;Bawl.prefSubsPageSubsKeysInt++){
				Bawl.debug('stalkSyncToLocalStorage: process subscription for section "' + Bawl.prefSubsPageSubsKeys[Bawl.prefSubsPageSubsKeysInt] + '" on ' + Bawl.prefSubsKeys[Bawl.prefSubsKeysInt]);
				if ( Bawl.currentSubs[Bawl.prefSubsKeys[Bawl.prefSubsKeysInt]].subs && Bawl.currentSubs[Bawl.prefSubsKeys[Bawl.prefSubsKeysInt]].subs[Bawl.prefSubsPageSubsKeys[Bawl.prefSubsPageSubsKeysInt]] && Bawl.prefSubsPageSubs[Bawl.prefSubsPageSubsKeys[Bawl.prefSubsPageSubsKeysInt]].u < Bawl.currentSubs[Bawl.prefSubsKeys[Bawl.prefSubsKeysInt]].subs[Bawl.prefSubsPageSubsKeys[Bawl.prefSubsPageSubsKeysInt]].u ) {
					Bawl.debug('stalkSyncToLocalStorage: lastupdate (u) for section is higher in localStorage (' + Bawl.currentSubs[Bawl.prefSubsKeys[Bawl.prefSubsKeysInt]].subs[Bawl.prefSubsPageSubsKeys[Bawl.prefSubsPageSubsKeysInt]].u + ') than prefs (' + Bawl.prefSubsPageSubs[Bawl.prefSubsPageSubsKeys[Bawl.prefSubsPageSubsKeysInt]].u + ').');
					Bawl.prefSubsPageSubs[Bawl.prefSubsPageSubsKeys[Bawl.prefSubsPageSubsKeysInt]].u = Bawl.currentSubs[Bawl.prefSubsKeys[Bawl.prefSubsKeysInt]].subs[Bawl.prefSubsPageSubsKeys[Bawl.prefSubsPageSubsKeysInt]].u;
				}
			}
			Bawl.debug('stalkSyncToLocalStorage: sync local subscriptions for page from prefs');
			Bawl.currentSubs[Bawl.prefSubsKeys[Bawl.prefSubsKeysInt]].subs = Bawl.prefSubsPageSubs;
			delete Bawl.lastViewedLocal;
			delete Bawl.lastViewedPrefs;
			if ( Bawl.currentSubs[Bawl.prefSubsKeys[Bawl.prefSubsKeysInt]].v ) {
				Bawl.lastViewedLocal = Bawl.currentSubs[Bawl.prefSubsKeys[Bawl.prefSubsKeysInt]].v;
			}
			if ( Bawl.currentPrefSubs[Bawl.prefSubsKeys[Bawl.prefSubsKeysInt]].v ) {
				Bawl.lastViewedPrefs = Bawl.currentPrefSubs[Bawl.prefSubsKeys[Bawl.prefSubsKeysInt]].v;
			}
			if ( Bawl.lastViewedLocal < Bawl.lastViewedPrefs ) {
				Bawl.debug('stalkSyncToLocalStorage: apply l (lastviewed) for ' + Bawl.prefSubsKeys[Bawl.prefSubsKeysInt] + ' from prefsubs');
				Bawl.currentSubs[Bawl.prefSubsKeys[Bawl.prefSubsKeysInt]].v = Bawl.currentPrefSubs[Bawl.prefSubsKeys[Bawl.prefSubsKeysInt]].v;
			} else if ( Bawl.lastViewedLocal > Bawl.lastViewedPrefs ) {
				Bawl.debug('stalkSyncToLocalStorage: apply l (lastviewed) for ' + Bawl.prefSubsKeys[Bawl.prefSubsKeysInt] + ' from local subs');
				Bawl.currentPrefSubs[Bawl.prefSubsKeys[Bawl.prefSubsKeysInt]].v = Bawl.currentSubs[Bawl.prefSubsKeys[Bawl.prefSubsKeysInt]].v;
			}
			delete Bawl.lastCheckedLocal;
			delete Bawl.lastCheckedPrefs;
			if ( Bawl.currentSubs[Bawl.prefSubsKeys[Bawl.prefSubsKeysInt]].c ) {
				Bawl.lastCheckedLocal = Number(Bawl.currentSubs[Bawl.prefSubsKeys[Bawl.prefSubsKeysInt]].c);
			}
			if ( Bawl.currentPrefSubs[Bawl.prefSubsKeys[Bawl.prefSubsKeysInt]].c ) {
				Bawl.lastCheckedPrefs = Number(Bawl.currentPrefSubs[Bawl.prefSubsKeys[Bawl.prefSubsKeysInt]].c);
			}
			if ( Bawl.lastCheckedLocal < Bawl.lastCheckedPrefs ) {
				Bawl.debug('stalkSyncToLocalStorage: apply c (lastchecked) for ' + Bawl.prefSubsKeys[Bawl.prefSubsKeysInt] + ' from prefsubs');
				Bawl.currentSubs[Bawl.prefSubsKeys[Bawl.prefSubsKeysInt]].c = Bawl.currentPrefSubs[Bawl.prefSubsKeys[Bawl.prefSubsKeysInt]].c;
			} else if ( Bawl.lastCheckedLocal > Bawl.lastCheckedPrefs ) {
				Bawl.debug('stalkSyncToLocalStorage: apply c (lastchecked) for ' + Bawl.prefSubsKeys[Bawl.prefSubsKeysInt] + ' from local subs');
				Bawl.currentPrefSubs[Bawl.prefSubsKeys[Bawl.prefSubsKeysInt]].c = Bawl.currentSubs[Bawl.prefSubsKeys[Bawl.prefSubsKeysInt]].c;
			}
		}
		Bawl.localSubsKeys = Object.keys(Bawl.currentSubs);
		for (Bawl.localSubsKeysInt=0;Bawl.localSubsKeysInt<Bawl.localSubsKeys.length;Bawl.localSubsKeysInt++){
			if ( ! Bawl.currentPrefSubs[Bawl.localSubsKeys[Bawl.localSubsKeysInt]] && Bawl.currentSubs[Bawl.localSubsKeys[Bawl.localSubsKeysInt]].subs ) {
				Bawl.debug('stalkSyncToLocalStorage: found a page title in localStorage subs that isn\'t in your subs in prefs. Could be something that got removed on another device, removing subs from localStorage');
				delete Bawl.currentSubs[Bawl.localSubsKeys[Bawl.localSubsKeysInt]].subs;
			}
		}
		Bawl.debug('stalkSyncToLocalStorage: write to localStorage');
		window.localStorage.setItem('BawlSubs',JSON.stringify(Bawl.currentSubs));
	}
};
if ( Bawl.settings.stalkSyncToPrefs ) {
	Bawl.stalkSyncToLocalStorage();
}
Bawl.stalkSyncToPrefs = function() {
	if ( ! Bawl.testValidJSON(window.localStorage.BawlSubs) ) {
		Bawl.debug('no valid window.localStorage.BawlSubs JSON found');
		return;
	}
	Bawl.currentSubs = JSON.parse(window.localStorage.BawlSubs);
	for (Bawl.compactSubsForPrefsInt=0;Bawl.compactSubsForPrefsInt<Object.keys(Bawl.currentSubs).length;Bawl.compactSubsForPrefsInt++) {
		if ( typeof Bawl.currentSubs[Object.keys(Bawl.currentSubs)[Bawl.compactSubsForPrefsInt]].subs == 'undefined' ) {
			Bawl.debug(Object.keys(Bawl.currentSubs)[Bawl.compactSubsForPrefsInt] + ' is an entry without subscriptions, remove before syncing to prefs');
			delete Bawl.currentSubs[Object.keys(Bawl.currentSubs)[Bawl.compactSubsForPrefsInt]];
		}
	}
	Bawl.newSubsLength = new Blob([JSON.stringify(Bawl.currentSubs)]).size;//depending on characters used, .length isn't the same as the byte length
	if ( Bawl.newSubsLength > 65535 ) {
		Bawl.newSubsArr = [];
		Bawl.newSubsObj = {};
		for ( Bawl.newSubsInt=0;Bawl.newSubsInt < Object.keys(Bawl.currentSubs).length;Bawl.newSubsInt++) {
			Bawl.newSubsArr.push(Bawl.currentSubs[Bawl.newSubsInt].v);
			Bawl.newSubsObj[Bawl.currentSubs[Bawl.newSubsInt].v] = Object.keys(Bawl.currentSubs)[Bawl.newSubsInt];
		}
		Bawl.newSubsArrSorted = Bawl.newSubsArr.sort(function(a, b){return a - b;});
	}
	while ( Bawl.newSubsLength > 65535 ) {
		Bawl.stalkPageToUnSub = Bawl.newSubsObj[Bawl.newSubsArrSorted[0]];
		Bawl.debug('subscriptions JSON is longer than 65535 characters, the maximum for a user preference. Dumping oldest entry: ' + Bawl.stalkPageToUnSub);
		delete Bawl.currentSubs[Bawl.stalkPageToUnSub];
		Bawl.newSubsArrSorted.shift();
		Bawl.newSubsLength = new Blob([JSON.stringify(Bawl.currentSubs)]).size;
	}
	Bawl.debug('subscriptions, under 65535 bytes:');
	Bawl.debug(Bawl.currentSubs);
	api.postWithEditToken( {format: 'json', action: 'options', change:['userjs-BawlSubs=' + JSON.stringify(Bawl.currentSubs)] } ).then( function ( data ) {
		Bawl.debug(data);
		if ( data.options == 'success' ) {
			Bawl.debug('updated subscriptions in preferences');
			mw.user.options.set({'userjs-BawlSubs':JSON.stringify(Bawl.currentSubs)});
		}
	}, function ( code, data ) { Bawl.APIError(code, data);
	});
};
Bawl.stalkSubscribe = function(replyLinkParams,mode,wikitextID,linkElementSub) {
	delete Bawl.stalkSectionID;
	Bawl.debug('subscribe to thread');
	Bawl.debug(replyLinkParams);
	Bawl.stalkPageTitle = replyLinkParams.pageTitle.replace(/_/g,' ');
	if ( wikitextID ) {
		Bawl.debug('got wikitextID as stalkSectionID from aborted run');
		Bawl.stalkSectionID = wikitextID;
	} else if ( replyLinkParams.origReplyTo && replyLinkParams.origTimestamp && replyLinkParams.origTimestamp.match(/^[0-9]{13,14}$/) ) {
		Bawl.debug('use locator as stalkSectionID');
		Bawl.stalkSectionID = replyLinkParams.origReplyTo + ':' + replyLinkParams.origTimestamp;
	} else if ( replyLinkParams.pageTitle && linkElementSub ) {
		Bawl.debug('search HTML for locator to use as stalkSectionID');
		Bawl.stalkCheckElement = linkElementSub.target.parentElement;
		for (Bawl.getStalkHeaderInt=0;Bawl.getStalkHeaderInt<10;Bawl.getStalkHeaderInt++) {
			Bawl.stalkCheckElement = Bawl.stalkCheckElement.parentElement;
			if ( Bawl.stalkCheckElement.nodeName.match(/^H[1-6]$/) ) {
				Bawl.debug('found header to stalk');
				Bawl.stalkSectionTitle = Bawl.stalkCheckElement.childNodes[0].innerText;
				break;
			}
		}
		if ( ! Bawl.stalkCheckElement.nodeName.match(/^H[1-6]$/) ) {
			Bawl.addScrewedLink('subscribe_section_failure_no_header','Could not subscribe: could not locate header element.');
			return false;
		}
		for (Bawl.subscribeElementsInt=0;Bawl.subscribeElementsInt < 20;Bawl.subscribeElementsInt++) {
			Bawl.debug('check next element ' + Bawl.subscribeElementsInt + ' for locator');
			Bawl.stalkCheckElement = Bawl.stalkCheckElement.nextElementSibling;
			Bawl.debug(Bawl.stalkCheckElement);
			if ( Bawl.stalkCheckElement != null && ! Bawl.stalkCheckElement.nodeName.match(/^H[1-6]$/) ) {
				Bawl.stalkFindLocator = Bawl.stalkCheckElement.innerHTML.match(/<span id="([^:]*:[0-9]{13,14})(:[^"]*)(" class="BawlCmt)/);
				if ( Bawl.stalkFindLocator ) {
					Bawl.stalkSectionID = Bawl.stalkFindLocator[1];
					Bawl.debug('got stalkSectionID: ' + Bawl.stalkSectionID);
					break;
				}
			} else {
				Bawl.debug('ran into next section, no locator found. will search wikitext for a timestamp instead');
				break;
			}
		}
	}
	if ( ! Bawl.stalkSectionID ) {
		Bawl.debug('stalkSectionID not yet available, get a timestamp from wikitext');
		api.get( {action: 'query', export: 'true', format: 'json', titles: Bawl.stalkPageTitle} ).then( function ( data ) {
			Bawl.debug(data);
			Bawl.stalkWikiText = Bawl.getWikitextFromExport(data.query.export["*"]);
			Bawl.stalkWikiTextSection = Bawl.getInsertionPointSection(replyLinkParams, Bawl.stalkWikiText).sectiontext;
			if ( Bawl.stalkWikiTextSection == Bawl.stalkWikiText ) {
				Bawl.debug('couldn\'t locate section');
				Bawl.addScrewedLink('subscribe_section_failure','Could not subscribe: could not locate section.');
				return false;
			} else {
				Bawl.stalkSectionSigDate = Bawl.stalkWikiTextSection.match(Bawl.signDateRegExpLocalMonths);
				if ( Bawl.stalkSectionSigDate ) {
					Bawl.debug('found some signature timestamp in section to use as subscriptionID');
					Bawl.stalkSectionIDRegExp = new RegExp('.*' + Bawl.escapeRegExp(Bawl.stalkSectionSigDate[0]));
					Bawl.stalkSectionID = Bawl.stalkWikiTextSection.match(Bawl.stalkSectionIDRegExp)[0];
					if ( Bawl.stalkSectionID.length > ( Bawl.stalkSectionSigDate[0].length + 30 ) ) {
						Bawl.stalkSectionID = Bawl.stalkSectionID.slice(0,30).replace(/ [^ ]*$/,'') + 'LEGACYTIMESTAMP' + Bawl.stalkSectionSigDate[0];
					} else {
						Bawl.stalkSectionID = Bawl.stalkSectionID;
					}
					Bawl.stalkSubscribe(replyLinkParams,mode,Bawl.stalkSectionID);
					return;
				}
			}
			if ( ! Bawl.stalkSectionID ) {
				Bawl.debug('no timestamp found to subscribe to');
				Bawl.addScrewedLink('subscribe_failure_no_timestamp','Could not subscribe: could not locate any timestamp within section.');
				return;
			}
		} );
		return false;
	}
	if ( window.localStorage.BawlSubs && Bawl.testValidJSON(window.localStorage.BawlSubs) ) {
		Bawl.currentSubs = JSON.parse(window.localStorage.BawlSubs);
	} else {
		Bawl.currentSubs = {};
	}
	if ( ! Bawl.currentSubs[Bawl.stalkPageTitle] ) {
		Bawl.currentSubs[Bawl.stalkPageTitle] = { 'v':Bawl.timestampInit,'c':Bawl.timestampInit,'subs':{} };
	}
	Bawl.stalkNewSub = Bawl.currentSubs[Bawl.stalkPageTitle];
	if ( typeof replyLinkParams.sectionTitle == 'string' ) {
		Bawl.stalkSectionTitle = replyLinkParams.sectionTitle;
	} else if ( Bawl.replyLinkParamsOpened.type == 'newsection' ) {
		Bawl.stalkSectionTitle = Bawl.flattenWikiText(Bawl.UITextInputTitle.getValue());
	} else if ( typeof Bawl.stalkSectionTitle != 'string' ) {
		Bawl.addScrewedLink('subscribe_failure_no_sectiontitle','Could not subscribe: could not find the name of this section.');
		return;
	}
	if ( typeof Bawl.stalkNewSub.subs == 'undefined' ) {
		Bawl.stalkNewSub.subs = {};
	}
	if ( typeof Bawl.stalkNewSub.subs[Bawl.stalkSectionTitle] == 'undefined' ) {
		Bawl.stalkNewSub.subs[Bawl.stalkSectionTitle] = { 'id':Bawl.stalkSectionID,'u':Bawl.timestampInit}; //is not strictly the correct value for u (lastupdate), but it matters not as we just want to know if any comment was placed since the last time we viewed the page
		Bawl.currentSubs[Bawl.stalkPageTitle] = Bawl.stalkNewSub;
		Bawl.debug('setting new subscriptions for page:');
		Bawl.debug(Bawl.currentSubs[Bawl.stalkPageTitle]);
		window.localStorage.setItem('BawlSubs',JSON.stringify(Bawl.currentSubs));
		if ( Bawl.settings.stalkSyncToPrefs ) {
			Bawl.stalkSyncToPrefs();
		}
		if ( mode == 'bellicon' ) {
			Bawl.processElementArray[Object.keys(Bawl.processElementArray)[replyLinkParams.int]].querySelectorAll('.BawlSVGBellIcon')[0].classList.add('BawlSVGBellStruckIcon');
			Bawl.processElementArray[Object.keys(Bawl.processElementArray)[replyLinkParams.int]].querySelectorAll('.BawlSVGBellIcon')[0].classList.remove('BawlSVGBellIcon');
			Bawl.processElementArray[Object.keys(Bawl.processElementArray)[replyLinkParams.int]].querySelectorAll('.BawlSVGBellStruckIcon')[0].attributes.onclick.nodeValue = 'Bawl.' + Bawl.keyStalkUnsubscribe + '(Bawl.' + Bawl.keyReplyLinkParams + '[' + replyLinkParams.int + '],\'bellicon\')';
		}
	}
};
Bawl.keyStalkSubscribe = Object.keys(Bawl)[Object.values(Bawl).indexOf(Bawl.stalkSubscribe)];
Bawl.stalkLastViewed = function(replyLinkParams,mode) {
	Bawl.stalkPageTitle = replyLinkParams.pageTitle.replace(/_/g,' ');
	if ( window.localStorage.BawlSubs && Bawl.testValidJSON(window.localStorage.BawlSubs) ) {
		Bawl.stalkLastViewedSubs = JSON.parse(window.localStorage.BawlSubs);
		if ( Bawl.stalkLastViewedSubs[Bawl.stalkPageTitle] ) {
			if ( mode == 'v' ) {
				return Bawl.stalkLastViewedSubs[Bawl.stalkPageTitle].v;
			} else if ( mode == 'c' ) {
				return Bawl.stalkLastViewedSubs[Bawl.stalkPageTitle].c;
			} else if ( mode == 'updatec' ) {
				Bawl.stalkLastViewedSubs[Bawl.stalkPageTitle].c = new Date().getTime();
				window.localStorage.setItem('BawlSubs',JSON.stringify(Bawl.stalkLastViewedSubs));
			}
		} else {
			return false;
		}
	} else {
			return false;
	}
};
Bawl.stalkCheckSubscriptions = function() {
	if ( Bawl.testValidJSON(mw.user.options.get('userjs-BawlTackOnEchoGlobal')) && Object.keys(JSON.parse(mw.user.options.get('userjs-BawlTackOnEchoGlobal'))).length > 0 ) {
		Bawl.debug('there are unread notifications waiting for you already. to prevent duplicates (and wasting resources in general) we won\'t check until you check those');
		Bawl.tackOnEchoIconHack();
		return;
	}
	if ( Bawl.testValidJSON(window.localStorage.BawlSubs) ) {
		Bawl.checkExistingSubs = JSON.parse(window.localStorage.BawlSubs);
		if ( Bawl.settings.stalkWatchListCmts && typeof Bawl.checkExistingSubs.unreadCmts != 'undefined' && mw.config.get('wgCanonicalSpecialPageName') == 'Watchlist' || ( mw.config.get('wgTitle') == 'BawlSubs' && mw.config.get('wgNamespaceNumber') == -1 ) ) {
			Bawl.debug('show you the unread comments you haven\'t acked yet');
			Bawl.stalkWatchList();
			return;
		} else if ( Bawl.settings.stalkWatchListCmts && typeof Bawl.checkExistingSubs.unreadCmts != 'undefined' ) {
			Bawl.debug('you already have unread comments waiting for you. Not checking again until you ack those');
			mw.notify($('<a href="' + mw.config.get('wgArticlePath').replace('$1','Special:BawlSubs') + '">' + Bawl.msgs.readYaCmts + '</a>'));
			return;
		}
		Bawl.checkExistingSubsLastviewArr = [];
		Bawl.checkExistingSubsLastviewObj = {};
		for ( Bawl.checkExistingSubsInt=0;Bawl.checkExistingSubsInt < Bawl.checkExistingSubs.length;Bawl.checkExistingSubsInt++) {
			Bawl.checkExistingSubsLastviewArr.push(Bawl.checkExistingSubs[Bawl.checkExistingSubsInt].v);
			Bawl.checkExistingSubsLastviewObj[Bawl.checkExistingSubs[Bawl.checkExistingSubsInt].v] = Object.keys(Bawl.checkExistingSubs)[Bawl.checkExistingSubsInt];
		}
		Bawl.checkExistingSubsLastviewArrSorted = Bawl.checkExistingSubsLastviewArr.sort(function(a, b){return a - b;});
		while ( Bawl.checkExistingSubsLastviewArrSorted.length > Bawl.settings.stalkMaxSubs * 0.9 ) { //dump subbed pages until we are 10% under the limit. So this operation won't have to run every time once the limit has been reached
			Bawl.stalkPageToUnSub = Bawl.checkExistingSubsLastviewObj[Bawl.checkExistingSubsLastviewArrSorted[0]];
			Bawl.debug('maximum page subscriptions too high, unsubscribing from ' + Bawl.stalkPageToUnSub);
			delete Bawl.checkExistingSubs[Bawl.stalkPageToUnSub];
			Bawl.checkExistingSubsLastviewArrSorted.shift();
		}
		Bawl.stalkTitlesToCheck = Object.keys(Bawl.checkExistingSubs);
		Bawl.stalkTitlesToCheckString = '';
		for(Bawl.stalkTitlesToCheckInt=0;Bawl.stalkTitlesToCheckInt<Bawl.stalkTitlesToCheck.length;Bawl.stalkTitlesToCheckInt++){
			if ( typeof Bawl.checkExistingSubs[Bawl.stalkTitlesToCheck[Bawl.stalkTitlesToCheckInt]].subs == 'object' && Object.keys(Bawl.checkExistingSubs[Bawl.stalkTitlesToCheck[Bawl.stalkTitlesToCheckInt]].subs).length > 0 ) {
				Bawl.debug(Bawl.stalkTitlesToCheck[Bawl.stalkTitlesToCheckInt] + ' has subscriptions, adding to title list for api request');
				Bawl.stalkTitlesToCheckString = Bawl.stalkTitlesToCheck[Bawl.stalkTitlesToCheckInt] + '|' + Bawl.stalkTitlesToCheckString;
			} else {
				Bawl.debug(Bawl.stalkTitlesToCheck[Bawl.stalkTitlesToCheckInt] + ' appears to have no subscriptions. Probably just used to track what sections to collapse/which comments to mark as new');
			}
		}
		Bawl.stalkTitlesToCheckString = Bawl.stalkTitlesToCheckString.replace(/\|$/,'');
		Bawl.stalkUnreadComments = {};
		if ( Bawl.stalkTitlesToCheckString == '' ) {
			Bawl.debug('no titles to check?');
			return;
		}
		api.get( {action: 'query', format: 'json', prop:'revisions', titles: Bawl.stalkTitlesToCheckString, rvprop:'timestamp', rvslots:'*'} ).then( function ( data ) {
			Bawl.debug('got revision data for subs:');
			Bawl.debug(data);
			Bawl.stalkPagesWithChanges = [];
			Bawl.tackOnEchoCmtsArray = [];
			for(Bawl.stalkCheckUpdateInt=0;Bawl.stalkCheckUpdateInt < Object.keys(data.query.pages).length;Bawl.stalkCheckUpdateInt++){
				if ( Object.keys(data.query.pages)[Bawl.stalkCheckUpdateInt] > 0 ) {
					Bawl.stalkProcessTitle = data.query.pages[Object.keys(data.query.pages)[Bawl.stalkCheckUpdateInt]].title;
					Bawl.stalkLastUpdate = new Date(data.query.pages[Object.keys(data.query.pages)[Bawl.stalkCheckUpdateInt]].revisions[0].timestamp).getTime();
					Bawl.stalkLastviewKnown = Bawl.stalkLastViewed({'pageTitle':Bawl.stalkProcessTitle},'v');
					if ( Bawl.stalkLastUpdate > Bawl.stalkLastviewKnown ) {
						Bawl.debug('adding "' + Bawl.stalkProcessTitle + '" to array to obtain wikitext as the last change to the page was after the last time you viewed the page');
						Bawl.stalkPagesWithChanges.push(Bawl.stalkProcessTitle);
					}
				}
			}
			if ( Bawl.stalkPagesWithChanges.length > 0 ) {
				Bawl.stalkPagesWithChangesString = '';
				Bawl.stalkUnreadCommentsAll = JSON.parse(window.localStorage.BawlSubs);
				for(Bawl.stalkPagesWithChangesInt=0;Bawl.stalkPagesWithChangesInt<Bawl.stalkPagesWithChanges.length;Bawl.stalkPagesWithChangesInt++){
					if ( Bawl.stalkPagesWithChanges[Bawl.stalkPagesWithChangesInt] != 'unreadCmts' ) {
						Bawl.stalkPagesWithChangesString = Bawl.stalkPagesWithChanges[Bawl.stalkPagesWithChangesInt] + '|' + Bawl.stalkPagesWithChangesString;
					}
				}
				Bawl.stalkPagesWithChangesString = Bawl.stalkPagesWithChangesString.replace(/\|$/,'');
				api.get( {action: 'query', format: 'json', prop:'revisions', titles: Bawl.stalkPagesWithChangesString, rvprop:'content', rvslots:'*'} ).then( function ( data ) {
					Bawl.debug('obtained wikitext for changed pages:');
					Bawl.debug(data);
					Bawl.stuff = data;
					for(Bawl.stalkCheckUpdateInt=0;Bawl.stalkCheckUpdateInt < Object.keys(data.query.pages).length;Bawl.stalkCheckUpdateInt++){
						if ( Object.keys(data.query.pages)[Bawl.stalkCheckUpdateInt] > 0 ) {
							Bawl.stalkProcessTitle = data.query.pages[Object.keys(data.query.pages)[Bawl.stalkCheckUpdateInt]].title;
							Bawl.debug('search "' + Bawl.stalkProcessTitle + '" for subscribed sections');
							Bawl.stalkProcessContent = data.query.pages[Object.keys(data.query.pages)[Bawl.stalkCheckUpdateInt]].revisions[0].slots.main["*"];
							Bawl.stalkProcessContentSplit = Bawl.stalkProcessContent.split('\n');
							Bawl.stalkSubListForPage = Object.keys(Bawl.checkExistingSubs[Bawl.stalkProcessTitle].subs);
							for(Bawl.stalkSubListForPageInt=0;Bawl.stalkSubListForPageInt < Bawl.stalkSubListForPage.length;Bawl.stalkSubListForPageInt++) {
								Bawl.debug('getting section ID..');
								Bawl.stalkTrySectionID = new RegExp(Bawl.escapeRegExp(Bawl.checkExistingSubs[Bawl.stalkProcessTitle].subs[Object.keys(Bawl.checkExistingSubs[Bawl.stalkProcessTitle].subs)[Bawl.stalkSubListForPageInt]].id).replace('LEGACYTIMESTAMP','.*'));
								Bawl.debug('search wikitext for "' + Bawl.stalkTrySectionID + '" to find the section to analyze');
								Bawl.stalkContentSectionNum = 0;
								Bawl.stalkContentSectionNumFound = false;
								for(Bawl.stalkContentLineInt=0;Bawl.stalkContentLineInt < Bawl.stalkProcessContentSplit.length;Bawl.stalkContentLineInt++) {
									if ( Bawl.stalkProcessContentSplit[Bawl.stalkContentLineInt].match(Bawl.stalkTrySectionID) ) {
										Bawl.debug('found section identifier');
										Bawl.stalkContentSectionNumFound = true;
										break;
									} else if (Bawl.stalkProcessContentSplit[Bawl.stalkContentLineInt].match(/^=.*=[ ]*$/) ) {
										Bawl.stalkContentSectionNum++;
									}
								}
								Bawl.lastKnownUpdate = Bawl.checkExistingSubs[Bawl.stalkProcessTitle].subs[Object.keys(Bawl.checkExistingSubs[Bawl.stalkProcessTitle].subs)[Bawl.stalkSubListForPageInt]].u;
								if ( Bawl.stalkContentSectionNumFound ) {
									Bawl.stalkFoundContentSectionText = Bawl.getSectionByNum(Bawl.stalkProcessContent,Bawl.stalkContentSectionNum);
									Bawl.debug('got sectiontext to search for new comments:');
									Bawl.debug(Bawl.stalkFoundContentSectionText);
									Bawl.stalkFoundContentSectionTextSplit = Bawl.stalkFoundContentSectionText.split('\n');
									Bawl.stalkUnreadCommentMaybe = '';
									Bawl.stalkSectionAnchor = '';
									Bawl.stalkLastViewedThisPage = Bawl.stalkLastViewed({'pageTitle':Bawl.stalkProcessTitle},'v');
									Bawl.stalkLastCheckedThisPage = Bawl.stalkLastViewed({'pageTitle':Bawl.stalkProcessTitle},'c');
									Bawl.getUserFromWikitext = new RegExp('\\[\\[(' + Bawl.userNSWikitextRegExpPart + '|' + Bawl.basicmsgs.specialcontribs + '\/)([^\\]\\|]*)');
									Bawl.getUserFromWikitextGlobal = new RegExp(Bawl.getUserFromWikitext.source,'g');
									for(Bawl.stalkFoundSectionSplitInt=0;Bawl.stalkFoundSectionSplitInt < Bawl.stalkFoundContentSectionTextSplit.length;Bawl.stalkFoundSectionSplitInt++){
										Bawl.debug('line: "' + Bawl.stalkFoundContentSectionTextSplit[Bawl.stalkFoundSectionSplitInt]);
										if ( Bawl.stalkFoundContentSectionTextSplit[Bawl.stalkFoundSectionSplitInt].match(/^=.*=$/) ) {
											Bawl.debug('that\'s a section header, not a comment');
											Bawl.stalkSectionAnchor = Bawl.flattenWikiText(Bawl.stalkFoundContentSectionTextSplit[Bawl.stalkFoundSectionSplitInt].replace(/^[= ]*(.*[^= ])[= ]*$/,'$1'));
										} else if ( Bawl.stalkFoundContentSectionTextSplit[Bawl.stalkFoundSectionSplitInt].match(Bawl.signDateRegExpLocalMonths) ) {
											Bawl.debug('line contains a timestamp');
											Bawl.stalkTimestamp = Bawl.sigDateToMachineReadable(Bawl.stalkFoundContentSectionTextSplit[Bawl.stalkFoundSectionSplitInt].match(Bawl.signDateRegExpLocalMonths)[0]);
											if ( Bawl.stalkTimestamp > Bawl.stalkLastViewedThisPage && Bawl.stalkTimestamp > Bawl.stalkLastCheckedThisPage ) {
												Bawl.debug('A NEW COMMENT!! (stalkLastViewedThisPage: ' + Bawl.stalkLastViewedThisPage + ', stalkLastCheckedThisPage: ' + Bawl.stalkLastCheckedThisPage);
												if ( Bawl.lastKnownUpdate < Bawl.stalkTimestamp ) {
													Bawl.checkExistingSubs[Bawl.stalkProcessTitle].subs[Object.keys(Bawl.checkExistingSubs[Bawl.stalkProcessTitle].subs)[Bawl.stalkSubListForPageInt]].u = Bawl.lastKnownUpdate;
													window.localStorage.setItem('BawlSubs',JSON.stringify(Bawl.checkExistingSubs));
												}
												Bawl.stalkGetUserFromWikiText = Bawl.stalkFoundContentSectionTextSplit[Bawl.stalkFoundSectionSplitInt].match(Bawl.getUserFromWikitextGlobal);
												Bawl.stalkGetLastUser = Bawl.stalkGetUserFromWikiText[Bawl.stalkGetUserFromWikiText.length - 1].match(Bawl.getUserFromWikitext)[2].replace(/_/g,' ');
												Bawl.stalkNewNotification = {'date':Bawl.stalkTimestamp,'at':mw.config.get('wgServerName')+mw.config.get('wgArticlePath'),'page':Bawl.stalkProcessTitle,'icon':'Bawl','user':Bawl.stalkGetLastUser,'section':Bawl.stalkSectionAnchor,'msg':'newcmt'};
												if ( Bawl.stalkGetLastUser != Bawl.userName ) {//don't notify me about my own comments
													Bawl.tackOnEchoCmtsArray.push(Bawl.stalkNewNotification);
													Bawl.debug('pushed new notification for comment by ' + Bawl.stalkGetLastUser + ' into tackOnEchoCmtsArray:');
												}
												Bawl.debug(Bawl.tackOnEchoCmtsArray);
												while ( typeof Bawl.stalkUnreadComments[Bawl.stalkTimestamp] != 'undefined' ) {
													Bawl.stalkTimestamp = Bawl.stalkTimestamp+1;//to ensure uniqueness for our array. bad things might happen when exceeding 60000 comments/minute, but Mediawiki will collapse long before that
												}
												Bawl.stalkUnreadComments[Bawl.stalkTimestamp] = '[[' + Bawl.stalkProcessTitle + '#' + Bawl.stalkSectionAnchor + '|&nbsp;&nbsp;→&nbsp;&nbsp;]]' + Bawl.stalkUnreadCommentMaybe + Bawl.stalkFoundContentSectionTextSplit[Bawl.stalkFoundSectionSplitInt];
												Bawl.stalkUnreadCommentMaybe = '';
											} else {
												Bawl.debug('old news (' + Bawl.stalkTimestamp + '), maximum age is ' + Bawl.stalkLastViewedThisPage + ' (' + new Date(Bawl.stalkLastViewedThisPage) + ') for v (lastviewed) or ' + Bawl.stalkLastCheckedThisPage + ' (' + new Date(Bawl.stalkLastCheckedThisPage) + ') for c (lastchecked)');
											}
											Bawl.stalkUnreadCommentMaybe = '';
										} else {
											Bawl.stalkUnreadCommentMaybe = Bawl.stalkUnreadCommentMaybe + '\n' + Bawl.stalkFoundContentSectionTextSplit[Bawl.stalkFoundSectionSplitInt];
										}
									}
									Bawl.stalkUnreadCommentsAll.unreadCmts = Bawl.stalkUnreadComments;
								} else {
									Bawl.debug('subscribed section NOT FOUND, tossing subscribtion (if it just moved we\'ll resubscribe later)');
									Bawl.lostSubLastUpdate = Bawl.checkExistingSubs[Bawl.stalkProcessTitle].subs[Object.keys(Bawl.checkExistingSubs[Bawl.stalkProcessTitle].subs)[Bawl.stalkSubListForPageInt]].u;
									Bawl.lostSubID = Bawl.checkExistingSubs[Bawl.stalkProcessTitle].subs[Object.keys(Bawl.checkExistingSubs[Bawl.stalkProcessTitle].subs)[Bawl.stalkSubListForPageInt]].id;
									Bawl.subsWithSubTossed = JSON.parse(JSON.stringify(Bawl.checkExistingSubs));
									delete Bawl.subsWithSubTossed[Bawl.stalkProcessTitle].subs[Object.keys(Bawl.checkExistingSubs[Bawl.stalkProcessTitle].subs)[Bawl.stalkSubListForPageInt]];
									window.localStorage.setItem('BawlSubs',JSON.stringify(Bawl.subsWithSubTossed));
									if ( Bawl.lastKnownUpdate < ((new Date().getTime())-259200000) ) {
										Bawl.debug('last known update for "' + Object.keys(Bawl.checkExistingSubs[Bawl.stalkProcessTitle].subs)[Bawl.stalkSubListForPageInt] + '" > 3 days ago, assume archived, nothing to do');
									} else {
										Bawl.debug('last known update for "' + Object.keys(Bawl.checkExistingSubs[Bawl.stalkProcessTitle].subs)[Bawl.stalkSubListForPageInt] + '" < 3 days ago, but where did it go??');
										Bawl.searchForMissingSectionID = Bawl.checkExistingSubs[Bawl.stalkProcessTitle].subs[Object.keys(Bawl.checkExistingSubs[Bawl.stalkProcessTitle].subs)[Bawl.stalkSubListForPageInt]].id;
										if ( Bawl.searchForMissingSectionID.match(/LEGACYTIMESTAMP/) ) {
											Bawl.searchForMissingSectionTerm = 'insource:"' + Bawl.searchForMissingSectionID.split('LEGACYTIMESTAMP')[0] + '" insource:"' + Bawl.searchForMissingSectionID.split('LEGACYTIMESTAMP')[1] + '"';
											Bawl.searchForMissingSectionRegExp = new RegExp(Bawl.escapeRegExp(Bawl.searchForMissingSectionID.split('LEGACYTIMESTAMP')[0]) + '.*' + Bawl.escapeRegExp(Bawl.searchForMissingSectionID.split('LEGACYTIMESTAMP')[1]));
										} else {
											Bawl.searchForMissingSectionTerm = 'insource:"' + Bawl.searchForMissingSectionID + '"';
											Bawl.searchForMissingSectionRegExp = new RegExp(Bawl.escapeRegExp(Bawl.searchForMissingSectionID));
										}
										Bawl.searchForMissingSectionTitles = [];
										Bawl.searchForMissingSectionParams = {'action':'query','format':'json','formatversion':'2','list':'search','srsearch':Bawl.searchForMissingSectionTerm,'srprop':'','srnamespace':'*','srlimit':'10'};
										Bawl.stalkSearchForMissingSection(Bawl.searchForMissingSectionParams);
									}
									//last known update > 3 days ago: toss it. last known update < 3 days ago? track it and update the pagetitle, toss if not trackable
									//lost cause for this run, just get it next time
								}
							}//end loop stalkSubListForPageInt
							Bawl.stalkLastViewed({'pageTitle':Bawl.stalkProcessTitle},'updatec');
						} else {
							Bawl.debug('requested invalid page name (negative stalkCheckUpdateInt)');
						}
					}//end loop to analyze wikitext of one page (stalkCheckUpdateInt)
					if ( Bawl.settings.stalkSyncToPrefs ) {
						Bawl.stalkSyncToPrefs();
					}
					if ( typeof Bawl.stalkUnreadCommentsAll.unreadCmts == 'undefined' ) {
						Bawl.debug('there are no unread comments to display');
						return;
					} else if ( Bawl.settings.stalkWatchListCmts || Bawl.settings.stalkTackOnEcho ) {
						if ( Bawl.settings.stalkWatchListCmts ) {
							Bawl.debug('run stalkWatchList()');
							Bawl.stalkWatchList();
						}
						if ( Bawl.settings.stalkTackOnEcho && Bawl.tackOnEchoCmtsArray.length > 0 ) {
							Bawl.debug('add notifications for new comments to tackOnEcho');
							Bawl.tackOnEchoWrite(Bawl.tackOnEchoCmtsArray);
						}
					}
				}, function ( code, data ) { Bawl.APIError(code, data);
				});
			} else {
				Bawl.debug('no pages appear to have changed since you last viewed them');
			}
		}, function ( code, data ) { Bawl.APIError(code, data);
		});
	} else {
		Bawl.debug('no subscriptions found in localStorage');
	}
};
Bawl.stalkSearchForMissingSection = function(params) {
	api.get(Bawl.searchForMissingSectionParams).then(function(data) {
		if ( data.query.searchinfo.totalhits > 0 ) {
			for (Bawl.searchMissingSectionInt=0;Bawl.searchMissingSectionInt<data.query.search.length;Bawl.searchMissingSectionInt++) {
				if ( ! Bawl.searchForMissingSectionTitles.includes(data.query.search[Bawl.searchMissingSectionInt].title) ) {
					Bawl.searchForMissingSectionTitles.push(data.query.search[Bawl.searchMissingSectionInt].title);
				}
			}
			Bawl.searchForMissingSectionResultsParams = {'action':'query','format':'json','prop':'revisions','rvprop':'content','titles':Bawl.searchForMissingSectionTitles};
			api.get(Bawl.searchForMissingSectionResultsParams).then(function(data) {
				Bawl.debug('obtained titles: ' + Bawl.searchForMissingSectionResultsParams.titles.toString());
				for ( Bawl.searchForMissingSectionPageTitleInt=0;Bawl.searchForMissingSectionPageTitleInt<Object.keys(data.query.pages).length;Bawl.searchForMissingSectionPageTitleInt++) {
					Bawl.searchForMissingSectionPageTitle = data.query.pages[Object.keys(data.query.pages)[Bawl.searchForMissingSectionPageTitleInt]].title;
					Bawl.debug('searching ' + Bawl.searchForMissingSectionPageTitle + ' for the missing section with ID ' + Bawl.searchForMissingSectionID);
					Bawl.searchForMissingSectionPageWikitext = data.query.pages[Object.keys(data.query.pages)[Bawl.searchForMissingSectionPageTitleInt]].revisions[0]['*'];
					Bawl.searchForMissingSectionPageWikitextSplit = Bawl.searchForMissingSectionPageWikitext.split(/\n/);
					for ( Bawl.searchForMissingSectionPageWikitextSplitInt=0;Bawl.searchForMissingSectionPageWikitextSplitInt<Bawl.searchForMissingSectionPageWikitextSplit.length;Bawl.searchForMissingSectionPageWikitextSplitInt++) {
						Bawl.debug('search line #' + Bawl.searchForMissingSectionPageWikitextSplitInt + ': ' + Bawl.searchForMissingSectionPageWikitextSplit[Bawl.searchForMissingSectionPageWikitextSplitInt]);
						if ( Bawl.searchForMissingSectionPageWikitextSplit[Bawl.searchForMissingSectionPageWikitextSplitInt].match(/^=.*=[ ]*$/) ) {
							Bawl.searchForMissingTitleOfSection = Bawl.flattenWikiText(Bawl.searchForMissingSectionPageWikitextSplit[Bawl.searchForMissingSectionPageWikitextSplitInt].replace(/^[= ]*(.*[^=])[= ]*$/,'$1'));
							Bawl.debug('found a section named ' + Bawl.searchForMissingTitleOfSection + ' on ' + Bawl.searchForMissingSectionPageTitle);
						}
						if (Bawl.searchForMissingSectionPageWikitextSplit[Bawl.searchForMissingSectionPageWikitextSplitInt].match(Bawl.searchForMissingSectionRegExp)) {
							Bawl.debug('recovered the subscribed section! re-subscribing now');
							if ( typeof Bawl.subsWithSubTossed[Bawl.searchForMissingSectionPageTitle] == 'undefined' ) {
								Bawl.debug('adding ' + Bawl.searchForMissingSectionPageTitle + ' to subs');
								Bawl.subsWithSubTossed[Bawl.searchForMissingSectionPageTitle] = { 'v':0,'subs':{} };
							}
							if ( typeof Bawl.subsWithSubTossed[Bawl.searchForMissingSectionPageTitle].subs == 'undefined' ) {
								Bawl.subsWithSubTossed[Bawl.searchForMissingSectionPageTitle].subs = {};
							}
							Bawl.subsWithSubTossed[Bawl.searchForMissingSectionPageTitle].subs[Bawl.searchForMissingTitleOfSection] = {'id':Bawl.lostSubID,'u':Bawl.lostSubLastUpdate};
							window.localStorage.setItem('BawlSubs',JSON.stringify(Bawl.subsWithSubTossed));
							if ( Bawl.settings.stalkSyncToPrefs ) {
								Bawl.stalkSyncToPrefs();
							}
						}
					}
				}
			}, function ( code, data ) { Bawl.APIError(code, data);
			});
		}
	}, function ( code, data ) { Bawl.APIError(code, data);
	});
};
Bawl.stalkWatchList = function(data) {
	//use data from stalkCheckSubscriptions to generate wikitext overview of new comments
	Bawl.debug('add box with new comments to watchlist');
	Bawl.unreadCmtsContainer = document.createElement('div');
	Bawl.unreadCmtsContainer.id = 'BawlUnreadCmts';
	$('#content').prepend(Bawl.unreadCmtsContainer);
	Bawl.stalkSeenItLink = '<div id="BawlstalkSeenIt" style="text-align:center">' + Bawl.msgs.subsSeenIt + '</div>';
	if ( typeof data == 'undefined' && typeof Bawl.checkExistingSubs.unreadCmts != 'undefined' ) {
		Bawl.unreadCmtsContainer.className = 'BawlSubsDiv';
		$('#BawlUnreadCmts')[0].innerHTML = Bawl.checkExistingSubs.unreadCmts;
		$('#BawlUnreadCmts').append(Bawl.stalkSeenItLink);
		$('#BawlstalkSeenIt').on('click',function(){Bawl.stalkSeenIt();});
		return;
	}
	if ( mw.config.get('wgCanonicalSpecialPageName') == 'Watchlist' || ( mw.config.get('wgTitle') == 'BawlSubs' && mw.config.get('wgNamespaceNumber') == -1 ) ) {
		Bawl.stalkWikitextUnreadCmts = '';
		for(Bawl.stalkWikitextUnreadCmtsInt=0;Bawl.stalkWikitextUnreadCmtsInt < Object.keys(Bawl.stalkUnreadCommentsAll.unreadCmts).length;Bawl.stalkWikitextUnreadCmtsInt++){
		Bawl.stalkWikitextUnreadCmts = Bawl.stalkWikitextUnreadCmts + '\n' + Bawl.stalkUnreadCommentsAll.unreadCmts[Object.keys(Bawl.stalkUnreadCommentsAll.unreadCmts)[Bawl.stalkWikitextUnreadCmtsInt]] + '\n----';
		}
		Bawl.debug('parse new comments');
		api.post( {action: 'parse', disablelimitreport: true, disableeditsection: true, contentmodel:'wikitext', format: 'json', pst: '1',formatversion: '2',prop: 'text',text: Bawl.stalkWikitextUnreadCmts} ).then( function ( data ) {
			if ( Bawl.testValidJSON(window.localStorage.BawlSubs) ) {
				Bawl.stalkDataAddParsed = JSON.parse(window.localStorage.BawlSubs);
			} else {
				Bawl.stalkDataAddParsed = {};
			}
			Bawl.stalkDataAddParsed.unreadCmts = data.parse.text;
			window.localStorage.setItem('BawlSubs',JSON.stringify(Bawl.stalkDataAddParsed));
			Bawl.unreadCmtsContainer.className = 'BawlSubsDiv';
			$('#BawlUnreadCmts')[0].innerHTML = data.parse.text;
			$('#BawlUnreadCmts').append(Bawl.stalkSeenItLink);
			$('#BawlstalkSeenIt').on('click',function(){Bawl.stalkSeenIt();});
		}, function ( code, data ) { Bawl.APIError(code, data);
		});
	}
};
Bawl.stalkSeenIt = function() {
	Bawl.debug('stalkSeenIt');
	if ( Bawl.testValidJSON(window.localStorage.BawlSubs) ) {
		Bawl.stalkDataRemoveParsed = JSON.parse(window.localStorage.BawlSubs);
		delete Bawl.stalkDataRemoveParsed.unreadCmts;
		window.localStorage.setItem('BawlSubs',JSON.stringify(Bawl.stalkDataRemoveParsed));
	}
	$('#BawlUnreadCmts').remove();
};
Bawl.tackOnEchoRead = function() {
	//can we push real echo notifications to ourselves? Atm, alas no: T306211. Fake it till you make it!
	if ( Bawl.testValidJSON(mw.user.options.get('userjs-BawlTackOnEchoGlobal')) ) {
		if ( mw.config.get('skin') == 'minerva' ) {
			Bawl.tackOnEchoDelay = 2000;
		} else {
			Bawl.tackOnEchoDelay = 700;
		}
		var DelayMarkAsReadButton = setInterval(function () {
		clearInterval(DelayMarkAsReadButton);
			if ( mw.config.get('skin') == 'minerva' ) {
				$('.header-action *').removeClass('oo-ui-element-hidden');
			} else {
				$('.mw-echo-ui-notificationBadgeButtonPopupWidget-popup:not(.oo-ui-element-hidden) .mw-echo-ui-notificationsWidget-markAllReadButton').removeClass('oo-ui-element-hidden');
				Bawl.markAsReadButtonElement = $('.mw-echo-ui-notificationBadgeButtonPopupWidget-popup:not(.oo-ui-element-hidden) .mw-echo-ui-notificationsWidget-markAllReadButton:not(.oo-ui-element-hidden) A')[0];
				if ( Bawl.markAsReadButtonElement ) {
					Bawl.markAsReadButtonElement.addEventListener('click',function(){Bawl.tackOnEchoClear();$('.BawlTackOnEcho').remove();});
				}
			}
			Bawl.tackOnEchoNotifications = JSON.parse(mw.user.options.get('userjs-BawlTackOnEchoGlobal'));
			Bawl.tackOnEchoHTML = {};
			for(Bawl.tackOnEchoNotificationsInt=0;Bawl.tackOnEchoNotificationsInt<Object.keys(Bawl.tackOnEchoNotifications).length;Bawl.tackOnEchoNotificationsInt++) {
				Bawl.tackOnEchoRenderKey = Object.keys(Bawl.tackOnEchoNotifications)[Bawl.tackOnEchoNotificationsInt];
				Bawl.tackOnEchoRenderKeyDate = Bawl.tackOnEchoRenderKey.replace(/_.*/,'');
				Bawl.tackOnEchoHTML[Bawl.tackOnEchoRenderKey] = document.createElement('a');
				Bawl.tackOnEchoHTML[Bawl.tackOnEchoRenderKey].classList = 'BawlTackOnEcho oo-ui-widget oo-ui-widget-enabled mw-echo-ui-notificationItemWidget mw-echo-ui-notificationItemWidget-initiallyUnseen mw-echo-ui-notificationItemWidget-unread';
				if ( Bawl.tackOnEchoNotifications[Bawl.tackOnEchoRenderKey].msg == 'newcmt' ) {
					Bawl.tackOnMsg = Bawl.msgs.tackOnNewCmt.replace('SECTION',Bawl.tackOnEchoNotifications[Bawl.tackOnEchoRenderKey].section);
					Bawl.tackOnLink = Bawl.tackOnEchoNotifications[Bawl.tackOnEchoRenderKey].page + '?BwlScrToUsr=' + encodeURIComponent(Bawl.tackOnEchoNotifications[Bawl.tackOnEchoRenderKey].user) + '&BwlScrToTime=' + Bawl.tackOnEchoRenderKey;
					Bawl.tackOnPage = Bawl.tackOnLink.replace(/^([^\?\#]*).*$/,'$1');
				} else {
					Bawl.tackOnMsg = Bawl.tackOnEchoNotifications[Bawl.tackOnEchoRenderKey].msg;
					Bawl.tackOnLink = Bawl.tackOnEchoNotifications[Bawl.tackOnEchoRenderKey].link;
					if ( typeof Bawl.tackOnEchoNotifications[Bawl.tackOnEchoRenderKey].page == 'undefined' ) {
						Bawl.tackOnPage = Bawl.tackOnLink.replace(/^([^\?\#]*).*$/,'$1');
					} else {
						Bawl.tackOnPage = Bawl.tackOnEchoNotifications[Bawl.tackOnEchoRenderKey].page;
					}
				}
				Bawl.tackOnEchoHTML[Bawl.tackOnEchoRenderKey].href = 'https://' + Bawl.tackOnEchoNotifications[Bawl.tackOnEchoRenderKey].at.replace('$1',Bawl.tackOnLink);
				if ( Bawl.tackOnEchoNotifications[Bawl.tackOnEchoRenderKey].icon == 'Bawl' ) {
					Bawl.tackOnIcon = '<span class="BawlSVGLargeIcon"></span>';
				} else {
					Bawl.tackOnIcon = '<img src="' + Bawl.tackOnEchoNotifications[Bawl.tackOnEchoRenderKey].icon + ' width="2em">';
				}
				if ( (new Date().getTime() - Bawl.tackOnEchoRenderKeyDate) < 60000 ) {
					Bawl.debug('event was less than 60s ago');
					Bawl.tackOnTime = Bawl.basicmsgs['notification-timestamp-ago-seconds'].replace(/\{\{PLURAL\:\$1\|(.*)\}\}/,'$1').replace('$1',Math.round((new Date().getTime() - Bawl.tackOnEchoRenderKeyDate) / 60000));
				} else if ( (new Date().getTime() - Bawl.tackOnEchoRenderKeyDate) < 3600000 ) {//less
					Bawl.debug('event was less than 60m ago');
					Bawl.tackOnTime = Bawl.basicmsgs['notification-timestamp-ago-minutes'].replace(/\{\{PLURAL\:\$1\|(.*)\}\}/,'$1').replace('$1',Math.round((new Date().getTime() - Bawl.tackOnEchoRenderKeyDate) / 60000));
				} else if ( (new Date().getTime() - Bawl.tackOnEchoRenderKeyDate) < 86400000 ) {
					Bawl.debug('event was less than 24hr ago');
					Bawl.tackOnTime = Bawl.basicmsgs['notification-timestamp-ago-hours'].replace(/\{\{PLURAL\:\$1\|(.*)\}\}/,'$1').replace('$1',Math.round((new Date().getTime() - Bawl.tackOnEchoRenderKeyDate) / 3600000));
				} else {
					Bawl.debug('event was more than 24hr ago');
					Bawl.tackOnTime = Bawl.basicmsgs['notification-timestamp-ago-days'].replace(/\{\{PLURAL\:\$1\|(.*)\}\}/,'$1').replace('$1',Math.round((new Date().getTime() - Bawl.tackOnEchoRenderKeyDate) / 86400000));
				}
				Bawl.tackOnEchoHTML[Bawl.tackOnEchoRenderKey].innerHTML = '<div class="mw-echo-ui-notificationItemWidget-icon">' + Bawl.tackOnIcon + '</div>'+
				'<div class="mw-echo-ui-notificationItemWidget-content"><div class="mw-echo-ui-notificationItemWidget-content-message">' + Bawl.tackOnMsg + '</div>'+
				'<div class="mw-echo-ui-notificationItemWidget-content-actions"><div class="mw-echo-ui-notificationItemWidget-content-actions-buttons oo-ui-widget oo-ui-widget-enabled oo-ui-selectWidget oo-ui-selectWidget-unpressed oo-ui-buttonSelectWidget">'+
				'<a class="oo-ui-widget oo-ui-widget-enabled oo-ui-labelElement oo-ui-optionWidget oo-ui-buttonElement oo-ui-buttonElement-frameless oo-ui-iconElement oo-ui-buttonOptionWidget mw-echo-ui-menuItemWidget mw-echo-ui-menuItemWidget-prioritized" href="' + mw.config.get('wgArticlePath').replace('$1','User:' + encodeURIComponent(Bawl.tackOnEchoNotifications[Bawl.tackOnEchoRenderKey].user)) + '">'+
				'<span class="oo-ui-buttonElement-button"><span class="oo-ui-iconElement-icon oo-ui-icon-userAvatar"></span><span class="oo-ui-labelElement-label">' + Bawl.tackOnEchoNotifications[Bawl.tackOnEchoRenderKey].user + '</span></span></a>'+
				'<a href="' + mw.config.get('wgArticlePath').replace('$1',encodeURIComponent(Bawl.tackOnPage)) + '" class="oo-ui-widget oo-ui-widget-enabled oo-ui-labelElement oo-ui-optionWidget oo-ui-buttonElement oo-ui-buttonElement-frameless oo-ui-iconElement oo-ui-buttonOptionWidget mw-echo-ui-menuItemWidget mw-echo-ui-menuItemWidget-prioritized">'+
				'<span class="oo-ui-buttonElement-button"><span class="oo-ui-iconElement-icon oo-ui-icon-userSpeechBubble"></span><span class="oo-ui-labelElement-label">' + Bawl.tackOnPage + '</span></span></a></div>'+
				'<label class="mw-echo-ui-notificationItemWidget-content-actions-timestamp oo-ui-widget oo-ui-widget-enabled oo-ui-labelElement oo-ui-labelElement-label oo-ui-labelWidget">' + Bawl.tackOnTime + '</label>';
				Bawl.tackOnEchoHTML[Bawl.tackOnEchoRenderKey].style = 'border-bottom: 1px solid #c8ccd1';
				if ( mw.config.get('skin') == 'minerva' ) {
					$('.mw-echo-ui-notificationsListWidget').prepend(Bawl.tackOnEchoHTML[Object.keys(Bawl.tackOnEchoNotifications)[Bawl.tackOnEchoNotificationsInt]]);
				} else {
					$('.mw-echo-ui-notificationBadgeButtonPopupWidget-popup:not(.oo-ui-element-hidden) .mw-echo-ui-sortedListWidget').prepend(Bawl.tackOnEchoHTML[Object.keys(Bawl.tackOnEchoNotifications)[Bawl.tackOnEchoNotificationsInt]]);
				}
			}
		}, Bawl.tackOnEchoDelay);
	}
};
Bawl.tackOnEchoIconHack = function() {
	if ( ! window.location.hostname.match(/(^m\.|\.m\.)/) && mw.config.get('skin') == 'minerva' ) {
		Bawl.debug('Not loading notifications. On Minerva desktop, notification icon only opens alerts (never notifications) T306737');
		return;
	}
	if ( Bawl.testValidJSON(mw.user.options.get('userjs-BawlTackOnEchoGlobal')) && Object.keys(JSON.parse(mw.user.options.get('userjs-BawlTackOnEchoGlobal'))).length > 0 ) {
		Bawl.debug('light up notification area');
		mw.util.addCSS('#pt-notifications-notice .mw-echo-notifications-badge::after{visibility:unset}');
		$('#pt-notifications-notice .mw-echo-notifications-badge,#pt-notifications-notice .mw-echo-notifications-badge-all-read').addClass('mw-echo-unseen-notifications');
		$('#pt-notifications-notice .mw-echo-notifications-badge,#pt-notifications-notice .mw-echo-notifications-badge-all-read').removeClass('mw-echo-notifications-badge-all-read');
		if ( mw.config.get('skin') == 'minerva' && $('#user-notifications .circle span')[0] ) {
			Bawl.debug('you\'re using Minerva and have real notifications');
			$('#user-notifications .circle span')[0].innerText = ( Number($('#user-notifications .circle span')[0].innerText) + Object.keys(JSON.parse(mw.user.options.get('userjs-BawlTackOnEchoGlobal'))).length);
		} else if ( mw.config.get('skin') == 'minerva' && $('#user-notifications')[0] ) {
			Bawl.debug('you\'re using Minerva but have no real notifications');
			Bawl.minervaCircle = document.createElement('div');
			Bawl.minervaCircle.classList = 'circle';
			Bawl.minervaCircle.innerHTML = '<span>' + Object.keys(JSON.parse(mw.user.options.get('userjs-BawlTackOnEchoGlobal'))).length + '</span>';
			$('#user-notifications')[0].innerText = '';
			$('#user-notifications')[0].append(Bawl.minervaCircle);
			$('#pt-notifications-alert #user-notifications').addClass('notification-unseen').addClass('notification-count').addClass('mw-echo-unseen-notifications').removeClass('mw-ui-icon').removeClass('mw-ui-icon-element').removeClass('mw-ui-icon-wikimedia-bellOutline-base20');
			$('#pt-notifications-alert #user-notifications').on('click',function(){Bawl.tackOnEchoRead();});
		} else if ( mw.config.get('skin') != 'minerva' ) {
			Bawl.debug('update notification count');
			$('#pt-notifications-notice .mw-echo-notifications-badge').on('click',function(){Bawl.tackOnEchoRead();});
			document.querySelector('#pt-notifications-notice .mw-echo-notifications-badge').dataset.counterText = ( Number(document.querySelector('#pt-notifications-notice .mw-echo-notifications-badge').dataset.counterText) + Object.keys(JSON.parse(mw.user.options.get('userjs-BawlTackOnEchoGlobal'))).length);
		}
	}
};
Bawl.tackOnEchoWrite = function(notifications) { //example: Bawl.tackOnEchoWrite([{'date':new Date().getTime(),'icon':'Bawl','user':'Jimbo Wales','page':'User talk:Jimbo Wales','link':'wiki/User_talk:Jimbo Wales#anchor','msg':'newcmt'},{'date':new Date().getTime(),'icon':'Bawl','user':'Jimbo Wales2','page':'User talk:Jimbo Wales2','link':'wiki/User_talk:Jimbo Wales2#anchor','msg':'newcmt'}])
	Bawl.debug('adding notifications:');
	Bawl.debug(notifications);
	api.get( {format:'json',action:'query',meta:'userinfo',uiprop:'options'} ).then( function ( data ) {
		Bawl.debug('obtained preferences');
		if ( Bawl.testValidJSON(data.query.userinfo.options['userjs-BawlTackOnEchoGlobal']) ) {
			Bawl.tackOnEchoMsgs = JSON.parse(data.query.userinfo.options['userjs-BawlTackOnEchoGlobal']);
		}
		if ( typeof Bawl.tackOnEchoMsgs == 'undefined' ) {
			Bawl.tackOnEchoMsgs = {};
		}
		for(Bawl.tackOnEchoWriteInt=0;Bawl.tackOnEchoWriteInt<notifications.length;Bawl.tackOnEchoWriteInt++){
			Bawl.debug('add ' + JSON.stringify(notifications[Bawl.tackOnEchoWriteInt]) + ' to tackOnEcho');
			Bawl.tackOnDate = notifications[Bawl.tackOnEchoWriteInt].date;
			delete notifications[Bawl.tackOnEchoWriteInt].date;
			Bawl.tackOnDateSeq = 0;
			while ( typeof Bawl.tackOnEchoMsgs[Bawl.tackOnDate + '_' + Bawl.tackOnDateSeq] != 'undefined' ) {
				Bawl.tackOnDateSeq++;
			}
			Bawl.tackOnEchoMsgs[Bawl.tackOnDate + '_' + Bawl.tackOnDateSeq] = notifications[Bawl.tackOnEchoWriteInt];
		}
		if ( new Blob([JSON.stringify(Bawl.tackOnEchoMsgs)]).size > 65535 ) {
			Bawl.debug('notifications exceed 65535 bytes, cannot write to preferences');
			return;
		}
		mw.user.options.set('userjs-BawlTackOnEchoGlobal',JSON.stringify(Bawl.tackOnEchoMsgs));
		Bawl.tackOnEchoIconHack();
		if ( Bawl.projectIsSULWiki ) {
			Bawl.tackOnEchoAction = 'globalpreferences';
		} else {
			Bawl.tackOnEchoAction = 'options';
		}
		api.postWithEditToken( {format: 'json', action: Bawl.tackOnEchoAction, change:['userjs-BawlTackOnEchoGlobal=' + JSON.stringify(Bawl.tackOnEchoMsgs)] } ).then( function ( data ) {
			Bawl.debug('wrote new notification to preferences');
		}, function ( code, data ) { Bawl.APIError(code, data);
		});
	}, function ( code, data ) { Bawl.APIError(code, data);
	});
};
Bawl.tackOnEchoClear = function(timestamp) {
	Bawl.tackOnEchoClearNewNotes = '';
	if ( typeof timestamp != 'undefined' && Bawl.testValidJSON(mw.user.options.get('userjs-BawlTackOnEchoGlobal')) && JSON.parse(mw.user.options.get('userjs-BawlTackOnEchoGlobal'))[timestamp] ) {
		Bawl.tackOnEchoClearNewNotes = JSON.parse(mw.user.options.get('userjs-BawlTackOnEchoGlobal'));
		delete Bawl.tackOnEchoClearNewNotes[timestamp];
		Bawl.tackOnEchoClearNewNotes = JSON.stringify(Bawl.tackOnEchoClearNewNotes);
	} else {
		mw.user.options.set('userjs-BawlTackOnEchoGlobal',undefined);
	}
	if ( Bawl.projectIsSULWiki ) {
		Bawl.tackOnEchoAction = 'globalpreferences';
	} else {
		Bawl.tackOnEchoAction = 'options';
	}
	api.postWithEditToken( {format: 'json', action: Bawl.tackOnEchoAction, change:['userjs-BawlTackOnEchoGlobal=' + Bawl.tackOnEchoClearNewNotes] } ).then( function ( data ) {
		Bawl.debug('cleared echo-like notifications');
	}, function ( code, data ) { Bawl.APIError(code, data);
	});
};
if ( Bawl.testValidJSON(window.localStorage.BawlSubs) ) {
	Bawl.stalkLastCheckDate = JSON.parse(window.localStorage.BawlSubs)[Object.keys(JSON.parse(window.localStorage.BawlSubs))[0]].c;
}
if ( ( Bawl.settings.stalkAddSubLinks || Bawl.settings.stalkAutoSub ) && ( mw.config.get('wgTitle') == 'BawlSubs' || mw.config.get('wgCanonicalSpecialPageName') == 'Watchlist' || ( typeof Bawl.stalkLastCheckDate != 'undefined' && (Bawl.stalkLastCheckDate + (Bawl.settings.stalkInterval * 60000) ) < new Date().getTime() ) ) ) {
	Bawl.debug('run subscription check. if the check results in a new notification the notifications will be shown.');
	if ( mw.config.get('wgTitle') == 'BawlSubs' ) {
		$('#firstHeading')[0].innerText = Bawl.msgs.subsHeader;
		$('head title')[0].innerText = Bawl.msgs.subsHeader;
		$('#mw-content-text')[0].innerHTML = '';
	}
	Bawl.stalkCheckSubscriptions();
} else if ( Bawl.settings.stalkTackOnEcho ) {
	Bawl.debug('subscription check not running right now, load existing new message notification (if any)');
	Bawl.tackOnEchoIconHack();
}
Bawl.getIndentationFromHTML = function(RLPInt) {
	Bawl.indentLevel = 0;
	Bawl.foundParserOutput = false;
	Bawl.foundParserOutputInt = 0;
	Bawl.analyzeIndentationElement = Bawl.processElementArray[RLPInt];
	delete Bawl.highestIndentElement;
	while ( Bawl.analyzeIndentationElement && Bawl.foundParserOutput == false && Bawl.foundParserOutputInt < 30 ) {
		Bawl.foundParserOutputInt++;
		if ( ['UL','DL'].includes(Bawl.analyzeIndentationElement.nodeName) ) {
			Bawl.indentLevel++;
			Bawl.highestIndentElement = Bawl.analyzeIndentationElement;
		} else if ( Bawl.analyzeIndentationElement.classList.contains('mw-parser-output') ) {
			Bawl.foundParserOutput = true;
		}
		Bawl.analyzeIndentationElement = Bawl.analyzeIndentationElement.parentElement;
	}
	return Bawl.indentLevel;
};
Bawl.sigDateToMachineReadable = function(sigDateToConvert,testSigDate) {
	Bawl.debug('convert ' + sigDateToConvert + ' into timestamp');
	if ( testSigDate && sigDateToConvert.match(/^[0-9]*$/) ) {
		return Number(sigDateToConvert);
	}
	Bawl.machineReadableDate = sigDateToConvert.trim();
	for (Bawl.intMonth = 1; Bawl.intMonth < 13; Bawl.intMonth++) {
		Bawl.machineReadableDate = Bawl.machineReadableDate.replace(Bawl.monthNames[Bawl.intMonth], Bawl.EnglishMonths[Bawl.intMonth]);
		Bawl.machineReadableDate = Bawl.machineReadableDate.replace(' ' + Bawl.monthNames[Bawl.intMonth].slice(0,3) + ' ', ' ' + Bawl.EnglishMonths[Bawl.intMonth] + ' ');
	}
	if ( mw.config.get('wgContentLanguage') == 'fa' ) {
		Bawl.FarsiNumerals = ['۰','۱','۲','۳','۴','۵','۶','۷','۸','۹'];
		for(Bawl.FarsiNumeralsInt=0;Bawl.FarsiNumeralsInt<10;Bawl.FarsiNumeralsInt++) {
			Bawl.machineReadableDate=Bawl.machineReadableDate.replace(new RegExp(Bawl.FarsiNumerals[Bawl.FarsiNumeralsInt],'g'),Bawl.FarsiNumeralsInt);
		}
		Bawl.machineReadableDate = Bawl.machineReadableDate.replace('ساعت ','').replace(/،/g,'');
	} else if ( mw.config.get('wgContentLanguage') == 'pt' ) {
		Bawl.machineReadableDate=Bawl.machineReadableDate.replace(/h([0-5][0-9])min/,':$1').replace(/ de /g,' ');
	}
	Bawl.machineReadableDateNoTZ = Bawl.machineReadableDate.replace(/[\.,]/g, '').match(Bawl.signDateRegExp);
	if ( Bawl.machineReadableDateNoTZ ) {
		Bawl.machineReadableDateWithTZ = Bawl.machineReadableDateNoTZ[0].replace(/\(.*\)/,Bawl.wikiTimezone);
		Bawl.machineReadableDateValid = new Date(Bawl.machineReadableDateWithTZ);
		if ( Bawl.machineReadableDateValid != 'Invalid Date' ) {
			return new Date(Bawl.machineReadableDateWithTZ).getTime();
		} else {
			Bawl.debug(sigDateToConvert + ' could not be converted to a timestamp');
			return false;
		}
	}
};
Bawl.getInsertionPointComment = function(replyLinkParams, justCurrentPageText) {
	Bawl.debug('collect sectiontext, indentation and insertion point of original comment');
	Bawl.justCurrentPageTextSafed = Bawl.safeText(justCurrentPageText,undefined,'skiplinks');
	Bawl.origReplyTo = Bawl.escapeRegExp(replyLinkParams.origReplyTo).replace(/[ _]/g, '[ _]'); //some users sign with [[User:User_Name]], others with [[User:User Name]], some with [[User:user Name]]
	Bawl.wikiTextSplitByUserRegExp = new RegExp('(?::' + '[' + Bawl.origReplyTo.slice(0,1).toUpperCase() + Bawl.origReplyTo.slice(0,1).toLowerCase() + ']' + Bawl.origReplyTo.slice(1) + '.*' + Bawl.escapeRegExp(replyLinkParams.origTimestamp) + '|' + Bawl.origReplyTo + ':' + Bawl.escapeRegExp(replyLinkParams.origTimestamp) + ').*', 'g'); //regular sig or locator
	Bawl.wikiTextSplitByUser = Bawl.justCurrentPageTextSafed.split(Bawl.wikiTextSplitByUserRegExp);
	if ( typeof replyLinkParams.seq == 'number' && replyLinkParams.seq <= Bawl.wikiTextSplitByUser.length && Bawl.wikiTextSplitByUser.length > 1 ) {
		Bawl.debug('there are ' + ( Bawl.wikiTextSplitByUser.length - 1 ) + ' occurences of username "' + Bawl.origReplyTo + '" with timestamp ' + replyLinkParams.origTimestamp + ' on this page');
		Bawl.wikiTextUpToSig = '';
		for (Bawl.wikitextseqint = 0; Bawl.wikitextseqint <= replyLinkParams.seq; Bawl.wikitextseqint++) {
			Bawl.wikiTextUpToSig = Bawl.wikiTextUpToSig + Bawl.wikiTextSplitByUser[Bawl.wikitextseqint];
		}
		Bawl.wikiTextNum = Bawl.wikiTextUpToSig.match(/^=.+=[ ]*$/gm);
		if ( Bawl.wikiTextNum ) {
			Bawl.sectionText = Bawl.getSectionByNum(Bawl.justCurrentPageTextSafed,Bawl.wikiTextNum.length);
		} else {
			Bawl.debug('found no section headers in the text leading up to the comment');
			Bawl.sectionText = 'SECTIONLESS';
			Bawl.wikiTextNum = 'SECTIONLESS';
		}
		Bawl.relevantPrecedingLine = Bawl.wikiTextUpToSig.split(/\n/)[ Bawl.wikiTextUpToSig.split(/\n/).length - 2 ] + '\n';
		if ( Bawl.relevantPrecedingLine == '\n' ) { Bawl.relevantPrecedingLine = ''; }
		Bawl.relevantCommentNoSig = Bawl.wikiTextUpToSig.split(/\n/)[ Bawl.wikiTextUpToSig.split(/\n/).length - 1 ];
		Bawl.relevantCommentSig = justCurrentPageText.match(Bawl.wikiTextSplitByUserRegExp)[replyLinkParams.seq];
		Bawl.debug('returning requested info');
		return { 'sectiontext':Bawl.sectionText,'sectionnum':Bawl.wikiTextNum.length,'relevantIndentation':Bawl.relevantCommentNoSig.replace(/([\\:\\*\\#]*).*/, '$1'),'relevantComment':Bawl.relevantCommentNoSig + Bawl.relevantCommentSig,'relevantPrecedingLine':Bawl.relevantPrecedingLine};
	} else {
		Bawl.debug('something unexpected happened. seq: ' + replyLinkParams.seq + ', Bawl.wikiTextSplitByUser.length: ' + Bawl.wikiTextSplitByUser.length);
		Bawl.addScrewedLink('username+timestamp ' + replyLinkParams.origReplyTo + '+' + replyLinkParams.origTimestamp + ' not found, seq: ' + replyLinkParams.seq,'Username/timestamp combination not found.');
		return 'ERRORBAD';
	}
};
Bawl.getInsertionPointSection = function(replyLinkParams, justCurrentPageText) {
	Bawl.justCurrentPageTextSafed = Bawl.safeText(justCurrentPageText,undefined,'skiplinks');
	if ( replyLinkParams.type == 'heading' && replyLinkParams.section == 0 ) {
		return {'sectiontext':justCurrentPageText.replace(/(^|\n)=.*=[ ]*\n[^]*/,''),'sectionnum':0};
	}
	Bawl.justCurrentPageTextSplitByLine = Bawl.justCurrentPageTextSafed.split(/\n/);
	Bawl.justCurrentPageTextFlattenedTitles = '';
	for(Bawl.justCurrentPageTextSplitByLineInt=0;Bawl.justCurrentPageTextSplitByLineInt<Bawl.justCurrentPageTextSplitByLine.length;Bawl.justCurrentPageTextSplitByLineInt++){
		Bawl.processLine = Bawl.justCurrentPageTextSplitByLine[Bawl.justCurrentPageTextSplitByLineInt];
		if ( Bawl.processLine.match(/^=.*=[ ]*$/) ) {
			Bawl.processLine = Bawl.flattenWikiText(Bawl.processLine);//flattening to allow matching a section title like "==[[Bad article]] and [[other bad article]]==" with the innerText "Bad article and other bad article"
		}
		Bawl.justCurrentPageTextFlattenedTitles = Bawl.justCurrentPageTextFlattenedTitles + Bawl.processLine + '\n';
	}
	Bawl.wikiTextSplitBySectionTitleRegExp = new RegExp('((?:^|\n)[=]+[ ]*' + Bawl.escapeRegExp(replyLinkParams.sectionTitle) + '[ ]*[=]+)', 'gm');
	Bawl.wikiTextSplitBySectionTitleNoGroupRegExp = new RegExp('(?:^|\n)[=]+[ ]*' + Bawl.escapeRegExp(replyLinkParams.sectionTitle) + '[ ]*[=]+', 'gm');//for the split we must NOT have the section titles themselves returned or the count gets all messed up
	Bawl.justCurrentPageTextWithPlaceHolder = Bawl.justCurrentPageTextFlattenedTitles.replace(/([^\n])\n=/g,'$1\n\n=').replace(Bawl.wikiTextSplitBySectionTitleRegExp,'BAWL_MATCHING_SECTION_TITLE\n$1');
	Bawl.wikiTextSplitBySectionTitle = Bawl.justCurrentPageTextWithPlaceHolder.split(Bawl.wikiTextSplitBySectionTitleNoGroupRegExp);
	Bawl.wikiTextUpToHeader = '';
	for (Bawl.wikitextseqint = 0; Bawl.wikitextseqint <= replyLinkParams.sectionseq; Bawl.wikitextseqint++) {
		Bawl.debug('compiling wikitext up to header #' + Bawl.wikitextseqint);
		Bawl.wikiTextUpToHeader = Bawl.wikiTextUpToHeader + Bawl.wikiTextSplitBySectionTitle[Bawl.wikitextseqint];
	}
	Bawl.wikiTextNum = Bawl.wikiTextUpToHeader.match(/^(BAWL_MATCHING_SECTION_TITLE|=.*=)[ ]*$/gm);
	if ( Bawl.wikiTextNum ) {
		return {'sectiontext':Bawl.getSectionByNum(Bawl.justCurrentPageTextSafed,Bawl.wikiTextNum.length),'sectionnum':Bawl.wikiTextNum.length};
	} else {
		return {'sectiontext':justCurrentPageText};
	}
};
Bawl.flattenWikiText = function(wikiTextToFlatten) {//not quite complete flattening, but generally sufficient for the purpose of flattening comments for summary snippets and section titles for anchors
	return wikiTextToFlatten.replace(/<([Nn]o[Ww]iki|NOWIKI)>(.*)<\/([Nn]o[Ww]iki|NOWIKI)>/g,'$2').replace(/\[\[([^\|\]\n]+\|)?(([^\]\|\n]|\][^\]])+)\]\]/g,'$2').replace(/\[\[([^\:\]\n]*\:)([^\|\n]+)\|\]\]/g,'$2').replace(/\[[a-z]{2,14}:\/\/[^ ]( ([^\]]*))?\]/,'$2').replace(/[']{2,3}/g,'').replace(/<[^>]*>([^<]*)<\/[^>]*>/g,'$1').replace(/<[^>]*>([^<]*)<\/[^>]*>/g,'$1').replace(/[ ]{2,}/g,' ').replace(/\{\{[^\\|\\\}\\\{]*\|([^\\\}]*)(\|[^\}]*)*\}\}/g, '$1').replace(/~{3,5}/g,'').replace(/<br[\/ ]*>/g,'');
};
Bawl.postReply1 = function(replyLinkParams,postReplyTrigger) {
	Bawl.debug('postReply1, trigger: ' + postReplyTrigger);
	Bawl.postReplyInProgress = new Date().getTime();
	if ( ! Bawl.dryRunOnce ) {
		Bawl.timeOutWait = 10000;
		var DelayedSuccessCheck = setInterval(function () {
			clearInterval(DelayedSuccessCheck);
			if ( Bawl.postReplyInProgress < ( new Date().getTime() - Bawl.timeOutWait + 20 ) && ! $('.BawlScrewed')[0] ) { //+20 gives 20ms to register the date and account for system clock fluctuations. 2ms should be more than enough, but meh. Every expected way to exit the posting process causes postReplyInProgress to be set to the current date so it'd be less than 10 seconds ago. If it didn't change, some went wrong. (or the MediaWiki server couldn't process the edit within 10 seconds)
				Bawl.debug('no successful exit was made from postReply1 and there\'s no "Awww shit" yet. Awww, shit. Trigger: ' + postReplyTrigger);
				Bawl.addScrewedLink('submit_timeout_' + postReplyTrigger,'After attempting to submit, success was not detected after 10 seconds. Sometimes an edit takes longer, but this may indicate something went wrong.');
			}
		}, Bawl.timeOutWait);
	}
	if ( Bawl.UITextInputTitle.getValue() == '' && Bawl.UITextInputTitle.isVisible() ) {
		$('#BawlUITextInputTitle input').removeClass('BawlShakeIt');
		$('#BawlUITextInputTitle input')[0].style = 'transition:all 0.2s ease-in !important';
		$('#BawlUITextInputTitle input').addClass('BawlEaseIn BawlPurpleBG');
		var BawlShakeTitle = setInterval(function () {
				clearInterval(BawlShakeTitle);
				$('#BawlUITextInputTitle input').addClass('BawlShakeIt');
		}, 20);
		var BawlPurpleTitle = setInterval(function () {
				clearInterval(BawlPurpleTitle);
				$('#BawlUITextInputTitle input').removeClass('BawlPurpleBG');
		}, 200);
		Bawl.debug('title is empty');
		Bawl.postReplyInProgress = new Date().getTime();
		return;
	}
	Bawl.disableForm(true); //disable form so you can't double click
	$(document.getElementById('BawlUIReplyButton')).addClass('BawlPendingBlink');
	Bawl.debug('get the wikitext of the page we want to add the comment to');
	Bawl.currentPageTextParams = {'action':'query','prop':'revisions|info','format': 'json','export':'true','titles': replyLinkParams.pageTitle,'inprop':'watched', 'intestactions':'edit'};
	api.get(Bawl.currentPageTextParams).then(function(data) {
		Bawl.debug(data);
		if ( typeof data.query.pages[ Object.keys(data.query.pages)[0] ].actions.edit != 'string' ) {
			Bawl.debug('you can\'t edit this page');
			Bawl.showProtectedWarning();
			Bawl.postReplyInProgress = new Date().getTime();
			return;
		}
		if ( typeof data.query.pages[ Object.keys(data.query.pages)[0] ].watched == 'string' ) {
			Bawl.watched = true;
			if ( typeof data.query.pages[ Object.keys(data.query.pages)[0] ].watchlistexpiry == 'string' ) {
				Bawl.watchlistexpiry = new Date(data.query.pages[ Object.keys(data.query.pages)[0] ].watchlistexpiry).getTime();
			}
		} else {
			Bawl.watched = false;
		}
		if ( ! data.query.pages[-1] ) {
			Bawl.debug('got wikitext');
			Bawl.justCurrentPageText = Bawl.repairWikiText(Bawl.getWikitextFromExport(data.query.export["*"]));
			Bawl.currentRevID = data.query.pages[ Object.keys(data.query.pages)[0] ].revisions[0].revid;
		} else {
			Bawl.debug('response indicates this page doesn\'t exist');
			Bawl.justCurrentPageText = '';
			Bawl.currentRevID = 0;
		}
		Bawl.debug('got wikitext');
		if ( Bawl.settings.checkNewComments && mw.config.get('wgArticleId') != 0 && ! data.query.pages[-1] && Bawl.pageRevisionIDSinceLastCheck && Bawl.pageRevisionIDSinceLastCheck[replyLinkParams.pageTitle] == Bawl.currentRevID ) {
			Bawl.debug('no new revisions since the last time we checked, moving on towards postReply2');
		} else if ( Bawl.settings.checkNewComments && mw.config.get('wgArticleId') != 0 && Bawl.replyLinkParamsOpened.type == 'comment' ) {
			Bawl.debug('check for new comments');
			Bawl.postReplyInProgress = new Date().getTime();
			Bawl.checkForNewComments(replyLinkParams, 'postreply', Bawl.justCurrentPageText, Bawl.currentRevID);
			return; //kill it for now, Bawl.checkForNewComments() will call postReply2 if there are no new comments
		}
		Bawl.postReply2(replyLinkParams, Bawl.justCurrentPageText, Bawl.currentRevID);
	}, function ( code, data ) { Bawl.APIError(code, data);
	});
};
Bawl.postReply2 = function(replyLinkParams, justCurrentPageText, currentRevID) {
	Bawl.debug('postReply2, process comment and actually post it');
	if ( replyLinkParams.type != 'editFullPage' ) {
		if ( replyLinkParams.type == 'edit' ) {
			Bawl.commentMilliseconds = replyLinkParams.origTimestamp.slice(-3);
		} else {
			Bawl.commentMilliseconds = new Date().getTime().toFixed().slice(-3); //indeed, the local clock may differ from server time which we primarily rely on through ((subst:#time:xNU)). And it's irrelevant as the milliseconds are only used to make the identifier more unique. Making two edits within the same second is already implausible but within the same millisecond? This doesn't solve the issue of non-Bawl users adding multiple comments in a single edit, but solving that would require MediaWiki to support "random" as a magic word that can produce different numbers when called multiple times within the same edit. Or have a bot that slightly adjusts timestamps to ensure they're unique.
		}
		if ( replyLinkParams.sectionTitle && replyLinkParams.sectionTitle != "" ) {
			Bawl.postCommentSummarySectionLink = '/* ' + replyLinkParams.sectionTitle + ' */ ';
		} else {
			Bawl.postCommentSummarySectionLink = ''; //no section? no link
		}
	}
	if ( Bawl.activeEditor == 'visualLight' ) {
		Bawl.syncToSource();
	}
	Bawl.processedComment = Bawl.processComment(Bawl.UITextInput.getValue(),'edit');
	Bawl.debug('comment processed');
	Bawl.debug('replyLinkParams:');
	Bawl.debug(replyLinkParams);
	if ( Bawl.watched && typeof Bawl.watchlistexpiry != 'number' && Bawl.settings.watchlist == 'watch' ) {
		Bawl.debug('you\'re already watching this page indefinitely');
		Bawl.newWatchSetting = 'nochange';
		Bawl.newExpiry = undefined;
	} else if ( Bawl.watched && typeof Bawl.watchlistexpiry == 'number' && Bawl.settings.watchlist == 'watch' && Bawl.settings.watchlistexpiry != 'indefinite' ) {
		Bawl.debug('you are watching this page with an expiration date');
		if ( Bawl.settings.watchlistexpiry.slice(0,1) == '+' ) {
			Bawl.watchUntil = Bawl.watchlistexpiry + (Bawl.settings.watchlistexpiry.match(/([0-9]+)/)[0] * 86400000);
		} else {
			Bawl.watchUntil = new Date().getTime() + (Bawl.settings.watchlistexpiry.match(/([0-9]+)/)[0] * 86400000);
		}
		if ( Bawl.watchUntil < Bawl.watchlistexpiry ) {
			Bawl.debug('you\'re already watching this page for a longer period than your watchlist setting, your watchlist expiry for this page will remain unchanged');
			Bawl.newWatchSetting = 'nochange';
			Bawl.newExpiry = undefined;
		} else {
			Bawl.newWatchSetting = 'watch';
			Bawl.newExpiry = new Date(Bawl.watchUntil).toISOString();
		}
	} else {
		Bawl.newWatchSetting = Bawl.settings.watchlist;
		if ( Bawl.settings.watchlistexpiry.slice(0,1) == '+' ) {
			Bawl.newExpiry = Bawl.settings.watchlistexpiry.slice(1);
		} else {
			Bawl.newExpiry = Bawl.settings.watchlistexpiry;
		}
	}
	Bawl.postCommentParams = {
		format: 'json',
		action: 'edit',
		title: replyLinkParams.pageTitle,
		baserevid: currentRevID,
		nocreate: true,
		watchlist: Bawl.newWatchSetting,
		watchlistexpiry: Bawl.newExpiry
	};
	Bawl.debug('posting type and subtype: ' + replyLinkParams.type + '/' + replyLinkParams.subtype);
	if ( replyLinkParams.type == 'comment' ) {
		Bawl.summarySnippetText = '';
		if ( Bawl.settings.sumSnippet && replyLinkParams.type == 'comment' && Bawl.processedComment ) {
			Bawl.snippetRemoveRecipient = new RegExp('^' + Bawl.escapeRegExp(Bawl.replyLinkParamsOpened.origReplyTo) + '[ ,:;]*'); //having "replying to USER: USER, foo bar.." in the summary is redundant
			Bawl.snippetForSummary = Bawl.flattenWikiText(Bawl.processedComment).replace(/^[\\:\\*\\#]*/, '').replace(Bawl.snippetRemoveRecipient, '');
			if ( Bawl.snippetForSummary.length > 1 ) {
				Bawl.snippetForSummaryShort = Bawl.snippetForSummary;
				if ( Bawl.snippetForSummary.length > 50 ) {
					Bawl.snippetForSummaryShort = Bawl.snippetForSummary.slice(0,40) + '...';
				}
				Bawl.summarySnippetText = ': (' + Bawl.snippetForSummaryShort + ')';
			}
		}
		Bawl.postCommentParams.summary = Bawl.postCommentSummarySectionLink + Bawl.wikiMsgs.postCommentSummaryPost.replace(/USER/g, Bawl.escapeReplacement(replyLinkParams.origReplyTo.replace(/_/g,' ')) + Bawl.summarySnippetText);
		Bawl.origCmtData = Bawl.getInsertionPointComment(replyLinkParams, justCurrentPageText);
		Bawl.debug('got insertion point');
		if ( Bawl.origCmtData.sectiontext != 'SECTIONLESS' ) {
			Bawl.postCommentParams.section = Bawl.origCmtData.sectionnum;
			Bawl.originalWikiText = Bawl.origCmtData.sectiontext;
		} else {
			Bawl.originalWikiText = justCurrentPageText;
		}
		Bawl.checkHigherLevelIndentRegExp = new RegExp('^([\:\#\*]{' + (Bawl.origCmtData.relevantIndentation.length + 1) + '}).*' + Bawl.signDateRegExpLocalMonths.source,'m'); //look for comments with higher indentation levels than what we're replying to. if found, no outdent
		Bawl.origCmtLevelPlusOne = Bawl.origCmtData.relevantIndentation.length + 1;
		Bawl.replyBelowThisRegExp = new RegExp('(' + Bawl.escapeRegExp(Bawl.origCmtData.relevantPrecedingLine + Bawl.origCmtData.relevantComment) + ')((\n[\\:\\*\\#]{' + Bawl.origCmtLevelPlusOne + ',}([^\\:\\*\\#\\=]|[$]).*)*)', 'm');
		if ( ! Bawl.originalWikiText.match(Bawl.replyBelowThisRegExp) ) {
			Bawl.replyBelowThisRegExp = new RegExp('(' + Bawl.escapeRegExp(Bawl.origCmtData.relevantComment) + ')((\n[\\:\\*\\#]{' + Bawl.origCmtLevelPlusOne + ',}([^\\:\\*\\#\\=]|[$]).*)*)', 'm');
		}
		if ( ! Bawl.originalWikiText.match(Bawl.replyBelowThisRegExp) ) {
			Bawl.addScrewedLink('insertion point RegExp no match','Insertion point not found.');
		}
		Bawl.replyBelowThis = Bawl.originalWikiText.match(Bawl.replyBelowThisRegExp)[0];
		Bawl.checkAlreadyOutdentedRegExp = new RegExp(Bawl.escapeRegExp(Bawl.origCmtData.relevantComment) + '\n[:\\*].*┌[─]*┘');
		if (Bawl.origCmtData.relevantIndentation.length >= Bawl.settings.outdent && ! Bawl.origCmtData.sectiontext.match(Bawl.checkHigherLevelIndentRegExp) && ( Bawl.origCmtData.sectiontext && ! Bawl.origCmtData.sectiontext.match(Bawl.checkAlreadyOutdentedRegExp) ) ) {
			Bawl.debug('maximum indentation exceeded, outdenting');
			Bawl.outdentLineLength = ( Bawl.origCmtData.relevantIndentation.length - 1) * 3;
			Bawl.commentTextIndent = Bawl.origCmtData.relevantIndentation.slice(Bawl.origCmtData.relevantIndentation.length - 1) + '┌';
			for (Bawl.indentint = 0; Bawl.indentint < Bawl.outdentLineLength; Bawl.indentint++) {
				Bawl.commentTextIndent = Bawl.commentTextIndent + '─';
			}
			Bawl.commentTextIndent = Bawl.commentTextIndent + '┘<br/>';
		} else if (Bawl.origCmtData.relevantIndentation.length != 0) {
			if ( Bawl.origCmtData.sectiontext && Bawl.origCmtData.sectiontext.match(Bawl.checkAlreadyOutdentedRegExp) ) { Bawl.debug('You\'re replying to a comment that is followed by an outdent. You do know that\'s bad form, right? Err, good for you? Fight the power I guess? No outdent for you'); }
			Bawl.debug('get indendation from the line we will be posting under');
			Bawl.commentTextIndent = Bawl.replyBelowThis.split(/\n/)[Bawl.replyBelowThis.split(/\n/).length -1].match(new RegExp('[\\:\\#\\*]{' + Bawl.origCmtData.relevantIndentation.length + ',' + (Bawl.origCmtData.relevantIndentation.length +1) + '}'))[0]; //we copy the indentation of the comment right above us instead of what we're replying to, which may or may not be the same. This prevents screwups in mixed indentation discussions
			if ( Bawl.origCmtData.relevantIndentation == Bawl.commentTextIndent ) {
				Bawl.debug('we\'re replying to the most indented comment in this tree, repeating the last character of the indentation of the previous message so e.g. ::* becomes ::**');
				Bawl.commentTextIndent = Bawl.commentTextIndent + Bawl.commentTextIndent.slice(Bawl.origCmtData.relevantIndentation.length - 1);
			}
			Bawl.debug('new indendation: ' + Bawl.commentTextIndent);
		} else {
			Bawl.commentTextIndent = Bawl.getMostPopularIndent(justCurrentPageText, Bawl.origCmtData.sectiontext);
		}
		if ( Bawl.oneTimeTools && Bawl.oneTimeTools.archiveSection.isSelected() && typeof Bawl.postCommentParams.section == 'number' ) {
			Bawl.archiveResult = '';
			if ( Bawl.UITextInputSummary.getValue() != '' ) {
				Bawl.archiveResult = Bawl.UITextInputSummary.getValue();
			}
			if ( Bawl.basicmsgs.atops != '' && Bawl.basicmsgs.abots != '' ) {
				Bawl.atopTemplate = '\n((subst:' + Bawl.basicmsgs.atops + '|1=COMMENT|2=EDITSUMMARY))';
				Bawl.abotTemplate = '\n((subst:' + Bawl.basicmsgs.abots + '|1=COMMENT|2=EDITSUMMARY))';
			} else {
				if ( Bawl.basicmsgs.lockicon != '' ) {
					Bawl.atopTemplateLockIcon = '[[File:' + Bawl.basicmsgs.lockicon + '|60px|right]]';
				} else {
					Bawl.atopTemplateLockIcon = '<div style="float:right;font-size:xx-large">&#x1F512;</div>';
				}
				Bawl.atopTemplate = '\n<div class="archived" style="background:#EDEAFF;padding:0.5em;border:0.1em solid grey">' + Bawl.atopTemplateLockIcon;
				Bawl.abotTemplate = '\n----\nCOMMENT\n</div>';
			}
			Bawl.postCommentParams.text = Bawl.originalWikiText.replace(/^(=.*=)/,'$1\n' + Bawl.atopTemplate.replace(/EDITSUMMARY/g,Bawl.archiveResult).replace(/COMMENT/g,Bawl.processedComment + Bawl.repairTagImbalance(Bawl.processedComment))).replace(/$/,Bawl.abotTemplate.replace(/EDITSUMMARY/g,Bawl.archiveResult).replace(/COMMENT/g,Bawl.processedComment + Bawl.repairTagImbalance(Bawl.processedComment)));
		} else {
			Bawl.postCommentParams.text = Bawl.originalWikiText.replace(Bawl.replyBelowThis, Bawl.replyBelowThis + '\n' + Bawl.commentTextIndent + Bawl.processedComment + Bawl.repairTagImbalance(Bawl.processedComment));
		}
		Bawl.addAnchorsRegExp = new RegExp('\\[\\[\#([0-9]{12})_([^\\|\\]]+)(\\||\\]\\])','g');
		Bawl.addAnchorsRegExpGroups = new RegExp(Bawl.addAnchorsRegExp.source);
		if ( Bawl.postCommentParams.text.match(Bawl.addAnchorsRegExp) ) {
			Bawl.debug('post contains links for which anchors may need to be added');
			Bawl.addAnchorsIntMatches = Bawl.postCommentParams.text.match(Bawl.addAnchorsRegExp);
			for (Bawl.addAnchorsInt=0;Bawl.addAnchorsInt<Bawl.addAnchorsIntMatches.length;Bawl.addAnchorsInt++) {
				Bawl.debug('check' + Bawl.addAnchorsIntMatches[Bawl.addAnchorsInt]);
				Bawl.addAnchorTarget = Bawl.addAnchorsIntMatches[Bawl.addAnchorsInt].match(Bawl.addAnchorsRegExpGroups);
				for (Bawl.addAnchorLoopRLPInt=0;Bawl.addAnchorLoopRLPInt<Object.keys(Bawl.replyLinkParams).length;Bawl.addAnchorLoopRLPInt++) {
					Bawl.checkParams = Bawl.replyLinkParams[Object.keys(Bawl.replyLinkParams)[Bawl.addAnchorLoopRLPInt]];
					Bawl.checkParams = Bawl.addPageAndSectionTitleToRPL(Bawl.checkParams);
					if ( Bawl.checkParams.origReplyTo == Bawl.addAnchorTarget[2] && Bawl.checkParams.pageTitle.replace(/ /g,'_') == replyLinkParams.pageTitle.replace(/ /g,'_') && Bawl.checkParams.sectionTitle.replace(/ /g,'_') == replyLinkParams.sectionTitle.replace(/ /g,'_') && Bawl.checkParams.sectionseq == replyLinkParams.sectionseq ) {
						if ( Bawl.unixTimeToFlatDate(Bawl.sigDateToMachineReadable(Bawl.checkParams.origTimestamp,true)) == Bawl.addAnchorTarget[1] ) {
							Bawl.debug('replyLinkParams #' + Bawl.checkParams.int + ' seems to match user/section/timestamp of link');
							Bawl.addAnchorReplaceRegExp = new RegExp('([\#\:\*]*)(.*)([' + Bawl.addAnchorTarget[2].slice(0,1).toUpperCase() + Bawl.addAnchorTarget[2].slice(0,1).toLowerCase() + ']' + Bawl.escapeRegExp(Bawl.addAnchorTarget[2].slice(1)).replace(/[ _]/g,'[ _]') + '.*' + Bawl.escapeRegExp(Bawl.checkParams.origTimestamp).replace(/[ _]/g,'[ _]') + ')');
							Bawl.debug('add anchor for:');
							Bawl.debug(Bawl.addAnchorReplaceRegExp);
							Bawl.addAnchorCheckForExistingAnchor = new RegExp('id=' + Bawl.escapeReplacement(Bawl.addAnchorTarget[1]) + '_' + Bawl.escapeReplacement(Bawl.addAnchorTarget[2]));
							if ( Bawl.postCommentParams.text.match(Bawl.addAnchorCheckForExistingAnchor) == null ) {
								Bawl.postCommentParams.text = Bawl.postCommentParams.text.replace(Bawl.addAnchorReplaceRegExp,'$1' + '<span id="' + Bawl.escapeReplacement(Bawl.addAnchorTarget[1]) + '_' + Bawl.escapeReplacement(Bawl.addAnchorTarget[2]) + '"></span>$2$3');
								Bawl.addAnchorOrigSpeechBalloon = document.getElementById('bawlLink-' + Bawl.checkParams.id);
								if ( typeof Bawl.addAnchorOrigSpeechBalloon == 'object' ) {
									Bawl.addAnchorForParseInPlace = document.createElement('span');
									Bawl.addAnchorForParseInPlace.id = Bawl.escapeReplacement(Bawl.addAnchorTarget[1]) + '_' + Bawl.escapeReplacement(Bawl.addAnchorTarget[2]);
									Bawl.addAnchorOrigSpeechBalloon.prepend(Bawl.addAnchorForParseInPlace);
								}
							}
							break;
						}
					}
				}
			}
		}
	} else if ( replyLinkParams.type == 'BCL' ) {
		Bawl.debug('posting message through BCL (Bawl Comment Link)');
		if ( typeof replyLinkParams.summary != 'undefined' ) {
			Bawl.BCLExtraSummary = replyLinkParams.summary;
		} else {
			Bawl.BCLExtraSummary = '';
		}
		if ( replyLinkParams.allowcreate ) {
			delete Bawl.postCommentParams.nocreate;
			delete Bawl.postCommentParams.baserevid;
		}
		if ( typeof replyLinkParams.sectionTitle != 'undefined' ) {
			Bawl.postCommentParams.summary = Bawl.postCommentSummarySectionLink + Bawl.BCLExtraSummary + Bawl.wikiMsgs.summaryCredit;
		} else {
			Bawl.postCommentParams.summary = Bawl.BCLExtraSummary + Bawl.wikiMsgs.summaryCredit;
		}
		Bawl.origCmtData = Bawl.getInsertionPointSection(replyLinkParams, justCurrentPageText);
		if ( replyLinkParams.indent ) {
			Bawl.commentTextIndent = replyLinkParams.indent;
		} else {
			Bawl.commentTextIndent = Bawl.getMostPopularIndent(justCurrentPageText, Bawl.origCmtData.sectiontext);
		}
		Bawl.postCommentParams.section = Bawl.origCmtData.sectionnum;
		if ( replyLinkParams.subtype == 'page' ) {
			delete Bawl.postCommentParams.section;
		}
		if ( replyLinkParams.indentation && replyLinkParams.indentation.match(/^\#\:\*$/) ) {
			Bawl.commentTextIndent = replyLinkParams.indentation;
		}
		Bawl.postCommentParams.appendtext = '\n' + Bawl.commentTextIndent + Bawl.processedComment + Bawl.repairTagImbalance(Bawl.processedComment);
		if ( replyLinkParams.createonly ) {
			delete Bawl.postCommentParams.nocreate;
			Bawl.postCommentParams.createonly = true;
			Bawl.postCommentParams.appendtext = Bawl.processedComment + Bawl.repairTagImbalance(Bawl.processedComment);
		}
	} else if ( replyLinkParams.type == 'newheading' ) {
		Bawl.postCommentParams.summary = Bawl.postCommentSummarySectionLink + Bawl.wikiMsgs.postSubsectionSummaryPost.replace(/SUBSECTION/g, Bawl.escapeReplacement(Bawl.UITextInputTitle.getValue()));
		Bawl.origSectData = Bawl.getInsertionPointSection(replyLinkParams, justCurrentPageText);
		Bawl.postCommentParams.section = Bawl.origSectData.sectionnum;
		Bawl.newSectionLevel = Bawl.origSectData.sectiontext.match(/^[=]*/)[0];
		if ( Bawl.newSectionLevel.length < 6 ) {
			Bawl.newSectionLevel = Bawl.newSectionLevel + '=';
		}
		Bawl.postCommentParams.appendtext = '\n' + Bawl.newSectionLevel + Bawl.UITextInputTitle.getValue() + Bawl.newSectionLevel + '\n' + Bawl.processedComment + Bawl.repairTagImbalance(Bawl.processedComment);
	} else if ( replyLinkParams.type == 'newsection' ) {
		Bawl.postCommentParams.summary = Bawl.wikiMsgs.postCommentSummaryNewSection.replace('SUMMARY', '').replace(/NEWSECTION/g, Bawl.escapeReplacement(Bawl.UITextInputTitle.getValue()));
		if ( replyLinkParams.summary ) {
			Bawl.debug('insert InputBox provided summary');
			Bawl.postCommentParams.summary = Bawl.wikiMsgs.postCommentSummaryNewSection.replace('SUMMARY', ' / ' + replyLinkParams.summary).replace(/NEWSECTION/g, Bawl.escapeReplacement(Bawl.UITextInputTitle.getValue()));
		}
		if ( replyLinkParams.minor == true ) {
			Bawl.debug('adding InputBox specified minor flag');
			Bawl.postCommentParams.minor = true;
		}
		Bawl.postCommentParams.section = 'new';
		Bawl.postCommentParams.sectiontitle = Bawl.UITextInputTitle.getValue();
		Bawl.postCommentParams.text = Bawl.processedComment + Bawl.repairTagImbalance(Bawl.processedComment);
		delete Bawl.postCommentParams.nocreate;
	} else if ( replyLinkParams.type == 'edit' ) {
		Bawl.editCommentSummaryHere = Bawl.wikiMsgs.editCommentSummary.replace(/USER/,'');
		if ( Bawl.settings.theStranger && replyLinkParams.origReplyTo != Bawl.userNameUnderscore) {
			Bawl.editCommentSummaryHere = Bawl.wikiMsgs.editCommentSummary.replace(/USER/,' ([[User:' + replyLinkParams.origReplyTo.replace(/_/g,' ') + '|' + replyLinkParams.origReplyTo.replace(/_/g,' ') + ']])');
		}
		Bawl.postCommentParams.summary = Bawl.postCommentSummarySectionLink + Bawl.editCommentSummaryHere;
		Bawl.origCmtData = Bawl.getInsertionPointComment(replyLinkParams, justCurrentPageText);
		if ( Bawl.origCmtData.sectiontext != 'SECTIONLESS' ) {
			Bawl.postCommentParams.section = Bawl.origCmtData.sectionnum;
			Bawl.originalWikiText = Bawl.origCmtData.sectiontext;
		} else {
			Bawl.originalWikiText = justCurrentPageText;
		}
		Bawl.userMentionInSummary = Bawl.pingFix(Bawl.UITextInput.getValue(),Bawl.wikiTextForEditComment);
		if ( Bawl.userMentionInSummary != '' ) {
			Bawl.postCommentParams.summary = Bawl.postCommentParams.summary.replace(Bawl.wikiMsgs.summaryCredit, ' [' + Bawl.userMentionInSummary.replace(/^, /, '') + ']' + Bawl.wikiMsgs.summaryCredit);
		}
		Bawl.commentToReplaceRegExp = new RegExp(Bawl.escapeRegExp(Bawl.wikiTextForEditComment));
		Bawl.unalteredCommentNoSig = Bawl.originalWikiText.match(Bawl.commentToReplaceRegExp)[0].replace(Bawl.wikiTextForEditSigForPreview,'');
		Bawl.alteredComment = Bawl.originalWikiText.match(Bawl.commentToReplaceRegExp)[0].replace(Bawl.unalteredCommentNoSig,Bawl.processedComment);
		Bawl.postCommentParams.text = Bawl.originalWikiText.replace(Bawl.commentToReplaceRegExp, Bawl.alteredComment);
	} else if ( replyLinkParams.type == 'editFullPage' ) {
		Bawl.postCommentParams.summary = Bawl.wikiMsgs.summaryCredit;
		Bawl.postCommentParams.text = Bawl.processedComment;
		delete Bawl.postCommentParams.nocreate;
	} else if ( replyLinkParams.type == 'heading' && replyLinkParams.subtype == 'edit' ) {
		Bawl.postCommentParams.summary = Bawl.postCommentSummarySectionLink + Bawl.wikiMsgs.summaryCredit;
		Bawl.postCommentParams.text = Bawl.processedComment;
		Bawl.postCommentParams.section = Bawl.getInsertionPointSection(replyLinkParams, justCurrentPageText).sectionnum;
	}
	if ( Bawl.UITextInputSummary.isElementAttached() && Bawl.UITextInputSummary.getValue() != '' ) {
		Bawl.postCommentParams.summary = Bawl.postCommentParams.summary.replace(Bawl.wikiMsgs.summaryCredit, ' ' + Bawl.UITextInputSummary.getValue() + Bawl.wikiMsgs.summaryCredit).replace(/^[ ]*/, '');
	}
	if ( Bawl.UIMinorCheck && Bawl.UIMinorCheck.isSelected() ) {
		Bawl.postCommentParams.minor = true;
	}
	if ( typeof Bawl.sectionNumFromLink == 'number' ) { //detection of section number from wikitext failed so we're using the fallback of the section number from the edit section link
		Bawl.postCommentParams.section = Bawl.sectionNumFromLink;
	}
	if ( Bawl.RETFsummary != '' ) {
		Bawl.postCommentParams.summary = Bawl.postCommentParams.summary.replace(Bawl.wikiMsgs.summaryCredit, ' [' + Bawl.RETFsummary + ']' + Bawl.wikiMsgs.summaryCredit);
	}
	if ( ( ['comment','editFullPage'].indexOf(replyLinkParams.type) != -1 || ( replyLinkParams.type == 'heading' && replyLinkParams.subtype == 'edit' ) ) && Bawl.oneTimeTools && Bawl.oneTimeTools.moveContentToPage.getValue() != '' ) {
		Bawl.debug('a pagename was entered to post or move the content to');
		Bawl.wipeSectionParams = $.extend( true, {}, Bawl.postCommentParams );
		Bawl.wipeSectionParams.text = '';
		delete Bawl.wipeSectionParams.appendtext;
		delete Bawl.postCommentParams.baserevid; //will appendtext the section or content. no point in checking for edit conflicts
		Bawl.wipeSectionAnchor = '';
		if ( replyLinkParams.sectionTitle != '' ) {
			Bawl.wipeSectionAnchor = '#' + replyLinkParams.sectionTitle;
		}
		Bawl.wipeSectionParams.summary = Bawl.wikiMsgs.postCommentSummaryMovedSection.replace('SOURCE','[[' + replyLinkParams.pageTitle.replace(/_/g,' ') + ']]').replace('TARGET','[[' + Bawl.oneTimeTools.moveContentToPage.getValue() + Bawl.wipeSectionAnchor + ']]');
		if ( typeof Bawl.postCommentParams.section == 'number' && ! Bawl.dryRunOnce ) {
			Bawl.debug('wipe existing section from ' + replyLinkParams.pageTitle);
			api.postWithEditToken(Bawl.wipeSectionParams).then(function(data) {
				Bawl.debug('section was wiped from ' + replyLinkParams.pageTitle);
				Bawl.debug(data);
			}, function ( code, data ) { Bawl.APIError(code, data);
			});
		}
		if ( ! Bawl.postCommentParams.appendtext ) {
			Bawl.postCommentParams.appendtext = '\n\n' + Bawl.postCommentParams.text;
			delete Bawl.postCommentParams.text;
		}
		delete Bawl.postCommentParams.section;
		Bawl.debug('rewrite pagename in locators');
		Bawl.postCommentParams.appendtext = Bawl.postCommentParams.appendtext.replace(/(<span id="[^:]*:([0-9]{10,11}|\{\{subst:#time:xNU\}\})[0-9]{3}:)([^"\n]*)(" class="BawlCmt")/g,'$1' + Bawl.escapeHTML(Bawl.oneTimeTools.moveContentToPage.getValue().replace(/ /g,'_').replace(/:/g,'BWLCLN')) + '$4');
		Bawl.postCommentParams.title = Bawl.oneTimeTools.moveContentToPage.getValue();
		Bawl.postCommentParams.summary = Bawl.wipeSectionParams.summary;
		if ( Bawl.oneTimeTools.allowPageCreation.isSelected() ) {
			delete Bawl.postCommentParams.nocreate;
		} else {
			Bawl.postCommentParams.nocreate = true;
		}
	}
	Bawl.applyModules('beforeEdit');
	Bawl.debug('ready to post');
	if ( justCurrentPageText != Bawl.wikiTextWithComment || Bawl.postCommentParams.appendtext ) {
		if ( ! Bawl.postCommentParams.appendtext ) {
			Bawl.debug('generated wikitext is different from the current wikitext, so it can be posted (without being a null edit). wikitext:\n' + Bawl.postCommentParams.text);
		}
		Bawl.debug(Bawl.postCommentParams);
		if ( Bawl.dryRunOnce == true ) {
			Bawl.dryRunOnce = false;
			Bawl.debug('dry run enabled, skipped API call');
			Bawl.dryRunInfoDiv = document.createElement('div');
			Bawl.dryRunInfoDiv.style = 'padding:1em;background:#efe;text-align:initial;font-style:normal;font-size:initial;font-family:initial';
			Bawl.dryRunInfoDiv.id = 'DryRunInfo' + Bawl.escapeHTML(Bawl.replyLinkParamsOpened.id);
			Bawl.dryRunInfo = '';
			for(Bawl.paramsInPreviewInt=0;Bawl.paramsInPreviewInt<Object.keys(Bawl.postCommentParams).length;Bawl.paramsInPreviewInt++) {
				Bawl.dryRunInfo = Bawl.dryRunInfo + '<b>' + Bawl.escapeHTML(Object.keys(Bawl.postCommentParams)[Bawl.paramsInPreviewInt]) + ': </b>' + Bawl.escapeHTML(Object.values(Bawl.postCommentParams)[Bawl.paramsInPreviewInt]).replace(/\n/g,'<br/>') + '<br/>';
			}
			Bawl.dryRunInfoDiv.innerHTML = Bawl.dryRunInfo + '<br/><a onclick="document.getElementById(\'' + Bawl.dryRunInfoDiv.id + '\').remove();$(\'.BawlPurpleBG\').removeClass(\'BawlPurpleBG\')">whatev</a>';
			if ( Bawl.replyLinkParamsOpened.type == 'heading' && Bawl.replyLinkParamsOpened.subtype == 'edit' ) {
				document.getElementById('bawlForm-' + Bawl.replyLinkParamsOpened.id).append(Bawl.dryRunInfoDiv);
			} else {
				document.getElementById('bawlForm-' + Bawl.replyLinkParamsOpened.id).parentElement.append(Bawl.dryRunInfoDiv);
			}
			document.getElementById(Bawl.dryRunInfoDiv.id).scrollIntoView(Bawl.smoothScroll);
			Bawl.disableForm(false); //re-enable form
			$(document.getElementById('BawlUIReplyButton')).removeClass('BawlPendingBlink');
		} else {
			Bawl.doAPICall(Bawl.postCommentParams);
		}
		if ( ( Bawl.settings.afterPost == 'parse' && ['comment','edit','newsection','newheading'].indexOf(replyLinkParams.type) != -1 && ! Bawl.replyLinkParamsOpened.redirect ) || ( Bawl.settings.afterPost == 'parsecmtonly' && ['comment','edit'].indexOf(replyLinkParams.type) != -1 ) ) { //.redirect would indicate a new section posted from section=new which requires a redirect
			delete Bawl.postedCommentParsed;
			Bawl.doPreview('previewposted', replyLinkParams);
		}
	} else {
		Bawl.debug('couldn\'t insert comment, wikitext same as current text, possibly insertion point failure');
		Bawl.disableForm(false); //re-enable form
		$(document.getElementById('BawlUIReplyButton')).removeClass('BawlPendingBlink');
	}
}; //end postReply2
if ( Bawl.settings.enableOnDiffOldId ) {
	Bawl.viewingPage = (mw.config.get('wgAction') == 'view' && window.location.href.match('veaction=') == null);
} else {
	Bawl.viewingPage = (mw.config.get('wgAction') == 'view' && mw.config.get('wgDiffNewId') == null && window.location.href.match('veaction=') == null && window.location.href.match('oldid=') == null);
}
Bawl.isDiscussionPage = ( $('#ca-addsection,.minerva-talk-add-button')[0] || mw.config.get('wgExtraSignatureNamespaces').includes(mw.config.get('wgNamespaceNumber')) );
Bawl.viewingArticle = ( mw.config.get('wgNamespaceNumber') == 0 && ! Bawl.isDiscussionPage && Bawl.viewingPage );
if ( Bawl.settings.RLmasq ) {
	Bawl.replyLinkInnerText = '<span style="color: #000">(</span><span style="color: #0645ad">reply</span><span style="color: #000">)</span>';
	Bawl.svgBawlIconClass = '';
} else {
	Bawl.replyLinkInnerText = '';
	Bawl.svgBawlIconClass = 'BawlSVGIcon BawlSVG';
}
if ( Bawl.testValidJSON(window.localStorage.BawlThanks) && Bawl.settings.thankLink ) {
	Bawl.thankedCommentsArray = Object.values(JSON.parse(window.localStorage.BawlThanks));
} else if ( Bawl.settings.thankLink ) {
	Bawl.thankedCommentsArray = [];
}
Bawl.testExistingSub = function(replyLinkParams) {
	try {
		Bawl.testSubExist = Bawl.checkSubs[replyLinkParams.pageTitle.replace(/_/g,' ')].subs[replyLinkParams.sectionTitle].foo;
	} catch (e) {return false;}
	return true;
};
Bawl.replyLinkDebugInfo = '';
Bawl.checkSubs = {};
if ( Bawl.testValidJSON(window.localStorage.BawlSubs) ) { Bawl.checkSubs = JSON.parse(window.localStorage.BawlSubs); }
Bawl.addReplyLinkTo = function(replyLinkParams,textNodeSig) {
	if ( ! replyLinkParams.origReplyTo ) {
		Bawl.replyLinkParams[replyLinkParams.int].origReplyTo = '';
	}
	if ( ! Bawl.viewingPage ) {
		Bawl.debug('don\'t add links to diff pages etc (you\'d still have new section/edit full page)');
		return;
	}
	if ( ! Bawl.finishedAddingLinks && typeof replyLinkParams.isFirst == 'undefined' && ( replyLinkParams.type == 'comment' || ( replyLinkParams.type == 'edit' && replyLinkParams.type == 'legacy' ) ) ) {
		Bawl.replyUserDate = replyLinkParams.origReplyTo + replyLinkParams.origTimestamp;
		for (Bawl.seqint = 0; Bawl.seqint < 100; Bawl.seqint++) {
			if ( Bawl.addedReplyLinks.indexOf(Bawl.replyUserDate + '-' + Bawl.seqint) == -1 ) {
				Bawl.addedReplyLinks.push(Bawl.replyUserDate + '-' + Bawl.seqint);
				Bawl.replyLinkParams[replyLinkParams.int].seq = Bawl.seqint;
				if ( Bawl.seqint > 0 ) {
					Bawl.replyLinkParams[replyLinkParams.int].id = replyLinkParams.id + '_' + Bawl.seqint;
				}
				break;
			}
		}
	}
	if ( Bawl.settings.debug && Bawl.int ) { Bawl.replyLinkDebugInfo = ' (int #' + Bawl.int + ', replyLinkParams.int #' + replyLinkParams.int + ', subtype: ' + replyLinkParams.subtype + ')';}//Bawl.debug
	if ( replyLinkParams.isFirst != true ) {
		Bawl.replyLinkHTML = document.createElement('span');
	} else {
		Bawl.replyLinkHTML = document.createElement('div');
	}
	Bawl.replyLinkHTML.id = 'bawlLink-' + Bawl.escapeHTML(replyLinkParams.id);
	Bawl.replyLinkHTML.className = 'BawlLinks';
	if ( replyLinkParams.type == 'comment' ) {
		Bawl.replyLinkText = '<span title="' + Bawl.msgs.replyToTitle.replace('USER', Bawl.escapeHTML(replyLinkParams.origReplyTo).replace(/_/g,' ')) + Bawl.replyLinkDebugInfo + '" class="BawlReplyLink ' + Bawl.svgBawlIconClass + '">' + Bawl.replyLinkInnerText + '</span>';
	} else if ( replyLinkParams.type == 'newheading' ) {
		Bawl.replyLinkText = '';
		if ( Bawl.settings.secLinks ) {
			Bawl.replyLinkText = '<span title="' + Bawl.msgs.newSectionTitle + Bawl.replyLinkDebugInfo + '" class="BawlReplyLink BawlSVGNewSectionIcon BawlSVG"></span>';
		}
	} else if ( replyLinkParams.type == 'edit' ) {
		Bawl.replyLinkText = '<span title="' + Bawl.msgs.editTitle + Bawl.replyLinkDebugInfo + '" class="BawlReplyLink BawlSVGEditIcon BawlSVG"></span>';
		Bawl.replyLinkHTML.id = 'bawlEditLink-' + Bawl.escapeHTML(replyLinkParams.id);
	}
	if ( Bawl.isDiscussionPage || replyLinkParams.type != 'newheading' ) {
		if ( Bawl.finishedAddingLinks ) {
			Bawl.onClickParams = '\'' + encodeURIComponent(JSON.stringify(replyLinkParams)).replace(/\'/g, '%27') + '\'';
		} else if ( replyLinkParams.type == 'edit' ) {
			Bawl.onClickParams = 'Bawl.' + Bawl.keyReplyLinkParamsEdit + '[' + JSON.stringify(replyLinkParams.int) + ']';
		} else {
			Bawl.onClickParams = 'Bawl.' + Bawl.keyReplyLinkParams + '[' + JSON.stringify(replyLinkParams.int) + ']';
		}
		Bawl.replyLinkHTML.innerHTML = '<a onclick="Bawl.' + Bawl.keyOpenReplyForm + '(' + Bawl.onClickParams + ')">' + Bawl.replyLinkText + '</a>';
	}
	if ( ! replyLinkParams.isFirst && ( ( Bawl.settings.dateLinksIcon && replyLinkParams.type == 'comment' ) || ( Bawl.settings.dateLinksIconSection && replyLinkParams.type == 'newheading' ) ) ) {
		Bawl.debug('add permalink generator link');
		Bawl.permaLinkGenLink = document.createElement('a');
		if ( replyLinkParams.type == 'newheading' ) {
			Bawl.permaLinkGenLink.href = '#' + encodeURIComponent(Bawl.getPageTitleAndSectionName(Bawl.int).sectionTitle.replace(/ /g,'_'));
		}
		Bawl.permaLinkGenLink.onclick = function(e){e.preventDefault();Bawl.genPermaLink(replyLinkParams,'link');};
		Bawl.permaLinkGenLink.id = 'genLink-' + replyLinkParams.int;
		Bawl.permaLinkGenLink.innerHTML = '<span class="BawlReplyLink BawlSVG BawlSVGLinkIcon"></span>';
		Bawl.replyLinkHTML.prepend(Bawl.permaLinkGenLink);
	}
	if ( ! replyLinkParams.isFirst && Bawl.settings.thankLink && replyLinkParams.type == 'comment' && replyLinkParams.origReplyTo != Bawl.userNameUnderscore ) {
		Bawl.debug('add thank link');
		Bawl.thankLinkElement = document.createElement('a');
		Bawl.thankLinkElement.id = 'thankLink-' + replyLinkParams.int;
		if ( Bawl.thankedCommentsArray.indexOf(replyLinkParams.id) == - 1 ) {
			Bawl.thankLinkElement.innerHTML = '<span class="BawlSVG BawlSVGHeartIcon"></span>';
			Bawl.thankLinkElement.onclick = function(){Bawl.giveThanks(replyLinkParams);};
			Bawl.thankLinkElement.classList = [ 'BawlReplyLink' ];
		} else {
			Bawl.thankLinkElement.innerHTML = '<span class="BawlSVG BawlSVGHeartRedIcon"></span>';
		}
		Bawl.replyLinkHTML.prepend(Bawl.thankLinkElement);
	}
	if ( replyLinkParams.type == 'newheading' && Bawl.settings.editFullSection ) {
		Bawl.editFullSectionLinkText = '<span title="' + Bawl.msgs.editFullSectionTitle + Bawl.replyLinkDebugInfo + '" class="BawlReplyLink BawlSVGEditIcon BawlSVG"></span>';
		Bawl.replyLinkParamsHeadingEdit[replyLinkParams.int] = $.extend( true, {}, replyLinkParams );
		Bawl.replyLinkParamsHeadingEdit[replyLinkParams.int].type = 'heading';
		Bawl.replyLinkParamsHeadingEdit[replyLinkParams.int].subtype = 'edit';
		Bawl.editFullSectionLink = document.createElement('span');
		Bawl.editFullSectionLink.innerHTML = '<a onclick="Bawl.' + Bawl.keyOpenReplyForm + '(Bawl.' + Object.keys(Bawl)[Object.values(Bawl).indexOf(Bawl.replyLinkParamsHeadingEdit)] + '[' + JSON.stringify(replyLinkParams.int) + '])">' + Bawl.editFullSectionLinkText + '</a>';
		Bawl.replyLinkHTML.append(Bawl.editFullSectionLink);
	}
	if ( Bawl.settings.stalkAddSubLinks && replyLinkParams.type == 'newheading' && Bawl.viewingPage && Bawl.isDiscussionPage ) {
		replyLinkParams = Bawl.addPageAndSectionTitleToRPL(replyLinkParams);
		Bawl.stalkerSubscribeLink = document.createElement('span');
		Bawl.stalkerSubscribeLink.innerHTML = '<a class="BawlSubscribe BawlSVG BawlReplyLink BawlSVGBellIcon" onclick="Bawl.' + Bawl.keyStalkSubscribe + '(Bawl.' + Bawl.keyReplyLinkParams + '[' + JSON.stringify(replyLinkParams.int) + '],\'bellicon\',null,event);"></a>';
		if ( Bawl.checkSubs[replyLinkParams.pageTitle.replace(/_/g,' ')] && Bawl.checkSubs[replyLinkParams.pageTitle.replace(/_/g,' ')].subs && Bawl.checkSubs[replyLinkParams.pageTitle.replace(/_/g,' ')].subs[replyLinkParams.sectionTitle.replace(/_/g,' ')] ) {
			Bawl.stalkerSubscribeLink.innerHTML = Bawl.stalkerSubscribeLink.innerHTML.replace('BawlSVGBellIcon','BawlSVGBellStruckIcon').replace('Bawl.' + Bawl.keyStalkSubscribe,'Bawl.' + Bawl.keyStalkUnsubscribe);
		}
		Bawl.replyLinkHTML.append(Bawl.stalkerSubscribeLink);
	}
	if ( replyLinkParams.isFirst == true ) {
		delete Bawl.replyLinkHTML.id;
		Bawl.replyLinkHTML.classList.add('BawlFirstReply');
		Bawl.replyLinkHTML.innerHTML = Bawl.replyLinkHTML.innerHTML.replace('BawlSVGIcon','BawlSVGFirstReplyIcon BawlFirstReply');
		if ( Bawl.firstReplyInSectionLastElement ) {
			if ( $('#BawlnSecBottom')[0] ) {
				$('#BawlnSecBottom')[0].parentElement.parentElement.insertBefore(Bawl.replyLinkHTML,$('#BawlnSecBottom')[0].parentElement);
			} else {
				$('#mw-content-text').append(Bawl.replyLinkHTML);
			}
		} else {
			Bawl.processElementArray[Bawl.int].parentElement.parentElement.insertBefore(Bawl.replyLinkHTML,Bawl.processElementArray[Bawl.int].parentElement);
		}
	} else if ( replyLinkParams.type == 'edit' ) {
		Bawl.debug('insert link to edit comment (' + replyLinkParams.int + ')' + ' bawlLink-' + Bawl.escapeHTML(replyLinkParams.id));
		document.getElementById('bawlLink-' + Bawl.escapeHTML(replyLinkParams.id)).append(Bawl.replyLinkHTML);
	} else if ( replyLinkParams.freshcomment == true ) {
		Bawl.debug('insert links after posting a new comment using parse-in-place, appending to #' + replyLinkParams.id);
		document.getElementById(replyLinkParams.id).append(Bawl.replyLinkHTML);
	} else if ( replyLinkParams.subtype == 'locator' ) {
			Bawl.debug('insert link to add comment (using locator), appending to processElementArray #' + Bawl.int);
			Bawl.processElementArray[Bawl.int].append(Bawl.replyLinkHTML);
			if ( Bawl.settings.autoCollapse || Bawl.settings.markNewCmts ) {
				if ( replyLinkParams.origReplyTo != Bawl.userNameUnderscore && ( Bawl.settings.autoCollapse || Bawl.settings.markNewCmts || Bawl.settings.markNewCmtsSubbed ) && Bawl.locatorTimestamp > Bawl.stalkLastViewedAutoCollapse ) {
					replyLinkParams = Bawl.addPageAndSectionTitleToRPL(replyLinkParams);//testExistingSub needs a section title
					if ( Bawl.settings.markNewCmtsSubbed && Bawl.testExistingSub(replyLinkParams) ) {
						Bawl.replyLinkHTML.parentElement.classList.add('BawlNewCmt','BawlNewCmtSubscribed','BawlEaseIn');
					} else if ( Bawl.settings.markNewCmts || Bawl.settings.autoCollapse ) {
						Bawl.replyLinkHTML.parentElement.classList.add('BawlNewCmt','BawlEaseIn');
					}
				}
			}
	} else if ( replyLinkParams.subtype == 'legacy' ) {
			Bawl.debug('insert link to add comment (legacy), appending to processElementArray #' + Bawl.int);
			Bawl.replyLinkHTMLButtons = Bawl.replyLinkHTML;
			Bawl.replyLinkHTML = document.createElement('span');
			Bawl.replyLinkHTML.append(Bawl.replyLinkHTMLButtons);
			delete Bawl.newSigTime;
			Bawl.legacyNodeDate = replyLinkParams.origTimestamp;
			if ( Bawl.settings.dateLinksLocalTime || ( Bawl.settings.autoCollapse || Bawl.settings.markNewCmts ) ) {
				Bawl.machineReadableDate = Bawl.sigDateToMachineReadable(Bawl.legacyNodeDate);
				if ( Bawl.machineReadableDate ) {
					if ( replyLinkParams.origReplyTo != Bawl.userNameUnderscore && ( Bawl.settings.autoCollapse || Bawl.settings.markNewCmts || Bawl.settings.markNewCmtsSubbed ) && Bawl.machineReadableDate > Bawl.stalkLastViewedAutoCollapse ) {
						replyLinkParams = Bawl.addPageAndSectionTitleToRPL(replyLinkParams);
						if ( Bawl.settings.markNewCmtsSubbed && Bawl.testExistingSub(replyLinkParams) ) {
							Bawl.replyLinkHTML.classList.add('BawlNewCmt','BawlNewCmtSubscribed','BawlEaseIn');
						} else if ( Bawl.settings.markNewCmts || Bawl.settings.autoCollapse ) {
							Bawl.replyLinkHTML.classList.add('BawlNewCmt','BawlEaseIn');
						}
					}
					if ( Bawl.settings.dateLinksLocalTime ) {
						Bawl.debug('replace sigdate with localized date');
						Bawl.newSigTime = Bawl.renderLocalDate(Bawl.machineReadableDate + Bawl.TZOffsetSeconds);
						Bawl.replyLinkHTML.prepend(textNodeSig.data.replace(replyLinkParams.origTimestamp, Bawl.newSigTime));
						Bawl.processElementArray[Bawl.int].title = replyLinkParams.origTimestamp;
					}
				}
			}
			if ( typeof Bawl.newSigTime == 'undefined' ) {
				Bawl.replyLinkHTML.prepend(textNodeSig.data);
			}
			Bawl.replyLinkHTML.classList.add('LegacyCmt');
			Bawl.processElementArray[Bawl.int].replaceChild(Bawl.replyLinkHTML,textNodeSig);
	} else if ( replyLinkParams.type == 'newheading' || replyLinkParams.type == 'heading' ) {
		Bawl.debug('insert link to add subsection (' + Bawl.int + ')');
		if ( mw.config.get('skin') == 'minerva' ) {
			Bawl.processElementArray[Bawl.int].prepend(Bawl.replyLinkHTML);
		} else {
			Bawl.processElementArray[Bawl.int].append(Bawl.replyLinkHTML);
		}
	}
	if ( ! replyLinkParams.isFirst && replyLinkParams.type == 'comment' && Bawl.userNameUnderscore && ( replyLinkParams.origReplyTo.replace(/ /g,'_') == Bawl.userNameUnderscore || Bawl.settings.theStranger ) && Bawl.settings.editLinks ) { //wait, I know this fucker, or I want to mess with other people's stuff
		Bawl.debug('add edit link');
		Bawl.replyLinkParamsEdit[replyLinkParams.int] = $.extend( true, {}, replyLinkParams );
		Bawl.replyLinkParamsEdit[replyLinkParams.int].type = 'edit';
		Bawl.addReplyLinkTo(Bawl.replyLinkParamsEdit[replyLinkParams.int]);
	}
};
Bawl.addToolBarLink = function(pos,newLinkSpanClass,textName,onClickAction,hrefContent) {
	if ( mw.config.get('skin') == 'minerva' ) {
		Bawl.skinLinkPadding = 'padding:0.75em 1.5em 0.75em 1.5em';
	} else if ( mw.config.get('skin') == 'monobook' ) {
		Bawl.skinLinkPadding = 'padding:0';
	} else {
		Bawl.skinLinkPadding = '';
	}
	Bawl.newLinkSpanInnerText = '';
	Bawl.newLinkSpanClass = newLinkSpanClass;
	if ( mw.config.get('skin') == 'modern' || mw.config.get('skin') == 'monobook' ) {
		Bawl.newLinkSpanInnerText = textName;
		Bawl.newLinkSpanClass = '';
	}
	Bawl.newLinkHref = '';
	if ( typeof hrefContent != 'undefined' ) {
		Bawl.newLinkHref = ' href="' + hrefContent + '"';
	}
	Bawl.newLinkOnclick = '';
	if ( typeof onClickAction != 'undefined' ) {
		Bawl.newLinkOnclick = ' onclick="' + onClickAction + '"';
	}
	Bawl.newLinkSpan = document.createElement('span');
	Bawl.newLinkSpan.title = textName + ' (Bawl)';
	Bawl.newLinkSpan.newLinkSpanClass = 'BawlYesDisplay';
	Bawl.newLinkSpan.innerHTML = '<a' + Bawl.newLinkHref + Bawl.newLinkOnclick + ' style="background-image:unset"><span style="' + Bawl.skinLinkPadding + '" class="BawlReplyLink ' + Bawl.newLinkSpanClass + '">' + Bawl.newLinkSpanInnerText + '</span></a>';
	if ( $('#ca-edit')[0] && (['vector','vector-2022','timeless','modern'].indexOf(mw.config.get('skin')) != -1 ) ) {
		Bawl.newLinkLi = document.createElement('li');
		if ( textName == Bawl.basicmsgs.newsection ) {
			Bawl.newLinkLi.id = 'BawlNewSectionTop';
		}
		Bawl.newLinkLi.appendChild(Bawl.newLinkSpan);
		if ( $('#ca-edit')[0].nextElementSibling ) {
			$('#ca-edit')[0].parentElement.insertBefore(Bawl.newLinkLi,$('#ca-edit')[0].nextElementSibling);
		} else {
			$('#ca-edit')[0].parentElement.append(Bawl.newLinkLi);
		}
		if ( Bawl.settings.hideDT && Bawl.settings.nSecLink && mw.user.options.get('discussiontools-betaenable') == 1 && mw.user.options.get('discussiontools-newtopictool') == 1 && $('#ca-addsection')[0] ) {
			$('#ca-addsection')[0].childNodes[0].classList.add('BawlNoDisplay');
		}
	} else if ( mw.config.get('skin') == 'monobook' && typeof $('#ca-edit')[0] != "undefined" ) {
		Bawl.newLinkLi = document.createElement('li');
		Bawl.newLinkLi.innerHTML = Bawl.newLinkSpan.outerHTML;
		if ( pos == -1 ) {
			$('#p-cactions .pBody ul').append(Bawl.newLinkLi);
		} else {
			$('#p-cactions .pBody ul')[0].insertBefore(Bawl.newLinkLi, $('#p-cactions .pBody ul')[0].children[pos]);
		}
	} else if ( mw.config.get('skin') == 'minerva' && typeof $('#ca-edit')[0] != "undefined" ) {
		$('#page-actions-edit').append(Bawl.newSectionLinkSpan);
		if ( Bawl.settings.hideDT ) {
			mw.util.addCSS('.ext-discussiontools-init-new-topic{display:none !important;}');
		}
	}
	if ( Bawl.settings.hideAdvFE && $('.comment .list-header')[0] ) {
		mw.util.addCSS('.comment .list-header,.comment .comment-content{display:none !important;}');
	}
};
if ( ( Bawl.settings.nSecLink || Bawl.settings.nSecBottomLink ) && mw.config.get('wgPageContentModel') == 'wikitext' && mw.config.get('wgIsProbablyEditable') ) {
	Bawl.replyLinkParamsnSec = {
		'id':'newSectionForm-' + encodeURIComponent(mw.config.get('wgPageName')),
		'type':'newsection',
		'pageTitle': mw.config.get('wgPageName'),
	};
	if ( mw.util.getParamValue('action') == 'edit' && mw.util.getParamValue('section') == 'new' ) {
		if ( mw.util.getParamValue('preloadtitle') || mw.util.getParamValue('preload') ) {
			Bawl.replyLinkParamsnSec.subtype = 'InputBox'; //we'll just pretend this is an inputbox so preload parameters will be processed
			if ( mw.util.getParamValue('preloadtitle') ) {
				Bawl.replyLinkParamsnSec.preloadtitle = mw.util.getParamValue('preloadtitle');
			}
			if ( mw.util.getParamValue('preload') ) {
				Bawl.replyLinkParamsnSec.preload = mw.util.getParamValue('preload');
				Bawl.replyLinkParamsnSec.preloadparams = [];
			}
			if ( mw.util.getParamValue('editintro') ) {
				Bawl.replyLinkParamsnSec.editIntro = mw.util.getParamValue('editintro');
			}
			Bawl.preloadParamsURL = window.location.href.match(/preloadparams%5[Bb]%5[Dd]=[^&]*/g);
			if ( Bawl.preloadParamsURL ) {
				for(Bawl.preloadParamsURLInt=0;Bawl.preloadParamsURLInt<Bawl.preloadParamsURL.length;Bawl.preloadParamsURLInt++){
					Bawl.replyLinkParamsnSec.preloadparams.push(decodeURIComponent(Bawl.preloadParamsURL[Bawl.preloadParamsURLInt].replace(/preloadparams%5[Bb]%5[Dd]=/,'')));
				}
			}
		}
	}
	if ( Bawl.settings.nSecLink ) {
		if ( $('#ca-addsection')[0] ) {
			Bawl.newSectionOrigLink = $('#ca-addsection a')[0].href;
			if ( Bawl.settings.hideDT && Bawl.newSectionOrigLink.match(/&action=edit&section=new$/) && mw.user.options.get('discussiontools-betaenable') == 1 && mw.user.options.get('discussiontools-newtopictool') == 1 ) {
				Bawl.newSectionOrigLink = Bawl.newSectionOrigLink + '&preloadparams=Bawl_nixed_DT_with_phony_preloadparams_you_are_welcome&loadBawl=0';
			} else {
				Bawl.newSectionOrigLink = Bawl.newSectionOrigLink + '&loadBawl=0';
			}
		}
		Bawl.addToolBarLink(5,'BawlSVGNewSectionIcon BawlSVG',Bawl.basicmsgs.newsection,'event.preventDefault();event.stopPropagation();$(\'#BawlnSecBottom\').addClass(\'BawlNoDisplay\');Bawl.' + Bawl.keyOpenReplyForm + '(Bawl.' + Object.keys(Bawl)[Object.values(Bawl).indexOf(Bawl.replyLinkParamsnSec)] + ')',Bawl.newSectionOrigLink);
	}
	if ( Bawl.settings.hideAdvFE && $('.minerva-talk-add-button')[0] ) {
		$('.minerva-talk-add-button')[0].outerHTML = $('.minerva-talk-add-button')[0].outerHTML.replace(/href="[^"]*"/,'');
		$('.minerva-talk-add-button').on('click',function(){Bawl.openReplyForm(Bawl.replyLinkParamsnSec);});
	}
	if ( Bawl.isDiscussionPage && Bawl.settings.nSecBottomLink && mw.config.get('wgAction') == 'view' ) {
		Bawl.newSectionBottomLinkDiv = document.createElement('div');
		Bawl.newSectionBottomLinkDiv.style = 'text-align:center';
		if ( Bawl.settings.replySecLink ) {
			Bawl.newSectionBottomLinkDiv.style = 'text-align:center;margin-top:1em'; //the extra reply-to-section-starter link (which uses a negative margin to avoid page jumping) can overlap with the bottom new section link
		}
		Bawl.newSectionBottomLink = document.createElement('a');
		Bawl.newSectionBottomLink.id = 'BawlnSecBottom';
		Bawl.newSectionBottomLink.style = 'text-align:center';
		Bawl.newSectionBottomLink.innerText = Bawl.basicmsgs['tooltip-ca-addsection'];
		Bawl.newSectionBottomLink.onclick = function() {$('#BawlnSecBottom').addClass('BawlNoDisplay');Bawl.openReplyForm(Bawl.replyLinkParamsnSec);};
		Bawl.newSectionBottomLinkDiv.append(Bawl.newSectionBottomLink);
		$('#mw-content-text').append(Bawl.newSectionBottomLinkDiv);
	}
}
if ( Bawl.settings.hideDT && $('.ext-discussiontools-init-replylink-buttons').css('display') != 'none' ) { //do not apply if already hidden in preferences
	mw.util.addCSS('.ext-discussiontools-init-replylink-buttons{display:none !important;}');
}
if ( Bawl.settings.hideDTSub && Bawl.settings.stalkAddSubLinks && $('.ext-discussiontools-init-section-subscribe').css('display') == 'block' ) {
	mw.util.addCSS('.ext-discussiontools-init-section-subscribe{display:none !important;}');
}
Bawl.replyLinkParamsFP = {'id':'editFullPage-' + mw.config.get('wgPageName'),'type':'editFullPage','pageTitle': mw.config.get('wgPageName')};
if ( Bawl.settings.editFullPage ) {
	Bawl.addToolBarLink(5,'BawlSVGEditIcon BawlSVG',Bawl.basicmsgs['action-edit'],'Bawl.' + Bawl.keyOpenReplyForm + '(Bawl.' + Object.keys(Bawl)[Object.values(Bawl).indexOf(Bawl.replyLinkParamsFP)] + ')');
}
Bawl.collapseSection = function(sectionID,level,linkElement) {
	if ( Bawl.settings.collapArticle && document.activeElement.nodeName == 'A' && ! document.activeElement.classList.contains('sectioncollapse') ) {
		Bawl.debug('you clicked a link within a header. not (un)collapsing section');
		return;
	} else if ( typeof sectionID == 'undefined' && ( linkElement.target.nodeName.match(/^H[12]$/) || linkElement.target.classList.contains('BawlSVGChevronIcon') || linkElement.target.classList.contains('mw-headline') ) ) {
		Bawl.debug('you clicked a header in a non-link area to collapse/uncollapse the section');
		Bawl.findCollapsHeaderElementInt = 0;
		Bawl.findCollapsHeaderElement = linkElement.target;
		while ( Bawl.findCollapsHeaderElementInt < 10 && ! Bawl.findCollapsHeaderElement.nodeName.match(/^H[12]$/) ) {
			Bawl.findCollapsHeaderElementInt++;
			Bawl.findCollapsHeaderElement = Bawl.findCollapsHeaderElement.parentElement;
		}
		sectionID = Bawl.findCollapsHeaderElement.parentElement.id;
		level = Bawl.findCollapsHeaderElement.nodeName.slice(1);
	}
	Bawl.debug('(un)collapse section ' + sectionID);
	if ( sectionID != '' && $('#'+sectionID + ' .BawlForm')[0]) {
		Bawl.debug('won\'t collapse a section with an open reply form in it');
		$('#BawlReplyForm').scrollIntoView(Bawl.smoothScroll);
		return;
	}
	if ( $('#'+sectionID)[0] && $('#'+sectionID).hasClass('collapsedSection') ) {
		Bawl.debug('unhiding section ' + sectionID);
		$('#'+sectionID+' *').removeClass('BawlNoDisplay');
		$('#'+sectionID).removeClass('collapsedSection');
		$('#'+sectionID + ' .sectioncollapse')[0].classList.remove('BawlSVGChevronIconRot');
		return;
	}
	Bawl.debug('hiding section ' + sectionID);
	$('#'+sectionID+' *:not(H' + level + ',H' + level + ' *)').addClass('BawlNoDisplay');
	$('#'+sectionID).addClass('collapsedSection');
	$('#'+sectionID + ' .sectioncollapse')[0].classList.add('BawlSVGChevronIconRot');
};
Bawl.toggleAllSections = function() {
	Bawl.toggleAllSectionsTotal = $('#mw-content-text .BawlH2SectContainer:not(.collapsedSection),#mw-content-text .BawlH1SectContainer:not(.collapsedSection)').length;
	if ( $('#mw-content-text .BawlH2SectContainer,#mw-content-text .BawlH1SectContainer').length == 0 ) {
		Bawl.debug('nothing was collapsed');
		return;
	} else if ( Bawl.toggleAllSectionsTotal != 0 ) {
		Bawl.debug('collapse all sections');
		$('#firstHeading .sectioncollapse span')[0].classList.add('BawlSVGChevronIconRot');
		Bawl.toggleAllH1SectionsTotal = $('#mw-content-text .BawlH1SectContainer:not(.collapsedSection)');
		Bawl.toggleAllH2SectionsTotal = $('#mw-content-text .BawlH2SectContainer:not(.collapsedSection)');
	} else {
		Bawl.debug('uncollapse all sections');
		$('#firstHeading .sectioncollapse span')[0].classList.remove('BawlSVGChevronIconRot');
		Bawl.toggleAllH1SectionsTotal = $('#mw-content-text .BawlH1SectContainer.collapsedSection');
		Bawl.toggleAllH2SectionsTotal = $('#mw-content-text .BawlH2SectContainer.collapsedSection');
	}
	for (Bawl.toggleAllSectionsInt=0;Bawl.toggleAllSectionsInt<Bawl.toggleAllH1SectionsTotal.length;Bawl.toggleAllSectionsInt++){
		Bawl.collapseSection(Bawl.toggleAllH1SectionsTotal[Bawl.toggleAllSectionsInt].id,1);
	}
	for (Bawl.toggleAllSectionsInt=0;Bawl.toggleAllSectionsInt<Bawl.toggleAllH2SectionsTotal.length;Bawl.toggleAllSectionsInt++){
		Bawl.collapseSection(Bawl.toggleAllH2SectionsTotal[Bawl.toggleAllSectionsInt].id,2);
	}
};
Bawl.allSectionsHTMLContainer = {};
Bawl.sectionHTMLContainer = {};
Bawl.splitHTMLSections = function(level,elementToSort) {
	if ( $(elementToSort + ' H' + level + ':not(#mw-toc-heading)')[1] ) { //don't bother if there are less than 2 sections of this type
		if ( ! Bawl.collapsingArticle && $('.toctogglecheckbox')[0] && Bawl.settings.reverseSectionOrder ) {
			Bawl.debug('hiding the TOC. kinda confusing when we\'re going to Australia, and if you are reversing sections you probably want to start reading anyway.');
			$('.toctogglecheckbox')[0].checked = true;
		}
		Bawl.sectionHTMLContainer[level] = {};
		Bawl.allSectionsHTMLContainer[level] = document.createElement('div');
		Bawl.allSectionsHTMLContainer[level].classList.add('BawlH' + level + 'SectionsContainer');
		$(elementToSort + ' H' + level + ':not(#mw-toc-heading)')[0].parentElement.insertBefore(Bawl.allSectionsHTMLContainer[level],$(elementToSort + ' H' + level + ':not(#mw-toc-heading)')[0]);
		Bawl.contentSectionChildren = Array.from($(elementToSort).children());
		Bawl.contentLength = Bawl.contentSectionChildren.length;
		for (Bawl.intContentElement = 0; Bawl.intContentElement < Bawl.contentLength; Bawl.intContentElement++) {
			if ( Bawl.contentSectionChildren[Bawl.intContentElement].nodeName == 'H' + level ) {
				Bawl.debug('another section header found');
				if ( ! Bawl.collapsingArticle && Bawl.settings.autoCollapse && Bawl.intContentElement == Bawl.contentLength -1 && typeof Bawl.sectionHTMLID != 'undefined' && ! $('#' + Bawl.sectionHTMLID + ' .BawlNewCmt')[0] ) {
					Bawl.debug('collapse previous section as it contains nothing new since your last visit');
					Bawl.collapseSection(Bawl.sectionHTMLID,level);
				}
				Bawl.parentSectionHTMLID = '';
				if ( Bawl.intContentH1Div ) {
					Bawl.parentSectionHTMLID = '_' + Bawl.intContentH1Div;
				}
				Bawl.sectionHTMLID = 'BawlL' + level + 'sectionContainer' + Bawl.intContentElement + Bawl.parentSectionHTMLID;
				if ( ( Bawl.collapsingArticle && Bawl.settings.collapArticle ) || Bawl.settings.collapsible ) {
					Bawl.collapseChevron = document.createElement('span');
					Bawl.collapseChevron.style = 'float:' + Bawl.CSSDirectionR;
					Bawl.collapseChevron.className = 'sectioncollapse BawlSVG BawlSVGChevronIcon';
					Bawl.contentSectionChildren[Bawl.intContentElement].append(Bawl.collapseChevron);
				}
				Bawl.debug('append or prepend (for section reversal) new section div to allSectionsHTMLContainer');
				Bawl.sectionHTMLContainer[level][Bawl.intContentElement] = document.createElement('div');
				Bawl.sectionHTMLContainer[level][Bawl.intContentElement].id = Bawl.sectionHTMLID;
				Bawl.sectionHTMLContainer[level][Bawl.intContentElement].classList.add('BawlH' + level + 'SectContainer');
				Bawl.sectionHTMLContainer[level][Bawl.intContentElement].prepend(Bawl.contentSectionChildren[Bawl.intContentElement]); //add H1/H2/etc element to new div
				if ( ! Bawl.collapsingArticle && Bawl.settings.reverseSectionOrder ) {
					Bawl.allSectionsHTMLContainer[level].prepend(Bawl.sectionHTMLContainer[level][Bawl.intContentElement]);
				} else {
					Bawl.allSectionsHTMLContainer[level].append(Bawl.sectionHTMLContainer[level][Bawl.intContentElement]);
				}
				Bawl.sectionHTMLContainer[level][Bawl.intContentElement].append(Bawl.contentSectionChildren[Bawl.intContentElement]);
				Bawl.latestHTMLSectionInt = Bawl.intContentElement;
			} else if ( typeof Bawl.latestHTMLSectionInt != 'undefined' ) { //some element of a section, reconstruct section within new div
				Bawl.sectionHTMLContainer[level][Bawl.latestHTMLSectionInt].append(Bawl.contentSectionChildren[Bawl.intContentElement]);
			}
		}
		if ( ( Bawl.collapsingArticle && Bawl.settings.collapArticle ) || ! Bawl.settings.ninjaLoader ) {
			$(elementToSort + ' H' + level).on('click',function() { Bawl.collapseSection(undefined,undefined,event); });
		}
		delete Bawl.latestHTMLSectionInt;
		if ( Bawl.settings.collapsible && ! $('#BawlCollapseAllSections')[0] ) {
			Bawl.collapseChevron = document.createElement('span');
			Bawl.collapseChevron.style = 'float:' + Bawl.CSSDirectionR;
			Bawl.collapseChevron.innerHTML = '<a id="BawlCollapseAllSections" class="sectioncollapse BawlReplyLink" style="color:#888"><span class="BawlSVG BawlSVGChevronIcon"></span></a>';
			$('#firstHeading').append(Bawl.collapseChevron);
			$('#BawlCollapseAllSections').on('click',function(){Bawl.toggleAllSections();});
		}
	} else {
		Bawl.debug('there\'s no or only one level ' + level + ' header in ' + elementToSort);
	}
};
Bawl.floatTheTOC = function(){
	if ( mw.config.get('skin') == 'vector-2022' ) {
		$('body').append($('.mw-table-of-contents-container.mw-sticky-header-element')[0]);
		$('.mw-table-of-contents-container.mw-sticky-header-element').addClass('BawlFloatingToC');
		$('.BawlFloatingToC').removeClass(['mw-sticky-header-element','mw-table-of-contents-container']);
		$('.BawlFloatingToC ul').addClass('BawlNoDisplay');
		$('.BawlFloatingToC').on('click',function(){
			if ( $('.BawlFloatingToC ul')[0] && $('.BawlFloatingToC ul')[0].classList.contains('BawlNoDisplay') ) {
				$('.BawlFloatingToC ul').removeClass('BawlNoDisplay');
			} else {
				$('.BawlFloatingToC ul').addClass('BawlNoDisplay');
			}
		});
	} else if ( $('#toc')[0] ) {
		if ( document.location.href.match(/(\.|\/\/)m\./) && mw.config.get('skin') == 'minerva' && $('#toctogglecheckbox')[0] ) {
			$('#toctogglecheckbox')[0].checked = false;
		} else if ( $('#toctogglecheckbox')[0] ) {
			$('#toctogglecheckbox')[0].checked = true;
		} else {
			$('#toc .toctitle:eq(0)').addClass('BawlNoDisplay');
		}
		$('body').append($('#toc')[0]);
		$('#toc').addClass('BawlFloatingToC');
		$('#toc').on('click',function(ev){ev.stopPropagation();});
		if ( $('#mw-toc-heading')[0] ) {
			$('#mw-toc-heading')[0].outerHTML = $('#mw-toc-heading')[0].outerHTML;
		}
	}
};
if ( Bawl.settings.replySecLink && ( Bawl.isDiscussionPage || $('.BawlCmt')[0] ) ) {
	Bawl.debug('links will be added to the bottom of sections to reply to them');
	Bawl.replyToSectionLinkNeeded = true;
}
Bawl.commentersInSection = [];
Bawl.commentersInSectionBySection = {};
Bawl.monthRegExpPrep = '';
for (Bawl.intMonthRegExp = 1; Bawl.intMonthRegExp < 13; Bawl.intMonthRegExp++) {
	Bawl.monthRegExpPrep = Bawl.monthRegExpPrep + Bawl.monthNames[Bawl.intMonthRegExp] + '|' + Bawl.monthNames[Bawl.intMonthRegExp].slice(0,3) + '|';
}
delete Bawl.intMonthRegExp;
Bawl.EnglishMonths = ['','Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
Bawl.monthRegExpPrep = Bawl.monthRegExpPrep.slice(0,Bawl.monthRegExpPrep.length - 1);
Bawl.signDateRegExp = new RegExp('([0-2]?[0-9]:[0-5][0-9] |[0-3]?[0-9] |(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) |[0-9]{4} |\\([A-Z]{1,9}\\)){5}');
Bawl.signDateRegExpLocalMonths = new RegExp('([0-2]?[0-9]:[0-5][0-9][\.,]? |[0-3]?[0-9][\.,]? |(' + Bawl.monthRegExpPrep + ')[\.,]? |[0-9]{4}[\.,]? |\\([A-Z0-9\+\-]{1,9}\\)){5}');
if ( mw.config.get('wgContentLanguage') == 'fa' ) {
	Bawl.signDateRegExpLocalMonths = new RegExp('([۰۱۲۳۴۵۶۷۸۹]?[۰۱۲۳۴۵۶۷۸۹]:[۰۱۲۳۴۵۶۷۸۹][۰۱۲۳۴۵۶۷۸۹][\.،]? |[۰۱۲۳۴۵۶۷۸۹]?[۰۱۲۳۴۵۶۷۸۹][\.،]? |(' + Bawl.monthRegExpPrep + ')[\.،]? |[۰۱۲۳۴۵۶۷۸۹]{4}[\.،]? |\\([A-Z۰۱۲۳۴۵۶۷۸۹\+\-]{1,9}\\)|ساعت| ){7}');
} else if ( mw.config.get('wgContentLanguage') == 'pt' ) {
	Bawl.signDateRegExpLocalMonths = new RegExp('[0-2][0-9]h[0-5][0-9]min de [0-3]?[0-9] de (' + Bawl.monthRegExpPrep + ') de [0-9]{4} \\([A-Z0-9\+\-]{1,9}\\)');
}
Bawl.TZOffsetDate = new Date();
Bawl.TZOffsetDateWiki = Bawl.TZOffsetDate.toLocaleString("en", {timeZone:Bawl.wikiTimezone});
Bawl.TZOffsetDateUTC = Bawl.TZOffsetDate.toLocaleString("en", {timeZone:'UTC'});
Bawl.TZOffsetDateWikiMs = new Date(Bawl.TZOffsetDateWiki).getTime();
Bawl.TZOffsetDateUTCMs = new Date(Bawl.TZOffsetDateUTC).getTime();
Bawl.TZOffsetSeconds = ( Bawl.TZOffsetDateWikiMs - Bawl.TZOffsetDateUTCMs);
Bawl.localDateFormat = {year:'numeric',month:'short',weekday:undefined,day:'numeric',hour:'2-digit',minute:'2-digit',hour12:false};
Bawl.localDateFormatTimeOnly = {year:undefined,month:undefined,weekday:undefined,day:undefined,hour:'2-digit',minute:'2-digit',hour12:false};
if ( Bawl.settings.dateLinksLocalTime12H ) { Bawl.localDateFormat.hour12 = true;Bawl.localDateFormatTimeOnly.hour12 = true;}
if ( Bawl.settings.dateLinksLocalTimeNumMonth ) { Bawl.localDateFormat.month = 'numeric';}
else if ( Bawl.settings.dateLinksLocalTimeLongMonth ) { Bawl.localDateFormat.month = 'long';}
if ( Bawl.settings.dateLinksLocalTimeWeekday ) { Bawl.localDateFormat.weekday = 'short';}
else if ( Bawl.settings.dateLinksLocalTimeWeekdayFull ) { Bawl.localDateFormat.weekday = 'long';}
Bawl.userOptTZ = mw.user.options.get('timecorrection').match(/ZoneInfo\|[0-9]+\|(.+)/);
if ( Bawl.settings.dateLinksLocalTimeUserOptTZ && Bawl.userOptTZ ) { Bawl.localDateFormat.timeZone = Bawl.userOptTZ[1];Bawl.localDateFormatTimeOnly.timeZone = Bawl.userOptTZ[1];}
Bawl.dayOfWeek = new Date(Bawl.timestampInit).getDay();
Bawl.msgDaysAgo = Bawl.basicmsgs.days.replace(/\{\{PLURAL[^\|]*\|([^\|]*)\|(.*)\}\}/,'$2');
Bawl.msgMonthsAgo = Bawl.basicmsgs.months.replace(/\{\{PLURAL[^\|]*\|([^\|]*)\|(.*)\}\}/,'$2');
Bawl.renderLocalDate = function(localTimestamp) {
	if ( Bawl.settings.dateLinksLocalTimeRelative ) {
		if ( (Bawl.timestampInit - localTimestamp) < 86400000 && Bawl.dayOfWeek == new Date(localTimestamp).getDay() ) { //today
			Bawl.localDateRelative = Bawl.basicmsgs['today-at'].replace('$1',new Date(localTimestamp).toLocaleString(undefined,Bawl.localDateFormatTimeOnly));
		} else if ( (Bawl.timestampInit - localTimestamp) < 172800000 && ( Bawl.dayOfWeek == (new Date(localTimestamp).getDay() +1) || ( Bawl.dayOfWeek == (new Date(localTimestamp).getDay() -6) ) ) ) { //yesterday
			Bawl.localDateRelative = Bawl.basicmsgs['yesterday-at'].replace('$1',new Date(localTimestamp).toLocaleString(undefined,Bawl.localDateFormatTimeOnly));
		} else if ( (Bawl.timestampInit - localTimestamp) < 604800000 ) { //less than 7 days ago, say "n days ago" based on the weekday
			Bawl.weekDayOfCmt = new Date(localTimestamp).getDay();
			if ( Bawl.dayOfWeek < Bawl.weekDayOfCmt ) {
				Bawl.commentDaysAgo = (Bawl.dayOfWeek +7) - Bawl.weekDayOfCmt;
			} else {
				Bawl.commentDaysAgo = Bawl.dayOfWeek - Bawl.weekDayOfCmt;
			}
			Bawl.localDateRelative = Bawl.basicmsgs.ago.replace('$1',Bawl.msgDaysAgo.replace('$1',Bawl.commentDaysAgo));
		} else if ( (Bawl.timestampInit - localTimestamp) < 5356800000 ) { //less than 62 days ago, say "n days ago"
			Bawl.localDateRelative = Bawl.basicmsgs.ago.replace('$1',Bawl.msgDaysAgo.replace('$1',Math.round((Bawl.timestampInit - localTimestamp)/86400000)));
		} else if ( (Bawl.timestampInit - localTimestamp) < 63244800000 ) { //less than 732 days ago (one non-leap year plus one leap year plus one day), say "n months ago"
			Bawl.localDateRelative = Bawl.basicmsgs.ago.replace('$1',Bawl.msgMonthsAgo.replace('$1',Math.round((Bawl.timestampInit - localTimestamp)/86400000/30.44))); //30.44 is like an average month.. I'd say close enough for this
		} else {
			Bawl.localDateRelative = Bawl.basicmsgs.ago.replace('$1',Bawl.msgMonthsAgo.replace('$1',Math.round((Bawl.timestampInit - localTimestamp)/86400000/365)));
		}
	}
	if ( Bawl.settings.dateLinksLocalTimeAbsolute) {
		Bawl.localDateAbsolute = new Date(localTimestamp).toLocaleString(undefined,Bawl.localDateFormat);
	}
	if ( Bawl.settings.dateLinksLocalTimeRelative && Bawl.settings.dateLinksLocalTimeAbsolute) {
		Bawl.localDateFormatted = Bawl.localDateRelative + ' (' + Bawl.localDateAbsolute + ')';
	} else if ( Bawl.settings.dateLinksLocalTimeRelative ) {
		Bawl.localDateFormatted = Bawl.localDateRelative;
	} else if ( Bawl.settings.dateLinksLocalTimeAbsolute ) {
		Bawl.localDateFormatted = Bawl.localDateAbsolute;
	}
	return Bawl.localDateFormatted;
};
Bawl.getPageTitleAndSectionName = function(mwHeadLineInt) { //this is called right after opening the reply form, so the user can start typing while this runs. Could also do it upon hitting the reply button, but that would make replying slightly less responsive
	if ( Bawl.UIReplyButton ) {
		Bawl.UIReplyButton.setDisabled(true); //just so you can't reply before this stuff is known
	}
	if ( typeof Bawl.mwHeadLineArray == 'undefined' ) {//going over .mw-headline/.mw-editsection elements (typically <50ms) only has to be done once per page load, after that the values can retrieved from the array (typically <1ms)
		Bawl.mwHeadLineArray = Array.from($('#mw-content-text .mw-headline'));
		Bawl.mwEditSectionArray = Array.from($('#mw-content-text .mw-editsection'));
		Bawl.mwHeadLineSectionTitle = [];
		if ( Bawl.mwHeadLineArray.length != Bawl.mwEditSectionArray.length ) {
			Bawl.debug('mismatched amount of .mw-headlines and .mw-editsections, get section titles using alternative slower method');
			Bawl.gotSectionTitlesAlt = true;
			Bawl.mwEditSectionArrayLength = Bawl.mwEditSectionArray.length;
			Bawl.mwEditSectionBadBadBad = false;
			for (Bawl.mwEditSectionInt=0;Bawl.mwEditSectionInt<Bawl.mwEditSectionArray.length;Bawl.mwEditSectionInt++) {
				Bawl.mwEditSectionAltCheckLink = Bawl.mwEditSectionArray[Bawl.mwEditSectionInt].querySelectorAll('A')[0];
				if ( Bawl.mwEditSectionAltCheckLink && Bawl.mwEditSectionAltCheckLink.href.match(/action=edit/) ) {
					Bawl.mwHeadLineSectionTitle.push(Bawl.mwEditSectionArray[Bawl.mwEditSectionInt].parentElement.querySelectorAll('.mw-headline')[0].innerText);
				} else {
					Bawl.debug('mwEditSectionArray #' + Bawl.mwEditSectionInt + ' is a FAKE .mw-editsection! Bad bad bad! Changing it\'s class to mw-editsection-like.');
					Bawl.mwEditSectionArray[Bawl.mwEditSectionInt].classList.add('mw-editsection-like');
					Bawl.mwEditSectionArray[Bawl.mwEditSectionInt].classList.remove('mw-editsection');
					Bawl.mwEditSectionBadBadBad = true;
				}
			}
			if ( Bawl.mwEditSectionBadBadBad ) {
				Bawl.debug('You had fake mw-editsections. Let\'s try this again.');
				delete Bawl.mwHeadLineArray;
				delete Bawl.gotSectionTitlesAlt;
				return Bawl.getPageTitleAndSectionName(mwHeadLineInt);
			}
		}
		if ( Bawl.mwHeadLineArray.length != Bawl.mwEditSectionArray.length && Bawl.mwHeadLineSectionTitle.length != Bawl.mwEditSectionArrayLength ) {
			Bawl.addScrewedLink('mismatched amount of headlines (' + Bawl.mwHeadLineArray.length + ') / section titles related to .mw-editsection (' + Bawl.mwHeadLineSectionTitle.length + ') and section edit links (' + Bawl.mwEditSectionArray.length + ')','Unexpected difference between the number of section titles and section edit links.');
			return false;
		}
		Bawl.mwHeadLinePageTitle = [];
		Bawl.mwHeadLineSectionSeqID = [];
		Bawl.mwHeadLineSectionSeq = [];
		for(Bawl.mwEditSectionArrayInt=0;Bawl.mwEditSectionArrayInt<Bawl.mwEditSectionArray.length;Bawl.mwEditSectionArrayInt++) {
			if ( typeof Bawl.gotSectionTitlesAlt == 'undefined' ) {
				Bawl.mwHeadLineSectionTitle.push(Bawl.mwHeadLineArray[Bawl.mwEditSectionArrayInt].innerText);
			}
			if ( mw.config.get('skin') == 'minerva' ) {
				Bawl.getPageTitleFromElement = 'A.edit-page';
			} else {
				Bawl.getPageTitleFromElement = 'A';
			}
			for (Bawl.mwEditSectionElementArrayInt=0;Bawl.mwEditSectionElementArrayInt<Bawl.mwEditSectionArray[Bawl.mwEditSectionArrayInt].querySelectorAll(Bawl.getPageTitleFromElement).length;Bawl.mwEditSectionElementArrayInt++){
				Bawl.mwEditSectionArrayTestElement = Bawl.mwEditSectionArray[Bawl.mwEditSectionArrayInt].querySelectorAll(Bawl.getPageTitleFromElement)[Bawl.mwEditSectionElementArrayInt];
				if ( Bawl.mwEditSectionArrayTestElement.attributes.href && Bawl.mwEditSectionArrayTestElement.attributes.href.nodeValue && Bawl.mwEditSectionArrayTestElement.attributes.href.nodeValue.match(/.*title=([^&]*).*/) ) {
					Bawl.mwHeadLinePageTitle.push(decodeURIComponent(Bawl.mwEditSectionArray[Bawl.mwEditSectionArrayInt].querySelectorAll(Bawl.getPageTitleFromElement)[Bawl.mwEditSectionElementArrayInt].attributes.href.nodeValue.replace( /.*title=([^&]*).*/, '$1')).replace(/_/g, ' '));
					break;
				}
			}
			Bawl.sectionPlusPage = Bawl.mwHeadLinePageTitle[Bawl.mwEditSectionArrayInt] + Bawl.mwHeadLineSectionTitle[Bawl.mwEditSectionArrayInt];
			for (Bawl.secseqint = 0; Bawl.secseqint < 100; Bawl.secseqint++) {
				Bawl.debug('make record of the section+pagename so others with the same data can be identified - this is #' + Bawl.secseqint);
				if ( Bawl.mwHeadLineSectionSeqID.indexOf(Bawl.sectionPlusPage + '-' + Bawl.secseqint) == -1 ) {
					Bawl.mwHeadLineSectionSeqID.push(Bawl.sectionPlusPage + '-' + Bawl.secseqint);
					Bawl.mwHeadLineSectionSeq.push(Bawl.secseqint);
					break;
				}
			}
		}
	}
	Bawl.mwHeadLineIndex = Bawl.mwEditSectionArray.indexOf(Bawl.processElementArray[mwHeadLineInt]);
	if ( Bawl.UIReplyButton ) {
		Bawl.UIReplyButton.setDisabled(false);
	}
	return {'pageTitle':Bawl.mwHeadLinePageTitle[Bawl.mwHeadLineIndex],'sectionTitle':Bawl.mwHeadLineSectionTitle[Bawl.mwHeadLineIndex],'sectionSeq':Bawl.mwHeadLineSectionSeq[Bawl.mwHeadLineIndex]};
};
Bawl.addPageAndSectionTitleToRPL = function(replyLinkParams) {
	if ( typeof replyLinkParams.sectionTitle != 'undefined' || typeof replyLinkParams.pageTitleInt != 'number') {
		Bawl.debug('these replyLinkParams either already have a sectionTitle or there is no pageTitleInt so we can\'t work with it');
		return replyLinkParams;
	}
	if ( replyLinkParams.pageTitleInt == -1 ) {
		Bawl.debug('addPageAndSectionTitleToRPL found pageTitleInt -1, assuming sectionless comment');
		replyLinkParams.sectionTitle = '';
		replyLinkParams.sectionseq = 0;
		if ( typeof replyLinkParams.pageTitle == 'undefined' ) { //locator for example already knows the pagetitle but doesn't know the section.
			replyLinkParams.pageTitle = mw.config.get('wgPageName');
		}
		Bawl.replyLinkParams[replyLinkParams.int] = replyLinkParams;
		return replyLinkParams;
	}
	Bawl.sectionInfo = Bawl.getPageTitleAndSectionName(replyLinkParams.pageTitleInt);
	if ( Bawl.sectionInfo ) {
		if ( typeof replyLinkParams.pageTitle == 'undefined' ) { //locator for example already knows the pagetitle but doesn't know the section.
			replyLinkParams.pageTitle = Bawl.sectionInfo.pageTitle;
		}
		replyLinkParams.sectionTitle = Bawl.sectionInfo.sectionTitle;
		replyLinkParams.sectionseq = Bawl.sectionInfo.sectionSeq;
	}
	return replyLinkParams;
};
//The following types exist, these describe how to handle the item:
// comment: reply to existing comment (has signature, placed in appropriate location below existing comment)
// edit: alteration of an existing comment (no new signature)
// newheading: new subsection with comment (has signature, uses appendtext in the API)
// heading: only exists with subtype "edit" (full section edit)
// newsection: creates a new section with comment at the bottom of the page (section=new in the API)
// BCL: Bawl Comment Link, special link that either opens the reply form (if the user has Bawl loaded already) or reloads the page with withJS option to load Bawl
// editFullPage: edit the page as a whole. Doesn't squeeze output into a single line, doesn't add signature, etc
//Subtypes, describes more minor adjustments to the general type:
// InputBox: subtype for newsection. See mediawiki.org/wiki/Extension:InputBox
// legacy: subtype for comments, searches HTML for text that looks like a signature date. Searches <p>, <dd> and <li>, end to start. If a date is found it keeps going to try and find a username link to extract the username.
// locator: subtype for comments, added to comments by Bawl by default. Contains username and the date as the number of milliseconds since 1970-01-01. You know. The SENSIBLE thing to do.
// heading: subtype for heading
// page: subtype for BCL, add comment to the bottom of the page.
// section: subtype for BCL, add comment to the bottom of the section.
// edit: subtype for "heading"
Bawl.searchNodeContents = function() {
	Bawl.elementClassList = Array.from(Bawl.processElementArray[Bawl.int].classList);
	if ( typeof Bawl.elementClassList == 'undefined' ) {
		Bawl.elementClassList = [];
	}
	if ( ( ! Bawl.settings.addLinkTS || ( Bawl.settings.addLinkTS && Bawl.nextCommentIsFirstInSection ) ) && Bawl.elementClassList.includes('BawlCmt') ) {
		Bawl.debug('locator found');
		if ( Bawl.processElementArray[Bawl.int].id.match(/(.*)\:([0-9]{13,14})\:([^\:]*).*/) == null ) {
			Bawl.debug('invalid locator');
			return;
		}
		Bawl.locatorUsername = Bawl.processElementArray[Bawl.int].id.replace(/(.*)\:([0-9]{13,14})\:([^\:]*).*/, '$1').replace(/(BAWLCOLON|BWLCLN)/g, ':'); //in time "BAWLCOLON" can be deprecated
		Bawl.locatorTimestamp = Bawl.processElementArray[Bawl.int].id.replace(/(.*)\:([0-9]{13,14})\:([^\:]*).*/, '$2');
		Bawl.locatorPageTitle = Bawl.processElementArray[Bawl.int].id.replace(/(.*)\:([0-9]{13,14})\:([^\:]*).*/, '$3').replace(/(BAWLCOLON|BWLCLN)/g, ':');
		Bawl.replyLinkParams[Bawl.int] = {
			'int': Bawl.int,
			'type':'comment',
			'subtype':'locator',
			'id': Bawl.processElementArray[Bawl.int].id,
			'pageTitle': decodeURIComponent(Bawl.locatorPageTitle),
			'pageTitleInt':Bawl.pageTitleToEditInt,
			'origReplyTo': decodeURIComponent(Bawl.locatorUsername),
			'origTimestamp': Bawl.locatorTimestamp,
		};
		if ( Bawl.settings.dateLinksLocalTime ) {
			Bawl.newSigTime = Bawl.renderLocalDate(Number(Bawl.locatorTimestamp));
			for(Bawl.newSigTimeChildNodesInt=0;Bawl.newSigTimeChildNodesInt<Bawl.processElementArray[Bawl.int].childNodes.length;Bawl.newSigTimeChildNodesInt++){
				if ( Bawl.processElementArray[Bawl.int].childNodes[Bawl.newSigTimeChildNodesInt].nodeName == '#text' && Bawl.processElementArray[Bawl.int].childNodes[Bawl.newSigTimeChildNodesInt].textContent.match(Bawl.signDateRegExpLocalMonths) ) {
					Bawl.origSigDate = Bawl.processElementArray[Bawl.int].childNodes[Bawl.newSigTimeChildNodesInt].textContent.replace(/[\.,]/g, '').match(Bawl.signDateRegExpLocalMonths)[0];
					Bawl.processElementArray[Bawl.int].title = Bawl.origSigDate; //put original timestamp in the title
					Bawl.processElementArray[Bawl.int].childNodes[Bawl.newSigTimeChildNodesInt].textContent = Bawl.processElementArray[Bawl.int].childNodes[Bawl.newSigTimeChildNodesInt].textContent.replace(/[\.,]/g, '').replace(Bawl.origSigDate, Bawl.newSigTime);
				}
			}
		}
		if ( ! Bawl.firstReplyInSection ) {
			Bawl.firstReplyInSection = $.extend( true, {}, Bawl.replyLinkParams[Bawl.int] );
			Bawl.firstReplyInSection.isFirst = true;
		}
		Bawl.addReplyLinkTo(Bawl.replyLinkParams[Bawl.int]);
		Bawl.nextCommentIsFirstInSection = false;
		if ( Bawl.commentersInSection.indexOf(decodeURIComponent(Bawl.locatorUsername.replace(/_/g,' '))) == -1 ) {
			Bawl.commentersInSection.push(decodeURIComponent(Bawl.locatorUsername.replace(/_/g,' ')));
		}
	} else if ( Bawl.elementClassList.includes('mw-editsection') ) { //section edit link
		if ( Bawl.replyToSectionLinkNeeded && Bawl.firstReplyInSection && Bawl.commentersInSection.length > 3 ) {
			Bawl.debug('found a new section. adding "reply to section starter" link for the previous section');
			Bawl.addReplyLinkTo(Bawl.firstReplyInSection);
			delete Bawl.firstReplyInSection;
		}
		Bawl.commentersInSectionBySection[Bawl.pageTitleToEditInt] = Bawl.commentersInSection;
		Bawl.commentersInSection = [];
		delete Bawl.firstReplyInSection;
		Bawl.debug('mw-editsection link found (' + Bawl.int + ')');
		Bawl.pageTitleToEditInt = Bawl.int;
		Bawl.replyLinkParams[Bawl.int] = {
			'int':Bawl.int,
			'id':'heading-' + Bawl.int,
			'type':'newheading',
			'subtype':'heading',
			'pageTitleInt':Bawl.pageTitleToEditInt,
		};
		if ( Bawl.settings.editFullSection || Bawl.settings.secLinks || Bawl.settings.stalkAddSubLinks || Bawl.settings.dateLinksIconSection ) {
			Bawl.addReplyLinkTo(Bawl.replyLinkParams[Bawl.int]); //add link to create a new subsection
			Bawl.sectionHeaderLinksAdded = true;
		}
		Bawl.nextCommentIsFirstInSection = true;
	} else if ( Bawl.elementClassList.includes('commentbox') || Bawl.elementClassList.includes('createbox') ) {
		Bawl.debug('found InputBox');
		if ( Bawl.settings.inputBoxTO ) {
			Bawl.debug('inputbox takeover enabled');
				Bawl.replyLinkParams[Bawl.int] = {
					'int': Bawl.int,
					'id':'newSectionForm-InputBox',
					'type':'newsection',
					'subtype':'InputBox',
					'pageTitle': mw.config.get('wgPageName'),
					'preloadparams': []
				};
				for (Bawl.intInputBox = 0; Bawl.intInputBox < Bawl.processElementArray[Bawl.int].children.length; Bawl.intInputBox++) {
					Bawl.debug('process child element #' + Bawl.intInputBox + '/' + Bawl.processElementArray[Bawl.int].children.length + ' for element #' + Bawl.int);
					if ( Bawl.processElementArray[Bawl.int].children[Bawl.intInputBox].name == 'preload' ) {
						Bawl.replyLinkParams[Bawl.int].preload = Bawl.processElementArray[Bawl.int].children[Bawl.intInputBox].value;
					} else if ( Bawl.processElementArray[Bawl.int].children[Bawl.intInputBox].name == 'preloadparams[]' ) {
						Bawl.replyLinkParams[Bawl.int].preloadparams.push(Bawl.processElementArray[Bawl.int].children[Bawl.intInputBox].value);
					} else if ( Bawl.processElementArray[Bawl.int].children[Bawl.intInputBox].name == 'editintro' ) {
						Bawl.replyLinkParams[Bawl.int].editIntro = Bawl.processElementArray[Bawl.int].children[Bawl.intInputBox].value;
					} else if ( Bawl.processElementArray[Bawl.int].children[Bawl.intInputBox].name == 'summary' ) {
						Bawl.replyLinkParams[Bawl.int].summary = Bawl.processElementArray[Bawl.int].children[Bawl.intInputBox].value;
					} else if ( Bawl.processElementArray[Bawl.int].children[Bawl.intInputBox].name == 'minor' ) {
						Bawl.replyLinkParams[Bawl.int].minor = Bawl.processElementArray[Bawl.int].children[Bawl.intInputBox].value;
					} else if ( Bawl.processElementArray[Bawl.int].children[Bawl.intInputBox].name == 'title' && Bawl.processElementArray[Bawl.int].children[Bawl.intInputBox].value != '' ) {
						Bawl.replyLinkParams[Bawl.int].pageTitle = Bawl.processElementArray[Bawl.int].children[Bawl.intInputBox].value;
					} else if ( Bawl.processElementArray[Bawl.int].children[Bawl.intInputBox].name == 'preloadtitle' ) {
						Bawl.replyLinkParams[Bawl.int].preloadtitle = Bawl.processElementArray[Bawl.int].children[Bawl.intInputBox].value;
					} else if ( Bawl.processElementArray[Bawl.int].children[Bawl.intInputBox].type == 'submit' ) {
						Bawl.debug('sabotage submit, add our own onclick instead');
						Bawl.processElementArray[Bawl.int].children[Bawl.intInputBox].type = ''; //don't do whatever you normally do
						Bawl.processElementArray[Bawl.int].children[Bawl.intInputBox].outerHTML = Bawl.processElementArray[Bawl.int].children[Bawl.intInputBox].outerHTML.replace(/>$/, ' onclick="Bawl.' + Bawl.keyOpenReplyForm + '(Bawl.' + Bawl.keyReplyLinkParams + '[' + JSON.stringify(Bawl.replyLinkParams[Bawl.int].int) + '])">');
					}
				}//for
				delete Bawl.intInputBox;
		}//Bawl.settings.inputBoxTO
	} else if ( ( Bawl.elementClassList.includes('mw-ui-button') || Bawl.elementClassList.includes('oo-ui-buttonElement-button')) && Bawl.settings.mwuibuttonTO) { //todo: add support for preload etc
		Bawl.debug('I haz a .mw-ui-button, what do I do wif it?');
		Bawl.mwuibuttonRegExp = new RegExp('\\?((title=[^=&]*[&]?|action=edit[&]?|section=new[&]?){3})$');
		if ( ( Bawl.processElementArray[Bawl.int].href && Bawl.processElementArray[Bawl.int].href.match(Bawl.mwuibuttonRegExp) ) || ( Bawl.processElementArray[Bawl.int].parentElement && Bawl.processElementArray[Bawl.int].parentElement.href && Bawl.processElementArray[Bawl.int].parentElement.href.match(Bawl.mwuibuttonRegExp) ) ) {
			Bawl.processElementArray[Bawl.int].onclick = function(ev){
				ev.preventDefault();ev.stopPropagation();
				Bawl.replyLinkParamsmwuibutton = $.extend( true, {}, Bawl.replyLinkParamsnSec );
				if ( this.href && this.href.match(Bawl.mwuibuttonRegExp) ) { // "this" is the .mw-ui-button element that was clicked
					Bawl.replyLinkParamsmwuibutton.pageTitle = decodeURIComponent(this.href.match(/title=([^&#]*)/)[1]);
				} else {
					Bawl.replyLinkParamsmwuibutton.pageTitle = decodeURIComponent(this.parentElement.href.match(/title=([^&#]*)/)[1]);
				}
				Bawl.openReplyForm(Bawl.replyLinkParamsmwuibutton);
			};
		}
	} else if ( Bawl.elementClassList.includes('Bawl-comment-link') ) {
		Bawl.debug('Bawl-comment-link found');
		Bawl.replyLinkParams[Bawl.int] = {
			'int': Bawl.int,
			'id':'Bawl-comment-link',
			'type':'BCL',
			'subtype':'page',
			'pageTitleInt':Bawl.pageTitleToEditInt,
			'createonly':false,
			'origReplyTo':'NO-VALUE-PLEASE-IGNORE',
			'origTimestamp':'2000-01-01T00:00:00.000Z',
			'preloadparams': [],
			'editintro':undefined
		};
		if ( Bawl.testValidJSON(decodeURIComponent(Bawl.processElementArray[Bawl.int].id)) ) {
			Bawl.commentLinkID = JSON.parse(decodeURIComponent(Bawl.processElementArray[Bawl.int].id));
			if ( Bawl.commentLinkID.type == 'section' ) {
				Bawl.replyLinkParams[Bawl.int].subtype = 'section';
			}
			if ( Bawl.commentLinkID.indent && decodeURIComponent(Bawl.commentLinkID.indent).match(/^[\:\*\#]{1,5}$/) ) {
				Bawl.replyLinkParams[Bawl.int].indent = decodeURIComponent(Bawl.commentLinkID.indent);
			}
			if ( Bawl.commentLinkID.page ) {
				Bawl.replyLinkParams[Bawl.int].pageTitle = decodeURIComponent(Bawl.commentLinkID.page);
			}
			if ( Bawl.commentLinkID.createonly ) {
				Bawl.replyLinkParams[Bawl.int].createonly = true;
			}
			if ( Bawl.commentLinkID.editintro ) {
				Bawl.replyLinkParams[Bawl.int].editintro = decodeURIComponent(Bawl.commentLinkID.editintro);
			}
			if ( Bawl.commentLinkID.preload ) {
				Bawl.replyLinkParams[Bawl.int].preload = decodeURIComponent(Bawl.commentLinkID.preload);
			}
			if ( Bawl.commentLinkID.preloadparams ) {
				for (Bawl.preloadParamsInt=0;Bawl.preloadParamsInt<decodeURIComponent(Bawl.commentLinkID.preloadparams).split(';').length;Bawl.preloadParamsInt++){
					Bawl.replyLinkParams[Bawl.int].preloadparams.push(decodeURIComponent(Bawl.commentLinkID.preloadparams).split(';')[Bawl.preloadParamsInt]);
				}
			}
			if ( Bawl.commentLinkID.summary ) {
				Bawl.replyLinkParams[Bawl.int].summary = decodeURIComponent(Bawl.commentLinkID.summary);
			}
			if ( Bawl.commentLinkID.create ) {
				Bawl.replyLinkParams[Bawl.int].allowcreate = true;
			}
			if ( Bawl.commentLinkID.purge ) {
				Bawl.replyLinkParams[Bawl.int].forcepurge = true;
			}
			Bawl.processElementArray[Bawl.int].childNodes[0].outerHTML = Bawl.processElementArray[Bawl.int].childNodes[0].outerHTML.replace(/href=\"[^"]*\"/, 'onclick="Bawl.' + Bawl.keyOpenReplyForm + '(\'' + encodeURIComponent(JSON.stringify(Bawl.replyLinkParams[Bawl.int])).replace(/\'/g, '\\\'') + '\')"');
			if ( mw.util.getParamValue('withJS') && mw.util.getParamValue('withJS').match('Bawl.js') && mw.util.getParamValue('Bawlform') == Bawl.processElementArray[Bawl.int].innerText ) {
				Bawl.automaticallyOpenFormParams = $.extend( true, {}, Bawl.replyLinkParams[Bawl.int] ); // copy as = only creates a shortcut
				if ( Bawl.testValidJSON(decodeURIComponent(Bawl.automaticallyOpenFormParams.preloadparams).replace(/\&quot\;/g, '"')) ) {
					Bawl.automaticallyOpenFormParams.preloadparams = JSON.parse(decodeURIComponent(Bawl.automaticallyOpenFormParams.preloadparams).replace(/\&quot\;/g, '"'));
				}
			}
		}
	} else if ( Bawl.elementClassList.includes('firstHeading') ) {
		if ( Bawl.settings.editFullSection && Bawl.processElementArray[Bawl.int].id == 'firstHeading' && ! $('#BawlEditLede')[0] ) {
			Bawl.debug('adding lede edit link');
			Bawl.replyLinkParamsLede = {'int':Bawl.int,'id':'editLede-' + mw.config.get('wgPageName'),'type':'heading','subtype':'edit','section':0,'sectionTitle':'','pageTitle': mw.config.get('wgPageName')};
			Bawl.ledeEditLinkSpan = document.createElement('span');
			Bawl.ledeEditLinkSpan.classList = 'BawlReplyLink BawlSVGEditIcon BawlSVG mw-editsection-like';
			Bawl.ledeEditLinkSpan.id = 'BawlEditLede';
			Bawl.ledeEditLink = document.createElement('a');
			if ( mw.config.get('wgPageContentModel') != 'wikitext' ) {
				Bawl.replyLinkParamsLede = Bawl.replyLinkParamsFP;
			}
			Bawl.ledeEditLink.onclick = function(){Bawl.openReplyForm(Bawl.replyLinkParamsLede);};
			Bawl.ledeEditLink.append(Bawl.ledeEditLinkSpan);
			Bawl.processElementArray[Bawl.int].append(Bawl.ledeEditLink);
		}
	} else {
		Bawl.debug('another element type, checking for legacy signature');
		for (Bawl.legacyElementInt=(Bawl.processElementArray[Bawl.int].childNodes.length -1);Bawl.legacyElementInt>-1;Bawl.legacyElementInt = Bawl.legacyElementInt -1){
			Bawl.debug('checking processElementArray #' + Bawl.int + ' childnode #' + Bawl.legacyElementInt);
			if ( Bawl.elementClassList.includes('localcomments') ) { //Gadget-CommentsInLocalTime HACK
				if ( Bawl.processElementArray[Bawl.int].parentElement.classList.contains('BawlCmt') ) {//izza locator
					return;
				}
				Bawl.legacyLOCOMatch = Bawl.processElementArray[Bawl.int].title;
			} else {
				delete Bawl.legacyLOCOMatch;
			}
			if ( Bawl.legacyLOCOMatch || ( Bawl.processElementArray[Bawl.int].childNodes[Bawl.legacyElementInt].nodeType == 3 && Bawl.processElementArray[Bawl.int].childNodes[Bawl.legacyElementInt].data.length < 50 && Bawl.processElementArray[Bawl.int].childNodes[Bawl.legacyElementInt].data.length > 12 ) ) {
				if ( Bawl.legacyLOCOMatch ) { //Gadget-CommentsInLocalTime HACK
					Bawl.debug('a legacyLOCOMatch');
					Bawl.legacyElementSigMatch = Bawl.legacyLOCOMatch.match(Bawl.signDateRegExpLocalMonths);
				} else {
					Bawl.debug('textnode with the right length to maybe be a timestamp');
					Bawl.legacyElementSigMatch = Bawl.processElementArray[Bawl.int].childNodes[Bawl.legacyElementInt].data.match(Bawl.signDateRegExpLocalMonths);
				}
				if ( Bawl.legacyElementSigMatch ) {
					Bawl.legacyTimestampNode = Bawl.processElementArray[Bawl.int].childNodes[Bawl.legacyElementInt];
					if ( Bawl.legacyLOCOMatch ) { //Gadget-CommentsInLocalTime HACK
						Bawl.legacyUsername = decodeURIComponent(Bawl.getLegacyUserForTimestamp(Bawl.processElementArray[Bawl.int]));
					} else {
						Bawl.legacyUsername = decodeURIComponent(Bawl.getLegacyUserForTimestamp(Bawl.legacyTimestampNode));
					}
					if ( Bawl.legacyUsername != false ) {
						Bawl.legacyUsername = decodeURIComponent(Bawl.legacyUsername);
						Bawl.legacyID = Bawl.legacyUsername + ':' + Bawl.legacyElementSigMatch[0] + ':' + Bawl.int;
						Bawl.replyLinkParams[Bawl.int] = {
							'int':Bawl.int,
							'type':'comment',
							'subtype':'legacy',
							'id':Bawl.legacyID,
							'pageTitleInt':Bawl.pageTitleToEditInt,
							'origReplyTo':Bawl.legacyUsername,
							'origTimestamp':Bawl.legacyElementSigMatch[0].trim(),
						};
						if ( ! Bawl.firstReplyInSection ) {
							Bawl.firstReplyInSection = $.extend( true, {}, Bawl.replyLinkParams[Bawl.int] );
							Bawl.firstReplyInSection.isFirst = true;
						}
						Bawl.legacyCommentCount++;//Bawl.debug
						if ( Bawl.commentersInSection.indexOf(Bawl.legacyUsername.replace(/_/g,' ')) == -1 ) {
							Bawl.commentersInSection.push(Bawl.legacyUsername.replace(/_/g,' '));
						}
						Bawl.addReplyLinkTo(Bawl.replyLinkParams[Bawl.int],Bawl.legacyTimestampNode);
						Bawl.nextCommentIsFirstInSection = false;
						break;
					}
				}
			}
		}
	} //end check which type the element is
};
Bawl.finishedAddingLinks = false;
Bawl.killSwitchTriggered = false;
Bawl.userNameFromLinkFRegExp = new RegExp('([\/\=])(' + Bawl.userNSLinkRegExpPart + '|' + Bawl.basicmsgs.specialcontribs + '\/)([^\/"\#\&\?]+)($|[\/"\#\&\?])');
if ( Bawl.settings.autoCollapse || Bawl.settings.markNewCmts ) {
	Bawl.stalkLastViewedAutoCollapse = Bawl.stalkLastViewed({'pageTitle':mw.config.get('wgPageName').replace(/_/g,' ')},'v');
}
if ( ( Bawl.settings.stalkAddSubLinks || Bawl.settings.autoCollapse || Bawl.settings.markNewCmts ) && ( Bawl.isDiscussionPage || $('.BawlCmt')[0] ) && mw.config.get('wgArticleId') != 0 ) {
	Bawl.debug('update v (lastviewed) for this page for autocollapse and subscription purposes');
	if ( ! Bawl.testValidJSON(window.localStorage.BawlSubs) ) {
		window.localStorage.setItem('BawlSubs',JSON.stringify({}));
	}
	Bawl.stalkAddLastViewed = JSON.parse(window.localStorage.BawlSubs);
	if ( ! Bawl.stalkAddLastViewed[mw.config.get('wgPageName').replace(/_/g,' ')] ) {
		Bawl.stalkAddLastViewed[mw.config.get('wgPageName').replace(/_/g,' ')] = {};
	}
	Bawl.stalkAddLastViewed[mw.config.get('wgPageName').replace(/_/g,' ')].v = Bawl.timestampInit;
	window.localStorage.setItem('BawlSubs',JSON.stringify(Bawl.stalkAddLastViewed));
}
Bawl.orphanedTimestamps = [];
Bawl.getLegacyUserForTimestamp = function(textNode) {
	Bawl.checkPreSigNode = textNode;
	delete Bawl.legacyUser;
	for (Bawl.preSigInt=0;Bawl.preSigInt < 5;Bawl.preSigInt++) {
		if ( textNode.parentElement.classList.contains('BawlCmt') ) {
			Bawl.debug('the parent of "' + textNode.data + '" is a locator, let the locator code handle it');
			return false;
		}
		if ( Bawl.checkPreSigNode.previousElementSibling ) {
			Bawl.checkPreSigNode = Bawl.checkPreSigNode.previousElementSibling;
			if ( Bawl.checkPreSigNode.nodeName == 'A' && Bawl.checkPreSigNode.attributes.href ) {
				Bawl.legacyUser = Bawl.checkPreSigNode.attributes.href.nodeValue.match(Bawl.userNameFromLinkFRegExp);
			} else if ( Bawl.checkPreSigNode.tagName ) {
				Bawl.legacyUser = Bawl.checkPreSigNode.innerHTML.match(Bawl.userNameFromLinkFRegExp);
			}
			if ( Bawl.legacyUser && Bawl.legacyUser[3] ) {
				return Bawl.legacyUser[3];
			}
		} else {
			break;
		}
	}
	Bawl.checkPostSigNode = textNode;
	for (Bawl.postSigInt=0;Bawl.postSigInt < 3;Bawl.postSigInt++) {
		if ( Bawl.checkPostSigNode.nextElementSibling ) {
			Bawl.checkPostSigNode = Bawl.checkPostSigNode.nextElementSibling;
			if ( Bawl.checkPostSigNode.nodeName == 'A' && Bawl.checkPostSigNode.attributes.href ) {
				Bawl.legacyUser = Bawl.checkPostSigNode.attributes.href.nodeValue.match(Bawl.userNameFromLinkFRegExp);
			} else if ( ['DD','DL','P'].indexOf(Bawl.checkPostSigNode.nodeName) != -1 ) {
				Bawl.debug('next comment or paragraph, guess this timestamp is an orphan');
				break;
			} else if ( Bawl.checkPostSigNode.tagName ) {
				Bawl.legacyUser = Bawl.checkPostSigNode.innerHTML.match(Bawl.userNameFromLinkFRegExp);
			}
			if ( Bawl.legacyUser && Bawl.legacyUser[3] ) {
				return Bawl.legacyUser[3];
			}
		} else {
			break;
		}
	}
	if ( textNode.parentElement.previousElementSibling && textNode.parentElement.previousElementSibling.nodeName == 'A' && textNode.parentElement.previousElementSibling.href ) { //Paine Ellsworth on enwiki has "[[User talk:Paine Ellsworth|<sup>put'r&nbsp;there</sup>]]&nbsp;<small>06:27, 17 April 2022 (UTC)</small>" for a signature, encapsulating ONLY the timestamp in a small tag. Doesn't seem like something you can set in your prefs?
		Bawl.legacyUser = textNode.parentElement.previousElementSibling.attributes.href.nodeValue.match(Bawl.userNameFromLinkFRegExp);
		if ( Bawl.legacyUser && Bawl.legacyUser[3] ) {
			return Bawl.legacyUser[3];
		}
	}
	Bawl.debug('orphaned timestamp found:');
	Bawl.debug(textNode);
	Bawl.orphanedTimestamps.push(textNode);//Bawl.debug
	return '';
};
if ( Bawl.settings.ninjaLoader ) {
	Bawl.loadOnDemand = function(triggerElement) {
		if ( document.activeElement.nodeName == 'A' ) {
			Bawl.debug('you clicked a link within a header. not loading links');
			return;
		}
		Bawl.searchNodeContentsLoop();
		if ( triggerElement.target.classList.contains('mw-headline') ) {
			window.location.hash = '#' + triggerElement.target.id;
		} else if ( triggerElement.target.nodeName.match(/^H[1-6]$/) && triggerElement.target.querySelectorAll('.mw-headline')[0] ) {
			window.location.hash = '#' + triggerElement.target.querySelectorAll('.mw-headline')[0].id;
		}
		Bawl.reJump();
		if ( mw.util.getParamValue('BwlScrToTime') ) {
			Bawl.scrollToComment(mw.util.getParamValue('BwlScrToUsr'),mw.util.getParamValue('BwlScrToTime'));
		}
	};
	$('#firstHeading,#mw-content-text H1,#mw-content-text H2,#mw-content-text H3,#mw-content-text H4,#mw-content-text H5,#mw-content-text H6').on('click',function() { Bawl.loadOnDemand(event); });
}
Bawl.searchNodeContentsLoop = function() {
	if ( ! Bawl.foundLOCO && mw.user.options.get('gadget-CommentsInLocalTime') ) {//Gadget-CommentsInLocalTime HACK
		$(document).ready(function() {
			window.commentsInLocalTimeWasRun = true; //If you're already done this changes nothing. If you're still processing, I count on you being done one second from now. If you hadn't started yet, I hereby declare you're done.
			var LOCODELAY = setInterval(function () {
				clearInterval(LOCODELAY);
				Bawl.foundLOCO = true;
				Bawl.searchNodeContentsLoop();
			},1000); //commentsInLocalTimeWasRun doesn't seem to indicate LOCO is actually DONE, just that it started, so we'll just pray it can do its thing in a second
			return;
		});
	}
	Bawl.applyModules('beforeLinkLoad');
	if ( typeof Bawl.legacyCommentCount != 'undefined' ) {
		Bawl.debug('already added all links');
		return;
	}
	if ( mw.config.get('skin') == 'minerva' && ( ! Bawl.settings.loadMinervaD && ! document.location.href.match(/(\.|\/\/)m\./) ) || ( ! Bawl.settings.loadMinervaM && document.location.href.match(/(\.|\/\/)m\./) ) ) {
		Bawl.debug('you disabled link adding on Minerva so I won\'t do it');
		return;
	}
	Bawl.loadTimeAddLinksStart = new Date().getTime();
	Bawl.replyLinkParams = {};
	Bawl.keyReplyLinkParams = Object.keys(Bawl)[Object.values(Bawl).indexOf(Bawl.replyLinkParams)];
	delete Bawl.automaticallyOpenFormParams;
	Bawl.debug('add reply/permalink/subsection links to comments and sections and replace dates');
	if ( Bawl.isDiscussionPage || $('.commentbox')[0] || $('.Bawl-comment-link')[0] || Bawl.settings.editFullSection || Bawl.settings.dateLinksIconSection ) {
		Bawl.processElementArrayElements = '#mw-content-text .commentbox,#mw-content-text .Bawl-comment-link,#firstHeading,#mw-content-text .mw-editsection,#mw-content-text .mw-ui-button,#mw-content-text .oo-ui-buttonElement-button'; //.mw-ui-button catches some custom new section links like on https://de.wikipedia.org/wiki/Wikipedia:Caf%C3%A9 and .oo-ui-buttonElement-button catches default "Start a discussion" buttons on nonexistent talk pages
	}
	if ( Bawl.settings.methodLocator ) {
		Bawl.processElementArrayElements = Bawl.processElementArrayElements + ',#mw-content-text .BawlCmt'; // Bawl locators
	}
	if ( Bawl.settings.methodLegacy && ( Bawl.isDiscussionPage || $('.BawlCmt')[0] ) ) {
		Bawl.processElementArrayElements = Bawl.processElementArrayElements + ',#mw-content-text dd,#mw-content-text p,#mw-content-text li,#mw-content-text dd small,#mw-content-text p small,#mw-content-text li small,#mw-content-text dd i,#mw-content-text p i,#mw-content-text li i,#mw-content-text dd s,#mw-content-text p s,#mw-content-text li s,#mw-content-text dd del,#mw-content-text p del,#mw-content-text li del';
	}
	if ( Bawl.settings.extendedSigDetect ) { //DiscussionTools. Sooooo many spans. Adds +/- 15% to detection time, increases detection rate on the Wiktionary RfD test page from 1170 to 1172 with two comments by Dentonius (19:19, 4 October 2020 (UTC) and 19:25, 4 October 2020 (UTC)) that were MANUALLY ALTERED to be encapsulated in <s><span style="color:gray">.
		Bawl.processElementArrayElements = Bawl.processElementArrayElements + ',#mw-content-text dd span,#mw-content-text p span,#mw-content-text li span';
	}
	if ( Bawl.foundLOCO && ! Bawl.settings.extendedSigDetect ) {//Gadget-CommentsInLocalTime HACK
		Bawl.processElementArrayElements = Bawl.processElementArrayElements + ',#mw-content-text .localcomments';
	}
	Bawl.processElementArray = Array.from($(Bawl.processElementArrayElements));
	Bawl.processElementArrayLength = Bawl.processElementArray.length;
	Bawl.pageTitleToEditInt = -1;
	Bawl.pageTitleToEdit = mw.config.get('wgPageName'); //in case the first comment comes before any section edit link we define the page title
	Bawl.sectionTitle = ""; //same for the ==Section title==
	Bawl.legacyCommentCount = 0;
	Bawl.killSwitchInt = 0;
	Bawl.nextCommentIsFirstInSection = true;
	Bawl.killSwitchTriggeredThisTime = false;
	Bawl.sectionHeaderLinksAdded = false;
	Bawl.stopAddingLinks = false;
	Bawl.addedReplyLinks = [];
	Bawl.sectionsFound = [];
	Bawl.replyLinkParamsEdit = {};
	Bawl.keyReplyLinkParamsEdit = Object.keys(Bawl)[Object.values(Bawl).indexOf(Bawl.replyLinkParamsEdit)];
	Bawl.replyLinkParamsHeadingEdit = {};
	for (Bawl.int = 0; Bawl.int < Bawl.processElementArrayLength; Bawl.int++) {
		if ( Bawl.killSwitchTriggered == false && Bawl.settings.killswitch ) { //if automatic loading gets killed, don't kill manual loading afterwards
			Bawl.killSwitchInt++;
			if ( Bawl.killSwitchInt == 50 ) {
				Bawl.killSwitchInt = 0;
				if ( Bawl.loadTimeAddLinksStart < (new Date().getTime() - 8000) ) {
					console.log('Bawl: KILL SWITCH TRIGGERED, loading took more than 8000ms, abort adding links.');
					Bawl.killSwitchTriggered = true;
					Bawl.killSwitchTriggeredThisTime = true;
					break;
				}
			}
		}
		Bawl.debug('Process element #' + Bawl.int + '/' + (Bawl.processElementArrayLength - 1) + ' from processElementArray');
		if ( Bawl.replyToSectionLinkNeeded && Bawl.firstReplyInSection && Bawl.int == (Bawl.processElementArrayLength-1) && Bawl.commentersInSection.length > 1 ) {
			Bawl.firstReplyInSectionLastElement = true;
			Bawl.addReplyLinkTo(Bawl.firstReplyInSection);
		}
		if ( Bawl.stopAddingLinks ) {
			Bawl.debug('found a section header after the section we were supposed to process, we\'re done');
			break;
		}
		Bawl.searchNodeContents();
	} //end for
	Bawl.resetDbg(true); //the load loop usually exceeds whatever limit is set (Bawl.debug)
	if ( Bawl.settings.hideArchived ) {
		$('.archived .BawlReplyLink,.boilerplate .BawlReplyLink').addClass('BawlNoDisplay');
	}
	$('.hide-legacy-cmts .LegacyCmt .BawlLinks').addClass('BawlNoDisplay'); //hide reply links for legacy signatures in .hide-legacy-cmts class. Useful for sectionless transclusion as such comments couldn't be replied to anyway.
	if ( Bawl.settings.markNewCmtsBorder ) {
		Bawl.debug('add side border to parentElement of comments marked as new');
		for(Bawl.BawlNewCmtInt=0;Bawl.BawlNewCmtInt<$('.BawlNewCmt').length;Bawl.BawlNewCmtInt++) {
			$('.BawlNewCmt')[Bawl.BawlNewCmtInt].parentElement.classList.add('BawlNewCmtBorder','BawlEaseIn');
		}
		for(Bawl.BawlNewCmtInt=0;Bawl.BawlNewCmtInt<$('.BawlNewCmtSubscribed').length;Bawl.BawlNewCmtInt++) {
			$('.BawlNewCmtSubscribed')[Bawl.BawlNewCmtInt].parentElement.classList.add('BawlNewCmtSubscribedBorder','BawlEaseIn');
		}
	}
	Bawl.scrollToNextNewCmt = function(cmtClass) {
		if ( $('#mw-content-text .' + cmtClass)[0] ) {
			$('#mw-content-text .' + cmtClass)[0].scrollIntoView(Bawl.smoothScroll);
			$('#mw-content-text .' + cmtClass)[0].classList.remove('BawlNewCmt','BawlNewCmtSubscribed');
			$('#' + cmtClass + 'Btn .cmtCount')[0].innerText = $('#mw-content-text .' + cmtClass).length;
		} else {
			Bawl.addScrewedLink('cant_scroll_cmt','No DOM object found, unable to scroll to next comment.');
		}
		Bawl.checkClearCycleBtn();
	};
	Bawl.checkClearCycleBtn = function() {
		if ( $('#BawlNewCmtBtn')[0] && $('#mw-content-text .BawlNewCmt').length == 0 ) {
			$('#BawlNewCmtBtn')[0].remove();
		}
		if ( $('#BawlNewCmtSubscribedBtn')[0] && $('#mw-content-text .BawlNewCmtSubscribed').length == 0 ) {
			$('#BawlNewCmtSubscribedBtn')[0].remove();
		}
		if ( $('.BawlCycleBtnsFixed')[0] && $('.BawlCycleBtnsFixed')[0].childNodes.length == 0 ) {
			$('.BawlCycleBtnsFixed')[0].remove();
		}
	};
	$('.BawlNewCmt').on('click',function(){this.classList.remove('BawlNewCmt','BawlNewCmtSubscribed');}); //"this" refers to the .BawlNewCmt that was clicked, marks it as read on click
	if ( ( Bawl.settings.stalkAddCycleBtn || Bawl.settings.stalkAddCycleBtnSubbed ) && $('.BawlNewCmt')[0] ) {
		Bawl.stalkCycleBtns = document.createElement('div');
		Bawl.stalkCycleBtns.classList.add('BawlCycleBtnsFixed');
		Bawl.stalkCycleButtons = '';
		if ( Bawl.settings.stalkAddCycleBtn && $('#mw-content-text .BawlNewCmt')[0] ) {
			Bawl.stalkCycleButtons = '<div id="BawlNewCmtBtn"><div class="cmtCount BawlNewCmt" style="width:2.5em;text-align:center;padding:0.6em 0 0.6em 0">' + $('#mw-content-text .BawlNewCmt').length + '</div></div>';
		}
		if ( Bawl.settings.stalkAddCycleBtnSubbed && $('#mw-content-text .BawlNewCmtSubscribed')[0] ) {
			Bawl.stalkCycleButtons = Bawl.stalkCycleButtons + '<div id="BawlNewCmtSubscribedBtn"><div class="cmtCount BawlNewCmtSubscribed" style="width:2.5em;text-align:center;padding:0.6em 0 0.6em 0">' + $('#mw-content-text .BawlNewCmtSubscribed').length + '</div></div>';
		}
		Bawl.stalkCycleBtns.innerHTML = Bawl.stalkCycleButtons;
		$('body')[0].prepend(Bawl.stalkCycleBtns);
		$('#BawlNewCmtBtn').on('click',function(){Bawl.scrollToNextNewCmt('BawlNewCmt');});
		$('#BawlNewCmtSubscribedBtn').on('click',function(){Bawl.scrollToNextNewCmt('BawlNewCmtSubscribed');});
		if ( $('#BawlNewCmtBtn .cmtCount')[0] ) {
			$('.BawlNewCmt').on('click',function(){if($('#BawlNewCmtBtn .cmtCount')[0]){$('#BawlNewCmtBtn .cmtCount')[0].innerText = $('#mw-content-text .BawlNewCmt').length;Bawl.checkClearCycleBtn();)));
		}
		if ( $('#BawlNewCmtSubscribedBtn .cmtCount')[0] ) {
			$('.BawlNewCmtSubscribed').on('click',function(){if($('#BawlNewCmtSubscribedBtn .cmtCount')[0]){$('#BawlNewCmtSubscribedBtn .cmtCount')[0].innerText = $('#mw-content-text .BawlNewCmtSubscribed').length;Bawl.checkClearCycleBtn();)));
		}
		if ( Bawl.settings.stalkMarkReadScroll ) {
			Bawl.scrollReadActive = false;
			document.addEventListener('scroll',function(){
				if ( Bawl.scrollReadActive || ! $('.BawlNewCmt')[0] ){//don't run a million times for a little scroll, only one concurrent instance of this function. also don't run if there are no .BawlNewCmt left
					return;
				}
				Bawl.scrollReadActive = true;
				Bawl.debug('you scrolled');
				var DelayedScrollRead = setInterval(function () { //we don't want to mark comments in the viewport as read INSTANTLY if they zoom past
					clearInterval(DelayedScrollRead);
					Bawl.debug('checking which (if any) .BawlNewCmt elements are in view');
					Bawl.scrollReadInViewTop = $(window).scrollTop() + ( $(window).height() / 100 * 15 ); //adding 10% of the viewport height as a margin so elements must be in the center 80% to count as in view
					Bawl.scrollReadInViewBot = $(window).scrollTop() + ( $(window).height() / 100 * 85 );
					if ( Bawl.scrollReadInViewTop < ( Bawl.scrollReadViewPortHeight / 100 * 15 ) ) { //you are (near) the top of the page. The top 15% is typically occupied by toolbars etc anyway, but if not somehow we'll treat any elements starting from the very top as being in view if you are scrolled less than 15% of the viewport from the top
						Bawl.scrollReadInViewTop = 0;
					}
					for(Bawl.scrollReadInt=0;Bawl.scrollReadInt<$('#mw-content-text .BawlNewCmt').length;Bawl.scrollReadInt++){
						Bawl.scrollReadElementPos = $('#mw-content-text .BawlNewCmt:eq(' + Bawl.scrollReadInt + ')').offset().top;
						if ( Bawl.scrollReadElementPos > Bawl.scrollReadInViewTop && Bawl.scrollReadElementPos < Bawl.scrollReadInViewBot ) {
							Bawl.debug('#mw-content-text .BawlNewCmt #' + Bawl.scrollReadInt + ' is in view, marking as read');
							$('#mw-content-text .BawlNewCmt')[Bawl.scrollReadInt].classList.remove('BawlNewCmtSubscribed','BawlNewCmt');
							Bawl.scrollReadInt = Bawl.scrollReadInt -1;
						}
					}
					if ( $('#BawlNewCmtBtn .cmtCount')[0] ) {
						$('#BawlNewCmtBtn .cmtCount')[0].innerText = $('#mw-content-text .BawlNewCmt').length;
					}
					if ( $('#BawlNewCmtSubscribedBtn .cmtCount')[0] ) {
						$('#BawlNewCmtSubscribedBtn .cmtCount')[0].innerText = $('#mw-content-text .BawlNewCmtSubscribed').length;
					}
					Bawl.checkClearCycleBtn();
					Bawl.scrollReadActive = false;
				},3000);
			});
		}
	}
	if ( Bawl.killSwitchTriggeredThisTime == false ) {
		Bawl.finishedAddingLinks = true;
	}
	Bawl.loadTimeAddLinksEnd = new Date().getTime();
	Bawl.loadTimeAddLinks = Bawl.loadTimeAddLinksEnd - Bawl.loadTimeAddLinksStart;
	if ( ( Bawl.settings.collapArticle && Bawl.viewingArticle ) || ( ( Bawl.settings.collapsible || Bawl.settings.reverseSectionOrder ) && ( $('.LegacyCmt')[0] || $('.BawlCmt')[0]) ) ) { //this can ONLY be done after adding links
		Bawl.collapsingArticle = ( Bawl.settings.collapArticle && Bawl.viewingArticle );
		if ( ( Bawl.collapsingArticle && Bawl.settings.collapArticle ) || Bawl.settings.collapsible ) {
			mw.util.addCSS('.skin-minerva .section-heading.collapsible-heading .mw-ui-icon-mf-expand{display:none}'); //Minerva on mobile also collapses sections. confusing to have two chevrons. As the collapsing feature of Bawl works on all skins, in the interest of consistency, we hide Minerva's chevrons.
		}
		Bawl.splitHTMLSections('1','#mw-content-text .mw-parser-output');
		if ( $('.BawlH1SectionsContainer')[0] ) {
			for (Bawl.intContentH1Div = 0; Bawl.intContentH1Div < $('.BawlH1SectionsContainer').children().length; Bawl.intContentH1Div++) {
				Bawl.splitHTMLSections('2','#' + $('.BawlH1SectionsContainer').children()[Bawl.intContentH1Div].id);
			}
		} else {
			Bawl.splitHTMLSections('2','#mw-content-text .mw-parser-output');
		}
		Bawl.reverseChildNodes = function(element){
			for(Bawl.reverseChildNodesInt=0;Bawl.reverseChildNodesInt<element.childNodes.length;Bawl.reverseChildNodesInt++){
				element.insertBefore(element.childNodes[element.childNodes.length -1],element.childNodes[Bawl.reverseChildNodesInt]);
			}
		};
		if ( Bawl.settings.reverseSectionOrder && ! Bawl.collapsingArticle ) {
			Bawl.debug('reversing the TOC');
			if ( $('#toc ul .toclevel-1')[0] ) {
				Bawl.reverseChildNodes($('#toc ul')[0]);
				if ( $('.BawlH1SectionsContainer')[0] && $('.BawlH2SectionsContainer')[0] ) {
					for(Bawl.reverseTOCLevel2Int=0;Bawl.reverseTOCLevel2Int<$('#toc .toclevel-1 ul').length;Bawl.reverseTOCLevel2Int++){
						if ($('#toc .toclevel-1 ul')[Bawl.reverseTOCLevel2Int].childNodes.length){//skip toclevel-1 elements without childNodes to sort
							Bawl.reverseChildNodes($('#toc .toclevel-1 ul')[Bawl.reverseTOCLevel2Int]);
						}
					}
				}
			}
		}
		if ( Bawl.collapsingArticle && Bawl.settings.collapArticleDefault && ( ! window.location.hash || ! document.getElementById(window.location.hash.slice(1)) ) ) {
			Bawl.toggledAllSections = true;
			Bawl.toggleAllSections();
		}
	}
	if ( mw.config.get('skin') == 'minerva' || Bawl.settings.collapsible || Bawl.settings.autoCollapse || Bawl.settings.collapArticle ) { //Links added to sections by Bawl cause sections to collapse/expand. MediaWiki uses stopPropagation on the edit button to stop the collapsing there but scripts that add links to H1/H2 are just fucked so here's another fun hack.
		$('.mw-editsection').on('click', function(event){event.stopPropagation();});
	}
	if ( Bawl.settings.collapArticleDefaultFloatingToC ) {
		Bawl.floatTheTOC();
	} else if ( Bawl.settings.collapArticleDefaultNoToC && $('#toc')[0] ) {
		$('#toc').addClass('BawlNoDisplay');
	}
	if ( Bawl.settings.autoCollapse && ! Bawl.toggledAllSections ) {
		Bawl.debug('collapse sections without new comments in them');
		Bawl.toggleAllH1SectionsTotal = $('#mw-content-text .BawlH1SectContainer');
		Bawl.toggleAllH2SectionsTotal = $('#mw-content-text .BawlH2SectContainer');
		for (Bawl.toggleAllSectionsInt=0;Bawl.toggleAllSectionsInt<Bawl.toggleAllH1SectionsTotal.length;Bawl.toggleAllSectionsInt++){
			if ( typeof $('#' + Bawl.toggleAllH1SectionsTotal[Bawl.toggleAllSectionsInt].id + ' .BawlNewCmt')[0] == 'undefined' ) {
				Bawl.collapseSection(Bawl.toggleAllH1SectionsTotal[Bawl.toggleAllSectionsInt].id,1);
			}
		}
		for (Bawl.toggleAllSectionsInt=0;Bawl.toggleAllSectionsInt<Bawl.toggleAllH2SectionsTotal.length;Bawl.toggleAllSectionsInt++){
			if ( typeof $('#' + Bawl.toggleAllH2SectionsTotal[Bawl.toggleAllSectionsInt].id + ' .BawlNewCmt')[0] == 'undefined' ) {
				Bawl.collapseSection(Bawl.toggleAllH2SectionsTotal[Bawl.toggleAllSectionsInt].id,2);
			}
		}
		Bawl.uncollapsedSectionCount = $('#mw-content-text .BawlH2SectContainer:not(.collapsedSection),#mw-content-text .BawlH1SectContainer:not(.collapsedSection)').length;
		if ( Bawl.uncollapsedSectionCount == 0 && $('#firstHeading .sectioncollapse span')[0] ) {
			Bawl.debug('change toggle all sections arrow to up as apparently we collapsed everything');
			$('#firstHeading .sectioncollapse span')[0].classList.add('BawlSVGChevronIconRot');
		}
	}
	Bawl.loadTimeSectionSplitting = new Date().getTime() - Bawl.loadTimeAddLinksEnd;
	if ( ! Bawl.automaticallyOpenFormParams && Bawl.settings.hideDT && Bawl.settings.nSecLink && mw.config.get('wgAction') == 'view' && mw.user.options.get('discussiontools-betaenable') == 1 && mw.user.options.get('discussiontools-newtopictool') == 1 && mw.util.getParamValue('action') == 'edit' && mw.util.getParamValue('section') == 'new' ) {
		Bawl.automaticallyOpenFormParams = Bawl.replyLinkParamsnSec;
		mw.util.addCSS('.ext-discussiontools-ui-newTopic{display:none}');
	}
	if ( Bawl.automaticallyOpenFormParams ) {
		Bawl.openReplyForm(Bawl.automaticallyOpenFormParams);
	}
	if ( typeof BawlShowLoadTime != 'undefined' ) { console.log('added links in ' + Bawl.loadTimeAddLinks + 'ms'); }
};
Bawl.timestampInitEnd = new Date().getTime();
if ( window.location.hash.match(/^#[Bb]awl[Ee]dit$/) ) {
		Bawl.openReplyForm(Bawl.replyLinkParamsFP);
} else if ( Bawl.settings.sectionIsNewTO && Bawl.replyLinkParamsnSec && mw.util.getParamValue('action') == 'edit' && mw.config.get('wgAction') == 'edit' && mw.util.getParamValue('section') == 'new' && mw.util.getParamValue('loadBawl') != '0' ) {//action and wgAction CAN differ if DT is fucking with us with the new topic tool
	Bawl.replyLinkParamsnSec.redirect = true;
	Bawl.openReplyForm(Bawl.replyLinkParamsnSec);
}
if ( ! Bawl.settings.ninjaLoader && Bawl.viewingPage && typeof Bawl.basicmsgs.version == 'string' ) { //don't load links on special pages etc, don't load if translations not loaded yet
	Bawl.searchNodeContentsLoop();
}
if ( ! Bawl.settings.markNewCmts && ! Bawl.settings.markNewCmtsSubbed && Bawl.settings.autoCollapse ) {
	$('.BawlNewCmt').removeClass('BawlNewCmt');
}
if ( window.location.hash.match(/:[0-9]{13,14}:/) && document.getElementById(window.location.hash.slice(1)) ) {
	Bawl.debug('anchor to locator found. Will now break the [reply] from DiscussionTools for this comment and those directly below it. Preserving their event listeners would be non-trivial here so to hell with them (damn it, why no HTML onclick? they clearly had no moral issues with littering the HTML with crap)');
	Bawl.highlightHTMLRegExp = new RegExp('([^]*)(' + Bawl.escapeRegExp(document.getElementById(window.location.hash.slice(1)).outerHTML) + ')');
	document.getElementById(window.location.hash.slice(1)).parentElement.innerHTML = document.getElementById(window.location.hash.slice(1)).parentElement.innerHTML.replace(/class="ext-discussiontools-init-replylink-buttons BawlYesDisplay/, 'class="ext-discussiontools-init-replylink-buttons BawlNoDisplay').replace(Bawl.highlightHTMLRegExp, '<div id="BawlAnchorLocator" class="BawlEaseIn BawlPurpleBG">$1$2</div>');
	var DelayJump = setInterval(function () {
		clearInterval(DelayJump);
		if ( $('#BawlAnchorLocator')[0] ) {$('#BawlAnchorLocator')[0].scrollIntoView(Bawl.smoothScroll);}
	}, 20);
	var DelayNormalDisplay = setInterval(function () {
		clearInterval(DelayNormalDisplay);$('#BawlAnchorLocator').removeClass('BawlPurpleBG');
	}, 1000);
	var DelayCleanUp = setInterval(function () {
		clearInterval(DelayCleanUp);$('#BawlAnchorLocator')[0].outerHTML = $('#BawlAnchorLocator')[0].innerHTML;
	}, 2000);
}
Bawl.reJump = function() {
	$(document).ready(function() {
		if ( window.location.hash != '' && document.getElementById(decodeURIComponent(window.location.hash.slice(1))) ) {
			Bawl.debug('url contains an anchor. as the page may have jumped, re-jump to anchor');
			document.getElementById(decodeURIComponent(window.location.hash.slice(1))).scrollIntoView({behavior: 'smooth'});
		}
	});
};
if ( Bawl.settings.cureDTBlueStreak && window.location.hash != '' ) {
	Bawl.waitingForBSint = 0;
	Bawl.waitingForBS = function() {
		Bawl.waitingForBSint++;
		var DelayedBS = setInterval(function () {
			clearInterval(DelayedBS);
			if ( $('.ext-discussiontools-init-targetcomment')[0] ) {
				$('.ext-discussiontools-init-targetcomment').removeClass('ext-discussiontools-init-targetcomment').addClass('BawlEaseIn').addClass('BawlPurpleBG');
				var DelayBlueCure = setInterval(function () {
					clearInterval(DelayBlueCure);
					$('.BawlPurpleBG').removeClass('BawlPurpleBG');
				}, 1500);
			} else if ( Bawl.waitingForBSint < 200 ) {
				Bawl.waitingForBS();
			}
		}, 50);
	};
	Bawl.waitingForBS();
}
Bawl.loadTimeTotal = new Date().getTime() - Bawl.timestampInit;
if ( typeof Bawl.loadTimeAddLinks == 'undefined' ) {
	Bawl.loadTimeAddLinks = 0;
	Bawl.loadTimeSectionSplitting = 0;
}
if ( Bawl.killSwitchTriggered ) { Bawl.maybeSkullNBones = '☠️'; } else { Bawl.maybeSkullNBones = ''; }
if ( typeof BawlShowLoadTime != 'undefined' ) { //this isn't a regular debug message because enabling debug can increase load time significantly. Declare BawlShowLoadTime in your common.js
	$(document).ready(function() {
		Bawl.loadTimeTotalReady = new Date().getTime() - Bawl.timestampInit;
		console.log('load time (initialisation): ' + (Bawl.timestampInitEnd - Bawl.timestampInit) + 'ms, adding links: ' + Bawl.loadTimeAddLinks + 'ms, making sections collapsible/reversed: ' + Bawl.loadTimeSectionSplitting + 'ms, total: ' + Bawl.loadTimeTotal + ', document ready: ' + Bawl.loadTimeTotalReady + 'ms');
	});
}
Bawl.scrollToComment = function(BwlScrToUsr,BwlScrToTime) {
	if ( ! Bawl.replyLinkParams ) {
		Bawl.addScrewedLink('cant_scroll','No replyLinkParams, unable to scroll to any comment.');
		return;
	}
	BwlScrToUsr = BwlScrToUsr.replace(/_/g,' ');
	for(Bawl.scrollToInt=0;Bawl.scrollToInt<Object.keys(Bawl.replyLinkParams).length;Bawl.scrollToInt++){
		Bawl.scrollTestElement = Bawl.replyLinkParams[Object.keys(Bawl.replyLinkParams)[Bawl.scrollToInt]];
		if ( Bawl.scrollTestElement.origReplyTo && Bawl.scrollTestElement.origReplyTo.replace(/_/g,' ') == BwlScrToUsr ) {
			Bawl.debug('user matches GET param');
			if ( Bawl.scrollTestElement.origTimestamp.match(/[0-9]{13,14}/) ) {
				Bawl.scrollTestDate = Bawl.scrollTestElement.origTimestamp;
			} else {
				Bawl.scrollTestDate = Bawl.sigDateToMachineReadable(Bawl.scrollTestElement.origTimestamp);
			}
			if ( Bawl.scrollTestDate == BwlScrToTime.replace(/_.*$/,'') ) {
				Bawl.scrollToFound = true;
				if ( Bawl.testValidJSON(mw.user.options.get('userjs-BawlTackOnEchoGlobal')) && JSON.parse(mw.user.options.get('userjs-BawlTackOnEchoGlobal'))[BwlScrToTime] ) {
					Bawl.tackOnEchoClear(BwlScrToTime);
				}
				break;
			}
		}
	}
	if ( Bawl.scrollToFound ) {
		Bawl.processElementArray[Object.keys(Bawl.replyLinkParams)[Bawl.scrollToInt]].scrollIntoView(Bawl.smoothScroll);
		Bawl.processElementArray[Object.keys(Bawl.replyLinkParams)[Bawl.scrollToInt]].classList.add('BawlEaseIn','BawlPurpleBG');
		var DelayedHighlightRemove = setInterval(function () {
			clearInterval(DelayedHighlightRemove);
			Bawl.processElementArray[Object.keys(Bawl.replyLinkParams)[Bawl.scrollToInt]].classList.remove('BawlPurpleBG');
		},2000);
	}
};
if ( mw.util.getParamValue('BwlScrToTime') && ! Bawl.settings.ninjaLoader ) {
	Bawl.scrollToComment(mw.util.getParamValue('BwlScrToUsr'),mw.util.getParamValue('BwlScrToTime'));
}
Bawl.reJump(); //jumping seems to wait for the document to be ready, messing with the load time numbers, so we jump after the load time has been recorded
Bawl.nowikiClose = '</nowiki>';
};
Bawl.run();
} else {
	console.log('Bawl: you seem to be trying to load me twice. No dice.');
}