User:Erutuon/scripts/templateParser.js

Note – after saving, you may have to bypass your browser’s cache to see the changes.

  • Mozilla / Firefox / Safari: hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (Command-R on a Macintosh);
  • Konqueror and Chrome: click Reload or press F5;
  • Opera: clear the cache in Tools → Preferences;
  • Internet Explorer: hold Ctrl while clicking Refresh, or press Ctrl-F5.

/* jshint esversion: 6, undef: true */

(function () {

/*
	Receives a template; parses it into an object.
	Numbered parameters are indexed in the MediaWiki fashion:
	1 comes first. Conflicts between explicitly numbered
	and positional parameters might be handled correctly.
*/
const templateNameSymbol = Symbol.for("templateName");
const parseTemplate = function (templateText) {
	const parameters	 = Object.new(null),
		  parameterRegex = /\|(?:([^=|}]+)=([^|}]+)|([^|}]+))/g;
	
	let match,
		index = 1,
		name  = templateText.match(/^{{([^|}]+)/);
	
	if (name !== null) name = name[1];
	else console.log(`No template name in ${templateText}.`);
	
	while ( (match = parameterRegex.exec(templateText)) ) {
		if ( match[1] ) {
			parameters[match[1]] = match[2];
		} else {
			parameters[index++] = match[3];
		}
	}
	
	/*
		None of these templates has a "name" parameter.
		Use a Symbol as key so that templates with |name=
		can be parsed in future.
	*/
	parameters[templateNameSymbol] = name;
	
	return parameters;
};

const formatTemplate = function (params) {	
	// isNaN(Number(key)) checks for a key that is a string.
	// In JavaScript, all keys except for Symbols are
	// strings, even numbers.
	// Assuming numbered arguments are sequential, which
	// should be true in this template!
	const formatParam = function ([key, value]) {
		return "|" + (isNaN(Number(key)) ? key + "=" : "") + value;
	};
	
	return `{{${params[templateNameSymbol]}${Object.entries(params).map(formatParam).join("")}}}`;
};

window.parseTemplate = parseTemplate;
window.formatTemplate = formatTemplate;

} ());