User:Ruakh/Tbot.js
Jump to navigation
Jump to search
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
// {{documentation}} <nowiki>
window.Tbot = window.Tbot || {};
window.Tbot.LanguagesToGreenify = window.Tbot.LanguagesToGreenify || [];
/* ==Change redlinks to greenlinks== */
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)
continue;
if (node.lang === langcode) // hit {t} or {t+} or {l}
break;
if (node.tagName.toUpperCase() === 'A') // hit [[ ]]
break;
if (node.tagName.toUpperCase() === 'SPAN' &&
node.hasAttribute('lang') &&
node.lang === '')
return node.innerHTML;
}
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'
ret += '|' + (tbotData.head || '{' + '{subst:PAGENAME}}');
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') {
var genders = tbotData.g.split(/[|]/);
ret += '|' + genders[0];
for (var i = 1; i < genders.length; ++i)
ret += '|g' + (i + 1) + '=' + genders[i];
}
if (tbotData.xlit)
ret += '|tr=' + tbotData.xlit;
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['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-decl';
if (tbotData.xlit)
template += '|tr=' + tbotData.xlit;
template += '}}';
return '\n====Declension====\n' + template + '\n';
};
$(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:languages/templates|getByCode|' + tbotData.lang + '|getCanonicalName}}==\n\n';
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);
document.getElementById('wpTextbox1').value = wikitext;
});
$(function(){
Tbot.LanguagesToGreenify.forEach(function(langcode){ Tbot.greenifyTranslinks(langcode);});
});
// </nowiki>