User:Erutuon/scripts/graveToAcuteRedirect.js
< User:Erutuon | scripts
Note: You may have to bypass your browser’s cache to see the changes. In addition, after saving a sitewide CSS file such as MediaWiki:Common.css, it will take 5-10 minutes before the changes take effect, even if you clear your cache.
- 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.
- This script lacks a documentation subpage. Please create it.
- Useful links: root page • root page’s subpages • links • redirects • your own
/*
* Automatically create three types of Ancient Greek redirects:
* - from titles with graves to the corresponding title with an acute:
* [[καὶ]] → [[καί]]
* - from titles with apostrophe-like characters to the straight apostrophe:
* [[γ’]] → [[γ']]
* - from a title with two accents in the final word to the version with the
* final accent removed:
* [[ἦέ]] → [[ἦε]]
*
* Install by adding this to your [[Special:MyPage/common.js]]:
importScript('User:Erutuon/scripts/graveToAcuteRedirect.js');
*/
/* jshint boss: true, undef: true, unused: true */
/* globals $, mw, OO */
// <nowiki>
(function () {
if (mw.config.get('wgCurRevisionId') !== 0)
return;
const decomposedTitle = mw.config.get('wgPageName').normalize('NFD');
// U+02BC MODIFIER LETTER APOSTROPHE, U+1FBD GREEK KORONIS, U+1FBF GREEK PSILI,
// U+2019 RIGHT SINGLE QUOTATION MARK
const wrongApostrophe = /[ʼ᾽᾿’]/g;
// U+0027 APOSTROPHE
const rightApostrophe = "'";
// const curlyApostrophe = "’";
// in mainspace and page hasn't been created and title contains a character in
// the Greek and Coptic block
if (mw.config.get('wgNamespaceNumber') === 0
&& /[Ͱ-Ͽ]/.test(decomposedTitle)) {
const grave = '\u0300';
const acute = '\u0301';
const circumflex = '\u0342';
const consonants = 'βγδζθκλμνξπρςστφχψ';
let rightTitle;
if (decomposedTitle.includes(grave)) {
const finalGraveRegex = new RegExp(grave + '([' + consonants + ']*)$');
if (!finalGraveRegex.test(decomposedTitle)) {
mw.notify("No grave accent at end of term!");
return;
}
// No need to recompose; the server does that automatically.
rightTitle = decomposedTitle.replace(finalGraveRegex, acute + '$1');
} else if (wrongApostrophe.test(decomposedTitle)) {
rightTitle = decomposedTitle.replace(wrongApostrophe, rightApostrophe);
} else {
// If last word has two accents, remove the last and redirect to it.
const match = decomposedTitle.match(/[^_]+$/);
const lastWord = match && match[0];
if (lastWord) {
const allTones = new RegExp("[" + acute + grave + circumflex + "]", "g");
const match = lastWord.match(allTones);
if (match && match.length === 2) {
let i = 0;
rightTitle = decomposedTitle.replace(lastWord,
lastWord.replace(allTones, function (tone) {
return ++i === 2 ? "" : tone;
}));
}
}
}
if (rightTitle) {
const redirect = '#REDIRECT [[' + rightTitle.normalize('NFC') + ']]';
$(function () {
switch (mw.config.get('wgAction')) {
case 'edit': case 'submit':
const textbox = $('#wpTextbox1');
if (textbox.textSelection('getContents') === '')
textbox.textSelection('setContents', redirect);
break;
case 'view': {
mw.loader.using([ 'mediawiki.Uri', 'oojs-ui' ]).done(function () {
// Use preloadtext parameter implemented in [[MediaWiki:Common.js]]
// to set text in textbox.
const button = new OO.ui.ButtonWidget({
label: 'Create redirect to ' + rightTitle,
href: new mw.Uri(location.href).extend({ action: 'edit', preloadtext: redirect }).toString()
});
const buttonContainer = $('<p>').append(button.$element);
$('#firstHeading').after(buttonContainer);
});
}
}
});
}
}
function hasAmbig(greekStr) {
// αιυ followed by diacritics (not macron, breve, circumflex, iota subscript)
greekStr = greekStr.normalize('NFD');
const diaeresis = '\u0308';
let match;
const vowelAndDiacritics = /([αεου]?ι|[αεηο]?υ|α)([\u0300-\u036F]*)/gi;
while (match = vowelAndDiacritics.exec(greekStr)) {
const [ , vowels, diacritics ] = match;
// macron, breve, circumflex (perispomeni), iota subscript
if (!/[\u0304\u0306\u0342\u0345]/.test(diacritics)
&& (vowels.length === 1 || diacritics.includes(diaeresis))) {
return true;
}
}
return false;
}
/*
console.log('start tests');
for (const [ word, expected ] of [
[ 'ἑκατόμβας', true ],
[ 'αἰδοίη', false ],
[ 'ἄγετ', true ],
[ 'Βηθσαϊδά', true ],
[ 'Βηθσαῐ̈δ', false ],
]) {
const result = hasAmbig(word);
console.log(word, expected, result, result === expected ? 'success' : 'failure');
}
*/
// in mainspace and page hasn't been created and title contains a character in
// the Greek and Coptic block and last character of title is straight apostrophe
if (mw.config.get('wgNamespaceNumber') === 0
&& /[Ͱ-Ͽ]/.test(decomposedTitle)
&& decomposedTitle[decomposedTitle.length - 1] == rightApostrophe
&& mw.config.get('wgAction') === 'edit') {
const charsTemplate = '{{subst:chars|grc|'
+ decomposedTitle.normalize('NFC')
+ '}}';
const ambigParameter = hasAmbig(decomposedTitle)
? '|' + charsTemplate.replace(rightApostrophe, '')
: '';
const contents = `==Ancient Greek==
===Pronunciation===
{{grc-IPA${ambigParameter}}}
===POS===
{{grc-POS|${ charsTemplate /* for curly apostrophe */ }}}
# {{apocopic form of|grc|${charsTemplate}}}`;
$('#wpTextbox1').textSelection('setContents', contents);
}
})();
// </nowiki>