User:Sarang/simpleSVGcheck/sandbox.js

From Wikimedia Commons, the free media repository
Jump to navigation Jump to search
Note: After saving, you have to bypass your browser's cache to see the changes. Internet Explorer: press Ctrl-F5, Mozilla: hold down Shift while clicking Reload (or press Ctrl-Shift-R), Opera/Konqueror: press F5, Safari: hold down Shift + Alt while clicking Reload, Chrome: hold down Shift while clicking Reload.
/**
* @Remarks
* Since Perhelion had quitted Wikipedia, this script is still much used; and maintenance is necessary.				//ed_
* Because nobody else did it, I tried some reparations and enhancements; the problem is: I have no JS knowledge.	//ed_
* It can be seen that I made a lot of helpless tries, marked all with  //ed_										//ed_
* It can well be seen that I fight heavily with JS and made things much more complicated							//ed_
* than an expert would have done it. Some things that I made function - more or less. Others don't.					//ed_
* 
* 
* @Description:
* Adds several SVG-valid-check-links on file-pages. Get the real byte-size for SVG-images. Put the template Igen prefilled in the file-description page.
* 14.07.2016 added tool-name recognition from SVG-code
* For usage show [[c:Template:Image generation]]
* @Revision: 12:00, 08 September 2020 (UTC)
* @Last Revision: 18:00, 02 February 2022  💃💃💃💃💃💃💃💃💃💃💃💃💃💃💃💃 Sarang
* @Author: [[User:Perhelion]], together featured with [[User:Sarang]]
* @License: CC BY-SA 3.0
* @Required modules: jquery.badge, mediawiki.api, mediawiki.util, jquery.spinner
* @TODO:
**/
// [[Category:User scripts|simpleSVGcheck]] <nowiki>
/* eslint-env es6*/
/* global mediaWiki, OO, importScript */
//   import {u_ex} from "User:Sarang/uexixt.js";
//   importScript('User:Sarang/uexixt.js');    // ed_wdh - does not work
let tstex = 0;	// global counter
let lcode = '';	// global langtst
(function ($, mw) {
'use strict';
let gbs = [],
c = mw.config.get([
			'wgAction',
	//		'wgScriptPath', 'wgScript',
			'wgPageName', 	'wgTitle',
			'wgUserLanguage',
			'wgUserName'	// For simplSVG
		]),
isEdit = /^(edit|submit)$/.test(c.wgAction),
err,
// size, // For simplSVG
toolName,
$textarea,
expeUser = /^Sarang|Sarangbot|JoKalliauer|Perhelion|Minorax$/.test(c.wgUserName),
myName   = c.wgUserName,
// Author= /^Hagar66|NordNordWest|TUBS$/.test(txT), // author with PGF ** invalide JS **
summary  =  'sSVG-[[User:Sarang/simpleSVGcheck/sandbox.js|script]]+SVG-[[Template:Image generation|template]]',
cSVG = {
	// When maintaining this script always bump this number!
	version: '0.5.6',
	name: 'simpleSVGcheck',
	failStr: 'FAIL automatic insert', // Igen, please insert manually
//	lcode: '',		// langtst	
	curSize: 0,
	flowRoot: 0,
	textPath: 0,
	timestamp: 0,
	badSVG: 0,											// 1=bad; 2=fake; 3=fake
//	author: 0,
//	PGFauthor: /^Hagar66|NordNordWest|TUBS$/.test(txT), // author with PGF  ** invalide JS **
	PGF: 0,
	switchTrans: 0,
	
	init: function () 
	{	// W3C-Validator check-link for every SVG (by [[User:Perhelion]] fixed also now for admins)
		let $g = $('<a>', 
			{	title: 'Get exact byte-size'
			}).badge('B?', 'inline', 1),
		$igen,
		/* = $('<a>', {
		title: 'Insert Template:Image_generation with W3-Validity',
		href: '#',
		text: '→SVG-Igen',
		click: mw.libs.simpleSVGcheck.getW3Data
		Uri <- Also
		})*/
		$SVGc = $('<a>', 
			{	title: 'Commons-libRSVG-Validator',
				href: '/wiki/Commons:Commons_SVG_Checker?withJS=MediaWiki:CommonsSvgChecker.js&checkSVG=' + encodeURIComponent(c.wgPageName),
				text: '→SVG Checker',
				target: '_blank'
			}),
		$rows = $('#mw-imagepage-section-filehistory').find('tr').slice(1),
		$t1 = $rows.first();

		$igen = $(mw.libs.commons.ui.addEditLink('', '→SVG Igen', 'e-igen', 'Insert Template:Image_generation with W3C-validity')).find('a')
			.on('click', mw.libs.simpleSVGcheck.getW3Data);

		$t1.children('td').slice(-3, -2).append(['<br>', $igen.clone(true)]);
		$t1.find('td[style]').append(['<br>', $SVGc]);
		$rows.each(function (i) 
		{	let $t = $(this);
			$t.find('td[style]>a:first').after(function () 
			{	let linkTxt = '→Valid SVG',
				file = $(this).attr('href'),
				// var href = "http://validator.w3.org/check?uri=" + $(this).attr("href") + "&group=1"; // there is an discrepance in automatic check

				href = 'https://validator.nu/?doc=' + file + '&group=1&schema=http%3A%2F%2Fs.validator.nu%2Fsvg-xhtml5-rdf-mathml.rnc+http%3A%2F%2Fs.validator.nu%2Fhtml5%2Fassertions.sch+http%3A%2F%2Fc.validator.nu%2Fall%2F&parser=xml',

				a = $('<a>', 
					{	title: 'W3C-Nu-Validator',
						href: href,
						target: '_blank'
					});
				return ['<br>', a.text(linkTxt),
					a.clone().attr('href', href + '&showsource=1#result').text(' (+src)?')
					// ,"<br>",a.clone().attr("href", "http://validator.w3.org/check?uri=" + file + "&group=1&ss=1").text( "(→old W3-check)" )
				];
			});
			$t.children('td').slice(-3, -2).children('span').after(function () 
			{	if (!/Byte/.test(this.textContent)) 
				{	let $gb = $g.clone();
					gbs.push($gb.attr('name', i).click(cSVG.getImgData));
					return $gb;
				}
				gbs.push('');
			});
		});
	},				// init 

	getImgData: function () 
	{	mw.loader.using(['mediawiki.api'], function () 
		{	new mw.Api().get
			({	prop: 'imageinfo',
				iiprop: 'user|size', // |archivename
				iilimit: 9, // max requested images
				titles: c.wgPageName
			}).done(function (json) 
			{	if (!json || !json.query || !json.query.pages)
					return;
				let data = json.query.pages;
				for (let p in data)
					p = data[p];
				if (!p)
					return;
				data = [];
				for (let i = 0; i < p.imageinfo.length; i++)
					data.push(p.imageinfo[i].size);
				c.wgUserName = p.imageinfo[0].user; // global var
				cSVG.setImgSize(data);
			});
		});
	},				// image data

	warnMsg: function (w) 
	{	mw.loader.using([], function () 
		{	if (typeof w === 'number') 
			{	return mw.notify('SVG file is with ' + w + ' error' + ((w === 1) ? '' : 's') + ' not valid! ', 
				{	title: 'W3-Validity-check',
					type: 'warn'
				});
			}

			if (w instanceof Object)
				return mw.notify(cSVG.failStr + '!', w);
			mw.notify(w + ' Please check manually again with the web-service.', 
			{	title: 'W3-Validity-check warning!',
				type: 'error',
				autoHideSeconds: 7
			});
		});
	},				// warn msg

	getW3Data: function (e) 
	{	if (e && e.preventDefault)
			e.preventDefault();
		// FIXME: maybe use also Rillke Bot
		if (isEdit) 
		{	$('#editform').prepend($.createSpinner({
					id: 'w3nu',
					size: 'large',
					type: 'block'
				}));
			if (cSVG.err)
				return cSVG.addToFileDesc($textarea, cSVG.err, '', cSVG.toolName);
		}
		let file = '';
		if (!(isEdit && e instanceof Object)) 
		{	file = $('#file > a:first'); // fullImageLink
			if (!file.length)
				$(this).parent().prev().find('a'); // thumb preview, may superfluous
			if (file.length)
				file = file.attr('href');
		}
		if (!file || !/SVG$/i.test(file))
			file = 'https:' + mw.config.get('wgServer') + '/wiki/Special:Filepath/' + c.wgTitle.replace(' ', '_');
		// console.log(typeof e, e.nodeName , file );

		/* https://validator.w3.org/docs/api.html */
		// only once
		if (cSVG.xhr)
			return cSVG.addToFileDesc($textarea, -1);

		cSVG.xhr = $.getJSON('https://validator.w3.org/nu/', 
			{	'out': 'json',
				'showsource': 1, // for check tool-name
				// "charset" : "UTF-8",
				'doctype': 'SVG 1.1 + URL + XHTML + MathML 3.0', // SVG+1.1+%2B+URL+%2B+XHTML+%2B+MathML+3.0
				'parser': 'xml',
				'user-agent': 'W3C_Validator/1.3 http://validator.w3.org/services', // W3C_Validator%2F1.3+http%3A%2F%2Fvalidator.w3.org%2Fservices
				'schema': 'http://s.validator.nu/svg-xhtml5-rdf-mathml.rnc http://s.validator.nu/html5/assertions.sch http://c.validator.nu/all/',
				'doc': file
			}
				// https://validator.w3.org/docs/users.html#Options
				// $.getJSON("https://validator.w3.org/check?uri=" + file + "&ss=1&output=json" // CORS-Kopfzeile 'Access-Control-Allow-Origin' fehlt
			).done(
				function (json) 
			{	let data = json.messages;
				if (!data || !json.source || !json.source.code)
					return cSVG.warnMsg('Fail to read file ' + json);
				let code = json.source.code,
//				lcode = code.slice(0, 14),		// langtst 
				doctype = /<!DOCTYPE svg/i.test(code),
				err = [],
				warn = [],
				warnRDF = 'This validator does not validate RDF.', // FIXME only discrepance if <!DOCTYPE present
				para = {};	// Parameter 5
				para.curSize = code.length;
				para.badSVG = /[<:]image[\s>]/.test(code);							// 1=bad
				para.PGF = /strator_pgf">\s*(<!\[CDATA\[\s*)?[a-zA-Z]+/.test(code);	// pgf very different
				let toolName = cSVG.toolName = cSVG.getToolName(code, para.PGF);
				para.flowRoot = /[<:]flowRoot/.test(code);
				para.timestamp = /Martin Weinelt<\/tspan/.test(code); 			//
				para.textLogo = 0;
				if (!para.timestamp)
					para.timestamp = /Christian Duscha<\/tspan/.test(code);
				if (!(para.badSVG && para.PGF)) 
				{	para.switchTrans = / systemLanguage/.test(code); // /[<:]switch[\s>]/;
					para.textTrans = /[^>]\s?(<\/tspan>)?\s?<\/text>/.test(code);
					if (para.switchTrans)
						para.switchTrans = para.textTrans;
					else
						para.switchTrans = 0;
					if (para.switchTrans && !expeUser)
						para.textTrans = 0;
				}
				if (para.badSVG && !/[<:](path|text|polyline|polygon)[\s>]/.test(code))
					para.badSVG = 2; // Fake SVG
				if (para.badSVG && !/[<:]path[\s>]/.test(code) && /[<:]text[\s>]/.test(code))
					para.badSVG = 3; // Fake SVG with text
				if ((toolName === 'inkscape' || toolName === 'IA') && code.indexOf('aria-label=') > 20)
					para.textPath = 1; // textPath

				for (let i in data) 
				{	// console.log(i, data[i], doctype); // data.messages is an array
					json = data[i].type;
					if (!json)
						continue;
					if (json === 'error')
						err.push(data[i].message);
					else if (json === 'info' && data[i].subType === 'warning')
						warn.push(data[i].message);
				}
				err = err.length;
				let w = warn.length;

				if (w && doctype) 
				{	while (w--) 
					{	if (!warn[w].indexOf(warnRDF)) 
						{	warn = warnRDF;
							warnRDF = '';
							break;
						}
					}
				}
				// console.log("Successfully checked for SVG errors ", err, w, warn.length, warnRDF); // error messages
				if (isEdit) 
				{	if (!(err || warnRDF))
						cSVG.warnMsg(warn);
					$.extend(cSVG, para);
					return cSVG.addToFileDesc($textarea, err, warn, toolName);
				} else if (!(err || warnRDF)) 
				{	cSVG.warnMsg(warn);
					setTimeout(function () 
					{	cSVG.addIgenURL(err, '', toolName, para);
					}, 4000);
				} else {
					cSVG.addIgenURL(err, '', toolName, para);
				}
			}).fail(function (e) 
			{	mw.log.warn('Ajax error to ', e);
				if (isEdit)
					return cSVG.addToFileDesc($textarea, -1);
			});
		return false;
	},				// getW3Data

	/**
	 * Gets the tool name from SVG code.
	 *
	 * @param      {string}		code
	 * @param      {boolean}	toolName
	 * @return     {string}		tool name
	 */
	getToolName: function (code, toolName) 
	{	// TODO can be extended
		let toolList = 
		[	'geogebra',
			'xmlns:vectornator',					// Spinner (+Inkscap+Adobe)
			'sodipodi',
			'Sketch',
			'ShareMap',
			'openoffice',
			'libreoffice',
			'inkscape',
			' potrace', // + whitespace
			' graphviz', // + whitespace
			' dot version 2.2.1', // ??
			'QGIS',
			'MetaPost',
			'MATLAB',
			'Illustrator',
			'Gnuplot',  'GNUPLOT',
			'fig2svg',
			'EazyDraw',		// Peter coxhead
			'CorelDRAW',
			'DrawShield',
			'ElCompLib',	// ed_wdh
			'Method Draw',	// Cookieman1.1.1
			'Microsoft Visio',
			'Chemtool',
			'ChemSketch',	// ChristianBausW	
			'bkchem',
			'dvisvgm',
			'Batik',
			'ArcMap',
			'Adobe',
	//		'parliament diagram creator'],
		//	'Generator: wikimedia.svg.chart',
			'wikimedia.svg.chart',
			'Generated with Qt',			// <desc>Generated with Qt</desc>
			'Ratio="xMidYMid meet" ',		// can be DrawShield ?
//			'1999/02/22-rdf-syntax-ns#',	// Inkscape ?
//			'baseProfile="full"',			// when nothing else can be used - only hint for GeoGebra
			'parliament'
		],
		i = toolList.length;

		toolName = toolName ? 'Adobe' : '';
		while (i-- && !toolName) 
		{	if (code.indexOf(toolList[i]) + 1) 
			{	toolName = toolList[i];
				break;
			}
		}
		if (!toolName) { // Guess tool, boilerplate in every Illustrator SVG export
			i = /<svg [^>]+>/i.exec(code); // Root
			if (i) 
			{	if (i[0].indexOf('enable-background') + 1)
					toolName = 'Adobe';
				if (i[0].indexOf('id="svg2"') + 1)
					toolName = toolName ? 'IA' : 'I';
			}
		} else if (toolName === 'inkscape' &&
			/(inkscape:grid|sodipodi:(guide|cx))/.test(code)) 
		{	toolName = 'Im';
		} // IMPORTANT=yes
		// Mixtures:
		if (toolName === 'xmlns:vectornator')					// Spinner
			toolName = 'Vectornator';
		else if ((/^[Aa]dobe|Illustrator/.test(toolName) && /[Ii]nkscape/.test(code)) || (/^[Ii]nkscape/.test(toolName) && /[Aa]dobe|Illustrator/.test(code)))
				toolName = 'IA';

		return toolName;
	},				// getToolName

	setImgSize: function (data)   // get & set file size
	{	$.each(gbs, function (i) 
		{	$(this).prev().remove();
			// no link for first
			if (this && this[0].name !== '0')
			{	return $(this).text('→' + data[i])
				.attr('title', 'Insert Template:Igen with actual simple size: ' + data[0])
				.off('click')
				.click(function (/* e*/) 
				{	cSVG.addIgenURL('0', [data[i], data[0]]);
				});
			}
			// first badge link only for display
			return $(this).replaceWith(data[0] + ' Byte');
		});
	},				// setImgSize

/*	 registerModules: function() { // Register custom modules
	if ( !mw.loader.getState('mediawiki.commons.MwJSBot') ) mw.loader.implement('mediawiki.commons.MwJSBot', ["//commons.wikimedia.org/w/index.php?action=raw&ctype=text/javascript&title=User:Rillke/MwJSBot.js"], {
	}, {
	});
	},				// registerModules
	
	run: function() { // Create GUI
	cSVG.registerModules();
	mw.loader.using(['mediawiki.commons.MwJSBot'], function() {
	});
	},				// run
*/

	setIgen: function (pre, post) 
	{	$textarea.textSelection('encapsulateSelection', 
		{	pre: pre,
			// peri: '',
			post: post
		});
	},				// setIgen

	replaceTag: function (txt, err, toolname) 
	{	if (!txt)
			return;
		let size = this.size,
		txT = txt,	//.replace(/( *\| *[Ii]m)(?:gen|ag)?( *= *)/, '$1age$2'),		//	pre_normalize [im, imag, imgen]
/*		Info/var	imRe: not-empty parameter
	Information		|other fields		{{file generation description
	COAInformation	|imgen, image		{{igen
	Infor[m]		|im, imag[e]		{{image generation
*/		imRE = /^\s*\| *(?:[Oo]ther[_ ]fields|[Ii]mage) *=\s*\{\{(?:[Ii]genc?|[Ii]mage generation|[Ff]ile generation description) *\|(\w+)\}\} *$/m,
//		ivar = /\{\{ *[Ii]nform?\s*\|\s*/.test(txT),								// Info/var
		imag = '|image',															// parm
		coai = /\{\{ *COAInformation\s*\|\s*/.test(txT),							// coat of arms template boolean
		imageRE = /\|\s*[Ii]mage\s*=\s*[^\s]+ *\n/,									// COA short parm (^imgen)
		imgenRE = /\|\s*[Ii]ma?gen?\s*=\s*[^\s]+ *\n/,								// COA short parm (=imgen)
		imPar = ((coai && imageRE.test(txT)) || imRE.test(txT)),					// coai & image, O_f
		toolName = '',			// default nothing, most possible is Inkscape
	//	IgenVar  = (coai) ? '|fields' : '|other fields',							// decide which param name
		IgenParm = (coai) ? '|image       ' : '|other fields',		// from here it comes  decide which param name
 		// sourcecode, // possible from which are generated for "Created with code"
		g = '',  // specify the Graphic lab
		r = '',  // retouched
		s = '',  // suffix for subcat = "topic"							💵💵💵💵💵💵💵💵💵💵💵
		T = '',  // additional trailing text for templates (extension)	💵💵💵💵💵💵💵💵💵💵💵
		p5 = '', // Parameter 5
		s1 = '', // leading whitespaces as indent?
		s2 = '', // whitespace on parameter?
		ls = '', // last substring index
		stxt = '|s=',	// or |s:=	
		topp = '', // template igen on topposition
		replaced = false,
		LeyoChem = false,
	 	Otagtab =					//  Other Tags Table:
		{	"bf"  : false,			//	37 broken file
			"bl"  : false,			//	33 colorblind
			"ci"  : false,			//	25 current int.
			"dm"  : false,			//	   diputed map
			"ff"  : false,			//	34 fictitious flag
			"fi"  : false,			//	36 fake sports logo
			"fw"  : false,			//	   fotowerkstatt		
			"in"  : false,			//	29 c.t. internetional
			"lh"  : false,			//	24 logo hist
			"ml"  : false,			//	30 c.t. multilang
			"ni"  : false,			//	14 no Inkscape
			"nu"  : false,			//	21 noUpdate
			"oq"  : true,			//	27 opaque
			"ov"  : false,			//	26 overlay
			"rd"  : false,			//	35 redrawn
			"re"  : false,			//	22 recent
			"rs"  : false,			//	38 restoration
			"tr"  : false,			//	28 translate
			"tw"  : false,			//	   taken with 
			"up"  : false,			//	23 update/outdate
			"wc"  : false,			//	31 c.t. wikichart
			"wt"  : false,			//	32 c.t. wikitable
			"zf"  : false			//	39 zoofary
		},
		Fwrktab =					//  Fotowerkstatt
		{	"fwc"  : false,			//	change
			"fwe"  : false,			//	editor
			"fwo"  : false,			//	orig
			"fwl"  : false,			//	orig-lang
			"fwt"  : false,			//	topic
			"fws"  : false,			//	style
		},
	//		ofRC = /( )*\|\s*[Oo]ther[_ ]fields( )*=\s*([^\n]*\n)/g,			// $1, $2, $3
		ofRE = /( )*\|\s*(?:[Oo]ther[_ ]fields|image)( )*=\s*([^\n]*\n)/g,	//  Info/var $1, $2, $3
		inRE = 
		[	/\{\{(COA)?[Ii]nform?(ation)?\s*\|\s*/,							//  var
			/( )*\|\s*[Pp]ermission( )*=\s*[^\n]*\n/,
			/( )*\|\s*[Oo]ther[_ ]versions( )*=(\n?[^\n]*\n)/
		],
		IgenName = '{{Igen|',
		IgenNameLong = '{{Image generation|',
		tempPre = '}}\n',
		fnam = c.wgTitle.slice(0, -4),	// without .extension 		
		fext = c.wgTitle.slice(-4),		// = .svg
	//	fbmp = '',			// fname of raster 
	//	fbmx = '',			// exten of raster 
		user = '',			// for u=
		
		// Normalized toolnames different to code
		toolNames = 
		{	'Fig2svg': 'Fig2SVG',
			'Illustrator': 'Adobe',	'Adobe Illustrator': 'Adobe',
			'bkchem': 'BKchem', 	'Bkchem': 'BKchem', 
			'Libreoffice': 'LibreOffice',
			'Microsoft Visio': 'Visio',
			'DrawShield': 'DrawShield', 
			'geogebra': 'GeoGebra',	
			'Openoffice': 'OpenOffice.org',
			'Generated with Qt': 'Qt',
			'wikimedia.svg.chart': 'WMC',						// 
			' potrace': 'Potrace',
			' Perl': 'perl',
			' graphviz': 'Graphviz',  ' dot version 2.2.1': 'Graphviz',
			'Dvisvgm': 'dvisvgm',								// sombody made it uppercase;
			' vector-effect="none" ': 'Natural Earth',			// maybe more ident is needed
			'path vector-effect': 'Natural Earth',				// maybe more ident is needed
			'Ratio="xMidYMid meet" ': 'DrawShield',				// (Potrace = ...meet">)
			'BaseProfile="full"': 'GeoGebra',					// - or Potrace ?
			'1999/02/22-rdf-syntax-ns#': 'Inkscape'				// Inkscape default
		},
		
		// Toolname abbreviations (experienced users only)
		toolAbbr = 
		{	'Adobe': 'A',
			'Adobe-hand': 'AH',
			'Inkscape': 'I',
			'Inkscape-hand': 'H',
			'BKchem': 'B',			// ed_sf
			'ChemDraw': 'C',		// ed_sf
			'CorelDraw': 'D',
			'CorelDRAW': 'D',
			'Fig2SVG': 'F',
			'Gnuplot': 'G', 'GNUPLOT': 'G',
			'LibreOffice': 'L',
			'OpenOffice.org': 'OOo',
			'Text Editor': 'T',
			'Parliament': 'Wpdc',
			'Vectornator': 'Ac'					// Spinner
		},
		// Full replace - use templates:W		Expand this table when there are more (W)ikilink templates 
		Langtab = 
		{	"en" :	"W" ,
			"ar" :	"WA" ,				// arab     199K
			"bn" :	"Wb" ,				// bengali  131K
			"ca" :	"WC" ,				// catalan
			"cs" :	"Wc" ,				// czech/český
			"da" :	"Wda" ,				// danish   136K
			"de" :	"Wd" ,
		//	"el" :	"Wel" ,				// hellenian 126K
			"eo" :	"WE" ,				// esperanto 139K
			"es" :	"We" ,
			"et" :	"Wet" ,				// estonian  112K
			"eu" :	"Weu" ,				// basque    
			"fa" :	"Wfa" ,				// persian   199K   
			"fi" :	"Wfi" ,				// finnish   257K
			"fr" :	"Wf" ,
			"gl" :	"Wg" ,
			"he" :	"Whe" ,				// ivrit     432K
		//	"hr" :	"Whr" ,				// croatian  102K
			"hu" :	"Wh" ,
		//	"id" :	"Wid" ,				// indonesian 95K
			"it" :	"Wi" ,
			"ja" :	"W日" ,				// japanese 1.116M
			"kn" :   "ವಿ" ,				// Kannada      4K –— very seldom
			"ko" :	"W말" ,				// korean
			"lt" :	"Wlt" ,				// lithunian   77K
			"lv" :	"Wlv" ,				// latvian     68K
			"mk" :	"Wm" ,				// makedonian 143K
			"ml" :  "വി" ,			    // malayalam   29K–— seldom
			"nl" :	"Wn" ,
		//	"no" :	"Wno" ,				// norsk (nb=Norsk Bokmål, 242K)   (nn=Norsk Nynorsk,  15K)
			"pl" :	"WP" ,
			"pt" :	"Wp" ,
			"ru" :	"Wr" ,
		//	"sa" :	"Wsa" ,				// sanskrit 	2K –— very seldom
		//	"sc" :	"Wsc" ,				// sardinian	1K –— very seldom
		//	"sd" :	"Wsd" ,				// sindhi   	1K –— very seldom
			"si" :   "වි" ,				// sinhala      2K –— very seldom
			"sk" :	"Wsk" ,				// slovak (Slovenčina)  155K
			"sl" :	"Wsl" ,				// sloven (Slovenščina) 127K
		//	"sq" :	"Wsq" ,				// albanian 	51K
			"sr" :	"Wsr" ,				// serbian     189K
			"su" :	"Wsu" , 			// sundanese    ~2K –— very seldom
			"sv" :	"Wsv" ,
			"th" :	"Wth" ,
			"tr" :	"Wtr" ,
			"uk" :	"Wu" ,
			"zh" :	"Wz"
		},
		// Dynamic table of users	(expanded by function when existence is checked)
		Usertab = 
		{	"Perhelion" :	"U" ,	// may be U, Ut, Uw, Uwt, Un, Uc, Uf
	//		"Sarangbot" :	"U" ,
			 myName     :   "U" ,	// dyn. (test)
			"Care"		:	"U"	,	// temp.
			"CdnMCG"	:	"U" ,	// temp.
			"Cburnett"  :	"U" ,	// temp.
	//		"Delta-9"	:	"U" ,	// temp. (Steve Perucchi, Geneva)
			"D Wells"	:	"U" ,	// temp.
			"Etxeko"    :   "U" ,	// temp
			"Erlenmeyer":   "U" ,
			"GabrielStella":"Ut" ,	// temp.
			"Gigillo83" :	"Ut" ,	// temp.
			"Jimmy44"   :	"U" ,	// temp.
			"Manassas"  :	"Uwt" ,	// temp.
			"Miyagawa":"U", "Pixelsquid":"U",
			"Miguillen"	:	"U" ,	// temp.
			"NEUROtiker":	"U" ,	// temp.
			"SanchoPanzaXXI" :	"Uw" ,	// do not link to dummy user entry !
			"Smokefoot" :	"U" ,	// temp.
			"Tomas.urban":	"U" ,	// temp.
			"Rodelar"	:	"U" ,	// temp.
			"Urhixidur" :	"U" ,	// temp.
			"NordNordWest": "U", "TUBS":"U", "Hagar66":"U",	// temp.
			"Biezl"		:	"U",	// temp.	
	//		"Zardoz91"	:	"U",	// temp.	
			"JoKalliauer":	"U"
		};

		/*
		 * t instanceof RegExp - "top position"
		 * return the end-index "topp" of info template before brackets
		 * ============================================================
		 */

		function encodeAlsoComponent(str) 
		{  return encodeURIComponent(str).
		       replace(/[%'()]/g, escape); // i.e., %25 %27 %28 %29
		}				// enc

		function _findPosition(t) 
		{	let p = 0; // end of info template
			let arr;
			let li = 0;
			let str;
			let RE = /[\s\S]+?\n\}\}\n/g;
			// sometimes index = 0
			t = t.lastIndex ? t.lastIndex - RegExp.lastMatch.length : txt.search(t);
			str = txt.substr(t);
			s1 = RegExp.$1 || s1;
			s2 = RegExp.$2 || s2;
			// Try to go at template end (fallback risky if another template ends in same way)    ed_wd 
			// often wrong position when 
			while ((arr = RE.exec(str)) !== null) 
			{	let m = arr[0];
				li = arr.index;
				p = m.lastIndexOf("{{");
				if (m && (p === -1 || (p = m.indexOf("}}", p)) !== -1 && p < m.length - 3)) 
				{	p = li + m.length - 3;
					str = "";
					break;
				} else
					p = 0;
			}
			if (!p) 
			{	p = str.search(/\n?\}\}$\n/m); // \s is trimmed before
				if (RegExp.lastMatch.length === 3) 
				{	txt = txt.substr(0, t + p) + '\n' + txt.substr(t + p);
					p++;
				}
			}

			t = (p >= 0) ? t + p : 0;
			return t;
		}				// _findPosition
		
	//	 * ============================================================ langtst
	function syslang ()  {return '/' + lcode;}
//	function syslang ()  {return lcode.slice(0, 44) + '/' + this.curSize;}
	//	 * ============================================================
	function _ucfirst(s)		// Uppercase
		{	return s.slice(0, 1).toUpperCase() + s.slice(1);
		}
	//	 * ============================================================
	function isHexval (val)		// test whether hexad
    	{ let retval = new RegExp('[0-9a-fA-F]');
    		return retval.test(val);
    	}
	//	 * ============================================================

	function pageExists(pagename, callback)
	{	$.ajax(mw.util.getUrl(pagename), 
		{	method: 'HEAD',
			success: function() { callback(true); },
			error: function(xhr) { callback(xhr.status === 404 ? false : null); }
		});
	}				// 

	function userExists(pagename, namespac) 
	{	++tstex;							// add 1 for each one of the expensive accesses
		pageExists(pagename, function(userexists) {
			var result = userexists ? namespac : 'Un';
			callback(result);
		});
	}				// 

	//	 * ============================================================
	function pageexist( pagename, callback )
	{	mw.loader.using( 'mediawiki.api', function () 
		{	( new mw.Api() ).get(
				{	action: 'query',
					prop: 'info',
					titles: pagename,
					formatversion: 2
				}, 
				{	success: function ( response ) 
					{	var page = response.query.pages[ 0 ];
						if ( page.invalid )
							{ callback( null );}
						else 
						if ( page.missing ) 
							{ callback( false );}
						else
							{ callback( true );}
					},
					error: function () { callback( null ); }
			}
		);
		} );
	}				// pageexist 
 	//	 * ============================================================
		function userexist( username, namespace ) 
		{	let retval = 'Un'; 
				++tstex;							// add 1 for each one of the expensive accesses
				pageexist ( username, (boolres) => 
			{	//	await;
				if (boolres)	retval = namespace;	// ns when 'true'
	//			else 
	//			if (boolres == null)	// CommonsMaintenanceBot issue
	//							retval = 'Uf';		// when 'null' 
	 			else retval = 'Un';					// when 'false'
			}); //setTimeout ( function() {return;} , 250);
				alert('r='+retval+'/'+username);	// does not work without
			return retval;
		}				// 
	//	 * ============================================================
	//	function get_param(ctxt) {
	//		return ctxt.replace(/\{\{(?:[^\|]*)\|([^\}]*)/, '$1');		// analize transcusion, and get params
	//	}																// not working test

		function generalCleanup(text)				//	🍬🍀🍬🍀🍬🍀🍬🍀🍬🍀🍬🍀🍬🍀🍬🍀🍬🍀🍬🍀🍬🍀🍬🍀
		{	// TODO: namespace User could be extended with any language
			// lowercase parameter name default, trim leading whitespace
		Otagtab.bf = (/\{\{\s*[Bb]roken file\s*[\|\}]/.test(txT)); 		// other tags
		Otagtab.bl = (/\{\{\s*[Cc]olou?r ?blind\s*[\|\}]/.test(txT));
		Otagtab.ci = (/\{\{ *[Cc]urrent *[\|\}]/.test(txT));
		Otagtab.dm = ( (/\{\{ *[Ii]naccurate-map-disputed *[\|\}]/.test(txT)) || (/\{\{ *[Dd]isputed map *[\|\}]/.test(txT)) );
		Otagtab.ff = ( (/\{\{ *[Ff]ictitious flag *[\|\}]/.test(txT)) || (/\{\{ *[Ff]ictional flag *[\|\}]/.test(txT)) );
		Otagtab.fw = ( (/\{\{ *[Ff]otowerkstatt *[\|\}]/.test(txT)) || (/\{\{ *[Bb]ilderwerkstatt *[\|\}]/.test(txT)) );  //  ??fw??
		Otagtab.fi = ( (/\{\{ *[Ff]ake sports logo *[\|\}]/.test(txT)) || (/\{\{ *[Bb]andeira falsa *[\|\}]/.test(txT)) );
		Otagtab.lh = (/\{\{ *[Ll]ogo history *[\|\}]/.test(txT));
		Otagtab.ni = (/\{\{ *[Nn]o[Ii]nkscape *[\|\}]/.test(txT));
		Otagtab.nu =  /\{\{ *[Nn]oUpdate\s*\}\}/.test(txT);		// no parm
		Otagtab.oq =  /\{\{\s*[Oo]paque\s*\}\}/.test(txT);		// no parm
		Otagtab.ov = (/\{\{\s*[Oo]verlay\s*\}\}/.test(txT));	// no parm
		Otagtab.re = (/\{\{\s*[Rr]ecent\s*[\|\}]/.test(txT));
		Otagtab.rs = (/\{\{\s*[Rr]estoration\s*[\|\}]/.test(txT));
		Otagtab.tr = (/\{\{\s*[Tt]ranslate\s*\}\}/.test(txT));
		Otagtab.tw = (/\{\{\s*[Tt]aken with\s*\}\}/.test(txT));
		Otagtab.up = ( (/\{\{\s*[Uu]pdate\s*\}\}/.test(txT)) || (/\{\{\s*[oO]utdated\s*\}\}/.test(txT)) );
		Otagtab.zf = (/\{\{\s*User:ZooFari\/Template:SVG\s*\}\}/i.test(txT));		// no parm
	//  ??fw?? 
	
	//	ge = (/\{\{\s*[Tt]aller de Cartografía\s*\}\}/i.test(text));
	
			if (inRE[0].test(text)) 				// ??? .test(txT) ???
			{	text = text.replace(/^( *)\|\s*([A-Z][^=\n{}|?!.]+ *=)/gm,
						function (m, p1, p2) {
						return p1 + '|' + p2.toLowerCase();
					});
			}
			// For AutVec, Own based, F, File, Filelist, Other versions, Derived from, Derivative versions; Retouched
			let fileTruncate = function (m, p1) 
			{	// Shorten parameter if names are the same - currently only 3 (or 4) letter ext is supported
				p1    = p1.trim(); 
				let fExt = p1.slice(-4),			//	3-letter ext
				fEx4  = p1.slice(-5),				//	6-letter ext
				fName = p1.slice(0, -4);			//	file name w/o ext
				fName = fName.substring(0, 5) === 'File:'  ? fName.substring(5 ) : fName;		//ed_wdh -
				fName = fName.substring(0, 5) === 'file:'  ? fName.substring(5 ) : fName;		//ed_wdh -
				fName = fName.substring(0, 6) === 'Image:' ? fName.substring(6 ) : fName;		//ed_wdh -
				fName = fName.substring(0, 6) === 'image:' ? fName.substring(6 ) : fName;		//ed_wdh -
				// replace understrokes 
				for (let i = 1; i < fName.length; i++)
  				{	if ( fName.substring(i, i+1) === "_")  
  						fName = fName.substring(0, i) + " " + fName.substring(0, i);	// change understroke 
				}									
				fName = (fEx4[0] === '.' && fName === c.wgTitle.slice(0, -5)) ? fEx4 : p1;		//ed_wdh -
				fName = (fExt[0] === '.' && fName === c.wgTitle.slice(0, -4)) ? fExt : p1;
				fName = fName === '.png' ? '.' : fName;
				fName = fName === '.gif' ? '.g' : fName;		// ed_wdh: 
				fName = fName === '.jpg' ? '.j' : fName;		// ed_wdh: 
				fName = fName === '.svg' ? '.s' : fName;		// ed_wdh: 
				fName = fName === '.tif' ? '.t' : fName;		// ed_wdh: 
				fName = fName === '.xcf' ? '.x' : fName;		// ed_wdh: 
				fName = fName === '.webp' ? '.w' : fName;		// ed_wdh: 
				Name = fName + "👻";							//test
				return m.replace ( fName );
			};

			return text					// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<🖍🖍🖍🖍🖍🖍
	.replace(/\(\[\[:es:Wikiproyecto:Ilustración\/Taller de Heráldica y Vexilología\|Taller de Heráldica y Vexilología in the Spanish Wikipedia\]\] \[\[Image:Proyecto Heraldica Wikipedia.svg\|20px\]\]\)/, '')
		.replace(inRE[2], '$1|other versions$2=$3') // standardize
		.replace(/( *\| *[Ii]m)(?:gen|ag)?( *= *)/, '$1age$2')		//	pre_normalize [im, imag, imgen]
		.replace(/ *\| *image *= *(?:.*)?\n/, '')     // pre_remove when coai	ed_wdh (ls)' |image       =')
	
	.replace(/\|[Oo]ther[ _](fields *= *\{\{)/g, '|@ther $1')		// masking	 🗩🗩🗩🗩🗩
	.replace(/\|@ther fields( *= *\{\{[Ii]m)/g, '|other fields$1') 	// demask when Imgen
 //		standardize	different layout formats of date	to	yyyy-mm-dd	
	.replace (/( *\| *[Dd]ate *= *\d{4}-\d{1,2}-\d{1,2}) *(?:\d{2}:\d{2}(?::\d{2})?)?(?: *\(?(?:UTC *[\+-]?\d?d?)?\)?)?/, '$1')	// ed_wdh: clock does NOT belong to date
	.replace (/( *\| *[Dd]ate *= *)\d{2}:\d{2}, (\d{1,2}) ([^\s]+) (\d{4})(?: \(UTC\))?/, '$1$4-$3-$2')		// ed_wdh: replace ~~~~~ h:m, dd Mmmmm yyyy
	.replace (/( *\| *[Dd]ate *= *)\d{2}:\d{2}, (\d{4}) ([^\s]+) (\d{1,2})(?: \(UTC\))?/, '$1$2-$3-$4')		// ed_wdh: replace ~~~~~ h:m, yyyy Mmmmm dd
	.replace (/( *\| *[Dd]ate *= *)\d{2}:\d{2}, ([^\s]+) (\d{1,2}), (\d{4})(?: \(UTC\))?/, '$1$4-$2-$3')	// ed_wdh: replace ~~~~~ h:m Mmmmm dd, yyyy
	.replace (/( *\| *[Dd]ate *= *)(\d{4})-(\d{1,2})-(\d{1,2})(?:T\d\d:\d\d:?\d?\d?\d?)?/, '$1$2-$3-$4')	// ed_wdh: replace ~~~~~ yyyy-mm-dd...
	.replace (/( *\| *[Dd]ate *= *)(\d{1,2})\/(\d{1,2})\/(\d{2}) (?:T\d\d:\d\d:?\d?\d?\d?)?/,'$120$4-$3-$2')// ed_wdh: replace ~~~~~ dd/mm/yy...
	.replace (/( *\| *[Dd]ate *= *)(\d{1,2})\/(\d{1,2})\/(\d{4})(?:T\d\d:\d\d:?\d?\d?\d?)?/, '$1$4-$3-$2')	// ed_wdh: replace ~~~~~ dd/mm/yyyy...

		.replace (/( *\| *[Dd]ate *= *)(\d{4})-(\d)-(\d{1,2}\s)/, '$1$2-0$3-$4')		// ed_wdh: normalize inserting zero
		.replace (/( *\| *[Dd]ate *= *)(\d{4})-(\d{2})-(\d\s)/, '$1$2-$3-0$4')			// ed_wdh: normalize inserting zero
	.replace (/( *\| *[Dd]ate *= *\d{4}-\d{2}-\d{2})(?:T\d\d:\d\d:?\d?\d?\d?)?/, '$1')	// ed_wdh: remove time

// restore falsified parameter names:
			.replace(/(\|\s*)svg(?= tool\s*=)/g, '$1 SVG')				// ed_wdh: undo
				.replace(/(\|\s*)tool(?=\s?name\s*=)/g, '$1 Tool')		// ed_wdh: undo
				.replace(/(\|\s*)other(?=\s?tool\s*=)/g, '$1 Other')	// ed_wdh: undo
			.replace(/(\|\s*)w3c(?= error count\s*=)/g, '$1 W3C')		// ed_wdh: undo
			.replace(/(\|\s*)topic(?=\s*=)/g, '$1 Topic')				// ed_wdh: undo
			.replace(/(\|\s*)text(?= embedded\s*=)/g, '$1 Text')		// ed_wdh: undo
			.replace(/(\|\s*)text(?= as path\s*=)/g, '$1 Text')			// ed_wdh: undo
			.replace(/(\|\s*)text(?=edit only\s*=)/g, '$1 Text')		// ed_wdh: undo
			.replace(/(\|\s*)draw(?= by hand\s*=)/g, '$1 Draw')			// ed_wdh: undo
			.replace(/(\|\s?)user(?=link\s*=)/g, '$1 User')				// ed_wdh: undo
// shorten indentions (if !coai):
			.replace(/\|blazon of      = ?/, '|blazon of   =')   // ed_wdh (ls)
			.replace(/\|blazon         = ?/, '|blazon      =')   // ed_wdh (ls)
			.replace(/\|references     = ?/, '|references  =')   // ed_wdh (ls)
			.replace(/\|description    = ?/, '|description =')   // ed_wdh (ls)
			.replace(/\|date           = ?/, '|date        =')   // ed_wdh (ls)
			.replace(/\|source         = ?/, '|source      =')   // ed_wdh (ls)
			.replace(/\|author         = ?/, '|author      =')   // ed_wdh (ls)
			.replace(/\|artist         = ?/, '|artist      =')   // ed_wdh (ls)
			.replace(/\|permission     = ?/, '|permission  =')   // ed_wdh (ls)
			.replace(/\|other fields *= ?/,  '|other fields=')   // ed_wdh (ls)		
		//	.replace(/\|other versions *= ?/,'|other versions=')   // ed_wdh (ls)		
			.replace(/\|fields *= ?/,        '|fields      =')   // ed_wdh (ls)		fields ?
			.replace(/\|versions *= ?/,      '|versions    =')   // ed_wdh (ls)	
			.replace(/\|element *= ?/,       '|element     =')   // ed_wdh (ls)
			.replace(/\|ecclesial *= ?/,     '|ecclesial   =')   // ed_wdh (ls)
			.replace(/\|tincture *= ?/,      '|tincture    =')   // ed_wdh (ls)
	//		.replace(/\|im[gen|age] *= ?/,   '|imAge       =')   // ed_wdh (ls) test
	.replace(/\[\[:de:Benutzer:\[\[User:Summer ... hier!\|[^\)]+\)*\]*/, '{{U|Summer ... hier!}}')
	.replace(/\|[Ss]ource *=\s*\n?\{\{de\|Eigene Arbeit, basiert auf:\}\}\s*\n\{\{en\|Own work, based on:\}\}\s*\n\*\[\[:File:([^\]]+)\]\], \[\[User:([^\|]+)\|\2\]\]/im, '|source={{Based|$1|by=$2}}')

		.replace(/== *[Gg]nuplot script to generate this plot *== *\n/, '')
		.replace(/<syntaxhighlight lang="gnuplot"> *\n/, '')
		.replace(/<source lang="gnuplot"> *\n/, '')
		.replace(/<\/syntaxhighlight> *\n/, '}}\n}}')
		.replace(/<\/source>/, '}}\n}}')
		.replace(/hist\.csv \] \|\|/g, 'hist.csv ] {{!!}}')
//		.replace(/([^\[]+)\[([^\]]+)\] *\n/g, '[$2] <$1>\n')		// OLY temp.


/*		//	 clean text switch part of files treated with toolforge translator
		//	 =================================================================
		// id="text1900-el" systemLanguage="el"><tspan id="tspan1893-el"
//	.replace(/ *\n*id="(text|trsvg|tspan|switc)[^"]+"/gm, '')									//  ed_wdh (useless id's)
		.replace(/ *\n*id="text[^"]+"/g, '')									//  ed_wdh (useless id's)
		.replace(/ *\n*id="trsvg[^"]+"/g, '')									//  ed_wdh (useless id's)
		.replace(/ *\n*id="tspan[^"]+"/g, '')									//  ed_wdh (useless id's)
		.replace(/ *\n*id="switc[^"]+"/g, '')									//  ed_wdh (useless id's)
	.replace(/<text id="trsvg[^"]+"><tspan id="trsvg[^"]+">([^<]+)<\/tspan>/g, '<text>$1')		// ed_wdh (first tspan)
	.replace(/ id="trsvg[^"]+"><tspan id="trsvg[^"]+">([^<]+)<\/tspan><\/text>/g, '>$1</text>')	// ed_wdh (last  tspan)
	.replace(/<\/tspan><tspan x="(\d+)" y="(\d+)" id="trsvg[^"]+">([^<]+)<\/tspan><\/text>/g, '</tspan><tspan x="$1" y="$2">$3</tspan></text>')   // ed_wdh 
	.replace(/<text(?: id="trsvg[^"]+")? systemLanguage="(\w+)"(?: id="trsvg[^"]+")?><tspan id="trsvg[^"]+">([^<]+)<\/tspan><\/text>/g, '<text systemLanguage="$1">$2</text>')   // ed_wdh
	.replace(/<text(?: id="trsvg[^"]+")? systemLanguage="(\w+)"(?: id="trsvg[^"]+")?><tspan id="trsvg[^"]+">([^<]+)<\/tspan><tspan([^<]+)<\/tspan><\/text>/g, '<text systemLanguage="$1">$2</tspan><tspan>$3</tspan></text>')   // ed_wdh 
		// <text systemLanguage="it"><tspan>Sistemici;</tspan>
	.replace(/systemLanguage="([^"]+)">\n?<tspan>([^<]+)<\/tspan>/g, 'systemLanguage="$1">$2')	// ed_wdh (first tspan)
		// <text><tspan>Systemic:</tspan>
	.replace(/<text><tspan>([^<]+)<\/tspan>/g, '<text>$1')										// ed_wdh (empty tspan)
	.replace(/<\/tspan>\n<\/text>/g, '</tspan></text>')  										// ed_wdh (remove newline)
	.replace(/<\/text><text/g, '</text>\n<text')  												// ed_wdh (insert newline)
	.replace(/<\/text><\/switch/g, '</text>\n</switch')  										// ed_wdh (insert newline)

	.replace(/stemLanguage="([^"]+)"><tspan x="0" y="([^"]+)">([^<]+)<\/tspan>/g, 'stemLanguage="$1" y="$2">$3')	// Mrmw x=0
	.replace(/<text><tspan x="0" y="([^"]+)">([^<]+)<\/tspan>/g, '<text y="$1">$2')									// Mrmw

	.replace(/<text systemLanguage="(\w+)"><tspan>([^<]+)<\/tspan>/g, '<text systemLanguage="$1">$2')   // ed_wdh first
*/
//	.replace(/<text(?: id="trsvg[^"]+")? systemLanguage="(\w+)"(?: id="trsvg[^"]+")?><tspan(?: id="trsvg[^"]+")?>([^<]+)<\/tspan>/g, '<text systemLanguage="$1">$2')   // ed_wdh 1 ts[an]


		// now simplify [[namespace: ...]] to the template transclusion {{N| ...}}
		// =======================================================================
		// namespaces: ns 0 = :W, ns 2 = U, ns 6 = :F, ns 10 = T, ns 14 = :C, ns 828 = M
/* replace: [[ns:link]]         -> {{N|link}}           one param
 *			[ns:link|name]]		-> {{N|link|name}}      two params
 *         
 *          [[ns:lx:link]]      -> {{N|link||lx}}       one param  plus language (two pipes)
 *          [[ns:lx:link|name]] -> {{N|link|name|lx}}   two params plus language

 *			[[ns:Link|Link]]    -> {{N|Link}}           two params, but 2nd is same
 *			[[ns:link|linkxyz]] -> {{N|link}}xyz        two params, but 2nd is 1st with suffix
                                    analog with language code
 *			[[ns:Link|link]]    -> {{N|link}}           two params, but 2nd is lcfirst
 *    		[[ns:link|Link]]    -> {{N|Link}}           two params, but 2nd is ucfirst
                                    analog with language code
 *			[[ns:lx:Link|linkxyz]]                      combination: same name lowercase,   
 *                              -> {{N|link||lx}}xyz           plus language, plus suffix 
 */

// first all other namespaces - then (as the last one) the namespace 0 
// ===================================================================

//		.replace(/\[\[:?(?:[Ww](?:ikipedia)?):([Uu]ser|[Ff]ile|[Tt]emplate|[Cc]ategory|[Mm]odule):/g, '[[:en:$1:')	// ed_wdh: W namespace 
//		.replace(/\[\[:?(?:[Ww](?:ikipedia)?):([a-z]{2,3}):/g, '[[:$1:') 		// double interlink - remove useless :w


	//	2  {{U		Wikipedia user links:
	.replace(/\|[Aa](rtist|uthor) *= *\*? *\{?\{?unknown\}?\}? *\n\n?\* *vectorized by (?:\[\[(?:[Uu]ser:)?|\{\{U\|)([^\]\}\|]+)(?:\|\2)?(?:\]\]|\}\})/m, '|a$1 = {{AutVec||$2}}')	// ed_wdh:
 		.replace(/Thom.lanaud/g, 'Thom.Lanaud')				//ed_wdh user writing
 		.replace(/User:Domdomegg/g, 'user:domdomegg')		//ed_wdh user writing
		.replace(/\{\{F\|([^\}]+?)\}\} +by +\[\[User\:([^\]]+?)\]\]/ig, '{{F|$1|by={{U|$2}}}}')	// L_P
		.replace(/\{\{F\|([^\}]+?)\}\} +by +\{\{U\|([^\}]+?)\}\}/ig, '{{F|$1|by={{U|$2}}}}')		// L_P
		.replace(/\{\{F\|([^\}]+?)\}\} +by +\{\{([^\}]+?)\}\}/ig, '{{F|$1|by={{$2}}}}')			// e.g. Wikidata
		.replace(/source=\{\{own\}\}\n\* \{\{Based/ig, 'source={{Based')
		.replace(/source=self-made \(based on/ig, 'source={{Based}}')		//bracket not closed 
		.replace(/\{\{fr\|1=\{\{Own work\}\}\}\}/, '{{Own}}')			// Jimmy44
		.replace(/\[\[w:fr:Utilisateur:Bvs-aca\|bvs-aca\]\]/i, '{{U|bvs-aca}}')	
//	.replace(/([Uu]ser|[Bb]enutzer|[Ff]ile|[Ii]mage|[Tt]emplate|[Cc]ategory|[Mm]odule): ?(_ucfirst([^\]\|]+?))(\|\2)([^\]]+?)?\]\]/g,  '$1:$3|$3]]$4💖')	
//	.replace(/\[\[(:?[Uu]ser|[Bb]enutzer|[Ff]ile|[Ii]mage|[Tt]emplate|[Cc]ategory|[Mm]odule): ?([^\]\|]+?)\|(_ucfirst(\2))([^\]]+?)?\]\]/g,  '[[$1:$3|$3]]$4💗')	
 			
		.replace(/\[\[:?(?:W(?:ikipedia)?:) ?User ?: ?([^\]\|]+?)(?:\|\1)?\]\]/ig, '{{U|$1||en}}')		// ed_wdh: U [single or same]
		.replace(/\[\[:?(?:W(?:ikipedia)?:) ?User ?: ?([^\]\|]+?)(\|[^\]]+?)?\]\]/ig, '{{U|$1$2|en}}')	// ed_wdh:
 				.replace(/\[\[:?(?:User|Benutzer): ?([^\]\|]+?)(?:\|\1)?\]\]/ig, '{{U|$1}}')			// ed_wdh: U [single or same]
				  .replace(/\[\[:?(?:User|Benutzer): ?([^\]\|]+?)(\| ?[^\]]+?)?\]\]/ig, '{{U|$1$2}}')	// ed_wdh: U [link & disp]
 	.replace(/\[\[:([a-z]{2,3}) ?:(?:User|Benutzer): ?([^\]\|]+?)(?:\|\2)?\]\]/ig, '{{U|$2||$1}}')		// ed_wdh: U [single or same]:lg
	.replace(/\[\[:([a-z]{2,3}):(?:User|Benutzer): ?([^\]\|]+?)\| ?([^\]]+?)\]\]/ig, '{{U|$2|$3|$1}}')	// ed_wdh: U [link & disp]:lg
 				  .replace(/\[\[:?(?:User talk): ?([^\]\|]+?)(?:\|\1)?\]\]/ig, '{{Ut|$1}}')				// ed_wdh: Ut[single or same]
				  .replace(/\[\[:?(?:User talk): ?([^\]\|]+?)(\| ?[^\]]+?)?\]\]/ig, '{{Ut|$1$2}}')		// ed_wdh: Ut[link & disp]
 	.replace(/\[\[:([a-z]{2,3}):(?:User talk): ?([^\]\|]+?)(?:\|\2)?\]\]/ig, '{{Ut|$2||$1}}')				// ed_wdh: Ut[single or same]:lg
	.replace(/\[\[:([a-z]{2,3}):(?:User talk): ?([^\]\|]+?)\| ?([^\]]+?)\]\]/ig, '{{Ut|$2|$3|$1}}')		// ed_wdh: Ut[link & disp]:lg

	//	6  {{F			l= for external	
			  .replace(/\[\[:(?:[Ff]ile|[Ii]mage): ?([^\]\|]+?)(?:\|(?:File:)\1)?\]\]/g, '{{F|$1}}')	// ed_wdh: F [single or same]
				  .replace(/\[\[:(?:[Ff]ile|[Ii]mage): ?([^\]\|]+?)\|(.+?)\]\]/g, '{{F|$1|$2}}')		// ed_wdh: F [link & disp]
	.replace(/\[\[:?(?:W(?:ikipedia)?:) ?(?:File|Image) ?: ?([^\]\|]+?)(\|[^\]]+?)?\]\]/ig, '{{F|$1$2|l=en}}')		// ed_wdh:
	.replace(/\[\[:([a-z]{2,3}):(?:[Ff]ile|[Ii]mage): ?([^\]\|]+?)(?:\|\2)?\]\]/g, '{{F|$2||l=$1}}')	// ed_wdh: F [single or same]:lg
	.replace(/\[\[:([a-z]{2,3}):(?:[Ff]ile|[Ii]mage): ?([^\]\|]+?)\|(.+?)\]\]/g, '{{F|$2|$3|l=$1}}')	// ed_wdh: F [link & disp]:lg
