User:Billinghurst/common.js

From Wikisource
Jump to navigation Jump to search
Note: After saving, changes may not occur immediately. Click here to learn how to bypass your browser's cache.
  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (Cmd-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (Cmd-Shift-R on a Mac)
  • Internet Explorer: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Clear the cache in Tools → Preferences

For details and instructions about other browsers, see Wikipedia:Bypass your cache.

// <syntaxhighlight lang="javascript">
/* global $, mw, importScript, pathoschild */

//importScript('User:Phe/Author fill.js');
mw.loader.load('//en.wikisource.org/w/index.php?title=User:Phe/Works about.js&action=raw&ctype=text/javascript');

// User:Inductiveload/scan_transcludes.js
mw.loader.load('//en.wikisource.org/w/index.php?title=User:Inductiveload/scan_transcludes.js&action=raw&ctype=text/javascript');

//without text (script enables clear and save of Page: ns pages)
mw.loader.load('//en.wikisource.org/w/index.php?title=MediaWiki:Gadget-Without text.js&action=raw&ctype=text/javascript');

//set some global parameters for selection
var isPageNS = mw.config.get('wgNamespaceNumber') == 104;
var isIndianBio = isPageNS && !!mw.config.get('wgTitle').match('The Indian Biographical Dictionary.djvu/');
var isIrishBio = !!mw.config.get('wgTitle').match('A Compendium of Irish Biography');
var isBiography = !!mw.config.get('wgTitle').match(/[\w ]+Biography/);
var isDNB00 = !!mw.config.get('wgTitle').match('Dictionary_of_National');
var isDictionary = isPageNS && !!mw.config.get('Dictionary of National');
var isBDMR = !!mw.config.get('wgTitle').match('Biographical Dictionary of Modern Rationalists');
var isCFB = !!mw.config.get('wgTitle').match('A cyclopaedia of female biography');


/**</syntaxhighlight>
 * TemplateScript adds configurable templates and scripts to the sidebar, and adds an example regex editor.
 * @see https://meta.wikimedia.org/wiki/TemplateScript
 * @update-token [[File:pathoschild/templatescript.js]]
 */
// <syntaxhighlight lang="javascript">
$.ajax('//tools-static.wmflabs.org/meta/scripts/pathoschild.templatescript.js', { dataType:'script', cache:true }).then(function() {
	// page NS
	pathoschild.TemplateScript.add(
		[
			// RunningHeader
			{ name: 'RunningHeader', position: 'cursor',
			script: function(editor) {
				editor.forField('#wpHeaderTextbox')
				.append('{{RunningHeader||}}');
			} },

			// CFB specific
			{ name: 'CFB', position: 'cursor',
			script: function(editor) {
				editor.replace(/ ?\n ?\n{{c(?:enter)?\|/gi, '<section end="" />\n\n{{center|')
				.replace(/(\n)?{{c(?:enter)?\|(.+)([,.]) ?}}/g, '$1<section begin="$2" />{{center|{{larger|$2$3}}}}')
				.replace(/\n?$$/, '<section end="" />')
				.replace(/^^([\w"])/, '<section begin="" />$1');
			} },

			// BDMR specific
			{ name: 'BDMR', position: 'cursor',
			script: function(editor) {
				editor.replace(/\b(B\.|Ed\.|D\.) /g, '\'\'$1\'\' ')
				.replace(/ s([ ,.])/g, '\'s$1');
			} },

			// remove refs from footer
			{
			name: 'killrefs',
			position: 'replace',
			script: function(editor) {
				editor.forField('#wpFooterTextbox')
				.replace(/[ \s\n]{0,2}(<references ?\/>|{{smallrefs}})\n?/g, '');
			}
			},

			// add refs to footer
			{
			name: 'addrefs',
			position: 'cursor',
			script: function(editor) {
				editor.forField('#wpFooterTextbox')
				.append('{{smallrefs}}');
			}
			},

			// replaces references with smallrefs
			{
			name: 'smallrefs', position: 'replace',
			script: function(editor) {
				editor.forField('#wpFooterTextbox')
				.replace(/(<references\/>)/,'{{smallrefs}}');
			}
			},

			// convert {{runningheader}} to {{center}} in header and footer, and also <center> to {{center}}
			{
			name: 'rh to c',
			position: 'replace',
			script: function (editor) {
				editor.replace(/<center>(.+?)<\/center>/g, '{{center|$1}}');
				editor.forField('#wpHeaderTextbox').replace(/\n?{{(rh|runningheader)\|/g, '{{center');
				editor.forField('#wpFooterTextbox').replace(/\n?{{(rh|runningheader)\|/g, '{{center');
			}
			},

			// puts {{right}} into footerbox
			{
			name: 'endword', position: 'replace',
			script: function(editor) {
				editor.forField('#wpHeaderTextbox')
				.replace(/(<\/div>)/,'{{right|}}$1');
			}
			},
			// wraps anchor+ around selected text
			/*{
			name: 'anchor+ select',
			script: function(editor) {
				editor.replaceSelection(function(selected) {
				return '{{anchor+|' + selected + '}}';
				});
			}
			}*/
			// used in dictionary-type works to add "end" then "begin" <section> markers in front of bold para
			{
			name: 'BoldSect',
			position: 'cursor',
			script: function(editor) {
				editor.replace(/\. ?\n ?\n'''/g, '.<section end="" />\n\n<section begin="" />\'\'\'');
			}
			},

			// standardise quote-type marks
			{
			name: '\'\"',
			position: 'cursor',
			script: function(editor) {
				editor.replace(/(‘‘ ?|“ ?| ?(”|’’))/g, '\"')
				.replace(/[‘`’]/g, '\'')
				.replace(/&quot;/g, '\"');
			}
			},


			// section tidy
			{
			name: 'sect tidy',
			position: 'cursor',
			  script: function(editor) {
			    editor.replace(/\n<section end/g, '<section end')
				.replace(/\/>\n<section begin/g, '/>\n\n<section begin')
                .replace(/\/>\n\[/g, '/>[')				;
			  }
			},

			// italicise Q.V. for "A catalogue of notable Middle Templars ..."
			{
			name: 'qvit',
			position: 'cursor',
			script: function(editor) {
			        editor.replace(/q\. v\./g, '\'\'q.v.\'\'');
			}
			},

			// main cleanup regex for general cleanup and tidy (grunt work)
			{
			name: 'cleanup',
			position: 'cursor',
			script: function(editor) {
				var header = editor.forField('#wpHeaderTextbox');
				var footer = editor.forField('#wpFooterTextbox');
				var isPageNS = mw.config.get('wgNamespaceNumber') == 104;
				var isDictionary = isPageNS && mw.config.get('Dictionary of National');

				// various cleanup
				editor
				// Digitized by Google (kill)
				.replace(/Digitized[\s\n]+by[^\n]+\n(Google)?/, '')

				// remove trailing spaces at the end of each line
				.replace(/ +\n/g, '\n')

				// remove trailing whitespace preceding a hard line break
				.replace(/ +<br *\/?>/g, '<br />')

				// remove leading blank lines
				.replace(/^^\n+/g, '')

				// convert double-hyphen to mdash (avoiding breaking HTML comment syntax)
				.replace(/([^\!])--([^>])/g, '$1—$2')

				// remove spacing around mdash, but only if it has spaces on both sides
				// (we don't want to remove the trailing space from "...as follows:— ",
				// bearing in mind that the space will already be gone if at end of line).
				.replace(/ +— +/g, '—')

				// remove trailing whitespace at the end of page text
				.replace(/\s+$/g, '')

				// remove trailing spaces at the end of refs
				.replace(/ +<\/ref>/g, '</ref>')

				// remove trailing spaces at the end of template calls
				.replace(/ +}}/g, '}}')

				// join words that are hyphenated across a line break
				// (but leave "|-" table syntax alone)
				.replace(/([^\|])(-|¬)\n/g, '$1')

				// remove unwanted spaces around punctuation marks
				.replace(/ ([);:\?!,])/g, '$1')

                //remove zero-width space (yes, it is in b/w the slashes)
                .replace(/⁠/g, '')

				// q.v. to q. v.
				.replace(/q\.v\./gi, 'q. v.')

				// fi to fi
				.replace(/fi/g, 'fi')

				// _m_ to _in_
				.replace(/ m /g, ' in ')

				// n -> ri
				.replace(/ Insh /g, ' Irish ')

				// bom to born
				.replace(/(-| |\n)([bB])om /g, '$1$2orn ')

				// l -> I
				.replace(/\blona\b/g, 'Iona')

				// 1 -> l
				// i -> l
				.replace(/co[1I]n/g, 'coln')

				// -> æ
				.replace(/Athenseum/g, 'Athenæum')
				.replace(/Archseol/g, 'Archæol')
				.replace(/isericordise/g, 'isericordiæ')

				//OCR fixes
				// convert i9 to 19, etc.
				.replace(/[il]([0-9])/g, '1$1')
				.replace(/Diet. Nat. Biog./g, 'Dict. Nat. Biog.')

				// li -> h ... "the", "them", "their", "with", "much", "here" and whe etcetera
				.replace(/([Tt])li(?=a[nt] |[iu]s |e |eir|em|ey|oug|re)/gi, '$1h')  //th start of word
				.replace(/(?<=wit|reat|ort|trut)li/g, 'h')                // th end stem case senstive
				.replace(/(?<=ot|whet|rt)li(?=e)/gi, 'h')               // the stem case insenstive
				.replace(/(?<=muc|bot|fres|Iris|mont|[Ss]out)li\b/g, 'h')    // th word terminate case senstive
				.replace(/wli(?=[aeiou])/g, 'wh')               // wh vowel
				.replace(/(wlii?cli|ivhic(li|h)|wlii[ce]h|wiiich|whicli)/g, 'which')
				.replace(/li(?=app|ave|ere|ead|i[ms]|osp|ould)/g, 'h')  // h start word
				.replace(/\bli(?=a[ds]\b)/g, 'h')    // has had
				.replace(/(?<=[aeiou])gli\b/g, 'gh') // gh word terminate
				.replace(/g[il]it\b/g, 'ght')        // ght
				.replace(/(?<=\dt)li/g, 'h')         // digit th
				.replace(/Cli(?=ar|rist)/g, 'Ch')    // Ch
				// specific word cases
				.replace(/(?<=[hH]ig)li/g, 'h')
				.replace(/liurcli/g, 'hurch')
				.replace(/Birmingliam/g, 'Birmingham')
				.replace(/sliire/g, 'shire')

				// im -> un  (under, until, young, round, count)
				.replace(/oim(?=[dgt])/g, 'oun')
				.replace(/im(?=de|ti|less|certain|res)/g, 'un')

				// mg -> ing
				.replace(/mg\b/g, 'ing')

				// Av -> w
				.replace(/Av(?=as |ay\b|e |ere |elc|hen|here |hich|ho|ife|ill|ith|or[kst]|ould|rath)/g, 'w')
				.replace(/AV(?=as |ay\b|e |ere |elc|hen|here |hich|ho|ife|ill|ith|or[kst]|ould|rath)/g, 'W')

				// weird w^ OCR
				.replace(/([Ww])\^(?=[aeiouh])/g, '$1')

				// U -> li & H -> li 
				.replace(/(?<=Dub|Ber)[HU]n/g, 'lin')
				.replace(/Dubhn/gi, 'Dublin')
				.replace(/b[hnU]c/g, 'blic')
				.replace(/\bU(?<=ttl|fe)/g, 'li')
				.replace(/Ehza/g, 'Eliza')
				.replace(/Enghsh/, 'English')
				.replace(/(?<=[aeiou])h(?=t)/g, 'li')
				.replace(/(?<=[a-fi-z]+)[HU](?=[a-z])/g, 'li')
				.replace(/thohc/g, 'tholic')
				.replace(/\bh(fe|t|ng)/g, 'li$1')
				.replace(/h(v|ng|ke|gh)/g, 'li$1')
				.replace(/\bbe(?:h|ll)e(f|v)/g, 'belie$1')

				// U -> ll when preceded by a lowercase letter.
				.replace(/(?<=[a-z])U/g, 'll')

                // u -> n
				.replace(/\baud\b/g, 'and')

				// j}3^ -> y
				.replace(/(3|j|\})\^/g, 'y')

				// EKo-> Ro
				.replace(/(?:E|K)om(e|an|ish)([ \.\,\n])/g, 'Rom$1$2')
				.replace(/(?:E|K)oscom/g, 'Roscom')

				// b -> h
				.replace(/\bbis\b/g, 'his')

				// Coimcil -> Council, sim. country
				.replace(/\b(?<=[Cc])oim(?=cil|try|tries)/g, 'oun')

				// London
				.replace(/ Loudon/g, ' London')

				// fiiture -> future
				.replace(/fiiture/g, 'future')

				// -> field
				.replace(/(?:fleid|fieid)/g, 'field')

				// -> don't
				.replace(/\b([dD])on t\b/g, '$1on\'t')

				// oi -> of
				.replace(/ oi /g, ' of ')

				// h -> b
				.replace(/heing/g, 'being')
				.replace(/\bhy\b/g, 'by')

				// unicode
				.replace(/&eth;/g, 'ð')
				.replace(/&ETH;/g, 'Ð')
				.replace(/&deg;/g, '°')
				.replace(/&thorn;/g, 'þ')
				.replace(/&THORN;/g, 'Þ')
				.replace(/&hellip;/g, '…')

				// TIWW Thom's Irish who's who (related)
					// J.P.
					.replace(/J\. P\./g, 'J.P.')
					.replace(/ CLE\./g, ' C.I.E.')
					// dau. & daus.
					.replace(/ da(ii|n)\. /g, ' dau. ')
					.replace(/ dans\. /g, ' daus. ')
					.replace(/( daus?.) o[it]/g, '$1 of')
					.replace(/([sS])ou o[fit]\b/g, '$1on of')
					// m.
					.replace(/ (ra|ni)\. /g, ' m. ')
					// Q -> G
					.replace(/Qe(n\.|orge)/g, 'Ge$1')
					// other abbreviations
					.replace(/R\.A\.M\.C;/g, 'R.A.M.C.;')
					.replace(/ \-(Col|Gen)./g, '-$1.')
					.replace(/Ediic\./g, 'Educ.')
					// o- -> g
					//(null replacing anglo-- etc.
                    //.replace(/(?<!her)o-(?!t)/, 'g')    // negative lookbehind and ahead
					// v -> y
					.replace(/(?<=a|er|t)rv\b/g, 'ry')
					.replace(/(?<=[nru]|log|ad|wa|[nr]l|ie?t|bl|[er]m)v\b/g, 'y')
					.replace(/(?<=\b([Mm]a?|b|[Tt]he|Jul))v\b/g, 'y')
					.replace(/Mavnooth/g, 'Maynooth')
					.replace(/Tvrone/g, 'Tyrone')
					.replace(/\b(?<=[Rr])oval/g, 'oyal')

                    // esh / long s works
                   .replace(/ fo /, ' so ')
                   .replace(/(au|crea|[twT]h[eo])fe/g, '$1se')
                   .replace(/vifion/g, 'vision')
                   .replace(/eafon/g, 'eason')
                   .replace(/refent/g, 'resent')
                   .replace(/ (la|mu)ft/g, ' $1st')

					// BEK -> R
					.replace(/\b(?:II|E|K|B)(?=ailw|ation|egi[ms]|enais|ep[ur]|es\.:|ev\.|evo|ich|ob|oyal|ural|ector|iver)/g, 'R')
					.replace(/\bF\.E\.S\.( |,|\n)/g, 'F.R.S.$1')

					// E -> F
					.replace(/\bE(rom|rench)\b/g, 'F$1')

					// X -> N
					.replace(/Xav(al|y)\b/, 'Nav$1')

				// {{c}} to {{center}}
 				editor.replace(/{{c\|/g, '{{center|');
 				header.replace(/{{c\|/g, '{{center|');
				footer.replace(/{{c\|/g, '{{center|');

				// {{rh}} to {{RunningHeader}}
				header.replace(/\n?{{rh\|/gi, '{{RunningHeader|');

				// more cleanup
				editor
				//{{hws}} & {{hwe}} expanded
				.replace(/{{hws\|/g, '{{hyphenated word start|')
				.replace(/{{hwe\|/g, '{{hyphenated word end|')

				// {{di}} expanded
				.replace(/{{di\|/g, '{{dropinitial|')

				// {{li}} expanded
				.replace(/{{li\|/g, '{{largeinitial|')

				// {{hi}} expanded
				.replace(/{{hi\|/g, '{{hanging indent|')

				// {{sm}} expanded
				.replace(/{{sm\|/g, '{{smaller|')

				// {{...}} replaced
				// expand diacritical templates
				.replace(/{{\.{3}}}/g, '…')

				// expand diacritical templates
				.replace(/{{(ae|oe|\w[:`'~^-])}}/g, '{{subst'+':$1}}')

				//convert {{—}} to —
				.replace(/{{—}}/g, '—');

				// M<sup>c</sup> to {{Mc}}
				editor.replace(/M<sup>c<\/sup>/g, '{{Mc}}');
				header.replace(/M<sup>c<\/sup>/g, '{{Mc}}');

				// Robert
				editor.replace(/(ll|li|E)obert/g, 'Robert');
				header.replace(/(ll|li|E)obert/g, 'Robert');

				// yet more cleanup
				editor
				//DNB link conversion
				.replace(/\[\[(.{0,40}?) \(DNB00\)\|([^\]]+?)\]\]/g, '{{DNB lkpl|$1|$2}}')
				.replace(/\[\[(.{0,40}?) \(DNB01\)\|([^\]]+?)\]\]/g, '{{DNB lkpl|$1|$2|year=01}}')
				.replace(/\[\[(.{0,40}?) \(DNB12\)\|([^\]]+?)\]\]/g, '{{DNB lkpl|$1|$2|year=12}}')

				//section tag fix
				.replace(/<section (begin|end)=(\w[^\/]+)\/>/g, '<section $1="$2"/>');

				// merged ... function smaller() 
				if (isDictionary) {
				editor
				.replace(/<small>(.+?)<\/small>/g, '{{smaller block|$1}}')
				.replace(/<p style="font-size:smaller">(.+?)<\/p>/g, '{{smaller block|$1}}')
				.replace(/\{\{smaller\|\[/g, '{{smaller block|[');
				} else {
				editor.replace(/<small>(.+?)<\/small>/g, '{{smaller|$1}}');
				}
				// 
				//if (isDictionary) {
				//editor.replace(/}} ?({{DNB .{2,5}})[ \n]?(\<sect[^\>]+?\>)/g, '}}\n$1$2\n')
				//}

				// stuff to do only if the page doesn't contain a <poem> tag:
				if (editor.get().indexOf("<poem>") === -1) {
				editor
				// remove single line breaks; preserve multiple.
				// not if there's a tag, template, table syntax, hash, asterisk either side of line break
				.replace(/([^>}\n])\n([^<{\|#\*\n])/g, '$1 $2')
	
				// collapse sequences of spaces into a single space
				.replace(/  +/g, ' ');
				}
			}
			}
		],
		{ category:'page', forNamespaces:'page' } // common fields
	);

	// main NS
	pathoschild.TemplateScript.add(

		[
			// adds subst: #tag for <pages>
			{ name: 'Pages', template: '{{#tag:pages||index={{subst:BASEPAGENAME}}.djvu|from=|to=}}', position: 'cursor'},

			//  adds subst: #tag for <pages> with sections
			{ name: 'Pages++', template: '{{#tag:pages||index={{subst:BASEPAGENAME}}.djvu|from=|to=|fromsection={{subst:SUBPAGENAME}}|tosection={{subst:SUBPAGENAME}}}}', position: 'cursor'},

			// similar to above though all on one page
			{ name: 'Pages+++', template: '{{#tag:pages||index={{subst:BASEPAGENAME}}.djvu|include=|onlysection={{subst:SUBPAGENAME}}}}', position: 'cursor'}, 

			// adds defaultsort for a subpage
			{ name: 'defsortsubpage', template: '{{DEFAULTSORT:{{subst:SUBPAGENAME}}}}', position: 'cursor'},

			// wikis Chapter -1/+1 to Prev/Next
			{
			name: 'PrevNext',
			position: 'replace',
			script: function (editor) {
				var oldtitle = mw.config.get('wgTitle');
				var prevtitle = parseInt(oldtitle.replace(/^.*\/Chapter (\d+)$/,'$1'))-1;
				var headerprevious = '[[../Chapter '+prevtitle+'/]]';
				var nexttitle = parseInt(oldtitle.replace(/^.*\/Chapter (\d+)$/,'$1'))+1;
				var headernext = '[[../Chapter '+nexttitle+'/]]';
				editor.replace(/\| previous   \= \n \| next       \= /, '| previous   \= ' + headerprevious +'\n \| next       \= ' + headernext );
			}
			},

			// prev and next populated for subpages
			{
			name: 'pn [[//]]',
			position: 'replace',
			script: function (editor) {
				var prevnextlink = '[[..//]]';
				editor.replace(/(\| previous *=|\| next *=) *\n/g, '$1 ' + prevnextlink + '\n' );
			}
			},

			// &#39; to '
			{
			name: '&#39;',
			position: 'replace',
			script: function (editor) {
				editor.replace(/&#39;/g, '\'');
			}
			},

			// converts header template to BDMR
			{
			name: 'BDMRset',
			position: 'replace',
			script: function (editor) {				editor.replace(/\{\{header[^\}]+\}\}\n/, '{{Biographical Dictionary of Modern Rationalists\n | previous = \n | next     = \n | from     = \n | to       = \n | notes    = \n}}\n{{DEFAULTSORT:{{subst:SUBPAGENAME}}}}');
			},
			enabled: isBDMR
			},

			// converts header template to DNB00
			{
			name: 'DNBset',
			position: 'replace',
			script: function (editor) {
				editor.replace(/\{\{header[^\}]+\}\}\n/, '{{subst:DNBset\n |article= \n |previous= \n |next= \n |volume = \n |contributor = \n  |extra_notes= \n |from= \n |to= \n |section= \n}}');
			},
			enabled: isDNB00
			},

			// converts DNB endash title to a redirect
			{
			name: 'DNBredirect',
			position: 'replace',
			editSummary: 'redirect',
			script: function (editor) {
				editor.replace(/{{header\n \| title\s+?\= ([^–]+?)–([^\)]+?\))[=\|\w\s\n]*}}/g, '#redirect [[Dictionary of National Biography, 1885-1900/$1-$2]]');
			},
			enabled: isDNB00
			},

			// add similar template
			{
			name: 'similar',
			position: 'replace',
			editSummary: '{{similar}}',
			script: function (editor) {
				editor.replace(/\{\{(?=(header|author|portal|versions)\n)/gi, '{{similar|}}\n{{');
			}
			},

			// translator to override_translator
			{
			name: 'override transl',
			position: 'replace',
			script: function (editor) {
				editor.replace(/ translator\w+\=/, ' override_translator = ');
			}
			},

			// rm text quality templates
			{
			name: 'text quality',
			position: 'replace',
			script: function (editor) {
				editor.replace(/\{\{TextQuality\|\d{2,3}%\}\}/, '');
			}
			},

			// Littell link replacement
			{ name: 'Littell', position: 'replace', editSummary: 'convert to {{Littell\'s link}}',
			script: function (editor) {
				editor.replace(/\[\[Littell\'s Living Age\/Volume (\d{3})\/Issue (\d{4})\/([^\|]+)\|[^\]]+\]\]/g, "{{Littell's link|$3|$1|$2}}");
			}
			},

			// import enwiki, though with a replacement of translator field
			{ name: 'imp en (trans)', position: 'replace', editSummary: '',
			script: function (editor) {
				editor.replace(/ translator *= */g, " wikipedia  = {{import enwiki}}");
			}
			},

			// import enwiki, push above notes parameter
			{ name: 'imp en (push)', position: 'replace', editSummary: '',
			script: function (editor) {
				editor.replace(/(\n *\| *notes)/, "\n | wikipedia = {{import enwiki}}$1");
			}
			},


			// {{page}} multi to <pages>>
			{ name: '{{page}} multi', position: 'replace', editSummary: 'convert to <pages>',
			script: function (editor) {
				editor
				.replace(/{{page\|(.+)?\.djvu\/(\d{1,3})\|section=([^\|]+?)\|num=.+?}}/ig, "{{#tag:pages||index=$1.djvu|include=$2|onlysection=$3}}")
				.replace(/{{page\|(.+)?\.djvu\/(\d{1,3})\|num=.+?}}/gi, "{{#tag:pages||index=$1.djvu|include=$2}}")
				.replace(/\<div class="indented-page"\>/g, "")
				.replace(/\<\/div\>/g, "");
			}
			},


			// und2ital() converts underlines to italics (PG adaption)
			{
			name: 'und2ital',
			position: 'replace',
			script: function (editor) {
				editor.replace(/\_/g, '\'\'');
			}
			}
		],
		{ category:'main', forNamespaces:0 } // common fields
	);

	// user talk NS
	pathoschild.TemplateScript.add(
		[
			{ name: 'welcome', template: '{{welcome}} ~~~~', editSummary: 'welcome' },
			{ name: 'Welcome+test', template: '{{subst:welcomeip}}\n{{test}} ~~~~', editSummary: 'welcome and test' },
			{ name: 'welcomeip', template: '{{subst:welcomeip}} ~~~~', editSummary:'welcome' },
			{ name: 'headertoggle', template: '{{subst:User:Billinghurst/HeaderToggle}}' }
		],
		{ category:'usertalk', position:'after', forNamespaces:'user talk' } // common fields
	);

	// author NS
	pathoschild.TemplateScript.add(
		[
			// authority control
			{ name: '^auc', template:'\n{{authority control}}', position: 'after'},

			// nop
			{ name: 'nop', template:'\n{{nop}}', position: 'after'},

			// &hellip; conversion
			{ name: 'hellip', position: 'replace',
			script: function (editor) {
				editor.replace(/ ({{\.\.\.}} |(\. ?){3,5})/g, ' &hellip; ');
			}
			},

 			// subst: PAGENAME
			{ name: 'suPG', template:'{{subst:'+'PAGENAME}}', position: 'after'},

			// convert CHAPTER to Chapter
			{ name: 'chapcase', position: 'replace',
			script: function (editor) {
				editor.replace(/CHAPTER/g, '{{sc|Chapter}}');
			}
			}
		]
	);
});
// end of TemplateScript

//CHARINSERT forced outside of edit form like old Edit Tools
//at some point in wmf development, this will no longer be
//possible regardless of Gadget used - just delete all this then
window.charinsertDontMove = true;

//CHARINSERT - quick toggle between last two selected character sets
window.editToolsRecall = true;

// Add custom CharInsert entries
window.charinsertCustom = {
 "User": '\<div.class=\"lefttext\"\>\n+\n\<\/div\> \<div.class=\"leftoutdent\"\>\n+\n\<\/div\> {{raw.image|{{PAGENAME}}}} {{subst:ucfirst:{{subst:lc:+}}}}', 
};

// old toolbar buttons
/* function addExtraButtons () {
	mw.toolbar.addButtons(
		{
			imageId: 'mw-customeditbutton-templateanchorlink',
			imageFile: '//upload.wikimedia.org/wikipedia/commons/d/db/Button_with_wikinumber_character.png',
			speedTip: 'A/L ',
			tagOpen: '{{anchor link|anchor=',
			tagClose: '|pageno=}}',
			sampleText: ''
		}
	);
} */
// add personal buttons for old toolbar

if ( mw.config.get( 'wgAction' ) === 'edit' || mw.config.get( 'wgAction' ) === 'submit' ) {
	mw.loader.using( 'user.options', function () {
		if ( ! mw.user.options.get( 'usebetatoolbar' ) && mw.user.options.get( 'showtoolbar' ) ) {
			mw.loader.using( 'mediawiki.action.edit', function(){
			$( addExtraButtons );
			} );
		}
	} );

};

/* 
* HotCat local configuration
*/

(function(){function setShortCuts(){if (!window.HotCat.addShortcuts) return; window.HotCat.addShortcuts({
 // Do not modify above. Add your shortcuts below
 // Shortcut : Replacement, both inside single quotes. If the replacement shall contain a single quote, write it as \'

 // ADD YOUR SHORTCUTS HERE. DO NOT FORGET THE COMMA AT THE END OF EACH LINE.
 'bg':'biographies of',
 'uka':'United Kingdom authors',
 'ukpt':'United Kingdom poets',
 'uspl':'United States politicians',

 // Do not modify below
' ':""});} if (window.HotCat && window.HotCat.runWhenReady) window.HotCat.runWhenReady(setShortCuts); else $('body').on('hotcatSetupCompleted',setShortCuts);})();

// set personal use of disambig_category to override global.js default
JSconfig.keys['HotCatDisambigCategory'] = "Disambiguation categories";

//</syntaxhighlight>