User:ZBroz/Tbot.js
Appearance
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
// <pre><nowiki>
var Tbot;
Tbot = Tbot || {};
/*</pre>
==Change redlinks to greenlinks==
<pre>*/
Tbot.greenifyTranslinks = function (langcode)
{
if(mw.config.get('wgAction') !== 'view')
return;
if(! document.querySelector)
return;
if(! document.querySelector
('table.translations span:lang(' + langcode + ') > a.new'))
return;
var headers = document.querySelectorAll('h3, h4, h5');
for(var i = 0; i < headers.length; ++i)
{
if($(headers[i].querySelector('.mw-headline')).text() !== 'Translations')
continue;
var posHeader = getPosForTransSect(i);
if(! posHeader)
continue;
for( var elem = headers[i].nextElementSibling;
elem && elem.tagName.search(/^[hH]\d$/) === -1;
elem = elem.nextElementSibling )
{
var linksToGreenify =
elem.querySelectorAll('span:lang(' + langcode + ') > a.new');
if(linksToGreenify.length === 0)
continue;
var gloss = getGlossForTransTable(elem);
for(var j = 0; j < linksToGreenify.length; ++j)
{
var link = linksToGreenify[j];
var tbotData =
{
lang: langcode,
pos: posHeader.toLowerCase(),
head: $(link).text().trim().replace(/ +/g, ' '),
xlit: getXlitForLink(link),
g: getGenderForLink(link),
trans: mw.config.get('wgTitle'),
gloss: gloss
};
if(mw.util.wikiUrlencode(tbotData.head)
=== link.getAttribute('href').match(/\?(?:.*?&)?title=([^&]+)/)[1])
delete tbotData.head;
removeEmptyProps(tbotData);
var href = link.getAttribute('href');
href = href.split('#')[0]; // shouldn't be needed
if(href.indexOf('?') === -1) // shouldn't happen
href += '?';
href += '&tbotData=' + encodeURIComponent(JSON.stringify(tbotData));
link.setAttribute('href', href);
link.style.color = 'rgb(34, 204, 0)';
}
}
}
function getPosForTransSect(i) // headers[i] is the trans-sect-header
{
// We start at headers[i-1], and scroll back until we find a header at
// a higher level than headers[i]. For example, if ====Translations====
// is at L4, then the closest-previous L3 header is the POS header.
for(var j = i - 1; j >= 0; --j)
if(headers[j].tagName < headers[i].tagName)
{
var ret = $(headers[j].querySelector('.mw-headline')).text();
ret = ret.replace(/\s+\d+$/, ''); // e.g. 'Noun 1' -> 'Noun'
return ret;
}
return null; // shouldn't happen
}
function getGlossForTransTable(navFrame)
{
var ret = $(navFrame.querySelector('.NavHead')).text();
ret = ret.trim().replace(/^\[.*?\]\s*/, '').replace(/^\u00B1\s*/, '');
return ret;
}
function getXlitForLink(link)
{
for(var node = link.parentNode.nextSibling; node; node = node.nextSibling)
{
if(node.nodeType === Node.ELEMENT_NODE
&& node.tagName.toUpperCase() === 'A') // hit {{t}} or [[ ]]
break;
if(node.nodeType === Node.ELEMENT_NODE
&& node.lang === langcode) // hit {{t-SOP}} or {{l}}
break;
if(node.nodeType !== Node.TEXT_NODE)
continue;
var match = node.data.match(/^ \((.*)\),? ?$/);
if(match)
return match[1];
}
return '';
}
function getGenderForLink(link) // e.g. '' or 'm' or 'c1' or 'm|f'
{
var ret = '';
for( var elem = link.parentNode.nextElementSibling;
elem;
elem = elem.nextElementSibling )
if(elem.tagName.toUpperCase() === 'A') // hit {{t}} or [[ ]]
return '';
else if(elem.lang === langcode) // hit {{t-SOP}} or {{l}}
return '';
else if(elem.className === 'gender')
return decodeGenderSpan(elem);
return '';
}
function decodeGenderSpan(span)
{
var child = span.firstChild;
if(child.nodeValue && child.nodeValue.trim() === 'class') {
child = child.nextSibling;
var ret = '';
while(child) {
if(child.nodeType === Node.ELEMENT_NODE) {
ret += '|c' + child.innerHTML.trim();
}
child = child.nextSibling;
}
return ret.replace(/^[|]/, '');
} else {
var abbrToCode = { pl: 'p', anim: 'an',
du: 'd', inan: 'in',
sg: 's', pers: 'pr' };
var ret = '';
while(child) {
if(child.nodeType === Node.ELEMENT_NODE) {
var abbr = child.innerHTML.trim();
ret += '-' + (abbrToCode[abbr] || abbr);
} else if(child.nodeType === Node.TEXT_NODE) {
if(child.nodeValue.trim() === ',')
ret += '|';
}
child = child.nextSibling;
}
return ret.replace(/(^|[|])-/g, '$1');
}
}
function removeEmptyProps(obj)
{
var propsToRemove = [];
for(var key in obj)
if(obj[key] === undefined || obj[key] === null || obj[key] === '')
propsToRemove.push(key);
for(var i = 0; i < propsToRemove.length; ++i)
delete obj[propsToRemove[i]];
}
};
/*</pre>
==Populate edit-window at target of a greenlink==
<pre>*/
Tbot.getHeadLine = Tbot.getHeadLine || {};
if(! Tbot.getHeadLine.run)
Tbot.getHeadLine.run = function(tbotData)
{
var f;
// Has a special case has been set up for this lang & POS?
f = f || Tbot.getHeadLine[tbotData.lang+'~'+tbotData.pos];
// . . . how about a special case for this lang, regardless of POS?
f = f || Tbot.getHeadLine[tbotData.lang+'~'];
// . . . or for this POS, regardless of lang?
f = f || Tbot.getHeadLine['~'+tbotData.pos];
// No? O.K., then just use the default:
f = f || Tbot.getHeadLine.default;
return f(tbotData);
};
// a suitable default, using the {{head}} template
if(! Tbot.getHeadLine.default)
Tbot.getHeadLine.default = function (tbotData)
{
var ret = '{{head|' + tbotData.lang;
if(tbotData.pos.indexOf('=') > -1)
ret += '||1=' + tbotData.pos;
else
ret += '|' + tbotData.pos;
if(tbotData.head)
ret += '|head=' + tbotData.head;
if(tbotData.xlit)
ret += '|tr=' + tbotData.xlit;
if(tbotData.g)
ret += '|g=' + tbotData.g.split('|')[0];
if(tbotData.g && tbotData.g.indexOf('|') > -1)
ret += '|g2=' + tbotData.g.split('|')[1];
ret += '}}';
return ret;
};
// An augmented default: use {{head}} initially, but also launch an
// AJAX request to see if there exists a more-specific template and,
// if so, to replace {{head}} with a stab in the dark at how to use
// that template.
Tbot.getHeadLine['attempt-{{xx-pos}}'] = function (tbotData)
{
var lang = tbotData.lang;
var pos = tbotData.pos;
jQuery.getJSON
(
'/w/api.php?format=jsonfm&action=query&titles='
+ 'Template:' + lang + '-' + pos,
function (data)
{
data = data && data.query && data.query.pages;
if(! data)
return;
var regex = new RegExp('[{][{]head[|]' + lang + '[|]' + pos + '(?=[|}]');
var wpTextbox1 = document.getElementById('wpTextbox1');
if(! wpTextbox1 || ! regex.test(wpTextbox1.value))
return;
for(var pageid in data)
if(pageid.charAt(0) !== '-')
{
wpTextbox1.value =
wpTextbox1.value.replace
(regex, '{{' + data[pageid].title.substr(9));
return;
}
}
);
return Tbot.getHeadLine['{{head}}'](tbotData);
};
Tbot.getHeadLine['ru~adjective'] =
Tbot.getHeadLine['ru~adverb'] =
Tbot.getHeadLine['ru~noun'] =
Tbot.getHeadLine['ru~proper noun'] =
Tbot.getHeadLine['ru~verb'] = function (tbotData)
{
var ret = '{{ru-';
if(tbotData.pos === 'adjective' || tbotData.pos === 'adverb')
ret += tbotData.pos.substr(0, 3); // 'adj' or 'adv'
else
ret += tbotData.pos; // 'noun', 'proper noun', 'verb'
if(tbotData.head)
ret += '|head=' + tbotData.head;
if(tbotData.xlit)
ret += '|tr=' + tbotData.xlit;
if(tbotData.g)
if(tbotData.pos === 'verb')
// not actually a gender: it's 'impf' or 'pf':
ret += '|' + tbotData.g.split('|')[0];
else if(tbotData.pos === 'noun' || tbotData.pos === 'proper noun')
ret += '|g=' + tbotData.g.replace(/[|]/g, '');
ret += '}}';
return ret;
};
Tbot.getHeadLine['cs~adjective'] =
Tbot.getHeadLine['cs~adverb'] =
Tbot.getHeadLine['cs~noun'] =
Tbot.getHeadLine['cs~proper noun'] =
Tbot.getHeadLine['cs~verb'] = function (tbotData)
{
var ret = '{{cs-';
if(tbotData.pos === 'adjective' || tbotData.pos === 'adverb')
ret += tbotData.pos.substr(0, 3); // 'adj' or 'adv'
else
ret += tbotData.pos; // 'noun', 'proper noun', 'verb'
if(tbotData.head)
ret += '|head=' + tbotData.head;
if(tbotData.g)
if(tbotData.pos === 'noun' || tbotData.pos === 'proper noun')
ret += '|g=' + tbotData.g.replace(/[|]/g, '');
ret += '}}';
return ret;
};
Tbot.getHeadLine['tpi~verb'] = function (tbotData)
{
if(mw.config.get('wgPageName').search(/im$/) > -1)
return '{{tpi-verb|t}}';
else
return '{{tpi-verb|i}}';
};
Tbot.getHeadLine['tpi~verb'] = function (tbotData)
{
if(mw.config.get('wgPageName').search(/im$/) > -1)
return '{{tpi-verb|t}}';
else
return '{{tpi-verb|i}}';
};
Tbot.getHeadLine['yi~adjective'] =
Tbot.getHeadLine['yi~adverb'] =
Tbot.getHeadLine['yi~noun'] =
Tbot.getHeadLine['yi~phrase'] =
Tbot.getHeadLine['yi~proper noun'] =
Tbot.getHeadLine['yi~verb'] = function (tbotData)
{
var ret = '{{yi-';
if(tbotData.pos === 'adjective' || tbotData.pos === 'adverb')
ret += tbotData.pos.substr(0, 3); // 'adj' or 'adv'
else
ret += tbotData.pos; // 'noun', 'phrase', etc.
if(tbotData.head)
ret += '|head=' + tbotData.head;
if(tbotData.xlit)
ret += '|tr=' + tbotData.xlit;
if(tbotData.pos === 'noun' && tbotData.g)
ret += '|g=' + tbotData.g.replace(/[|]/, '');
if(tbotData.pos === 'noun' && tbotData.g === 'f'
&& mw.config.get('wgPageName').search(/\u05E2$/) > -1)
ret += '|pl=s';
ret += '}}';
return ret;
};
Tbot.getInflSect = function (tbotData)
{
// allow special-casing of specific languages and POSes:
if(Tbot.getInflSect[tbotData.lang + '~' + tbotData.pos])
return Tbot.getInflSect[tbotData.lang+'~'+tbotData.pos](tbotData);
return '';
};
Tbot.getInflSect['yi~adjective'] = function (tbotData)
{
var template = '{{yi-adj-';
var curr = mw.config.get('wgTitle');
if(curr.search(/[\u05DA\u05DD\u05DF\u05E3\u05E5]$/) > -1) // final letter
{
if(curr.charAt(curr.length - 1) === '\u05DD') // final mem
template += 'm';
else if(curr.charAt(curr.length - 1) === '\u05DF') // final nun
template += 'n';
else // final khaf, final fei, or final tsadi
template += 'final';
template += '|' + curr.substr(0, curr.length - 1)
+ String.fromCharCode(curr.charCodeAt(curr.length - 1) + 1);
}
else if(curr.search(/\u05D5\u05BC?$|\u05D9\u05B4?$|\u05D0[\u05B7\u05B8]$|\u05E2$/) > -1)
template += 'vowel';
else
template += '1';
if(tbotData.xlit)
template += '|' + tbotData.xlit;
template += '}}';
return '\n====Declension====\n' + template + '\n';
};
// DP custom BEGIN
Tbot.getLanguageHeading = function (langCode) {
// Hardcode some languages for a nicer wiki markup before substitution
if (langCode=="cs")
return '==Czech==\n\n';
else
return '=={{subst:#invoke:language utilities|lookup_language|' + langCode + '|names}}==\n\n';
};
Tbot.getExternalLinks = function (langCode) {
if (langCode=="cs")
return "\n===External links===\n* {{R:PSJC}}\n* {{R:SSJC}}";
else
return "";
};
// DP custom END
$(function ()
{
if(mw.config.get('wgNamespaceNumber') !== 0)
return;
if(mw.config.get('wgAction') !== 'edit')
return;
if(! document.getElementById('ca-nstab-main'))
return;
if(document.getElementById('ca-nstab-main').className !== 'selected new')
return;
var tbotData = document.location.href.match(/&tbotData=([^&]+)/);
if(! tbotData)
return;
tbotData = JSON.parse(decodeURIComponent(tbotData[1]));
if(tbotData.pos)
tbotData.posHeader =
tbotData.pos.charAt(0).toUpperCase() + tbotData.pos.substr(1);
var wikitext = '';
if(! tbotData.lang || tbotData.lang.search(/^[a-z-]+$/) === -1)
return;
//wikitext += '=={{subst:#invoke:language utilities|lookup_language|' + tbotData.lang + '|names}}==\n\n';
wikitext += Tbot.getLanguageHeading(tbotData.lang);
if(! tbotData.posHeader)
return;
if(tbotData.posHeader.search(/^=|=$/) > -1)
wikitext += '=== ' + tbotData.posHeader + ' ===\n';
else
wikitext += '===' + tbotData.posHeader + '===\n';
wikitext += Tbot.getHeadLine.run(tbotData) + '\n\n';
if(! tbotData.trans)
return;
wikitext += '# [[' + tbotData.trans + ']]';
if(tbotData.gloss)
wikitext += ' {{gloss|' + tbotData.gloss + '}}';
wikitext += '\n';
wikitext += Tbot.getInflSect(tbotData);
wikitext += Tbot.getExternalLinks(tbotData.lang);
document.getElementById('wpTextbox1').value = wikitext;
});
// </nowiki></pre>