// test "by=":
				.replace(/\{\{F\|([^\}]+?)\}\} *by *\{\{U\|([^\}]+?)\}\}/g, '{{F|$1|by={{U|$2}}}}')		// ed_wdh: simplify by=U later
				.replace(/\{\{U\|([^\|]+?) ?((?:\| ?)[^\|]*?)? ?\|de\}\}/g, '{{Ud|$1$2}}')				// ed_wdh: Ud
				.replace(/\{\{(U|Ud|Ut)\|([^\|\}]+?)\|\}\}/g, '{{$1|$2}}')								// ed_wdh: remove pipe 
	
//(cleanup)	.replace(/\[\[(?:[Ff]ile:|[Ii]mage: *)([^\|]+?)\|(\d+)px\]\] */gm, '{{F|$1|Z|$2}}')			// ed_wdh: display image
//			.replace(/\{\{F\|([^\|]+?)\|Z\|(\d+)\}\} ?\{\{F\|([^\|]+?)\|Z\|(\2)\}\}/gm, '{{F1|$1|Z|$2}}{{F2|$3|Z|$2}}')
//			.replace(/\{\{F2\|([^\|]+?)\|Z\|(\d+)\}\} ?\{\{F[12]?\|([^\|]+?)\|Z\|(\2)\}\}/gm, '{{F2|$1|Z|$2}}{{F2|$3|Z|$2}}')
//			.replace(/\{\{F2\|([^\|]+?)\|Z\|\d+\}\}/gm, '{{F2|$1}}')		// rem. |Z|dd
//			.replace(/\}\}\{\{F2\|([^\|\}]+?)(\|?\}*)/gm, '|$1$2')			// rem. }}{{F2		  
//			.replace(/\{\{F1(\|[^\|]+?)\|Z\|(\d+)\|/g, '{{Fl|d=$2|o=Z$1|')	// change to {{Fl
				
	// 10  {{T
		.replace(/\[\[(?::?[Tt]emplate): ?([^\]\|]+?) ?(\| ?[^\]]+?)?\]\]/g, '{{T|$1$2}}')			// ed_wdh: T [link & disp]
 					.replace(/\{\{[Tt]emplate:/g, '{{')			//ed_wdh written by some users
		.replace(/\[\[:([a-z]{2,3}):(?:[Tt]emplate): ?([^\]\|]+?)((?:\| ?)[^\]]+?)?\]\]/g, '{{T|$2|$3|$1}}')	// ed_wdh: T [link & disp]:lg

	// 14  {{C
		.replace(/\[\[(?::[Cc]at(?:egory)?): ?([^\]\|]+?) ?(\| ?[^\]]+)?\]\]/g, '{{C|$1$2}}')	// ed_wdh: C [link & disp]

	//828  {{M
		.replace(/\[\[(?::?[Mm]odule): ?([^\]\|]+?) ?(\| ?[^\]]+)?\]\]/g, '{{M|$1$2}}')		// ed_wdh: M

	//	0  {{W    	 Wikipedia interwikilinks: 🏮 (🔅🔆)
	.replace(/\[\[:?(?:[Ww](?:ikipedia)?:)(?:([a-z]{2,3}):) ?([^\]\|]+?)(?:\|\2)?\]\]/g, '{{W|$2||$1}}')	// ed_wdh: W [single/same]
	.replace(/\[\[:?(?:[Ww](?:ikipedia)?:)(?:([a-z]{2,3}):) ?([^\]\|]+?)\|(.+?)\]\]/g, '{{W|$2|$3|$1}}')	// ed_wdh: W [link & disp] 
	.replace(/\[\[:?(?:[Ww](?:ikipedia)?:) ?([^\]\|]+?)(?:\|\1)?\]\]/g, '{{W|$1||en}}')		// ed_wdh: W:en [single/same]
	.replace(/\[\[:?(?:[Ww](?:ikipedia)?:) ?([^\]\|]+?)\|(.+?)\]\]/g, '{{W|$1|$2|en}}')		// ed_wdh: W:en [link & disp] 
