MediaWiki:InformationToCOA.js
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.
Documentation for this user script can be added at MediaWiki:InformationToCOA. |
/**
@Desc: Quick helper script to replace the [[template: Information]] with the [[template: COAInformation]].
@Revision: 20:27, 11 August 2018 (UTC)
@Author: [[User:Perhelion]] 2018-08 (based on [[MediaWiki:Catcheck.js]] by [[User:Lupo]] / [[MediaWiki:InformationToArtwork.js]] by [[User:Multichill]])
@License: Quadruple licensed GFDL, GPL, LGPL and CC-BY-3.0
Choose whichever license of these you like best :-)
*/
// [[Category:User scripts|InformationToCOA]] <nowiki>
/* global mw, $*/
/* eslint space-in-parens:0, indent:0, vars-on-top:0, computed-property-spacing:0, array-bracket-spacing:0, quote-props:0, one-var:0, curly:0 */
/* jshint curly:false, scripturl:true, forin:false*/
(function () {
'use strict';
if (mw.config.get('wgNamespaceNumber') !== 6 || mw.config.get('wgAction') !== 'edit') return;
var run = mw.libs.InformationToCOA = function () {
// Grab the text
var textbox = document.getElementById('wpTextbox1'),
text,
summary,
desc,
blazonOf = '',
blazon = '',
ref = '',
imgen = '',
ov = '',
lang = '',
pos = 0,
lastIndex = 0,
match = null,
// Terms from Template:I18n/COA
i18nCOA = [
'Escut d\'armes', // ca
'Znak', // cs
'Våben', // da
'(?:Stadt|Gemeinde)wappen|Wappen', // de
'[Cc]oats? [Oo]f [Aa]rms|[Cc][Oo][Aa]|[Aa]rms', // en
'Escudo de armas|[Ee]scudo', // es
'Armoiries|Blason', // fr
'Blazono', // eo
'Vapp', // et
'Armarria', // eu
'Vaakuna', // fi
'Escudo', // gl
'סמל', // he
'wopon', // hsb
'Címer', // hu
'Skjaldarmerki', // is
'Emblema|Stemma', // it
'Ģerbonis', // lv
'Грб', // mk
'Wapen', // nds
'Wapen', // nl
'Våpen', // nn
'Våpen', // no
'Herb', // pl
'Brasão de armas|[Bb]ras[ãa]o', // pt
'Герб', // ru
'Erb', // sk
'Grb', // sl
'Vapen' // sv
].join('|'),
reCOAclean = new RegExp('(' + i18nCOA + ')', 'g'),
reTmpEnd = /\}\}\n/,
reDesc = /\s*\|\s*[Dd]escription\s*=\s*(.+\.?)(?:: |\n)/,
reLang = /^\s*\{\{(\w\w)\s*\| ?(?:1 ?= ?(?!\n))?([^\n]{4})/mg, // without linebreak
reLang2 = /^\s*\{\{(\w\w)\s*\| ?(?:1 ?=)?\s*/mg,
reBlason = /:?\s*(?:(?:'')?[„"“»«]|[Bb]lason(?:ierung|ing)?)[\s:]*(?:(?:'')?[„"“»«])?([^\n"“”»«]+)["“”»«]?('')?\s*/g;
// No text?
if (!textbox || !textbox.value) return;
/**
* @brief Fill blazon;
*
* @param {string} str search target
* returns cleaned var blazonOf, desc
*/
function getBlason(str) {
var match = '', singleBlason;
blazon = [];
reBlason.lastIndex = 0;
while (reBlason.test(str)) {
singleBlason = RegExp.$1;
match = RegExp.lastMatch.replace(/\s*$/, '');
match = new RegExp(mw.RegExp.escape(match), 'g');
// Language tag
if (reLang2.test(str) && lang !== RegExp.$1) {
lang = RegExp.$1;
// w:Quotation_mark#Summary_table
switch (lang) {
case 'is':
case 'lf':
case 'lt':
case 'sq':
singleBlason = '„' + singleBlason + '“';
break;
case 'bs':
case 'cs':
case 'da':
case 'de':
case 'hr':
case 'hu':
singleBlason = '»' + singleBlason + '«';
break;
case 'af':
case 'cy':
case 'en':
case 'ga':
case 'ia':
case 'lo':
case 'th':
case 'vi':
singleBlason = '“' + singleBlason + '”';
break;
case 'fr':
singleBlason = '« ' + singleBlason + ' »';
break;
default:
singleBlason = '«' + singleBlason + '»';
}
singleBlason = '{{' + lang + '|' + singleBlason + '}}';
} else { // Only one "block" for each lang
singleBlason = ''; // blazon.pop();
continue;
}
desc = desc.replace(match, '\n');
blazonOf = blazonOf.replace(match, '\n');
if (singleBlason) blazon.push(singleBlason);
}
reLang2.lastIndex = 0;
blazon = blazon.join('\n');
}
/**
* @brief Find the index position of the next parameter
* and select until the previous.
* @param {number} pos first index
* @param {number} p length of previous match
* @return {string} full text between pos and next parameter
*/
function findNextPos(pos, p) {
lastIndex = pos + p;
p = text.slice(lastIndex).search(/^\s*\|/m);
lastIndex += p;
return text.slice(pos, lastIndex);
}
function syncCurlyBrackets(block) {
// Synchronize open & closing curly brackets
for (var reOtag = /\{\{/g, c = 0, reCtag = /\}\}/g; reOtag.test(block); c++)
if (!reCtag.test(block)) {
// Missing closing tag
block = block.replace(/\n*$/, '}}');
if (reLang.test(block)) {
// Then the opening lang-tag is missing on desc.
lang = RegExp.$1;
if (!reLang.test(desc))
desc = '{{' + lang + '|' + desc.replace(/^\s*/, '');
}
break;
}
lang = '';
reLang.lastIndex = 0;
return block;
}
text = textbox.value;
// Don't modify existing!?
if (/\{\{COAInformation/.test(text))
return;
// Get blazonOf including langTag
if ((match = reDesc.exec(text))) {
pos = match.index;
var blazonOfcont,
validDesc = false,
langTag = '',
p = match[0].length;
blazonOf = match[1];
// Get full description
desc = findNextPos(pos, p);
/* Get blason first */
if (reBlason.test(desc))
getBlason(desc);
else if (reBlason.test(blazonOf))
getBlason(blazonOf);
validDesc = desc.indexOf(blazonOf) !== -1;
// Remove reDesc (match[1]) from "description"
desc = desc.replace(reDesc, '\n');
if (blazonOf)
// No short desc??
if (validDesc && lang && !reLang2.test(desc)) {
desc = '{{' + lang + '|' + desc.replace(/^\s*/, '');
blazonOf = '';
} else blazonOf = syncCurlyBrackets(blazonOf);
blazonOfcont = '\n' + blazonOf;
desc = $.trim(desc);
/* Get blasonOf second */
if (desc) {
// If in language tags, copy this
var part;
while ((part = reLang.exec(desc)) && part[1] !== lang) {
lang = part[1]; // RegExp.$1;
langTag = '{{' + lang + '|';
blazonOf = desc.slice(reLang.lastIndex - 4);
match = '';
var firstIndex = part.index; // reLang.lastIndex - part; // common 0
part = part[0].length - 1; // RegExp.lastMatch.length;
if ((match = blazonOf.search(reTmpEnd)) !== -1)
reLang.lastIndex = Math.max(firstIndex, 0);
else if ((match = blazonOf.search(/\n/)) === -1)
match = blazonOf.length - 2; // - part // full match
blazonOf = blazonOf.slice(0, match);
match += firstIndex;
// Remove
desc = desc.slice(0, firstIndex) + desc.slice(part + match);
if (desc.replace(reTmpEnd, '').replace(reLang2, '').replace(/^\s*/, '')) {
if (!reLang2.test(desc))
desc = langTag + desc.replace(/^\s*/, '');
} else { desc = ''; }
// Add
blazonOfcont += '\n' + langTag + blazonOf + '}}';
blazonOf = '';
}
blazonOf = $.trim(blazonOf || blazonOfcont) + '\n';
}
// Cleanup empty parameter
if (!blazonOf.replace(reTmpEnd, '').replace(reLang2, '').replace(/\s+/, ''))
blazonOf = '';
text = text.slice(0, pos) + text.slice(lastIndex);
}
// FIXME: this is only dirty cleanup
blazonOf = blazonOf.replace(reCOAclean, '')
.replace(/\| ?1 ?= */, '| '); // 1st entry
if (desc)
text = text.slice(0, pos) + '\n |description = ' + desc + '\n' + text.slice(pos);
if (/[Rr]ef(?:eren(?:ce|z))?[\s:]+([^\n]+)/.test(text)) {
ref = RegExp.$1;
text = text.replace(RegExp.lastMatch, '');
}
if (/\s*\|\s*[Ss]ource\s*=\s*([^\n]+)/.test(text)) {
text = text.replace(RegExp.lastMatch, '\n |source = ' + RegExp.$1);
}
if (/\s*\|\s*[Oo]ther[ _]fields\s*=\s*(\{\{[Ii]m?gen[^\n]+)\s*/.test(text)) {
imgen = RegExp.$1;
match = RegExp.lastMatch;
if (/\{\{[Ii](?:gen|mage generation) ?\| ?([Ii](?:nkscape)?|[Aa](?:dobe)?|IA)? ?\|(?:(\d*)\| ?)?(\+\| ?)?s=c\}\}/.test(imgen))
imgen = RegExp.$1 + '/' + (RegExp.$2 || '0');
imgen = '\n |image = ' + imgen + '\n';
text = text.replace(match, imgen); // problems when additional fields, e.g. |other fields = {{Igen|...}} and {{InFi|.....}} (splitting needed)
}
if ((match = /\s*\|\s*[Oo]ther[ _]versions\s*= *(.*)/.exec(text))) {
pos = match.index;
lastIndex = match[0].length;
if (match[1]) {
ov = match[0].indexOf(match[1], 15);
ov = findNextPos(pos + ov, lastIndex);
} else { lastIndex += pos; }
ov = '\n |versions = ' + ov;
text = text.slice(0, pos) + ov + text.slice(lastIndex);
}
// Do the actual replace
text = text
.replace(/\{\{\s*[Ii]nformation\s*\n?/, '{{COAInformation' +
'\n |blazon of =\n' + blazonOf +
'\n |blazon = ' + blazon +
'\n |references = ' + ref +
'\n |tincture = \n ')
.replace(/\n *\|\s*[Aa]uthor\s*= */, // exclude Citebook!
'\n |artist = ' /* + artist*/)
.replace(/\n *\|\s*[Dd]ate\s*= */, // exclude Citebook!
'\n |date = ' /* + date*/)
.replace(/\s*\|\s*[Pp]ermission\s*= */,
'\n |permission = ')
.replace(/\s*\|\s*[Oo]ther[ _]fields\s*= */,
'\n |fields = ') // shorten
.replace(/\n \|permission\s*= *\n/,
'\n') // remove empty
.replace(/\n \|fields\s*= *\n/,
'\n') // remove empty
.replace(/\n \|versions\s*= *\n/,
'\n'); // remove empty
// Need jQuery for CodeMirror hook
$(textbox).val(text);
// textbox.value = text;
// Set edit summary
summary = document.getElementById('wpSummary');
if (!summary) return;
summary.value += ((summary.value || '') ? ' ' : '') + 'toCOA-[[MediaWiki:InformationToCOA.js|script]]';
// Are we sure we want to convert and autosave the page?
// if (window.confirm('Are you sure you want to convert the template Information to template COAInformation?'))
// document.editform.wpSave.click();
};
mw.loader.using('mediawiki.util', run);
}());
// </nowiki>