//	.replace(/\[\[(?:(:[a-z]{2,3}))?:([Bb}ooks|{Dd}ata|[Mm]eta|[Nn]ews|[Qq]ote|[Ss]ource|[Ss]pecies|[Vv]ersity|[Vv}oyage|[Ww](?:ikipedia)):([^\]\|]+?)\|(.+?)\]\]/g, '{{W|$3|$4|$1:$2}}')	// ed_wdh: W [link & disp]  
	.replace(/\[\[:[Cc]:/g, '[[c:')
	.replace(/\[\[:?(\w):(?:([a-z]{2,3}):)?(?:[Ww](?:ikipedia)?:)? ?([^\]\|]+?)(?:\|\3)?\]\]/g, '{{W|$3||$1:$2}}')	// ed_wdh:+W [single/same]
	.replace(/\[\[:(?:([a-z]{2,3}):)?(?:[Ww](?:ikipedia)?:)? ?([^\]\|]+?)(?:\|\2)?\]\]/g, '{{W|$2||$1}}')	// ed_wdh: W [single/same] 
	.replace(/\[\[:?([\W\w][\w]{0,7}):(?:([a-z]{2,3}):)(?:[Ww](?:ikipedia)?:)? ?([^\]\|]+?)\|(.+?)\]\]/g, '{{W|$3|$4|$1:$2}}')	// ed_wdh:+W [l&d] lg
	.replace(/\[\[:(?:([a-z]{2,3}):)?(?:[Ww](?:ikipedia)?:)? ?([^\]\|]+?)\|(.+?)\]\]/g, '{{W|$2|$3|$1}}')	// ed_wdh: W [link & disp]  

	.replace(/\[\[:?(?:[Ww](?:ikt(?:ionary)?)): ?([^\]\|]+?)(\| ?[^\]]+)?\]\]/g, '{{Wt|$1$2}}')		// ed_wdh: Wikt:en [link & disp]
	.replace(/\{\{W\|User:([^\}]+)\}\}/g, '{{U|$1||en}}')	// en User (without link)
 //	.replace(/\{\{([UFTCMW]|Ut|Ud|Uc|Wt|[HX])\|(?: *1 *= *)?([^\|\}]*?)(?:\|([^\}\|]+?))?(?:\|([a-z]{2,3}))?\}\}/g, function (m, ns, link, disp='', lang='') 
 	.replace(/\{\{ *([UFTCMW]|Ut|Ud|Uc|Wt) *\|(?:1 *= *)?([^\|\}]*?)(?:\|([^\}\|]*?))?(?:\|([a-z]{2,3})?)?\}\}/g, function (m, ns, link, disp='', lang='') 
		{	if (lang !== '')				lang = "|" + lang;	// pipe only when present

 			let ssts = "";									// sub-string suffix
			if (link.length <= disp.length) {
 	 			for (let i = 1; i < link.length; i++)
  				{	if ( link.substring(i, i+1) === "_")  
  						link = link.substring(0, i) + " " + link.substring(i + 1);	// replace 
  					if ( disp.substring(i, i+1) === "_")  
  						disp = disp.substring(0, i) + " " + disp.substring(i + 1);	// replace, except {{U}}
  				}
	
 				ssts += disp.substring(0, link.length);	// part of possible sameness
 				if (ssts ===  link
				 || ssts ===  link.substring(0,1).toUpperCase() + link.substring(1)
				 || ssts ===  link.substring(0,1).toLowerCase() + link.substring(1)  )
 				{	link = ssts;					// case_correct from disp
 					ssts = "" + disp.substring(link.length, disp.length);	// suffix
 					disp = "";						// strip 
 				} 
 				else ssts = "";						// without suffix
 			}
		 	if (disp !== "" || lang !== "")		disp = "|" + disp; 
// ===================================================================

 			if ( lang === '' && ( ns === 'U' || ns === 'Uc' ) )	// user existence check
 			{	let linx = link.slice(0, 1).toUpperCase() + link.slice(1); // standardize user id
 	//			if (!Usertab[myName]) 
	//				Usertab[myName] = 'U';			// assume that own user page exists: insert when not element
  				ns = Usertab[linx] ? ''+Usertab[linx] : 'Un';	// test: with prefix when from Usertab
				if (myName !== 'Sarang')			// perform tests only for Sarang(not _bot)
					ns = 'U';						// otherwise assume that user page exists
				if (ns === 'Un')					// when not in table
 					ns = userexist("User:" + linx, 'U');				
 				if (ns === 'Un')
 					ns = userexist("User talk:" + linx, 'Ut');	
 				if (ns === 'Un')
 					ns = userexist("User:" + linx + '~commonswiki', 'Uw');
 				if (ns === 'Un')
					ns = userexist("User talk:" + linx + '~commonswiki', 'Uwt');
				Usertab[linx] = ns;				// new element into Usertab
 			}	
// ===================================================================
			return "{{" + ns + "|" + link  + disp + lang + "}}" + ssts;
		})

		// Full replace (was not intentional by oalb) using Langtab
	.replace(/\{\{[Ww]\|([^\|\}]*?)(?:\|\||(\|[^\|]*?)\|)([a-z]{2,3})\}\}/g, function (m, link, disp = "", lang = "")
		{	//if (!disp)	 disp =  "";
		 	//if (!lang)	 lang =  "";
			let diss = "" + disp;
			if (diss === "")		diss =  "|";
			let ns = lang;
			ns = Langtab[lang] ? Langtab[lang] : lang;
			if (ns !== lang) 
				return "{{" + ns + "|" + link  + disp + "}}";		// language replaced🔺
			else
				return "{{W|" + link  + diss + "|" + lang + "}}";	// language not found 
		})

			.replace(/\|by=\{\{U\|([^\|\}]+?)\}\}/g, '|by=$1')		// ed_wdh: simplify by=U
			.replace(/(XY \(siehe Dateiname\)|[Xx][Yy] ? \(see filename\))/g, '{{F|F}}')	// ed_wdh: 'XY' TUBS
			.replace(/von  \{\{F\|F\}\}/g, 'von {{F|F}}')			// ed_wdh: TUBS doublespace
			.replace(/(XY \(див. назву файлу\))/g, '{{F|F}}')						// ed_wdh: 'XY' TUBS
			.replace(/1=Siehe Dateiname und Grafikinhalt/, '{{F|F}}')				// summer hier
			.replace (/\{\{AutVec\|o\=\{\{Creator/, '{{AutVec|{{Creator') 			// ed_wdh
			.replace(/\(?\[\[[Uu]ser[ _]talk: ?([^\]|[]+)\|?[^\][]*\]\]\)?/g, '')	// ed_wdh: User talk - only when not stand-alone 
			.replace(/\[\[Category:Location not applicable ?(\|[^\n\]]+)?\]\]\n*/, '')	// Perhelion 2016-09-08 (disliked by Koavf)
			.replace (/\{\{([Ll]ocation) (?:dms|dec)/g, '{{$1') 					// ed_wdh deprecated
			.replace (/\{\{([Kk]oordynaty)/g, '{{Location') 						// ed_wdh deprecated
		.replace(/\[\[Category:Created with ShareMap ?(\|[^\n\]]+)?\]\]\n*/, '')	// ed_wdh
		.replace(/Created with \[\[ShareMap:\|ShareMap\.org\]\]\n*/, '')  			// ed_wdh 
		.replace(/Created with \[http:\/\/sharemap\.org ShareMap\.org\]\n*/, '')	// ed_wdh 
		.replace(/\[\[\Category:Created with Inkscape\]\]\s?/, '')					// ed_wdh  remove / uncat
		.replace(/(?:<center>)?\{\{(?:[Cc]reated with |[Mm]ade with )?Inkscape(?:\|err=\d*)?\}\}(?:<\/center>)?\s?\n*/, '')	// ed_wdh  Orem remove
		.replace(/<center>\s?\n*<\/center>\s?\n*/, '')	// ed_wdh  Orem remove
		.replace(/\{\{Created with Inkscape\}\}\s?\n*/, '')							// ed_wdh  remove / uncat
		.replace(/\[\[\Category:Inkscape\]\]\s?/, '')								// ed_wdh  remove even worse

		.replace(/\{\{\s*[Bb]roken file\s*\}\}\s*\n?/, '')						// ed_wdh  remove (bf)
		.replace(/\{\{\s*[Cc]olou?r ?blind\s*\}\}\s*\n?/, '')					// ed_wdh  remove (bl)
		.replace(/\{\{\s*[Ii]naccurate-map-disputed\s*\}\}\s*\n?/, '')			// ed_wdh  remove (dm)
		.replace(/\{\{\s*[Dd]isputed map\s*\}\}\s*\n?/, '')						// ed_wdh  remove (dm)
		.replace(/\{\{\s*[Ff]ictitious flag\s*\}\}\s*\n?/, '')					// ed_wdh  remove (ff)
		.replace(/\{\{\s*[Ff]ictional flag\s*\}\}\s*\n?/, '')					// ed_wdh  remove (ff)
		.replace(/\{\{\s*[Ff]ake sports logo\s*\}\}\s*\n?/, '')					// ed_wdh  remove (fi)
		.replace(/\{\{\s*[Ff]otowerkstatt\s*\}\}\s*\n?/, '')					// ed_wdh  remove (fw)		-- ??fw??
		.replace(/\{\{\s*[Bb]ilderwerkstatt\s*\}\}\s*\n?/, '')					// ed_wdh  remove (fi)		-- ??fw??
		.replace(/\{\{\s*[Bb]andeira falsa\s*\}\}\s*\n?/, '')					// ed_wdh  remove (fi)
		.replace(/\{\{\s*[Ll]ogo history\s*\}\}\s*\n?/, '')						// ed_wdh  remove (lh)
		.replace(/\{\{\s*[Nn]o[Ii]nkscape\s*\}\}\s*\n?/, '')					// ed_wdh  remove {ni}
		.replace(/\{\{\s*[Nn]oUpdate\s*\}\}\s*\n?/, '')							// ed_wdh  remove (nu)
		.replace(/\{\{\s*[Oo]paque\s*\}\}\s*\n?/, '')							// ed_wdh  remove (oq)
		.replace(/\{\{\s*[Oo]verlay\s*\}\}\s*\n?/, '')							// ed_wdh  remove (ov) 
		.replace(/\{\{\s*[Rr]ecent\s*\}\}\s*\n?/, '')							// ed_wdh  remove (re)
		.replace(/\{\{\s*[Rr]estoration\s*\}\}\s*\n?/, '')						// ed_wdh  remove (rs)
		.replace(/\{\{\s*[Tt]ranslate\s*\}\}\s*\n?/, '')						// ed_wdh  remove (tr)
	//	.replace(/\{\{\s*[Tt]aken with\s*\}\}\s*\n?/, '')						// ed_wdh  remove (tw)
		.replace(/\{\{\s*[Nn]oUpdate\s*\}\}\s*\n?/, '')							// ed_wdh  remove (up)
		.replace(/\{\{\s*User:ZooFari\/Template:SVG\s*\}\}\n?/, '')				// ed_wdh  remove {zf}
	//	.replace(/\{\{ *[Vv]ector text versions *\| *\.*\}\}\s*\n?/, '')		// ed_wdh  remove Zoofari's


		.replace(/\[\[Category:SVG files ?(\|[^\n\]]+)?\]\]\n*/, '')				// MetaCat
		.replace(/ ?(?:[Vv]ector(?:ized|ization)|r?e?drawn|[Vv]ektorisiert) ?(?:by|von)? ?(\{\{U\|(?:[^}]+)\}\})/g, ' {{author|Vectorization|$1}}')

		.replace(/\*\{\{F\|([^\]|[]+?)\|\+\}\} licensed/g, '*{{F|$1|-}} licensed')	// ed_wdh: Original upload log

		.replace(/( *\|source *= *)\* *\{\{F\|([^\}]+?)\}/g, '$1{{Based|$2|by=}')	// ed_wdh: replace F with Based
		.replace(/\[?https:\/\/www\.hdbg\.eu\/gemeinden\/web\/index\.php\/detail\?rschl=([\d]{3,9})\]?/, '{{hdbg|$1}}')

// ========================================  filetruncate
		.replace(/(?:[Dd]erived ?(?:[Ff]rom)?|(?:[Oo]wn)? ?[Bb]ased(?: on)?)\|([^\|\}]+)/, function (m, fn)	
		{
			let fbmp = fn.slice(0, -4);			// fname of raster
			let fbmx = fn.slice(-4);			// exten of raster 
//			if (fbmx.toLowerCase() === ".svg")
//	minorax			return m;						// don't generate Abbr 


			let abbr = "";						// for raster file:
			switch  (fn.slice(-4))				// analize raster extension	
			{	case ".png":	abbr = ".";		break;
				case ".jpg":	abbr = ".j";	break;
				case ".gif":	abbr = ".g";	break;
				case ".tif":	abbr = ".t";	break; 
				case ".xcf":	abbr = ".x";	break;
				case "webp":	abbr = ".w";	break;
				default: 		abbr = fn.slice(-4);	// other extension
			}
			if (fbmp !== fnam)					// compare file names
			{  	for (let i = 1; i < fbmp.length; i++)
  				{	if ( fbmp.substring(i, i+1) === "_")  
 						fbmp = fbmp.substring(0, i) + " " + fbmp.substring(i+1);	// change raster understrokes 
				}
			}
			if (fbmp !== fnam)				// compare again 
				abbr = fbmp + fbmx;			// other file name: not shortened 

//			if (fn.slice(-4) === ".svg")
//				abbbr = fn;					// restore original name (Minorax errer)

			return  "Based|" + abbr;
		}	)


// ========================================  filetruncate

	.replace(/(\n)?\* *derivative work:/, '$1{{Derivative}}:')
// 	.replace(/ *\|author *= *(?:[^\n]+)(?:[^\n]+)/m, function (m) { alert (m);  return m; })
	.replace(/( *\|author *= *)\* *\{\{F\|([^\}]+?)\}\}\:? *(\{\{Un?w?t?\|(?:[^\}]+?)\}\}) *\n? *\*?\/? *\{\{Derivative\}\}\:? *(\{\{Un?w?t?\|(?:[^\}]+?)\}\})/gm, function (m, p1, fn, u1, u2)	// 
		{
			let fbmp = fn.slice(0, -4);			// fname of raster
			let fbmx = fn.slice(-4);			// exten of raster 
			let pix  = '';						// testvarable
			if (fbmx.toLowerCase() === ".svg")
				return m;						// don't generate AutVec 

			let abbr = "";						// for raster file:
			switch  (fn.slice(-4))				// analize raster extension	
			{	case ".png":	abbr = ".";		break;
				case ".jpg":	abbr = ".j";	break;
				case ".gif":	abbr = ".g";	break;
				case ".tif":	abbr = ".t";	break; 
				case ".xcf":	abbr = ".x";	break;
				case "webp":	abbr = ".w";	break;
				default: 		abbr = fn.slice(-4);	// other extension
			}
			if (fbmp !== fnam)					// compare file names
			{  	for (let i = 1; i < fbmp.length; i++)
  				{	if ( fbmp.substring(i, i+1) === "_")  
  						fbmp = fbmp.substring(0, i) + " " + fbmp.substring(0, i);	// change raster understrokes 
				}
			}
				if (fbmp !== fnam)				// compare again 
					abbr = fbmp + fbmx;			// other file name: not shortened 
		
	//	analize user names u1 and u2; remove "U" transclusion (but not e.g. "Ut" ! )
			u1 = u1.trim();
			if (u1.slice(0, 4) === "{{U|")
			{	u1 = u1.slice(0, -2);
				u1 = u1.slice(4);
			}
			if (u1.slice(0, 5) === "{{Un|")
			{	u1 = u1.slice(0, -2);
				u1 = "<>" + u1.slice(5);
			}
	 		u2 = u2.trim();
			if (u2.slice(0, 4) === "{{U|")
			{	u2 = u2.slice(0, -2);
				u2 = u2.slice(4);
			}
			if (u2 === 'Pixelsquid' )
				pix = '🎱';						// //AutVec test maint 
	
			return p1 + "{{AutVec|" + u1 + "|" + u2 + "|" + abbr + "}}" + pix + "\n";
		}	)
// ========================================  
	
			.replace(/\[\[:[Cc]ategory: ?([^\]|[\n]+)(?:\| ?\1 ?)\]\]/g, '{{C|$1}}')
			.replace(/[Aa]uthor=moi même/, 'author=')						// fr:own
			.replace(/=\s*\{?\{?(own)?\}?\}? ?(work|made|after|nach|from)?,? (?:based|basierend|from)? (after|nach|on|off):?/gi, '={{Own based}}')
			.replace(/=\s*\{\{[Oo]wn\}\} ?from /g, '={{Own based}} ')		// ed_wdh (previous did not work); include the file:
			.replace(/=\s*\{\{[Oo]wn\}\} ?from /g, '={{Own based}} ')		// ed_wdh (previous did not work); include the file:
			.replace(/\{\{[Oo]wn\}\}\.? ?[Bb]ased ?(?:on)? ?/g, '{{Own based}} ')	// ed_wdh 
	
			.replace(/\| *[Oo]rig(?:off)? *=([^\]|[\n]+)(?:\}\}|\|)/g, fileTruncate)		// ed_wdh
			.replace(/\{\{ *[Oo]wn based *\|([^\]|[\n]+)(?:\}\}|\|)/g, fileTruncate)		// ed_wdh
		.replace(/\{\{ *[Vv][Vv][Aa] *=([^\]|[\n]+)(?:\}\}|\|)/g, fileTruncate)			// ed_wdh + aliases
		.replace(/\{\{ *[Dd]erived(?: +from)? *\|([^\]|[\n]+)(?:\}\}|\|)/g, fileTruncate)	// ed_wdh
		.replace(/\{\{ *[Ff]ile(?:list)? ?\|([^\]|[\n]+)(?:\}\}|\|)/g, fileTruncate)	// ed_wdh
			
		.replace(/=\s*(?:(?:[Nn]achgezeichnet )?nach|[Bb]ased on|(?:[Rr]edrawn )?after)? (?:Vorlage)?:?\s*\*?\[?(?:\{\{[Nn]gw2\|(?:1|url ?=)?)? ?(?:(?:heraldrywiki\/index\.php\?title=)([\w_ ()]*)|(?:(?:http:\/\/)?www\.ngw\.nl\/?(?:heraldrywiki\/index\.php\?title=([\w_ ()]*)|int\/dld\/\w+\/(?:images\/)?([\w_ ()]*)\.\w{3})?))\}?\}?(?: [\w .]+)?\]?/g, function (m, p1, p2, p3) {
			m = '';
			let l = [p1, p2, p3],
			p = 3,
			r = /\d$/,
			w = '<!--PLEASE CHECK-->';
			while (p--) {
				m += (l[p] || '');
				if (r.test(m)) {
					m = m.replace(r, w);
					w = '';
				}
			}
			if (w && (m.length === 8 || c.wgTitle.toLowerCase().indexOf(m) === -1))
				m += w;
			// never use ngw2 on SVG
			return '={{Ngw3|' + _ucfirst(m) + '}}';
		})
//
//	*** Iterative replacings for:    Attrib;  Legend;  Gallery; 
//  *** but when it is the template {{Attribution}} restore it !
			.replace(/\{\{\s?[Aa]ttrib(?:SVG)? ?\|(?: ?1 ?= ?)?(?:[Ff]ile:|[Ii]mage:)?/g, '{{Attrib|')		// ed_wdh
		// when there are more "Attrib"s, change to "Attribs":			[[[without backreference ! ]]]
					.replace(/(\s*\{\{Attrib\|(?:.*?)\}\})\{\{Attrib\|/gm, '$1@\n{{Attrib|')		//ed_wdh
			.replace(/(\s*\{\{Attrib\|(?:.*?)\}\})[\s ]*\{\{Attrib\|/gm, '$1@\n{{Attrib|')		//ed_wdh
			.replace(/(\s*\{\{Attrib\|(?:.*?)\}\})[\s ]*\{\{Attrib\|/gm, '$1@\n{{Attrib|')		//ed_wdh
 			.replace(/(?:\}\}@[\s ]*\{\{Attrib\|)/gm, '\n |')		//ed_wdh
 			.replace(/(\s*\{\{Attrib)/g, '$1s|t=\n ')				//ed_wdh (all, also singles! - better: only first of queue)
//	*** Assume "coat of arms" (c) - but be aware that it can be as well "map" (m/lm/wm) or another topic			
			.replace(/\{\{Attribs?\|t=\n \|Blason_Vide_3D\.svg\}\}/m, '{{Attrib|t=c|Blason Vide 3D.svg}}')	//ed_wdh aroche
			.replace(/\{\{Attribs?\|t=\n \|(.*?) map([^\|]*?)/g, '{{Attribs|t=m\n |$1 map$2')				// it's a  map
 			.replace(/\{\{Attribs?\|t=m\n \|(.*?)world([^\|]*?)/g, '{{Attribs|t=wm\n |$1 location $2')		// wm/ggg map
 			.replace(/\{\{Attribs?\|t=m\n \|(.*?) location ([^\|]*?)/g, '{{Attribs|t=lm\n |$1 location $2')	// locator map
 			.replace(/\{\{Attribs\|t=(c|lm|wm|m)?\n \|([^\n\}]*?)\}\} *\n/m, '{{Attrib|t=$1|$2}}\n')	//ed_wdh re_singularize	 
 		.replace(/\{\{Attrib(s)?\|t= *([\n\|])/m,  function (m, tm, lf) {
			let topic = '';
			if (!tm)	tm = '';		// undefined ?
			if (/Bandera/.test(txT) && /Escut/.test(txT))
				topic = 'f|f=c';		// flag from coa *?*
			else 
			if (coai || /PD-Coa|coats? of arms|[Ee]scu|:CoA/i.test(txT))
				topic = 'c';
			else 
			if (/[Mm]aps/.test(txT) && /green and grey/i.test(txT))
				topic = 'ggg';
			else 
			if (/[Mm]aps/.test(txT) && /[Ww]orld/.test(txT))
				topic = 'wm';
			else 
			if (/[Mm]aps/.test(txT) && /[Ff]lag/.test(txT))
				topic = 'fm';
			else 
			if (/[: -_]icon/i.test(txT) && /[Ff]lag/.test(txT))
				topic = 'fi';
			else 
			if (/[Mm]aps/.test(txT))
				topic = 'm';
	//		else 
	//		if (/[Ff]ootball/.test(txT) && /line-up/.test(txT))
	//			topic = 'm';
			else 
			if (/Bandera|PD-Flag-|flag/.test(txT))
				topic = 'f';		// |f=c
			return '{{Attrib' + tm + '|t=' + topic + lf; 		//ed_wdh: topic 
		}) 	
		.replace (/\{\{Attribs\|t=\n ution([\|\}])/, '{{Attribution$1') 		// restore erroneously changed name

	
 		.replace(/\{\{ *PD-shape\}\}/g, function (m, txt)
		{	if (/Parliament diagram tool/.test(txT) || /Wpdc/.test(txT))
				return '{{PD-wpdc}}';	//+code.slice(160, 180); 		//ed_wdh: wpdc
			else
				return m;					// PD-shape
		}) 			
 		.replace(/(?:\{\{Using\}\} *)?\[?https:\/\/parliamentdiagram\.toolforge\.org\/parliamentinputform\.html Parliament diagram tool\]?/, '{{Wpdcx}}')
 		.replace(/(?:\{\{(?:[Oo]wn )?[Uu]sing\}\} *)?\[?https:\/\/tools\.wmflabs\.org\/parliamentdiagram\/parliamentinputform\.html Parliament diagram (tool|creator)\]?/, '{{Wpdcx}}')

//		replace(/\{\{self\|cc-zero\}\}/g, function (m, txt)
//		{	if (/Parliament diagram tool/.test(txT) || /Wpdc/.test(txT))
//				return '{{PD-wpdc}}'; 		//ed_wdh: wpdc 
//			else
//				return m;					// self|cc-zero
//		}) 			
 
//  ***  template:Legend (here it is necessary to remove the "1=" independently of the "LAW OF 9/22")
 		.replace(/\{\{ *([Ll])egend(-small|-line| inline|2)? *\| *([^\|]*) *\| *([^\}]*)/g, function (m, cas, typ="", col="", txt="")
		{	if (col.substring(0,2) === "1=")	col = col.substring(2);
			if (txt.substring(0,2) === "2=")	
			{	txt = txt.substring(2);
				for (let i = 0; i < txt.length; i++)
				{	if ( txt.substring(i, i+1) === "=")  
  						txt = txt.substring(0, i) + "&#61;" + txt.substring(i+1);	// replace equal sign
  					if ( txt.substring(i, i+2) === ">=")  
  						txt = txt.substring(0, i) + "≥" + txt.substring(i+2);	// replace  
  	 				if ( txt.substring(i, i+2) === "<=")  
  	 					txt = txt.substring(0, i) + "≤" + txt.substring(i+2);	// replace 
  				}
			}
			return "{{"+cas+"egend" + typ + "|" + col + "|" + txt;				// txt without "="
		})
 
		.replace(/\{[Cc]olorString\|/g, '{Legend|')				//ed_wdh reset
		.replace(/\s*\{\{[Ll]egend\|\|line=/g, '{{Legend-linew|')	//ed_wdh	
//	dw	.replace(/(\s*\{\{[Ll]egend(?:[^\|]*?)\|(?:[^\|]*?)\| *2 *= *[^=]*)=((?:.*?)\}\}(?:[\s ]*)\{\{[Ll]egend)/g, '$1🏮&#61;🏮$2')	//ed_wdh 
//		.replace(/(\s*\{\{[Ll]egend(?:[^\|]*?)\|)(?: *1 *= *)?([^\|]*\|?)(?: *2 *= *)?/g, '$1$2')	//ed_wdh rem. pos. (??=both)
	// border/line: does not work when $2 contains a pipe
		.replace(/(\s*\{\{[Ll]egend *\|(?:.*?)\}\}(?:[\s ]*))\{\{[Ll]egend([\s ]*)\|/gm, '$1✋{{Legend|$2')	//ed_wdh
		.replace(/(\s*\{\{[Ll]egend *\|(?:.*?)\}\}(?:[\s ]*))\{\{[Ll]egend([\s ]*)\|/gm, '$1✋{{Legend|$2') 	//ed_wdh
		.replace(/\|border=transparent\}/gm, '|border=thin solid transparent}')			// complete	  ed_wdh 
		.replace(/\{\{[Ll]egend\|\|([^\|]*)\|line=([^\|\}]+)/gm, '{{legend|$2|$1')					//ed_wdh
		.replace(/\{\{[Ll]egend\|([^\|]*)\|([^\|]*)\|char=([^\|\}]+)/gm, '{{legend|$1 $3|$2')		//ed_wdh
		.replace(/\{\{[Ll]egend\|([^\|]*)\|([^\|]*)\|file=([^\|\}]+)/gm, '{{legend|$1 $3|$2')		//ed_wdh (no space in filename)
		.replace(/\{\{[Ll]egend\|([^\|]*)\|([^\|]*)\|border=([^\|\}]+)/gm, '{{legend|$1 $3|$2')		//ed_wdh
		.replace(/\{\{[Ll]egend\|([^\|]*)\|([^\|]*)\|line=([^\|\}]+)/gm, '{{legend|$1  $3|$2')		//ed_wdh  two spaces !
		.replace(/\{\{[Ll]egend\|([^\|]*)\|([^\|]*)\|striped=([^\|\}]+)/gm, '{{legend|$3)$1|$2')	//ed_wdh
 		.replace(/(?:\}\}([\s ]*)✋\{\{[Ll]egend)/gm, '$1')							//ed_wdh: remove all but 1st
		.replace(/(\s*\{\{[Ll])(?:egend)( *\|)/g, '$1egtab$2')						//ed_wdh (+ singles)
 		.replace(/(\s*\{\{[Ll])(?:egtab)( *\| *\n*(?:[^\|]+)\|(?:[^\{\}\|]+)\}\})/gm, '$1egend$2')	//ed_wdh re_singularize	??? 

	.replace(/(\s*\{\{[Ll]egend-small *\|(?:.*?)\}\})([\s ]*)\{\{[Ll]egend-small([\s ]*)\|/g, '$1☕$2{{Legend-small|$3') //ed_test
	.replace(/(\s*\{\{[Ll]egend-small *\|(?:.*?)\}\})([\s ]*)\{\{[Ll]egend-small([\s ]*)\|/g, '$1☕$2{{Legend-small|$3') //ed_ repeat
	.replace(/(?:\}\}☕([\s ]*)\{\{Legend-small\|)/gm, '$1|')						//ed_wdh
	.replace(/(\s*\{\{[Ll])(?:egend-small *\|)/g, '$1egtab||M|')					//ed_wdh (+ singles)	

	.replace(/(\s*\{\{[Ll]egend-line *\|(?:.*?)\}\})([\s ]*)\{\{[Ll]egend-line([\s ]*)\|/g, '$1♓$2{{Legend-line|$3') //ed_test
	.replace(/(\s*\{\{[Ll]egend-line *\|(?:.*?)\}\})([\s ]*)\{\{[Ll]egend-line([\s ]*)\|/g, '$1♓$2{{Legend-line|$3') //ed_ repeat
	.replace(/(?:\}\}♓([\s ]*)\{\{Legend-line\|)/gm, '$1|')						//ed_wdh
	.replace(/(\s*\{\{[Ll])(?:egend-line *\|)/g, '$1eglin|')					//ed_wdh (+ singles)	

	.replace(/(\s*\{\{[Ll]egend-linew *\|(?:.*?)\}\})([\s ]*)\{\{[Ll]egend-linew([\s ]*)\|/g, '$1♓$2{{Legend-linew|$3') //ed_test
	.replace(/(\s*\{\{[Ll]egend-linew *\|(?:.*?)\}\})([\s ]*)\{\{[Ll]egend-linew([\s ]*)\|/g, '$1♓$2{{Legend-linew|$3') //ed_ repeat
	.replace(/(?:\}\}♓([\s ]*)\{\{Legend-linew\|)/gm, '$1|')					//ed_wdh
	.replace(/(\s*\{\{[Ll])(?:egend-linew *\|)/g, '$1eglin|w=33px|')			//ed_wdh (+ singles)	

	.replace(/(\s*\{\{[Ll]egend inline *\|(?:.*?)\}\})([\s ]*)\{\{[Ll]egend inline([\s ]*)\|/g, '$1⌛$2{{Legend inline|$3') //ed_test
	.replace(/(\s*\{\{[Ll]egend inline *\|(?:.*?)\}\})([\s ]*)\{\{[Ll]egend inline([\s ]*)\|/g, '$1⌛$2{{Legend inline|$3') //ed_test
	.replace(/(?:\}\}⌛([\s ]*)\{\{Legend inline\|)/gm, '$1|')						//ed_wdh
	.replace(/(\s*\{\{[Ll])(?:egend inline *\|)/g, '$1eglin|t=Legend inline|')		//ed_wdh (+ singles)	

	.replace(/(\s*\{\{[Ll]egend2 *\|(?:.*?)\}\})([\s ]*)\{\{[Ll]egend2([\s ]*)\|/g, '$1⛺$2{{Legend2|$3') //ed_test
	.replace(/(\s*\{\{[Ll]egend2 *\|(?:.*?)\}\})([\s ]*)\{\{[Ll]egend2([\s ]*)\|/g, '$1⛺$2{{Legend2|$3') //ed_test
	.replace(/(?:\}\}⛺([\s ]*)\{\{Legend2\|)/gm, '$1|')						//ed_wdh
	.replace(/(\s*\{\{[Ll])(?:egend2 *\|)/g, '$1eglin|t=Legend2|')			//ed_wdh (+ singles)	

	//	.replace(/\{\{en\|1=(\{\{[Ll]eg)/, '$1')							//ed_wdh remove "en|1=" without )) pair
		.replace(/\{\{en\|1=(\{\{leg[^\}]+)\}\}(\}\}\n\|date=)/, '$1$2')	//ed_wdh remove "en|1=" (TapticInfo)

//	*** Set 6-byte-Colorcode to uppercase; when possible, shorten 'rrggbb' to 'rgb'
		.replace(/(#[\dA-Fa-f]{6})(..)/g, function (m, c, o)
		{	let rgb = c.toUpperCase();			//		if (expeUser &&
	//		let o3   = o.toUpperCase();
	//		let o2 = isHexval (o.substring(0,1)) + '.' + isHexval (o.substring(1,2));
			if (rgb.substring(1,2) === rgb.substring(2,3)	// rr
			&&  rgb.substring(3,4) === rgb.substring(4,5)	// gg
			&&  rgb.substring(5,6) === rgb.substring(6,7) 	// bb
			&& !(isHexval(o.substring(0,1)) && isHexval(o.substring(1,2))) // not both hex
			)
				return rgb.substring(0,2) + rgb.substring(3,4) + rgb.substring(5,6) + o;
			else
				return rgb + o;		// uppercase only
		})	// 8-byte-Colorcode to uppercase:

			.replace(/([^{])[Dd]erivative[ _]versions?[ _]?(?!of):?([^s}]?)/, '$1{{Derivative versions}}$2') // TODO: parameter as filenames
			.replace(/([^{]?)[Dd]erivative[ _]work(?![ _]of)(:?)([^s}]?)/, '$1{{Derivative}}$2$3') // TEST
			.replace(/[Ss]ource( +)?=( +)?\{\{\w\w\|(?:1=)?([^|\]]+)([| ])(?:Vorlage|Template)(\]\]?)?\s*\}\}/, 'source$1=$2$3$4{{Template-ns}}$5')
//	*** gallery treating
		.replace (/(?:\n?)<[Gg]allery>([\w\s]+?)<\/[Gg]allery>/gm, '{{G|$1}}☕') 	// ed_wdh
		// 		.replace (/<[Gg]allery>([\n\s\w]+?)<\/[Gg]allery>/gm, '{{H|$1}}') 			// ed_wdh   dmy template
		//		.replace (/<[Gg]allery>(?:[^\n]+?)(\n.+)<\/[Gg]allery>/gm, '{{J|$1}}') 		// ed_wdh
		//	.replace (/<[Gg]allery>(.*?)<\/[Gg]allery>/gm, '{{X|$1}}') 				// ed_wdh ⓵⓶⓷⓸
		// 	.replace (/<[Gg]allery>([\n.]+?)<\/[Gg]allery>/gm, '{{Y|$1}}⌛')			// ed_wdh
//  *** single item 
		.replace(/(?:\n?)<Gallery>\s*(?:File\:|Image\:)?([^\n|]+)(\|?[^\n]+)?\s*<\/Gallery>(?:\n?)/ig, '{{G|\n$1$2}}\n') // ed_wdh test	
		.replace(/\{\{G\|\n([^\n\}]+?)\}\}/gm, '{{G|$1}}') 						// ed_wdh: single item gallery only one line
//		.replace(/(?:\n?)<[Gg]allery>\s*(?:[Ff]ile\:|[Ii]mage\:)?([^\n|]+)(\|?[^\n]+)?\s*<\/[Gg]allery>(?:\n?)/g, '{{G|\n$1$2}}⓵\n') // ed_wdh test	

//  *** multiple items 
		.replace (/<[Gg]allery>\n?([^<]*?)\n?<\/[Gg]allery>/gm, '{{G|\n$1}}') 			// ed_wdh: multiple lines
//		.replace (/<[Gg]allery>([^<]*?)\n?<\/[Gg]allery>/gm, '{{G|$1}}') 			// ed_wdh: multiple lines


	//?	.replace   ( /\[\[[Uu]ser:(.*?)(\|[^\]|[]+)?\]\]/g, '{{U|$1}}')		// ed_wdh test ????
//	*** Try to sort the parameters: date - source - author
	//				dsa✓	das		sda		sad		ads		asd	
	//	as			 		dsa✓	 		  		 		sad	
	//	ad			 		 		 		sda		das		sda	
	//	as			 		 		 		 		dsa✓	 	
	//	sd			 		 		dsa✓	dsa✓			dsa✓	
		.replace (/( *\| *[Aa]uthor(?:.*))\n( *\| *[Ss]ource(?:.*))\n/, '$2\n$1\n' ) // ed_wdh sort: as 
		.replace (/( *\| *[Aa]uthor(?:.*))\n( *\| *[Dd]ate(?:.*))\n/,   '$2\n$1\n' ) // ed_wdh sort: ad  
		.replace (/( *\| *[Ss]ource(?:.*))\n\n?( *\| *[Dd]ate(?:.*))\n/,'$2\n$1\n' ) // ed_wdh sort: sd 		
			
			.replace (/\{\{self-photographed\}\}/, '{{Own}}')				// Aliman
			.replace (/\(\[\[Switzerland\]\]\)/, '({{W|Switzerland}})')		// Aliman
			.replace (/SVG is own work/, '{{Own}}')						// D'Arch
			
	//??		.replace(/\|s\=-COAInformation/, '|s=c')		              	// ed_wdh ???
		.replace(/https:\/\/armorialdefrance\.fr\/page_blason\.php\?ville=(\d+)/, '{{Page blason|$1}}')			// ed_wdh
		.replace(/\[https?:\/\/www\.newgaso\.fr\/lecture([^\]]*)\]/, 'http://www.newgaso.fr/lecture$1')			// ed_wdh [_]		
		.replace(/https?:\/\/www\.newgaso\.fr\/lecture[ _]fiche[ _]commune\.php3\?page=(f\d+)/, '{{Fiche commune|$1}}')	// ed_wdh		

		.replace(/^ *\|\s*[Pp]ermission\s*= *(?:\[\])? *\n( *[\|\}])/m, '$1')			// ed_wdh remove empty permission param up
		.replace(/^ *\|\s*[Pp]ermission\s*= *[Pp]ublic domain *\n( *[\|\}])/m, '$1')	// ed_wdh remove obsolete permission
		.replace(/^ *\|\s*[Pp]ermission\s*= *(?:[Oo]wn work,?)? *(?:all rights released)? *(?:\(?Public domain\)?)? *\n( *[\|\}])/, '$1')	// ed_wdh rem

//	*** AutVec([[Switzerland]])
			
			.replace(/Original:? ([^\n|<]+)(?:<br ?\/?>)?\s*(?:SVG:? )(\[\[[\w:]*User:[^\n|[\]]+(?:\|[^\n|[\]]+)?\]\])/i, '{{AutVec|o=$1|v=$2}}');	// semicolon here
	//	?	.replace(/=\s*\{\{AutVec ?\|\s*(?:o=)?(?:(?:\{\{Uc?\|[^\}]+)(?:\}\})|[^\}\|]*)?\|(?:v=)?(?:(?:\{\{Uc?\|[^\}]+)(?:\}\})|[^\}\|]*)?\|([^\]|[\n]+)(?:\}\}|\|)/g, fileTruncate);
		}	// ========================================= end	function generalCleanup	

		// COAInformation has special parameter ¿imgen/image? so warn if present
		if ( (coai && imgenRE.test(txT)) || /\{\{[Ii]genc/.test(txT)) {
			cSVG.warnMsg({
				title: 'Coa already present, ' + (err ? 'there ' + ((err === 1) ? 'is 1 error' : 'are ' + err + ' errors') : 'file is valid') + '!',
				type: 'warn'		//					
			});
 				if (/[st]\=sf|[st]\=eq/.test(txT)) {
 					LeyoChem = 1;	// use FGD  773
 				} 
		}
	/* more test:
		if ( imageRE.test(txT)) {
			cSVG.warnMsg({
				title: 'Image= presenT !',
				type: 'warn'
			});
		}
		if ( imgenRE.test(txt)) {
			cSVG.warnMsg({
				title: 'Imgen= present !',
				type: 'warn'
			});
		}
		if ( imgenRE.test(txT)) {
			cSVG.warnMsg({
				title: 'Imgen= presenT !',
				type: 'warn'
			});
			txt = txt.replace(/( *\| *[Ii]m)(?:gen|ag)?( *= *)/, '$1age$2');		//	pre_normalize [im, imag, imgen]
		}
		if ( imgenRE.test(txt)) {
			cSVG.warnMsg({
				title: 'Imgen= present !',
				type: 'warn'
			});
		}
	*/
 	// SVG Template and cosmetic replace:  all graphic labs, replace later in cleanup.js
		txt = txt /* Other SVG related templates (for T), currently only working for sure if they are on a single line */
			.replace(/\s?(\{\{\s?(\w+werkstatt|[Gg]raphic[ _][Ll]ab|[Ww]PGW[ _]vector[ _]im|[Tt]HV|[Aa]telier[ _]graphique|[Ll]aboratorio[ _]grafico|[Tt][\s_\w]+Cartografía|[Pp]rojet[ _]Blasons)[^\|\n\}]*\}\})\s?/g, function (m, p) {
				T += p;				return '';
			})
			.replace(/(\{\{(TracedSVG|Autotraced|Bad[ _]trace|PoorSVG)\}\})\s?/i, function (m, p) {
				p5 = '|§';
				return '';
			}) // PoorSVG
			.replace(/\{\{\s?Bad[ _]?SVG\s?\}\}\s?/i, function (/* m, p*/) {
				p5 = '|!';
				return '';
			}) // BadSVG
			.replace(/\{\{\s?[Ee]asy[ _-]?border(?:\s?\|\s?([^\n]+))?\s?\}\}\s?/, function (m, p) {
				p5 += '|°';
				s = p || s;
				return '';
			}) // Easy-border
	//	tr	.replace(/(\{\{([Tt]ranslat(?:e|able|ion possible)|[Ee]asy translation)[^\\n}]*}})\s?/, function () {
			.replace(/(\{\{([Tt]ranslat(?:able|ion possible)|[Ee]asy translation)[^\\n}]*}})\s?/, function () {
				p5 += '|%';
				return '';
			})
			.replace(/\{\{\s?([Ss]uper[cs]eded(?:-Image)|(?:[Rr]aster|PNG|Bitmap)(?:[ _]version)?(?:[ _]available)|[Oo]bsolete)(?:\s?\|\s?([^\n]+))?\s?\}\}\s?/, function (m, p, p2) {
				p5 += '|\\' + (p2 ? '=' + p2 : '');
				return '';
			}) // Superseded
	//		.replace(/\{\{\s?([Ss]uper[cs]edes)(?:\s?\|\s?([^\n]+))?\s?\}\}\s?/, function (m, p, p2) {
			.replace(/\{\{\s?([Ss]uper[cs]edes)(?:\s?\|\s?(?:1=)?([^\n]+))?\s?\}\}\s?/, function (m, p, p2) {
				p5 += '|\\+=' + p2;
				return '';
			}) // Supersedes
			.replace(/\{\{\s?([Cc]ommonist)(?: no icon)?(?:\s?\|\s?([^\n]+))?\s?\}\}\s?/, function () {
				p5 += '|$';
				return '';
			}) // Commonist (works not properly}

			.replace(/\{\{[Rr]etouched(?:[Pp]icture)?\|[^\.]+\. Vector(?:ed|ized)[^\n]+/, '')		// remove => AutVec
			.replace(/(?:\{\{(?:[Rr]etouched[ _]?(?:[Pp]icture|[Ii]mage)?|[Rr]estored|[Mm]odified)([^}\n]+\}\}))/, function (m, p) {
				T += '{{retouched' + p;		// 1st create "T= ", later make it with "|r="; variable 'p' contains all the parameters
				return '';
			})
			.replace(/\{\{\s?(in)?valid[ _]?(SVG)?[^}]*\}\}\s?/ig, '') // remove SVG validity templates
			.replace(/\[\[\Category:ChemSketch\]\]\s?/ig, '')               		// ed_wdh  
			.replace(/\[\[\Category:Created with Inkscape\]\]\s?/ig, '')			// ed_wdh 2nd
			.replace(/\{\{[Hh]andSVG\}\}\s?\n/ig, '') 		// remove (creted with ...)
			
			.replace(/^ *\|\s*[Pp]ermission\s*= *\n( *[\|\}])/m, '$1')			// ed_wdh remove empty permission param
			.replace(/^ *\|\s*[Oo]ther[ _]versions\s*= *\n*( *[\|\}])/m, '$1')	// ed_wdh remove empty other_versions param
			.replace(/^\s*\}\}\s*$/gm, '}}\n'); 		// trim on every separate temp end

		/* Search SVG templates for tool-name and remove them */
		if (size) {
			txt = txt.replace(/\{\{\s?[Ss]implSVG\|([^{}|]+)\|[^}]+\}\}\s*/ig, function (m, p) {
					toolName = p;
					return '\n';
				});
		}
		txt = txt.replace(/\{\{(Inkscape(-hand)?|Adobe([ _]Illustrator|-hand)?|Illustrator|Gnuplot|CorelDraw)\|?[^{}]*\}\}\s?/i,
				function (m, p, p2) {
				if (p2)
					toolName = /[Aa]dobe-hand$/m.test(p2) ? 'AH' : 'H';
				else
					toolName = p;
				replaced = 1;
				if (/code ?=/.test(m))
					T += m;
				else if (p === 'Inkscape' && /IMPORTANT=yes/.test(m))
					toolName = 'Im';
				return '\n';
			} // replace success
			);
		if (!replaced) { // search Created with ... templates
			txt = txt.replace(/\{\{[Cc]reated with ([^{}|]+)\|?([^{}]*)\}\}\s?/, function (m, p, p2) {
					toolName = p;
					replaced = 1;
					if (/code/.test(p2.slice(0,6)))	// " code "	?
						p5 += '|' + p2;				// T += m;			T T T T T
					return '\n';
				} // replace success
				);
			if (!replaced) { // TODO: search redirects to Created with ... templates
				txt = txt.replace(/\{\{(QGIS|[Ll]ibreOffice|[Oo]penOffice(?:\.org)?|MATLAB|[Gg]numeric|[Mm]athematica)\|?[^{}]*\}\}\s*/,
						function (m, p) {
						toolName = p || toolName;
						replaced = 1;
						return '\n';
					});
				if (!replaced) { // replace previous igen
 					if (/[st]\=sf|[st]\=eq/.test(txT)) {
 						LeyoChem = 1;	// use FGD
 					} 
					// FIXME: don't replace fully
					
					txt = txt.replace(/(\s)?\{\{[Ii](gen|mage[ _]generation)\|([\w ]*)?\|?[^{}]*\}\}\1?/,
							function (m, s, i, p) {
							if (i.length > 4)
								IgenName = IgenNameLong;
							toolName = p || toolName;
							replaced = 1;
							return /code ?=/.test(m) ? m : '\n';
						} // replace success
						);
					if (!replaced) { // replace completely previous FGD   ed_wdh
						if (/structural formula|chemical equation/i.test(txT)) {
							LeyoChem = 1;	// use FGD
						} 
						txt = txt.replace(/\{\{File generation description((?:[^\}]{2})+\}\}\n)/m, '');
					}
				}
			}
		}
		toolName = toolname || toolName;	// "toolname" from SVG code  has priority over "toolName" from file desc
											// (this inhibits tool specification if is later e.g. inkscaped)
		/* Exclude nowiki text with split */
		let nowiki = txt.split('<nowiki>'), // TODO: Works only on non nested (may be sufficient)
		wikiTxt = [nowiki.shift()];
		if (nowiki.length) {
			for (let n = 0; n < nowiki.length; n++) {
				let nClose = nowiki[n].split('<\/nowiki>');
				if (nClose.length > 1) {
					nowiki[n] = '<nowiki>' + nClose.shift() + '<\/nowiki>';
					wikiTxt.push(nClose.join());
				} else {
					wikiTxt[n - 1] += nowiki.splice(n, 1);
				}
				// console.log(n, nowiki[n])
			}
		}
		txt = ''; // clear

		for (let wt in wikiTxt)
			txt += generalCleanup(wikiTxt[wt]) + (nowiki[wt] || '');

		txT += c.wgTitle;
		/* Search for sub suffix parameter */
		if (/openclipart/.test(txT)) {
			s = 'oc';	// :openclipart
		} else if (/text[: -_]?logo/i.test(txT)) {
	//		this.textTrans = 0; // Logos don't get translated
			this.textLogo  = 1; 
			s = 'tl';	// :textlogo
			p5 = p5.replace(/\|%/, '');		// tl not translateable para.textLogo = 0;
		} else if (/blazon|våben/i.test(txT) || /COAInf/.test(txT) || /raldic/.test(txT)) {
			s = 'c'; // :CoA 
		} else if (/seal/i.test(txT)) {
			s = 's';	// :seal
		} else if (/logos? of |:logos?/i.test(txT)) {
			s = 'l';	// :Logos
		} else if (/maps/i.test(txT) && /green and grey/i.test(txT)) {			
			s = 'ggg';	// :green and gray world maps
		} else if (/maps/i.test(txT) && /World war/i.test(txT)) {			
			s = 'm';	//  :maps (not wm})
		} else if (/Natural Earth/.test(txT)) {
			s = 'm|w=Natural Earth map|>';	// :Natural Earth map		// multi_error SVG 
		} else if (/maps/i.test(txT) && /globe|earth|world|monde|mondial/i.test(txT)) {			
			s = 'wm';	// :World maps
		} else if (/maps/i.test(txT) && /Localisation|Locator|location /i.test(txT)) {
			s = 'lm';	// :locator maps
		} else if (/DescrMapComuneItaly/.test(txT)) {
			s = 'lm';	// :italian locator maps
		} else if (/maps/i.test(txT) && /flag/i.test(txT)) {
			s = 'fm';	// :flag maps
		} else if (/maps/i.test(txT)) {			
			s = 'm';	// :Maps
		} else if (/Military map symbol/.test(txT) && /CdnMCG/.test(txT)) {			
			s = '|s:=Military map symbol|U=CdnMCG';	// :mmy 
		} else if (/Military map symbol/.test(txT)) {			
			s = '|s:=Military map symbol';			// :mmy ( |s=|s:= )
		} else if (/pictogram/i.test(txT)) {			
			s = 'p';	// :SVG sports pictograms
		} else if (/[: -_]icon/i.test(txT) && /[Ff]lag/.test(txT)) {
			s = 'fi';	// :flag icons
//		} else if (/Chess/i.test(txT)) {
//			s = 'chesspiece'; // :user:Churnett/Chess				*** temporar ***
		} else if (/[: -_]icon/i.test(txT) && /Noun Project/.test(txT)) {
			s = 'npi';	// :flag icons
		} else if (/OOUI icons/.test(txT)) {
			s = 'OOUI'; // :icons
		} else if (/BSicon/.test(txT) || /Icons for riverfloat/.test(txT)) {
			s = 'bi';	// :BSicons
		} else if (/[: -_]icon/i.test(txT) && /coats of arms/i.test(txT)) {
			s = 'c';	// :Coa
		} else if (/[: -_]icon/i.test(txT)) {
			s = 'i';	// :Icons
		} else if (/Bandi?era/i.test(txT) || /Drapeau/.test(txt) || /Category:Flags/.test(txT)) {
			s = 'f';	// :Flags
		} else if (/japanese crest/i.test(txT)) {
			s = 'jc';	// :jap.crest
		} else if (coai) {
			s = 'c';	// :CoA
		} else if (/PD-Coa|coats? of arms|escu|:CoA|heraldic/i.test(txT)) {
			s = 'c';	// :CoA / ecclesiastical heraldry
		} else if (/fin flash/i.test(txT) && (this.curSize < 2000)) {
			s = 'fin flash'; // :f flash, 
			stxt = '|s:=';
//		} else if (/fin flash/i.test(txT) && (toolName === 'Text Editor')) {
//			s = 'fin flash';	// :f flash, 
//			stxt = '|s:=';
		} else if (/Insignia|Identification badge|Emblem|uniforms/i.test(txT)) {
			s = 'em';	// :Emblems
		} else if (/PD-chem|BKchem|ChemDraw|Chemtool|ChemSketch|GChemPaint|N2S|dvisvgm|Chemical structure|Drug synthes|reactio/i.test(txT)) {
			LeyoChem = 1;					// use FGD (unsure whether "reactio" should trigger) |stru[ck]tur|
			s = 'sf';						// :Structural formulas
		} else if (/Igen\|[B|C]|Image generation\|[B|C]/i.test(txT)) {
			LeyoChem = 1;					// use FGD when old version abbreviation B=BKchem or C=ChemDraw (or User:#11)
			s = 'sf';	// :Structural formulas
		//			IgenName = IgenNameLong;						// for Leyo
		} else if (/Ribbon bar|Order /i.test(txT)) {
			s = 'o';	// :Orders
		} else if (/ signs|[Rr]oad [Ss]ign\]/.test(txT)) {
			s = 'v';	// :Signs {when category}
		} else if (/\[Category\:Signature/.test(txT)) {
			s = 'sig';	// :Signatures (even when 'letter')
		} else if (/Unicode|alphabet|letter/i.test(txT)) {
			s = 'u';	// :Unicode
		} else if (/Symbol/i.test(txT) && !/flags/i.test(txT)) {
			s = 'y';	// :Symbols
		} else if (/Mathematic|Algorit|Trigonometry|Geometry|Isometric/i.test(txT)) {
			s = 't';	// :Trigonometry 
		} else if (/ route marker/.test(txT)) {
			s = 'v';	// :Signs
		} else if (/Diagram/i.test(txT) && !/parliament/i.test(txT)) {     // ed_wdh 
			s = 'd';	// :Diagrams
		} else if (/PD-Flag-|flag|Флаг/i.test(txT)) {
			s = 'f';	// :Flags
		} else if (/Football/i.test(txT) && /line-up/.test(txT)) {
			s = 'm|sd=/line-up'; // :line ups
		} else if (/Football/i.test(txT)) {
			s = 'fk';	// :Football kits
		} else if (LeyoChem) {
 			s = 'sf';	// :Structural formulas
		} else if (/ex[ae]mpe?l/i.test(txT)) {
			s = 'ex';	// :Example (exempel)
		} else if (/highway/i.test(txT)) {			
			s = 'm';	// :Maps
		} else if (/Autogra/i.test(txT)) {
			s = 'sig';	// :Signatures
		} else if (/Signatur/i.test(txT) && !/signature-talk/i.test(txT)) {
			s = 'sig';	// :Signatures                          // 'sig' comes too often
		}  else if (/barnstar/i.test(txT)) {
			s = 'bs';	// :Barnstars         
		} else if (/Monogram/i.test(txT)) {
			s = 'rm';	// :Royal monogram
		}

// change PD-chem for all chemical equations
		if (LeyoChem) 
		{	txt = txt.replace(/\{\{self\|[Cc]c-by-sa-4\.0\}\}/, '{{PD-chem}}');	//t=sf~eq
			txt = txt.replace(/\{\{self\|[Cc]c-zero\}\}/, '{{PD-chem|t=sf}}');	//
			txt = txt.replace(/\{\{PD-self\}\}/, '{{PD-chem}}');
		}
		if (/Topic = chemical equation|\|[st]=eq[\|\}]/.test(txT))		//s* C{{int:license-header}} ==\n{{PD-self}}
		{	txt = txt.replace(/\{\{PD-chem(?:\|s=eq)?\}\}(?:\|[st]=eq[\|\}])?/, "{{PD-chem|t=eq}}"); // -helper "|s=eq}"
			s = 'eq';			// repair afterwards to "chemical equation"  
		}
		if (/\{\{PD-chem(?:\|[st]=eq)?\}\}/.test(txT))
			txt = txt.replace(/\n?== *\{\{int:license-header\}\} *==\n\{\{PD-self\}\}/, '');	// remove

	//	if  (s === 'm' && /globe|earth|world|monde|mondial/i.test(txT))
	//		s = 'wm';									// world maps
	//	if  (s === 'm' && /Locator|location /i.test(txT))
	//		s = 'lm';									// locat maps
	//	// topic with UserID (only special users)   	// ed_wdh if
	
		if (s === 'wm' && /Hagar66/.test(txT) && toolName === 'Adobe')	
			s = 'wm|U=Hagar66';							// Hagar world maps (precedence over TUBS!)
		if (s === 'wm' && /NordNordWest/.test(txT))
			s = 'wm|u=NordNordWest';					// NordNordWest world maps (precedence over TUBS, but not over Hagar)
		if (s === 'wm' && /TUBS/.test(txT))	  
			s = 'wm|u=TUBS';							// TUBS world maps

		if (/Hagar66/.test(txT) && s === 'lm' && toolName === 'Adobe')	
			s = 'lm|U=Hagar66';							// Hagar location maps (precedence over TUBS)
		if  (/NordNordWest/.test(txT) && s === 'lm')
			s = 'lm|u=NordNordWest';					// NordNordWest location maps (precedence over TUBS, but not over Hagar)
		if  (/TUBS/.test(txT) && s === 'lm')	  
			s = 'lm|u=TUBS';							// TUBS location maps
	if  (/TUBS/.test(txT) && s === 'lm|u=TUBS' && /Latvia/.test(txT))	  
			s += '|sd=-Latvia';							// TUBS location maps **temp** for all regional subcats
	if  (s === 'lm|u=NordNordWest' && /Lettland 2/.test(txT))	  
			s += '|sd=-Latvia';							// TUBS location maps **temp** for all regional subcats

		if (/Hagar66/.test(txT) && s === 'm' && toolName === 'Adobe')		// PGFauthor	
			s = 'm|U=Hagar66';						// Hagars maps (precedence over TUBS)
		if  (/NordNordWest/.test(txT) && s === 'm')	// (/NordNordWest/.test(txT) && s === 'm')  
			s = 'm|u=NordNordWest';					// NordNordWest maps (precedence over TUBS)
		if  (/TUBS/.test(txT) && s === 'm')			// (/TUBS/.test(txT) && s === 'm' && toolName === 'Adobe')  
			s = 'm|u=TUBS';							// TUBS maps
	//	if (/Hagar66/.test(txT) && (s === 'm' || s === 'm|u=TUBS'))	
	//		s = 'm|U=Hagar66';						// Hagars maps (replacing TUBS)
		if  (/Locator|Location maps/i.test(txT) && s === 'm')
			s = 'lm';								// location maps
		if (/Petrus3743/.test(txT)  && s === 't')	// && toolName === 'GeoGebra'
			s = 't|u=Petrus3743|<v';				// Petrus_trigonometry	✔
		if (/\[\[User\:Cdang\|Cdang\]\]/i.test(txT) || /\{\{U\|Cdang\}\}/i.test(txT))	// Cdang ?
			s += '|u=cdang';						// cdang ✔
//		if  (s === 's' && /SVG - Seals of the United States/.test(txT) )
//			s += '|sd=(US)';						// **temp**
			
		// default: "Unknown tool" (but can also be Text Editor)	SVG - Seals of the United States
		toolName = _ucfirst(toolName) || ((this.curSize && this.curSize > 50 && this.curSize < 2000) ? 'T' : 'U');
		toolName = toolNames[toolName] ? toolNames[toolName] : toolName;
		if (expeUser)
			toolName = toolAbbr[toolName] ? toolAbbr[toolName] : toolName;

		// Graphic Lab replace: Map Lab	🐞🐞🐞🐞🐞🐞 this buggy procedure is disabled 🐞🐞🐞🐞🐞🐞
		if (T) {
			T = T.replace(/\{\{Grafikwerkstatt🐜\}\}/, function (/* m*/) {
	//	ed_			g = 'de';
					gd;
					return '';
				});

			if (T && !g) {
				T = T.replace(/\{\{[Tt]aller🐜[ _]de[ _]Cartografía\}\}/, function (m, p) {
	//	ed_				g = 'es';
						ge;
						s = (p && !s) ? 'm' : s;
						return '';
					});
			}
			if (T && !g) {
				T = T.replace(/\{\{[Aa]telier🐜[ _]graphique([ _]carte)?\}\}/, function (m, p) 
	//	ed_				g = 'fr';
					{	gf;
						s = (p && !s) ? 'm' : s;
						return '';
					});
			}
			if (T && !g) {
				T = T.replace(/\{\{[Ll]aboratorio🐜[ _]grafico([ _]mappa)?\}\}/, function (m, p) 
	//	ed_				g = 'it';
					{	gi;
						s = (p && !s) ? 'm' : s;
						return '';
					});
			}
			if (T && !g) 
			{	T = T.replace(/\{\{\s*[Gg]raphic[ _][Ll]ab\s*\|\s*([\w-]+)\|?(map|[^{}]*)?\}\}/, function (m, p1, p)
	//	ed_			g = p1;
					{	gP;
						s = (p && !s) ? 'm' : s;
						return '';
					});
			}
			if (T && !g) 
			{	T = T.replace(/\{\{WPGW🐜 vector image\}\}/, function (m, p1, p) 
					{	gP;
						s = (p && !s) ? 'm' : s;
						return '';
					});
			}
			g = g ? '|g=' + g : '';

	//		put $1 (modifications) into '|r', $2 contains all the other parameters		
			if (/\{\{retouched\|([^|}\n]*)\|?([^}\n]+)\}\}/.test(T)) 				// TODO: filename can't contain "}"
			{	r = '|r=' + (RegExp.$1 || '-🎨-') + '|' + (RegExp.$2 || '');		// 🎨 for removing useless "r=-"
				T = T.replace(RegExp.lastMatch, '');								// FIXME: non standard
			}
			T = (T.length > 4) ? '|T=' + T : '';
		}

		// Cleanup remnants
		txt = txt.replace(/\{\{\s?[Ii]n(formation[ _]field|Fi)\|[^{}\n|]+\|\s?value\s?=(\s*\}\})?\s*/g, ''); // empty field
		if (s === 'm')
			txt = txt.replace('<!--PLEASE CHECK, not generally for all SVG maps-->', '');

		/** *
		 * Get lastIndex, from now, NO text manipulation anymore, or var topp must be fixed
		 ***/
		if (!ofRE.test(txt)) 										// no orevious igen
		{	let i = inRE.length;
			while (i--) { // iter over possible positions
				if ((topp = new RegExp(inRE[i], 'g')).test(txt)) 
				{	topp = _findPosition(topp);
					i = 0;
					break;
				} else
					topp = 0;
			}
		} else 
		{	topp = ofRE.lastIndex;
			if (!(coai && imageRE.test(txt)))  
			{	txt = txt.replace(ofRE, '');		// $1 $2 $3 (but not when "image")
				topp -= RegExp.lastMatch.length;
				ls = RegExp.$3;						// or
			}
		}
		s1 = s1 || RegExp.$1;
		s2 = s2 || RegExp.$2;
//		s1 = s1.slice(0, 1);			// elminate strange error ?

		if (coai && /[Ii]mage\|/.test(ls)) 		// CoA but without COAInformation
			{	IgenName = s1 + '|imag-' + s2 + '=' + s2;	// test  + ' °°°'
				tempPre = '';
			} 
		else if (/\{\{ *[Ii]nform?\s*\|\s*/.test(txT)) 			//  Info/var
			{	imag = '|imAge';
				if (/[Ii]nform?\s*\|\s*desc\s*=/.test(txT))
					imag = '|imag';										// param length as "description"
				if (/[Ii]nform?\s*\|\s*de\s*=/.test(txT))
					imag = '|im';
				IgenName = s1 + imag + s2 + '=' + s2 + IgenName;		// + ls (later)	
			}
		 else if (!topp && /\}\}/g.test(txt)) 
			{	topp = txt.lastIndexOf(tempPre) + 3;	// put on last postion of a template
			} 
		else 
			{
	//			IgenName = s1 + '|other fields' + s2 + '=' + s2 + IgenName;	//  Info/var
				IgenName = s1 + IgenParm + '=' + IgenName;			// without the spaces
			}

		if (this.switchTrans && (myName === 'Sarang'))		// langtst
	//		if (/( )*\|\s*[Oo]ther[_ ]versions( )*= *[^\n]*\n/.test(txT))
	//			txt = txt.replace(/( )*\|\s*[Oo]ther[_ ]versions( )*= *[^\n]*\n/, '$1|other versions$2={{' + syslang(code) + '')}}\n');
	//		else
				tempPre = tempPre + syslang ();			//  Test
		//		tempPre = tempPre + '%%';				//  Test


		if (typeof err === 'number')
		{	if (!topp) 
			{	this.setIgen(IgenName += (toolName || '×?×') + (err ? '|' + err.toString() : '') + '|+|s=' + s, tempPre);
				return '';
			}
		} else if (typeof err === 'undefined') {
			return txt; // don't insert igen
		}

		// Parameter 5
		if (this.badSVG) 
		{	if (!/^\|!/.test(p5))
				p5 += '|!';
			if (this.badSVG === 2)
				p5 += '=f'; // Fake SVG
			if (this.badSVG === 3)
				p5 += '=x'; // Fake SVG with text
	//		if (this.badSVG > 1 && /Smokefoot/.test(txT))
	//			p5 += '|u=Smokefoot'; // Fake SVG **temp**
			if (expeUser && s === 'm' && this.badSVG < 2) 
				p5 += '=t'; // may be TOPO SVG
			else if (!expeUser && s !== 'm')
				p5 += '<!--PLEASE CHECK, not generally for all graphic types-->'; // Maybe
		}
		if (this.curSize > 3407872)			// 3407872 = 3.4M; 4194304 = 4M
			p5 += '|>'; // Large SVG 4 MB? 3.4 MB?
		if ((this.textPath) || /with non-modifiable/.test(txT))			// Zoofari's
			p5 += '|<'; // "less" sign to insert the {Path text SVG} tag.
		if (this.flowRoot)
			p5 += '|?x'; // "q_mark" sign for flowRoot
		else if (this.switchTrans) 
			p5 = p5.replace(/\|%/, '') + '|%s';
		if (this.PGF)							// table processing would be better
		{	if (/Hagar66/.test(txT))
				p5 += '|~U=' + 'Hagar66';		//
			else
			if (/NordNordWest/.test(txT))
				p5 += '|~u=' + 'NordNordWest';	//
			else
			if (/TUBS/.test(txT))
				p5 += '|~u=' + 'TUBS';			//
			else
				p5 += '|~'; // "squiggle" sign for PGF CDATA
		}

 	 	else if (this.timestamp)
	  		p5 += '|%w';					// or '|%|%w'
		else if (this.textTrans && !/\|%/.test(p5) && toolName !== 'Wpdc')			//ed_wdh (after code)
		{	if (this.textLogo)					
				p5 += '|%v';				// smallest display		
			else
				p5 += '|%r';				// reduced display		
		}
		else if (/Impru20/.test(txT) && toolName === 'Wpdc')			//ed_wdh Impru
			p5 += '|sub=/Impru';			//		
								// other tags
	 	if	(Otagtab.bf)		p5 += '|bf';	// Broken file
		if	(Otagtab.bl)		p5 += '|bl';
		if	(Otagtab.ci)		p5 += '|ci';
		if	(Otagtab.dm)		p5 += '|dm';
		if	(Otagtab.ff)		p5 += '|ff';
		if	(Otagtab.fi)		p5 += '|fi';
	//	if	(Otagtab.fw)		p5 += '|fw';	// Fotowerkstatt		??fw??
		if	(Otagtab.lh)		p5 += '|lh';
		if	(Otagtab.ni)		p5 += '|ni';	//	|←
		if	(Otagtab.nu)		p5 += '|nu';
		if	(Otagtab.oq)		p5 += '|oq';
		if	(Otagtab.ov)		p5 += '|ov';
		if	(Otagtab.re)		p5 += '|re';
		if	(Otagtab.rs)		p5 += '|rs';
		if	(Otagtab.tr)		p5 += '|tr';
		if	(Otagtab.tw)		p5 += '|tw';	// Taken with ...
		if	(Otagtab.up)		p5 += '|up';
		if	(Otagtab.zf)		p5 += '|zf';

		if	(Fwrktab.fwc || Fwrktab.fwe || Fwrktab.fwo || Fwrktab.fwl || Fwrktab.fwt)
			{	if	(Fwrktab.fwc)	p5 += '|fwc='+Fwrktab.fwc;	
				if	(Fwrktab.fwe)	p5 += '|fwe='+Fwrktab.fwe;			
				if	(Fwrktab.fwo)	p5 += '|fwo='+Fwrktab.fwo;			
				if	(Fwrktab.fwl)	p5 += '|fwl='+Fwrktab.fwl;			
				if	(Fwrktab.fwt)	p5 += '|fwt='+Fwrktab.fwt;			
				if	(Fwrktab.fws)	p5 += '|fws='+Fwrktab.fws;			
			}
		else	if	(Otagtab.fw)	p5 += '|fw';	// Fotowerkstatt		??fw??

//		p5 += Otagtab.zf ? '~zf~' : '';  test
//		p5 += Otagtab.ov ? '~ov~' : '';
	
		T = p5 + r + T;

		if (/parliament/i.test(txT)) 
		{	s = '';										// not "d"
			stxt = '';	}								// not "|s="	
		if (topp) 
		{	err = Number(err);
			if (size) 
				IgenName += toolName + '|' + size + '|9=+|10=S|user=' + c.wgUserName + '|4=' + s + T;
			else
			 	IgenName += toolName + (err ? '|' + err : '') + '|+' + g + T + stxt + s;

//			s1 = s1.slice(0, 1);			// elminate strange error ?
			txt = txt.substr(0, topp) + s1 + IgenName + tempPre + ls + txt.substr(topp);
			return txt;
		}		// if topp			🔺🔺🔺🔺🔺🔺🔺🔺🔺🔺🔺🔺🔺🔺🔺

		mw.log.warn('Igen not inserted ');
		return { 	type: 'warn'	};
	},			// 	replaceTag: function (txt, err, toolname) 

	addToFileDesc: function ($textarea, e, warn, toolName)  
	{	// WikiEditor
		$textarea = $textarea.$textarea || $textarea;
		return mw.loader.using('oojs-ui-core', function () {
			let txt = $textarea.val();
			if (typeof e === 'string') {
				e = Number(e);
				if (e)
					cSVG.warnMsg(e);
				if (warn)
					cSVG.warnMsg(warn);
			}
			$.removeSpinner('w3nu');
			txt = cSVG.replaceTag(txt, e, toolName);
			if (txt) {
				if (txt instanceof Object)
					return cSVG.warnMsg(txt);
				else
					$textarea.val(txt);
			}
			// mw.notify("Igen inserted ", { title: "Done!" });
			if (expeUser && tstex > 1)
				mw.notify("expensive: "+tstex.toString() );		// display number of (expensive) existence checks

			$('#wpSummary').val(function (i, v) {
				return (v.replace(summary, '') + ' ' + summary).trim();
			});
			$('#wpMinoredit').prop('checked', 1);
			// if (typeof e === 'string')
			mw.hook('gadget.cleanup.done').add(function () {
				mw.loader.using(['mediawiki.action.edit.preview', 'mediawiki.diff.styles']).always(
					function () {
					$('#wpDiff').trigger('click');
				});
			});
			// TODO: may only manual or cleanup same time?
			mw.hook('gadget.cleanup.run').fire({ text: 0 });
			return false;
		});
	},				// addToFileDesc	

	addIgenURL: function (err, size, toolName, para) 
	{	let param = '';
		if (typeof err === 'number')
			console.log('Successfully checked for SVG errors: ', err);
		// else err = 0;
		size = ($.isArray(size)) ? '&SVGsize=' + size[0] + '|' + size[1] + '&username=' + encodeURIComponent(c.wgUserName) : '';
		toolName = toolName ? '&toolname=' + encodeURI(toolName) : '';
		if (para instanceof Object) {
			$.each(para, function (i, o) {
				param += '&' + i + '=' + Number(o);
			});
		}
		location.href = mw.config.get('wgScript') + '?title=' + encodeURIComponent(c.wgPageName) + '&action=edit&' + cSVG.name + '=' + err + size + toolName + param;
	},				// addIgenURL

	/**
	 * Get the text of a template
	 * @param {string} fullStr
	 * @param {number} start
	 * @return {string} endPart
	 */
	getTempBlock: function (fullStr, start) 
	{	start = start || 0;
		let pos = 0,
		endPos = 0,
		RE = /\}\}/g,
		endPart = fullStr.slice(start + 2);
		while (RE.test(endPart)) {
			endPos = RE.lastIndex;
			// console.log(endPos, endPart.slice(pos, endPos - 2));
			if (!/\{\{/.test(endPart.slice(pos, endPos - 2)))
				break;
			pos = endPos;
		}
		endPart = endPos ? fullStr.slice(start, start + endPos) : '';
		return endPart;
	},				// getTempBlock

	insertIgenSub: function () 
	{	let txt = $textarea.val(),
		$this = $(this),
		sub = $this.data('key'),
		igenRE = /\s*\{\{[Ii](m?gen|mage[ _]generation)/g, // =?
		t1 = 0, // first
		t2 = 0; // last
		if (igenRE.test(txt)) {
			t1 = igenRE.lastIndex;
		} else {
			cSVG.warnMsg({
				title: 'Igen not found!',
				type: 'warn'
			});
			return;
		}
		igenRE = /\|\s*[Ss](ub|[c: -m])?= ?([^\n|}]*)/g;
		t2 = txt.substr(t1);
		if (igenRE.test(t2)) {
			t2 = t1 += igenRE.lastIndex;
			t1 -= RegExp.lastMatch.length;
		} else {
			t2 = cSVG.getTempBlock(t2);
			//	console.log('getTempBlock', t2);
			igenRE = /([^\n|}]+)/g;
			if (igenRE.test(t2)) {
				let lastIndex = igenRE.lastIndex;
				igenRE.lastIndex = 0;
				while (igenRE.test(t2))
					lastIndex = igenRE.lastIndex;
				// console.log('para', RegExp.lastMatch);
				t2 = t1 += lastIndex;
			} else {
				t1 = 0;
			}
		}
		cSVG.XHR.abort(); // current ajax
		$this.off('mouseover');
		if (t1) {
			txt = txt.substr(0, t1) + '|s=' + sub + txt.substr(t2);
			$textarea.val(txt);
		} else { // Should never happen?
			cSVG.warnMsg({
				title: 'Igen not valid!?',
				type: 'error'
			});
		}
	},				// insertIgenSub
	
	// Template:AutVec
	insertAutVec: function ($textarea) 
	{	let autRE = /^( *\|\s*[Aa](?:uthor|rtist)\s*=\s*)\*? ?(?:{{[Uu]nknown\|?(?:artist|author)?}}\s*)?(?:\*? ?vectorized by \s*)?({{[Uu]\|([^|\n]+)}}|[^\n]+) *$/m,
		txt,
		lm,
		pr,
		p1,
		p2,
		pre = '{{AutVec|',
		post = '}}';
		$textarea = $textarea.$textarea;
		txt = $textarea.val();

		if (autRE.test(txt)) {
			lm = RegExp.lastMatch;
			pr = RegExp.$1;
			p1 = RegExp.$2;
			p2 = RegExp.$3;
			if (!p2 && /(?:\[\[(?:[Uu]ser:)?)([^|\n]+)(\|\1)?(?:\]\])/.test(p1))
				p2 = RegExp.$1;
			p2 = p2 ? '|' + p2 : 'o=|2=' + p1;
			txt = txt.replace(lm, pr + pre + p2 + post);
			$textarea.val(txt);
		} else {
			$textarea.textSelection('encapsulateSelection', {
				pre: pre + 'o=|2=',
				post: post
			});
		}
	},				// insertAutVec

	addButtons: function ($textarea) 
	{	cSVG.done = 1;
		$textarea.on('wikiEditor-toolbar-buildSection-IgenSub', function (/* event, section*/) {
			$.removeCookie('wikiEditor-0-toolbar-section', {
				path: '/'
			});
			// $('.wikiEditor-ui-toolbar .sections').hide(); not working
			$('#wikiEditor-section-IgenSub')
			.attr('aria-expanded', 'false')
			.removeClass('section-visible')
			.addClass('section-hidden')
			.parent().hide();
		});

		$textarea.wikiEditor('addToToolbar', {
			section: 'main',
			groups: {
				SVG: {
					tools: {
						Igen: {
							label: 'SVG Image Generation (+W3Ccheck)',
							type: 'button',
							icon: 'https://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/SVG_Simple_Icon.svg/24px-SVG_Simple_Icon.svg.png',
							action: {
								type: 'callback',
								execute: mw.libs.simpleSVGcheck.getW3Data
							}
						},
						AutVec: {
							label: 'Author-Vector',
							type: 'button',
							icon: 'https://upload.wikimedia.org/wikipedia/commons/thumb/6/6a/Gnome-vector-author.svg/24px-Gnome-vector-author.svg.png',
							action: {
								type: 'callback',
								execute: mw.libs.simpleSVGcheck.insertAutVec
							}
						},
						descCleanup: {
							label: 'Description cleanup (without Igen)',
							type: 'button',
							icon: 'https://upload.wikimedia.org/wikipedia/commons/thumb/8/8e/Gnome-vector-cleanup.svg/24px-Gnome-vector-cleanup.svg.png',
							action: {
								type: 'callback',
								execute: mw.libs.simpleSVGcheck.addToFileDesc
								// execute: function (el) { cSVG.addToFileDesc(el.$textarea); }
							}
						}
					}
				}
			},
			sections: {
				IgenSub: {
					type: 'booklet',
					// label: 'SubCats',
					pages: {
						subtree: {
							// label: 'SubCats1',
							layout: 'characters'
						}
					}
				}
			}
		});
		this.$button = $('#wikiEditor-section-main .group.group-insert a[rel="Igen"]').css('float', 'left');
		// Made section button (HACK)
		$('#wikiEditor-ui-toolbar .tabs .tab-IgenSub')
		.before(this.$button)
		.find('a').css('padding', '0 8px').append($('<img>', {
				'src': 'https://upload.wikimedia.org/wikipedia/commons/thumb/3/32/SVG_category_subtree.svg/24px-SVG_category_subtree.svg.png',
				'width': 22,
				'height': 22,
				'title': 'Igen subtree parameter',
				'rel': 'IgenSub',
				'role': 'button',
				'class': 'tool tool-button'
			})).one('click', cSVG.addToolbar);

		// Add another toollink to the edit-dropdown
		mw.loader.using('ext.gadget.editDropdown', function () {
			mw.libs.commons.ui.addEditLink('', 'SVG Igen +', 'e-igen', 'Insert Template:Image_generation with W3-validity')
			.addEventListener('click', mw.libs.simpleSVGcheck.getW3Data);
		});
	},				// addButtons
	
	getIgenTop: function () 
	{	let $this = $(this),
		toolTip,
		// mouseOut = function(){ if ($this.tipsy) $this.tipsy('hide'); },
		mouseOut = function (tooltip) 
		{	if (tooltip && tooltip.visible)
				tooltip.toggle(false);
		},
		json = cSVG.jsonIgenTop,
		r,
		lang = c.wgUserLanguage,
		sub = $this.data('key');
		if (!sub)
			return false;
		// $this.tipsy(); // install tooltip
		// Auto-close
		setTimeout(function () 
		{	if (!toolTip || !toolTip.visible)
				return;
			setTimeout(function () 
			{	mouseOut(toolTip);
			}, 2000);
		}, 1000);

		function addTooltip(r) 
		{	// $this.attr('title', r).tipsy('show');
			let tooltip = new OO.ui.PopupWidget({
					padded: true,
					width: 'auto',
					align: 'forwards',
					// label: $this.attr('title'),
					// classes: [ 'mw-revslider-tooltip', 'mw-revslider-revision-tooltip' ],
					$content: r
				});
			$this.append(tooltip.$element)
			// .removeAttr('title')
			.on('mouseout', function () 
			{	mouseOut(tooltip);
			})
			.on('mouseover', function () 
			{	tooltip.toggle(true);
			});
			// setTimeout(function () { if (tooltip) tooltip.toggle(false); }, 2000);
			tooltip.toggle(true);
			toolTip = tooltip;
		} 				// addTooltip

		function getParse(text) 
		{	// console.log('getParse', text);
			// $.getJSON('/w/api.php?action=expandtemplates&format=json&text=%7B%7BIgen%2Ftop%7C' + sub + '%7D%7D&prop=wikitext',
			cSVG.XHR = $.getJSON('/w/api.php?action=parse&format=json&text=' + text + '&prop=text&pst=1&disablelimitreport=1&disableeditsection=1&disabletidy=1&contentmodel=wikitext&noimages=1', function (r) {
					// if (!(r = r.expandtemplates) || !(r = r.wikitext))
					if (!(r = r.parse) || !(r = r.text) || !(r = r['*']))
						r = $('<p>').text(sub);
					else
						r = $(r).unwrap(); // div
					if (!(text = r.html()))
						return;
					addTooltip(r);
					// Save parsed to json for possible later usage
					cSVG.jsonIgenTop[sub][lang] = text;
				});
		}				// getParse
		
		// TODO: could be outsourced as lib
		// r = json[sub]
		function langSwitch(r) 
		{	let i;
			if (!(lang in r)) 
			{	lang = 'en';
				// Allow input in format: {{LangSwitch|de=Grün|es/it/pt=Verde|fr=Vert|en=Green |lang=en}}
				// with multiple languages mapping to a single value
				for (let name in r) 
				{	var val,
					args;
					if (typeof name === 'string' && (val = r[name])) 
					{	args = name.split('/');
						if (args.length === 2)
							for (i = 1; i >= 0; i--)
								r[args[i]] = val.replace('{{{lang|{{int:lang|}}}}}', args[i]);

						// TODO: {{#switch:{{{1}}} pre parse?
					}
				}
				cSVG.jsonIgenTop[sub] = r; // put back
				// get the list of accepetable language (lang + those in lang's fallback chain) and check their content
				for (i = cSVG.langChain.length - 1; i >= 0; i--)
					if (cSVG.langChain[i]in r)
						lang = cSVG.langChain[i]; // no break as lower i is better

			}
			r = r[lang];
			// if (r)?
			if (/{/.test(r))
				getParse(encodeURIComponent(r));
			else
				addTooltip($('<p>').html(r));
		}

		// JSON source!
		if (json instanceof Object && (r = json[sub])) 
		{	if (r instanceof Object) 
			{	langSwitch(r);
			} else if (typeof(sub = r) === 'string' && (r = json[r]) && r instanceof Object) 
			{	// link
				langSwitch(r);
			} else 
			{	r = 0;
			}
		}
		if (!r)  // Fallback API parse!?
		{	getParse('%7B%7BIgen%2Ftop%7C' + sub + '%7D%7D');
		}
	},					//

	addToolbar: function () 
	{	$.getJSON('/w/index.php?title=Template:Igen/sub.json&action=raw', function (r)  // &ctype=text/javascript
		{	// mw.util.addCSS( '#wikiEditor-section-IgenSub .index{display:none}\n#wikiEditor-section-IgenSub .page div span {line-height:.8em;font-size:.8em;}' );
			if (c.wgUserLanguage === 'en') 
			{	cSVG.getIgenTop = null;
			} else 
			{	$.getJSON('/w/index.php?title=Template:Igen/top.json&action=raw', function (json) 
				{	cSVG.langChain = mw.language.getFallbackLanguages();
					cSVG.jsonIgenTop = json;
				});
			}
			mw.loader.load('oojs-ui'); // 'jquery.tipsy'
			let section = [],
			itemChk = {},
			$section = $('#wikiEditor-section-IgenSub');
			$section.find('.index').remove();
			// TODO: could be improved
			$.each(r, function (key, value) 
			{	let title = key,
				mouseover = cSVG.getIgenTop;
				if (!value) 
				{	value = '-';
					title = 'inhibit subcategorizing';
					mouseover = null;
				} else 
				{	value = value.replace('&#58;', '');
				}
				// Exclude double values
				if (itemChk[value]) 
				{	// console.log(value, 'is double', key, itemChk[value]);
					return;
				}
				itemChk[value] = key;
				section.push($('<span>', 
					{	title: title,
						data: 
						{	key: key
						},
						text: value,
						style: 'font-size:.8em',
						click: cSVG.insertIgenSub
					})
					// .tipsy({title: mouseover, fallback: title })
					.one('mouseover', mouseover));
			});
			$section.find('.page div').append(section);
			$section.parent().animate({
				opacity: 1
			}, 200);
			// });
		});
	}
};				// langSwitch


mw.libs.simpleSVGcheck = cSVG; // Expose globally
if (mw.config.get('wgNamespaceNumber') === 6 && /SVG$/i.test(c.wgTitle)) 
	{	if (isEdit) 
		{	// Allways collapsed
			if ($.fn.cookie && $.cookie('wikiEditor-0-toolbar-section') === 'IgenSub')
				$.removeCookie('wikiEditor-0-toolbar-section',
				{	path: '/'
				}); // 0 is original $( this ).data( 'context' ).instance

		// Late try?
		// (window.RLQ = window.RLQ || []).push(function () {
		window.addEventListener('load', function () {
			if ($.fn.wikiEditor && mw.loader.getState('ext.wikiEditor') === 'ready') 
			{	if (!cSVG.done)
					cSVG.addButtons($textarea);
			} else if (expeUser) 
			{	mw.log.error('WikiEditor not ready!?', mw.loader.getState('ext.wikiEditor'), $textarea, $.fn.wikiEditor);
			}
		});
		$textarea = $('#wpTextbox1');
		// Early try, direct load (as we don't know if the ready load event triggered)
		if ($textarea[0]) {
			$textarea.on('wikiEditor-toolbar-doneInitialSections', function () 
			{	if (!cSVG.done)
					cSVG.addButtons($textarea);
			});
		} else if (expeUser)
		{	throw Error('$textarea is not ready!?!');
		}
		/* if (mw.loader.getState('ext.wikiEditor') === 'registered') 
		{	mw.loader.using('user.options', function () 
			{	if (!mw.user.options.get('usebetatoolbar')) mw.log.warn('You must enable the Wikieditor to use the SVG-Igen buttons.');
			});
		}*/
		// Force Wikieditor on!?
		$.when(mw.loader.using(['mediawiki.util', 'mediawiki.user', 'jquery.spinner', 'ext.wikiEditor']), $.ready).always(function () {
			// if (mw.config.get('wgPageContentModel') === 'wikitext' && /^(edit|submit)$/.test(c.wgAction)) {
			// deprecated [[phab:T30856]]
	/*		mw.loader.using( 'mediawiki.toolbar', function () {
			mw.toolbar.addButtons( {
			speedTip: 'SVG Igen',
			imageFile: 'https://upload.wikimedia.org/wikipedia/commons/thumb/6/6c/SVG_Simple_Icon.svg/24px-SVG_Simple_Icon.svg.png',
			onClick: mw.libs.simpleSVGcheck.getW3Data
			} );
			});
 	*/		// $textarea = $( '#wpTextbox1' );
			if (!cSVG.done)
				cSVG.addButtons($textarea);
			// cleanup?							🔹🔹🔹🔹🔹🔹🔹🔹🔹🔹🔹🔹🔹🔹🔹🔹🔹🔹🔹
			if (!mw.libs.fastCleanup)
	 			importScript('User:Sarang/cleanup/sandbox.js');    // ed_wdh
			// Get parameter					🔹🔹🔹🔹🔹🔹🔹🔹🔹🔹🔹🔹🔹🔹🔹🔹🔹🔹🔹
			let URL = window.location.search,
			param = {},
			nameReg = new RegExp(cSVG.name + '=(\\d+)', 'g');
			err = nameReg.test(URL);
			if (c.wgAction === 'edit' && err) {
				cSVG.err = err = mw.util.getParamValue(cSVG.name);	// TODO only one err needed
				cSVG.size = mw.util.getParamValue('SVGsize');
				c.wgUserName = mw.util.getParamValue('username');
				toolName = mw.util.getParamValue('toolname');
				let URn = URL.substr(nameReg.lastIndex + 1);		// RL is readonly ?
				for (let aItKey, nKeyId = 0, aCouples = URn.split('&'); nKeyId < aCouples.length; nKeyId++) {
					aItKey = aCouples[nKeyId].split('=');
					param[aItKey[0]] = aItKey.length > 1 ? Number(aItKey[1]) : 0;
				}
				$.extend(cSVG, param);
				cSVG.addToFileDesc($textarea, err, '', toolName);
			}
		});
	} else 
	{	mw.loader.using(['ext.gadget.jquery.badge', 'ext.gadget.editDropdown'], cSVG.init);
	}
	// mw.libs.simpleSVGcheck.addButtons($('#wpTextbox1')); // DEBUG
}
}
(jQuery, mediaWiki));
// EOF </nowiki>